Initial publish v0.1.0: standalone workflow core (corpus + examples + guards)

This commit is contained in:
octopus
2026-09-15 08:41:51 +08:00
commit bb35e661b2
114 changed files with 20240 additions and 0 deletions
+503
View File
@@ -0,0 +1,503 @@
---
name: analyze-dag
description: >
Use ONLY when an Epic is routed to the DAG ticket pipeline (Kind/Epic or
Kind/Feature — both resolve to analyze-dag via the routes table directly,
[org-internal #3072] phase 3 / [org-internal #3061] Phase 2). The
Analyst decomposes the Epic into a single task-DAG artifact — merging
roadmap+requirements+design+plan into one graph (nodes = acceptance
criteria, edges = contracts, topology = plan).
triggers:
- analyze-dag
- "dag pipeline"
- "DAG 管线"
- "任务 DAG"
- "task DAG"
- "DAG decomposition"
- "DAG 分解"
# `stage` is intentionally omitted: analyze-dag is the DAG route's entry skill,
# replacing roadmap+requirements+design+plan — it has no single stage identifier
# in the stage registry (see `<instance-root>/workflow-routing.yaml` dag.route and
# core/schemas/workflow-routing.schema.json stage enum). Phase-boundary
# signalling for the DAG route is the review-dag single gate and verify
# milestone, not a StageDone event.
role: Producer
---
# Analyze DAG — Task-DAG Decomposition (DAG route entry skill)
## Purpose
analyze-dag is the **entry skill** of the DAG ticket pipeline
(`dag.route.entry.skill`, spec-07 §2). For a DAG-routed Epic
(`Kind/Epic`, or `Kind/Feature` — both resolve here via the routes table
directly, [org-internal #3072] phase 3 / [org-internal #3061] Phase 2 / TD-388 —
including BACKFILL mode for MVP graduates and big-bug relabels), it
**replaces** `roadmap` + `requirements-elicitation` + `design` +
`plan-iterations` and produces **ONE artifact**: the task DAG, published as
wiki page `{epic-slug}/dag` (Tier 2 — human-visible, cross-worktree stable).
The task DAG merges three views into a single graph:
| View | Where it lives in the DAG |
| ---- | ------------------------- |
| requirements | node `acceptance_criteria` (each node is its own spec) |
| design | edge `contract_ref` (inter-node interface contract) |
| plan | topology (edge direction = dependency / execution order) |
`{epic-slug}` = the slug of the routed Epic — **not** this design's own slug
`dag-pipeline`.
## Agent Role
The **Analyst** (Producer) owns and produces the task DAG. The Analyst
decomposes the Epic into nodes (acceptance criteria), edges (contracts), and
a topological order (the plan), then publishes the single graph.
## Route Disqualifiers — 适用性预检(分解前必查)
分解前,Analyst 必须对照下表预检。任一命中 → **不分解**,将具体未决问题
列回 Epic 并 bounce(在不稳定需求上分解会产出一个即刻腐烂的冻结图;
"先出个小 DAG" 不是降级选项——不进管线,先稳定需求):
| Disqualifier | 判定 | Bounce 动作 |
| --- | --- | --- |
| 需求未稳 | scope item 含糊、互相矛盾、或只能以 "视情况" 回答;关键干系人问题仍开放 | 在 Epic 上列出澄清问题清单;问题解决后重入 analyze-dag |
| 设计主导 | 主要风险是一个有 ≥2 个可行选项的架构/平台决策,而非任务分解;需要先做一次探索 | 将开放问题转 `prototype`THROWAWAY spike)或设计探索;决策记录后重入 |
| 外部契约未决 | scope 依赖未决的外部契约(第三方 schema、上游 API 未定) | 按 External-System Rule(见下文)解析或围栏;不可拆的残余隔离后再重入 |
**反向拦截(Kind/MVP 降级建议,[org-internal #3061]**:一个 `Kind/Feature` 工单在分解预检中
暴露"概念未稳"(scope 仍在探索、成功标准未定、决策日志会推翻节点划分)时,
正确出口不是硬分解,而是建议改标签 `Kind/MVP` 先行交互式验证——概念稳定后
经 backfill 模式(见下文)带着决策日志重入。
### Phase 0 需求澄清(disqualifier 的结构化扩展,[org-internal #3061]
预检不止于"能否分解",还须证明"需求已澄清到可分解"。两项强制检查:
**1. Scope item 可证伪性预检**:逐条检查 Epic 的 scope item。每条必须能改写为
一个可观察的通过条件(给定输入/操作 → 可观测的结果);写不出来的条目就是
澄清问题,列入 bounce 清单。禁止把不可证伪条目直接塞进 node AC。
**2. 横向完备性三态清单**:对下表每个维度做三态判定——**已覆盖**(scope 有
对应条目)/ **不适用**(一句话理由)/ **待澄清**(列具体问题)。任一维度停在
"待澄清" → bounce(澄清问题清单随 bounce 一起给出,不让用户猜缺什么):
| 维度 | 检查 |
| --- | --- |
| 外部系统 | 沿用 External-System Rule(见下文):每个外部交互有明确协议与失败语义 |
| 错误路径 | 关键流程的失败分支有定义(不是只写 happy path |
| 数据生命周期 | 数据的创建/保留/删除策略已明确 |
| 权限/安全 | 访问边界与敏感数据处理已明确(或显式声明"无安全面" |
| NFR | 性能/容量/兼容性约束已枚举(见下) |
| 边界条件 | 值域/并发/时序等边界有约定(或声明"无特殊边界" |
**NFR 输入来源明确化**NFR 不允许"分解时脑补"。Epic 必须自带 NFR 输入——
scope item 中带 `NFR:` 前缀的条目,或一行显式声明"无 NFR 约束"。两者皆缺 →
作为澄清问题 bounce,而不是默认无约束。node schema 的 `NFR:` 条目只能来自
该枚举,不得新增臆造。
## Node Schema (spec-03 §1)
```yaml
node:
id: "N-01" # task node N-{nn}; milestone node M-{nn}
title: "契约骨架" # one line
type: task # task | milestone
acceptance_criteria: # "requirements" view — one falsifiable AC per line
- "AC-1: <可证伪的验收条件, 映射 test_id>"
- "NFR: <产品 NFR 条目>" # NFR:-prefixed entry — enumerated storage, no REQ-F number
req_refs: # functional-requirement references
- "REQ-F-001"
status: pending # pending | ready | in_progress | done | blocked | green(仅里程碑)
owner_session: null # assigned session id, null when unassigned
size_attrs: # decomposition-time measured attributes (spec-06)
cross_session_in: 1
cross_session_out: 1
contract_change: additive # none | additive | breaking (out-edge aggregation)
estimated_hours: 8 # task nodes only; milestone nodes omitted
estimated_sessions: 1 # task nodes only; milestone nodes omitted
```
Field semantics:
- `acceptance_criteria` — the node **is** its spec. Each AC is falsifiable and
maps a `test_id``{ file-path::test-name | MANUAL | BENCH:<script> }`
(the plan-iterations §6 SDD→TDD handshake; no other values). Entries MAY be
`NFR:`-prefixed (product NFRs — written into node AC as enumerated storage;
they carry no `REQ-F` number and are not functional ACs).
- `req_refs` — functional-requirement ids this node covers, derived from the
requirement registry (see below). Drives the REQMAP "every requirement ≥1
node / every node ≥1 requirement" mechanical check.
- `status` — drives rolling release (spec-04 RELEASE). `ready` = all
cross-session in-edge source nodes reached their terminal state (task `done`,
milestone `green`; same-session edges do not block). `green` is **milestone
only** (a task node's terminal state is `done`).
- `size_attrs` — decomposition-time measured inputs; the DAG-level `dag_metrics`
aggregates them. `estimated_hours` / `estimated_sessions` are **required only
for `type: task` nodes** (milestone nodes have no implementation work and
omit them). The two fields are two units of the same estimate; the
consistency invariant is `|estimated_hours 8 × estimated_sessions| ≤ 2`,
and **granularity is always judged by `estimated_sessions`** (1 session ≈ 8h).
## Edge Schema (spec-03 §2)
```yaml
edge:
from: "N-01" # source node id
to: "N-02" # target node id
contract_ref: "shared/types-v1" # contract pointer (wiki {epic-slug}/shared/ or schema $id)
cross_session: true # from/to owned by different sessions?
contract_state: draft # draft | frozen (only meaningful for task-to-task cross-session edges)
change_type: additive # none | additive | breaking (only cross-session edges)
```
Field semantics:
- `contract_ref` — the "design" view: where the contract lives. Cross-session
task edges point at wiki `{epic-slug}/shared/` or a schema `$id`; same-session
contracts may be inlined.
- `cross_session` — contract freezing applies **only** to `true` edges (spec-02 §1 D-05).
Same-session edges are `cross_session: false` (zero freeze cost).
- `contract_state``draft` (initial, freely revisable) → `frozen` (after the
single-gate PASS). Only meaningful for task-to-task cross-session edges.
- `change_type` — the contract change surface, feeding `contract_change_surface`.
**Milestone edge exception (frozen, spec-03 §2 / spec-02 §2.1):**
a milestone is a session-less integration point, so every edge connected to a
milestone (in + out) is `cross_session: true` but carries **NO `contract_ref`,
NO `change_type`**, and `contract_state` is **not applicable** (never frozen).
Milestone edges do not participate in `contract_change_surface` aggregation
(treated as `none`).
## Topology Constraints (spec-03 §3 — must satisfy, or TOPO fails)
1. **Acyclicity** — the directed graph must have no cycle. A cycle = BLOCKER.
2. **Milestone weld rule** — any node with `cross_session_in ≥ 2` (≥2
cross-session in-edges converging on it) MUST have a milestone `M` welded at
the convergence point, such that:
- (a) all cross-session in-edges terminate at `M` (M **is** the convergence
point — fan-in edges end at M, no separate original convergence task node);
- (b) M has no implementation work (`type: milestone`, no
`acceptance_criteria`, only a DoD);
- (c) M's DoD = integration verification of the converged scope (spec-05);
- (d) M is the **必经 (must-pass) node** for all downstream consumers —
downstream nodes may not become `ready` before M is `green`.
A convergence point with no downstream consumer is a sink milestone (in-edges
only).
3. **Granularity floor** — every `type: task` node's implementation estimate is
carried by `size_attrs.estimated_hours` / `estimated_sessions` (milestones
omit both). Judged by `estimated_sessions` (1 session ≈ 8h). The SINGLE
SOURCE of the judging criteria — floor/ceiling bounds, the severity
mapping (field-inconsistency, below-floor, above-ceiling, giant node), and
the folded checklist rows — is `core/checklists/dag-single-gate.md`
§TOPO: recalibrate there, not here. (One-line summary: sessions far below
the floor → merge candidates; far above → split/giant; hours-sessions
mismatch → field inconsistency.)
## Requirement Registry (需求登记表, spec-02 §2.9)
Maintained at the DAG root. Each row:
```yaml
- id: "REQ-F-001" # derived from the Epic scope-item number
title: "<需求标题>"
source: "<来源 scope item>"
refs_by: ["N-01", "N-02"] # node ids that reference this requirement
```
Rules:
- **Only functional requirements** (Epic scope items) get `REQ-F-{NNN}` numbers
and rows in the registry.
- **Product NFRs do NOT get `REQ-F` numbers** and are NOT registered as rows —
they are written into node `acceptance_criteria` as `NFR:`-prefixed entries
(enumerated storage), so "every NFR ≥1 node" is mechanically checkable via
node-AC enumeration.
- `refs_by` is derived from the REQMAP "every requirement ≥1 node" criterion
(missing coverage = a requirement with no node).
## Breadth Coverage — 类目覆盖矩阵 + 排除账本 ([org-internal #2905] 方案 1)
The four-stage fold that produced the single DAG artifact kept requirement
**depth** (REQMAP three-path coverage + falsifiable AC) but dropped legacy
elicitation's **breadth** scanning ("还有什么别的需求?"-style category
sweep). The registry above only registers what the proposer wrote — a
requirement nobody wrote does not exist in the system, and REQMAP's
bidirectional mapping checks *in-table* consistency, never `表 ↔ 现实`
completeness. The coverage matrix is the mechanical, enumerable part of the
compensation (three layers: artifact = matrix, graph = probe nodes, data =
`dag.route.preflight` learning loop; this section is the artifact layer).
analyze-dag MUST emit both sections in `{epic-slug}/dag` (template
`core/templates/dag.md` §2.1/§2.2):
1. **类目覆盖矩阵 (coverage matrix)** — the fixed category set (≤10
categories, extracted from legacy
`<instance-root>/archive/checklists/requirements-analysis.md`
CMP/SAF dimensions) × state ∈ {已覆盖, 明确排除, 待确认}. The category
list is FIXED in the template — do not invent or drop categories per
Epic; state is per-Epic.
- **已覆盖** — the category has registered demand (registry `REQ-F-{NNN}`
row or a node `NFR:` entry); evidence cell cites the id(s).
- **明确排除** — out of scope, with a ledger row (below). An exclusion
without a ledger row is NOT valid.
- **待确认** — intermediate state; MUST carry (向{确认人}确认{什么}) so it
is distinguishable from 漏了. 待确认 rows SHOULD be driven to a terminal
state (已覆盖/明确排除) before the draft is submitted to review-dag.
2. **排除账本 (exclusion ledger)** — one `E-n` row per exclusion:
条目 — out of scope, 理由, 确认人. Exclusions are reversible (delete the
row + flip the matrix state in the same revision).
**明确排除 ≠ 漏了 (distinguishability)**: excluded = matrix row 明确排除 +
ledger `E-n` row with reason and confirmer; 漏了 = blank state, or an "N/A"
without a ledger row. The single gate does NOT gain criteria for this —
REQMAP's three tables are frozen (spec-04 §1) and `表 ↔ 现实`
completeness is a **production-side obligation** of analyze-dag; reviewers
may still raise findings on the matrix as ordinary artifact content.
**Relation to the Product-Epic External-System Rule**: that rule is the
external-integration category applied to product Epics — the matrix
generalizes its shape from 1 category to N. For a product-type Epic the
外部系统集成 category remains mandatory-covered (task node or cross-session
contract edge, see the rule below). Process-infrastructure Epics will
typically 明确排除 most product-facing categories — that is legitimate;
the ledger records why.
**Page-size budget**: the matrix + ledger participate in the ≤800-line
budget (spec-02 §2.6). If the page exceeds, sink category DETAIL to
sub-page `{epic-slug}/dag-coverage` using the same mechanics as AC sinking
(in-page pointer, return link above the status line, version stamp rides the
frozen copy) — purely organizational, NOT an oversize signal, no
re-derivation.
### Breadth probe nodes (P2, [org-internal #2905] 方案 2)
When a 待确认 category is cheapest to resolve empirically, a **probe node**
is a legal task node at the granularity floor:
```yaml
- id: "N-07"
title: "探查:{类目} 存量/可行性核对"
type: task
acceptance_criteria:
- "AC-1: 产出 {类目} 结论(进/不进登记表)— MANUAL"
req_refs: ["REQ-F-00n"] # 指向被其澄清的需求;探查本身不派生新 REQ-F
status: pending
size_attrs:
cross_session_in: 0
cross_session_out: 0
contract_change: none
estimated_hours: 2
estimated_sessions: 0.25 # 粒度下限(Topology Constraints 3)——合法,不得更低
```
- `MANUAL` is a legal `test_id` value — a probe's deliverable is a human
verdict (matrix flip), not an automated test.
- A probe node anchors to an **existing** requirement it clarifies
(`req_refs` non-empty — REQMAP 节点溯源 requires it). A 待确认 category
with NO anchor requirement is resolved by confirmation (向确认人问询),
not by a probe node.
- The probe's conclusion flips the category: → 已覆盖 (new registry row +
covering nodes) or → 明确排除 (new ledger row). A conclusion landing
BEFORE freeze is ordinary draft revision (no signal).
- **登记表单独加行 ≡ node_split**(显式化):post-freeze 新增登记表行(新需求)
`node_split` oversize 信号处理——触发重派生 + 无条件重跑 review-dag、修订
冻结副本(新增需求必然改变节点集合或 `req_refs`;需要新节点时全额按
node_split 建单传播)。
### Data layer — read `dag.route.preflight` BEFORE decomposition ([org-internal #2905] 方案 3)
Before starting decomposition, analyze-dag MUST read
`<instance-root>/workflow-routing.yaml` `dag.route.preflight` and, when the list is
non-empty, verify each item as a producer self-check (the same injection
contract `implement` applies for `routes.{Kind}.preflight`, [org-internal #2599] — landed
items carry their retro evidence in `evidence`):
1. Read the `dag:` block's `route.preflight` array (live yaml, repo root).
2. For each item: run its `item` self-check against the Epic's scope /
breadth matrix before writing the DAG (items are typically recurring
late-discovery categories, e.g. the retro-derived
`REQ × late-discovery` class — requirements that surfaced only after
previous DAGs froze).
3. An item that fires becomes a 待确认 matrix row (or a probe node, above)
— never silently dropped.
4. Absent/empty array → no injection, proceed (current state: the list is
empty until a retro cycle lands evidence).
## dag_metrics (spec-03 §4 / spec-06)
Stored at the DAG root / Epic aggregator. Keys are frozen (spec-02 §2.6):
```yaml
dag_metrics:
node_count: 6 # task + milestone nodes total
cross_session_edge_count: 7 # total cross_session:true edges (milestone edges counted too)
contract_change_surface: additive # none | additive | breaking
review_depth: D4 # derived tier D1D4
```
- `contract_change_surface`**worst-value aggregation** of `change_type` across
cross-session **task edges only** (`breaking > additive > none`). Milestone
edges are excluded (treated as `none` — no contract, no `change_type`).
- `review_depth` — derived (decomposition **is** the sizing, 分解即定档):
```
review_depth = max(
depth_by(node_count),
depth_by(cross_session_edge_count),
depth_by(contract_change_surface)
)
```
Thresholds (spec-06 §2 — authoritative):
| Measured attribute | D1 | D2 | D3 | D4 |
| --- | --- | --- | --- | --- |
| `node_count` | ≤3 | ≤8 | ≤15 | >15 |
| `cross_session_edge_count` | 0 | — | 13 | ≥4 |
| `contract_change_surface` | none | — | additive | breaking |
- `cross_session_edge_count`: 0 → D1; 13 → D3; ≥4 → D4. **D2 is not derivable
from this dimension.**
- `contract_change_surface`: none → D1; additive → D3; breaking → D4 (D2 not
derivable from this dimension).
- `review_depth` is the review-dag review-resource parameter (reviewers / round
cap, spec-06 §3) — analyze-dag computes it; it does not assign `Size/*`
labels (DAG-routed tickets ignore `Size/*`).
## Page-Size Budget (spec-02 §2.6)
> Threshold single source: the page-size budget and the `> 页尺寸自检: 超限`
> signal are judged by `core/checklists/dag-single-gate.md` (TOPO 页尺寸自检信号
> row) — recalibrate there, not here. (One-line summary: the `{epic-slug}/dag`
> body has a line budget (~800 lines at calibration time); on breach, sink
> node detail to sub-pages and emit the self-check signal per the checklist
> row.)
The `{epic-slug}/dag` page body — node table + edge table + requirement registry
+ breadth coverage matrix (§2.1) + exclusion ledger (§2.2) + `dag_metrics`
must fit the checklist's page-size budget (see the single-source note above;
~800 lines at calibration time). On breach, analyze-dag MUST:
1. Sink node AC detail into sub-pages `{epic-slug}/dag-nodes/{node-id}`
(sub-page naming `{epic-slug}/dag-nodes/{node-id}` is **frozen**);
2. Keep an in-page pointer `{node-id} → {epic-slug}/dag-nodes/{node-id}` for
each sunk node;
3. Put a return-link line on each sub-page, **above** its status line:
`> 返回 [{epic-slug}/dag](…)`;
4. Write a page-size self-check signal into the DAG page header, **parallel to**
the `> DAG 工件状态` line:
`> 页尺寸自检: 超限({node-id} 已下沉子页)`.
Category detail (matrix/ledger 细目) may likewise sink to
`{epic-slug}/dag-coverage` (same mechanics — see Breadth Coverage). This is
**NOT** an `oversize_signal` and does **NOT** trigger re-derivation —
page overflow does not change the three derivation inputs
(`node_count` / `cross_session_edge_count` / `contract_change_surface`); sub-page
sinking is purely organizational. (Re-derivation is triggered only by the four
spec-06 §5 oversize signals.)
## Product-Epic External-System Rule (spec-04 §2 ARCH 1.1 alternative)
For a **product-type** Epic, external systems and integration protocols MUST
explicitly appear in the DAG — **either** as task nodes (with acceptance
criteria) **or** as cross-session contract edges (`contract_ref` pointing at an
external contract). This is what lets the REQMAP "需求覆盖" (requirement
coverage) check mechanically verify that external-integration requirements map
to nodes. (The `ARCH 1.1` system-context diagram is discarded only for
process-infrastructure-type Epics; product Epics get this alternative rule
instead.) [org-internal #2905]: this rule is the 外部系统集成 category of the breadth
coverage matrix held at its original strength — see Breadth Coverage above.
## Exec-Resource Configuration (spec-07 §4 — mechanical destination of folded checklist rows)
This clause is the **mechanically checkable destination** of the folded plan
checklist rows `RISK 3.73.10` / `EST 6.36.12` / `EXE 8.78.11` (single-gate
does not re-audit these — they live here, in the skill). A analyze-dag run MUST
observe:
| Resource | Configuration |
| --- | --- |
| Model tier assignment | reasoning-tier for decomposition; fast-tier for mechanical transcription (node/edge/registry/dag_metrics table assembly). reviewer-tier — i.e. the `Reviewer` Explorer role (`_shared/roles/reviewer.yaml`; the vocabulary the review skills use for reviewer dispatch is agent type Explorer) — is used **only** via the review-dag gate (see `review-artifact` target review-dag "Reviewer Constants": Model tier) — **never** inside analyze-dag. |
| Token budget | a single analyze-dag agent call's estimated token consumption must stay within the model's context-window capacity, and the `{epic-slug}/dag` page body ≤ 800 lines (page-size budget) bounds the artifact's token footprint. |
| Context-window ceiling | keep single-call consumption ≤ 70% of the model's context window. |
| RAG supplement | if the Epic's scope touches knowledge newer than the model's training cutoff, configure RAG supplementation before decomposition. |
| API-unavailable fallback | define a fallback path (retry / degrade to a lower tier / pause and report) when the model API is unavailable. |
| Deterministic tasks | deterministic tasks (mechanical transcription) run at `temperature ≤ 0.1`. |
| AI-artifact origin annotation | the DAG artifact is annotated with its origin — model + temperature + timestamp. |
## Output & Lifecycle
1. analyze-dag writes wiki page `{epic-slug}/dag` with first line:
`> DAG 工件状态: draft`.
2. After the single-gate (`review-dag`) PASS, the **aggregator agent** (main
session / Orchestrator — not analyze-dag) asks the freeze confirmation
question ([org-internal #3379]), then on confirmation flips the page to
`> DAG 工件状态: frozen` and stamps version `v1`. The confirmation is an
OPTIONIZED `question` call (stage `review-dag`, never `destructive`
freeze is a process gate, not a business decision): options
`Freeze as v1 (Recommended)` / `Hold — back to review`, plus a one-line
summary of the gate verdict (rounds, worst severity, open waivers) in the
question text. Choosing hold = do NOT flip — leave the page `draft`,
record the hold and the reason as a comment on the source Epic, and route
back to `review-artifact`. An unconfirmed flip is a spec violation: the
flip MUST be preceded by the question call in the same session, and the
confirmation leaves a trace — post a comment on the source Epic
(`DAG frozen: {epic-slug}/dag v1 — confirmed via question, {date}`) before
flipping. In autonomous runs the question auto-approves via its stage
(choosing the recommended freeze) — the gate guarantees the decision
SURFACES with a defined shape at a defined moment, not that a human
always attends it.
3. On each post-freeze re-review PASS (an oversize-signal re-run, spec-06
§5), the aggregator agent updates the frozen copy in place and increments
the version stamp `vN → vN+1` (no re-confirmation — only the initial
freeze gates on a decision).
## Backfill Input Mode (Kind/MVP graduation & big-bug relabels, [org-internal #3061])
When a `Kind/MVP` ticket graduates (relabel → `Kind/Feature` → Step 0 → this
skill), the DAG is derived from **what was actually built**, not from greenfield
decomposition:
- **Inputs**: the ticket body's `## 决策日志` (one line per decision: what /
why / expiry) + `## Debt Register` section + codegraph reverse call graph
of the implemented surface.
- **Nodes** follow the code's actual module/contract structure; each node's AC
traces to a decision-log line or an existing test. The decision log is the
REQMAP baseline for the single gate — decisions still marked deferred/expires
become explicit open questions on the Epic, not silent assumptions.
- **Debt register items** map to node ACs when they describe unfinished
behavior; remaining shortcuts stay debt (prototype/EVOLUTIONARY path →
verify Phase 5.5 registration).
- **Big-bug relabel inputs** (a `Kind/Bug` relabeled `Kind/Feature` per the
big-bug rule, `rules/workflow-routing.md` §"Runtime growth signals
(post-sizing)" — big-bug relabel rule): the repro
+ root-cause notes (wiki page `{slug}/repro-notes`) carry over as node
input — node ACs trace to the reproduction steps and root-cause findings,
and the root-cause analysis (not a decision log) serves as the REQMAP
baseline for the single gate.
- Disqualifiers STILL apply in backfill mode: an MVP whose decision log shows
unresolved conflicting deferred decisions bounces (stabilize first) instead
of freezing a contradictory graph.
## What analyze-dag does NOT do
- **No synthesis.** analyze-dag does not produce a synthesis — the review-artifact skill
Phase E produces the single-gate synthesis after review-dag converges.
- **No `## 工件索引` issue comment.** analyze-dag is a sub-agent; it does NOT
create the Epic's `## 工件索引` comment. The aggregator agent / main session
creates and maintains that comment (issue-cross-linking Pattern 10), and the
review / verify stages report their rows to it — analyze-dag only publishes the
`{epic-slug}/dag` artifact.
## References
- `core/templates/dag.md` — the DAG artifact structure contract (this skill writes `{epic-slug}/dag` against it; node/edge/milestone/dag_metrics shape + §6 topology constraints)
- `dag-pipeline/spec-02` — frozen contracts (§2.1 node/edge, §2.6 dag_metrics + page-size budget, §2.9 requirement registry + test_id)
- `dag-pipeline/spec-03` — node/edge schema + topology constraints
- `dag-pipeline/spec-04` — single-gate TOPO/REQMAP/RELEASE dimensions (folded-row destinations)
- `dag-pipeline/spec-06` — dag_metrics derivation + thresholds
- `dag-pipeline/spec-07` — dag.route landing row (entry skill, skip set, single-gate) + §4 landing list
- `dag-pipeline/spec-08` — DAG artifact lifecycle / version stamp
- `<instance-root>/archive/skills/roadmap/SKILL.md` — legacy route (archived 2026-08-21, [org-internal #3072] phase 3; this skill replaces it for all Epics)