2026-09-15 08:41:51 +08:00
{
"$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" ,
2026-09-16 13:13:18 +08:00
"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."
2026-09-15 08:41:51 +08:00
},
"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 ,
2026-09-16 13:13:18 +08:00
"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)."
2026-09-15 08:41:51 +08:00
},
"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" ],
2026-09-16 13:13:18 +08:00
"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." ,
2026-09-15 08:41:51 +08:00
"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" ],
2026-09-16 13:13:18 +08:00
"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." ,
2026-09-15 08:41:51 +08:00
"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" } }
}
}
}
}