Skip to content

CL-6324: deployAtHead on the code-sourced adoption seam - #97

Closed
TheGreatAxios wants to merge 7 commits into
cl-6324-vendored-seamsfrom
cl-6324-deployathead-convert
Closed

CL-6324: deployAtHead on the code-sourced adoption seam#97
TheGreatAxios wants to merge 7 commits into
cl-6324-vendored-seamsfrom
cl-6324-deployathead-convert

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Contributor

Stack: #87#96this. Also carries #90's four commits (@corbits/agent-runtime), cherry-picked clean.

What this does

packages/folded-runs' deployAtHead is cut over to the code-sourced seam. The in-memory single-step definition it built and handed to deploySingleStepAtHead is deleted, not gated — that front went away with the on-disk workflow.json, and a deployment's definition is now whatever its own pinned source closure evaluates to.

The new path, shared by launchFoldedRun and wakeFoldedRun:

  1. Render — the run's deploy-time config (trigger address, system prompt, resolved inference chain, tool-package pins, credential bindings, shape) becomes an AgentRuntimeConfig literal inside a per-run @corbits/agent-runtime package. The config has to be in the bytes: the approval probe and the run child evaluate the entry independently and the child refuses a definition whose recomputed wire hash differs — and every one of those fields is in the hashed preimage.
  2. Commit — the tree lands in the run's own workflow-kind definition asset (resolved workflow_run → workflow_definition.assetId) on refs/heads/runs/<runId>. Reuse, not a second asset: one asset backs many runs, so each run gets a ref, and the commitSha is the pin.
  3. DeploydeployAdoptedWorkflowFromSource (CL-6324: restore the onBodyFailure delta (plus its projection) and add an adopting code-sourced deploy front #96), the only front a folded run can use: its anchor row is minted before any deployment attaches, so the inserting front collides on the primary key and the prepared front needs an exclusive allocation it never has.

The credential cipher is threaded instead of a pre-built delivery — the front resolves the material itself from the deployed definition's own bindings. buildCredentialDelivery stays only for the credential: use grants the run's principal needs in its own grants.json.

Section mode

The step's input selector became the config's mode: step (with an optional literalInput — the workbench host's CL-6164 pin) or section with a per-turn timeout. Phase 1.3 changes a caller's argument, never a branch inside deployAtHead. Section mode authors onBodyFailure: "continue", asserted both on the definition and through the live→inert projection.

hubPublicKey leaves FoldedRunsDeps: the adopting front does not take it and nothing else in the folded-run path read it.

Results

  • Typecheck: 50 → 24. All 28 deploySingleStepAtHead errors are gone. The 24 that remain are the apps/sidecar rows already on the inventory's conversion table (projection.definition, createWorkflowSpawnChild, SpawnTimeEnv.referencedDefinitionHashes, RunWorkflowChildBindings.workflowDefinitionRepoId) — untouched here by design.
  • packages/folded-runs: 44 pass / 0 fail. packages/chat: 509 pass / 0 fail. packages/agent-runtime: 29 / 0. apps/hub: 130 / 0. packages/webhook-triggers: 29 / 0.
  • Repo-wide bun test fail count is 552 both before and after (pre-existing root-run mock.module interference; pass count 4238 → 4246).
  • Lint: 0 errors.

Honest remainders

  • Nothing has executed this end to end. The two sidecar prerequisites are untouched: nothing produces CLOSURE_PACKAGE_DIR and no WorkflowProbeExecutor is wired, so every probe still answers workflow.probe.error. Fakes prove the round trip; a real deploy needs conversion step 2.
  • Defect surfaced, not fixed. Rendering parses the config, which is the first time a folded run's credential bindings meet the platform's CredentialBinding schema. apps/hub/src/mcp-credential-bindings.ts mints handle: "mcp:<slug>", and ToolCredentialHandle is /^[a-z0-9][a-z0-9._-]*$/ — no colon. Every MCP-pinned launch would now fail closed at render time. Either the handle shape changes here (and with it the env.credentials.resolve("mcp:<slug>") key @corbits/mcp-tools uses) or upstream widens the grammar. The folded-runs test fixture uses a conforming handle; the gap is written up in docs/revendor-inventory.md.
  • The rendered package pins @corbits/agent-runtime at workspace:*, which only resolves inside this monorepo's closure. Correct for how the sidecar materializes it today; revisit if the runtime is ever published.

Covers the deploy-time config contract (arktype-parsed, env-delivered) and
the two definition shapes its mode selects: the folded unbounded step and
the per-turn onTrigger section.
…deploy

The workflow.json retirement makes source-ref the only deploy lineage: a
deployment's definition is evaluated from its own pinned code closure and
re-verified against the hub-approved wire hash. Workbench had no code-sourced
package to deploy, so this adds the one every agent run will share.

The bytes are static and versioned; everything per-run — mailbox, system
prompt, inference chain, tool package pins, credential bindings — arrives as
deploy-time config in the child's environment and is parsed at the entry
module's boundary. The config's mode selects the shape, so the deploy front
keeps one parameter set and never branches on step-vs-section.
The first shape here read the config from the child's environment. That
cannot work: the approval probe and the run child each evaluate the entry
module independently, and the hashed projection covers the trigger address,
the system prompt, the (provider, model) pairs, the tool package pins, and
the credential bindings — every field of the config. A config read from
outside the closure diverges between the two evaluations and fails the
re-verify barrier closed. There is also nowhere to read one from: no source
variant carries an overlay, the deploy frame carries no config bag, and the
probe frame carries no environment at all.

So the config becomes the bytes. renderAgentRuntimeSourceTree emits a thin
per-run package that pins this versioned one and calls the builder with the
run's config as a literal, ready to commit into a workflow-kind asset and
deploy as source at a commitSha — the only source variant cheap enough to
mint per run.
Red/green coverage for the conversion (CL-6324): deployAtHead renders the
run's per-run workflow source package, commits it into the run's own
definition asset on a per-run ref, and deploys the resulting commitSha
through the adopting code-sourced front against the pre-minted anchor.

Covers the whole round trip -- the committed tree's shape, the config
rendered into the deployed bytes (address, system prompt, model pairs,
tool pins, credential bindings, mode), the adopted deploy's frame, the
wake path taking the same route, a caller-supplied section mode riding
through untouched, and a run whose definition has no workflow-kind asset
failing before any deploy. Section mode is proven to author
onBodyFailure "continue" and to keep it through the live->inert
projection.

Fails against the in-memory synthesize-and-deploy path, which neither
renders bytes nor touches an asset.
…nition

Cuts deployAtHead over to the code-sourced seam. The in-memory
single-step definition it used to build and hand to deploySingleStepAtHead
is gone -- that front was retired with the on-disk workflow.json, and a
deployment's definition is now whatever its own pinned source closure
evaluates to.

The run's deploy-time config (trigger address, system prompt, resolved
inference chain, tool package pins, credential bindings, shape) is
rendered into a per-run @corbits/agent-runtime package, committed into
the run's OWN definition asset on refs/heads/runs/<runId>, and deployed
by pinning that commitSha. The config has to be inside the bytes: the
approval probe and the run child evaluate the entry independently and the
child refuses a definition whose recomputed wire hash differs, and every
one of those fields is in the hashed preimage.

The deploy goes through deployAdoptedWorkflowFromSource, the only front a
folded run can use -- its anchor workflow_run row is minted before any
deployment attaches to it, so the inserting front collides on the primary
key and the prepared front needs an exclusive allocation it never has.
The credential cipher is threaded instead of a pre-built delivery, since
the front resolves the material itself from the deployed definition's own
bindings; buildCredentialDelivery stays only for the credential: use
grants the run's principal needs in its own grants.json.

The step's input selector becomes the config's mode: `step` (with an
optional literalInput, the workbench host's CL-6164 pin) or `section`
with a per-turn timeout, so the Phase 1.3 swap changes a caller's
argument rather than a branch here. Section mode authors onBodyFailure
"continue" so one failed turn re-arms the section instead of retiring the
run.

hubPublicKey leaves FoldedRunsDeps: the adopting front does not take it,
and nothing else in the folded-run path read it.
Records the conversion in the CL-6324 inventory: what deployAtHead now
does (render, commit into the run's own definition asset on a per-run
ref, deploy the pinned commit through the adopting front), why the asset
is reused rather than minted per deploy, and how the step/section shape
became config data.

Also records what still blocks EXECUTION -- CLOSURE_PACKAGE_DIR and the
sidecar's WorkflowProbeExecutor, the remaining typecheck failures -- and
a defect the conversion surfaced: apps/hub mints MCP credential handles
("mcp:<slug>") that the platform's ToolCredentialHandle grammar rejects,
which now fails closed at render time because the config is finally
parsed.
@TheGreatAxios

Copy link
Copy Markdown
Contributor Author

Landed via the stack tip: PR #108 (merge fbf0852) contains this branch's commits in full.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant