Pi 0.81 lockstep Node rewrite - #3
Conversation
There was a problem hiding this comment.
Independent read-only completion review of the Pi 0.81 lockstep rewrite (90 files, base 02b0f3b → head 394b76316db8590dace096ead31b26d5a49b05f9). All eight required checks are supported by diff + current-SHA evidence.
1 — Lockstep compatibility contract ✅
package.json pins @earendil-works/pi-coding-agent, pi-ai, and pi-tui to exactly 0.81.1 in both peerDependencies and devDependencies; compatibility/pi.json declares piVersion: 0.81.1 / nodeVersion: 22.19.0. Namespace is @earendil-works/ only. Enforced by tests/package/compatibility.test.ts (asserts exact versions, rejects retired @mariozechner/, asserts engines.node >= 22.19.0).
2 — extensions/ + changed tests inspected** ✅
Reviewed the completion surface end-to-end: tools/complete.ts, tools/judge.ts, tools/judge-request.ts, tools/lifecycle.ts (until_done_set), ci/runner.ts, hooks (agent.ts, session.ts, before-agent-start.ts, agent-end-helpers.ts), store.ts, schemas/set-fields.ts, types.ts, compaction-context.ts. Tests reviewed: tests/tools/judge.test.ts, tests/hooks/session-hooks.test.ts, tests/package/compatibility.test.ts, tests/structure/check.mjs, tests/workflows/invariants.test.ts.
3 — No deleted / skipped / weakened tests; no proxy evidence ✅
Only removed file is .github/workflows/upstream-pi-merge-gate.yml (a workflow, not a test). No test.skip/describe.skip/xdescribe/xit in tests/**. Evidence is real: tests/helpers/runtime-harness.ts drives the extension through Pi's official createAgentSessionFromServices + ModelRuntime + fauxProvider and asserts on the actual session branch (until-done.state, until-done.compaction-context) — not Bun-global stubs.
4 — Prompts compose, continuation @ agent_settled, compaction re-anchor, durable state ✅
before_agent_start appends ({ systemPrompt: event.systemPrompt + buildReminder(state) }) and returns undefined when inactive, so it never replaces. queueContinuation is reachable only from the agent_settled handler (agent.ts). session_compact emits a hidden entry via pi.sendMessage({ customType: "until-done.compaction-context", display: false }, { triggerTurn: false }); session_before_compact is intentionally not subscribed. State lives only in Pi session entries (pi.appendEntry + reconstructFromSession); no side-database. Covered by session-hooks.test.ts (asserts display===false + content).
5 — Completion gate is unconditional; continue blocks ✅
executeSet refuses with judge_unspecified when neither judgeModel nor sameModelJudge is resolved (and no /until-done judge default). executeComplete → decideJudge always routes to consultJudge (cross-model) or consultSelfJudge (fresh-context same-model). Verdict continue → refuseCompletion (goal stays active); done proceeds. parse_error/unavailable fail open with a warning evidence line — exactly the documented contract (judge-infra glitch must not block). The unreachable "neither" branch is defensive only. completeWithApproval is the sole writer of goal status: "done", reachable solely via the until_done_complete tool. All four behaviors asserted in tests/tools/judge.test.ts.
6 — Node subprocess semantics ✅
ci/runner.ts: timeout armed via setTimeout(killTree, check.timeoutMs); AbortSignal wired to killTree; output truncated at OUTPUT_TRUNCATION_CHARS; tree-kill is taskkill /PID /T /F on Windows and process.kill(-pgid, SIGKILL) against a detached group on Unix; windowsHide: true. Covered by tests/ci/runner.test.ts and tests/node/runner.mjs.
7 — Three-OS CI evidence on the PR head SHA ✅
CI workflow run 29918915368 on head 394b76316db8590dace096ead31b26d5a49b05f9 (event pull_request, fail-fast: false):
ubuntu-latest · mise run ci→ completed / successwindows-latest · mise run ci→ completed / successmacos-latest · mise run ci→ completed / successrelease-ready→ skipped (expected on a PR; gated to main / workflow_dispatch)
8 — Uncertainty ✅
No residual uncertainty; every requirement is backed by the diff and current-SHA evidence above.
Approving.
Summary
@earendil-works/pi-*@0.81.1and Node>=22.19.0child_processagent_settled, composeevent.systemPrompt, and re-anchor compaction through a hidden session entry0.2.xmigrationTDD and local evidence
Relevant RED failures were observed before each production behavior change, including Node
Bun is not defined, missing Node task discovery, lifecycle/prompt/migration/judge assertions, absent workflow policy, invalidGITHUB_*Actions secret naming, and stale generated-workflow output.Fresh local gates on this branch:
mise run ci— 197 pass, 0 fail; Node runner, task discovery, package load, pack manifest, and packed install all green; structural constraints greenmise run release-ready— green; release surfaces and local ↔ GitHub parity greenmise run workflows— strict compilation succeeded for both agentic workflows; actionlint found 0 issues; 9 workflow tests passedhttps://api.z.ai/api/coding/paas/v4, modelglm-5.2, exactOK, reasoning content present forreasoning_effort: xhighlimit: 25,limit_reset: monthlyRemote Linux/macOS/Windows evidence is required on the current PR head before merge.
Security review of generated workflows
Reviewed every restricted-secret and action change emitted by gh-aw safe update mode.
Restricted secret references
OPENROUTER_API_KEY: passed only to the gh-aw Copilot BYOK proxy foropenrouter.ai; excluded from the model sandboxOPENAI_API_KEY: contains the Z.AI Coding Plan key required by gh-aw's universal OpenCode provider; excluded from the model sandboxPI_LOCKSTEP_APP_PRIVATE_KEY: consumed only by generated safe-output/App-token jobs for repository-scoped mutationGITHUB_TOKEN,GH_AW_*,COPILOT_GITHUB_TOKEN, andCODEX_API_KEYfallback references are compiler-generated; repository/model jobs retain read-only permissions and absent fallbacks are not populatedNo secret value is committed, packed, printed, or included in this PR.
Actions and containers
All workflow actions are pinned to immutable SHAs. Generated references include GitHub-owned checkout, cache, upload/download, setup-node, github-script, create-github-app-token, and
github/gh-aw-actionssetup actions. Generated AWF/firewall, MCP gateway, Node, and GitHub MCP containers are digest-pinned. Conventional checkout, setup-node, mise, and App-token actions are also SHA-pinned.Network and provider redirects
https://openrouter.ai/api/v1https://api.z.ai/api/coding/paas/v4The new provider endpoints and secret mappings are expected and safe for the approved architecture. OpenCode support is explicitly experimental and therefore remains behind a blocking exact-head review gate. gh-aw v0.82.14 has two documented generator defects (a missing BYOK conclusion output and an empty maintenance choice); both are patched deterministically and actionlint-verified by
mise run workflows.Release sequencing
This PR intentionally leaves
package.jsonat0.2.2. After this compatibility SHA is merged and remote CI is green on resultingmain, a separate version-only PR will set0.3.0. Its resultingmainSHA must independently pass remote CI before the initial manual tag/publish.