Commit Graph

1546 Commits

Author SHA1 Message Date
Saravanakumar D
e83ab9907e fix(config): remove :3300 port from Gitea npm registry URLs
The Gitea instance runs on default port 80, not 3300. Updated the
npmrc template and AGENTS.md references accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 23:29:07 -07:00
Saravanakumar D
da98c9fd3f docs(config): add GITEA_NPM_TOKEN to .env.example
Include Gitea npm registry variables (token, host, owner) so
developers know which env vars to set for @bytelyst package access.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 23:15:43 -07:00
saravanakumardb1
4f9ec3332f Merge: Phase 2 scheduler/router core (§7) + fleet artifacts/blob (§13)
Combined parallel work (file-disjoint). Scheduler: deterministic scoring router
wired into atomic claim. Artifacts: blob-backed pointers in fleet_artifacts.
fleet suite 79/79; platform-service 1591/1591; build clean.
2026-05-29 23:12:33 -07:00
saravanakumardb1
b65e818f3d feat(platform-service): fleet artifacts + blob wiring (§13)
Artifact pointers in fleet_artifacts; large outputs in @bytelyst/blob (never
Cosmos). Routes: POST/GET /fleet/jobs/:id/artifacts, GET/DELETE
/fleet/artifacts/:id with short-lived SAS. 7 artifact tests.
2026-05-29 23:11:45 -07:00
saravanakumardb1
7930e8b0bd feat(platform-service): Phase 2 scheduler/router core (§7) + wire into atomic claim
Add a pure, fixed-weight scoring engine that decides WHICH queued job a claiming
factory gets, and wire it into coordinator.claimNextJob (the atomic rev-CAS claim
in tryClaimJob is unchanged).

scheduler.ts (pure, synchronous, no I/O):
- scoreCandidate(job, factory, ctx, weights?) -> { score, breakdown }
  score = w1*capabilityFit + w2*affinity + w3*(1/(1+load)) + w4*costFit(budget)
        + w5*health - w6*starvationPenalty(age); breakdown is per-weighted-term
        and sums to score (explainability / Phase-3 readiness).
- selectJob(candidates, factory, ctx, weights?) -> FleetJobDoc | null
  filters to stage-eligible + deps-satisfied (injected pure predicate) +
  capability-subset (+ down-health floor), ranks by score, deterministic
  tie-break: higher priority -> older createdAt -> lower cost class.
- Fixed default weights + bucketed anti-starvation aging (Phase 3 = tunable
  weights + preemption; intentionally NOT built here).

coordinator.ts (candidate-ranking section only):
- claimNextJob now resolves deps (store-backed) into a pure predicate, builds the
  factory view + authoritative now, and selects via selectJob; tryClaimJob CAS /
  lease / fence logic untouched. ClaimContext gains additive optional scheduler
  inputs (health/load/seatLimit/factoryEngines/warmScopes/costCeilingUsd). The
  pure capability-subset predicate moved into scheduler.ts and is re-exported.

Tests: scheduler.test.ts (16) covers capability hard-filter, priority/age
tie-breaks, load, health (+ down floor), starvation, cost fit, affinity, breakdown
sum, determinism, empty/no-eligible. coordinator.test.ts adds score-driven
selection, health floor, and ordered drain; all prior fleet tests stay green.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 23:03:40 -07:00
saravanakumardb1
6f6e005114 Merge PR #29: Phase 2 atomic-claim hardening — true single-winner claim
Adds @bytelyst/datastore updateIfMatch (Cosmos If-Match/_etag + process-atomic
memory impl); rewires fleet revUpdate* to conditional writes. Concurrent claim
proven via Promise.all + N-claimer stress (fails on old read-check-write, passes
now). datastore 48 + fleet 53 green; builds clean; no consumer regressed.
2026-05-29 21:04:33 -07:00
saravanakumardb1
33c1d8d5fa fix(platform-service): make fleet job claim truly atomic via datastore updateIfMatch
The foundation's revUpdateJob/revUpdateLease did a read -> rev-check -> write with
await points between them, so two CONCURRENT claims could both read the same rev,
both pass the check, and both write — a double-assignment the old (sequential) race
test could not catch.

