@junghanacs/entwurf 0.41.0 → 0.41.1
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 +241 -0
- package/README.md +53 -56
- package/VERIFY.md +1 -1
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +1 -1
- package/docs/setup-clean-host.md +52 -12
- package/package.json +12 -11
- package/pi/pi-durable/carrier/tui.js +18 -3
- package/pi/pi-durable/overlay/upstream-pin.json +12 -12
- package/pi-extensions/lib/acp/backend-adapter.ts +5 -3
- package/pi-extensions/lib/acp/backend.ts +12 -9
- package/pi-extensions/meta-bridge-pi-durable.ts +1 -1
- package/run.sh +45 -27
- package/scripts/check-gate-qualification.ts +1 -1
- package/scripts/lib/codex-fresh-live-protocol.ts +3 -2
- package/scripts/mutants/control-send-receipt.json +1 -1
- package/scripts/mutants/pack-install.json +4 -4
- package/scripts/mutants/pi-durable.json +60 -0
- package/scripts/mutants/pi-floor.json +5 -5
- package/scripts/smoke-codex-fresh-live.ts +2 -1
- package/scripts/smoke-herdr-raw-install-live.sh +10 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,247 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.41.1 — 2026-10-23
|
|
8
|
+
|
|
9
|
+
**Unpublished candidate; release acceptance is not complete.** The actual operator
|
|
10
|
+
transition and Native aggregate below have been measured. Final prepared-SHA CI and
|
|
11
|
+
the requested manual BODY, the exact carrier-bearing artifact, main promotion, tags
|
|
12
|
+
and publication remain separate gates. Main still carries the published 0.41.0 Herdr
|
|
13
|
+
lock: promoting the checkout lock can change what main-tracking installations acquire.
|
|
14
|
+
A validation artifact or an earlier checkpoint's green run is not final acceptance.
|
|
15
|
+
|
|
16
|
+
### Pi 1.4.0 reference shell
|
|
17
|
+
|
|
18
|
+
- Move the coherent nine-member production SDK set from exact 1.3.0 to exact 1.4.0,
|
|
19
|
+
keeping Entwurf's owned app/TUI composition and deterministic carrier emission.
|
|
20
|
+
The SDK owns execution, storage, queues, compaction and recovery; this adds no second
|
|
21
|
+
engine, supervisor, automatic retry policy or credential surface. The ordinary Pi
|
|
22
|
+
adapter's supported range becomes `>=1.4.0 <1.5`.
|
|
23
|
+
- Show sleeping tasks in the background-task tally, their local wake time in the task
|
|
24
|
+
panel, and the SDK's blocked reason verbatim. Keep cancellation distinct from retry;
|
|
25
|
+
no new retry command or UI is added.
|
|
26
|
+
- Adapt the ACP vendor-rejection test to pi-ai 1.4's bounded HTTP-status matching:
|
|
27
|
+
digits inside opaque request/tool ids no longer classify as transient. The raw
|
|
28
|
+
`Internal error` control remains transient. The production non-replay verdict and
|
|
29
|
+
raw diagnostic preservation are unchanged.
|
|
30
|
+
- Add SDK 1.3 public-API-generated SQL fixtures and independent SQLite conformance
|
|
31
|
+
tests for the SDK 1.4 schema transition, row/index preservation, constraints,
|
|
32
|
+
reopening and future-version refusal. These are SDK conformance, not a local
|
|
33
|
+
mutation claim over the upstream engine. Keep fixture data and its generator out
|
|
34
|
+
of installed packages, with npm packlist and tarball-floor checks.
|
|
35
|
+
- Separate this unpublished candidate's checkout instructions from public npm
|
|
36
|
+
0.41.0 / SDK 1.3 instructions. The Herdr lock uses the closed `herdr-checkout`
|
|
37
|
+
verification carrier; it invents no unpublished npm integrity. No new Herdr
|
|
38
|
+
snapshot or registry publication is implied.
|
|
39
|
+
- Keep the Codex LIVE fixture callback-only on its outbound Pi leg. Asking for an
|
|
40
|
+
extra ACK created a fourth real tool call while the audit required three. The
|
|
41
|
+
exact-three, nonce and terminal-turn assertions remain unchanged; only the two
|
|
42
|
+
matching task strings changed, not production routing or retry behavior.
|
|
43
|
+
- Trim historical platform details, dated labels and duplicated lifecycle prose
|
|
44
|
+
from the README while retaining operator consent, unknown-outcome handling,
|
|
45
|
+
platform limits and the published-versus-candidate install distinction.
|
|
46
|
+
|
|
47
|
+
### Upgrade boundary
|
|
48
|
+
|
|
49
|
+
Opening each existing durable session with SDK 1.4 migrates its SQLite storage to
|
|
50
|
+
schema 2. SDK 1.3 / Entwurf 0.41.0 refuses that session. Reinstalling the older package
|
|
51
|
+
is not data rollback: restoring a pre-upgrade backup reopens the old data, but omits
|
|
52
|
+
work done after that backup. Database restoration does not undo external messages,
|
|
53
|
+
tool/file/network effects, meta records or mailbox read receipts. Preserve the newer
|
|
54
|
+
set and inspect unknown outcomes before considering a restore or resend.
|
|
55
|
+
Even a refused SDK 1.4 open can change the file header
|
|
56
|
+
and sidecars while preserving logical rows (measured on a future-schema copy). Back up the complete target session
|
|
57
|
+
file set before its first new-SDK open.
|
|
58
|
+
|
|
59
|
+
Close the old owner normally and prove the process has exited before cutover. A
|
|
60
|
+
stale lock is not proof: a bounded, SQLite-free fixture reproduced a stalled but live
|
|
61
|
+
owner losing its lock. This lock behavior already existed in 0.41.0. Use the resume
|
|
62
|
+
picker to select the intended session rather than guessing with `--continue`.
|
|
63
|
+
|
|
64
|
+
SDK 1.4 counts a task SDK 1.3 left running as an interrupted run at its first open;
|
|
65
|
+
SDK 1.4's own normal close does not add a restart. Repeated interruptions can park a
|
|
66
|
+
task at the restart limit. Inspect outcomes before any resend; cancellation is not
|
|
67
|
+
retry, and recovery of an actual parked model generation remains unmeasured.
|
|
68
|
+
|
|
69
|
+
### Preparation and operating evidence — not final release acceptance
|
|
70
|
+
|
|
71
|
+
Implementation checkpoint `3ed079b` follows independent source/proof reviews. Its
|
|
72
|
+
earlier working candidate passed the deterministic FULL floor in 885 seconds with
|
|
73
|
+
source/index unchanged, carrier 45 tests, storage conformance 11 tests, and ACP
|
|
74
|
+
vendor rejection 14 tests. The final pre-commit vocabulary sweep then changed one
|
|
75
|
+
harness-table SDK literal into a reference to the pin authority, independently read
|
|
76
|
+
and checked. These are implementation-era observations, not this prepared version's
|
|
77
|
+
FULL, native LIVE, installed artifact, operating-session migration or exact-SHA CI.
|
|
78
|
+
|
|
79
|
+
Private sandbox observations separately cover old-package refusal, backup restoration
|
|
80
|
+
and loss of later marker work, SDK task replay/parking, candidate shell open/close,
|
|
81
|
+
SDK 1.3-born fixture identity carried into the SDK 1.4 shell, and in-process open
|
|
82
|
+
failure releasing the session lock. Parked non-generation Hold tasks did not block
|
|
83
|
+
root input; conversation abort cancelled only the non-background Hold. None proves
|
|
84
|
+
real model-generation continuity or an operating citizen's actual upgrade.
|
|
85
|
+
|
|
86
|
+
Kill-power re-measured at this shipped SHA: none (all 1178 committed claims not
|
|
87
|
+
re-proved, #144).
|
|
88
|
+
|
|
89
|
+
That required line records the source's preparation-time measurement state, not a
|
|
90
|
+
prediction of later CI. GLG separately requested manual BODY evidence. The earlier
|
|
91
|
+
validation SHA `ff86c88bd58ba776e15ef48e1e4be566971a3e9a` has a four-job green push run
|
|
92
|
+
[39790950791](https://github.com/junghan0611/entwurf/actions/runs/39790950791) and a
|
|
93
|
+
separate `workflow_dispatch qualify=true` run
|
|
94
|
+
[39792701159](https://github.com/junghan0611/entwurf/actions/runs/39792701159): 85 lanes,
|
|
95
|
+
1178 unique claims KILLED, survived/error/skipped 0. Those are that SHA's receipts,
|
|
96
|
+
not this later prepared SHA's. Its requested exact-SHA CI/BODY results must be recorded
|
|
97
|
+
separately in [#148's live evidence thread](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6348113761);
|
|
98
|
+
no future result is invented here and the standing release policy is unchanged.
|
|
99
|
+
|
|
100
|
+
Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
|
|
101
|
+
6a9481bc357c -- `["bash","run.sh","check-dep-versions"]` 4/4 receipt 48d085e06816.
|
|
102
|
+
|
|
103
|
+
Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
|
|
104
|
+
6a9481bc357c -- `["bash","run.sh","check-pack-pin-matcher"]` 2/2 receipt 593dd0401502.
|
|
105
|
+
|
|
106
|
+
Earlier-candidate PARTIAL (operator-attested, not this SHA): head addcb8cd0bac surface
|
|
107
|
+
6a9481bc357c -- `["bash","run.sh","check-pi-durable-carrier"]` 35/35 receipt 258f783406a7.
|
|
108
|
+
|
|
109
|
+
Earlier-candidate PARTIAL (operator-attested, not this SHA): head ff86c88bd58b surface
|
|
110
|
+
7c75301f53a9 -- `["bash","run.sh","check-release-gate-outcomes"]` 21/21 receipt 251b71584442.
|
|
111
|
+
|
|
112
|
+
Earlier-candidate PARTIAL (operator-attested, not this SHA): head ff86c88bd58b surface
|
|
113
|
+
7c75301f53a9 -- `["bash","run.sh","check-mux-fresh-call"]` 150/150 receipt 56c3558f9a15.
|
|
114
|
+
|
|
115
|
+
Both ff86c88 PARTIAL receipts were taken with the Codex fixture correction still
|
|
116
|
+
uncommitted on that head, on the recorded working surface.
|
|
117
|
+
|
|
118
|
+
The versioned working candidate's earlier FULL completed in 890 seconds, exit 0,
|
|
119
|
+
with source/index unchanged (log SHA256 `757115f291c05f397631f6e8de48a2b77fdfde973d5219edf70e63658c3b8e88`).
|
|
120
|
+
It predates later checkpoint metadata and is not a final committed-SHA CI result.
|
|
121
|
+
|
|
122
|
+
**Actual operator transition:** after the human closed the original owners and their
|
|
123
|
+
exit was proven with the scheme-aware owner classifier, the complete session file
|
|
124
|
+
set was consistently backed up without opening SQLite. The exact Linux validation
|
|
125
|
+
tarball (`92e5b2722ab8063d2bc50936db358a36a02a5e92e36babc3e1fbf98b399c2f44`)
|
|
126
|
+
was accepted unchanged in a container, separately exercised through an isolated pnpm
|
|
127
|
+
global old-to-new takeover, then installed as the operator's 0.41.1/SDK 1.4 runtime.
|
|
128
|
+
User-scope extension loading and doctors passed. The coordinator resumed the actual
|
|
129
|
+
old conversation: garden/native/createdAt/cwd stayed unchanged, a new owner attached,
|
|
130
|
+
a real model turn recalled the pre-close agreement and used tools, and four
|
|
131
|
+
send/read/reply/read receipts closed a round trip with an existing Claude Code sibling.
|
|
132
|
+
The human-reopened Pi reviewer also confirmed its identity, model, tools and recall.
|
|
133
|
+
No separate live DB query or universal transcript/parked-generation recovery claim is
|
|
134
|
+
made. This addon-less Linux validation tarball is not the carrier-bearing release file.
|
|
135
|
+
|
|
136
|
+
**Native aggregate:** the first run at `ff86c88` was MUST 23/1/0 and BEHAVIOR 1/0/0:
|
|
137
|
+
the extra requested ACK was a fourth distinct call, not parser duplication. Its raw
|
|
138
|
+
failure is preserved. After the scoped fixture correction, an affected fresh Codex
|
|
139
|
+
run passed 66 assertions with both terminal audits exactly 3/3. The new full run at
|
|
140
|
+
`a9d05847295230ed58f53b0bfd689d9ebd6ac1da` then passed **MUST 24/0/0,
|
|
141
|
+
BEHAVIOR 1/0/0**, including the deterministic FULL; source/index stayed unchanged.
|
|
142
|
+
The operator still used the **ff86c88 validation install**, not an installed a9d0584
|
|
143
|
+
artifact. Its runtime closure (bridge dist, pi-durable carrier, bootstrap and resolver)
|
|
144
|
+
was byte-identical to the checkout before and after the run; README and LIVE fixture
|
|
145
|
+
bytes differ. This is checkout-gate evidence with that installed runtime, not a claim
|
|
146
|
+
that the complete a9d0584 package was installed or accepted.
|
|
147
|
+
Scratch `/tmp/entwurf-release-gate-0.41.1-r2.cl0DDR`, log `release-gate.log`, SHA256
|
|
148
|
+
`020f489bf6fe024447bfc26a12f3499e5b80e844b0dcadf1e474e6adc8b4ae05`.
|
|
149
|
+
P9 was a read-only census: root 4.9 GiB and home 6.9 GiB free, with the existing
|
|
150
|
+
Emacs infrastructure identified rather than killed; current receipts and scratch
|
|
151
|
+
were preserved. Only the explicitly owned test app-server was normally stopped.
|
|
152
|
+
|
|
153
|
+
The final prepared-SHA push CI/manual BODY and Win32-bearing artifact acceptance
|
|
154
|
+
are still pending. The validation tarball has no Win32 addon; it cannot stand for
|
|
155
|
+
M3w or final macOS/Windows acceptance. No tag, GitHub release, npm publication,
|
|
156
|
+
Herdr re-pin or laptop rollout has occurred. Earlier 0.41.0 receipts below remain
|
|
157
|
+
historical.
|
|
158
|
+
|
|
159
|
+
## v2026.10.22-herdr.0.41.0 — Herdr Entwurf plugin 0.41.0
|
|
160
|
+
|
|
161
|
+
A separate Herdr plugin snapshot, not another core release: core package 0.41.0 and its
|
|
162
|
+
`v0.41.0` tag remain unchanged. Core 0.41.0 is now published to npm; the publication is
|
|
163
|
+
verified from the registry, not from observing who ran it.
|
|
164
|
+
|
|
165
|
+
**Reading guide (2026-10-22).** The `## 0.41.0` section below and the body of the
|
|
166
|
+
[v0.41.0 GitHub release](https://github.com/junghan0611/entwurf/releases/tag/v0.41.0) are
|
|
167
|
+
prepare-time and make-time text: their npm wording (the Herdr lock's "unpublished candidate",
|
|
168
|
+
"npm publication each need their own approval") predates the publication. The publish is the later registry fact recorded in this section (`latest` 0.41.0,
|
|
169
|
+
published 2026-10-22T04:37:02.853Z, registry bytes equal to the accepted candidate). Neither the
|
|
170
|
+
published tarball's CHANGELOG nor the core release page is amended by this snapshot.
|
|
171
|
+
|
|
172
|
+
### Herdr plugin
|
|
173
|
+
|
|
174
|
+
- **Re-pin the published core 0.41.0 and close the checkout window.**
|
|
175
|
+
`plugins/herdr/runtime-lock.json` returns from the `herdr-checkout` carrier that core 0.41.0
|
|
176
|
+
rode to production npm source `@junghanacs/entwurf@0.41.0` with the registry's measured
|
|
177
|
+
sha512 (`sha512-hSf6St0u…fBlvA==`). The plugin manifest moves 0.40.0 → 0.41.0; admission
|
|
178
|
+
remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged. From the
|
|
179
|
+
`v2026.10.20-herdr.0.40.0` snapshot to `v0.41.0`, the changes under `plugins/herdr/`,
|
|
180
|
+
`scripts/herdr-runtime.mjs` and `scripts/fixtures/herdr-supply.json` were that lock's return
|
|
181
|
+
to `herdr-checkout` and the plugin README's resume/retire wording; the runtime helper and the
|
|
182
|
+
Herdr supply pin did not change.
|
|
183
|
+
- **What the acquired runtime now carries.** Core 0.41.0's lifecycle verbs ride in the runtime's
|
|
184
|
+
bytes: its installed bridge lists nine tools, `entwurf_retire_call` among them. Inside Herdr,
|
|
185
|
+
`entwurf_resume_call` still refuses as `herdr-resume-unsupported`. This snapshot measures no
|
|
186
|
+
retirement or resume through Herdr.
|
|
187
|
+
- **Pi range unchanged.** The acquired runtime still accepts Pi `>=1.3.0 <1.4`; core 0.41.0
|
|
188
|
+
keeps the Pi 1.3.0 SDK set.
|
|
189
|
+
- **Upgrade by acquisition source, not just version.** A settled npm-source 0.40.0 installation
|
|
190
|
+
can rebind under the plugin README's ownership conditions. A host that installed an
|
|
191
|
+
intervening `herdr-checkout` candidate must explicitly deactivate by its own absolute runtime
|
|
192
|
+
path before reinstalling the npm-source snapshot. No operator installation or active session
|
|
193
|
+
is rewired by this release work.
|
|
194
|
+
- **README.** The first-user-path receipt description no longer says the installed
|
|
195
|
+
`check-bridge` lists an eight-verb set; it names the verb set the installed bridge declares,
|
|
196
|
+
nine since 0.41.0.
|
|
197
|
+
- **Raw-install smoke scaffolding follows the Claude Code floor.** The first public-ref run of
|
|
198
|
+
`smoke-herdr-raw-install-live` at `cfdae0e` built its container with Claude Code 2.1.278, a
|
|
199
|
+
hand-kept pin from 2026-09-19, and the acquired 0.41.0 runtime refused to wire Claude below its
|
|
200
|
+
supported floor `>= 2.1.306` — the product's intended refusal, not a runtime defect. The smoke now
|
|
201
|
+
derives its exact Claude Code version from `package.json` `entwurf.claudeCodeFloor` instead of
|
|
202
|
+
retyping it. The product floor, the Pi, Herdr and Node pins and the smoke's end-state oracle are
|
|
203
|
+
unchanged.
|
|
204
|
+
|
|
205
|
+
### Source-specific verification
|
|
206
|
+
|
|
207
|
+
- Registry metadata reports `latest` 0.41.0 and `repair` 0.12.8-repair.1, 642 files, published
|
|
208
|
+
2026-10-22T04:37:02.853Z. The downloaded registry tarball is byte-equal to the preserved
|
|
209
|
+
accepted core candidate (SHA256 `2bd03ba900324a7c0882c2738c29593df0a1e4829fb3ae18d22be62186cf67ad`,
|
|
210
|
+
11399545 bytes); its independently computed sha512 and sha1 equal `dist.integrity` and
|
|
211
|
+
`dist.shasum`, so core make's Docker consumer of those bytes (`node:24-bookworm`, repoDigest
|
|
212
|
+
`node@sha256:6dac556d…`) is reused here, not repeated. A sandboxed `pi install` of the
|
|
213
|
+
registry package resolved its bridge inside the sandbox, recorded the registry URL with that
|
|
214
|
+
integrity, and listed the curated Claude anchors with `--list-models entwurf`; a sandboxed
|
|
215
|
+
global npm install of the same package passed its installed `check-bridge` with nine tools.
|
|
216
|
+
No model turn. The accepted run stripped every `PI_`, `ENTWURF_`, `CLAUDE`, `CODEX_HOME`,
|
|
217
|
+
`TMUX` and `HERDR_` carrier and ran on the branch worktree, whose only checkout input (the
|
|
218
|
+
bridge resolver script) is unchanged; an earlier run from the clean tag HEAD left `TMUX` and
|
|
219
|
+
non-identity `PI_*` variables set and is kept only as a preliminary record.
|
|
220
|
+
- **The npm runtime swap against the real registry**, by the registry-shipped
|
|
221
|
+
`scripts/herdr-runtime.mjs` (byte-equal to this checkout's) in sandboxed user roots, 22/22
|
|
222
|
+
checks. The 0.40.0 runtime was seeded from its own committed lock (`036e268`); the swap to
|
|
223
|
+
0.41.0 took one acquisition, the cached tarball's sha512 equals the lock and its sha256 equals
|
|
224
|
+
both the ready journal's observed digest and the accepted candidate. The `installing` journal
|
|
225
|
+
carried the 0.40.0 identity as `previousRuntime` and the `runtime-ready` journal carries
|
|
226
|
+
`null`; when acquisition began the 0.40.0 tree was still at the active address. A manually
|
|
227
|
+
seeded torn swap (the active tree moved to the backup address with a half candidate in
|
|
228
|
+
staging; not a killed process) was restored before acquisition and reported `recovered:
|
|
229
|
+
torn-swap-with-candidate`. An exact re-request acquired nothing and left journal and tree
|
|
230
|
+
byte-identical, and the owned removal reclaimed cache, runtime and journal. The helper is a
|
|
231
|
+
leaf that probes no Pi, so these cells certify neither a Pi upgrade nor Herdr's
|
|
232
|
+
install/update relocation, harness wiring, the installed CLI's deactivate path, a model turn,
|
|
233
|
+
or recovery from a real kill.
|
|
234
|
+
- **Focused gates on the branch**, with HEAD, index and work surface unchanged across them:
|
|
235
|
+
`check-herdr-supply` (11 assertions), `check-herdr-plugin` (49),
|
|
236
|
+
`check-herdr-plugin-profile` (14), `check-herdr-runtime-bootstrap` (31),
|
|
237
|
+
`check-herdr-activation` (33), `check-herdr-placement` (25), `check-herdr-fresh-call` (45),
|
|
238
|
+
`check-herdr-plugin-build` (21, its real-binary cell on herdr 0.9.5), `check-herdr-sandbox`
|
|
239
|
+
(12, a private herdr 0.9.5 server), `check-dep-versions`, `check-install-surface` and
|
|
240
|
+
`check-gate-manifests` (1173 committed mutants across 85 lanes validated, none executed).
|
|
241
|
+
- Pending, and not claimed here: the pushed SHA's four-job CI and the public-ref
|
|
242
|
+
install/use/deactivate journey of this npm pin, on Herdr 0.9.5 (the binary
|
|
243
|
+
`scripts/fixtures/herdr-supply.json` names) with Pi 1.3.0, from the public `main` ref rather
|
|
244
|
+
than the tag. Earlier npm or checkout-carrier receipts cannot certify these source-specific
|
|
245
|
+
axes. Those outcomes are recorded in the snapshot's post-push acceptance ledger, not in this
|
|
246
|
+
frozen text.
|
|
247
|
+
|
|
7
248
|
## 0.41.0 - 2026-10-22
|
|
8
249
|
|
|
9
250
|
A sibling's garden id is its birthday, and this cut lets it rest and come back under it. A
|
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Git branches, worktrees, file isolation and internal delegation remain their con
|
|
|
27
27
|
|---|---|---|---|
|
|
28
28
|
| **Open** a new sibling | `entwurf_fresh_call` | Herdr: a new unfocused tab in the caller's workspace. tmux: a new window in the caller's session, or an existing session named by `placement.tmuxSession`; without an explicit tmux placement, a Codex caller opens beside its own TUI pane | Herdr: pi, Claude Code. tmux: pi, pi-durable, Claude Code, Copilot, OMP, Codex |
|
|
29
29
|
| **Reopen** a dormant sibling | `entwurf_resume_call` | A visible tmux window under the same garden id, with its record selecting the native session (Pi: identity-checked recorded transcript supplies launch metadata; Claude Code: `claude --resume <session id>` at the record cwd); the verb submits no prompt | pi, Claude Code |
|
|
30
|
-
| **Retire** one sibling the human operator explicitly requested
|
|
30
|
+
| **Retire** one sibling the human operator explicitly requested | `entwurf_retire_call` | One guarded attempt on that target: a Pi shutdown request or Claude Code fd-pinned process termination. Refused/unknown outcomes remain possible; the record stays for guarded same-id return. Not a grant, a roster cleanup or an automatic retry | pi, Claude Code |
|
|
31
31
|
| **Message** an existing sibling | `entwurf_v2` | Its own rail: control socket, self-fetch mailbox or native push; delivery starts no process | pi, pi-durable, Claude Code, Copilot, OMP, Antigravity, Codex |
|
|
32
32
|
|
|
33
33
|
Antigravity is message-only: an existing conversation registers itself, and Entwurf never
|
|
@@ -54,15 +54,26 @@ ownership of the harness.
|
|
|
54
54
|
|
|
55
55
|
Prerequisites: **Node >=24.0.0**, Python 3 for `setup`, and any harnesses you choose
|
|
56
56
|
to use, already installed and authenticated. Pi is optional-by-presence, supported
|
|
57
|
-
range `>=1.
|
|
57
|
+
range `>=1.4.0 <1.5`; Claude Code supported floor `>=2.1.306` is required for its
|
|
58
58
|
managed exec-hook lifecycle. pnpm is needed only for source-checkout setup.
|
|
59
59
|
|
|
60
|
+
**Release state.** The Pi range above belongs to this source candidate, which moves the Pi SDK
|
|
61
|
+
set to 1.4.0 and is **not published to npm yet**. The newest published package, `0.41.0`,
|
|
62
|
+
ships the Pi 1.3.0 SDK set and requires Pi 1.3.x; the README inside that tarball and the Herdr
|
|
63
|
+
snapshot `v2026.10.22-herdr.0.41.0` are its contract. Pick the path that matches the Pi you run.
|
|
64
|
+
|
|
65
|
+
The published package (Pi 1.3.x):
|
|
66
|
+
|
|
60
67
|
```bash
|
|
61
|
-
npm install -g @junghanacs/entwurf
|
|
68
|
+
npm install -g @junghanacs/entwurf@0.41.0
|
|
62
69
|
entwurf setup /path/to/your-project
|
|
63
70
|
entwurf check-bridge
|
|
64
71
|
```
|
|
65
72
|
|
|
73
|
+
This candidate (Pi 1.4): a source checkout of this commit, set up with `./run.sh setup` as
|
|
74
|
+
[Clean-host setup](./docs/setup-clean-host.md) describes. It has no npm install command until it
|
|
75
|
+
is released.
|
|
76
|
+
|
|
66
77
|
`setup` composes each harness it finds and reports PASS / SKIP / FAIL. An absent
|
|
67
78
|
harness is an explicit SKIP; a detected incomplete/below-floor integration is a
|
|
68
79
|
named FAIL with nonzero exit, not a false green. `check-bridge` proves the installed
|
|
@@ -76,27 +87,18 @@ consent: [the operator steps](./docs/setup-clean-host.md#three-operator-decision
|
|
|
76
87
|
Plain MCP registration alone does not make a garden citizen.
|
|
77
88
|
|
|
78
89
|
**Platform bounds:** Linux is the certified harness-rail axis. macOS Entwurf-only
|
|
79
|
-
installation is **CERTIFIED (CI)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
0.39.0 (published to npm); 0.38.1 and earlier carry no Windows addon. On a GitHub Actions
|
|
87
|
-
`windows-2025` x64 runner with Node 24.18.1 and Pi 1.3.0, a CI-built artifact was installed,
|
|
88
|
-
wired with `pi install`, birthed two Pi citizens and
|
|
89
|
-
delivered one garden-id `entwurf_v2` message between them, with an offline scripted model
|
|
90
|
-
and no vendor turn. Every other native-Windows surface (other harnesses, `setup` and the
|
|
91
|
-
`.sh` bins, fresh/resume, mux/Herdr/ACP, physical machines) is **not declared**; the
|
|
92
|
-
measured scope and its named gaps are in [BASELINE](./BASELINE.md#release-host-baseline).
|
|
93
|
-
The package has no npm `os` restriction; that is not certification of every platform's
|
|
94
|
-
harness rails.
|
|
90
|
+
installation is **CERTIFIED (CI)**; native harness rails, ACP and mux remain
|
|
91
|
+
**NOT CERTIFIED — pending physical host**, so detected wiring can still leave setup non-green.
|
|
92
|
+
WSL2 and native Windows have **experimental CI previews**, not general or physical-host support.
|
|
93
|
+
The native-Windows preview covers Pi citizens and offline scripted delivery, not vendor turns,
|
|
94
|
+
other harnesses, shell entrypoints, fresh/resume, mux, Herdr or ACP.
|
|
95
|
+
[BASELINE](./BASELINE.md#release-host-baseline) owns the version-specific receipts and gaps;
|
|
96
|
+
an npm package without an `os` restriction is not an all-platform certification.
|
|
95
97
|
|
|
96
98
|
### Native durable (pi-durable)
|
|
97
99
|
|
|
98
|
-
**
|
|
99
|
-
members
|
|
100
|
+
**This candidate's package supplies Entwurf's owned app/TUI carrier and nine exact Pi 1.4.0 SDK
|
|
101
|
+
members** (unpublished; the published 0.41.0 supplies the 1.3.0 set). No separate runtime checkout, patch, build or ordinary Pi CLI is needed.
|
|
100
102
|
The launch verifies carrier integrity and every reachable SDK edge's name/version;
|
|
101
103
|
incomplete, drifted or mixed supply refuses by name.
|
|
102
104
|
|
|
@@ -106,7 +108,7 @@ entwurf pi-durable --continue
|
|
|
106
108
|
entwurf pi-durable --resume
|
|
107
109
|
```
|
|
108
110
|
|
|
109
|
-
`--continue` opens this directory's
|
|
111
|
+
`--continue` opens this directory's latest-created durable session. `--resume` lists its
|
|
110
112
|
sessions, most recently written first, by creation time, garden id and last write, and
|
|
111
113
|
reopens the one you choose as it was saved; a cancelled choice opens nothing.
|
|
112
114
|
|
|
@@ -117,20 +119,23 @@ SQLite, transcripts and recovery remain the upstream SDK's:
|
|
|
117
119
|
|
|
118
120
|
Optional `--native-module <absolute file>` initializes trusted ESM before runtime/TUI
|
|
119
121
|
imports, then installs its default native Extension after the contact.
|
|
120
|
-
`--native-module-dir <absolute directory>`
|
|
121
|
-
|
|
122
|
-
background-task badge on screen at any terminal size. No automatic module discovery or
|
|
122
|
+
`--native-module-dir <absolute directory>` loads that named directory's top-level
|
|
123
|
+
`*.extension.mjs` files in byte-wise order instead. No automatic module discovery or
|
|
123
124
|
classic Pi API shim; guards are not a sandbox or rollback.
|
|
124
|
-
Ordinary Pi's known `peerDependencies` warning reflects the separate native SDK supply.
|
|
125
125
|
[Native setup](./docs/setup-clean-host.md#2b-optional-native-durable-pi-durable)
|
|
126
126
|
owns flags, refusals and the extension contract.
|
|
127
127
|
|
|
128
128
|
### Herdr workbench
|
|
129
129
|
|
|
130
130
|
```bash
|
|
131
|
-
herdr plugin install junghan0611/entwurf/plugins/herdr --yes
|
|
131
|
+
herdr plugin install junghan0611/entwurf/plugins/herdr --ref "$CANDIDATE_REF" --yes
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
Set `CANDIDATE_REF` explicitly to a published branch or tag that carries the runtime you mean;
|
|
135
|
+
these examples do not select a candidate from Herdr's default ref. A validation branch is not a
|
|
136
|
+
release acceptance. The [Herdr guide](./plugins/herdr/README.md#from-a-raw-linux-box-in-nine-steps)
|
|
137
|
+
says which runtime each ref installs.
|
|
138
|
+
|
|
134
139
|
This separate path activates Herdr-integrated **pi and Claude Code** with an
|
|
135
140
|
independently locked runtime and an observation pane; it puts no Entwurf bins on PATH.
|
|
136
141
|
An Entwurf release does not automatically re-pin that runtime.
|
|
@@ -169,7 +174,7 @@ In that **harness session**, ask the agent to:
|
|
|
169
174
|
```
|
|
170
175
|
|
|
171
176
|
These are tools, not shell subcommands. Pi calls
|
|
172
|
-
`mcp__entwurf_bridge__<verb>` through Pi's built-in MCP. The
|
|
177
|
+
`mcp__entwurf_bridge__<verb>` through Pi's built-in MCP. The bridge exposes **nine**
|
|
173
178
|
verbs; a pi citizen has **seven active + two hidden** (`entwurf_inbox_read` and
|
|
174
179
|
`entwurf_register_native`), since it has no mailbox and its own extension births it.
|
|
175
180
|
Those counts describe the source; a running host offers what its already-loaded bridge
|
|
@@ -199,9 +204,15 @@ pi / pi-durable / Claude Code / Copilot / OMP / Antigravity / Codex
|
|
|
199
204
|
| Message, reply or hand off to an existing garden id | `entwurf_v2 {target, intent:"fire-and-forget", message}` | Receiver acceptance boundary, mailbox enqueue or native injection; not completion |
|
|
200
205
|
| Open a new visible sibling | `entwurf_fresh_call {backend, model, task, cwd?}` | Launch receipt only; the sibling's nonce callback envelope supplies its new garden id |
|
|
201
206
|
| Reopen a dormant pi or Claude Code citizen under its own id | `entwurf_resume_call {target}` | Separate LAUNCH and OBSERVATION receipts (pi: same-id socket; Claude Code: a new live receiver marker in the opened pane, bound to the record); the verb submits no prompt |
|
|
202
|
-
| Attempt retirement of one explicitly requested Pi or Claude Code target
|
|
207
|
+
| Attempt retirement of one explicitly requested Pi or Claude Code target | `entwurf_retire_call {target}` | Separate action, append-only record and lock-release results. Pi ACK is request-only; CC exit is that fd-pinned process only |
|
|
203
208
|
|
|
204
|
-
**Retirement is never autonomous.**
|
|
209
|
+
**Retirement is never autonomous.** It requires the human operator's explicit target/action;
|
|
210
|
+
a role, caller identity or tool annotation grants no permission. Host approval applies where
|
|
211
|
+
provided or configured. No roster expansion, timer or retry of an unknown/cancelled/lost result;
|
|
212
|
+
an absent event is unknown, not proof that no action occurred.
|
|
213
|
+
[DELIVERY](./DELIVERY.md#candidate-lifecycle-commands-are-not-delivery-boundaries-147)
|
|
214
|
+
owns the lifecycle boundaries; [BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1)
|
|
215
|
+
keeps dated native evidence separate from release and rollout acceptance.
|
|
205
216
|
|
|
206
217
|
**Delivery starts no process.** A live pi receives over its record-addressed control
|
|
207
218
|
address (a Unix socket; on the experimental native-Windows Pi preview, a named pipe);
|
|
@@ -220,32 +231,18 @@ is a live rail fact, not merely a consequence of trusted identity.
|
|
|
220
231
|
|
|
221
232
|
**One declared remote pair (opt-in, #107).** The operator places an `entwurf-remote-pair.json` on each of two hosts. Then `entwurf_v2` to the declared remote garden id runs the other host's `entwurf remote-pair-receive` once over the operator's own SSH, and that host checks the pair and dispatches locally. The trust is the same operator's SSH account. It makes one attempt with no retry, and it uses no relay or listener. [DELIVERY](./DELIVERY.md#remote-pair-107-one-declared-pair-across-two-hosts) owns the contract; [setup](./docs/setup-clean-host.md#2c-optional-remote-pair-between-two-hosts-107) covers the operator steps.
|
|
222
233
|
|
|
223
|
-
**Mux launches; it never delivers.**
|
|
224
|
-
in the
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
tmux
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
session-header cwd and first `model_change` provider/model feed the launch resolver, without a
|
|
236
|
-
record/host cwd fallback. Claude Code uses `claude --resume <record session id>` at the record cwd,
|
|
237
|
-
without restoring model or permission flags;
|
|
238
|
-
a live, unprovably dormant, unbound or other-backend target refuses, and an unobserved window
|
|
239
|
-
stays visible without retry. Claude Code's [V3 arm binding](./docs/adding-a-harness.md#arm-binding-within-v3)
|
|
240
|
-
is a record–receiver witness, not a new identity or an occupancy/permission token.
|
|
241
|
-
Claude Code dormancy is read only from attaches the Entwurf hook committed: a process that
|
|
242
|
-
holds the session without one (hooks disabled, a lock timeout or store failure at its start)
|
|
243
|
-
is invisible to that check.
|
|
244
|
-
Claude Code same-id resume is new in 0.41.0. One dated test-owned
|
|
245
|
-
[Native round trip](./BASELINE.md#147-native-round-trip-2026-10-22-n1) was measured; its
|
|
246
|
-
release acceptance remains separate from the shipped Pi resume history.
|
|
247
|
-
Exact boundaries: [tmux launch](https://github.com/junghan0611/entwurf/blob/main/docs/mux-launch-rail.md)
|
|
248
|
-
and [Herdr launch](https://github.com/junghan0611/entwurf/blob/main/docs/herdr-launch-rail.md).
|
|
234
|
+
**Mux launches; it never delivers.** Fresh uses the caller's Herdr workspace or tmux server,
|
|
235
|
+
within the harness limits in the table above. The model is required; optional `cwd` is a literal
|
|
236
|
+
absolute directory (omitted or empty means caller cwd). `placement.tmuxSession` names an
|
|
237
|
+
existing tmux session, never a new session or a cwd lookup, and is refused inside Herdr.
|
|
238
|
+
Without that override, a Codex caller opens beside its thread-id-matched TUI pane;
|
|
239
|
+
other callers use their own session. Missing or ambiguous context refuses without fallback.
|
|
240
|
+
Resume is tmux-only for pi and Claude Code, selected by the record, with no submitted prompt.
|
|
241
|
+
Claude Code dormancy covers only attaches its hook committed, not every possible session holder;
|
|
242
|
+
[V3 arm binding](./docs/adding-a-harness.md#arm-binding-within-v3) is not occupancy or permission.
|
|
243
|
+
An unobserved window stays visible without retry. Address liveness alone is not conversation recall.
|
|
244
|
+
Exact argv, identity checks and limits belong to [tmux launch](./docs/mux-launch-rail.md)
|
|
245
|
+
and [Herdr launch](./docs/herdr-launch-rail.md).
|
|
249
246
|
|
|
250
247
|
## Concepts
|
|
251
248
|
|
package/VERIFY.md
CHANGED
|
@@ -374,7 +374,7 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
374
374
|
**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.
|
|
375
375
|
|
|
376
376
|
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`)
|
|
377
|
-
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.
|
|
377
|
+
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.4.0 <1.5`) 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
|
|
378
378
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
379
379
|
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
|
|
380
380
|
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
|
@@ -24,7 +24,7 @@ takes/helpers/tests are maintainer tooling and are deliberately excluded from th
|
|
|
24
24
|
|
|
25
25
|
- Node at the `package.json#engines.node` floor; the checkout's pinned dependencies and
|
|
26
26
|
current compiled bridge. After a source/bootstrap change, build with `pnpm run build-bridge`.
|
|
27
|
-
- Pi at the checkout's supported floor (**current floor 1.
|
|
27
|
+
- Pi at the checkout's supported floor (**current floor 1.4.0**); `entwurf` on PATH must be
|
|
28
28
|
the intended source stable-bin. Source evidence is not registry-package acceptance.
|
|
29
29
|
- `herdr` on PATH at exactly `scripts/fixtures/herdr-supply.json#version`; `asciinema` v3.
|
|
30
30
|
- Herdr's existing Pi integration at
|
package/docs/acp-backend-rail.md
CHANGED
|
@@ -135,7 +135,7 @@ Dep bump ledger. 0.38.0 (#145) changes only the pi SDK set; the ACP rows are unc
|
|
|
135
135
|
| Surface | Declaration | Class | What a green actually says |
|
|
136
136
|
|---|---|---|---|
|
|
137
137
|
| Entwurf package | `package.json` `version` | checkout declaration, not a release receipt | names the package label these rows sit beside; whether that label shipped, and with which rows, is CHANGELOG's record |
|
|
138
|
-
| pi runtime | SDK exact `1.
|
|
138
|
+
| pi runtime | SDK exact `1.4.0`, host `>=1.4.0 <1.5` | **exact** oracle + **closed range** | the SDK set this checkout builds, gates and (since #130) ships as exact production dependencies; an ordinary Pi host inside the range is accepted, and the ceiling moves only on measurement. The published 0.36.0 through 0.37.1 shipped the 1.2.0 set (#141); 0.38.0 (#145) is the first to carry 1.3.0. Historical: the published 0.33.0 through 0.35.1 ship SDK exact 1.1.0, 0.32.0 ships SDK exact 1.0.4 with the next-minor ceiling (ROADMAP's 2026-10-07 bump entry), and 0.31.0 declared the earlier peer floor 1.0.2 |
|
|
139
139
|
| ACP wire SDK | `@agentclientprotocol/sdk 1.8.0` | **exact** | the shared wire oracle both adapters speak |
|
|
140
140
|
| Claude ACP adapter | `@agentclientprotocol/claude-agent-acp 0.90.0` | **exact**, bundled | shipped since 0.36.1; resolved before any PATH fallback; declaration is not compatibility evidence |
|
|
141
141
|
| Claude Agent SDK | `0.3.296` (transitive) | **exact** oracle | the runtime risk surface behind the adapter |
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -23,14 +23,18 @@ evidence split, and its three states must not collapse into "macOS is supported"
|
|
|
23
23
|
|
|
24
24
|
## Requirements
|
|
25
25
|
|
|
26
|
+
This table is this source candidate's, which moves the Pi SDK set to 1.4.0 and is **not published
|
|
27
|
+
to npm yet**. The newest published package, `@junghanacs/entwurf@0.41.0`, ships the Pi 1.3.0 SDK
|
|
28
|
+
set and requires Pi 1.3.x; the setup guide inside that tarball is its contract.
|
|
29
|
+
|
|
26
30
|
| Component | Requirement | Needed for |
|
|
27
31
|
|---|---|---|
|
|
28
32
|
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
29
33
|
| npm/pnpm | npm is bundled with Node; pnpm is required for source setup | package or source installation |
|
|
30
34
|
| Python 3 | required by `setup`/`install` (project-path normalization + settings writers); `--help`/`check-bridge` stay Python-free | pi/Claude/agy/Copilot/Codex wiring writers |
|
|
31
35
|
| entwurf | global/project-local `@junghanacs/entwurf`, or a source checkout | operator command and garden capability |
|
|
32
|
-
| pi | optional-by-presence, `>=1.
|
|
33
|
-
| Native durable (`pi-durable`) | supplied by the Entwurf package (#130): Entwurf's owned app carrier plus the exact 1.
|
|
36
|
+
| pi | optional-by-presence, `>=1.4.0 <1.5` — absent is an explicit setup SKIP, below-floor is a named FAIL | ACP provider, control sockets |
|
|
37
|
+
| Native durable (`pi-durable`) | supplied by the Entwurf package (#130): Entwurf's owned app carrier plus the exact 1.4.0 pi SDK set as production dependencies — setup PASS when they verify, a named FAIL otherwise (never SKIP) | the `entwurf pi-durable` contact; native birth/LIVE on this supply surface is a separate release proof (§2b) |
|
|
34
38
|
| Claude Code | optional, **`>=2.1.306`** — the exec-form hook floor | Claude ACP auth/runtime and mailbox-backed native citizen |
|
|
35
39
|
| GitHub Copilot CLI | optional-by-presence, operator-installed and authenticated — absent is an explicit setup SKIP; detected composes all four units (birth/MCP/receiver/footer) | self-fetch citizen and visible fresh |
|
|
36
40
|
| OMP (`omp`) | optional-by-presence, operator-installed — absent is an explicit setup SKIP; detected composes all four units (birth/MCP/`tools.xdev` setting/receiver) | self-fetch citizen and visible fresh (accepted on one host — see §4b) |
|
|
@@ -79,11 +83,15 @@ node --version
|
|
|
79
83
|
npm --version
|
|
80
84
|
```
|
|
81
85
|
|
|
86
|
+
The two npm forms below install the **published** package, `0.41.0` (Pi 1.3.x, the Pi 1.3.0 SDK
|
|
87
|
+
set), not this candidate. This candidate (Pi 1.4) installs only from a source checkout of its
|
|
88
|
+
commit, further down this section; it has no npm install command until it is released.
|
|
89
|
+
|
|
82
90
|
Global install is simplest when native harnesses should find stable bins from every
|
|
83
91
|
working directory:
|
|
84
92
|
|
|
85
93
|
```bash
|
|
86
|
-
npm install -g @junghanacs/entwurf
|
|
94
|
+
npm install -g @junghanacs/entwurf@0.41.0
|
|
87
95
|
entwurf --help
|
|
88
96
|
entwurf setup /path/to/your-project
|
|
89
97
|
entwurf check-bridge
|
|
@@ -94,7 +102,7 @@ A project-local installation is also supported:
|
|
|
94
102
|
```bash
|
|
95
103
|
mkdir -p ~/entwurf-smoke && cd ~/entwurf-smoke
|
|
96
104
|
npm init -y
|
|
97
|
-
npm install --save-dev @junghanacs/entwurf
|
|
105
|
+
npm install --save-dev @junghanacs/entwurf@0.41.0
|
|
98
106
|
npx entwurf setup .
|
|
99
107
|
npx entwurf check-bridge
|
|
100
108
|
```
|
|
@@ -119,9 +127,15 @@ with a nonzero setup result):
|
|
|
119
127
|
```bash
|
|
120
128
|
git clone https://github.com/junghan0611/entwurf ~/repos/gh/entwurf
|
|
121
129
|
cd ~/repos/gh/entwurf
|
|
130
|
+
git checkout "$CANDIDATE_REF" # set it first to the commit you mean to run; a bare clone gives the default branch
|
|
122
131
|
./run.sh setup /path/to/consumer-project
|
|
123
132
|
```
|
|
124
133
|
|
|
134
|
+
Set `CANDIDATE_REF` explicitly to a published branch or tag that carries the commit you mean;
|
|
135
|
+
a bare clone selects the default branch, not a promised candidate. A validation branch is not a
|
|
136
|
+
release acceptance. A checkout that already holds the intended commit skips the clone and the
|
|
137
|
+
`git checkout`.
|
|
138
|
+
|
|
125
139
|
This owns `~/.local/bin/entwurf` as a symlink to that checkout's `run.sh` and fails if the
|
|
126
140
|
link is foreign, outside PATH, or shadowed by another command. It detects and wires
|
|
127
141
|
pi/Claude/agy/Copilot/OMP/Codex by presence and prints a computed per-component
|
|
@@ -207,18 +221,21 @@ physical-Darwin receipt. `entwurf install` may write `.pi/settings.json`
|
|
|
207
221
|
on Darwin; that is wiring, not a rail receipt. If `pi` is on PATH,
|
|
208
222
|
`setup` names the pi row FAIL with the §1 Darwin wording.
|
|
209
223
|
|
|
210
|
-
Install
|
|
224
|
+
Install this candidate's exact Pi floor, then wire the project from the candidate's source
|
|
225
|
+
checkout (§1; `entwurf` is the link `./run.sh setup` made to it). The published 0.41.0 instead
|
|
226
|
+
takes the Pi 1.3.x its own setup guide names and the global package root,
|
|
227
|
+
`$(npm root -g)/@junghanacs/entwurf`, in place of the checkout:
|
|
211
228
|
|
|
212
229
|
```bash
|
|
213
|
-
npm install -g @earendil-works/pi-coding-agent@1.
|
|
230
|
+
npm install -g @earendil-works/pi-coding-agent@1.4.0
|
|
214
231
|
pi --version
|
|
215
232
|
|
|
216
233
|
cd ~/entwurf-smoke
|
|
217
234
|
entwurf install .
|
|
218
|
-
pi -e
|
|
235
|
+
pi -e ~/repos/gh/entwurf --list-models entwurf
|
|
219
236
|
```
|
|
220
237
|
|
|
221
|
-
The supported range is `>=1.
|
|
238
|
+
The supported range is `>=1.4.0 <1.5`. It is a hard minimum: installing this
|
|
222
239
|
release onto a 0.83.x pi host upgrades the runtime rather than keeping the older
|
|
223
240
|
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
224
241
|
control socket; no delivery rail launches a pi process.
|
|
@@ -322,7 +339,7 @@ by `entwurf pi` or by registering ordinary Pi's adapter.
|
|
|
322
339
|
What the Entwurf package supplies:
|
|
323
340
|
|
|
324
341
|
1. **The pi SDK set** — `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
325
|
-
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.
|
|
342
|
+
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.4.0`, plus
|
|
326
343
|
`proper-lockfile`, as Entwurf's own production dependencies (declared once in
|
|
327
344
|
`pi/pi-durable/overlay/upstream-pin.json` `sdk`). Model data rides the published
|
|
328
345
|
`pi-ai`; there is no catalog copy.
|
|
@@ -335,7 +352,7 @@ What the Entwurf package supplies:
|
|
|
335
352
|
(`pi/pi-durable/carrier-resolver.mjs`), which maps them to the published package's
|
|
336
353
|
own `dist/` as installed — never through a source checkout.
|
|
337
354
|
|
|
338
|
-
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.
|
|
355
|
+
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.4.0/packages/durable/README.md)
|
|
339
356
|
and the [experimental app guide](https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/src/experimental/durable/README.md)
|
|
340
357
|
(last published at v1.1.0) describe what the carrier is. Running the bare upstream app does not attach Entwurf's
|
|
341
358
|
garden contact. Entwurf does not rebuild the controller/model/auth/storage system or
|
|
@@ -420,7 +437,7 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
420
437
|
manifest field; it is a known constraint of supplying both from one package, accepted for 0.32,
|
|
421
438
|
not a claim that every load path is harmless.
|
|
422
439
|
|
|
423
|
-
The ordinary Pi CLI on PATH is a separate subject (§2, range `>=1.
|
|
440
|
+
The ordinary Pi CLI on PATH is a separate subject (§2, range `>=1.4.0 <1.5`): a host Pi is
|
|
424
441
|
not needed to run pi-durable, and a host inside the range need not be the same copy as the
|
|
425
442
|
carrier's. Native Pi owns credentials, model settings and durable SQLite sessions; keep them
|
|
426
443
|
in place rather than copying credentials or migrating ordinary Pi transcripts. Native
|
|
@@ -431,6 +448,29 @@ to the app's own model resolution; the checkout contact/send/receive gates run t
|
|
|
431
448
|
with scripted S plus native H; Pi ↔ pi-durable LIVE on this supply surface is a separate release
|
|
432
449
|
proof ([#130](https://github.com/junghan0611/entwurf/issues/130)).
|
|
433
450
|
|
|
451
|
+
### Moving durable sessions from the Pi 1.3 SDK to 1.4
|
|
452
|
+
|
|
453
|
+
This candidate is unpublished, and moving a live host onto it is a separate operator decision. When
|
|
454
|
+
you do:
|
|
455
|
+
|
|
456
|
+
1. **Confirm the old owner is gone.** Close the 0.41 (SDK 1.3) durable session normally and check
|
|
457
|
+
that its process has exited. A stale session lock alone is not proof.
|
|
458
|
+
2. **Back up first.** Before the first 1.4 open, copy the target session directory whole
|
|
459
|
+
(`session.sqlite` with any `-wal`/`-shm`) as one consistent set.
|
|
460
|
+
3. **Choose the session by name.** Reopen with the `--resume` picker and pick the entry you mean;
|
|
461
|
+
do not use `--continue` on a host with more than one session.
|
|
462
|
+
4. **Package downgrade is not data rollback.** The first 1.4 open migrates SQLite storage to
|
|
463
|
+
schema 2, which SDK 1.3 (Entwurf 0.41) refuses to open. Reinstalling the old package does not
|
|
464
|
+
undo that. Restoring the backup does, and work done after the 1.4 open is not in the backup.
|
|
465
|
+
5. **Inspect parked work before retrying.** On its first open, 1.4 counts a task that SDK 1.3 left
|
|
466
|
+
running as one restart, and after repeated cut-offs it parks the task (`restart_limit`). Read
|
|
467
|
+
what the task already did before you resend anything: recovery of a parked model turn is not
|
|
468
|
+
measured, and its side effects or outcome may be unknown. The existing conversation abort is
|
|
469
|
+
cancellation, not retry; it need not affect background tasks.
|
|
470
|
+
|
|
471
|
+
The measurements behind these points, and what they do not cover, are in the
|
|
472
|
+
[#148 checkpoint](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6339048361).
|
|
473
|
+
|
|
434
474
|
### Maintainer: re-emitting the carrier
|
|
435
475
|
|
|
436
476
|
Only a maintainer changing the pi-durable app runs `scripts/emit-pi-durable-carrier.ts`. Its
|
|
@@ -647,7 +687,7 @@ as a note rather than a fault.
|
|
|
647
687
|
|
|
648
688
|
**entwurf sets no OMP version floor in code, and will not grow one on schedule.** Detection is
|
|
649
689
|
presence-only (`command -v "${OMP_BIN:-omp}"`); there is no `entwurf.ompFloor`, no coherence
|
|
650
|
-
gate, and no exact pin — unlike Node (`engines.node`), pi (`>=1.
|
|
690
|
+
gate, and no exact pin — unlike Node (`engines.node`), pi (`>=1.4.0 <1.5`) and Claude Code
|
|
651
691
|
(`entwurf.claudeCodeFloor`), each of which has an enforcement point. That asymmetry is a
|
|
652
692
|
decision, not an omission. A floor is the answer to a vendor that fails SILENTLY — Claude Code
|
|
653
693
|
earned one because an older binary validates the exec manifest, drops `args` at runtime, and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@junghanacs/entwurf",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.1",
|
|
4
4
|
"description": "Visible sibling sessions across independent agent harnesses: launch in Herdr or tmux, retire on request and reopen pi or Claude Code in tmux, and deliver messages by garden id; native bridges and Claude/Cortex ACP adapters.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -89,7 +89,8 @@
|
|
|
89
89
|
"CHANGELOG.md",
|
|
90
90
|
"!**/__pycache__",
|
|
91
91
|
"!**/*.pyc",
|
|
92
|
-
"!pi-extensions/**/*.test.ts"
|
|
92
|
+
"!pi-extensions/**/*.test.ts",
|
|
93
|
+
"!pi-extensions/**/fixtures/**"
|
|
93
94
|
],
|
|
94
95
|
"engines": {
|
|
95
96
|
"node": ">=24.0.0"
|
|
@@ -101,15 +102,15 @@
|
|
|
101
102
|
"@agentclientprotocol/claude-agent-acp": "0.90.0",
|
|
102
103
|
"@agentclientprotocol/sdk": "1.8.0",
|
|
103
104
|
"@anthropic-ai/sdk": "0.100.1",
|
|
104
|
-
"@earendil-works/chord": "1.
|
|
105
|
-
"@earendil-works/pi-agent-core": "1.
|
|
106
|
-
"@earendil-works/pi-ai": "1.
|
|
107
|
-
"@earendil-works/pi-codemode": "1.
|
|
108
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
109
|
-
"@earendil-works/pi-durable": "1.
|
|
110
|
-
"@earendil-works/pi-mcp": "1.
|
|
111
|
-
"@earendil-works/pi-telemetry": "1.
|
|
112
|
-
"@earendil-works/pi-tui": "1.
|
|
105
|
+
"@earendil-works/chord": "1.4.0",
|
|
106
|
+
"@earendil-works/pi-agent-core": "1.4.0",
|
|
107
|
+
"@earendil-works/pi-ai": "1.4.0",
|
|
108
|
+
"@earendil-works/pi-codemode": "1.4.0",
|
|
109
|
+
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
110
|
+
"@earendil-works/pi-durable": "1.4.0",
|
|
111
|
+
"@earendil-works/pi-mcp": "1.4.0",
|
|
112
|
+
"@earendil-works/pi-telemetry": "1.4.0",
|
|
113
|
+
"@earendil-works/pi-tui": "1.4.0",
|
|
113
114
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
114
115
|
"proper-lockfile": "4.1.2",
|
|
115
116
|
"smol-toml": "^1.8.0",
|
|
@@ -219,6 +219,7 @@ export class TaskBadge {
|
|
|
219
219
|
...tally("aborting", (node) => node.abortRequested),
|
|
220
220
|
...tally("completing", (node) => !node.abortRequested && node.state.status === "completing"),
|
|
221
221
|
...tally("waiting", (node) => !node.abortRequested && node.state.status === "waiting"),
|
|
222
|
+
...tally("sleeping", (node) => !node.abortRequested && node.state.status === "sleeping"),
|
|
222
223
|
...tally("pending", (node) => !node.abortRequested && node.state.status === "pending"),
|
|
223
224
|
].join(", ");
|
|
224
225
|
}
|
|
@@ -621,19 +622,33 @@ class DurableTui {
|
|
|
621
622
|
}
|
|
622
623
|
}
|
|
623
624
|
|
|
624
|
-
|
|
625
|
+
/** A task's line in the tasks panel: a sleeping task says when it wakes, a blocked one why it cannot run. */
|
|
626
|
+
export function describeTask(node ) {
|
|
625
627
|
const state = node.state;
|
|
626
628
|
const status =
|
|
627
629
|
state.status === "waiting"
|
|
628
630
|
? `waiting on ${state.on.join(", ")}`
|
|
629
631
|
: state.status === "completing"
|
|
630
632
|
? `completing (${state.outcome})`
|
|
631
|
-
:
|
|
632
|
-
|
|
633
|
+
: state.status === "sleeping"
|
|
634
|
+
? `sleeping ${state.phase} until ${localTime(state.until)}`
|
|
635
|
+
: `${state.status} ${state.phase}`;
|
|
636
|
+
const flags = [
|
|
637
|
+
node.background ? "background" : "",
|
|
638
|
+
node.abortRequested ? "aborting" : "",
|
|
639
|
+
node.blocked !== undefined ? `blocked:${node.blocked}` : "",
|
|
640
|
+
].filter(Boolean);
|
|
633
641
|
const owned = node.conversations.length > 0 ? ` owns conversation ${node.conversations.join(", ")}` : "";
|
|
634
642
|
return `${node.kind} #${node.id}: ${status}${flags.length > 0 ? ` [${flags.join(", ")}]` : ""}${owned}`;
|
|
635
643
|
}
|
|
636
644
|
|
|
645
|
+
/** Epoch milliseconds as local wall-clock time, `YYYY-MM-DD HH:MM:SS`. */
|
|
646
|
+
function localTime(epoch ) {
|
|
647
|
+
const at = new Date(epoch);
|
|
648
|
+
const pad = (n ) => String(n).padStart(2, "0");
|
|
649
|
+
return `${at.getFullYear()}-${pad(at.getMonth() + 1)}-${pad(at.getDate())} ${pad(at.getHours())}:${pad(at.getMinutes())}:${pad(at.getSeconds())}`;
|
|
650
|
+
}
|
|
651
|
+
|
|
637
652
|
function userText(content ) {
|
|
638
653
|
if (typeof content === "string") return content;
|
|
639
654
|
return content
|
|
@@ -76,8 +76,8 @@
|
|
|
76
76
|
{
|
|
77
77
|
"name": "tui.js",
|
|
78
78
|
"source": "pi/pi-durable/src/experimental/durable/tui.ts",
|
|
79
|
-
"blob": "
|
|
80
|
-
"sha256": "
|
|
79
|
+
"blob": "405600f6ba1558bf6bf22d144afdcf3f1295c282",
|
|
80
|
+
"sha256": "d4bf4e2861bde917e1dcdea6f063bdc3e101ab500107a9c5fab0e3ce97fb2c4a"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
"name": "harness-setup.js",
|
|
@@ -132,17 +132,17 @@
|
|
|
132
132
|
]
|
|
133
133
|
},
|
|
134
134
|
"sdk": {
|
|
135
|
-
"comment": "The published library set the carrier runs against, derived from the 1.
|
|
135
|
+
"comment": "The published library set the carrier runs against, derived from the 1.4.0 declarations. members: the @earendil-works packages the carrier imports and every @earendil-works package those declare. direct: a third-party package a carrier file imports itself (sessions.ts: proper-lockfile, at the version pi-coding-agent 1.4.0 pins). Each is an exact production dependency in package.json. Since 1.3.0 the members' own edges are exact too (upstream #10865), and the installed physical edges are still what must equal these versions.",
|
|
136
136
|
"members": {
|
|
137
|
-
"@earendil-works/chord": "1.
|
|
138
|
-
"@earendil-works/pi-agent-core": "1.
|
|
139
|
-
"@earendil-works/pi-ai": "1.
|
|
140
|
-
"@earendil-works/pi-codemode": "1.
|
|
141
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
142
|
-
"@earendil-works/pi-durable": "1.
|
|
143
|
-
"@earendil-works/pi-mcp": "1.
|
|
144
|
-
"@earendil-works/pi-telemetry": "1.
|
|
145
|
-
"@earendil-works/pi-tui": "1.
|
|
137
|
+
"@earendil-works/chord": "1.4.0",
|
|
138
|
+
"@earendil-works/pi-agent-core": "1.4.0",
|
|
139
|
+
"@earendil-works/pi-ai": "1.4.0",
|
|
140
|
+
"@earendil-works/pi-codemode": "1.4.0",
|
|
141
|
+
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
142
|
+
"@earendil-works/pi-durable": "1.4.0",
|
|
143
|
+
"@earendil-works/pi-mcp": "1.4.0",
|
|
144
|
+
"@earendil-works/pi-telemetry": "1.4.0",
|
|
145
|
+
"@earendil-works/pi-tui": "1.4.0"
|
|
146
146
|
},
|
|
147
147
|
"direct": {
|
|
148
148
|
"proper-lockfile": "4.1.2"
|
|
@@ -239,9 +239,11 @@ export interface AcpBackendAdapter {
|
|
|
239
239
|
|
|
240
240
|
/** OPTIONAL capability (#127): recognise a typed vendor rejection of `session/prompt`
|
|
241
241
|
* whose raw text must not become pi's `errorMessage`. pi decides a whole-prompt replay
|
|
242
|
-
* from `errorMessage` alone, and a vendor's "Internal error"
|
|
243
|
-
*
|
|
244
|
-
* from a cold session.
|
|
242
|
+
* from `errorMessage` alone, and a vendor's "Internal error" reads as transient
|
|
243
|
+
* (pi-ai's `internal.?error` term), so a turn whose tools already ran would be resent
|
|
244
|
+
* from a cold session. Through pi-ai 1.3 a digit run inside the ids it carries (`…8503…`)
|
|
245
|
+
* read as an HTTP status too; pi-ai 1.4 bounds the status terms (upstream #11057), so
|
|
246
|
+
* the ids no longer trigger it — the "Internal error" text alone still does. A recognised rejection returns a fixed, authored verdict for
|
|
245
247
|
* `errorMessage`; backend.ts keeps the raw rejection as a pi diagnostic instead.
|
|
246
248
|
*
|
|
247
249
|
* ABSENT means every failure of this backend keeps the verbatim-first `errorMessage`.
|
|
@@ -668,13 +668,15 @@ async function settleChildEnd(latch: ChildEndLatch, ms: number): Promise<void> {
|
|
|
668
668
|
* may appear here, or a dead child would put a full cold prompt replay back on
|
|
669
669
|
* the table — with the tool side effects this turn already produced.
|
|
670
670
|
*
|
|
671
|
-
* That pattern is a
|
|
672
|
-
*
|
|
673
|
-
* "502", "503", "504"
|
|
674
|
-
* CHILD_END_SETTLE_MS made this line say "within 500ms", which pi read as an
|
|
675
|
-
*
|
|
676
|
-
*
|
|
677
|
-
*
|
|
671
|
+
* That pattern is a substring alternation (`new RegExp(terms.join("|"), "i")` — NO word
|
|
672
|
+
* boundaries on its word terms). Through pi-ai 1.3 its HTTP status terms ("429", "500",
|
|
673
|
+
* "502", "503", "504", "520", "524") were bare substrings too, and rendering
|
|
674
|
+
* CHILD_END_SETTLE_MS made this line say "within 500ms", which pi read as an HTTP 500 and
|
|
675
|
+
* classified as transient. pi-ai 1.4 bounds only those status terms (upstream #11057), so
|
|
676
|
+
* "500ms" no longer matches; the word terms above are still unbounded. The settle bound
|
|
677
|
+
* stays deliberately NOT interpolated: naming the window in prose keeps a later change of
|
|
678
|
+
* that constant, or of the classifier, from silently re-arming the replay — do not
|
|
679
|
+
* "improve" this by putting the number back; the bound belongs in the code and the gate.
|
|
678
680
|
*
|
|
679
681
|
* The three endings are kept DISTINCT on purpose (issue #72 Done-when): an
|
|
680
682
|
* exit code, a signal, and "we waited and it never said" are three different
|
|
@@ -1468,8 +1470,9 @@ export function streamAcpTurn(
|
|
|
1468
1470
|
// the turn-scoped full-transcript-replay cause.
|
|
1469
1471
|
const hint = aborted ? undefined : actionableAcpBackendHint(full);
|
|
1470
1472
|
// #127: pi's retry and overflow classifiers read `errorMessage` ALONE, and a
|
|
1471
|
-
// vendor's "Internal error"
|
|
1472
|
-
//
|
|
1473
|
+
// vendor's "Internal error" reads as transient — a replay of a turn whose tools
|
|
1474
|
+
// already ran. (Through pi-ai 1.3 a digit run in its ids/stderr did too; 1.4 bounds
|
|
1475
|
+
// the status terms, upstream #11057.) A rejection the adapter names gets
|
|
1473
1476
|
// its fixed verdict there; every raw part rides one diagnostic, appended after any
|
|
1474
1477
|
// existing ones. An abort keeps the abort path.
|
|
1475
1478
|
const rejection = aborted ? undefined : adapter?.readPromptRejection?.(err);
|
|
@@ -354,7 +354,7 @@ export interface PiDurableRoots {
|
|
|
354
354
|
// ---------------------------------------------------------------------------
|
|
355
355
|
// Durable surface, typed NARROWLY and locally — read at pi-durable 1.0.2 @cd32f77 (#129,
|
|
356
356
|
// `harness/types.ts`; historical coordinates, not re-anchored here). The current supply is the
|
|
357
|
-
// carrier emitted from Entwurf's owned source (pi/pi-durable/src, #141) against the 1.
|
|
357
|
+
// carrier emitted from Entwurf's owned source (pi/pi-durable/src, #141) against the 1.4.0 SDK set
|
|
358
358
|
// `pi/pi-durable/overlay/upstream-pin.json` names (origin `abe508e`). `[read 2026-10-13]` at
|
|
359
359
|
// v1.2.0 one shape typed below moved: `ToolExecutionResult.content` is now `output`, beside the new
|
|
360
360
|
// `structuredOutput` (`harness/types.ts`, its CHANGELOG's breaking changes). An omitted `output`
|
package/run.sh
CHANGED
|
@@ -4021,6 +4021,10 @@ check_pack() {
|
|
|
4021
4021
|
# JS for installed entrypoints. The files array lists pi/pi-durable per FILE, so nothing admits these
|
|
4022
4022
|
# today; this tripwire is what fails loud the day an allowlist entry would.
|
|
4023
4023
|
local durable_source_pattern='^pi/pi-durable/(src/|tsconfig\.json$|overlay/runtime-contacts\.patch$)'
|
|
4024
|
+
# #148 S1b: the goldens and generator a beside test reads (pi-extensions/lib/fixtures/) are test input,
|
|
4025
|
+
# not product. `pi-extensions/` ships whole, so the `!pi-extensions/**/fixtures/**` negation is the only
|
|
4026
|
+
# thing keeping them out, and this is its tripwire (same 결합 규칙 as the `.test.ts` pattern above).
|
|
4027
|
+
local test_fixture_pattern='^pi-extensions/(.*/)?fixtures/'
|
|
4024
4028
|
|
|
4025
4029
|
local pass=1 f pat hit
|
|
4026
4030
|
|
|
@@ -4047,6 +4051,13 @@ check_pack() {
|
|
|
4047
4051
|
pass=0
|
|
4048
4052
|
fi
|
|
4049
4053
|
|
|
4054
|
+
hit=$(grep -E "$test_fixture_pattern" <<<"$file_list" || true)
|
|
4055
|
+
if [ -n "$hit" ]; then
|
|
4056
|
+
fail "[check-pack] a beside test's fixtures (pi-extensions/**/fixtures/) ride the tarball — test input is not product; restore the files-array negation:"
|
|
4057
|
+
echo "$hit" | sed 's/^/ /' >&2
|
|
4058
|
+
pass=0
|
|
4059
|
+
fi
|
|
4060
|
+
|
|
4050
4061
|
# #78 — a pack carries the Windows addon not at all, or as exactly a verified addon + manifest
|
|
4051
4062
|
# pair (pack_win32_carrier_verdict, proven on owned fixtures by check-pack-win32-carrier).
|
|
4052
4063
|
# "present" means the carrier verified, never that the build was approved for publication.
|
|
@@ -4157,7 +4168,7 @@ check_pack_win32_carrier() {
|
|
|
4157
4168
|
# which is exactly what property (1)'s `(_|$)` absorbs; all three shapes are fixtures
|
|
4158
4169
|
# below so a future suffix change cannot pass vacuously.)
|
|
4159
4170
|
pack_install_leaked_pi() {
|
|
4160
|
-
grep '^@earendil-works+' | grep -Ev '@1\.
|
|
4171
|
+
grep '^@earendil-works+' | grep -Ev '@1\.4\.0(_|$)' || true
|
|
4161
4172
|
}
|
|
4162
4173
|
|
|
4163
4174
|
# Matcher self-test on SYNTHETIC lookalikes: a healthy install tree cannot exercise either
|
|
@@ -4174,18 +4185,18 @@ check_pack_pin_matcher() {
|
|
|
4174
4185
|
# Cell 1 — the version boundary. Every measured peer-hash shape is a fixture: the
|
|
4175
4186
|
# 0.84.4-era `_@modelcontextprotocol+sdk@…`, the `_ws@8.21.3` observed on a real
|
|
4176
4187
|
# 0.85.1 tree, and `[측정 2026-09-20]` the combined suffix a 0.86.0 install carries.
|
|
4177
|
-
# None may leak; the two lookalikes must — a PREFIX-EXTENDED version (`
|
|
4188
|
+
# None may leak; the two lookalikes must — a PREFIX-EXTENDED version (`1.4.0-beta.1`,
|
|
4178
4189
|
# the prerelease shape that an unanchored match would bless) and an off-pin version.
|
|
4179
4190
|
matcher_probe=$(printf '%s\n' \
|
|
4180
|
-
'@earendil-works+pi-ai@1.
|
|
4181
|
-
'@earendil-works+pi-ai@1.
|
|
4182
|
-
'@earendil-works+pi-ai@1.
|
|
4183
|
-
'@earendil-works+pi-ai@1.
|
|
4184
|
-
'@earendil-works+pi-ai@1.
|
|
4191
|
+
'@earendil-works+pi-ai@1.4.0' \
|
|
4192
|
+
'@earendil-works+pi-ai@1.4.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6' \
|
|
4193
|
+
'@earendil-works+pi-ai@1.4.0_ws@8.21.3' \
|
|
4194
|
+
'@earendil-works+pi-ai@1.4.0_@modelcontextprotocol+sdk@1.29.0_zod@4.3.6__ws@8.21.3_zod@4.3.6' \
|
|
4195
|
+
'@earendil-works+pi-ai@1.4.0-beta.1' \
|
|
4185
4196
|
'@earendil-works+pi-agent-core@0.87.1' | pack_install_leaked_pi)
|
|
4186
|
-
if [ "$matcher_probe" != '@earendil-works+pi-ai@1.
|
|
4197
|
+
if [ "$matcher_probe" != '@earendil-works+pi-ai@1.4.0-beta.1
|
|
4187
4198
|
@earendil-works+pi-agent-core@0.87.1' ]; then
|
|
4188
|
-
fail "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED] the pin-leak matcher must flag the prefix-extended 1.
|
|
4199
|
+
fail "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED] the pin-leak matcher must flag the prefix-extended 1.4.0-beta.1 and the off-pin 0.87.1 lookalikes, and pass 1.4.0 bare or with any measured peer-hash — got: ${matcher_probe:-<nothing leaked>}"
|
|
4189
4200
|
return 1
|
|
4190
4201
|
fi
|
|
4191
4202
|
|
|
@@ -4193,9 +4204,9 @@ check_pack_pin_matcher() {
|
|
|
4193
4204
|
# (0.85.0 onward, still true at 0.99.1). An off-pin chord MUST leak; the pinned one must not. A matcher narrowed
|
|
4194
4205
|
# back to `^@earendil-works+pi-` sees nothing here and dies at this signature.
|
|
4195
4206
|
matcher_probe=$(printf '%s\n' \
|
|
4196
|
-
'@earendil-works+chord@1.
|
|
4207
|
+
'@earendil-works+chord@1.4.0' \
|
|
4197
4208
|
'@earendil-works+chord@0.87.1' \
|
|
4198
|
-
'@earendil-works+pi-ai@1.
|
|
4209
|
+
'@earendil-works+pi-ai@1.4.0' | pack_install_leaked_pi)
|
|
4199
4210
|
if [ "$matcher_probe" != '@earendil-works+chord@0.87.1' ]; then
|
|
4200
4211
|
fail "[QK:PACK-INSTALL-PIN-MATCHER-COVERS-CLOSURE] the pin-leak matcher must cover every @earendil-works closure member, not just the pi-* families — an off-pin @earendil-works/chord has to leak (it was a runtime dependency of pi-coding-agent, pi-agent-core, pi-client and pi-protocol — `[측정 2026-09-20]` at 0.86.0, re-measured `[측정 2026-09-22]` at 0.87.0, `[측정 2026-09-23]` at 0.87.1 and `[측정 2026-09-30]` at 0.99.1, where pi-coding-agent adds pi-codemode and pi-mcp beside them; `[측정 2026-10-13]` at 1.2.0 pi-durable alone declares it) — got: ${matcher_probe:-<nothing leaked>}"
|
|
4201
4212
|
return 1
|
|
@@ -4209,7 +4220,7 @@ check_pack_pin_matcher() {
|
|
|
4209
4220
|
# Cells: L1s (Entwurf alone, $3), L1 (project-local beside an aligned host pi-coding-agent at the
|
|
4210
4221
|
# pinned SDK version), L2 (an isolated `npm -g --prefix`), each through (a) the INSTALLED verifier
|
|
4211
4222
|
# (exit 0, prints its own carrier-resolver) and (b) an independent consumer oracle; then the L3
|
|
4212
|
-
# NEGATIVE (an override binds pi-durable's pi-
|
|
4223
|
+
# NEGATIVE (an override binds pi-durable's pi-codemode edge to an older published version: the installed verifier must
|
|
4213
4224
|
# refuse it by name, while a bare import still succeeds); then (c) the public launch on L1s.
|
|
4214
4225
|
# The oracle observes RESOLUTIONS (a resolve hook), not every filesystem read; it asserts each
|
|
4215
4226
|
# resolved product file lies inside THIS consumer's node_modules — a sandbox ancestor is not the
|
|
@@ -4304,13 +4315,18 @@ ORACLE
|
|
|
4304
4315
|
echo "[check-pack-install] pi-durable $cell: installed verifier PASS; consumer oracle $out"
|
|
4305
4316
|
done
|
|
4306
4317
|
|
|
4307
|
-
|
|
4318
|
+
# The wrong edge must still IMPORT, or the control proves a crash rather than a refusal. `[측정 2026-10-22]`
|
|
4319
|
+
# SDK 1.4 pi-durable imports pi-ai's new `utils/identity`, absent from the older pi-ai control versions
|
|
4320
|
+
# checked here (1.0.3 and 1.3.0 both fail to load); pi-telemetry 1.0.3/1.3.0 and chord 1.3.0 lack exports
|
|
4321
|
+
# it imports. pi-codemode 1.3.0 loads, and depends on no SDK member, so this tree carries exactly one
|
|
4322
|
+
# depth-2 mismatch (L4 keeps depth 3).
|
|
4323
|
+
printf '%s\n' "{\"name\":\"pd-mismatch\",\"version\":\"1.0.0\",\"private\":true,\"overrides\":{\"@earendil-works/pi-durable\":{\"@earendil-works/pi-codemode\":\"1.3.0\"}}}" > "$box/pd-mismatch/package.json"
|
|
4308
4324
|
out=$(cd "$box/pd-mismatch" && npm install "$tgz" --no-audit --no-fund 2>&1) || {
|
|
4309
4325
|
fail "[check-pack-install] pi-durable L3 (mismatch control) install failed:"; echo "$out" | tail -10 | sed 's/^/ /' >&2; return 1; }
|
|
4310
4326
|
pkg="$box/pd-mismatch/node_modules/@junghanacs/entwurf"
|
|
4311
4327
|
rc=0; out=$(cd "$box" && node "$pkg/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js" resolve 2>&1) || rc=$?
|
|
4312
|
-
if [ "$rc" -ne 3 ] || ! grep -q "pi-durable-sdk-mismatch: @earendil-works/pi-durable → @earendil-works/pi-
|
|
4313
|
-
fail "[QK:PACK-INSTALL-DURABLE-MISMATCH-REFUSED] [check-pack-install] pi-durable L3: an installed tree whose pi-durable binds pi-
|
|
4328
|
+
if [ "$rc" -ne 3 ] || ! grep -q "pi-durable-sdk-mismatch: @earendil-works/pi-durable → @earendil-works/pi-codemode wants $pin_ver, binds 1.3.0" <<<"$out"; then
|
|
4329
|
+
fail "[QK:PACK-INSTALL-DURABLE-MISMATCH-REFUSED] [check-pack-install] pi-durable L3: an installed tree whose pi-durable binds pi-codemode 1.3.0 must be refused by name as pi-durable-sdk-mismatch (rc=$rc): $out"
|
|
4314
4330
|
return 1
|
|
4315
4331
|
fi
|
|
4316
4332
|
rc=0; out=$(cd "$box" && node --input-type=module -e "import { pathToFileURL } from 'node:url'; await import('$pkg/pi/pi-durable/carrier-resolver.mjs'); const m = await import(pathToFileURL('$pkg/pi/pi-durable/carrier/runtime.js').href); console.log(typeof m.openDurable);" 2>&1) || rc=$?
|
|
@@ -4835,19 +4851,21 @@ _check_pack_install_impl() {
|
|
|
4835
4851
|
# `[측정 2026-10-16]` at 1.3.0 the constellation is unchanged: the installed manifests give the
|
|
4836
4852
|
# same member edges as at 1.2.0, now every one exact 1.3.0 (upstream #10865), and the consumer
|
|
4837
4853
|
# oracle walked 10 member edges with 0 mismatches (.tmp-verify/145-stage1/08-pack-install.log).
|
|
4838
|
-
|
|
4854
|
+
# `[측정 2026-10-22]` at 1.4.0 the nine members are again exact 1.4.0 edges (registry manifests; #148 S0),
|
|
4855
|
+
# and pi-tui 1.4.0 adds one third-party dependency (marked-cjk-friendly 0.1.2) outside the closure.
|
|
4856
|
+
echo "[check-pack-install] pnpm add into $tmp (with the aligned 1.4.x SDK + chord + codemode + mcp + durable + typebox)"
|
|
4839
4857
|
local install_log
|
|
4840
4858
|
install_log=$(cd "$tmp" && pnpm add \
|
|
4841
4859
|
"$tgz_path" \
|
|
4842
|
-
"@earendil-works/pi-ai@1.
|
|
4843
|
-
"@earendil-works/pi-coding-agent@1.
|
|
4844
|
-
"@earendil-works/pi-tui@1.
|
|
4845
|
-
"@earendil-works/pi-agent-core@1.
|
|
4846
|
-
"@earendil-works/pi-telemetry@1.
|
|
4847
|
-
"@earendil-works/chord@1.
|
|
4848
|
-
"@earendil-works/pi-codemode@1.
|
|
4849
|
-
"@earendil-works/pi-mcp@1.
|
|
4850
|
-
"@earendil-works/pi-durable@1.
|
|
4860
|
+
"@earendil-works/pi-ai@1.4.0" \
|
|
4861
|
+
"@earendil-works/pi-coding-agent@1.4.0" \
|
|
4862
|
+
"@earendil-works/pi-tui@1.4.0" \
|
|
4863
|
+
"@earendil-works/pi-agent-core@1.4.0" \
|
|
4864
|
+
"@earendil-works/pi-telemetry@1.4.0" \
|
|
4865
|
+
"@earendil-works/chord@1.4.0" \
|
|
4866
|
+
"@earendil-works/pi-codemode@1.4.0" \
|
|
4867
|
+
"@earendil-works/pi-mcp@1.4.0" \
|
|
4868
|
+
"@earendil-works/pi-durable@1.4.0" \
|
|
4851
4869
|
"typebox@latest" \
|
|
4852
4870
|
--ignore-workspace --ignore-scripts 2>&1) || {
|
|
4853
4871
|
fail "[check-pack-install] pnpm add failed:"
|
|
@@ -4863,11 +4881,11 @@ _check_pack_install_impl() {
|
|
|
4863
4881
|
local leaked_pi
|
|
4864
4882
|
leaked_pi=$(ls "$tmp/node_modules/.pnpm" 2>/dev/null | pack_install_leaked_pi)
|
|
4865
4883
|
if [ -n "$leaked_pi" ]; then
|
|
4866
|
-
fail "[check-pack-install] UNVERIFIED pi runtime resolved into the install tree (expected only 1.
|
|
4884
|
+
fail "[check-pack-install] UNVERIFIED pi runtime resolved into the install tree (expected only 1.4.0):"
|
|
4867
4885
|
printf '%s\n' "$leaked_pi" | sed 's/^/ /' >&2
|
|
4868
4886
|
return 1
|
|
4869
4887
|
fi
|
|
4870
|
-
echo "[check-pack-install] pi runtime tree pin verified: every @earendil-works package is 1.
|
|
4888
|
+
echo "[check-pack-install] pi runtime tree pin verified: every @earendil-works package is 1.4.0 (chord and pi-durable included)"
|
|
4871
4889
|
|
|
4872
4890
|
# Resolve the installed package.json and confirm pi.extensions
|
|
4873
4891
|
# arrived intact. If pi.extensions is empty or missing, the
|
|
@@ -52,8 +52,9 @@ export function buildCodexInstruction(input: CodexInstructionInput): string {
|
|
|
52
52
|
// DIRECTORY must come from this Codex's own record (#95 lane C), which is a fact only
|
|
53
53
|
// because its thread now opens where its pane is rather than where the app-server sits.
|
|
54
54
|
// Omitting the parameter is the whole point — passing one would prove neither.
|
|
55
|
-
'NO cwd parameter and NO placement parameter, and task "
|
|
56
|
-
|
|
55
|
+
'NO cwd parameter and NO placement parameter, and task "Your automatic callback is the whole task and there is ' +
|
|
56
|
+
"no result to send. After it succeeds, end the turn: no message, no report, no further tool call. Do not open " +
|
|
57
|
+
'another sibling."\n' +
|
|
57
58
|
"2. Stop and wait for the Pi callback delivered into this Codex thread. Accept only a callback whose body " +
|
|
58
59
|
"repeats the exact nonce from your LAUNCH receipt and whose sender envelope carries a garden id on its `session:` line.\n" +
|
|
59
60
|
`3. Only after that match, call public mcp__entwurf_bridge__entwurf_v2 once with target ${input.callerGid}, ` +
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
"claim": "PI-CORE-PIN-TRACKS-FLOOR",
|
|
182
182
|
"title": "the queue oracle's pi-agent-core pin drifts off the floor the rest of the pi runtime is pinned to, so the oracle keeps answering honestly — about a pi nobody in this repo runs",
|
|
183
183
|
"subject": "package.json",
|
|
184
|
-
"find": ["\"@earendil-works/pi-agent-core\": \"1.
|
|
184
|
+
"find": ["\"@earendil-works/pi-agent-core\": \"1.4.0\","],
|
|
185
185
|
"replace": ["\"@earendil-works/pi-agent-core\": \"0.87.1\","],
|
|
186
186
|
"gate": ["bash", "run.sh", "check-dep-versions"],
|
|
187
187
|
"timeoutSeconds": 300,
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"claim": "PACK-INSTALL-PIN-MATCHER-BOUNDED",
|
|
7
7
|
"title": "the pin-leak matcher loses its version boundary and blesses substring lookalikes \u2014 @0.85.10 reads as the pinned 0.85.1 and the gate announces a verified tree it never verified (independent review, 2026-08-25)",
|
|
8
8
|
"subject": "run.sh",
|
|
9
|
-
"find": [" grep '^@earendil-works+' | grep -Ev '@1\\.
|
|
10
|
-
"replace": [" grep '^@earendil-works+' | grep -v '@
|
|
9
|
+
"find": [" grep '^@earendil-works+' | grep -Ev '@1\\.4\\.0(_|$)' || true"],
|
|
10
|
+
"replace": [" grep '^@earendil-works+' | grep -v '@1\\.4\\.0' || true"],
|
|
11
11
|
"gate": ["bash", "run.sh", "check-pack-pin-matcher"],
|
|
12
12
|
"timeoutSeconds": 120,
|
|
13
13
|
"signature": "[QK:PACK-INSTALL-PIN-MATCHER-BOUNDED]",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"claim": "PACK-INSTALL-PIN-MATCHER-COVERS-CLOSURE",
|
|
18
18
|
"title": "the pin-leak matcher narrows back to the pi-* families and goes blind to a non-pi member of the same runtime closure \u2014 @earendil-works/chord (new in pi 0.85.0, a runtime dependency of pi-coding-agent/pi-agent-core/pi-client/pi-protocol) floats unpinned while the gate prints a verified pin (measured 2026-09-06 on a real 0.85.1 install tree)",
|
|
19
19
|
"subject": "run.sh",
|
|
20
|
-
"find": [" grep '^@earendil-works+' | grep -Ev '@1\\.
|
|
21
|
-
"replace": [" grep '^@earendil-works+pi-' | grep -Ev '@1\\.
|
|
20
|
+
"find": [" grep '^@earendil-works+' | grep -Ev '@1\\.4\\.0(_|$)' || true"],
|
|
21
|
+
"replace": [" grep '^@earendil-works+pi-' | grep -Ev '@1\\.4\\.0(_|$)' || true"],
|
|
22
22
|
"gate": ["bash", "run.sh", "check-pack-pin-matcher"],
|
|
23
23
|
"timeoutSeconds": 120,
|
|
24
24
|
"signature": "[QK:PACK-INSTALL-PIN-MATCHER-COVERS-CLOSURE]",
|
|
@@ -1207,6 +1207,66 @@
|
|
|
1207
1207
|
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1208
1208
|
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1209
1209
|
},
|
|
1210
|
+
{
|
|
1211
|
+
"claim": "PI-DURABLE-TASK-SLEEPING-COUNTED",
|
|
1212
|
+
"title": "the badge stops naming sleeping tasks: a background task in its durable backoff is counted but said to be nothing",
|
|
1213
|
+
"subject": "pi/pi-durable/carrier/tui.js",
|
|
1214
|
+
"find": ["\t\t\t...tally(\"sleeping\", (node) => !node.abortRequested && node.state.status === \"sleeping\"),"],
|
|
1215
|
+
"replace": ["\t\t\t// sleeping is not named"],
|
|
1216
|
+
"gate": ["bash", "run.sh", "check-pi-durable-carrier"],
|
|
1217
|
+
"timeoutSeconds": 300,
|
|
1218
|
+
"signature": "[QK:PI-DURABLE-TASK-SLEEPING-COUNTED]",
|
|
1219
|
+
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1220
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1221
|
+
},
|
|
1222
|
+
{
|
|
1223
|
+
"claim": "PI-DURABLE-TASK-SLEEPING-SHOWN",
|
|
1224
|
+
"title": "a sleeping task's panel line drops its wake time, so nothing on screen says when the sleeping work comes back",
|
|
1225
|
+
"subject": "pi/pi-durable/carrier/tui.js",
|
|
1226
|
+
"find": ["\t\t\t\t\t? `sleeping ${state.phase} until ${localTime(state.until)}`"],
|
|
1227
|
+
"replace": ["\t\t\t\t\t? `sleeping ${state.phase}`"],
|
|
1228
|
+
"gate": ["bash", "run.sh", "check-pi-durable-carrier"],
|
|
1229
|
+
"timeoutSeconds": 300,
|
|
1230
|
+
"signature": "[QK:PI-DURABLE-TASK-SLEEPING-SHOWN]",
|
|
1231
|
+
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1232
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1233
|
+
},
|
|
1234
|
+
{
|
|
1235
|
+
"claim": "PI-DURABLE-TASK-BLOCKED-SHOWN",
|
|
1236
|
+
"title": "the panel stops marking blocked tasks: a task the SDK will not run reads as ordinary pending work",
|
|
1237
|
+
"subject": "pi/pi-durable/carrier/tui.js",
|
|
1238
|
+
"find": ["\t\tnode.blocked !== undefined ? `blocked:${node.blocked}` : \"\","],
|
|
1239
|
+
"replace": ["\t\t\"\","],
|
|
1240
|
+
"gate": ["bash", "run.sh", "check-pi-durable-carrier"],
|
|
1241
|
+
"timeoutSeconds": 300,
|
|
1242
|
+
"signature": "[QK:PI-DURABLE-TASK-BLOCKED-SHOWN]",
|
|
1243
|
+
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1244
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
"claim": "PI-DURABLE-TASK-BLOCKED-REASON",
|
|
1248
|
+
"title": "every blocked task is said to be parked by the restart limit, whatever reason the SDK gave",
|
|
1249
|
+
"subject": "pi/pi-durable/carrier/tui.js",
|
|
1250
|
+
"find": ["\t\tnode.blocked !== undefined ? `blocked:${node.blocked}` : \"\","],
|
|
1251
|
+
"replace": ["\t\tnode.blocked !== undefined ? `blocked:restart_limit` : \"\","],
|
|
1252
|
+
"gate": ["bash", "run.sh", "check-pi-durable-carrier"],
|
|
1253
|
+
"timeoutSeconds": 300,
|
|
1254
|
+
"signature": "[QK:PI-DURABLE-TASK-BLOCKED-REASON]",
|
|
1255
|
+
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1256
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
"claim": "PI-DURABLE-TEST-FIXTURES-NOT-SHIPPED",
|
|
1260
|
+
"title": "package.json drops its fixture negation, so every published tarball carries the test goldens under pi-extensions/**/fixtures/",
|
|
1261
|
+
"subject": "package.json",
|
|
1262
|
+
"find": ["\t\t\"!pi-extensions/**/*.test.ts\",", "\t\t\"!pi-extensions/**/fixtures/**\""],
|
|
1263
|
+
"replace": ["\t\t\"!pi-extensions/**/*.test.ts\""],
|
|
1264
|
+
"gate": ["bash", "run.sh", "check-pi-durable-carrier"],
|
|
1265
|
+
"timeoutSeconds": 300,
|
|
1266
|
+
"signature": "[QK:PI-DURABLE-TEST-FIXTURES-NOT-SHIPPED]",
|
|
1267
|
+
"signatureSource": "pi-extensions/lib/pi-durable-carrier.test.ts",
|
|
1268
|
+
"build": { "argv": ["bash", "scripts/build-bridge.sh"], "output": "mcp/entwurf-bridge/dist" }
|
|
1269
|
+
},
|
|
1210
1270
|
{
|
|
1211
1271
|
"claim": "PI-DURABLE-STREAM-TRANSPORT-WIRE",
|
|
1212
1272
|
"title": "the Harness settings stop carrying the transport: the provider never continues a response, so every request of a long session resends the whole conversation",
|
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
"title": "one row of the pnpm workspace closure is left on the previous floor while every other surface moved — the shape a version bump actually fails in. Nothing else reads that file, so the stranded row surfaces only at install time, in a different command, far from the change that stranded it",
|
|
8
8
|
"subject": "pnpm-workspace.yaml",
|
|
9
9
|
"find": [
|
|
10
|
-
" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2 || 1.0.0 || 1.0.2 || 1.0.4 || 1.1.0 || 1.2.0 || 1.3.0'"
|
|
10
|
+
" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2 || 1.0.0 || 1.0.2 || 1.0.4 || 1.1.0 || 1.2.0 || 1.3.0 || 1.4.0'"
|
|
11
11
|
],
|
|
12
12
|
"replace": [
|
|
13
|
-
" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2 || 1.0.0 || 1.0.2 || 1.0.4 || 1.1.0 || 1.2.0'"
|
|
13
|
+
" - '@earendil-works/pi-telemetry@0.85.0 || 0.85.1 || 0.86.0 || 0.87.0 || 0.87.1 || 0.99.1 || 0.99.2 || 1.0.0 || 1.0.2 || 1.0.4 || 1.1.0 || 1.2.0 || 1.3.0'"
|
|
14
14
|
],
|
|
15
15
|
"gate": ["bash", "run.sh", "check-dep-versions"],
|
|
16
16
|
"timeoutSeconds": 300,
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"claim": "PI-SDK-PRODUCTION-SET",
|
|
22
22
|
"title": "the durable library's production pin falls one release behind the SDK set the pin declares, so the carrier would bind a pi-durable nobody verified it against",
|
|
23
23
|
"subject": "package.json",
|
|
24
|
-
"find": ["\"@earendil-works/pi-durable\": \"1.
|
|
25
|
-
"replace": ["\"@earendil-works/pi-durable\": \"1.
|
|
24
|
+
"find": ["\"@earendil-works/pi-durable\": \"1.4.0\","],
|
|
25
|
+
"replace": ["\"@earendil-works/pi-durable\": \"1.3.0\","],
|
|
26
26
|
"gate": ["bash", "run.sh", "check-dep-versions"],
|
|
27
27
|
"timeoutSeconds": 300,
|
|
28
28
|
"signature": "[QK:PI-SDK-PRODUCTION-SET]",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"title": "an @earendil-works package returns as a dev dependency beside its production pin, one name in two dependency classes",
|
|
34
34
|
"subject": "package.json",
|
|
35
35
|
"find": ["\"@biomejs/biome\": \"^2.4.13\","],
|
|
36
|
-
"replace": ["\"@biomejs/biome\": \"^2.4.13\",\n\t\t\"@earendil-works/pi-ai\": \"1.
|
|
36
|
+
"replace": ["\"@biomejs/biome\": \"^2.4.13\",\n\t\t\"@earendil-works/pi-ai\": \"1.4.0\","],
|
|
37
37
|
"gate": ["bash", "run.sh", "check-dep-versions"],
|
|
38
38
|
"timeoutSeconds": 300,
|
|
39
39
|
"signature": "[QK:PI-SDK-NO-DUAL-DECLARATION]",
|
|
@@ -1082,7 +1082,8 @@ async function run(): Promise<void> {
|
|
|
1082
1082
|
const codexWaitToken = `CODEX-WAIT-${Math.random().toString(36).slice(2, 10).toUpperCase()}`;
|
|
1083
1083
|
const finalToken = `CODEX-PI-FINAL-${Math.random().toString(36).slice(2, 10).toUpperCase()}`;
|
|
1084
1084
|
expectedReportTokens.push(finalToken);
|
|
1085
|
-
const outboundPiTask =
|
|
1085
|
+
const outboundPiTask =
|
|
1086
|
+
"Your automatic callback is the whole task and there is no result to send. After it succeeds, end the turn: no message, no report, no further tool call. Do not open another sibling.";
|
|
1086
1087
|
const codexTask =
|
|
1087
1088
|
`After your required callback receipt, end the turn and wait passively for the addressed instruction containing ${codexWaitToken}. ` +
|
|
1088
1089
|
"Do not call shell, sleep, terminal, or any tool to wait.";
|
|
@@ -110,9 +110,16 @@ fi
|
|
|
110
110
|
|
|
111
111
|
PI_SPEC="$(node -p "require('$REPO/package.json').dependencies['@earendil-works/pi-coding-agent']")"
|
|
112
112
|
# Pinned, not floating: a receipt that cannot say WHICH Claude Code it ran is not
|
|
113
|
-
# reproducible.
|
|
114
|
-
#
|
|
115
|
-
|
|
113
|
+
# reproducible. The exact version is the support floor itself, derived from
|
|
114
|
+
# `package.json` `entwurf.claudeCodeFloor` rather than retyped: a hand-kept pin stayed at
|
|
115
|
+
# 2.1.278 after the floor moved to 2.1.306 and the activation then refused it, as it should.
|
|
116
|
+
# Claude Code is scaffolding here (Rule 17) — the product face starts at `herdr integration install`.
|
|
117
|
+
CLAUDE_FLOOR="$(node -p "require('$REPO/package.json').entwurf.claudeCodeFloor")"
|
|
118
|
+
CLAUDE_SPEC="${CLAUDE_FLOOR#>=}"
|
|
119
|
+
if [[ "$CLAUDE_FLOOR" != ">=$CLAUDE_SPEC" || ! "$CLAUDE_SPEC" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
120
|
+
echo "[smoke-herdr-raw-install-live] FAIL — package.json entwurf.claudeCodeFloor is '$CLAUDE_FLOOR', not '>=X.Y.Z'." >&2
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
116
123
|
FLOOR_SPEC="$(node -p "require('$REPO/package.json').engines.node")"
|
|
117
124
|
FLOOR_MAJOR="${FLOOR_SPEC#>=}"; FLOOR_MAJOR="${FLOOR_MAJOR%%.*}"
|
|
118
125
|
HERDR_VERSION="$(node -p "require('$REPO/scripts/fixtures/herdr-supply.json').version")"
|