@junghanacs/entwurf 0.20.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/AGENTS.md +85 -190
  2. package/BASELINE.md +6 -3
  3. package/CHANGELOG.md +473 -14
  4. package/CONTRIBUTING.md +1 -1
  5. package/DELIVERY.md +332 -60
  6. package/README.md +100 -22
  7. package/VERIFY.md +93 -7
  8. package/docs/acp-backend-rail.md +0 -1
  9. package/docs/external-mcp-host.md +64 -33
  10. package/docs/setup-clean-host.md +151 -17
  11. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +130 -114
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-caller-seat.js +174 -0
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +519 -0
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +22 -2
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +3 -1
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -7
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-native-push.js +30 -17
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +7 -1
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -2
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +8 -4
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +7 -4
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +20 -11
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-sender-identity.js +227 -1
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +189 -19
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/adapter.js +10 -7
  26. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +403 -0
  27. package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/register.js +4 -4
  28. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook-codex.js +325 -0
  29. package/mcp/entwurf-bridge/dist/scripts/codex-socket-path.js +30 -0
  30. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +6 -1
  31. package/mcp/entwurf-bridge/src/index.ts +154 -116
  32. package/mcp/entwurf-bridge/tsconfig.build.json +10 -0
  33. package/package.json +13 -4
  34. package/pi-extensions/entwurf-control.ts +71 -19
  35. package/pi-extensions/lib/codex-caller-seat.ts +204 -0
  36. package/pi-extensions/lib/codex-fresh-preflight.ts +580 -0
  37. package/pi-extensions/lib/compaction-send-guard.ts +80 -0
  38. package/pi-extensions/lib/entwurf-fact-provider.ts +29 -3
  39. package/pi-extensions/lib/entwurf-peers-render.ts +4 -1
  40. package/pi-extensions/lib/entwurf-v2-contract.ts +6 -7
  41. package/pi-extensions/lib/entwurf-v2-native-push.ts +35 -18
  42. package/pi-extensions/lib/entwurf-v2-production.ts +10 -3
  43. package/pi-extensions/lib/entwurf-v2-runner.ts +3 -2
  44. package/pi-extensions/lib/entwurf-v2-send.ts +16 -11
  45. package/pi-extensions/lib/entwurf-v2-surface.ts +7 -4
  46. package/pi-extensions/lib/meta-mailbox-body.ts +22 -13
  47. package/pi-extensions/lib/meta-sender-identity.ts +305 -0
  48. package/pi-extensions/lib/mux-fresh-call.ts +233 -29
  49. package/pi-extensions/lib/native-push/adapter.ts +21 -24
  50. package/pi-extensions/lib/native-push/codex-ws-client.ts +506 -0
  51. package/pi-extensions/lib/native-push/register.ts +7 -9
  52. package/pi-extensions/meta-bridge-hook-codex.ts +371 -0
  53. package/run.sh +342 -28
  54. package/scripts/check-agy-sender-identity.ts +1 -1
  55. package/scripts/check-codex-app-server-launch.ts +445 -0
  56. package/scripts/check-codex-birth-hook.ts +264 -0
  57. package/scripts/check-codex-bridge-identity.ts +179 -0
  58. package/scripts/check-codex-native-push.ts +386 -0
  59. package/scripts/check-codex-sender-identity.ts +495 -0
  60. package/scripts/check-compaction-send-guard.ts +130 -0
  61. package/scripts/check-copilot-receive-arm.ts +4 -1
  62. package/scripts/check-entwurf-fact-provider.ts +38 -0
  63. package/scripts/check-entwurf-peers-surface.ts +13 -1
  64. package/scripts/check-entwurf-self-address.ts +15 -16
  65. package/scripts/check-entwurf-v2-contract.ts +4 -3
  66. package/scripts/check-entwurf-v2-decider.ts +7 -5
  67. package/scripts/check-entwurf-v2-native-push.ts +35 -7
  68. package/scripts/check-entwurf-v2-production.ts +245 -12
  69. package/scripts/check-entwurf-v2-runner.ts +1 -1
  70. package/scripts/check-entwurf-v2-send.ts +26 -7
  71. package/scripts/check-entwurf-v2-surface.ts +1 -1
  72. package/scripts/check-gate-qualification.ts +8 -3
  73. package/scripts/check-harness-admission-parity.ts +0 -1
  74. package/scripts/check-mux-launch-tmux.ts +345 -4
  75. package/scripts/check-native-push-adapter.ts +20 -16
  76. package/scripts/check-native-push-register.ts +5 -1
  77. package/scripts/check-release-gate-outcomes.ts +47 -1
  78. package/scripts/check-setup-qualification.sh +3 -1
  79. package/scripts/codex-app-server-launch.sh +275 -0
  80. package/scripts/codex-birth-doctor.sh +276 -0
  81. package/scripts/codex-birth-install.sh +414 -0
  82. package/scripts/codex-birth-uninstall.sh +170 -0
  83. package/scripts/codex-mcp-config.py +435 -0
  84. package/scripts/codex-socket-path.ts +33 -0
  85. package/scripts/codex-statusline-config.py +434 -0
  86. package/scripts/codex-terminal-title-config.py +500 -0
  87. package/scripts/codex_toml_io.py +653 -0
  88. package/scripts/lib/codex-fresh-live-protocol.ts +121 -0
  89. package/scripts/lib/codex-fresh-source-receipts.ts +426 -0
  90. package/scripts/lib/launch-receipt-windows.ts +46 -0
  91. package/scripts/lib/tmux-coordinate-row.ts +58 -0
  92. package/scripts/meta-bridge-fresh-cut.ts +6 -1
  93. package/scripts/mutants/codex-app-server-launch.json +157 -0
  94. package/scripts/mutants/codex-caller-seat.json +336 -0
  95. package/scripts/mutants/codex-native.json +838 -0
  96. package/scripts/mutants/compaction-send-guard.json +103 -0
  97. package/scripts/mutants/entwurf-peers.json +19 -0
  98. package/scripts/mutants/mux-fresh-call.json +93 -10
  99. package/scripts/mutants/omp-fresh.json +6 -4
  100. package/scripts/mutants/release-gate.json +13 -0
  101. package/scripts/mutants/v2-surface.json +75 -1
  102. package/scripts/raw-async-delivery/README.md +2 -1
  103. package/scripts/raw-codex-measure/README.md +114 -46
  104. package/scripts/smoke-agy-native-push-live.ts +3 -1
  105. package/scripts/smoke-codex-birth.sh +347 -0
  106. package/scripts/smoke-codex-config-state.sh +700 -0
  107. package/scripts/smoke-codex-fresh-live.ts +1426 -0
  108. package/scripts/smoke-codex-native-push-live.ts +75 -0
  109. package/scripts/smoke-entwurf-chain-live.ts +50 -0
  110. package/scripts/smoke-setup-verdict.sh +125 -10
  111. package/scripts/tsconfig.json +1 -0
package/AGENTS.md CHANGED
@@ -1,225 +1,120 @@
1
1
  # AGENTS.md — Maintainer Guidelines for entwurf
2
2
 