Rewire revUpdateJob/revUpdateLease to delegate to the datastore's updateIfMatch,
which performs the compare and the write as one indivisible operation (Cosmos
If-Match; synchronous compare-set on memory). The coordinator's tryClaimJob keeps
identical external behavior (ok/conflict) but is now genuinely single-winner.

Upgrades the coordinator tests to prove atomicity under TRUE concurrency:
- two contenders via Promise.all -> exactly one ok, one conflict; assigned once;
  one run; one lease; leaseEpoch 1.
- N-claimer (15) stress via Promise.all -> one ok, N-1 conflicts, no double-assignment.
- N concurrent claimNextJob for one job -> exactly one non-null claim.
- N concurrent lease renewals -> exactly one wins.

Verified these concurrent tests FAIL against the old read-check-write (double-assign)
and pass after the fix.
2026-05-29 20:59:08 -07:00
saravanakumardb1
40fd0e05ad feat(datastore): add updateIfMatch optimistic-concurrency write (If-Match / atomic CAS)
Adds an additive, backward-compatible conditional write to the datastore abstraction
so consumers can do true single-winner compare-and-swap:

  updateIfMatch(id, partitionKey, expected: { etag?, rev? }, patch)
    -> { ok: true, doc } | { ok: false, reason: 'conflict' | 'not_found' }

- types: ConcurrencyToken + UpdateIfMatchResult; optional _etag on BaseDocument
  (provider-managed, surfaced on reads); new method on DocumentCollection; exported.
- memory provider: get -> compare -> set in ONE synchronous block (no await/yield),
  so two concurrent callers cannot interleave under the single-threaded event loop —
  the first wins and bumps rev + _etag, the rest get conflict. True in-process atomicity.
- cosmos provider: conditional replace with accessCondition { type: 'IfMatch',
  condition: _etag }; translates Cosmos 412 -> conflict, 404 -> not_found; also
  compares/bumps rev for parity.

Existing method signatures are unchanged (additive only). Tests: memory match/stale/
missing + an N-concurrent Promise.all atomicity proof; cosmos If-Match mapping via a
fake @azure/cosmos (match writes, stale etag -> 412 conflict, missing -> not_found).
2026-05-29 20:58:55 -07:00
saravanakumardb1
873955ac04 Merge PR #28: Phase 2 Foundation — fleet module + coordinator (claim/lease/fence/heartbeat/reaper)
Foundation review: 50 fleet tests green, build clean, no regressions. NOTE: the
atomic-claim uses an in-module rev-CAS over an unconditional datastore write —
true cross-process atomicity requires an If-Match/_etag-conditional update in
@bytelyst/datastore (tracked P0 hardening follow-up before P2-S3).
2026-05-29 20:41:36 -07:00
saravanakumardb1
95dd7aa1d0 docs(platform-service): fleet module README (containers, claim/lease/fence protocol, reaper) 2026-05-29 20:20:54 -07:00
saravanakumardb1
8eb02c48aa feat(platform-service): fleet REST routes + module registration (P2 foundation)
Guarded REST under /api (auth + productId, like items): POST /fleet/jobs (idempotent
submit), GET /fleet/jobs (by stage/idempotencyKey), GET /fleet/jobs/:id, PATCH
/fleet/jobs/:id (fenced transition), POST /fleet/claim, lease renew/release,
factories/heartbeat, and runs/events streams. Every body validated with the Zod
schemas; fenced/conflict map to 409, missing to 404, invalid to 400. Registers
fleetRoutes in server.ts next to itemRoutes. Routes tested via Fastify inject on
the memory provider (real coordinator).
2026-05-29 20:20:46 -07:00
saravanakumardb1
8f51570da7 feat(platform-service): fleet coordinator — claim/lease/fence/heartbeat/reaper (P2 foundation)
The concurrency core (§4/§7/§8/§18/§25):
- claimNextJob: priority+age selection over queued/dep-satisfied jobs whose caps
  are a subset of the factory's, then tryClaimJob does a rev CAS to flip to
  assigned + acquire the lease — exactly one contender wins, no double-assignment.
