Assay-Runner Boundary And Extraction Map

July 27, 2026 ยท View on GitHub

Internal Phase 2A reference. This page defines the current Assay-Runner boundary candidate after the delegated Linux/eBPF Phase 1 proof. It is not a repository-split plan and does not create a released product surface.

Phase 1 proved that Assay can produce deterministic measured-run bundles on a delegated Linux/eBPF host. Phase 2A keeps that proof reviewable while the runner boundary is consolidated. Extraction is only possible after the boundary is stable; it is not the goal of this document.

Core Rule

Assay remains the owner of artifact semantics.

Runner may own measured execution, layer capture orchestration, cgroup-scoped process placement, and correlation mechanics. Runner must not become an independent authority for what an Assay evidence artifact means.

Implications:

  • artifact schemas stay owned by Assay core/reference docs
  • archive verification stays an Assay responsibility
  • runner-generated bundles must remain verifiable through Assay evidence semantics
  • runner projection or capability diff may consume artifacts, but must not redefine them

Boundary Table

LayerStays In Assay CoreRunner Candidate OwnsShared Contract
Archive semanticsmanifest shape, digest semantics, bundle verificationarchive assembly for measured runsarchive manifest schema and run-id consistency
Observation healthfield set, status values, strict health semanticscomputing health from capture resultsobservation-health.v0
Capability surfaceartifact schema, evidence categories, deterministic set serializationderiving the surface from normalized runner eventscapability-surface.v0
Correlation reportschema, status values, ambiguity semanticsproducing bindings from SDK/policy/kernel windowscorrelation-report.v0
Kernel monitor and eBPFmonitor implementation, BPF programs, stats modelselecting capture window, cgroup scope, and normalizer filters for runner proofmonitor event schema, drop accounting, cgroup health
Policy decisionsMCP/proxy policy semantics and decision event shapeincluding policy logs in measured-run archivespolicy event schema and tool_call_id extraction
SDK eventsnormalized SDK event schemashim-specific event adapters and fixture captureassay.runner.sdk_event.v0
Acceptance fixturesfixture contract and delegated acceptance semanticsfixture programs and control paths for runner prooffixture v0 contract
CI disciplinerepository-required checks and ordinary CIdelegated proof lane selection and run recordingCI lane contract
Operational runbooksecurity posture and hosted runner policydelegated host procedure and failure triagedelegated runbook
Capability diffTrust Basis / Harness projection semanticsmeasured-run capability input bundlesfuture Phase 2B diff contract

Dependency Direction

Allowed dependency direction:

Assay core semantics
  -> runner measured execution
  -> harness/report projection

Forbidden direction:

runner implementation detail
  -> redefines Assay artifact meaning

Runner code may depend on Assay core crates or exported contracts. Assay core must not depend on a publishable runner crate for artifact interpretation. If a core crate needs a helper currently living in runner-spike code, move the helper to the appropriate core module first and cover that move with tests.

Additional extraction rule:

  1. If a runner candidate module contains artifact schema or data-structure definitions needed by both Assay and a future runner repository, those definitions must migrate to an Assay-owned shared contract before extraction. The runner may fill those structures, but it may not be the sole owner of their meaning across a repository boundary.

Current In-Repo Ownership

The current spike surfaces remain in Rul1an/assay:

