@junghanacs/entwurf 0.24.0 → 0.25.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/CHANGELOG.md +455 -0
- package/DELIVERY.md +24 -1
- package/README.md +2 -2
- package/VERIFY.md +19 -1
- package/demo/README.md +5 -2
- package/docs/acp-backend-rail.md +49 -2
- package/docs/setup-clean-host.md +4 -4
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +5 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/control-send-receipt.js +101 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +6 -2
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-production.js +17 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +4 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +53 -6
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +38 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +13 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +11 -0
- package/mcp/entwurf-bridge/dist/protocol.js +0 -7
- package/mcp/entwurf-bridge/dist/scripts/doctor-pi-provider.js +40 -3
- package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +72 -0
- package/mcp/entwurf-bridge/src/index.ts +5 -4
- package/package.json +10 -9
- package/pi-extensions/entwurf-control.ts +27 -154
- package/pi-extensions/lib/compaction-send-guard.ts +5 -3
- package/pi-extensions/lib/control-send-receipt.ts +108 -0
- package/pi-extensions/lib/entwurf-v2-contract-schema.ts +1 -1
- package/pi-extensions/lib/entwurf-v2-contract.ts +6 -2
- package/pi-extensions/lib/entwurf-v2-production.ts +19 -1
- package/pi-extensions/lib/entwurf-v2-runner.ts +23 -1
- package/pi-extensions/lib/entwurf-v2-send.ts +82 -6
- package/pi-extensions/lib/entwurf-v2-surface.ts +42 -3
- package/pi-extensions/lib/herdr-fresh-call.ts +13 -3
- package/pi-extensions/lib/herdr-placement.ts +11 -0
- package/protocol.js +0 -8
- package/run.sh +197 -29
- package/scripts/check-entwurf-v2-surface.ts +289 -10
- package/scripts/check-gate-qualification.ts +7 -4
- package/scripts/check-herdr-fresh-call.ts +10 -2
- package/scripts/check-herdr-placement.ts +51 -0
- package/scripts/check-herdr-plugin-build.ts +11 -4
- package/scripts/check-herdr-plugin.ts +745 -38
- package/scripts/check-mux-launcher-fence.ts +37 -0
- package/scripts/check-pi-launch.ts +7 -4
- package/scripts/check-release-gate-outcomes.ts +165 -0
- package/scripts/doctor-pi-provider.ts +44 -4
- package/scripts/herdr-rails.mjs +75 -0
- package/scripts/meta-bridge-state.py +18 -1
- package/scripts/mutants/bridge-command-boot.json +38 -0
- package/scripts/mutants/control-send-receipt.json +235 -0
- package/scripts/mutants/herdr-fresh-call.json +4 -4
- package/scripts/mutants/herdr-plugin-build.json +7 -11
- package/scripts/mutants/herdr-plugin.json +177 -9
- package/scripts/mutants/meta-retire.json +22 -0
- package/scripts/mutants/pack-install.json +4 -4
- package/scripts/mutants/pi-floor.json +17 -0
- package/scripts/mutants/release-gate.json +48 -0
- package/scripts/mutants/retired-sent-surface.json +32 -0
- package/scripts/mutants/v2-surface.json +7 -7
- package/scripts/smoke-codex-fresh-live.ts +94 -13
- package/scripts/smoke-herdr-fresh-call-live.ts +15 -8
- package/scripts/smoke-herdr-raw-install-live.sh +59 -2
- package/scripts/smoke-meta-install-state.sh +107 -1
- package/scripts/smoke-mux-lifecycle-live.ts +9 -2
- package/scripts/smoke-pi-provider-state.sh +106 -0
- package/scripts/smoke-setup-verdict.sh +18 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,461 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.25.0 - 2026-09-23
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **The Herdr status pane stopped reporting presence and started reporting capability, in four
|
|
12
|
+
blocks that never merge (#120 P1-A).** `herdr plugin pane open --plugin junghan0611.entwurf
|
|
13
|
+
--entrypoint status` now draws HERDR INTEGRATION, ACTIVATION, RAILS and CITIZENS, and each block
|
|
14
|
+
carries three things that do not merge: `owner` (who is speaking — Herdr's listing is Herdr's
|
|
15
|
+
word about Herdr, the ledger is Entwurf's word about its own install, the rails table is this
|
|
16
|
+
package's own declaration), `observedAt` (`now`, `install-time`, or `static`) and its own
|
|
17
|
+
`outcome`. **There is deliberately no aggregate** — no reducer, no `overall`, no readiness word:
|
|
18
|
+
three of the four blocks answer at different times, so one token over them would have to pick one
|
|
19
|
+
time and lie about the other two, and a host whose Herdr integration is current, whose ledger was
|
|
20
|
+
written last week, and whose runtime has since been deleted is exactly the case a summary word
|
|
21
|
+
erases. A block that could not be read says so in its own voice with the gatherer's named code
|
|
22
|
+
rather than degrading to an empty section, because an empty section and a failed read look
|
|
23
|
+
identical on a screen and only one of them is safe to act on. The render is a pure data-to-data
|
|
24
|
+
leaf (`plugins/herdr/lib/capability-report.mjs`: no `fs`, no `spawnSync`, no `process.env`, no
|
|
25
|
+
dynamic import, no clock) and the gathering that must open files and import an installed module
|
|
26
|
+
lives in `activation-evidence.mjs`, so it stays visible WHICH artifact answered — the checkout or
|
|
27
|
+
the runtime. The measured blocker repaired on the way in: the writer's ledger is XDG **state**,
|
|
28
|
+
not XDG **data**, and the first candidate crashed before drawing any block on a normal
|
|
29
|
+
writer-produced ledger. Herdr `outdated|needs-repair` is block [1]'s own named red while
|
|
30
|
+
`not-installed` stays a reported skip; only `phase=active` grants a runtime fallback, and
|
|
31
|
+
`activating|deactivating` remain visible install-time receipts that grant no binary. THREE READS
|
|
32
|
+
/ ONE OPEN is restored behind exactly one spawn callsite. Receipts: `check-herdr-plugin` 48
|
|
33
|
+
assertions, and that lane 24/24 mutants killed in the implementer's scratch mirror and again in
|
|
34
|
+
the coordinator's body.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **A control-socket send now reports the acceptance boundary it actually got, and that
|
|
39
|
+
vocabulary is closed (#120 P2).** `entwurf_v2` answered `sent` whether the receiver was idle or
|
|
40
|
+
busy, and prose in four places called the busy path an interrupt or an immediate delivery.
|
|
41
|
+
Neither queue is an interrupt: a busy receiver drains steering after each turn and follow-ups
|
|
42
|
+
only when its inner loop ends, so a later steer overtakes every earlier follow-up and there is no
|
|
43
|
+
order between the two. Sender-visible acceptance is now its own closed axis — `sent |
|
|
44
|
+
queued-steer | queued-follow-up | accepted-unknown-boundary` — preserved through send →
|
|
45
|
+
structured error → runner → surface, while the route/release `SendFinalOutcome` is unchanged.
|
|
46
|
+
`sent` means the turn was TRIGGERED, not that the model has seen the text, and both queues are
|
|
47
|
+
volatile process memory an abort drops. A fallback socket preserves that boundary; a fallback
|
|
48
|
+
mailbox names its own durable enqueue receipt; dirty-lock receipts keep the actual boundary, file
|
|
49
|
+
and refusal reason instead of flattening them. The receiver wire no longer emits a bare
|
|
50
|
+
`delivered:true` or the unused `deliveredAs`. The oracle is the installed `pi-agent-core` itself
|
|
51
|
+
(`test/pi-queue.oracle.test.ts`, now on `check:full` with its exact core pin gated to the pi
|
|
52
|
+
floor): cross-mode overtaking, one-at-a-time drain, no mid-flight merge, and abort loss, proven
|
|
53
|
+
with zero model, network or ACP child turn. `DELIVERY.md`, `docs/acp-backend-rail.md`, the demo
|
|
54
|
+
README and the `entwurf-dev` skill were corrected to those same four words. Three proof holes
|
|
55
|
+
were closed before acceptance: dirty-lock end-to-end field loss, a `test/**` oracle that was not
|
|
56
|
+
on the public floor, and a reachability checker a comment could satisfy.
|
|
57
|
+
|
|
58
|
+
- **pi runtime floor 0.86.0 → 0.87.1 (#120 P4, landed in two measured steps).** Four exact dev
|
|
59
|
+
pins (including P2's direct `pi-agent-core` queue oracle), three closed peer ranges
|
|
60
|
+
(`>=0.87.1 <0.88`), the
|
|
61
|
+
eight-package install/workspace constellation (seven `pi-*` packages plus `chord`), the
|
|
62
|
+
pack-install version matcher, and the support declarations in README, the Herdr install docs, mux
|
|
63
|
+
docs, setup docs, VERIFY and the ACP support matrix now name one floor.
|
|
64
|
+
`[QK:PI-FLOOR-SINGLE-SOURCE]` closes a measured static hole: before this, `check-dep-versions`
|
|
65
|
+
did not read `pnpm-workspace.yaml`, so one stale release-age row failed only later, during
|
|
66
|
+
installation. The five declared 0.87 breaking changes were re-measured rather than relabelled and
|
|
67
|
+
production contact is zero — and the three type fences are what confirm that, not grep
|
|
68
|
+
(`tsc --noEmit`, `-p scripts`, `-p mcp`, all rc=0). The installed 0.87 extension context still
|
|
69
|
+
exposes `isIdle()` / `signal` at the same coordinates and still has no `isCompacting`; the
|
|
70
|
+
`pi-agent-core` queue drain coordinates MOVED (`agent.js` `:98-99` → `:96-97`, `agent-loop.js`
|
|
71
|
+
steering drain `:159` → `:186`, follow-up drain `:162-166` → `:191-197`) while all four
|
|
72
|
+
queue-behaviour QKs stayed green; the sandbox CLI still refuses an unregistered
|
|
73
|
+
`--entwurf-control`. A deterministic gate now writes a REAL 0.87 session JSONL through the
|
|
74
|
+
installed public `SessionManager` with zero model, network or child process and proves basename
|
|
75
|
+
id = header id = manager id, so `check-herdr-placement` re-measures that axis on every run rather
|
|
76
|
+
than carrying a hand-made receipt. **0.86.1 was skipped with a reason:** its coding-agent
|
|
77
|
+
CHANGELOG has no Breaking Changes section at all and `packages/agent` 0.86.1 is an empty entry,
|
|
78
|
+
so it touches none of our surfaces and its provider/CLI improvements arrive inside 0.87.0 anyway.
|
|
79
|
+
ROADMAP's dated ledger carries the per-file sha256 pairs (written with real `packages/...`
|
|
80
|
+
paths, after a prior entry recorded an empty-file hash for a path that did not exist) and the
|
|
81
|
+
per-breaking-change contact receipts.
|
|
82
|
+
**The second step, 2026-09-23: 0.87.0 → 0.87.1, and it is the floor this release declares.**
|
|
83
|
+
0.87.0 was already superseded on npm (`dist-tags.latest` said 0.87.1) while the prepared
|
|
84
|
+
candidate still named 0.87.0, and no gate reads upstream `latest`, so a person found the gap
|
|
85
|
+
rather than a check. The patch carries **no Breaking Changes section in any of the seven
|
|
86
|
+
package changelogs**, and the contact measurement says why: all six load-bearing files this
|
|
87
|
+
repo tracks are byte-identical across the two tags (their sha256 pairs match the values the
|
|
88
|
+
0.87.0 entry above recorded, so the ledger cross-checks itself), `packages/agent` changed only
|
|
89
|
+
its CHANGELOG and `package.json`, and the whole `coding-agent/src` diff is three files. Each
|
|
90
|
+
was judged, not skimmed: `--mode` now rejects an invalid value instead of ignoring it, and
|
|
91
|
+
every `--mode` this repo passes pi is `rpc` or `json` (the other `--mode` hits are OMP's CLI,
|
|
92
|
+
a different vendor under the same flag name); the xAI default moved to Grok 4.7 and nothing
|
|
93
|
+
here depends on a provider default; the third is compaction summary wording, which entwurf
|
|
94
|
+
does not own on any rail (#94). Because `pi-agent-core` shipped no source change, the P2
|
|
95
|
+
queue coordinates could not move — and that was re-measured on the installed 0.87.1 rather
|
|
96
|
+
than inferred: `agent.js:96-97`, `agent-loop.js:186` and `:191-197` are where they were. The
|
|
97
|
+
per-floor hand receipts were re-taken too, additively: the sandbox CLI still refuses an
|
|
98
|
+
unregistered `--entwurf-control` byte-identically, and the extension context still declares
|
|
99
|
+
`isIdle()` at `:233` and `signal` at `:237` with no `isCompacting`. **The floor has exactly one
|
|
100
|
+
knob**, which is what made this a small change: `check-dep-versions` derives the peer range
|
|
101
|
+
and `check_pi_runtime_version` derives its FLOOR from the same exact devDep pin, so a
|
|
102
|
+
candidate cannot pin 0.87.1 while advertising 0.87.0. Moving it reddened four surfaces on cue
|
|
103
|
+
— and the gates named two omissions the author had missed: `[QK:MUTANT-FIND-MATCHES-SUBJECT]`
|
|
104
|
+
caught two `pack-install` pin-matcher mutants at `matched 0×`, and the prose scan caught
|
|
105
|
+
`demo/README.md`'s `current floor` and ROADMAP's `pi <version> fence`. The 0.87.0 numbers
|
|
106
|
+
above and in ROADMAP's two dated ledgers are preserved as the measurements of their own day;
|
|
107
|
+
one blind pass had rewritten two ledger receipts and was reverted.
|
|
108
|
+
|
|
109
|
+
- **The Codex first-admission acceptance stays a release MUST, and what a cut must supply to it is
|
|
110
|
+
now written where a cut is taken from.** Reclassifying its absent prerequisite as a SKIP (see
|
|
111
|
+
Fixed) could have been read as demoting the step to an on-demand axis; that boundary is decided
|
|
112
|
+
the other way and gated. #87 made a newly admitted harness's visible-fresh receipt a MUST **after
|
|
113
|
+
measuring what the on-demand wording permitted** — a harness could be admitted as a full citizen
|
|
114
|
+
that `entwurf_fresh_call` cannot open and still pass the whole floor — so demoting Codex would
|
|
115
|
+
reopen exactly that hole. (VERIFY's standing "on-demand host axis" sentence is about
|
|
116
|
+
`smoke-codex-native-push-live`, the operator-loaded-thread probe, and is unchanged.) A SKIP is
|
|
117
|
+
therefore not a softening: `--cut` refuses it as `cut: BLOCKED (MUST SKIP)`, asked of the shared
|
|
118
|
+
shell authority rather than re-implemented, so a cut without this receipt is still impossible and
|
|
119
|
+
a host with no Codex app-server cannot take one — the intended cost of that release stop rather
|
|
120
|
+
than an accident. What changed is that the reproducible green is now stated: VERIFY says
|
|
121
|
+
`release-gate --cut` inherits the operator-supplied triple, and the release skill's P5 carries it
|
|
122
|
+
on the invocation (measured: `release_gate` exports no scrub and unsets nothing, so an exported
|
|
123
|
+
triple already reaches the step — no plumbing was added). **The instructions obey the
|
|
124
|
+
no-inference rule they teach.** The first draft of that P5 derived the pid with
|
|
125
|
+
`pgrep -f 'codex.*app-server' | head -1`, which is the inference the step exists to refuse,
|
|
126
|
+
written onto the page an operator follows, and on a host running several app-servers it hands the
|
|
127
|
+
gate an arbitrary process to verify as "the operator's answer". Each value is now STATED and
|
|
128
|
+
guarded by an explicit `: "${VAR:?...}"` required-value check before any LIVE cost. Three claims
|
|
129
|
+
keep the boundary from drifting back, one per direction, each with its own exact-once mutant:
|
|
130
|
+
`[QK:CODEX-OPERATOR-PREREQ-ABSENT-SKIPS]` (which pins the filter → guard → `skipLive` shape as one
|
|
131
|
+
contiguous sequence, reading the source with comments stripped — a promise in prose is precisely
|
|
132
|
+
where this defect hid for a release, and a first candidate mutant SURVIVED a weaker regex before
|
|
133
|
+
that cell was tightened), `[QK:CODEX-OPERATOR-PREREQ-WRONG-FAILS]`, and
|
|
134
|
+
`[QK:CODEX-OPERATOR-PREREQ-STATED-NOT-SEARCHED]`. The installed-config preflights are
|
|
135
|
+
deliberately OUTSIDE this split and still FAIL on absence: a missing Codex birth, user
|
|
136
|
+
MCP/status/terminal-title config, runtime, bridge, tmux seat or an unanswered launch directory is
|
|
137
|
+
host state `setup` and the Codex doctors own, not a per-invocation input.
|
|
138
|
+
|
|
139
|
+
- **The Herdr plugin manifest version moves 0.4.1 → 0.5.0 for this cut, and nothing else reads
|
|
140
|
+
that literal.** `plugins/herdr/herdr-plugin.toml` is the sole declaration (measured: one hit
|
|
141
|
+
repository-wide); `check-herdr-plugin` asserts semver SHAPE, not a value
|
|
142
|
+
(`scripts/check-herdr-plugin.ts:82`), and `min_herdr_version` stays the measured 0.9.0 floor.
|
|
143
|
+
`plugins/herdr/runtime-lock.json` returns to the `herdr-checkout` candidate carrier for the cut,
|
|
144
|
+
because `certifyLockCoherence` requires an npm lock to name a version that is BOTH already
|
|
145
|
+
published and equal to this checkout's `package.json` — and the version bump lands before the
|
|
146
|
+
publish. That is the same order `dd84ac0`/`3c3a67d`/`47f6d36` recorded: `v0.23.1` and `v0.24.0`
|
|
147
|
+
were both tagged on that carrier and the npm pin returned afterwards. The lock never moves onto an
|
|
148
|
+
unpublished version, and the 0.25.0 npm pin plus its published sha512 is a follow-up commit, not
|
|
149
|
+
part of this cut. The build gate and the README's release sentence move with it, because they read
|
|
150
|
+
the committed lock beside it.
|
|
151
|
+
|
|
152
|
+
- **The Herdr plugin README is rebuilt around the two questions a visitor actually
|
|
153
|
+
arrives with: which route do I want, and what do I type first.** It now opens by saying what the
|
|
154
|
+
plugin is *not* (a second workbench), then a route chooser, the Herdr built-ins this plugin
|
|
155
|
+
depends on versus what Entwurf adds, a quick start that runs from a raw box in nine steps to the
|
|
156
|
+
first status pane, and only then the direct/mux comparison, boundaries, runtime and developer
|
|
157
|
+
detail. Four facts were repaired against source while re-reading it: the install narration is
|
|
158
|
+
four usage notes, not two (`lib/build.mjs:217-227,292-294`); the receipt section named the
|
|
159
|
+
superseded npm 0.23.1 pin instead of the 0.24.0 lock at `deb73f1`; `check-bridge` asserts
|
|
160
|
+
**eight** garden verbs, not seven (`run.sh:4708` `EXPECT_TOOLS`); and an unmeasured "~45 s,
|
|
161
|
+
hundreds of MB" claim was dropped. The route paragraph no longer says the two routes install the
|
|
162
|
+
same *runtime* — they install the same capability package, but this plugin pins an exact
|
|
163
|
+
`@junghanacs/entwurf@<version>` plus its published sha512 while a direct `npm install -g`
|
|
164
|
+
follows whatever version npm is asked for. The neighbouring-plugin table is now explicitly
|
|
165
|
+
"observed mechanism families, not a census or a compatibility matrix", and every family-wide
|
|
166
|
+
property assertion in it (pane-bound addresses, workspace-scoped identity, receipts as a
|
|
167
|
+
non-goal, "structurally the closest to Entwurf") was narrowed to implementation-specific: the
|
|
168
|
+
differentiator stated in prose is Entwurf's record-backed garden id and the no-argument same-id
|
|
169
|
+
`entwurf_resume_call`, not a uniqueness claim about durable addresses. Docs ship with the
|
|
170
|
+
plugin, so the manifest moves with them. Receipts: `check-herdr-plugin` 32 ok,
|
|
171
|
+
`check-herdr-plugin-build` 14 ok, `check-herdr-plugin-profile` 14 ok, `check-dep-versions` ok
|
|
172
|
+
(pi 0.86.0 across 9 ranges, unchanged), `check-node-floor-coherence` ok, all four relative links
|
|
173
|
+
resolve, `git diff --check` clean.
|
|
174
|
+
- **The plugin runtime lock is pinned to npm `@junghanacs/entwurf@0.24.0`** and its published
|
|
175
|
+
sha512, closing the candidate window 0.24.0 shipped in — the second of the two steps the 0.24.0
|
|
176
|
+
entry below names. The integrity was measured here twice, independently: `npm view
|
|
177
|
+
@junghanacs/entwurf@0.24.0 dist.integrity` and `openssl dgst -sha512` over the preserved
|
|
178
|
+
candidate `make` accepted (`/tmp/entwurf-release-candidate-0.24.0.LXYL1S`, sha256
|
|
179
|
+
`fd750bcb…`) agree, and the registry tarball's sha256 equals the candidate's, so the lock names
|
|
180
|
+
the exact bytes the release gate consumed. Lock and `check-herdr-plugin-build` moved together
|
|
181
|
+
(the measured forward of `47f6d36`, version literals and the `IDENTITY` fixture's sha512 moved
|
|
182
|
+
to 0.24.0), the plugin README drops the candidate sentence, and `herdr-plugin.toml` already says
|
|
183
|
+
0.4.0. Receipts: `check-herdr-plugin-build` 14/14, `check-herdr-runtime-bootstrap` 31 ok with
|
|
184
|
+
`source=npm … version 0.24.0 … npm-coherent=true`, `check-herdr-plugin` 32 ok,
|
|
185
|
+
`check-gate-manifests` 739/59 unchanged, `pnpm check` exit 0 (57 s). Registry smoke: a
|
|
186
|
+
sandboxed `pi install npm:@junghanacs/entwurf@0.24.0` resolves the bridge to the registry
|
|
187
|
+
install and `--list-models entwurf` lists the curated Claude and Cortex anchors; dist-tags
|
|
188
|
+
`latest=0.24.0`, `repair=0.12.8-repair.1` preserved.
|
|
189
|
+
- **`smoke-herdr-raw-install-live` says the eighth verb too.** Its verb cell keeps an
|
|
190
|
+
independent copy of the shipped `EXPECT_TOOLS` set on purpose, so an upstream verb reddens it
|
|
191
|
+
until somebody says so there — and `entwurf_callback` had not been said. First run on the
|
|
192
|
+
public remote at `deb73f1` with the npm 0.24.0 runtime: every acquisition, identity, [7]/[8a]
|
|
193
|
+
0-token citizen and teardown/reinstall cell green, only that copy red; with the eighth verb
|
|
194
|
+
named the smoke is PASS (`ref=main`, runtime `@junghanacs/entwurf@0.24.0`, observed sha256
|
|
195
|
+
`fd750bcb…`). The comment's stale `run.sh:5187` line reference now names the constant instead.
|
|
196
|
+
|
|
197
|
+
### Removed
|
|
198
|
+
|
|
199
|
+
- **The sender-side `entwurf-sent` transcript box, which had no producer (#120 P3).** Repository
|
|
200
|
+
measurement found one definition, one renderer registration and **zero** producers, while two
|
|
201
|
+
live comments named producers that did not exist. The shipped `ENTWURF_SENT_MESSAGE_TYPE` export
|
|
202
|
+
and the dead `SentBoxData` / builder / renderer / registration are gone; the independent
|
|
203
|
+
receive-side `entwurf-message` producer and renderer are untouched. The remaining receive-side
|
|
204
|
+
comment now states the true boundary — a sender receives an acceptance-boundary text receipt, and
|
|
205
|
+
only a receiver can claim a transcript box was rendered. Two claims keep it retired: AST-based
|
|
206
|
+
`[QK:NO-RENDERER-WITHOUT-PRODUCER]`, so a comment or a string literal cannot satisfy the producer
|
|
207
|
+
proof, and `[QK:RETIRED-SENT-SURFACE-ABSENT]`, which seals both identifiers and the stale
|
|
208
|
+
`entwurf sent` / `sender-side UI box` prose. The two mutants went into their own
|
|
209
|
+
`retired-sent-surface` lane rather than mixing into P2 receipt semantics, and historical
|
|
210
|
+
ROADMAP/demo evidence was kept as history with a dated correction rather than rewritten.
|
|
211
|
+
|
|
212
|
+
### Fixed
|
|
213
|
+
|
|
214
|
+
- **`showTurnDuration` was never ours, and entwurf had been forcing the operator's own display
|
|
215
|
+
off.** The native meta-bridge install owned a list of Claude Code policy scalars that close
|
|
216
|
+
background autonomy and suggestion surfaces — and this one had been sitting in it, pinned to
|
|
217
|
+
`false`. It closes nothing: it reports how long a turn took, which is operator INFORMATION, so the
|
|
218
|
+
policy reason the rest of that list stands on never applied to it. GLG's ruling is that the
|
|
219
|
+
operator owns the scalar and entwurf must neither own it nor force it. The symptom had been
|
|
220
|
+
misread as drift: `./run.sh doctor-meta-bridge` was FAIL on the source host for exactly one
|
|
221
|
+
managed scalar, with `~/.claude/settings.json` saying `true` and the writer requiring `false`, and
|
|
222
|
+
the install-state carries no per-scalar provenance to say whose value that was. The actual cause
|
|
223
|
+
is measurable and is **two owners on one key**: `check-keyset-overlap` against the operator's own
|
|
224
|
+
`agent-config` settings fragment failed on `showTurnDuration` and on nothing else, because both
|
|
225
|
+
sides claimed it. Dropping our claim is what resolves that collision, with **zero change to
|
|
226
|
+
agent-config**. The key is RETIRED rather than deleted, through the same one-shot path #94 built
|
|
227
|
+
for compaction, because an existing install-state already carries its entry — measured on the
|
|
228
|
+
source host, `original {existed: true, value: false}` under a live `true`, i.e. the operator
|
|
229
|
+
turned the display on after our install — and `uninstall()` walks every ledger entry through
|
|
230
|
+
`restore_entry`, so deleting the constant would have written `false` back over that choice.
|
|
231
|
+
`[QK:META-RETIRE-TURN-DURATION-OPERATOR-OWNED]` measures the premise instead of quoting it: it
|
|
232
|
+
asks the SSOT whether the key is claimed, pins the retired comparison value by type as well as
|
|
233
|
+
equality, drives the real relinquish leaf on the exact host shape above, and proves the ledger row
|
|
234
|
+
is consumed so no later inverse can reach the key. Its mutant drifts the scalar back under
|
|
235
|
+
management. **The migration ran on the host and was measured on both sides:** before
|
|
236
|
+
`showTurnDuration=true`, after `showTurnDuration=true`, the ledger entry gone (15 managed keys
|
|
237
|
+
→ 14), and `doctor-meta-bridge` now PASS with 33 ok where it had been exit 1 on that one axis.
|
|
238
|
+
|
|
239
|
+
- **A release MUST step reported a missing operator input as a FAILURE, so the aggregate gate was
|
|
240
|
+
structurally red on every host at every cut.** `smoke-codex-fresh-live` takes three values only
|
|
241
|
+
the operator can supply — the app-server pid and two model tiers — and `release_gate()` supplies
|
|
242
|
+
none of them, by design: entwurf neither starts nor supervises that app-server. Its own skip line
|
|
243
|
+
promised four prerequisites in one breath (`LIVE=1` plus the three env names), but only the first
|
|
244
|
+
could produce a SKIP; the other three were `ok()` assertions, and `ok()` throws. So the step
|
|
245
|
+
declined as a defect. `scripts/lib/step-outcome.sh` had already written the rule this broke —
|
|
246
|
+
*"a step that RAN AND BROKE and a step that NEVER RAN are different facts, and a release record
|
|
247
|
+
that blurs them is worthless: the first is a defect to fix, the second is a prerequisite to
|
|
248
|
+
supply"* — and the candidate receipt below shows the cost: `MUST PASS=23 FAIL=1`,
|
|
249
|
+
`cut: BLOCKED (MUST FAIL)`, with a prose classification standing in for a floor. **The repair is
|
|
250
|
+
the classification, not the requirement.** An ABSENT input is now a protocol SKIP naming each
|
|
251
|
+
missing one; a PRESENT but wrong one — a malformed or dead pid, a process whose argv is not a
|
|
252
|
+
Codex app-server, a foreign uid, an app-server sharing the gate's own session — stays a FAIL.
|
|
253
|
+
Both arms were measured, and neither opens a window or spends a turn: unset triple under `LIVE=1`
|
|
254
|
+
exits 97 with its `[entwurf:skip]` line, `ENTWURF_CODEX_APP_SERVER_PID=abc` exits 1 naming the
|
|
255
|
+
value. No inference was added and no default invented for a value nobody gave.
|
|
256
|
+
|
|
257
|
+
- **The Herdr status pane died before drawing a single block on the carrier every candidate window
|
|
258
|
+
rides.** `plugins/herdr/lib/activation-evidence.mjs` located the installed ledger reader by
|
|
259
|
+
reading the package directory name off `runtime-lock.json` — but that file is a discriminated
|
|
260
|
+
union and only its `npm` arm carries a `name`, so on the `herdr-checkout` arm
|
|
261
|
+
(`{source, repository}`) the name was `undefined` and `path.join` answered it with a `TypeError`
|
|
262
|
+
raised OUTSIDE the `try` that was supposed to name every failure this module can have. Measured on
|
|
263
|
+
this cut: with that lock committed, `check-herdr-plugin` reported `block was ""` and every one of
|
|
264
|
+
its 48 assertions stood on a pane that had crashed. The carrier is not an edge case — `v0.23.1`
|
|
265
|
+
and `v0.24.0` were both tagged on it. The gatherer now takes `checkoutRoot` and asks
|
|
266
|
+
`readCheckoutPackageSpec`: the manifest is the one name both lock arms already agree about, since
|
|
267
|
+
the npm arm is certified coherent with it and the checkout arm packs that very manifest. The join
|
|
268
|
+
moved inside the same `try`, so a locator that ever yields a non-string is a named
|
|
269
|
+
`activation-reader-unavailable` rather than a process death. `VERIFY.md` had already written this
|
|
270
|
+
rule down for `smoke-herdr-raw-install-live`; the lesson had not crossed to the gatherer `79391fb`
|
|
271
|
+
added. `[QK:HPL-PACKAGE-NAME-FROM-MANIFEST]` measures the premise instead of quoting it — it
|
|
272
|
+
writes a checkout-arm lock and asks the real reader what `.name` is — then requires the module to
|
|
273
|
+
ask the manifest and never the lock, with comments stripped first so prose cannot satisfy it; its
|
|
274
|
+
mutant drifts the call back to `readRuntimeLock`.
|
|
275
|
+
|
|
276
|
+
- **`doctor-pi-provider` called every Herdr-plugin host red while its bridge booted and served all
|
|
277
|
+
eight verbs (#120 P1-B).** The install-state's `ownership` field is a PREIMAGE classification —
|
|
278
|
+
what stood at the key BEFORE that install — so `absent` means "we created it", not "nobody owns
|
|
279
|
+
it"; reading it as an ownership verdict is what produced the false red. The doctor now reads the
|
|
280
|
+
recorded `command` beside it, because that string and not the bare name is the canonical managed
|
|
281
|
+
command (`register-pi-provider.py` writes the same string into the settings entry and into the
|
|
282
|
+
record), and in plugin mode it is an absolute bridge under the certified stable runtime, since a
|
|
283
|
+
Herdr-plugin host has nothing `entwurf` on PATH. For a known managed preimage carrying a recorded
|
|
284
|
+
command the comparison now runs REGARDLESS of whether the effective command happens to be the
|
|
285
|
+
bare name: keeping that decision inside a `!isBare` branch is how real drift escaped — a record
|
|
286
|
+
naming the absolute plugin bridge with the settings repointed at bare `entwurf-bridge` is drift,
|
|
287
|
+
and a bare bridge that boots would otherwise have carried it to green. A record that names no
|
|
288
|
+
command, or one whose ownership is a word this doctor does not know, falls through to the
|
|
289
|
+
original logic unchanged; the state is rewritten by `./run.sh setup`, never by its reader.
|
|
290
|
+
|
|
291
|
+
- **Three qualification control reds, which were gate defects rather than product ones (#120).**
|
|
292
|
+
The first committed body at `bad2677` ran 69m42s and ended 746/777, with the remaining 31 voided
|
|
293
|
+
only by baseline-red controls. `[QK:MUTANT-GATES-INSIDE-FULL-FLOOR]`: `check-control-send-receipt`
|
|
294
|
+
and `check-entwurf-v2-runner` were valid narrow mutant coordinates but absent from `check:full`,
|
|
295
|
+
so they are now wired into `check:contracts` (~1.5 s combined, measured) while keeping their
|
|
296
|
+
source-adjacent discovery. `[QK:LAUNCHFENCE-EXPOSED-SMOKE-WIRED]`: P1's new XDG data-root cell
|
|
297
|
+
moved `smoke-herdr-raw-install-live.sh` into launcher-fence scrutiny, and the fence's env-block
|
|
298
|
+
parser understood only TypeScript object literals, not a continued shell `env` command — it now
|
|
299
|
+
reads that actual invocation and grants the exemption only when `HOME=` is relocated in the same
|
|
300
|
+
block, with a negative cell deleting that assignment to prove the exemption disappears.
|
|
301
|
+
`smoke-setup-verdict` S-8's intermittent second-run idempotence red had its output discarded by a
|
|
302
|
+
`| grep -q`, leaving no causal receipt; the second setup output is now captured and printed on
|
|
303
|
+
failure. No retry, sleep, enlarged timeout or speculative behaviour change was added, and S-8 is
|
|
304
|
+
explicitly NOT claimed fixed — it did not recur in the accepted body, and if it returns the next
|
|
305
|
+
receipt carries the output instead of one context-free FAIL line.
|
|
306
|
+
|
|
307
|
+
- **Two stale oracles in `smoke-codex-fresh-live`, both surfaced by the LIVE floor of this cut.**
|
|
308
|
+
(a) The step read a control-socket receipt as successful only when it said `sent|delivered`.
|
|
309
|
+
`6d90d73` widened two sibling LIVE smokes to the closed four-value axis and named the reason in
|
|
310
|
+
`smoke-herdr-fresh-call-live.ts:89` — *"the old literal `→ sent` pin would have gone red on the
|
|
311
|
+
common case and passed only when the caller happened to be idle"* — and this third one was missed.
|
|
312
|
+
Measured on this exact step: the fixture addresses the initial Pi mid-turn, the rail answered
|
|
313
|
+
`queued-follow-up`, and a release-gate MUST went red on a delivery that had succeeded. Before P2
|
|
314
|
+
it passed on the busy path only because the rail said `sent` either way, which is the dishonesty
|
|
315
|
+
P2 removed; `delivered` was never a member of the set. (b) The initial-Pi exact-once audit still
|
|
316
|
+
expected the PRE-0.24.0 callback shape — an `entwurf_v2` carrying the nonce as arguments — while a
|
|
317
|
+
pi sibling's first action has been the zero-argument `entwurf_callback` since 0.24.0, as this
|
|
318
|
+
smoke's own launch receipt says in the same run: *"its first action is the zero-argument callback
|
|
319
|
+
verb (codex is the one arm that still sends the nonce as arguments)"*. A sibling obeying the
|
|
320
|
+
shipped framing was therefore reported as an unexpected call. Only the pi branch moved; the Codex
|
|
321
|
+
audit keeps `entwurf_v2`, because codex really is still the argument-carrying arm
|
|
322
|
+
(`codex-callback-env-unsupported`). This is the class `e506716` closed for
|
|
323
|
+
`smoke-herdr-raw-install-live`, and it stayed hidden in 0.24.0 because that cut's run died earlier
|
|
324
|
+
at the Pi→Codex template relay. Neither repair weakens an assertion: `{}` is matched by
|
|
325
|
+
`isDeepStrictEqual`, so it pins the verb's zero-argument contract rather than accepting any
|
|
326
|
+
arguments, the exact-once count is unchanged, a refusal still fails, and the callback-nonce
|
|
327
|
+
correlation was never carried by that audit — it is proven earlier and from the DELIVERED body by
|
|
328
|
+
`the initial Pi callback carries the exact launch nonce`, which reads the fixture's own mailbox,
|
|
329
|
+
requires exactly one exact match and refuses duplicates.
|
|
330
|
+
|
|
331
|
+
### Verification
|
|
332
|
+
|
|
333
|
+
Frozen candidate `69a6f1d`, host `oracle`, 2026-09-23 KST. Two receipts, kept apart on purpose.
|
|
334
|
+
|
|
335
|
+
- **Deterministic floor:** `pnpm run check:full` exit 0, 607 s.
|
|
336
|
+
- **Aggregate LIVE floor**, `LIVE=1 ./run.sh release-gate <scratch> --cut` with ambient identity
|
|
337
|
+
carriers stripped, scratch `/tmp/entwurf-release-gate-0.25.0-final.HghiXh`:
|
|
338
|
+
**MUST PASS=23 FAIL=1 SKIP=0**, **BEHAVIOR PASS=1 FAIL=0 SKIP=0**, `cut: BLOCKED (MUST FAIL)`.
|
|
339
|
+
Inside it, `check-gate-qualification` killed **778/778** with `[gate-qualification] ok` and both
|
|
340
|
+
purity axes green — measured on these exact bytes, which is why the aggregate was re-run after the
|
|
341
|
+
two gate commits above: `scripts/smoke-codex-fresh-live.ts` is the subject of three committed
|
|
342
|
+
mutants (`CODEX-LIVE-EVIDENCE-RECORD-PATH`, `CODEX-LIVE-EVIDENCE-RECOVERY-FAILSAFE`,
|
|
343
|
+
`CODEX-LIVE-RECOVERY-SOURCE-ONLY`), and all three killed at `sha256=40c7852fc273…`.
|
|
344
|
+
- **The one MUST red is the shape of that step, not a defect.** `release_gate()` supplies no
|
|
345
|
+
`ENTWURF_CODEX_APP_SERVER_PID`, and `smoke-codex-fresh-live` refuses to infer one — VERIFY: *"The A
|
|
346
|
+
cell takes no inferred server or models"* — so it declines inside every aggregate on every host.
|
|
347
|
+
Its pair is the standalone run on the SAME frozen `69a6f1d`: `LIVE=1
|
|
348
|
+
ENTWURF_CODEX_APP_SERVER_PID=3969303 ENTWURF_CODEX_FRESH_MODEL=gpt-5.6-luna
|
|
349
|
+
ENTWURF_CODEX_FRESH_PI_MODEL=openai-codex/gpt-5.6-terra ./run.sh smoke-codex-fresh-live` →
|
|
350
|
+
**66 assertions ok, exit 0**, `initial-pi=3/3 completed exact`, `codex=3/3 completed exact`.
|
|
351
|
+
The Pi tier is terra rather than luna, and that is a recorded tier choice, not a gate change: the
|
|
352
|
+
0.23.1 follow-up already measured luna losing relay fidelity where terra preserves it, and on this
|
|
353
|
+
cut luna pre-substituted the `<placeholder>` template the smoke audits for byte equality
|
|
354
|
+
(ROADMAP 0.24.0 follow-up 3). The receipt this cell is accepted on is the run that actually ran.
|
|
355
|
+
- **Host residue (P9, run at the gate's verdict and again at the end of prepare):** 588 → 586 dirs,
|
|
356
|
+
2 roots / 112 K reclaimed, by prefix `entwurf-s2b-overlay` and `check-probe-ordering`. One
|
|
357
|
+
reparented process holds a `/tmp` path and was named rather than killed: pid 489788, the
|
|
358
|
+
operator's own `emacs --init-directory=/tmp/agent-emacs-init --daemon`, which no gate mints.
|
|
359
|
+
- **Open, pre-cut, not resolved by this candidate:** `./run.sh doctor-meta-bridge` is FAIL on this
|
|
360
|
+
host for exactly one managed scalar — `settings showTurnDuration missing/drifted`, where
|
|
361
|
+
`~/.claude/settings.json` says `true` and `scripts/meta-bridge-state.py:90` requires `false`.
|
|
362
|
+
Every other axis of that doctor reads ok (hook launch form, doorbell static contract, statusline,
|
|
363
|
+
user-scope MCP reachability, cached artifact). The install-state carries no per-scalar provenance,
|
|
364
|
+
so whether this is drift from our write or the operator's own UI choice is not decided here, and
|
|
365
|
+
the host was deliberately left untouched.
|
|
366
|
+
|
|
367
|
+
- **Resolved 2026-09-23, after the paragraph above was written.** That doctor red was not drift and
|
|
368
|
+
not undecidable: the key had two owners, and GLG ruled the operator owns it. The scalar is retired
|
|
369
|
+
(see Fixed), and the host migration was measured on both sides — `showTurnDuration=true` before
|
|
370
|
+
and after, the install-state ledger entry consumed (15 managed keys → 14), and
|
|
371
|
+
`./run.sh doctor-meta-bridge` now **exit 0, PASS, 33 ok**. The paragraph above is kept as what was
|
|
372
|
+
true when the frozen candidate was measured.
|
|
373
|
+
|
|
374
|
+
**Post-prepare release-fix candidate (2026-09-23, host `oracle`) — source, focused and host
|
|
375
|
+
receipts only.** This is not a cut receipt. `check-gate-qualification`'s body (`782/782` killed,
|
|
376
|
+
`[gate-qualification] ok`) and `pnpm run check:full` (`total elapsed 603s exit 0`) ran on the earlier
|
|
377
|
+
frozen seal (`git diff --cached --binary | sha256sum` =
|
|
378
|
+
`ee478d4eac77aae6db187eeb5da2d357ab275c00e6d1eb9463ca04f29bf42425`), before this paragraph and two
|
|
379
|
+
documentation lines were amended; they are not re-attributed to the amended bytes. When this
|
|
380
|
+
paragraph was written (2026-09-23, before 09:44 KST) the LIVE release gate (`--cut`) had not been run
|
|
381
|
+
on this candidate, so this paragraph by itself does not speak to releasability; the LIVE receipt is
|
|
382
|
+
the dated addendum below, and it belongs to the `00264f…` seal only. What was measured:
|
|
383
|
+
|
|
384
|
+
- **Focused gates, green on the working candidate:** `check-dep-versions`
|
|
385
|
+
(`ok — pi 0.87.1 is coherent … 9 range + 1 exact + 3 prose declarations`), `check-gate-manifests`
|
|
386
|
+
(**782** committed mutants across 62 lanes, every `find` still matching its subject exactly once,
|
|
387
|
+
lane inventory matching its declared contract), `check-release-gate-outcomes`,
|
|
388
|
+
`smoke-meta-install-state`, `smoke-meta-keyset-guard`, `check-keyset-overlap` against the
|
|
389
|
+
operator's own agent-config fragment (exit 1 → exit 0, `keyset disjoint ok: 1 fragment vs 15
|
|
390
|
+
pi-owned key(s)`), `check-meta-doctor-oracle`, `check-meta-manifest-schema`, `smoke-meta-honesty`,
|
|
391
|
+
`smoke-setup-verdict`, `smoke-user-scope-citizen`, `smoke-meta-prune`, `check-pi-runtime-version`,
|
|
392
|
+
`check-pi-import-surface`, `check-model-lock`, `check-node-floor-coherence`, `check-pi-preflight`,
|
|
393
|
+
`check-pi-launch`, `check-pack-pin-matcher`, `check-pack` (540 files), `check-herdr-activation`,
|
|
394
|
+
`check-herdr-placement`, `check-pi-queue-oracle`, `check-entwurf-v2-surface`,
|
|
395
|
+
`check-control-send-receipt`, `check-compaction-send-guard`, `check-mux-launcher-fence`,
|
|
396
|
+
`check-codex-bridge-identity`, `check-codex-native-push`, `check-env-namespace`,
|
|
397
|
+
`check-shell-quote`, `check-tests-beside-behavior`, `check-install-surface`,
|
|
398
|
+
`smoke-agy-install-state`, `check-acp-sdk-surface`, `check-mux-fresh-call`. Three type fences
|
|
399
|
+
`tsc --noEmit` / `-p scripts` / `-p mcp` rc=0, and `pnpm lint` at 0 errors / 22 warnings — the
|
|
400
|
+
same counts a pristine HEAD produces, measured in its own snapshot for the comparison.
|
|
401
|
+
- **Four new mutants, each killed at its own claimed signature** in a scratch snapshot mirror with
|
|
402
|
+
control-pre and control-post green, because the shared checkout is never mutated in place:
|
|
403
|
+
`META-RETIRE-TURN-DURATION-OPERATOR-OWNED`, `CODEX-OPERATOR-PREREQ-ABSENT-SKIPS`,
|
|
404
|
+
`CODEX-OPERATOR-PREREQ-WRONG-FAILS`, `CODEX-OPERATOR-PREREQ-STATED-NOT-SEARCHED`. The
|
|
405
|
+
release-gate lane inventory moves 19 → 22 and meta-retire 3 → 4.
|
|
406
|
+
- **`check-install-surface` was re-run the only way it can tell the truth about an unstaged
|
|
407
|
+
edit, and that mattered.** It reads the candidate through `git show :<file>`, so a first run over
|
|
408
|
+
a working-tree-only change is a false green — a trap `NEXT.md` already documented from the
|
|
409
|
+
previous release. Two U+2014 em dashes had in fact landed in the ASCII-only release skill at
|
|
410
|
+
`(334,64)` and `(347,9)`. They are gone, and the proof was taken in a scratch snapshot where the
|
|
411
|
+
whole candidate was `git add -A`ed (**exit 0**, S7e and S6's 494 NUL-free sources included), with
|
|
412
|
+
a negative control planting one em dash back to confirm S7e really reddens rather than passing
|
|
413
|
+
vacuously. No staging was performed in the shared checkout.
|
|
414
|
+
- **Host receipts (operator-owned steps, run by the coordinator under GLG's authority and verified
|
|
415
|
+
independently here):** the retired-scalar migration applied with the operator's `true` intact and
|
|
416
|
+
the ledger entry consumed; `doctor-meta-bridge` PASS; the global pi CLI moved 0.87.0 → **0.87.1**
|
|
417
|
+
and this repo's installed `pi-coding-agent` reads **0.87.1**. The running pi coordinator process
|
|
418
|
+
may predate that upgrade, so it is not used as evidence for it — the versions above were read from
|
|
419
|
+
the CLI and the installed package.
|
|
420
|
+
|
|
421
|
+
**LIVE release gate on the amended candidate (2026-09-23 09:44–11:15 KST, host `oracle`) — dated
|
|
422
|
+
addendum.** Candidate seal: HEAD `61cde06755c1eb353c2338c314cdf1eed384b26e`, `git diff HEAD --binary |
|
|
423
|
+
sha256sum` = `git diff --cached --binary | sha256sum` =
|
|
424
|
+
`00264f9177cfc2fde16d468299f12a4d00abc8d54fad1fd3c6c70df06d56478f`, unstaged 0, untracked 0. The
|
|
425
|
+
coordinator's launcher refused to start unless HEAD and both seals matched, and printed them again
|
|
426
|
+
after the run: pre and post identical. That seal is the bytes with the D1/D2/O2 documentation
|
|
427
|
+
amendment above and WITHOUT this addendum; the result is not re-attributed to the documentation-only
|
|
428
|
+
seal that adds these lines. The 69a6f1d `FAIL=1` receipt and the `ee478d…` seal receipts above stay
|
|
429
|
+
as history.
|
|
430
|
+
|
|
431
|
+
- **Command:** `env -u CLAUDE_CONFIG_DIR -u PI_SESSION_ID -u PI_AGENT_ID LIVE=1
|
|
432
|
+
ENTWURF_CODEX_APP_SERVER_PID=3067196 ENTWURF_CODEX_FRESH_MODEL=gpt-5.6-luna
|
|
433
|
+
ENTWURF_CODEX_FRESH_PI_MODEL=openai-codex/gpt-5.6-terra ./run.sh release-gate
|
|
434
|
+
/tmp/entwurf-release-gate-0.25.0-00264f --cut`, exit 0. The app-server pid is the pane pid of the
|
|
435
|
+
one the coordinator started (on GLG's direct instruction) in its own tmux session
|
|
436
|
+
`entwurf025_codex_server`; it was stated, not searched. Its uid and exact `app-server --listen`
|
|
437
|
+
argv were checked through `/proc`, and its session differs from the gate's.
|
|
438
|
+
- **Log (cross-host artifact):** `/tmp/entwurf-release-gate-0.25.0-00264f/release-gate.log`, sha256
|
|
439
|
+
`100c61a5721dee3e693a5f6d4851138d52172ad5301a231431a10478237bf20d`. The decisive lines, verbatim:
|
|
440
|
+
|
|
441
|
+
```text
|
|
442
|
+
[check:full] total elapsed 621s exit 0
|
|
443
|
+
[gate-qualification] origin checkout: HEAD + work-surface content hash identical before/after
|
|
444
|
+
[gate-qualification] qualified claims: 782/782 killed — …
|
|
445
|
+
[gate-qualification] ok
|
|
446
|
+
[smoke-codex-fresh-live] 64 assertions ok — fixture -> initial visible Pi -> visible Codex/exact callback -> Pi-addressed native-push v2 -> Codex outbound v2 -> visible Pi/exact callback
|
|
447
|
+
MUST: PASS=24 FAIL=0 SKIP=0
|
|
448
|
+
BEHAVIOR: PASS=1 FAIL=0 SKIP=0
|
|
449
|
+
mode: --cut (a MUST SKIP is a BLOCKER — this run is being read as release acceptance)
|
|
450
|
+
cut: OK
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
- **Claude Code host:** `claude --version` = 2.1.280, which is above the `>=2.1.217` floor. Host
|
|
454
|
+
doctor log `/tmp/entwurf-0251-claude-280-doctor.log`, sha256
|
|
455
|
+
`568f73883a60025e370b5f45cba111620a60c45af351165bab25ddfa0d5be1e7`, exit 0, PASS.
|
|
456
|
+
- **P9, run right after the verdict:** the prefix-blind census found one reparented process holding
|
|
457
|
+
a `/tmp` path (pid 489788, the operator's own emacs). It is not gate residue and was left alone.
|
|
458
|
+
`OWNED` derived 107 prefixes. Idle roots older than 60 minutes: 3 (128K). Two were
|
|
459
|
+
`check-probe-ordering` and one `entwurf-s2b-overlay`; they were inspected, then removed. After P9,
|
|
460
|
+
the operator owned 592 directories under `/tmp`.
|
|
461
|
+
|
|
7
462
|
## 0.24.0 - 2026-09-20
|
|
8
463
|
|
|
9
464
|
### Added
|
package/DELIVERY.md
CHANGED
|
@@ -27,7 +27,7 @@ API. The levels compare capabilities, not implementation shapes.
|
|
|
27
27
|
|
|
28
28
|
| State | Meaning |
|
|
29
29
|
|---|---|
|
|
30
|
-
| `queued` | A
|
|
30
|
+
| `queued` | A receiver queue accepted the message; the backend may not have seen it. Durability is a property of the RAIL, not of this word — see the acceptance table below. |
|
|
31
31
|
| `triggered` | A supported event/API accepted the signal. |
|
|
32
32
|
| `woke` | An idle interactive session began a turn without user typing. |
|
|
33
33
|
| `injected` | The message reached model-visible context. |
|
|
@@ -36,6 +36,29 @@ API. The levels compare capabilities, not implementation shapes.
|
|
|
36
36
|
|
|
37
37
|
Avoid bare `delivered`; name the observed boundary.
|
|
38
38
|
|
|
39
|
+
### Control-socket acceptance boundaries (#120)
|
|
40
|
+
|
|
41
|
+
A control-socket send answers with ONE of these, and the sender renders that word rather than the
|
|
42
|
+
internal route it took. They are not four spellings of success: they differ on every axis an
|
|
43
|
+
operator has to reason about.
|
|
44
|
+
|
|
45
|
+
| Boundary | Order | Durability | Visibility | Rejection |
|
|
46
|
+
|---|---|---|---|---|
|
|
47
|
+
| `sent` | n/a — the receiver was idle and the turn was TRIGGERED directly | none needed; the turn started | the turn is running, but the model has NOT necessarily read the text yet, and nothing here says the turn completed | an in-band refusal is `rejected`, never this |
|
|
48
|
+
| `queued-steer` | drained after each turn; overtakes every `queued-follow-up` already waiting | **none** — volatile receiver process memory | nothing shows it: it is not in the TUI's pending-message count | an abort clears the queue and the message is gone, silently |
|
|
49
|
+
| `queued-follow-up` | drained only when the receiver's inner loop ends; a steer arriving later still goes first | **none** — volatile receiver process memory | same: invisible in the receiver's own queue display | same: an abort drops it |
|
|
50
|
+
| `accepted-unknown-boundary` | unknown | unknown | unknown | the receiver ACCEPTED; this names our inability to classify its answer (version skew), and it must never be retried or rendered as `sent` |
|
|
51
|
+
|
|
52
|
+
`[측정 2026-09-22, pi-agent-core 0.87.0; 재측정 2026-09-23, 0.87.1 — 좌표 동일]` `dist/agent.js:60-71,96-97,137-138`
|
|
53
|
+
(two independent `one-at-a-time` queues, no FIFO between them)
|
|
54
|
+
and `dist/agent-loop.js:85,186,191-197`
|
|
55
|
+
(steering drained every turn, follow-ups only once the inner loop ends).
|
|
56
|
+
|
|
57
|
+
The **meta-mailbox** rail is the contrast, not a fifth boundary: it writes a durable `*.msg` before
|
|
58
|
+
ringing any doorbell, its filenames are ISO stamps so a drain is a global FIFO, an undrained inbox
|
|
59
|
+
is an honest `mailbox-undeliverable` refusal, and its receipt is that FILE. A mailbox enqueue is a
|
|
60
|
+
durable file receipt; a control-socket queue is process memory.
|
|
61
|
+
|
|
39
62
|
## Levels (D0–D8)
|
|
40
63
|
|
|
41
64
|
These are independent of VERIFY's `L0–L5` evidence levels and BASELINE's question
|
package/README.md
CHANGED
|
@@ -254,7 +254,7 @@ cd ~/repos/gh/entwurf
|
|
|
254
254
|
|
|
255
255
|
The full source setup requires Node 24, pnpm, and Python 3 on PATH. Harnesses are
|
|
256
256
|
optional-by-presence: `setup` runs the frozen dependency install, then composes what the operator
|
|
257
|
-
already installed — a compatible `pi` (`>=0.
|
|
257
|
+
already installed — a compatible `pi` (`>=0.87.1 <0.88`), Claude Code, agy, and the Copilot CLI
|
|
258
258
|
each get their wiring completed when detected, an absent harness is an explicit zero-state SKIP,
|
|
259
259
|
and a detected harness that cannot be completed (including a below-floor `pi`) is a named FAIL
|
|
260
260
|
that makes setup exit nonzero. `setup` never installs a harness binary or touches a credential
|
|
@@ -288,7 +288,7 @@ This rail is CERTIFIED on Linux; on macOS it is NOT CERTIFIED — pending
|
|
|
288
288
|
physical host (control sockets, mux, ACP plugin hosting).
|
|
289
289
|
|
|
290
290
|
To use the `entwurf` provider inside pi, install a compatible pi binary
|
|
291
|
-
separately (`@earendil-works/pi-coding-agent >=0.
|
|
291
|
+
separately (`@earendil-works/pi-coding-agent >=0.87.1 <0.88`). Then point pi at
|
|
292
292
|
the npm-installed package or development clone:
|
|
293
293
|
|
|
294
294
|
```bash
|
package/VERIFY.md
CHANGED
|
@@ -132,6 +132,24 @@ that moved out of `scripts/` and into a file beside its subject would otherwise
|
|
|
132
132
|
> `LIVE=1 ENTWURF_CODEX_APP_SERVER_PID=<existing-app-server-pid>
|
|
133
133
|
> ENTWURF_CODEX_FRESH_MODEL=<codex-model>
|
|
134
134
|
> ENTWURF_CODEX_FRESH_PI_MODEL=<pi-model> ./run.sh smoke-codex-fresh-live`.
|
|
135
|
+
>
|
|
136
|
+
> Those three values are the step's operator-supplied prerequisite, and
|
|
137
|
+
> **`release-gate --cut` inherits that triple** — it is exported onto the aggregate invocation (the
|
|
138
|
+
> release skill's P5 carries it), never inferred by the gate, so the no-inference rule above holds
|
|
139
|
+
> unchanged inside the aggregate. **An ABSENT value is a protocol SKIP naming what was missing; a PRESENT but wrong one
|
|
140
|
+
> stays a FAIL.** That split is the honest reading of the step-outcome protocol — a step that never
|
|
141
|
+
> ran and a step that ran and broke are different facts — and it is what makes this MUST reproducible
|
|
142
|
+
> at every cut instead of inviting a standing exception: before 2026-09-23 all three were assertions, so their
|
|
143
|
+
> absence threw, and because the aggregate supplied none of them this step went red inside every
|
|
144
|
+
> cut on every host (0.25.0's candidate receipt, `MUST PASS=23 FAIL=1`, is that shape). A SKIP is
|
|
145
|
+
> **not** a softening: `--cut` refuses it as `cut: BLOCKED (MUST SKIP)`, so a cut without this
|
|
146
|
+
> receipt is still impossible — the operator supplies the triple and re-runs. A host with no Codex
|
|
147
|
+
> app-server therefore cannot take a cut, which is the intended cost of #87's release stop
|
|
148
|
+
> (「A visible-fresh receipt outside the MUST tier is no longer the general rule」above) rather than
|
|
149
|
+
> an accident. The installed-config preflights are deliberately NOT in that split and remain FAIL
|
|
150
|
+
> on absence — a missing Codex birth, user MCP/status/terminal-title config, runtime, bridge, tmux
|
|
151
|
+
> seat, or an unanswered launch directory is host state `setup` and the Codex doctors own, not a
|
|
152
|
+
> per-invocation input.
|
|
135
153
|
> **Both of THIS cell's live-spend defaults are `gpt-5.6-luna` from 2026-09-17**
|
|
136
154
|
> (`openai-codex/gpt-5.6-luna` on the pi side) — the Codex leg came down off `sol`. It is a tier
|
|
137
155
|
> choice and not a gate change; the receipt this cell is accepted on must be the one that actually
|
|
@@ -269,7 +287,7 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
269
287
|
**One install command to remember: `./run.sh setup <project>`.** It is idempotent — re-run the exact same command whenever anything looks wrong. There is no second install surface to juggle: from a clone `setup` runs the whole floor in order.
|
|
270
288
|
|
|
271
289
|
1. `pnpm install` — installs the pinned development dependencies and builds the bridge (source-checkout bootstrap only; an installed package never runs npm/pnpm inside `node_modules`)
|
|
272
|
-
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=0.
|
|
290
|
+
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=0.87.1 <0.88`) is on PATH; absent pi is an explicit zero-state SKIP, a below-floor pi is a detected FAIL. The user-scope entry is owner-recorded (#86 C2): another root's live-or-missing ownership makes this step a zero-write refusal (setup: pi FAIL) that names `takeover-user-scope`; the install-states bind the exact managed settings path (a drifted/symlinked/corrupt target is a zero-write refusal) and the inverse removes only the recorded owner's exact entry; `doctor-pi-package` reports the verdict
|
|
273
291
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
274
292
|
4. source stable-bin exposure — including certified `entwurf` → this checkout's `run.sh`, the managed runtime Copilot fresh resolves; helper units are attempted independently and a foreign helper is a named FAIL
|
|
275
293
|
5. agy bridge + exact permission + statusline + `PreInvocation` hook — only when `agy` is on PATH; each adapter is idempotent and independently doctorable
|
package/demo/README.md
CHANGED
|
@@ -46,7 +46,10 @@ a background driver types the scene prompts into the sender pane.
|
|
|
46
46
|
1. **Spawn** a sonnet sibling (memory write — "tempered indigo").
|
|
47
47
|
2. **Resume** that same sibling (memory recall — identity preservation,
|
|
48
48
|
the #9 regression guard).
|
|
49
|
-
3. **Cross-session greeting** via `entwurf_send
|
|
49
|
+
3. **Cross-session greeting** via `entwurf_send`. *(Historical: `entwurf_send` was retired in the
|
|
50
|
+
0.12 cutover, and the "sent box" half of that pairing was never actually reachable — the
|
|
51
|
+
sender-side renderer had zero producers and was removed in #120 P3. What the recording shows on
|
|
52
|
+
the receive side is real; the send side is a box the operator could not have seen.)*
|
|
50
53
|
|
|
51
54
|
Run:
|
|
52
55
|
|
|
@@ -139,7 +142,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
|
|
|
139
142
|
|
|
140
143
|
## Prerequisites
|
|
141
144
|
|
|
142
|
-
- `pi` on PATH (current floor 0.
|
|
145
|
+
- `pi` on PATH (current floor 0.87.1)
|
|
143
146
|
- `entwurf` provider configured + auth ready for the selected sender/peer models
|
|
144
147
|
- `asciinema` installed
|
|
145
148
|
- `agg` installed (optional — only for GIF conversion)
|