@tea-agent/loop-agent 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +3 -2
  3. package/dist/application/dag/generate-task-dag.js +15 -0
  4. package/dist/application/dag/run-dag.js +10 -0
  5. package/dist/application/dag/validate-dag.js +11 -0
  6. package/dist/commands/init.js +74 -7
  7. package/dist/shared/package-metadata.js +135 -0
  8. package/dist/task/config-types.js +1 -0
  9. package/dist/worker/cli.js +3 -1
  10. package/dist/worker/observability/event-history.js +216 -0
  11. package/dist/worker/observability/read-model.js +312 -83
  12. package/dist/worker/observe/paths.js +17 -0
  13. package/dist/worker/observe/routes.js +165 -21
  14. package/dist/worker/observe/server.js +59 -1
  15. package/dist/worker/observe/static/api.js +27 -0
  16. package/dist/worker/observe/static/app.js +120 -2598
  17. package/dist/worker/observe/static/constants.js +148 -0
  18. package/dist/worker/observe/static/copy.js +67 -0
  19. package/dist/worker/observe/static/dag-helpers.js +172 -0
  20. package/dist/worker/observe/static/dag-model.js +72 -0
  21. package/dist/worker/observe/static/dom.js +61 -0
  22. package/dist/worker/observe/static/format-pool.js +67 -0
  23. package/dist/worker/observe/static/format.js +292 -0
  24. package/dist/worker/observe/static/index.html +300 -82
  25. package/dist/worker/observe/static/kpi.js +94 -0
  26. package/dist/worker/observe/static/relations.js +128 -0
  27. package/dist/worker/observe/static/router.js +85 -0
  28. package/dist/worker/observe/static/run-processing.js +148 -0
  29. package/dist/worker/observe/static/shell-chrome.js +68 -0
  30. package/dist/worker/observe/static/state.js +253 -0
  31. package/dist/worker/observe/static/styles.css +1719 -495
  32. package/dist/worker/observe/static/views/batch.js +226 -0
  33. package/dist/worker/observe/static/views/dag-graph.js +172 -0
  34. package/dist/worker/observe/static/views/dag-inspector.js +477 -0
  35. package/dist/worker/observe/static/views/dag.js +362 -0
  36. package/dist/worker/observe/static/views/dashboard.js +442 -0
  37. package/dist/worker/observe/static/views/failures.js +143 -0
  38. package/dist/worker/observe/static/views/feature.js +453 -0
  39. package/dist/worker/observe/static/views/pool.js +347 -0
  40. package/dist/worker/observe/static/views/run.js +453 -0
  41. package/dist/worker/observe/static/views/session-timeline.js +205 -0
  42. package/dist/worker/observe/static/views/shell.js +7 -0
  43. package/dist/worker/observe/static/views/task.js +260 -0
  44. package/dist/worker/observe/static/views/timeline.js +163 -0
  45. package/dist/workflows/dag/controller-identity.js +104 -0
  46. package/dist/workflows/dag/init-hybrid.js +396 -3
  47. package/dist/workflows/dag/node-execution.js +123 -29
  48. package/dist/workflows/dag/repair-artifact.js +91 -0
  49. package/dist/workflows/dag/report.js +50 -0
  50. package/dist/workflows/dag/retry-policy.js +138 -0
  51. package/dist/workflows/dag/runner.js +32 -0
  52. package/dist/workflows/dag/runtime-contract.js +87 -0
  53. package/dist/workflows/dag/skill-snapshot.js +2 -0
  54. package/dist/workflows/dag/types.js +44 -1
  55. package/dist/workflows/dag/validate.js +68 -4
  56. package/docs/agent-dag-runner.md +26 -1
  57. package/docs/architecture/dag-execution.md +6 -0
  58. package/docs/architecture/evolution.md +4 -3
  59. package/docs/architecture/facts-and-state.md +1 -1
  60. package/docs/design/README.md +4 -3
  61. package/docs/exec-plans/active/README.md +1 -3
  62. package/docs/exec-plans/completed/README.md +11 -0
  63. package/docs/feature-workflow.md +28 -0
  64. package/docs/progress/README.md +18 -0
  65. package/docs/reports/README.md +8 -2
  66. package/docs/templates/agent-dag-report.schema.json +17 -0
  67. package/docs/templates/agent-dag.schema.json +69 -1
  68. package/docs/templates/agent-dag.supervised-implementation.json +8 -2
  69. package/docs/templates/backend-test-dag.generate-pytest.prompt.md +139 -0
  70. package/docs/templates/backend-test-dag.json +276 -0
  71. package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -0
  72. package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -0
  73. package/package.json +1 -1
  74. package/skills/loop-agent/references/command-reference.md +1 -0
  75. package/skills/loop-agent/references/hybrid-dag.md +22 -3
  76. package/skills/loop-agent/references/verification-and-failure-handling.md +6 -0
@@ -17,7 +17,32 @@ loop-agent run-dag --dag <temp-dir>/<task-id>-dag.json --cwd .
17
17
  - `static`:确定性生成的 artifacts 或 notes
18
18
  - `shell`:验证与文件系统检查
19
19
  - `pi`:规划、review、诊断;节点设 `toolProfile: "write"` 时有界写入
