@junghanacs/entwurf 0.45.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +5 -3
- package/BASELINE.md +110 -1
- package/CHANGELOG.md +249 -0
- package/CONTRIBUTING.md +1 -1
- package/ENTWURF-CLI.json +1229 -0
- package/ENTWURF.json +63 -15
- package/FAQ.md +4 -4
- package/README.md +132 -188
- package/VERIFY.md +18 -11
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +1 -1
- package/docs/external-mcp-host.md +4 -4
- package/docs/setup-clean-host.md +94 -22
- package/mcp/entwurf-bridge/dist/ENTWURF.json +63 -15
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +19 -8
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-contract.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +483 -18
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +613 -33
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-resume-call.js +497 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +3 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +50 -5
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +7 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-location.js +347 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-owner-fence.js +1132 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +1 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +18 -11
- package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +30 -15
- package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +40 -7
- package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +1 -27
- package/mcp/entwurf-bridge/dist/scripts/meta-bridge-prune.js +1 -1
- package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
- package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +1 -1
- package/mcp/entwurf-bridge/src/index.ts +28 -8
- package/mcp/entwurf-bridge/tsconfig.build.json +7 -1
- package/native/win32-x64/manifest.json +1 -1
- package/package.json +16 -20
- package/pi/pi-durable/bootstrap.mjs +179 -6
- package/pi/pi-durable/carrier/runtime.js +327 -57
- package/pi/pi-durable/carrier/session-name.js +11 -0
- package/pi/pi-durable/carrier/sessions.js +96 -20
- package/pi/pi-durable/carrier/subagent.js +5 -2
- package/pi/pi-durable/carrier/tui.js +60 -22
- package/pi/pi-durable/overlay/upstream-pin.json +26 -19
- package/pi-extensions/lib/entwurf-v2-contract-schema.ts +73 -69
- package/pi-extensions/lib/entwurf-v2-contract.ts +4 -4
- package/pi-extensions/lib/entwurf-v2-visible-resume.ts +710 -38
- package/pi-extensions/lib/fresh-call-dispatch.ts +64 -12
- package/pi-extensions/lib/herdr-fresh-call.ts +919 -40
- package/pi-extensions/lib/herdr-resume-call.ts +810 -0
- package/pi-extensions/lib/meta-session.ts +13 -8
- package/pi-extensions/lib/mux-resume-call.ts +77 -4
- package/pi-extensions/lib/pi-durable-fresh-preflight.ts +9 -2
- package/pi-extensions/lib/pi-durable-location.ts +446 -0
- package/pi-extensions/lib/pi-durable-owner-fence.ts +1461 -0
- package/pi-extensions/lib/pi-durable-runtime.ts +4 -0
- package/pi-extensions/lib/resume-launch-identity.ts +31 -12
- package/pi-extensions/meta-bridge-pi-durable.ts +30 -16
- package/run.sh +552 -699
- package/scripts/check-claude-launch.ts +341 -0
- package/scripts/check-entwurf-v2-contract.ts +4 -4
- package/scripts/check-entwurf-v2-surface.ts +2 -2
- package/scripts/check-fresh-call-dispatch.ts +70 -9
- package/scripts/check-fresh-cut-gate.sh +23 -9
- package/scripts/check-gate-qualification.ts +19 -14
- package/scripts/check-herdr-activation.ts +301 -23
- package/scripts/check-herdr-fresh-call.ts +161 -25
- package/scripts/check-herdr-plugin-build.ts +173 -1
- package/scripts/check-herdr-plugin.ts +28 -2
- package/scripts/check-herdr-runtime-bootstrap.ts +136 -0
- package/scripts/check-install-surface.ts +1236 -6
- package/scripts/check-meta-doctor-oracle.sh +1 -1
- package/scripts/check-meta-facts.ts +20 -1
- package/scripts/check-mux-resume-call.ts +28 -0
- package/scripts/check-peer-facts.ts +39 -2
- package/scripts/cli-help.mjs +222 -0
- package/scripts/dev-bin.sh +39 -2
- package/scripts/herdr-activation.mjs +28 -6
- package/scripts/herdr-operator-link.mjs +389 -0
- package/scripts/herdr-plugin-activate.mjs +5 -0
- package/scripts/herdr-plugin-deactivate.mjs +18 -5
- package/scripts/herdr-rails.mjs +43 -7
- package/scripts/herdr-runtime.mjs +27 -0
- package/scripts/meta-bridge-fresh-cut.ts +1 -27
- package/scripts/meta-bridge-prune.ts +1 -1
- package/scripts/meta-facts.ts +1 -1
- package/scripts/mutants/agent-guidance.json +4 -4
- package/scripts/mutants/claude-launch.json +142 -0
- package/scripts/mutants/cli-help-source.json +420 -0
- package/scripts/mutants/control-send-receipt.json +1 -1
- package/scripts/mutants/dev-gate-dispatch.json +109 -0
- package/scripts/mutants/fresh-call-dispatch.json +38 -2
- package/scripts/mutants/fresh-cut.json +15 -0
- package/scripts/mutants/herdr-activation.json +128 -0
- package/scripts/mutants/herdr-fresh-call.json +278 -5
- package/scripts/mutants/herdr-operator-link.json +318 -0
- package/scripts/mutants/herdr-plugin-build.json +55 -0
- package/scripts/mutants/herdr-plugin.json +17 -0
- package/scripts/mutants/herdr-resume-call.json +288 -0
- package/scripts/mutants/herdr-runtime-bootstrap.json +48 -0
- package/scripts/mutants/meta-facts.json +15 -0
- package/scripts/mutants/mux-resume-call.json +63 -2
- package/scripts/mutants/pack-install.json +4 -4
- package/scripts/mutants/peer-facts.json +15 -0
- package/scripts/mutants/pi-durable.json +1167 -3
- package/scripts/mutants/pi-floor.json +22 -5
- package/scripts/mutants/source-install.json +35 -0
- package/scripts/mutants/v2-surface.json +2 -2
- package/scripts/mutants/v2-visible-resume.json +255 -6
- package/scripts/peer-facts.ts +1 -1
- package/scripts/smoke-agy-install-state.sh +66 -0
- package/scripts/smoke-meta-prune.sh +23 -0
- package/scripts/smoke-omp-fresh-live.ts +12 -3
- package/scripts/smoke-omp-receive-live.ts +7 -1
- package/scripts/smoke-pi-durable-fresh-live.ts +12 -2
- package/team.json.example +39 -0
package/docs/setup-clean-host.md
CHANGED
|
@@ -23,10 +23,11 @@ evidence split, and its three states must not collapse into "macOS is supported"
|
|
|
23
23
|
|
|
24
24
|
## Requirements
|
|
25
25
|
|
|
26
|
-
This table
|
|
26
|
+
This table and the 1.4-specific install examples below describe the published `@junghanacs/entwurf@0.50.0`, which ships the Pi 1.4.0 SDK set. The #155 0.51.0 preparation at `434874ef6d6e399a0ae6813c850d01c5232eb1d9` pins SDK 1.5.0; its separate validation TGZ was installed in the approved operating window, but is not the still-unpublished final shipping artifact. npm publication requires its own authority. See the [SDK 1.5 boundary](#sdk-15-development-boundary-155) below; these 0.50 instructions do not select or prove 0.51 bytes.
|
|
27
27
|
The previous package, `0.41.0`, ships the Pi 1.3.0 SDK set and requires Pi 1.3.x; the setup guide
|
|
28
28
|
inside that tarball is its contract.
|
|
29
29
|
|
|
30
|
+
<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->
|
|
30
31
|
| Component | Requirement | Needed for |
|
|
31
32
|
|---|---|---|
|
|
32
33
|
| Node | **`>=24.0.0`** | package and bridge runtime |
|
|
@@ -41,6 +42,7 @@ inside that tarball is its contract.
|
|
|
41
42
|
| Antigravity `agy` | optional, operator-installed and authenticated | legacy citizen; native push paused (#152) |
|
|
42
43
|
| OpenAI Codex CLI | optional-by-presence, operator-installed and authenticated; detected composes all four operator-owned units (birth/MCP/status-line/terminal-title) and stays non-green until the operator trusts the birth declaration once in a visible Codex; visible fresh also requires the operator-owned app-server, started with `entwurf codex-app-server` in a tmux session of the operator's choosing (#95 D1 retired the fixed `codex` home) | native-push and visible fresh, supported in 0.21.0 |
|
|
43
44
|
| Cortex Code | optional, operator-installed and authenticated | Cortex ACP backend |
|
|
45
|
+
<!-- /entwurf:published -->
|
|
44
46
|
|
|
45
47
|
Claude Code >=2.1.306 is required for the managed exec-hook lifecycle and same-id resume. The package
|
|
46
48
|
never supplies or proxies backend credentials.
|
|
@@ -83,14 +85,16 @@ node --version
|
|
|
83
85
|
npm --version
|
|
84
86
|
```
|
|
85
87
|
|
|
86
|
-
The two npm forms below install the **published** package, `0.
|
|
87
|
-
set).
|
|
88
|
+
The two npm forms below install the **published** package, `0.50.0` (Pi 1.4.x, the Pi 1.4.0 SDK
|
|
89
|
+
set). The [product entry](../README.md#install)'s unpinned `npm install -g @junghanacs/entwurf`
|
|
90
|
+
takes whichever version npm's `latest` dist-tag names; pin `@<version>` as below when you mean the
|
|
91
|
+
exact artifact the [Requirements](#requirements) table describes.
|
|
88
92
|
|
|
89
93
|
Global install is simplest when native harnesses should find stable bins from every
|
|
90
94
|
working directory:
|
|
91
95
|
|
|
92
96
|
```bash
|
|
93
|
-
npm install -g @junghanacs/entwurf@0.
|
|
97
|
+
npm install -g @junghanacs/entwurf@0.50.0
|
|
94
98
|
entwurf --help
|
|
95
99
|
entwurf setup /path/to/your-project
|
|
96
100
|
entwurf check-bridge
|
|
@@ -101,7 +105,7 @@ A project-local installation is also supported:
|
|
|
101
105
|
```bash
|
|
102
106
|
mkdir -p ~/entwurf-smoke && cd ~/entwurf-smoke
|
|
103
107
|
npm init -y
|
|
104
|
-
npm install --save-dev @junghanacs/entwurf@0.
|
|
108
|
+
npm install --save-dev @junghanacs/entwurf@0.50.0
|
|
105
109
|
npx entwurf setup .
|
|
106
110
|
npx entwurf check-bridge
|
|
107
111
|
```
|
|
@@ -111,7 +115,7 @@ project-local install, or `./run.sh <command>` from a source checkout. Keep that
|
|
|
111
115
|
same scope when upgrading and checking; native process restarts are separate (§7).
|
|
112
116
|
|
|
113
117
|
`check-bridge` is auth-free. It proves the installed prebuilt MCP server boots and
|
|
114
|
-
lists the nine garden tools (0.
|
|
118
|
+
lists the nine garden tools (0.50.0); it does not prove a backend model turn, native hook or retirement permission.
|
|
115
119
|
|
|
116
120
|
Neither npm form installs a harness runtime. `pi`, Claude Code, Copilot CLI, Codex CLI, agy,
|
|
117
121
|
Cortex, and their authentication remain operator-owned optional prerequisites for the
|
|
@@ -226,6 +230,7 @@ Install the exact release floor, then wire the project. The previous 0.41.0 inst
|
|
|
226
230
|
Pi 1.3.x its own setup guide names. A source checkout passes its checkout path to `-e` in place of
|
|
227
231
|
the global package root:
|
|
228
232
|
|
|
233
|
+
<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->
|
|
229
234
|
```bash
|
|
230
235
|
npm install -g @earendil-works/pi-coding-agent@1.4.0
|
|
231
236
|
pi --version
|
|
@@ -239,6 +244,7 @@ The supported range is `>=1.4.0 <1.5`. It is a hard minimum: installing this
|
|
|
239
244
|
release onto a 0.83.x pi host upgrades the runtime rather than keeping the older
|
|
240
245
|
minor. A host using only the external MCP bridge can skip pi until it needs a
|
|
241
246
|
control socket; no delivery rail launches a pi process.
|
|
247
|
+
<!-- /entwurf:published -->
|
|
242
248
|
|
|
243
249
|
For daily garden-native pi sessions:
|
|
244
250
|
|
|
@@ -257,7 +263,7 @@ A plain `pi` can load the package without becoming a citizen.
|
|
|
257
263
|
In that session ask for `entwurf_self`, then `entwurf_peers`. Pick an existing
|
|
258
264
|
live garden id and ask for `entwurf_v2` with `intent: "fire-and-forget"` and your
|
|
259
265
|
message. These are harness tools, not shell subcommands; pi exposes them through
|
|
260
|
-
Pi's built-in MCP as `mcp__entwurf_bridge__<verb>`. The 0.
|
|
266
|
+
Pi's built-in MCP as `mcp__entwurf_bridge__<verb>`. The 0.50.0 bridge has nine tools;
|
|
261
267
|
pi hides `entwurf_inbox_read` and `entwurf_register_native`, leaving seven active.
|
|
262
268
|
The added `entwurf_retire_call` is only for one target/action explicitly requested by the
|
|
263
269
|
human operator, never autonomous cleanup. Where a host provides or is configured with an approval
|
|
@@ -270,6 +276,10 @@ Tool-call ingress is MCP; delivery to a pi citizen is still its record-addressed
|
|
|
270
276
|
control address (a Unix socket; a named pipe on the experimental native-Windows Pi
|
|
271
277
|
preview). A boot/listing from `check-bridge` is not a model-turn or
|
|
272
278
|
native-rail acceptance.
|
|
279
|
+
The server key stays `entwurf-bridge`. An operator/trusted-project MCP entry with
|
|
280
|
+
that normalized namespace can replace the registration by Pi's own precedence;
|
|
281
|
+
`/mcp` shows it, and Entwurf does not scan or fight that choice.
|
|
282
|
+
Codemode is harness-internal, not another garden citizen.
|
|
273
283
|
|
|
274
284
|
To inspect the ACP provider from a project-local package instead of a global one:
|
|
275
285
|
|
|
@@ -338,11 +348,11 @@ by `entwurf pi` or by registering ordinary Pi's adapter.
|
|
|
338
348
|
|
|
339
349
|
What the Entwurf package supplies:
|
|
340
350
|
|
|
341
|
-
1. **The pi SDK set** — `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
342
|
-
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry}` at exactly `1.
|
|
343
|
-
`proper-lockfile`, as Entwurf's own production dependencies
|
|
344
|
-
|
|
345
|
-
|
|
351
|
+
1. **The pi SDK set** — in the 0.51.0 prepared checkout, `@earendil-works/{pi-coding-agent, pi-ai, pi-tui, pi-agent-core,
|
|
352
|
+
pi-durable, chord, pi-mcp, pi-codemode, pi-telemetry, pi-schema}` at exactly `1.5.0`, plus
|
|
353
|
+
`proper-lockfile`, as Entwurf's own production dependencies. The authoritative current set is
|
|
354
|
+
the [SDK pin](../pi/pi-durable/overlay/upstream-pin.json) and [package manifest](../package.json);
|
|
355
|
+
for this candidate, model data rides `@earendil-works/pi-ai@1.5.0`, not a catalog copy.
|
|
346
356
|
2. **The native app/TUI carrier** — upstream does not publish the experimental durable
|
|
347
357
|
app (`pi-coding-agent` excludes `dist/experimental`; `pi-durable` on npm is the
|
|
348
358
|
library). Entwurf owns the six app files as canonical source (`pi/pi-durable/src`,
|
|
@@ -352,7 +362,7 @@ What the Entwurf package supplies:
|
|
|
352
362
|
(`pi/pi-durable/carrier-resolver.mjs`), which maps them to the published package's
|
|
353
363
|
own `dist/` as installed — never through a source checkout.
|
|
354
364
|
|
|
355
|
-
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.
|
|
365
|
+
The upstream [library guide](https://github.com/earendil-works/pi/blob/v1.5.0/packages/durable/README.md)
|
|
356
366
|
and the [experimental app guide](https://github.com/earendil-works/pi/blob/v1.1.0/packages/coding-agent/src/experimental/durable/README.md)
|
|
357
367
|
(last published at v1.1.0) describe what the carrier is. Running the bare upstream app does not attach Entwurf's
|
|
358
368
|
garden contact. Entwurf does not rebuild the controller/model/auth/storage system or
|
|
@@ -367,8 +377,7 @@ carrier file, the license, the resolver and its relocation grammar are present
|
|
|
367
377
|
(`pi-durable-carrier-drift`); every declared SDK package resolves from the carrier
|
|
368
378
|
(`pi-durable-sdk-absent`); and every reachable physical edge — from the carrier to each package,
|
|
369
379
|
and from every package copy it reaches, at any depth, to its own `@earendil-works` dependencies —
|
|
370
|
-
lands on a package of the declared name at exactly the pinned version (`pi-durable-sdk-mismatch`). The members
|
|
371
|
-
ranges, so semver satisfaction is not the contract; the bytes an import binds are. Sharing
|
|
380
|
+
lands on a package of the declared name at exactly the pinned version (`pi-durable-sdk-mismatch`). The members' declarations are exact in the prepared 1.5.0 set; even so, the physical package each import binds must be checked. Sharing
|
|
372
381
|
one copy with an aligned host install of the same version is an ordinary layout. A mixed
|
|
373
382
|
tree (for example an override that binds pi-durable's `pi-ai` to an older published version) still
|
|
374
383
|
*imports* — which is why the edge check exists — and is refused by name.
|
|
@@ -385,15 +394,28 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
385
394
|
entwurf pi-durable --provider <provider> --model <exact catalog id> --width task-wide
|
|
386
395
|
entwurf pi-durable --continue # this directory's newest durable session
|
|
387
396
|
entwurf pi-durable --resume # choose one of this directory's durable sessions
|
|
397
|
+
entwurf pi-durable --session <native id> # reopen exactly that session of this directory
|
|
388
398
|
```
|
|
389
399
|
|
|
400
|
+
`--continue`, `--resume` and `--session` reopen a session as it was saved: they take no
|
|
401
|
+
`--provider`, `--model`, `--width` or `--entwurf-bootstrap` and are mutually exclusive.
|
|
402
|
+
`--session` takes the native session id (`<13-digit ms>-<uuid>`, as `--resume` lists it), not a
|
|
403
|
+
garden id, with no interactive session picker or picker-specific TTY check (the normal TUI still
|
|
404
|
+
runs); a value of any other shape is refused as `session-id-malformed` before your module is
|
|
405
|
+
evaluated, the TUI loads or the app opens. To retain an operator module on a CLI reopen, pass
|
|
406
|
+
its original explicit `--native-module <absolute file>` or `--native-module-dir <absolute directory>`
|
|
407
|
+
again; garden-id `entwurf_resume_call` is bridge-only and does not restore either ingress or
|
|
408
|
+
the prior seat. It opens on the caller's launch rail; check for an existing owner before opening
|
|
409
|
+
another instance. Close the old owner normally and prove its exit before reopening; for an SDK transition, back up
|
|
410
|
+
the complete durable SQLite file set before the first write ([upgrade boundary](#default-radius-for-a-requested-pi-sdk-upgrade)). Ordinary Pi transcripts are separate JSONL files.
|
|
411
|
+
|
|
390
412
|
The bootstrap imports only the compiled closure shipped beside it
|
|
391
413
|
(`mcp/entwurf-bridge/dist/…`); a source checkout needs a built bridge
|
|
392
414
|
(`pnpm run build-bridge`) and its development dependencies installed first.
|
|
393
415
|
`plugins/pi-durable/bootstrap.mjs` is only the checkout path that re-exports it.
|
|
394
416
|
|
|
395
|
-
- **One explicit native module (optional).** Add `--native-module <absolute file>` to
|
|
396
|
-
|
|
417
|
+
- **One explicit native module (optional).** Add `--native-module <absolute file>` to any of these
|
|
418
|
+
launches to load ONE module of your own. It is an ordinary ES module: its top-level code (top-level
|
|
397
419
|
await included) runs first, before the TUI and the durable runtime load, so it can prepare the
|
|
398
420
|
environment the provider runtime and tool children will read; its default export is a native
|
|
399
421
|
durable `Extension` (`{ name, tools?, sections?, hooks?, … }`, the upstream durable API, not
|
|
@@ -437,7 +459,7 @@ tree (for example an override that binds pi-durable's `pi-ai` to an older publis
|
|
|
437
459
|
manifest field; it is a known constraint of supplying both from one package, accepted for 0.32,
|
|
438
460
|
not a claim that every load path is harmless.
|
|
439
461
|
|
|
440
|
-
The ordinary Pi CLI on PATH is a separate subject (§2, range
|
|
462
|
+
The ordinary Pi CLI on PATH is a separate subject (§2, range <!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->`>=1.4.0 <1.5`<!-- /entwurf:published -->): a host Pi is
|
|
441
463
|
not needed to run pi-durable, and a host inside the range need not be the same copy as the
|
|
442
464
|
carrier's. Native Pi owns credentials, model settings and durable SQLite sessions; keep them
|
|
443
465
|
in place rather than copying credentials or migrating ordinary Pi transcripts. Native
|
|
@@ -448,10 +470,49 @@ to the app's own model resolution; the checkout contact/send/receive gates run t
|
|
|
448
470
|
with scripted S plus native H; Pi ↔ pi-durable LIVE on this supply surface is a separate release
|
|
449
471
|
proof ([#130](https://github.com/junghan0611/entwurf/issues/130)).
|
|
450
472
|
|
|
473
|
+
### SDK 1.5 development boundary (#155)
|
|
474
|
+
|
|
475
|
+
The published 0.50.0 / SDK 1.4.0 instructions above and the #155 SDK 1.5 development
|
|
476
|
+
candidates are distinct subjects. Synthetic migration and downgrade-refusal fixtures on `0408a66`
|
|
477
|
+
did not authorize an operating first write. A separately approved 1.5 operating window and Native
|
|
478
|
+
LIVE were later measured as described below; neither makes the validation TGZ the final release
|
|
479
|
+
artifact. Installing an older package is not a data rollback. Follow the current evidence in
|
|
480
|
+
[#155](https://github.com/junghan0611/entwurf/issues/155), not the 1.3→1.4 receipt below.
|
|
481
|
+
|
|
482
|
+
### Default radius for a requested Pi SDK upgrade
|
|
483
|
+
|
|
484
|
+
**[Decision, 2026-11-03 (#155)](https://github.com/junghan0611/entwurf/issues/155#issuecomment-6595580400): reuse existing native authentication; do not make a fresh login or credential copy the default upgrade prerequisite.** An upgrade request selects this method without another authentication-strategy questionnaire. It does not authorize an immediate operating cutover, autonomous retirement, or publication.
|
|
485
|
+
|
|
486
|
+
The measured precedent is [#148's pre-cutover hold](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6342034678) and [its actual Pi 1.4 operating reattachment](https://github.com/junghan0611/entwurf/issues/148#issuecomment-6348113761): isolated package/SDK checks first; no authentication-copy or mixed host/extension workaround; then normal owner exit, a consistent complete durable-session file-set backup, coherent candidate installation/takeover, same-identity reattachment and actual turns/round trips. Native aggregate acceptance followed the coherent installation. These are historical receipts, not evidence for the next SDK.
|
|
487
|
+
|
|
488
|
+
- **Proceed within the requested upgrade:** inspect upstream changes; isolate the development checkout from stable operating runtimes; pin the coherent SDK set; run private, authentication-free fixtures, focused checks, review and the required floors. Prepare the exact candidate, shutdown/reopen commands and backup manifest before the operating window.
|
|
489
|
+
- **Reuse at the coherent operating boundary:** the native harness uses its existing account/subscription authentication in its ordinary location. Its normal same-account token refresh is not a reason to demand another login. Entwurf does not extract, print, copy, transplant or proxy credentials, and does not introduce an auth-path shim. Keep the selected subscription/provider rail; no account, endpoint, scope or billing-rail substitution is implied.
|
|
490
|
+
- **Still coordinate the human-owned lifecycle window:** identify the exact operating owners and obtain the requested normal shutdown; prove old-owner exit and preserve the complete session directory consistently, including WAL/SHM, before the newer SDK opens operating data. Verify candidate, host, extension, bridge and SDK coherence, then reopen the same identities and measure actual model/tool/round-trip behavior. Authentication reuse is the default method, not permission to skip these gates or to force-close a working citizen.
|
|
491
|
+
- **Do not invent a pre-cutover exception:** if a real-model test cannot use the approved isolated surface without touching operating auth/data, defer it to that operating window. A separate private login or operating-agent-directory experiment is optional and needs a specific request; neither is a recurring prerequisite. Record the missing model/TUI evidence rather than claiming scripted S/H proves it.
|
|
492
|
+
- **Stop and report a real exception:** expired/revoked authentication needing login, changed account/permissions/endpoint or an unmeasured new external transfer, ownership conflict, inconsistent backup, unexpected write, or unknown result. No blind retry or automatic data rollback; downgrading the package does not undo a newer document write.
|
|
493
|
+
|
|
494
|
+
Push, release/tag/npm publication and retirement of any other citizen retain their separate authorization boundaries. This decision fixes the repeatable method; it does not pre-authorize those actions.
|
|
495
|
+
|
|
496
|
+
**Recurring SDK rail.** At task start, agree the exact SDK and the scope of development, review and verification once; do not repeatedly ask for the existing-auth strategy. Inspect the published SDK set and upstream changes, isolate the development checkout from operating runtimes, and implement against the coherent pinned set in private HOME, PI and writable XDG roots. Use the gate's own temporary-directory constraints: the #155 FULL's deeper scratch produced 117/109-byte socket paths and EINVAL; run3 used `TMPDIR=/tmp` with each gate creating its own private scratch and passed. Preserve both `pnpm_config_verify_deps_before_run=error` and `npm_config_verify_deps_before_run=error`, managed builds and candidate seals; do not run offline gates under ambient CI.
|
|
497
|
+
|
|
498
|
+
The owned canonical app/TUI source is production responsibility; the SDK owns the execution engine. In independent upgrade review, compare old and new app-visible payload semantics against known fixtures and a separate official SDK oracle: more than 50 active entries on reopen and same-process conversation switch, head/reset and background-compaction retention, and the distinction from model memory. API names, typechecks or a QK that only fixes the new SDK's window can all be green while older display compatibility regresses. When official emission changes a generated digest, check its pin-linked mutant find literal and the existing manifest inventory together; this is not a new gate.
|
|
499
|
+
|
|
500
|
+
Freeze for sequential independent review, then affected PARTIAL groups, frozen FULL and applicable scripted/native-H carrier cells. Accept the **same reviewed validation TGZ** in the Linux container and rehearse ownership refusal/takeover in isolation. Measure SDK publication age early to plan the window, then recheck it fresh before installation; never automatically exempt the global policy.
|
|
501
|
+
|
|
502
|
+
In the named operating window, identify owners, obtain their normal exit and prove it, then take a consistent complete session backup including WAL/SHM before the first new-SDK write. Install a coherent host and validation TGZ, verify installed global root (GR), runtime and ownership independently, and perform only the approved takeover. Reopen the same identities with their original explicitly named native modules and existing auth; observe real turns and round trips before the Native LIVE floor. Public pi-durable `entwurf_resume_call` is bridge-only: it does not save or restore operator native modules. If one is needed, use the original explicit CLI entry; do not infer a profile or kill a citizen automatically. One approval can cover the named scope, sibling roles and fixture work, but not bypass normal exit, the first-write decision, or separate push/npm authority.
|
|
503
|
+
|
|
504
|
+
For each named Native fixture, record the runtime root and SDK actually selected separately from the operator installation: a private PATH can select the genuine source CLI while an ordinary Pi extension still comes from an older installed GR. Do not substitute a wrapper or rewire the operating host to make the evidence agree. A planned source-CLI Native run is not a completed receipt.
|
|
505
|
+
|
|
506
|
+
**#155 measured example (2026-11-03; before the D1 display repair):** at 20:47 KST host Pi 1.5.0 and the unpublished, addon-less 0.51.0 validation TGZ (SHA-256 `199e5f41d20e5b2665125868b7e3e27740e5985f7a25ac61902126b7ed638bf5`) were installed, not the final publication artifact. Four owners exited normally; the 171-file durable backup's source-before/backup/source-after manifests matched (`5c08bed1968fd1e26baa58112f0ce5c36874e147ccc5e9b4c69ec1a0d9070a46`); two Pi transcripts were also backed up. All ten SDK members were freshly measured at 24.70–24.84 hours old, without a policy exception. The P5 Native LIVE cut recorded MUST 24/0/0 and BEHAVIOR 1/0/0 (pass/fail/skip) on its own sealed candidate, not the prepared SHA. Native-host criterion 4 separately measured a fresh Claude Code fixture's actual installed 0.51 MCP child and strict doctor; existing pre-cutover Claude sessions retained their loaded 0.50 bridge. Neither the 20:47 installation nor P5 proves that the later D1 display repair is operating: the D1-bearing artifact must first be installed, and the human must then restart the process; restarting against the earlier artifact still loads the old app. See [0.51.0 release evidence](../CHANGELOG.md#release-evidence) for scopes and receipts.
|
|
507
|
+
|
|
508
|
+
The Windows-bearing release TGZ, its Linux acceptance, exact prepared-SHA CI, installed-host acceptance and publication/registry proof are separate later evidence. Re-measure owners, loaded bytes, version/integrity, backup and candidate evidence on every upgrade; this ordering does not guarantee success for a future SDK.
|
|
509
|
+
|
|
510
|
+
For the separate land, prepare, make and publish authorities and the one accepted artifact, follow [entwurf-release](../.claude/skills/entwurf-release/SKILL.md). Push, tag, human-owned npm publication and the subsequent Herdr re-pin remain independently coordinated decisions. The current SDK-specific decisions and receipts belong to the active issue and handoff, not this reusable ordering.
|
|
511
|
+
|
|
451
512
|
### Moving durable sessions from the Pi 1.3 SDK to 1.4
|
|
452
513
|
|
|
453
|
-
0.41.1
|
|
454
|
-
separate operator decision for each host. When you do:
|
|
514
|
+
0.41.1, 0.41.2, 0.45.0 and 0.50.0 are published on the 1.4.0 SDK set; moving a live host onto any of them
|
|
515
|
+
remains a separate operator decision for each host. When you do:
|
|
455
516
|
|
|
456
517
|
1. **Confirm the old owner is gone.** Close the 0.41 (SDK 1.3) durable session normally and check
|
|
457
518
|
that its process has exited. A stale session lock alone is not proof.
|
|
@@ -558,7 +619,7 @@ entwurf install-meta-bridge
|
|
|
558
619
|
entwurf doctor-meta-bridge
|
|
559
620
|
```
|
|
560
621
|
|
|
561
|
-
The supported floor `>=2.1.306` is enforced by package metadata through installer
|
|
622
|
+
The Claude Code supported floor `>=2.1.306` is enforced by package metadata through installer
|
|
562
623
|
and doctor gates. Older Claude versions validate an exec-form hook but silently drop
|
|
563
624
|
its `args` at runtime, so there is no shell-form fallback.
|
|
564
625
|
|
|
@@ -568,6 +629,17 @@ validation, or hand-inspected marker cannot replace a new real session. If the l
|
|
|
568
629
|
form is unsupported, reinstall; if ownership is correct but the live join is absent,
|
|
569
630
|
restart the affected session.
|
|
570
631
|
|
|
632
|
+
Start a session as plain `claude` or as `entwurf claude [args…]`. The second execs the
|
|
633
|
+
`claude` on PATH in this terminal — same cwd, pid and exit status, signals reaching it directly,
|
|
634
|
+
arguments and `--help` unchanged — after removing an inherited `PI_SESSION_ID`/`PI_AGENT_ID` and
|
|
635
|
+
exporting only `ENTWURF_CLAUDE_LAUNCH_ACTIVE=1`. Unlike `entwurf copilot` it checks no Entwurf setup
|
|
636
|
+
or citizen precondition before launch — only that `claude` resolves to an executable file that
|
|
637
|
+
is not this launcher — and sets no feature flag: either spelling is a citizen through the hooks above,
|
|
638
|
+
and plain Claude Code without them. A launch whose environment already carries that sentinel
|
|
639
|
+
(inherited from an earlier `entwurf claude` up its process tree), or whose `claude` resolves to
|
|
640
|
+
Entwurf's own `run.sh`, refuses as a recursive managed launch instead of looping; its message
|
|
641
|
+
currently names only the PATH cause. Run plain `claude` there.
|
|
642
|
+
|
|
571
643
|
The Darwin install fence is open (`Linux | Darwin`); python3 is the
|
|
572
644
|
refusal, not the platform name. A completed Darwin install is still not
|
|
573
645
|
a rail receipt: this rail is NOT CERTIFIED — pending physical host. The
|
|
@@ -701,7 +773,7 @@ as a note rather than a fault.
|
|
|
701
773
|
|
|
702
774
|
**entwurf sets no OMP version floor in code, and will not grow one on schedule.** Detection is
|
|
703
775
|
presence-only (`command -v "${OMP_BIN:-omp}"`); there is no `entwurf.ompFloor`, no coherence
|
|
704
|
-
gate, and no exact pin — unlike Node (`engines.node`), pi (
|
|
776
|
+
gate, and no exact pin — unlike Node (`engines.node`), pi (<!-- entwurf:published @junghanacs/entwurf@0.50.0 pi 1.4.0 -->`>=1.4.0 <1.5`<!-- /entwurf:published --> for published 0.50.0) and Claude Code
|
|
705
777
|
(`entwurf.claudeCodeFloor`), each of which has an enforcement point. That asymmetry is a
|
|
706
778
|
decision, not an omission. A floor is the answer to a vendor that fails SILENTLY — Claude Code
|
|
707
779
|
earned one because an older binary validates the exec manifest, drops `args` at runtime, and
|
|
@@ -6,8 +6,56 @@
|
|
|
6
6
|
"editing": "Preserve decoded strings exactly unless an explicit semantic amendment is intended. Review related consumers and independent oracles atomically. Accepted payload changes advance revision; history-only edits, routine releases and unrelated code changes do not. schemaVersion tracks reader/structural compatibility. A slotted hint holds only the text around its slot: the slot value (for record-less-socket, the fresh-cut command in both invocation forms) is supplied by its code owner and never copied here. Metadata is not delivered to models."
|
|
7
7
|
},
|
|
8
8
|
"schemaVersion": 6,
|
|
9
|
-
"revision":
|
|
9
|
+
"revision": 19,
|
|
10
10
|
"history": [
|
|
11
|
+
{
|
|
12
|
+
"revision": 19,
|
|
13
|
+
"source": "2734f524bfeca6eb1a0ae092494d45576af9ebef",
|
|
14
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
15
|
+
"change": "Claude Code same-id resume on the herdr rail (#157 stage 4): both entwurf_resume_call descriptions open every resumable backend inside herdr in a new herdr tab and drop the Claude Code refusal there, the MCP description's Claude Code observation names the window or tab and herdr's pane-process-unread outcome, and the tmux leaf's herdr guard hint no longer says the herdr rail reopens pi only (stale since B3)"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"revision": 18,
|
|
19
|
+
"source": "43594eba588a51bdb9d58a4631e3ebc7b3a235ea",
|
|
20
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
21
|
+
"change": "pi-durable same-id resume, joint-review alignment (#157 B3): the entwurf_resume_call MCP description is rewritten within the host cap to state pi-durable eligibility (claim closed and released, or holder proven gone), its observation classes and that a held session is refused without unconditional delivery advice, since a pi-durable reservation awaiting adoption is not reachable by entwurf_v2; the durable description names that holder; the entwurf_v2 and entwurf_peers descriptions add pi-durable to the resume domain; the target-live and target-indeterminate visible-resume hints become holder-neutral. No wire value, argument, schema or reason identifier changes."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"revision": 17,
|
|
25
|
+
"source": "46c7c776c7fed9001be4498ea024cfd214f4347f",
|
|
26
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
27
|
+
"change": "Same-id visible resume names pi-durable (#157 B3): both entwurf_resume_call descriptions and its target parameter add pi-durable beside pi and Claude Code, the MCP description's OBSERVATION receipt names the pi-durable adoption of this call's reservation and both descriptions put pi-durable with pi inside herdr, and the target-backend-unsupported hint lists pi-durable among the backends that do resume. No wire value, argument, schema shape or reason identifier changes."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"revision": 16,
|
|
31
|
+
"source": "d6129139ad9738a3bc0ade9b5ef3abbac4b7580f",
|
|
32
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
33
|
+
"change": "The entwurf_fresh_call cwd parameter's last sentence names every source an echoed directory can come from: the REQUESTED path, a Codex caller's record directory, or another caller's own process directory, which its default clause already named (checkpoint amendment A1 D3). Every description and every other parameter are unchanged. No wire value, argument, schema or reason identifier changes."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"revision": 15,
|
|
37
|
+
"source": "d6129139ad9738a3bc0ade9b5ef3abbac4b7580f",
|
|
38
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
39
|
+
"change": "The entwurf_fresh_call MCP description restores four contract phrases that revision 14's host-cap rewrite dropped (entwurf_peers only reports, Model is REQUIRED, the CALLER, NOTHING is created), at 1748 characters under the 2048-character host description cap (A-L1 host-cap recovery). The durable description, every parameter and the other tools are unchanged. No wire value, argument, schema or reason identifier changes."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"revision": 14,
|
|
43
|
+
"source": "d6129139ad9738a3bc0ade9b5ef3abbac4b7580f",
|
|
44
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
45
|
+
"change": "The entwurf_fresh_call MCP description is rewritten to fit the 2048-character host description cap (A-L1 host-cap recovery): revision 13's 2182-character text becomes 1732 characters. The durable description, every parameter and the other tools are unchanged. No wire value, argument, schema or reason identifier changes."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"revision": 13,
|
|
49
|
+
"source": "d6129139ad9738a3bc0ade9b5ef3abbac4b7580f",
|
|
50
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
51
|
+
"change": "pi-durable opens inside herdr through one layout.apply request (A-L1): the entwurf_fresh_call MCP description says the herdr tab is requested unfocused, names pi and claude-code through agent start and pi-durable through a native layout command, and keeps the by-name herdr refusal for copilot/omp/codex only; the durable description's last sentence and the backend parameter name pi-durable among the herdr backends. No wire value, argument, schema or reason identifier changes."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"revision": 12,
|
|
55
|
+
"source": "0e04bf6e728aa14320decc056ec91e74727a8f2b",
|
|
56
|
+
"issue": "https://github.com/junghan0611/entwurf/issues/157",
|
|
57
|
+
"change": "Pi same-id visible resume gains a herdr rail (G1a): both entwurf_resume_call descriptions name the pi-only herdr tab and the Claude Code refusal there, the launch-refused hint no longer says only tmux was not asked, and the tmux leaf's herdr guard hint is narrowed to that leaf. No wire value, schema or reason identifier changes."
|
|
58
|
+
},
|
|
11
59
|
{
|
|
12
60
|
"revision": 11,
|
|
13
61
|
"source": "d3963c2d16a93453baf7a318ad9395c57990531d",
|
|
@@ -78,7 +126,7 @@
|
|
|
78
126
|
"tools": {
|
|
79
127
|
"entwurf_v2": {
|
|
80
128
|
"descriptions": {
|
|
81
|
-
"mcp": "CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id alone does not say which rail that citizen answers on. Give target + intent; the decider picks transport from liveness (live socket citizen → control-socket send; deliverable self-fetch citizen → meta-bridge mailbox; probe-alive native-push citizen → direct injection into its conversation) and reports ONE outcome, named per rail: a control receiver's acceptance boundary (`sent` / `queued-steer` / `queued-follow-up` / `accepted-unknown-boundary` — those four, or `mailbox-enqueued` on a re-resolved mailbox leg), a mailbox ENQUEUE receipt, a native-push INJECTION, a rejection, or lock-dirty. This receipt is not the colleague's reply or evidence of reading. EXISTING targets only; discover with entwurf_peers. A live socket can receive fire-and-forget. unsupported means only \"no control-socket probe,\" not reachability. The decider resolves the actual rail at dispatch time: a self-fetch mailbox only while deliverable, native-push direct injection only while its adapter probe is alive, or a THIRD RESULT: rejection when neither holds. An inactive self-fetch citizen is mailbox-undeliverable; native-push has NO mailbox: dead → native-push-target-dead; indeterminate → native-push-probe-indeterminate; agy (paused, #152) → native-push-paused, no probe. A dormant socket rejects this delivery verb as dormant-fire-forget-unsupported. owned-outcome was withdrawn. Only on an explicit operator request, entwurf_resume_call may visibly reopen a proven-dormant Pi or Claude Code citizen under the same id, submitting no prompt; that lifecycle is separate from delivery. LOCK: taken for a control-socket-DOMAIN dispatch. The mailbox and native-push rails are lock-free — deliverability and the adapter probe guard them. mode applies to a CONTROL-SOCKET send only; other plans carry no mode. wants_reply rides every rail. message caps at 16000 chars; send an artifact path + digest for more.",
|
|
129
|
+
"mcp": "CANONICAL DELIVERY SURFACE for garden ids: message, reply, or hand off to whoever an id names. The id alone does not say which rail that citizen answers on. Give target + intent; the decider picks transport from liveness (live socket citizen → control-socket send; deliverable self-fetch citizen → meta-bridge mailbox; probe-alive native-push citizen → direct injection into its conversation) and reports ONE outcome, named per rail: a control receiver's acceptance boundary (`sent` / `queued-steer` / `queued-follow-up` / `accepted-unknown-boundary` — those four, or `mailbox-enqueued` on a re-resolved mailbox leg), a mailbox ENQUEUE receipt, a native-push INJECTION, a rejection, or lock-dirty. This receipt is not the colleague's reply or evidence of reading. EXISTING targets only; discover with entwurf_peers. A live socket can receive fire-and-forget. unsupported means only \"no control-socket probe,\" not reachability. The decider resolves the actual rail at dispatch time: a self-fetch mailbox only while deliverable, native-push direct injection only while its adapter probe is alive, or a THIRD RESULT: rejection when neither holds. An inactive self-fetch citizen is mailbox-undeliverable; native-push has NO mailbox: dead → native-push-target-dead; indeterminate → native-push-probe-indeterminate; agy (paused, #152) → native-push-paused, no probe. A dormant socket rejects this delivery verb as dormant-fire-forget-unsupported. owned-outcome was withdrawn. Only on an explicit operator request, entwurf_resume_call may visibly reopen a proven-dormant Pi, pi-durable or Claude Code citizen under the same id, submitting no prompt; that lifecycle is separate from delivery. LOCK: taken for a control-socket-DOMAIN dispatch. The mailbox and native-push rails are lock-free — deliverability and the adapter probe guard them. mode applies to a CONTROL-SOCKET send only; other plans carry no mode. wants_reply rides every rail. message caps at 16000 chars; send an artifact path + digest for more.",
|
|
82
130
|
"durable": "Send a message to an existing garden citizen by garden id through the entwurf-bridge (intent fire-and-forget). Returns the bridge's delivery receipt, or fails with its named rejection. This receipt is not the colleague's reply."
|
|
83
131
|
},
|
|
84
132
|
"parameters": {
|
|
@@ -98,7 +146,7 @@
|
|
|
98
146
|
},
|
|
99
147
|
"entwurf_peers": {
|
|
100
148
|
"descriptions": {
|
|
101
|
-
"mcp": "List the entwurf fact surface: garden citizens (from meta-records) with their liveness, plus diagnostics. The record is the sole address axis — a control socket no record claims is a `record-less-socket` diagnostic (a stale/diagnostic state), never a peer row. This reports FACTS, never verbs: `liveness` is a fact (alive/dead/indeterminate, or `unsupported` for a backend with no control-socket probe such as claude-code); the delivery choice or rejection is resolved LATER by entwurf_v2 from the record and current rail facts, not here — this surface carries no per-row routing field, so do not read a transport off a row. A `dead` socket row is a REPORTED FACT: no entwurf_v2 delivery is available while it is dormant. Listing it grants no action and is not an invitation to dispatch. Only on an explicit operator request, the separate entwurf_resume_call may visibly reopen a proven-dormant Pi or Claude Code citizen under the same id, submitting no prompt. In particular `unsupported` does NOT mean mailbox: it means this backend has no control-socket probe. Dispatch has THREE possible answers — a self-fetch mailbox (only while that mailbox is deliverable), native-push direct injection (only while its adapter probe is alive), or a REJECT when neither holds: mailbox-undeliverable for a self-fetch citizen whose inbox nobody drains, and on the native-push probe dead → native-push-target-dead vs indeterminate → native-push-probe-indeterminate, kept apart because an unestablished probe is not a departed host; an agy target rejects as native-push-paused (#152) without being probed. Note: this is the *active* world and it is facts-only — it creates nothing. Pass an existing garden id to entwurf_v2; to open a NEW sibling use entwurf_fresh_call.",
|
|
149
|
+
"mcp": "List the entwurf fact surface: garden citizens (from meta-records) with their liveness, plus diagnostics. The record is the sole address axis — a control socket no record claims is a `record-less-socket` diagnostic (a stale/diagnostic state), never a peer row. This reports FACTS, never verbs: `liveness` is a fact (alive/dead/indeterminate, or `unsupported` for a backend with no control-socket probe such as claude-code); the delivery choice or rejection is resolved LATER by entwurf_v2 from the record and current rail facts, not here — this surface carries no per-row routing field, so do not read a transport off a row. A `dead` socket row is a REPORTED FACT: no entwurf_v2 delivery is available while it is dormant. Listing it grants no action and is not an invitation to dispatch. Only on an explicit operator request, the separate entwurf_resume_call may visibly reopen a proven-dormant Pi, pi-durable or Claude Code citizen under the same id, submitting no prompt. In particular `unsupported` does NOT mean mailbox: it means this backend has no control-socket probe. Dispatch has THREE possible answers — a self-fetch mailbox (only while that mailbox is deliverable), native-push direct injection (only while its adapter probe is alive), or a REJECT when neither holds: mailbox-undeliverable for a self-fetch citizen whose inbox nobody drains, and on the native-push probe dead → native-push-target-dead vs indeterminate → native-push-probe-indeterminate, kept apart because an unestablished probe is not a departed host; an agy target rejects as native-push-paused (#152) without being probed. Note: this is the *active* world and it is facts-only — it creates nothing. Pass an existing garden id to entwurf_v2; to open a NEW sibling use entwurf_fresh_call.",
|
|
102
150
|
"durable": "List the garden's citizens with their liveness facts from the entwurf-bridge. Read-only; facts, not verbs."
|
|
103
151
|
},
|
|
104
152
|
"parameters": {}
|
|
@@ -124,12 +172,12 @@
|
|
|
124
172
|
},
|
|
125
173
|
"entwurf_fresh_call": {
|
|
126
174
|
"descriptions": {
|
|
127
|
-
"mcp": "Open ONE fresh visible sibling beside you and hand it a first task.
|
|
128
|
-
"durable": "Open ONE fresh visible sibling beside this durable host through the entwurf-bridge and hand it a first task (backend, model and task required; optional cwd and placement). Returns the bridge's LAUNCH receipt or its named refusal — not a started runtime, a delivered task or a reply; the sibling's callback names it.
|
|
175
|
+
"mcp": "Open ONE fresh visible sibling beside you and hand it a first task. Rail follows THIS agent's process context: inside herdr (HERDR_ENV=1), request a NEW UNFOCUSED TAB in your workspace: pi/claude-code via agent start, pi-durable via one native layout request; otherwise use the operator's tmux with all six backends (pi, claude-code, copilot, omp, codex, pi-durable). No fallback: incomplete herdr context rejects by name, never opens unseen tmux. The sibling is asked to call back before its task with the launch nonce; match it and take its garden id from the callback sender envelope. Returns a LAUNCH receipt (owner coordinates + nonce), NOT proof of runtime start, first turn or task delivery. Coordinates are a VIEW, never an address; herdr tab/pane ids can change. Nothing polls. EXISTING citizens: entwurf_v2; entwurf_peers only reports. Model is REQUIRED, passed to runtime CLI: provider/model for pi; id/alias for Claude Code; provider/<exact catalog model id> for pi-durable; pattern for the rest. On tmux, copilot/omp/codex/pi-durable refuse BEFORE window creation if birth, MCP, receive or visible-identity units are absent; pi-durable also refuses installed-carrier/exact-SDK failures; codex needs the operator-owned app-server socket Entwurf never starts. In herdr, copilot/omp/codex reject first; pi-durable runs the same unit/carrier/SDK preflight before layout. Optional placement.tmuxSession is TMUX ONLY: ONE EXISTING session, always wins. Omitted, seat follows the CALLER, not opened backend: a CODEX CALLER opens beside its TUI pane, others in their own session. Missing session: tmux-session-missing, NOTHING is created. Herdr refuses placement by name. No secrets in task: model/task argv are visible to same-user processes.",
|
|
176
|
+
"durable": "Open ONE fresh visible sibling beside this durable host through the entwurf-bridge and hand it a first task (backend, model and task required; optional cwd and placement). Returns the bridge's LAUNCH receipt or its named refusal — not a started runtime, a delivered task or a reply; the sibling's callback names it. Inside herdr, it requests a new unfocused tab in this host's workspace for pi, claude-code or pi-durable; elsewhere it needs the tmux pane this host itself was launched in."
|
|
129
177
|
},
|
|
130
178
|
"parameters": {
|
|
131
|
-
"backend": "Which fixed runtime to open. Only these six, and only pi/claude-code when this agent runs inside herdr; there is no arbitrary command.",
|
|
132
|
-
"cwd": "Optional literal ABSOLUTE path of an existing directory to start the sibling in (cross-repo fresh). Omit or pass \"\" to start where the CALLER is — this agent's own cwd on BOTH rails, or for a Codex caller its own record directory, because this bridge is the app-server's child and that process's directory is not the caller's. Taken exactly as given: no trim, no realpath, no project-name resolution. '#' is refused on the tmux rail only, because tmux format-expands a start directory; inside herdr it is an ordinary path character. The receipt echoes the directory that was REQUESTED
|
|
179
|
+
"backend": "Which fixed runtime to open. Only these six, and only pi/claude-code/pi-durable when this agent runs inside herdr; there is no arbitrary command.",
|
|
180
|
+
"cwd": "Optional literal ABSOLUTE path of an existing directory to start the sibling in (cross-repo fresh). Omit or pass \"\" to start where the CALLER is — this agent's own cwd on BOTH rails, or for a Codex caller its own record directory, because this bridge is the app-server's child and that process's directory is not the caller's. Taken exactly as given: no trim, no realpath, no project-name resolution. '#' is refused on the tmux rail only, because tmux format-expands a start directory; inside herdr it is an ordinary path character. The receipt echoes the directory that was REQUESTED, a Codex caller's record directory, or another caller's own process directory, never an observation of where the pane landed.",
|
|
133
181
|
"model": "Required runtime model: canonical provider/model for pi (a bare alias is refused), provider/<exact catalog model id> for pi-durable, a Claude Code model id/alias, or a Copilot/OMP/Codex model name. Neither pi nor pi-durable may name the openrouter provider.",
|
|
134
182
|
"placement": "Optional expert seat override, TMUX ONLY: open the sibling in ONE EXISTING tmux session of this agent's own server, and it always wins. When omitted the seat follows the CALLER, never the backend being opened: a Codex CALLER opens beside its own TUI pane, matched by thread-id in that pane's terminal title (0 or 2+ matching panes refuse, never fall back); every other caller opens in its own session. A pane title is a placement input only — never an address, liveness or delivery fact. Nothing is ever created. Inside herdr this field is refused by name — placement there belongs to herdr, and a tmux session name would silently place the sibling somewhere else. Independent of cwd; neither is inferred from the other. The receipt reports the selected name (absent for the caller-pane rule, which observed a session rather than requesting a name), its source, and resolved target session id.",
|
|
135
183
|
"placement.tmuxSession": "EXACT name of an EXISTING session on this agent's own tmux server. Nothing is created: an absent session is refused as tmux-session-missing, and a name outside [A-Za-z0-9][A-Za-z0-9_-]* as tmux-session-name-invalid.",
|
|
@@ -138,11 +186,11 @@
|
|
|
138
186
|
},
|
|
139
187
|
"entwurf_resume_call": {
|
|
140
188
|
"descriptions": {
|
|
141
|
-
"mcp": "Only on an explicit operator request, reopen ONE DORMANT pi or Claude Code citizen under its OWN garden id, in a visible window in the operator's own tmux session. The record supplies
|
|
142
|
-
"durable": "Only on an explicit operator request, reopen ONE dormant pi or Claude Code citizen under its own garden id in a visible tmux window through the entwurf-bridge (target required; the record supplies the session and cwd — no task or prompt is submitted). Returns the bridge's LAUNCH and OBSERVATION receipts or its named refusal: a live
|
|
189
|
+
"mcp": "Only on an explicit operator request, reopen ONE DORMANT pi, pi-durable or Claude Code citizen under its OWN garden id, in a visible window in the operator's own tmux session — or, inside herdr, a new herdr tab. The record supplies session, cwd and, for pi, the transcript's model and provider; the only input is the target id (no model override, task or prompt). Claude Code returns as `claude --resume <session id>` without its earlier model or permission flags. This verb submits NO prompt; what the runtime does once back (for Claude Code, unread mail may wake a turn) is not measured; talking to it is still entwurf_v2 fire-and-forget. TWO receipts mean different things: a LAUNCH receipt (a tmux window or herdr tab was made and asked to start the runtime) and an OBSERVATION receipt (pi: the control socket answered under the same id; pi-durable: the started child adopted this call's reservation (not readiness), or not-yet-adopted / reservation-lost; Claude Code: a NEW live process in this call's window or tab re-armed the session's marker with a fresh binding in the record, or pane-process-unread if herdr reports no pane child; or resume-unobserved, or record-unreadable with its cause). Unobserved is an outcome, not an error to retry; read the visible window. A session a live process holds is refused: a running citizen is reached only via entwurf_v2's rail check; an unadopted pi-durable reservation is not reachable by entwurf_v2. pi-durable reopens only if its session claim is closed and released or its holder is proven gone. Claude Code reopens only if the last validated owner its Entwurf hook armed is proven gone AND that arm is still the record's last; a missing, unreadable, mismatched or unbound marker or an inconclusive owner refuses, and a session held without a committed hook attach is invisible to that proof. Other backends have no same-id resume. This agent itself must run inside tmux or herdr; a herdr launch never falls back to tmux.",
|
|
190
|
+
"durable": "Only on an explicit operator request, reopen ONE dormant pi, pi-durable or Claude Code citizen under its own garden id in a visible tmux window — or, inside herdr, a new herdr tab — through the entwurf-bridge (target required; the record supplies the session and cwd — no task or prompt is submitted). Returns the bridge's LAUNCH and OBSERVATION receipts or its named refusal: a session a live process holds (a running citizen, or a pi-durable reservation awaiting adoption), another backend, or a citizen not proven dormant is refused by name, and opening it needs the tmux session — or the herdr pane — this host itself was launched in; a herdr launch never falls back to tmux. Existing unread mail may still wake the resumed runtime; neither receipt proves what it did."
|
|
143
191
|
},
|
|
144
192
|
"parameters": {
|
|
145
|
-
"target": "Garden id of the DORMANT pi or Claude Code citizen to reopen (discover with entwurf_peers)."
|
|
193
|
+
"target": "Garden id of the DORMANT pi, pi-durable or Claude Code citizen to reopen (discover with entwurf_peers)."
|
|
146
194
|
}
|
|
147
195
|
},
|
|
148
196
|
"entwurf_retire_call": {
|
|
@@ -171,16 +219,16 @@
|
|
|
171
219
|
},
|
|
172
220
|
"resumeRejectHints": {
|
|
173
221
|
"target-invalid": "the target is not a valid garden id; use entwurf_peers to discover valid targets",
|
|
174
|
-
"target-backend-unsupported": "that citizen's backend has no same-id resume (only pi and Claude Code do) — reach it with entwurf_v2, or open a fresh sibling",
|
|
222
|
+
"target-backend-unsupported": "that citizen's backend has no same-id resume (only pi, pi-durable and Claude Code do) — reach it with entwurf_v2, or open a fresh sibling",
|
|
175
223
|
"target-locked": "another resume or dispatch holds this citizen's lock right now",
|
|
176
|
-
"target-live": "that citizen
|
|
177
|
-
"target-indeterminate": "the citizen could not be proven dormant (an inconclusive socket probe or
|
|
224
|
+
"target-live": "a live process holds that citizen's session — this verb only reopens dormant ones",
|
|
225
|
+
"target-indeterminate": "the citizen could not be proven dormant (an inconclusive socket probe, receiver owner or session holder), so nothing was started",
|
|
178
226
|
"target-receiver-absent": "a Claude Code citizen is proven dormant only by its receiver marker, and it has none — there is no marker with which this verb could prove dormancy, so it opens nothing. Ask the human operator whether its window is still open; reopening it is the operator's act, not this verb's",
|
|
179
227
|
"target-receiver-corrupt": "the citizen's receiver marker cannot be read as a marker, so its owner cannot be judged",
|
|
180
228
|
"target-receiver-mismatch": "the receiver marker under this garden id names another backend or native session than the record — look at the store before anything reopens",
|
|
181
229
|
"target-receiver-unbound": "the dead receiver owner is not bound to the record's last arm (none observed, a later attach, or the record moved), so a Claude Code process may still hold the session and this verb opens nothing. Ask the human operator whether its window is still open; reopening it is the operator's act, not this verb's",
|
|
182
230
|
"target-address-conflict": "that citizen's control-socket path is corrupt",
|
|
183
|
-
"launch-refused": "tmux
|
|
231
|
+
"launch-refused": "the launcher refused before creating anything — no tmux window and no herdr tab was opened"
|
|
184
232
|
},
|
|
185
233
|
"freshLaunchRejectHints": {
|
|
186
234
|
"no-tmux-context": "this agent is not running inside tmux, so there is no session to open a sibling beside",
|
|
@@ -212,7 +260,7 @@
|
|
|
212
260
|
"cwd-format-token": "the recorded cwd contains '#', which tmux expands as a format inside -c — it would silently rewrite the path or run a command",
|
|
213
261
|
"cwd-missing": "the recorded cwd no longer exists; tmux would not report this, it would open the window in $HOME and look successful",
|
|
214
262
|
"cwd-not-directory": "the recorded cwd exists but is not a directory",
|
|
215
|
-
"herdr-resume-unsupported": "this agent runs inside herdr,
|
|
263
|
+
"herdr-resume-unsupported": "this agent runs inside herdr, where this tmux resume leaf does not open anything — nothing was opened in any ambient tmux session (from inside herdr, entwurf_resume_call reopens through its herdr rail instead)",
|
|
216
264
|
"runtime-unresolved": "the citizen's runtime (pi or claude) is not installed on PATH",
|
|
217
265
|
"runtime-not-absolute": "the resolved runtime path is not absolute",
|
|
218
266
|
"runtime-path-whitespace": "the resolved runtime path contains whitespace, which tmux would re-split",
|
|
@@ -31,9 +31,10 @@
|
|
|
31
31
|
* seat, #105; nothing is ever created), optionally at ONE literal requested
|
|
32
32
|
* cwd (cross-repo fresh, #73); returns a LAUNCH receipt only, and the new
|
|
33
33
|
* address arrives later as the sender envelope of the sibling's nonce callback.
|
|
34
|
-
* - entwurf_resume_call — reopen ONE DORMANT pi or Claude Code citizen under its OWN
|
|
35
|
-
* in a visible window; target-only, submits no prompt,
|
|
36
|
-
* receipts stay apart, the caller is attributed but
|
|
34
|
+
* - entwurf_resume_call — reopen ONE DORMANT pi, pi-durable or Claude Code citizen under its OWN
|
|
35
|
+
* garden id in a visible window or herdr tab; target-only, submits no prompt,
|
|
36
|
+
* LAUNCH and OBSERVATION receipts stay apart, the caller is attributed but
|
|
37
|
+
* grants nothing.
|
|
37
38
|
* - entwurf_retire_call — one operator-requested target, one retirement attempt; actor is not
|
|
38
39
|
* permission, and action / append-record / lock-release receipts stay separate.
|
|
39
40
|
* - entwurf_callback — ZERO-ARGUMENT fresh-sibling callback. Reads ENTWURF_CALLBACK_TARGET +
|
|
@@ -84,10 +85,10 @@ import { retireCitizen } from "../../../pi-extensions/lib/entwurf-v2-retire.js";
|
|
|
84
85
|
import { makeProductionRetireDeps } from "../../../pi-extensions/lib/entwurf-v2-retire-production.js";
|
|
85
86
|
import { runAndRenderEntwurfV2FromSurface } from "../../../pi-extensions/lib/entwurf-v2-surface.js";
|
|
86
87
|
import { makeVisibleResumeDeps, renderVisibleResume, visibleResume, } from "../../../pi-extensions/lib/entwurf-v2-visible-resume.js";
|
|
87
|
-
import { dispatchFreshCall, renderDispatchedFreshCall } from "../../../pi-extensions/lib/fresh-call-dispatch.js";
|
|
88
|
+
import { dispatchFreshCall, dispatchResumeLaunch, renderDispatchedFreshCall, } from "../../../pi-extensions/lib/fresh-call-dispatch.js";
|
|
88
89
|
import { probeNativeSenderAlive, reconcileSenderIdentityClaims, resolveCodexRequestSenderIdentity, resolveTrustedMetaSenderIdentity, } from "../../../pi-extensions/lib/meta-sender-identity.js";
|
|
89
90
|
import { applyOmpBridgeChildRootPolicy, defaultMetaMailboxDir, defaultMetaSessionsDir, makeStoreRecordReader, readActiveStoreEntries, readMetaIdentityByGardenId, readMetaInbox, readMetaReceiverMarker, readMetaSenderMarker, requireBackend, } from "../../../pi-extensions/lib/meta-session.js";
|
|
90
|
-
import { RESUME_CALL_REJECT_HINT, resumeCall } from "../../../pi-extensions/lib/mux-resume-call.js";
|
|
91
|
+
import { RESUME_CALL_REJECT_HINT, resumeCall, resumePiDurableCall, } from "../../../pi-extensions/lib/mux-resume-call.js";
|
|
91
92
|
import { registerNativeConversation } from "../../../pi-extensions/lib/native-push/register.js";
|
|
92
93
|
import { makeLocalTraceFact, readRemotePairOptIn, remotePairOptInPath, runEntwurfV2WithRemoteRoute, } from "../../../pi-extensions/lib/remote-pair-send.js";
|
|
93
94
|
import { processTransport } from "../../../pi-extensions/lib/remote-pair-transport.js";
|
|
@@ -641,12 +642,22 @@ server.tool("entwurf_fresh_call", ENTWURF_TOOL_GUIDANCE.entwurf_fresh_call.descr
|
|
|
641
642
|
// halves, so it is where the mux launcher is handed to the v2 composition. `entwurf-v2-visible-
|
|
642
643
|
// resume` cannot open a window on its own and `mux-resume-call` cannot read a record — that is
|
|
643
644
|
// the import fence in docs/mux-launch-rail.md §11, expressed as a function argument.
|
|
644
|
-
|
|
645
|
-
|
|
645
|
+
//
|
|
646
|
+
// #157 G1a: this surface does NOT choose the rail. It hands the fixed tmux mapping below to the
|
|
647
|
+
// shared rail root (`fresh-call-dispatch`), which reads the same capability fact fresh_call reads
|
|
648
|
+
// and, inside herdr, launches the herdr resume instead — never calling this mapping there.
|
|
649
|
+
//
|
|
650
|
+
// #157 B3: a pi-durable resume is the same leaf's second entry, which also carries the fixed adopt
|
|
651
|
+
// projection the v2 side built from its reservation; no other backend can hand it one.
|
|
652
|
+
const tmuxResumeLaunch = (input) => {
|
|
653
|
+
const launched = input.backend === "pi-durable"
|
|
654
|
+
? resumePiDurableCall({ cwd: input.cwd, runtimeArgs: input.runtimeArgs, adoptEnv: input.piDurableAdoptEnv })
|
|
655
|
+
: resumeCall({ backend: input.backend, cwd: input.cwd, runtimeArgs: input.runtimeArgs });
|
|
646
656
|
return launched.ok
|
|
647
|
-
? { ok: true, handle: launched.receipt }
|
|
657
|
+
? { ok: true, handle: { rail: "tmux", ...launched.receipt } }
|
|
648
658
|
: { ok: false, reason: launched.reason, hint: RESUME_CALL_REJECT_HINT[launched.reason] };
|
|
649
659
|
};
|
|
660
|
+
const visibleResumeLaunch = (input) => dispatchResumeLaunch(input, tmuxResumeLaunch);
|
|
650
661
|
server.tool("entwurf_resume_call", ENTWURF_TOOL_GUIDANCE.entwurf_resume_call.descriptions.mcp, {
|
|
651
662
|
target: z
|
|
652
663
|
.string()
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* verb (0.11 Stage 0 step 4-pre / 동결결정 10). PURE pi-FREE core: the
|
|
4
4
|
* intent×liveness decision table + the reject taxonomy + a pure resolver.
|
|
5
5
|
* NO runtime dispatch, NO spawn/send, NO I/O — step 5 wires this to transports.
|
|
6
|
-
* The pi-
|
|
6
|
+
* The pi-schema REPRESENTATION of this contract lives in the separate
|
|
7
7
|
* `entwurf-v2-contract-schema.ts` (0.12.1 B-1) so this module — which the
|
|
8
8
|
* harness-neutral MCP bridge reaches at boot — carries no pi dependency.
|
|
9
9
|
*
|
|
@@ -431,9 +431,9 @@ export function resolveNativePushDispatch(intent, liveness) {
|
|
|
431
431
|
observedLiveness: liveness,
|
|
432
432
|
};
|
|
433
433
|
}
|
|
434
|
-
// ──
|
|
435
|
-
// MOVED to `entwurf-v2-contract-schema.ts` (0.12.1 B-1): the pi
|
|
436
|
-
// builders (StringEnum
|
|
434
|
+
// ── JSON schemas ───────────────────────────────────────────────────────────
|
|
435
|
+
// MOVED to `entwurf-v2-contract-schema.ts` (0.12.1 B-1): the pi schema
|
|
436
|
+
// builders (pi-ai StringEnum, pi-schema since #155) are a pi-lane dependency, so they cannot live in
|
|
437
437
|
// this pi-free core — the MCP bridge reaches this module at boot and must stay
|
|
438
438
|
// harness-neutral (check-entwurf-bridge-pi-free). The schemas import the
|
|
439
439
|
// constants/types above; pi-side consumers import the schemas from there.
|