Skip to content

v0.2.51.0 feat: the chat explains a repository's own Node HTTP server live, paused in its route handler (Cycle 0057 pt2) - #141

Merged
ryota-murakami merged 28 commits into
mainfrom
codex/cycle-0057-pt2
Oct 27, 2026
Merged

ryota-murakami merged 28 commits into
mainfrom
codex/cycle-0057-pt2

Conversation

@ryota-murakami

@ryota-murakami ryota-murakami commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor
{
  "schema_version": 1,
  "pr": 141,
  "head": "3f1473fbd191b43ef5a33c5320bb223bcb07719f",
  "version": "0.2.51.0",
  "base": "main",
  "gate": {
    "tests": {
      "pass": 7798,
      "fail": 0,
      "skip": 10
    }
  },
  "session_kind": "interactive",
  "pregate": "warn @542ef58794ce (6 checks, current for 3f1473fbd191)",
  "issues": {
    "fixes": [],
    "refs": [
      139
    ],
    "flakes": []
  },
  "docs": {
    "status": "current",
    "scope": "AGENTS.md, CHANGELOG.md, PRODUCT_GOAL.md, README.md, extension/README.md, extension/skills/codebook/SKILL.md, the v9 PNG (read-only re-audit, attempt 2)"
  },
  "review_loop": {
    "passes": 3,
    "blocking_found": 7,
    "deferred": 0,
    "noted": 12,
    "fixed": 3,
    "scope": "frozen"
  }
}

Refs #139 (Cycle 0057, a feature cycle: second of its three pull requests, per Owner decision O1). pt1 (#140) laid the launch parts and the redaction contract; this PR offers the node-server profile through MCP; pt3 adds the bundled skill's server route and the native trial N57 in both editors. Issue #139 stays open for pt3.

Summary