20
- - `cursor`:显式启用时的可选有界写后端
20
+
21
+ ## Retry (read-only Pi nodes)
22
+
23
+ planner/scout/reviewer/verifier/closeout 角色的只读 Pi 节点可声明 opt-in `retryPolicy`,用于在同一 run 内有界重试模型连接中断、provider 限流、临时不可用或请求 timeout。生成器会为这些安全节点自动声明默认策略:总尝试次数 3(手工配置上限 5),指数退避,单次等待上限 30s。
24
+
25
+ - 仅以下原始失败分类默认可重试:`timeout`、`network`、`rate-limit`、`unavailable`。
26
+ - `quota`、`auth`、`invalid-output`、`write-guard`、`decision-envelope` 与未知失败不重试。`quota` 不是 rate limit,不会被自动重试。
27
+ - 资格由确定性 helper 判断:仅 `writePolicy=read-only|none`(或 Pi 默认只读)的 planner/scout/reviewer/verifier/closeout 可用。supervisor、implementer、writer(`toolProfile=write` 或 `writePolicy=exclusive`)、docs-only、dynamic、shell、static 与 decision-gate 节点一律不重试,DAG validation 会拒绝其策略。
28
+ - 每次 attempt 写入独立不可变证据(`<node-id>/attempt-<n>.json`,run-relative path),最终 node record 的 `attempts` 字段引用完整 attempt 历史;后一次成功不会覆盖前一次失败证据。
29
+ - 重试期间复用同一 run、controller identity、skill snapshot、prompt、model 与上游输入。节点终态的 `durationMs`、`tokensUsed`、`parsedEvents` 聚合全部 attempts;退避等待会刷新 `lastActivityAt`,避免被误判为 node-quiet。当前退避会占用该节点所在的并发槽。
30
+
31
+ 示例:
32
+
33
+ ```json
34
+ {
35
+ "retryPolicy": {
36
+ "maxAttempts": 3,
37
+ "backoff": "exponential",
38
+ "initialDelayMs": 2000,
39
+ "maxDelayMs": 30000,
40
+ "retryCategories": ["timeout", "network", "rate-limit", "unavailable"]
41
+ }
42
+ }
43
+ ```
44
+
45
+ 未声明 `retryPolicy` 的历史 DAG 行为不变(单次执行、无 `attempts` 字段,也不新增 attempt artifact)。
21
46
 
22
47
  ## Skills
23
48
 
@@ -34,6 +34,12 @@ src/commands/dag-validate.ts runDagValidate
34
34
  → src/application/dag/validate-dag.ts validateDagUseCase
