@junghanacs/entwurf 0.13.0 → 0.13.1
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 +57 -203
- package/CHANGELOG.md +19 -0
- package/CONTRIBUTING.md +1 -1
- package/DELIVERY.md +117 -261
- package/README.md +68 -408
- package/VERIFY.md +58 -87
- package/demo/README.md +1 -1
- package/docs/acp-backend-rail.md +231 -0
- package/docs/external-mcp-host.md +132 -0
- package/docs/fresh-cut-policy.md +99 -0
- package/docs/setup-clean-host.md +123 -328
- package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +21 -48
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/acp-client.js +12 -0
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/backend-adapter.js +11 -10
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/config.js +1 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/engraving.js +42 -1
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/models.js +4 -4
- package/mcp/entwurf-bridge/dist/pi-extensions/lib/acp/overlay.js +3 -3
- package/mcp/entwurf-bridge/src/index.ts +21 -48
- package/package.json +12 -9
- package/pi-extensions/entwurf-control.ts +20 -49
- package/pi-extensions/lib/acp/acp-client.ts +22 -0
- package/pi-extensions/lib/acp/augment.ts +42 -3
- package/pi-extensions/lib/acp/backend-adapter.ts +12 -11
- package/pi-extensions/lib/acp/backend.ts +305 -36
- package/pi-extensions/lib/acp/config.ts +1 -1
- package/pi-extensions/lib/acp/engraving.ts +43 -1
- package/pi-extensions/lib/acp/event-mapper.ts +16 -13
- package/pi-extensions/lib/acp/models.ts +4 -4
- package/pi-extensions/lib/acp/overlay.ts +3 -3
- package/prompts/engraving.md +13 -5
- package/run.sh +244 -108
- package/scripts/check-acp-carrier-augment.ts +246 -10
- package/scripts/check-acp-cortex.ts +5 -5
- package/scripts/check-acp-prompt-lifecycle.ts +565 -0
- package/scripts/check-acp-sdk-surface.ts +60 -21
- package/scripts/check-acp-stop-reason.ts +342 -0
- package/scripts/check-entwurf-v2-surface.ts +41 -0
- package/scripts/check-gate-qualification.ts +6 -3
- package/scripts/check-probe-ordering.ts +39 -7
- package/scripts/check-release-gate-outcomes.ts +332 -0
- package/scripts/lib/live-skip.ts +33 -0
- package/scripts/lib/probe-acp-turn.ts +33 -12
- package/scripts/lib/step-outcome.sh +88 -0
- package/scripts/mutants/acp-augment.json +106 -0
- package/scripts/mutants/acp-cortex.json +2 -2
- package/scripts/mutants/acp-prompt-lifecycle.json +100 -0
- package/scripts/mutants/acp-stop-reason.json +80 -0
- package/scripts/mutants/probe-ordering.json +27 -5
- package/scripts/mutants/release-gate.json +105 -0
- package/scripts/mutants/v2-surface.json +26 -15
- package/scripts/smoke-acp-bundled-mcp-live.ts +4 -3
- package/scripts/smoke-acp-carrier-augment-live.ts +2 -2
- package/scripts/smoke-acp-cortex-live.ts +8 -14
- package/scripts/smoke-acp-long-turn-live.ts +185 -0
- package/scripts/smoke-acp-mcp-live.ts +2 -2
- package/scripts/smoke-acp-memory-containment-live.ts +2 -2
- package/scripts/smoke-acp-ordering-probe-live.ts +2 -2
- package/scripts/smoke-acp-overlay-live.ts +2 -2
- package/scripts/smoke-acp-provider-live.ts +2 -2
- package/scripts/smoke-acp-raw-turn-live.ts +3 -3
- package/scripts/smoke-acp-session-reuse-live.ts +2 -2
- package/scripts/smoke-acp-skill-live.ts +2 -2
- package/scripts/smoke-acp-socket-citizen-live.ts +4 -3
- package/scripts/smoke-acp-v2-send-live.ts +4 -3
- package/scripts/smoke-agy-native-push-live.ts +4 -3
- package/scripts/smoke-claude-native-resume-live.sh +13 -3
- package/scripts/smoke-entwurf-chain-live.ts +352 -0
- package/scripts/smoke-entwurf-v2-matrix-live.ts +2 -2
- package/scripts/smoke-entwurf-v2-spawn-resume-live.ts +2 -4
- package/scripts/smoke-meta-install-state.sh +4 -0
package/VERIFY.md
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
# VERIFY.md
|
|
2
2
|
|
|
3
|
-
Agent-driven verification guide for the `entwurf` surface
|
|
3
|
+
Agent-driven verification guide for the current `entwurf` surface. Machine-checkable
|
|
4
|
+
invariants live in gates; this file defines evidence strength, release acceptance,
|
|
5
|
+
and the manual judgements a gate cannot make.
|
|
4
6
|
|
|
5
|
-
> **Current surface.**
|
|
7
|
+
> **Current surface.** `entwurf-bridge` exposes `entwurf_v2`, `entwurf_peers`,
|
|
8
|
+
> `entwurf_self`, `entwurf_inbox_read`, and `entwurf_register_native`. The ACP
|
|
9
|
+
> backends are Claude and Snowflake Cortex Code. Antigravity is a separate shipped
|
|
10
|
+
> native-push citizen lane; Codex has delivery-probe evidence but no managed citizen
|
|
11
|
+
> lane. Retired v1 verbs and bridge implementations belong only in CHANGELOG/git.
|
|
6
12
|
|
|
7
|
-
This is a
|
|
13
|
+
This is a working protocol, not a metrics ledger. Per-run counts, digests, and release
|
|
14
|
+
chronology belong in [BASELINE.md](./BASELINE.md), CHANGELOG, and release artifacts.
|
|
8
15
|
|
|
9
16
|
VERIFY.md is the **agent-driven** surface; [BASELINE.md](./BASELINE.md) is the operator-driven one. One ACP-bridged model runs the checks against another and writes down what it sees — if the bridge is faithful, two replicants looking at the same mirror describe the mirror the same way. This is in-bridge cross-validation, not external evidence: verifier and subject share the same bridge, MCP servers, and overlay, so a uniform corruption of those would not surface here (that gap is what the L3+ rungs close).
|
|
10
17
|
|
|
@@ -35,78 +42,39 @@ Verification here is not a benchmark. In production we exchange short turns and
|
|
|
35
42
|
|
|
36
43
|
- **Deterministic floor:** `pnpm check` — the full `check-*` gate set (the `check` script in `package.json` is the SSOT for what runs). Run first; it is the offline, machine-checkable layer.
|
|
37
44
|
- **Discriminating power of that floor:** `./run.sh check-gate-qualification` (inside `pnpm check`) re-plants committed defect mutants (`scripts/mutants/*.json`, one per closed defect class) in an isolated snapshot repo and requires each to turn its gate red **bounded and at its claimed `[QK:<claim>]` signature** — a wrong-reason red fails, a baseline-red control voids the whole group, and the runner is negative-controlled on every run (zero-match/multi-match/survived/wrong-reason/hang/control-red/impurity). This measures whether the deterministic gates still *block* what they claim to block; it is **not a new evidence level** (L0–L5 are untouched) and never substitutes for LIVE evidence. Per-cut records cite claim IDs + killed mutant IDs — "N checks passed" alone is not evidence. `check-agy-permission-matrix` complements it with the enumerated permission contract space (literal cells + stated exclusion rules, oracle independent of the SUT).
|
|
38
|
-
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir
|
|
39
|
-
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm check`, `smoke-entwurf-v2-spawn-resume-live`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen),
|
|
45
|
+
- **Live floor:** `LIVE=1 ./run.sh release-gate <scratch-project-dir> --cut` — `pnpm check` + the v2-native live gates + the ACP plugin acceptance floor. It reports a **two-tier summary**:
|
|
46
|
+
- **MUST tier** (release-blocking — owns the exit code; "green" applies only here): `pnpm check`, `smoke-entwurf-v2-spawn-resume-live`, `smoke-entwurf-v2-matrix-live`, `check-bridge`, the resident-garden-guard zero-token half (record birth / record-keyed socket / attach-on-reopen), the `smoke-acp-*-live` ACP plugin smokes (socket-citizen / raw-turn / overlay / provider / session-reuse / carrier-augment / memory-containment / rgg / mcp / skill / bundled-mcp / v2-send), the two axes wired in on 2026-07-31 that the aggregate had simply never listed (`smoke-entwurf-v2-spawn-live`, `smoke-claude-native-resume-live`), and `smoke-entwurf-chain-live` — the cross-harness delivery chain (native Claude Code → pi GPT → pi ACP Sonnet → mailbox terminus) proving sender identity and replyability at every hop plus a real read receipt at the end. (`smoke-session-id-name` is gone — #50 C3: its `--session-id`/`--name` substrate has no entwurf consumer anymore.)
|
|
40
47
|
- **BEHAVIOR tier** (advisory, non-blocking): the resident-garden-guard positive (a model-in-loop `entwurf_self` turn). A BEHAVIOR FAIL is surfaced with its artifact path but **never blocks the cut**. The lane holds what the model *chooses*, never what our wiring fails to deliver — a gate that TELLS the model which tool to call stays MUST, because its failure is ours — measured 2026-07-24, when the tool turned out to be absent from the session schema in both observed failures (the bundled-MCP readiness gap recorded in `scripts/smoke-acp-v2-send-live.ts`).
|
|
41
|
-
-
|
|
48
|
+
- **Every MUST step is invoked and reports its own outcome** (P1 STEP OUTCOME protocol, `scripts/lib/step-outcome.sh`): exit 0 = PASS, exit 97 = SKIP (a prerequisite the step does not have, printed as an `[entwurf:skip]` line), anything else = FAIL. A skip is never counted as a pass — that hole is what let a cortex-less host read as cortex acceptance. Without `--cut` this is the unattended diagnostic: SKIPs are reported and the run still exits 0. **`--cut` makes it acceptance and any MUST SKIP is red**, which is how "a real cut needs `LIVE=1` with `SKIP=0`" stopped being prose. A green MUST gate is **necessary, not sufficient** — GLG authorizes the cut.
|
|
42
49
|
- **When cost-bearing MUST gates run (fixed 2026-07-23, the F6/F7 lesson):** a commit that touches a rail a MUST-tier live gate covers runs that gate **before cross-review is requested** — never parked behind "run it at approval time". Deferring a wired gate to a human decision is what let F6/F7 ship reviewed-and-approved; the wiring exists so the verdict never depends on who pressed enter. "배선이 없어 못 한 것은 OK, 배선이 있는데 안 돌린 것은 우리가 남긴 구멍이다." Model-in-loop cost is spent via the subscription-backed `entwurf` provider where the gate allows it, a free-tier native model otherwise; cost is a reason to pick the cheap target, not to skip the gate.
|
|
43
50
|
|
|
51
|
+
> **Cortex is an on-demand axis, not an aggregate one.** Its rail needs an external Snowflake connection and login that the host owns, not the repo — so wiring it into the aggregate would block every cut taken on a host without that account. **The 0.13.1 aggregate does not re-certify Cortex**; `LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live` stays a required direct call whenever a cut changes Cortex rail code or an operator elects to certify that host. Its honest-skip behaviour is unchanged: run it without the connection and it reports protocol SKIP, never a pass.
|
|
52
|
+
>
|
|
53
|
+
> A cut that touches the prompt-lifecycle contract (no wall clock on a running turn) owes one long-turn acceptance the aggregate floor is too short to carry: `LIVE=1 ./run.sh smoke-acp-long-turn-live` drives a real turn whose tool work outlasts the retired 600s cutoff and requires exactly one cold ACP bootstrap in the transcript. It takes >12 minutes by construction and is on-demand, not part of `release-gate`.
|
|
54
|
+
>
|
|
44
55
|
> The aggregate release gate does not own a live agy conversation id, so agy's real native-push round trip is a separate acceptance axis: three fail-loud doctors plus `LIVE=1 AGY_CONVERSATION_ID=<id> ./run.sh smoke-agy-native-push-live`, followed by a fresh-conversation sender/reply check after package install. Its deterministic install/sender gates are already inside `pnpm check`; do not misreport the aggregate gate as live agy evidence.
|
|
45
56
|
>
|
|
46
|
-
>
|
|
57
|
+
> Authoritative per-cut counts and digests live in BASELINE/CHANGELOG, not inline
|
|
58
|
+
> here; embedding them in the protocol makes a correct guide stale after every cut.
|
|
47
59
|
|
|
48
|
-
###
|
|
60
|
+
### Release acceptance axes
|
|
49
61
|
|
|
50
|
-
Do not collapse package
|
|
51
|
-
one word such as “green.” They answer different questions.
|
|
62
|
+
Do not collapse source, package, fixture, and native-host evidence into one “green.”
|
|
52
63
|
|
|
53
|
-
| Axis |
|
|
54
|
-
|
|
55
|
-
| Source
|
|
56
|
-
|
|
|
57
|
-
| Linux artifact consumer | `check-install-container`
|
|
58
|
-
|
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
new native session proves that a real host supplied those layers.
|
|
68
|
-
|
|
69
|
-
### Stable 0.12.8 order (current execution; authority is mode-specific)
|
|
70
|
-
|
|
71
|
-
The repo-local `entwurf-release` skill is a checkpointed state machine. Each mode
|
|
72
|
-
is a separate authorization; one mode never implies the next. The repair history
|
|
73
|
-
remains in CHANGELOG: repair.0 was field-broken, repair.1 restored delivery, and
|
|
74
|
-
on 2026-07-25 its installed artifact passed the real native doctor on maintainer
|
|
75
|
-
and secondary Linux hosts. That closed the explicit prerequisite for promoting
|
|
76
|
-
this line to stable `0.12.8`; it does not transfer CI/LIVE/candidate evidence to
|
|
77
|
-
the new stable bytes.
|
|
78
|
-
|
|
79
|
-
1. `land 0.12.8` pushes only the clean **pre-version landing HEAD** and requires
|
|
80
|
-
a push-triggered `ci.yml` run whose `headSha` is exactly that commit. Current
|
|
81
|
-
accepted landing: `1345688001ed6629bd0f58996a36134e7b7874bc`, run
|
|
82
|
-
[30150824225](https://github.com/junghan0611/entwurf/actions/runs/30150824225),
|
|
83
|
-
with `check`, `install-surface`, and `artifact-consumer` all success.
|
|
84
|
-
2. `prepare 0.12.8` promotes the changelog, sets the package version, reruns the
|
|
85
|
-
deterministic and LIVE gates, and creates the release-prep commit. It never
|
|
86
|
-
pushes, tags, creates a candidate, or publishes.
|
|
87
|
-
3. `make 0.12.8` pushes that clean prepared HEAD and requires the same three jobs
|
|
88
|
-
on that exact version commit. Only after the second exact-SHA CI is green does
|
|
89
|
-
it preserve and accept one candidate without repacking:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
ARTIFACT_DIR=$(mktemp -d /tmp/entwurf-release-candidate-0.12.8.XXXXXX)
|
|
93
|
-
bash scripts/with-dist-lock.sh npm pack --dry-run=false --pack-destination "$ARTIFACT_DIR"
|
|
94
|
-
CANDIDATE="$(realpath "$ARTIFACT_DIR/junghanacs-entwurf-0.12.8.tgz")"
|
|
95
|
-
sha256sum "$CANDIDATE"
|
|
96
|
-
ENTWURF_REQUIRE_DOCKER=1 ENTWURF_CANDIDATE_TGZ="$CANDIDATE" \
|
|
97
|
-
./run.sh check-install-container | tee "$ARTIFACT_DIR/acceptance.log"
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
The gate must print caller-preserved candidate mode, the same canonical path
|
|
101
|
-
and SHA-256, and the image identity. `make` then tags the exact prepared SHA
|
|
102
|
-
and creates the GitHub release. Never repack accepted bytes.
|
|
103
|
-
4. Only an explicit `publish 0.12.8 <absolute-candidate> latest` may publish the
|
|
104
|
-
accepted file. Registry proof requires `latest=0.12.8` while preserving
|
|
105
|
-
`repair=0.12.8-repair.1`, followed by the registry-installed smoke.
|
|
106
|
-
|
|
107
|
-
Invoking `land`, `prepare`, `make`, or `publish` grants only that named mode's
|
|
108
|
-
authority. `prepare` stops at a local commit; `make` and `publish` remain separate
|
|
109
|
-
GLG decisions.
|
|
64
|
+
| Axis | Required proof | Limit |
|
|
65
|
+
|---|---|---|
|
|
66
|
+
| Source | `pnpm check` | Does not prove an installed consumer. |
|
|
67
|
+
| Packed install | `check-pack-install` | Real tarball, but checkout-visible. |
|
|
68
|
+
| Linux artifact consumer | required `check-install-container` CI job against one preserved candidate | Fixtures prove package/oracle shape, not a real Claude lifecycle. |
|
|
69
|
+
| Exact release commit | all required CI jobs green at the exact SHA | A different green SHA is not transferable evidence. |
|
|
70
|
+
| LIVE runtime | `LIVE=1 ./run.sh release-gate <scratch> --cut` plus any shipped on-demand backend axis | `--cut` enforces `SKIP=0`; a red wired gate blocks the cut. |
|
|
71
|
+
| Native Claude host | installed strict doctor against a new real session | Missing live join is `NOT CERTIFIED`, not a fixture PASS. |
|
|
72
|
+
| Native agy host | three doctors plus conversation-id-gated native-push round trip | Aggregate release-gate does not own an agy conversation id. |
|
|
73
|
+
|
|
74
|
+
The repo-local `entwurf-release` skill owns the `land → prepare → make → publish`
|
|
75
|
+
state machine. Each mode is a separate GLG authorization. Preserve one candidate,
|
|
76
|
+
accept and publish those exact bytes without repacking, and record its digest and
|
|
77
|
+
consumer image outside this standing protocol.
|
|
110
78
|
|
|
111
79
|
### Verifying the two capabilities a gate cannot fully judge
|
|
112
80
|
|
|
@@ -136,7 +104,7 @@ When injecting a fact for a continuity check, use **plaintext that does not trig
|
|
|
136
104
|
|
|
137
105
|
### bridge continuity vs semantic continuity
|
|
138
106
|
|
|
139
|
-
- **bridge continuity:** same `sessionKey` / same `acpSessionId`
|
|
107
|
+
- **bridge continuity:** same `sessionKey` / same `acpSessionId` through in-memory process-scoped reuse. Persisted session records are written for a future resume/load lane but are not consumed today.
|
|
140
108
|
- **semantic continuity:** a fact from a prior turn is retrievable in a later turn.
|
|
141
109
|
|
|
142
110
|
Either can be alive while the other looks dead (the wording case above is bridge-alive / semantic-looks-dead). When in doubt, change the wording and retry once, and check the `[entwurf:bootstrap]` lines in bridge stderr. No automated smoke separates these yet.
|
|
@@ -145,7 +113,7 @@ Either can be alive while the other looks dead (the wording case above is bridge
|
|
|
145
113
|
|
|
146
114
|
The goal is not merely "invoke Claude Code." We want:
|
|
147
115
|
|
|
148
|
-
1. **Session continuity at the agent-shell level** —
|
|
116
|
+
1. **Session continuity at the agent-shell level** — process-scoped turns reuse one live ACP session; fresh/turn-scoped paths open a new one rather than reconstructing a transcript inside entwurf.
|
|
149
117
|
2. **Preservation of pi harness semantics** — pi session files / transcripts / memory pipeline stay a shared axis.
|
|
150
118
|
3. **restart-hygienic** — process-scoped reuse continues the same ACP session across turns inside a long-lived resident; persisted records are written/validated for the future resume-load lane, not the live continuity path today.
|
|
151
119
|
4. **Thin bridge** — no second harness built inside this repo.
|
|
@@ -185,7 +153,7 @@ cd "$REPO_DIR" && ./run.sh setup "$PROJECT_DIR"
|
|
|
185
153
|
### 1.2 Live acceptance (optional)
|
|
186
154
|
|
|
187
155
|
```bash
|
|
188
|
-
LIVE=1 ./run.sh release-gate /path/to/consumer-project
|
|
156
|
+
LIVE=1 ./run.sh release-gate /path/to/consumer-project --cut
|
|
189
157
|
pi --provider entwurf --model claude-sonnet-5 -p "reply with ok only" # one-turn smoke
|
|
190
158
|
```
|
|
191
159
|
|
|
@@ -197,13 +165,18 @@ addressable sends require `--entwurf-control` (measured 2026-07-24: the same
|
|
|
197
165
|
one-shot with that flag returns its own gid and delivers `entwurf_v2` to a peer
|
|
198
166
|
mailbox with `origin=pi-session`, `replyable=true`).
|
|
199
167
|
|
|
200
|
-
`setup` runs `pnpm install` + project/user-scope install + detected native-harness wiring (Claude and/or agy) + the v2 install smoke. A green setup proves the required core path and reports optional-harness degradation; it does **not** replace the native-harness doctors. The full aggregate live floor is still `LIVE=1 ./run.sh release-gate
|
|
168
|
+
`setup` runs `pnpm install` + project/user-scope install + detected native-harness wiring (Claude and/or agy) + the v2 install smoke. A green setup proves the required core path and reports optional-harness degradation; it does **not** replace the native-harness doctors. The full aggregate live floor is still `LIVE=1 ./run.sh release-gate <scratch> --cut` — without `--cut` it is a diagnostic pass, not acceptance — with agy's conversation-id-gated round trip verified separately.
|
|
201
169
|
|
|
202
170
|
### 1.4 Cross-install / cross-backend parity (optional, high-value)
|
|
203
171
|
|
|
204
|
-
Compare a fresh self-awareness report across axes: (1) same backend, different install path — answer must be path-invariant; (2) same backend, different machine — identical native tool list + MCP server/tool set; (3) different backend, same bridge — same garden capability but **different** native tool surface (a Claude session reporting another backend's native tools is a fail); (4) native pi routing vs ACP-bridged, same model — the native target reports no `entwurf-bridge` MCP (capability via pi's extension surface), while the ACP target reports it as the single MCP server. Honest "native: I cannot tell" hedging is PASS on the native side.
|
|
172
|
+
Compare a fresh self-awareness report across axes: (1) same backend, different install path — answer must be path-invariant; (2) same backend, different machine — identical native tool list + MCP server/tool set; (3) different backend, same bridge — same garden capability but **different** native tool surface (a Claude session reporting another backend's native tools is a fail); (4) native pi routing vs ACP-bridged, same model — the native target reports no `entwurf-bridge` MCP (capability via pi's extension surface), while the ACP target reports it as the single MCP server. Honest "native: I cannot tell" hedging is PASS on the native side. agy is graded by its native-citizen checklist, not by pretending it has an ACP overlay.
|
|
205
173
|
|
|
206
|
-
**Cortex
|
|
174
|
+
**Cortex on axis 3.** A cortex session must expose the same garden capability
|
|
175
|
+
while keeping cortex's own native tool surface. Its callable MCP identifier shape is
|
|
176
|
+
the same as Claude's, but it has no system-prompt carrier: engraving is prepended to
|
|
177
|
+
the first user augment. Installed-model enumeration is deterministic; candidate-installed
|
|
178
|
+
LIVE Cortex acceptance and its remaining host limits are recorded per cut rather than
|
|
179
|
+
frozen here.
|
|
207
180
|
|
|
208
181
|
---
|
|
209
182
|
|
|
@@ -243,8 +216,9 @@ The single-turn / multi-turn / cross-process / persistence-boundary / shutdown i
|
|
|
243
216
|
| Single-turn prompt extraction, SessionStart hook not mistaken for prompt | `smoke-acp-raw-turn-live`, `check-acp-prompt-builder` |
|
|
244
217
|
| Multi-turn continuity + recall (process-scoped reuse) | `smoke-acp-session-reuse-live`, `check-acp-session-reuse` |
|
|
245
218
|
| Cross-process continuity / cache before-after | `check-acp-session-store` (signature, decideBootstrap, persist/parse) |
|
|
246
|
-
| Lifecycle policy —
|
|
219
|
+
| Lifecycle policy — turn-scoped is always new; process-scoped may reuse only the live in-memory session; persisted records are not a resume/load path today | `check-acp-session-store`, `check-acp-session-reuse` |
|
|
247
220
|
| Tool-call / event mapping | `check-acp-event-mapper`, `smoke-acp-provider-live` |
|
|
221
|
+
| Prompt lifecycle — no wall-clock cutoff on a running turn; abort ends it by ACP `session/cancel` with bounded cleanup; a child death is reported with exit status + stderr on new AND reuse turns; our prompt-phase error text is not classified transient by pi | `check-acp-prompt-lifecycle`, `check-probe-ordering` |
|
|
248
222
|
| Operator mcpServers / skills reach the live session | `smoke-acp-mcp-live`, `smoke-acp-skill-live`, `check-acp-config` |
|
|
249
223
|
| Overlay isolation + memory containment | `check-acp-overlay`, `smoke-acp-memory-containment-live`, `check-acp-tool-surface` |
|
|
250
224
|
|
|
@@ -252,18 +226,16 @@ The single-turn / multi-turn / cross-process / persistence-boundary / shutdown i
|
|
|
252
226
|
|
|
253
227
|
The literal callable identifier differs per backend — probe by asking the agent to print it **verbatim** (do not ask "hyphen or underscore" — ambiguous between outer separator and inner server name):
|
|
254
228
|
|
|
255
|
-
| Backend | Literal identifier |
|
|
256
|
-
|
|
257
|
-
| Claude | `mcp__entwurf-bridge__entwurf_v2` |
|
|
258
|
-
| Cortex
|
|
259
|
-
| Codex | `mcp__entwurf_bridge__.entwurf_v2` | `__` | `entwurf_bridge` (underscore) + **literal dot** |
|
|
260
|
-
| Gemini *(probe)* | `mcp_entwurf-bridge_entwurf_v2` | `_` (single) | `entwurf-bridge`, no dot |
|
|
229
|
+
| Backend | Literal identifier | Boundary |
|
|
230
|
+
|---|---|---|
|
|
231
|
+
| Claude | `mcp__entwurf-bridge__entwurf_v2` | native Claude tool surface + explicit MCP server |
|
|
232
|
+
| Cortex | `mcp__entwurf-bridge__entwurf_v2` | same identifier shape, different native tool surface |
|
|
261
233
|
|
|
262
|
-
|
|
234
|
+
The identifier cannot distinguish Claude from Cortex; native tools and carrier facts must.
|
|
263
235
|
|
|
264
|
-
### 2.2 MCP injection visibility
|
|
236
|
+
### 2.2 MCP injection visibility
|
|
265
237
|
|
|
266
|
-
The sole MCP responsibility of `entwurf` is to
|
|
238
|
+
The sole MCP responsibility of `entwurf` is to project explicit `entwurfProvider.mcpServers` into every newly opened backend session. Ask for visible MCP server names: `entwurf-bridge` appears, ambient servers do not, and changing the declaration changes `bridgeConfigSignature` so a live incompatible session is replaced rather than silently reused. `check-acp-config` and `smoke-acp-mcp-live` pin this; the manual check is honesty corroboration.
|
|
267
239
|
|
|
268
240
|
### 2.3 Process / cache hygiene — the orphan bound (§gate-external judgement)
|
|
269
241
|
|
|
@@ -274,7 +246,7 @@ AFTER_<BACKEND> ≤ BEFORE_<BACKEND> + (distinct alive
|
|
|
274
246
|
(sessionKey, backend, modelId, bridgeConfigSignature) tuples this run holds open)
|
|
275
247
|
```
|
|
276
248
|
|
|
277
|
-
An **upper bound**, not an equation: child reuse
|
|
249
|
+
An **upper bound**, not an equation: child reuse and idle reaping may keep the delta below it; a config-signature or `(provider, model)` switch may add one. `AFTER > BEFORE + alive_tuples` is actionable. Walk the backend process parent chain; any ACP child whose parent `pi` has exited is an orphan—preserve it as evidence.
|
|
278
250
|
|
|
279
251
|
### 2.4 pi session record as a shared memory axis
|
|
280
252
|
|
|
@@ -289,13 +261,13 @@ Pass: user/assistant turns accumulate normally; the transcript is not broken/emp
|
|
|
289
261
|
|
|
290
262
|
---
|
|
291
263
|
|
|
292
|
-
## 3. Pass criteria —
|
|
264
|
+
## 3. Pass criteria — current release floor
|
|
293
265
|
|
|
294
266
|
The minimum passing bar:
|
|
295
267
|
|
|
296
268
|
1. **Deterministic floor green:** `pnpm check` passes (lint + typecheck + the `check-*` gate set + `check-pack`).
|
|
297
269
|
2. **All three CI jobs green on the exact release commit:** `check`, `install-surface`, and the required Linux `artifact-consumer`; preserve the latter's tarball digest and image identity.
|
|
298
|
-
3. **Live floor MUST green:** `LIVE=1 ./run.sh release-gate <dir
|
|
270
|
+
3. **Live floor MUST green:** `LIVE=1 ./run.sh release-gate <dir> --cut` exits 0 reporting `MUST PASS=N FAIL=0 SKIP=0`; with `--cut` a single SKIP is red, so the exit code itself now carries this condition. A BEHAVIOR FAIL is advisory, not blocking.
|
|
299
271
|
4. **Native-host doctor green where the Claude meta-bridge is claimed:** a new post-install Claude session exists, live evidence is present, and the installed `doctor-meta-bridge` exits 0. `NOT CERTIFIED` is a release failure for that host, not a skip.
|
|
300
272
|
5. **Honest self-recognition:** the bridged model identifies its actual harness/backend, lists `entwurf-bridge` as the single MCP server with its five current tools, and presents a backend-native (not normalized) tool surface.
|
|
301
273
|
6. **Carrier separation honored:** engraving vs pi-context-augment kept distinct (§1A.0); no bridge-identity narrative attributed to the engraving carrier.
|
|
@@ -315,7 +287,6 @@ Passing establishes a **release verification floor**, not an 8-hour/day operatio
|
|
|
315
287
|
- **Retired dedicated smokes, live code invariants** (manual/troubleshooting only — *not* part of the release floor):
|
|
316
288
|
- *Model-switch lock* — entwurf sessions are locked to their starting model. Gate: `check-model-lock` (in `pnpm check`). The dedicated live `smoke-model-switch` was retired in v2; the invariant lives in `pi-extensions/model-lock.ts` (extension guard) + `session-store.ts` `SessionModelLockedError` (the `decideBootstrap` fail-loud model lock).
|
|
317
289
|
- *Cancel / abort cleanup* — `onAbort` → `cancelActivePrompt()` (session stays reusable); the stream catch closes the bridge only on `stopReason === "error"`. Dedicated `smoke-cancel` retired; invariant in code.
|
|
318
|
-
- *Transcript-poison invalidation (#12)* — **historical (0.11):** a poisoned backend transcript (empty text block ± `cache_control`) returned the same Anthropic 400 forever, handled by a dedicated classifier + `verify-transcript-poison` smoke. Both were retired in the 0.12 cutover; there is **no dedicated classifier or gate on the current surface** — recorded only so the failure mode is not forgotten.
|
|
319
290
|
|
|
320
291
|
### Evidence preservation when a problem occurs
|
|
321
292
|
|
package/demo/README.md
CHANGED
|
@@ -137,7 +137,7 @@ SCENE_DELAY=30 FINAL_PAUSE=10 bash demo.sh
|
|
|
137
137
|
|
|
138
138
|
## Prerequisites
|
|
139
139
|
|
|
140
|
-
- `pi` on PATH (current floor 0.
|
|
140
|
+
- `pi` on PATH (current floor 0.83.0)
|
|
141
141
|
- `entwurf` provider configured + auth ready for the selected sender/peer models
|
|
142
142
|
- `asciinema` installed
|
|
143
143
|
- `agg` installed (optional — only for GIF conversion)
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# ACP backend adapter rail
|
|
2
|
+
|
|
3
|
+
The ACP plugin is one provider with backend adapters behind a common turn loop.
|
|
4
|
+
It is not a second harness and does not create another citizen or socket layer. The
|
|
5
|
+
host pi session already owns the record-backed citizen identity; each backend owns
|
|
6
|
+
its own process, auth, transcript, and native tool surface.
|
|
7
|
+
|
|
8
|
+
Claude is the reference adapter. Snowflake Cortex Code is the second shipped adapter.
|
|
9
|
+
Implementation history and audit chronology live in CHANGELOG, issues, and git; this
|
|
10
|
+
document keeps the current contract and its open evidence boundary.
|
|
11
|
+
|
|
12
|
+
## Boundary
|
|
13
|
+
|
|
14
|
+
| Layer | Owns |
|
|
15
|
+
|---|---|
|
|
16
|
+
| entwurf core | identity, facts, dispatch, rail choice, delivery evidence |
|
|
17
|
+
| ACP common loop | spawn, initialize, new session, model enforcement, prompt, event mapping, teardown |
|
|
18
|
+
| backend adapter | model routing, launch, overlay, carrier, backend settings, model enforcement details |
|
|
19
|
+
| backend runtime | credentials, subscription, transcript, native tools, native configuration semantics |
|
|
20
|
+
|
|
21
|
+
The common sequence is invariant:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
resolve adapter once
|
|
25
|
+
→ load backend settings and carrier
|
|
26
|
+
→ materialize backend overlay
|
|
27
|
+
→ spawn → initialize → newSession → enforceModel
|
|
28
|
+
→ prompt → event map → retain-or-teardown
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
No layer reconstructs a backend transcript, proxies credentials, scans ambient MCP
|
|
32
|
+
configuration, or grants tools through prose. Explicit `entwurfProvider.mcpServers`
|
|
33
|
+
and the callable schema are the tool truth.
|
|
34
|
+
|
|
35
|
+
## Adapter contract
|
|
36
|
+
|
|
37
|
+
Source of truth: `pi-extensions/lib/acp/backend-adapter.ts`.
|
|
38
|
+
|
|
39
|
+
| Method | Responsibility |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `routeModel` | Claim a curated id and return the backend-native id. Zero or multiple owners fail loud. |
|
|
42
|
+
| `curatedModels` | Contribute rows to the single `entwurf` provider. Non-Claude backends use a reserved prefix. |
|
|
43
|
+
| `resolveAdapterSettings` | Parse only this backend's settings into an opaque value. |
|
|
44
|
+
| `resolveLaunch` | Return command/argv; honor only the backend's explicit override. |
|
|
45
|
+
| `launchEnvDefaults` | Supply static launch environment defaults. |
|
|
46
|
+
| `ensureOverlay` | Materialize session isolation and return spawn environment overrides. |
|
|
47
|
+
| `loadCarrier` | Return a short operator carrier or `null` when the backend has no carrier. |
|
|
48
|
+
| `buildSessionMeta` | Build optional `newSession._meta` from the already-loaded carrier. |
|
|
49
|
+
| `enforceModel` | Make the requested native model authoritative before the prompt. |
|
|
50
|
+
| `configSignatureFields` | Return a stable primitive map whose changes invalidate reuse. |
|
|
51
|
+
|
|
52
|
+
`backend.ts` resolves the adapter once at turn entry. Common config never branches on
|
|
53
|
+
backend-specific keys; `adapterSettings` remains opaque until handed back to its owner.
|
|
54
|
+
A connection, model, carrier, MCP declaration, or overlay-relevant setting change must
|
|
55
|
+
change the reuse signature rather than mutate a live incompatible session.
|
|
56
|
+
|
|
57
|
+
A streaming message begins with `stopReason: "pending"`. ACP's terminal set is mapped
|
|
58
|
+
explicitly: `end_turn → stop`, `max_tokens → length`, `cancelled → aborted`; refusal,
|
|
59
|
+
exhausted turn budget, unknown, and absent reasons end as errors. The original ACP
|
|
60
|
+
reason is preserved in `rawStopReason`. Returning to a default-success branch is a
|
|
61
|
+
contract violation.
|
|
62
|
+
|
|
63
|
+
### Prompt lifecycle — who may end a turn
|
|
64
|
+
|
|
65
|
+
Bootstrap (`initialize`, `newSession`, set-model) carries 30s wall-clock bounds: those
|
|
66
|
+
steps make no model progress, so a stuck one is a dead session. **The prompt carries
|
|
67
|
+
none.** A turn ends only on a lifecycle event:
|
|
68
|
+
|
|
69
|
+
| Ending | Behavior |
|
|
70
|
+
|---|---|
|
|
71
|
+
| the agent answers | mapped through the terminal set above |
|
|
72
|
+
| the operator aborts | ACP `session/cancel` first — the agent closes its own turn (`cancelled → aborted`); process-group teardown only after a bounded grace, so an abort always returns |
|
|
73
|
+
| the child dies / stdio ends | the turn fails naming the exit status and the session-scoped stderr tail, on both the new and the reuse path |
|
|
74
|
+
|
|
75
|
+
Elapsed time is not evidence of failure, and a silent turn is not a failed turn: tool
|
|
76
|
+
use, reasoning, and provider queueing all legitimately outrun any number we could pick.
|
|
77
|
+
Suspected stalls are handled by exposing progress, never by a killing timer.
|
|
78
|
+
|
|
79
|
+
A prompt-phase failure message is also part of the contract. pi classifies a failed
|
|
80
|
+
assistant message by matching its text against `RETRYABLE_PROVIDER_ERROR_PATTERN`
|
|
81
|
+
(`@earendil-works/pi-ai` `utils/retry`), and a "transient" verdict makes it replay the
|
|
82
|
+
WHOLE prompt from a cold session up to `retry.maxRetries` times. Our own prompt-phase
|
|
83
|
+
text must never read as transient — that pairing (absolute cutoff × blind retry) is what
|
|
84
|
+
turned one long turn into four in 0.13.0. Gates: `check-acp-prompt-lifecycle` (behavior,
|
|
85
|
+
with pi's own classifier as the oracle), `check-probe-ordering` (no production prompt
|
|
86
|
+
cutoff in source).
|
|
87
|
+
|
|
88
|
+
## Shipped adapters
|
|
89
|
+
|
|
90
|
+
| Seam | Claude | Cortex Code |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| Model ids | unprefixed `claude-sonnet-5`, `claude-opus-5` | `cortex-auto`, `cortex-claude-opus-5`, `cortex-claude-sonnet-5`, `cortex-openai-gpt-5.4`; prefix stripped before set-model |
|
|
93
|
+
| Launch | bundled `claude-agent-acp`; `CLAUDE_AGENT_ACP_COMMAND` override | `cortex acp serve`; optional connection; `CORTEX_ACP_COMMAND` override; never a launch-time `-m` |
|
|
94
|
+
| Model authority | per-turn ACP set-model | per-turn ACP set-model; an unavailable curated id fails before prompt |
|
|
95
|
+
| Carrier | engraving in `_meta.systemPrompt` | no system-prompt carrier; engraving rides the first-user augment |
|
|
96
|
+
| Overlay | `CLAUDE_CONFIG_DIR` whitelist, configured-empty hooks, native memory hidden | session-scoped isolated HOME + `SNOWFLAKE_HOME`, private `cortex/mcp.json`, measured-minimum auth passthrough |
|
|
97
|
+
| MCP | explicit wire `mcpServers` | explicit declarations projected to private `mcp.json` because Cortex ignores the wire field |
|
|
98
|
+
| Backend setting | none | `cortexConnection`; env override wins and participates in the signature |
|
|
99
|
+
|
|
100
|
+
### Claude
|
|
101
|
+
|
|
102
|
+
The bundled adapter resolves before any PATH fallback. Its overlay retains only the
|
|
103
|
+
auth/runtime state required by the Claude Agent SDK and hides operator memory, hooks,
|
|
104
|
+
agents, history, and local settings. Rich project/operator context rides the first-user
|
|
105
|
+
augment; the system carrier stays short to avoid changing billing semantics.
|
|
106
|
+
|
|
107
|
+
The carrier owns its own leading boundary. A string `_meta.systemPrompt` replaces the
|
|
108
|
+
`claude_code` preset, but the SDK still prefixes a fixed identity sentence and joins the
|
|
109
|
+
two with nothing, so the loader opens every rendered carrier with one blank line. The
|
|
110
|
+
template cannot supply it — the render is trimmed so operator whitespace never drifts the
|
|
111
|
+
reuse signature. That same rendered string is what `bridgeConfigSignature` folds and what
|
|
112
|
+
`buildSessionMeta` sends; normalizing it at either hop desynchronizes the wire from the
|
|
113
|
+
signature.
|
|
114
|
+
|
|
115
|
+
`clientCapabilities` intentionally remains empty. Terminal-output widgets and nested
|
|
116
|
+
subagent transcripts are therefore not requested. Enabling either is a separate
|
|
117
|
+
rendering contract, not a capability bit flip.
|
|
118
|
+
|
|
119
|
+
### Cortex Code audit (D1–D10)
|
|
120
|
+
|
|
121
|
+
The original audit labels remain useful coordinates for source comments and gates:
|
|
122
|
+
|
|
123
|
+
| Audit | Landed contract |
|
|
124
|
+
|---|---|
|
|
125
|
+
| D1–D2 | Isolated HOME hides operator-global Claude/Cortex skills and settings; install-directory plugins remain a host fact. |
|
|
126
|
+
| D3 | Refuse `CORTEX_HOME` whenever present, including empty. |
|
|
127
|
+
| D4 | Author `autoUpdate: false`; launch only `cortex acp serve`. |
|
|
128
|
+
| D5–D6 | Pass through measured-minimum local auth; entwurf never runs or supplies authentication. |
|
|
129
|
+
| D7 | Four curated rows; enforce the stripped native id before prompt. |
|
|
130
|
+
| D8 | Credential boundary is AGENTS Hard Rule 9 and the ACP Plugin Boundary. |
|
|
131
|
+
| D9 | Project explicit MCP declarations into private `cortex/mcp.json`; wire `mcpServers` is ignored upstream. |
|
|
132
|
+
| D10 | Restore real operator HOME only for `entwurf-bridge`, so the isolated child still sees the garden store. |
|
|
133
|
+
|
|
134
|
+
Cortex containment was measured against the live CLI rather than copied from Claude:
|
|
135
|
+
|
|
136
|
+
- **Dual HOME:** the child receives an isolated `HOME` and `SNOWFLAKE_HOME`. Global
|
|
137
|
+
`~/.claude`/`~/.cortex` skills, hooks, settings, and operator `cortex/mcp.json` are
|
|
138
|
+
outside the session; explicit cwd project scope remains visible.
|
|
139
|
+
- **`CORTEX_HOME` presence refusal:** Cortex gives it precedence over
|
|
140
|
+
`SNOWFLAKE_HOME`; even an empty ambient value can make ownership ambiguous.
|
|
141
|
+
- **Auth passthrough:** only `connections.toml`, optional `config.toml`, and
|
|
142
|
+
`cortex/cache/credential_cache` are symlinked through. This narrows reachable paths;
|
|
143
|
+
it is not a read-only mount and entwurf never supplies the credential.
|
|
144
|
+
- **Launch integrity:** the overlay authors `autoUpdate: false`, preventing a CLI
|
|
145
|
+
replacement in the middle of a turn. The launch is exactly `cortex acp serve` plus
|
|
146
|
+
an optional connection; protocol initialization fails loud if a TUI was started.
|
|
147
|
+
- **MCP projection:** Cortex's ACP server ignores wire `mcpServers`, so the adapter
|
|
148
|
+
exact-writes an overlay-private `cortex/mcp.json`. Non-stdio declarations fail before
|
|
149
|
+
spawn. Only the `entwurf-bridge` entry receives the real operator HOME required to
|
|
150
|
+
see the garden store.
|
|
151
|
+
- **Carrier:** Cortex has no `_meta.systemPrompt` contract. The engraving is placed at
|
|
152
|
+
the head of the first-user augment; claiming a system-prompt engraving is false.
|
|
153
|
+
|
|
154
|
+
Cortex's bundled install-directory plugins are outside any HOME overlay and remain a
|
|
155
|
+
host fact. Also unclaimed: project-hook behavior on every host, the semantics of its
|
|
156
|
+
caller-session `_meta`, and cross-machine certification.
|
|
157
|
+
|
|
158
|
+
## 11-7. Readiness boundary
|
|
159
|
+
|
|
160
|
+
A backend can return `newSession` before its declared MCP server is callable. This was
|
|
161
|
+
observed intermittently on the Claude rail and directly on Cortex's private `mcp.json`
|
|
162
|
+
path. Neither `claude-agent-acp` 0.64.0 nor the Cortex landing adds a client-side
|
|
163
|
+
readiness fence, and `mcpServerStatus()` is not called by the common loop.
|
|
164
|
+
|
|
165
|
+
### 11-7-a/b. Instrument and first measurement
|
|
166
|
+
|
|
167
|
+
The ordering probe is an **instrument**, not a fix. It separates:
|
|
168
|
+
|
|
169
|
+
1. client request/response ordering;
|
|
170
|
+
2. backend MCP receive/reply markers;
|
|
171
|
+
3. the first prompt/tool decision;
|
|
172
|
+
4. probe admissibility (the test itself did not create the race).
|
|
173
|
+
|
|
174
|
+
Its first paired measurement was inconclusive. Do not convert that into “no race” or
|
|
175
|
+
“the adapter fixed it.” A green intermittent run measures one sample; a red run proves
|
|
176
|
+
the symptom remains.
|
|
177
|
+
|
|
178
|
+
### 11-7-c. CLI snapshot producer
|
|
179
|
+
|
|
180
|
+
The B-name-snapshot producer is admissible only when the run pins the real target
|
|
181
|
+
executable and digest, refuses ambient overrides, preserves argv/stdin/stdout/stderr and
|
|
182
|
+
exit/signal behavior, bounds NDJSON framing, scrubs only the exact probe env allowlist,
|
|
183
|
+
and timestamps snapshot/prompt hand-offs inside the downstream write callback. One
|
|
184
|
+
post-wire init snapshot may support the controlled-absence row; malformed, duplicate,
|
|
185
|
+
pre-wire, unarmed, or target-mismatched snapshots invalidate the run rather than proving
|
|
186
|
+
absence. The deterministic mutants in `probe-ordering.json` are the detailed oracle.
|
|
187
|
+
|
|
188
|
+
Current probe contract and gates:
|
|
189
|
+
|
|
190
|
+
- `check-probe-ordering` — interval/envelope and marker ordering;
|
|
191
|
+
- `check-probe-cli-shim` — CLI shim admissibility and environment boundary;
|
|
192
|
+
- `smoke-acp-ordering-probe-live` — opt-in paired observation.
|
|
193
|
+
|
|
194
|
+
Until a causal fix lands, release gates continue to exercise real MCP availability and
|
|
195
|
+
fail when the callable surface is absent. Do not add sleeps or infer readiness from
|
|
196
|
+
`newSession` latency.
|
|
197
|
+
|
|
198
|
+
## Verification
|
|
199
|
+
|
|
200
|
+
Deterministic floor:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
pnpm check
|
|
204
|
+
./run.sh check-acp-provider-surface
|
|
205
|
+
./run.sh check-acp-sdk-surface
|
|
206
|
+
./run.sh check-acp-session-reuse
|
|
207
|
+
./run.sh check-acp-stop-reason
|
|
208
|
+
./run.sh check-acp-cortex
|
|
209
|
+
./run.sh check-gate-qualification
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Live axes:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
LIVE=1 ./run.sh release-gate /path/to/scratch --cut
|
|
216
|
+
LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> \
|
|
217
|
+
./run.sh smoke-acp-cortex-live
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
The aggregate release gate is Claude-backed so a host without Cortex/Snowflake auth
|
|
221
|
+
can run the package floor. That means Cortex is **on demand**, not optional evidence:
|
|
222
|
+
a cut that changes or ships the Cortex rail must run and read its dedicated smoke.
|
|
223
|
+
Per-cut counts, digests, versions, and host observations belong in BASELINE/CHANGELOG,
|
|
224
|
+
not this standing contract.
|
|
225
|
+
|
|
226
|
+
## Open work
|
|
227
|
+
|
|
228
|
+
- causal MCP-readiness diagnosis and, only with proof, a backend-invariant fence;
|
|
229
|
+
- broader installed-host and cross-machine Cortex evidence;
|
|
230
|
+
- Codex managed native-citizen work on the reserved 0.14.0 lane—separate from ACP;
|
|
231
|
+
- persisted ACP resume/load, which is not implemented by today's in-memory reuse.
|