A learner who asks how a project's API handles a request could only get a source reading or a browser-page explanation: Codebook ran browser apps and tests, not servers. Now the chat can start the repository's own Node HTTP server under the editor's debugger, send one declared request, pause in the route handler's actual TypeScript source and explain with the live values the learner also sees in the Variables view, then report the response it observed and stop the server.

  • One declared run, nothing more. The chat declares the entry, package folder, port, one request and the stops; Codebook starts exactly node [--import <the repository's tsx>] <entry>, passes only an allowlisted environment and never sets the port.
  • The learner confirms anything that changes data. A POST, PUT, PATCH or DELETE waits for a native dialog that names the method, path and run; the chat cannot answer it, and a dialog an earlier run left on screen never sends this run's request.
  • The request reaches only the started server. Before the first byte, the connected socket's server process must be the launched one; otherwise nothing is sent and the run stays ready.
  • Pauses stay the learner's. Declared stops are captured and continued only with the run's own continuation arguments; a learner's breakpoint, debugger;, exception or Pause button is never resumed by Codebook.
  • Stopping never lets paused or in-flight code run on (D14 v2). While the request is under way, or the server is paused at a declared stop, a Stop ends the process group with SIGKILL before the debugger lets go; otherwise the debugger detaches first and SIGTERM lets the server shut down.
  • Truthful states. The status bar and the run resource show starting, listening, paused at stop n of m, paused by you, responded, failed with a code, stopping and stopped; 13 new error codes carry recovery text in codebook://help/errors and codebook://help/node-server.

Blast radius

The profile adds code paths beside the existing repository-browser and node-test profiles; it shares only the service's admission, receipt and status machinery, whose existing browser and test replay suites pass unchanged in the full lane (7,801 tests, 0 fail, run). MCP stays 1.8 (additions only), stored learner data and saved replays are untouched, and the bundled skill stays 1.0.50.

Test Coverage

Every new mechanism has host tests (fake editor, DAP, process table, listener tool and clock) and the run loop has real-process tests against a test-only fixture server, with the test's own debugger client standing in for pwa-node (evidence level 3). The state × call table generates the refusal tests for all ten states and four calls.

Tests: 514 → 515 files (+1 new from the coverage audit; every implementation commit carries its own tests)
Coverage: 87% value-weighted (97% including 3 weakly covered paths)
Test value: 6 tests written, 7 rejected by the authoring gate, 0 existing tests extended, 3 paths weakly covered (weak = ★, gate-failing or unrated).

  • ★ weak: createNodeServerRunUtilities, createMemoryOrphanStore, nodeServerRunDependencies (wiring, covered only indirectly through the environment and real-process tests).
  • Gap: the journal's retained-event byte bound has no direct test (carried to pt3).
  • Review-round fixes added 18 red-first tests (7 after round 1, 11 after the last round), each failing on the commit before its fix.

Tests ran: tests count unavailable (receipt; the runner summary of the final run reads 7,801 tests, 7,791 pass, 0 fail, 10 skipped)

Pre-Landing Review

Step 9 ran three passes under review_scope frozen and did not converge (converged:false). Pass 1 (full diff, 6 specialists and a red team) found 13 informational findings, carried as pt3 tasks under the feature-cycle rule. Step 11's first round (native adversarial, Codex adversarial, Codex structured) returned three Codex P1 findings; pass 2 fixed them (8257e534). Pass 3 reviewed that fix and was capped with four untested kill-first state cells and five informational notes. Under the owner's ship review limit every last-round finding (pass 3 and Step 11's second round, including Codex adversarial's P1 that led to D14 v2) was fixed in 0f008416; no Critical or Major defect stays open, so no Issue records one.

REVIEW_LOOP: passes=3 blocking_found=7 deferred=0 noted=12 fixed=3 scope=frozen

Gate edits: 43 listed, 4 read, 0 findings (4 hunks kept with reasons)

  • RH-16 extension/src/extension.ts: the Output line writer catches a disposed channel; the line is also in the run's events.
  • RH-16 extension/src/ownedNodeServerRun.ts: each catch names its owner (the response promise, a retryable stop, or a recorded orphan record).
  • RH-16 extension/src/service.ts: the confirmation modal fails closed (no Send, nothing sent) and the release paths report their errors.
  • untagged extension/src/tests/fixtures/node-server/server.ts: the test-only fixture gained routes; nothing was relaxed.

Outside review: Codex structured round 1 FAIL (three P1, fixed); round 2 PASS (VERDICT clean, four P2 fixed). Codex adversarial round 1 unavailable (timed out at 540 s; missing coverage), round 2 completed (one P1, fixed).

Review notes

Recorded and fixed after the cap (last round) or carried to pt3 (earlier rounds):

  • Fixed after the cap: the kill-first state cells; a Stop after the first byte; the content type in the dialog key; an abort after end() reported "nothing was sent"; unreported stops kept for the entry pause and child sessions; a rejected learner Continue clearing a pause; a stale stack token; the request event journaled before the ownership check; the ownership refusals' recovery at request time; one dialog slot.
  • Carried to pt3 (Issue Cycle 0057: a Node HTTP server of a real repository is explained live (node-server profile) #139 tasks): the orphan sweep keeps no record when it cannot verify or close a group; the leader-only orphan check; a learner pause outside the request window still detaches first (D14 v2 keeps Stop v2 there by design, to revisit); the run view sanitizes private roots after the body cut; the close sequence's SIGKILL lands at about 6 s; the state × call table also against the real run class; the journal's work after truncation; runningTimeLimit's untested cells.

Exploratory QA

  • Real-process fixture loop (CI): start, readiness, owned listener, request with zero bytes to an unowned process, pause, values, continue, response, stop with the port free.
  • AC 2(c) on the final code (b40af1e7, the Mac, pinned clones with their databases): 4/4 pass. switch-time GET /api/healthz paused at app.ts:54, 200 {"status":"ok"}; sign-in of an unknown user paused at db/client.ts:254 with the e-mail value, 401 INVALID_EMAIL_OR_PASSWORD; nsx GET /api/health paused at health.ts:60, 200 with the database up and 503 with it down. Skipped in CI with the reason pinned clones and their databases are local-only.
  • N57 step 0 (development evidence, the Space's VS Code 1.142.0 on macOS 26, Copilot Chat Agent with GPT-6.1 Terra; the picker lists no GPT-6.1 Luna): PASS on the integrated candidate, re-smoked on the review candidate, and re-smoked again on this PR's final VSIX (SHA-256 f697fa1e…cff9e, 0.2.51). The last run asked a new natural question (sign-in with an unregistered e-mail): the chat declared the run on its first attempt, the native dialog named the POST and the run, the learner chose Send, the server paused at app.ts:65 (stop 1 of 2) and db/client.ts:254 (stop 2 of 2, the SQL parameter readable), and the chat explained both stops. After the long pause the app's own 25 s request deadline answered 500; the chat reported that as observed, sent nothing more, stopped the server (port freed, no process left) and labeled its 401 explanation as source-derived.
  • Not run here: Cursor and the database-backed write paths (pt3's N57), Express (P07) native.

Design Review

No frontend files changed — design review skipped (the status bar text and the native dialog are editor-owned surfaces).

Eval Results

No prompt-related files changed — evals skipped.

Plan Completion

pt2 scope of #139 (O1): tasks 9–12 delivered (run, MCP lifecycle and the state × call table, recovery text and help, status item), N57 step 0 done, task 14's pt2 docs done (CHANGELOG 0.2.51.0, the packaged README section, the root README status). D14 v2 recorded on the Issue before its code. Remaining for pt3: task 13 (skill route), task 15 (N57 in both editors) and the carried findings above.

Issues

Refs #139

Verification Results

Step 8.1 obligations: 9 PASS, 0 FAIL, 0 BLOCKED, 0 NOT RUN.

  • health:static and the suite on the final tree; AC 2(b) fixture tests in the suite; AC 5 replay tests green.
  • AC 2(c) clones 4/4 on the final code (b40af1e7; the later commits change docs, version lines and tests only).
  • N57 step 0 re-smoke on the final VSIX (c6641821): PASS.
  • 15-check exact-HEAD gate on 3f1473fb (tree 542ef587, clean before and after): 15/15 exit 0. pnpm test 7,808 tests, 7,798 pass, 0 fail, 10 skipped; Reader DOM 288 + 55 + 12 + 8 + 26 cases, all pass; pnpm test:package 1,081 tests, 1,071 pass, 0 fail, 10 skipped; pnpm health exit 0 (86 A); context-restore test 9/9.
  • Found after /ship and fixed before merge: the first gate run on c6641821 failed only pnpm health: refusalText in assertNodeServerPortFree.ts scored CRAP 72 with no test reaching it. 3f1473fb adds seven tests (every refusal wording, the occupant named or not, Codebook's own run running or stopping); no product code changed.
  • Required CI on 3f1473fb: 23 pass, 2 skipped (hosted CodeRabbit, off by owner decision O6; the main-only split-files job).
  • Local CodeRabbit CLI on origin/main..c6641821 (round 3) and on origin/main..3f1473fb (round 4), outcome completed: six minor findings in five subjects, no critical (the help's NODE_SERVER_SOURCE_REFUSED row, the wall-time backstop's message, the CHANGELOG smoke's revisions, the invalid-UTF-8 note at the end of a body, and the README's 10 s stop deadline). Under the feature-cycle rule they are carried to pt3 as Issue tasks.

TODOS

No TODO items completed in this PR (the repository keeps no TODOS.md; carried work lives in Issue #139).

Documentation

Scope: The audit covered committed, unstaged and selected content against base 4ff53d2: AGENTS.md, README.md, CHANGELOG.md (0.2.51.0), extension/README.md, plus PRODUCT_GOAL.md, the bundled skill and the v9 PNG, which have no diff against the base. Read-only mode, so I made no edits.

Result: The CHANGELOG 0.2.51.0 entry matches the new README section "## Explain a Node HTTP server". Every user-visible behavior the entry names has a sentence in the packaged README:

  • the declared inputs and the exact launch
  • the environment allowlist and codebook.nodeExecutable
  • the confirmation dialog for POST, PUT, PATCH and DELETE
  • the LISTENER_NOT_OWNED check
  • stops and the user's own pauses
  • the observed response, REQUEST_FAILED, REQUEST_TIMEOUT and PAUSE_HOLD_EXPIRED
  • stop semantics
  • the status bar
  • limits and codebook_status

The README recovery-table row for NODE_SERVER_SOURCE_REFUSED matches errors.ts and the throw sites in resolveNodeServerLaunch.ts and resolveNodeServerStops.ts. All three cover the same cases: a missing or outside-the-repository packageRoot, entry, stop file or the repository's own tsx. The row's recovery (correct the path or install dependencies, then declare again) is consistent with the errors.ts recovery text. The top-level README "Implementation status" paragraph and the AGENTS.md VS Code model line (GPT-6.1 Terra) are consistent with the CHANGELOG and with the extension version 0.2.51.

Debt: None. The skill's server route is the planned pt3 work.

Test plan

  • gstack-evidence run --label tests -- 'cd extension && corepack pnpm test 2>&1' on c6641821: 7,801 tests, 7,791 pass, 0 fail, 10 skipped (the gate reran the suite on 3f1473fb: 7,808 tests, 0 fail)
  • pnpm --dir extension format:check, lint, health:static, dupes, dead-code after the last fixes: exit 0
  • CODEBOOK_NODE_SERVER_CLONES=<clones JSON> node --test dist/tests/ownedNodeServerRun.pinnedClones.test.js on b40af1e7: 4/4 pass
  • gstack-pregate --stage preflight --allow-repo-commands: warn (11 medium non-credential findings, all benign test or doc examples)
  • N57 step 0 re-smoke in the Space's VS Code on the final VSIX: PASS
  • 15-check exact-HEAD gate on 3f1473fb: 15/15 exit 0
  • Required CI on 3f1473fb: 23 pass, 2 skipped
  • Local CodeRabbit CLI on origin/main..3f1473fb: completed, minor findings carried to pt3

🤖 Generated with Claude Code

ryota-murakami and others added 27 commits October 28, 2026 00:01
…ecovery, profile, run view and environment hooks (Issue #139)

The shared contract the pt2 parts build on (tasks 9–12):
- errors.ts: the 13 new codes of task 11 (PORT_UNAVAILABLE,
  LISTENER_NOT_OWNED, PORT_OWNER_UNKNOWN, RUN_NOT_READY,
  REQUEST_ALREADY_SENT, REQUEST_NOT_CONFIRMED, NO_PAUSE, LEARNER_PAUSED,
  SERVER_EXITED, SERVER_NOT_LISTENING, REQUEST_FAILED, REQUEST_TIMEOUT,
  PAUSE_HOLD_EXPIRED), each with the fix first, its recovery class, side
  effects, a retry bound and its codebook://help/node-server anchor.
- constants.ts: NODE_SERVER_PROFILE and NODE_SERVER_ACTION.
- runtime.ts: NodeServerState (the ten states), NodeServerView with its
  stops, pause, held pause, request, response, failures and in-memory
  captures, the NodeServerRuntime interface, and the environment's
  createNodeServerRun and confirmStateChangingRequest hooks (D1, D6, D9,
  D14 in the Issue's pt2 expectation notes).
No caller yet.
…equest sender, orphan records) into pt2 (Issue #139)
…, state and events through the service (Issue #139)
… real readiness, listener, peer, request and orphan-record utilities (Issue #139)

Integration of parts U and R: ownedNodeServerRun.process.test.ts drops its
test-local stand-ins and runs the fixture server through
waitForServerReadiness, verifyListenerOwnership (lsof), readListeningPortsOfProcess,
readConnectionServerPid (lsof), sendDeclaredRequest and the orphan
record functions over an in-memory store; the loop test also asserts the
running server's orphan record and its removal at stop. Evidence level 3
(a direct inspector client stands in for pwa-node). 4/4 pass.
…rror channel, confirmation modal and status item (Issue #139)
…n, its machine utilities and the window's orphan records (Issue #139)

Integration of parts U, R and S:
- environment.ts createNodeServerRun: the configured external Node with
  its version (resolveExternalNode), lazily the VS Code-backed run
  (createOwnedNodeServerRun) with the product dependencies and U's
  readiness, listener, connection, request and orphan-record utilities
  (createNodeServerRunUtilities) bound to the window's workspaceState
  (an in-memory store when a host gives none); the node-test and
  node-server factories share one prerequisite and workspace check.
- extension.ts: activation hands workspaceState to reapNodeServerOrphans
  once, with NODE_SERVER_SHUTDOWN_GRACE_MS (TD-7).
- The event whitelist keeps the fields the run emits: learner-paused
  kind and declaredStopIndex, learner-resumed declaredStopIndex,
  response location, and ready, stop-hit-at-start, pause,
  capture-budget-exhausted, port-held-by-other, attached and stopped;
  its text limits move to constants.ts.
- nextActions names the continuation continue-server, as the other
  profiles do.

Test changes, each for the integration: nodeServerStatus expects the
environment's run factory (S's part had none); nodeServerEvents records
the shapes the run emits; nodeServerState expects continue-server. New
tests: lifecycle event whitelist and activation reaping (red first on
the pre-integration files), resolveExternalNode.
…ofile; the root README names Cycle 0057's delivery (Issue #139)

extension/README.md 'Explain a Node HTTP server': what the chat declares,
the environment (the server's own .env plus the allowlist, NODE_ENV unset,
codebook.nodeExecutable for a newer Node), the one request and its
confirmation for POST/PUT/PATCH/DELETE, your own pauses stay yours, what
the run reports (responses, REQUEST_FAILED/REQUEST_TIMEOUT never resent,
PAUSE_HOLD_EXPIRED), the status bar texts beside 'Learning replay is not
available for server runs yet', and the limits. Root README: the
delivered version and Cycle 0057's three pull requests.
… lists it (owner rule of 2026-10-27, Issue #139)

The Space's VS Code 1.142.0 Copilot picker listed GPT-6.1 Terra (and
GPT-6.1 Sol, no GPT-6.1 Luna) on 2026-10-28 JST, so the owner's
2026-10-27 rule moves VS Code trials from GPT6 Luna to GPT-6.1 Terra;
each trial still searches the picker and takes GPT-6.1 Luna if it
appears.
…han sweep, redact-then-cut response body, bounded content type (Issue #139)
…te path, one oversized event no longer ends the journal, the deadline ends a finished server run normally, and the confirmation modal is joined (Issue #139)
…tside the window, failed continue, unclassified pauses, path hiding, notice handling, peer holders, fact keys) (Issue #139)
…tsLoopbackConnection (Issue #139)

The pre-gate's stray-file check read probeLoopbackPort.ts as a scratch
file name. The utility is renamed with its single function; its three
callers follow. No behaviour change (28/28 tests of its callers pass).
… the secret scan's assignment pattern; two intentional waits are marked (Issue #139)

The Stage 1 pre-gate's secret scan read nine added lines as secret-named
assignments with high-entropy values: idempotency keys in tests
('changed-hash', 'run-${index}', ...), isDebugSessionOfRun's 'session'
parameter and the debugger's 'token: ++this.nextToken'. The keys become
plain words or String(index), the parameter debugSession, and the stop
number is taken into 'sequence' first; behaviour is unchanged (250/250
affected tests). The two sleep-then-assert waits in
waitForServerReadiness.test.ts are part of their scenarios (a late
server start; an abort inside the poll pause) and carry gstack-timing-ok
reasons.
…ld; event-type and reaper-poll limits live in constants.ts (CodeRabbit r2, Issue #139)

Local CodeRabbit CLI r2 on the pt2 range (5 findings, 2 duplicates):
- extension/README.md names that the 300 s pause hold covers a pause of
  yours as well as a declared stop (PAUSE_HOLD_EXPIRED never resumes it).
- EVENT_TYPE_LIMIT_CHARS (128) replaces the literal in the node-server
  journal and in the node-test journal of service.ts;
  NODE_SERVER_GROUP_EXIT_POLL_MS (50) in the orphan reaper.
- ownedNodeServerRun.process.test.ts reuses tests/utils/freeLoopbackPort.
No behaviour change in code.
…d P08 and P07 clones on the Mac, and skipped in CI with its reason (AC 2(c), Issue #139)

ownedNodeServerRun.pinnedClones.test.ts runs the real run (CDP debugger
stand-in, the real readiness/listener/peer/request/orphan utilities)
against switch-time 4f68953 and nsx 502545c7 from
CODEBOOK_NODE_SERVER_CLONES (JSON); without it every test skips with
"pinned clones and their databases are local-only". Each test checks the
clone revision, hits the declared .ts stop with the recorded local, observes
the response and frees the group and the port:
- switch-time GET /api/healthz: app.ts:54, c.req.path, 200 {"status":"ok"}
- switch-time POST /api/auth/sign-in/email (unknown e-mail): db/client.ts:254,
  values ["nobody@example.com"], 401 INVALID_EMAIL_OR_PASSWORD
- nsx GET /api/health, MySQL up: server/routes/health.ts:60, _req.path, 200
- nsx GET /api/health, MySQL stopped by the test and restored: 503
Local run on the Mac (Node 26.10.0 for the targets): 4/4 pass, ~31 s; without
the variable 4 skipped.

Test support: tests/utils/realNodeServerDependencies.ts (shared with the
fixture process test, which now imports it) and generatedPositionOfOriginal.ts
(inline source-map lookup). Changed test helper: cdpNodeServerDebugger.ts now
binds a .ts stop through the script's inline source map (V8's
beforeScriptWithSourceMapExecution instrumentation pause for ESM, scriptParsed
for CommonJS), as Part A bound them; the fixture process test still passes 4/4.
…kills a server paused in the request first; each run asks in its own dialog (Issue #139)

/ship Step 11, Codex structured review P1 x3 (gate FAIL, fixed under the
recommended option):

- A stop admitted while the connected peer is verified aborts the request's
  own signal, so nothing is written; the call answers RUN_NOT_READY.
- D14 kill-first also covers a stop the editor reported but whose stack is
  still being read (NodeServerDebugger.hasUnreportedPause) and a declared
  stop, or any pause inside the request, that arrives after the stop was
  admitted.
- The window-wide confirmation modal is keyed by the run id and the whole
  declared request, so a modal an earlier run left open never sends this
  run's request.

Red first: the seven new tests failed on cdc2736.
…, and paused stops, sent requests and dialogs read what is true (Issue #139)

/ship pt2 last review round (Step 9 pass 3 capped, Step 11 round 2);
every finding fixed under the owner's ship review limit:

- D14 v2: a Stop while the declared request is under way ends the group
  with SIGKILL before the debugger lets go, so a stop the handler reaches
  during the detach is never resumed (Codex adversarial P1).
- The sender counts a request handed to the socket as written when an
  abort comes after end(), so a Stop never reports "nothing was sent" for
  bytes that may be on the wire; the node-server.request event is
  journaled only once the request was written, never for a refused peer.
- The VS Code debugger clears a pause on the adapter's accepted resume or
  a continued event, per thread, not on the request: a rejected Continue
  keeps the pause current and its unreported stop counted, and a stop
  resumed while its stack was read is never reported. Only the bound
  session's stops queued for the run count as unreported (the entry pause
  and child sessions do not).
- Open confirmation dialogs are kept per run and request, so a retry
  joins its own dialog after another run asked; each names its run.
- LISTENER_NOT_OWNED and PORT_OWNER_UNKNOWN recovery covers a refusal at
  the request (the run still reads ready).
- Tests for the kill-first cells, a Stop after the first byte and the
  content type in the dialog key.

Red first: 11 new tests failed on 8257e53.
…rofile checks before the first byte, how a Stop ends the server, and when NODE_SERVER_SOURCE_REFUSED comes (Issue #139)
Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

…, a port the system refuses, an unreadable port and Codebook's own run (gate: pnpm health CRAP on refusalText, Issue #139)
@ryota-murakami
ryota-murakami merged commit 6ce0908 into main Oct 27, 2026
25 checks passed
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