FE-846: Web revamp pass II#195
Conversation
…-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
PR SummaryMedium Risk Overview Refreshes the web sidecar UI to match structured spec patterns from the prior trunk: global Docs ( Reviewed by Cursor Bugbot for commit c506aab. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
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 frompackage.jsonand 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.
| }: { | ||
| title: string; | ||
| description: string; | ||
| action?: React.ReactNode; | ||
| }) { |

Summary