@junghanacs/entwurf 0.50.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +80 -0
- package/README.md +12 -4
- package/VERIFY.md +16 -9
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +2 -2
- package/docs/setup-clean-host.md +65 -18
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +4 -4
- package/package.json +11 -18
- package/pi/pi-durable/carrier/runtime.js +221 -50
- package/pi/pi-durable/carrier/subagent.js +5 -2
- package/pi/pi-durable/carrier/tui.js +60 -22
- package/pi/pi-durable/overlay/upstream-pin.json +17 -16
- package/pi-extensions/lib/entwurf-v2-contract-schema.ts +73 -69
- package/pi-extensions/lib/entwurf-v2-contract.ts +4 -4
- package/pi-extensions/meta-bridge-pi-durable.ts +1 -1
- package/run.sh +141 -42
- package/scripts/check-entwurf-v2-contract.ts +4 -4
- package/scripts/check-gate-qualification.ts +2 -2
- package/scripts/mutants/control-send-receipt.json +1 -1
- package/scripts/mutants/pack-install.json +4 -4
- package/scripts/mutants/pi-durable.json +189 -3
- package/scripts/mutants/pi-floor.json +22 -5
package/AGENTS.md
CHANGED
|
@@ -104,9 +104,10 @@ implement → affected focused gates → independent review → one amendment bu
|
|
|
104
104
|
|
|
105
105
|
## Type and Working Boundaries
|
|
106
106
|
|
|
107
|
-
- Each `.ts` file belongs to one declared typecheck fence; `exclude` may move a file between fences but never out of all of them, so an exclude states the receiving `include` in the same change.
|
|
107
|
+
- Each `.ts` file belongs to one declared typecheck fence; `exclude` may move a file between fences but never out of all of them, so an exclude states the receiving `include` in the same change. The pi-facing contract schema uses builders and schema types from `@earendil-works/pi-schema` and `StringEnum` from `@earendil-works/pi-ai`; MCP/scripts use explicit `.ts` imports required by Node strip-types. Installed surfaces route to compiled JS. Behavior-adjacent `.test.ts` takes the fence `test/` takes — `scripts/tsconfig.json`, never the emit-capable root program — and is kept out of the tarball by a files-array negation whose tripwire is `check-pack`.
|
|
108
108
|
- Develop only on branches in this repository checkout; never use worktrees or tmp development clones. Isolated test fixtures and temporary evidence are not development checkouts.
|
|
109
109
|
- Make surgical, one-contract changes. Removal repairs source and its proof together; a green gate never proves retired behavior.
|
|
110
|
+
- A requested Pi SDK upgrade defaults to existing native authentication after coherent candidate installation, not a new login or credential copy. Do not re-ask that strategy each bump. Operating owner exit, consistent full session backup and the human-owned shutdown/reopen window remain gates; auth reuse grants no autonomous cutover, retirement or publication. The decision and #148 receipts are in [the SDK upgrade radius](./docs/setup-clean-host.md#default-radius-for-a-requested-pi-sdk-upgrade).
|
|
110
111
|
- Before commit, sweep repository-wide for retired authority vocabulary and landed-plan future tense. Historical tombstones may remain; live docs, source, gates, and usage must agree.
|
|
111
112
|
- Prefer capability-domain language over identity rank. Use tabs unless the project formatter requires otherwise. GLG decides commit, push, and release gates.
|
|
112
113
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,86 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.51.0 — 2026-11-04
|
|
8
|
+
|
|
9
|
+
Entwurf now runs on the Pi 1.5.0 SDK set (#155). The exact SDK closure grows from nine to ten members, the supported host Pi range moves to `>=1.5.0 <1.6`, and the pi-durable carrier follows the 1.5 durable API. An operating host moves to this version only through a planned cutover, because SDK 1.5's first write to a durable session is not readable by SDK 1.4.
|
|
10
|
+
|
|
11
|
+
What this release is not: it adds no MCP tool (the nine tools are unchanged) and no new authority. It adopts no 1.5 feature beyond what the migration requires. Hosts that stay on the published 0.50.0 / Pi 1.4.0 SDK set keep following the published 0.50.0 instructions, which remain checked separately.
|
|
12
|
+
|
|
13
|
+
### Pi SDK 1.5.0 (#155)
|
|
14
|
+
|
|
15
|
+
- **Exact SDK set.** All ten `@earendil-works/*` members are pinned at exactly 1.5.0: chord, pi-agent-core, pi-ai, pi-codemode, pi-coding-agent, pi-durable, pi-mcp, pi-schema (new), pi-telemetry and pi-tui. The pi-durable overlay pin moves with them.
|
|
16
|
+
- **Host range.** The supported host Pi range is derived from the pinned SDK and is now `>=1.5.0 <1.6`; setup and `install-user-scope` refuse a detected pi outside it. A 1.4 host is outside the range of this version; install host Pi 1.5 by exact version.
|
|
17
|
+
- **Tool schemas on pi-schema.** pi-ai 1.5.0 no longer exports TypeBox's `Type`, and upstream pi-durable 1.5.0 drops its `typebox` dependency. The `entwurf_v2` contract schema and the pi-durable subagent tool are built with `@earendil-works/pi-schema` builders; the subagent tool's input stays open (`{ open: true }`) so it accepts what it accepted before. The optional `typebox` peer dependency and its `peerDependenciesMeta` entry are removed from the package.
|
|
18
|
+
- **pi-durable carrier on the 1.5 durable API.** The carrier no longer calls the removed `viewState()`, `taskGraph()` and `subscribeCommits()`. The transcript shows the SDK's whole active transcript (`Conversation.context().entries`, head marker first), not the latest entries of the 1.5 conversation window: it is read once, a watch attached right after that read appends later entries in ID order, and a compaction, a reset or a window that skipped entries reads it again from the SDK (#155 D1). A read that lands after a switch, the close or the session's own failure is dropped, and a read that fails is reported on screen as stopped updating, without a retry. The task panel follows `watchTaskGraph()`, and commits are observed through `observeCommits()`, whose end decides nothing because SDK 1.5 ends it `failed` at a normal close as well. Whether a session ended closed or failed is read from the session end's `kind`; the 1.4 `reason` field is absent in 1.5 and would otherwise read every end as closed. Reports show `report.error`, compaction status shows its `trigger`, and a run that ended without an answer stays visible as `pi.live.runFailure`.
|
|
19
|
+
- **Durable data and rollback boundary.** SDK 1.5 keeps SQLite schema version 2 but stores `pi.live` at version 3, `pi.generation` at 2 and `pi.tool` at 3; SDK 1.4 refuses a session after 1.5 has written it. Two synthetic sessions written by SDK 1.4, one closed and one killed, with a hashed golden manifest, are opened by 1.5 without a resume or new input. A storage open keeps schema version 2 and every row. A Harness open that only reads the root conversation, the live document and the task inspection stores no new document version and changes exactly the tables SDK 1.4's own reopen of the same file changed: none for the closed session, the `durable_metadata` and `tasks` rows for the killed one, where the open runs crash recovery. The first 1.5 write stores `pi.live` at the version SDK 1.4 refuses. This is fixture evidence for those two files. It does not show that the database is opened read-only, and it does not certify compatibility or recovery for operating data. Upstream states that restart-limited tasks no longer park in 1.5 and end visibly instead; this release does not measure that behaviour.
|
|
20
|
+
- **Published recipes stay separate.** Documentation regions marked `entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0` keep describing the published 0.50.0 package and are checked by `check-dep-versions` against a frozen record of that artifact, independent of the development floor.
|
|
21
|
+
|
|
22
|
+
### Release and upgrade workflow
|
|
23
|
+
|
|
24
|
+
- **Default radius for a Pi SDK upgrade.** A requested SDK upgrade reuses the existing native authentication after a coherent installation; it does not make a fresh login or credential copy a prerequisite. Isolated, authentication-free checks come first; the operating window keeps normal owner exit, a consistent backup of the whole durable-session directory and same-identity reattachment. The decision does not authorize a cutover, retirement or publication ([setup](docs/setup-clean-host.md#default-radius-for-a-requested-pi-sdk-upgrade)). Setup also records the recurring SDK rail.
|
|
25
|
+
- **Persistent release candidates.** `make` creates each candidate in a private, uniquely named directory under `${XDG_STATE_HOME:-~/.local/state}/entwurf-releases/<version>-<sha12>/` instead of `/tmp`, keeps failed candidates, and never relocates a candidate or adds a `current` alias.
|
|
26
|
+
- **One human publish line.** After U0 passes and a named pre-publication receipt records both dist-tags, the handoff prints exactly one shell-quoted line, `cd ~/repos/gh/entwurf && npm publish <canonical tgz> --tag <latest|repair>`. U2 restores its baseline from that receipt rather than from the post-publish registry. The supported dist-tags are `latest` and `repair`.
|
|
27
|
+
- The `entwurf-dev` skill is narrowed to the citizen lifecycle; release and upgrade ordering live in the release skill and setup.
|
|
28
|
+
|
|
29
|
+
### Herdr plugin
|
|
30
|
+
|
|
31
|
+
The first five bullets record the plugin's re-pin to the published npm 0.50.0 runtime, made after the 0.50.0 release (`f45a95a`); they describe that runtime's Pi 1.4.0 SDK set, not this release's. The last bullet is this release's change.
|
|
32
|
+
|
|
33
|
+
- Pinned the published npm `@junghanacs/entwurf@0.50.0` with its measured registry sha512 and align the plugin manifest to 0.50.0. The downloaded registry tarball is byte-identical to the accepted Windows-carrier core artifact (SHA-256 `64ca198067d8ad5265f89a903efdaa3e7946bfe7ba3a83dd27009a878631afba`). This closes the prepare-time `herdr-checkout` window described below; the core tag, npm bytes and historical 0.50.0 release section are unchanged.
|
|
34
|
+
- Kept the Pi 1.4.0 SDK set and host range `>=1.4.0 <1.5`. The owning install guides name 0.50.0; the root README's unpinned entrance is unchanged. A checkout-source installation must explicitly deactivate before reinstalling this npm-source pin; a settled npm-source host follows the existing rebind/ownership rules. No operator installation or working session is automatically changed.
|
|
35
|
+
- Source-specific verification: registry metadata reports `latest=0.50.0`, `repair=0.12.8-repair.1` and 668 files. The downloaded registry tarball's SHA-512 and SHA-1 equal `dist.integrity` and `dist.shasum`; SHA-256 and `cmp` match the accepted core artifact. No immediate pre-publish dist-tag snapshot was collected by the agent, so `repair` preservation is observed against the earlier dated reading, not claimed as a measured publication delta. The unchanged tarball's Windows and Linux package-consumer acceptance is explicitly reused, not re-run.
|
|
36
|
+
- A private registry-installed Pi 1.4.0 consumer resolved the bridge inside its own installed root and listed seven `entwurf` model rows without a model turn. Its registry-shipped `herdr-runtime.mjs` is byte-equal to this checkout's. That helper acquired real npm 0.45.0, swapped to 0.50.0, restored the previous runtime before acquiring again in a manually seeded `torn-swap-with-candidate` state, skipped acquisition on an exact re-request, and removed its owned sandbox runtime/cache/journal. This is not recovery from an actual kill or a harness activation proof.
|
|
37
|
+
- The public-ref install/use/activation/deactivation journey and pushed-SHA CI receive their own post-push receipts; prior checkout-carrier or older npm receipts are not those measurements. No plugin snapshot tag is claimed by this commit.
|
|
38
|
+
- **This prepare returns the lock to the verification carrier.** Core 0.51.0 has no published bytes while it is prepared, and an npm lock must name the checkout's own version, so `plugins/herdr/runtime-lock.json` goes back to the closed `herdr-checkout` source, as the 0.50.0 and earlier candidates did. No npm version or integrity is invented for 0.51.0 and the plugin manifest version is not bumped. An install that tracks this source builds its runtime from the checked-out commit; a host switching from npm runs `herdr-plugin-deactivate` first. Hosts that installed the npm 0.50.0 runtime keep running it (Pi 1.4.0 SDK set) until they reinstall. A separate step re-pins npm 0.51.0 once it is published.
|
|
39
|
+
|
|
40
|
+
### Upgrade
|
|
41
|
+
|
|
42
|
+
- **Operating hosts** move in one planned window, following the [SDK upgrade radius](docs/setup-clean-host.md#default-radius-for-a-requested-pi-sdk-upgrade) and the cutover conditions in [#155](https://github.com/junghan0611/entwurf/issues/155): close the old owners normally and prove they exited, back up the whole durable-session directory (including `-wal`/`-shm`) as one consistent set before the first 1.5 open, install host Pi at the pinned exact version 1.5.0 rather than through a bare `pi update`, install this package and move the user-scope ownership with `entwurf takeover-user-scope`, check the doctors, then reopen the same identities. Installing an older package afterwards is not a data rollback: returning a session to SDK 1.4 requires restoring the consistent backup taken before the first 1.5 open, and work done after that open is not in it.
|
|
43
|
+
- **Checkout-run hosts** refresh the bytes each surface actually loads. Ordinary Pi and pi-durable require `pnpm run build-bridge`, accepted output/SDK verification, then a new host process; copied hook/extension units require their owning installer. Follow [Applying new source to a running host](docs/setup-clean-host.md#applying-new-source-to-a-running-host) before restarting sessions. An already-running bridge keeps the modules it loaded.
|
|
44
|
+
- **Claude Code hosts** re-run `entwurf install-meta-bridge`, then restart open Claude Code sessions in the operator's own order. An already-running bridge keeps the modules it loaded.
|
|
45
|
+
- **npm consumers** re-run `entwurf setup` in the same scope, then `check-bridge`.
|
|
46
|
+
|
|
47
|
+
### Release evidence
|
|
48
|
+
|
|
49
|
+
- Source checkpoint: `c95bd66`, branch push CI run 41587081824, all four required jobs successful. This is that checkpoint's evidence, not the prepared SHA's CI.
|
|
50
|
+
- Prepare-time floor: working tree over `c95bd66` (index tree `6824440955ce`), patch `7081abf50b08447c89739976b825a30c0ded390188c7a058c7f48d04e8be5417`, before the branch handoff edits and this evidence wording. The managed build left the 99-file compiled manifest byte-identical (`3c3c679a466c5489d921960f082f1024bf6774b2f4fa1115173bed68c6386d85`). `check:full` ran 959 s, exit 0. The checkout-only pi-durable cells passed against that compiled bridge: `check-pi-durable-contact` 91, `check-pi-durable-send` 19, its `native-module` cell 14 and `check-pi-durable-receive` 21, 0 failed (V not run). The candidate seal was identical before and after.
|
|
51
|
+
- LIVE release gate: working tree over `c95bd66`, same index tree and compiled manifest, patch `c8295e54606dbe3f9aaa0abcadf3e4a818d3b1466525969b8e2bb2591c4b5289` (the floor's patch plus branch handoff edits, before this evidence wording). `release-gate --cut` ran once on 2026-11-03 from 21:03:41 to 21:24:44 KST (1262 s), with `check:full` 953 s exit 0, MUST PASS=24 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0 SKIP=0, cut OK. Scratch/log: `/tmp/entwurf-release-gate-0.51.0.WGGdxZ/release-gate.log`, 598,872 bytes, SHA-256 `059bf77d197a5c10fd0dc0d0697839edae59380d3d9c9c385c08164365ed3ede`; the operator evidence copy is byte-identical (`cmp`). The candidate seal (HEAD, index tree, porcelain, changed-path bytes, compiled manifest) was identical before and after the gate.
|
|
52
|
+
- That gate ran on the operating host after the cutover below, so its LIVE steps used host Pi 1.5.0 and the installed 0.51.0 validation package with the existing native authentication. Codex CLI 0.166.0 used an operator-owned app-server started for this run in its own tmux session, not the gate's, with models `gpt-6-luna` / `openai-codex/gpt-6.1-terra`; it was stopped afterwards. The wrapper ran in the real HOME with `PI_SESSION_ID`, `PI_AGENT_ID`, `CI` and the Claude Code session variables removed, and both verify-deps settings at `error`. `CLAUDE_CONFIG_DIR` was not in that removal list: it was absent from a sample of the gate session's running process tree taken during the run, from the tmux global environment and from the launching shell, so its absence was sampled, not enforced by the wrapper. A corrected wrapper that also removes it was written during the run and has not been run.
|
|
53
|
+
- Host residue after the gate, read-only: no reparented process from the gate and no process using its paths. Its scratch, the pi-durable fresh-live receipts and the chain smoke's records were kept as evidence. `check:full`'s `herdr-resume-call` and `mux-resume-call` tests leave two directories per prefix per run (eight here, at most 34 bytes each); they are recorded as a finding and were not deleted.
|
|
54
|
+
- Installation-validation tarball: unpublished and addon-less, packed from the floor's candidate, SHA-256 `199e5f41d20e5b2665125868b7e3e27740e5985f7a25ac61902126b7ed638bf5` (11,611,560 bytes), accepted by the unchanged Linux container (`validation-acceptance.log` SHA-256 `e505f5e9ec3982ad3091ac6582a1d3832573b5933a42e0aaf02325b8f1f70efe`). It carries no Windows build and is not the release candidate, which `make` produces from the prepared SHA. An isolated rehearsal of the global ownership transition passed (old 0.50.0 owner, then a normal install refused with exit 6 and settings unchanged, then an explicit `takeover-user-scope` to 0.51.0; run log SHA-256 `4d84a7b3433f7097d606b83d097facec25f5ea9a9a6a1559a665f21e081a6c00`).
|
|
55
|
+
- Operating cutover on the maintainer host, 2026-11-03 20:46–20:49 KST, under the [#155](https://github.com/junghan0611/entwurf/issues/155) conditions. Four operating owners were closed normally and classified dead by the product's owner check, with no durable file holder and no lock left. The whole durable-session directory (171 files, 487,281,652 bytes; source-before, backup and source-after manifests identical, SHA-256 `5c08bed1968fd1e26baa58112f0ce5c36874e147ccc5e9b4c69ec1a0d9070a46`) and the two Pi transcripts were backed up before the first 1.5 open. Host Pi 1.5.0 was installed by exact version once all ten SDK members had passed pnpm's one-day release age, with the global pnpm policy file unchanged. The validation tarball above was installed and `takeover-user-scope` moved ownership to its root. The doctors reported ownership (`owned — this root`) and runtime (nine tools boot) separately, and the ten SDK members resolve to 1.5.0 from that root. The same identities were then reopened and the main pi-durable citizen made real turns on 1.5. A pi-durable same-id resume through `entwurf_resume_call` came back without the operator's `--native-module`, as its bridge-only launch contract states; the operator restarted that citizen by hand with its module.
|
|
56
|
+
- Native Claude Code host after the cutover (VERIFY pass criterion 4), 2026-11-03 21:37–21:39 KST: a fresh Claude Code fixture opened through `entwurf_fresh_call` called back with its exact launch nonce. Its receiver and sender markers join its record (native session id and attach incarnation, with the owner's start key re-measured live). Its direct MCP child is the 0.51.0 bridge from the installed root, reached through the bare `entwurf-bridge` user-scope command, and no 0.50.0 bridge runs under it. The installed `doctor-meta-bridge` passed while the fixture was alive, with the deployed writer and hook lock module matching source. This was measured on the validation installation, not the release artifact, and Claude Code sessions opened before the cutover were not restarted.
|
|
57
|
+
- Not covered by the above: the operating root is the validation tarball, not the published artifact, and rebinding operation to the registry's 0.51.0 is a separate step after publication. Claude Code sessions that were already open keep the 0.50.0 bridge they loaded until they restart. One Claude Code citizen's dedicated MCP file still names the 0.50.0 root, pending its operator's own decision; that root stays installed. Exact prepared-SHA CI, the Windows-carrier candidate and its Linux acceptance, installed-host acceptance of the release artifact and the registry proof need their own receipts. npm publication is GLG's own action.
|
|
58
|
+
- **D1 transcript repair after that gate.** The transcript change above (#155 D1) landed after the gate and the cutover above, as the checkpoint `20426b2` over `434874e`. It changes the pi-durable carrier and its pin, not the compiled bridge or the SDK set: the 99-file compiled manifest stays `3c3c679a466c…`. The carrier qualification group ran on working-tree candidates over `434874e`, before that checkpoint commit. Its first run was red: it killed 65 of 66 claims, and the `ACTIVE-SEED` claim failed for the wrong reason because the test's setup failed before its assertion ran. After a one-line observer fix in the test, a second run on the corrected working tree killed 66 of 66 with both controls green; that receipt (head `434874e`, surface `b6cee8925072`) is listed below as an earlier-candidate PARTIAL.
|
|
59
|
+
- LIVE release gate on the D1 checkpoint:
|
|
60
|
+
- **Candidate.** HEAD `20426b2` (tree `ba596c153283`) with working patch `b8172a65fd356db69a5f00d52c54ab84aeb75496acefab815dc855978124ba5c`, which touches only this file and the branch handoff and predates this evidence wording. The compiled manifest `3c3c679a466c…` was byte-identical after a managed build.
|
|
61
|
+
- **Result.** `release-gate --cut` ran once on 2026-11-04, from 03:02:41 to 03:23:10 KST (1229 s); the wrapper around it, including the managed build and the seals, ran from 03:02:34 to 03:23:11. Its own `check:full` was the first MUST step and ran 963 s, exit 0; no separate offline full floor was run for this candidate. MUST PASS=24 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0 SKIP=0, cut OK.
|
|
62
|
+
- **Integrity.** Log SHA-256 `d16537ca4455498c6a371bc80a869d0de70832d30d86d770ccbc8212427380c2`; the scratch original and the evidence copy are identical. The candidate seal was identical before and after the gate (`37446ea0a4f5…`).
|
|
63
|
+
- How that gate reached the new source:
|
|
64
|
+
- **PATH.** `entwurf` on the gate's PATH resolved to this checkout's `run.sh` through a private directory holding only that link. `entwurf-bridge`, `entwurf-statusline` and `pi` stayed the installed 0.51.0 validation root.
|
|
65
|
+
- **Witness.** A read-only process sampler ran for the whole gate. It observed that the pi-durable fresh-live fixture's host ran this checkout's carrier bootstrap and resolver, that the host owned the new location whose garden is the smoke's pi-durable record, and that the host's `entwurf-bridge` child ran from this checkout's compiled bridge. The fixture's initial visible Pi ran the installed validation root's bridge.
|
|
66
|
+
- **Limit.** The sampler judged only that fixture; which root each other LIVE step loaded was not observed.
|
|
67
|
+
- That gate's environment:
|
|
68
|
+
- **Host and auth.** It ran in the real HOME with the existing native authentication.
|
|
69
|
+
- **Removed variables.** Exactly these names were removed: `PI_SESSION_ID`, `PI_AGENT_ID`, `CI`, `CLAUDE_CONFIG_DIR`, `CLAUDECODE`, `CLAUDE_CODE_SESSION_ID`, `CLAUDE_CODE_ENTRYPOINT`, `CLAUDE_CODE_CHILD_SESSION`, `CLAUDE_CODE_MESSAGING_SOCKET`, `CLAUDE_CODE_MESSAGING_TOKEN`, `CLAUDE_PID`, `ENTWURF_CALLBACK_TARGET`, `ENTWURF_CALLBACK_NONCE` and `ENTWURF_META_SENDER_MARKER`. Both verify-deps settings were `error`.
|
|
70
|
+
- **Models.** Codex CLI 0.166.0 used `gpt-6-luna`, with `openai-codex/gpt-6.1-terra` for its callback Pi; the pi-durable fresh-live fixture's pi-durable host and its initial Pi used `openai-codex/gpt-6.1-sol`.
|
|
71
|
+
- **Codex app-server.** A dedicated app-server was started for this run in its own tmux session, not the gate's, and stopped after the gate. Before the gate, the launch helper's own listener check stopped with exit 3: it looked for the control path's text, but the socket is reached through Codex's rendezvous alias. A follow-up check found the same app-server process, with the same pid and start time, listening on the alias's target, and the gate ran against it.
|
|
72
|
+
- Host residue after that gate (read-only, nothing deleted):
|
|
73
|
+
- No smoke private tmux server and no new reparented process naming `/tmp` were observed, and this run's own app-server, sampler and pi-durable host were gone; the one reparented process naming `/tmp` predates the run.
|
|
74
|
+
- `check:full`'s `herdr-resume-*` and `mux-resume-call-pd` tests again left two directories per prefix (eight, 0–34 bytes each), and the chain smoke left one.
|
|
75
|
+
- Its scratch, the pi-durable fresh-live receipts and the run evidence were kept.
|
|
76
|
+
- The native Claude Code receipt above (criterion 4) remains evidence for the unchanged bridge and SDK on the validation installation. It was not repeated for D1, and that installed root does not carry the D1 carrier.
|
|
77
|
+
- Not run for the D1 checkpoint: CI for the shipped SHA, the Windows-carrier candidate and Linux acceptance of that same tarball, installing D1 on the operating host, npm publication and the registry proof.
|
|
78
|
+
- The gate validated the manifest's 1506 claims across 94 lanes without executing the qualification body (#144).
|
|
79
|
+
- The 2026-11-04 gate on the D1 checkpoint validated the manifest's 1513 claims across 94 lanes without executing the qualification body (#144).
|
|
80
|
+
- Kill-power re-measured at this shipped SHA: none (all 1513 committed claims not re-proved, #144).
|
|
81
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head fe4780ee5c82 surface 811db89aeab8 -- ["bash","run.sh","check-pack-pin-matcher"] 2/2 receipt bffbc106e427
|
|
82
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head fe4780ee5c82 surface 811db89aeab8 -- ["bash","run.sh","check-dep-versions"] 5/5 receipt d890494fb815
|
|
83
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head fe4780ee5c82 surface 811db89aeab8 -- ["bash","run.sh","check-acp-vendor-rejection"] 4/4 receipt ff9a31e78a1d
|
|
84
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head fe4780ee5c82 surface 811db89aeab8 -- ["bash","run.sh","check-pi-durable-carrier"] 59/59 receipt 0558e6e723a7
|
|
85
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 434874ef6d6e surface b6cee8925072 -- ["bash","run.sh","check-pi-durable-carrier"] 66/66 receipt 822f2d8b950e
|
|
86
|
+
|
|
7
87
|
## 0.50.0 — 2026-11-02
|
|
8
88
|
|
|
9
89
|
Same-id resume now reaches every resumable backend on both launch rails. A dormant pi, pi-durable or Claude Code citizen reopens under its own garden id in a visible tmux window or, inside Herdr, a new Herdr tab, with no fallback from one rail to the other (#157). The CLI gains one description source, safe help and a thin `entwurf claude` entry (#153, continued in #157).
|
package/README.md
CHANGED
|
@@ -86,13 +86,21 @@ entwurf pi-durable --resume
|
|
|
86
86
|
entwurf pi-durable --session <native id>
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
The package supplies Entwurf's thin app/TUI carrier
|
|
90
|
-
|
|
89
|
+
The package supplies Entwurf's thin app/TUI carrier, emitted from its own canonical production
|
|
90
|
+
source, and the exact pi SDK set it declares; the launch verifies both and refuses incomplete,
|
|
91
|
+
drifted or mixed supply by name. No separate runtime checkout,
|
|
91
92
|
patch, build or ordinary Pi CLI is needed. The contact adds garden identity and two-way mailbox
|
|
92
93
|
communication; execution, models, auth, queues, storage and recovery stay the upstream SDK's
|
|
93
94
|
([Hard Rule 17](./AGENTS.md#hard-rules): **supply the missing surface; do not become the harness**).
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
On a CLI reopen, name the original `--native-module <absolute file>` or
|
|
96
|
+
`--native-module-dir <absolute directory>` again if needed. Public garden-id
|
|
97
|
+
`entwurf_resume_call` is bridge-only: it restores neither those modules nor the old seat. To retain
|
|
98
|
+
them, use the explicit CLI in the terminal you choose, after confirming the old owner has exited.
|
|
99
|
+
For an SDK upgrade, normally close the owner and back up the complete SQLite session file set,
|
|
100
|
+
including WAL/SHM, before the first write; verify the exact version and artifact, then reopen the
|
|
101
|
+
same identity. [Setup §2b](./docs/setup-clean-host.md#2b-optional-native-durable-pi-durable) owns
|
|
102
|
+
selectors and refusals; the [SDK upgrade boundary](./docs/setup-clean-host.md#default-radius-for-a-requested-pi-sdk-upgrade)
|
|
103
|
+
owns the operating and publication gates.
|
|
96
104
|
|
|
97
105
|
### Herdr workbench
|
|
98
106
|
|
package/VERIFY.md
CHANGED
|
@@ -239,12 +239,19 @@ holds that node and the badge counts it, `pending` while recovered), and the car
|
|
|
239
239
|
`durableLayout` drawn by the published pi-tui renderer on a fake terminal across rows 1–8 × cols
|
|
240
240
|
1–12, count changes and resizes, against the pinned upstream screen for the zero-task case. Its
|
|
241
241
|
editor is a fixed stand-in: the real `CustomEditor`, overlays, emoji width and a consumer's own task
|
|
242
|
-
are the visible-terminal and consumer subjects.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
242
|
+
are the visible-terminal and consumer subjects. Another sandboxed child holds the active transcript the
|
|
243
|
+
TUI renders (#155 D1): the carrier runtime over a session seeded through the SDK's public API, through
|
|
244
|
+
an open with a commit between its read and its watch, appends, one commit past the window's 100, a
|
|
245
|
+
switch away and back, compaction-like and reset head markers, a read held across a switch, a refused
|
|
246
|
+
read and the close. Its oracles are the entry IDs the SDK returned and, after close, a non-participant
|
|
247
|
+
open's `Conversation.context().entries`; the SDK boundary is steered test-only at the Conversation
|
|
248
|
+
prototype the child and carrier share. The bootstrap child on the pinned set also observes `--resume`
|
|
249
|
+
reopening the chosen session, by what its screen shows, and cancelling to nothing (#143). Two more
|
|
250
|
+
sandboxed children reach the owned app's settings and prompt mapping: one drives the real bootstrap
|
|
251
|
+
against a loopback WebSocket Responses endpoint, whose received frames decide the forwarded transport
|
|
252
|
+
and its continuation and the SDK's compaction policy under those settings (the SDK's background summary beside the turn, held on the
|
|
253
|
+
wire while the turn answers; blocking and overflow kept, #146), each placed summary, manual ones
|
|
254
|
+
included, heading the screen's active transcript; the other renders the carrier prompt's skills section with no model, against a fixture
|
|
248
255
|
of both settings scopes, an absolute entry, a same-name pair and a wrong-base decoy.
|
|
249
256
|
`check-pi-runtime-version` asks the
|
|
250
257
|
same installed verifier (`check-pi-durable-beside`) whether this checkout resolves exactly the pinned SDK set (the native set; the PATH
|
|
@@ -269,8 +276,8 @@ constructed depth-3 mismatch refused by the verifier and seen by the oracle, the
|
|
|
269
276
|
app's own model refusal before any birth — also with one installed `--native-module` initialized
|
|
270
277
|
first, a reserved extension name refused before anything opens, one installed `--native-module-dir`
|
|
271
278
|
initializing only its top-level `*.extension.mjs` (#134) and a directory without a module refused
|
|
272
|
-
before anything opens — and the HOST kept a separate subject — a real pi 1.
|
|
273
|
-
binary (the previous generation) beside the pinned native set is a named pi FAIL with zero Pi wiring while pi-durable still
|
|
279
|
+
before anything opens — and the HOST kept a separate subject — a real pi 1.2.0
|
|
280
|
+
binary (below the supported range; a fixture version, not the pinned set's previous generation) beside the pinned native set is a named pi FAIL with zero Pi wiring while pi-durable still
|
|
274
281
|
PASSes — not native admission. The carrier's rebuild
|
|
275
282
|
equality is the owned source's emission (#141): the carrier claim `PI-DURABLE-CARRIER-EMIT-SOURCE-EQUAL`
|
|
276
283
|
on every floor, `emit-pi-durable-carrier --check` as its CLI. The emitter's exact Node is red in the CI
|
|
@@ -374,7 +381,7 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
374
381
|
**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
382
|
|
|
376
383
|
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.
|
|
384
|
+
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.5.0 <1.6`) 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
385
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
379
386
|
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
387
|
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.5.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.5.0`, host `>=1.5.0 <1.6` | **exact** oracle + **closed range** | the #155 development checkout's declared SDK set and derived host range, not a release or operating-host acceptance; an ordinary Pi host inside the range is accepted by the source's version predicate, 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 |
|
|
@@ -11,9 +11,9 @@ the one-line registration; everything an operator needs to actually wire a host
|
|
|
11
11
|
|
|
12
12
|
**Being garden-native is not the same as being replyable, and Copilot is the case that separates them.** Its hook writes a sender marker, so an `entwurf_v2` send carries its own garden id and the receiver learns who wrote — measured 2026-08-21 on Copilot CLI 1.0.80, where a live send arrived under its own garden id with `origin: "meta-session"` and `replyable: false`. Replyability arrived later and through a different process: a first-party extension (`run.sh install-copilot-receive`) that the CLI forks, which binds to the same V3 record and writes a receiver marker owned by its own pid (#82 RAIL 5). So a Copilot citizen is `replyable: true` exactly while that extension is armed for it, and `replyable: false` — honestly, with a real garden identity — when it is not installed, not launched with `COPILOT_CLI_ENABLED_FEATURE_FLAGS=EXTENSIONS` (which is what `entwurf copilot` sets for one invocation), not yet born, or gone. Read the two facts off different rails: the sender marker answers *who sent this*; the receiver marker answers *can a reply land*. The onboarding obligations are in [`adding-a-harness.md`](./adding-a-harness.md) step 7, and the evidence boundary — the managed LIVE acceptance that moved receive to D6, and what D7-partial / D3-pending still exclude — is in [`DELIVERY.md`](../DELIVERY.md).
|
|
13
13
|
|
|
14
|
-
**Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and the
|
|
14
|
+
**Which verb an external agent should reach for:** to deliver to / reply to a garden id, use **`entwurf_v2`** — it is the canonical delivery surface and resolves the target's current rail: a live pi control socket, a deliverable self-fetch mailbox (pi-durable, Claude Code, Copilot or OMP), or probe-alive Codex native push. Dormant pi and undeliverable targets reject; Antigravity native push is paused and rejects before probing (#152). Discover targets with `entwurf_peers`, confirm your own identity with `entwurf_self`, drain a mailbox with `entwurf_inbox_read`, and use `entwurf_register_native` only as the explicit/manual fallback for binding an already-running agy conversation. Open a NEW sibling with **`entwurf_fresh_call {backend, model, task, cwd?, placement?}`**, and reopen a DORMANT pi, pi-durable or Claude Code citizen under the same id with **`entwurf_resume_call {target}`**. **`entwurf_retire_call {target}`** (new in 0.41.0) attempts retirement of exactly one target, and only one the human operator explicitly requested; mounting or seeing the tool, a coordinator role or caller identity is not permission, and an unknown result is not a reason to replay.
|
|
15
15
|
|
|
16
|
-
Observed: Claude Code, Codex CLI, Antigravity CLI, GitHub Copilot CLI and OMP all reach this MCP bridge. Claude, Copilot and OMP become
|
|
16
|
+
Observed: Claude Code, Codex CLI, Antigravity CLI, GitHub Copilot CLI and OMP all reach this MCP bridge. Claude, Copilot and OMP become replyable through deliverable mailbox-backed meta-sessions; Codex uses native push, while Antigravity's native-push rail is paused (#152). Codex's identity is request-scoped `_meta.threadId`, and its replyability requires that exact record plus a loaded app-server thread. Plain external hosts still need an identity lane to send.
|
|
17
17
|
|
|
18
18
|
Prerequisites on the host running the external MCP client:
|
|
19
19
|
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -23,10 +23,11 @@ evidence split, and its three states must not collapse into "macOS is supported"
|
|
|
23
23
|
|
|
24
24
|
## Requirements
|
|
25
25
|
|
|
26
|
-
This table
|
|
26
|
+
This table and the 1.4-specific install examples below describe the published `@junghanacs/entwurf@0.50.0`, which ships the Pi 1.4.0 SDK set. The #155 0.51.0 preparation at `434874ef6d6e399a0ae6813c850d01c5232eb1d9` pins SDK 1.5.0; its separate validation TGZ was installed in the approved operating window, but is not the still-unpublished final shipping artifact. npm publication requires its own authority. See the [SDK 1.5 boundary](#sdk-15-development-boundary-155) below; these 0.50 instructions do not select or prove 0.51 bytes.
|
|
27
27
|
The previous package, `0.41.0`, ships the Pi 1.3.0 SDK set and requires Pi 1.3.x; the setup guide
|
|
28
28
|
inside that tarball is its contract.
|
|
29
29
|
|
|
30
|
+
<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->
|
|
30
31
|
| Component | Requirement | Needed for |
|
|
31
32
|
|---|---|---|
|
|
32
33
|
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
@@ -41,6 +42,7 @@ inside that tarball is its contract.
|
|
|
41
42
|
| Antigravity `agy` | optional, operator-installed and authenticated | legacy citizen; native push paused (#152) |
|
|
42
43
|
| OpenAI Codex CLI | optional-by-presence, operator-installed and authenticated; detected composes all four operator-owned units (birth/MCP/status-line/terminal-title) and stays non-green until the operator trusts the birth declaration once in a visible Codex; visible fresh also requires the operator-owned app-server, started with `entwurf codex-app-server` in a tmux session of the operator's choosing (#95 D1 retired the fixed `codex` home) | native-push and visible fresh, supported in 0.21.0 |
|
|
43
44
|
| Cortex Code | optional, operator-installed and authenticated | Cortex ACP backend |
|
|
45
|
+
<!-- /entwurf:published -->
|
|
44
46
|
|
|
45
47
|
Claude Code >=2.1.306 is required for the managed exec-hook lifecycle and same-id resume. The package
|
|
46
48
|
never supplies or proxies backend credentials.
|
|
@@ -83,7 +85,7 @@ node --version
|
|
|
83
85
|
npm --version
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
The two npm forms below install the **published** package, `0.
|
|
88
|
+
The two npm forms below install the **published** package, `0.50.0` (Pi 1.4.x, the Pi 1.4.0 SDK
|
|
87
89
|
set). The [product entry](../README.md#install)'s unpinned `npm install -g @junghanacs/entwurf`
|
|
88
90
|
takes whichever version npm's `latest` dist-tag names; pin `@<version>` as below when you mean the
|
|
89
91
|
exact artifact the [Requirements](#requirements) table describes.
|
|
@@ -92,7 +94,7 @@ Global install is simplest when native harnesses should find stable bins from ev
|
|
|
92
94
|
working directory:
|
|
93
95
|
|
|
94
96
|
```bash
|
|
95
|
-
npm install -g @junghanacs/entwurf@0.
|
|
97
|
+
npm install -g @junghanacs/entwurf@0.50.0
|
|
96
98
|
entwurf --help
|
|
97
99
|
entwurf setup /path/to/your-project
|
|
98
100
|
entwurf check-bridge
|
|
@@ -103,7 +105,7 @@ A project-local installation is also supported:
|
|
|
103
105
|
```bash
|
|
104
106
|
mkdir -p ~/entwurf-smoke && cd ~/entwurf-smoke
|
|
105
107
|
npm init -y
|
|
106
|
-
npm install --save-dev @junghanacs/entwurf@0.
|
|
108
|
+
npm install --save-dev @junghanacs/entwurf@0.50.0
|
|
107
109
|
npx entwurf setup .
|
|
108
110
|
npx entwurf check-bridge
|
|
109
111
|
```
|
|
@@ -113,7 +115,7 @@ project-local install, or `./run.sh <command>` from a source checkout. Keep that
|
|
|
113
115
|
same scope when upgrading and checking; native process restarts are separate (§7).
|
|
114
116
|
|
|
115
117
|
`check-bridge` is auth-free. It proves the installed prebuilt MCP server boots and
|
|
116
|
-
lists the nine garden tools (0.
|
|
118
|
+
lists the nine garden tools (0.50.0); it does not prove a backend model turn, native hook or retirement permission.
|
|
117
119
|
|
|
118
120
|
Neither npm form installs a harness runtime. `pi`, Claude Code, Copilot CLI, Codex CLI, agy,
|
|
119
121
|
Cortex, and their authentication remain operator-owned optional prerequisites for the
|
|
@@ -228,6 +230,7 @@ Install the exact release floor, then wire the project. The previous 0.41.0 inst
|
|
|
228
230
|
Pi 1.3.x its own setup guide names. A source checkout passes its checkout path to `-e` in place of
|
|
229
231
|
the global package root:
|
|
230
232
|
|
|
233
|
+
<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->
|
|
231
234
|
```bash
|
|
232
235
|
npm install -g @earendil-works/pi-coding-agent@1.4.0
|
|
233
236
|
pi --version
|
|
@@ -241,6 +244,7 @@ The supported range is `>=1.4.0 <1.5`. It is a hard minimum: installing this
|
|
|
241
244
|
release onto a 0.83.x pi host upgrades the runtime rather than keeping the older
|
|
242
245
|
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
243
246
|
control socket; no delivery rail launches a pi process.
|
|
247
|
+
<!-- /entwurf:published -->
|
|
244
248
|
|
|
245
249
|
For daily garden-native pi sessions:
|
|
246
250
|
|
|
@@ -259,7 +263,7 @@ A plain `pi` can load the package without becoming a citizen.
|
|
|
259
263
|
In that session ask for `entwurf_self`, then `entwurf_peers`. Pick an existing
|
|
260
264
|
live garden id and ask for `entwurf_v2` with `intent: "fire-and-forget"` and your
|
|
261
265
|
message. These are harness tools, not shell subcommands; pi exposes them through
|
|
262
|
-
Pi's built-in MCP as `mcp__entwurf_bridge__<verb>`. The 0.
|
|
266
|
+
Pi's built-in MCP as `mcp__entwurf_bridge__<verb>`. The 0.50.0 bridge has nine tools;
|
|
263
267
|
pi hides `entwurf_inbox_read` and `entwurf_register_native`, leaving seven active.
|
|
264
268
|
The added `entwurf_retire_call` is only for one target/action explicitly requested by the
|
|
265
269
|
human operator, never autonomous cleanup. Where a host provides or is configured with an approval
|
|
@@ -344,11 +348,11 @@ by `entwurf pi` or by registering ordinary Pi's adapter.
|
|
|
344
348
|
|
|
345
349
|
What the Entwurf package supplies:
|
|
346
350
|
|
|
347
|
-
1. **The pi SDK set** — `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
348
|
-
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.
|
|
349
|
-
`proper-lockfile`, as Entwurf's own production dependencies
|
|
350
|
-
|
|
351
|
-
|
|
351
|
+
1. **The pi SDK set** — in the 0.51.0 prepared checkout, `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
352
|
+
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry, pi-schema}` at exactly `1.5.0`, plus
|
|
353
|
+
`proper-lockfile`, as Entwurf's own production dependencies. The authoritative current set is
|
|
354
|
+
the [SDK pin](../pi/pi-durable/overlay/upstream-pin.json) and [package manifest](../package.json);
|
|
355
|
+
for this candidate, model data rides `@earendil-works/pi-ai@1.5.0`, not a catalog copy.
|
|
352
356
|
2. **The native app/TUI carrier** — upstream does not publish the experimental durable
|
|
353
357
|
app (`pi-coding-agent` excludes `dist/experimental`; `pi-durable` on npm is the
|
|
354
358
|
library). Entwurf owns the six app files as canonical source (`pi/pi-durable/src`,
|
|
@@ -358,7 +362,7 @@ What the Entwurf package supplies:
|
|
|
358
362
|
(`pi/pi-durable/carrier-resolver.mjs`), which maps them to the published package's
|
|
359
363
|
own `dist/` as installed — never through a source checkout.
|
|
360
364
|
|
|
361
|
-
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.
|
|
365
|
+
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.5.0/packages/durable/README.md)
|
|
362
366
|
and the [experimental app guide](https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/src/experimental/durable/README.md)
|
|
363
367
|
(last published at v1.1.0) describe what the carrier is. Running the bare upstream app does not attach Entwurf's
|
|
364
368
|
garden contact. Entwurf does not rebuild the controller/model/auth/storage system or
|
|
@@ -373,8 +377,7 @@ carrier file, the license, the resolver and its relocation grammar are present
|
|
|
373
377
|
(`pi-durable-carrier-drift`); every declared SDK package resolves from the carrier
|
|
374
378
|
(`pi-durable-sdk-absent`); and every reachable physical edge — from the carrier to each package,
|
|
375
379
|
and from every package copy it reaches, at any depth, to its own `@earendil-works` dependencies —
|
|
376
|
-
lands on a package of the declared name at exactly the pinned version (`pi-durable-sdk-mismatch`). The members
|
|
377
|
-
ranges, so semver satisfaction is not the contract; the bytes an import binds are. Sharing
|
|
380
|
+
lands on a package of the declared name at exactly the pinned version (`pi-durable-sdk-mismatch`). The members' declarations are exact in the prepared 1.5.0 set; even so, the physical package each import binds must be checked. Sharing
|
|
378
381
|
one copy with an aligned host install of the same version is an ordinary layout. A mixed
|
|
379
382
|
tree (for example an override that binds pi-durable's `pi-ai` to an older published version) still
|
|
380
383
|
*imports* — which is why the edge check exists — and is refused by name.
|
|
@@ -399,7 +402,12 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
399
402
|
`--session` takes the native session id (`<13-digit ms>-<uuid>`, as `--resume` lists it), not a
|
|
400
403
|
garden id, with no interactive session picker or picker-specific TTY check (the normal TUI still
|
|
401
404
|
runs); a value of any other shape is refused as `session-id-malformed` before your module is
|
|
402
|
-
evaluated, the TUI loads or the app opens.
|
|
405
|
+
evaluated, the TUI loads or the app opens. To retain an operator module on a CLI reopen, pass
|
|
406
|
+
its original explicit `--native-module <absolute file>` or `--native-module-dir <absolute directory>`
|
|
407
|
+
again; garden-id `entwurf_resume_call` is bridge-only and does not restore either ingress or
|
|
408
|
+
the prior seat. It opens on the caller's launch rail; check for an existing owner before opening
|
|
409
|
+
another instance. Close the old owner normally and prove its exit before reopening; for an SDK transition, back up
|
|
410
|
+
the complete durable SQLite file set before the first write ([upgrade boundary](#default-radius-for-a-requested-pi-sdk-upgrade)). Ordinary Pi transcripts are separate JSONL files.
|
|
403
411
|
|
|
404
412
|
The bootstrap imports only the compiled closure shipped beside it
|
|
405
413
|
(`mcp/entwurf-bridge/dist/…`); a source checkout needs a built bridge
|
|
@@ -451,7 +459,7 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
451
459
|
manifest field; it is a known constraint of supplying both from one package, accepted for 0.32,
|
|
452
460
|
not a claim that every load path is harmless.
|
|
453
461
|
|
|
454
|
-
The ordinary Pi CLI on PATH is a separate subject (§2, range
|
|
462
|
+
The ordinary Pi CLI on PATH is a separate subject (§2, range <!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->`>=1.4.0 <1.5`<!-- /entwurf:published -->): a host Pi is
|
|
455
463
|
not needed to run pi-durable, and a host inside the range need not be the same copy as the
|
|
456
464
|
carrier's. Native Pi owns credentials, model settings and durable SQLite sessions; keep them
|
|
457
465
|
in place rather than copying credentials or migrating ordinary Pi transcripts. Native
|
|
@@ -462,9 +470,48 @@ to the app's own model resolution; the checkout contact/send/receive gates run t
|
|
|
462
470
|
with scripted S plus native H; Pi ↔ pi-durable LIVE on this supply surface is a separate release
|
|
463
471
|
proof ([#130](https://github.com/junghan0611/entwurf/issues/130)).
|
|
464
472
|
|
|
473
|
+
### SDK 1.5 development boundary (#155)
|
|
474
|
+
|
|
475
|
+
The published 0.50.0 / SDK 1.4.0 instructions above and the #155 SDK 1.5 development
|
|
476
|
+
candidates are distinct subjects. Synthetic migration and downgrade-refusal fixtures on `0408a66`
|
|
477
|
+
did not authorize an operating first write. A separately approved 1.5 operating window and Native
|
|
478
|
+
LIVE were later measured as described below; neither makes the validation TGZ the final release
|
|
479
|
+
artifact. Installing an older package is not a data rollback. Follow the current evidence in
|
|
480
|
+
[#155](https://github.com/junghan0611/entwurf/issues/155), not the 1.3→1.4 receipt below.
|
|
481
|
+
|
|
482
|
+
### Default radius for a requested Pi SDK upgrade
|
|
483
|
+
|
|
484
|
+
**[Decision, 2026-11-03 (#155)](https://github.com/junghan0611/entwurf/issues/155#issuecomment-6595580400): reuse existing native authentication; do not make a fresh login or credential copy the default upgrade prerequisite.** An upgrade request selects this method without another authentication-strategy questionnaire. It does not authorize an immediate operating cutover, autonomous retirement, or publication.
|
|
485
|
+
|
|
486
|
+
The measured precedent is [#148's pre-cutover hold](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6342034678) and [its actual Pi 1.4 operating reattachment](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6348113761): isolated package/SDK checks first; no authentication-copy or mixed host/extension workaround; then normal owner exit, a consistent complete durable-session file-set backup, coherent candidate installation/takeover, same-identity reattachment and actual turns/round trips. Native aggregate acceptance followed the coherent installation. These are historical receipts, not evidence for the next SDK.
|
|
487
|
+
|
|
488
|
+
- **Proceed within the requested upgrade:** inspect upstream changes; isolate the development checkout from stable operating runtimes; pin the coherent SDK set; run private, authentication-free fixtures, focused checks, review and the required floors. Prepare the exact candidate, shutdown/reopen commands and backup manifest before the operating window.
|
|
489
|
+
- **Reuse at the coherent operating boundary:** the native harness uses its existing account/subscription authentication in its ordinary location. Its normal same-account token refresh is not a reason to demand another login. Entwurf does not extract, print, copy, transplant or proxy credentials, and does not introduce an auth-path shim. Keep the selected subscription/provider rail; no account, endpoint, scope or billing-rail substitution is implied.
|
|
490
|
+
- **Still coordinate the human-owned lifecycle window:** identify the exact operating owners and obtain the requested normal shutdown; prove old-owner exit and preserve the complete session directory consistently, including WAL/SHM, before the newer SDK opens operating data. Verify candidate, host, extension, bridge and SDK coherence, then reopen the same identities and measure actual model/tool/round-trip behavior. Authentication reuse is the default method, not permission to skip these gates or to force-close a working citizen.
|
|
491
|
+
- **Do not invent a pre-cutover exception:** if a real-model test cannot use the approved isolated surface without touching operating auth/data, defer it to that operating window. A separate private login or operating-agent-directory experiment is optional and needs a specific request; neither is a recurring prerequisite. Record the missing model/TUI evidence rather than claiming scripted S/H proves it.
|
|
492
|
+
- **Stop and report a real exception:** expired/revoked authentication needing login, changed account/permissions/endpoint or an unmeasured new external transfer, ownership conflict, inconsistent backup, unexpected write, or unknown result. No blind retry or automatic data rollback; downgrading the package does not undo a newer document write.
|
|
493
|
+
|
|
494
|
+
Push, release/tag/npm publication and retirement of any other citizen retain their separate authorization boundaries. This decision fixes the repeatable method; it does not pre-authorize those actions.
|
|
495
|
+
|
|
496
|
+
**Recurring SDK rail.** At task start, agree the exact SDK and the scope of development, review and verification once; do not repeatedly ask for the existing-auth strategy. Inspect the published SDK set and upstream changes, isolate the development checkout from operating runtimes, and implement against the coherent pinned set in private HOME, PI and writable XDG roots. Use the gate's own temporary-directory constraints: the #155 FULL's deeper scratch produced 117/109-byte socket paths and EINVAL; run3 used `TMPDIR=/tmp` with each gate creating its own private scratch and passed. Preserve both `pnpm_config_verify_deps_before_run=error` and `npm_config_verify_deps_before_run=error`, managed builds and candidate seals; do not run offline gates under ambient CI.
|
|
497
|
+
|
|
498
|
+
The owned canonical app/TUI source is production responsibility; the SDK owns the execution engine. In independent upgrade review, compare old and new app-visible payload semantics against known fixtures and a separate official SDK oracle: more than 50 active entries on reopen and same-process conversation switch, head/reset and background-compaction retention, and the distinction from model memory. API names, typechecks or a QK that only fixes the new SDK's window can all be green while older display compatibility regresses. When official emission changes a generated digest, check its pin-linked mutant find literal and the existing manifest inventory together; this is not a new gate.
|
|
499
|
+
|
|
500
|
+
Freeze for sequential independent review, then affected PARTIAL groups, frozen FULL and applicable scripted/native-H carrier cells. Accept the **same reviewed validation TGZ** in the Linux container and rehearse ownership refusal/takeover in isolation. Measure SDK publication age early to plan the window, then recheck it fresh before installation; never automatically exempt the global policy.
|
|
501
|
+
|
|
502
|
+
In the named operating window, identify owners, obtain their normal exit and prove it, then take a consistent complete session backup including WAL/SHM before the first new-SDK write. Install a coherent host and validation TGZ, verify installed global root (GR), runtime and ownership independently, and perform only the approved takeover. Reopen the same identities with their original explicitly named native modules and existing auth; observe real turns and round trips before the Native LIVE floor. Public pi-durable `entwurf_resume_call` is bridge-only: it does not save or restore operator native modules. If one is needed, use the original explicit CLI entry; do not infer a profile or kill a citizen automatically. One approval can cover the named scope, sibling roles and fixture work, but not bypass normal exit, the first-write decision, or separate push/npm authority.
|
|
503
|
+
|
|
504
|
+
For each named Native fixture, record the runtime root and SDK actually selected separately from the operator installation: a private PATH can select the genuine source CLI while an ordinary Pi extension still comes from an older installed GR. Do not substitute a wrapper or rewire the operating host to make the evidence agree. A planned source-CLI Native run is not a completed receipt.
|
|
505
|
+
|
|
506
|
+
**#155 measured example (2026-11-03; before the D1 display repair):** at 20:47 KST host Pi 1.5.0 and the unpublished, addon-less 0.51.0 validation TGZ (SHA-256 `199e5f41d20e5b2665125868b7e3e27740e5985f7a25ac61902126b7ed638bf5`) were installed, not the final publication artifact. Four owners exited normally; the 171-file durable backup's source-before/backup/source-after manifests matched (`5c08bed1968fd1e26baa58112f0ce5c36874e147ccc5e9b4c69ec1a0d9070a46`); two Pi transcripts were also backed up. All ten SDK members were freshly measured at 24.70–24.84 hours old, without a policy exception. The P5 Native LIVE cut recorded MUST 24/0/0 and BEHAVIOR 1/0/0 (pass/fail/skip) on its own sealed candidate, not the prepared SHA. Native-host criterion 4 separately measured a fresh Claude Code fixture's actual installed 0.51 MCP child and strict doctor; existing pre-cutover Claude sessions retained their loaded 0.50 bridge. Neither the 20:47 installation nor P5 proves that the later D1 display repair is operating: the D1-bearing artifact must first be installed, and the human must then restart the process; restarting against the earlier artifact still loads the old app. See [0.51.0 release evidence](../CHANGELOG.md#release-evidence) for scopes and receipts.
|
|
507
|
+
|
|
508
|
+
The Windows-bearing release TGZ, its Linux acceptance, exact prepared-SHA CI, installed-host acceptance and publication/registry proof are separate later evidence. Re-measure owners, loaded bytes, version/integrity, backup and candidate evidence on every upgrade; this ordering does not guarantee success for a future SDK.
|
|
509
|
+
|
|
510
|
+
For the separate land, prepare, make and publish authorities and the one accepted artifact, follow [entwurf-release](../.claude/skills/entwurf-release/SKILL.md). Push, tag, human-owned npm publication and the subsequent Herdr re-pin remain independently coordinated decisions. The current SDK-specific decisions and receipts belong to the active issue and handoff, not this reusable ordering.
|
|
511
|
+
|
|
465
512
|
### Moving durable sessions from the Pi 1.3 SDK to 1.4
|
|
466
513
|
|
|
467
|
-
0.41.1, 0.41.2 and 0.
|
|
514
|
+
0.41.1, 0.41.2, 0.45.0 and 0.50.0 are published on the 1.4.0 SDK set; moving a live host onto any of them
|
|
468
515
|
remains a separate operator decision for each host. When you do:
|
|
469
516
|
|
|
470
517
|
1. **Confirm the old owner is gone.** Close the 0.41 (SDK 1.3) durable session normally and check
|
|
@@ -726,7 +773,7 @@ as a note rather than a fault.
|
|
|
726
773
|
|
|
727
774
|
**entwurf sets no OMP version floor in code, and will not grow one on schedule.** Detection is
|
|
728
775
|
presence-only (`command -v "${OMP_BIN:-omp}"`); there is no `entwurf.ompFloor`, no coherence
|
|
729
|
-
gate, and no exact pin — unlike Node (`engines.node`), pi (
|
|
776
|
+
gate, and no exact pin — unlike Node (`engines.node`), pi (<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->`>=1.4.0 <1.5`<!-- /entwurf:published --> for published 0.50.0) and Claude Code
|
|
730
777
|
(`entwurf.claudeCodeFloor`), each of which has an enforcement point. That asymmetry is a
|
|
731
778
|
decision, not an omission. A floor is the answer to a vendor that fails SILENTLY — Claude Code
|
|
732
779
|
earned one because an older binary validates the exec manifest, drops `args` at runtime, and
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* verb (0.11 Stage 0 step 4-pre / 동결결정 10). PURE pi-FREE core: the
|
|
4
4
|
* intent×liveness decision table + the reject taxonomy + a pure resolver.
|
|
5
5
|
* NO runtime dispatch, NO spawn/send, NO I/O — step 5 wires this to transports.
|
|
6
|
-
* The pi-
|
|
6
|
+
* The pi-schema REPRESENTATION of this contract lives in the separate
|
|
7
7
|
* `entwurf-v2-contract-schema.ts` (0.12.1 B-1) so this module — which the
|
|
8
8
|
* harness-neutral MCP bridge reaches at boot — carries no pi dependency.
|
|
9
9
|
*
|
|
@@ -431,9 +431,9 @@ export function resolveNativePushDispatch(intent, liveness) {
|
|
|
431
431
|
observedLiveness: liveness,
|
|
432
432
|
};
|
|
433
433
|
}
|
|
434
|
-
// ──
|
|
435
|
-
// MOVED to `entwurf-v2-contract-schema.ts` (0.12.1 B-1): the pi
|
|
436
|
-
// builders (StringEnum
|
|
434
|
+
// ── JSON schemas ───────────────────────────────────────────────────────────
|
|
435
|
+
// MOVED to `entwurf-v2-contract-schema.ts` (0.12.1 B-1): the pi schema
|
|
436
|
+
// builders (pi-ai StringEnum, pi-schema since #155) are a pi-lane dependency, so they cannot live in
|
|
437
437
|
// this pi-free core — the MCP bridge reaches this module at boot and must stay
|
|
438
438
|
// harness-neutral (check-entwurf-bridge-pi-free). The schemas import the
|
|
439
439
|
// constants/types above; pi-side consumers import the schemas from there.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@junghanacs/entwurf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Visible sibling sessions across independent agent harnesses: launch in Herdr or tmux, retire on request, visibly reopen supported sessions under the same id, and deliver messages by garden id; native bridges and Claude/Cortex ACP adapters.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -105,23 +105,21 @@
|
|
|
105
105
|
"@agentclientprotocol/claude-agent-acp": "0.90.0",
|
|
106
106
|
"@agentclientprotocol/sdk": "1.8.0",
|
|
107
107
|
"@anthropic-ai/sdk": "0.100.1",
|
|
108
|
-
"@earendil-works/chord": "1.
|
|
109
|
-
"@earendil-works/pi-agent-core": "1.
|
|
110
|
-
"@earendil-works/pi-ai": "1.
|
|
111
|
-
"@earendil-works/pi-codemode": "1.
|
|
112
|
-
"@earendil-works/pi-coding-agent": "1.
|
|
113
|
-
"@earendil-works/pi-durable": "1.
|
|
114
|
-
"@earendil-works/pi-mcp": "1.
|
|
115
|
-
"@earendil-works/pi-
|
|
116
|
-
"@earendil-works/pi-
|
|
108
|
+
"@earendil-works/chord": "1.5.0",
|
|
109
|
+
"@earendil-works/pi-agent-core": "1.5.0",
|
|
110
|
+
"@earendil-works/pi-ai": "1.5.0",
|
|
111
|
+
"@earendil-works/pi-codemode": "1.5.0",
|
|
112
|
+
"@earendil-works/pi-coding-agent": "1.5.0",
|
|
113
|
+
"@earendil-works/pi-durable": "1.5.0",
|
|
114
|
+
"@earendil-works/pi-mcp": "1.5.0",
|
|
115
|
+
"@earendil-works/pi-schema": "1.5.0",
|
|
116
|
+
"@earendil-works/pi-telemetry": "1.5.0",
|
|
117
|
+
"@earendil-works/pi-tui": "1.5.0",
|
|
117
118
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
118
119
|
"proper-lockfile": "4.1.2",
|
|
119
120
|
"smol-toml": "^1.8.0",
|
|
120
121
|
"zod": "^3.25.0 || ^4.0.0"
|
|
121
122
|
},
|
|
122
|
-
"peerDependencies": {
|
|
123
|
-
"typebox": "*"
|
|
124
|
-
},
|
|
125
123
|
"devDependencies": {
|
|
126
124
|
"@biomejs/biome": "^2.4.13",
|
|
127
125
|
"@types/node": "^24.3.0",
|
|
@@ -220,10 +218,5 @@
|
|
|
220
218
|
"entwurf-agy-statusline": "./scripts/agy-statusline.sh",
|
|
221
219
|
"entwurf-agy-imprint": "./scripts/agy-imprint.sh",
|
|
222
220
|
"entwurf-copilot-statusline": "./scripts/copilot-statusline.sh"
|
|
223
|
-
},
|
|
224
|
-
"peerDependenciesMeta": {
|
|
225
|
-
"typebox": {
|
|
226
|
-
"optional": true
|
|
227
|
-
}
|
|
228
221
|
}
|
|
229
222
|
}
|