3
- For agents that own this repo: invariant principles and reproducible verification, not release-story archaeology.
4
-
5
- > **Direction.** This repo is the **entwurf capability package**: a v2 garden-citizen dispatch substrate, native-harness bridges, an ACP plugin, and the pi adapter that hosts that plugin today. `entwurf` is the subject; pi is one harness adapter. ACP is a plugin, not the boundary (#38). V1 verbs are gone. V2 addresses existing citizens; fresh sibling creation is the separate `entwurf_fresh_call` capability. Current work and ordering live in [NEXT.md](./NEXT.md).
3
+ For agents who own this repository: durable invariants and the documents that own the changing evidence. This is the **entwurf capability package**: garden-citizen dispatch substrate, native-harness bridges, ACP plugin, and pi adapter. Entwurf is the subject; pi is one adapter. ACP is a plugin, not the boundary. V2 addresses existing citizens; `entwurf_fresh_call` creates a new sibling.
6
4
 
7
5
  ## North Star — One Forged Screwdriver
8
6
 
9
- `entwurf`는 스위스 아미 나이프나 두 번째 하네스가 아니다. 이것은 **담금질된 드라이버 한 자루**다: 작고, 명시적이고, 맡은 접점에서만 강해야 한다.
10
-
11
- - **entwurf가 주어이고 pi는 한 adapter다.** pi는 가장 깊게 붙은 하네스지만 다른 하네스보다 높은 정체성 계층이 아니다.
12
- - **다른 하네스의 세션은 형제다.** Claude Code, Codex, Antigravity, pi는 각자의 transcript/auth/runtime을 소유한다. 증명된 lifecycle과 transport가 있을 때 같은 garden address space의 citizen이 된다.
13
- - **능력을 surface 이름으로 재단하지 않는다.** 도구 이름이나 transport 비대칭은 capability 차이이지 존재의 등급이 아니다.
14
- - **substrate는 결정적 dispatch만 맡는다.** record에서 identity를 읽고, rail별 liveness와 caller intent로 transport를 고른다. 숨은 hydration, ambient MCP scanning, 근거 없는 tool claim을 만들지 않는다.
15
- - **좁은 tool surface는 규율이다.** entwurf가 backend를 몰 때 sub-agent/todo 없이 한 자루 드라이버로 움직인다. 두 번째 orchestrator로 자라지 않게 한다.
16
- - **entwurf는 부속품이 아니라 분신을 연다.** resumed/spawned session은 runtime-isolated peer이지 disposable worker가 아니다.
17
- - **증거가 말을 훈육한다.** README, source, gates, VERIFY, BASELINE이 받치지 않는 강한 주장은 멈춘다.
7
+ `entwurf`는 두 번째 하네스나 오케스트레이터가 아니라, 맡은 접점에서만 강한 드라이버다.
18
8
 
19
- 판단할 묻는다:
9
+ - Entwurf is primary; pi is not a privileged identity layer. Harness sessions are peers that retain their own transcript, auth, and runtime.
10
+ - Capability/rail asymmetry is not a rank. Dispatch reads the record, live rail facts, and caller intent; it never reconstructs prompts, hydrates transcripts, scans ambient MCP, or invents a tool claim.
11
+ - A spawned or resumed session is a runtime-isolated sibling, never a disposable worker.
12
+ - 전송 방식은 달라도, 형제로서 부르고 불리는 기본 UX는 대칭이어야 한다.
13
+ - Evidence disciplines claims: source, gates, and the owning document must support an assertion.
20
14
 
21
- 1. tool 이름을 보는가, capability 보는가?
22
- 2. backend 비대칭을 정직하게 기록하는가, 형제성을 포기하는 핑계로 쓰는가?
23
- 3. 두 번째 하네스를 만드는가, 드라이버 한 자루를 단단하게 만드는가?
24
- 4. 이미 주어진 방향을 되묻는가, 실행 가능한 다음 증거를 만드는가?
15
+ Ask: does this follow capability rather than a surface name; record backend asymmetry without denying siblinghood; preserve one narrow driver rather than grow a harness; and make the next observable evidence rather than reopen settled direction?
25
16
 
26
17
  ## Architecture
27
18
 
28
- - **entwurf-core (v2)** owns garden-id addressing, peer facts, liveness interfaces, dispatch decisions, rail choice, and delivery evidence.
29
- - **Record authority** owns citizen identity. Every addressable citizen uses the same V3 `MetaIdentity` schema. `backend` selects capability/rail behavior; it does not create an identity hierarchy.
30
- - **pi adapter** attaches a pi session to a record at `session_start`, hosts the record-keyed control socket, and exposes the native pi tool surface.
31
- - **Native bridges** register already-running native sessions without taking over their transcript or auth: Claude Code and Copilot CLI are mailbox/self-fetch (a Claude hook arms the watch; a forked Copilot extension holds it); Antigravity is probe-backed native-push. Codex's decline was reversed by GLG on 2026-09-08: lane #95 is open at step 1 (`scripts/raw-codex-measure/`), mints no record, and must not become an ACP backend.
32
- - **ACP plugin** registers provider `entwurf` inside a pi host session and drives a backend under an isolated overlay. The host pi session is already a record-backed socket citizen; the plugin does not mint another citizen/socket/peer layer.
33
- - **mux is launch-only and deliberately small.** Shipped: the tmux placement leaf (`mux-placement.ts` — inspect/append in the caller's own session, close on its whole SERVER), the visible runtime launch composition (`mux-launch.ts`), the fresh-call composition (`mux-fresh-call.ts`), the cwd-aware resume placement composition (`mux-resume-call.ts`), and the import-free leaves they inject (`classify-tmux-cwd.ts`, `resolve-tmux-session.ts`). Fresh call is exposed as `entwurf_fresh_call`; visible same-id resume is `entwurf_resume_call`, composed at the two public surfaces by injecting `mux-resume-call` into the v2-side `entwurf-v2-visible-resume.ts`. The exact import graph is enumerated in [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) §11. `entwurf_v2` behavior is unchanged and delivery still never imports launch. Fresh call learns a new sibling's garden id from the CALLBACK it makes, never from a lookup — so the pre-injected-token → identity-lookup design (rail §6) is **closed, not paused**. Do not reopen it without new evidence and explicit GLG re-approval. Fresh-call requires one explicit model and passes it in each runtime's measured CLI dialect (Pi `--model <provider/model>`, Claude Code `--model=<id-or-alias>`, Copilot `--model <name>` beside `--interactive <prompt>` and the explicit `--yolo` policy — a GLG width decision, 2026-08-25, after a callback-only `--allow-tool` grant stopped the sibling at every task tool); the Copilot backend opens through entwurf's OWN managed invocation (`entwurf copilot`), never the bare vendor, and its four required capabilities — birth, MCP hand, receiver, visible footer — are decided by `copilot-fresh-preflight.ts` BEFORE the tmux mutation, so a missing unit is a named refusal instead of a dead window; it also takes ONE optional literal absolute `cwd` (#73 — omitted/`""` means the caller's own directory; no trim, no realpath, no project-name resolver; classified by the shared `classify-tmux-cwd.ts` leaf; the receipt echoes the REQUEST only), so a cross-repo fresh sibling is a fresh-call fact and never a reason to resume a dormant record. It also takes ONE optional project seat, `placement.tmuxSession` (#105 the exact name of an EXISTING session on the caller's OWN server, turned into a `$id` by `resolve-tmux-session.ts` before anything reaches `-t`). **It creates nothing** `tmux-session-missing`/`tmux-session-name-invalid` are named refusals, no `ifMissing`/`new-session` axis exists (GLG, 2026-09-07), seat and cwd never infer each other, and close binds to the SERVER half since a placed window may sit outside the caller's session. Resume takes only an existing target id and gets transcript/model/provider/cwd from its record. Do not grow either narrow carrier into a generic driver, harness profile, arbitrary command/env selection, or a second creation API. Ownership and import prohibitions: [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) §11.
34
- - **One delivery verb:** `entwurf_v2` addresses an existing garden id. Current routes are live control-socket send, active self-fetch mailbox enqueue, and probe-alive native-push. NO route starts a process: the hidden background resume for a dormant citizen was withdrawn under the visible-first rule, so a dormant in-domain citizen rejects as `dormant-fire-forget-unsupported` and the intent axis is single-valued. Every other complementary state pair rejects honestly too. Fresh creation is a separate verb — `entwurf_fresh_call` — and it returns a launch receipt only; the new sibling's address arrives asynchronously as the sender envelope of its nonce callback.
19
+ - **entwurf-core (v2):** garden-id addressing, record facts, rail liveness, dispatch decisions, and delivery evidence.
20
+ - **Record authority:** every citizen uses V3 `MetaIdentity`; `backend` selects rail capability, never identity rank.
21
+ - **pi adapter:** attaches its native session to a record, hosts the record-keyed control socket, and exposes pi’s native tools.
22
+ - **Native bridges:** register existing sessions without owning transcript or auth. Claude Code and Copilot are self-fetch; Antigravity and Codex are native-push. Codex remains native rather than ACP so its vendor tools, delegation, and work context remain intact. Admission/evidence details belong in [DELIVERY.md](./DELIVERY.md) and [VERIFY.md](./VERIFY.md).
23
+ - **ACP plugin:** one `entwurf` provider under an isolated overlay. The host pi session is already a record-backed citizen; ACP creates neither a second citizen nor a socket layer.
24
+ - **mux:** launch-only placement and fixed-runtime launch. It never imports into delivery. Fresh identity arrives only through its callback envelope, never a lookup; same-id visible resume keeps identity/liveness/locking on the v2 side of the injected seam. Fresh call accepts only the narrow model, literal absolute cwd, and existing caller-server seat inputs; it creates no session and does not infer seat from cwd. A Codex CALLER alone has an omitted-placement rule: it opens beside its own TUI pane, matched by thread-id in that pane title; 0/2+ matches reject; explicit placement still wins. Do not turn either fresh call or resume into a generic driver, command/env carrier, or second creation API. Exact module/argv/import ownership: [docs/mux-launch-rail.md](./docs/mux-launch-rail.md).
25
+ - **Delivery:** `entwurf_v2` addresses an existing garden id through a live control socket, deliverable self-fetch mailbox, or probe-alive native push. It never starts a process. Fresh creation and visible same-id resume are separate lifecycle verbs.
35
26
 
36
27
  ## Hard Rules
37
28
 
38
- 1. **One surface name, hard cut.** Runtime/provider/routing identity is `entwurf`. No permanent aliases, legacy readers, or hidden dual routing. One-shot migration or documented break only.
39
- 2. **The record is the sole garden address authority.** A socket, env var, marker, filename, model id, or transcript id is never an independent address axis. `PI_SESSION_ID` is only a child-process carrier for the garden id already established by pi's record birth.
40
- 3. **All citizens share one identity contract; rails differ by capability.** The control-socket liveness domain currently contains backend `pi`; self-fetch and native-push have different predicates. Branch on capability/domain, not on a privileged notion of “pi citizen.”
41
- 4. **Dispatch is computed from live facts.** Never store liveness. Never infer send/resume from session type before resolving the target and probing its rail.
42
- 5. **Rejects are real.** Wrong intent, dead/drifted identity, undeliverable mailbox, ambiguous address, or indeterminate probe returns a reject and mutates nothing. No cosmetic success or silent fallback.
43
- 6. **MCP is explicit.** Only explicit `mcpServers` wiring. No ambient `~/.mcp.json` scan or automatic retrieval.
44
- 7. **Meta-record store contract is one contract.** Record body is authority; filename must agree with the body; every active entry is a regular non-symlink file readable by the live V3 schema; `nativeSessionId` ownership is unique. Identity writers and doctor certify the whole active store before writing. Address-bearing reads use `readAddressableMetaIdentity`; targeted relay reads keep the documented per-entry contract. `readStoreRecordFile`/`O_NOFOLLOW` and the lstat policy layer are both load-bearing—do not merge or bypass them. No legacy reader/migrator: quiesce and run `entwurf meta-bridge-fresh-cut` when the generation is unreadable. An unknown-backend defect is a stale deployed reader, not a rotten generation: redeploy the sibling unit; do not fresh-cut. `doctor-meta-bridge` already names that — run it after `META_BACKENDS` changes. Source and gates: `meta-session.ts`, `check-meta-*`, `check-fresh-cut-gate`.
45
- 8. **GC reclaims process resources, never memory/data.** Records and transcripts are preserved or archived; they are not casually deleted.
46
- 9. **This is not a second harness.** No prompt reconstruction, transcript hydration, tool-result ledger, credential mediation, or harness emulation. Each backend owns auth and transcript state.
47
- 10. **Native-push is its own rail.** It is not a mailbox or pi socket in disguise. Antigravity replyability is record-backed plus probe-alive; no receiver marker, watch state, or resume authority is invented for it.
48
- 11. **Package proof must model a consumer.** Operator entrypoints reach compiled JS when installed; `run_ts` is the single TS crossing. Keep `check-install-surface`, `check-pack-install`, and the checkout-invisible `check-install-container` distinct. A green clone is not a green tarball or consumer.
49
- 12. **Offline verification never rewires the operator.** Sandbox `HOME`, `PI_CODING_AGENT_DIR`, and every writable `XDG_*` root. LIVE gates alone may touch the real host and must say so. Keep static tripwires and dynamic outer self-fences; neither substitutes for the other.
50
- 13. **Doctors report runtime truth and ownership truth separately.** Runtime coverage does not prove entwurf owns the configuration; broken ownership does not erase visibly working runtime configuration. Final verdict remains red when either required axis fails.
51
- 14. **Native hook ownership is structural.** Claude hooks use the shipped exec-form launcher and provenance token; marker writers/readers share `isPlausibleOwnerPid`; no shell-form fallback, ancestry guess, or retired pid carrier. entwurf requires Claude Code `>=2.1.217` and enforces that floor itself because upstream gives no fail-loud — an older Claude validates the exec manifest, then drops `args` at runtime and reports success. The number is derived from `package.json` `entwurf.claudeCodeFloor`, never retyped as a second source. Currently certified axis is Linux desktop/workstation. Source/gates: `hook-launch.sh`, `meta-session.ts`, `check-hook-launch-topology`, `check-claude-floor-coherence`, `check-meta-doctor-oracle`.
52
- 15. **Crash, don't warn.** Bad config/path/model/store state throws. Empty catches are only for bounded environment probing; operator diagnostics go to stderr.
53
- 16. **mux is launch, never delivery.** A tmux window/pane handle is an ephemeral operator view, not an address: it mints no garden id, stores no record, and reports no liveness. Screen text and keystrokes are never an `entwurf_v2` receipt. Mux owns only placement and fixed-runtime launch; fresh identity correlation stays in callback envelopes, while same-id resume identity/liveness/locking stays on the v2 side of an injected launch seam.
54
- 17. **Entwurf installs itself; setup composes what the operator already chose.** Package installation and source bootstrap supply Entwurf's own bytes, bins, dependencies and development fixtures only. They never install a harness binary, subscription, credential or login — `pi` has no privileged exception. `setup` detects already-present harnesses by capability and completes each detected integration; absence is an explicit zero-state SKIP, while a detected-but-incomplete integration is named non-green rather than cosmetic success. Source-only pinned Pi dev dependencies are build/test fixtures, not a product promise that neutral npm consumers receive Pi. Installation portability and rail/runtime support are separate evidence axes: Linux proof never certifies macOS or native Windows, and WSL counts as Linux rather than Windows.
55
-
56
- Detailed incident histories belong in CHANGELOG/issues/BASELINE and source-adjacent comments, not in this prompt. When a concise rule and old archaeology disagree, verify source + gate and repair the stale prose.
57
-
58
- ## ACP Plugin Boundary
29
+ 1. **One surface name, hard cut.** Runtime/provider/routing identity is `entwurf`; no permanent alias, legacy reader, or hidden dual route.
30
+ 2. **Record is the sole address authority.** Socket, env, marker, filename, model, and transcript are carriers or evidence, never a competing address axis. `PI_SESSION_ID` only carries record-established identity. If record birth fails, no socket starts and no `PI_SESSION_ID` is exported.
31
+ 3. **One identity contract, capability domains.** Branch on rail/liveness capability, not a privileged citizen class.
32
+ 4. **Live-fact dispatch.** Never store liveness or infer send/resume before resolving the record and probing its rail.
33
+ 5. **Rejects are real.** Wrong intent, dead/drifted identity, undeliverable mailbox, ambiguity, and indeterminate probe reject without mutation or fallback.
34
+ 6. **MCP is explicit.** Only explicit `mcpServers`; no ambient configuration scan or automatic retrieval.
35
+ 7. **One meta-store contract.** Record body and filename agree; active records are readable regular non-symlink V3 files; `nativeSessionId` is unique. Writers and doctor certify the active store before writing. Address-bearing reads use the addressable reader; `readStoreRecordFile`/`O_NOFOLLOW` and lstat policy both remain load-bearing. Quiesce and fresh-cut an unreadable generation; redeploy a stale unknown-backend reader. Store protocol and gates: `meta-session.ts`, `check-meta-*`, `check-fresh-cut-gate`.
36
+ 8. **GC reclaims processes, not memory.** Preserve or archive records and transcripts; do not casually delete them.
37
+ 9. **Not a second harness.** No prompt reconstruction, transcript hydration, tool-result ledger, credential mediation, or harness emulation. Backends own auth and transcript.
38
+ 10. **Native-push is distinct.** It is neither mailbox nor pi socket. Native-push citizens are record-backed plus probe-alive, with no receiver/watch state or resume authority. Antigravity retries only after bounded re-probe; Codex never replays queue acceptance. Codex sender identity is request-scoped metadata; app-server environment carries root/placement, never citizen identity.
39
+ 11. **Package proof models a consumer.** Installed operator entrypoints reach compiled JS; `run_ts` is the sole TS crossing. Keep checkout, tarball, and consumer proofs distinct.
40
+ 12. **Offline verification never rewires the operator.** Sandbox HOME, `PI_CODING_AGENT_DIR`, and writable XDG roots. Only named LIVE gates may touch the host, and must say so.
41
+ 13. **Doctors report runtime and ownership independently.** Working runtime does not prove ownership; broken ownership does not erase runtime observation. Required failure on either axis is red.
42
+ 14. **Native-hook ownership is structural.** Use shipped exec launchers and provenance, shared plausible-owner-pid policy, no shell fallback or ancestry guess. Version floors belong to their package source and are enforced there; hook contract/docs own the changing detail.
43
+ 15. **Crash, dont warn.** Invalid config/path/model/store state throws. Empty catches are only bounded environment probes; diagnostics go to stderr.
44
+ 16. **mux launches, never delivers.** A tmux handle is an ephemeral view, not an address or liveness receipt; screen text/keystrokes are not delivery evidence. A Codex caller's seat is the pane whose title carries its own thread-id, a placement input only; it is never an address, and never a pane nobody named. Cross-window adjacency requires the documented observed-coordinate proof, never pane guessing.
45
+ 17. **Entwurf installs itself; setup composes.** Installation supplies Entwurf bytes and development fixtures, never a harness binary, subscription, credential, or login. Setup detects existing harness capability; absence is explicit skip and detected incompleteness is non-green. Portability evidence and rail/runtime support remain separate.
46
+
47
+ History and incident detail belong in [CHANGELOG.md](./CHANGELOG.md), issue threads, [BASELINE.md](./BASELINE.md), or source-adjacent comments. When prose and behavior disagree, repair the owning source or document.
48
+
49
+ ## ACP Boundary
59
50
 
60
51
  | Layer | Owns |
61
52
  |---|---|
62
- | **entwurf-core** | identity/fact interfaces · dispatch table · delivery evidence · rail choice |
63
- | **ACP plugin** | backend process lifecycle · isolated overlay · tool narrowing · per-backend ACP dialect · turn evidence |
64
- | **ACP plugin does not own** | citizen registration · socket registry · peer protocol · memory DB · planner/orchestrator · auth |
65
-
66
- - One `entwurf` provider, model-id routing, adapter resolved once at turn entry. Backend-specific settings remain opaque behind `adapterSettings`.
67
- - The common turn sequence stays backend-invariant: spawn → initialize → newSession → enforceModel → prompt → event map.
68
- - Rich operator/project context rides the **first user message augment**, not a large system prompt. The actual callable schema is the tool truth; prose never grants a tool.
69
- - A backend may have no carrier or use launch-time model pinning; those asymmetries stay inside its adapter.
70
- - A streaming assistant message starts `pending`. ACP terminal reasons are mapped explicitly; refusal, exhausted turn budget, unknown, or absent reasons end as errors, and the raw reason is preserved. Never restore a default-to-success branch.
71
- - Bootstrap steps carry wall-clock bounds; a running prompt does not. A turn ends only when the agent answers, the operator aborts (ACP `session/cancel` first, bounded cleanup after), or the child dies. Elapsed time is not evidence, and a prompt-phase failure we author must never read as transient to pi's retry classifier — a cutoff plus blind retry replays the whole prompt from cold.
72
- - Claude is the reference adapter. Cortex is the second landed adapter (0.13.0): session-scoped dual-HOME containment, overlay-private `mcp.json` projection (its ACP server ignores the wire `mcpServers` param), `CORTEX_HOME` presence refusal, per-turn set-model. Current contract: `docs/acp-backend-rail.md` “Cortex Code audit (D1–D10)”.
73
- - entwurf never supplies, copies, proxies, decrypts, or bypasses vendor credentials/subscriptions. It uses the operator's existing local authenticated backend.
53
+ | **entwurf-core** | identity/facts, dispatch table, rail choice, delivery evidence |
54
+ | **ACP plugin** | isolated backend lifecycle, tool narrowing, backend dialect, turn evidence |
55
+ | **ACP does not own** | citizen registration, socket registry, peer protocol, memory/planner, transcript, or auth |
56
+
57
+ - One provider; resolve its adapter once per turn. Backend settings remain opaque behind the adapter.
58
+ - Common sequence is spawn → initialize → newSession → model enforcement → prompt → event map. Callable schema is tool truth; prose grants no tool.
59
+ - Rich context rides the first user-message augment, not a large system prompt. Carrier/backend differences stay inside the adapter.
60
+ - Start streaming assistant messages as pending; explicitly map every terminal reason. Refusal, exhausted budget, unknown, or absent reason is an error and preserves the raw reason.
61
+ - Bootstrap has bounded wall-clock steps; a running prompt has no elapsed-time success/failure inference. Cancel through ACP first, then bounded cleanup. A failure we author must not invite blind whole-prompt replay.
62
+ - Entwurf never provides, copies, proxies, decrypts, or bypasses vendor credentials/subscriptions.
63
+ - Adapter/overlay contracts and backend-specific evidence: [docs/acp-backend-rail.md](./docs/acp-backend-rail.md).
74
64
 
75
65
  ## Citizen Identity and Dispatch
76
66
 
77
- ### One record axis
78
-
79
- A `--entwurf-control` pi session is a citizen for the same reason a native bridge session is: it has a V3 meta-record.
80
-
81
- - pi owns its native session id, filename, transcript, name, `/new`, `/fork`, `/clone`, and `/resume` lifecycle.
82
- - `birthPiCitizen` upserts `(backend:"pi", nativeSessionId)` and receives the stable `gardenId` from the record.
83
- - The control socket is `~/.pi/entwurf-control/<gardenId>.sock`; a record-less socket is a diagnostic, never a citizen.
84
- - `PI_SESSION_ID` and `PI_AGENT_ID` propagate the record-established identity to child MCP processes. They are carriers, not a second authority.
85
- - If record birth fails, no socket starts and no `PI_SESSION_ID` is exported.
86
- - Reopening the same pi native session attaches to the same record; in-process replacement creates/attaches the replacement's own record.
87
- - Resume is shipped as its OWN verb, `entwurf_resume_call {target}` — never as an intent on delivery. It reopens a DORMANT pi citizen under the same garden id in a visible window, and it runs no turn: the window comes back with the conversation and waits. The record supplies transcript, model, provider and cwd, so there is no prompt, no task and no model override. The record-authoritative preconditions live in `resume-launch-identity.ts` / `check-resume-launch-identity` (record existence, transcript-header ↔ `record.nativeSessionId` integrity, addressable-read uniqueness, an absolute recorded transcript, model preservation) and now have a consumer.
67
+ A pi control session and native bridge session are citizens for the same reason: each has a V3 record.
88
68
 
89
- ### Capability domains, not rank
69
+ - Pi owns its native session lifecycle; `birthPiCitizen` attaches `(backend: "pi", nativeSessionId)` to the stable garden id. Socket and env values are record-derived carriers.
70
+ - `entwurf_resume_call {target}` is a separate pi-only lifecycle verb, not delivery intent. It reopens the same dormant id visibly, runs no turn, and receives transcript/model/provider/cwd solely from the record. A launch receipt and socket observation are distinct; an unobserved window stays visible. No watcher, retry, or supervisor.
71
+ - **control-socket:** live send under per-target lock; dormant rejects.
72
+ - **self-fetch:** active receiver plus deliverable mailbox; no resume authority. Sender/receiver joins are owner-kind specific and must not be generalized across vendors.
73
+ - **native-push:** probe-alive direct injection; no mailbox and no resume authority.
74
+ - `entwurf_peers` reports facts only; `entwurf_self` requires record-backed active-rail identity.
75
+ - Delivery returns only an acknowledgement/receipt, not a peer turn result. `wants_reply` is etiquette, not ownership. Sender envelope contains session/agent/cwd/time and derived provenance/replyability.
90
76
 
91
- - **control-socket domain (currently `pi`)**: socket liveness, per-target lock, live send, and a dormant cell that rejects.
92
- - **No relaunch transport exists inside delivery.** `spawn-bg` — a detached, window-less resume child — was removed under the visible-first rule, not deprecated behind a reject, and `entwurf_v2` still starts no process: a dormant socket-domain citizen is refused as `dormant-fire-forget-unsupported`. Reopening one is the separate lifecycle verb `entwurf_resume_call`, which is pi-only (`target-not-pi` otherwise), returns a LAUNCH receipt and an OBSERVATION receipt that are never merged, releases its per-gid lock on every path, and on an unobserved socket leaves the visible window open rather than retrying. No watcher, no retry, no supervisor. Do not re-route it through `entwurf_v2` and do not describe a spawn domain that does not exist.
93
- - **self-fetch domain (Claude Code, Copilot CLI)**: active receiver + mailbox deliverability; no resume authority. The two arm that receiver through different vendor surfaces — a Claude hook that emits watchPaths, a Copilot first-party extension that holds the watch in a forked child — and the marker records which, because the pid a reader verifies differs. A live marker is not by itself an armed doorbell: where the watch owner IS the process the sender marker is keyed to (`ownerKind: claude-code-cli`), that owner may switch sessions in place, so deliverability also requires its sender marker to still name the same garden. That join is `ownerKind`-scoped by construction — a Copilot watch lives in a forked child with its own pid, so the join does not exist there and must never be applied to it (#101).
94
- - **native-push domain (currently Antigravity)**: adapter probe + direct injection; no mailbox and no resume authority.
95
- - `origin: "pi-session" | "meta-session" | "external-mcp"` records sender provenance. It is not the citizen identity schema and not a hierarchy.
96
- - `entwurf_peers` reports record citizens and liveness facts only. It never embeds routing verbs or socket addresses for peers.
97
- - `entwurf_self` is identity-required. For pi, its env carrier must have been planted from record birth; native marker identity must be backed by the matching record. Replyability is derived from the active rail, never hardcoded.
77
+ ## Issue Queue
98
78
 
99
- ### Send-is-throw
79
+ Keep at most ten open issues, including at most five implementation issues. Classify by destination: a diff-closing issue is implementation; research or a decision is not. An issue needs current evidence and an executable next measurement. Do not keep collection points or “just in case” issues; move enduring direction to [ROADMAP.md](./ROADMAP.md) and close solved work at its durable SHA. The issue thread is the live contract; repair a stale body visibly when it diverges.
100
80
 
101
- - Delivery returns an ack/receipt, not the peer's turn result. If a reply is wanted, say so and set `wants_reply`; that flag is etiquette, not ownership.
102
- - Sender envelope: `{ sessionId, agentId, cwd, timestamp, origin?, replyable? }`.
103
- - Human-opened and spawned/resumed siblings use the same addressing and messaging semantics.
104
-
105
- ## Issue queue — a manual sweeper, not a backlog
81
+ ## Verification
106
82
 
107
- - **Two caps, and the inner one is what disciplines the work.** OPEN issues are capped at **ten** in total; of those, **implementation issues the ones that will go out on a branch are capped at five**. A sixth implementation issue means one closes first; that inner cap does not bend.
108
- - **What sits outside the implementation five:** research issues, and issues GLG keeps open to look at. These are not slots to be earned or swept — a research lane may stay open across releases, and a north-star issue other repos read may never close. They still count toward the ten, so the queue cannot grow without limit.
109
- - Classify by destination, not by size: if closing it produces a diff, it is an implementation issue. If closing it produces a decision, a document, or nothing, it is not.
110
- - A slot is earned by a current defect or executable contract, not by importance, age, or possible future value.
111
- - Direction, philosophy, frozen invariants and observations without a current action live in `ROADMAP.md`, durable docs, or closed history.
112
- - Nothing stays open "in case." If a closed problem recurs, it returns as a new issue carrying the new evidence.
113
- - Anything whose only value is knowing it gets moved to the document that owns it, then closed.
114
- - A new issue brings the best available observation plus an executable next measurement. Recovering a missing signature may be the first acceptance; an idea with neither evidence nor a next measurement is not an issue.
115
- - No collection points, umbrella trackers, or fallout buckets. Merge issues only when they share one cause and one acceptance.
116
- - Sweep manually after a release and before opening an issue. Solved work closes at its durable SHA; it does not wait for the next release.
117
- - **An issue body is a snapshot; the thread is the live contract.** A body written before GLG stated what the work is *for* will disagree with the thread, and a reader who opens only the body inherits the stale half — including its fences, which is how a fence once forbade the very deliverable the lane existed to produce (#82, 2026-08-20). When they disagree the thread wins. Whoever notices owes the body an edit that strikes the withdrawn clause and says why it was there; deleting it silently makes the queue tidy and the lesson invisible.
83
+ Two independent axes are required: deterministic/package gates and opt-in LIVE evidence. Exact commands, evidence levels, and release acceptance are owned by [VERIFY.md](./VERIFY.md); recorded host evidence by [BASELINE.md](./BASELINE.md). Run LIVE gates from scratch with ambient identity carriers stripped so artifacts and callbacks cannot bleed from the operator session.
118
84
 
119
- ## Verification
85
+ ### Scheduling
120
86
 
121
- Two axes are required: deterministic/package gates and opt-in LIVE evidence.
122
-
123
- ```bash
124
- pnpm typecheck
125
- pnpm check # everyday core — prints total wall time; ≤60s on oracle
126
- pnpm run check:full # full deterministic floor — core + hermetic/package tiers
127
- ./run.sh check-entwurf-v2-matrix
128
- ./run.sh check-meta-session
129
- ./run.sh check-entwurf-bridge-boot
130
- ./run.sh check-install-surface
131
- ./run.sh check-install-container # require Docker in release acceptance
132
-
133
- LIVE=1 ./run.sh release-gate /path/to/scratch --cut
134
- LIVE=1 ./run.sh smoke-acp-socket-citizen-live
135
- LIVE=1 ./run.sh smoke-acp-bundled-mcp-live
136
- LIVE=1 ./run.sh smoke-acp-v2-send-live
137
- LIVE=1 ./run.sh smoke-mux-lifecycle-live
138
- LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live # on-demand; outside the claude release floor
139
- LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live
87
+ ```text
88
+ implement → affected focused gates → independent review → one amendment bundle
89
+ → qualification once if gate/mutant/matrix changed → full floor once on frozen candidate → commit
140
90
  ```
141
91
 
142
- - The deterministic floor is tiered (#70). `pnpm check` is the everyday core — toolchain (lint + typecheck), the vitest lanes, and the pure-unit / behavioral-contract / source-topology gates plus the cheap static coherence checks. It prints its own total wall time; acceptance is ≤60s on the reference host `oracle` (an operator measurement, never a hard wall-clock gate on arbitrary hosts). `pnpm run check:full` is the full deterministic floor — the core plus the hermetic-integration and package/install tiers — and is what the candidate protocol, push CI, release-gate, and `prepublishOnly` run. Exact membership is the named `check:*` group scripts in `package.json` (the executable SSOT); a gate changes tier by semantic-class decision, never because it happened to get faster or slower. The full tier carries `check-gate-manifests` (the qualification HEAD, through `check:hermetic`); the everyday core does not, and neither tier carries the mutant-executing `check-gate-qualification`, which is scheduled separately (below).
143
- - **Kill-proof discipline (gate qualification).** A gate is a test only if re-planting a closed defect turns it red for the claimed reason. `check-gate-qualification` proves that automatically: committed mutants in `scripts/mutants/` must be KILLED at their `[QK:<claim>]` signature inside an isolated snapshot repo (control→mutant→restore→control; the real checkout is never written). Gates a release touches carry such manifests; assertion counts are never evidence — claim IDs + killed mutant IDs are. `check-agy-permission-matrix` holds the enumerated permission contract space; matrix cells change by axis/rule edits, never by appending cases.
144
- - **When changing a contract/gate:** name the production subject and an oracle independent of it; give the failing assertion a stable `[QK:<claim>]` label and add/update the exact-once mutant in `scripts/mutants/*.json`; if the contract is combinatorial, update the literal matrix axes/cells/exclusions together with their declared counts; then verify the focused gate, and let qualification and the full floor follow the scheduling contract below — once on the frozen candidate, not once per amendment. `MUTANT-STALE`/`SURVIVED`/`WRONG-REASON`/`CONTROL-RED`/`HANG`/`IMPURE` are red — never substitute an assertion count for a kill.
145
- - Run LIVE gates with `PWD` in scratch so session artifacts do not land in the repo. Strip `CLAUDE_CONFIG_DIR`, `PI_SESSION_ID`, and `PI_AGENT_ID` from the gate process a live pi/ACP session exports them into children, where they strip Claude hooks or capture a fresh-call callback.
146
- - Release acceptance and evidence levels are defined in [VERIFY.md](./VERIFY.md); recorded host evidence is in [BASELINE.md](./BASELINE.md).
147
- - A failed gate or evidence downgrade blocks commit/release. Pipes can be connected and the water can still taste wrong.
92
+ - Inner loop runs only affected gates; review and its corrections finish before the full floor.
93
+ - A changed contract names a production subject and independent oracle; its focused assertion has a stable QK and exact-once mutant. Matrices change by their declared axes/cells, not appended anecdotes.
94
+ - Qualification body is scheduled once when its surface changes; its manifest/head checks remain in the deterministic floor. A release requires the exact-SHA qualification evidence required by VERIFY, never a nearby green run.
95
+ - Freeze the candidate while the full floor runs; any worktree/index movement voids that receipt. Pre-commit is not the full floor.
96
+ - LIVE/release floors are not lowered by a shorter inner loop. Failed gate or evidence downgrade blocks the relevant commit/release decision.
148
97
 
149
- ### Verification scheduling when the floor runs
98
+ ## Type and Working Boundaries
150
99
 
151
- Gate quality and gate scheduling are different axes: the gates above define *what* green means; this contract owns *when* each layer runs. It exists because repeating the full floor around every review amendment once cost more than the work it verified (history: CHANGELOG/git).
100
+ - Each `.ts` file belongs to one declared typecheck fence; never hide a file with `exclude`. Root pi extensions use TypeBox through `@earendil-works/pi-ai`; MCP/scripts use explicit `.ts` imports required by Node strip-types. Installed surfaces route to compiled JS.
101
+ - Make surgical, one-contract changes. Removal repairs source and its proof together; a green gate never proves retired behavior.
102
+ - Before commit, sweep repository-wide for retired authority vocabulary and landed-plan future tense. Historical tombstones may remain; live docs, source, gates, and usage must agree.
103
+ - Prefer capability-domain language over identity rank. Use tabs unless the project formatter requires otherwise. GLG decides commit, push, and release gates.
152
104
 
153
- ```text
154
- implement → affected focused gates → independent review → one amendment bundle
155
- → [gate/mutant changed? check-gate-qualification once] → pnpm run check:full once on the frozen candidate → commit
156
- ```
105
+ ### Review Discipline
157
106
 
158
- - **Inner loop:** run only the gates whose subject changed. Do not open the full floor to learn what a focused gate already answers.
159
- - **Review before floor:** independent review and its corrections close as one bundle before the full floor runs.
160
- - **Qualification is scheduled, not ambient — but its HEAD is not.** The mutant-EXECUTING body, `check-gate-qualification`, is not in the default check chains (core or full), so the operator inner loop never re-pays the full mutant inventory. It runs standalone once when a lane changed a gate, mutant, or matrix; machine time re-proves it everywhere else — the CI `check` job runs it on a branch push whose two-dot range touched the qualification surface (`scripts/ci-qualify-decide.sh` derives that path set from the manifests themselves), unconditionally on `workflow_dispatch -f qualify=true` and a weekly schedule, and release-gate carries it as a MUST step. The exact-SHA release oracle refuses a SHA whose body step did not conclude success, so a filtered-out release commit is a named failure with a documented dispatch recovery, never a quiet pass. Its head — runner self-test, manifest-set validation, declared lane inventory — is `check-gate-manifests`, which executes no mutant and never snapshots the repo, and it IS in `check:hermetic`: three of the five reds qualification has ever produced in CI died there in under five seconds. A tag push runs no CI at all, and the exact-SHA evidence a release quotes is whichever run at that commit carries the body concluding success — the branch run when the push moved the qualification surface, else the dispatch run the release skill's recovery creates.
161
- - **Full floor once** (`pnpm run check:full`), on the frozen commit candidate. While it runs, nothing edits the worktree or index including the NEXT boot sectors; a moved candidate voids the run's evidence.
162
- - **pre-commit is not the floor.** `.husky/pre-commit` carries only fast static checks (whitespace, lint, typecheck); the full floor is owned by this protocol, not by the hook. Do not grow the hook back, and do not build receipt/cache machinery to prove the protocol was followed.
163
- - **Release/LIVE acceptance is untouched.** VERIFY.md floors keep full strength; a shorter inner loop never lowers release evidence.
107
+ - Reproduce one manual action per step: measure narrow leaf visible composition observe pain next step. Never pre-build manager, watcher, backlog, role system, or model-specific scaffolding.
108
+ - Classify findings: **Blocker** (false success, data loss, authority violation) fixes now; **Defect** (explicit-contract mismatch) joins one amendment bundle; **Observation** records future risk without opening current work. Two new architecture blockers in an amendment bundle return to design.
109
+ - Source-adjacent proof belongs with its capability. Unrelated scheduling/cache/receipt infrastructure does not ride that lane. If verification grows beyond the capability it serves, stop and report to GLG.
110
+ - Claims crossing sessions carry evidence state: measured receipt, `file:line`, external artifact, or named unverified source. Keep inherited facts separate from proposals; paste decisive evidence into cross-host artifacts.
164
111
 
165
- ## Repository Map
112
+ ## References
166
113
 
167
- | Path | Purpose |
168
- |---|---|
169
- | `pi-extensions/entwurf-control.ts` | pi adapter: record attach, record-keyed socket, RPC, native tools |
170
- | `pi-extensions/lib/pi-citizen-birth.ts` | pi native session shared V3 record → socket address |
171
- | `pi-extensions/lib/meta-session.ts` | shared V3 record/store authority plus native marker/mailbox primitives |
172
- | `pi-extensions/lib/entwurf-v2-*.ts` | v2 contract, decider, transports, runner, production wiring; visible resume keeps launch injected |
173
- | `pi-extensions/lib/mux-*.ts` | same-tmux placement plus narrow fresh-call and visible-resume launch compositions |
174
- | `pi-extensions/lib/entwurf-fact*.ts` | record citizens + transport-specific liveness facts |
175
- | `pi-extensions/lib/entwurf-peer-observe.ts` | the IO half of the observed peer facts (receiver / transcript) |
176
- | `pi-extensions/lib/native-push/` | native-push adapter/probe/register leaf |
177
- | `pi-extensions/acp-provider.ts` | `entwurf` provider registration |
178
- | `pi-extensions/lib/acp/` | ACP adapter rail, config/overlay, augment, turn loop, event mapping |
179
- | `mcp/entwurf-bridge/` | MCP surface for v2/self/peers/inbox/native-register/fresh-call/resume-call |
180
- | `scripts/` | deterministic gates, LIVE smokes, install/doctor surfaces |
181
- | `run.sh` | installed command and gate dispatcher |
182
-
183
- ## Type and Runtime Boundaries
184
-
185
- - Every `.ts` file belongs to one typecheck fence: root emit-capable config, MCP strip-types config, or scripts strip-types config. Do not hide files with `exclude`.
186
- - Root pi extensions import TypeBox through `@earendil-works/pi-ai`; do not mix direct `@sinclair/typebox` types.
187
- - MCP/scripts use explicit `.ts` imports where Node strip-types requires them. Installed operator surfaces route to compiled JS.
188
- - pi runtime range is `>=0.85.1 <0.86` with devDep exact `0.85.1`; re-evaluate loader aliases and `/compat` at every minor ceiling. The ceiling moves on measurement, never on assumption, and a previous bump's argument is never reused: at 0.83.0→0.84.0 `compat.ts` was still byte-identical but `loader.ts` was NOT, so the diff itself had to be read and judged reachable-or-not. Per-bump hashes, diff judgments, and reachability findings live in the ROADMAP **Dep bump(별도 트랙)** ledger — keep them there, not here.
189
- - ACP pins are recorded in `package.json` and owned by `check-acp-sdk-surface`, which is the vitest contract `test/acp-sdk-surface.contract.test.ts` (`./run.sh check-acp-sdk-surface` is a transition shim into it, not a `scripts/` gate). `check-dep-versions` is the **pi** pin's oracle and reads no ACP pin — do not cite it for one. Do not describe a dependency bump as a behavioral fix without evidence.
190
-
191
- ## Working Style
192
-
193
- - Surgical changes, one contract at a time. Ask whether a change belongs in core, a harness adapter, a backend adapter, or the resident's own repo.
194
- - Removal/repair changes source and their gates together. Do not leave a green gate that only proves retired behavior.
195
- - Before commit, perform a **repo-wide** stale-prose sweep on two axes:
196
- 1. retired symbols/authority vocabulary (`dual-read`, old schema names, removed commands, privileged identity wording);
197
- 2. landed-plan future tense (`yet`, `will land`, `not here`, stale step headers).
198
- - Judge each grep hit: historical CHANGELOG tombstones may remain; live claims, comments, usage text, gates, README, docs, NEXT, and source-module prose must agree with current behavior.
199
- - Prefer capability/domain names (`control-socket domain`, `self-fetch`, `native-push`, `out-of-domain`) over identity-rank names (`pi-only citizen`, `non-pi citizen`).
200
- - Keep docs calibrated and compact. Implementation archaeology belongs in git/CHANGELOG/issues; AGENTS keeps only invariants needed before acting.
201
- - Use tabs unless the existing file/linter requires otherwise.
202
- - GLG decides commit, push, and release gates. Never infer push from a commit request.
203
-
204
- ### Review triage and lane discipline
205
-
206
- An overgrowth is built from locally correct steps; what fails is the absence of a budget and a stop rule. These are that budget.
207
-
208
- - **Reproduce one manual operator action per step.** Measure → narrow leaf → visible composition → observe real pain → next step. Never pre-build the general future (orchestrator, watcher, manager, backlog, role system) ahead of an observed bottleneck, and never build structure to compensate for a current model's habits — both burn with the next model or billing change.
209
- - **Triage review findings into three grades.** *Blocker* (false success, data loss, authority violation): fix in the current lane. *Defect* (real mismatch against the current explicit contract): fix in the amendment bundle. *Observation* (future risk, stronger-proof possibility): record it — it does not open work in the current lane.
210
- - **One amendment bundle per review.** If the bundle itself surfaces two or more new architecture blockers, stop repairing and go back to the design.
211
- - **Unrelated meta-infra never rides a capability lane.** The source-adjacent gate/mutant that proves a capability's contract belongs in the same change as that capability — the removal/repair rule above is untouched. What stays out of a feature commit candidate is unrelated verification machinery: scheduling rework, selectors, caches, receipts, floor restructuring. That pain is recorded and handled in its own subtraction lane later.
212
- - **Stop signal — evidence outgrowing the product.** When verification/meta-tool changes grow larger than the capability change they serve, stop and report to GLG. This is an operator-judgment trigger, deliberately not a mechanized ratio gate.
213
- - **Claim only what the evidence carries.** "The full floor was green once on the declared candidate" is strong enough; a stronger sentence mints proof obligations, and those obligations mint subsystems.
214
- - **A claim that crosses sessions carries its evidence state.** Measured here (name the receipt), read at `file:line`, read from an external artifact (name the path), inherited and unchecked (name the source) — and design proposals in a box of their own, since a proposal is adopted or decided differently, never measured. This repo is where siblings from many models each get a few turns, so a bare sentence costs the next one its turn re-deriving the ground, and leaves it only "believe or refute" when the honest move is "that carries no receipt, so I measured it." Retire claims, not people. Receipts in host-local paths do not travel: paste the decisive lines into the artifact that crosses.
215
- - **Risk classes are not equal.** Data loss, identity authority, false delivery success, install destruction, and secrets get fail-closed strength. Doc tense, future possibility, and total environment-byte binding get repaired when seen — they do not justify new gate machinery.
216
-
217
- ## Next and References
218
-
219
- - [NEXT.md](./NEXT.md) — current priority and exact next move; branch work uses disposable `NEXT--<branch>.md`.
220
- - [ROADMAP.md](./ROADMAP.md) — forward direction and deferred lanes.
221
- - [docs/adding-a-harness.md](./docs/adding-a-harness.md) — **first entry point for putting a NEW harness in the garden.** The order the eight steps are actually walked in (lane choice, vendor measurement, backend registration, birth, statusline, MCP hand, sender identity, receive, grade), what each owes before the next may start, and which of the other docs owns each slice. It routes; it grants nothing — Hard Rule 7 remains the authority on the meta-record store contract its registration step touches, and the gates and doctors it names remain the truth.
222
- - [docs/acp-backend-rail.md](./docs/acp-backend-rail.md) — ACP adapter contract and current entry conditions.
223
- - [DELIVERY.md](./DELIVERY.md) — delivery capability/evidence coordinates.
224
- - [VERIFY.md](./VERIFY.md) / [BASELINE.md](./BASELINE.md) — verification protocol and recorded evidence.
114
+ - [NEXT.md](./NEXT.md) current ordering and handoff.
115
+ - [ROADMAP.md](./ROADMAP.md) — direction and deferred work.
116
+ - [docs/adding-a-harness.md](./docs/adding-a-harness.md) entry route for a new harness.
117
+ - [docs/mux-launch-rail.md](./docs/mux-launch-rail.md) mux ownership and launch contracts.
118
+ - [docs/acp-backend-rail.md](./docs/acp-backend-rail.md) ACP adapter contract.
119
+ - [DELIVERY.md](./DELIVERY.md), [VERIFY.md](./VERIFY.md), [BASELINE.md](./BASELINE.md) delivery coordinates, verification protocol, and evidence.
225
120
  - [README.md](./README.md) — operator-facing package contract.
package/BASELINE.md CHANGED
@@ -8,9 +8,9 @@ not what it was told to claim.
8
8
 
9
9
  Claude is the reference ACP backend. Cortex Code has a separate compact baseline
10
10
  because it has no system-prompt carrier and keeps its own native tool surface.
11
- Antigravity (`agy`) is a native-push citizen rather than an ACP backend and therefore
12
- has a separate citizen/round-trip baseline. Historical Codex/Gemini probes are not
13
- part of this operator interview.
11
+ Antigravity (`agy`) and Codex are native-push citizens rather than ACP backends and therefore
12
+ have separate citizen/round-trip baselines. Codex's 0.153.4 explicit-`codex`-home acceptance
13
+ receipt and protocol live in `DELIVERY.md`; neither is part of this ACP operator interview.
14
14
 
15
15
  ## Release-host baseline
16
16
 
@@ -34,6 +34,9 @@ not **UNSUPPORTED** — the deliberate never, which today is native Windows only
34
34
  | Maintainer NixOS installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 registry install → doctor exit 0 (HISTORY) |
35
35
  | Secondary Ubuntu installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 same artifact, isolated agent dir → doctor exit 0 (HISTORY) |
36
36
  | macOS Claude meta-bridge | NOT CERTIFIED — pending physical host | No physical-Mac doctor yet; a CI runner has no Claude login. Physical-host rental remains unscheduled; no cut has carried it. |
37
+ | Native Codex Linux caller-DIRECTORY axis (current; #95 lane C) | **certified** | 2026-09-16, Codex 0.153.4: 65-assertion LIVE, exit 0, at `b3e07dc` with a clean worktree. Same host and topology as the lane B row below (app-server `737636` in A `$30/@41/%45`; initial Pi `20260916T154902-556eb5` `$2/@58`, Codex `20260916T155037-10ddaa` `$2/@59`, Codex-opened Pi `20260916T155102-9add8a` `$2/@61`, `seat-source=codex-title-anchor`). **hop 1 (cwd requested):** pane `#{pane_current_path}` = rollout `session_meta.cwd` = record cwd = requested scratch = `/tmp/entwurf-codex-fresh-live-db65N2`, against app-server cwd `/home/junghan/repos/gh/entwurf` read from `/proc/737636/cwd`. **hop 2 (cwd NOT requested):** the outbound Pi's pane, its own birth-written record and the Codex caller's record all read that same scratch, and its receipt names the caller-record rule. Artifact `.probe-artifacts/codex-fresh-live-w4yJBw/`; stdout `.probe-artifacts/lane-c-live-20260916T154900.log` sha256 `712050e7a8cf03ece98e7f34029ae98a92e9b2a7fd96aff87d0c1e6ba2ee9af2`. Cleanup reclaimed `@58`/`@59`/`@61` with no failure; records and transcripts preserved; app-server and `$30` untouched. 65 and 56 are different contracts — lane C added the cwd axis on top of lane B. Long floors (qualification body, frozen `check:full`) NOT run at this SHA; GLG decides host vs CI. |
38
+ | Native Codex Linux caller-seat topology (current; #95 lane B) | **certified** | 2026-09-16, Codex 0.153.4: 56-assertion LIVE, exit 0. App-server `737636` alone in session A `$30/@41/%45`; initial Pi `20260916T144205-e876ff` `$2/@46`, omitted-placement Codex `20260916T144230-d050d7` `$2/@47`, Codex-opened Pi `$2/@48`. A ≠ S is the decisive half: the app-server env names A, so S can only have come from the caller's pane title — receipt `seat-source=codex-title-anchor`. Artifact `.probe-artifacts/codex-fresh-live-nYcGC1/run-stdout.log` sha256 `ed60c2bd…`; the 43-assertion hop-1 run that measured the D1 retirement is kept at `codex-fresh-live-4aFCDD/run-stdout.log` sha256 `8392a603…`. Cleanup reclaimed `@46`/`@47`/`@48` with no failure; app-server and `$30` untouched. |
39
+ | Native Codex Linux home topology (PAST CONTRACT — #95 D1 retired the fixed home 2026-09-16) | **certified** for 0.21.0 as shipped | 2026-09-12, Codex 0.153.4: 57-assertion explicit-home LIVE. Initial Pi `$150/@397`; operator app-server `$158/@390/%390`; omitted-placement Codex `$158/@398`; Codex-opened Pi `$158/@399`; exact callbacks and addressed delivery both ways. Receipt and digest: `DELIVERY.md`. Deterministic closure of that axis: qualification 460/460 across 43 lanes with origin/snapshot purity green, then frozen full floor exit 0 in 506s — both pre-amendment. **Observer-amended acceptance, 2026-09-12:** standalone LIVE 48 assertions exit 0, source audit `initial-pi=3/3`/`codex=3/3` completed exact, initial Pi `$150/@431`, Codex `$158/@432`, Codex-opened Pi `$158/@433`, all three reclaimed by their own source receipts; artifact `.probe-artifacts/codex-fresh-live-fZccoK/`. The 48 and 57 counts are different contracts, not a regression. **Release acceptance at that same fingerprint:** `check:full` exit 0 502s, LIVE release gate `--cut` MUST 24/0/0 · BEHAVIOR 1/0/0 · `cut: OK`, `check-gate-qualification` 475/475 across 43 lanes with origin purity green, and the aggregate's Codex leg repeating the 48-assertion acceptance (artifact `codex-fresh-live-2oId4C`). Unrestricted attached-TUI placement remains unsupported and unclaimed. |
37
40
  | Darwin install fence (meta/copilot/omp-bridge + omp-receive) | portable (Linux or Darwin) | Four installers accept Darwin; python3/node/harness presence holds the seat, not the platform name. A Darwin install is not a rail receipt. |
38
41
  | Doctor fail-closed on unreadable environ | Linux measured; Darwin unmeasured | Copilot launch-flag and omp identity-carrier: missing `/proc/<pid>/environ` as predicate INPUT is `UNVERIFIABLE` (non-green), not a benign note. omp distinguishes `pgrep` exit 1 (absent) from exit 2 (enumeration failed); copilot distinguishes ENOENT/ESRCH (gone) from other errno (read denied). |
39
42
  | setup on uncertified platform with harness present | named non-green | All 13 harness units ask `harness_rail_certified_platform()`; uncertified → FAIL whose wording is not "install failed". Harness-absent Darwin setup (the CI cell) can still be computed green. |