Skip to content

FE-846: Web revamp pass II#195

Merged
lunelson merged 23 commits into
nextfrom
ln/fe-846-web-revamp-ii
Jun 11, 2026
Merged

FE-846: Web revamp pass II#195
lunelson merged 23 commits into
nextfrom
ln/fe-846-web-revamp-ii

Conversation

@lunelson

@lunelson lunelson commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replace the graph overview with the read-only structured spec web view.
  • Add global Brunch header chrome and nested route layout for spec list/detail views.
  • Keep web mode scoped to the TUI-driven sidecar and inject the package version at build time.

lunelson and others added 23 commits June 9, 2026 14:49
…-query projection

- Convert session-query/introspect-query params from TypeBox to Zod via
  new shared/pi-tool-schema.ts adapter; z.toJSONSchema emits draft 2020-12
  (prefixItems), which Anthropic's strict validator requires.
- Normalize session-query entry view: flatten message fields + entry
  sidecars so the same select grammar (content[0].text, details, role)
  works across message and custom entries, and no-select returns that
  same view.
- Reconcile SPEC I26-L, extensions README adapter notes, and add schema
  + projection regression tests.

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
getBranch() already returns SessionEntry[]; the prior code erased it to a
local Record<string, unknown> alias via an as-unknown-as cast, so every
helper operated on an untyped bag with no drift protection.

- Import SessionEntry and type the query boundary (querySessionBranch,
  countMatchingEntries) and all entry helpers on it.
- Replace the dynamic messageForEntry shape-sniff with .type narrowing in
  queryableEntry: only message entries nest under .message. If Pi renames
  that field or restructures the union, this now breaks the build.
- Keep the dotted-path projector on unknown (LLM-supplied paths are
  inherently dynamic) and route predicate/ref/text reads through the one
  normalized flat view.
- Fixtures derive their entry envelope from SessionEntry; the single
  faux-message cast is isolated to the test helper.

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
The find.role enum was hand-authored and had drifted (missing branchSummary,
compactionSummary). Derive EntryRole from SessionEntry's message role, declare
an ENTRY_ROLES object as const satisfies Record<EntryRole, true> (a missing or
stray role is now a build error), and build the Zod enum from its keys so the
runtime predicate contract cannot diverge from the type.

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
The Pi session header is not part of getEntries() (which returns
SessionEntry[]); it is only reachable via getHeader(). projectSessionContext
searched getEntries() for a type:'session' entry that can never appear, so a
real bound session always projected not_ready / missing_session_header. The
local SessionManagerLike interface typed getEntries() as FileEntry[], which
hid the impossibility from the compiler.

- Read the header via getHeader(); keep getEntries() for the binding.
- Correct SessionManagerLike to the real getHeader()/getEntries() surface.
- Fix the read_session_context tests, which fabricated the header inside
  getEntries() (a fixture wider than the real contract), and add a
  null-getHeader regression for the missing_session_header path.

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
… header

resolveWorkspaceCwd searched getEntries() for the Pi session header to read its
cwd, but getEntries() never contains the header (SessionEntry[]); it is only on
getHeader(). The lookup always missed, so the tool silently fell back to
process.cwd() and inventoried the wrong directory under a --cwd launch.

- Resolve cwd via getHeader(); correct SessionManagerLike accordingly.
- Update read_workspace_context tests, which fabricated the header inside
  getEntries() (wider than the real contract).

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
…nager

Mock-based fakes (getEntries: () => [...]) let the header bugs through because
they could assert a shape the real API never produces. This test drives the
context tools against the faux harness's real SessionManager.inMemory, where the
Pi header is genuinely behind getHeader() and absent from getEntries(). It
asserts read_session_context reaches a ready frame and read_workspace_context
resolves cwd from the header (finds the temp-workbench markdown) — both
impossible under the old getEntries()-search code.

Bonus: with getEntries() correctly typed SessionEntry[], searching it for a
'session' entry is now a compile error, so the root cause is caught statically.

Amp-Thread-ID: https://ampcode.com/threads/T-019eac9a-2407-766b-9be6-be7faeb2615e
Co-authored-by: Amp <amp@ampcode.com>
Web view:
- Replace GraphOverview with read-only structured spec view (KnowledgeGraphView)
- Add global header chrome with canonical brunch logo, app-meta, icons
- Nested route shape: global header over index spec-list and /$id spec view
- Shell owns scroll; NodeRefChip on node cards

