Commit graph

11 commits

Author SHA1 Message Date
Nexus Dev
fb76b5eeef refactor(nexus): wave 3a controller integration pass
Three coordinated fixes after phases 12, 13, 14, 15 all landed in
parallel on nexus/design-system-migration:

1. TopStrip.test.tsx provider stubs for phase 14 contexts.

Phase 14 wired CmdKButton to a new CommandPaletteContext via the
useCommandPalette() hook. TopStrip renders CmdKButton internally,
so its existing tests (written in phase 8 before the context
existed) throw "useCommandPalette must be used within a
CommandPaletteProvider" on every case. Same issue on GlobalMicButton
which now reads from VoiceContext.

Fix: add module-scope vi.mock() stubs for both contexts returning
minimal shapes, matching the existing CompanyContext mock pattern
already in the file. No test semantics change - the TopStrip is
still rendered in isolation, still verified to contain the three
children (ModeBreadcrumb, CmdKButton, GlobalMicButton) and the
header landmark. All 4 TopStrip tests pass again.

Phase 15's report flagged this breakage explicitly and confirmed
via git stash that it was pre-existing on phase 14's HEAD, not
introduced by phase 15.

2. PromoteTransition mobile variant.

Phase 15 deferred the mobile variant of the promote-to-project
transition because PromoteTransition.tsx did not yet exist when
phase 15 started (phase 12 created it mid-dispatch). The defer
was correct per explicit instructions.

Fix: add a CSS media query inside the existing scoped <style>
block in PromoteTransition.tsx:

  @media (max-width: 767px) {
    .nx-promote-ribbon[data-pstate="prompting"],
    .nx-promote-ribbon[data-pstate="creating"] {
      max-height: 0;
      box-shadow: none;
      overflow: hidden;
    }
    .nx-promote-label[data-pstate="prompting"],
    .nx-promote-label[data-pstate="creating"] {
      display: none;
    }
  }

On mobile the brainstormer completely covers the chat thread
instead of sharing a 30/70 split, per spec section 9.1. The panel
itself already takes the remaining viewport height via flex, so
once the ribbon collapses to zero the brainstormer naturally
fills the whole area.

Pure CSS - no JS media query, no useMediaQuery call, no test
changes needed. Single 768px breakpoint matches the rest of the
Nexus frame.

3. Layout.tsx onSearch now calls useCommandPalette().setOpen(true)
   directly instead of dispatching a synthetic Cmd+K keydown.

Phase 14 installed a real command palette context with a provider
mounted in main.tsx, but left Layout.tsx's onSearch callback using
the old synthetic keydown shim because Layout is phase 15-owned
(parallel dispatch rules). The synthetic dispatch worked end-to-end
because the provider's global keydown listener catches it, but it's
a code smell: a Layout-level callback generating a synthetic event
for a listener the Layout also owns.

Fix: import useCommandPalette, hold a commandPalette ref in the
Layout body, and replace the synthetic keydown dispatch with
commandPalette.setOpen(true). Drop the Phase 8 shim comment; leave
a single-line Phase 14 explanation.

All 294 tests pass across 37 test files (frame, assistant, studio,
projects, settings, Voice/CommandPalette contexts, home-status and
gate-indicator and promote-to-project hooks, StudioWorkshopDetail
page). Typecheck clean across every wave 1-3A file plus App.tsx
and Layout.tsx.

Known deferrals not addressed in this commit:
  - MobileTabBar does not port MobileBottomNav's "new issue" FAB or
    inbox badge count. Spec section 9.1 says 4 destinations only;
    requires user decision on whether to restore as a separate mobile
    affordance or route through the command palette.
  - VoiceMicButton.tsx and useVadRecorder.ts are now dead code after
    phase 14's ChatInput migration. Both are in the phase 16 cleanup
    plan's deletion list.
  - Destination regexes are duplicated between IconRail and
    MobileTabBar. Phase 16 DRY target via a shared frame/destinations
    module.
  - Phase 13 left ui/src/lib/instance-settings.ts whitelisting
    /heartbeats and /experimental paths. Redirect routes catch these,
    so the whitelist is cosmetic; phase 16 cleanup target.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:32:46 +00:00
Nexus Dev
45d2a9ff24 refactor(nexus): wire frame buttons to phase 14 contexts
GlobalMicButton drops the state and onClick scaffolding props from
phase 8 and now consumes VoiceContext directly — click calls
toggleListening(). It also reflects hasQueuedVoice via the idle dot
color and an updated aria-label so the assistant-bound queue is
observable from any route.