PathCurrent roleBoundary classification
crates/assay-runner-schema/publish-disabled v0 schema data structures (Phase 2D Slice 1)shared contract owned by the Runner extraction line; the data half of the runner v0 contract layer
crates/assay-runner-schema/src/health.rsobservation-health data structures and validationshared contract; hosted by the schema crate since Slice 1
crates/assay-runner-schema/src/surface.rscapability-surface data structures and deterministic set storageshared contract; hosted by the schema crate since Slice 1
crates/assay-runner-schema/src/correlation.rscorrelation-report data structures and validationshared contract; hosted by the schema crate since Slice 1
crates/assay-runner-schema/src/sdk_event.rsSDK event schema string and SdkLayerEvent shapeshared contract; hosted by the schema crate since Slice 1
crates/assay-runner-schema/src/archive_manifest.rsarchive manifest schema string, archive file path constants, ArchiveFile, ArchiveManifestshared contract (manifest semantics half of the archive boundary conflict); hosted by the schema crate since Slice 1
crates/assay-runner-core/publish-disabled runner mechanics crate (Phase 2D Slice 2)runner candidate orchestration, archive assembly, and layer normalizers; consumes assay-runner-schema for v0 types; the mechanics half of the runner v0 contract layer
crates/assay-runner-core/src/run.rsmeasured command execution, run id, archive handoffrunner candidate orchestration; hosted by the core crate since Slice 2
crates/assay-runner-core/src/kernel.rskernel capture normalization and health applicationrunner candidate mechanics using Assay monitor semantics; hosted by the core crate since Slice 2
crates/assay-runner-core/src/policy.rspolicy log normalization and binding into the archiverunner candidate mechanics using Assay policy semantics; hosted by the core crate since Slice 2
crates/assay-runner-core/src/sdk.rsSDK ndjson parsing and SDK/policy mismatch markingrunner candidate mechanics; consumes SdkLayerEvent/SDK_EVENT_SCHEMA from the schema crate; hosted by the core crate since Slice 2
crates/assay-runner-core/src/archive.rsrunner archive assembly and writingrunner candidate mechanics; consumes manifest types from the schema crate; hosted by the core crate since Slice 2
crates/assay-runner-spike/removed legacy alias crate (post-Slice 6B cleanup)removed after proving no in-workspace consumers. Historical extraction docs may still reference the alias wrapper as pre-removal context
crates/assay-runner-linux/publish-disabled Linux platform adapter crate (Phase 2D Slice 3)runner Linux placement primitives only; currently hosts cgroup v2 placement (CgroupManager, SessionCgroup). Phase 2D Slice 4 confirmed this boundary: the eBPF monitor adapter and the kernel programs stay in their existing Assay-owned crates (see below); macOS/Windows adapters are out of scope until separate platform spikes open under platform-and-extraction-readiness.md
crates/assay-runner-linux/src/cgroup.rscgroup v2 placement primitiveshosted by the Linux platform crate since Slice 3 (previously at crates/assay-cli/src/cgroup.rs)
crates/assay-cli/src/cgroup.rsremoved in Phase 2D Slice 3the placement primitives moved to assay-runner-linux; crates/assay-cli/src/cli/commands/runner_spike.rs now imports CgroupManager/SessionCgroup from assay_runner_linux
crates/assay-monitor/monitor reader, stats, event decodingShared Assay measurement substrate. Used by the runner candidate (assay-runner-core consumes MonitorStatsSnapshot) AND by Assay's own assay monitor standalone CLI command. Slice 4 explicitly confirms this stays Assay-owned and is not relocated into assay-runner-linux, because moving it would break the non-runner Assay consumers
crates/assay-ebpf/eBPF programsAssay-owned Linux kernel program substrate. Loaded by assay-monitor. Slice 4 explicitly confirms this stays Assay-owned; it is the kernel-side counterpart of the shared measurement substrate, not a runner-private adapter
crates/assay-cli/src/cli/commands/runner_spike.rsTemporary runner composition layer (until Phase 2D Slice 6). Hidden CLI command that wires together assay-runner-schema (data), assay-runner-core (mechanics), assay-runner-linux (cgroup), and assay-monitor (events).This composition lives in assay-cli because no public Runner entrypoint exists yet. Slice 6 (Assay-consumes-Runner-as-external) decides whether a public runner entrypoint replaces this composition or whether assay-cli continues to host it across the extraction boundary. Until then, this file is treated as a runner-candidate-adjacent surface in the lane-check classifier (Gate.ALL via the explicit-paths rule)
crates/assay-evidence/**evidence artifact verification and existing bundle semanticsAssay core artifact semantics
crates/assay-core/**MCP, policy, runtime, and shared decision semanticsAssay core semantics
runner-fixtures/gemini-google-genai/Gemini Python google-genai second-runtime fixture package (Phase 2D Slice 5A)runner-owned fixture asset structured as a separate package; moved from tests/fixtures/runner-spike/gemini-google-genai/ so the fixture boundary is visible at the top of the tree, mirroring an eventual extracted runner repo layout
runner-fixtures/openai-agents/S5 OpenAI Agents (@openai/agents) accepted-fixture package (Phase 2D Slice 5B)runner-owned fixture asset; moved + renamed from tests/fixtures/runner-spike/openai-agents-js/ (the -js language suffix dropped because the fixture identity is the runtime). The SDK source-identity emitted by fixture-agent.js was renamed from openai-agents-js-fixture to openai-agents-fixture in the same slice to keep the package boundary, directory name, and recorded evidence consistent
tests/fixtures/runner-spike/deterministic shared cross-runtime helpers (kernel-only fixture, mcp-policy-agent, mcp_file_server, sdk-event-wrapper, sdk-policy-agent); both runtime fixtures (S5 OpenAI Agents and Gemini) moved out to runner-fixtures/ in Slices 5A and 5Bcandidate runner fixtures under shared fixture contract; a later Slice 5C may relocate the shared helpers themselves if a clean package boundary for them emerges
scripts/ci/runner-spike-*.shacceptance and determinism wrapperscandidate runner gates under shared CI lane contract
.github/workflows/runner-spike-delegated.ymlmanual delegated Linux/eBPF workflowrepository-owned proof lane
docs/reference/runner/*.mdPhase 2A contractsshared internal contracts
docs/ops/ASSAY-RUNNER-DELEGATED-RUNBOOK-2026-05-21.mddelegated host runbookshared operational contract

Active Boundary Conflicts

These are the known hard cases. Do not resolve them by moving code first and explaining the ownership later.

ConflictWhy it is hardCurrent rule
archive.rsthe runner assembles archives, but manifest shape, digest meaning, and verification are artifact semanticsFully resolved by Phase 2D Slices 1 + 2: manifest schema constants, ArchiveFile, and ArchiveManifest moved to assay-runner-schema in Slice 1; assembly (RunnerSpikeArchive, RunnerSpikeArchiveError, write) moved to assay-runner-core in Slice 2. Archive verification continues to use the existing Assay evidence path; the runner side no longer mixes assembly mechanics with manifest semantics ownership
health.rs and observation-health.jsonthe runner measures drops and cgroup health, but kernel_layer=complete and related status meanings are Assay claimsAssay owns the status definitions; runner computes whether a measured run satisfies them
telemetry-versus-evidence filtersthe runner implements event-type and path filters, but deciding what counts as evidence is artifact semanticsAssay owns the evidence taxonomy and rationale; runner owns the implementation and diagnostics
tool_call_id fallback semanticsfallback would change correlation mechanics and correlation-report.json ambiguity semantics at the same timev0 clean correlation and the first Phase 2B capability-diff contract require stable tool-call ids; call-id-less support is out of scope until a separate fallback contract exists

If a future PR touches one of these conflicts, reviewers should require a contract update or an explicit statement that the PR does not change the boundary.

What Must Never Move Alone

The following cannot be moved to a separate runner repository without an explicit shared-contract replacement:

  • artifact schema definitions
  • archive verification semantics
  • observation-health status meanings
  • telemetry-versus-evidence filter rationale
  • CI lane decision table
  • fixture v0 contract
  • delegated proof acceptance note

If extraction happens later, these must either stay in Assay core or become a versioned shared contract package consumed by both repositories.

Extraction Readiness Criteria

Do not create a separate Assay-Runner repository until all of the following are true:

CheckReady when
Contract stabilityartifact, fixture, CI-lane, and boundary contracts have no semantic churn for one consolidation window
CI classificationrunner-impacting changes can be classified by the CI lane contract without discussion
Delegated proof recordingdelegated workflow run URL, commit SHA, selected gate, and result are recorded on runner-impacting PRs
Shared schema ownershipassay.runner.*.v0 schemas have an owner and release/versioning path importable by both Assay and any future runner repo
Dependency directionno Assay core crate depends on a publishable runner crate for artifact interpretation
CLI couplingrunner orchestration does not require private assay-cli types or hidden command internals across a repo boundary
Cgroup APIcgroup placement uses a stable API rather than assay-cli-local helpers
Monitor APIrunner capture can depend on a stable monitor API without copying monitor/eBPF internals
Archive verificationrunner archives verify through Assay evidence semantics without copying verification logic
Boundary API stabilitytwo consecutive minor releases, or an equivalent internal stabilization window, pass without breaking the boundary API
External consumerat least one non-spike consumer can read the runner bundle contract without depending on spike implementation details
Call-id decisioncall-id-less correlation is explicitly excluded from the extracted v0 scope unless a later fallback contract replaces that rule
Drop diagnosticsthe ring-buffer debug follow-up in
https://github.com/Rul1an/assay/issues/1271 is either implemented or
explicitly accepted as post-extraction operational work
CI enforcement paththe Assay-Runner lane-check/proof required status and
reviewer workflow are active; future refinements are tracked separately
rather than blocking the v0 boundary
Maintainer explainabilitya maintainer can explain which crate owns each boundary row above without reading the Phase 1 history

If the boundary map remains materially unstable after a 4-6 week consolidation window, treat that as evidence that extraction is premature. Do not force a repository split while the ownership line is still moving.

The consolidation window is an evidence requirement, not a calendar requirement. After Phase 2D Slices 1-6B landed, the passive 4-6 week wait is replaced by the burn-in criteria defined in phase-2d-consolidation-audit.md. The burn-in criteria are the new satisfaction condition for this consolidation gate; they are not necessarily satisfied yet โ€” the audit page tracks which criteria are observed and which are still pending. Counting weeks without observing repo behavior is weak evidence; the audit page makes the evidence concrete.

Extraction Blocking Conditions

Extraction is blocked if any of these are true:

  • assay.runner.*.v0 schemas still need breaking changes to remain useful
  • delegated CI selection still depends on reviewer intuition rather than the CI lane contract
  • fixture stability requires undocumented local knowledge
  • tool_call_id fallback semantics are being decided implicitly
  • runner schema definitions are still coupled to Assay internals in ways a future runner repository would need to import
  • runner orchestration still depends on assay-cli-local cgroup helpers without a stable API boundary
  • runner crate build boundaries require more Assay internals than a deliberate shared schema/monitor contract allows
  • macOS or Windows support is being treated as a port rather than a separate platform spike
  • a separate repo would need to copy Assay evidence verification logic
  • runner code cannot be tested without private host state that is absent from the delegated runbook
  • there is no non-spike consumer of the runner bundle format

Future Split Shape

If extraction becomes justified, the likely shape is:

AreaFuture owner
Artifact schemas and verificationAssay core or shared contract crate
Monitor/eBPF substrateAssay core unless runner needs a separately versioned monitor package
Runner orchestration CLIAssay-Runner candidate
Deterministic runner fixturesAssay-Runner candidate, governed by shared fixture contract
Delegated CI workflowDepends on repository ownership of the dedicated runner
Capability diff projectionAssay-Harness or a later Runner/Harness shared surface

The first extracted release, if it ever exists, should be narrow: Linux/eBPF delegated measured runs with the existing none, kernel+policy, and OpenAI Agents fixture paths. It should not bundle macOS, live LLM calls, fleet operations, or OTel mappings into the first boundary.

Non-Goals

This boundary map does not:

  • choose an external product name
  • create a new repository
  • promise publication or packaging
  • define macOS or Windows measurement
  • define live LLM or cassette semantics
  • define OTel mappings
  • change delegated acceptance criteria

Those decisions require separate contracts after the Linux boundary is stable.