Machine-readable contracts for the three sanctioned receipt families audited in #506. These are documentation contracts, not runtime JSON Schema files.
schema_versionis an integer. Bump only for breaking changes (rename, remove, or change the type/meaning of an existing field).- Within a
schema_version, evolution is additive only. New optional fields may appear (including #491 telemetry projection). Patch identity from #485 is already represented by verifyschema_version: 2. Consumers must ignore unknown keys. - Absent vs null: optional fields are omitted when unset. Producers should
not write JSON
nullfor optional top-level fields unless the field's presence carries semantic meaning. Intentional nullable shapes:- Verify version 2 always includes
baseline_commit,tree_fingerprint, andchanges_patch_sha256. All three arenullwhen identity capture is unavailable, keeping the binding tuple structurally complete. - Verify
commands[].exit_codemay benullwhen an interrupted or timed-out child has no exit status. A command rejected before execution uses exit code2. - Run
scheduler.usedmay benullwhile a run is in flight. - Run
roster.jsonagent rows may include"env": nullwhen the seat has no env overrides (snapshot preserves the roster table shape). - Synthesis
orchestratormay be explicit JSONnullin direct-worker mode. - Outcome
prev_digestmay benullon the first ledger row. - Work closeout
taskandverificationmay benullwhen absent. - Reused verify receipts omit
reused_fromwhen the source receipt lacks arun_id.
- Verify version 2 always includes
- Serialization: on-disk JSON uses UTF-8, indent 2, trailing newline, and
sort_keys=Trueat every object level unless noted (JSONL: one sorted object per line). - Readers must accept records without
schema_version(pre-#506 storage).
Path: .brigade/work/verify-runs/<run-id>/receipt.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema_version |
integer | yes (new writes) | Always 2 for this contract |
run_id |
string | yes | Timestamp-prefixed id |
target |
string | yes | Absolute workspace path |
status |
string | yes | running, completed, failed, rejected, canceled |
started_at |
string (ISO-8601) | yes | UTC timestamp |
completed_at |
string (ISO-8601) | no | Set at finalize |
duration_seconds |
number | no | Wall time |
timeout |
integer | no | Per-command timeout seconds |
path |
string | yes | Run directory path |
commands |
array of object | yes | See command object below |
planned_commands |
array of string | no | Display argv joined |
evidence |
object | no | Workspace evidence snapshot |
baseline_commit |
string | null | yes | Verified Git baseline, or null when identity capture is unavailable |
tree_fingerprint |
string | null | yes | Verified Git tree hash, or null with the unavailable identity tuple |
changes_patch_sha256 |
string | null | yes | SHA-256 of changes.patch, or null with the unavailable identity tuple |
git |
object | no | {head, branch, dirty_files} |
code_graph_delta |
object | no | GraphTrail summary |
harness_session |
object | no | {harness, fingerprint} |
digests |
object | no | {algorithm, logs, receipt_sha256, signature?, key_id?} |
reused_from |
string | no | Prior run id when reused |
interruption |
object | no | Cancel metadata |
verify_manifest_id |
string | no | Registered manifest id when the run was manifest-selected |
required_utility_check_ids |
array of string | no | Manifest-owned utility guardrail ids required for scoring (#503) |
subject_binding |
object | no | Verifier-authored scoreable subject metadata (manifest runs only) |
failure_class |
string | no | Receipt-level #474-style failure class when status is not completed |
failure_kind |
string | no | Receipt-level failure kind paired with failure_class |
subject_binding object (additive, manifest-selected runs)
| Field | Type | Notes |
|---|---|---|
binding_mode |
string | patch_backed or fixture_eval |
artifact_kind |
string | skill or card |
artifact_id |
string | Verifier-owned subject id |
content_fingerprint |
string | Subject content fingerprint at verify time |
manifest_binding |
object | {manifest_id, payload_sha256, source_path?} for the exact tracked verifier manifest |
patch_source |
string | worktree or generated (patch-backed only) |
producer_binding |
object | {work_session_id, owned_delta_sha256, subject_clean_at_start, start_git} for patch-backed runs |
verifier_identity |
object | {verifier_id, session_id} independent verifier session |
patch_binding |
object | Patch-backed tuple plus subject_path and subject_hash |
fixture_binding |
object | {manifest_id, case_id, check_id} for fixture evaluation runs |
Ad hoc --command / --argv-json runs omit subject_binding and remain audit-only (non-scoreable).
Tracked workspace verifier manifests live under verify/manifests/*.json. A manifest owns its
subject, ordered checks, required utility ids, optional scoped-write globs, and optional route
opt-in (route_paths or exact route_classes). Untracked manifests cannot produce scoreable
receipts or routing authority.
Command object
| Field | Type | Notes |
|---|---|---|
command |
string | Display command |
argv |
array of string | no |
env |
array of string | Sorted KEY=value pairs |
status |
string | completed, failed, timed_out, rejected, interrupted |
exit_code |
integer | null | Child exit status. null when interrupted or timed out without one. Rejected commands use 2 |
started_at, completed_at |
string | ISO-8601 |
duration_seconds |
number | |
stdout_summary, stderr_summary |
string | |
stdout_log_path, stderr_log_path |
string | Paths under run dir |
check_role |
string | effectiveness or utility_guardrail (manifest-selected runs) |
check_id |
string | Stable verifier-owned check id (manifest-selected runs) |
obligation_id |
string | Optional obligation id from the manifest |
failure_class |
string | #474-style class when the command did not succeed |
failure_kind |
string | Typed failure kind paired with failure_class |
Path: <verify-archive-root>/index.jsonl (one JSON object per line, append-only,
sorted keys per line). The default archive root is .brigade/work/verify-archive;
.brigade/config.json keys verify_archive_enabled and verify_archive_dir override it.
Retention prunes the local .brigade/work/verify-runs/ directory down to the newest
verify_runs_keep runs (default 50). Before any run directory is deleted it is copied
into the archive root as <verify-archive-root>/<run-id>/ and one index line is
appended. A run directory whose archival fails is kept locally, so pruning never
destroys receipt evidence that was not preserved first. Archival re-checks integrity
both ways: the archived receipt.json bytes must hash to the source bytes, and a
receipt carrying digests.receipt_sha256 must still re-hash to that value after the
copy. The archive root must not overlap the local verify-runs root in either direction,
including through a symlink alias. Source trees containing symlinks or special files
are kept locally. An existing archive destination is reused only when it is a regular
directory with the same files and file hashes as the source.
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.verify_archive_index.v1 |
schema_version |
integer | yes | Always 1 for this contract |
run_id |
string | yes | Run directory name that was archived |
archived_at |
string (ISO-8601) | yes | When the archival completed |
source_run_dir |
string | yes | Original run directory path |
archive_run_dir |
string | yes | Archived copy path |
already_archived |
boolean | yes | true when an identical archive already existed |
receipt_file_sha256 |
string | null | yes | SHA-256 of the archived receipt.json bytes; null when the run dir had no receipt |
receipt_schema_version |
integer | null | yes | The receipt's own schema_version; null for legacy receipts without one |
receipt_sha256 |
string | null | yes | The receipt's self-declared canonical digest; null when absent |
signature |
string | null | yes | Receipt signature when the run was signed; null otherwise |
key_id |
string | null | yes | Signing key id paired with signature; null otherwise |
status |
string | null | yes | Receipt status at archival time |
started_at |
string | null | yes | Receipt start timestamp |
completed_at |
string | null | yes | Receipt completion timestamp |
Path: .brigade/work/closeouts/<closeout-id>/closeout.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema_version |
integer | yes (new writes) | 1 |
closeout_id |
string | yes | |
target |
string | yes | |
status |
string | yes | ready or blocked |
ready |
boolean | yes | |
created_at |
string | yes | ISO-8601 |
session |
object | yes | Session summary |
session_path |
string | yes | |
task |
object | null | Task summary | |
acceptance_criteria |
array | yes | |
verification |
object | null | Latest verify receipt ref | |
scanner_sweep |
object | yes | |
code_review |
object | yes | |
handoff_drafts |
object | yes | |
blockers |
array of string | yes |
Session summary (session object)
| Field | Type | Notes |
|---|---|---|
path |
string | Session directory |
id |
string | Session id |
status |
string | Session status |
title |
string | null | |
started_at, ended_at |
string | null | ISO-8601 |
note, latest_note |
string | null | |
handoff |
object | null | Handoff metadata when present |
branch |
string | null | Git branch from snapshot |
dirty_files |
integer | Count from snapshot |
next |
string | null | Suggested next step |
Verification summary (verification object, when present)
| Field | Type | Notes |
|---|---|---|
run_id |
string | Latest verify run id |
status |
string | Verify receipt status |
path |
string | Verify run directory |
command_count |
integer | Number of command records |
Path: .brigade/runs/<run-id>/run.json
The required column below describes normal run creation. Stale-lock recovery may create the partial recovery variant documented after the main table when the original file is missing, corrupt, or not an object.
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.run.v1 |
schema_version |
integer | yes (new writes) | 1 |
task |
string | yes | |
cwd |
string | no | Omitted when unknown |
orchestrator |
string | yes | Seat name |
dry_run, read_only |
boolean | yes | |
status |
string | yes | Lifecycle status |
started_at, status_started_at |
string | yes | ISO-8601 UTC (Z) |
finished_at |
string | no | |
duration_seconds |
number | no | |
suspected_noop |
boolean | yes | |
code_graph_brief, drift_impact_brief, evidence_brief, brief_budget |
object | yes | Brief attachment summaries |
scheduler |
object | no | {requested, used, fallback_reason} |
roster |
object | no | Resolution metadata |
lock_workspace |
string | no | |
route |
object | no | Routing brief |
skill_route_policy |
object | no | Frozen pre-plan score inputs, assignments, quota counters, and acceptance reasons |
worker |
string | no | Direct-worker seat |
git |
object | no | |
pre_run_snapshot |
object | no | Run-guard snapshot |
code_graph_delta |
object | no | |
context_eval |
object | no | |
artifacts |
string | no | Output directory |
handoff |
string | no | Handoff path |
error |
string | no | |
failure_phase, failure_kind |
string | no | |
failure |
object | no | {phase, kind, detail, seat?} |
transport_warning |
object | no | |
codex_transport |
string | no | |
control_transport, control_socket |
object / string | no | |
active_stage |
integer | no | Current dispatch stage |
active_seats |
array of string | no | Seats active in the current dispatch stage |
phase_owner |
string | no | Seat responsible for result processing |
artifact_collection |
object | no | Artifact-retention result |
resumed_at |
array of string | no | ISO-8601 resume timestamps |
recovery_history |
array of object | no | Prior failure objects retained after a successful resume |
lifecycle_journal_requested |
boolean | no | Durable enrollment request. Present and true on every new run |
run_journal_authority_requested |
boolean | no | Durable authority request. Present and true on every new run |
projector_version |
integer | no | Journal projector version used for the compatibility snapshot |
journal_present |
boolean | no | Whether the verified lifecycle journal exists |
journal_last_sequence |
integer | no | Last event sequence applied to this snapshot |
journal_last_event_digest |
string / null | no | Digest at journal_last_sequence. Null only at sequence zero |
approval_reference |
object | no | Redacted approval identity, source, fingerprints, and decision state |
Partial stale-recovery variant
When no valid original run.json object survives, runguard._recover_run_artifact
writes this smaller receipt:
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | brigade.run.v1 |
schema_version |
integer | yes | 1 |
artifacts |
string | yes | Recovered run directory |
recovery_preserved_artifact |
string | no | Renamed corrupt source, when one existed |
cwd, lock_workspace |
string | no | Recovered from lock metadata |
started_at |
string | no | Recovered lock acquisition time |
status, status_started_at, finished_at |
string | yes | Terminal recovery state and timestamps |
error, failure_phase |
string | yes | Recovery summary |
failure |
object | yes | Stale-lock failure variant documented below |
Brief attachment objects (code_graph_brief, drift_impact_brief, evidence_brief)
| Field | Type | Notes |
|---|---|---|
attached |
boolean | Whether the brief was attached |
bytes |
integer | Serialized brief size |
drift_impact_brief also includes pending_count (integer).
brief_budget object
| Field | Type | Notes |
|---|---|---|
bytes |
integer | Budget ceiling |
attached |
array of object | Rows shaped {name: string, bytes: integer, truncated: boolean} |
scheduler object
| Field | Type | Notes |
|---|---|---|
requested |
string | Requested scheduler name |
used |
string | null | Resolved scheduler. null while unresolved |
fallback_reason |
string | null | null unless a fallback scheduler was used |
roster object (resolution metadata on run.json)
| Field | Type | Notes |
|---|---|---|
path |
string | Resolved roster file path |
source |
string | Resolution source label |
shadowed |
array of string | Shadowed roster paths |
failure object
| Field | Type | Notes |
|---|---|---|
phase |
string | Failure phase |
kind |
string | Failure kind |
detail |
string | Human-readable detail |
seat |
string | Optional single seat attribution |
seats |
array of string | Optional multi-seat attribution |
owner_pid |
integer | Stale-lock recovery only |
prior_status |
string | Stale-lock recovery only |
recovered_at |
string | Stale-lock recovery only, ISO-8601 |
artifact_collection object
| Field | Type | Notes |
|---|---|---|
status |
string | ok or failed |
patch_ref |
string | Relative patch path when collected |
changed |
boolean | Whether the worktree changed |
tracked_count, untracked_count |
integer | Change counts |
worktree |
string | Detached worktree path when used |
failure |
object | Same shape as failure when collection failed |
Lifecycle: journal authority is the default for every new run.
events/lifecycle.jsonl is the append-only lifecycle record and run.json is its
latest brigade.run.v1 compatibility projection. Existing run directories that
lack both durable request fields remain snapshot-only and are not migrated in
place. Readers must ignore additive keys. A paused approval projects status: running so a previous version still sees a known nonterminal status.
Do not create a journal or add durable request fields to a legacy receipt by
hand. Journal-aware writers verify the bounded chain and checkpoint before
replacing the snapshot. An older release may inspect the additive run.json
shape, but operators must roll forward before it writes, recovers, or resumes a
journal-authoritative run. A retry after an approval action redeemed its claim
but exited before outcome persistence verifies the same run and fingerprints.
Daily approvals also bind the redeemed claim to the exact completed Daily run
receipt. A missing or changed completion receipt is not recoverable by retry.
The source-store lock spans validation, any missing approval.consumed and
run.resumed facts, and the refreshed snapshot. Review writes wait until that
transaction finishes. Reconciliation does not execute the action again.
Sidecars (roster.json, plan.json, worker-results.json, synthesis.json)
are write-once per phase (resume salvage and patch-ref binding may rewrite
worker/synthesis artifacts).
Path: .brigade/runs/<run-id>/route-decision.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema_version |
string | yes | brigade.route-decision.v1 |
chosen_route |
array of string | null | yes | Route stages selected for the run |
confidence, template_version |
string | null | yes | Route metadata |
admissible_seats |
array of string | yes | Non-orchestrator seats |
decided_at |
string | no | Pre-plan policy timestamp |
policy_version |
string | no | Skill route-policy version |
score_inputs |
object | no | Receipt-only score inputs keyed by artifact id |
skill_assignments |
array of object | no | Band, authority, manifest, scope, and exploration selection |
exploration |
object | no | Route class, 7/30-day counters, quota, and accept/reject reasons |
When skill routing applies, this receipt preserves the decision made before planning. Finalization must not recompute it from post-run state.
Path: .brigade/runs/<run-id>/roster.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.roster_snapshot.v1 |
schema_version |
integer | yes (new writes) | 1 |
orchestrator |
string | yes | Seat name |
max_workers |
integer | yes | |
timeout_seconds |
integer | null | yes | |
allow_models |
array of string | yes | |
sandbox |
string | null | yes | |
agents |
object | yes | Seat name → agent row (below) |
Agent row (values in agents)
| Field | Type | Notes |
|---|---|---|
cli |
string | null | CLI adapter name for direct seats |
model |
string | null | Model id |
reasoning |
string | null | Reasoning effort tier |
transport |
string | direct, acpx, app-server, etc. |
transport_version |
string | null | Transport adapter version |
role |
string | orchestrator or worker |
timeout_seconds |
number | null | Per-seat timeout override |
invalid_final_fallback |
string | null | Fallback seat for invalid finals |
read_only_capable |
boolean | Whether the seat may run read-only |
env |
object | null | Env override table (names/refs only) |
Path: .brigade/runs/<run-id>/plan.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.run_plan.v1 |
schema_version |
integer | yes (new writes) | 1 |
assignments |
array of object | yes | See assignment object below |
Assignment object (run_receipts.assignment_payload)
| Field | Type | Notes |
|---|---|---|
stage |
integer | Dispatch stage number |
worker |
string | Assigned seat name |
task |
string | Task text for the worker |
covers |
array of string | Optional covered artifact ids |
selected_skill_ids |
array of string | Optional pre-plan exploratory skill binding |
Path: .brigade/runs/<run-id>/worker-results.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.worker_results.v1 |
schema_version |
integer | yes (new writes) | 1 |
results |
array of object | yes | Worker result entries (below) |
ground_truth |
object | no | No-op / ground-truth metadata when present |
Worker result entry (run_receipts.worker_payload)
| Field | Type | Notes |
|---|---|---|
worker |
string | Seat name |
task |
string | Assigned task text |
ok |
boolean | Whether the worker succeeded |
detail |
string | Failure or status detail |
text |
string | Worker output text |
transport |
string | Transport used |
failure_phase |
string | Optional failure phase |
failure_kind |
string | Optional failure kind |
transport_warning |
object | Optional transport warning metadata |
thread_id |
string | App-server thread id when resumable |
status |
string | App-server turn status (with thread_id) |
exit_code |
integer | Optional child exit code |
timed_out |
boolean | Present when exit metadata or timeout applies |
stdout_log, stderr_log |
string | Optional log paths under the run dir |
duration_seconds |
number | Optional wall time |
requested_model |
string | Optional requested model |
effective_model |
string | Optional resolved model |
reasoning |
string | Optional reasoning tier |
stop_reason |
string | Optional terminal reason |
protocol_version |
integer | Optional protocol version |
session_id |
string | Optional session id |
request_id |
string | Optional request id |
acpx_version |
string | Optional ACPX adapter version |
events |
array of object | Optional redacted transport events |
env_overrides |
array of string | Sorted env override key names |
endpoint_host |
string | Comma-joined endpoint hosts from env |
attempts |
array of object | Optional retry log (below) |
Attempt object (run_receipts._attempt_payload)
| Field | Type | Notes |
|---|---|---|
kind |
string | Attempt kind label |
worker |
string | Seat name |
task |
string | Task text |
transport |
string | Transport used |
model |
string | null | Model id |
reasoning |
string | null | Reasoning tier |
started_at, finished_at |
string | ISO-8601 timestamps |
exit_code |
integer | null | Child exit code |
terminal_reason |
string | Terminal status label |
failure_phase |
string | null | Failure phase when applicable |
failure_kind |
string | null | Failure kind when applicable |
session_id |
string | null | Session id when applicable |
selected |
boolean | Whether this attempt was selected |
stdout_log, stderr_log |
string | Optional log paths |
Path: .brigade/runs/<run-id>/synthesis.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema |
string | yes | Always brigade.synthesis.v1 |
schema_version |
integer | yes (new writes) | 1 |
orchestrator |
string | null | no | Orchestrator seat. null in direct-worker mode |
worker |
string | no | Direct-worker seat name when mode is direct-worker |
mode |
string | no | direct-worker when dispatch skipped planning/synthesis |
result |
object | yes | {ok, detail, text} from run_receipts.agent_result_payload |
ground_truth |
object | no | Copied from worker-results when present |
Synthesis result object (run_receipts.agent_result_payload)
| Field | Type | Notes |
|---|---|---|
ok |
boolean | Whether synthesis succeeded |
detail |
string | Failure or status detail |
text |
string | Synthesis output text |
transport |
string | Transport used |
failure_phase |
string | Optional failure phase |
failure_kind |
string | Optional failure kind |
transport_warning |
object | Optional transport warning metadata |
exit_code |
integer | Optional child exit code |
timed_out |
boolean | Present when exit metadata or timeout applies |
stdout_log, stderr_log |
string | Optional log paths |
duration_seconds |
number | Optional wall time |
requested_model |
string | Optional requested model |
effective_model |
string | Optional resolved model |
reasoning |
string | Optional reasoning tier |
stop_reason |
string | Optional terminal reason |
protocol_version |
integer | Optional protocol version |
session_id |
string | Optional session id |
request_id |
string | Optional request id |
acpx_version |
string | Optional ACPX adapter version |
events |
array of object | Optional redacted transport events |
Path: memory/outcome/records.jsonl (one object per line)
| Field | Type | Required | Notes |
|---|---|---|---|
schema_version |
integer | yes (new writes) | 1 |
artifact_id |
string | yes | Skill or card id |
artifact_kind |
string | yes | skill or card |
task_id |
string | yes | May be empty |
source |
string | yes | verify, run, friction, … |
signal_value |
integer | yes | -1, 0, or +1 |
evidence_ref |
string | yes | Path to receipt |
ts |
string | yes | ISO-8601 |
prev_digest |
string | null | yes | Chain link |
digest |
string | yes | Row digest |
code_graph_delta |
object | no | Compact delta |
context_eval |
object | no | |
content_fingerprint |
string | no | Artifact bytes hash |
context |
object | no | Harness manifest |
capability_fingerprint |
string | no | |
route |
object | no | Route manifest |
route_fingerprint |
string | no |
Path: memory/outcome/decisions/<timestamp>-<slug>.json
| Field | Type | Required | Notes |
|---|---|---|---|
schema_version |
integer | yes (new writes) | 1 |
artifact_id |
string | yes | |
action |
string | yes | install, rollback, hold, … |
prior_status, new_status, decided_status |
string | yes | |
reason |
string | yes | |
score |
object | yes | Scoring breakdown |
execution |
string | yes | Physical side-effect result |
created_at |
string | yes | ISO-8601 |
content_fingerprint |
string | no | Current content fingerprint when stale evidence was excluded |
lifetime_score |
number | no | Lifetime score before fingerprint filtering |
lifetime_helped |
integer | no | Lifetime positive-signal count |
lifetime_hurt |
integer | no | Lifetime negative-signal count |
stale_records |
integer | no | Records excluded as stale |
legacy_records |
integer | no | Records without a content fingerprint |
brigade receipts verify: digest chain checks for verify receipts and outcome rowsbrigade receipts export miseledger: adapter export (separatemiseledger.adapter.v1envelope)brigade outcome rebuild-status: provestatus.jsonmatches decision receipts