CmdKButton replaces the synthetic Meta+K keydown shim with a direct
setOpen(true) call on the CommandPaletteContext. The shim comment
block is gone; no more document dispatch side effects on click.

Tests updated to render inside their respective providers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:23:04 +00:00
Nexus Dev
4623c8aea0 feat(nexus): add mobile tab bar and sheet variants (phase 15)
Replace legacy MobileBottomNav with the new 4-destination MobileTabBar
that mirrors the desktop IconRail (Assistant, Studio, Projects,
Settings). Adds volt active states with a 2px bar above the icon,
safe-area bottom padding, and scroll-hide wiring via the existing
mobileNavVisible handler in Layout.

Adapts Phase 9 HistorySheet and MemorySheet to a full-screen variant
below 768px via useMediaQuery, and makes Phase 11 BuilderTabStrip
horizontally scrollable with scroll-snap and edge fade on mobile.
Light TopStrip polish (tighter padding, truncating breadcrumb)
completes the mobile frame.

PromoteTransition mobile variant is deferred — Phase 12 had not yet
landed when Phase 15 started; the controller can add the mobile
branch when merging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 13:21:28 +00:00
Nexus Dev
1b7e3d44fe refactor(nexus): wire wave 2 routing and icon rail gate indicator
Controller integration pass after the three wave 2 subagents (phases
9, 10, 11) completed their phase implementations. Three changes in
one commit because they're a single coordinated post-dispatch step:

1. App.tsx routing
   - Adds 5 new per-project builder tab routes for phase 11:
       projects/:projectId/agents
       projects/:projectId/gates
       projects/:projectId/costs
       projects/:projectId/activity
       projects/:projectId/org
     plus their unprefixed UnprefixedBoardRedirect variants so
     direct nav and deep links resolve through the same fallback
     chain as /overview and /issues.
   - Adds content-studio/:workshopSlug as a sibling route for
     phase 10's workshop detail view. Without this, clicking a
     workshop card hit the * fallback NotFoundPage because the
     existing content-studio route was an exact match and the
     ContentStudio-internal pathname workaround couldn't fire.
   - Does NOT rename the legacy /convert route. ConvertPage still
     renders directly at /convert for backwards compat; Studio's
     Convert workshop reuses the ConvertPanel body inside its own
     detail shell.

2. IconRail volt-dot indicator
   - Imports useCompany from CompanyContext and useGateIndicator
     from the new phase 11 hook.
   - When selectedCompanyId resolves to a company with at least
     one pending approval (displayed as "gates" per phase 11's
     display rename), renders a 6px volt dot overlay in the
     top-right of the Assistant destination icon and updates
     the link's aria-label to "Assistant (pending gates)".
   - This is the single global notification surface specified by
     spec section 10.4 - no badge counts, no inbox icons, no toasts.

3. IconRail.test.tsx
   - Mocks useGateIndicator at module scope so tests don't need
     a QueryClientProvider for the rail's useQuery-backed data.
   - Replaces the plain function mock with a vi.fn() spy so
     per-suite overrides can flip hasPendingGates without dynamic
     imports.
   - Adds a sibling describe block that verifies the volt dot
     renders and the aria-label updates when hasPendingGates is true.
   - 7 original tests pass; 2 new tests cover dot-absent and
     dot-present cases. 9 tests total.

Verification: 211/211 tests passing across 22 files in the combined
frame + assistant + studio + projects suites; tsc clean on every
wave 1 and wave 2 file plus App.tsx.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:32:56 +00:00
Nexus Dev
c521ae4403 feat(nexus): add TopStrip composite for layout overhaul (phase 8)
48px sticky top strip per docs/specs/2026-04-11-nexus-layout-overhaul.md
§4.2. Composes ModeBreadcrumb (left) + CmdKButton and GlobalMicButton
(right) inside a <header aria-label="Top bar"> landmark.

Completes the frame component set for Phase 8. The next task (task 6)
rewrites Layout.tsx to mount IconRail + TopStrip as the new global
chrome and delete the old sidebar/ChatPanel/PropertiesPanel/
BreadcrumbBar combination.

Part of Phase 8 of the Nexus layout overhaul (task 5 of 7).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:17:09 +00:00
Nexus Dev
bfcdf1f598 feat(nexus): add GlobalMicButton scaffold for layout overhaul (phase 8)
Visual-only mic button for the top strip per
docs/specs/2026-04-11-nexus-layout-overhaul.md §4.2. Renders three
specified states (idle / listening / speaking) but Phase 8 only
wires the idle state functionally. Phase 14 will toggle the state
prop from the voice pipeline without changing this component's
signature.

