Skip to content

feat(runtime): mounted-resource manifest + caller selection receipts on LoopResult#362

Merged
drewstone merged 1 commit into
mainfrom
feat/rt-353-mount-provenance
Jun 22, 2026
Merged

feat(runtime): mounted-resource manifest + caller selection receipts on LoopResult#362
drewstone merged 1 commit into
mainfrom
feat/rt-353-mount-provenance

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

What

Adds a generic, domain-free observability primitive to the driven-loop run output. LoopResult gains provenance:

  • mounts — a manifest of what was mounted into the run's boxes. Each entry: path, sha256, bytes, source. Pure provenance — no domain semantics.
  • selectionReceipts — one receipt per scored candidate: candidateIndex, selected, score?, reason?, and selector ('caller' | 'driver' | 'default'). Answers "why did THIS one win?".

This makes a run auditable after the fact ("what exactly was this agent given, and why did the kernel pick this output?") without the kernel attaching any meaning to the data.

How

Mounts ride the existing prepareBox seam (src/runtime/types.ts). prepareBox's ctx gains a recordMount recorder so the caller — which owns the bytes it writes into the box — declares each mount. The kernel never reads box contents; it only collects what the caller records. The recorder is threaded through both box-acquisition paths:

  • the fresh-box path (createSandboxForSpec in run-loop.ts)
  • the lineage path (createSandboxLineage in sandbox-lineage.ts, covering fresh start + fork branches)

Receipts are assembled at finalize from the iterations and the resolved winner, attributing the selector that ran (caller-supplied selectWinner, driver-authored selectWinner, or the kernel's default argmax). Only the default selector gets a kernel-authored reason; caller/driver winners run by their own rationale, so the kernel leaves reason unset rather than inventing one. Errored or output-less iterations were never selectable, so they get no receipt.

Safety / scope

Additive and optional. When nothing is recorded the manifest is an empty array. Shared box helpers used outside runLoop (sandbox-act, detached-turn) pass no recorder and get a no-op, so the prepareBox ctx shape is always satisfied and no behavior changes on those paths.

Verification

  • pnpm run build green (dist regenerated)
  • pnpm run typecheck green (incl. typecheck:examples)
  • pnpm test green — 107 files, 1049 passed / 1 skipped
  • pnpm run lint green
  • pnpm run docs:freshness OK; docs/api/* regenerated via TypeDoc and committed so the freshness gate stays green
  • New focused test src/runtime/run-loop.provenance.test.ts (4 cases): mount manifest surfaced, empty manifest when nothing mounted, default-selector receipts with scores + winner flag across a fanout, and an errored iteration omitted with a caller-selector attribution.

Closes rt#353.

…on LoopResult

Add a domain-free observability primitive to the driven-loop run output:
`LoopResult.provenance` carries a manifest of what was mounted into the run's
boxes (each entry path/sha256/bytes/source) and one selection receipt per
scored candidate (which iteration the selector chose + score + why + selector
identity). Pure provenance for run auditability — nothing in the kernel
branches on it.

Mounts are populated from the existing prepareBox seam: `prepareBox`'s ctx
gains a `recordMount` recorder so the caller (which owns the bytes it writes)
declares each mount; the kernel never reads box contents. The recorder is
threaded through both box-acquisition paths — the fresh-box path
(createSandboxForSpec) and the lineage path (createSandboxLineage). Receipts
are assembled at finalize from the iterations and the resolved winner,
attributing the caller/driver/default selector.

Additive and optional: when nothing is recorded the manifest is an empty array,
and shared box helpers used outside runLoop (sandbox-act, detached-turn) pass no
recorder and get a no-op.

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Auto-approved PR — 969e8cb8

Blanket team auto-approval is enabled for this reviewer service.
The full PR reviewer audit still runs separately and will publish findings if it detects issues.

tangletools · auto-approval · reason: blanket_auto_approve · 2026-06-22T13:38:28Z

@drewstone drewstone merged commit 21659a9 into main Jun 22, 2026
1 check passed
@drewstone drewstone mentioned this pull request Jun 22, 2026
drewstone added a commit that referenced this pull request Jun 22, 2026
…provenance + artifact lifecycle (#363)

Bundles the build-phase PRs landed since 0.72.0:
- #360 max-live-workers concurrency cap + explicit worker metering opt-in
- #362 mounted-resource manifest + caller selection receipts on LoopResult
- #361 artifact registry + marginal-lift ablation (rt#267 phase 1, ./lifecycle)
- #359 preserve partial events on abort via typed SandboxRunAbortError

Bumps package.json to 0.73.0, pins docs/canonical-api.md to 0.73.0, and adds
decision-table rows for run provenance (result.provenance.mounts/selectionReceipts)
and the artifact-lifecycle ablation (measureMarginalLift / ArtifactRegistry, /lifecycle).
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.

2 participants