Files
octopus-workflow/core/rules/workflow-routing.md
T

138 lines
7.7 KiB
Markdown
Raw Normal View History

> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Workflow Routing — type-driven process selection (mandatory)
A ticket's `Kind/*` label determines its process route. The main-session
Process Assessment Gate MUST resolve the route BEFORE matching a skill, so a
labeled ticket never re-derives its path from scratch. Routing is **additive**:
it can only skip stages a ticket doesn't need — it can never weaken a
mandatory gate or skip review/verify.
**Authoritative table**: the workflow-routing table in the instance config
area (`label → { entry, skip, keep_gates }`). The table is the single source
of truth; this rule only says _when and how_ to consult it.
### When to route (Step 0 — runs before the gate's "Articulate intent")
On every substantive request that is tied to a ticket, run Step 0:
1. **Identify the working ticket**. Priority order: explicit `Closes #N` /
`Fixes #N` / `Resolves #N` in the PR or commit → `## 父级 / Parent` link
or chunk mapping → the issue the user pasted or referenced by number.
None of these → no ticket, skip to degradation.
2. **Resolve the route with the 路由解析工具 FIRST** — pass the full
`Kind/*` label when known; omit `kind` when not yet read (the tool returns
the default route plus a read-ticket-then-re-invoke instruction). Agents
with the route-gate option enabled enforce this mechanically
[org-internal #3328]: other tool calls are dispatch-rejected until the
路由解析工具 runs. Do not hand-read the routing table when the tool is
available.
3. **Read the ticket's `Kind/*` label** from the issue body or via the issue
tools (unblocked once the route gate is satisfied). Pick the FIRST
`Kind/*` label if several exist; on a non-default route, re-invoke the
路由解析工具 with the full label.
4. **Apply the route**:
- `entry.skill` non-null → invoke that skill (with `entry.mode` if given)
instead of natural-language matching. This satisfies gate Step 3.
- `entry.skill` null → normal natural-language match, still honoring
`skip` / `keep_gates` downstream. Never drop a gate the route lists in
`keep_gates`; never add back a stage the route lists in `skip`.
### Degradation — label missing, unknown, or wrong ([org-internal #1828] AC)
- **No ticket / no `Kind/*` label / label not in the table** → `default`
route (natural-language matching). State this in one line ("no Kind/\*
label → default route") so the choice is auditable; never block or ask
the user just because a label is absent.
- **Label looks wrong for the work** → do NOT silently override the label.
Apply the labeled route, flag the mismatch in your first response, and
recommend the correct label — the creator owns label correctness; routing
acts only on what is written.
- **Routing table file missing/unreadable** → fall back to natural-language
matching session-wide and note it once — a broken table never blocks work.
### Interaction with the rest of the pipeline
- Routing chooses the **entry** and the **skip set** only. L0/L1 enforcement
(worktree/branch discipline, commit-msg format, stash ban,
claim-discipline, issue-checklist-sync, issue-cross-linking) applies on
every route; a `Kind/Documentation` ticket still needs a worktree and a
PR.
- `keep_gates` from the route and the skill's own mandatory gates intersect:
a gate is mandatory if EITHER source requires it. Skipping is valid only
when BOTH the route and the skill agree it's skippable for this ticket type.
### Runtime growth signals (post-sizing)
Two live growth mechanisms (narrative: Tier-2 reference page
`rules/workflow-routing-detail`, reachable via the ticket backend; retired
Size/* history: the instance rules-history archive). Canonical key:
`dag.size_derivation.oversize_signals` (TD/DUP-F009).
- **DAG-routed tickets** (DAG Epic, DAG-routed `Kind/Feature`, their
`Kind/Task` children — no `Size/*` tier): runtime growth fires the
oversize signals → response is **re-derivation + review-dag re-run**.
- **Bug tickets (big-bug relabel rule, [org-internal #3061])**: a `Kind/Bug`
hitting a design-level trigger (design-decision root cause, shared-contract /
public-API change, data migration) has outgrown the bug type — mandatory
action is **relabel `Kind/Feature`** (Step 0 reroutes into the DAG
pipeline; repro + root-cause notes carry over as node input). Scale-only
triggers stay in bugfix with batched iterations.
Both follow "act on what's written, surface the doubt": when reality
disagrees with the label, pause, reclassify, and make the change visible —
never quietly override.
### DAG 路由 (v2) — default (转正)
The DAG ticket pipeline (`analyze-dag` → task DAG → single gate `review-dag`)
is the **default** route for `Kind/Epic` and `Kind/Feature`
([org-internal #3061] Phase 2 / TD-388). Both resolve via the routes table
directly — **no trigger/marker check** (route rollback = revert PR).
Authoritative definition: the `dag:` block in the workflow-routing table;
narrative + history: Tier-2 reference page `rules/workflow-routing-detail`.
1. **`Kind/Epic` or `Kind/Feature``dag.route`**: entry `analyze-dag`,
single gate `review-dag` (replaces review-design-space +
review-iteration-plan), `keep_gates` `[review-dag, verify]`.
2. **`Kind/Task` under a DAG parent → `dag.task_route`** (entry `implement`,
`implement → review-code → verify`), NOT `dag.route`. All three skills
carry a DAG branch; `pipeline/review-dag` success replaces the
design-space + iteration-plan convergence preconditions at review-code
and verify.
**Routing stickiness**: once an Epic is routed to DAG (draft DAG artifact
exists or `## DAG 状态` table created), all subsequent Step 0 for that Epic
stays on the DAG route — stickiness starts at first routing, NOT at
single-gate PASS. Symmetrically, an Epic already decomposed via legacy
roadmap stays legacy through close (no new legacy decomposition).
**Ticket creation after single-gate PASS** (switch values authoritative in
the routing table `dag.ticket_creation`; analyze-dag itself does NOT create
tickets): on `review-dag` PASS the **aggregator agent** creates one
`Kind/Task` ticket per `type: task` node (body: node `acceptance_criteria`
or dag subpage link + `test_id` suite; `## 父级 / Parent` → DAG parent so
Step 0 resolves `dag.task_route`); `type: milestone` nodes get NO ticket
(DoD carried by `dag.verify_milestone`); the parent body aggregates
`## DAG 状态` + `## 当前状态` (single writer: the aggregator). Each task
ticket then flows implement → review-code (`mode: "dag-task"`) → verify
(task mode).
### Retired sections (index)
Retired mechanisms (Sizing, JIT decomposition, marker disambiguation,
legacy-route sunset, publish-target-by-tier, gate-trim) live in the instance
rules archive; rulings in the phase-3 retirement ruling doc (Tier-2
reference, reachable via the ticket backend). Nothing trims gates —
`never_trim` is structural.
### 立案降档 — filing/sprint-mode[org-internal #3002] G5 / [org-internal #3007]
Sprint 期间债务侧显式降档,不靠纪律。开关:routing table `filing.sprint-mode`
(默认 `false`)。`true`(冲刺期)时 verify Phase 5.5 registry-only 不分严重度
(登记行照写、零丢失;独立工单创建冻结至开关回 `false`,已登记行按
ticket-lifecycle 规则正常认领升票;期间 HIGH/MEDIUM 行不被 reaper 触碰,
[org-internal #3004])。BF/FT5.55/5.56)不受影响。谁翻转:冲刺负责人(人),
在冲刺跟踪单记一行;开关值即 routing table 当前值,verify 每次运行时读取。
动机与细节:Tier-2 参考页(经 ticket backend`rules/workflow-routing-detail`