- leases + fencing: acquire/reclaim bumps leaseEpoch; patchJobFenced/renew/release
  reject a call whose leaseEpoch < job.leaseEpoch (zombie worker can't overwrite).
- heartbeat + isFactoryStale for factory liveness.
- reapExpiredLeases: returns expired-lease jobs to queued/blocked, bumps the epoch
  (fencing the dead holder), preserves the checkpoint pointer (resume), marks the
  lease expired; idempotent. Documents why Cosmos TTL cannot do this.
- submit: idempotent (dedup/supersede/409) + submit-time dependency cycle
  detection; deps gating (shipped, or testing when depsMode:soft).

Tests drive the atomic-claim race, fencing, and reaper deterministically via the
rev CAS (no real threads).
2026-05-29 20:20:30 -07:00
saravanakumardb1
fada354df8 feat(platform-service): fleet repositories with rev compare-and-swap (P2 foundation)
One repository per fleet_* container on the @bytelyst/datastore abstraction
(memory + cosmos): create/getById/list (by productId, stage, idempotencyKey),
partition-aware single-partition queries, ordered append-only appendEvent, and
runs/leases/factories/profiles/artifacts CRUD. Adds revUpdateJob/revUpdateLease —
a `rev`-token compare-and-swap that writes only when the stored rev still matches
(the optimistic-concurrency primitive for atomic claim + fenced transitions;
maps to Cosmos _etag/If-Match in production).
2026-05-29 20:20:15 -07:00
saravanakumardb1
721d3fcb48 feat(platform-service): fleet data model + container registration (P2 foundation)
Adds the agent-gigafactory fleet data model (modules/fleet/types.ts): Zod schemas
as the source of truth with inferred types (no `any`) for the 7 durable containers
— FleetJobDoc, FleetRunDoc, FleetLeaseDoc, FleetFactoryDoc, FleetProfileDoc,
FleetEventDoc, FleetArtifactDoc — each carrying productId. Lifecycle stages mirror
the agent-queue gigafactory spec (queued|blocked|assigned|building|review|testing|
shipped|failed|dead_letter). Registers fleet_* containers with their partition keys
(/productId for jobs/factories/profiles, /jobId for runs/leases/events/artifacts).
2026-05-29 20:19:59 -07:00
saravanakumardb1
1846201364 chore(chat-history): refresh WINDSURF archive artifacts (workflows, env audit, repos) 2026-05-29 20:07:00 -07:00
305d3d7eaa docs: clean AIOS roadmap markdown whitespace 2026-05-29 21:40:17 +00:00
fff5d993ba docs: add ByteLyst AIOS adoption roadmap 2026-05-29 21:26:36 +00:00
fe8338c2c5 feat(monitoring): add VM Overview Grafana dashboard
12-panel dashboard auto-provisioned via /var/lib/grafana/dashboards:
  - 4 stat tiles (disk %, RAM avail, swap used, CPU steal) with
    threshold colouring matching vm-health-check.sh
  - 4 time-series (disk %, RAM trend, steal, sda write GB/hr) — 7d default
  - 2 bargauge top-10 by RAM and CPU (cAdvisor container_memory_working_set,
    container_cpu_usage)
  - Load average (1/5/15) + network throughput (RX/TX, host interfaces)

uid: vm-overview. Picked up on next Grafana boot.

Closes Phase 5: "Add Grafana" item from VM observability roadmap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 21:26:35 +00:00
f91d5d57a1 feat(infra): Phase 2.3 — add memory limits to Docker services
deploy.resources.limits.memory applied per roadmap table.
Limits derived from 2-day RSS baseline (2026-05-27-29).
Takes effect on next docker compose up — no running containers affected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 21:26:35 +00:00
saravanakumardb1
263bee6886 chore(admin-web): defer UX-6 (no feed) + complete cross-cutting CC.1-CC.6 (UX-6/CC)
- UX-6 system banners DEFERRED: platform-service (:4003) is unreachable in this
  environment, so there is no real broadcasts/maintenance feed to surface.
  Per the wave's explicit condition, banners are not added against an empty feed.
  Recorded in the waves list + Deferrals table with a follow-up.
- CC.1-CC.6 ticked: suite/build green every wave; dark-mode parity via the bridge;
  zero new color literals; a11y labels on all new controls; charts/palette/motion
  code-split via next/dynamic (chart chunk ~3.8 KB gzip); size:check has no
  bundlesize config in-repo so gzip sizes recorded inline (follow-up logged).
- Add token-bridge guard test (CC.2/CC.3): asserts every --bl-* maps to an admin
  var that flips under .dark and that the bridge contains no raw color literals.

Verify: typecheck+lint+build green (123 routes); vitest 22 files / 183 tests;
format:check no new failures (29 pre-existing); e2e 11 passed / 80 failed
(unchanged vs UX-1 baseline — environmental, no backend).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 14:24:27 -07:00
saravanakumardb1
f12009f49c docs(admin-web): tick UX-5 with SHA + test counts (UX-5) 2026-05-29 14:20:00 -07:00
saravanakumardb1
aa0e67d219 feat(admin-web): add @bytelyst/motion reveal/stagger on dashboard (UX-5)
- @bytelyst/motion added workspace:* (importer-only lockfile change;
  --frozen-lockfile clean).
- Dashboard overview only: KPI cards grid wrapped in StaggerList (from up,
  50ms stagger); the Model-Usage / Recent-Users table row wrapped in Reveal.
- Primitives honor prefers-reduced-motion and resolve to opacity 1, so no
  element is stranded transparent (no contrast/a11y regression); prefersReduced
  is SSR-safe. Motion is confined to the auth-gated dashboard, not the public
  e2e surfaces, per tracker-web's axe/opacity caution.
- vitest.config: inline @bytelyst/motion + react dedupe for the render test.

Tests: happy-dom asserts Reveal/StaggerList end visible and render all children.

Verify: typecheck+lint+build green (123 routes); vitest 21 files / 170 tests
(+2); format:check no new failures; e2e 11 passed / 80 failed (unchanged vs
UX-1 baseline — environmental).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 14:19:28 -07:00
saravanakumardb1
89a56739bd docs(admin-web): tick UX-4 with SHA + test counts (UX-4) 2026-05-29 14:10:05 -07:00
saravanakumardb1
94ef3f1c20 feat(admin-web): adopt @bytelyst/dashboard-components page chrome (UX-4)
- error.tsx -> ErrorPage (keep telemetry on mount; retry wired to Next reset).
- (dashboard)/loading.tsx -> LoadingSpinner inside the existing skeleton.
- not-found.tsx already used NotFoundPage (confirmed, unchanged).
- dashboard overview page.tsx header -> PageHeader (Refresh as actions; the
  subtitle/last-updated line preserved directly below).

Rich detail headers (e.g. users/[id] back-button + plan/status badges) left
bespoke on purpose: PageHeader has no subtitle/badge slot, so forcing it would
regress them (additive-only rule). dashboard-components reads --color-* which
admin maps via @theme inline, so it themes in light + dark.

Verify: typecheck+lint+build green (123 routes); vitest 20 files / 168 tests
(+3 happy-dom chrome render tests); format:check no new failures; e2e 11 passed
/ 80 failed (unchanged vs UX-1 baseline — environmental).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 14:09:40 -07:00
saravanakumardb1
997002e913 docs(admin-web): tick UX-3 with SHA + test counts (UX-3) 2026-05-29 13:59:30 -07:00
saravanakumardb1
b4e450d68a feat(admin-web): add @bytelyst/command-palette (Cmd-K) to dashboard (UX-3)
- Mount CommandRegistryProvider in (dashboard)/layout.tsx and a CommandMenu
  that binds the global Cmd-K / Ctrl-K hotkey (useCommandPalette) and lazy-loads
  the dialog via next/dynamic (own chunk; dynamic target is a local re-export
  command-palette-dialog.tsx because the package declares only an `import`
  export condition).
- src/lib/admin-commands.ts: pure builder for 21 navigate-mode commands across
  the major surfaces (Users, Subscriptions, Licenses, Billing, Usage,
  Broadcasts, Flags, Experiments, Audit, Ops, …) plus theme-toggle and sign-out
  actions wired to the existing auth/theme contexts; onNavigate -> router.push.
- @bytelyst/command-palette added as workspace:* (importer-only lockfile change;
  --frozen-lockfile clean).
- vitest.config: inline command-palette + dedupe react for the interaction test.

Tests: pure command-set assertions + a happy-dom Cmd-K/Ctrl-K interaction test
(react-dom/client + act, no new deps).

Verify: typecheck+lint+build green (123 routes); vitest 19 files / 165 tests
(+6); format:check no new failures; e2e 11 passed / 80 failed (unchanged vs
UX-1 baseline — environmental, no backend).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 13:58:49 -07:00
saravanakumardb1
50704c6e45 docs(admin-web): tick UX-2 with SHA + test counts (UX-2) 2026-05-29 13:47:11 -07:00
saravanakumardb1
01f79afaf3 feat(admin-web): migrate recharts to @bytelyst/charts + data-viz, drop recharts (UX-2)
Replace all 5 direct recharts usages with the shared, token-themed SVG
primitives, lazy-loaded for bundle savings:
- dashboard, usage, users/[id], ops/client-logs, extraction/entity-chart
  now render AreaChart/BarChart/Donut from @bytelyst/charts.
- new src/components/charts: next/dynamic wrappers (own chunk, ssr:false)
  that dynamic-import a local static re-export (primitives.tsx) — the chart
  packages declare only an `import` export condition, so a direct
  import('@bytelyst/charts') trips Next's resolver.
- new src/lib/chart-data.ts: pure, finite-safe data mappers (unit-tested).
- recharts removed from package.json + the admin-web lockfile importer entry
  (now fully unused). Lockfile delta is importer-only (+charts/+data-viz as
  workspace:*, -recharts); no monorepo re-normalization; --frozen-lockfile clean.
- vitest.config: inline @bytelyst/{charts,data-viz} + dedupe react so the
  SSR no-NaN render tests use a single React copy.

Fidelity notes (charts are single-series/vertical; StackedBar is charts 0.2.x):
stacked severity chart -> single bars colored by dominant severity; pie charts
-> Donut; horizontal bars -> vertical.

Verify: typecheck+lint+build green (123 routes); vitest 18 files / 159 tests
(+19); format:check no new failures; e2e 11 passed / 80 failed (unchanged vs
UX-1 baseline — failures are environmental, no backend).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 13:46:28 -07:00
saravanakumardb1
a993c5c924 docs(admin-web): tick UX-1 with SHA + test counts (UX-1) 2026-05-29 13:25:26 -07:00
saravanakumardb1
df72199cd1 feat(admin-web): --bl-* token bridge + UI-drift ratchet + baseline audit (UX-1)
Additive phase-1 foundation for ByteLyst UX integration:
- globals.css: bridge the shared --bl-* contract onto admin's shadcn OKLCH
  ramp (surfaces/borders/text/accent/danger/focus) so @bytelyst/* components
  theme correctly in light AND dark. Mappings reference admin --* vars that
  flip under .dark, so parity is inherited with zero new color literals.
  Status hues (success/warning/info) intentionally inherit design-tokens.
- eslint.config.mjs: no-restricted-imports ratchet forbidding direct
  @bytelyst/ui imports outside the Primitives.tsx adapter seam.
- primitives-exports.test.ts: export-presence guard for the adapter surface.
- roadmap: author verified baseline audit + green/red gate table + e2e baseline.

Verify: typecheck+lint+build green; vitest 17 files / 140 tests (+29);
format:check no new failures (29 pre-existing, out of scope); e2e baseline
11 passed / 80 failed (80 environmental — no backend).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 13:25:00 -07:00
saravanakumardb1
b2539f21d0 docs(admin-web): note deferred phase-2 shadcn-layer migration 2026-05-29 13:07:27 -07:00
saravanakumardb1
42aaea03e5 docs(admin-web): add ByteLyst UX integration roadmap (additive phase 1) 2026-05-29 13:05:00 -07:00
saravanakumardb1
060daa4883 docs(tracker-web): record backend enablers for UX-12.3/13.1
Mark UX-12.3 (rich-text) and UX-13.1 (NotificationCenter) as
🔒 blocked-on-backend rather than open — they are excluded from the 
count and each now carries a one-paragraph spec of the exact
platform-service change required:
- UX-12.3: server-side HTML sanitization (allowlist tags/attrs; strip
  scripts/event-handlers/js: + data: URLs) on items.description +
  comments.body write paths, so RichTextEditor/RichTextViewer can be
  safely adopted.
- UX-13.1: emit notifications into platform-service's existing
  notifications module on tracker events (new comment, status change,
  vote milestone) targeted to the item author/subscribers with productId,
  exposed via the /api/tracker proxy, so NotificationCenter binds a real
  feed.

Add BACKEND_ENABLERS.md tracking both follow-ups (title, blocking item,
target module, acceptance criteria, backward-compat constraint —
platform-service is shared by 9 products). Update the Expand tracker line
and notes to show all client-only waves complete and these two
backend-blocked. Docs only — no source/dep/lockfile changes.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:31:55 -07:00
saravanakumardb1
81b5ed0baf docs(tracker-web): tick UX-8 (AppShell) — Core wave UX-2…UX-8 complete (UX-8)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:16:18 -07:00
saravanakumardb1
cbd4274a52 feat(tracker-web): adopt @bytelyst/ui AppShell nav shell (UX-8)
Replace the hand-rolled sticky top nav in the dashboard layout with the
shared AppShell (AppShellSidebar/AppShellNav/AppShellNavItem/AppShellMain/
AppShellSkipLink + mobile toggle + overlay). The sidebar keeps the
ProductSwitcher, user email and Sign out, and adds a ⌘K trigger (replays
the global hotkey) and a theme toggle. Nav items use aria-current for the
active route and client-side navigation; the skip-link targets the
focusable main region. AppShell exports are routed through the Primitives
adapter (CC.6 ratchet) and covered by the export-presence test.

AppShellPageHeader is intentionally not used so the per-page PageHeader
(UX-10) remains the single h1 per route (no duplicate headings).

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:15:43 -07:00
saravanakumardb1
bfccd48b37 docs(tracker-web): tick UX-7 (motion) with SHA + a11y deviation note (UX-7)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:13:13 -07:00
saravanakumardb1
002b55c3c0 feat(tracker-web): reduced-motion-aware motion polish (UX-7)
Add @bytelyst/motion (workspace:* + minimal lockfile importer entry).
Apply Reveal to the dashboard overview cards/charts (staggered) and the
items DataTable, and NumberFlow to the overview KPI totals. All motion
primitives no-op under prefers-reduced-motion.

The public /roadmap is intentionally left without entrance motion: the
offline @axe-core gate scans the page synchronously and the Reveal
transient sub-1 opacity trips color-contrast (a hard CC.4 a11y gate). The
dashboard/items surfaces are auth-gated and not axe-scanned, so they keep
the motion.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:12:31 -07:00
saravanakumardb1
9ac311f138 docs(tracker-web): tick UX-6 (toasts) with SHA + test counts (UX-6)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:03:45 -07:00
saravanakumardb1
3fc559d066 feat(tracker-web): toasts replace inline status divs (UX-6)
Mount the shared ToastProvider in providers.tsx and replace the inline
error/success banners across the overview, items list, board, item detail
and public roadmap with toast() calls — load errors, create, delete, vote,
status/priority/visibility updates, comment add, and idea submission. The
roadmap submit now toasts + closes the dialog instead of an in-modal
banner; the item-detail page keeps a single inline empty-state for the
hard "couldn't load this item" case.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 07:03:16 -07:00
saravanakumardb1
fd7f12513d docs(tracker-web): tick UX-5 wave (5.1-5.3) with SHA + test counts (UX-5)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:56:49 -07:00
saravanakumardb1
a7cb866cab feat(tracker-web): ⌘K command palette (UX-5)
Add @bytelyst/command-palette (workspace:* + minimal lockfile importer
entry). Mount CommandRegistryProvider + a lazily-loaded CommandMenu in
providers.tsx, opened with ⌘K / Ctrl-K. Register navigate commands
(Overview/Items/Board/Roadmap), New item (navigates to items with ?new=1
which auto-opens the create modal), Toggle theme, Sign out, and per-product
Switch commands wired to setProductId. Command building lives in the pure
src/lib/command-registry.ts. Add command-menu.test.tsx (jsdom) asserting the
builder set and that the palette opens on ⌘K and lists commands.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:56:11 -07:00
saravanakumardb1
dfdc9777c4 docs(tracker-web): tick UX-4 wave (4.1-4.3) with SHA + test counts (UX-4)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:52:13 -07:00
saravanakumardb1
f2dfddf944 feat(tracker-web): data-viz overview with charts + KpiCards (UX-4)
Add @bytelyst/charts + @bytelyst/data-viz as workspace:* deps (minimal
importer link entries in the lockfile). Replace the badge-pill breakdowns
on /dashboard with KpiCards (total/open/in-progress/done) and a dynamically
imported chart surface: Donut for By Status + By Type (centered total) and
a BarChart for By Priority, coloured from the bridged --bl-chart-* palette.

Pure transforms live in src/lib/overview-charts.ts (finite-coerced, no NaN
reaches the SVG); the heavy chart surface is split into overview-charts.tsx
and loaded via next/dynamic (ssr:false) to keep it out of the route bundle.
Add overview-charts.test.tsx rendering the surface with mocked stats via
react-dom/server (no NaN in paths) + transform unit tests; dedupe react in
vitest so the SSR render uses a single React instance.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:51:39 -07:00
saravanakumardb1
95084d38b3 docs(tracker-web): tick UX-3 wave (3.1-3.2) with SHAs + test counts (UX-3)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:47:12 -07:00
saravanakumardb1
51c30ed73d feat(tracker-web): roadmap submit + email-prompt modals via shared Modal (UX-3.2)
Replace the bespoke local Modal (and its slate/blue/white chrome) with the
shared @bytelyst/ui Modal (Radix dialog — focus-trap/Esc/scroll-lock) for
both the Submit Idea and vote email-prompt dialogs. The dialog titles
become the accessible heading; form fields move to Input/Select/Textarea
and the submit-result message to AlertBanner. Behaviour preserved.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:46:39 -07:00
saravanakumardb1
f612d2ecd1 feat(tracker-web): re-skin public roadmap to the token system (UX-3.1)
Replace the hardcoded slate-*/blue-*/white utility classes on /roadmap
with tokenized equivalents (bg-background/bg-card/text-foreground/
text-muted-foreground/border-border). Swap the type/priority pills to the
shared Badge, the status column/list markers to StatusDot tones, the stat
tiles to MetricCard, search/type filter to Input/Select, the Submit Idea
button to Button, and load/vote errors to AlertBanner. Behaviour, the
board/list SegmentedControl toggle, and the vote-button a11y attrs
(aria-pressed/aria-label) are preserved. The submit + email-prompt modals
are migrated to the shared Modal in UX-3.2.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:44:22 -07:00
saravanakumardb1
8354595d0f docs(tracker-web): tick UX-2 wave (2.1-2.4) with SHAs + test counts (UX-2)
Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:39:58 -07:00
saravanakumardb1
aa36671e95 feat(tracker-web): migrate board + item detail to primitives (UX-2.3)
Board: type/priority pills → StatusDot/StatusBadge tones, count pill →
Badge, quick status-move buttons → Button, load errors → AlertBanner
(keeping the existing TooltipProvider + column accents).

Item detail: title/description editor → Input/Textarea/Button, the
status/priority/visibility selects → shared Select, the vote control →
Button, comment composer → Textarea/Button, errors → AlertBanner.
ActionMenu + Timeline (UX-12.2) are untouched.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:39:15 -07:00
saravanakumardb1
c9e65d435c feat(tracker-web): overview MetricCard + ConfirmDialog delete (UX-2.2)
Replace the bespoke total-count card chrome with the shared MetricCard on
the dashboard overview (breakdown cards stay until the UX-4 chart swap),
and surface load errors via AlertBanner. Wrap the items-list delete
confirm() in the accessible ConfirmDialog (focus-trapped AlertDialog)
instead of the native browser prompt.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:36:18 -07:00
saravanakumardb1
a7a6f191ca feat(tracker-web): migrate items page controls + create modal to primitives (UX-2.1)
Replace the raw search input, the three filter selects, the New Item
button, and the hand-rolled create modal with @bytelyst/ui Input/Select/
Field/Button/Modal (via the Primitives adapter). The shared Modal closes
the focus-trap/Esc/scroll-lock a11y gap. Swap the inline type/status/
priority cell pills to StatusBadge with token-driven tones.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-29 06:33:20 -07:00