{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://eightarms.net/octopus-workflow/schemas/runs-bundle.schema.json", "title": "Tier 1 Run Archive Bundle", "description": "Composite archive bundle committed at close: runs/archive/{slug}.json = {meta, index}. Dual-profile by schema_version: >= 2 strict (closed core field set + free-form context bag), 1 or absent legacy (structural typing only; historical drift normalized by repair-run-bundles.ts, see [org-internal #2588]). Validated by validate-run-bundles.ts; CI wiring: .gitea/workflows/octopus-schemas.yml. Authoritative layout: templates/runs-layout.md. Boundary rule: rules/two-tier-artifacts.md.", "type": "object", "additionalProperties": false, "required": ["meta", "index"], "properties": { "meta": true, "index": true, "working_notes": { "type": "string", "description": "Final content of runs/{slug}/working-notes.md ([org-internal #2600]), inlined at archive time when the file exists. The one Tier 1 artifact whose CONTENT (not just digest) rides in the bundle — the run's narrative memory (decisions, dead ends, reviewer feedback), consumed by later retro probes and the notes-injection degradation path ([org-internal #2601]). Absent when the run kept no working notes." }, "review_history": { "type": "array", "description": "Offline-verifiability digest of the run's review rounds (TD/TRC-F006, [org-internal #2688]): one entry per review stage the run executed, each derived from that stage's live reviews/{stage}/status.json history[] at archive time. Lets closed-run probes reconstruct round counts and verdicts from the bundle alone, without the (removed) live workspace or path reconstruction ([org-internal #2591]). Absent when the run kept no review rounds.", "items": { "$ref": "#/$defs/reviewHistoryEntry" } } }, "allOf": [ { "if": { "properties": { "meta": { "properties": { "schema_version": { "const": 2 } }, "required": ["schema_version"] } } }, "then": { "properties": { "meta": { "$ref": "#/$defs/metaStrict" } } }, "else": { "properties": { "meta": { "$ref": "#/$defs/metaLegacy" } } } }, { "if": { "properties": { "index": { "properties": { "schema_version": { "const": 2 } }, "required": ["schema_version"] } } }, "then": { "properties": { "index": { "$ref": "#/$defs/indexStrict" } } }, "else": { "properties": { "index": { "$ref": "#/$defs/indexLegacy" } } } } ], "$defs": { "reviewHistoryEntry": { "type": "object", "additionalProperties": false, "required": ["stage", "rounds", "final_verdict"], "description": "Per-stage summary of one review stage's rounds. Shapes mirror review-status.schema.json (stage dir name; history[] item fields).", "properties": { "stage": { "type": "string", "minLength": 1, "description": "Review stage identifier matching the reviews/{stage}/ directory (e.g. code, review-dag, audit-process — the live values; design-space is a retired historical value)." }, "rounds": { "type": "integer", "minimum": 1, "description": "Number of executed rounds." }, "final_verdict": { "type": "string", "enum": ["PASS", "WARN", "FAIL"] }, "per_round": { "type": "array", "description": "One entry per executed round, mirroring the live status.json history[] items.", "items": { "type": "object", "additionalProperties": false, "required": ["round", "overall_verdict", "blockers", "majors"], "properties": { "round": { "type": "integer", "minimum": 1 }, "overall_verdict": { "type": "string", "enum": ["PASS", "WARN", "FAIL"] }, "blockers": { "type": "integer", "minimum": 0 }, "majors": { "type": "integer", "minimum": 0 }, "minors": { "type": "integer", "minimum": 0, "description": "Count of MINOR findings for this round." } } } } } }, "ticket": { "oneOf": [ { "type": "null" }, { "type": "object", "additionalProperties": false, "required": ["owner", "repo", "number"], "properties": { "owner": { "type": "string", "minLength": 1 }, "repo": { "type": "string", "minLength": 1 }, "number": { "type": "integer", "minimum": 1 } } } ], "description": "Source issue reference, or null for an ad-hoc run (no ticket)." }, "parentEpic": { "oneOf": [ { "type": "null" }, { "type": "object", "additionalProperties": false, "required": ["number"], "properties": { "number": { "type": "integer", "minimum": 1 } } } ], "description": "Parent Epic issue number, or null if the run is not under an Epic." }, "metaLegacy": { "type": "object", "additionalProperties": true, "required": ["slug", "state", "created_at"], "description": "Legacy profile (schema_version 1 or absent): historical bundles AND current live-workspace runs — runs-meta.schema.json / runs-index.schema.json pin schema_version 1 today. Core fields type-checked when present; extra context properties (route/pr/node/kind/...) tolerated as-is. The v2 strict profile (below) is the migration target: it becomes the profile for new runs once the live-workspace schemas are bumped to emit schema_version 2 with the context bag.", "properties": { "schema_version": { "type": "integer", "minimum": 1 }, "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" }, "branch": { "type": "string" }, "state": { "type": "string", "enum": ["active", "archived"] }, "created_at": { "type": "string", "anyOf": [{ "format": "date-time" }, { "format": "date" }] }, "updated_at": { "type": "string", "anyOf": [{ "format": "date-time" }, { "format": "date" }] }, "closed_at": { "type": ["string", "null"], "anyOf": [{ "format": "date-time" }, { "format": "date" }] }, "close_commit_sha": { "type": ["string", "null"], "pattern": "^([0-9a-f]{40}|[0-9a-f]{64})$", "description": "Full git SHA, or null when unresolvable (legacy runs whose landing commit is unknown)." }, "ticket": { "$ref": "#/$defs/ticket" }, "parent_epic": { "$ref": "#/$defs/parentEpic" }, "worktree": { "type": ["string", "null"] } } }, "metaStrict": { "type": "object", "additionalProperties": false, "required": ["schema_version", "slug", "state", "created_at", "updated_at", "ticket"], "description": "Strict profile (schema_version 2): closed core field set. Run-specific context (route/pr/node/task_node/...) goes in the context bag — the ONLY place for non-core fields.", "allOf": [ { "if": { "properties": { "state": { "const": "archived" } }, "required": ["state"] }, "then": { "properties": { "closed_at": { "type": "string", "format": "date-time" }, "close_commit_sha": { "type": "string", "pattern": "^([0-9a-f]{40}|[0-9a-f]{64})$" } }, "required": ["closed_at", "close_commit_sha"] } } ], "properties": { "schema_version": { "type": "integer", "const": 2 }, "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" }, "branch": { "type": "string", "minLength": 1 }, "worktree": { "type": ["string", "null"], "description": "Absolute path of the worktree hosting this run, or null for ad-hoc runs without a worktree." }, "state": { "type": "string", "enum": ["active", "archived"] }, "created_at": { "type": "string", "format": "date-time" }, "updated_at": { "type": "string", "format": "date-time" }, "closed_at": { "type": ["string", "null"], "format": "date-time" }, "close_commit_sha": { "type": ["string", "null"], "pattern": "^([0-9a-f]{40}|[0-9a-f]{64})$" }, "ticket": { "$ref": "#/$defs/ticket" }, "parent_epic": { "$ref": "#/$defs/parentEpic" }, "context": { "type": "object", "additionalProperties": true, "description": "Free-form run context (route, pr, node, task_node, mode, kind, ...). In v2 every non-core field MUST live here, not at meta top level." } } }, "artifactLegacy": { "type": "object", "additionalProperties": true, "required": ["path"], "properties": { "path": { "type": "string", "minLength": 1 }, "sha": { "type": ["string", "null"], "pattern": "^[0-9a-f]{12,64}$", "description": "Legacy digests may be truncated (12/16-hex; source files no longer exist, cannot be re-computed). v2 requires full 64-hex." } } }, "artifactStrict": { "type": "object", "additionalProperties": false, "required": ["path", "type", "tier"], "properties": { "path": { "type": "string", "minLength": 1 }, "type": { "type": "string", "enum": [ "meta", "index", "design", "plan", "review-findings", "review-status", "review-synthesis", "synthesis-prompt", "precondition-gate", "working-notes", "analysis", "browser-evidence", "other" ] }, "schema": { "type": ["string", "null"], "format": "uri" }, "tier": { "type": "integer", "const": 1 }, "stage": { "type": ["string", "null"], "enum": [ "requirements", "design", "plan-iterations", "roadmap", "implement", "review-roadmap", "review-design-space", "review-iteration-plan", "review-dag", "review-code", "verify", "audit-process", "merge-pr", null ], "description": "Producing pipeline stage. Live stage ids (per schemas/workflow-routing.schema.json): review-dag, review-code, verify, audit-process, merge-pr. Retired/phase names retained only so historical archived bundles keep validating." }, "produced_by": { "type": ["string", "null"], "enum": [ "Producer", "Reviewer", "Verifier", "Tool", "Coordinator", "Analyst", "Architect", "Planner", "Developer", "Synthesizer", "Orchestrator", "Remediator", "Auditor", null ] }, "sha": { "type": ["string", "null"], "pattern": "^[0-9a-f]{64}$" }, "tier2_ref": { "type": ["string", "null"] } } }, "indexLegacy": { "type": "object", "additionalProperties": true, "required": ["artifacts"], "properties": { "schema_version": { "type": "integer", "minimum": 1 }, "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" }, "artifacts": { "type": "array", "items": { "$ref": "#/$defs/artifactLegacy" } } } }, "indexStrict": { "type": "object", "additionalProperties": false, "required": ["schema_version", "slug", "artifacts"], "properties": { "schema_version": { "type": "integer", "const": 2 }, "slug": { "type": "string", "pattern": "^[a-z0-9][a-z0-9-]*$" }, "artifacts": { "type": "array", "items": { "$ref": "#/$defs/artifactStrict" } } } } } }