35
35
  ```
36
36
 
37
+ ### runtime contract preflight 与 repair writer 解析
38
+
39
+ - `src/workflows/dag/runtime-contract.ts` `assertRuntimeContractCompatible` 依据 controller capabilities(`DAG_CONTROLLER_CAPABILITIES`:`agentRuntime="pi-only"`、`repairWriterProtocol="explicit-node-v1"`)校验 DagSpec v3 必需的 `runtimeContract`。v3 让旧 controller 在解析阶段拒绝;新 controller 的 `validateDagUseCase`、`runDagUseCase`、`runDag` 与 resume 还会校验 capability 和可选最低版本,不兼容在任何节点执行前 fail-fast。legacy v1/v2 DagSpec 可读但没有 v3 握手。
40
+ - `src/workflows/dag/repair-artifact.ts` `resolveRepairTaskForGate` 解析 `shell.repairArtifactGate`:优先显式 `repairNodeId`,否则推导唯一的下游受治理 Pi writer(`repairWriterContractIssues` 校验 executor/toolProfile/writePolicy/path 契约)。`validate.ts` 与 `node-execution.ts` 复用同一 resolver,runtime 不再按节点名硬编码。
41
+ - `src/workflows/dag/controller-identity.ts` 在 run 创建前要求 controller identity 可解析,再由 `captureControllerIdentity` 冻结到 `<runDir>/controller-identity.json`;`verifyControllerIdentityForResume` 在 resume 前重新校验并对漂移、篡改或 legacy-unpinned run fail closed。
42
+
37
43
  ## rank 调度
38
44
 
39
45
  拓扑排序与按 rank 执行的符号归属(校准版,勿笼统归到 `runner.ts`):
@@ -2,7 +2,7 @@
2
2
 
3
3
  本页区分 loop-agent **当前已实现**的架构能力与**未来规划**。当前事实以代码、发布 CLI、已完成计划为准;未来能力一律标「规划 / 未实现 / 前瞻」。权威源:`CHANGELOG.md`、`docs/reports/current-capability-summary.md`、ADR 0001–0003、`docs/exec-plans/completed/`。
4
4
 
5
- ## 当前已实现(0.10.0 + 主干 Unreleased
5
+ ## 当前已实现(0.11.0)
6
6
 
7
7
  | 域 | 现状 | 权威入口 |
8
8
  | --- | --- | --- |
@@ -12,7 +12,8 @@
12
12
  | 版本化自举 | controller identity + run-owned skill snapshot + deterministic canary | `docs/reports/2026-07-13-versioned-self-hosting-bootstrap.md` |
13
13
  | Feature 交付(M2) | review/run/approve-followup/delivery/closeout/verify-final | `docs/reports/2026-07-12-m2-completion-audit.md` |
14
14
  | Task Pool | 唯一根 `.harness/task-pool/` | ADR 0002 |
15
- | Observe | 本地只读暖白控制台(derived) | `website/docs/guides/observe-ui.md` |
15
+ | Observe | 本地只读暖白运营控制台 R1–R5(derived) | `website/docs/guides/observe-ui.md`、`CHANGELOG.md [0.11.0]` |
16
+ | DagSpec / repair | v3 + `runtimeContract`;显式 `repairNodeId` | `CHANGELOG.md [0.11.0]`、`dag-execution.md` |
16
17
  | 文档双树 | `website/docs/` 用法 vs `docs/` 治理;docs-converge | ADR 0003 |
17
18
  | 文档治理 | `docs/architecture/` 主题文档(本目录)+ package 可达 | 本目录 README |
18
19
 
@@ -24,7 +25,7 @@
24
25
 
25
26
  ## 未来规划(第 3–6 月,**未实现**)
26
27
 
27
- 以下能力来自 `docs/design/六个月规划.md` 与 `docs/design/dynamic-workflow-dag-engine-roadmap.md`(两文件均带 2026-07-14 校准条,未交付 phase 为**设计输入**,不是已实现证明)。它们**当前不存在于代码或 CLI**:
28
+ 以下能力来自 `docs/design/六个月规划.md` 与 `docs/design/dynamic-workflow-dag-engine-roadmap.md`(六个月规划页首 2026-07-15 / 0.11.0 校准;未交付 phase 为**设计输入**,不是已实现证明)。它们**当前不存在于代码或 CLI**:
28
29
 
29
30
  | 未来方向 | 状态 | 规划来源 |
30
31
  | --- | --- | --- |
@@ -15,7 +15,7 @@
15
15
 
16
16
  ### 区分要点
17
17
 
18
- - **Task vs DAG run**:Task 是用户意图的源(`source/`、需求、执行约束、artifacts);DAG run 是一次执行实例,`<runId>/` 下落 spec、state、节点 artifacts、skill snapshot、decision envelope、convergence。
18
+ - **Task vs DAG run**:Task 是用户意图的源(`source/`、需求、执行约束、artifacts);DAG run 是一次执行实例,`<runId>/` 下落 spec、state、节点 artifacts、skill snapshot、controller identity(`controller-identity.json`,冻结执行 controller 的 package version/binary 哈希/portable fingerprint,state 记录相对 ref 与内容哈希,resume 时重新校验、漂移 fail closed)、decision envelope、convergence。
19
19
  - **DAG run vs one-shot run**:DAG run 在 `.harness/dag-runs/`,有三态 lifecycle;one-shot run(当前主要由 `cursor-prompt` 及显式 one-shot evidence 路径产生)在 `.harness/runs/`,三态为 `active|completed|failed`。`pi-prompt` 当前不创建该目录下的 run evidence。两者是不同根、不同 schema。
20
20
  - **Loop 不是顶层根**:Loop 状态在 `.harness/tasks/<taskId>/loop/`,是 task 之上的多轮状态机(round、signal、context、failureStreak、closeout)。
21
21
  - **Task Pool 是 Worker 专用可选根**:只有使用 `agent-worker` 产品线时才存在;唯一根 `.harness/task-pool/`。
@@ -16,10 +16,10 @@
16
16
  | 文档 | 用途 |
17
17
  |---|---|
18
18
  | `dynamic-workflow-dag-engine-roadmap.md` | Dynamic Workflow 适配分析与阶段规划;**页首有实现状态 / Pi-only 校准条**(已落地 vs 设计输入);正文 Cursor 叙述视为历史 |
19
- | `六个月规划.md` | 长期路线;**第 1–2 月已收敛为 archive/reports 指针**,当前有效前瞻从第 3 月起 |
20
- | `产品线共享知识库.md` | 产品线文档仓库作为上游事实源 |
19
+ | `六个月规划.md` | 长期路线;**页首 2026-07-15 / 0.11.0 校准**;第 1–2 月为 archive/reports 指针,当前有效前瞻从第 3 月起 |
20
+ | `产品线共享知识库.md` | 产品线文档仓库作为上游事实源;**页首 2026-07-15 / 0.11.0 校准**(模板+Feature dogfood 已落地 vs docs-sync 未来) |
21
21
  | `研发模式.md` | 10 个工作日 Feature 团队工作流 |
22
- | `腾讯实践对当前项目的指引.md` | 腾讯 Harness Engineering 实践对本仓库的映射笔记 |
22
+ | `腾讯实践对当前项目的指引.md` | 腾讯 Harness Engineering 实践对本仓库的映射笔记;源文见 `website/docs/practices/tencent-harness-engineering/index.md` |
23
23
 
24
24
  ## 视觉参考
25
25
 
@@ -39,6 +39,7 @@
39
39
  | `archive/2026-07-10-observe-ui.md` | 已归档:Observe UI v0 设计(OBS-001~010;0.9.0 暖白重设计在其上演进) |
40
40
  | `archive/2026-07-10-observe-ui-optimization.md` | 已归档:Observe UI 中文化与过程时间线(UI-1~UI-9 已实现) |
41
41
  | `archive/2026-07-10-observe-ui-goal.md` | 已归档:OBS-001~010 逐任务进度看板(全部 done) |
42
+ | `archive/2026-07-14-observe-ui-roadmap.md` | 已归档:Observe R1–R5 运营控制台路线图(资源池/Batch-Run/Feature 关联/事件时间线/前端模块化;证据见 completed plans + reports) |
42
43
  | `archive/2026-07-11-第一月规划.md` | 已归档:首月落地计划(0.8.0 + Round 1/2/3 闭环) |
43
44
  | `archive/2026-07-11-第一月wbs.md` | 已归档:首月 WBS 与分工(历史记录) |
44
45
  | `archive/2026-07-12-第二月规划.md` | 已归档:第二月本地 Feature 交付闭环(M2-01~08;见 `docs/reports/2026-07-12-m2-completion-audit.md`) |
@@ -6,6 +6,4 @@
6
6
 
7
7
  当前 active execution plan:
8
8
 
9
- - 暂无。
10
-
11
- - 已归档:`../completed/2026-07-14-init-canonical-layout.md`、`../completed/2026-07-12-observe-warm-console-redesign.md`、`../completed/2026-07-14-website-docs-ia-and-converge.md`、`../completed/2026-07-13-versioned-self-hosting-bootstrap.md`、`../completed/2026-07-12-pi-only-agent-runtime.md`、第二月 M2-01~M2-08、`../completed/2026-07-11-observe-dashboard-page-system.md`、`../completed/2026-07-11-observe-dashboard-detail-refinement.md`、`../completed/2026-07-11-observe-terminal-dag-kpi.md`、`../completed/2026-07-11-observe-polling-efficiency.md`、`../completed/2026-07-11-command-performance-guardrails.md` 及更早计划。
9
+ - 已归档:`../completed/2026-07-15-repair-artifact-gate-runtime-contract.md`、`../completed/2026-07-14-observe-ui-r5.md`、`../completed/2026-07-14-observe-ui-r4.md`、`../completed/2026-07-14-observe-ui-r3.md`、`../completed/2026-07-14-observe-ui-r2.md`、`../completed/2026-07-14-observe-ui-r1.md`、`../completed/2026-07-14-init-canonical-layout.md`、`../completed/2026-07-12-observe-warm-console-redesign.md`、`../completed/2026-07-14-website-docs-ia-and-converge.md`、`../completed/2026-07-13-versioned-self-hosting-bootstrap.md`、`../completed/2026-07-12-pi-only-agent-runtime.md`、第二月 M2-01~M2-08、`../completed/2026-07-11-observe-dashboard-page-system.md`、`../completed/2026-07-11-observe-dashboard-detail-refinement.md`、`../completed/2026-07-11-observe-terminal-dag-kpi.md`、`../completed/2026-07-11-observe-polling-efficiency.md`、`../completed/2026-07-11-command-performance-guardrails.md` 及更早计划。
@@ -4,6 +4,13 @@
4
4
 
5
5
  npm 包携带本 README 作为目录契约。具体 completed plan 属于目标仓库历史,不从 loop-agent 源码历史复制。
6
6
 
7
+ - [`2026-07-15-repair-artifact-gate-runtime-contract.md`](2026-07-15-repair-artifact-gate-runtime-contract.md) — 显式 `repairNodeId` + 严格 repair writer 契约、DagSpec `runtimeContract` capability preflight,以及 run-owned controller identity(resume 漂移 fail-closed)
8
+ - [`2026-07-14-backend-test-dag-template.md`](2026-07-14-backend-test-dag-template.md) — 通过 `taskKind: "backend-test"` 生成需求分析、功能用例、pytest 自动化、执行与复盘的 Pi-only 专用 DAG
9
+ - [`2026-07-14-observe-ui-r5.md`](2026-07-14-observe-ui-r5.md) — Observe 原生 ES module 拆分、四态 helper、Pool hash 筛选与入口 re-export
10
+ - [`2026-07-14-observe-ui-r4.md`](2026-07-14-observe-ui-r4.md) — Observe Batch/Pool 有界事件时间线、cursor/limit、JSONL 容量与投影 fault-first
11
+ - [`2026-07-14-observe-ui-r2.md`](2026-07-14-observe-ui-r2.md) — Observe Batch / Worker Run 证据化详情、三层只读结构与安全 artifact preview
12
+ - [`2026-07-14-observe-ui-r3.md`](2026-07-14-observe-ui-r3.md) — Observe Feature 决策详情、copy-only 建议命令与 canonical 对象关系导航
13
+ - [`2026-07-14-observe-ui-r1.md`](2026-07-14-observe-ui-r1.md) — Observe 资源池总览、Task 下钻、精确对象关联与有界 run history
7
14
  - [`2026-07-14-init-canonical-layout.md`](2026-07-14-init-canonical-layout.md) — 目标项目治理资料统一到 `ai_workspace/loop-agent/` 与 `.agents/skills/`,并为旧布局提供保守安全迁移
8
15
  - [`2026-07-14-self-update-notifier-implementation.md`](2026-07-14-self-update-notifier-implementation.md) — 实现 loop-agent CLI 自更新提醒,覆盖拒绝版本、精确安装、npm global 来源证明和验证收口
9
16
  - [`2026-07-12-observe-warm-console-redesign.md`](2026-07-12-observe-warm-console-redesign.md) — 以暖白、细边界和高密度信息架构重构 Observe Dashboard;多轮细节调整后按用户确认收口归档。
@@ -60,3 +67,7 @@ npm 包携带本 README 作为目录契约。具体 completed plan 属于目标
60
67
  - [`2026-07-10-observe-ui-review-remediation.md`](2026-07-10-observe-ui-review-remediation.md) — 修复 Observe UI 事件链路、历史 run 投影、artifact 安全边界与失败状态展示
61
68
 
62
69
  - [`2026-07-13-exec-plan-lifecycle.md`](2026-07-13-exec-plan-lifecycle.md)
70
+
71
+ - [`2026-07-15-readonly-node-retry.md`](2026-07-15-readonly-node-retry.md)
72
+
73
+ - [`2026-07-15-init-update-surface-coverage.md`](2026-07-15-init-update-surface-coverage.md)
@@ -121,6 +121,30 @@ frontend-contract-pi
121
121
  ```
