@junghanacs/entwurf 0.18.2 → 0.20.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.
- package/AGENTS.md +2 -2
- package/BASELINE.md +23 -5
- package/CHANGELOG.md +415 -0
- package/DELIVERY.md +59 -6
- package/README.md +43 -12
- package/VERIFY.md +10 -2
- package/docs/acp-backend-rail.md +9 -1
- package/docs/external-mcp-host.md +8 -5
- package/docs/setup-clean-host.md +93 -7
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +18 -7
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +3 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +6 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +76 -9
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-placement.js +54 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resolve-tmux-session.js +114 -0
- package/mcp/entwurf-bridge/src/index.ts +22 -7
- package/package.json +2 -2
- package/pi-extensions/acp-provider.ts +1 -1
- package/pi-extensions/entwurf-control.ts +27 -3
- package/pi-extensions/lib/acp/models.ts +3 -3
- package/pi-extensions/lib/acp/overlay.ts +6 -2
- package/pi-extensions/lib/meta-session.ts +25 -0
- package/pi-extensions/lib/mux-fresh-call.ts +98 -11
- package/pi-extensions/lib/mux-placement.ts +65 -10
- package/pi-extensions/lib/resolve-tmux-session.ts +137 -0
- package/run.sh +71 -26
- package/scripts/agy-bridge.sh +1 -1
- package/scripts/agy-imprint.sh +10 -7
- package/scripts/check-acp-carrier-augment.ts +6 -5
- package/scripts/check-acp-cortex.ts +41 -0
- package/scripts/check-acp-provider-surface.ts +9 -6
- package/scripts/check-copilot-birth-hook.ts +3 -1
- package/scripts/check-copilot-receive-arm.ts +169 -21
- package/scripts/check-copilot-statusline.ts +3 -1
- package/scripts/check-fresh-cut-gate.sh +54 -2
- package/scripts/check-gate-qualification.ts +13 -12
- package/scripts/check-hook-launch-topology.ts +6 -5
- package/scripts/check-install-surface.ts +2 -1
- package/scripts/check-meta-facts.ts +6 -4
- package/scripts/check-meta-hook-session-switch.ts +4 -3
- package/scripts/check-meta-identity-consumers.ts +8 -7
- package/scripts/check-meta-receiver-marker.ts +2 -1
- package/scripts/check-mux-launch-tmux.ts +77 -2
- package/scripts/check-mux-launch.ts +17 -0
- package/scripts/check-mux-placement-tmux.ts +61 -1
- package/scripts/check-mux-placement.ts +33 -0
- package/scripts/check-omp-birth-hook.ts +3 -2
- package/scripts/check-probe-bridge-command.ts +3 -1
- package/scripts/check-setup-qualification.sh +21 -0
- package/scripts/copilot-bridge-doctor.sh +15 -5
- package/scripts/copilot-bridge-install.sh +6 -2
- package/scripts/copilot-launch.sh +16 -2
- package/scripts/copilot-receive-bridge.sh +80 -13
- package/scripts/lib/reclaim-on-exit.ts +86 -0
- package/scripts/meta-bridge-doctor.sh +56 -15
- package/scripts/meta-bridge-install.sh +13 -7
- package/scripts/meta-bridge-uninstall.sh +6 -4
- package/scripts/mutants/acp-cortex.json +26 -2
- package/scripts/mutants/copilot-receive.json +26 -0
- package/scripts/mutants/fresh-cut.json +26 -0
- package/scripts/mutants/mux-boundary.json +24 -0
- package/scripts/mutants/mux-fresh-call.json +81 -0
- package/scripts/mutants/omp-birth.json +33 -3
- package/scripts/mutants/setup-verdict.json +13 -0
- package/scripts/omp-bridge-doctor.sh +110 -31
- package/scripts/omp-bridge-install.sh +6 -2
- package/scripts/omp-receive-install.sh +7 -2
- package/scripts/raw-async-delivery/README.md +10 -1
- package/scripts/raw-codex-measure/README.md +689 -0
- package/scripts/raw-codex-measure/source-audit.md +243 -0
- package/scripts/raw-macos-measure/README.md +148 -0
- package/scripts/raw-macos-measure/probe.sh +389 -0
- package/scripts/smoke-meta-async-drift.sh +7 -5
- package/scripts/smoke-meta-install-state.sh +70 -19
- package/scripts/smoke-mux-fresh-call-live.ts +175 -3
- package/scripts/smoke-omp-bridge-state.sh +43 -2
- package/scripts/smoke-setup-verdict.sh +100 -0
package/AGENTS.md
CHANGED
|
@@ -28,9 +28,9 @@ For agents that own this repo: invariant principles and reproducible verificatio
|
|
|
28
28
|
- **entwurf-core (v2)** owns garden-id addressing, peer facts, liveness interfaces, dispatch decisions, rail choice, and delivery evidence.
|
|
29
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
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
|
|
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
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
|
|
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
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.
|
|
35
35
|
|
|
36
36
|
## Hard Rules
|
package/BASELINE.md
CHANGED
|
@@ -18,17 +18,28 @@ This table is the operator-facing support/certification view. It complements the
|
|
|
18
18
|
model interview below; a persuasive answer from the model cannot turn an unmeasured
|
|
19
19
|
host into a certified one. Verdicts are one of **certified** (a real host ran the
|
|
20
20
|
installed doctor green), **shape-only** (gates model the package, no live host),
|
|
21
|
-
or **unverified**.
|
|
21
|
+
or **unverified**. Since 0.20.0 the table also carries two qualifiers:
|
|
22
|
+
**CERTIFIED (CI)** marks a shape-only surface observed green on a CI runner — a
|
|
23
|
+
runner is not a physical host, so bare **certified** still means a physical-host
|
|
24
|
+
doctor green; and **NOT CERTIFIED — pending physical host** marks a rail whose
|
|
25
|
+
missing evidence only a physical host can supply. That is an evidence boundary,
|
|
26
|
+
not **UNSUPPORTED** — the deliberate never, which today is native Windows only.
|
|
22
27
|
|
|
23
28
|
| Surface | Verdict | Evidence |
|
|
24
29
|
|---|---|---|
|
|
25
30
|
| Node 24 Linux package consumer | shape-only | Required `artifact-consumer` CI |
|
|
31
|
+
| Node 24 macOS package consumer (GitHub Actions runner, not a physical Mac) | shape-only · CERTIFIED (CI) | Required `macos-install-surface` CI run 34303884286 @ `70eda03` (`macos-latest`, 65 s, 10/10 steps): pack → clean consumer install → bin links → `entwurf --help` → `check-bridge` (7 tools) → harness-absent `setup` (all SKIP, computed green, zero no-write-axis writes, `auth.json` byte-identical). Certifies no harness rail. |
|
|
26
32
|
| Claude Code >=2.1.217 exec form | **certified** — supported floor | Topology + floor gates, doctor oracle; B2 live NixOS session |
|
|
27
33
|
| Claude Code 2.1.138 | **unsupported** | Launcher refuses empty argv; no shell-form fallback |
|
|
28
34
|
| Maintainer NixOS installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 registry install → doctor exit 0 (HISTORY) |
|
|
29
35
|
| Secondary Ubuntu installed package | **certified** for `0.12.8-repair.1` | 2026-07-25 same artifact, isolated agent dir → doctor exit 0 (HISTORY) |
|
|
30
|
-
| macOS Claude meta-bridge |
|
|
31
|
-
|
|
|
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 is postponed past this 0.20.0 cut. |
|
|
37
|
+
| 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
|
+
| 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
|
+
| 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. |
|
|
40
|
+
| macOS physical-host probe | shipped, unrun on a Mac | `scripts/raw-macos-measure/` — `/bin/sh`, cells M1–M9, 3.5 s; needs neither entwurf install nor login. Still unmeasured: Darwin foreign-process environ (`ps -Eww`) and whether macOS `python3` is a CommandLineTools stub. |
|
|
41
|
+
| WSL2 | unverified | Counts as Linux evidence, never a Windows surface (AGENTS Hard Rule 17) |
|
|
42
|
+
| native Windows | UNSUPPORTED | Locked pending GLG; a scope decision, not an evidence gap |
|
|
32
43
|
|
|
33
44
|
Notes the table cannot carry without becoming prose again:
|
|
34
45
|
|
|
@@ -36,13 +47,20 @@ Notes the table cannot carry without becoming prose again:
|
|
|
36
47
|
candidate `.tgz`, checkout-invisible non-root global install, PATH shims, a frozen
|
|
37
48
|
package root, the path+sha256 regular-file fence, and a strict doctor fixture. Its
|
|
38
49
|
planted Claude cache/owner/bridge are synthetic — no real Claude lifecycle runs there.
|
|
50
|
+
- **A CI runner is not a physical host.** The macOS consumer row is `macos-latest`
|
|
51
|
+
— an image, not the NixOS/Ubuntu "host" of the certified rows. Its green covers
|
|
52
|
+
the Entwurf-only install surface (pack, install, bins, `--help`, `check-bridge`,
|
|
53
|
+
harness-absent `setup`); it cannot log into a harness, so no rail, marker join,
|
|
54
|
+
ACP turn, or mux lifecycle is certified by it.
|
|
39
55
|
- **Both certified hosts are certified for the published repair artifact only**, including
|
|
40
56
|
physical `entwurf_v2` delivery and the live owner join. Stable cuts earn their own host
|
|
41
57
|
proof; hand-patched hooks and `plugin validate` output are never acceptance.
|
|
42
58
|
- **The maintainer host first went doctor-RED** on a managed dev-bin shadowing the registry
|
|
43
59
|
bridge, and now runs dev wiring again.
|
|
44
|
-
- **macOS is not
|
|
45
|
-
|
|
60
|
+
- **macOS evidence is split, not a support claim.** The Entwurf-only install surface is
|
|
61
|
+
CERTIFIED (CI) (row above); the harness rails are NOT CERTIFIED — pending
|
|
62
|
+
physical host (rental postponed past this cut). The package-level `os` field stays
|
|
63
|
+
unrestricted, and native Windows is UNSUPPORTED.
|
|
46
64
|
|
|
47
65
|
**Operator acceptance rule:** on a claimed Claude host, reinstall from the released
|
|
48
66
|
artifact, restart every old Claude process, open a new session, and run the doctor
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,421 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.20.0 - 2026-09-09
|
|
8
|
+
|
|
9
|
+
This range carries three lanes that are not one cause: the macOS
|
|
10
|
+
install-surface axis (#78), `claude-fable-5-1` on the curated ACP surface,
|
|
11
|
+
and the Cortex `realHome` path-flavor fix (PR #77). GLG (2026-09-09)
|
|
12
|
+
deferred the physical-Mac loan: this cut is honest about a **CERTIFIED (CI)**
|
|
13
|
+
install surface and does not pretend the harness rails are certified.
|
|
14
|
+
|
|
15
|
+
**macOS in this release.** This release adds macOS support for Entwurf's
|
|
16
|
+
install surface: the npm package installs, `entwurf --help` and `entwurf
|
|
17
|
+
check-bridge` boot, and `entwurf setup` composes the integrations it finds.
|
|
18
|
+
The four installers that previously rejected Darwin by platform name no longer
|
|
19
|
+
do. We validated that surface only in macOS CI because the developers did not
|
|
20
|
+
have a physical Mac. So macOS native-harness rails—marker join, an ACP turn,
|
|
21
|
+
and mux included—are not yet certified; setup writes their wiring but reports
|
|
22
|
+
them non-green. Linux's certified rail status is unchanged.
|
|
23
|
+
|
|
24
|
+
### Upgrade note — this one asks something of the operator
|
|
25
|
+
|
|
26
|
+
**On Darwin, `entwurf setup` no longer prints `result: green` when a harness
|
|
27
|
+
is already present.** Opening the four Darwin install fences (below) had a
|
|
28
|
+
side-effect the command an operator actually types did not stay honest for:
|
|
29
|
+
the installer that used to refuse on a platform name now writes the wiring,
|
|
30
|
+
and setup graded that `PASS` / `result: green` — while every harness doctor
|
|
31
|
+
still refuses on Darwin, and setup runs no doctor. That is cosmetic success
|
|
32
|
+
against Hard Rule 17 ("a detected-but-incomplete integration is named
|
|
33
|
+
non-green rather than cosmetic success").
|
|
34
|
+
|
|
35
|
+
All 13 harness units now ask one predicate
|
|
36
|
+
(`harness_rail_certified_platform`). On an uncertified platform they emit a
|
|
37
|
+
named non-green (FAIL) whose wording is lexically disjoint from an install
|
|
38
|
+
failure — `entwurf setup` says so by name:
|
|
39
|
+
|
|
40
|
+
`<unit> FAIL — the wiring WAS written and nothing failed to install, but this
|
|
41
|
+
harness rail is NOT CERTIFIED — pending physical host on <uname>. setup runs
|
|
42
|
+
no doctor; the rail axis is owned by '<doctor>'. Tracking: #78.`
|
|
43
|
+
|
|
44
|
+
`bins` and `core` are not rail axes and still PASS. A Darwin host with no
|
|
45
|
+
harness still five-SKIPs and `result: green` — that is the path
|
|
46
|
+
`macos-install-surface` asserts, and it did not move. Linux is unchanged: a
|
|
47
|
+
completed rail install is still PASS.
|
|
48
|
+
`[QK:SETUP-DARWIN-RAIL-COSMETIC-PASS]` plants the restoration of "a completed
|
|
49
|
+
install always PASSes" and was KILLED at that signature.
|
|
50
|
+
|
|
51
|
+
The four installers that used to refuse Darwin (`entwurf install-meta-bridge`,
|
|
52
|
+
`install-copilot-bridge`, `install-omp-bridge`, `install-omp-receive`) now
|
|
53
|
+
run; their own refusal is the toolchain check (python3 / node / harness
|
|
54
|
+
presence), never the platform name. A green Darwin install certifies the
|
|
55
|
+
install surface only, never a harness rail.
|
|
56
|
+
|
|
57
|
+
Hosts with no detected harness, and every Linux host, see no new prompt.
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- **`claude-fable-5-1` joins the curated ACP model surface.** The `entwurf` provider now registers
|
|
62
|
+
three unprefixed Claude ids (`claude-opus-5`, `claude-sonnet-5`, `claude-fable-5-1`) beside the
|
|
63
|
+
four `cortex-` rows. Routing needed no change: `backend-adapter.ts` derives `SUPPORTED_CLAUDE_IDS`
|
|
64
|
+
from the same constant, and `curatedClaudeModels()` filters the pi-ai registry — which carries
|
|
65
|
+
`claude-fable-5-1` (measured: `getModels("anthropic")` lists it beside `claude-fable-5`). The
|
|
66
|
+
curation comment's "verify across both axes" commitment is met by a live citizen: GLG opened B on
|
|
67
|
+
`entwurf/claude-fable-5-1` (garden `20260908T181437-30802a`, `backend=pi`, `liveness=alive`) and a
|
|
68
|
+
fire-and-forget send to it went out on the control-socket rail.
|
|
69
|
+
- **Two exact-set pins moved with the surface, and one of them was the real gap.**
|
|
70
|
+
`check-acp-provider-surface` counts the curated constants (6 → 7) and
|
|
71
|
+
`check-pack-install` enumerates the installed provider's own model list — that second one is a
|
|
72
|
+
package gate in `check:full`/`prepublishOnly` and would have gone red on the next release with a
|
|
73
|
+
drift message rather than a missing-support message. `check-acp-cortex` asks presence
|
|
74
|
+
(`includes`), not an exact set, so it needed nothing.
|
|
75
|
+
- **`[QK:CLAUDE-CURATED-THREE-ROWS]` — the claude curated list gets its own oracle.** The cortex list
|
|
76
|
+
has had `CORTEX-CURATED-FOUR-ROWS` since 0.13.0; the claude list had none, and it could not borrow
|
|
77
|
+
the exact-set comparison beside it: `expectedIds` derives from the same constant, so a dropped
|
|
78
|
+
claude row moves expected and captured together and that assertion stays green. The independent
|
|
79
|
+
count is what catches it, so the count now carries the claim and a committed mutant plants the
|
|
80
|
+
real defect (dropping `claude-fable-5-1` from `SUPPORTED_ANTHROPIC_MODEL_IDS`). Lane inventory
|
|
81
|
+
`acp-cortex` 12 → 13; total 386 → 387.
|
|
82
|
+
|
|
83
|
+
- **macOS gets its own evidence axis — an install surface, not a support claim.**
|
|
84
|
+
The `macos-install-surface` CI job (GitHub Actions `macos-latest`) was promoted
|
|
85
|
+
from non-voting to required after its first green at commit `70eda03`
|
|
86
|
+
(run 34303884286, 65 s, 10/10 steps): npm pack → checkout-invisible clean
|
|
87
|
+
consumer install → bin links → `entwurf --help` → `check-bridge` (direct MCP
|
|
88
|
+
smoke, 246 ms, the seven tools + `test.sh`) → harness-absent `setup` (pi/Claude/agy/Copilot/
|
|
89
|
+
OMP all SKIP, bins/core PASS, computed verdict green, zero writes on the five
|
|
90
|
+
no-write axes and `auth.json` byte-identical). Platform vocabulary across
|
|
91
|
+
README/BASELINE now separates three states: the Entwurf-only install surface on
|
|
92
|
+
macOS is **CERTIFIED (CI)** — a CI runner, never a physical host; the harness
|
|
93
|
+
rails (Claude/Copilot/OMP/agy wiring, marker join, a real ACP turn, mux) are
|
|
94
|
+
**NOT CERTIFIED — pending physical host**; native Windows is **UNSUPPORTED**.
|
|
95
|
+
- **`scripts/raw-macos-measure/` — the borrowed-Mac measurement ledger.** `probe.sh`
|
|
96
|
+
(`/bin/sh`, cells M1–M9) measures one host and writes nothing: no install, no
|
|
97
|
+
record, no state. The README maps each cell to the surface it measures and keeps a
|
|
98
|
+
`[host-linux]` control run so the probe itself is never the thing under test. Opened
|
|
99
|
+
by the promotion above; it is where a borrowed Mac produces the physical-host
|
|
100
|
+
evidence the CI runner cannot.
|
|
101
|
+
- **`scripts/raw-codex-measure/` — Codex 0.153.4 vendor measurement (#95 step 1).**
|
|
102
|
+
Nothing is installed: no birth hook, no record, no marker, no doctor, and
|
|
103
|
+
`entwurf_fresh_call` still cannot open a codex sibling. GLG reversed the
|
|
104
|
+
2026-08-01 decline on 2026-09-08; live claims that still said otherwise
|
|
105
|
+
were repaired. The ledger closes step 1: SessionStart fires on the first
|
|
106
|
+
turn, not at window open; a fourth callback spelling
|
|
107
|
+
(`mcp__entwurf_bridge__entwurf_v2`); the delivery-capable app-server join
|
|
108
|
+
cannot use parent-pid as a citizen key; hook-trust is an ownership cost
|
|
109
|
+
(`/etc/codex`, root-owned), not a capability gap; clause 4 is
|
|
110
|
+
`thread/name/set` plus a status_line config. Step 2 is not opened.
|
|
111
|
+
`PIN_CODEX_MINOR` 0.144 → 0.153 is a re-verification of the archived drift
|
|
112
|
+
probe, not a product pin.
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
|
|
116
|
+
- **`[QK:CORTEX-PROVIDER-SIX-ROW-SURFACE]` → `[QK:CORTEX-PROVIDER-EXACT-ROW-SURFACE]`.** The claim's
|
|
117
|
+
substance is "the compiled entry registers the EXACT union of every adapter's curated rows", which
|
|
118
|
+
is count-independent; the old id carried a row count that this change made false and that any
|
|
119
|
+
future curation change would falsify again. Gate assertion, mutant manifest (`claim` +
|
|
120
|
+
`signature`), the `acp-provider.ts` comment and the `run.sh` usage line moved together. The
|
|
121
|
+
mutant's `find`/`replace` are untouched — it still plants the same defect (filtering the cortex
|
|
122
|
+
rows out of the real entry).
|
|
123
|
+
- **Four install fences now accept `Linux | Darwin`** — `meta-bridge-install.sh`,
|
|
124
|
+
`copilot-bridge-install.sh`, `omp-bridge-install.sh`, `omp-receive-install.sh`
|
|
125
|
+
(the `meta-bridge-uninstall.sh` precedent). The installers' own refusal is the
|
|
126
|
+
toolchain check (python3/node/harness presence), never the platform name. A green
|
|
127
|
+
Darwin install certifies the install surface only, never a harness rail —
|
|
128
|
+
installation portability and rail certification are separate axes (Hard Rule 17).
|
|
129
|
+
- **Doctor python `start_key`/`parent` now mint the same two-tier key the TS core
|
|
130
|
+
mints** (`/proc` stat field 22 → `linux:<ticks>`, else `ps -o lstart=` /
|
|
131
|
+
`ps -o ppid=`, the same argv vectors `meta-session.ts` uses). Darwin's remaining
|
|
132
|
+
doctor reason is per-process environment DISCOVERY, not start-key.
|
|
133
|
+
The `ps:` format is unchanged: 1-second resolution against `linux:` at
|
|
134
|
+
10 ms, but a same-second pid reuse needs a full PID_MAX wrap inside one
|
|
135
|
+
second (≈99,900 spawn/s vs a measured pathological ceiling of 14,873/s).
|
|
136
|
+
Coarsening can mint a false `live` and never a false `dead`. The migration
|
|
137
|
+
axis is empty — 1,248 marker files, all `linux:`, zero `ps:`. Widening the
|
|
138
|
+
key with argv was measured insufficient (two same-argv children share it,
|
|
139
|
+
and same-argv restart is the normal harness shape).
|
|
140
|
+
- **Operator-surface portability substitutions (audit P1).** `grep -P` negative
|
|
141
|
+
lookaheads moved to awk (6 sites); `sha256sum` moved to the in-repo python3
|
|
142
|
+
hashlib helper (3 sites) — not a second `shasum` convention. `readlink -f` on the
|
|
143
|
+
operator path (`agy-imprint.sh`, `copilot-launch.sh`) replaced with the POSIX
|
|
144
|
+
symlink walk `mcp/entwurf-bridge/start.sh` already ships, and `agy-bridge.sh`
|
|
145
|
+
advice no longer prints a GNU-only command.
|
|
146
|
+
|
|
147
|
+
### Fixed
|
|
148
|
+
|
|
149
|
+
- **The Cortex overlay's `realHome` guard now states path-flavor absoluteness, not the host it runs
|
|
150
|
+
on.** `ensureCortexDualHomeOverlay` refused a non-absolute `realHome` with `startsWith("/")`, so a
|
|
151
|
+
drive/UNC path (`C:\Users\x`, `\\server\share`) read as relative. The guard is now
|
|
152
|
+
`isAbsolute(realHome) || win32.isAbsolute(realHome)`; the error text and the D10 contract sentence
|
|
153
|
+
are unchanged. First evidence: PR #77 (@yizixu) found the defect. The flavor-explicit form is what
|
|
154
|
+
makes it killable on a Linux host — `check-acp-cortex` gained two positive cells (drive and UNC,
|
|
155
|
+
`realSnowflakeHome` pinned under tmp so only the guard is exercised) plus an empty-string negative
|
|
156
|
+
cell, and mutant `CORTEX-REALHOME-PLATFORM-NEUTRAL` replants `startsWith("/")` and dies at
|
|
157
|
+
`[QK:CORTEX-REALHOME-PLATFORM-NEUTRAL]`. This claims no native-Windows support; the certified
|
|
158
|
+
platform axis is unchanged.
|
|
159
|
+
- **Doctors no longer call an unmeasured host clean.** When `/proc` is absent, the
|
|
160
|
+
Copilot launch-flag and OMP identity-carrier doctors used to fail OPEN — a `note`
|
|
161
|
+
and a green verdict. They now emit `UNVERIFIABLE` through the existing `bad` path:
|
|
162
|
+
no new severity, emitter, or exit code. The same contract is pinned one step
|
|
163
|
+
further — absent and unknowable are no longer collapsed: a failed enumeration
|
|
164
|
+
(`pgrep` rc 2) or an unreadable `cmdline` is UNKNOWN and stays non-green, while a
|
|
165
|
+
genuine no-match or a vanished process remains the benign note it always was.
|
|
166
|
+
That distinction is bidirectional and holds on Linux too, where `/proc`'s presence
|
|
167
|
+
had merely hidden the defect.
|
|
168
|
+
- **Recovered-host selectors moved from GNU BRE alternation to ERE**
|
|
169
|
+
(`omp-bridge-doctor.sh`, `copilot-bridge-doctor.sh`), so BSD grep cannot report a
|
|
170
|
+
recovered host as unrecovered (a false RED that only Darwin's grep would mint).
|
|
171
|
+
- **A red or interrupted gate no longer leaves its children and temp roots
|
|
172
|
+
behind.** Teardown written as the last line ran only on the green path;
|
|
173
|
+
gates throw to go red, and `^C`/SIGTERM runs no statement. Measured on
|
|
174
|
+
oracle: 360 reparented Node receivers from the copilot-receive stub and
|
|
175
|
+
~9,200 stale temp roots (3.8 G), one of them minted by a `pnpm check` that
|
|
176
|
+
had just reported clean. Teardown now belongs to `process.on("exit")` plus
|
|
177
|
+
the three signals (`scripts/lib/reclaim-on-exit.ts`); the SDK stub gains
|
|
178
|
+
the parent-death watchdog production already has.
|
|
179
|
+
`[QK:COPILOT-RECEIVE-STUB-CHILD-DIES-WITH-PARENT]` carries the watchdog.
|
|
180
|
+
The release skill gains P9 (prefix-blind census; delete only prefixes this
|
|
181
|
+
checkout's `mkdtempSync` calls mint), run at the release-gate verdict, at
|
|
182
|
+
the end of prepare, and after the publish smoke.
|
|
183
|
+
|
|
184
|
+
### Verification
|
|
185
|
+
|
|
186
|
+
Lane receipts (oracle, 2026-09-09) plus prepare P4/P5 on this host. There is
|
|
187
|
+
**no** physical-Mac receipt.
|
|
188
|
+
|
|
189
|
+
- **`pnpm run check:full`** exit 0, 461 s (`9cc5b09`) / 469 s (`e09b84e`) /
|
|
190
|
+
465 s (prepare P4, this worktree).
|
|
191
|
+
- **Prepare P5** `LIVE=1 ./run.sh release-gate --cut`:
|
|
192
|
+
scratch `/tmp/entwurf-release-gate-0.20.0.rerun`, **MUST PASS=23 FAIL=0
|
|
193
|
+
SKIP=0**, BEHAVIOR PASS=1, `cut: OK`. Qualification **391/391 KILLED**
|
|
194
|
+
inside that gate. The first attempt was `cut: BLOCKED` (MUST FAIL=2):
|
|
195
|
+
host `STALE writer` on the deployed omp-receive unit, and the omp-fresh
|
|
196
|
+
nonce callback captured by the preparing session's `PI_SESSION_ID`.
|
|
197
|
+
Rerun after `install-meta-bridge` / `install-omp-bridge` /
|
|
198
|
+
`install-omp-receive` and `env -u PI_SESSION_ID -u PI_AGENT_ID -u
|
|
199
|
+
CLAUDE_CONFIG_DIR`.
|
|
200
|
+
- **`check-gate-qualification` 390/390 → 391/391 KILLED** (`9cc5b09` then
|
|
201
|
+
`e09b84e`). New claims this range: `CLAUDE-CURATED-THREE-ROWS`,
|
|
202
|
+
`CORTEX-REALHOME-PLATFORM-NEUTRAL`,
|
|
203
|
+
`COPILOT-RECEIVE-STUB-CHILD-DIES-WITH-PARENT`,
|
|
204
|
+
`OMP-DOCTOR-UNENUMERATED-IS-UNVERIFIABLE`,
|
|
205
|
+
`COPILOT-RECEIVE-DOCTOR-UNREADABLE-ARGV-IS-UNVERIFIABLE`,
|
|
206
|
+
`SETUP-DARWIN-RAIL-COSMETIC-PASS`.
|
|
207
|
+
- **`check-pack-install`** exit 0. **`check-install-container`** exit 0.
|
|
208
|
+
- The macos-install-surface cell replayed against the packed candidate on
|
|
209
|
+
Linux: all 12 pins HOLD (`9cc5b09`).
|
|
210
|
+
- Doctors (4 files) HEAD-vs-worktree output IDENTICAL (`9cc5b09`).
|
|
211
|
+
- CI run
|
|
212
|
+
[`34303884286`](https://github.com/junghan0611/entwurf/actions/runs/34303884286)
|
|
213
|
+
@ `70eda03` — `macos-install-surface` required, `macos-latest`, 65 s,
|
|
214
|
+
steps 10/10.
|
|
215
|
+
- CI run
|
|
216
|
+
[`34316688064`](https://github.com/junghan0611/entwurf/actions/runs/34316688064)
|
|
217
|
+
@ `9cc5b09` — 4 jobs + qualification step `success`.
|
|
218
|
+
- Land exact-SHA CI run
|
|
219
|
+
[`34329931791`](https://github.com/junghan0611/entwurf/actions/runs/34329931791)
|
|
220
|
+
@ `a5a6dfe`, `event=workflow_dispatch` — 4 jobs + qualification body
|
|
221
|
+
`success` (the push run at this SHA skipped the body; L3 dispatch recovered it).
|
|
222
|
+
|
|
223
|
+
### Notes
|
|
224
|
+
|
|
225
|
+
- **What this cut claims about macOS, and what it does not.** Claimed: the
|
|
226
|
+
Entwurf-only install surface is **CERTIFIED (CI)**; the shipped operator
|
|
227
|
+
path is portable (no `readlink -f`, no `grep -P`, no `sha256sum`, no GNU BRE
|
|
228
|
+
alternation on recovered-host selectors); doctors fail closed on an
|
|
229
|
+
uncertified discovery axis (`UNVERIFIABLE`, not a green note). Not claimed:
|
|
230
|
+
harness rails, marker join, a real ACP turn, mux, or a physical-host doctor
|
|
231
|
+
green — all **NOT CERTIFIED — pending physical host**. native Windows is
|
|
232
|
+
**UNSUPPORTED**. A CI `macos-latest` runner has no logged-in harness; it
|
|
233
|
+
cannot mint the stronger `certified`. macOS is never UNSUPPORTED.
|
|
234
|
+
- **Two cells are unmeasured, by name.** Whether Darwin can read another
|
|
235
|
+
process's environ (`ps -Eww`), and whether macOS `python3` is the
|
|
236
|
+
CommandLineTools stub. Both are cells the borrowed-Mac probe
|
|
237
|
+
(`scripts/raw-macos-measure/probe.sh`, M6 and M3) is built to answer. Do
|
|
238
|
+
not fill them from a CI image spec.
|
|
239
|
+
- **Codex is not a garden backend in this cut.** Step 1 of #95 closed as
|
|
240
|
+
measurement; step 2 is not opened. `entwurf_fresh_call` still cannot open a
|
|
241
|
+
codex sibling.
|
|
242
|
+
|
|
243
|
+
## 0.19.0 - 2026-09-07
|
|
244
|
+
|
|
245
|
+
One lane: #105 slice ①, the project seat. `entwurf_fresh_call` gains an optional
|
|
246
|
+
`placement.tmuxSession` so a fresh sibling can open in the operator's project session instead of the
|
|
247
|
+
caller's own, and `closeWindow` binds to the server half so a window placed elsewhere can still be
|
|
248
|
+
closed by its handle. Minor rather than patch: an optional input appears on all three public
|
|
249
|
+
surfaces at once and a shipped contract moves. Slices ② (no-turn retirement) and ③ (remote routing)
|
|
250
|
+
did not ship and were carried out of the issue intact before it closed, so nothing about them is
|
|
251
|
+
inferred from what landed here.
|
|
252
|
+
|
|
253
|
+
It also carries two repairs that were not planned: verifying this release ran the deterministic floor
|
|
254
|
+
often enough to expose a defect class the repo had already written down and not finished applying —
|
|
255
|
+
an early-exiting `grep -q` whose producer dies of SIGPIPE, which `pipefail` then promotes into the
|
|
256
|
+
CLEAN branch of an `if`. One instance was a shipped operator doctor; the other was a credential
|
|
257
|
+
tripwire that had been dead since it was written.
|
|
258
|
+
|
|
259
|
+
### Added
|
|
260
|
+
|
|
261
|
+
- **One project seat: `placement: { tmuxSession }` (#105).** The exact name of an EXISTING session
|
|
262
|
+
on the caller's own tmux server. **It creates nothing** — an absent session is
|
|
263
|
+
`tmux-session-missing`, a name outside `[A-Za-z0-9][A-Za-z0-9_-]*` is `tmux-session-name-invalid`,
|
|
264
|
+
and both leave no window and no session behind. There is no `ifMissing`/`create` axis and no
|
|
265
|
+
`new-session` verb anywhere in the product (GLG, 2026-09-07: "없으면 reject … 다 자동화하면
|
|
266
|
+
테스트·검증 비용이 커진다"). The operator makes the seat and calls again. Omitting `placement`
|
|
267
|
+
keeps today's behaviour exactly.
|
|
268
|
+
- **`pi-extensions/lib/resolve-tmux-session.ts`** — an import-free leaf owning the name grammar and
|
|
269
|
+
the name → native `$id` lookup, with its tmux runner injected so it cannot run tmux itself. The
|
|
270
|
+
engine is `list-windows -t '=NAME' -F '#{session_id}'` with absence read from the exit code, and
|
|
271
|
+
every rule in its header is a measured tmux 3.6a behaviour: the `-f` filter engine matched **every**
|
|
272
|
+
session when a name contained `}` (6/6), `display-message -p -t '=NAME'` answers rc=0 with empty
|
|
273
|
+
output for a name that does not exist, `#` is format-expanded when the name is stored, `.` and `:`
|
|
274
|
+
are tmux's own pane/window separators inside a target, and a session NAMED `$0` loses to the id
|
|
275
|
+
`$0`. Only the resolved id ever reaches `-t`.
|
|
276
|
+
- **Nine kill-qualified claims and their exact-once replants, inventory 373 → 382:**
|
|
277
|
+
`TMUXSESSION-LOOKUP-ENGINE`, `TMUXSESSION-NAME-GRAMMAR`, `RESOLVE-TMUX-SESSION-IMPORT-FREE`,
|
|
278
|
+
`FRESHCALL-PLACEMENT-MISSING-REJECTS`, `FRESHCALL-PLACEMENT-TARGET-ARGV`,
|
|
279
|
+
`FRESHCALL-PLACEMENT-RECEIPT-TARGET`, `FRESHCALL-PLACEMENT-SURFACE-PARITY`,
|
|
280
|
+
`FRESHCALL-PLACEMENT-BACKEND-PARITY` and `MUX-CLOSE-SERVER-BOUND`.
|
|
281
|
+
|
|
282
|
+
### Changed
|
|
283
|
+
|
|
284
|
+
- **`closeWindow` binds to the SERVER half (`requireSameServer`), not the session.** A placed window
|
|
285
|
+
may legitimately live outside the caller's session, so the old handle↔now context check would have
|
|
286
|
+
refused a normal close. The session half was measured to add no protection and real harm: window
|
|
287
|
+
ids are never reused within one server's lifetime (`@1` killed → next is `@2`; a whole session
|
|
288
|
+
killed → the counter still moves), so a vanished session's handle already reaches the existing
|
|
289
|
+
`already-gone` outcome, and a session clause would have turned that into a throw. `isSameContext` /
|
|
290
|
+
`requireSameContext` are untouched and still guard `appendWindow` / `launchPi`.
|
|
291
|
+
- **The seat is stated the same way on every surface an operator reads.** A documentation review
|
|
292
|
+
(pi `grok-4.6`) read README, the skill and the tool schema as three independent readers and found
|
|
293
|
+
five places where each was correct alone but a caller reading only one got the seat wrong — the
|
|
294
|
+
README's v2 section did not mention the seat at all, `docs/external-mcp-host.md` advertised the
|
|
295
|
+
verb as `{backend, model, task, cwd?}`, "an absent one is refused" read equally as an absent
|
|
296
|
+
session and an omitted placement, and the grammar lived only inside a schema `describe`. The most
|
|
297
|
+
expensive misreading had no positive statement anywhere: **naming the `org` seat does not put the
|
|
298
|
+
sibling in the `org` directory.** That is now said as a fact, not as a prohibition.
|
|
299
|
+
- **A symlinked `cwd` shows two spellings of one place, and the docs now say so.** entwurf never
|
|
300
|
+
resolves the path — it hands the literal string to tmux — so the launch receipt echoes what was
|
|
301
|
+
requested while the record, the transcript path, the callback envelope and `pane_current_path` all
|
|
302
|
+
carry what the OS resolved it to. The resolved one is what `entwurf_resume_call` later reopens,
|
|
303
|
+
which is why recording it that way is load-bearing rather than incidental.
|
|
304
|
+
|
|
305
|
+
### Fixed
|
|
306
|
+
|
|
307
|
+
- **`entwurf doctor-omp-bridge` could report a contaminated omp process as clean.** Its carrier scan
|
|
308
|
+
read `/proc/<pid>/environ` through `tr '\0' '\n' | grep -qE …` under `set -o pipefail`. `grep -q`
|
|
309
|
+
exits at the FIRST match and closes the pipe; `tr` — still writing the rest of a ~12 KB environ —
|
|
310
|
+
dies of SIGPIPE (141); `pipefail` makes that the pipeline's status, and the `if` takes the clean
|
|
311
|
+
branch. So a live omp session whose MCP children would speak under a PARENT pi citizen's garden id
|
|
312
|
+
was reported as no contamination, and the doctor printed PASS. It is a race on how far `tr` got, so
|
|
313
|
+
it read as flakiness rather than a defect: measured on one live fixture at 5–15% of reads depending
|
|
314
|
+
on load (6/40 and 1/40 in two independent measurements; 0/40 with `pipefail` off, and the shipped
|
|
315
|
+
doctor answered PASS on 3 of 60 runs against a genuinely contaminated fixture). The scan now counts
|
|
316
|
+
with `grep -c`, which consumes all of stdin, so there is no early close and nothing to race. The
|
|
317
|
+
predicate itself is unchanged byte-for-byte — `grep -qz` would have removed the pipeline entirely
|
|
318
|
+
but also quietly changes what counts as a carrier in both directions (a `PI_SESSION_ID=` inside
|
|
319
|
+
another variable's value; a value containing a newline), so transport was fixed and contract left
|
|
320
|
+
alone. `smoke-omp-bridge-state`'s own `wait_carrier` carried the same shape, where it cost only a
|
|
321
|
+
retry, and was fixed with it.
|
|
322
|
+
- **The `sync_auth` credential tripwire had never been able to fire (`check-fresh-cut-gate` D4b).**
|
|
323
|
+
Same cause, deterministic rather than racy: the producer is `awk` over a 433 KB `run.sh` emitting
|
|
324
|
+
~229 KB, so an early-exiting `grep -q` guarantees SIGPIPE. Measured with one `sync_auth` line
|
|
325
|
+
injected as code into a copy of `run.sh`: the pipeline exited 141 on **100 of 100** runs and the
|
|
326
|
+
gate printed `ok — no sync_auth credential surface remains`, while a clean `run.sh` exits 1 and is
|
|
327
|
+
correctly green. The tripwire was blind exactly when it had something to catch, which is why a
|
|
328
|
+
green floor never revealed it. After the repair the injected copy fires 50/50 and the clean copy
|
|
329
|
+
stays silent. D7 — the cell that forbids an install from cutting a generation by itself — carried
|
|
330
|
+
the same shape and is under one pipe buffer today, so it had no SIGPIPE window; that is a size
|
|
331
|
+
coincidence rather than a property, and it was counted too.
|
|
332
|
+
|
|
333
|
+
### Verification
|
|
334
|
+
|
|
335
|
+
All on oracle (Linux, node 24.18.1, pi 0.85.1, tmux 3.6a).
|
|
336
|
+
|
|
337
|
+
- **`LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.19.0.0HsnIq --cut` → `cut: OK`.**
|
|
338
|
+
**MUST: PASS=23 FAIL=0 SKIP=0**, BEHAVIOR: PASS=1 FAIL=0 SKIP=0, exit 0, 06:06:31→07:05:45
|
|
339
|
+
(59m14s). `check-gate-qualification` as its MUST step: **385/385 KILLED**. `pnpm run check:full`
|
|
340
|
+
inside it: exit 0, 507s.
|
|
341
|
+
- **`check-gate-qualification` 381/381 KILLED** on the frozen `a39b637` candidate;
|
|
342
|
+
`pnpm run check:full` exit 0 (554s).
|
|
343
|
+
- **`LIVE=1 ./run.sh smoke-mux-fresh-call-live` 39/39** — four launches covering the
|
|
344
|
+
{cwd omitted, cwd requested} × {caller session, seat} matrix, reading `pane_current_path` by stable
|
|
345
|
+
pane id after a settle delay, with the seat session's own `session_path` a fourth directory no cell
|
|
346
|
+
may land in. On-demand, not a release MUST (VERIFY.md).
|
|
347
|
+
- **`check-mux-launch-tmux` 36** including a real-tmux seat cell that calls production
|
|
348
|
+
`freshCall`/`closeWindow` against a second session on a private server; `check-mux-fresh-call`
|
|
349
|
+
186/186; `check-gate-manifests` 383 mutants across 40 lanes.
|
|
350
|
+
- **For the two repairs above:** `smoke-omp-bridge-state` 20 consecutive green runs (it was 1 red in
|
|
351
|
+
5 before) and `check-fresh-cut-gate` 169/169 with its two new self-test cells. Three replants,
|
|
352
|
+
inventory 383 → 385, each KILLED 3/3 deterministically at its own signature:
|
|
353
|
+
`OMP-DOCTOR-CARRIER-NONBLANK-IS-RED`, `FRESHCUT-SYNCAUTH-TRIPWIRE-FIRES` and
|
|
354
|
+
`FRESHCUT-PREFLIGHT-CUT-DETECTED`. The middle one replants the ACTUAL defect — `grep -c` back to
|
|
355
|
+
`grep -q` — and that is only a valid replant because the self-test plants its surface early in a
|
|
356
|
+
file far larger than the pipe buffer, which makes the SIGPIPE deterministic. The omp one cannot be
|
|
357
|
+
written that way: there the same restoration fails only ~15% of runs and would SURVIVE
|
|
358
|
+
qualification, so it makes the identical false-clean deterministic by another route. Same defect,
|
|
359
|
+
two replant strategies, and the difference is recorded in the manifests rather than smoothed over.
|
|
360
|
+
|
|
361
|
+
### Notes
|
|
362
|
+
|
|
363
|
+
- **The seat's first pass over the real MCP wire was the operator's, not a gate's.** Both mux LIVE
|
|
364
|
+
smokes were blind to that seam by construction: `smoke-mux-fresh-call-live` imports `freshCall` and
|
|
365
|
+
calls it directly, and `smoke-mux-lifecycle-live` does enter through `tools/call` but passes no
|
|
366
|
+
`placement`. Between them the bridge handler's pass-through was proven by a tools/list schema and a
|
|
367
|
+
source regex — by construction, never by execution. GLG's hand-driven review on 2026-09-07 closed
|
|
368
|
+
that: four `tools/call entwurf_fresh_call` invocations (seat, seat + cwd, absent session, off-grammar
|
|
369
|
+
name), receipts read as receipts, with the whole-server `list-windows -a` byte-identical across both
|
|
370
|
+
refusals and exactly one added line across the successes.
|
|
371
|
+
- **Every seat assertion this repo owned was written against `pi`.** The unit block, the real-tmux
|
|
372
|
+
seat cell and both LIVE seat cells all passed `backend: "pi"`, so a later branch making the seat a
|
|
373
|
+
pi-only input would have gone unnoticed — while the cwd axis (#73) had carried four-backend parity
|
|
374
|
+
since it landed. The production path was already uniform (the seat becomes `targetSessionId`, the
|
|
375
|
+
backend becomes `backendArgs`, and `buildFreshCallArgs` takes them as separate parameters); what was
|
|
376
|
+
missing was an oracle saying so. `FRESHCALL-PLACEMENT-BACKEND-PARITY` is that oracle, and
|
|
377
|
+
`check-gate-manifests` caught the omission that came with it — a manifest set that drifted from its
|
|
378
|
+
declared inventory is red before any mutant runs.
|
|
379
|
+
- **Two ceilings are close enough to name.** The composed ACP first-user augment sits **311 bytes**
|
|
380
|
+
under its 50 KB cap (measured: 50,889 / 51,200 with the shipped repo AGENTS.md plus a 12 KB global
|
|
381
|
+
baseline), and the MCP `entwurf_fresh_call` description sits **28 chars** under the 2048-char host
|
|
382
|
+
cap (measured: 2020). The first already bit once during this lane: the initial qualification run
|
|
383
|
+
went CONTROL-RED on `check-acp-carrier-augment` because the feature's +1207 B to AGENTS.md breached
|
|
384
|
+
a cap that had 932 B of headroom, and the text was compressed to +616 B rather than the cap moved.
|
|
385
|
+
Neither number is a gate threshold to tune; both are room that the next lane has to spend
|
|
386
|
+
deliberately.
|
|
387
|
+
- **Independent review is where the second defect came from.** A `zai/glm-5.3` sibling was asked to
|
|
388
|
+
review the doctor repair and to try to disprove it, reproducing everything in an isolated snapshot
|
|
389
|
+
rather than trusting the implementer's summary. It confirmed the mechanism, corrected two claims —
|
|
390
|
+
the measured miss rate is load-dependent rather than a fixed 15%, and Copilot's immunity comes from
|
|
391
|
+
a TypeScript `readFileSync` reader rather than the Python one that was asserted — rejected the
|
|
392
|
+
`grep -qz` alternative on evidence the implementer did not have, and then found the dead credential
|
|
393
|
+
tripwire, which is the more severe of the two and was in a different lane entirely.
|
|
394
|
+
- **A forbidding cell that is green on a clean tree cannot tell blindness from compliance.** That is
|
|
395
|
+
why D4b was dead for as long as it was: it printed `ok` on every run this repo ever took, and it
|
|
396
|
+
would have printed `ok` on the run that mattered. Both cells now carry a self-test that plants the
|
|
397
|
+
thing they forbid and requires the SAME predicate — factored into a function precisely so a
|
|
398
|
+
re-typed copy cannot keep passing while the real one goes blind — to see it. The `sync_auth` plant
|
|
399
|
+
goes near the TOP of the real 433 KB `run.sh` rather than into a small synthetic fixture, because
|
|
400
|
+
the defect only exists when the consumer can exit while the producer still has bulk to write; a
|
|
401
|
+
tidy fixture would pass under the very mutant that must kill it.
|
|
402
|
+
- **A MUST gate can fail with the wiring intact.** `smoke-mux-lifecycle-live` is release-blocking on
|
|
403
|
+
the stated ground that a gate which TELLS the model which tool to call owns its own failures. This
|
|
404
|
+
cut met the case that rule does not describe: the wiring delivered perfectly — launch receipt, a
|
|
405
|
+
born citizen with its own garden id, the mandated first-action prompt verbatim on the visible pane —
|
|
406
|
+
and the model spent its one turn advising the operator to go to bed instead of calling back. Twice,
|
|
407
|
+
at 00:00 and 01:04, with the same cause and different wording, then green on the first daytime run.
|
|
408
|
+
Nothing was changed to make it pass: adjusting a shipped prompt to a current model's habit would
|
|
409
|
+
outlive the habit. Recorded because "MUST because failure is ours" now has a measured exception.
|
|
410
|
+
- **The long-command discipline earned its receipt.** The harness low-memory watchdog killed a
|
|
411
|
+
background tool call mid-cut while `free` reported 7 GB available and the kernel logged no OOM —
|
|
412
|
+
the lead recorded in 0.18.0's notes, met directly on a release lane for the first time. The gate
|
|
413
|
+
itself, running under tmux, was untouched every time. "Long commands go in tmux" stops being a
|
|
414
|
+
preference at that point.
|
|
415
|
+
- **An agent asking tmux where it is will answer wrong from a seat.** A seated sibling is opened
|
|
416
|
+
detached, so `tmux display-message -p` without `-t "$TMUX_PANE"` resolves to the target session's
|
|
417
|
+
ACTIVE window, not the sibling's own — measured, while the carrier itself was correct
|
|
418
|
+
(`TMUX_PANE=%181` in the process env). entwurf's own facts are unaffected: the launch receipt and
|
|
419
|
+
`list-windows` both name the right window. This is an agent-instruction gap and is tracked outside
|
|
420
|
+
this repo (junghan0611/sorge#7).
|
|
421
|
+
|
|
7
422
|
## 0.18.2 - 2026-09-07
|
|
8
423
|
|
|
9
424
|
One lane: #103, the second stage of the CI evidence budget (#99). The mutant body — 373 replants,
|
package/DELIVERY.md
CHANGED
|
@@ -80,13 +80,16 @@ axis; neither word is an admission grade or a synonym of *supported*. A pre-cont
|
|
|
80
80
|
can be owned without being supported; a supported harness still has to walk
|
|
81
81
|
[`docs/adding-a-harness.md`](./docs/adding-a-harness.md) step 9.
|
|
82
82
|
|
|
83
|
+
Every row in this table is Linux evidence. macOS rails are NOT CERTIFIED — pending
|
|
84
|
+
physical host. Do not read a D-level cell as a Darwin receipt.
|
|
85
|
+
|
|
83
86
|
| Harness / surface | Product status | Capability | Transport and boundary |
|
|
84
87
|
|---|---|---|---|
|
|
85
88
|
| **pi native Entwurf** | shipped | D7; D8 partial | Record-addressed Unix control socket. A record-less socket is diagnostic only and never dispatched. |
|
|
86
89
|
| **Claude Code interactive `>=2.1.217`** | shipped; Linux certified | D6; D7/D8 partial | Per-session mailbox + exec-form `FileChanged`/`asyncRewake`. B2 proved idle wake and same-session continuity on one NixOS host. |
|
|
87
90
|
| **Antigravity / agy** | shipped | D6; D7 partial | Record-backed native-push through LS gRPC `agentapi send-message`; no mailbox or receiver marker. Admitted before the #82 step 9 contract and not re-evaluated under it, so it is legacy citizen evidence, not a step-9 supported harness: `entwurf_fresh_call` cannot open an agy sibling, and nothing here should be read as claiming visible lifecycle parity. |
|
|
88
|
-
| **Codex app-server-backed TUI** | verified probe | D7; D8 unproven | WebSocket-over-UDS `turn/start` into a live `threadId`; status events expose completion. No owned native-citizen install/invocation lane. |
|
|
89
|
-
| **Codex embedded TUI** | deferred | D0 partial | No supported receive socket/hook on the measured standalone shape. |
|
|
91
|
+
| **Codex app-server-backed TUI** | verified probe, re-verified at 0.153.4 | D7; D8 unproven | WebSocket-over-UDS `turn/start` into a live `threadId`; status events expose completion. Re-run as shipped on 2026-09-08 at codex-cli **0.153.4** (garden lane #95): idle plain `codex` auto-attached to a bare `codex app-server --listen`, woke with zero typing, and the model replied in the same visible session — `{"ok": true, "threadId": "01a08145-ce6d-77d0-b7a4-cfb57c608282", "turnId": "01a08146-7c06-7b83-9e65-32e3814ee490", "status_seen": ["active","active","idle"]}`. No owned native-citizen install/invocation lane. Step 1 measurement only — the lane is open (#95) but nothing is installed, so this row stays the declared pre-#82 exception `check-harness-admission-parity` reads. |
|
|
92
|
+
| **Codex embedded TUI** | deferred | D0 partial | No supported receive socket/hook on the measured standalone shape. Re-checked in source at 0.153.4: the hook vocabulary grew to 12 events but still has no `watchPaths`/`FileChanged`/`asyncRewake` analogue, so the negative stands. |
|
|
90
93
|
| **Copilot CLI first-party extension** | raw transport probe; superseded by the owned product unit | D7 path observed; D3 control receipt incomplete; D8 unproven | CLI-spawned extension over stdio JSON-RPC; `joinSession()` + documented `fs.watch` → `session.send({mode:"enqueue"})`. Idle wake, exact-marker reply, and completion passed on 2026-08-23 (CLI 1.0.80, L4, one Linux host). Two-process isolation was observed but its decisive B log was not preserved. Kept as the transport receipt the owned receive unit was built on; the shipped unit differs deliberately — it announces the inbox instead of injecting the body. |
|
|
91
94
|
| **Copilot CLI garden citizen** | shipped in 0.15.0; send + receive + visible fresh accepted on one host | D6; D7 partial; D3 pending; D8 unproven | Birth, garden id, MCP hand and record-backed sender identity are accepted; the RECEIVER is an installed first-party extension that binds to the V3 record, writes a receiver marker owned by the WATCHER pid, and rings a doorbell the model drains with `entwurf_inbox_read`. `wakeMode` is `self-fetch`, so dispatch reaches the mailbox rail: armed → delivered, unarmed/stale → the honest `mailbox-undeliverable` refusal. **D6 is the owned-invocation LIVE acceptance of 2026-08-23** — garden `20260823T181316-d9f6ba`, native `20fe30c8-b2bc-4600-91a0-8a409131be51`, CLI 1.0.80: receive log `joined`→`armed`→`doorbell fresh=1`→`rang`, mailbox `lastEnqueuedAt 09:23:41.235Z` / `lastReadAt 09:23:56.480Z`, and a model reply on the same record/native/gid chain. **Visible fresh (step 9 clause 7) is a separate LIVE, 2026-08-25** — launch window `@89`/`%89` nonce `mux-fresh-call-690529ae99f99faa2252aefb`; exact-callback garden `20260825T085721-f68be0`; one `entwurf_v2` → `meta-mailbox → enqueued`; same garden `lastReadAt 2026-08-24T23:57:47.784Z` plus same-gid reply; GLG saw footer garden id and a healthy multi-turn window. Those rows stay unmerged. D7 is PARTIAL: reply and read receipt were observed, the completion taxonomy and long-haul operation were not. D3 (second-session isolation of an owned invocation) is PENDING — observed once, decisive log lost to scratch cleanup. Evidence level L4: one host. Launch through the owned invocation `entwurf copilot`, which sets `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` for that one process; `doctor-copilot-receive` reads live CLI environments because a session launched without it is silently inert. Visible fresh is operator-metered and is not a release-gate MUST. |
|
|
92
95
|
| **OMP (`omp`) garden citizen** | shipped in 0.16.0; send + receive + visible fresh accepted on one host | D6; D3 proven; D7 partial; D8 partial | Two in-process extensions in the operator's own TUI: birth mints the `mode === "tui"` host (subagents mint nothing) and names it as sender; the RECEIVER unit joins that citizen in the SAME process, holds an `fs.watch` on its mailbox signal, and rings an announce-only doorbell through the vendor's `pi.sendUserMessage` — measured to be on the FACTORY object, not the event ctx, and measured to start a turn on an idle host with zero typing (`agent_start` +31ms). `wakeMode` is `self-fetch`: the model drains with `entwurf_inbox_read` and THAT read is the receipt. **D6 is the LIVE acceptance of 2026-08-30** (oracle, omp 18.0.0) — garden `20260830T140819-116f6a`, `lastEnqueuedAt 05:08:20.555Z` / `lastReadAt 05:08:23.958Z`, and the citizen's own transcript carrying `mcp__entwurf_bridge_entwurf_inbox_read` for its own garden id. **D3 is PROVEN, not pending**: with two live omp citizens armed, one addressed enqueue rang exactly one doorbell and the sibling persisted no transcript and kept an empty mailbox. D7 is PARTIAL (`lastReadAt` needs no scraping; the reply does). D8 is PARTIAL — dedupe and every stale-handling path are implemented and hermetically pinned, ordering/loop-guard/crash-recovery are not. The `/new` unarm is the rail-specific one: the watch lives in the operator's TUI, so pid + start-key cannot see a citizen change underneath a living process, and without an explicit unarm the previous garden id would keep reading deliverable. Requires `tools: xdev: false` in `~/.omp/agent/config.yml` — the vendor default hides MCP tool schemas from the prompt, so the doorbell would name a tool the model cannot call. The decisive receipt lines — the ordering probe, the D6 chain, the D3 isolation and the `/new` unarm — are pasted into `scripts/raw-omp-measure/README.md` §M7 rather than left in a host-local `/tmp` path. Evidence level L4: one Linux host, ARM. **Visible fresh (step 9) is ACCEPTED — the clause 7 LIVE went green on 2026-08-30:** `entwurf_fresh_call` opens omp on all three public surfaces through the bare `omp` runtime with an explicit `--approval-mode yolo` width and the `mcp__entwurf_bridge_entwurf_v` callback name, behind a five-axis pre-mutation preflight whose fifth axis is omp-specific (`tools.xdev !== true`, without which the model cannot call the callback tool at all). **The first turn is a TWO-STAGE BOOTSTRAP rather than a positional prompt, and that is a measured correction, not a preference.** `[LIVE 2026-08-30]` the positional-prompt candidate opened its window and minted its citizen (garden `20260830T181342-452167`, native `01a051f2-3107-7147-8806-fa2a6f527610`), delivered the byte-identical framing as a user message at `09:13:42.413Z`, and the model answered the literal text `ACK` at `09:13:47.105Z` with ZERO tool calls; the caller timed out at 240s. `[source]` the interactive UI defers MCP discovery (`sdk.ts:1847-1855`, `:1881-1905`) while the positional `initialMessage` prompts straight after `mode.init()` (`main.ts:540-565`), and `[측정]` an observer on the same runtime saw `turn_start` at +654ms with the entwurf tools absent and the callback tool present only at +1484ms. So the launcher now carries `{v,target,nonce,task}` on the fixed registered flag `--entwurf-bootstrap`, and the in-process birth extension polls `getAllTools`(`source:"mcp"`) AND `getActiveTools` for the exact callback name, sends a callback-ONLY prompt, arms the task only on a `tool_result` whose stored `toolCallId`, tool name, target, nonce and `isError === false` all match, and DELIVERS it at the next `turn_end` of that same session. `[LIVE 2026-08-30]` that last boundary is itself a measured correction: a first attempt sent the task from inside the `tool_result` handler with an explicit `deliverAs: "followUp"`, the hook log showed the full chain (`bootstrap-armed` → `bootstrap-ready` +440ms → `bootstrap-callback-observed` → `bootstrap-released`), and the task still never appeared in the session — `[source]` an explicit `deliverAs` queues without starting a turn in either state, while the omitted form starts one when idle (`agent-session.ts:6511-6513`), which the same transcript confirmed three seconds later when the Bundle B doorbell's omitted-option send landed and started a turn. `[측정 2026-08-30]` the callback-only half is what was proven to work: model `openai-codex/gpt-5.6-sol`, tool live at +1105ms, prompt injected at +1107ms, and the sibling calling `mcp__entwurf_bridge_entwurf_v` with the exact nonce (`omp-cb-btkvva4r87` → `20260830T184054-1aa1f2`, `meta-mailbox → enqueued`). **The clause 7 acceptance, `smoke-omp-fresh-live` (release-gate MUST), 2026-08-30, 21 assertions, omp 18.0.0 / `openai-codex/gpt-5.6-sol`:** launch through `tools/call entwurf_fresh_call` with nonce `mux-fresh-call-34faea228f3c3638684b40ff`; sibling garden `20260830T192913-df52b9` taken from the CALLBACK's sender envelope and never from the launch receipt; exactly one new citizen (§3.5); addressed `entwurf_v2` → `meta-mailbox → enqueued`; `lastEnqueuedAt 10:29:19.179Z` / `lastReadAt 10:29:24.673Z`; the drain visible in that session's own transcript for its own garden id. **Both bootstrap stages are in that transcript in order** — the callback-only prompt at offset 970, the caller's task at 4732, no four-backend positional framing anywhere, and an assistant message after the task proving it started a turn rather than sitting in a queue. The unit's own log carries the state machine: `bootstrap-armed 10:29:13.399Z` → `bootstrap-ready 10:29:13.819Z` (+420ms) → `bootstrap-callback-observed 10:29:18.663Z` (`toolCallId=call_KZJtkxfzy1IEE4ejKutCPWcm|fc_0858…`) → `bootstrap-released 10:29:18.731Z` → `bootstrap-task-sent 10:29:18.759Z`. Evidence level L4: one Linux host, ARM, one run. `check-harness-admission-parity` keeps the deterministic half of the admission from being a matter of memory. What this does NOT establish: multi-host, multi-model, or repeated fresh calls in one process. **Cross-harness leg, 2026-08-31 (first bidirectional live-turn roundtrip on the committed bytes + operator redeploy):** a claude-code citizen (`20260831T090152-f998ac`) opened a fresh omp sibling through the public surface (nonce `mux-fresh-call-807cb693b1913ce98ffdbfd1`, callback sender garden `20260831T124226-eac41a`), dispatched an addressed `entwurf_v2` → `meta-mailbox → enqueued`, and the omp citizen's own live turn drained and replied into the claude mailbox — its self-report (doorbell → `entwurf_inbox_read`; callback-only first user message, task second) agrees with every receipt on the chain. |
|
|
@@ -131,10 +134,60 @@ in [BASELINE.md](./BASELINE.md); deterministic ownership and sender gates run in
|
|
|
131
134
|
|
|
132
135
|
Do not describe “Codex” as one delivery shape. The measured app-server-backed TUI can
|
|
133
136
|
accept `turn/start` for a live thread and report completion; the standalone embedded
|
|
134
|
-
TUI exposed no equivalent receive route.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
TUI exposed no equivalent receive route. `turn/steer` is active-turn steering, not idle wake.
|
|
138
|
+
|
|
139
|
+
**The 2026-08-01 decline is reversed.** GLG re-opened the Codex native lane on 2026-09-08
|
|
140
|
+
(“코덱스 레일 들어가자”) as one of the two 사용자층 확보 axes; the lane is
|
|
141
|
+
`#95` and the pi-already-supplies-GPT argument no longer settles it. Nothing here is a
|
|
142
|
+
support claim: no codex record has ever been minted, there is no birth hook, no sender or
|
|
143
|
+
receiver marker, and `entwurf_fresh_call` cannot open a codex sibling.
|
|
144
|
+
|
|
145
|
+
**But step 2 is already spent, and it is spent WRONG.** `codex` is in `META_BACKENDS`
|
|
146
|
+
(`meta-session.ts:84`) and `META_CITIZEN_BACKENDS` (`:308`), and `pi/entwurf-capabilities.json`
|
|
147
|
+
grades it `wakeMode: "direct-inject"`, `deliveryLevel: "D6"`, `nativeIdLabel: "threadId"`.
|
|
148
|
+
That D6 is a **registry promise with no channel behind it** — precisely the shape
|
|
149
|
+
`docs/adding-a-harness.md` step 8(c) names — and it predates this lane. Correcting the grade
|
|
150
|
+
is step 8 work; it is recorded here so the next reader does not inherit a D6 as evidence.
|
|
151
|
+
|
|
152
|
+
**Current coordinates are 0.153.4** (source `~/repos/3rd/codex` at `rust-v0.153.4`), measured
|
|
153
|
+
2026-09-08 in `scripts/raw-codex-measure/` — step 1 of `docs/adding-a-harness.md` only. The
|
|
154
|
+
0.136.0 rows above are preserved history. What the re-measurement changed:
|
|
155
|
+
|
|
156
|
+
- **Delivery survives 17 minor lines unchanged.** The shipped raw probe ran as-is (receipt in
|
|
157
|
+
the matrix row above). One method note: at 0.153.4 the rollout JSONL is materialized lazily,
|
|
158
|
+
so `thread/loaded/list` — not newest-rollout scraping — is the reliable `threadId` source.
|
|
159
|
+
- **Birth timing is first-turn, not window-open**, and the gap is ~47s wide on a live TUI.
|
|
160
|
+
- **A subagent raises `SubagentStart`, never `SessionStart`**, so §3.5's top-level predicate is
|
|
161
|
+
vendor-authoritative and costs nothing.
|
|
162
|
+
- **The callback dialect is `mcp__entwurf_bridge__entwurf_v2`** — a fourth spelling; the
|
|
163
|
+
sanitizer maps `-` to `_` but keeps the digit that omp's charset eats.
|
|
164
|
+
- **The step-6 join holds in both launch modes, but its owner moves — and in the
|
|
165
|
+
delivery-capable mode it cannot separate citizens.** Embedded:
|
|
166
|
+
`hook.ppid == mcp.ppid == the TUI`. App-server-attached: both resolve to the app-server, and
|
|
167
|
+
that is now measured rather than inferred — two live threads on one app-server, two separate
|
|
168
|
+
visible windows, **one `ppid` for every hook and every MCP child of both**, neither TUI in
|
|
169
|
+
the chain. A parent-pid sender marker would be one marker for N citizens, which Hard Rule 7's
|
|
170
|
+
`nativeSessionId` uniqueness forbids. **A different key was then found, and it is not a
|
|
171
|
+
marker at all:** every `tools/call` carries `_meta.threadId` plus an
|
|
172
|
+
`x-codex-turn-metadata.{session_id,thread_id,turn_id}` block, so the caller names itself on
|
|
173
|
+
each call — and that id is byte-identical to the hook's `session_id`, so birth, delivery and
|
|
174
|
+
tool calls share ONE identifier and `record.nativeSessionId = threadId` needs no mapping.
|
|
175
|
+
Both halves are vendor-traced, not just captured: `core/src/mcp_tool_call.rs:1328-1349`
|
|
176
|
+
inserts `threadId` unconditionally (constant at `:1184`) from the call site at `:506-516`,
|
|
177
|
+
and `:1238-1263` carries the turn-metadata block.
|
|
178
|
+
(The registry's pre-existing `nativeIdLabel: "threadId"` is right on that axis; its `D6` on
|
|
179
|
+
the same row still is not.) Consuming `_meta` is new bridge code and is step 6, unstarted.
|
|
180
|
+
- **Both admission questions this lane opened have since been CLOSED by measurement**, and
|
|
181
|
+
neither cost a design decision. The **hook trust prompt** has a real non-interactive path: a
|
|
182
|
+
hook in the managed `/etc/codex/config.toml` layer runs with no prompt, in both launch modes,
|
|
183
|
+
with `turn/start` wake intact — while `--dangerously-bypass-hook-trust` runs the hook but
|
|
184
|
+
kills auto-attach and is therefore unusable here. The remaining constraint is ownership:
|
|
185
|
+
`/etc/codex/` is root-owned, so that is a root-level operator step, not something `setup`
|
|
186
|
+
writes (Hard Rule 17). **Clause 4** has a working carrier: `thread/name/set` plus
|
|
187
|
+
`[tui] status_line = ["thread-title", …]` renders a garden id and survives turns in both
|
|
188
|
+
orderings, because the vendor's auto-titler is guarded on the thread being unnamed
|
|
189
|
+
(`tui/src/app/thread_routing.rs:1841`). It is reachable only over the app-server, and the
|
|
190
|
+
config key needs a writer that owns exactly it.
|
|
138
191
|
|
|
139
192
|
### Copilot CLI: one citizen, two rails, one pending receipt
|
|
140
193
|
|