Skip to content

FE-737: Web shell over the same host (M3)#147

Merged
lunelson merged 36 commits into
nextfrom
ln/fe-737-web-shell
Jun 2, 2026
Merged

FE-737: Web shell over the same host (M3)#147
lunelson merged 36 commits into
nextfrom
ln/fe-737-web-shell

Conversation

@lunelson
Copy link
Copy Markdown
Contributor

FE-737: Start web shell frontier

FE-737 reject non-linear transcript JSONL

FE-737 fail fast on non-linear session RPC

FE-737 block TUI branch flows

Comment thread src/web-host.ts Outdated
}

function websocketHandshakeResponse(key: string): string {
const accept = createHash("sha1")
Copy link
Copy Markdown

@semgrep-code-hashintel semgrep-code-hashintel Bot May 21, 2026

Choose a reason for hiding this comment

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

The use of a weak cryptographic algorithm (e.g., SHA-1 or MD5) has been identified. These algorithms are considered insecure due to vulnerabilities that make them susceptible to collision attacks, allowing attackers to compromise data integrity or security. Replace SHA-1 or MD5 with secure hashing algorithms, such as: SHA-256 or higher (e.g., SHA-3).

Fixed in commit ec2f985

@lunelson lunelson changed the title FE-737: Start web shell frontier FE-737: Web shell over the same host (M3) May 27, 2026
@lunelson lunelson marked this pull request as ready for review May 27, 2026 16:30
@cursor
Copy link
Copy Markdown

cursor Bot commented May 27, 2026

PR Summary

Medium Risk
Touches session/RPC contracts and transcript policy (linear-only, explicit session targeting) that TUI, fixtures, and the new web client all share; regressions would affect every read surface, though coverage is broad.

Overview
M3 web shell (FE-737) adds brunch --mode web: a native React app (TanStack Router + Query) served as static assets with a WebSocket-backed JSON-RPC client—no REST product reads and no pi-web-ui. The build pipeline gains vite builddist-web, wired into npm run build.

Session-facing reads are tightened around a canonical Brunch session envelope (readBrunchSessionEnvelope): one Pi header, one brunch.session_binding, validated shapes, and fail-fast linear transcript checks. Active-branch / flattening projection is removed; elicitation and transcript display go through linear loaders and explicit { sessionId, specId } RPC targets (session.elicitationExchanges, session.transcriptDisplay). Non-linear JSONL surfaces a product error on RPC (and tests cover stdio/WebSocket).

JSON-RPC dispatch/response helpers move to json-rpc-protocol.ts; TUI hooks cancel session_before_tree / session_before_fork with a stable warning. Elicitation projection uses an allowlist of prompt-side custom entry types and renders displayable brunch.elicitation_prompt rows in the web transcript.

Planning/spec docs mark web-shell done, advance graph-data-plane, and codify D33-L (connections are client attachments, one-writer/many-observer POC) plus partial coverage updates for I19-L / I21-L. Also adds the ln-judo-review agent skill and minor Graphite frontier-setup notes.

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

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 eab91df. Configure here.


function hasRequiredSessionEntryShape(value: unknown): value is SessionEntry {
return isTranscriptEntry(value) && hasStringOrNullParentId(value)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Identical function duplicated within same file

Low Severity

hasRequiredSessionEntryShape and isSessionEntry in brunch-session-envelope.ts have identical implementations — both return isTranscriptEntry(value) && hasStringOrNullParentId(value). One of them is unnecessary and risks diverging silently if only one is updated in the future.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit eab91df. Configure here.

Comment thread src/elicitation-exchange.ts
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 27, 2026

🤖 Augment PR Summary

Summary: This PR introduces the M3 “web shell” as a native React UI served by the Brunch host, using a single WebSocket-backed JSON-RPC transport (no REST read model).

Changes:

  • Adds --mode web CLI support and a Node HTTP host that serves built web assets plus /rpc WebSocket JSON-RPC.
  • Introduces a typed JSON-RPC protocol helper module to centralize parsing/dispatch and standard error frames.
  • Adds a browser WebSocket RPC client with request multiplexing and protocol-failure hardening.
  • Builds the initial React dashboard using TanStack Router + Query to render workspace chrome and a read-only transcript display.
  • Adds a canonical “Brunch session envelope” reader that validates session self-description (brunch.session_binding) and enforces linear transcript constraints.
  • Hardens projection/RPC paths to reject non-linear transcripts and to require explicit session/spec targets for durable reads.
  • Blocks Pi branch flows (/tree, /fork) in the TUI with a stable user-facing warning.
  • Wires Vite build output to dist-web and updates packaging/tsconfig accordingly.

Technical Notes: Session-consuming reads now treat transport connections as ephemeral attachments; explicit { sessionId, specId } targeting is used for web projections, and non-linear Pi JSONL shapes fail fast.

🤖 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. 1 suggestion posted.

Fix All in Augment

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

Comment thread src/fixture-capture.ts

const response = JSON.parse(chunks.join("")) as JsonRpcResponse<T>
if (response.error) {
if ("error" in response) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

src/fixture-capture.ts:164 — Since response comes from JSON.parse without runtime validation, a malformed frame that lacks both error and result will now fall through and return undefined, which can mask protocol failures during fixture capture.

Severity: medium

Generating Fix in Augment link...

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

@lunelson lunelson self-assigned this Jun 2, 2026
@lunelson lunelson requested a review from kostandinang June 2, 2026 13:35
@graphite-app graphite-app Bot changed the base branch from ln/fe-736-jsonl-session-viability to graphite-base/147 June 2, 2026 17:32
@lunelson lunelson force-pushed the ln/fe-737-web-shell branch from eab91df to 8204774 Compare June 2, 2026 17:35
@lunelson lunelson force-pushed the graphite-base/147 branch from c6c33ee to 55d9122 Compare June 2, 2026 17:35
@graphite-app graphite-app Bot changed the base branch from graphite-base/147 to next June 2, 2026 17:35
@graphite-app
Copy link
Copy Markdown

graphite-app Bot commented Jun 2, 2026

Merge activity

  • Jun 2, 5:35 PM UTC: Graphite rebased this pull request, because this pull request is set to merge when ready.

@lunelson lunelson merged commit b28b964 into next Jun 2, 2026
12 checks passed
@lunelson lunelson deleted the ln/fe-737-web-shell branch June 2, 2026 17:48
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