Skip to content

v0.13.0

Choose a tag to compare

@junghan0611 junghan0611 released this 30 Jul 03:19

Added

  • Snowflake Cortex Code joins the ACP rail as the first non-claude backend — the cortexAdapter contributed 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 reserved cortex- routing prefix; launch is cortex acp serve from PATH (+ -c <connection> via entwurfProvider.cortexConnection / ENTWURF_ACP_CORTEX_CONNECTION) with no -m pin — the model is enforced per turn through session/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 is homedir()-anchored and CORTEX_HOME outranks SNOWFLAKE_HOME, so the adapter refuses an ambient CORTEX_HOME outright (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, optional config.toml, cortex/cache/credential_cache — symlink-through, never copied), authors autoUpdate: false, and — because cortex's ACP newSession ignores the wire mcpServers param — projects the envelope-enriched explicit entwurfProvider.mcpServers into the overlay-private cortex/mcp.json, restoring the real operator HOME on the entwurf-bridge entry 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 deterministic check-acp-cortex gate (in pnpm check) plus the acp-cortex mutant lane's twelve kill-qualified claims — ten on that gate, and two cross-gate: the production overlay call site passing resolveSessionKey'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 every cortex- row can no longer go green) — and the on-demand CP2 live smoke LIVE=1 ENTWURF_ACP_CORTEX_CONNECTION=<conn> ./run.sh smoke-acp-cortex-live — a real cortex model turn delivering outbound entwurf_v2 to 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 cortex CLI 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, and cortex acp serve is spawned only when a turn actually selects a cortex- 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 deterministic check-acp-cortex gate 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 without LIVE=1, without cortex on PATH, 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 newSession returns — 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, so check-probe-ordering pins the sequence against backend.ts source, 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, ts derives from a single clock read, and per (runId, pid) writer the raw append order must have strictly increasing seq and 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-wire says 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 at CLAUDE_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 9f1c7dc9e1fa77103e29a6f1884af7759e1595eb passed exact-SHA GitHub Actions run 30505001694: check, install-surface, and artifact-consumer all success. That run is also the third-party half of the optionality claim above, at the strength its sources actually carry: .github/workflows/ci.yml provisions only checkout, pnpm, and Node 24 — it installs no Cortex CLI and supplies no Snowflake auth — and the required Linux artifact-consumer job ran the candidate inside a clean node:24-bookworm container 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, including check-gate-qualification at 111/111 committed mutants killed (the acp-cortex lane contributing twelve). Then LIVE=1 ./run.sh release-gate /tmp/entwurf-release-gate-0.13.0.drnRyR completed 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-live passed 23/23 — a deliberate rerun after the resolveSessionKey overlay-scope repair, so the shipped claim no longer rests on the earlier CP2 run's code. check-pack-install enumerated the exact six curated rows (claude 2 + cortex 4) out of the installed package's own model list, and ENTWURF_REQUIRE_DOCKER=1 ./run.sh check-install-container consumed candidate sha256=63342aa8a144011dee86ebea8f0b778c7860e54dc0f1c710438983c679e8af87 on node: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 envelope origin=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 record 20260729T204101-7aaa6f remains on disk as corroboration.
  • Deferred to make as a release-blocking tag gate: the preserved exact 0.13.0 candidate must be installed into a fresh temporary root and drive one cold entwurf/cortex-claude-sonnet-5 turn 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 to make as 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 27e5f0928e2fb52654db35367e343c5a5b5414d5 passed exact-SHA CI run 30510354126: check, install-surface, artifact-consumer all success.
  • One preserved candidate was accepted without repack: junghanacs-entwurf-0.13.0.tgz, sha256=dc9da57df525a2952efde975292ea47d9048f8d31e0b75318de3eba893d4d563, consumed by the checkout-invisible node:24-bookworm container (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_PATH unset, pi agent dir / settings / writable XDG_* isolated, CORTEX_HOME absent — and drove one cold entwurf/cortex-claude-sonnet-5 turn 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.