Uses text-primary/bg-primary for volt (already migrated in phases
1-3) and literal #166534 / #a0a0a0 for forest and silver, which
MIGRATION-PLAN.md §3 proposes as new semantic tokens that have not
yet shipped.

Part of Phase 8 of the Nexus layout overhaul (task 4 of 7).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:15:15 +00:00
Nexus Dev
c1647e70d7 feat(nexus): add CmdKButton shim for layout overhaul (phase 8)
Top-strip button that renders the ⌘K glyph and opens the existing
CommandPalette by dispatching a synthetic Meta+K keydown on document,
which CommandPalette.tsx already listens for at its useEffect
(lines 42-51). This is explicitly a Phase 8 shim; Phase 14 of
docs/specs/2026-04-11-nexus-layout-overhaul.md replaces it with a
proper command-palette context when globalizing the palette's
search index.

Part of Phase 8 of the Nexus layout overhaul (task 3 of 7).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:12:55 +00:00
Nexus Dev
1de78f855f fix(nexus): tighten settings-route guard in ModeBreadcrumb (phase 8)
Code-quality review for Task 2 caught a startsWith false-positive:
`/instance/settings-foo` was matching the settings branch of
deriveBreadcrumbSegments and producing nonsense output like
["SETTINGS", "-FOO"]. Tightened the guard to require an exact
match or a literal trailing slash before entering the settings
branch.

Added three test cases to lock it in:
  - /instance/settings (exact, no trailing) -> ["SETTINGS"]
  - /instance/settings-foo -> ["HOME"]
  - /instance/settings-foo/bar -> ["HOME"]

22 tests pass. No behavior change for any previously-tested path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:11:06 +00:00
Nexus Dev
bd4e7c5c5d feat(nexus): add ModeBreadcrumb for layout overhaul (phase 8)
Uppercase slash-separated breadcrumb that derives from the current
pathname per docs/specs/2026-04-11-nexus-layout-overhaul.md §4.2.
Leaf segment in text-primary (volt), non-leaf segments in
text-muted-foreground (silver). Pure function deriveBreadcrumbSegments
is exported for unit testing and covers 16 route patterns plus the
catch-all HOME fallback.

The derivation intentionally collapses Phase 11's soon-to-be-demoted
routes (issues/agents/routines/goals/approvals/costs/activity/inbox/
execution-workspaces) under the PROJECTS umbrella segment. When
Phase 11 lands and those routes become /projects/:slug/<tab>, the
derivation will naturally produce PROJECTS / PROJECT-SLUG without
code changes.

Part of Phase 8 of the Nexus layout overhaul (task 2 of 7).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:04:31 +00:00
Nexus Dev
9c1525a0f9 refactor(nexus): apply Task 1 code-quality fixes to IconRail (phase 8)
Addresses two Important findings from the Task 1 code-quality review:

1. Swap literal #faff69 hex for the text-primary / bg-primary token
   (4 sites). The --primary CSS variable is already wired to volt via
   MIGRATION-PLAN.md phases 1-3, and 50+ existing files use the token.
   The original Task 1 commit landed on literal hex as a self-
   documenting placeholder; moving to the token aligns with the rest
   of the codebase and makes theme swaps a single-file change.

2. Add focus-visible styles to the Nexus mark link and each
   DestinationLink. Previously the component relied on browser-default
   outline, which on pure-black canvas + volt icons is both off-palette
   and visually weak. Now uses a volt ring with background offset for
   clear keyboard focus indication.

No behavior change. All 7 IconRail tests still pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:01:17 +00:00
Nexus Dev
332ed47bc0 feat(nexus): add icon rail component for layout overhaul phase 8
Introduces the 56px left icon rail specified in
docs/specs/2026-04-11-nexus-layout-overhaul.md §4.1. Four primary
destinations (Assistant, Studio, Projects, Settings) rendered as Lucide
icons with silver default + volt active state and a 2px volt bar on the
right edge of the active item. Destinations are company-prefixed except
Settings, which points at the global /instance/settings/general route.

The Studio icon also highlights on /convert because Phase 10 folds
ConvertPage into Studio as a workshop. The Projects icon is the umbrella
for all Phase 11 per-project-tab routes (issues, agents, routines,
goals, approvals, costs, activity, inbox, execution-workspaces).

The rail is not yet mounted in Layout.tsx — that happens in task 6.

Part of the Nexus v1.7 structural overhaul (Phase 8 of MIGRATION-PLAN.md
§8b). Companion tests cover all 4 destinations, active-state derivation,
and aria-current semantics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 10:52:18 +00:00