122
122
 
123
123
  这条链在实现前加入 design gate,并将前端静态验证与行为验证分开建模;当前 MVP 不包含独立 a11y、视觉回归或浏览器自动化 executor。
124
+
125
+ 后端测试任务可通过 `task.json.taskKind = "backend-test"` 选择专用模板;它不新增 governance profile:
126
+
127
+ ```text
128
+ analyze-inputs-pi
129
+ -> generate-backend-functional-cases-pi
130
+ -> review-backend-cases-pi
131
+ -> review-backend-cases-gate-shell
132
+ -> generate-backend-pytest-pi
133
+ -> execute-backend-pytest-shell
134
+ -> test-retrospect-pi
135
+ ```
136
+
137
+ 这条链覆盖后端功能测试从需求分析到复盘评级的全链路流程:
138
+
139
+ 1. **analyze-inputs-pi**:读取需求.md 和开发详设等参考文档,产出端到端测试分析契约(范围、风险、策略要点)
140
+ 2. **generate-backend-functional-cases-pi**:根据契约生成结构化后端功能测试用例(Markdown),用例 ID 带 `BE-` 前缀(如 `BE-ORDER-001`),写入 `testcase/md/`
141
+ 3. **review-backend-cases-pi**:评审后端功能测试用例,输出审查报告 + `VERDICT: pass` / `VERDICT: request-revision`
142
+ 4. **review-backend-cases-gate-shell**:只有评审首条 verdict 为 `VERDICT: pass` 时才允许继续生成 pytest
143
+ 5. **generate-backend-pytest-pi**:将后端功能用例转化为 pytest 自动化代码,仅写入 `testcase/**/test_*.py`
144
+ 6. **execute-backend-pytest-shell**:执行 `pytest testcase/` 并生成 HTML 报告
145
+ 7. **test-retrospect-pi**:读取上游审查报告和测试报告,生成复盘报告 + 成熟度评级(A/B/C/D)
146
+
147
+ 前端测试模板(`frontend-test-dag`)后续沿用对称命名即可接入。
124
148
  前端 shell 验证优先使用任务源 `需求.md` / `执行约束.md` 中声明的前端验证命令,例如 `npm run typecheck`、`npm run build`、`npm test`;解析不到时再使用 adapter 验证命令和模板 fallback。
125
149
 
126
150
  `verify-shell` 使用 adapter 根据 task verify preset/quota 解析出的最终验证命令,并把新鲜 exit code/stdout/stderr 交给后续只读 verifier。review-gated 模板继续插入:
@@ -131,6 +155,10 @@ verify-shell -> verify-pi -> review-pi -> review-gate-shell -> closeout-pi
131
155
 
132
156
  supervised 模板在实现路径上增加 write-set audit、soft/hard shell 验证、process supervision、有界 repair、decision gates 与可选 convergence retry。
133
157
 
158
+ ### 只读 Pi 节点安全重试
159
+
160
+ 所有生成模板都会为安全的只读 Pi 节点(planner/scout/reviewer/verifier/closeout,且 `writePolicy=read-only|none`、非 writer、非 dynamic、非 decision-gate)自动声明默认 `retryPolicy`(总尝试 3 次,手工配置最多 5 次,指数退避,单次等待上限 30s)。supervisor 与 implementer 明确不在资格范围。仅重试 `timeout`、`network`、`rate-limit`、`unavailable`;`quota`、`auth`、`invalid-output`、`write-guard` 与未知失败不重试。每次 attempt 保留独立证据,详见 [docs/agent-dag-runner.md](./agent-dag-runner.md#retry-read-only-pi-nodes)。
161
+
134
162
  ### 可选 repo-local SDD skill 增强
135
163
 
136
164
  `dag run-task` 会在目标项目的 `.agents/skills/` 中探测三个可选 skill:
@@ -6,6 +6,15 @@
6
6
 
7
7
  ## 近期要点(导读)
8
8
 
9
+ - [`2026-07-15-init-update-surface-coverage.md`](2026-07-15-init-update-surface-coverage.md) — 修复初始化 surface 升级漏检(自动发现 copied 文件、blockedTargetPaths fail-safe、drift gate)实施交接(已验证)
10
+ - [`2026-07-15-readonly-node-retry.md`](2026-07-15-readonly-node-retry.md) — 只读 Pi DAG 节点安全重试(默认策略、attempt 证据、validation 门禁)实施交接(已验证)
11
+ - [`2026-07-15-repair-artifact-gate-runtime-contract-implementation.md`](2026-07-15-repair-artifact-gate-runtime-contract-implementation.md) — 显式 repairNodeId、runtime contract preflight 与 run-owned controller identity 实施交接(已验证)
12
+ - [`2026-07-14-observe-ui-r5-boundary-final.md`](2026-07-14-observe-ui-r5-boundary-final.md) — R5 轻量入口与显式模块边界 DAG closeout
13
+ - [`2026-07-14-observe-ui-r5-remediation.md`](2026-07-14-observe-ui-r5-remediation.md) — R5 浏览器状态所有权修复 DAG closeout
14
+ - [`2026-07-14-observe-ui-r5.md`](2026-07-14-observe-ui-r5.md) — Observe 前端模块化与体验收敛(已验证)
15
+ - [`2026-07-14-observe-ui-r4.md`](2026-07-14-observe-ui-r4.md) — Observe 事件时间线、有界 JSONL 与投影健康(已验证)
16
+ - [`2026-07-14-observe-ui-r3.md`](2026-07-14-observe-ui-r3.md) — Observe Feature 决策详情与对象关联导航(已验证)
17
+ - [`2026-07-14-observe-ui-r2.md`](2026-07-14-observe-ui-r2.md) — Observe Batch / Worker Run 证据化详情收口
9
18
  - [`2026-07-14-init-canonical-layout-handoff.md`](2026-07-14-init-canonical-layout-handoff.md) — 目标项目初始化布局迁移到 `ai_workspace/loop-agent/` 与 `.agents/skills/` 的跨会话交接
10
19
  - [`2026-07-14-self-update-notifier-implementation.md`](2026-07-14-self-update-notifier-implementation.md) — loop-agent CLI 自更新提醒实现、TDD 验证和 bounded DAG fallback 交接
11
20
  - [`2026-07-14-docs-living-docs-calibration.md`](2026-07-14-docs-living-docs-calibration.md) — 活文档校准(Dynamic Workflow / 六个月 / ADR)
@@ -18,6 +27,15 @@
18
27
 
19
28
  ## 全量列表(新→旧)
20
29
 
30
+ - [`2026-07-15-init-update-surface-coverage.md`](2026-07-15-init-update-surface-coverage.md)
31
+ - [`2026-07-15-readonly-node-retry.md`](2026-07-15-readonly-node-retry.md)
32
+ - [`2026-07-15-repair-artifact-gate-runtime-contract-implementation.md`](2026-07-15-repair-artifact-gate-runtime-contract-implementation.md)
33
+ - [`2026-07-14-observe-ui-r5-boundary-final.md`](2026-07-14-observe-ui-r5-boundary-final.md)
34
+ - [`2026-07-14-observe-ui-r5-remediation.md`](2026-07-14-observe-ui-r5-remediation.md)
35
+ - [`2026-07-14-observe-ui-r5.md`](2026-07-14-observe-ui-r5.md)
36
+ - [`2026-07-14-observe-ui-r4.md`](2026-07-14-observe-ui-r4.md)
37
+ - [`2026-07-14-observe-ui-r3.md`](2026-07-14-observe-ui-r3.md)
38
+ - [`2026-07-14-observe-ui-r2.md`](2026-07-14-observe-ui-r2.md)
21
39
  - [`2026-07-14-init-canonical-layout-handoff.md`](2026-07-14-init-canonical-layout-handoff.md)
22
40
  - [`2026-07-14-self-update-notifier-implementation.md`](2026-07-14-self-update-notifier-implementation.md)
23
41
  - [`2026-07-14-website-docs-ia-and-converge.md`](2026-07-14-website-docs-ia-and-converge.md)
@@ -8,11 +8,14 @@
8
8
 
9
9
  - 按日期前缀浏览下方列表(新→旧)
10
10
  - init surface 审查:文件名含 `init-evolution-review`
11
- - 能力基线滚动分析:[`2026-07-02-repository-analysis.md`](2026-07-02-repository-analysis.md)(长文,非单次任务证据)
11
+ - 能力基线滚动分析:[`2026-07-02-repository-analysis.md`](2026-07-02-repository-analysis.md)(**已冻结**;2026-07-15 最终再采样关闭 0.11.0;非第二 CHANGELOG)
12
12
 
13
13
  ## 近期要点(导读,非权威全集)
14
14
 
15
15
  - [`current-capability-summary.md`](current-capability-summary.md) — **活**能力摘要(新进展写这里 / CHANGELOG / 新 report)
16
+ - [`2026-07-15-init-update-surface-coverage-init-evolution-review.md`](2026-07-15-init-update-surface-coverage-init-evolution-review.md) — 初始化 surface 升级漏检修复的 init surface 审查(init update required)
17
+ - [`2026-07-15-readonly-node-retry-init-evolution-review.md`](2026-07-15-readonly-node-retry-init-evolution-review.md) — 只读 Pi DAG 节点安全重试的 init surface 审查(surface check only,无需 init evolution)
18
+ - [`2026-07-15-backend-test-dag-init-evolution-review.md`](2026-07-15-backend-test-dag-init-evolution-review.md) — 后端测试专用 DAG 的 package/init surface 审查
16
19
  - [`2026-07-15-init-canonical-layout-init-evolution-review.md`](2026-07-15-init-canonical-layout-init-evolution-review.md) — init canonical layout、旧布局安全迁移和废弃 harness 字段清理审查
17
20
  - [`2026-07-14-self-update-notifier-implementation.md`](2026-07-14-self-update-notifier-implementation.md) — loop-agent CLI 自更新提醒实现、DAG 边界、TDD 与 init surface 非影响证据
18
21
  - [`2026-07-14-docs-living-docs-calibration.md`](2026-07-14-docs-living-docs-calibration.md) — 活文档校准(Dynamic Workflow / 六个月 / analysis 冻结 / ADR)
@@ -21,10 +24,13 @@
21
24
  - [`2026-07-13-sdd-embedded-skills.md`](2026-07-13-sdd-embedded-skills.md) — repo-local SDD skill 嵌入增强的 DAG、TDD、独立审查、验证和基线风险证据
22
25
  - [`2026-07-13-versioned-self-hosting-bootstrap.md`](2026-07-13-versioned-self-hosting-bootstrap.md) — 版本化自举证据
23
26
  - [`2026-07-12-m2-completion-audit.md`](2026-07-12-m2-completion-audit.md) — 第二月完成审计
24
- - [`2026-07-02-repository-analysis.md`](2026-07-02-repository-analysis.md) — **已冻结**仓库能力基线快照(勿再当 CHANGELOG)
27
+ - [`2026-07-02-repository-analysis.md`](2026-07-02-repository-analysis.md) — **已冻结**仓库能力基线快照(2026-07-15 最终再采样至 0.11.0;勿再当 CHANGELOG)
25
28
 
26
29
  ## 全量列表(新→旧)
27
30
 
31
+ - [`2026-07-15-init-update-surface-coverage-init-evolution-review.md`](2026-07-15-init-update-surface-coverage-init-evolution-review.md)
32
+ - [`2026-07-15-readonly-node-retry-init-evolution-review.md`](2026-07-15-readonly-node-retry-init-evolution-review.md)
33
+ - [`2026-07-15-backend-test-dag-init-evolution-review.md`](2026-07-15-backend-test-dag-init-evolution-review.md)
28
34
  - [`2026-07-15-init-canonical-layout-init-evolution-review.md`](2026-07-15-init-canonical-layout-init-evolution-review.md)
29
35
  - [`dogfood-preflight-static-20260709090443.md`](dogfood-preflight-static-20260709090443.md)
30
36
  - [`current-capability-summary.md`](current-capability-summary.md)
@@ -444,6 +444,23 @@
444
444
  },
445
445
  "pausedByNodeId": { "type": "string" },
446
446
  "pauseReason": { "type": "string" },
447
+ "controllerIdentity": {
448
+ "type": "object",
449
+ "additionalProperties": false,
450
+ "required": ["status", "capturedAt", "runtimeContractCompatibility"],
451
+ "properties": {
452
+ "status": { "enum": ["pinned", "legacy-unpinned"] },
453
+ "capturedAt": { "type": "string" },
454
+ "packageName": { "type": "string" },
455
+ "packageVersion": { "type": "string" },
456
+ "packageFingerprint": { "type": "string" },
457
+ "binarySha256": { "type": "string" },
458
+ "runtimeContractCompatibility": {
459
+ "enum": ["compatible", "incompatible", "legacy-unspecified"]
460
+ },
461
+ "runtimeContractReason": { "type": "string" }
462
+ }
463
+ },
447
464
  "executorJsonl": { "$ref": "#/$defs/dagArtifactRef" },
448
465
  "convergence": { "$ref": "#/$defs/dagConvergence" },
449
466
  "nodes": {
@@ -5,18 +5,29 @@
5
5
  "type": "object",
6
6
  "additionalProperties": false,
7
7
  "required": ["version", "title", "tasks"],
8
+ "allOf": [
9
+ {
10
+ "if": { "properties": { "version": { "const": 3 } }, "required": ["version"] },
11
+ "then": { "required": ["runtimeContract"] }
12
+ },
13
+ {
14
+ "if": { "required": ["runtimeContract"] },
15
+ "then": { "properties": { "version": { "const": 3 } } }
16
+ }
17
+ ],
8
18
  "properties": {
9
19
  "$schema": {
10
20
  "type": "string"
11
21
  },
12
22
  "version": {
13
- "enum": [1, 2],
23
+ "enum": [1, 2, 3],
14
24
  "default": 1
15
25
  },
16
26
  "title": {
17
27
  "type": "string",
18
28
  "minLength": 1
19
29
  },
30
+ "runtimeContract": { "$ref": "#/$defs/runtimeContract" },
20
31
  "objective": {
21
32
  "type": "string"
22
33
  },
@@ -72,6 +83,21 @@
72
83
  "required": ["models"]
73
84
  },
74
85
  "$defs": {
86
+ "runtimeContract": {
87
+ "type": "object",
88
+ "additionalProperties": false,
89
+ "required": ["schemaVersion", "agentRuntime", "repairWriterProtocol"],
90
+ "description": "DagSpec v3 controller capability handshake. Compatibility is decided by capability fields first; minimumControllerVersion is enforced when present. Legacy v1/v2 DAGs may omit this block.",
91
+ "properties": {
92
+ "schemaVersion": { "const": 1 },
93
+ "agentRuntime": { "const": "pi-only" },
94
+ "repairWriterProtocol": { "const": "explicit-node-v1" },
95
+ "minimumControllerVersion": {
96
+ "type": "string",
97
+ "pattern": "^\\d+\\.\\d+\\.\\d+([-+].+)?$"
98
+ }
99
+ }
100
+ },
75
101
  "complexity": {
76
102
  "enum": ["LOW", "MED", "HIGH"]
77
103
  },
@@ -140,6 +166,11 @@
140
166
  "fromNodeId": {
141
167
  "type": "string",
142
168
  "pattern": "^[a-z][a-z0-9-]*$"
169
+ },
170
+ "repairNodeId": {
171
+ "type": "string",
172
+ "pattern": "^[a-z][a-z0-9-]*$",
173
+ "description": "Explicit governed Pi repair writer this gate feeds (executor=pi, toolProfile=write, writePolicy=exclusive, non-empty allowedPaths+writeSet, depends_on the gate). New DAGs must set this; legacy DAGs are only accepted when a unique safe downstream Pi writer can be derived."
143
174
  }
144
175
  }
145
176
  },
@@ -211,6 +242,39 @@
211
242
  "status": { "enum": ["success", "error"] }
212
243
  }
213
244
  },
245
+ "retryPolicy": {
246
+ "type": "object",
247
+ "additionalProperties": false,
248
+ "required": ["maxAttempts"],
249
+ "description": "Retry policy for safe read-only planner/scout/reviewer/verifier/closeout Pi nodes. Total attempts include the first try and are capped at five. Supervisors, implementers, and side-effecting nodes are ineligible. Only the categories listed in retryCategories are retried; quota/auth/invalid-output/write-guard are never retried.",
250
+ "properties": {
251
+ "maxAttempts": {
252
+ "type": "integer",
253
+ "minimum": 1,
254
+ "maximum": 5,
255
+ "description": "Total attempts including the first try. 1 disables retry."
256
+ },
257
+ "backoff": { "const": "exponential", "default": "exponential" },
258
+ "initialDelayMs": {
259
+ "type": "integer",
260
+ "minimum": 0,
261
+ "default": 2000
262
+ },
263
+ "maxDelayMs": {
264
+ "type": "integer",
265
+ "minimum": 0,
266
+ "default": 30000
267
+ },
268
+ "retryCategories": {
269
+ "type": "array",
270
+ "items": {
271
+ "enum": ["timeout", "network", "rate-limit", "unavailable"]
272
+ },
273
+ "default": ["timeout", "network", "rate-limit", "unavailable"],
274
+ "description": "Failure categories eligible for retry. quota is never eligible."
275
+ }
276
+ }
277
+ },
214
278
  "promptSource": {
215
279
  "type": "object",
216
280
  "additionalProperties": false,
@@ -296,6 +360,10 @@
296
360
  "default": "record-only"
297
361
  }
298
362
  }
363
+ },
364
+ "retryPolicy": {
365
+ "$ref": "#/$defs/retryPolicy",
366
+ "description": "Opt-in retry policy. Allowed only on safe read-only planner/scout/reviewer/verifier/closeout non-dynamic Pi nodes; validation rejects it on supervisors, implementers, writers, dynamic, shell, static, docs-only, and decision-gate nodes. Generated DAGs declare the default policy on eligible nodes automatically."
299
367
  }
300
368
  },
