feat: P1-21 ADR 变更级联失效 — 架构变更自动失效已完成任务

- TaskNode 新增 adr_refs 字段(ADR→任务溯源链)
- 新增 INVALIDATED 状态,允许覆盖 DONE/DISPATCHED
- TaskGraph.invalidate_by_adr() 级联失效 + BFS 下游传播
- PlanDelta 新增 rollback_ref(回滚快照引用)
- CascadeReport 数据结构(失效统计 + 任务ID列表)
- Eng dispatch_frozen 冻结调度,ready_tasks() 返回空
- handle_adr_invalidation() 10步处理流程(含 git revert)
- unfreeze_after_replan() Arc 重新规划后解冻
- AirRvr check_invalidated_cleanup() 检查旧代码残留
- INV-15 + L1 保障项 15 写入 SKILL.md
- 11 项功能测试全通过,含 ffmpeg→gstreamer 完整场景

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
AirLongDian
2026-06-11 11:13:53 +08:00
parent 19a4550830
commit f2f49d0094
6 changed files with 709 additions and 5 deletions

View File

@@ -78,10 +78,12 @@ def _ensure_dirs(paths: dict[str, Path]) -> None:
def _export_task_graph_json(graph: TaskGraph, path: Path) -> None:
data = {
"dispatchFrozen": graph.dispatch_frozen, # P1-21
"nodes": {nid: {"id": n.id, "status": n.status, "task": n.task,
"filesDirs": n.files_dirs, "doneWhen": n.done_when,
"inDegree": n.in_degree, "outEdges": n.out_edges,
"writeSet": n.write_set, "testRequired": n.test_required}
"writeSet": n.write_set, "testRequired": n.test_required,
"adrRefs": n.adr_refs} # P1-21
for nid, n in graph.nodes.items()},
"edges": [{"source": e.source, "target": e.target, "kind": e.kind} for e in graph.edges],
}
@@ -96,9 +98,14 @@ def _build_graph_from_todo(todo_path: Path) -> tuple[TaskGraph, list[str]]:
violations = [] # P1-19.1: 记录 Done When 不含"测试通过"的任务
for t in tasks:
# P1-21: 从 todo.md ADR 列提取 adr_refs
adr_refs = []
if hasattr(t, "adr") and t.adr:
adr_refs = [a.strip() for a in t.adr.split(",") if a.strip()]
node = TaskNode(
id=t.task_id, status=t.status, task=t.task,
files_dirs=t.files_dirs, done_when=t.done_when,
adr_refs=adr_refs,
)
graph.add_node(node)