Skip to content

FE-735: Mode shell and fixture driver (M1)#144

Open
lunelson wants to merge 18 commits into
ln/fe-729-walking-skeletonfrom
ln/fe-735-mode-shell-fixture-driver
Open

FE-735: Mode shell and fixture driver (M1)#144
lunelson wants to merge 18 commits into
ln/fe-729-walking-skeletonfrom
ln/fe-735-mode-shell-fixture-driver

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

FE-735: Add print snapshot transport shell

FE-735: Add named JSON-RPC stdio skeleton

FE-735: Project elicitation exchanges from JSONL

FE-735: Project real Pi JSONL exchanges

FE-735: Scope session exchange RPC to current session

FE-735: Add RPC print snapshot parity smoke

FE-735: Add fixture capture bundle skeleton

FE-735: Seed deterministic fixture briefs

FE-735: Scope capture seam review fixes

FE-735: Stabilize current session capture

FE-735: Reconcile fixture brief format docs

FE-735: Use Pi session entry types for exchange projection

FE-735: Report Brunch-owned fixture metadata version

FE-735: Capture scripted brief runs

Copy link
Copy Markdown
Contributor Author

lunelson commented May 21, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

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

@lunelson lunelson changed the title FE-735: Add print snapshot transport shell FE-735: Mode shell and fixture driver (M1) May 27, 2026
@lunelson lunelson marked this pull request as ready for review May 27, 2026 16:31
@cursor
Copy link
Copy Markdown

cursor Bot commented May 27, 2026

PR Summary

Medium Risk
Touches core boot/session selection and new stdio RPC surface; risk is mitigated by coordinator seam, tests, and runbook, but wrong session reopen or projection drift would break fixtures and headless clients.

Overview
Delivers M1 (mode shell + fixture driver): the Brunch CLI now dispatches --mode print (workspace snapshot, no agent turn) and --mode rpc (newline JSON-RPC over stdio) through the same host and WorkspaceSessionCoordinator, with named workspace.snapshot and session.elicitationExchanges handlers that project product state from Pi JSONL—not raw file paths.

Adds elicitation exchange projection from transcript entries (prompt/response spans, open-prompt detection), fixture brief loading (JSON under .brunch-fixtures/briefs/), and capture that copies the coordinator-selected session JSONL plus .meta.json (driver mode, projection summary, deferred graph/coherence). Coordinator changes persist currentSessionFile in .brunch/state.json, reopen the selected session on headless paths, and support createNewSpec for scripted brief runs.

Golden fixtures: three curated briefs and scripted-001 replay bundles; docs/plan/spec updated (YAML→JSON briefs, transport vs agent mode, M1 complete → jsonl-session-viability active). runbooks/verify-m1.sh and broad unit/integration tests cover RPC contracts, print/RPC parity, capture, and replay projection parity.

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

@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 27, 2026

🤖 Augment PR Summary

Summary: This PR delivers M1 “mode shell + fixture driver” support by adding headless transport modes and the first deterministic fixture capture loop.

Changes:

  • Adds runBrunchCli() with --mode print (snapshot-only) and --mode rpc (newline JSON-RPC over stdio), while keeping TUI mode intact.
  • Introduces a product-shaped WorkspaceSnapshot projection and a human-readable print renderer.
  • Adds a minimal JSON-RPC adapter with named methods (workspace.snapshot, session.elicitationExchanges) scoped to the coordinator-selected session.
  • Implements elicitation-exchange projection over Pi JSONL transcripts and disk loader utilities.
  • Adds fixture brief library loading (JSON briefs) and a fixture capture path that writes .jsonl + .meta.json bundles.
  • Seeds three deterministic briefs and commits scripted capture bundles under .brunch-fixtures/.
  • Extends the workspace session coordinator to persist/reopen the selected session file via .brunch/state.json.
  • Adds a runbook (runbooks/verify-m1.sh) plus unit tests covering print/RPC parity and fixture replay/projection parity.

Technical notes: The RPC surface is intentionally thin (named method families over projections), and print mode is treated as a transport proof-of-life rather than an agent turn.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

): Promise<WorkspaceSessionReadyState["session"]> {
await ensureWorkspaceDirs(cwd)
const files = await listSessionFiles(cwd)
const manager = currentSessionFile
Copy link
Copy Markdown

@augmentcode augmentcode Bot May 27, 2026

Choose a reason for hiding this comment

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

currentSessionFile is read from .brunch/state.json, so a stale/tampered path here can throw (breaking print/RPC) and also cause bindSessionToSpec to rewrite an unexpected file. Consider guarding that it exists and is within .brunch/sessions/ (and falling back when invalid) before calling SessionManager.open().

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

}

function isPromptSideEntry(entry: SessionEntry): boolean {
if (isCustomTranscriptEntry(entry) && entry.customType.includes("prompt")) {
Copy link
Copy Markdown

@augmentcode augmentcode Bot May 27, 2026

Choose a reason for hiding this comment

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

isPromptSideEntry() only treats custom(_message) entries as prompt-side when customType contains "prompt", so other model-visible injected custom_message entries (e.g. brunch/world_update/v1) would be omitted from promptEntryIds/ranges. If those injections are meant to be part of the prompt span between user turns, the current projection will silently drop them.

Severity: medium

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e32eb02. Configure here.


const role = roleOf(entry)
return role === "assistant" || role === "toolResult"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Prompt-side classification uses fragile substring match

Medium Severity

isPromptSideEntry uses customType.includes("prompt") as a substring match, while isResponseSideEntry uses an explicit Set (STRUCTURED_RESPONSE_TYPES). This asymmetry means any future custom entry type containing "prompt" anywhere in its name (e.g. brunch.prompt_history, brunch.user_prompt_feedback) would silently be classified as prompt-side, potentially corrupting exchange projections. The response side is already guarded against this with an allowlist pattern.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e32eb02. Configure here.

Comment thread runbooks/verify-m1.sh
)
workspace.session.manager.appendMessage({ role: "user", content: "Runbook response" })
await coordinator.bindCurrentSpecToSession(workspace.session.manager)
NODE
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Runbook setup failure silently skipped without error check

Low Severity

The workspace setup block (the node heredoc that creates a temp workspace, appends entries, and binds the spec) runs outside run_check and without set -e. If this step fails, the exit code is silently ignored and subsequent run_check blocks (print-mode smoke, RPC smoke) run against a broken or empty workspace, producing misleading failure messages instead of attributing the root cause.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e32eb02. Configure here.

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.

1 participant