301
369
  "oneOf": [
@@ -1,7 +1,12 @@
1
1
  {
2
2
  "$schema": "./agent-dag.schema.json",
3
- "version": 2,
3
+ "version": 3,
4
4
  "title": "Agent DAG supervised implementation template",
5
+ "runtimeContract": {
6
+ "schemaVersion": 1,
7
+ "agentRuntime": "pi-only",
8
+ "repairWriterProtocol": "explicit-node-v1"
9
+ },
5
10
  "objective": "Demonstrate a reusable supervised implementation DAG: contract → parallel scouts → plan → write-set audit → write-set gate → implement → soft verify → process supervisor → repair → hard verify → review verdict → review gate → decision gate → closeout. Write-set, process, and review verdict nodes emit first-line VERDICT for deterministic gates, reducing main-session intervention.",
6
11
  "successCriteria": [
7
12
  "contract-pi returns a read-only implementation contract with narrow write boundaries",
@@ -318,7 +323,8 @@
318
323
  "lineMode": "first-verdict-line"
319
324
  },
320
325
  "repairArtifactGate": {
321
- "fromNodeId": "process-supervisor-pi"
326
+ "fromNodeId": "process-supervisor-pi",
327
+ "repairNodeId": "repair-pi"
322
328
  },
323
329
  "cwd": ".",
324
330
  "timeoutMs": 60000
@@ -0,0 +1,139 @@
1
+ # Backend Test DAG Generate Pytest Prompt Template
2
+
3
+ ## Purpose
4
+
5
+ Use this prompt for a **pytest code generation** node: `executor: "pi"`, `role: "implementer"`, `toolProfile: "write"`, `writePolicy: "exclusive"`. The implementer converts reviewed backend functional test cases into pytest automation code with 1:1 traceability.
6
+
7
+ Do **not** create a new executor type. This is a standard `executor: pi` writer node.
8
+
9
+ ## Recommended DAG Node Shape
10
+
11
+ ```json
12
+ {
13
+ "id": "generate-backend-pytest-pi",
14
+ "depends_on": ["review-backend-cases-gate-shell"],
15
+ "complexity": "HIGH",
16
+ "executor": "pi",
17
+ "role": "implementer",
18
+ "toolProfile": "write",
19
+ "writePolicy": "exclusive",
20
+ "writeSet": ["testcase/**/test_*.py"],
21
+ "allowedPaths": ["testcase/**/test_*.py"],
22
+ "forbiddenPaths": [".harness/**", "artifacts/**"],
23
+ "outputContract": "Pytest test files under tests/backend/ with 1:1 mapping to functional test case IDs. Summary lists generated files, test function count, and any skipped cases with reasons.",
24
+ "subtask_prompt_markdown": "./backend-test-dag.generate-pytest.prompt.md"
25
+ }
26
+ ```
27
+
28
+ ## Prompt Body
29
+
30
+ You are the Backend Test DAG **pytest code generator**.
31
+
32
+ Your job is to convert reviewed test cases under `testcase/md/` into pytest automation code. Write test files under `testcase/` only. Stay within `writeSet`. Do not write root `artifacts/**`.
33
+
34
+ ### Output Steps (do in order)
35
+
36
+ 1. First, output a brief summary: how many files, how many test functions planned
37
+ 2. Then write each test file under `testcase/`
38
+
39
+ ### Inputs
40
+
41
+ 1. **Reviewed test cases** — files under `testcase/md/` (approved by `review-backend-cases-pi`).
42
+ 2. **Target project conventions** — read `conftest.py`, `pytest.ini` / `pyproject.toml` to understand conventions, but do NOT modify them.
43
+
44
+ Do NOT re-read source documents. Use the reviewed cases only.
45
+
46
+ ### Conversion Rules
47
+
48
+ #### File Naming
49
+
50
+ - Every test file must start with `test_` prefix (e.g. `test_order.py`, `test_user_api.py`)
51
+ - pytest collects tests from files matching `test_*.py` or `*_test.py` — use `test_` prefix exclusively
52
+ - Never create test files without the `test_` prefix
53
+
54
+ #### Write Boundary
55
+
56
+ - Only **create new** test script files under `testcase/`
57
+ - Do NOT modify existing files: `conftest.py`, `pytest.ini`, `pyproject.toml`, `setup.cfg`, `__init__.py`, or any other framework/config file
58
+ - Reuse existing fixtures; if required fixtures do not exist, report the gap instead of creating or modifying framework files
59
+ - Read existing framework files to understand conventions, but treat them as immutable
60
+
61
+ #### Naming Conflict Resolution
62
+
63
+ - If a file with the target name already exists under `testcase/`, add a numeric suffix: `test_order.py` → `test_order_01.py` → `test_order_02.py`
64
+ - Never overwrite or append to existing files — each test script must be a standalone file
65
+ - Check for existing files before writing; if `test_<module>.py` exists, use `test_<module>_01.py`
66
+
67
+ #### 1:1 Traceability
68
+
69
+ Every functional test case ID (`BE-<MODULE>-<NNN>`) must map to exactly one pytest function:
70
+
71
+ ```python
72
+ # testcase/md/BE-ORDER-001 → testcase/test_order.py
73
+ def test_BE_ORDER_001_create_order_with_valid_data():
74
+ """BE-ORDER-001: Create order with valid request body."""
75
+ ...
76
+ ```
77
+
78
+ - Function name: `test_<CASE_ID_with_underscores>` (e.g. `test_BE_ORDER_001_...`)
79
+ - Docstring first line: `<CASE_ID>: <Case Title>`
80
+
81
+ #### File Organization
82
+
83
+ - All test files go under `testcase/` directory in the host project root
84
+ - Group test files by MODULE segment: `BE-ORDER-*` → `testcase/test_order.py`, `BE-USER-*` → `testcase/test_user.py`
85
+ - Follow existing project conventions for import style, fixture scope
86
+
87
+ #### Fixture Strategy
88
+
89
+ - Reuse existing project fixtures from `conftest.py` when available
90
+ - Do not create or modify fixture/configuration files in this node
91
+ - Prefer `@pytest.fixture(scope="function")` for test isolation
92
+ - Use `@pytest.mark.parametrize` for boundary condition cases with multiple inputs
93
+
94
+ #### Test Integrity
95
+
96
+ - Tests verify implementation correctness — if a test fails, the implementation likely has a bug, not the test
97
+ - Do NOT weaken assertions, remove test cases, or modify test logic to make tests pass
98
+ - Do NOT add workarounds, skips, or try/except blocks to hide failures without explicit justification
99
+ - Report all failures honestly in the output; the downstream `execute-backend-pytest-shell` node captures exit codes and stdout/stderr as-is
100
+
101
+ #### Assertions
102
+
103
+ - Use `assert` statements, not `unittest` assertions
104
+ - Assert specific values, not just "no exception"
105
+ - For API tests: assert status code, response body keys, and specific field values
106
+ - For database tests: assert record state after operation
107
+
108
+ #### Conditional Test Implementation (include ONLY if test cases exist)
109
+
110
+ - **Authentication tests**: implement ONLY if `testcase/md/` contains auth-related cases
111
+ - Use `@pytest.mark.auth` marker
112
+ - Test no token, expired token, invalid token, insufficient permissions, cross-user access
113
+ - **Timeout tests**: implement ONLY if `testcase/md/` contains timeout-related cases
114
+ - Use `@pytest.mark.timeout` marker
115
+ - Use `unittest.mock.patch` or `pytest-mock` to simulate slow responses
116
+ - If no such cases exist in the reviewed test cases, do NOT add these tests
117
+
118
+ #### Markers
119
+
120
+ - `@pytest.mark.positive` — happy path cases
121
+ - `@pytest.mark.negative` — error/exception cases
122
+ - `@pytest.mark.boundary` — edge cases
123
+ - `@pytest.mark.<MODULE>` — module-specific marker (e.g. `@pytest.mark.order`)
124
+
125
+ #### Skip Policy
126
+
127
+ If a test case cannot be automated (requires external service not mockable, requires manual verification), add it with `@pytest.mark.skip(reason="...")` and document the reason. Do not omit the function — traceability requires it exists.
128
+
129
+ ### Output Shape (after summary line)
130
+
131
+ After the mandatory summary line, provide:
132
+
133
+ 1. **Generated Files** — list of files written under `tests/backend/`.
134
+ 2. **Function Mapping Table** — `| Test Case ID | Pytest Function | File | Marker |`.
135
+ 3. **Skipped Cases** — if any, list with reason.
136
+ 4. **Conventions Observed** — note project fixtures/config discovered and followed.
137
+ 5. **Residual Risks** — cases that may need manual verification or environment setup.
138
+
139
+ Do not include chain-of-thought. Do not write root `artifacts/**`.