v0.13.0
Added
- Snowflake Cortex Code joins the ACP rail as the first non-claude backend — the
cortexAdaptercontributed by hvkiefer (PR #40), landed together with the revisions the CP0 live audit of 2026-07-29 measured against Cortex Code v1.1.52 (docs/acp-backend-rail.md§11-8 records the ten defects D1–D10 and the agreed contract; the deltas are drift repair, not contributor error). As landed: the curated surface is the GLG-decided 4-row set (cortex-auto,cortex-claude-opus-5,cortex-claude-sonnet-5,cortex-openai-gpt-5.4) riding real pi-ai registry bases behind the reservedcortex-routing prefix; launch iscortex acp servefrom PATH (+-c <connection>viaentwurfProvider.cortexConnection/ENTWURF_ACP_CORTEX_CONNECTION) with no-mpin — the model is enforced per turn throughsession/set_config_option("model", <native id>), the same wire call as claude, so a curated id the running cortex no longer serves fails loud before the prompt. Containment is a session-scoped dual-HOME overlay: cortex's config/skill/hook surface ishomedir()-anchored andCORTEX_HOMEoutranksSNOWFLAKE_HOME, so the adapter refuses an ambientCORTEX_HOMEoutright (empty string included), runs the child under an isolated HOME (global-scope leak measured to zero; explicit cwd project scope retained), passes through only the measured-minimum auth (connections.toml, optionalconfig.toml,cortex/cache/credential_cache— symlink-through, never copied), authorsautoUpdate: false, and — because cortex's ACPnewSessionignores the wiremcpServersparam — projects the envelope-enriched explicitentwurfProvider.mcpServersinto the overlay-privatecortex/mcp.json, restoring the real operator HOME on theentwurf-bridgeentry alone so a cortex sibling sees the real garden (an isolated-HOME bridge measured an empty citizen roster); non-stdio entries fail loud before spawn. Cortex is system-prompt-carrier-less: the operator engraving rides the first-user augment. Coverage: the deterministiccheck-acp-cortexgate (inpnpm check) plus theacp-cortexmutant lane's twelve kill-qualified claims — ten on that gate, and two cross-gate: the production overlay call site passingresolveSessionKey's authoritative value (check-acp-session-reuse) and the real compiled provider entry registering both adapters' curated rows (check-acp-provider-surface, so an entry that silently dropped everycortex-row can no longer go green) — and the on-demand CP2 live smokeLIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live— a real cortex model turn delivering outboundentwurf_v2to a seeded peer as itself, plus overlay disk facts and process-group reclaim (an MCP-configured cortex child ignores stdin EOF) — deliberately outside the claude-only aggregate LIVE floor, so a host that runs no cortex cannot redden a claude release; that is a wiring decision, and a cut shipping cortex still owes a deliberate run of it. - A host that does not run Cortex is unaffected by this release. The external
cortexCLI is not an npm dependency, and neither package install nor provider registration looks for the executable: the four curated rows are enumerated deterministically from the compiled provider entry, andcortex acp serveis spawned only when a turn actually selects acortex-model — so selecting one on a host without Cortex fails loud at that turn rather than degrading install or the rest of the provider. The deterministiccheck-acp-cortexgate runs on fake/injected seams and needs neither the CLI nor Snowflake auth; the aggregate release floor contains no Cortex LIVE step; and the dedicated smoke honest-skips withoutLIVE=1, withoutcortexonPATH, or without a connection on the adapter seam. Rows are deliberately not hidden by PATH detection — that would make the provider surface differ per host and dissolve the exact-six-row fence — so an explicit operator enable/disable control remains a separate future contract, not a silent behaviour of this cut. - The ACP ordering probe lands as a gated instrument, and the readiness question it exists to answer stays open. The rail's open question — whether MCP tool availability precedes what
newSessionreturns — had no observable signal, so the probe injects a controlled fixture startup delay and reads control + D1 + D2 paired runs off one shared NDJSON axis instead of reconstructing order from separate logs with drifting clocks. A raw client may stand in for the backend only while a gate holds it to the same calls, arguments, and order, socheck-probe-orderingpins the sequence againstbackend.tssource, attributes every failure to its wire phase, drives the probe-mode fixture as a real child process, types the event log at its door, and replays the paired-verdict truth table through the pure classifier. The log's door is a gate too: the envelope belongs to the writer,tsderives from a single clock read, and per(runId, pid)writer the raw append order must have strictly increasingseqand a non-regressing clock — a JSON-valid line with an unknown marker, a broken sort axis, or a payload the classifier cannot judge takes the INVALIDATED path instead of moving a verdict. The runner now holds the child open past the turn until the marker lands, the child exits, or a deadline anchored on the fixture's own delay markers passes, and only a deadline close lets a missing marker read as evidence; every intervention reports ordering and callability as two axes so a settled comparison is not buried by an unsettled verdict, and each ordering value is named for the comparison it is (prompt-request-ahead-of-wiresays we issued the request first, never that the server failed to wait). The delta-B name oracle cannot be the model, so that seam is a CLI shim atCLAUDE_CODE_EXECUTABLE: the consumer half (target preconditions by key presence, absolute/regular/executable/no-script-suffix assertions, path+sha256 roster pinning with a post-pair re-hash, snapshot channel doors, receive-axis single-prompt binding, structural-vs-reading severity split) and then the producer shim itself both land kill-qualified. No readiness finding is claimed. The first paired run under the door contract produced 57 events with zero malformed lines, so the parser is calibrated rather than merely strict, and rail §11-7-b carries the numbers — but the verdict is inconclusive, and an inconclusive verdict is not "nothing wrong". Artifacts predating the window protocol re-parse as INVALIDATED and remain forensic records only.
Verification
- Pre-version landing HEAD
9f1c7dc9e1fa77103e29a6f1884af7759e1595ebpassed exact-SHA GitHub Actions run 30505001694:check,install-surface, andartifact-consumerall success. That run is also the third-party half of the optionality claim above, at the strength its sources actually carry:.github/workflows/ci.ymlprovisions only checkout, pnpm, and Node 24 — it installs no Cortex CLI and supplies no Snowflake auth — and the required Linuxartifact-consumerjob ran the candidate inside a cleannode:24-bookwormcontainer and passed. That is a workflow-configuration fact plus a passing consumer run; it is not a probe of the runner image's contents. - The prepared tree passed an independent
pnpm check, includingcheck-gate-qualificationat 111/111 committed mutants killed (theacp-cortexlane contributing twelve). ThenLIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.13.0.drnRyRcompleted all green: MUST PASS=17 FAIL=0 SKIP=0 and BEHAVIOR PASS=1 FAIL=0, EXIT=0. Full log:/tmp/entwurf-release-gate-0.13.0.drnRyR/release-gate.log; per-step artifacts are preserved inside it. - Cortex acceptance on the landing tree (2026-07-30, Linux/thinkpad, Cortex Code v1.1.52, connection on the adapter seam): the on-demand
smoke-acp-cortex-livepassed 23/23 — a deliberate rerun after theresolveSessionKeyoverlay-scope repair, so the shipped claim no longer rests on the earlier CP2 run's code.check-pack-installenumerated the exact six curated rows (claude 2 + cortex 4) out of the installed package's own model list, andENTWURF_REQUIRE_DOCKER=1 ./run.sh check-install-containerconsumed candidatesha256=63342aa8a144011dee86ebea8f0b778c7860e54dc0f1c710438983c679e8af87onnode:24-bookworm(id=sha256:fcd0f74fb415c752…,repoDigest=node@sha256:5711a0d445a1af54…). - Cross-rail live round trips are operator-session evidence, not a gate (2026-07-29, same implementation set): a Cortex resident used the host pi citizen's garden id rather than inventing one —
agentId=entwurf/cortex-claude-sonnet-5,backend=pi, reply envelopeorigin=pi-session,replyable=true— and exchanged real turns with native Claude Code (mailbox drain), pi native (control socket), and pi ACP Claude Sonnet (control socket). The record20260729T204101-7aaa6fremains on disk as corroboration. - Deferred to
makeas a release-blocking tag gate: the preserved exact 0.13.0 candidate must be installed into a fresh temporary root and drive one coldentwurf/cortex-claude-sonnet-5turn from those installed bytes — unique nonce, exit 0, candidate SHA-256 unchanged before and after, resolved installed package root recorded. Until it runs, installed-artifact evidence and real-Cortex evidence have never met in one execution; a RED there stops the cut before the tag. Prepared-HEAD exact-SHA CI and preserved-candidate container acceptance remain deferred tomakeas usual.
Release acceptance for this tag
Recorded at cut time, after the changelog body above was committed — the last bullet's
deferred gate is now closed:
- Prepared HEAD
27e5f0928e2fb52654db35367e343c5a5b5414d5passed exact-SHA CI run 30510354126:check,install-surface,artifact-consumerall success. - One preserved candidate was accepted without repack:
junghanacs-entwurf-0.13.0.tgz,sha256=dc9da57df525a2952efde975292ea47d9048f8d31e0b75318de3eba893d4d563, consumed by the checkout-invisiblenode:24-bookwormcontainer (id=sha256:fcd0f74fb415c752…,repoDigest=node@sha256:5711a0d445a1af54…). - The candidate-installed Cortex gate passed. Those exact candidate bytes were installed into a fresh temporary root — repo checkout and global package excluded by resolved-path assertion,
NODE_PATHunset, pi agent dir / settings / writableXDG_*isolated,CORTEX_HOMEabsent — and drove one coldentwurf/cortex-claude-sonnet-5turn that returned its unique nonce exactly, exit 0, with the candidate's SHA-256 unchanged before and after. Installed-artifact evidence and real-Cortex evidence have now met in one execution.
Thanks to @hvkiefer for the Cortex backend (PR #40); the
implementation commit preserves their authorship and this release credits them as a
contributor to the cut.