Mode flag:
- Remove standalone --mode web dispatch; defer web-only mode as future feature
- Web ships only as the TUI-driven sidecar
- Update app/web-host docs and pi-seam-extensions accordingly

Build:
- Inject __BRUNCH_VERSION__ in vite.config from package.json

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019eb0d3-781e-7747-b86d-4330fb423eea

lunelson commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@lunelson lunelson marked this pull request as ready for review June 10, 2026 18:57
Copilot AI review requested due to automatic review settings June 10, 2026 18:57
@cursor

cursor Bot commented Jun 10, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
CLI behavior change (--mode web now errors) may break scripts or docs that assumed a headless web host; web routing and graph presentation are substantially reworked though still read-only over RPC.

Overview
Defers standalone --mode web and documents three live CLI modes (TUI default, RPC, print). brunch --mode web now throws with guidance to use the TUI; the injectable webHostRunner path is removed from brunch.ts and tests. The browser is described everywhere as a read-only TUI sidecar (startWebHost stays on the TUI launch path).

Refreshes the web sidecar UI to match structured spec patterns from the prior trunk: global AppHeader (logo, app-meta, version from Vite __BRUNCH_VERSION__), index route as a spec list only, and /spec/$id using KnowledgeGraphView (kind filter chips, collapsible sections, NodeRefChip) instead of GraphOverviewPanel. Session/workspace debug panels are dropped from the web shell; root layout owns scroll (overflow: hidden on html/body).

Docs (prd.md, app/ / web/ READMEs, M3 demo scenario) and a minor web-host error string align with the sidecar-only product story.

Reviewed by Cursor Bugbot for commit c506aab. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reshapes the browser surface to be a read-only, TUI-driven web sidecar and aligns the web UI with the structured spec/knowledge-graph presentation patterns (global header + spec list + structured graph view). It also removes standalone --mode web execution and injects the app version into the web bundle at build time.

Changes:

  • Replace the prior graph overview panel with a read-only structured knowledge-graph list view and add a global header layout for all web routes.
  • Scope web usage to the TUI sidecar by rejecting standalone --mode web, and update related docs/error messaging accordingly.
  • Inject __BRUNCH_VERSION__ into the Vite build from package.json and surface it in the web header.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
vite.config.ts Injects __BRUNCH_VERSION__ via Vite define from package.json.
src/web/styles.css Moves scrolling ownership into the app shell by disabling html/body scroll.
src/web/routes/spec.tsx Switches spec route rendering to KnowledgeGraphView and updates invalid-id layout.
src/web/routes/root.tsx Introduces global header chrome and simplifies the index route to a spec list.
src/web/README.md Updates web docs to describe the TUI sidecar posture and new module topology.
src/web/features/graph/structured-list-view.tsx Adds the new read-only structured knowledge-graph list UI.
src/web/features/graph/kind-display.ts Adds presentation-only grouping/ordering and plural labels for node kinds.
src/web/features/graph/GraphOverview.tsx Removes the prior GraphOverviewPanel implementation.
src/web/components/node-card.tsx Adds NodeRefChip for consistent node reference presentation.
src/web/components/icons.tsx Adds a small inline SVG icon set (no external icon dependency).
src/web/components/app-header.tsx Adds global header (logo + name/version/tagline + abbreviated cwd).
src/web/app.test.tsx Updates web app tests for the new header/index/spec view behavior.
src/web/app-meta.ts Adds app identity constants and __BRUNCH_VERSION__ fallback wiring.
src/rpc/web-host.ts Updates missing-bundle guidance to refer to the “web sidecar”.
src/app/README.md Updates app entrypoint documentation to reflect deferred web mode.
src/app/brunch.ts Rejects --mode web with a “not available yet” error; removes web host dispatch.
src/app/brunch.test.ts Updates CLI tests to assert --mode web is rejected.
docs/architecture/prd.md Updates PRD to reflect web as a TUI sidecar now, with planned standalone web mode later.
docs/architecture/pi-seam-extensions.md Minor wording alignment with updated mode posture.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +230 to +234
}: {
title: string;
description: string;
action?: React.ReactNode;
}) {
@lunelson lunelson changed the title Align web view with structured spec patterns; scope web to TUI sidecar FE-846: Web revamp pass II Jun 11, 2026
Base automatically changed from ln/fe-825-dx-introspection-live to next June 11, 2026 12:17
@lunelson lunelson merged commit e37b905 into next Jun 11, 2026
12 of 13 checks passed
@lunelson lunelson deleted the ln/fe-846-web-revamp-ii branch June 11, 2026 12:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants