@junghanacs/entwurf 0.39.0 → 0.41.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 +4 -2
- package/BASELINE.md +60 -5
- package/CHANGELOG.md +557 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +52 -2
- package/FAQ.md +8 -4
- package/README.md +37 -17
- package/VERIFY.md +23 -10
- package/docs/acp-backend-rail.md +5 -1
- package/docs/external-mcp-host.md +8 -6
- package/docs/fresh-cut-policy.md +9 -1
- package/docs/setup-clean-host.md +64 -9
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +100 -24
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/cc-retire-pidfd.py +236 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/cc-retire-request.js +473 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/control-retire.js +125 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-retire-production.js +149 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-retire.js +158 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-surface.js +2 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +283 -20
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +7 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -3
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +3 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-mailbox-body.js +10 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +96 -16
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +5 -29
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-launch.js +28 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +26 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-retire-request.js +76 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-receive.js +123 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-send.js +259 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/remote-pair-transport.js +80 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +67 -17
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/retirement-event.js +211 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-hook.js +124 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +53 -2
- package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
- package/mcp/entwurf-bridge/dist/scripts/probe-bridge-command.js +1 -0
- package/mcp/entwurf-bridge/dist/scripts/remote-pair-receive.js +65 -0
- package/mcp/entwurf-bridge/src/index.ts +118 -24
- package/mcp/entwurf-bridge/test.sh +2 -2
- package/mcp/entwurf-bridge/tsconfig.build.json +17 -1
- package/package.json +5 -5
- package/pi/meta-bridge/entwurf-meta-receive/scripts/hook-launch.sh +3 -3
- package/pi-extensions/entwurf-control.ts +55 -20
- package/pi-extensions/lib/cc-retire-pidfd.py +236 -0
- package/pi-extensions/lib/cc-retire-request.ts +553 -0
- package/pi-extensions/lib/control-retire.ts +195 -0
- package/pi-extensions/lib/entwurf-control-rpc.ts +17 -1
- package/pi-extensions/lib/entwurf-v2-retire-production.ts +227 -0
- package/pi-extensions/lib/entwurf-v2-retire.ts +269 -0
- package/pi-extensions/lib/entwurf-v2-surface.ts +2 -1
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +390 -36
- package/pi-extensions/lib/fresh-call-composition.ts +15 -0
- package/pi-extensions/lib/fresh-call-dispatch.ts +45 -4
- package/pi-extensions/lib/herdr-fresh-call.ts +5 -0
- package/pi-extensions/lib/meta-mailbox-body.ts +13 -4
- package/pi-extensions/lib/meta-session.ts +140 -16
- package/pi-extensions/lib/mux-fresh-call.ts +7 -27
- package/pi-extensions/lib/mux-launch.ts +29 -0
- package/pi-extensions/lib/mux-resume-call.ts +33 -12
- package/pi-extensions/lib/pi-retire-request.ts +111 -0
- package/pi-extensions/lib/remote-pair-receive.ts +184 -0
- package/pi-extensions/lib/remote-pair-send.ts +325 -0
- package/pi-extensions/lib/remote-pair-transport.ts +81 -0
- package/pi-extensions/lib/resume-launch-identity.ts +104 -18
- package/pi-extensions/lib/retirement-event.ts +253 -0
- package/pi-extensions/meta-bridge-hook.ts +142 -13
- package/pi-extensions/meta-bridge-pi-durable.ts +56 -2
- package/run.sh +122 -7
- package/scripts/agy-bridge-config.py +4 -1
- package/scripts/build-bridge.sh +14 -0
- package/scripts/check-capability-bundle-reach.ts +135 -2
- package/scripts/check-entwurf-bridge-boot.ts +2 -1
- package/scripts/check-entwurf-fact-provider.ts +1 -0
- package/scripts/check-entwurf-v2-production.ts +2 -0
- package/scripts/check-entwurf-v2-surface.ts +7 -0
- package/scripts/check-gate-qualification.ts +20 -8
- package/scripts/check-herdr-activation.ts +2 -2
- package/scripts/check-herdr-placement.ts +1 -0
- package/scripts/check-hook-launch-topology.ts +6 -15
- package/scripts/check-install-container.sh +2 -2
- package/scripts/check-meta-doctor-oracle.sh +27 -1
- package/scripts/check-meta-facts.ts +8 -3
- package/scripts/check-meta-hook-session-switch.ts +230 -13
- package/scripts/check-meta-identity-consumers.ts +1 -0
- package/scripts/check-meta-listing.ts +1 -0
- package/scripts/check-meta-manifest-schema.py +1 -1
- package/scripts/check-meta-session.ts +31 -0
- package/scripts/check-meta-v3-record.ts +55 -1
- package/scripts/check-mux-resume-call.ts +35 -9
- package/scripts/check-peer-facts.ts +1 -0
- package/scripts/check-pi-durable-contact.ts +3 -1
- package/scripts/check-pi-durable-send.ts +4 -2
- package/scripts/check-pi-mcp-bridge.ts +1 -0
- package/scripts/check-remote-pair-installed.ts +242 -0
- package/scripts/check-resume-launch-identity.ts +62 -23
- package/scripts/lib/meta-hook-bundle.ts +72 -0
- package/scripts/lib/remote-pair-installed-audit.ts +25 -0
- package/scripts/meta-bridge-claude-floor.sh +13 -9
- package/scripts/meta-bridge-doctor.sh +17 -0
- package/scripts/meta-bridge-install.sh +6 -0
- package/scripts/meta-facts.ts +1 -1
- package/scripts/mutants/bridge-boot-resume.json +5 -2
- package/scripts/mutants/cc-retire-pidfd.json +129 -0
- package/scripts/mutants/cc-retire-request.json +171 -0
- package/scripts/mutants/control-retire.json +105 -0
- package/scripts/mutants/control-send-receipt.json +2 -2
- package/scripts/mutants/copilot-receive.json +2 -6
- package/scripts/mutants/entwurf-v2-retire.json +476 -0
- package/scripts/mutants/fresh-call-dispatch.json +37 -0
- package/scripts/mutants/meta-hook-session-switch.json +88 -0
- package/scripts/mutants/meta-identity.json +57 -0
- package/scripts/mutants/mux-fresh-call.json +1 -1
- package/scripts/mutants/mux-resume-call.json +40 -4
- package/scripts/mutants/pi-durable.json +79 -0
- package/scripts/mutants/pi-retire-request.json +72 -0
- package/scripts/mutants/remote-pair-display.json +53 -0
- package/scripts/mutants/remote-pair-installed-audit.json +28 -0
- package/scripts/mutants/remote-pair-receive.json +126 -0
- package/scripts/mutants/remote-pair-roundtrip.json +83 -0
- package/scripts/mutants/remote-pair-send.json +194 -0
- package/scripts/mutants/remote-pair-transport.json +66 -0
- package/scripts/mutants/resume-launch-identity.json +35 -8
- package/scripts/mutants/retirement-event.json +195 -0
- package/scripts/mutants/v2-surface.json +16 -0
- package/scripts/mutants/v2-visible-resume.json +283 -13
- package/scripts/probe-bridge-command.ts +1 -0
- package/scripts/remote-pair-receive.ts +73 -0
- package/scripts/smoke-agy-install-state.sh +2 -2
- package/scripts/smoke-copilot-mcp-state.sh +1 -1
- package/scripts/smoke-herdr-raw-install-live.sh +5 -4
- package/scripts/smoke-meta-install-state.sh +4 -4
- package/scripts/smoke-mux-lifecycle-live.ts +10 -10
- package/scripts/smoke-omp-mcp-state.sh +1 -1
- package/scripts/smoke-pi-durable-fresh-live.ts +5 -3
- package/scripts/smoke-pi-provider-state.sh +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,563 @@ All notable changes to this project will be documented here. Format follows [Kee
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.41.0 - 2026-10-22
|
|
8
|
+
|
|
9
|
+
A sibling's garden id is its birthday, and this cut lets it rest and come back under it. A
|
|
10
|
+
sibling can now be opened, spoken to, retired when the human operator names it, and reopened
|
|
11
|
+
under the same id with its conversation intact. That holds for ordinary Pi and native Claude
|
|
12
|
+
Code. Retirement is a pause in a long session, not cleanup: it is never autonomous, a paired
|
|
13
|
+
requested/outcome record beside the target's record is attempted for every request with any
|
|
14
|
+
recording failure reported on its own axis, and the record and transcript stay.
|
|
15
|
+
A durable pi-durable sibling can drive both verbs. Each was measured once on real sessions, which
|
|
16
|
+
is recorded as dated evidence, not as a release gate.
|
|
17
|
+
|
|
18
|
+
### Fresh call
|
|
19
|
+
|
|
20
|
+
- **A Pi-dialect model names its provider, and never OpenRouter (#76).** The dispatch root both
|
|
21
|
+
rails share now refuses, before either rail is asked anything, a pi or pi-durable model whose
|
|
22
|
+
provider segment is `openrouter` in any letter case (`model-openrouter-forbidden`) and a pi
|
|
23
|
+
model that names no provider at all (`pi-model-not-provider-qualified`). The second replaces
|
|
24
|
+
the 2026-08-13 non-goal that allowed a bare id: GLG decided on 2026-10-21 that the provider is
|
|
25
|
+
stated explicitly, because a bare alias resolves to whichever catalog row Pi prefers (the
|
|
26
|
+
2026-09-17 bare `terra` opened on an OpenRouter row). It is a call-time input contract, not a
|
|
27
|
+
version pin: no model list, catalog copy, resolved-row or endpoint check was added, so a later
|
|
28
|
+
model name passes this provider check once it is written `<provider>/<id>` (not a promise
|
|
29
|
+
that it launches, nor a bypass of #128). Other backends' model names
|
|
30
|
+
(a claude-code `opus` alias) are not judged; resume and #128 curation are unchanged. The
|
|
31
|
+
refusal checks the name a caller wrote, not the endpoint a provider name reaches. The
|
|
32
|
+
`entwurf_fresh_call` model description says both rules. Proof:
|
|
33
|
+
`pi-extensions/lib/fresh-call-dispatch.test.ts` (three QKs) and three mutants in the
|
|
34
|
+
`fresh-call-dispatch` lane (12 → 15), executed through `./run.sh check-fresh-call-provider`.
|
|
35
|
+
|
|
36
|
+
### pi-durable
|
|
37
|
+
|
|
38
|
+
- **The durable contact offers `entwurf_resume_call` (#147 L1).** A pi-durable citizen (the
|
|
39
|
+
coordinator's host) could not call the existing same-id resume verb: its contact exposed six bridge
|
|
40
|
+
tools and resume was not among them. It now registers a seventh, under the bridge's own
|
|
41
|
+
single-`target` schema, and forwards the call to the bridge unchanged. The verb itself is
|
|
42
|
+
unchanged by L1: at that checkpoint pi-only targets (L2 below widens the domain), a live target
|
|
43
|
+
refused, no turn, the record supplies the launch facts. Nothing new authorises who may resume, a
|
|
44
|
+
retire verb is not here, and a running durable host offers the tool only after it is restarted onto a build that
|
|
45
|
+
carries it. Because the bootstrap reserves every contact tool name, an operator native module
|
|
46
|
+
that registers a tool named `entwurf_resume_call` is now refused as `native-module-name-reserved`.
|
|
47
|
+
Proof: two QKs in `pi-extensions/meta-bridge-pi-durable.test.ts` — the tool is offered and hands
|
|
48
|
+
the bridge exactly `{target}`, and a faux model's call on the published runtime reaches this
|
|
49
|
+
package's compiled bridge through the contact's production connector and reads the bridge's named
|
|
50
|
+
refusal for a test-owned record of a backend with no same-id resume (codex since L2; no citizen is
|
|
51
|
+
resumed). Two mutants
|
|
52
|
+
in the `pi-durable` lane (84 → 86), executed through `./run.sh check-pi-durable-beside`. The
|
|
53
|
+
independent tool lists of `check-pi-durable-contact`, `check-pi-durable-send` and
|
|
54
|
+
`smoke-pi-durable-fresh-live` now name seven tools. One default-cell `check-pi-durable-send` run
|
|
55
|
+
(scripted loopback endpoint and the carrier app's native tool path; no vendor model turn) offered
|
|
56
|
+
`entwurf_resume_call` in the app's first model request, and its parameters there equal the
|
|
57
|
+
bridge's own listed schema — read from that run's raw wire receipt, because the default cell's
|
|
58
|
+
QK judges only self, peers and v2; the seven-tool `native-module` cell was not run. A running
|
|
59
|
+
coordinator host offering seven tools, and any operator rollout, remain unmeasured.
|
|
60
|
+
|
|
61
|
+
### Operator-requested retirement (#147)
|
|
62
|
+
|
|
63
|
+
- `entwurf_retire_call {target}` makes one explicitly human-requested Pi or Claude Code attempt. Development, coordinator status and record-backed attribution are not standing permission. Where a host provides or is configured with an approval step, that step applies as well; Pi and pi-durable 1.3.0 have no built-in approval prompt by default. MCP annotations and caller identity are hints and attribution, not permission. No autonomous cleanup, roster expansion or automatic replay.
|
|
64
|
+
- The per-request production binding captures its directories and cancellation signal. Requested/outcome events share an id in a target-gid append-only sidecar with explicit actor/target fields. Action, record-write failure and lock cleanup stay independent; an append failure cannot turn a possibly effective action into a safe retry. The source bridge lists nine tools, ordinary Pi seven active plus two hidden, and the durable contact eight.
|
|
65
|
+
- Independent review repaired a metadata-test oracle, random-id privacy-test flakiness and snapshot/file-target consistency. A private `node_modules` compiled consumer passed29 assertions over anonymous/self refusal, existing resume refusal, inert Node RPC and two-line attribution. Operator dist hashes stayed unchanged. That consumer is not real Pi/Claude Code retirement, Native/LIVE, G4 rollout or release acceptance; final candidate floors and exact-SHA CI are still owed.
|
|
66
|
+
- 2026-10-22, source `a9c9459`: one operator-requested, test-owned Native round trip per backend — a fresh pi-durable caller (actual offering of all eight contact tools) retired and same-id resumed a fresh ordinary Pi and a native Claude Code 2.1.307 target once each, with dormant delivery refused, identity and transcript preserved across the promptless resume, and blind recall. n=1; not a MUST gate, ACP, Herdr, Windows, release-artifact or flush/descendant claim ([BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1)). The five stale on-disk Codex/Copilot/OMP reader copies were rolled forward with their owning installers; Copilot birth's doctor runtime axis remains RED on a historical hook error. GLG explicitly deferred its Native runtime validation for this landing: the current free `auto` account, not a subscription, is impractical to test (GLG reports a greeting taking over a minute; not re-benchmarked here). On-disk reader compatibility is closed with that named runtime deferral; resident-process reloads and broader runtime/release acceptance remain unmeasured. Earlier component receipts below do not become this candidate's kill-power.
|
|
67
|
+
|
|
68
|
+
### Internal retirement checkpoints (#147; before public composition)
|
|
69
|
+
|
|
70
|
+
- **Pi's control server now serves an internal `retire` RPC.** A Pi started from this
|
|
71
|
+
checkout can already receive it; this is not a claim about the published 0.40.0 package.
|
|
72
|
+
Immutable garden/native identity, TUI, idle and no-pending guards precede one SDK shutdown
|
|
73
|
+
request. The shared production response envelope and strict one-shot client keep
|
|
74
|
+
`shutdown-requested` distinct from exit, flush or model silence. Busy work is refused, not
|
|
75
|
+
aborted or queued for a later shutdown.
|
|
76
|
+
- **Claude Code has a fixed Linux pidfd helper and request adapter.** The helper is copied
|
|
77
|
+
beside the compiled adapter; it pins a process, checks its start key, accepts one complete
|
|
78
|
+
go/cancel frame and requests one fd SIGTERM with bounded exit observation. Fresh
|
|
79
|
+
record/receiver/sender birth, arm binding, owner domain and pid/key joins run before helper
|
|
80
|
+
spawn and after ready. Unknown is not safe-retry permission. A fd-process exit does not
|
|
81
|
+
prove conversation identity, descendant termination or transcript flush.
|
|
82
|
+
- **A private dispatcher preserves action and cleanup independently.** Trusted caller
|
|
83
|
+
attribution/self refusal, fresh target and liveness checks, one adapter and one lock release
|
|
84
|
+
are composed through mandatory seams. It creates no grant/role database. At these component
|
|
85
|
+
checkpoints there was no accepted production host composition or public retirement MCP/contact
|
|
86
|
+
registration. The later candidate composition above owns its separate binding and runtime proof.
|
|
87
|
+
- **Proof remains candidate-local:** owned receiver/helper fixtures; independent review;
|
|
88
|
+
primitive PARTIAL Pi9 + CC11, later request-adapter PARTIAL9+6+15+40, then pure-dispatcher
|
|
89
|
+
PARTIAL10 on different candidates; private compiled consumer28 and a missing-Pi-entry
|
|
90
|
+
negative on the adapter candidate. These are not release-SHA kill-power, installed retirement
|
|
91
|
+
runtime or four-cell native lifecycle evidence. Actual host composition, G4 reader rollout,
|
|
92
|
+
public caller integration and the preserved #106 B append-only attribution record remain
|
|
93
|
+
open. Existing live/release floors are not waived by these checkpoints.
|
|
94
|
+
|
|
95
|
+
### Resume
|
|
96
|
+
|
|
97
|
+
- **`entwurf_resume_call` reopens a dormant Claude Code citizen under its own garden id (#147 L2).**
|
|
98
|
+
The verb's domain is now pi and claude-code, a closed set; every other backend is the named
|
|
99
|
+
`target-backend-unsupported` (the retired `target-not-pi` has no alias). A Claude Code target is
|
|
100
|
+
launched as the fixed `claude --resume <record nativeSessionId>` at the record's cwd — no model or
|
|
101
|
+
permission flag it was once started with is restored, and no transcript is read; the record's
|
|
102
|
+
session id must be a lowercase UUID and its recorded transcript an existing file. Dormancy means
|
|
103
|
+
the LAST VALIDATED owner the Entwurf hook armed is proven gone AND that arm is still the record's
|
|
104
|
+
last one: the receiver marker, read through the no-follow fd reader (`readStoreRecordFile`: a
|
|
105
|
+
symlink or non-regular entry is corrupt, never followed) and judged by the shared
|
|
106
|
+
`classifyMarkerOwner`, must name this record's session and an owner proven DEAD, and the record
|
|
107
|
+
re-read after that verdict must carry the same non-null `attachIncarnation` the marker copied.
|
|
108
|
+
No marker, an unreadable or mismatched one, a live owner, an inconclusive one and an unbound one
|
|
109
|
+
each refuse by name (`target-receiver-absent` / `-corrupt` / `-mismatch` / `-unbound`,
|
|
110
|
+
`target-live`, `target-indeterminate`) with no window; the launch uses the re-read record, and no
|
|
111
|
+
marker or record is removed or rewritten. The observation succeeds only when a NEW live owner in
|
|
112
|
+
the pane this call opened re-arms the marker for the same session with a fresh binding the
|
|
113
|
+
current record also carries (same createdAt); a record defect stops it at once as
|
|
114
|
+
`record-unreadable` with its cause (window kept), and an unseen re-arm is `resume-unobserved`.
|
|
115
|
+
The verb submits no prompt; for Claude Code what the runtime does after it comes back (a doorbell
|
|
116
|
+
on unread mail may wake a turn) is unmeasured. Both backends' resume windows now carry the fixed
|
|
117
|
+
identity scrub fresh-call already had (`-e PI_SESSION_ID= -e PI_AGENT_ID=`, shared from
|
|
118
|
+
`mux-launch.ts`), because a resumed Claude Code never re-exports its own. Inside herdr the tmux
|
|
119
|
+
resume rail refuses as `herdr-resume-unsupported` instead of using an ambient `TMUX` (this also
|
|
120
|
+
applies to pi). The receipt names the caller from the same authoritative identity fresh_call reads,
|
|
121
|
+
as attribution only: an anonymous caller is `unattributed`, never refused, while a defect in the
|
|
122
|
+
caller's own store fails the call loud — for pi resume too — exactly as fresh_call does.
|
|
123
|
+
- **The arm binding: one new V3 key, `attachIncarnation` (#147 L2 B1).** A dead receiver marker
|
|
124
|
+
used to be resume evidence even when a LATER attach of the same session had committed but could
|
|
125
|
+
not re-arm the marker (owner unproven, marker write failed), so a second window could open on a
|
|
126
|
+
live session. Now the Claude Code hook mints a clock-independent 128-bit value (`randomBytes(16)`)
|
|
127
|
+
on every arm-capable event (SessionStart, CwdChanged, FileChanged — an arm revision, so one live
|
|
128
|
+
process mints many), commits it in the same atomic record upsert and copies it into the receiver
|
|
129
|
+
marker; UserPromptSubmit and every other writer preserve it, and nothing fills it by inference.
|
|
130
|
+
Every write the hook makes to an existing record runs under a per-gid record-arm lock in its own
|
|
131
|
+
directory (`meta-record-arm-locks`, beside the receivers dir; never the v2 dispatch lock visible
|
|
132
|
+
resume holds across its observation): the garden id is learned by a read-only certified lookup,
|
|
133
|
+
an absent record is published create-only (`upsertMetaSession` `expectAction` refuses a raced
|
|
134
|
+
create instead of turning it into an unlocked attach), an arm waits at most 2 s for the lock and
|
|
135
|
+
otherwise writes NOTHING and logs ERROR, and a busy UserPromptSubmit skips its backfill. A marker
|
|
136
|
+
write failure after the record committed is an ERROR logged after `INFO armed watch`, and resume
|
|
137
|
+
then refuses that garden as unbound. **Schema:** the same V3, one key wider — absent reads as
|
|
138
|
+
`null` ("no binding observed"), every serialize emits it, a present value must be 32 lowercase
|
|
139
|
+
hex, every other stray key is still refused; gardenId, nativeSessionId and createdAt keep their
|
|
140
|
+
values and no record is rewritten. `meta-facts` citizens carry the key verbatim. **One-way per host:** a reader that predates the key refuses
|
|
141
|
+
every record that carries it, and an old writer certifies the whole store first, so once one new
|
|
142
|
+
write lands every old reader and writer on that host refuses — a mixed-reader incident on oracle
|
|
143
|
+
on 2026-10-21 (records written by a Pi loaded from the development checkout) took the CC hook
|
|
144
|
+
and the pi-durable contact down until the checkout dist and the CC hook bundle were re-deployed.
|
|
145
|
+
Codex birth, the Copilot extension/receiver, the OMP bridge/receiver and the external
|
|
146
|
+
`entwurf-peek` mirror still carried the old reader there at L2; the on-disk copies were rolled
|
|
147
|
+
forward on 2026-10-22 (see the retirement section).
|
|
148
|
+
Old dormant Claude Code citizens whose record has no binding stay `target-receiver-unbound` until
|
|
149
|
+
a human reopens them once under a new hook. **Accepted boundary (GLG, 2026-10-21, current live
|
|
150
|
+
Pi/CC cohort scope):** only committed hook attaches are guarded — a process that holds the session
|
|
151
|
+
without one (hooks disabled, a record-arm lock timeout or a store failure at its start) is
|
|
152
|
+
invisible to the proof. The installed CC hook bundle now carries `lib/entwurf-v2-lock`, and the
|
|
153
|
+
doctor's writer-version parity checks it beside the writer.
|
|
154
|
+
- **Claude Code floor `>=2.1.306`** (`package.json` `entwurf.claudeCodeFloor`, GLG 2026-10-21):
|
|
155
|
+
same-id resume runs `claude --resume` from the record's last observed cwd, and the vendor CLI
|
|
156
|
+
reference says the session-id search covers other projects only from v2.1.223. 2.1.306 is the
|
|
157
|
+
version GLG relayed as running here; it is a declared floor with no LIVE receipt at 2.1.306 itself
|
|
158
|
+
(the 2026-10-22 n=1 round trip ran on 2.1.307). The
|
|
159
|
+
exec-form observations at 2.1.217 stand as observations.
|
|
160
|
+
- Proof: QKs beside the composition (`entwurf-v2-visible-resume.test.ts`), in
|
|
161
|
+
`check-resume-launch-identity`, `check-mux-resume-call`, `check-meta-v3-record`,
|
|
162
|
+
`check-meta-session`, `check-meta-hook-session-switch` (binding pair, UPS preserve, unproven owner,
|
|
163
|
+
lock busy/wait/own-dir, two overlapping successful schedules, and an install-closure check that
|
|
164
|
+
compares the hook's static double-quoted `from` imports with what the installer copies and then
|
|
165
|
+
runs the staged compiled hook) and `check-meta-doctor-oracle` (installed binding; lock module
|
|
166
|
+
missing/drifted). Mutants: v2-visible-resume 18 → 40, mux-resume-call 10 → 13,
|
|
167
|
+
resume-launch-identity 7 → 10, meta-hook-session-switch 17 → 25, meta-identity 4 → 9, existing
|
|
168
|
+
ones re-anchored. At the L2 checkpoint the LIVE dormant→resume journey for Claude Code had not
|
|
169
|
+
been measured, and `smoke-mux-lifecycle-live`'s Claude Code cell, which expects the still-live
|
|
170
|
+
sibling's resume to be refused as `target-live`, had not been run. Retire (G3) and the caller's
|
|
171
|
+
four cells were not part of L2; the later 2026-10-22 n=1 round trip is recorded in the
|
|
172
|
+
retirement section. The Claude Code dormant leg is still not a release-gate MUST.
|
|
173
|
+
|
|
174
|
+
### Team bookmarks
|
|
175
|
+
|
|
176
|
+
- **`team.json.example` shows one way to keep long-lived siblings in view.** It is a fictional,
|
|
177
|
+
caller-maintained bookmark: each member's name, the descriptive form of address
|
|
178
|
+
`coordinating sibling` or `sibling`, backend, garden id and native session id. The real
|
|
179
|
+
`team.json` at a repository root stays ignored. No program loads either file; the record stays
|
|
180
|
+
the address authority, liveness is re-read from `entwurf peer-facts`, and membership is not
|
|
181
|
+
permission to send, resume or retire.
|
|
182
|
+
|
|
183
|
+
### Herdr plugin
|
|
184
|
+
|
|
185
|
+
- **Back to the checkout carrier for this unpublished candidate.** `plugins/herdr/runtime-lock.json`
|
|
186
|
+
moves from the published `@junghanacs/entwurf@0.40.0` npm pin to the closed `herdr-checkout`
|
|
187
|
+
source, as the 0.40.0 preparation did; no npm integrity is invented and the plugin manifest
|
|
188
|
+
version is not bumped. The npm re-pin follows publication in its own Herdr snapshot. Inside
|
|
189
|
+
Herdr, `entwurf_resume_call` still refuses as `herdr-resume-unsupported`; retirement from a
|
|
190
|
+
Herdr pane was not measured.
|
|
191
|
+
|
|
192
|
+
### Upgrade notes
|
|
193
|
+
|
|
194
|
+
- A running process keeps the bytes it loaded. Ordinary Pi's built-in MCP bridge and pi-durable
|
|
195
|
+
load the compiled `dist`, `start.sh` hosts load the source in a checkout, and installed
|
|
196
|
+
hook/extension copies change only through their owning installers; restart the session after
|
|
197
|
+
that ([setup](./docs/setup-clean-host.md#applying-new-source-to-a-running-host)). A reader that
|
|
198
|
+
predates `attachIncarnation` refuses records carrying it, so roll every installed reader forward.
|
|
199
|
+
- Claude Code needs `>=2.1.306` for same-id resume. Its retirement uses a Linux pidfd helper and is
|
|
200
|
+
refused elsewhere. The native-Windows preview has no resume, and retirement was not
|
|
201
|
+
measured there. Copilot's Native
|
|
202
|
+
runtime validation is deferred by GLG's decision on the free `auto` account.
|
|
203
|
+
|
|
204
|
+
### Evidence boundary
|
|
205
|
+
|
|
206
|
+
- **One real round trip per backend, at `a9c9459`, not at this release's SHA.** A fresh pi-durable
|
|
207
|
+
caller retired and same-id resumed a fresh ordinary Pi and a native Claude Code 2.1.307 target
|
|
208
|
+
once each: dormant delivery refused, native identity and transcript preserved across the
|
|
209
|
+
promptless resume, blind recall correct. n=1; not a release-gate MUST, ACP, Herdr, Windows,
|
|
210
|
+
release-artifact or flush/descendant claim
|
|
211
|
+
([BASELINE](./BASELINE.md#147-native-round-trip-2026-10-22-n1),
|
|
212
|
+
[#147](https://github.com/junghan0611/entwurf/issues/147#issuecomment-6329217980)).
|
|
213
|
+
- Kill-power re-measured at this shipped SHA: none (all 1173 committed claims not re-proved,
|
|
214
|
+
#144).
|
|
215
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
|
|
216
|
+
d53b8f8d6602 -- `["bash","run.sh","check-entwurf-v2-retire"]` 32/32 receipt fc08567fb8d3
|
|
217
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
|
|
218
|
+
d53b8f8d6602 -- `["bash","run.sh","check-retirement-event"]` 16/16 receipt 948a9661fdc0
|
|
219
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
|
|
220
|
+
d53b8f8d6602 -- `["bash","run.sh","check-pi-durable-beside"]` 44/44 receipt 61e5b0552648
|
|
221
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
|
|
222
|
+
d53b8f8d6602 -- `["bash","run.sh","smoke-agy-install-state"]` 12/12 receipt deccfdbf3990
|
|
223
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 639f783df2d5 surface
|
|
224
|
+
d53b8f8d6602 -- `["bash","scripts/smoke-pi-provider-state.sh"]` 5/5 receipt 9de492738ef4
|
|
225
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head a9c945921a7e surface
|
|
226
|
+
80a4f8a7b942 -- `["bash","run.sh","check-entwurf-v2-surface"]` 17/17 receipt b4c765bd35b7
|
|
227
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head a9c945921a7e surface
|
|
228
|
+
80a4f8a7b942 -- `["bash","run.sh","check-pi-durable-beside"]` 44/44 receipt b6751a543d7a
|
|
229
|
+
- **Local static and LIVE floor, measured on this preparation's candidate:** head `c318f30` plus
|
|
230
|
+
the three release-prep files (this evidence line excepted); the HEAD/index/worktree fingerprint
|
|
231
|
+
and the 94-file compiled `dist` were unchanged before and after each run. `pnpm run check:full`
|
|
232
|
+
PASS (exit 0, 882 s) with the host herdr at the supply pin 0.9.5, where `check-herdr-sandbox`
|
|
233
|
+
passed its 12 assertions on a private server and left the operator's panes and Pi trust store
|
|
234
|
+
untouched. Two earlier local attempts stayed RED and are kept, each at its own head: at
|
|
235
|
+
`bf24e17`, a `dist` built 35 s before the last `.ts` commit (the managed rebuild then produced
|
|
236
|
+
byte-identical output); at `c318f30`, the host herdr 0.9.4 against the 0.9.5 pin. `LIVE=1 ./run.sh release-gate <scratch> --cut`:
|
|
237
|
+
**MUST PASS=24 FAIL=0 SKIP=0, BEHAVIOR PASS=1 FAIL=0, cut OK**, 11:59:15–12:19:05 KST, with the
|
|
238
|
+
caller identity carriers stripped. The Codex step ran against a test-owned app-server started
|
|
239
|
+
for this run in its own tmux session (pid named from its own launch, start ticks recorded,
|
|
240
|
+
stopped by one TERM afterwards) from a different gate session, with the requested tiers
|
|
241
|
+
`gpt-6-luna` and `openai-codex/gpt-6-luna` — the request, not a billing or model-identity
|
|
242
|
+
proof. Receipts on the operator host: `.tmp-verify/release-0.41.0/` (`full-r3/full.log`
|
|
243
|
+
`44332ee7fd78`, `live/release-gate.log` `6f56fffab3da`).
|
|
244
|
+
- **Still owed before the tag.** This prepared SHA's exact push CI (four required jobs). This
|
|
245
|
+
release is carrier-bearing, so its candidate is the native-Windows preview workflow's pack at
|
|
246
|
+
the prepared SHA, never a local `npm pack`. The strict `doctor-meta-bridge` on an installed
|
|
247
|
+
0.41.0 Claude host in a new post-install session, the agy shipped-lane cell and the Codex
|
|
248
|
+
caller-seat cell (VERIFY release acceptance 4, 7, 8) follow that candidate. Tag, GitHub
|
|
249
|
+
release and npm publication each need their own approval.
|
|
250
|
+
|
|
251
|
+
## v2026.10.20-herdr.0.40.0 — Herdr Entwurf plugin 0.40.0
|
|
252
|
+
|
|
253
|
+
A separate Herdr plugin snapshot, not another core release: core package 0.40.0 and its
|
|
254
|
+
`v0.40.0` tag remain unchanged. The operator has published the core to npm.
|
|
255
|
+
|
|
256
|
+
**Reading guide (2026-10-20).** The `## 0.40.0` section below and the body of the
|
|
257
|
+
[v0.40.0 GitHub release](https://github.com/junghan0611/entwurf/releases/tag/v0.40.0) are
|
|
258
|
+
prepare-time text: their "still owed before the tag" lines and their npm wording predate the
|
|
259
|
+
cut. The cut-time acceptance (exact-SHA CI, the Windows preview candidate, the Linux consumer,
|
|
260
|
+
the installed remote-pair gate, VERIFY §3.4, and §3.7 (agy) excluded for that cut only by the
|
|
261
|
+
operator's decision, not a PASS) is recorded in the
|
|
262
|
+
[#107 cut receipt](https://github.com/junghan0611/entwurf/issues/107#issuecomment-6281283301).
|
|
263
|
+
The publish is the later registry fact recorded in this section (`latest` 0.40.0, published
|
|
264
|
+
2026-10-20T01:49:33Z, registry bytes equal to the accepted candidate). Neither the published
|
|
265
|
+
tarball's CHANGELOG nor the release page is amended by this snapshot.
|
|
266
|
+
|
|
267
|
+
### Herdr plugin
|
|
268
|
+
|
|
269
|
+
- **Re-pin the published core 0.40.0 and close the checkout window.**
|
|
270
|
+
`plugins/herdr/runtime-lock.json` returns from the `herdr-checkout` carrier that core 0.40.0
|
|
271
|
+
rode to production npm source `@junghanacs/entwurf@0.40.0` with the registry's measured
|
|
272
|
+
sha512 (`sha512-y9HgQIcm…bQnZUW/g==`). The plugin manifest moves 0.39.0 → 0.40.0; admission
|
|
273
|
+
remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged. From the
|
|
274
|
+
`v2026.10.19-herdr.0.39.0` snapshot to `v0.40.0`, the only change under `plugins/herdr/`,
|
|
275
|
+
`scripts/herdr-runtime.mjs` and `scripts/fixtures/herdr-supply.json` was that lock's return
|
|
276
|
+
to `herdr-checkout`.
|
|
277
|
+
- **Pi range unchanged.** The acquired runtime still accepts Pi `>=1.3.0 <1.4`; core 0.40.0
|
|
278
|
+
keeps the Pi 1.3.0 SDK set.
|
|
279
|
+
- **Not a remote-pair certification.** Core 0.40.0's remote pair (#107) is carried in the
|
|
280
|
+
acquired runtime's bytes, but this snapshot measures no remote delivery, no SSH and no second
|
|
281
|
+
host through Herdr. The one real exchange remains the core section's L4 trial.
|
|
282
|
+
- **Upgrade by acquisition source, not just version.** A settled npm-source 0.39.0 installation
|
|
283
|
+
can rebind under the plugin README's ownership conditions. A host that installed an
|
|
284
|
+
intervening `herdr-checkout` candidate must explicitly deactivate by its own absolute runtime
|
|
285
|
+
path before reinstalling the npm-source snapshot. No operator installation or active session
|
|
286
|
+
is rewired by this release work.
|
|
287
|
+
|
|
288
|
+
### Source-specific verification
|
|
289
|
+
|
|
290
|
+
- Registry metadata reports `latest` 0.40.0 and `repair` 0.12.8-repair.1, 621 files, published
|
|
291
|
+
2026-10-20T01:49:33Z. The downloaded registry tarball is byte-equal to the preserved accepted
|
|
292
|
+
core candidate (SHA256 `4a6906ac38ff5024b9e07f7a092cc54a7686696082893293dfa653036f87fa55`,
|
|
293
|
+
11292707 bytes); its independently computed sha512 and sha1 equal `dist.integrity` and
|
|
294
|
+
`dist.shasum`, so core make's Docker consumer of those bytes (`node:24-bookworm`, repoDigest
|
|
295
|
+
`node@sha256:6dac556d…`) is reused here, not repeated. A sandboxed `pi install` of the
|
|
296
|
+
registry package resolved its bridge inside the sandbox, recorded the registry URL with that
|
|
297
|
+
integrity, and listed the curated Claude anchors with `--list-models entwurf`; a sandboxed
|
|
298
|
+
global npm install of the same package passed its installed `check-bridge`. No model turn.
|
|
299
|
+
- **The npm runtime swap against the real registry**, by the registry-shipped
|
|
300
|
+
`scripts/herdr-runtime.mjs` (byte-equal to this checkout's) in sandboxed user roots, 22/22
|
|
301
|
+
checks. The 0.39.0 runtime was seeded from its own committed lock (`ba46dec`); the swap to
|
|
302
|
+
0.40.0 took one acquisition, the cached tarball's sha512 equals the lock and its sha256 equals
|
|
303
|
+
both the ready journal's observed digest and the accepted candidate. The `installing` journal
|
|
304
|
+
carried the 0.39.0 identity as `previousRuntime` and the `runtime-ready` journal carries
|
|
305
|
+
`null`; when acquisition began the 0.39.0 tree was still at the active address. A manually
|
|
306
|
+
seeded torn swap (the active tree moved to the backup address with a half candidate in
|
|
307
|
+
staging; not a killed process) was restored before acquisition and reported `recovered:
|
|
308
|
+
torn-swap-with-candidate`. An exact re-request acquired nothing and left journal and tree
|
|
309
|
+
byte-identical, and the owned removal reclaimed cache, runtime and journal. The helper is a
|
|
310
|
+
leaf that probes no Pi, so these cells certify neither a Pi upgrade nor Herdr's
|
|
311
|
+
install/update relocation, harness wiring, the installed CLI's deactivate path, a model turn,
|
|
312
|
+
or recovery from a real kill.
|
|
313
|
+
- **Focused gates on the branch**, with HEAD, index and work surface unchanged across them:
|
|
314
|
+
`check-herdr-supply` (11 assertions), `check-herdr-plugin` (49),
|
|
315
|
+
`check-herdr-plugin-profile` (14), `check-herdr-runtime-bootstrap` (31),
|
|
316
|
+
`check-herdr-activation` (33), `check-herdr-placement` (25), `check-herdr-fresh-call` (45),
|
|
317
|
+
`check-dep-versions`, `check-install-surface` and `check-gate-manifests` (1034 committed
|
|
318
|
+
mutants across 79 lanes validated, none executed). `check-herdr-plugin-build` and
|
|
319
|
+
`check-herdr-sandbox` were not run locally because they run the operator's own herdr; they
|
|
320
|
+
ride the pushed SHA's FULL floor in CI.
|
|
321
|
+
- Pending, and not claimed here: the pushed SHA's four-job CI and the public-ref
|
|
322
|
+
install/use/deactivate journey of this npm pin, on Herdr 0.9.5 (the binary
|
|
323
|
+
`scripts/fixtures/herdr-supply.json` names) with Pi 1.3.0, from the public `main` ref rather
|
|
324
|
+
than the tag. Earlier npm or checkout-carrier receipts cannot certify these source-specific
|
|
325
|
+
axes. Those outcomes are recorded in the snapshot's post-push acceptance ledger, not in this
|
|
326
|
+
frozen text.
|
|
327
|
+
|
|
328
|
+
## 0.40.0 - 2026-10-20
|
|
329
|
+
|
|
330
|
+
The bridge is crossed and the questions are carried forward. A person laid a bridge
|
|
331
|
+
between two machines, and a message sent across it to an existing sibling came back. That
|
|
332
|
+
crossing happened once, at pre-release branch commit `e632294`. This cut carries that
|
|
333
|
+
capability and its open questions, not a new two-host LIVE measurement at its own SHA. It
|
|
334
|
+
does not solve remote trust or remote visibility; the questions it leaves open are listed
|
|
335
|
+
below as questions, not as features.
|
|
336
|
+
|
|
337
|
+
### Remote pair (#107)
|
|
338
|
+
|
|
339
|
+
- **One operator-declared pair across two hosts.** An opt-in `entwurf-remote-pair.json`
|
|
340
|
+
beside each host's meta-record store has exactly four keys: `remoteGardenId`, `ssh` (an
|
|
341
|
+
existing alias), `localGardenId` and `remotePairFile` (the other host's own file). One
|
|
342
|
+
file serves both directions. An absent file is off. A symlink, non-regular, unreadable
|
|
343
|
+
or invalid file is refused. The file is read at every send and receive and never cached.
|
|
344
|
+
The operator owns the connection between the hosts (a private network such as Tailscale
|
|
345
|
+
is recommended, not required) and SSH authentication. Entwurf installs, configures,
|
|
346
|
+
discovers and retries none of it.
|
|
347
|
+
- **Send.** `entwurf_v2` to the declared `remoteGardenId` makes exactly one `ssh -o
|
|
348
|
+
BatchMode=yes -o ConnectTimeout=10 <alias> entwurf remote-pair-receive --pair <file>`
|
|
349
|
+
call, with no shell and the claim on stdin. A declared target that also has a local
|
|
350
|
+
trace is refused as `remote-route-local-conflict`. A sender other than `localGardenId`
|
|
351
|
+
is refused as `remote-sender-not-declared`. Both refusals make zero SSH calls. An
|
|
352
|
+
undeclared target takes the unchanged local path. The send ends in one of three ways.
|
|
353
|
+
The first is the other host's receipt, quoted verbatim: an acceptance, or an error it
|
|
354
|
+
reported while processing (`remote-reported-error`). The second is its named refusal
|
|
355
|
+
before any mutation. The third is `remote-indeterminate`. A result is decided only when
|
|
356
|
+
the exit code and JSON kind agree. There is no retry.
|
|
357
|
+
- **Receive.** `entwurf remote-pair-receive` accepts only its own canonical file path
|
|
358
|
+
(normalized, not realpath). It refuses a `from` or `target` outside the declared pair
|
|
359
|
+
before any mailbox mutation and hands a match to that host's existing local `entwurf_v2`
|
|
360
|
+
dispatch. The compiled twin ships in the tarball
|
|
361
|
+
(`dist/scripts/remote-pair-receive.js`). The received envelope names the remote origin,
|
|
362
|
+
marks the sender's cwd as a sender-host path and carries `replyable=false`, with "reply
|
|
363
|
+
route declared, not probed". This display is proven for the self-fetch mailbox body
|
|
364
|
+
only. `entwurf_callback` stays local.
|
|
365
|
+
- **Trust and visibility, as built.** The trust model is same-operator SSH account trust.
|
|
366
|
+
The receiving host checks the declared pair. It does not cryptographically authenticate
|
|
367
|
+
a citizen, and it says nothing about whether the content deserves trust. The route has
|
|
368
|
+
no launch, fresh or resume path. For the measured self-fetch pair an OFF citizen is
|
|
369
|
+
undeliverable, and every other target keeps its own rail's admission. The code does not
|
|
370
|
+
check that the target's screen is open; owner pids, TTYs and garden-id labels are not
|
|
371
|
+
visibility. Delivery to an active, armed pi-durable can start a turn at once.
|
|
372
|
+
- **A reported error is not read as non-delivery.** When the other host's dispatch reports
|
|
373
|
+
an error (exit 4), the sender's first line says that an error was reported, that
|
|
374
|
+
delivery is not inferred from that line and that nothing was retried, and it quotes the
|
|
375
|
+
other host's text verbatim. That text includes its own `retry-safe: false` after a
|
|
376
|
+
possible write. An external source review on #107 raised this before the cut.
|
|
377
|
+
- **Docs.** DELIVERY ("Remote pair (#107)") owns the contract. `docs/setup-clean-host.md`
|
|
378
|
+
gains the operator steps (§2c) and "Applying new source to a running host": a pi-durable
|
|
379
|
+
host runs the compiled bridge even from a checkout, and a running bridge keeps the
|
|
380
|
+
modules it loaded, so neither a pull nor a green setup line shows which bytes are live.
|
|
381
|
+
`docs/remote-sibling-principles.md` is new; it holds the boundaries kept across hosts
|
|
382
|
+
and the questions below.
|
|
383
|
+
|
|
384
|
+
### Questions carried forward
|
|
385
|
+
|
|
386
|
+
- **Is a connection the same as trust?** Today's boundary is an operator-owned SSH account
|
|
387
|
+
and one exactly declared pair. How should the reach of an account be told apart from
|
|
388
|
+
trusting the sibling that sent a message?
|
|
389
|
+
- **Does visibility survive a machine boundary?** Locally, the operator's visible-first
|
|
390
|
+
policy keeps conversation turns to siblings the user has open; that is a policy, not a
|
|
391
|
+
technical screen check. Across hosts, the first exchange relied on the user's own
|
|
392
|
+
confirmation that both sessions were open. What would observe and keep visible-first
|
|
393
|
+
remotely, without a hidden turn or a watcher?
|
|
394
|
+
- **How much can a sender know?** Acceptance is not a read, and a reply does not tell its
|
|
395
|
+
sender that the reply was read. How should that uncertainty be shown honestly without
|
|
396
|
+
retries, a third ACK, read tracking or a conversation manager?
|
|
397
|
+
|
|
398
|
+
None of these is a hidden backlog item;
|
|
399
|
+
[remote-sibling-principles](./docs/remote-sibling-principles.md) keeps them as open
|
|
400
|
+
questions. Automatic discovery, reconnection, OFF wake, hidden model turns, remote
|
|
401
|
+
callbacks and support for every backend or platform are not claimed.
|
|
402
|
+
|
|
403
|
+
### Evidence boundary
|
|
404
|
+
|
|
405
|
+
- **Deterministic and installed.** T1 executor-in and T2 surface-in cells sit beside the
|
|
406
|
+
behavior: the real bridge over MCP stdio, with a stand-in `ssh` running the other host's
|
|
407
|
+
real entry under a separate HOME. `./run.sh check-remote-pair-installed --tgz <abs>`
|
|
408
|
+
(checkout-only) runs T2 against installed bytes and audits module realpaths, with a
|
|
409
|
+
checkout negative control. Six new mutant lanes (remote-pair display 3, receive 8,
|
|
410
|
+
roundtrip 5, send 12, transport 4, installed-audit 2): the committed set is now 1034
|
|
411
|
+
mutants across 79 lanes. `check:vitest` runs `check-remote-pair-installed-audit`.
|
|
412
|
+
- **One real exchange, at `e632294`, not at this release's SHA.** On 2026-10-20 B's native
|
|
413
|
+
`entwurf_v2` went over one SSH call to A's mailbox
|
|
414
|
+
(`2026-10-19T22-19-47-662Z-13c897.msg`). A's one reply carried nonce
|
|
415
|
+
`107-live-20261020T071937-B-A-6e42d1`, and B read it at `2026-10-19T22:20:24.837Z`. The
|
|
416
|
+
pair was two already-open pi-durable siblings on two Linux hosts, which the user
|
|
417
|
+
reopened visibly beforehand. Before the send, the selected compiled bridge hash, the
|
|
418
|
+
bridge start time after the build and the record/owner/sender joins were checked on both
|
|
419
|
+
hosts. That check first caught one host still on a pre-feature build, so the trial was
|
|
420
|
+
held until a manual build and visible resume. This is L4 (one pair, one run). It is not
|
|
421
|
+
a release-gate MUST and was not re-measured at this release's SHA. Unmeasured: an OFF
|
|
422
|
+
target, negative paths over real SSH, other rails, more than one pair, non-Linux hosts,
|
|
423
|
+
GUI rendering, and SSH's own known-hosts side effects. Receipt:
|
|
424
|
+
[#107](https://github.com/junghan0611/entwurf/issues/107#issuecomment-6278665895).
|
|
425
|
+
- Kill-power re-measured at this shipped SHA: none (all 1034 committed claims not re-proved,
|
|
426
|
+
#144).
|
|
427
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 6ac477d944c6 surface
|
|
428
|
+
974e264f5879 -- `["bash","run.sh","check-tests-beside-behavior"]` 38/38 receipt
|
|
429
|
+
c8d59ba79b6a
|
|
430
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 3afbfb660562 surface
|
|
431
|
+
bc925701184b -- `["bash","run.sh","check-tests-beside-behavior"]` 37/37 receipt
|
|
432
|
+
4e324810643d
|
|
433
|
+
- Earlier-candidate PARTIAL (operator-attested, not this SHA): head 3afbfb660562 surface
|
|
434
|
+
bc925701184b -- `["bash","run.sh","check-remote-pair-installed-audit"]` 2/2 receipt
|
|
435
|
+
bfa5031abc54
|
|
436
|
+
- **An earlier RED is kept as history.** The `check-tests-beside-behavior` group at the R2
|
|
437
|
+
candidate (head a7aaac7390d8 surface 07625e040df9, receipt b5d681a291f5) killed 34 of
|
|
438
|
+
37: three mutants failed type-checking rather than the claim. Their replacements were
|
|
439
|
+
repaired and the group re-ran on the next candidate. No kill-power was carried over from
|
|
440
|
+
that run.
|
|
441
|
+
- **Static/LIVE split.** Local `check:full` is not run on this operator host and is not
|
|
442
|
+
counted as passed. The whole static floor is owed to this prepared SHA's exact push CI.
|
|
443
|
+
The earlier branch commit `e632294` passed all four jobs in run 39202248407; that is not
|
|
444
|
+
this SHA. The remote-pair installed gate is owed against this release's own candidate
|
|
445
|
+
tarball. The installed 11/11 on an earlier manually produced tarball is not this
|
|
446
|
+
release's evidence.
|
|
447
|
+
- **Local LIVE r1, this release's non-static LIVE: MUST (non-static 23) PASS=23 FAIL=0
|
|
448
|
+
SKIP=0 UNRUN=0; BEHAVIOR PASS=1 FAIL=0.** It ran once, 09:40:03–09:44:49 KST on
|
|
449
|
+
2026-10-20, on head `de0bf03` plus this preparation's four metadata files (diff
|
|
450
|
+
`22d0a8b856ae`), with the candidate fingerprint (`22053b62bc0e`) equal at freeze, before
|
|
451
|
+
and after. The one-off driver (`15d7fb9dd49f`) ran the release gate's non-static steps
|
|
452
|
+
in its own order, command, environment and working directory; its 24 step lines equal
|
|
453
|
+
`release_gate()`'s by kind, name and argv, and that body is byte-identical to 0.39.0's.
|
|
454
|
+
GLG approved this shape for this cut: test-owned scratch sessions only, including
|
|
455
|
+
headless model turns and the gates' own close/resume, with no existing user or OFF
|
|
456
|
+
session as a target
|
|
457
|
+
([#107](https://github.com/junghan0611/entwurf/issues/107#issuecomment-6280460022)). The
|
|
458
|
+
Codex step ran against a test-owned app-server in its own tmux session A (named pane pid
|
|
459
|
+
with its recorded start ticks, stopped by one TERM afterwards) from gate session S, with
|
|
460
|
+
the requested tiers `gpt-6-luna` and `openai-codex/gpt-6-luna`; that is the request, as
|
|
461
|
+
the step's own assertions check it, not a billing or model-identity proof. The compiled
|
|
462
|
+
bridge those steps spawned was rebuilt once beforehand, with GLG's approval, and matched
|
|
463
|
+
a private emit of this source 87/87. Receipts on the operator host:
|
|
464
|
+
`.tmp-verify/release-0.40.0/live-r1/` (`live.log` `4ced6b51ec03`, `steps.SHA256SUMS`
|
|
465
|
+
`f1b7e7b79d97`, 24 logs). It is not a local `release-gate --cut` PASS: the static step
|
|
466
|
+
did not run locally.
|
|
467
|
+
- **Still owed before the tag.** The static floor is this prepared SHA's exact push CI
|
|
468
|
+
(four required jobs). This release is carrier-bearing, so its candidate is the
|
|
469
|
+
native-Windows preview workflow's pack at the prepared SHA (release skill M3w), accepted
|
|
470
|
+
by the eight Windows cells and the Linux container, never a local `npm pack`; the
|
|
471
|
+
remote-pair installed gate runs against that same candidate. VERIFY §3.4 (the strict
|
|
472
|
+
`doctor-meta-bridge` on an installed 0.40.0 Claude host in a new post-install session)
|
|
473
|
+
follows the accepted candidate. Tag, GitHub release and npm publication each need their
|
|
474
|
+
own GO.
|
|
475
|
+
- **agy excluded from this cut.** VERIFY §3.7 (three agy doctors and a same-gid
|
|
476
|
+
native-push reply in a new operator conversation) is excluded by GLG's explicit decision
|
|
477
|
+
of 2026-10-20: unmeasured, not a PASS. It is a new decision for this cut only, not the
|
|
478
|
+
0.39.0 exclusion carried over and not a standing waiver
|
|
479
|
+
([#107](https://github.com/junghan0611/entwurf/issues/107#issuecomment-6280460022)).
|
|
480
|
+
- **Host residue after LIVE (P9).** The census counted 1934 directories owned by this
|
|
481
|
+
operator under `/tmp` after one stale, unused root of this repo's own prefix (16K) was
|
|
482
|
+
reclaimed, from 1935. The largest groups (`acp-cache-test`, `render-take-test`,
|
|
483
|
+
`caption-take-test`) do not match the prefixes this repo's gates mint, so their
|
|
484
|
+
ownership is not certified by that extractor; they were not deleted. One reparented
|
|
485
|
+
holder of a `/tmp` path is an unrelated editor daemon, untouched. Observation: the
|
|
486
|
+
memory-containment and chain gates left fresh roots of their own prefixes
|
|
487
|
+
(`entwurf-memguard-overlay-*`, `entwurf-chain-*`); that is a finding about those gates,
|
|
488
|
+
not fixed in this cut.
|
|
489
|
+
- **Herdr follows core.** `plugins/herdr/runtime-lock.json` returns from the published npm
|
|
490
|
+
0.39.0 pin to the closed `herdr-checkout` source for this unpublished candidate, as
|
|
491
|
+
0.38.1 and 0.39.0 did; the comment is re-dated only. The runtime-bootstrap gate requires
|
|
492
|
+
an npm-source lock to equal the checkout's package version, so an npm 0.39.0 pin cannot
|
|
493
|
+
sit beside package 0.40.0. There are no plugin manifest, registry pin or snapshot
|
|
494
|
+
changes; re-pinning the measured 0.40.0 registry bytes is a separate Herdr snapshot
|
|
495
|
+
after publication.
|
|
496
|
+
|
|
497
|
+
## v2026.10.19-herdr.0.39.0 — Herdr Entwurf plugin 0.39.0
|
|
498
|
+
|
|
499
|
+
A separate Herdr plugin snapshot, not another core release: core package 0.39.0 and its
|
|
500
|
+
`v0.39.0` tag remain unchanged. The operator has published the core to npm.
|
|
501
|
+
|
|
502
|
+
**Reading guide (2026-10-19).** The `## 0.39.0` section below and the appendix of the
|
|
503
|
+
[v0.39.0 GitHub release](https://github.com/junghan0611/entwurf/releases/tag/v0.39.0) are
|
|
504
|
+
prepare- and cut-time text. The appendix records the tag, VERIFY §3.4 met, and §3.7 (agy)
|
|
505
|
+
excluded for that cut only by the operator's decision, not a PASS. Both still say npm was not
|
|
506
|
+
published. The publish is the later registry fact recorded in this section (`latest` 0.39.0,
|
|
507
|
+
published 2026-10-18T21:24:39Z, registry bytes equal to the accepted candidate). Neither the
|
|
508
|
+
published tarball's CHANGELOG nor the release page is amended by this snapshot.
|
|
509
|
+
|
|
510
|
+
### Herdr plugin
|
|
511
|
+
|
|
512
|
+
- **Re-pin the published core 0.39.0 and close the checkout window.**
|
|
513
|
+
`plugins/herdr/runtime-lock.json` returns from the `herdr-checkout` carrier that core 0.39.0
|
|
514
|
+
rode to production npm source `@junghanacs/entwurf@0.39.0` with the registry's measured
|
|
515
|
+
sha512 (`sha512-xTRMQkSi…JY+1A==`). The plugin manifest moves 0.38.0 → 0.39.0; admission
|
|
516
|
+
remains Herdr >= 0.9.0 and the one-build/one-pane/Linux shape is unchanged. Core 0.38.1 got
|
|
517
|
+
no Herdr snapshot, so the previous npm pin is 0.38.0.
|
|
518
|
+
- **Pi range unchanged.** The acquired runtime still accepts Pi `>=1.3.0 <1.4`.
|
|
519
|
+
- **Upgrade by acquisition source, not just version.** A settled npm-source 0.38.0 installation
|
|
520
|
+
can rebind under the plugin README's ownership conditions. A host that installed an
|
|
521
|
+
intervening `herdr-checkout` candidate must explicitly deactivate by its own absolute runtime
|
|
522
|
+
path before reinstalling the npm-source snapshot. No operator installation or active session
|
|
523
|
+
is rewired by this release work.
|
|
524
|
+
|
|
525
|
+
### Source-specific verification
|
|
526
|
+
|
|
527
|
+
- Registry metadata reports `latest` 0.39.0 and `repair` 0.12.8-repair.1, 605 files, published
|
|
528
|
+
2026-10-18T21:24:39Z. The downloaded registry tarball is byte-equal to the preserved accepted
|
|
529
|
+
core candidate (SHA256 `1d5693241b8cd5fa827869cf15ecbf0048215c7f0b4ebb0422650b6ae2773578`,
|
|
530
|
+
11254616 bytes); its independently computed sha512 and sha1 equal `dist.integrity` and
|
|
531
|
+
`dist.shasum`, so core make's Docker consumer of those bytes (`node:24-bookworm`, repoDigest
|
|
532
|
+
`node@sha256:6dac556d…`) is reused here, not repeated. A sandboxed `pi install` of the
|
|
533
|
+
registry package resolved its bridge inside the sandbox, recorded the registry URL with that
|
|
534
|
+
integrity, and listed the curated Claude anchors with `--list-models entwurf`; a sandboxed
|
|
535
|
+
global npm install of the same package passed its installed `check-bridge`.
|
|
536
|
+
- **The npm runtime swap against the real registry**, by the registry-shipped
|
|
537
|
+
`scripts/herdr-runtime.mjs` (byte-equal to this checkout's) in sandboxed user roots, 22/22
|
|
538
|
+
checks. The 0.38.0 runtime was seeded from its own committed lock (`beb5925`); the swap to
|
|
539
|
+
0.39.0 took one acquisition, the cached tarball's sha512 equals the lock and its sha256 equals
|
|
540
|
+
both the ready journal's observed digest and the accepted candidate. The `installing` journal
|
|
541
|
+
carried the 0.38.0 identity as `previousRuntime` and the `runtime-ready` journal carries
|
|
542
|
+
`null`; when acquisition began the 0.38.0 tree was still at the active address. A manually
|
|
543
|
+
seeded torn swap (the active tree moved to the backup address with a half candidate in
|
|
544
|
+
staging; not a killed process) was restored before acquisition and reported `recovered:
|
|
545
|
+
torn-swap-with-candidate`. An exact re-request acquired nothing and left journal and tree
|
|
546
|
+
byte-identical, and the owned removal reclaimed cache, runtime and journal. The helper is a
|
|
547
|
+
leaf that probes no Pi, so these cells certify neither a Pi upgrade nor Herdr's
|
|
548
|
+
install/update relocation, harness wiring, the installed CLI's deactivate path, a model turn,
|
|
549
|
+
or recovery from a real kill.
|
|
550
|
+
- **Focused gates on the branch**, with HEAD, index and work surface unchanged across them:
|
|
551
|
+
`check-herdr-supply` (11 assertions), `check-herdr-plugin` (49),
|
|
552
|
+
`check-herdr-plugin-profile` (14), `check-herdr-runtime-bootstrap` (31),
|
|
553
|
+
`check-herdr-activation` (33), `check-herdr-placement` (25), `check-herdr-fresh-call` (45)
|
|
554
|
+
and `check-gate-manifests` (1000 committed mutants across 73 lanes validated, none executed).
|
|
555
|
+
`check-herdr-plugin-build` and `check-herdr-sandbox` were not run locally because they run
|
|
556
|
+
the operator's own herdr; they ride the pushed SHA's FULL floor in CI.
|
|
557
|
+
- Pending, and not claimed here: the pushed SHA's four-job CI and the public-ref
|
|
558
|
+
install/use/deactivate journey of this npm pin, on Herdr 0.9.5 (the binary
|
|
559
|
+
`scripts/fixtures/herdr-supply.json` names) with Pi 1.3.0, from the public `main` ref rather
|
|
560
|
+
than the tag. Earlier npm or checkout-carrier receipts cannot certify these source-specific
|
|
561
|
+
axes. Those outcomes are recorded in the snapshot's post-push acceptance ledger, not in this
|
|
562
|
+
frozen text.
|
|
563
|
+
|
|
7
564
|
## 0.39.0 - 2026-10-18
|
|
8
565
|
|
|
9
566
|
### Native Windows (experimental preview, #78)
|
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` 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.
|
|
7
|
+
`entwurf` opens and messages visible sibling sessions across independent harnesses, and reopens dormant pi or Claude Code 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
|
|