Contracts¶
The tools meet only at versioned files and APIs. Each row links to the repo that defines the contract; this page indexes them and never copies their schemas. Tower and Spaceport are private repositories, so their files and issues are named without links. How it fits shows the same seams along a ticket's journey.
| Producer → consumer | Contract | Defined in | Status |
|---|---|---|---|
| ai-dlc → team harness repo → hangar | Workflow plugin with plugin.lock.json, pinned in a harness lock as the component plugin:ai-dlc-workflow@team-harness. Its digest is the component's own digest field |
ai-dlc#191, #193, hangar#221 | Plugin and lock support on main; the team's harness turning it on: hangar#139 |
| Team harness repo → hangar | harness.lock (hangar.harness-lock/v1) plus native files and channels.yaml; the lock's harness_digest is computed the same way as the manifest's |
hangar spec 0014 §2, docs/harness-lock.md, docs/api/harness-lock.schema.json |
On main: freeze and check (hangar#133), thaw with turn-1 drift (#134), plugin mounts (#221), a registry by git URL; the team's own repo: #138 |
| hangar → Claude Code sandboxes | Read-only plugin seed, enabledPlugins, auto-update off, plugins listed in the manifest |
hangar#136 | On main |
| hangar canary → hangar, ai-dlc | harnesses.lock.yaml: CLI version and checksum per harness |
hangar src/hangar/harnesses.lock.yaml |
On main |
| hangar → flightdeck, Tower | hangar.manifest/v1: what ran, with config_digest, harness_digest, environment_digest |
hangar docs/api/manifest.schema.json |
On main |
| hangar → flightdeck, Tower | hangar.trace/v1: OTLP spans with hangar.tool.kind, hangar.shell.ops, taint and outcome class |
hangar docs/api/traces.md |
On main; export to Tower's /v1/traces: hangar#176 |
| flightdeck → hangar | hangar.experiment/v1: tasks × variants × trials, pinned, with sealed graders; hangar records a pin set per variant |
hangar docs/api/experiment.schema.json |
On main (flightdeck#11); lock variants on hangar's side (hangar#135), not yet sent by flightdeck |
| flightdeck → hangar | hangar.pinset/v1 and POST /api/trials {pin_set, task, n, budget}: a content-addressed, immutable pin set (harness_lock and harness_digest, environment_spec_digest and optionally environment_digest, model_id, each task's base_sha, grader_digest, egress_digest, optionally knowledge_snapshot); flightdeck owns sampling; a trial whose turn 1 drifted ends as infra_error / drift and is not retried |
hangar docs/api/trials.md, src/hangar/pinsets.py |
hangar on main (hangar#178, trial cache #180); flightdeck client: flightdeck#25 |
| hangar outbox → flightdeck | hangar.run/v1, hangar.tests/v1 and hangar.job_event/v1 objects under v1/runs/{date}/{session}.{run}/ and v1/jobs/; run.json is written last and marks the run complete |
hangar docs/api/outbox.md |
On main (hangar#163); on in the GKE deploy: hangar#273 |
| flightdeck internal | flightdeck.parquet/v1: runs, spans, events, manifests, grades, test cases, spec results; built nightly by the compactor |
flightdeck docs/data-plane.md |
On main (flightdeck#4, #5) |
| Team repos → flightdeck | Behavior specs flightdeck.spec/v1 and ADR checks:, judged nightly |
flightdeck docs/behavior-specs.md, ai-dlc#207 |
Spec language on main (flightdeck#14) and the ADR convention (ai-dlc#207); nightly runner: flightdeck#15 |
| hangar ↔ Tower | hangar.decision/v1 to POST /v1/decisions: five kinds (job.release, tool.call, landing.approve, egress.request, secret.request); allow, deny or wait plus a receipt; fails closed; off → shadow → enforce |
hangar spec 0015, Tower docs/api/decisions.md |
Both sides built: Tower's API (Tower#13), hangar's client and contract tests (hangar#171); wiring: hangar#172, #173 |
| Tower → hangar | HMAC-signed approval.created and approval.decided events to one route, /api/governance/events; hangar re-reads the decision |
spec 0015 §12, Tower docs/api/webhooks.md |
Tower's side on main (Tower#17); hangar's receiver: hangar#190 |
| hangar sandbox → Tower | Passport: workload token exchanged under RFC 8693 for a 15-minute passport with the requester as subject | Tower aw/workload.py, hangar#174 |
Exchange on main for /mcp; for /hooks: Tower#14; hangar's side: hangar#174 |
| Tower → auditors and PRs | Hash-chained receipts; an attestation envelope aw.attest/v1 with digests, model, requester and approver |
Tower aw/audit.py, docs/api/receipts.md |
On main (Tower#18) |
| hangar → reviewers | Review packet on each PR; Harness-Digest: (and, for a thawed job, Harness-Lock:) trailers on the PR body and the landed commit |
hangar landing.py, trailers.py, hangar#137 |
On main |
| hangar → engineers | Inbox items (review, question, approval, failed); a Slack DM for questions and approvals, and a digest at 10:15 and 16:00 | hangar inbox.py, #157, #158 |
On main; Tower's approvals in the digest: Tower#21, hangar#277 |
| Spaceport → agents | Four MCP tools with typed results | spaceport gateway/mcp/server.py |
On main, frozen; asking Tower: spaceport#14 |