@junghanacs/entwurf 0.35.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +209 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +15 -0
- package/FAQ.md +3 -3
- package/README.md +30 -16
- package/VERIFY.md +9 -7
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +1 -1
- package/docs/setup-clean-host.md +30 -22
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +4 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/native-push/codex-ws-client.js +99 -18
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +3 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +59 -14
- package/mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js +44 -0
- package/mcp/entwurf-bridge/tsconfig.build.json +5 -0
- package/package.json +19 -14
- package/pi/pi-durable/bootstrap.mjs +12 -8
- package/pi/pi-durable/carrier/runtime.js +52 -2
- package/pi/pi-durable/carrier/subagent.js +6 -1
- package/pi/pi-durable/carrier/tui.js +31 -4
- package/pi/pi-durable/carrier-relocation.mjs +2 -2
- package/pi/pi-durable/overlay/upstream-pin.json +79 -36
- package/pi-extensions/lib/codex-fresh-preflight.ts +4 -3
- package/pi-extensions/lib/native-push/codex-ws-client.ts +129 -18
- package/pi-extensions/lib/pi-durable-runtime.ts +4 -4
- package/pi-extensions/meta-bridge-pi-durable.ts +77 -21
- package/run.sh +112 -38
- package/scripts/check-codex-app-server-launch.ts +55 -12
- package/scripts/check-codex-native-push.ts +231 -12
- package/scripts/check-gate-qualification.ts +3 -3
- package/scripts/codex-app-server-launch.sh +54 -29
- package/scripts/codex-socket-classify.ts +46 -0
- package/scripts/emit-pi-durable-carrier.ts +159 -168
- package/scripts/mutants/codex-app-server-launch.json +39 -12
- package/scripts/mutants/codex-native.json +15 -0
- package/scripts/mutants/control-send-receipt.json +1 -1
- package/scripts/mutants/pack-install.json +3 -3
- package/scripts/mutants/pi-durable.json +165 -16
- package/scripts/mutants/pi-floor.json +5 -5
- package/scripts/pi-durable-contact-host.mjs +1 -1
- package/pi/pi-durable/overlay/runtime-contacts.patch +0 -283
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AGENTS.md — Maintainer Guidelines for entwurf
|
|
2
2
|
|
|
3
|
-
For agents who own this repository: durable invariants and the documents that own the changing evidence. This is the **entwurf capability package**: garden-
|
|
3
|
+
For agents who own this repository: durable invariants and the documents that own the changing evidence. This is the **entwurf capability package**: visible sibling lifecycle and garden-id delivery — the v2 dispatch core, native-harness bridges, ACP plugin, and pi adapter. Entwurf is the subject; pi is one adapter. ACP is a plugin, not the boundary. V2 addresses existing citizens; `entwurf_fresh_call` creates a new sibling.
|
|
4
4
|
|
|
5
5
|
## North Star — One Forged Screwdriver
|
|
6
6
|
|
|
@@ -42,7 +42,7 @@ Ask: does this follow capability rather than a surface name; record backend asym
|
|
|
42
42
|
14. **Native-hook ownership is structural.** Use shipped exec launchers and provenance, shared plausible-owner-pid policy, no shell fallback or ancestry guess. Version floors belong to their package source and are enforced there; hook contract/docs own the changing detail.
|
|
43
43
|
15. **Crash, don’t warn.** Invalid config/path/model/store state throws. Empty catches are only bounded environment probes; diagnostics go to stderr.
|
|
44
44
|
16. **mux launches, never delivers.** A tmux handle is an ephemeral view, not an address or liveness receipt; screen text/keystrokes are not delivery evidence. A Codex caller's seat is the pane whose title carries its own thread-id, a placement input only; it is never an address, and never a pane nobody named. Cross-window adjacency requires the documented observed-coordinate proof, never pane guessing.
|
|
45
|
-
17. **Supply the missing surface; do not become the harness.** Installation supplies Entwurf bytes, development fixtures, and declared upstream SDK dependencies. Where upstream omits a native execution surface from its distribution, Entwurf
|
|
45
|
+
17. **Supply the missing surface; do not become the harness.** Installation supplies Entwurf bytes, development fixtures, and declared upstream SDK dependencies. Where upstream omits a native execution surface from its distribution, Entwurf owns that thin, removable app/TUI composition as canonical source and ships its deterministic emission (type strip + import relocation) as a carrier, against one coherent published-library version set. The engine — native execution, auth, queues, storage, transcript, compaction, cancellation and recovery — remains the upstream SDK (Rule 9). Provenance, license, rebuild and installed-consumer proof belong to the supply contract. No Entwurf-owned copying/inlining of provider model catalogs, subscription, credential or login; no launch-time download, repair, update or fallback. Setup checks capability, version-set coherence and carrier integrity: absent optional capability is explicit skip; incomplete installation, mismatch and drift are named non-green refusals. Portability and runtime evidence remain separate.
|
|
46
46
|
|
|
47
47
|
History and incident detail belong in [CHANGELOG.md](./CHANGELOG.md), issue threads, [BASELINE.md](./BASELINE.md), or source-adjacent comments. When prose and behavior disagree, repair the owning source or document.
|
|
48
48
|
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,215 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.36.0 - 2026-10-13
|
|
8
|
+
|
|
9
|
+
### pi-durable
|
|
10
|
+
|
|
11
|
+
- **The thin app/TUI composition is Entwurf-owned source (#141).** The six carrier files
|
|
12
|
+
are emitted from `pi/pi-durable/src/experimental/durable/*.ts` (with `src/LICENSE`), which
|
|
13
|
+
folds in the retired `runtime-contacts.patch`, and run on the 1.2.0 SDK set (below). Net
|
|
14
|
+
against 0.35.1, three carrier files change: `runtime.js` `60c2965e…118403`, `tui.js`
|
|
15
|
+
`0f9ebaf8…b3abc5` and `subagent.js` `1cb2390b…a64220`. `harness-setup.js`, `prompt.js`,
|
|
16
|
+
`sessions.js` and LICENSE keep their 0.35.1 bytes. The source checkpoint `86d4b65` left the
|
|
17
|
+
package version at 0.35.1; this release sets 0.36.0. The first step (S0) moved ownership
|
|
18
|
+
alone: no carrier byte, no LICENSE and no SDK version (then 1.1.0) changed, only the pin's
|
|
19
|
+
carrier source blob ids. The upstream SDK still owns
|
|
20
|
+
execution, auth, queues, storage/transcript, compaction, cancellation and recovery (Rule 17).
|
|
21
|
+
- **Pin schema 3.** `pi/pi-durable/overlay/upstream-pin.json` keeps its path and the shapes
|
|
22
|
+
installed readers use. A frozen `origin` holds the upstream commit, its recorded blobs, the
|
|
23
|
+
retired patch's digest and the 0.35.1 carrier digests. Only `carrier` is generated.
|
|
24
|
+
- **Emitter.** `scripts/emit-pi-durable-carrier.ts --check` reads only in-repo source, and a
|
|
25
|
+
missing file is a named refusal. A host running a different Node gets the byte proof plus a
|
|
26
|
+
named emitter-identity SKIP, not a PASS. `--write` names every generated field it changes.
|
|
27
|
+
`--origin <clone>` checks provenance only. The CI `check` job runs the pinned emitter Node
|
|
28
|
+
exactly, with `ENTWURF_REQUIRE_EMITTER_NODE=1`; other jobs float the major.
|
|
29
|
+
- **Typecheck fence.** `pi/pi-durable/tsconfig.json` is the fourth `pnpm typecheck` program:
|
|
30
|
+
strict, `erasableSyntaxOnly` / `verbatimModuleSyntax`, and `rootDirs` onto the installed
|
|
31
|
+
`pi-coding-agent/dist`, so internals are typed by their published declarations. Its explicit
|
|
32
|
+
empty `exclude` receives what the root program excludes. The exact devDependency
|
|
33
|
+
`@types/proper-lockfile@4.1.4` supplies the one missing declaration.
|
|
34
|
+
- **Formatting.** The owned source uses upstream width (indentWidth 3), with no per-file
|
|
35
|
+
exception. Formatting `tui.ts` wrapped its one Entwurf-written dock line and added one trailing
|
|
36
|
+
comma, so `tui.js` was re-emitted (sha256 `63600d4b…095b`, the S1-B1 intermediate; the S1-B3
|
|
37
|
+
changes below produce the current `0f9ebaf8…b3abc5`). A parser-derived token/AST
|
|
38
|
+
comparison found nothing else changed. The `PI-DURABLE-FOOTER-BADGE-PROTECTED` mutant follows
|
|
39
|
+
the wrapped line and plants the same fault.
|
|
40
|
+
- **Proof.** New claims: `PI-DURABLE-CARRIER-EMIT-SOURCE-EQUAL`, `-EMIT-NODE-EXACT`,
|
|
41
|
+
`PI-DURABLE-SOURCE-FENCE-RESOLVES`, `PI-DURABLE-SOURCE-NOT-SHIPPED` (the source, the fence and the
|
|
42
|
+
retired patch stay out of the JS-only tarball; proved on npm's own file list with
|
|
43
|
+
`--ignore-scripts` beside the carrier, while check-pack keeps the same tripwire on the floor), and
|
|
44
|
+
`PI-DURABLE-EMITTER-NODE-CI-BOUND` / `-CI-REQUIRED`. These two read the check job's active
|
|
45
|
+
setup-node input and its actual `check:full` step env, never comment text or another step.
|
|
46
|
+
Retired with the patch: `PI-DURABLE-CARRIER-PATCH-SECTIONS`.
|
|
47
|
+
- **SDK set 1.2.0 (#141 S1-B2).** The nine published `@earendil-works/*` production dependencies
|
|
48
|
+
move from 1.1.0 to 1.2.0, with the pin's `sdk.members`, the install constellation, the pin-leak
|
|
49
|
+
matcher and the declared ranges (`>=1.2.0 <1.3`). `pi-client` and `pi-protocol` leave the set (not
|
|
50
|
+
published at 1.2.0); the only new third-party package is `@silvia-odwyer/photon@0.3.3`.
|
|
51
|
+
- **1.2.0 tool output (#141 S1-B3).** On the 1.2.0 SDK set a native durable tool result's model
|
|
52
|
+
channel is `output`, which the SDK renamed from 1.1's `content`. When a result omits `output`, the
|
|
53
|
+
model gets the text the tool retained through `api.output()`. `content` is not read, so a result
|
|
54
|
+
naming only `content` that retained no output reaches the model as nothing. The subagent tool (now
|
|
55
|
+
`satisfies ToolExecutionResult`), the contact's bridge tools and the synthetic native-module
|
|
56
|
+
fixture retain none, so they answer in `output`. The ordinary Pi
|
|
57
|
+
`ToolExecutionComponent.updateResult` and `InputSubmissionDraft` keep `content`.
|
|
58
|
+
- **Fatal session.** The carrier runtime takes the Session's own close listener and the report that
|
|
59
|
+
follows it: a session that failed and closed itself is on screen at once (`Session failed: <cause>.
|
|
60
|
+
It takes no more input, and a tool still running may take a while to stop. Close this session,
|
|
61
|
+
then reopen it with --continue.`) and input to it is refused by name, without waiting for
|
|
62
|
+
`closed`, which a tool ignoring its abort can hold off. A normal `close()` unsubscribes first and
|
|
63
|
+
is no failure. A failure listener subscribed after the failure is told at once, once. On that
|
|
64
|
+
signal the contact retires its receiver as `session-failed` before the next doorbell — also when
|
|
65
|
+
the session had already failed before the contact attached, so no receiver marker is left behind;
|
|
66
|
+
a normal close still retires it as `closed`, and a cleanup failure is thrown, not swallowed.
|
|
67
|
+
- **Compaction failure.** The TUI draws the conversation's retained `pi.live.compactionFailure`
|
|
68
|
+
(`Compaction failed (<reason>): <error>`) for as long as the SDK keeps it. A failed background
|
|
69
|
+
compaction the SDK starts on its own (`threshold`) had no other report; the manual one keeps its
|
|
70
|
+
existing notice beside the line.
|
|
71
|
+
- **Proof (S1-B3).** New claims `PI-DURABLE-SUBAGENT-OUTPUT-MODEL-VISIBLE`,
|
|
72
|
+
`-BRIDGE-TOOL-OUTPUT-MODEL-VISIBLE`, `-FATAL-SESSION-VIEW`, `-FATAL-SESSION-SHOWN`,
|
|
73
|
+
`-FATAL-SUBMIT-REFUSED`, `-RECEIVER-RETIRE-ON-FATAL`, `-SELF-CLOSE-NOT-FAILURE` and
|
|
74
|
+
`-COMPACTION-FAILURE-SHOWN` run the real bootstrap and carrier on the published 1.2.0 SDK with a
|
|
75
|
+
faux model and an injected storage failure; each mutant plants its fault in the generated carrier
|
|
76
|
+
or the bridge source.
|
|
77
|
+
|
|
78
|
+
### Codex
|
|
79
|
+
|
|
80
|
+
- **The 0.162.1 control endpoint is accepted as its exact alias (#141).** Codex 0.162.1 binds its
|
|
81
|
+
0600 control socket under `realpath(/tmp)/codex-daemon-<euid>/`, named by the sha256 of the
|
|
82
|
+
canonical advertised path, and makes the advertised path a symlink to it. One classifier,
|
|
83
|
+
`checkCodexSocketFile`, accepts a plain socket or exactly that alias (link owner, byte-equal
|
|
84
|
+
target, a 0700 socket directory owned by the same euid, a socket no other user can open) and
|
|
85
|
+
refuses every other symlink. The delivery probe, `codex queue --remote` and the fresh-call
|
|
86
|
+
preflight connect to the socket it verified. The managed launcher runs the same classifier's
|
|
87
|
+
compiled twin (`mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js`) and keeps no copy of
|
|
88
|
+
its own: a missing twin is an incomplete installation, refused as
|
|
89
|
+
`codex-app-server-classifier-missing` (reinstall the package, or run `pnpm run build-bridge` in
|
|
90
|
+
a source checkout), and an answer it does not recognise is refused by name. This is measured
|
|
91
|
+
on the 0.162.1 layout only and promises nothing about a later Codex. The plain-socket layout is
|
|
92
|
+
kept; its native acceptance remains the dated 0.153.4 record, not a claim about every older or
|
|
93
|
+
newer version.
|
|
94
|
+
- **Stated limits.** The launcher reports a dangling exact alias as the dead leftover the vendor
|
|
95
|
+
removes on start and launches over it, but its alias and dangling-alias paths have no LIVE
|
|
96
|
+
observation; they are proven on the classifier in a sandbox. The birth hook's thread naming,
|
|
97
|
+
the fresh Codex TUI's `--remote` endpoint and the fresh-call smoke's thread reads still hand the
|
|
98
|
+
advertised path to a connect without classifying it. Those connections worked in the named
|
|
99
|
+
diagnostic on this host; they remain unclassified. That is recorded as an Observation: not
|
|
100
|
+
every Codex connection goes through the classifier. A same-euid process can still replace the
|
|
101
|
+
verified socket file; that residual is named, not locked.
|
|
102
|
+
|
|
103
|
+
### Docs
|
|
104
|
+
|
|
105
|
+
- **Open, reopen and message lead the one-line surfaces.** The README, FAQ, CONTRIBUTING,
|
|
106
|
+
AGENTS, the Herdr plugin README and manifest description, and the package description and
|
|
107
|
+
keywords name the three verbs and where each lands, instead of describing Entwurf as
|
|
108
|
+
garden-id messaging alone. The README gains an open/reopen/message table with each verb's
|
|
109
|
+
harness scope. FAQ's tmux list includes pi-durable again, and CONTRIBUTING no longer calls
|
|
110
|
+
the shipped Codex native-push citizen an unreleased candidate.
|
|
111
|
+
|
|
112
|
+
### Release boundary and verification
|
|
113
|
+
|
|
114
|
+
- **Review.** The source checkpoint `86d4b65` and its amendment `d1c9103` were reviewed by
|
|
115
|
+
the #141 coordinator, Fable advisory reviews (no Blocker; their Defects were fixed before
|
|
116
|
+
the checkpoint) and a read-only Grok review of `86d4b65`. Grok's eight documentation and
|
|
117
|
+
live-authority findings were closed in `d1c9103`, and its recheck found no new Defect. The
|
|
118
|
+
Codex fix `90fa8bb` follows a coordinator-approved design with a read-only Grok design
|
|
119
|
+
review; a Fable advisory review of its pre-commit bytes found no Blocker, and its one Defect,
|
|
120
|
+
the missing Codex entry above, is closed in this section.
|
|
121
|
+
- **Local evidence before this preparation is focused, not a whole pass.** Each affected
|
|
122
|
+
qualification wave (PARTIAL) measured its own candidate and none is carried to another. S0
|
|
123
|
+
killed 70/70 in two groups; 891 of its 961 committed claims were not run. The S1-B3 source
|
|
124
|
+
bytes killed 82/82 in three groups (dep-versions 4, pin-matcher 2, pi-durable beside 76), each
|
|
125
|
+
with a green control; 887 of the 969 committed claims were not run there, nor was the
|
|
126
|
+
node-floor coherence group. The Codex fix bytes, verified content-identical to `90fa8bb`,
|
|
127
|
+
killed 219/219 in six groups (app-server launch 10, native push 8, admission parity 2,
|
|
128
|
+
attribution self-test 1, gate manifests 52, mux fresh call 146), each with a green control;
|
|
129
|
+
752 of the 971 committed claims were not run. An earlier wave over that fix stopped at its
|
|
130
|
+
first group with 9 killed and one WRONG-REASON; it is kept as it was, not relabelled. The
|
|
131
|
+
vitest results cache drifting outside the dependency seal and one socket fixture temp root
|
|
132
|
+
observed during the native-push group are recorded, not waived. A fresh Entwurf-only npm
|
|
133
|
+
consumer of the `86d4b65` source bytes (packed with 0.35.1 metadata) proved graph and load
|
|
134
|
+
only: nine SDK members at 1.2.0, 24/24 carrier dist targets inside the consumer, and the
|
|
135
|
+
public launch reaching the SDK's own model refusal before any birth. A store migrated by a
|
|
136
|
+
1.2.0 run and reopened on 1.1.0 kept its version-2 tool task blocked as `task_too_old`: a
|
|
137
|
+
one-time fixture receipt, not a supported downgrade.
|
|
138
|
+
- **Codex 0.162.1 diagnostic is not a cut.** On the pre-amendment candidate, one Linux
|
|
139
|
+
`smoke-codex-fresh-live` diagnostic against a live 0.162.1 app-server passed 65 assertions,
|
|
140
|
+
native push included, with `gpt-5.6-sol` on the Codex side and `openai-codex/gpt-6.1-sol` for
|
|
141
|
+
the Pi sibling only. It is not release-gate acceptance and covers no other model. The earlier
|
|
142
|
+
local FULL and LIVE `--cut` were taken on the pre-fix candidate (the cut was BLOCKED when the
|
|
143
|
+
advertised alias was refused) and are not evidence for this one. The frozen FULL and the final
|
|
144
|
+
LIVE `--cut` passed on this candidate (below); the installed-consumer proof
|
|
145
|
+
(`check-pack-install`, run by the CI `install-surface` job, not by `check:full`) and the
|
|
146
|
+
prepared SHA's CI body are pending.
|
|
147
|
+
- **Final frozen floor on this candidate.** One frozen tree, HEAD `90fa8bb` plus this release's
|
|
148
|
+
metadata, with the same work-surface fingerprint before and after both runs.
|
|
149
|
+
`pnpm run check:full` passed once (817 s, exit 0; 599 files in the dry-run pack).
|
|
150
|
+
`LIVE=1 ./run.sh release-gate <scratch> --cut` passed once: **MUST PASS=24 FAIL=0 SKIP=0**,
|
|
151
|
+
**BEHAVIOR PASS=1 FAIL=0 SKIP=0**, `cut: OK`. Its own static FULL (814 s) means this floor ran
|
|
152
|
+
FULL twice. The Codex step named the operator-owned 0.162.1 app-server by pid (851181) with
|
|
153
|
+
`gpt-5.6-sol` on the Codex side and `openai-codex/gpt-6.1-sol` for the Pi siblings, and passed
|
|
154
|
+
65 assertions, native push included; it attaches to an existing server, so the managed
|
|
155
|
+
launcher's alias and dangling-alias paths remain unobserved. Scratch
|
|
156
|
+
`/tmp/entwurf-release-gate-0.36.0.lw5Xju`, log SHA-256
|
|
157
|
+
`17a2bd54efaaeba2899bf9bbd3c13c0e68749d9d03367347c4872d6f4126ad30`; FULL log SHA-256
|
|
158
|
+
`184ea443326a72858d25b70ba25b44e804307205586d8a03d4af7c5b07ee1288`. A read-only host census
|
|
159
|
+
afterwards found one `entwurf-chain-*` and one `smoke-pi-durable-fresh-live-*` root from this
|
|
160
|
+
run, the same per-run residue earlier LIVE runs left; it is recorded and was not cleaned. This
|
|
161
|
+
is local acceptance only: not the exact CI, not a whole qualification pass.
|
|
162
|
+
- **Exact CI pending.** The prepared SHA's exact CI (the four required jobs and the
|
|
163
|
+
qualification body) is the next checkpoint and is not presumed PASS.
|
|
164
|
+
- **Unpublished candidate carrier.** As in 0.35.1, `plugins/herdr/runtime-lock.json`
|
|
165
|
+
temporarily names the closed `herdr-checkout` source: an npm-source lock must agree with
|
|
166
|
+
the checkout's core version, and 0.36.0 has no published integrity yet. The Herdr
|
|
167
|
+
manifest stays 0.35.1. After the operator publishes core 0.36.0, a separate Herdr snapshot
|
|
168
|
+
re-pins the measured registry bytes.
|
|
169
|
+
- **Publication boundary.** No make artifact, core tag, GitHub Release or npm publication
|
|
170
|
+
is claimed; they wait for the exact CI, the make decision and the operator.
|
|
171
|
+
|
|
172
|
+
## v2026.10.13-herdr.0.35.1 — Herdr Entwurf plugin 0.35.1
|
|
173
|
+
|
|
174
|
+
A separate Herdr plugin snapshot, not another core release: core package 0.35.1 and
|
|
175
|
+
its `v0.35.1` tag remain unchanged. The operator has published the core to npm.
|
|
176
|
+
|
|
177
|
+
### Herdr plugin
|
|
178
|
+
|
|
179
|
+
- **Re-pin the published core 0.35.1 and close the checkout window.**
|
|
180
|
+
`plugins/herdr/runtime-lock.json` returns to production npm source
|
|
181
|
+
`@junghanacs/entwurf@0.35.1` with the registry's measured sha512
|
|
182
|
+
(`sha512-cZZaGfNP…EIchcQ==`). The plugin manifest moves 0.35.0 → 0.35.1;
|
|
183
|
+
admission remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged.
|
|
184
|
+
- **The same core capability through Herdr.** The runtime this snapshot acquires carries
|
|
185
|
+
core 0.35.1: the Claude 5.5 curation with its set-model readback and the pi-durable inbox
|
|
186
|
+
repair (#140). The core release also adds an English, source-only checkout menu. The
|
|
187
|
+
plugin changes no rail, gate or mutant.
|
|
188
|
+
- **Upgrade by acquisition source, not just version.** A settled npm-source 0.35.0
|
|
189
|
+
installation can rebind under the plugin README's ownership conditions. A host that
|
|
190
|
+
installed the intervening `herdr-checkout` candidate must explicitly deactivate by
|
|
191
|
+
its own absolute runtime path before reinstalling the npm-source snapshot.
|
|
192
|
+
No operator installation or active session is rewired by this release work.
|
|
193
|
+
|
|
194
|
+
### Source-specific verification
|
|
195
|
+
|
|
196
|
+
- Registry metadata reports version/latest 0.35.1, repair 0.12.8-repair.1. The downloaded
|
|
197
|
+
tarball is 11101943 bytes, SHA256
|
|
198
|
+
`6edbcf9fbf31a6df1aff04f34b28ac279a071917d13916410bf466fd33a44eae`, equal to the preserved
|
|
199
|
+
core release candidate. Independently computed sha512 equals `dist.integrity`;
|
|
200
|
+
the registry-shipped runtime helper is byte-equal to this checkout's.
|
|
201
|
+
- Required exact-registry-tarball Docker consumer passed without repacking. Real-npm
|
|
202
|
+
0.35.0 → 0.35.1 swap and harness-seeded torn-swap recovery passed: the product restored
|
|
203
|
+
the last-good tree before reacquisition, certified the new registry digest, then
|
|
204
|
+
performed an exact-request no-op and owned-fixture removal. Seven focused
|
|
205
|
+
Herdr/manifest gates passed with HEAD, index and work surface unchanged.
|
|
206
|
+
`check-herdr-sandbox` was not run locally for this snapshot because it reads the
|
|
207
|
+
operator's own herdr panes; it rides the pushed SHA's FULL floor in CI.
|
|
208
|
+
- At preparation time, the public-ref install/use/deactivate/reinstall journey and the
|
|
209
|
+
pushed plugin SHA's ordinary four-job CI are still pending. Their actual outcomes belong
|
|
210
|
+
to the release checkpoint; this paragraph is not their acceptance. Earlier npm or
|
|
211
|
+
checkout-carrier receipts cannot certify these source-specific axes.
|
|
212
|
+
- Core 0.35.1's native Codex LIVE remains an explicit per-cut unmeasured exception, not a
|
|
213
|
+
PASS or a standing waiver. Its whole qualification body ran at the core release SHA;
|
|
214
|
+
this plugin-only metadata change does not borrow that body as its own.
|
|
215
|
+
|
|
7
216
|
## 0.35.1 - 2026-10-13
|
|
8
217
|
|
|
9
218
|
### ACP
|
package/CONTRIBUTING.md
CHANGED
|
@@ -4,7 +4,7 @@ This is a daily-driver bridge. Correctness beats feature breadth. Read this befo
|
|
|
4
4
|
|
|
5
5
|
## What this repo is
|
|
6
6
|
|
|
7
|
-
`entwurf`
|
|
7
|
+
`entwurf` opens and messages visible sibling sessions across independent harnesses, and reopens dormant pi siblings in tmux ([capability table](./README.md)), with the garden id as their address — entwurf-core (v2 dispatch) + a meta-bridge + a pi adapter + an **ACP plugin on a two-backend adapter rail**; pi is one adapter, not the subject. The ACP plugin borrows the backend's identity (system prompt preset, model behavior, tool implementations) and shapes the *operating surface* — tools, MCP, skills, permissions — to match pi's own policy **wherever that backend exposes a knob for it**. Where it does not, the plugin does not fake one: a cortex session keeps its own native tool surface and receives MCP through an overlay projection, so "shaped to pi's policy" is a Claude-strength claim, not a universal one. Claude is the reference ACP backend and Snowflake Cortex Code is the second (landed 0.13.0, `cortex-` prefixed ids — [docs/acp-backend-rail.md](./docs/acp-backend-rail.md#cortex-code-audit-d1d10)); Codex is not on this rail at all — it is a shipped native-push citizen that keeps its own vendor tools and work context (see AGENTS.md, DELIVERY.md), never ACP-managed — and Gemini is not a shipped backend. That is the entire ACP-rail scope.
|
|
8
8
|
|
|
9
9
|
**How a backend joins the rail** (the shape a PR must take): one adapter object in `pi-extensions/lib/acp/backend-adapter.ts` + its own curated rows/overlay modules + its own `check-acp-*` gate and mutant lane. Backend-specific *behavior* must stay behind the adapter, and backend-specific settings ride the opaque `adapterSettings` seam rather than growing the common config. That is not a ban on ever touching the common layer (`backend.ts`'s turn loop, `acp-client.ts`, `event-mapper.ts`, `session-store.ts`, `config.ts`) — cortex's landing did change `backend.ts` to pass the authoritative session key through the generic `ensureOverlay` seam. The rule is narrower and stricter: a common-layer change must be **backend-invariant** (it reads no backend name and branches on no backend) and **separately gated**. A common file that grows an `if (backend === …)` is the thing to reject.
|
|
10
10
|
|
package/DELIVERY.md
CHANGED
|
@@ -193,6 +193,21 @@ no daemon and no pid file: Ctrl-C is the operator's. A live socket, an unidentif
|
|
|
193
193
|
second `--listen` are named refusals; a dead socket file is reported and launched over. Passing
|
|
194
194
|
the raw vendor command by hand remains equivalent and is not deprecated.
|
|
195
195
|
|
|
196
|
+
**The control endpoint from Codex 0.162.1 (#141).** `[source rust-v0.162.1]` The advertised path is
|
|
197
|
+
now only an alias: the vendor binds a 0600 socket under `realpath(/tmp)/codex-daemon-<euid>/`, named
|
|
198
|
+
by the sha256 of the canonical advertised path, and symlinks the advertised path to it
|
|
199
|
+
(`app-server-transport/src/transport/unix_socket.rs:43-131, 290-304`; `uds/src/daemon_directory.rs:1-38`).
|
|
200
|
+
One classifier, `checkCodexSocketFile`, accepts exactly a plain socket or that exact alias — link
|
|
201
|
+
owner, byte-equal target, a 0700 socket directory, a socket no other user can open — and refuses
|
|
202
|
+
every other symlink. The delivery probe, `codex queue --remote` and the fresh-call preflight connect
|
|
203
|
+
to the socket it verified, never to the alias again. The launcher runs the same classifier's
|
|
204
|
+
compiled twin (`mcp/entwurf-bridge/dist/scripts/codex-socket-classify.js`) directly, refuses any
|
|
205
|
+
answer it does not recognise, and reports a dangling exact alias as the dead leftover the vendor
|
|
206
|
+
removes on start. A same-euid process can still replace the verified socket file; that residual is
|
|
207
|
+
named, not locked. The alias layout is certified on the classifier in a sandbox; the 0.162.1
|
|
208
|
+
app-server protocol itself requires a named LIVE observation; a diagnostic is not release-cut
|
|
209
|
+
acceptance, which separately requires the official release gate.
|
|
210
|
+
|
|
196
211
|
#95 D1 (GLG, 2026-09-16) retired the requirement that this session be named `codex`, and with it the
|
|
197
212
|
rule that an omitted-placement Codex TARGET selected it. The operator still owns the app-server and
|
|
198
213
|
still chooses its room; Entwurf neither creates nor supervises it, and a missing app-server rejects.
|
package/FAQ.md
CHANGED
|
@@ -8,7 +8,7 @@ No. Entwurf is closer to a workshop than a factory: it connects independently ow
|
|
|
8
8
|
|
|
9
9
|
## What does Entwurf do?
|
|
10
10
|
|
|
11
|
-
It
|
|
11
|
+
It opens, reopens and messages visible sibling sessions across independent harnesses, each under a stable **garden id**. `entwurf_fresh_call` opens a new sibling in the caller's Herdr workspace or tmux session by default, `entwurf_resume_call` reopens a dormant pi sibling under the same id, and `entwurf_v2` delivers a message, reply or hand-off to an existing one through the rail it actually supports. It does not reconstruct prompts, hydrate transcripts, manage credentials, or emulate another harness.
|
|
12
12
|
|
|
13
13
|
## What is a garden id?
|
|
14
14
|
|
|
@@ -28,11 +28,11 @@ No. [`entwurf_v2`](./README.md#entwurf_v2--canonical-dispatch-verb) only address
|
|
|
28
28
|
|
|
29
29
|
## Where do visible siblings open?
|
|
30
30
|
|
|
31
|
-
Inside Herdr, Entwurf opens a new unfocused tab in the caller's workspace and currently admits pi and Claude Code. Outside Herdr, it opens one of the fixed pi, Claude Code, Copilot, OMP, or Codex runtimes in a visible tmux window. The runtime keeps its own model, tools, authentication, and transcript.
|
|
31
|
+
Inside Herdr, Entwurf opens a new unfocused tab in the caller's workspace and currently admits pi and Claude Code. Outside Herdr, it opens one of the fixed pi, pi-durable, Claude Code, Copilot, OMP, or Codex runtimes in a new window of the caller's tmux session, or of an existing session the caller names; without an explicit tmux placement, a Codex caller opens beside its own TUI pane. A dormant pi sibling reopens under the same id in a visible tmux window. The runtime keeps its own model, tools, authentication, and transcript.
|
|
32
32
|
|
|
33
33
|
## Does Entwurf replace Herdr or tmux?
|
|
34
34
|
|
|
35
|
-
No. Herdr and tmux provide visible seats. Entwurf
|
|
35
|
+
No. Herdr and tmux provide visible seats. Entwurf opens siblings into them, reopens dormant pi siblings, and carries identity, delivery, and receipts across independent harness sessions. A pane or tmux session is a location for a sibling, never its address or liveness proof.
|
|
36
36
|
|
|
37
37
|
## How do I install it?
|
|
38
38
|
|
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# entwurf
|
|
2
2
|
|
|
3
|
-
`entwurf`
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
`entwurf` connects independent agent harnesses as visible siblings: open a new session,
|
|
4
|
+
reopen a dormant pi session in tmux, or reach an existing sibling by **garden id**. Fresh
|
|
5
|
+
sessions open in the caller's Herdr workspace or tmux session by default; explicit tmux
|
|
6
|
+
placement can name another existing session. Each harness keeps its own runtime,
|
|
7
|
+
authentication, tools and transcript.
|
|
6
8
|
|
|
7
|
-

|
|
8
10
|
|
|
9
11
|
**Pi ↔ native Claude Code inside the [Herdr workbench](#herdr-workbench).**
|
|
10
12
|
A recorded source-checkout demo: callback → task → native Bash → reply.
|
|
@@ -21,12 +23,15 @@ receipts and named lifecycle verbs; the operator and native harnesses keep steer
|
|
|
21
23
|
Git branches, worktrees, file isolation and internal delegation remain their concern.
|
|
22
24
|
[Short answers: FAQ](./FAQ.md).
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
| Verb | Tool | Where it lands | Harnesses |
|
|
27
|
+
|---|---|---|---|
|
|
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
|
+
| **Reopen** a dormant sibling | `entwurf_resume_call` | A visible tmux window under the same garden id, with the transcript, model, provider and cwd its record names; no turn is run | pi |
|
|
30
|
+
| **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 |
|
|
31
|
+
|
|
32
|
+
Antigravity is message-only: an existing conversation registers itself, and Entwurf never
|
|
33
|
+
launches one. A launch receipt is neither the new sibling's address nor proof that it
|
|
34
|
+
processed its task; the sibling's own callback envelope supplies its garden id.
|
|
30
35
|
|
|
31
36
|
The package holds the v2 core, native-harness bridges, a pi adapter and an ACP
|
|
32
37
|
plugin. ACP is one ingress, not the boundary; pi is one adapter, not the center.
|
|
@@ -40,14 +45,15 @@ receipts; [CHANGELOG](./CHANGELOG.md) records source history.
|
|
|
40
45
|
## Install
|
|
41
46
|
|
|
42
47
|
**Choose by where you work. Bring your own harnesses, subscriptions and login.**
|
|
43
|
-
The native durable route below additionally supplies
|
|
44
|
-
release; it does not supply credentials or take
|
|
48
|
+
The native durable route below additionally supplies an app/TUI, Entwurf's own thin composition of
|
|
49
|
+
the durable app upstream omits from its npm release; it does not supply credentials or take
|
|
50
|
+
ownership of the harness.
|
|
45
51
|
|
|
46
52
|
### Direct — ordinary shell or tmux
|
|
47
53
|
|
|
48
54
|
Prerequisites: **Node >=24.0.0**, Python 3 for `setup`, and any harnesses you choose
|
|
49
55
|
to use, already installed and authenticated. Pi is optional-by-presence, supported
|
|
50
|
-
range `>=1.
|
|
56
|
+
range `>=1.2.0 <1.3`; Claude Code supported floor `>=2.1.217` is required for its
|
|
51
57
|
managed exec-hook lifecycle. pnpm is needed only for source-checkout setup.
|
|
52
58
|
|
|
53
59
|
```bash
|
|
@@ -77,7 +83,7 @@ restriction; that is not certification of every platform's harness rails.
|
|
|
77
83
|
|
|
78
84
|
### Native durable (pi-durable)
|
|
79
85
|
|
|
80
|
-
**The package supplies
|
|
86
|
+
**The package supplies Entwurf's owned app/TUI carrier and nine exact Pi 1.2.0 SDK
|
|
81
87
|
members.** No separate runtime checkout, patch, build or ordinary Pi CLI is needed.
|
|
82
88
|
The launch verifies carrier integrity and every reachable SDK edge's name/version;
|
|
83
89
|
incomplete, drifted or mixed supply refuses by name.
|
|
@@ -87,8 +93,9 @@ entwurf pi-durable --provider <provider> --model <model-id> --width task-wide
|
|
|
87
93
|
entwurf pi-durable --continue
|
|
88
94
|
```
|
|
89
95
|
|
|
90
|
-
The contact adds garden identity and two-way mailbox communication.
|
|
91
|
-
|
|
96
|
+
The contact adds garden identity and two-way mailbox communication. Entwurf owns the
|
|
97
|
+
thin app/TUI composition (shipped as an emitted JS carrier); execution, models/auth, queues,
|
|
98
|
+
SQLite, transcripts and recovery remain the upstream SDK's:
|
|
92
99
|
[Hard Rule 17](./AGENTS.md#hard-rules), **supply the missing surface; do not become the harness**.
|
|
93
100
|
|
|
94
101
|
Optional `--native-module <absolute file>` initializes trusted ESM before runtime/TUI
|
|
@@ -161,6 +168,13 @@ Liveness is read at dispatch time; an id's shape does not tell you its transport
|
|
|
161
168
|
|
|
162
169
|
### `entwurf_v2` — canonical dispatch verb
|
|
163
170
|
|
|
171
|
+
```text
|
|
172
|
+
pi / pi-durable / Claude Code / Copilot / OMP / Antigravity / Codex
|
|
173
|
+
→ record-backed garden id
|
|
174
|
+
→ entwurf_v2
|
|
175
|
+
→ control-socket | self-fetch mailbox | native-push
|
|
176
|
+
```
|
|
177
|
+
|
|
164
178
|
| What you want | Tool | What its receipt means |
|
|
165
179
|
|---|---|---|
|
|
166
180
|
| 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 |
|
package/VERIFY.md
CHANGED
|
@@ -213,8 +213,8 @@ Do not collapse source, package, fixture, and native-host evidence into one “g
|
|
|
213
213
|
**Native durable contact (#129, #130 carrier).** `check-pi-durable-beside` is the deterministic
|
|
214
214
|
beside-test/mutant coordinate in `check:contracts`: the adapter, the installed carrier/SDK-set
|
|
215
215
|
verifier, the preflight, the owner join, the carrier's relocation grammar, resolver and
|
|
216
|
-
maintainer emitter (its
|
|
217
|
-
|
|
216
|
+
maintainer emitter (its `--check` reads only the owned in-repo source, #141; the overlay patch is
|
|
217
|
+
retired, and `--origin <clone>` checks provenance only), and the bootstrap's explicit `--native-module` ingress
|
|
218
218
|
(#130 P2) with its paired `--native-module-dir` (#134), driven through the packaged `main`'s own
|
|
219
219
|
seams: initialization before the TUI and the open, named refusals, the identity and directory
|
|
220
220
|
guards, the top-level `*.extension.mjs` filter and byte-wise order, cross-module name refusals, the
|
|
@@ -250,11 +250,13 @@ constructed depth-3 mismatch refused by the verifier and seen by the oracle, the
|
|
|
250
250
|
app's own model refusal before any birth — also with one installed `--native-module` initialized
|
|
251
251
|
first, a reserved extension name refused before anything opens, one installed `--native-module-dir`
|
|
252
252
|
initializing only its top-level `*.extension.mjs` (#134) and a directory without a module refused
|
|
253
|
-
before anything opens — and the HOST kept a separate subject — a real pi 1.0
|
|
253
|
+
before anything opens — and the HOST kept a separate subject — a real pi 1.1.0
|
|
254
254
|
binary (the previous generation) beside the pinned native set is a named pi FAIL with zero Pi wiring while pi-durable still
|
|
255
|
-
PASSes — not native admission. The
|
|
256
|
-
equality is
|
|
257
|
-
|
|
255
|
+
PASSes — not native admission. The carrier's rebuild
|
|
256
|
+
equality is the owned source's emission (#141): the beside claim `PI-DURABLE-CARRIER-EMIT-SOURCE-EQUAL`
|
|
257
|
+
on every floor, `emit-pi-durable-carrier --check` as its CLI. The emitter's exact Node is red in the CI
|
|
258
|
+
`check` job (`ENTWURF_REQUIRE_EMITTER_NODE=1`) and a named SKIP on a host running another Node, not
|
|
259
|
+
acceptance there. First-release visible fresh/callback and native
|
|
258
260
|
caller/target/cross-harness LIVE are owed by `smoke-pi-durable-fresh-live`, a release-gate MUST
|
|
259
261
|
(LIVE=1; vendor V on a real Pi and a real pi-durable host); SDK or package green does not waive it.
|
|
260
262
|
|
|
@@ -348,7 +350,7 @@ The goal is not merely "invoke Claude Code." We want:
|
|
|
348
350
|
**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.
|
|
349
351
|
|
|
350
352
|
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`)
|
|
351
|
-
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.
|
|
353
|
+
2. pi wiring → `<project>/.pi/settings.json` + user-scope registration — only when a `pi` inside the supported range (`>=1.2.0 <1.3`) 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
|
|
352
354
|
3. Claude meta-bridge global plugin — only when `claude` is on PATH; otherwise skipped cleanly
|
|
353
355
|
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
|
|
354
356
|
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.2.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
|
@@ -134,7 +134,7 @@ ledger, 2026-10-03).
|
|
|
134
134
|
| Surface | Declaration | Class | What a green actually says |
|
|
135
135
|
|---|---|---|---|
|
|
136
136
|
| 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 |
|
|
137
|
-
| pi runtime | SDK exact `1.
|
|
137
|
+
| pi runtime | SDK exact `1.2.0`, host `>=1.2.0 <1.3` | **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. Unshipped candidate: #141's 1.2.0 move has its own acceptance still owed. 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 |
|
|
138
138
|
| ACP wire SDK | `@agentclientprotocol/sdk 1.6.0` | **exact** | the shared wire oracle both adapters speak |
|
|
139
139
|
| Claude ACP adapter | `@agentclientprotocol/claude-agent-acp 0.85.1` | **exact**, bundled | checkout candidate; resolved before any PATH fallback; declaration is not compatibility evidence |
|
|
140
140
|
| Claude Agent SDK | `0.3.286` (transitive) | **exact** oracle | the runtime risk surface behind the adapter |
|
package/docs/setup-clean-host.md
CHANGED
|
@@ -28,8 +28,8 @@ evidence split, and its three states must not collapse into "macOS is supported"
|
|
|
28
28
|
| npm/pnpm | npm is bundled with Node; pnpm is required for source setup | package or source installation |
|
|
29
29
|
| Python 3 | required by `setup`/`install` (project-path normalization + settings writers); `--help`/`check-bridge` stay Python-free | pi/Claude/agy/Copilot/Codex wiring writers |
|
|
30
30
|
| entwurf | global/project-local `@junghanacs/entwurf`, or a source checkout | operator command and garden capability |
|
|
31
|
-
| pi | optional-by-presence, `>=1.
|
|
32
|
-
| Native durable (`pi-durable`) | supplied by the Entwurf package (#130):
|
|
31
|
+
| pi | optional-by-presence, `>=1.2.0 <1.3` — absent is an explicit setup SKIP, below-floor is a named FAIL | ACP provider, control sockets |
|
|
32
|
+
| Native durable (`pi-durable`) | supplied by the Entwurf package (#130): Entwurf's owned app carrier plus the exact 1.2.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) |
|
|
33
33
|
| Claude Code | optional, **`>=2.1.217`** — the exec-form hook floor | Claude ACP auth/runtime and mailbox-backed native citizen |
|
|
34
34
|
| 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 |
|
|
35
35
|
| 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) |
|
|
@@ -209,7 +209,7 @@ on Darwin; that is wiring, not a rail receipt. If `pi` is on PATH,
|
|
|
209
209
|
Install the exact release floor, then wire the project:
|
|
210
210
|
|
|
211
211
|
```bash
|
|
212
|
-
npm install -g @earendil-works/pi-coding-agent@1.
|
|
212
|
+
npm install -g @earendil-works/pi-coding-agent@1.2.0
|
|
213
213
|
pi --version
|
|
214
214
|
|
|
215
215
|
cd ~/entwurf-smoke
|
|
@@ -217,7 +217,7 @@ entwurf install .
|
|
|
217
217
|
pi -e "$(npm root -g)/@junghanacs/entwurf" --list-models entwurf
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
The supported range is `>=1.
|
|
220
|
+
The supported range is `>=1.2.0 <1.3`. It is a hard minimum: installing this
|
|
221
221
|
release onto a 0.83.x pi host upgrades the runtime rather than keeping the older
|
|
222
222
|
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
223
223
|
control socket; no delivery rail launches a pi process.
|
|
@@ -313,23 +313,22 @@ by `entwurf pi` or by registering ordinary Pi's adapter.
|
|
|
313
313
|
What the Entwurf package supplies:
|
|
314
314
|
|
|
315
315
|
1. **The pi SDK set** — `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
316
|
-
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.
|
|
316
|
+
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.2.0`, plus
|
|
317
317
|
`proper-lockfile`, as Entwurf's own production dependencies (declared once in
|
|
318
318
|
`pi/pi-durable/overlay/upstream-pin.json` `sdk`). Model data rides the published
|
|
319
319
|
`pi-ai`; there is no catalog copy.
|
|
320
320
|
2. **The native app/TUI carrier** — upstream does not publish the experimental durable
|
|
321
321
|
app (`pi-coding-agent` excludes `dist/experimental`; `pi-durable` on npm is the
|
|
322
|
-
library). Entwurf
|
|
323
|
-
|
|
324
|
-
applied to `runtime.ts`, type-stripped and relocated, in `pi/pi-durable/carrier/`
|
|
322
|
+
library). Entwurf owns the six app files as canonical source (`pi/pi-durable/src`,
|
|
323
|
+
first taken from upstream tag `v1.1.0` `abe508e1b89912adde45528136c3221eb69acdd7`) and ships them type-stripped and relocated in `pi/pi-durable/carrier/`
|
|
325
324
|
with upstream's MIT license. Each file's source blob and emitted digest are in the pin.
|
|
326
325
|
The carrier reaches pi-coding-agent's internals only through its resolver
|
|
327
326
|
(`pi/pi-durable/carrier-resolver.mjs`), which maps them to the published package's
|
|
328
327
|
own `dist/` as installed — never through a source checkout.
|
|
329
328
|
|
|
330
|
-
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.
|
|
331
|
-
and [experimental app guide](https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/src/experimental/durable/README.md)
|
|
332
|
-
describe what the carrier is. Running the bare upstream app does not attach Entwurf's
|
|
329
|
+
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.2.0/packages/durable/README.md)
|
|
330
|
+
and the [experimental app guide](https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/src/experimental/durable/README.md)
|
|
331
|
+
(last published at v1.1.0) describe what the carrier is. Running the bare upstream app does not attach Entwurf's
|
|
333
332
|
garden contact. Entwurf does not rebuild the controller/model/auth/storage system or
|
|
334
333
|
proxy a subscription; native execution, models, auth, queues, SQLite and recovery stay
|
|
335
334
|
upstream-owned.
|
|
@@ -411,7 +410,7 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
411
410
|
manifest field; it is a known constraint of supplying both from one package, accepted for 0.32,
|
|
412
411
|
not a claim that every load path is harmless.
|
|
413
412
|
|
|
414
|
-
The ordinary Pi CLI on PATH is a separate subject (§2, range `>=1.
|
|
413
|
+
The ordinary Pi CLI on PATH is a separate subject (§2, range `>=1.2.0 <1.3`): a host Pi is
|
|
415
414
|
not needed to run pi-durable, and a host inside the range need not be the same copy as the
|
|
416
415
|
carrier's. Native Pi owns credentials, model settings and durable SQLite sessions; keep them
|
|
417
416
|
in place rather than copying credentials or migrating ordinary Pi transcripts. Native
|
|
@@ -424,19 +423,28 @@ proof ([#130](https://github.com/junghan0611/entwurf/issues/130)).
|
|
|
424
423
|
|
|
425
424
|
### Maintainer: re-emitting the carrier
|
|
426
425
|
|
|
427
|
-
Only a maintainer
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
426
|
+
Only a maintainer changing the pi-durable app runs `scripts/emit-pi-durable-carrier.ts`. Its
|
|
427
|
+
input is Entwurf's own source in this repository (`pi/pi-durable/src`, #141, typechecked by
|
|
428
|
+
`pi/pi-durable/tsconfig.json` against the installed SDK's declarations): it type-strips with
|
|
429
|
+
Node's own strip-only TypeScript, relocates, and checks that the six files import exactly the
|
|
430
|
+
pin's declared `distTargets`:
|
|
432
431
|
|
|
433
432
|
```bash
|
|
434
|
-
node scripts/emit-pi-durable-carrier.ts --
|
|
435
|
-
node scripts/emit-pi-durable-carrier.ts --
|
|
433
|
+
node scripts/emit-pi-durable-carrier.ts --write # names every generated field it changes
|
|
434
|
+
node scripts/emit-pi-durable-carrier.ts --check # rebuild equality
|
|
435
|
+
node scripts/emit-pi-durable-carrier.ts --origin <clone holding origin.commit> # provenance only
|
|
436
436
|
```
|
|
437
437
|
|
|
438
|
-
|
|
439
|
-
|
|
438
|
+
A missing source file is a named refusal, never a skip. The byte comparison also runs as a
|
|
439
|
+
beside claim on every floor. The emitter's Node is part of the pin: under another Node,
|
|
440
|
+
`--check` compares the bytes and then reports the identity as a named SKIP, never rebuild
|
|
441
|
+
acceptance; the CI `check` job runs the pinned Node with `ENTWURF_REQUIRE_EMITTER_NODE=1`, where
|
|
442
|
+
a mismatch is red. `--origin` checks the frozen `origin` record against the upstream objects
|
|
443
|
+
it names (`<commit>:<path>`, `--no-replace-objects`) and never feeds a rebuild.
|
|
444
|
+
|
|
445
|
+
The owned source is formatted at upstream width (`biome.json` override, indentWidth 3), with no
|
|
446
|
+
per-file exception. A formatting change to an owned file changes its emitted bytes. So it is
|
|
447
|
+
re-emitted with `--write`, and its generated digest is reviewed like any other carrier change.
|
|
440
448
|
|
|
441
449
|
## 3. Optional Claude Code native citizen
|
|
442
450
|
|
|
@@ -601,7 +609,7 @@ as a note rather than a fault.
|
|
|
601
609
|
|
|
602
610
|
**entwurf sets no OMP version floor in code, and will not grow one on schedule.** Detection is
|
|
603
611
|
presence-only (`command -v "${OMP_BIN:-omp}"`); there is no `entwurf.ompFloor`, no coherence
|
|
604
|
-
gate, and no exact pin — unlike Node (`engines.node`), pi (`>=1.
|
|
612
|
+
gate, and no exact pin — unlike Node (`engines.node`), pi (`>=1.2.0 <1.3`) and Claude Code
|
|
605
613
|
(`entwurf.claudeCodeFloor`), each of which has an enforcement point. That asymmetry is a
|
|
606
614
|
decision, not an omission. A floor is the answer to a vendor that fails SILENTLY — Claude Code
|
|
607
615
|
earned one because an older binary validates the exec manifest, drops `args` at runtime, and
|
|
@@ -549,10 +549,11 @@ export async function codexFreshPreflight(env, deps = {}) {
|
|
|
549
549
|
return "codex-mcp-hand-missing";
|
|
550
550
|
if (visibleIdentityMissing(config))
|
|
551
551
|
return "codex-visible-identity-missing";
|
|
552
|
-
const
|
|
553
|
-
const socket = (deps.checkSocket ?? checkCodexSocketFile)(socketPath);
|
|
552
|
+
const socket = (deps.checkSocket ?? checkCodexSocketFile)(resolveCodexDefaultSocketPath(env));
|
|
554
553
|
if (!socket.ok)
|
|
555
554
|
return "codex-app-server-unavailable";
|
|
556
|
-
|
|
555
|
+
// The protocol exchange goes to the endpoint the check verified, never the advertised path
|
|
556
|
+
// again (on Codex 0.162.1 that path is an alias; see `checkCodexSocketFile`).
|
|
557
|
+
const live = await appServerIsLive(socket.connectPath, deps.openProtocol ?? realCodexProtocolOpener, deps.appServerTimeoutMs ?? DEFAULT_APP_SERVER_TIMEOUT_MS);
|
|
557
558
|
return live ? null : "codex-app-server-unavailable";
|
|
558
559
|
}
|