2026-09-15 08:41:51 +08:00
{
"$schema" : "https://json-schema.org/draft/2020-12/schema" ,
"$id" : "https://eightarms.net/octopus-workflow/schemas/workflow-routing.schema.json" ,
"title" : "Workflow Routing Table" ,
2026-09-16 13:13:18 +08:00
"description" : "Schema for workflow-routing.yaml — type-driven (Kind/*) process selection. Referenced by rules/workflow-routing.md and the auto-approve rule. When this schema and the rules markdown disagree, the YAML (validated by this schema) is authoritative." ,
2026-09-15 08:41:51 +08:00
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "version" , "default" , "routes" ],
"properties" : {
"$schema" : { "type" : "string" },
"version" : { "type" : "integer" , "const" : 1 },
"default" : { "$ref" : "#/$defs/route" },
"routes" : {
"type" : "object" ,
"additionalProperties" : { "$ref" : "#/$defs/route" },
"description" : "Keys are Kind/* label names, e.g. Kind/Bug, Kind/Feature."
},
"preflight" : { "$ref" : "#/$defs/preflightPolicy" },
"dag" : { "$ref" : "#/$defs/dag" },
"filing" : { "$ref" : "#/$defs/filing" },
"review" : { "$ref" : "#/$defs/review" }
},
"$defs" : {
"stage" : {
"type" : "string" ,
2026-09-16 13:13:18 +08:00
"description" : "A pipeline stage identifier — the 5 live gates (post-[org-internal #3072] phase 3, 2026-08-21): review-dag, review-code, verify, audit-process, merge-pr. Production-phase names (requirements, design, roadmap, implement) and the 7 retired stage ids (roadmap-exit, review-roadmap, requirements-exit, design-exit, review-design-space, review-iteration-plan, plan-iterations) are no longer valid anywhere — the sizing block that consumed the phase names was retired the same ruling." ,
2026-09-15 08:41:51 +08:00
"enum" : [ "review-dag" , "review-code" , "verify" , "audit-process" , "merge-pr" ]
},
"entry" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"skill" : {
"type" : [ "string" , "null" ],
"enum" : [ "implement" , "review-artifact" , "review-code" , "verify" , "analyze-dag" , null ],
"description" : "Skill name to enter, or null for natural-language routing. The legacy roadmap / requirements-elicitation / design / plan-iterations entries were removed when those skills were archived ([org-internal #3072] phase 3, 2026-08-21 - the instance archive)."
},
"mode" : {
"type" : [ "string" , "null" ],
"enum" : [ "bugfix" , "refactor" , "port" , null ],
"description" : "Skill mode, or null."
}
}
},
"stageList" : {
"type" : "array" ,
"items" : { "$ref" : "#/$defs/stage" }
},
"route" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"entry" : { "$ref" : "#/$defs/entry" },
"skip" : { "$ref" : "#/$defs/stageList" },
"keep_gates" : { "$ref" : "#/$defs/stageList" },
"preflight" : {
"type" : "array" ,
"items" : { "$ref" : "#/$defs/preflightItem" },
2026-09-16 13:13:18 +08:00
"description" : "Evidence-based producer pre-flight checklist ([org-internal #2599]) — landed by a human from retrospective PRE-FLIGHT PROPOSAL rows. Absent/empty = no injection. Cap is governed by preflight.max_items (policy), not the schema."
2026-09-15 08:41:51 +08:00
},
"notes" : { "type" : "string" },
"effort" : {
"type" : "string" ,
"enum" : [ "low" , "high" , "max" ],
2026-09-16 13:13:18 +08:00
"description" : "Reasoning-effort hint for this route (llm-latency phase 2): maps onto the active model's variant table when it exposes one (GLM-5.2+ low/high/max); fail-open otherwise. Reserve `low` for genuinely lightweight routes (direct-edit, no pipeline) — reasoning dominates GLM-5.3 generation latency."
2026-09-15 08:41:51 +08:00
}
}
},
"preflightPolicy" : {
"type" : "object" ,
"additionalProperties" : false ,
2026-09-16 13:13:18 +08:00
"description" : "Thresholds for the retro → routes.{Kind}.preflight evidence loop ([org-internal #2599]). Authoritative values live here; the retrospective consults this block, it does not restate the numbers." ,
2026-09-15 08:41:51 +08:00
"properties" : {
"max_items" : { "type" : "integer" , "minimum" : 1 },
"min_sample" : { "type" : "integer" , "minimum" : 0 },
"consecutive_recur" : { "type" : "integer" , "minimum" : 1 },
"aging_consecutive_clean" : { "type" : "integer" , "minimum" : 1 }
}
},
"preflightItem" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "id" , "item" , "evidence" ],
"properties" : {
"id" : { "type" : "string" , "description" : "Stable slug, e.g. cor-unhandled-null." },
"item" : { "type" : "string" , "description" : "One checklist line the Producer verifies before implementing." },
"evidence" : {
"type" : "string" ,
2026-09-16 13:13:18 +08:00
"description" : "Retro reference justifying the item, e.g. 'retro [org-internal #2599]: COR × unhandled-null, 5/8 first-round FAILs on Kind/Bug'."
2026-09-15 08:41:51 +08:00
},
"added_cycle" : {
"type" : "string" ,
"description" : "Cycle id when landed, e.g. 2026-08. Drop-oldest beyond preflight.max_items sorts on this."
}
}
},
"filing" : {
"type" : "object" ,
"additionalProperties" : false ,
2026-09-16 13:13:18 +08:00
"description" : "Filing policy (立案/登记策略). sprint-mode ([org-internal #3007]): when true, verify Phase 5.5 promotes registry rows to tickets in sprint mode only. work-ticket-wip-cap ([org-internal #3005] G3): open non-TD work tickets beyond this count require scheduling evidence, else they stay registry rows." ,
2026-09-15 08:41:51 +08:00
"properties" : {
"sprint-mode" : {
"type" : "boolean" ,
"description" : "Sprint-mode filing downgrade switch ([org-internal #3007])."
},
"work-ticket-wip-cap" : {
"type" : "integer" ,
"minimum" : 0 ,
"description" : "WIP cap on open non-TD work tickets (Kind/* without assignee) before new filings require scheduling evidence ([org-internal #3005] G3)."
}
}
},
"review" : {
"type" : "object" ,
"additionalProperties" : false ,
2026-09-16 13:13:18 +08:00
"description" : "Review round budget (process-diet P0b, [org-internal #3567]/TD-564): a tail cut, not the norm — at budget without convergence, STOP; residual findings flow to the TD registry. High risk = a BLOCKER survived a round or the diff touches a frozen cross-session contract." ,
2026-09-15 08:41:51 +08:00
"required" : [ "max_rounds" ],
"properties" : {
"max_rounds" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "default" , "high_risk" ],
"properties" : {
"default" : { "type" : "integer" },
"high_risk" : { "type" : "integer" }
}
}
}
},
"dag" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "route" , "task_route" , "ticket_creation" , "verify_milestone" , "size_derivation" , "review_depth" ],
"properties" : {
"route" : { "$ref" : "#/$defs/dagRoute" },
"task_route" : { "$ref" : "#/$defs/dagTaskRoute" },
"ticket_creation" : { "$ref" : "#/$defs/dagTicketCreation" },
"verify_milestone" : { "$ref" : "#/$defs/dagVerifyMilestone" },
"size_derivation" : { "$ref" : "#/$defs/dagSizeDerivation" },
"review_depth" : { "$ref" : "#/$defs/dagReviewDepth" }
}
},
"dagRoute" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "entry" , "skip" , "keep_gates" , "single_gate" ],
"properties" : {
"entry" : { "$ref" : "#/$defs/entry" },
"skip" : { "$ref" : "#/$defs/stageList" },
"keep_gates" : { "$ref" : "#/$defs/stageList" },
"single_gate" : { "$ref" : "#/$defs/dagSingleGate" },
"preflight" : {
"type" : "array" ,
"items" : { "$ref" : "#/$defs/preflightItem" },
2026-09-16 13:13:18 +08:00
"description" : "Evidence-based pre-flight checklist for the DAG route ([org-internal #2905] 方案 3) — same item shape as routes.{Kind}.preflight ([org-internal #2599]). Landed by a human from retrospective PRE-FLIGHT PROPOSAL rows, including the 'REQ × late-discovery' root cause (requirements found only after the DAG froze: DAG oversize signals, demo-period feedback). Consumed by analyze-dag (the route's entry skill) before decomposition. Absent/empty = no injection. Optional — deliberately NOT in dagRoute.required (spec-02 §2.8 frozen required array unchanged). Cap governed by preflight.max_items (policy), not the schema."
2026-09-15 08:41:51 +08:00
}
}
},
"dagTaskRoute" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "entry" , "skip" , "keep_gates" , "inherit" ],
"properties" : {
"entry" : { "$ref" : "#/$defs/entry" },
"skip" : { "$ref" : "#/$defs/stageList" },
"keep_gates" : { "$ref" : "#/$defs/stageList" },
"inherit" : { "type" : "string" , "enum" : [ "parent_dag" ] }
}
},
"dagSingleGate" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "id" , "dimensions" , "replaces" , "depth_from" , "never_trim" ],
"properties" : {
"id" : { "type" : "string" , "enum" : [ "review-dag" ] },
"dimensions" : {
"type" : "array" ,
"items" : { "type" : "string" , "enum" : [ "TOPO" , "REQMAP" , "RELEASE" ] },
"uniqueItems" : true ,
"minItems" : 3 ,
"maxItems" : 3
},
"replaces" : {
"type" : "array" ,
"items" : { "type" : "string" },
2026-09-16 13:13:18 +08:00
"description" : "Historical documentation of which legacy gates the single gate replaced ([org-internal #3072] phase 3 retired them) — free-form strings, not the live stage vocabulary."
2026-09-15 08:41:51 +08:00
},
"depth_from" : { "type" : "string" , "enum" : [ "size_derivation" ] },
"never_trim" : { "type" : "boolean" }
}
},
"dagTicketCreation" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "per_node" , "milestone_no_ticket" , "inherit_parent" , "parent_aggregator" ],
"properties" : {
"per_node" : { "type" : "boolean" },
"milestone_no_ticket" : { "type" : "boolean" },
"inherit_parent" : {
"type" : "array" ,
"items" : { "type" : "string" , "enum" : [ "Kind/Epic" , "Kind/Feature" ] },
"uniqueItems" : true ,
"minItems" : 1 ,
2026-09-16 13:13:18 +08:00
"description" : "Ticket kinds whose DAG children reference them as ## 父级 / Parent ([org-internal #3061] Phase 2 / TD-388: Kind/Feature added alongside Kind/Epic)."
2026-09-15 08:41:51 +08:00
},
"parent_aggregator" : { "type" : "boolean" }
}
},
"dagVerifyMilestone" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "weld_at_convergence" , "milestone_skill" , "integration_trigger" ],
"properties" : {
"weld_at_convergence" : { "type" : "boolean" },
"milestone_skill" : { "type" : "string" , "enum" : [ "verify" ] },
"integration_trigger" : { "type" : "string" , "enum" : [ "all_incoming_done_and_green" ] }
}
},
"dagSizeDerivation" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "enabled" , "thresholds" , "size_labels" , "oversize_signals" ],
"properties" : {
"enabled" : { "type" : "boolean" },
"formula" : { "type" : "string" },
"thresholds" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"node_count" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"d1" : { "type" : "integer" },
"d2" : { "type" : "integer" },
"d3" : { "type" : "integer" }
}
},
"cross_session_edge_count" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"d1" : { "type" : "integer" },
"d3" : { "type" : "integer" }
}
},
"contract_change_surface" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
"none" : { "type" : "string" },
"additive" : { "type" : "string" },
"breaking" : { "type" : "string" }
}
}
}
},
"size_labels" : { "type" : "string" },
"oversize_signals" : { "type" : "array" , "items" : { "$ref" : "#/$defs/dagOversizeSignal" } }
}
},
"dagOversizeSignal" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "id" , "trigger" ],
"properties" : {
"id" : {
"type" : "string" ,
"enum" : [
"node_split" ,
"new_cross_session_edge" ,
"draft_contract_breaking" ,
"frozen_contract_breaking" ,
"node_scope_drift"
]
},
"trigger" : { "type" : "string" }
}
},
"dagReviewDepth" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "D1" , "D2" , "D3" , "D4" ],
"properties" : {
"D1" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "reviewers" , "rounds" , "dim_split" ],
"properties" : {
"reviewers" : { "type" : "integer" },
"rounds" : { "type" : "integer" },
"dim_split" : { "type" : "string" }
}
},
"D2" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "reviewers" , "rounds" , "dim_split" ],
"properties" : {
"reviewers" : { "type" : "integer" },
"rounds" : { "type" : "integer" },
"dim_split" : { "type" : "string" }
}
},
"D3" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "reviewers" , "rounds" , "dim_split" ],
"properties" : {
"reviewers" : { "type" : "integer" },
"rounds" : { "type" : "integer" },
"dim_split" : { "type" : "string" }
}
},
"D4" : {
"type" : "object" ,
"additionalProperties" : false ,
"required" : [ "reviewers" , "rounds" , "dim_split" ],
"properties" : {
"reviewers" : { "type" : "integer" },
"rounds" : { "type" : "integer" },
"dim_split" : { "type" : "string" }
}
}
}
}
}
}