Files
octopus-workflow/core/schemas/workflow-routing.schema.json

329 lines
14 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eightarms.net/octopus-workflow/schemas/workflow-routing.schema.json",
"title": "Workflow Routing Table",
"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.",
"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",
"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.",
"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" },
"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."
},
"notes": { "type": "string" },
"effort": {
"type": "string",
"enum": ["low", "high", "max"],
"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."
}
}
},
"preflightPolicy": {
"type": "object",
"additionalProperties": false,
"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.",
"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",
"description": "Retro reference justifying the item, e.g. 'retro [org-internal #2599]: COR × unhandled-null, 5/8 first-round FAILs on Kind/Bug'."
},
"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,
"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.",
"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,
"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.",
"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" },
"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."
}
}
},
"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" },
"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."
},
"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,
"description": "Ticket kinds whose DAG children reference them as ## 父级 / Parent ([org-internal #3061] Phase 2 / TD-388: Kind/Feature added alongside Kind/Epic)."
},
"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" }
}
}
}
}
}
}