@junghanacs/entwurf 0.45.0 → 0.50.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 +3 -2
- package/BASELINE.md +110 -1
- package/CHANGELOG.md +169 -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 +124 -188
- package/VERIFY.md +2 -2
- package/docs/external-mcp-host.md +3 -3
- package/docs/setup-clean-host.md +37 -12
- 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-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 +6 -3
- package/pi/pi-durable/bootstrap.mjs +179 -6
- package/pi/pi-durable/carrier/runtime.js +108 -9
- package/pi/pi-durable/carrier/session-name.js +11 -0
- package/pi/pi-durable/carrier/sessions.js +96 -20
- package/pi/pi-durable/overlay/upstream-pin.json +11 -5
- 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 +29 -15
- package/run.sh +411 -657
- package/scripts/check-claude-launch.ts +341 -0
- 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 +18 -13
- 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/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/peer-facts.json +15 -0
- package/scripts/mutants/pi-durable.json +979 -1
- 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
|
@@ -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()
|