3 Commits
78 changed files with 1548 additions and 1391 deletions
+1 -1
View File
@@ -44,7 +44,7 @@
- `script/check-scaffold-parity.ts` — scaffold-template twin 逐字节 - `script/check-scaffold-parity.ts` — scaffold-template twin 逐字节
校验(schema $id owner token 归一化比较); 校验(schema $id owner token 归一化比较);
- `script/delink-core.ts` — 去链接化契约执行(#NNNN 活引用 → [org-internal #NNNN] - `script/delink-core.ts` — 去链接化契约执行(#NNNN 活引用 → [org-internal #NNNN]
注记;幂等;--check 零剩余才过;Inc 6b 字节锁镜像翻转 rewritten 后无递延); 注记,`--strip` 进一步收敛为溯源短注 [TT-NNNN];幂等;--check 零剩余才过;Inc 6b 字节锁镜像翻转 rewritten 后无递延);
- `script/check-core-p1.ts` — P1 零残留终验(私网 IP / 实例主机名 / 个人 - `script/check-core-p1.ts` — P1 零残留终验(私网 IP / 实例主机名 / 个人
身份 / 旧 owner token 全树 grep;豁免 id-aliases.json 与历史命名空间 身份 / 旧 owner token 全树 grep;豁免 id-aliases.json 与历史命名空间
URL 声明;Inc 6b 起无字节锁递延); URL 声明;Inc 6b 起无字节锁递延);
+2 -1
View File
@@ -67,7 +67,7 @@ creating thin wrapper checklist files would add no value.
| # | 检查项 | 通过 | 不通过 | 备注 | | # | 检查项 | 通过 | 不通过 | 备注 |
| --- | --------------------------------------------------------------------- | ---- | ------ | ---- | | --- | --------------------------------------------------------------------- | ---- | ------ | ---- |
| 1.1 | SDLC 流水线各阶段均有对应 skill(analyze-dag→review-dag 单门→implement→review-code→verify→release→retrospective;legacy roadmap/requirements/design/plan 已归档 [org-internal #3072] phase 3,见 `<instance-root>/archive/`) | ☐ | ☐ | | | 1.1 | SDLC 流水线各阶段均有对应 skill(analyze-dag→review-dag 单门→implement→review-code→verify→release→retrospective;legacy roadmap/requirements/design/plan 已归档 [TT-3072] phase 3,见 `<instance-root>/archive/`) | ☐ | ☐ | |
| 1.2 | 每个 `skills/<name>/` 目录恰好包含一个 `SKILL.md`(例外:`_shared/` 目录不含 `SKILL.md`,为共享引用文档目录) | ☐ | ☐ | | | 1.2 | 每个 `skills/<name>/` 目录恰好包含一个 `SKILL.md`(例外:`_shared/` 目录不含 `SKILL.md`,为共享引用文档目录) | ☐ | ☐ | |
| 1.3 | 每个产物型 skill 都有配套 `checklists/<name>.md`(无清单的自检要求即为缺口) | ☐ | ☐ | | | 1.3 | 每个产物型 skill 都有配套 `checklists/<name>.md`(无清单的自检要求即为缺口) | ☐ | ☐ | |
| 1.4 | `checklists/` 中无孤儿清单(存在清单但无任何 skill 引用) | ☐ | ☐ | | | 1.4 | `checklists/` 中无孤儿清单(存在清单但无任何 skill 引用) | ☐ | ☐ | |
@@ -179,6 +179,7 @@ creating thin wrapper checklist files would add no value.
| 8.5 | 防范范围收窄:明令禁止「只看重点/从简」类弱化措辞(IEEE 1028-2008 完整性) | ☐ | ☐ | | | 8.5 | 防范范围收窄:明令禁止「只看重点/从简」类弱化措辞(IEEE 1028-2008 完整性) | ☐ | ☐ | |
| 8.6 | 留痕:审计产物落盘到结构化文件,而非仅存于对话 | ☐ | ☐ | | | 8.6 | 留痕:审计产物落盘到结构化文件,而非仅存于对话 | ☐ | ☐ | |
| 8.7 | 闭环:存在重审循环与收敛/审批终止条件(ISO 19011:2018 跟踪与关闭) | ☐ | ☐ | | | 8.7 | 闭环:存在重审循环与收敛/审批终止条件(ISO 19011:2018 跟踪与关闭) | ☐ | ☐ | |
| 8.8 | 流程自身测试为绿:Orchestrator(bash 可用)在派发审计员**之前**机械运行流程自身的测试套件与守卫门(`bun run test:parallel` 全量分片 + `check:*` 守卫族,如 core-parity / encoding-health / derived-artifacts),并把命令、基线 SHA 与结果摘要落盘到 `<runs-root>/audit/reviews/audit-process/process-tests-green.md`(Tier 1);审计员(只读,无 bash)核对该记录存在于当前基线且为绿——任何红测试/红守卫本身即流程缺陷,按 findings 登记(缺陷逃逸案例:红测试存活 3 轮审计、无任何维度运行过测试套件,[TT-4787]) | ☐ | ☐ | 运行归 Orchestrator、核对归审计员(角色边界:`core/skills/_shared/review-orchestrator-rules.md` §No bash for Explorer sub-agents) |
--- ---
+2 -2
View File
@@ -116,8 +116,8 @@
| 5.4 | 测试相互独立,可任意顺序运行,无共享可变状态 | ☐ | ☐ | | | 5.4 | 测试相互独立,可任意顺序运行,无共享可变状态 | ☐ | ☐ | |
| 5.5 | Mock/Stub 的使用合理,模拟的外部行为与真实行为一致 | ☐ | ☐ | | | 5.5 | Mock/Stub 的使用合理,模拟的外部行为与真实行为一致 | ☐ | ☐ | |
| 5.6 | 测试命名清晰表达了测试场景和预期结果 | ☐ | ☐ | | | 5.6 | 测试命名清晰表达了测试场景和预期结果 | ☐ | ☐ | |
| 5.7 | 本次变更涉及的测试已通过(`test:changed`,由 mechanical-green gate 机器判定,评审员引用 gate 结果即可)。全量套件(`test:parallel`)归 verify,不是代码评审门禁([org-internal #2598] 检查分层) | ☐ | ☐ | | | 5.7 | 本次变更涉及的测试已通过(`test:changed`,由 mechanical-green gate 机器判定,评审员引用 gate 结果即可)。全量套件(`test:parallel`)归 verify,不是代码评审门禁([TT-2598] 检查分层) | ☐ | ☐ | |
| 5.8 | 评审发现的"dummy fixture / harness 默认值漂移"类问题,不能仅凭 `WAIVED` 处置:若漂移值是 harness 对**生产 CLI/配置默认值**的镜像(如 harness 旧 owner 默认 vs CLI 新 owner 默认这类 token 漂移),WAIVED 会把真实漂移放行到 post-merge([org-internal #3169] TST-F002 → 后续 [org-internal #3172] 才修)。处置前确认该值是否被生产路径读取;被读取则必须 FIX 或显式登记 TD | ☐ | ☐ | | | 5.8 | 评审发现的"dummy fixture / harness 默认值漂移"类问题,不能仅凭 `WAIVED` 处置:若漂移值是 harness 对**生产 CLI/配置默认值**的镜像(如 harness 旧 owner 默认 vs CLI 新 owner 默认这类 token 漂移),WAIVED 会把真实漂移放行到 post-merge([TT-3169] TST-F002 → 后续 [TT-3172] 才修)。处置前确认该值是否被生产路径读取;被读取则必须 FIX 或显式登记 TD | ☐ | ☐ | |
--- ---
+1 -1
View File
@@ -7,7 +7,7 @@
> **权威源**:本文件判据逐行复制 `dag-pipeline/spec-04` §1 三张表 > **权威源**:本文件判据逐行复制 `dag-pipeline/spec-04` §1 三张表
> (含 `NFR:` 前缀 / 里程碑边 / 里程碑节点豁免与 `estimated_sessions` 判据)。 > (含 `NFR:` 前缀 / 里程碑边 / 里程碑节点豁免与 `estimated_sessions` 判据)。
> 若本文件与 spec-04 §1 不一致,以 spec-04 §1 为唯一权威源。 > 若本文件与 spec-04 §1 不一致,以 spec-04 §1 为唯一权威源。
> (`spec-0N` 前身为 `dag-pipeline/03-design-0N-*`,2026-08-21 [org-internal #3072] phase 3 > (`spec-0N` 前身为 `dag-pipeline/03-design-0N-*`,2026-08-21 [TT-3072] phase 3
> 升格迁移,旧名仅保留墓碑占位以维持旧 URL 可达。) > 升格迁移,旧名仅保留墓碑占位以维持旧 URL 可达。)
## TOPO — 拓扑维 ## TOPO — 拓扑维
+8 -8
View File
@@ -11,7 +11,7 @@
2. **POST** 项在完成编码和所有验证命令后检查; 2. **POST** 项在完成编码和所有验证命令后检查;
3. 对"不通过"项必须在代码评审前修复; 3. 对"不通过"项必须在代码评审前修复;
4. 无法满足的项标记 `[N/A: <原因>]`; 4. 无法满足的项标记 `[N/A: <原因>]`;
5. **DAG 路由产物解析([org-internal #3072] phase 3 后唯一管线模式)**:DAG 运行不存在 5. **DAG 路由产物解析([TT-3072] phase 3 后唯一管线模式)**:DAG 运行不存在
legacy `{slug}/04-plan-*` / `{slug}/03-design-*` 页面,PRE-1~PRE-7、 legacy `{slug}/04-plan-*` / `{slug}/03-design-*` 页面,PRE-1~PRE-7、
PRE-11、PRE-12、PRE-19、POST-15.1 引用的产物按 `implement`/`verify` PRE-11、PRE-12、PRE-19、POST-15.1 引用的产物按 `implement`/`verify`
SKILL 的 DAG-route read map 解析:工作项定义 → 冻结 DAG 副本 SKILL 的 DAG-route read map 解析:工作项定义 → 冻结 DAG 副本
@@ -68,17 +68,17 @@
| ------ | -------------------------------------------------------------------------- | ---- | ------ | --- | ---- | | ------ | -------------------------------------------------------------------------- | ---- | ------ | --- | ---- |
| PRE-11 | 设计文档(wiki pages `{slug}/03-design-**`)已存在且包含本工作项涉及的全部组件设计 | ☐ | ☐ | ☐ | | | PRE-11 | 设计文档(wiki pages `{slug}/03-design-**`)已存在且包含本工作项涉及的全部组件设计 | ☐ | ☐ | ☐ | |
| PRE-12 | 迭代计划(plan/)已存在且本工作项有明确的工作项 ID 和验收条件 | ☐ | ☐ | ☐ | | | PRE-12 | 迭代计划(plan/)已存在且本工作项有明确的工作项 ID 和验收条件 | ☐ | ☐ | ☐ | |
| PRE-13 | 评审门已收敛:DAG 路由下为 review-dag 单门收敛(`octopus review status --stage review-dag` 的 state 为 `success`,与 `pipeline-gate.md` DAG 路由变体一致);standalone 模式(bugfix/refactor/port)无上游评审门,标记 `[N/A: standalone 无上游评审]`(legacy design-space / iteration-plan 双门已随 [org-internal #3072] phase 3 归档) | ☐ | ☐ | ☐ | | | PRE-13 | 评审门已收敛:DAG 路由下为 review-dag 单门收敛(`octopus review status --stage review-dag` 的 state 为 `success`,与 `pipeline-gate.md` DAG 路由变体一致);standalone 模式(bugfix/refactor/port)无上游评审门,标记 `[N/A: standalone 无上游评审]`(legacy design-space / iteration-plan 双门已随 [TT-3072] phase 3 归档) | ☐ | ☐ | ☐ | |
| PRE-14 | 合并前基准刷新:当前分支已 rebase 到目标分支(`git fetch origin && git rebase origin/main`),无合并冲突。若 rebase 引入新变更,重新运行 `bun typecheck && bun run test:parallel` 后再提交 | ☐ | ☐ | ☐ | | | PRE-14 | 合并前基准刷新:当前分支已 rebase 到目标分支(`git fetch origin && git rebase origin/main`),无合并冲突。若 rebase 引入新变更,重新运行 `bun typecheck && bun run test:parallel` 后再提交 | ☐ | ☐ | ☐ | |
### 5. UI 组件设计完整性(仅前端/UI 工作项) ### 5. UI 组件设计完整性(仅前端/UI 工作项)
| # | 检查项 | 通过 | 不通过 | N/A | 备注 | | # | 检查项 | 通过 | 不通过 | N/A | 备注 |
| ------ | -------------------------------------------------------------------------- | ---- | ------ | --- | ---- | | ------ | -------------------------------------------------------------------------- | ---- | ------ | --- | ---- |
| PRE-15 | 设计文档覆盖了组件的全部四种状态(Loading / Empty / Error / Success),每种状态有明确的渲染内容和触发条件(参见 `.octopus/archive/templates/design.md` §11.1,legacy 设计模板 [org-internal #3072] phase 3) | ☐ | ☐ | ☐ | | | PRE-15 | 设计文档覆盖了组件的全部四种状态(Loading / Empty / Error / Success),每种状态有明确的渲染内容和触发条件(参见 `.octopus/archive/templates/design.md` §11.1,legacy 设计模板 [TT-3072] phase 3) | ☐ | ☐ | ☐ | |
| PRE-16 | 设计文档覆盖了组件所需的全部交互行为:列表导航、焦点管理、键盘快捷键、展开/折叠、实时过滤(参见 `.octopus/archive/templates/design.md` §11.2,legacy 设计模板 [org-internal #3072] phase 3) | ☐ | ☐ | ☐ | | | PRE-16 | 设计文档覆盖了组件所需的全部交互行为:列表导航、焦点管理、键盘快捷键、展开/折叠、实时过滤(参见 `.octopus/archive/templates/design.md` §11.2,legacy 设计模板 [TT-3072] phase 3) | ☐ | ☐ | ☐ | |
| PRE-17 | 设计文档覆盖了组件的全部可访问性要求:ARIA role/label、键盘可达、焦点环、对比度、色彩独立性(参见 `.octopus/archive/templates/design.md` §11.3,legacy 设计模板 [org-internal #3072] phase 3) | ☐ | ☐ | ☐ | | | PRE-17 | 设计文档覆盖了组件的全部可访问性要求:ARIA role/label、键盘可达、焦点环、对比度、色彩独立性(参见 `.octopus/archive/templates/design.md` §11.3,legacy 设计模板 [TT-3072] phase 3) | ☐ | ☐ | ☐ | |
| PRE-18 | 设计文档已逐组件声明测试策略类型(render / source-verification / E2E / manual)。已知测试基础设施限制(Kobalte portal + happydom、路由上下文缺失等)已有对应替代方案标记(参见 `.octopus/archive/templates/design.md` §11.4,legacy 设计模板 [org-internal #3072] phase 3) | ☐ | ☐ | ☐ | | | PRE-18 | 设计文档已逐组件声明测试策略类型(render / source-verification / E2E / manual)。已知测试基础设施限制(Kobalte portal + happydom、路由上下文缺失等)已有对应替代方案标记(参见 `.octopus/archive/templates/design.md` §11.4,legacy 设计模板 [TT-3072] phase 3) | ☐ | ☐ | ☐ | |
| PRE-19 | 超过 3 个 MANUAL 类型的 AC 已标记为设计风险,并在 plan 中标注更高级测试基础设施依赖 | ☐ | ☐ | ☐ | | | PRE-19 | 超过 3 个 MANUAL 类型的 AC 已标记为设计风险,并在 plan 中标注更高级测试基础设施依赖 | ☐ | ☐ | ☐ | |
--- ---
@@ -97,7 +97,7 @@
| POST-6 | 若不得已偏离设计,有明确的注释标注原因和设计修正建议(含 ADR/amend 引用 — 不可仅写"偏离设计") | ☐ | ☐ | ☐ | | | POST-6 | 若不得已偏离设计,有明确的注释标注原因和设计修正建议(含 ADR/amend 引用 — 不可仅写"偏离设计") | ☐ | ☐ | ☐ | |
| POST-6.1 | 已用设计文档中的决策树/状态机/真值表,代入至少 2 组具体输入手工 trace 每条分支,确认代码输出与设计预期一致(尤其条件取反、`===` vs `!==`、状态翻转等易错点) | ☐ | ☐ | ☐ | | | POST-6.1 | 已用设计文档中的决策树/状态机/真值表,代入至少 2 组具体输入手工 trace 每条分支,确认代码输出与设计预期一致(尤其条件取反、`===` vs `!==`、状态翻转等易错点) | ☐ | ☐ | ☐ | |
| POST-6.2 | 因 API 不兼容、上游限制或测试基础设施不足而延迟的项,已在代码中用 `[OPEN: <short-id>]` 标注(含延迟原因、影响范围、建议解决时机)。verify Phase 5.5 会为每个 `[OPEN]` 项在源票 `## TD 登记` 评论登记一行(registry-first,`ticket-lifecycle.md`;排期后才升格独立票)。禁止仅标注 `[OPEN]` 而不登记 | ☐ | ☐ | ☐ | | | POST-6.2 | 因 API 不兼容、上游限制或测试基础设施不足而延迟的项,已在代码中用 `[OPEN: <short-id>]` 标注(含延迟原因、影响范围、建议解决时机)。verify Phase 5.5 会为每个 `[OPEN]` 项在源票 `## TD 登记` 评论登记一行(registry-first,`ticket-lifecycle.md`;排期后才升格独立票)。禁止仅标注 `[OPEN]` 而不登记 | ☐ | ☐ | ☐ | |
| POST-6.3 | 邻近配额([org-internal #3002] G3):本迭代触碰的区域(包/模块)若在源票 `## TD 登记` 中有适用行,已带走 ≥1 项一并处置(修复或带理由显式再延迟);无适用行时在报告记录 `0 applicable` | ☐ | ☐ | ☐ | | | POST-6.3 | 邻近配额([TT-3002] G3):本迭代触碰的区域(包/模块)若在源票 `## TD 登记` 中有适用行,已带走 ≥1 项一并处置(修复或带理由显式再延迟);无适用行时在报告记录 `0 applicable` | ☐ | ☐ | ☐ | |
### 5. 代码质量 ### 5. 代码质量
@@ -115,7 +115,7 @@
| POST-10.4 | 多写操作(INSERT + UPDATE)用 `Database.transaction` 包裹保证原子性 | ☐ | ☐ | ☐ | | | POST-10.4 | 多写操作(INSERT + UPDATE)用 `Database.transaction` 包裹保证原子性 | ☐ | ☐ | ☐ | |
| POST-11 | 无硬编码凭据、密钥、内网地址或环境特定值 | ☐ | ☐ | ☐ | | | POST-11 | 无硬编码凭据、密钥、内网地址或环境特定值 | ☐ | ☐ | ☐ | |
| POST-11.1 | 提交前无法跟踪链接检查(单一事实来源:`code-review.md` SEC 3.7.1——`git diff --cached --diff-filter=T` 为空;判据以该条为准)| ☐ | ☐ | ☐ | | | POST-11.1 | 提交前无法跟踪链接检查(单一事实来源:`code-review.md` SEC 3.7.1——`git diff --cached --diff-filter=T` 为空;判据以该条为准)| ☐ | ☐ | ☐ | |
| POST-11.2 | 提交前已确认无进程/流程副产品混入暂存区(如 `.claim` 空文件、claim carrier、临时 pid/日志)——`git status` 逐条核对,`git add -A` 前先看 untracked 清单([org-internal #3169] 教训:`.claim` 空文件随 iter-0 混入,round-1 九维评审要求 `git rm`) | ☐ | ☐ | ☐ | | | POST-11.2 | 提交前已确认无进程/流程副产品混入暂存区(如 `.claim` 空文件、claim carrier、临时 pid/日志)——`git status` 逐条核对,`git add -A` 前先看 untracked 清单([TT-3169] 教训:`.claim` 空文件随 iter-0 混入,round-1 九维评审要求 `git rm`) | ☐ | ☐ | ☐ | |
| POST-12 | 无注释掉的代码块或 `console.log` 调试语句 | ☐ | ☐ | ☐ | | | POST-12 | 无注释掉的代码块或 `console.log` 调试语句 | ☐ | ☐ | ☐ | |
| POST-13 | 无 `as any` 类型断言绕过类型检查(生产代码必须保有完整类型安全) | ☐ | ☐ | ☐ | | | POST-13 | 无 `as any` 类型断言绕过类型检查(生产代码必须保有完整类型安全) | ☐ | ☐ | ☐ | |
+5 -5
View File
@@ -18,7 +18,7 @@ Upstream Artifact Existence 与 Upstream Review Convergence 检查
`success`(替代 design-space + iteration-plan 双门;任务工单 `success`(替代 design-space + iteration-plan 双门;任务工单
不重跑单门,只核对其已收敛) 不重跑单门,只核对其已收敛)
- [ ] (仅任务工单)票 body `## 父级 / Parent` 指向 DAG 父级 - [ ] (仅任务工单)票 body `## 父级 / Parent` 指向 DAG 父级
(`Kind/Epic` 或 `Kind/Feature`,[org-internal #3061] 阶段 2), (`Kind/Epic` 或 `Kind/Feature`,[TT-3061] 阶段 2),
Step 0 解析到 `dag.task_route`(entry `implement`),不继承 Step 0 解析到 `dag.task_route`(entry `implement`),不继承
`dag.route` `dag.route`
- [ ] 跨节点依赖由 DAG 拓扑承担:节点 ready 以其全部跨 session 上游 - [ ] 跨节点依赖由 DAG 拓扑承担:节点 ready 以其全部跨 session 上游
@@ -34,7 +34,7 @@ review-dag)直至收敛;DAG 副本缺失或未冻结 → 回到 `analyze-dag
- [ ] standalone bugfix:repro notes wiki page `{slug}/repro-notes` 存在且含环境快照(via `wiki 读写 API(见 TERMINOLOGY)`) - [ ] standalone bugfix:repro notes wiki page `{slug}/repro-notes` 存在且含环境快照(via `wiki 读写 API(见 TERMINOLOGY)`)
- [ ] 验收条件可解析:来自请求/工单 body 或节点 AC(等价的验收条件文档,via `wiki 读写 API(见 TERMINOLOGY)` / `工单 API(见 TERMINOLOGY)get`) - [ ] 验收条件可解析:来自请求/工单 body 或节点 AC(等价的验收条件文档,via `wiki 读写 API(见 TERMINOLOGY)` / `工单 API(见 TERMINOLOGY)get`)
> Legacy([org-internal #3072] phase 3,2026-08-21 归档):requirements/design/plan baseline > Legacy([TT-3072] phase 3,2026-08-21 归档):requirements/design/plan baseline
> 页(`{slug}/02-requirements-index` / `{slug}/03-design-index` / > 页(`{slug}/02-requirements-index` / `{slug}/03-design-index` /
> `{slug}/04-plan-index` / `{slug}/04-plan-05-acceptance-criteria`)与 > `{slug}/04-plan-index` / `{slug}/04-plan-05-acceptance-criteria`)与
> design-space / iteration-plan 双门收敛检查随 legacy 管线归档 > design-space / iteration-plan 双门收敛检查随 legacy 管线归档
@@ -65,10 +65,10 @@ review-dag)直至收敛;DAG 副本缺失或未冻结 → 回到 `analyze-dag
## PR 准入(pr-admission) ## PR 准入(pr-admission)
> 纪律:`core/rules/ticket-lifecycle.md` PR 准入节(TD-678 / [org-internal #3881] / [org-internal #4425])。 > 纪律:`core/rules/ticket-lifecycle.md` PR 准入节(TD-678 / [TT-3881] / [TT-4425])。
- [ ] PR 标题符合 `[slug][iter-N] type(scope): 描述` 格式 - [ ] PR 标题符合 `[slug][iter-N] type(scope): 描述` 格式
- [ ] PR 正文含变更清单 + 自测结果 + 关联合规(关联 issue 引用,如 `Closes #N`;数字后须接 ASCII 标点或行尾——紧跟全角标点会破坏 Gitea 自动关闭,PR [org-internal #3882] 实例) - [ ] PR 正文含变更清单 + 自测结果 + 关联合规(关联 issue 引用,如 `Closes #N`;数字后须接 ASCII 标点或行尾——紧跟全角标点会破坏 Gitea 自动关闭,PR [TT-3882] 实例)
- [ ] 交付推送前本地验证已绿:`<harness-package>` 下 `bun run test:changed` 全绿 + `bun typecheck` 0 error(WIP 备份推送不受此门约束——分支裸推零 CI,交付信号是完成回报而非推送) - [ ] 交付推送前本地验证已绿:`<harness-package>` 下 `bun run test:changed` 全绿 + `bun typecheck` 0 error(WIP 备份推送不受此门约束——分支裸推零 CI,交付信号是完成回报而非推送)
- [ ] 分支已推送 origin;PR **未**由本会话自行创建(由编排按容量串行开启,一次一张、双绿并入再开下一张) - [ ] 分支已推送 origin;PR **未**由本会话自行创建(由编排按容量串行开启,一次一张、双绿并入再开下一张)
- [ ] 交付报告已发(branch= 分支名 / 改动文件清单 / 自测结果 / verify 与 risk 回执) - [ ] 交付报告已发(branch= 分支名 / 改动文件清单 / 自测结果 / verify 与 risk 回执)
@@ -81,7 +81,7 @@ review-dag)直至收敛;DAG 副本缺失或未冻结 → 回到 `analyze-dag
> 状态跃迁),不得等到技能退出边界。规则:`core/rules/issue-checklist-sync.md`。 > 状态跃迁),不得等到技能退出边界。规则:`core/rules/issue-checklist-sync.md`。
- [ ] 若存在 source issue:其 checklist 已按同步点表渐进勾选(DAG 冻结、iteration commit、PR 创建、review PASS、CI 跃迁、verify 终扫),无陈旧 `- [ ]` 项 - [ ] 若存在 source issue:其 checklist 已按同步点表渐进勾选(DAG 冻结、iteration commit、PR 创建、review PASS、CI 跃迁、verify 终扫),无陈旧 `- [ ]` 项
- [ ] 若为 incident / standalone-bugfix 流程:issue 含 `## 当前状态` live-status 小节,且 PR / review / CI 行已随跃迁更新([org-internal #1689]) - [ ] 若为 incident / standalone-bugfix 流程:issue 含 `## 当前状态` live-status 小节,且 PR / review / CI 行已随跃迁更新([TT-1689])
- [ ] 过程性 AC(如"连续 N 次绿")的进度注记已更新(带 run 编号) - [ ] 过程性 AC(如"连续 N 次绿")的进度注记已更新(带 run 编号)
- [ ] 遗留项(未勾选)均有 `(Deferred: ...)` 或 `(Pending: ...)` 注记 - [ ] 遗留项(未勾选)均有 `(Deferred: ...)` 或 `(Pending: ...)` 注记
- [ ] verify PASS 时 `## 当前状态` 小节已折叠进 checklist 注记并移除 - [ ] verify PASS 时 `## 当前状态` 小节已折叠进 checklist 注记并移除
+2 -2
View File
@@ -24,7 +24,7 @@
| 2.1 | 重构目标明确(哪种变换,为什么) | ☐ | ☐ | | | 2.1 | 重构目标明确(哪种变换,为什么) | ☐ | ☐ | |
| 2.2 | 步骤分解 ≤ 10 步 | ☐ | ☐ | | | 2.2 | 步骤分解 ≤ 10 步 | ☐ | ☐ | |
| 2.3 | 不存在范围蔓延(未在同一重构中混入新功能或 Bug 修复) | ☐ | ☐ | | | 2.3 | 不存在范围蔓延(未在同一重构中混入新功能或 Bug 修复) | ☐ | ☐ | |
| 2.4 | 若重构涉及身份/owner token 改名(org、账号、邮箱、域名前缀):已先产出"不改清单"——OS 账号、个人邮箱、历史记录归属、dummy fixture 等非组织身份引用逐类明确保留,再执行机械替换([org-internal #3169] 教训:D1 缺此边界 → round-1 15 MAJOR) | ☐ | ☐ | | | 2.4 | 若重构涉及身份/owner token 改名(org、账号、邮箱、域名前缀):已先产出"不改清单"——OS 账号、个人邮箱、历史记录归属、dummy fixture 等非组织身份引用逐类明确保留,再执行机械替换([TT-3169] 教训:D1 缺此边界 → round-1 15 MAJOR) | ☐ | ☐ | |
--- ---
@@ -51,7 +51,7 @@
| 4.4 | 测试覆盖率未下降(±1%) | ☐ | ☐ | | | 4.4 | 测试覆盖率未下降(±1%) | ☐ | ☐ | |
| 4.5 | 无新增或修改的测试(重构不应改变测试中的断言逻辑) | ☐ | ☐ | | | 4.5 | 无新增或修改的测试(重构不应改变测试中的断言逻辑) | ☐ | ☐ | |
| 4.6 | 若重构改变了对外可见字符串(stage 名称、tool description、错误消息等),对应的 snapshot 已通过 `bun test --update-snapshots` 更新 | ☐ | ☐ | | | 4.6 | 若重构改变了对外可见字符串(stage 名称、tool description、错误消息等),对应的 snapshot 已通过 `bun test --update-snapshots` 更新 | ☐ | ☐ | |
| 4.7 | 若重构变更了身份/owner token:残留扫描守卫(如 `script/verify-urls.ts`)已做**语义正反验证**——搜索模式指向**旧** token(旧 owner 前缀的 URL 形态),且已知新 token(新 owner 前缀的 URL 形态)与真实旧残留各跑一次,确认守卫对"合规新 URL"不误报、对"真实残留"不漏报([org-internal #3169] 教训:D5 模式被翻转 → 守卫对新 URL 误报、对旧残留失明) | ☐ | ☐ | | | 4.7 | 若重构变更了身份/owner token:残留扫描守卫(如 `script/verify-urls.ts`)已做**语义正反验证**——搜索模式指向**旧** token(旧 owner 前缀的 URL 形态),且已知新 token(新 owner 前缀的 URL 形态)与真实旧残留各跑一次,确认守卫对"合规新 URL"不误报、对"真实残留"不漏报([TT-3169] 教训:D5 模式被翻转 → 守卫对新 URL 误报、对旧残留失明) | ☐ | ☐ | |
--- ---
+1 -1
View File
@@ -1,6 +1,6 @@
# Release 检查清单 # Release 检查清单
> 发版前自检。Release Manager 在 Phase 1 和 Phase 6 完整过一遍。 > 发版前自检。Producer (Worker) 在 Phase 1 和 Phase 6 完整过一遍。
> **维度命名空间(dimension namespace)**: 本清单中的维度代码(如 TST/BEH/GATE/REG)是**清单局部(checklist-local)**标识符,仅在本文档内唯一;其他清单可能对相同字母串绑定不同概念(如 code-review.md 的 TST=Test Quality、verification.md 的 TST=Test Suite Completeness、port.md 的 TST=Test Porting)。跨清单引用时必须带清单限定(如 code-review.md TST 5.8),不得使用裸代码。 > **维度命名空间(dimension namespace)**: 本清单中的维度代码(如 TST/BEH/GATE/REG)是**清单局部(checklist-local)**标识符,仅在本文档内唯一;其他清单可能对相同字母串绑定不同概念(如 code-review.md 的 TST=Test Quality、verification.md 的 TST=Test Suite Completeness、port.md 的 TST=Test Porting)。跨清单引用时必须带清单限定(如 code-review.md TST 5.8),不得使用裸代码。
+1 -1
View File
@@ -21,7 +21,7 @@
| 1.11 | 已检查 merged workflow/* 分支与关联 worktree 在合并后已清理(本地分支删除 + worktree 移除) | ☐ | ☐ | | | 1.11 | 已检查 merged workflow/* 分支与关联 worktree 在合并后已清理(本地分支删除 + worktree 移除) | ☐ | ☐ | |
| 1.12 | 周期时长和团队规模已记录(压缩周期 = 质量风险,单点故障) | ☐ | ☐ | | | 1.12 | 周期时长和团队规模已记录(压缩周期 = 质量风险,单点故障) | ☐ | ☐ | |
| 1.13 | 范围估算验证:triage/scope 声明前已统计各标签下的 issue 数量(如 `Status/Blocked`、`Kind/*`、`Priority/*`),并与之前声明对比,偏差 >20% 标注为估算偏差 | ☐ | ☐ | | | 1.13 | 范围估算验证:triage/scope 声明前已统计各标签下的 issue 数量(如 `Status/Blocked`、`Kind/*`、`Priority/*`),并与之前声明对比,偏差 >20% 标注为估算偏差 | ☐ | ☐ | |
| 1.14 | 门缺陷逃逸分析已运行(§2.8 escape-rate 单指标,[org-internal #3061]):各 gate 的 clean runs / escapes / escape_rate 已统计,UNDER-POWERED(≥0.3)门已标注并回馈 §2.9 pre-flight(gate-trim 元进程已退役,[org-internal #3072] phase 3) | ☐ | ☐ | | | 1.14 | 门缺陷逃逸分析已运行(§2.8 escape-rate 单指标,[TT-3061]):各 gate 的 clean runs / escapes / escape_rate 已统计,UNDER-POWERED(≥0.3)门已标注并回馈 §2.9 pre-flight(gate-trim 元进程已退役,[TT-3072] phase 3) | ☐ | ☐ | |
--- ---
+2 -2
View File
@@ -119,9 +119,9 @@
| # | 检查项 | 通过 | 不通过 | 备注 | | # | 检查项 | 通过 | 不通过 | 备注 |
| --- | --------------------------------------------------------------------- | ---- | ------ | ---- | | --- | --------------------------------------------------------------------- | ---- | ------ | ---- |
| 8.1 | 本迭代全部 UNVERIFIABLE / ACCEPTED_RISK / `[OPEN]` 项均已登记为源票 `## TD 登记` 评论中的行(registry-first,`ticket-lifecycle.md`;`filing.sprint-mode: true` 期间禁止升格独立票) | ☐ | ☐ | | | 8.1 | 本迭代全部 UNVERIFIABLE / ACCEPTED_RISK / `[OPEN]` 项均已登记为源票 `## TD 登记` 评论中的行(registry-first,`ticket-lifecycle.md`;`filing.sprint-mode: true` 期间禁止升格独立票) | ☐ | ☐ | |
| 8.2 | 每行含 `TD-NNN`、type、Severity、origin、一句话摘要与可客观验证的 Reactivation Trigger;TD-NNN 为注册期分配——经 `script/td-alloc.sh` 从号段台账(TD allocation ledger,常设 tracker)取号,任何分配必须先落台账 td-alloc 评论([org-internal #3322] 互斥) | ☐ | ☐ | | | 8.2 | 每行含 `TD-NNN`、type、Severity、origin、一句话摘要与可客观验证的 Reactivation Trigger;TD-NNN 为注册期分配——经 `script/td-alloc.sh` 从号段台账(TD allocation ledger,常设 tracker)取号,任何分配必须先落台账 td-alloc 评论([TT-3322] 互斥) | ☐ | ☐ | |
| 8.3 | 两处登记的 `TD-NNN` 标识一致,且每项都有可客观验证的 Reactivation Trigger | ☐ | ☐ | | | 8.3 | 两处登记的 `TD-NNN` 标识一致,且每项都有可客观验证的 Reactivation Trigger | ☐ | ☐ | |
| 8.4 | 邻近配额复核([org-internal #3002] G3):报告含本迭代触碰区域的登记册带走情况(consumed/applicable,或 `0 applicable`);与本 run 的债务配额记录一致(legacy roadmap 状态追踪表已归档,[org-internal #3072] phase 3) | ☐ | ☐ | | | 8.4 | 邻近配额复核([TT-3002] G3):报告含本迭代触碰区域的登记册带走情况(consumed/applicable,或 `0 applicable`);与本 run 的债务配额记录一致(legacy roadmap 状态追踪表已归档,[TT-3072] phase 3) | ☐ | ☐ | |
--- ---
+2 -2
View File
@@ -2,7 +2,7 @@
## Artifact-Index Guards (mandatory) ## Artifact-Index Guards (mandatory)
> Check-mechanized (injection-budget batch-3, [org-internal #3699]): guards > Check-mechanized (injection-budget batch-3, [TT-3699]): guards
> 1-3's checkable invariants run in the repo's artifact-index-check script > 1-3's checkable invariants run in the repo's artifact-index-check script
> (`<artifact-index-check-cmd> <ticket>`, see the term mapping; exit 4 = > (`<artifact-index-check-cmd> <ticket>`, see the term mapping; exit 4 =
> violation, `--json` summary; tolerant of wild archive-marker dialects). > violation, `--json` summary; tolerant of wild archive-marker dialects).
@@ -16,7 +16,7 @@
Before creating a `## 工件索引` comment, scan the issue's existing comments Before creating a `## 工件索引` comment, scan the issue's existing comments
for the legacy prefix `## Pipeline 工件追踪表`. If found, UPGRADE it for the legacy prefix `## Pipeline 工件追踪表`. If found, UPGRADE it
in place (edit, not create) and rename. NEVER create a second index comment in place (edit, not create) and rename. NEVER create a second index comment
(DEFECT-1 / [org-internal #1924]). Mechanized: reports the comment_id to edit. (DEFECT-1 / [TT-1924]). Mechanized: reports the comment_id to edit.
### 2. Never-duplicate invariant (single-comment) ### 2. Never-duplicate invariant (single-comment)
+5 -6
View File
@@ -40,9 +40,9 @@ UI's "auto-accept permissions" toggle (browser-local, not the project
> fix this table. `merge-pr` is excluded from default/preset `stages` arrays > fix this table. `merge-pr` is excluded from default/preset `stages` arrays
> (not structurally blocked; explicitly adding it is not recommended). > (not structurally blocked; explicitly adding it is not recommended).
> Legacy stage retirement (12 → 5): the phase-3 retirement ruling doc > Legacy stage retirement (12 → 5): the phase-3 retirement ruling doc
> (Tier-2 reference, reachable via the ticket backend). > (instance detail (in the consuming instance)).
Config shape: `"auto_approve": { "stages": ["review-code", "verify"], "stageless": false }` — `stages` empty (`[]`) = all manual; `stageless: true` also auto-approves questions called without a stage. Absent block defaults to `{ stages: ["review-code", "verify", "audit-process"], stageless: false }`; the removed `enabled` field migrates on load (mapping: Tier-2 reference page `rules/auto-approve-detail`). Presets (`safe`/`full`/`off`/`show`): same reference page — `full` never includes `merge-pr`. Config shape: `"auto_approve": { "stages": ["review-code", "verify"], "stageless": false }` — `stages` empty (`[]`) = all manual; `stageless: true` also auto-approves questions called without a stage. Absent block defaults to `{ stages: ["review-code", "verify", "audit-process"], stageless: false }`; the removed `enabled` field migrates on load (mapping: instance detail page `rules/auto-approve-detail`). Presets (`safe`/`full`/`off`/`show`): same reference page — `full` never includes `merge-pr`.
### Stage matching behavior ### Stage matching behavior
@@ -55,7 +55,7 @@ Config shape: `"auto_approve": { "stages": ["review-code", "verify"], "stageless
Check logic: the harness 内建的问询与自动批准判定模块 Check logic: the harness 内建的问询与自动批准判定模块
(resolveAutoApproveDecision). (resolveAutoApproveDecision).
### Live-gate degradation chain ([org-internal #3531]) ### Live-gate degradation chain ([TT-3531])
An auto-approved question is NOT consumed instantly: L1 — a live human An auto-approved question is NOT consumed instantly: L1 — a live human
watching the session (SSE declaration / fresh presence ping) answers within watching the session (SSE declaration / fresh presence ping) answers within
@@ -73,7 +73,7 @@ before the gate runs (iron law).
### Mandatory destructive list (业务决策类问询强制清单) ### Mandatory destructive list (业务决策类问询强制清单)
Origin: [org-internal #3223] — a stage whitelist auto-answered two Origin: [TT-3223] — a stage whitelist auto-answered two
irreversible production data changes because nothing marked them irreversible production data changes because nothing marked them
`destructive`. A stage whitelist grants "execution gates may proceed `destructive`. A stage whitelist grants "execution gates may proceed
uninterrupted"; it must NEVER grant "business decisions may be uninterrupted"; it must NEVER grant "business decisions may be
@@ -87,8 +87,7 @@ is never a substitute for human confirmation of these categories.**
1. **Merge / release landing** — merging a PR to main, cutting a tag or 1. **Merge / release landing** — merging a PR to main, cutting a tag or
release, deploying/promoting to production (server-side auto-merge is a release, deploying/promoting to production (server-side auto-merge is a
human-configured policy robot, never agent self-answer latitude; kill human-configured policy robot, never agent self-answer latitude; kill
switch: the auto-merge-low-risk runbook, Tier-2 reference via the ticket switch: the auto-merge-low-risk runbook, instance detail (in the consuming instance)).
backend).
2. **Production database writes** — upsert/update/delete against production 2. **Production database writes** — upsert/update/delete against production
data stores, production data migrations, live-data backfills. data stores, production data migrations, live-data backfills.
3. **Billing / plan changes** — plan or tier migration, pricing/concurrency 3. **Billing / plan changes** — plan or tier migration, pricing/concurrency
+1 -1
View File
@@ -52,7 +52,7 @@ plausible-looking result to fill the gap.
contents, API responses, search hits, metrics. If the tool did not return contents, API responses, search hits, metrics. If the tool did not return
it, you do not know it — say so. it, you do not know it — say so.
Origin: [org-internal #2115] root cause 5 / [org-internal #2118] — deepseek-v4-flash reviewers fabricated Origin: [TT-2115] root cause 5 / [TT-2118] — deepseek-v4-flash reviewers fabricated
full review JSON when the wiki tool surface (MCP tooling at the time, now full review JSON when the wiki tool surface (MCP tooling at the time, now
retired) was unavailable to subagents. retired) was unavailable to subagents.
+1 -1
View File
@@ -30,7 +30,7 @@ NOT grep + read whole files to reconstruct relationships.
The main checkout's `.codegraph/` indexes ONLY that tree. A git worktree lives The main checkout's `.codegraph/` indexes ONLY that tree. A git worktree lives
outside the repo path, so nearest-`.codegraph/` resolution finds nothing under outside the repo path, so nearest-`.codegraph/` resolution finds nothing under
it — graph queries in a workflow worktree silently degrade to grep+read it — graph queries in a workflow worktree silently degrade to grep+read
(the [org-internal #2561] / TD-006 gap). (the [TT-2561] / TD-006 gap).
- `script/session-worktree.sh create` and `script/scratch-worktree.sh create` - `script/session-worktree.sh create` and `script/scratch-worktree.sh create`
build a per-worktree index automatically: `codegraph init -i <path>` runs in build a per-worktree index automatically: `codegraph init -i <path>` runs in
+8 -9
View File
@@ -6,13 +6,13 @@ Context compaction keeps long pipelines inside the model's context window.
Two mechanisms exist: Two mechanisms exist:
1. **Stage-boundary compaction** (main session / orchestrator) — 1. **Stage-boundary compaction** (main session / orchestrator) —
capacity-driven [org-internal #2601]: compact at a clean stage boundary capacity-driven [TT-2601]: compact at a clean stage boundary
ONLY when a capacity trigger holds (below), not merely because the ONLY when a capacity trigger holds (below), not merely because the
boundary was reached. boundary was reached.
2. **Round-boundary compaction** (multi-round reviews) — compact at every 2. **Round-boundary compaction** (multi-round reviews) — compact at every
review round ≥ 2, after the round's state is persisted. review round ≥ 2, after the round's state is persisted.
### Stage-boundary compaction (capacity-driven, [org-internal #2601]) ### Stage-boundary compaction (capacity-driven, [TT-2601])
The main session orchestrates the whole pipeline while delegating stages to The main session orchestrates the whole pipeline while delegating stages to
subagents, but still accumulates their result summaries, planning reasoning, subagents, but still accumulates their result summaries, planning reasoning,
@@ -35,16 +35,16 @@ A trigger holding → compact at the NEAREST clean boundary. No trigger → KEEP
the context: preserved working context is worth more than the tokens it costs. the context: preserved working context is worth more than the tokens it costs.
**Mixed capacity threshold — min(water_level, absolute cap) **Mixed capacity threshold — min(water_level, absolute cap)
[org-internal #3321] / TD-434]**: the capacity threshold is [TT-3321] / TD-434]**: the capacity threshold is
`min(context × water_level, compaction.max_context_tokens)` — whichever is `min(context × water_level, compaction.max_context_tokens)` — whichever is
LOWER (`max_context_tokens` default 100_000; `0` restores pure water_level LOWER (`max_context_tokens` default 100_000; `0` restores pure water_level
semantics [org-internal #3342]). On large windows the 100k cap binds first. semantics [TT-3342]). On large windows the 100k cap binds first.
Measurement basis: the provider's REAL reported usage (input tokens), not Measurement basis: the provider's REAL reported usage (input tokens), not
local estimates; the rendered guidance and the Trigger A/B overflow paths local estimates; the rendered guidance and the Trigger A/B overflow paths
resolve the same normalized values (harness 内建的压缩引导模块, see the resolve the same normalized values (harness 内建的压缩引导模块, see the
instance term mapping). instance term mapping).
**Sub-session posture [org-internal #3321]**: Explorers compact by returning **Sub-session posture [TT-3321]**: Explorers compact by returning
promptly, persisting only what their skill protocol REQUIRES (review findings promptly, persisting only what their skill protocol REQUIRES (review findings
JSON to the run workspace reviews directory). Workers persist outputs to JSON to the run workspace reviews directory). Workers persist outputs to
Tier 1 BEFORE finishing. The parent context is where the mixed threshold Tier 1 BEFORE finishing. The parent context is where the mixed threshold
@@ -52,8 +52,7 @@ applies. Tier 1 boundary: two-tier-artifacts rule.
**Short runs target zero intra-run compaction** — an implement → **Short runs target zero intra-run compaction** — an implement →
review-code → verify run fits one window; clean boundaries do not compact review-code → verify run fits one window; clean boundaries do not compact
without a trigger. (Rationale + retired legacy stages: Tier-2 reference page without a trigger. (Rationale + retired legacy stages: instance detail page `rules/compact-detail`, reachable via the ticket backend.)
`rules/compact-detail`, reachable via the ticket backend.)
Clean boundaries where triggers are evaluated (live skills): Clean boundaries where triggers are evaluated (live skills):
@@ -74,7 +73,7 @@ DAG-routed runs, the latest review pages, or the DoD matrix
(`{slug}/05-verify-*`) — to recover the current slug, stage, and outstanding (`{slug}/05-verify-*`) — to recover the current slug, stage, and outstanding
items. Do not rely on the compacted summary alone. items. Do not rely on the compacted summary alone.
**Identity verification precedes re-orientation [org-internal #2459].** **Identity verification precedes re-orientation [TT-2459].**
Every compacted summary opens with a harness-injected `### Session Identity` Every compacted summary opens with a harness-injected `### Session Identity`
card (agent, role/mode/ticket, CORE artifact rows, role re-read set), card (agent, role/mode/ticket, CORE artifact rows, role re-read set),
rendered from role-yaml `compact.preserve` lists and issue CORE rows by the rendered from role-yaml `compact.preserve` lists and issue CORE rows by the
@@ -99,7 +98,7 @@ The `compact` tool rejects calls made too soon after the previous one
turns); no boundary type is exempt. Beyond `insufficient_turns` the tool has turns); no boundary type is exempt. Beyond `insufficient_turns` the tool has
more guard outcomes (`min_interval`, `no_model`, `circuit_breaker_open`, more guard outcomes (`min_interval`, `no_model`, `circuit_breaker_open`,
`disabled` — rejected; `compaction_in_progress`, `deduplicated` — deferred; `disabled` — rejected; `compaction_in_progress`, `deduplicated` — deferred;
full table: Tier-2 reference page `rules/compact-detail`, reachable via the full table: instance detail page `rules/compact-detail`, reachable via the
ticket backend). All are accept-and-continue: never retry past a guard, ticket backend). All are accept-and-continue: never retry past a guard,
never work around the dedup/breaker state. A boundary whose compaction was never work around the dedup/breaker state. A boundary whose compaction was
rejected or deferred simply keeps its context; the persisted artifacts still rejected or deferred simply keeps its context; the persisted artifacts still
+15 -16
View File
@@ -11,16 +11,16 @@ point and see exactly what is done, in progress, and deferred.
| When | Who | What | | When | Who | What |
|------|-----|------| |------|-----|------|
| After the DAG artifact is frozen (`review-dag` PASS + freeze confirmation per `analyze-dag/SKILL.md` §Output & Lifecycle step 2, [org-internal #3379]) | Aggregator agent | Convert the source Epic's draft acceptance criteria into a formal checklist; annotate requirement-covered items `_(DAG frozen: {epic-slug}/dag v1)_` | | After the DAG artifact is frozen (`review-dag` PASS + freeze confirmation per `analyze-dag/SKILL.md` §Output & Lifecycle step 2, [TT-3379]) | Aggregator agent | Convert the source Epic's draft acceptance criteria into a formal checklist; annotate requirement-covered items `_(DAG frozen: {epic-slug}/dag v1)_` |
| After each iteration commit (`implement` Phase 4.5) | Developer | Check off items delivered by this iteration | | After each iteration commit (`implement` Phase 4.5) | Developer | Check off items delivered by this iteration |
| After a PR is created | Developer | Append a `## 当前状态` live-status section (or update it) with PR number + mergeable; in an Epic task list, append the PR reference to the corresponding row | | After a PR is created | Developer | Append a `## 当前状态` live-status section (or update it) with PR number + mergeable; in an Epic task list, append the PR reference to the corresponding row |
| After code review converges (`review-code` PASS, Phase E) | Orchestrator | Check off review-related items; annotate `_(reviewed: round N PASS)_`; update the `## 当前状态` review row; label the PR `ready-to-merge` — keep-mergeable automation takes over (hand-written keep-mergeable commits are retired) | | After code review converges (`review-code` PASS, Phase E) | Orchestrator | Check off review-related items; annotate `_(reviewed: round N PASS)_`; update the `## 当前状态` review row; label the PR `ready-to-merge` — keep-mergeable automation takes over (hand-written keep-mergeable commits are retired) |
| On CI key state transitions (first green / failure / cumulative goal reached) | Verifier or Developer | Update the process-type AC (e.g. "N consecutive green runs") progress note in the issue; record the run number | | On CI key state transitions (first green / failure / cumulative goal reached) | Verifier or Developer | Update the process-type AC (e.g. "N consecutive green runs") progress note in the issue; record the run number |
| At `verify` Phase 5.6 (final sweep before PASS) / issue close | Closing agent (Verifier on the primary path; otherwise the last role that closes the issue) | Final sweep — every remaining item gets annotated; **archive-at-close**: fold `## 当前状态`, then mark the `## 工件索引` comment archived per the artifact-index-guards rule guard #3 (see「归档动作」below) | | At `verify` Phase 5.6 (final sweep before PASS) / issue close | Closing agent (Verifier on the primary path; otherwise the last role that closes the issue) | Final sweep — every remaining item gets annotated; **archive-at-close**: fold `## 当前状态`, then mark the `## 工件索引` comment archived per the artifact-index-guards rule guard #3 (see「归档动作」below) |
> Historical ([org-internal #3072] phase 3): the requirements/design/plan exit sync points > Historical ([TT-3072] phase 3): the requirements/design/plan exit sync points
> were archived with their skills (detail: Tier-2 reference page > were archived with their skills (detail: instance detail page
> `rules/issue-checklist-sync-detail`, reachable via the ticket backend). > `rules/issue-checklist-sync-detail`, in the consuming instance).
Between sync points the checklist stays as-is. **PR / review / CI Between sync points the checklist stays as-is. **PR / review / CI
transitions** MUST also be visible via the live status note below — the transitions** MUST also be visible via the live status note below — the
@@ -32,12 +32,12 @@ For flows with externally visible transitions between skill exits —
standalone bugfix, incident response, long-running reviews — maintain a short standalone bugfix, incident response, long-running reviews — maintain a short
live status table near the top of the issue body, updated in place via the live status table near the top of the issue body, updated in place via the
ticket-backend issue-update API at the transition moment (closes the ticket-backend issue-update API at the transition moment (closes the
stale-issue gap [org-internal #1668]/[org-internal #1689]]). stale-issue gap [TT-1668]/[TT-1689]]).
All roles use the literal heading `## 当前状态` (no suffix). If an issue carries All roles use the literal heading `## 当前状态` (no suffix). If an issue carries
a legacy variant (e.g. `## 当前状态 (live)` from [org-internal #1668]), normalize it to a legacy variant (e.g. `## 当前状态 (live)` from [TT-1668]), normalize it to
`## 当前状态` at the first transition touched. Example table + legacy-variant `## 当前状态` at the first transition touched. Example table + legacy-variant
list: Tier-2 reference page `rules/issue-checklist-sync-detail`, reachable list: instance detail page `rules/issue-checklist-sync-detail`, reachable
via the ticket backend. via the ticket backend.
Rules: Rules:
@@ -57,15 +57,15 @@ Rules:
- At verify PASS / issue close, fold the table's content into checklist - At verify PASS / issue close, fold the table's content into checklist
annotations and remove the section (see the「归档动作」section below). annotations and remove the section (see the「归档动作」section below).
### Automated sync ([org-internal #1833], timer-polled since [org-internal #2813]) ### Automated sync ([TT-1833], timer-polled since [TT-2813])
PR / review / CI status-row transitions are automated by the `status-sync` PR / review / CI status-row transitions are automated by the `status-sync`
poller (deployed as a host timer, every 5 min; event sources + latency table poller (deployed as a host timer, every 5 min; event sources + latency table
on the Tier-2 reference page `rules/issue-checklist-sync-detail`, reachable on the instance detail page `rules/issue-checklist-sync-detail`, reachable
via the ticket backend). Roles do NOT hand-write those three row types. A PR via the ticket backend). Roles do NOT hand-write those three row types. A PR
body may carry several close refs (batch PRs, [org-internal #3731] body may carry several close refs (batch PRs, [TT-3731]
`land-batch`): rows fan out to EVERY referenced issue `land-batch`): rows fan out to EVERY referenced issue
(`parseClosesFixesWide` — [org-internal #3867], merged 2026-08-31) — Chinese 关闭/修复 refs (`parseClosesFixesWide` — [TT-3867], merged 2026-08-31) — Chinese 关闭/修复 refs
drive rows too, even though the ticket backend never auto-closes those drive rows too, even though the ticket backend never auto-closes those
keywords. The remaining sync points (checklist annotations at skill exits, keywords. The remaining sync points (checklist annotations at skill exits,
`## 当前状态` creation, deferral/pending marking, section fold-at-close) are `## 当前状态` creation, deferral/pending marking, section fold-at-close) are
@@ -80,8 +80,7 @@ deduplicated `[status-sync-cron]` issue.
Pipeline mode has natural sync points at skill exits; standalone bugfix and Pipeline mode has natural sync points at skill exits; standalone bugfix and
incident flows do NOT — the only boundaries are commit → PR → review → CI → incident flows do NOT — the only boundaries are commit → PR → review → CI →
merge, and EACH is a sync point with the same annotations as the progressive merge, and EACH is a sync point with the same annotations as the progressive
table above (full table: Tier-2 reference page table above (full table: instance detail page `rules/issue-checklist-sync-detail`, reachable via the ticket backend): fix
`rules/issue-checklist-sync-detail`, reachable via the ticket backend): fix
commit → tick fix-delivered ACs `_(commit {sha}: file)_`; PR → open/update commit → tick fix-delivered ACs `_(commit {sha}: file)_`; PR → open/update
`## 当前状态`; review convergence → tick review ACs + review row; CI `## 当前状态`; review convergence → tick review ACs + review row; CI
transitions → process-AC progress with run number; verify PASS / close → transitions → process-AC progress with run number; verify PASS / close →
@@ -108,7 +107,7 @@ For tickets routed through the DAG pipeline (see workflow-routing rule
comment (single-comment invariant). The body aggregator table is kept as a comment (single-comment invariant). The body aggregator table is kept as a
historical snapshot at close and does NOT carry ARCHIVE. historical snapshot at close and does NOT carry ARCHIVE.
### Kind/MVP tickets — exemption ([org-internal #3061]) ### Kind/MVP tickets — exemption ([TT-3061])
`Kind/MVP` tickets run the interactive no-pipeline mode: no stage exits → `Kind/MVP` tickets run the interactive no-pipeline mode: no stage exits →
**nothing to sync**, no `## 当前状态` section (no PR/review/CI rows until **nothing to sync**, no `## 当前状态` section (no PR/review/CI rows until
@@ -137,7 +136,7 @@ non-checklist content. PR / review / CI transitions ALSO go into the
### 归档动作(issue 关闭 = 归档) ### 归档动作(issue 关闭 = 归档)
**生命周期 = 工单生命周期**([org-internal #1929]):文档生命周期与源 issue 绑定 —— verify PASS → issue 关闭 = 归档。Tier-2 工件库无独立生命周期。 **生命周期 = 工单生命周期**([TT-1929]):文档生命周期与源 issue 绑定 —— verify PASS → issue 关闭 = 归档。Tier-2 工件库无独立生命周期。
归档是 **显式动作**,由关闭 issue 的 agent 执行:主路径为 Verifier 在 `verify` Phase 5.6;路径跳过 verify 时(audit-only、文档类、standalone/bugfix)由关闭 issue 的 role 代为执行。无论哪个 actor,均遵循 artifact-index-guards 规则 guard #3(机制以共享 write-patterns Pattern 10 为准)。动作序列: 归档是 **显式动作**,由关闭 issue 的 agent 执行:主路径为 Verifier 在 `verify` Phase 5.6;路径跳过 verify 时(audit-only、文档类、standalone/bugfix)由关闭 issue 的 role 代为执行。无论哪个 actor,均遵循 artifact-index-guards 规则 guard #3(机制以共享 write-patterns Pattern 10 为准)。动作序列:
@@ -146,7 +145,7 @@ non-checklist content. PR / review / CI transitions ALSO go into the
3. **标记 `## 工件索引` 归档**:按共享 write-patterns Pattern 10 Archive-at-close 原位 edit(机制以 Pattern 10 为准)。横幅日期以实际关闭日为准。 3. **标记 `## 工件索引` 归档**:按共享 write-patterns Pattern 10 Archive-at-close 原位 edit(机制以 Pattern 10 为准)。横幅日期以实际关闭日为准。
4. **关闭 issue**:PR body 的 `Closes #N` 在 merge 时自动关闭;无 PR 的流程由 **关闭 issue 的 agent** 执行工单后端的 issue-close API 完成闭环。 4. **关闭 issue**:PR body 的 `Closes #N` 在 merge 时自动关闭;无 PR 的流程由 **关闭 issue 的 agent** 执行工单后端的 issue-close API 完成闭环。
约束([org-internal #1928] 设计约束;机制细节以共享 write-patterns Pattern 10 Archive-at-close 为准,此处不重复): 约束([TT-1928] 设计约束;机制细节以共享 write-patterns Pattern 10 Archive-at-close 为准,此处不重复):
- **L 级大件(>~300 行)留 Tier-2 工件库不删除** —— 页面与位置列 URL 保持不动(稳定 URL 供历史与共享契约引用)。 - **L 级大件(>~300 行)留 Tier-2 工件库不删除** —— 页面与位置列 URL 保持不动(稳定 URL 供历史与共享契约引用)。
- **索引/状态/归档判定全部收敛到 issue** —— Tier-2 工件库无独立生命周期;归档标记只落在 `## 工件索引` 评论。 - **索引/状态/归档判定全部收敛到 issue** —— Tier-2 工件库无独立生命周期;归档标记只落在 `## 工件索引` 评论。
+5 -5
View File
@@ -14,7 +14,7 @@ regression-test follow-up, or any parent/child breakdown — the issues MUST be
cross-linked: cross-linked:
- **Parent issue**: after creating all children, update the parent body so its - **Parent issue**: after creating all children, update the parent body so its
task list references each child by `#<number>` (e.g. `- [ ] [org-internal #1556] — [P0] ...`). task list references each child by `#<number>` (e.g. `- [ ] [TT-1556] — [P0] ...`).
The ticket backend renders these as clickable links and auto-generates a The ticket backend renders these as clickable links and auto-generates a
back-reference on each child's timeline. back-reference on each child's timeline.
- **Child issue**: its body MUST contain a `## 父级 / Parent` section referencing - **Child issue**: its body MUST contain a `## 父级 / Parent` section referencing
@@ -25,7 +25,7 @@ cross-linked:
### Issue ↔ Tier-2 artifact (pipeline traceability) ### Issue ↔ Tier-2 artifact (pipeline traceability)
When a production skill (`analyze-dag`, publishing the `{epic-slug}/dag` When a production skill (`analyze-dag`, publishing the `{epic-slug}/dag`
artifact; historically the pre-[org-internal #3072] producer skills) publishes artifact; historically the pre-[TT-3072] producer skills) publishes
an artifact to the Tier-2 artifact library, the link to the source issue is an artifact to the Tier-2 artifact library, the link to the source issue is
only **half-built** — the library's index page links forward to the issue, only **half-built** — the library's index page links forward to the issue,
but the issue has no link back to the library. A stakeholder opening the but the issue has no link back to the library. A stakeholder opening the
@@ -44,7 +44,7 @@ After publishing, the skill MUST complete the reverse link on the source issue:
reads the 工件索引 comment and fetches every CORE row's 位置 (shared reads the 工件索引 comment and fetches every CORE row's 位置 (shared
read-patterns doc Pattern 6), instead of hard-coded library paths. Skills' read-patterns doc Pattern 6), instead of hard-coded library paths. Skills'
re-read instructions therefore point at the index. re-read instructions therefore point at the index.
- **Archive-at-close(归档动作, [org-internal #1929]/[org-internal #1928])** — issue 关闭即归档;Tier-2 工件库无独立 - **Archive-at-close(归档动作, [TT-1929]/[TT-1928])** — issue 关闭即归档;Tier-2 工件库无独立
生命周期。`ARCHIVE` is not just a per-row re-read priority: at issue close the 生命周期。`ARCHIVE` is not just a per-row re-read priority: at issue close the
whole index is marked archived by the closing agent (Verifier at `verify` whole index is marked archived by the closing agent (Verifier at `verify`
Phase 5.6 on the primary path; otherwise the Orchestrator / last-role that Phase 5.6 on the primary path; otherwise the Orchestrator / last-role that
@@ -56,11 +56,11 @@ After publishing, the skill MUST complete the reverse link on the source issue:
- **Sync the issue's checklist** per the issue-checklist-sync rule for the - **Sync the issue's checklist** per the issue-checklist-sync rule for the
matching exit point (live: the DAG-freeze sync point after `review-dag` matching exit point (live: the DAG-freeze sync point after `review-dag`
PASS; the legacy requirements-exit / design-exit / plan-exit points were PASS; the legacy requirements-exit / design-exit / plan-exit points were
retired with their skills, [org-internal #3072] phase 3). retired with their skills, [TT-3072] phase 3).
- Skip if no source issue exists (no `Closes #N` / `Fixes #N` / roadmap chunk - Skip if no source issue exists (no `Closes #N` / `Fixes #N` / roadmap chunk
mapping ties this slug to an issue). mapping ties this slug to an issue).
**Size/S & Size/M exception ([org-internal #1832]) — RETIRED (2026-08-21, [org-internal #3072] **Size/S & Size/M exception ([TT-1832]) — RETIRED (2026-08-21, [TT-3072]
phase 3)**: retired with the legacy producer skills and the `sizing:` block. phase 3)**: retired with the legacy producer skills and the `sizing:` block.
Historical indexes pointing at in-issue artifacts (`位置 = #comment-{id}`) Historical indexes pointing at in-issue artifacts (`位置 = #comment-{id}`)
remain valid, readable locations; new artifacts publish where their live remain valid, readable locations; new artifacts publish where their live
+9 -11
View File
@@ -3,7 +3,7 @@
## Session Scope Guard (mandatory) ## Session Scope Guard (mandatory)
> Enforcement layer: precheck-mechanized (injection-budget batch-2, > Enforcement layer: precheck-mechanized (injection-budget batch-2,
> [org-internal #3667]) — pre-flight sources 1-3 below live in the repo's > [TT-3667]) — pre-flight sources 1-3 below live in the repo's
> session-conflicts script, source 4 in the claim script's compare-and-swap. > session-conflicts script, source 4 in the claim script's compare-and-swap.
> This file is the normative definition, NOT part of any `agents_md` > This file is the normative definition, NOT part of any `agents_md`
> injection whitelist since 2026-08-29 — do not re-add; the checks run at > injection whitelist since 2026-08-29 — do not re-add; the checks run at
@@ -11,8 +11,7 @@
Standalone and ticket-seeded sessions run without a pipeline around them — Standalone and ticket-seeded sessions run without a pipeline around them —
no plan, no reviewer keeping them inside their work item. When such a no plan, no reviewer keeping them inside their work item. When such a
session hits a test failure NOT caused by its own change ([org-internal session hits a test failure NOT caused by its own change ([TT-1803], via [TT-1753]/[TT-1744]), it tends to fix the foreign
[org-internal #1803]], via [org-internal #1753]/[[org-internal #1744]]), it tends to fix the foreign
failure in place (drifting off-task), and sessions seeded for the same issue failure in place (drifting off-task), and sessions seeded for the same issue
collide on the same shared flaky test. collide on the same shared flaky test.
@@ -48,17 +47,17 @@ on ANY source → the ticket is already owned: ABORT (or, for a DEAD claim,
take over via the mechanized channel below; otherwise coordinate on the take over via the mechanized channel below; otherwise coordinate on the
issue), never silently start a second owner. issue), never silently start a second owner.
**Mechanized ([org-internal #3667])**: the repo's session-conflicts script **Mechanized ([TT-3667])**: the repo's session-conflicts script
(`<session-conflicts-cmd> <ticket>`) scans sources 1-3 in one read-only pass (`<session-conflicts-cmd> <ticket>`) scans sources 1-3 in one read-only pass
(exit 4 = conflict, matching the claim script; source 1 fail-opens visibly (exit 4 = conflict, matching the claim script; source 1 fail-opens visibly
when the app API is down — the backend hard guard [org-internal #1989] when the app API is down — the backend hard guard [TT-1989]
backstops); source 4 IS the claim script's compare-and-swap. Dead-claim backstops); source 4 IS the claim script's compare-and-swap. Dead-claim
takeover is mechanized in the claim script (see below); manual recipes: takeover is mechanized in the claim script (see below); manual recipes:
the headless-session-ops skill's ticket-recipe reference §0. the headless-session-ops skill's ticket-recipe reference §0.
**Dead-claim takeover ([org-internal #3668]).** A claim whose session is **Dead-claim takeover ([TT-3668]).** A claim whose session is
gone (404 on the app API) and whose branch was never pushed is a DEAD claim gone (404 on the app API) and whose branch was never pushed is a DEAD claim
— the [org-internal #3419] shape. Do NOT hand-edit the dead claim comment — the [TT-3419] shape. Do NOT hand-edit the dead claim comment
(the retired admin workaround — unauditable); run the claim script's (the retired admin workaround — unauditable); run the claim script's
takeover subcommand (`<claim-takeover-cmd> <ticket> <branch> --session-id takeover subcommand (`<claim-takeover-cmd> <ticket> <branch> --session-id
<id>`) instead. Evidence rule (the claim script's header is normative): a <id>`) instead. Evidence rule (the claim script's header is normative): a
@@ -77,8 +76,7 @@ ticket-driven work is to claim the ticket — one atomic action of THREE
steps, valid ONLY when all complete: (1) set the issue assignee to the steps, valid ONLY when all complete: (1) set the issue assignee to the
working account, (2) post a claim comment naming the workflow branch and working account, (2) post a claim comment naming the workflow branch and
session id, (3) push the workflow branch to remote (even an empty commit — session id, (3) push the workflow branch to remote (even an empty commit —
a purely local branch is invisible to other sessions, [org-internal a purely local branch is invisible to other sessions, [TT-2280]/[TT-2282]). Use the repo's claim wrappers (staged-transaction claim
[org-internal #2280]/[org-internal #2282]]). Use the repo's claim wrappers (staged-transaction claim
script; exit codes and CAS semantics in its header; non-zero = NOT claimed) script; exit codes and CAS semantics in its header; non-zero = NOT claimed)
and the provision wrapper (adds the worktree + Tier-1 runs scaffold). The and the provision wrapper (adds the worktree + Tier-1 runs scaffold). The
manual 3-step is the fallback where the scripts are unavailable, same manual 3-step is the fallback where the scripts are unavailable, same
@@ -88,7 +86,7 @@ re-verification.
branch's recent commits for `#<ticket>` — surfacing an equivalent branch's recent commits for `#<ticket>` — surfacing an equivalent
implementation already on main *before* the merge rejection. implementation already on main *before* the merge rejection.
**Merge-time review gate ([org-internal #2345]).** `pipeline/review-code` is **Merge-time review gate ([TT-2345]).** `pipeline/review-code` is
a required status: merge needs it green OR the route-based exemption a required status: merge needs it green OR the route-based exemption
(Kind/* close routes skip review-code — posted by the repo's (Kind/* close routes skip review-code — posted by the repo's
review-gate-exemption script). Read the commit-status endpoint for the PR review-gate-exemption script). Read the commit-status endpoint for the PR
@@ -102,7 +100,7 @@ your chunk before starting.
Two sessions owning the same issue or code area is never faster — it is the Two sessions owning the same issue or code area is never faster — it is the
exact collision this rule prevents. If a collision HAS happened, follow the exact collision this rule prevents. If a collision HAS happened, follow the
failure-path playbook at the ownership-collision runbook (Tier-2 reference failure-path playbook at the ownership-collision runbook (instance detail page
page, reachable via the ticket backend). page, reachable via the ticket backend).
### Scope ### Scope
+5 -5
View File
@@ -13,8 +13,8 @@ each other's entries and one session's `pop` returns the other session's
content — or `drop`/`clear` wipes uncommitted work belonging to a session in content — or `drop`/`clear` wipes uncommitted work belonging to a session in
a different worktree. a different worktree.
This failure mode has already destroyed completed work in production ([org-internal #1655] / This failure mode has already destroyed completed work in production ([TT-1655] /
[org-internal #1629] — a finished 25-test implementation overwritten on the shared stack). [TT-1629] — a finished 25-test implementation overwritten on the shared stack).
**Iron Law: NEVER use `git stash` (or `git stash pop` / `push` / `drop` / **Iron Law: NEVER use `git stash` (or `git stash pop` / `push` / `drop` /
`clear` / `apply`) inside an octopus worktree.** `clear` / `apply`) inside an octopus worktree.**
@@ -70,7 +70,7 @@ If you must `git checkout <base>` to reproduce a failure but the worktree is
dirty, do **not** reach for stash. Instead: dirty, do **not** reach for stash. Instead:
- WIP-commit first (option 1), or - WIP-commit first (option 1), or
- Use the lifecycle-managed scratch-worktree script ([org-internal #2790]) to materialise - Use the lifecycle-managed scratch-worktree script ([TT-2790]) to materialise
the base commit in a *separate* worktree and run the failing test there: the base commit in a *separate* worktree and run the failing test there:
```bash ```bash
@@ -82,7 +82,7 @@ dirty, do **not** reach for stash. Instead:
classification check. The script registers the worktree, symlinks classification check. The script registers the worktree, symlinks
`node_modules` from the source checkout when `bun.lock` matches, and the `node_modules` from the source checkout when `bun.lock` matches, and the
`sweep` backstop reclaims worktrees abandoned by dying sessions — bare `sweep` backstop reclaims worktrees abandoned by dying sessions — bare
`git worktree add /tmp/octopus/...` has no such recovery ([org-internal #2790]). `git worktree add /tmp/octopus/...` has no such recovery ([TT-2790]).
### Exceptions ### Exceptions
@@ -110,4 +110,4 @@ dirty, do **not** reach for stash. Instead:
If a parallel-session stash collision happens again despite this rule, treat If a parallel-session stash collision happens again despite this rule, treat
it as a Sev-2 process incident: stop work, recover via it as a Sev-2 process incident: stop work, recover via
`git fsck --unreachable` / `git log -g --walk-reflogs stash`, open a follow-up `git fsck --unreachable` / `git log -g --walk-reflogs stash`, open a follow-up
referencing [org-internal #1655]. referencing [TT-1655].
+8 -8
View File
@@ -6,7 +6,7 @@
- Test actual implementation, do not duplicate logic into tests - Test actual implementation, do not duplicate logic into tests
- Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs. - Tests cannot run from repo root (guard: `do-not-run-tests-from-root`); run from package dirs.
- **Local pre-check: run `<test-cmd:changed>`** from the owning package after editing source. It selects only tests affected by your uncommitted + branch changes (path-mapping ∪ CodeGraph direct dependents) and runs them in a single process — seconds, machine stays responsive. Use `--print` to see the selection without running, `--all` to scan beyond the home package. - **Local pre-check: run `<test-cmd:changed>`** from the owning package after editing source. It selects only tests affected by your uncommitted + branch changes (path-mapping ∪ CodeGraph direct dependents) and runs them in a single process — seconds, machine stays responsive. Use `--print` to see the selection without running, `--all` to scan beyond the home package.
- **Before a delivery push: `<test-cmd:changed>` green + `<typecheck-cmd>` clean** — same selector as CI's PR side (local parity, [org-internal #4425]). The full suite (`<test-cmd:parallel>`) stays with nightly / `run-full-tests` / manual pre-merge runs. 实例命令绑定见 core/adapters/TERMINOLOGY.md。 - **Before a delivery push: `<test-cmd:changed>` green + `<typecheck-cmd>` clean** — same selector as CI's PR side (local parity, [TT-4425]). The full suite (`<test-cmd:parallel>`) stays with nightly / `run-full-tests` / manual pre-merge runs. 实例命令绑定见 core/adapters/TERMINOLOGY.md。
- Never use the bare single-process test runner for the full suite; `<test-cmd:parallel>` shards it and process-isolates known-corrupting files. Parallelism is controlled by `TEST_SHARDS` (default 3; raise it on beefy CI runners, e.g. `TEST_SHARDS=7`). - Never use the bare single-process test runner for the full suite; `<test-cmd:parallel>` shards it and process-isolates known-corrupting files. Parallelism is controlled by `TEST_SHARDS` (default 3; raise it on beefy CI runners, e.g. `TEST_SHARDS=7`).
### Pre-existing test failures must be filed, not silently logged ### Pre-existing test failures must be filed, not silently logged
@@ -18,7 +18,7 @@ problem" and do NOT bury it in a report body.
- Classify it: run the failing test on the base commit (see `verify` Phase 2.6). - Classify it: run the failing test on the base commit (see `verify` Phase 2.6).
Fails there too → pre-existing (BF); passes there → regression you must fix. Fails there too → pre-existing (BF); passes there → regression you must fix.
- De-duplicate BEFORE filing (retro [org-internal #2696]): search existing - De-duplicate BEFORE filing (retro [TT-2696]): search existing
`baseline-failure` tickets — open AND closed — by test/file name to surface `baseline-failure` tickets — open AND closed — by test/file name to surface
candidates, then match by **failure signature** (error signature + affected candidates, then match by **failure signature** (error signature + affected
surface — one root-cause family may span several tests; see the surface — one root-cause family may span several tests; see the
@@ -40,7 +40,7 @@ it is a **flaky test**. Do NOT silently re-run until it passes and move on.
- Detect: re-run the suite (or use the project's flaky detector). Record every - Detect: re-run the suite (or use the project's flaky detector). Record every
test that shows intermittent behavior — name, failure rate, and run count. test that shows intermittent behavior — name, failure rate, and run count.
- De-duplicate BEFORE filing (retro [org-internal #2696]): same - De-duplicate BEFORE filing (retro [TT-2696]): same
signature-based procedure as baseline failures above, against existing signature-based procedure as baseline failures above, against existing
`flaky-test` tickets. `flaky-test` tickets.
- File it: the Verifier registers every un-tracked flaky test as a - File it: the Verifier registers every un-tracked flaky test as a
@@ -55,7 +55,7 @@ it is a **flaky test**. Do NOT silently re-run until it passes and move on.
NOT fix it in place — classify, file, and return to your task per the NOT fix it in place — classify, file, and return to your task per the
session-scope-guard rule. A repository-wide flaky test is a shared magnet — session-scope-guard rule. A repository-wide flaky test is a shared magnet —
fixing it in place drifts off-task and collides with its owner fixing it in place drifts off-task and collides with its owner
([org-internal #1803]). ([TT-1803]).
### Testing Kobalte components with happydom ### Testing Kobalte components with happydom
@@ -74,7 +74,7 @@ render reliably.
A single component MUST NOT carry both a `.test.ts` and a `.test.tsx` test A single component MUST NOT carry both a `.test.ts` and a `.test.tsx` test
file — the two-file split duplicated ~3300 lines of overlapping assertions file — the two-file split duplicated ~3300 lines of overlapping assertions
across one UI package [org-internal #1712]. Use exactly one file per across one UI package [TT-1712]. Use exactly one file per
component, chosen by test style: component, chosen by test style:
| Test style | Extension | When to use | | Test style | Extension | When to use |
@@ -129,17 +129,17 @@ expect(source).not.toContain(`@${NAMESPACE}`)
Each package MUST have exactly ONE test root — no parallel tracks Each package MUST have exactly ONE test root — no parallel tracks
(`src/**/__tests__/`, a `tests/` dir alongside colocated `src/`, or a `test/` (`src/**/__tests__/`, a `tests/` dir alongside colocated `src/`, or a `test/`
alongside `tests/`); a second root drifts and breaks test discovery alongside `tests/`); a second root drifts and breaks test discovery
([org-internal #1711], extended to all packages by [org-internal #1821]). ([TT-1711], extended to all packages by [TT-1821]).
Rules: Rules:
- New tests: create them at the package's single root from the start. - New tests: create them at the package's single root from the start.
- Do NOT create `src/**/__tests__/` directories in any package — parallel - Do NOT create `src/**/__tests__/` directories in any package — parallel
tracks drift (residuals eliminated by [org-internal #1821]). tracks drift (residuals eliminated by [TT-1821]).
- For `test/`-root packages: mirror the `src/` path (`test/<src-relative>.test.ts`); - For `test/`-root packages: mirror the `src/` path (`test/<src-relative>.test.ts`);
type-level tests live alongside the behavioral suites in the config area. type-level tests live alongside the behavioral suites in the config area.
- For colocated-root packages: keep tests next to the source file; one test - For colocated-root packages: keep tests next to the source file; one test
file per component [org-internal #1712]. file per component [TT-1712].
Per-package root tables live in the instance layer (they name concrete Per-package root tables live in the instance layer (they name concrete
package paths); the invariant itself — ONE root per package — is universal. package paths); the invariant itself — ONE root per package — is universal.
+6 -6
View File
@@ -1,6 +1,6 @@
> Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。 > Core 中立版(Increment 2 改写)。术语对照见 core/adapters/TERMINOLOGY.md;本组织实例表述见 dogfood 对应文件。
## Ticket Lifecycle — registry-first filing, claim-to-promote ([org-internal #3002] G1) ## Ticket Lifecycle — registry-first filing, claim-to-promote ([TT-3002] G1)
Bugs worth fixing start life as a **registry row**, not an independent ticket. Bugs worth fixing start life as a **registry row**, not an independent ticket.
This extends the two-tier-artifacts philosophy to the ticket queue: a This extends the two-tier-artifacts philosophy to the ticket queue: a
@@ -25,20 +25,20 @@ is how the 2026-08 backlog formed.)
``` ```
- **TD-NNN** is allocated at REGISTRATION via the ledger mutex - **TD-NNN** is allocated at REGISTRATION via the ledger mutex
[org-internal #3322]: the 配额账本脚本 (`td-alloc` 形态, `bash <alloc-script> [TT-3322]: the 配额账本脚本 (`td-alloc` 形态, `bash <alloc-script>
<count> <source-slug> [--ticket N]`) takes a contiguous range from the TD <count> <source-slug> [--ticket N]`) takes a contiguous range from the TD
allocation ledger (a standing tracker issue) — append-only `**td-alloc**` allocation ledger (a standing tracker issue) — append-only `**td-alloc**`
comments, earliest-comment-id wins on collision. **ANY allocation — manual comments, earliest-comment-id wins on collision. **ANY allocation — manual
included — must land a td-alloc comment on the ledger BEFORE the registry included — must land a td-alloc comment on the ledger BEFORE the registry
row is written** (script, tool API, or web UI). Hand-computed `max + 1` row is written** (script, tool API, or web UI). Hand-computed `max + 1`
without a ledger comment is FORBIDDEN (parallel-session races, without a ledger comment is FORBIDDEN (parallel-session races,
[org-internal #3322]). The id is **reserved for life**: promotion reuses [TT-3322]). The id is **reserved for life**: promotion reuses
it, never renumbers. Run the alloc script's `--check` (reconciliation) it, never renumbers. Run the alloc script's `--check` (reconciliation)
when the last check predates this batch, and in retrospectives. when the last check predates this batch, and in retrospectives.
- **De-duplication** queries the TD index (same-source rows) plus open - **De-duplication** queries the TD index (same-source rows) plus open
promoted issues (cross-source); index matching replaces title-keyword promoted issues (cross-source); index matching replaces title-keyword
matching (keyword dedup once produced 18 fragments from one source). matching (keyword dedup once produced 18 fragments from one source).
- **Query-failure ruling ([org-internal #3383]: fail-open, visible)**: if the - **Query-failure ruling ([TT-3383]: fail-open, visible)**: if the
dedup query itself errors (backend API failure — NOT "queried and found no dedup query itself errors (backend API failure — NOT "queried and found no
match"), retry once; on second failure file anyway, marking the comment match"), retry once; on second failure file anyway, marking the comment
`dedup-unverified` for retro/reconciliation sweep. Fail-closed rejected: `dedup-unverified` for retro/reconciliation sweep. Fail-closed rejected:
@@ -63,7 +63,7 @@ source.
### PR 准入(pr-admission,TD-678) ### PR 准入(pr-admission,TD-678)
会话交付物 = 分支 + 报告;开 PR 属编排职权,按容量串行一次一张、双绿并入 会话交付物 = 分支 + 报告;开 PR 属编排职权,按容量串行一次一张、双绿并入
再开下一张([org-internal #3864] 管合并出口、本节管 PR 入口)。交付推送前置 再开下一张([TT-3864] 管合并出口、本节管 PR 入口)。交付推送前置
本地验证(`<test-cmd:changed>` + `<typecheck-cmd>` 绿;实例命令绑定见 本地验证(`<test-cmd:changed>` + `<typecheck-cmd>` 绿;实例命令绑定见
core/adapters/TERMINOLOGY.md)。编排不可达可自开,PR 正文标 core/adapters/TERMINOLOGY.md)。编排不可达可自开,PR 正文标
`uncoordinated`。细则与门控项:pipeline-gate 清单 PR 准入节。 `uncoordinated`。细则与门控项:pipeline-gate 清单 PR 准入节。
@@ -75,7 +75,7 @@ occurrence: evidence (run, commit, failing output, failure rate) attaches as
comments on the family's **umbrella ticket** (ticket-backend issue), keyed by comments on the family's **umbrella ticket** (ticket-backend issue), keyed by
failure signature (error signature + affected surface, not just failure signature (error signature + affected surface, not just
`file::test-name` — one root-cause family may span several tests; precedents `file::test-name` — one root-cause family may span several tests; precedents
[org-internal #2585], [org-internal #2925]). Filing a new ticket when the [TT-2585], [TT-2925]). Filing a new ticket when the
signature already matches an existing family (open or closed) is forbidden — signature already matches an existing family (open or closed) is forbidden —
attach evidence instead. A family umbrella is closed when its signature no attach evidence instead. A family umbrella is closed when its signature no
longer reproduces. longer reproduces.
+5 -7
View File
@@ -53,8 +53,7 @@ Tier 1 is an optimization an artifact opts INTO, not out of.
### Common classifications ### Common classifications
Per-artifact table (review findings, prompt files, working drafts, draft/frozen Per-artifact table (review findings, prompt files, working drafts, draft/frozen
contracts, issue checklist, 工件索引, `index.json` …): Tier-2 reference page contracts, issue checklist, 工件索引, `index.json` …): instance detail page `rules/two-tier-artifacts-detail` (reachable via the ticket backend); the
`rules/two-tier-artifacts-detail` (reachable via the ticket backend); the
decision rule above classifies anything unlisted. decision rule above classifies anything unlisted.
### Two indexes, parallel not replacement ### Two indexes, parallel not replacement
@@ -74,14 +73,13 @@ Closed by the **Verifier** at verify PASS (or the Orchestrator when no
verify). The archive step is the ONLY point active-run Tier 1 content enters verify). The archive step is the ONLY point active-run Tier 1 content enters
git history: git history:
1. Generate the bundle [org-internal #3604]: 1. Generate the bundle [TT-3604]:
the run-bundle generator script with `--slug {slug} [--ticket N] [--pr N]` the run-bundle generator script with `--slug {slug} [--ticket N] [--pr N]`
— flips meta to "archived", hashes the workspace into the `sha256_16` — flips meta to "archived", hashes the workspace into the `sha256_16`
manifest, writes `archive/{ticket}-{slug}.json`, validates. manifest, writes `archive/{ticket}-{slug}.json`, validates.
2. Commit the bundle on the workflow branch (rides into main via `--no-ff`). 2. Commit the bundle on the workflow branch (rides into main via `--no-ff`).
Direct pushes to main stay blocked by branch protection [org-internal Direct pushes to main stay blocked by branch protection [TT-3604]; do not bypass.
[org-internal #3604]]; do not bypass. 3. **归档前置校验** [TT-2727]: the generator validates by default
3. **归档前置校验** [org-internal #2727]: the generator validates by default
(`--no-validate` must not reach a merge); red exit = fix before close. (`--no-validate` must not reach a merge); red exit = fix before close.
The L0 merge gate rejects non-compliant bundles at merge anyway. The L0 merge gate rejects non-compliant bundles at merge anyway.
@@ -109,7 +107,7 @@ reproducibility trace — enough to reconstruct what a run produced.
the designated re-read entry — after `compact`, read `runs/{slug}/index.json`, the designated re-read entry — after `compact`, read `runs/{slug}/index.json`,
not conversation memory. not conversation memory.
### Gate furlough([org-internal #3607]) ### Gate furlough([TT-3607])
强制门的唯一退出通道是 gate 台账(furlough ledger)的 furlough 条目 强制门的唯一退出通道是 gate 台账(furlough ledger)的 furlough 条目
(测量证据 + reopen 条件);无台账条目的减门/跳过改动一律拒绝,台账 (测量证据 + reopen 条件);无台账条目的减门/跳过改动一律拒绝,台账
+9 -10
View File
@@ -24,7 +24,7 @@ On every substantive request that is tied to a ticket, run Step 0:
`Kind/*` label when known; omit `kind` when not yet read (the tool returns `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 the default route plus a read-ticket-then-re-invoke instruction). Agents
with the route-gate option enabled enforce this mechanically with the route-gate option enabled enforce this mechanically
[org-internal #3328]: other tool calls are dispatch-rejected until the [TT-3328]: other tool calls are dispatch-rejected until the
路由解析工具 runs. Do not hand-read the routing table when the tool is 路由解析工具 runs. Do not hand-read the routing table when the tool is
available. available.
3. **Read the ticket's `Kind/*` label** from the issue body or via the issue 3. **Read the ticket's `Kind/*` label** from the issue body or via the issue
@@ -38,7 +38,7 @@ On every substantive request that is tied to a ticket, run Step 0:
`skip` / `keep_gates` downstream. Never drop a gate the route lists in `skip` / `keep_gates` downstream. Never drop a gate the route lists in
`keep_gates`; never add back a stage the route lists in `skip`. `keep_gates`; never add back a stage the route lists in `skip`.
### Degradation — label missing, unknown, or wrong ([org-internal #1828] AC) ### Degradation — label missing, unknown, or wrong ([TT-1828] AC)
- **No ticket / no `Kind/*` label / label not in the table** → `default` - **No ticket / no `Kind/*` label / label not in the table** → `default`
route (natural-language matching). State this in one line ("no Kind/\* route (natural-language matching). State this in one line ("no Kind/\*
@@ -64,15 +64,14 @@ On every substantive request that is tied to a ticket, run Step 0:
### Runtime growth signals (post-sizing) ### Runtime growth signals (post-sizing)
Two live growth mechanisms (narrative: Tier-2 reference page Two live growth mechanisms (narrative: instance detail page `rules/workflow-routing-detail`, reachable via the ticket backend; retired
`rules/workflow-routing-detail`, reachable via the ticket backend; retired
Size/* history: the instance rules-history archive). Canonical key: Size/* history: the instance rules-history archive). Canonical key:
`dag.size_derivation.oversize_signals` (TD/DUP-F009). `dag.size_derivation.oversize_signals` (TD/DUP-F009).
- **DAG-routed tickets** (DAG Epic, DAG-routed `Kind/Feature`, their - **DAG-routed tickets** (DAG Epic, DAG-routed `Kind/Feature`, their
`Kind/Task` children — no `Size/*` tier): runtime growth fires the `Kind/Task` children — no `Size/*` tier): runtime growth fires the
oversize signals → response is **re-derivation + review-dag re-run**. oversize signals → response is **re-derivation + review-dag re-run**.
- **Bug tickets (big-bug relabel rule, [org-internal #3061])**: a `Kind/Bug` - **Bug tickets (big-bug relabel rule, [TT-3061])**: a `Kind/Bug`
hitting a design-level trigger (design-decision root cause, shared-contract / hitting a design-level trigger (design-decision root cause, shared-contract /
public-API change, data migration) has outgrown the bug type — mandatory public-API change, data migration) has outgrown the bug type — mandatory
action is **relabel `Kind/Feature`** (Step 0 reroutes into the DAG action is **relabel `Kind/Feature`** (Step 0 reroutes into the DAG
@@ -87,10 +86,10 @@ never quietly override.
The DAG ticket pipeline (`analyze-dag` → task DAG → single gate `review-dag`) The DAG ticket pipeline (`analyze-dag` → task DAG → single gate `review-dag`)
is the **default** route for `Kind/Epic` and `Kind/Feature` is the **default** route for `Kind/Epic` and `Kind/Feature`
([org-internal #3061] Phase 2 / TD-388). Both resolve via the routes table ([TT-3061] Phase 2 / TD-388). Both resolve via the routes table
directly — **no trigger/marker check** (route rollback = revert PR). directly — **no trigger/marker check** (route rollback = revert PR).
Authoritative definition: the `dag:` block in the workflow-routing table; Authoritative definition: the `dag:` block in the workflow-routing table;
narrative + history: Tier-2 reference page `rules/workflow-routing-detail`. narrative + history: instance detail page `rules/workflow-routing-detail`.
1. **`Kind/Epic` or `Kind/Feature` → `dag.route`**: entry `analyze-dag`, 1. **`Kind/Epic` or `Kind/Feature` → `dag.route`**: entry `analyze-dag`,
single gate `review-dag` (replaces review-design-space + single gate `review-dag` (replaces review-design-space +
@@ -126,12 +125,12 @@ rules archive; rulings in the phase-3 retirement ruling doc (Tier-2
reference, reachable via the ticket backend). Nothing trims gates — reference, reachable via the ticket backend). Nothing trims gates —
`never_trim` is structural. `never_trim` is structural.
### 立案降档 — filing/sprint-mode([org-internal #3002] G5 / [org-internal #3007]) ### 立案降档 — filing/sprint-mode([TT-3002] G5 / [TT-3007])
Sprint 期间债务侧显式降档,不靠纪律。开关:routing table `filing.sprint-mode` Sprint 期间债务侧显式降档,不靠纪律。开关:routing table `filing.sprint-mode`
(默认 `false`)。`true`(冲刺期)时 verify Phase 5.5 registry-only 不分严重度 (默认 `false`)。`true`(冲刺期)时 verify Phase 5.5 registry-only 不分严重度
(登记行照写、零丢失;独立工单创建冻结至开关回 `false`,已登记行按 (登记行照写、零丢失;独立工单创建冻结至开关回 `false`,已登记行按
ticket-lifecycle 规则正常认领升票;期间 HIGH/MEDIUM 行不被 reaper 触碰, ticket-lifecycle 规则正常认领升票;期间 HIGH/MEDIUM 行不被 reaper 触碰,
[org-internal #3004])。BF/FT(5.55/5.56)不受影响。谁翻转:冲刺负责人(人), [TT-3004])。BF/FT(5.55/5.56)不受影响。谁翻转:冲刺负责人(人),
在冲刺跟踪单记一行;开关值即 routing table 当前值,verify 每次运行时读取。 在冲刺跟踪单记一行;开关值即 routing table 当前值,verify 每次运行时读取。
动机与细节:Tier-2 参考页(经 ticket backend)`rules/workflow-routing-detail`。 动机与细节:instance detail page `rules/workflow-routing-detail`。
+2 -2
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eightarms.net/octopus-workflow/schemas/review-status.schema.json", "$id": "https://eightarms.net/octopus-workflow/schemas/review-status.schema.json",
"title": "Review Status", "title": "Review Status",
"description": "Schema for tracking the lifecycle state of a review session. This file lives at runs/{slug}/reviews/{stage}/status.json: initialized by the Orchestrator at Phase A (step 0.5) with the full required set, appended by the Synthesizer at Phase B (history[] + current_round), and finalized with `converged` by the Orchestrator at Phase E (see skills/_shared/review-pipeline-phases.md). Reader: the retrospective token-telemetry probe (retrospective/scripts/token-telemetry.ts) walks runs/**/reviews/*/status.json (canonical) and the legacy .artifacts/**/reviews/*/status.json, reading `history[]` (code-level legacy alias `rounds[]`, both handled) and `current_round`. For CLOSED runs (active workspace removed at archive-at-close), the probe reconstructs per-stage round counts from reviews/{stage}/round{N}/ artifact paths in the committed archive bundle runs/archive/{slug}.json ([org-internal #2591]). Since TD/TRC-F006 ([org-internal #2688]) the archive bundle can also embed an explicit digest of this history[] (top-level review_history: {stage, rounds, final_verdict, per_round[]}) so round counts and verdicts stay verifiable offline, without path reconstruction.", "description": "Schema for tracking the lifecycle state of a review session. This file lives at runs/{slug}/reviews/{stage}/status.json: initialized by the Orchestrator at Phase A (step 0.5) with the full required set, appended by the Synthesizer at Phase B (history[] + current_round), and finalized with `converged` by the Orchestrator at Phase E (see skills/_shared/review-pipeline-phases.md). Reader: the retrospective token-telemetry probe (retrospective/scripts/token-telemetry.ts) walks runs/**/reviews/*/status.json (canonical) and the legacy .artifacts/**/reviews/*/status.json, reading `history[]` (code-level legacy alias `rounds[]`, both handled) and `current_round`. For CLOSED runs (active workspace removed at archive-at-close), the probe reconstructs per-stage round counts from reviews/{stage}/round{N}/ artifact paths in the committed archive bundle runs/archive/{slug}.json ([TT-2591]). Since TD/TRC-F006 ([TT-2688]) the archive bundle can also embed an explicit digest of this history[] (top-level review_history: {stage, rounds, final_verdict, per_round[]}) so round counts and verdicts stay verifiable offline, without path reconstruction.",
"type": "object", "type": "object",
"required": ["slug", "started_at", "current_round", "max_rounds", "converged", "history"], "required": ["slug", "started_at", "current_round", "max_rounds", "converged", "history"],
"properties": { "properties": {
@@ -19,7 +19,7 @@
"max_rounds": { "max_rounds": {
"type": "integer", "type": "integer",
"default": 3, "default": 3,
"description": "Per-skill bound: `review-artifact` skill (process target) = 3 (the roadmap/design/plan targets were archived 2026-08-21, [org-internal #3072] phase 3); `review-code` = 2 default / 3 high-risk (`workflow-routing.yaml` `review.max_rounds`, [org-internal #3567]). `review-dag` (the review-artifact skill's DAG single-gate target) binds per depth from `dag_metrics.review_depth`: D1 ≤2, D2 ≤3, D3 ≤3, D4 ≤4 — D4 reaches round 4, exceeding the shared `review-artifact` default, so the DAG per-depth cap takes precedence (see review-artifact/SKILL.md review-dag Phase D MAX_ROUNDS). Set explicitly by the skill; default 3 is a fallback only." "description": "Per-skill bound: `review-artifact` skill (process target) = 3 (the roadmap/design/plan targets were archived 2026-08-21, [TT-3072] phase 3); `review-code` = 2 default / 3 high-risk (`workflow-routing.yaml` `review.max_rounds`, [TT-3567]). `review-dag` (the review-artifact skill's DAG single-gate target) binds per depth from `dag_metrics.review_depth`: D1 ≤2, D2 ≤3, D3 ≤3, D4 ≤4 — D4 reaches round 4, exceeding the shared `review-artifact` default, so the DAG per-depth cap takes precedence (see review-artifact/SKILL.md review-dag Phase D MAX_ROUNDS). Set explicitly by the skill; default 3 is a fallback only."
}, },
"converged": { "converged": {
"type": "boolean" "type": "boolean"
+2 -2
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eightarms.net/octopus-workflow/schemas/reviewer-output.schema.json", "$id": "https://eightarms.net/octopus-workflow/schemas/reviewer-output.schema.json",
"title": "Reviewer Output", "title": "Reviewer Output",
"description": "Schema for a single reviewer's output for one review dimension. Also the Tier 1 review-findings schema ([org-internal #1988]): migrated skills (review-code) write each dimension's finding as a JSON file at runs/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json validated by this schema; the index.json row for that file carries type=review-findings, schema=this $id. When a dimension has multiple reviewers (dim_split > 1, e.g. D3 TOPO:2 / D4 TOPO:2), each writes its OWN slot file findings-{DIMENSION_CODE}-r{k}.json with reviewer_slot/reviewer_count set. See templates/runs-layout.md and rules/two-tier-artifacts.md.", "description": "Schema for a single reviewer's output for one review dimension. Also the Tier 1 review-findings schema ([TT-1988]): migrated skills (review-code) write each dimension's finding as a JSON file at runs/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json validated by this schema; the index.json row for that file carries type=review-findings, schema=this $id. When a dimension has multiple reviewers (dim_split > 1, e.g. D3 TOPO:2 / D4 TOPO:2), each writes its OWN slot file findings-{DIMENSION_CODE}-r{k}.json with reviewer_slot/reviewer_count set. See templates/runs-layout.md and rules/two-tier-artifacts.md.",
"type": "object", "type": "object",
"required": ["dimension", "dimension_label", "verdict", "quantitative_summary", "findings", "reviewed_files"], "required": ["dimension", "dimension_label", "verdict", "quantitative_summary", "findings", "reviewed_files"],
"properties": { "properties": {
@@ -17,7 +17,7 @@
"reviewer_slot": { "reviewer_slot": {
"type": "integer", "type": "integer",
"minimum": 1, "minimum": 1,
"description": "1-based slot of this reviewer WITHIN its dimension, when dim_split assigns >1 reviewer to the dimension (e.g. review-dag D3 TOPO:2, D4 TOPO:2 — dim_split per `workflow-routing.yaml` dag.size_derivation.review_depth). Multi-reviewer dimensions write one file per slot: findings-{DIMENSION_CODE}-r{k}.json. Omitted for single-reviewer dimensions (file stays findings-{DIMENSION_CODE}.json). Preserves per-reviewer attribution for the retrospective overlap analysis ([org-internal #2996] step 1a)." "description": "1-based slot of this reviewer WITHIN its dimension, when dim_split assigns >1 reviewer to the dimension (e.g. review-dag D3 TOPO:2, D4 TOPO:2 — dim_split per `workflow-routing.yaml` dag.size_derivation.review_depth). Multi-reviewer dimensions write one file per slot: findings-{DIMENSION_CODE}-r{k}.json. Omitted for single-reviewer dimensions (file stays findings-{DIMENSION_CODE}.json). Preserves per-reviewer attribution for the retrospective overlap analysis ([TT-2996] step 1a)."
}, },
"reviewer_count": { "reviewer_count": {
"type": "integer", "type": "integer",
+3 -3
View File
@@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema", "$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://eightarms.net/octopus-workflow/schemas/runs-bundle.schema.json", "$id": "https://eightarms.net/octopus-workflow/schemas/runs-bundle.schema.json",
"title": "Tier 1 Run Archive Bundle", "title": "Tier 1 Run Archive Bundle",
"description": "Composite archive bundle committed at close: runs/archive/{slug}.json = {meta, index}. Dual-profile by schema_version: >= 2 strict (closed core field set + free-form context bag), 1 or absent legacy (structural typing only; historical drift normalized by repair-run-bundles.ts, see [org-internal #2588]). Validated by validate-run-bundles.ts; CI wiring: .gitea/workflows/octopus-schemas.yml. Authoritative layout: templates/runs-layout.md. Boundary rule: rules/two-tier-artifacts.md.", "description": "Composite archive bundle committed at close: runs/archive/{slug}.json = {meta, index}. Dual-profile by schema_version: >= 2 strict (closed core field set + free-form context bag), 1 or absent legacy (structural typing only; historical drift normalized by repair-run-bundles.ts, see [TT-2588]). Validated by validate-run-bundles.ts; CI wiring: .gitea/workflows/octopus-schemas.yml. Authoritative layout: templates/runs-layout.md. Boundary rule: rules/two-tier-artifacts.md.",
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
"required": ["meta", "index"], "required": ["meta", "index"],
@@ -11,11 +11,11 @@
"index": true, "index": true,
"working_notes": { "working_notes": {
"type": "string", "type": "string",
"description": "Final content of runs/{slug}/working-notes.md ([org-internal #2600]), inlined at archive time when the file exists. The one Tier 1 artifact whose CONTENT (not just digest) rides in the bundle — the run's narrative memory (decisions, dead ends, reviewer feedback), consumed by later retro probes and the notes-injection degradation path ([org-internal #2601]). Absent when the run kept no working notes." "description": "Final content of runs/{slug}/working-notes.md ([TT-2600]), inlined at archive time when the file exists. The one Tier 1 artifact whose CONTENT (not just digest) rides in the bundle — the run's narrative memory (decisions, dead ends, reviewer feedback), consumed by later retro probes and the notes-injection degradation path ([TT-2601]). Absent when the run kept no working notes."
}, },
"review_history": { "review_history": {
"type": "array", "type": "array",
"description": "Offline-verifiability digest of the run's review rounds (TD/TRC-F006, [org-internal #2688]): one entry per review stage the run executed, each derived from that stage's live reviews/{stage}/status.json history[] at archive time. Lets closed-run probes reconstruct round counts and verdicts from the bundle alone, without the (removed) live workspace or path reconstruction ([org-internal #2591]). Absent when the run kept no review rounds.", "description": "Offline-verifiability digest of the run's review rounds (TD/TRC-F006, [TT-2688]): one entry per review stage the run executed, each derived from that stage's live reviews/{stage}/status.json history[] at archive time. Lets closed-run probes reconstruct round counts and verdicts from the bundle alone, without the (removed) live workspace or path reconstruction ([TT-2591]). Absent when the run kept no review rounds.",
"items": { "$ref": "#/$defs/reviewHistoryEntry" } "items": { "$ref": "#/$defs/reviewHistoryEntry" }
} }
}, },
+1 -1
View File
@@ -55,7 +55,7 @@
"browser-evidence", "browser-evidence",
"other" "other"
], ],
"description": "Artifact category. 'meta'/'index' for the manifest files themselves; stage categories for produced artifacts. 'review-synthesis' marks a synthesis result artifact (round verdict) as distinct from 'synthesis-prompt' (the Phase B task prompt) and 'review-status' (the lifecycle file). 'precondition-gate' marks the review-code mechanical-green gate log. 'working-notes' is the cross-stage narrative memory file ([org-internal #2600]) — one file per run, appended by every role at close, registered once (stage/produced_by null: multi-stage, multi-role). 'browser-evidence' marks a browser evidence pack manifest ([org-internal #4497] N-03, browser/{session-id}/manifest.json — shared/pack-manifest-v1)." "description": "Artifact category. 'meta'/'index' for the manifest files themselves; stage categories for produced artifacts. 'review-synthesis' marks a synthesis result artifact (round verdict) as distinct from 'synthesis-prompt' (the Phase B task prompt) and 'review-status' (the lifecycle file). 'precondition-gate' marks the review-code mechanical-green gate log. 'working-notes' is the cross-stage narrative memory file ([TT-2600]) — one file per run, appended by every role at close, registered once (stage/produced_by null: multi-stage, multi-role). 'browser-evidence' marks a browser evidence pack manifest ([TT-4497] N-03, browser/{session-id}/manifest.json — shared/pack-manifest-v1)."
}, },
"schema": { "schema": {
"type": ["string", "null"], "type": ["string", "null"],
+12 -12
View File
@@ -23,7 +23,7 @@
"$defs": { "$defs": {
"stage": { "stage": {
"type": "string", "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.", "description": "A pipeline stage identifier — the 5 live gates (post-[TT-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"] "enum": ["review-dag", "review-code", "verify", "audit-process", "merge-pr"]
}, },
"entry": { "entry": {
@@ -33,7 +33,7 @@
"skill": { "skill": {
"type": ["string", "null"], "type": ["string", "null"],
"enum": ["implement", "review-artifact", "review-code", "verify", "analyze-dag", 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)." "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 ([TT-3072] phase 3, 2026-08-21 - the instance archive)."
}, },
"mode": { "mode": {
"type": ["string", "null"], "type": ["string", "null"],
@@ -56,7 +56,7 @@
"preflight": { "preflight": {
"type": "array", "type": "array",
"items": { "$ref": "#/$defs/preflightItem" }, "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." "description": "Evidence-based producer pre-flight checklist ([TT-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" }, "notes": { "type": "string" },
"effort": { "effort": {
@@ -69,7 +69,7 @@
"preflightPolicy": { "preflightPolicy": {
"type": "object", "type": "object",
"additionalProperties": false, "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.", "description": "Thresholds for the retro → routes.{Kind}.preflight evidence loop ([TT-2599]). Authoritative values live here; the retrospective consults this block, it does not restate the numbers.",
"properties": { "properties": {
"max_items": { "type": "integer", "minimum": 1 }, "max_items": { "type": "integer", "minimum": 1 },
"min_sample": { "type": "integer", "minimum": 0 }, "min_sample": { "type": "integer", "minimum": 0 },
@@ -86,7 +86,7 @@
"item": { "type": "string", "description": "One checklist line the Producer verifies before implementing." }, "item": { "type": "string", "description": "One checklist line the Producer verifies before implementing." },
"evidence": { "evidence": {
"type": "string", "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'." "description": "Retro reference justifying the item, e.g. 'retro [TT-2599]: COR × unhandled-null, 5/8 first-round FAILs on Kind/Bug'."
}, },
"added_cycle": { "added_cycle": {
"type": "string", "type": "string",
@@ -97,23 +97,23 @@
"filing": { "filing": {
"type": "object", "type": "object",
"additionalProperties": false, "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.", "description": "Filing policy (立案/登记策略). sprint-mode ([TT-3007]): when true, verify Phase 5.5 promotes registry rows to tickets in sprint mode only. work-ticket-wip-cap ([TT-3005] G3): open non-TD work tickets beyond this count require scheduling evidence, else they stay registry rows.",
"properties": { "properties": {
"sprint-mode": { "sprint-mode": {
"type": "boolean", "type": "boolean",
"description": "Sprint-mode filing downgrade switch ([org-internal #3007])." "description": "Sprint-mode filing downgrade switch ([TT-3007])."
}, },
"work-ticket-wip-cap": { "work-ticket-wip-cap": {
"type": "integer", "type": "integer",
"minimum": 0, "minimum": 0,
"description": "WIP cap on open non-TD work tickets (Kind/* without assignee) before new filings require scheduling evidence ([org-internal #3005] G3)." "description": "WIP cap on open non-TD work tickets (Kind/* without assignee) before new filings require scheduling evidence ([TT-3005] G3)."
} }
} }
}, },
"review": { "review": {
"type": "object", "type": "object",
"additionalProperties": false, "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.", "description": "Review round budget (process-diet P0b, [TT-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"], "required": ["max_rounds"],
"properties": { "properties": {
"max_rounds": { "max_rounds": {
@@ -152,7 +152,7 @@
"preflight": { "preflight": {
"type": "array", "type": "array",
"items": { "$ref": "#/$defs/preflightItem" }, "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." "description": "Evidence-based pre-flight checklist for the DAG route ([TT-2905] 方案 3) — same item shape as routes.{Kind}.preflight ([TT-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."
} }
} }
}, },
@@ -183,7 +183,7 @@
"replaces": { "replaces": {
"type": "array", "type": "array",
"items": { "type": "string" }, "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." "description": "Historical documentation of which legacy gates the single gate replaced ([TT-3072] phase 3 retired them) — free-form strings, not the live stage vocabulary."
}, },
"depth_from": { "type": "string", "enum": ["size_derivation"] }, "depth_from": { "type": "string", "enum": ["size_derivation"] },
"never_trim": { "type": "boolean" } "never_trim": { "type": "boolean" }
@@ -201,7 +201,7 @@
"items": { "type": "string", "enum": ["Kind/Epic", "Kind/Feature"] }, "items": { "type": "string", "enum": ["Kind/Epic", "Kind/Feature"] },
"uniqueItems": true, "uniqueItems": true,
"minItems": 1, "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)." "description": "Ticket kinds whose DAG children reference them as ## 父级 / Parent ([TT-3061] Phase 2 / TD-388: Kind/Feature added alongside Kind/Epic)."
}, },
"parent_aggregator": { "type": "boolean" } "parent_aggregator": { "type": "boolean" }
} }
+1 -1
View File
@@ -9,7 +9,7 @@
> - `frontend/SKILL.md` > - `frontend/SKILL.md`
> >
> (The `roadmap`, `requirements-elicitation`, `design`, and `plan-iterations` > (The `roadmap`, `requirements-elicitation`, `design`, and `plan-iterations`
> referencing skills were archived 2026-08-21, [org-internal #3072] phase 3 — see > referencing skills were archived 2026-08-21, [TT-3072] phase 3 — see
> `.octopus/archive/skills/`; their copies of this directive moved with them.) > `.octopus/archive/skills/`; their copies of this directive moved with them.)
> >
> **When editing:** update this file only. Each skill references this file via a > **When editing:** update this file only. Each skill references this file via a
@@ -70,6 +70,6 @@
`review-dag` (review-artifact targets — same id feeds the `review-dag` (review-artifact targets — same id feeds the
`pipeline/{REVIEW_TYPE}` commit-status context; see review-artifact Phase `pipeline/{REVIEW_TYPE}` commit-status context; see review-artifact Phase
Bindings). (The design-space/plan targets were archived 2026-08-21, Bindings). (The design-space/plan targets were archived 2026-08-21,
[org-internal #3072] phase 3.) [TT-3072] phase 3.)
- `{DIMENSION_COUNT}` — 10 (code review; 9 in standalone-bugfix mode), 3 (review-dag single gate), or 10 (process audit); used in - `{DIMENSION_COUNT}` — 10 (code review; 9 in standalone-bugfix mode), 3 (review-dag single gate), or 10 (process audit); used in
the skill's SKILL.md reference text, not inside this template body the skill's SKILL.md reference text, not inside this template body
@@ -113,7 +113,7 @@ Each skill references this base template via `core/skills/_shared/review-orchest
rather than inlining the JSON array. This centralization ensures the base rather than inlining the JSON array. This centralization ensures the base
permission surface stays consistent across all review/audit skills. permission surface stays consistent across all review/audit skills.
**Tier-1 local exception** ([org-internal #1988]): migrated skills that write raw per-dimension **Tier-1 local exception** ([TT-1988]): migrated skills that write raw per-dimension
findings to `<runs-root>/**` (e.g. `review-code`) add ONE scoped `edit` allow findings to `<runs-root>/**` (e.g. `review-code`) add ONE scoped `edit` allow
to the base set — `{ permission: "edit", pattern: "<runs-root>/**", action: to the base set — `{ permission: "edit", pattern: "<runs-root>/**", action:
"allow" }` — so the reviewer can write its OWN finding file. This is a "allow" }` — so the reviewer can write its OWN finding file. This is a
@@ -122,7 +122,7 @@ edit on the code under review, so rule #7 (auditor independence) holds. See
`_shared/review-pipeline-phases.md` Phase A step 4 and `review-code/SKILL.md` `_shared/review-pipeline-phases.md` Phase A step 4 and `review-code/SKILL.md`
Phase A step 3 for the inline extended array. Phase A step 3 for the inline extended array.
Residual risk — accepted trade-off (TD/STD-F004, [org-internal #2688]): the grant is scoped Residual risk — accepted trade-off (TD/STD-F004, [TT-2688]): the grant is scoped
to `<runs-root>/**`, wider than the reviewer's own findings file. Per-file to `<runs-root>/**`, wider than the reviewer's own findings file. Per-file
narrowing was considered and rejected: findings paths are round- and narrowing was considered and rejected: findings paths are round- and
dimension-dependent (`{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`), dimension-dependent (`{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json`),
@@ -132,7 +132,7 @@ residual exposure — a misbehaving reviewer could overwrite a sibling stage's
Tier 1 files — is recorded here as accepted; auditor independence is Tier 1 files — is recorded here as accepted; auditor independence is
unaffected (code under review lives outside `runs/`). unaffected (code under review lives outside `runs/`).
### No bash for Explorer sub-agents (deliberate boundary, [org-internal #2115] RC4 / [org-internal #2126]) ### No bash for Explorer sub-agents (deliberate boundary, [TT-2115] RC4 / [TT-2126])
Explorer sub-agents (Reviewer / auditor / Tool roles) have **no bash**. The Explorer sub-agents (Reviewer / auditor / Tool roles) have **no bash**. The
`explorer` agent is built deny-by-default at `explorer` agent is built deny-by-default at
@@ -151,7 +151,7 @@ Synthesizer / Verifier's job (Worker sub-agents, which DO have bash via the
`worker` agent defaults) — not the Reviewer's. Report the need in findings `worker` agent defaults) — not the Reviewer's. Report the need in findings
instead of attempting bash. instead of attempting bash.
> **[org-internal #2126] Task 2 conclusion — keep + document.** The `deny **` pushed per-tool > **[TT-2126] Task 2 conclusion — keep + document.** The `deny **` pushed per-tool
> at `<harness-package>/src/session/prompt.ts` is the **session tool-enable / > at `<harness-package>/src/session/prompt.ts` is the **session tool-enable /
> disable map** (it disables `todowrite` / `task` / `experimental.primary_tools` > disable map** (it disables `todowrite` / `task` / `experimental.primary_tools`
> for subagents and allows forwarded MCP tools). It is NOT the source of the > for subagents and allows forwarded MCP tools). It is NOT the source of the
@@ -165,4 +165,4 @@ instead of attempting bash.
- `{REVISION_ROLE}` — "Developer" (code review), "Analyst" (review-dag single - `{REVISION_ROLE}` — "Developer" (code review), "Analyst" (review-dag single
gate), or "Remediator" (process audit). The Worker role that revises gate), or "Remediator" (process audit). The Worker role that revises
artifacts between rounds. (The Architect/Planner revision roles belonged to artifacts between rounds. (The Architect/Planner revision roles belonged to
the archived design-space / iteration-plan targets, [org-internal #3072] phase 3.) the archived design-space / iteration-plan targets, [TT-3072] phase 3.)
+27 -20
View File
@@ -9,14 +9,14 @@ parameters and reference this doc rather than duplicating the shared mechanics.
legitimately uses "auditor"/"Re-audit" terminology. All generic descriptions legitimately uses "auditor"/"Re-audit" terminology. All generic descriptions
use `{REVIEWER_OR_AUDITOR}`. use `{REVIEWER_OR_AUDITOR}`.
**Output model — two findings sinks** ([org-internal #1988] Tier 1 migration): raw per-dimension **Output model — two findings sinks** ([TT-1988] Tier 1 migration): raw per-dimension
reviewer findings have ONE of two sinks, chosen per skill. The **synthesis** reviewer findings have ONE of two sinks, chosen per skill. The **synthesis**
(human gate) and **commit status** are ALWAYS Tier 2 (Gitea) regardless of the (human gate) and **commit status** are ALWAYS Tier 2 (Gitea) regardless of the
findings sink. findings sink.
| Sink | Skills | Reviewer writes findings to | Synthesizer reads findings from | | Sink | Skills | Reviewer writes findings to | Synthesizer reads findings from |
|---|---|---|---| |---|---|---|---|
| `tier1-local` (migrated) | `review-code`, `review-artifact` (live targets: review-dag, audit-process; the roadmap/design-space/plan targets were archived 2026-08-21, [org-internal #3072] phase 3) | `<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json` (validated by `core/schemas/reviewer-output.schema.json`) | the local finding files (no Gitea call) | | `tier1-local` (migrated) | `review-code`, `review-artifact` (live targets: review-dag, audit-process; the roadmap/design-space/plan targets were archived 2026-08-21, [TT-3072] phase 3) | `<runs-root>/{slug}/reviews/{stage}/round{N}/findings-{DIMENSION_CODE}.json` (validated by `core/schemas/reviewer-output.schema.json`) | the local finding files (no Gitea call) |
| `tier2-comment` (fallback) | _(none — all targets migrated)_ | Gitea PR/issue comment via `工单评论 API(见 TERMINOLOGY)` (Pattern 5) | `工单评论 API(见 TERMINOLOGY)` (Pattern 3) | | `tier2-comment` (fallback) | _(none — all targets migrated)_ | Gitea PR/issue comment via `工单评论 API(见 TERMINOLOGY)` (Pattern 5) | `工单评论 API(见 TERMINOLOGY)` (Pattern 3) |
Migration complete — every review/audit skill now outputs `tier1-local`; the Migration complete — every review/audit skill now outputs `tier1-local`; the
@@ -61,7 +61,7 @@ in `_shared/gitea-write-patterns.md`.
`stage` = `{REVIEW_TYPE}`, `produced_by` = `Orchestrator`, `schema` = the `stage` = `{REVIEW_TYPE}`, `produced_by` = `Orchestrator`, `schema` = the
review-status `$id`). review-status `$id`).
1. **Tool-availability probe** (defense-in-depth, [org-internal #2115] RC1 / [org-internal #2126]). Before 1. **Tool-availability probe** (defense-in-depth, [TT-2115] RC1 / [TT-2126]). Before
dispatching any {REVIEWER_OR_AUDITOR}, verify reviewers will be able to read dispatching any {REVIEWER_OR_AUDITOR}, verify reviewers will be able to read
wiki artifacts (requirements / design / plan / prior-review reports). A wiki artifacts (requirements / design / plan / prior-review reports). A
reviewer that cannot read its inputs aborts or hallucinates — catch this ONCE reviewer that cannot read its inputs aborts or hallucinates — catch this ONCE
@@ -74,7 +74,7 @@ in `_shared/gitea-write-patterns.md`.
reachable; anything else — timeout, connection refused, 5xx — is reachable; anything else — timeout, connection refused, 5xx — is
unreachable). If reachable → continue to step 2. unreachable). If reachable → continue to step 2.
- **Fallback path** (when REST is unreachable, e.g. a - **Fallback path** (when REST is unreachable, e.g. a
cross-repo scenario [org-internal #2115]): verify the **local wiki clone** at cross-repo scenario [TT-2115]): verify the **local wiki clone** at
`<wiki-clone-root>/{repo}-wiki/` is readable — `<wiki-clone-root>/{repo}-wiki/` is readable —
`glob(pattern="*.md", path="<wiki-clone-root>/{repo}-wiki/")`. If the clone `glob(pattern="*.md", path="<wiki-clone-root>/{repo}-wiki/")`. If the clone
is readable → continue to step 2; reviewers use the local clone (see is readable → continue to step 2; reviewers use the local clone (see
@@ -266,7 +266,7 @@ Otherwise:
- The {REVISION_ROLE} MUST NOT receive the full text of all findings inline — - The {REVISION_ROLE} MUST NOT receive the full text of all findings inline —
use finding-file path / comment references only to avoid context explosion. use finding-file path / comment references only to avoid context explosion.
- Convergence status: blockers/majors remaining vs. previous round. - Convergence status: blockers/majors remaining vs. previous round.
- **Revision survival ([org-internal #2601]) — primary path**: the task tool's completion - **Revision survival ([TT-2601]) — primary path**: the task tool's completion
output includes a `task_id`; passing it back resumes the SAME output includes a `task_id`; passing it back resumes the SAME
{REVISION_ROLE} subagent session instead of creating a fresh one. Round 1: {REVISION_ROLE} subagent session instead of creating a fresh one. Round 1:
persist the returned `task_id` with the round's working-notes entry (it persist the returned `task_id` with the round's working-notes entry (it
@@ -322,17 +322,24 @@ After the {REVISION_ROLE} completes revision:
`core/schemas/review-status.schema.json`). `core/schemas/review-status.schema.json`).
- `review-code` skill: **2** default / **3** high-risk (a BLOCKER survived a - `review-code` skill: **2** default / **3** high-risk (a BLOCKER survived a
round, or the diff touches a frozen cross-session contract) — round, or the diff touches a frozen cross-session contract) —
`<instance-root>/workflow-routing.yaml` `review.max_rounds` ([org-internal #3567], process-diet `<instance-root>/workflow-routing.yaml` `review.max_rounds` ([TT-3567], process-diet
P0b). At budget without convergence: STOP, register the remaining P0b). At budget without convergence: STOP, register the remaining
BLOCKER/MAJOR findings as TD registry rows, verdict FAIL if any BLOCKER BLOCKER/MAJOR findings as TD registry rows, then compute the verdict
remains else PASS — the debt is carried by those TD registry rows with the shared three-tier ladder (`core/schemas/synthesis.schema.json`
`overall_verdict` + `core/skills/_shared/review-orchestrator-rules.md`
rule 3): FAIL if any BLOCKER or FAIL dimension remains, else WARN,
PASS only if every remaining dimension is PASS ([TT-4786]:
the prior binary "else PASS" wording silently upgraded WARN-eligible
outcomes to PASS; a PASS round has already stopped at the convergence
table above, so the residual tail lands WARN or FAIL). The debt is
carried by those TD registry rows
(see `review-code/SKILL.md` Phase D). This (see `review-code/SKILL.md` Phase D). This
supersedes the 2026-08-25 [org-internal #3380] calibration (p50=2, p95=5, n=66): the runs supersedes the 2026-08-25 [TT-3380] calibration (p50=2, p95=5, n=66): the runs
past round 3 are the marathon tail this budget exists to cut; their residue past round 3 are the marathon tail this budget exists to cut; their residue
flows to the TD registry instead of reviewer rounds. Ledger: flows to the TD registry instead of reviewer rounds. Ledger:
`docs/workflow-refactor/thresholds-ledger.md`. `docs/workflow-refactor/thresholds-ledger.md`.
Rationale for `review-artifact` = 3 (evaluated in [org-internal #1969], replacing the prior blanket Rationale for `review-artifact` = 3 (evaluated in [TT-1969], replacing the prior blanket
default of 5): (1) the Round-3 Escalation Guardrail below already detects default of 5): (1) the Round-3 Escalation Guardrail below already detects
non-convergence at the start of round 3; (2) the INFO-disposition rule below non-convergence at the start of round 3; (2) the INFO-disposition rule below
removes spurious WARN rounds previously caused by non-blocking INFO findings; removes spurious WARN rounds previously caused by non-blocking INFO findings;
@@ -343,8 +350,8 @@ reaches round 4 — its round budget is 2/3, see the binding above.)
**Provisional, not empirically validated**: the four safeguards make `review-artifact`=3 **Provisional, not empirically validated**: the four safeguards make `review-artifact`=3
defensible, but it has no fresh run-data yet. Treat it as a hypothesis to defensible, but it has no fresh run-data yet. Treat it as a hypothesis to
confirm via the retrospective signal ([org-internal #1834]; gate-trim's landing machinery was confirm via the retrospective signal ([TT-1834]; gate-trim's landing machinery was
retired, [org-internal #3072] phase 3 — the check is observational, not a trim proposal): if retired, [TT-3072] phase 3 — the check is observational, not a trim proposal): if
live `review-artifact` runs frequently hit round 3 still improving yet are live `review-artifact` runs frequently hit round 3 still improving yet are
forced to stop at WARN/FAIL, bump it back to 4. forced to stop at WARN/FAIL, bump it back to 4.
@@ -372,8 +379,8 @@ block convergence and NEVER drive a reviser round.
**Round-3 Escalation Guardrail** (applies to the `review-artifact` skill's **Round-3 Escalation Guardrail** (applies to the `review-artifact` skill's
live targets — the process audit target AND the review-dag single-gate live targets — the process audit target AND the review-dag single-gate
target; the roadmap / design / plan targets were archived 2026-08-21, target; the roadmap / design / plan targets were archived 2026-08-21,
[org-internal #3072] phase 3). `review-code` does NOT use this guardrail; it uses its round [TT-3072] phase 3). `review-code` does NOT use this guardrail; it uses its round
budget ([org-internal #3567], see the `{MAX_ROUNDS}` binding above). budget ([TT-3567], see the `{MAX_ROUNDS}` binding above).
At the start of round 3, if the combined blocker+major count is still >50% of At the start of round 3, if the combined blocker+major count is still >50% of
round 1's count, STOP the loop and surface to the user: round 1's count, STOP the loop and surface to the user:
@@ -384,7 +391,7 @@ round 1's count, STOP the loop and surface to the user:
> (a) Return to upstream — for the `process` audit target, escalate to the > (a) Return to upstream — for the `process` audit target, escalate to the
> octopus maintainer for a process-level redesign (the legacy producer skills > octopus maintainer for a process-level redesign (the legacy producer skills
> `roadmap` / `requirements-elicitation` / `design` / `plan-iterations` were > `roadmap` / `requirements-elicitation` / `design` / `plan-iterations` were
> archived 2026-08-21, [org-internal #3072] phase 3 — `<instance-root>/archive/`), then restart this > archived 2026-08-21, [TT-3072] phase 3 — `<instance-root>/archive/`), then restart this
> review at round 1. > review at round 1.
> (b) Continue iterating — accept that more rounds may be needed (capped by > (b) Continue iterating — accept that more rounds may be needed (capped by
> `{MAX_ROUNDS}`). > `{MAX_ROUNDS}`).
@@ -399,7 +406,7 @@ review and escalate to a human, or (b) continue into round 4 — via the
`question` tool. The guard means "escalate with a choice", NOT "force-stop". `question` tool. The guard means "escalate with a choice", NOT "force-stop".
The choice is UNCONDITIONAL at the round-3→4 transition — instance skills may The choice is UNCONDITIONAL at the round-3→4 transition — instance skills may
narrow when an escalation *variant* (e.g. a design-level decision) fires, but narrow when an escalation *variant* (e.g. a design-level decision) fires, but
never narrow the choice gate itself. The call MUST be optionized ([org-internal #3378]): never narrow the choice gate itself. The call MUST be optionized ([TT-3378]):
two options — `Stop & escalate to a human` (first, when recommended) / two options — `Stop & escalate to a human` (first, when recommended) /
`Continue into round 4` — with `stage` set to the running skill's stage so `Continue into round 4` — with `stage` set to the running skill's stage so
auto-approval applies in autonomous mode; free-text asking is a spec auto-approval applies in autonomous mode; free-text asking is a spec
@@ -407,12 +414,12 @@ violation.
Instance: review-dag D4 option-b (`review-artifact/SKILL.md` §"Round-3 Instance: review-dag D4 option-b (`review-artifact/SKILL.md` §"Round-3
Escalation Guardrail interaction") — the sole live instance, its D4 round cap Escalation Guardrail interaction") — the sole live instance, its D4 round cap
(≤4) being the only budget that reaches round 4 (`review-code` is capped 2/3, (≤4) being the only budget that reaches round 4 (`review-code` is capped 2/3,
[org-internal #3567]). [TT-3567]).
Rationale (retro 2026-08-21 / [org-internal #3050]): unattended late-round loops drift into Rationale (retro 2026-08-21 / [TT-3050]): unattended late-round loops drift into
review marathons — the choice forces the design-level stall to surface to a review marathons — the choice forces the design-level stall to surface to a
human at round 4 instead of round 6. human at round 4 instead of round 6.
**Efficiency optimization**: From round 2 onward ([org-internal #2598]), only spawn **Efficiency optimization**: From round 2 onward ([TT-2598]), only spawn
{REVIEWER_OR_AUDITOR}s for dimensions that had FAIL, WARN, or UNRESOLVED in {REVIEWER_OR_AUDITOR}s for dimensions that had FAIL, WARN, or UNRESOLVED in
the previous round. Every 2 rounds, run a full {DIMENSION_COUNT}-reviewer the previous round. Every 2 rounds, run a full {DIMENSION_COUNT}-reviewer
sweep to catch regressions. From round 2 onward reviewer input is also sweep to catch regressions. From round 2 onward reviewer input is also
@@ -479,7 +486,7 @@ not the round-1 full set.
`REQUEST_REVIEW` registration to be recorded, and only THEN ask the human `REQUEST_REVIEW` registration to be recorded, and only THEN ask the human
to approve. Approving before the reviewer is registered produces to approve. Approving before the reviewer is registered produces
`official: false` on the approval — the gate treats the PR as unapproved `official: false` on the approval — the gate treats the PR as unapproved
and the approval must be re-done. ([org-internal #1931]: audit R2→R3 re-loop + re-approve, and the approval must be re-done. ([TT-1931]: audit R2→R3 re-loop + re-approve,
~30min wasted on exactly this ordering.) ~30min wasted on exactly this ordering.)
4. Present the final report to the user and obtain approval via the `question` 4. Present the final report to the user and obtain approval via the `question`
@@ -31,7 +31,7 @@ After revising, report a summary of changes made:
- Findings waived as cosmetic MINOR (round 2+): {WAIVED-{id} → reason} - Findings waived as cosmetic MINOR (round 2+): {WAIVED-{id} → reason}
Persist that summary to `{RETURN_FILE}` as your LAST action, BEFORE Persist that summary to `{RETURN_FILE}` as your LAST action, BEFORE
returning it — worker-report persistence ([org-internal #2847], see returning it — worker-report persistence ([TT-2847], see
`.octopus/skills/_shared/worker-report-persistence.md`). The persisted copy `.octopus/skills/_shared/worker-report-persistence.md`). The persisted copy
is the report of record; if your completion notification is lost, the is the report of record; if your completion notification is lost, the
Orchestrator recovers the revision outcome from this file. Orchestrator recovers the revision outcome from this file.
+4 -4
View File
@@ -1,7 +1,7 @@
> Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。 > Core 中立版(Increment 6a 改写,原 deferHard verbatim)。编号与条目结构严格不变(C-2 不变量);实例术语按 `core/adapters/TERMINOLOGY.md` 绑定。
name: Coordinator name: Coordinator
purpose: > purpose: >
Pool dispatch coordinator (billing-v2 [org-internal #4041] §7, REQ-F-012): a wake-driven, Pool dispatch coordinator (billing-v2 [TT-4041] §7, REQ-F-012): a wake-driven,
STATELESS decision-maker session living in the pool pod alongside workers. STATELESS decision-maker session living in the pool pod alongside workers.
List eligible issues (Gitea API, scoped token) → produce DAG-aware dispatch List eligible issues (Gitea API, scoped token) → produce DAG-aware dispatch
proposals → commit each dispatch through the N-16 assignment API proposals → commit each dispatch through the N-16 assignment API
@@ -62,14 +62,14 @@ agents_md:
# #
# Security posture (AC-5, see docs/security/threat-model.md §自治批处理): # Security posture (AC-5, see docs/security/threat-model.md §自治批处理):
# the coordinator authenticates with a workspace-level API token # the coordinator authenticates with a workspace-level API token
# (TD-687/[org-internal #3898] owner-minted, jti-revocable, role claim org_role). TODAY'S # (TD-687/[TT-3898] owner-minted, jti-revocable, role claim org_role). TODAY'S
# mint shape hardcodes org_role=viewer — read-capable only (assignment table # mint shape hardcodes org_role=viewer — read-capable only (assignment table
# + pool surfaces); the editor-capable mint needed for dispatch submission is # + pool surfaces); the editor-capable mint needed for dispatch submission is
# an explicit deployment-time decision on the [org-internal #3898] channel (not landed with # an explicit deployment-time decision on the [TT-3898] channel (not landed with
# N-19). Either way the token can NOT mint tokens, touch wallet internals, or # N-19). Either way the token can NOT mint tokens, touch wallet internals, or
# merge PRs — the merge gate stays human (E-4). # merge PRs — the merge gate stays human (E-4).
# #
# Worker-report persistence ([org-internal #2847] — see # Worker-report persistence ([TT-2847] — see
# core/skills/_shared/worker-report-persistence.md): a Coordinator # core/skills/_shared/worker-report-persistence.md): a Coordinator
# sub-agent persists its FINAL RETURN REPORT to disk as its LAST action, # sub-agent persists its FINAL RETURN REPORT to disk as its LAST action,
# before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md # before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md
+2 -2
View File
@@ -15,7 +15,7 @@ agents_md:
- claim-discipline - claim-discipline
- compact - compact
# Worker-report persistence ([org-internal #2847], retro-2696 AI#2 — see # Worker-report persistence ([TT-2847], retro-2696 AI#2 — see
# core/skills/_shared/worker-report-persistence.md): every Producer # core/skills/_shared/worker-report-persistence.md): every Producer
# sub-agent persists its FINAL RETURN REPORT to disk as its LAST action, # sub-agent persists its FINAL RETURN REPORT to disk as its LAST action,
# before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md # before returning — <runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md
@@ -23,7 +23,7 @@ agents_md:
# else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the # else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the
# report of record; the task notification is a convenience copy. # report of record; the task notification is a convenience copy.
# #
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md § # Working-notes contract ([TT-2600] — see core/templates/runs-layout.md §
# working-notes.md): at stage exit the Producer appends ONE entry (≤30 lines: # working-notes.md): at stage exit the Producer appends ONE entry (≤30 lines:
# decisions and why, dead ends, reviewer feedback that changed the work, hints # decisions and why, dead ends, reviewer feedback that changed the work, hints
# for the next stage) to <runs-root>/{slug}/working-notes.md, and registers # for the next stage) to <runs-root>/{slug}/working-notes.md, and registers
+1 -1
View File
@@ -14,7 +14,7 @@ agents_md:
- ticket-lifecycle - ticket-lifecycle
- compact - compact
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md § # Working-notes contract ([TT-2600] — see core/templates/runs-layout.md §
# working-notes.md): the Reviewer side appends ONE distilled entry via the # working-notes.md): the Reviewer side appends ONE distilled entry via the
# Synthesizer at review convergence — never per dimension dispatch (9 # Synthesizer at review convergence — never per dimension dispatch (9
# dimension dispatches = 1 entry) — to <runs-root>/{slug}/working-notes.md. # dimension dispatches = 1 entry) — to <runs-root>/{slug}/working-notes.md.
+1 -1
View File
@@ -12,7 +12,7 @@ agents_md:
- claim-discipline - claim-discipline
- compact - compact
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md § # Working-notes contract ([TT-2600] — see core/templates/runs-layout.md §
# working-notes.md): Tool agents append to <runs-root>/{slug}/working-notes.md # working-notes.md): Tool agents append to <runs-root>/{slug}/working-notes.md
# ONLY when the task produced a load-bearing finding (e.g. image evidence that # ONLY when the task produced a load-bearing finding (e.g. image evidence that
# changed a decision) — not for routine single-shot output. # changed a decision) — not for routine single-shot output.
+2 -2
View File
@@ -15,7 +15,7 @@ agents_md:
- claim-discipline - claim-discipline
- compact - compact
# Worker-report persistence ([org-internal #2847], retro-2696 AI#2 — see # Worker-report persistence ([TT-2847], retro-2696 AI#2 — see
# core/skills/_shared/worker-report-persistence.md): the Verifier # core/skills/_shared/worker-report-persistence.md): the Verifier
# persists its FINAL RETURN REPORT (DoD verdict + evidence pointers) to disk # persists its FINAL RETURN REPORT (DoD verdict + evidence pointers) to disk
# as its LAST action, before returning — # as its LAST action, before returning —
@@ -23,7 +23,7 @@ agents_md:
# else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the # else /tmp/octopus/{chunk-id}-worker-{seq}.md. The persisted copy is the
# report of record; the task notification is a convenience copy. # report of record; the task notification is a convenience copy.
# #
# Working-notes contract ([org-internal #2600] — see core/templates/runs-layout.md § # Working-notes contract ([TT-2600] — see core/templates/runs-layout.md §
# working-notes.md): the Verifier appends ONE entry at verify exit (what the # working-notes.md): the Verifier appends ONE entry at verify exit (what the
# DoD sweep caught, flaky/deferral context the next run should know). The # DoD sweep caught, flaky/deferral context the next run should know). The
# Phase 5.5 archive step additionally inlines the final working-notes.md # Phase 5.5 archive step additionally inlines the final working-notes.md
+3 -3
View File
@@ -42,7 +42,7 @@
- **Commit SHA**: `{SHA}` (the HEAD commit being reviewed). - **Commit SHA**: `{SHA}` (the HEAD commit being reviewed).
- **Review type**: `{REVIEW_TYPE}` — one of `review-code`, `review-dag`, - **Review type**: `{REVIEW_TYPE}` — one of `review-code`, `review-dag`,
`audit-process` (the `review-design-space` / `review-iteration-plan` / `audit-process` (the `review-design-space` / `review-iteration-plan` /
`review-roadmap` targets were archived 2026-08-21, [org-internal #3072] phase 3 — their `review-roadmap` targets were archived 2026-08-21, [TT-3072] phase 3 — their
historical synthesis data remains readable). historical synthesis data remains readable).
## Your Job ## Your Job
@@ -189,7 +189,7 @@
9. Persist your return summary (the exact text from the Return Format 9. Persist your return summary (the exact text from the Return Format
below) to `<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md` below) to `<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md`
(Tier 1) as your LAST action, BEFORE returning it — worker-report (Tier 1) as your LAST action, BEFORE returning it — worker-report
persistence ([org-internal #2847], `_shared/worker-report-persistence.md`). The persisted persistence ([TT-2847], `_shared/worker-report-persistence.md`). The persisted
copy is the report of record; if your completion notification is lost, the copy is the report of record; if your completion notification is lost, the
Orchestrator recovers the round verdict from this file. Orchestrator recovers the round verdict from this file.
@@ -211,7 +211,7 @@ synthesis JSON — it is already posted to the pipeline PR / source issue
comment (for audit-process runs, the wiki page `audit/{date}/round{N}/synthesis`). comment (for audit-process runs, the wiki page `audit/{date}/round{N}/synthesis`).
Persist this summary verbatim to Persist this summary verbatim to
`<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md` before `<runs-root>/{slug}/reviews/{stage}/round{N}/synthesis-return.md` before
returning (step 9 above — worker-report persistence [org-internal #2847]). returning (step 9 above — worker-report persistence [TT-2847]).
``` ```
## Synthesis Complete ## Synthesis Complete
@@ -3,7 +3,7 @@
> Canonical convention for every worker sub-agent dispatch (roles whose > Canonical convention for every worker sub-agent dispatch (roles whose
> `agent:` is `worker` — Producer sub-roles, Verifier, Synthesizer, …), > `agent:` is `worker` — Producer sub-roles, Verifier, Synthesizer, …),
> foreground or background (`task background=true`). Origin: retro WWW#5 / > foreground or background (`task background=true`). Origin: retro WWW#5 /
> [org-internal #2696] action item #2 ([org-internal #2847]) — at least one confirmed case where a > [TT-2696] action item #2 ([TT-2847]) — at least one confirmed case where a
> background worker's completion report reached the orchestrating session > background worker's completion report reached the orchestrating session
> only via the task-tool notification; the notification was lost and the > only via the task-tool notification; the notification was lost and the
> report evaporated, leaving nothing but reverse-engineering from artifacts. > report evaporated, leaving nothing but reverse-engineering from artifacts.
+12 -12
View File
@@ -3,7 +3,7 @@ name: analyze-dag
description: > description: >
Use ONLY when an Epic is routed to the DAG ticket pipeline (Kind/Epic or 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, Kind/Feature — both resolve to analyze-dag via the routes table directly,
[org-internal #3072] phase 3 / [org-internal #3061] Phase 2). The [TT-3072] phase 3 / [TT-3061] Phase 2). The
Analyst decomposes the Epic into a single task-DAG artifact — merging Analyst decomposes the Epic into a single task-DAG artifact — merging
roadmap+requirements+design+plan into one graph (nodes = acceptance roadmap+requirements+design+plan into one graph (nodes = acceptance
criteria, edges = contracts, topology = plan). criteria, edges = contracts, topology = plan).
@@ -31,7 +31,7 @@ role: Producer
analyze-dag is the **entry skill** of the DAG ticket pipeline analyze-dag is the **entry skill** of the DAG ticket pipeline
(`dag.route.entry.skill`, spec-07 §2). For a DAG-routed Epic (`dag.route.entry.skill`, spec-07 §2). For a DAG-routed Epic
(`Kind/Epic`, or `Kind/Feature` — both resolve here via the routes table (`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 — directly, [TT-3072] phase 3 / [TT-3061] Phase 2 / TD-388 —
including BACKFILL mode for MVP graduates and big-bug relabels), it including BACKFILL mode for MVP graduates and big-bug relabels), it
**replaces** `roadmap` + `requirements-elicitation` + `design` + **replaces** `roadmap` + `requirements-elicitation` + `design` +
`plan-iterations` and produces **ONE artifact**: the task DAG, published as `plan-iterations` and produces **ONE artifact**: the task DAG, published as
@@ -66,12 +66,12 @@ a topological order (the plan), then publishes the single graph.
| 设计主导 | 主要风险是一个有 ≥2 个可行选项的架构/平台决策,而非任务分解;需要先做一次探索 | 将开放问题转 `prototype`(THROWAWAY spike)或设计探索;决策记录后重入 | | 设计主导 | 主要风险是一个有 ≥2 个可行选项的架构/平台决策,而非任务分解;需要先做一次探索 | 将开放问题转 `prototype`(THROWAWAY spike)或设计探索;决策记录后重入 |
| 外部契约未决 | scope 依赖未决的外部契约(第三方 schema、上游 API 未定) | 按 External-System Rule(见下文)解析或围栏;不可拆的残余隔离后再重入 | | 外部契约未决 | scope 依赖未决的外部契约(第三方 schema、上游 API 未定) | 按 External-System Rule(见下文)解析或围栏;不可拆的残余隔离后再重入 |
**反向拦截(Kind/MVP 降级建议,[org-internal #3061])**:一个 `Kind/Feature` 工单在分解预检中 **反向拦截(Kind/MVP 降级建议,[TT-3061])**:一个 `Kind/Feature` 工单在分解预检中
暴露"概念未稳"(scope 仍在探索、成功标准未定、决策日志会推翻节点划分)时, 暴露"概念未稳"(scope 仍在探索、成功标准未定、决策日志会推翻节点划分)时,
正确出口不是硬分解,而是建议改标签 `Kind/MVP` 先行交互式验证——概念稳定后 正确出口不是硬分解,而是建议改标签 `Kind/MVP` 先行交互式验证——概念稳定后
经 backfill 模式(见下文)带着决策日志重入。 经 backfill 模式(见下文)带着决策日志重入。
### Phase 0 需求澄清(disqualifier 的结构化扩展,[org-internal #3061]) ### Phase 0 需求澄清(disqualifier 的结构化扩展,[TT-3061])
预检不止于"能否分解",还须证明"需求已澄清到可分解"。两项强制检查: 预检不止于"能否分解",还须证明"需求已澄清到可分解"。两项强制检查:
@@ -217,7 +217,7 @@ Rules:
- `refs_by` is derived from the REQMAP "every requirement ≥1 node" criterion - `refs_by` is derived from the REQMAP "every requirement ≥1 node" criterion
(missing coverage = a requirement with no node). (missing coverage = a requirement with no node).
## Breadth Coverage — 类目覆盖矩阵 + 排除账本 ([org-internal #2905] 方案 1) ## Breadth Coverage — 类目覆盖矩阵 + 排除账本 ([TT-2905] 方案 1)
The four-stage fold that produced the single DAG artifact kept requirement The four-stage fold that produced the single DAG artifact kept requirement
**depth** (REQMAP three-path coverage + falsifiable AC) but dropped legacy **depth** (REQMAP three-path coverage + falsifiable AC) but dropped legacy
@@ -271,7 +271,7 @@ sub-page `{epic-slug}/dag-coverage` using the same mechanics as AC sinking
frozen copy) — purely organizational, NOT an oversize signal, no frozen copy) — purely organizational, NOT an oversize signal, no
re-derivation. re-derivation.
### Breadth probe nodes (P2, [org-internal #2905] 方案 2) ### Breadth probe nodes (P2, [TT-2905] 方案 2)
When a 待确认 category is cheapest to resolve empirically, a **probe node** When a 待确认 category is cheapest to resolve empirically, a **probe node**
is a legal task node at the granularity floor: is a legal task node at the granularity floor:
@@ -306,12 +306,12 @@ is a legal task node at the granularity floor:
冻结副本(新增需求必然改变节点集合或 `req_refs`;需要新节点时全额按 冻结副本(新增需求必然改变节点集合或 `req_refs`;需要新节点时全额按
node_split 建单传播)。 node_split 建单传播)。
### Data layer — read `dag.route.preflight` BEFORE decomposition ([org-internal #2905] 方案 3) ### Data layer — read `dag.route.preflight` BEFORE decomposition ([TT-2905] 方案 3)
Before starting decomposition, analyze-dag MUST read Before starting decomposition, analyze-dag MUST read
`<instance-root>/workflow-routing.yaml` `dag.route.preflight` and, when the list is `<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 non-empty, verify each item as a producer self-check (the same injection
contract `implement` applies for `routes.{Kind}.preflight`, [org-internal #2599] — landed contract `implement` applies for `routes.{Kind}.preflight`, [TT-2599] — landed
items carry their retro evidence in `evidence`): items carry their retro evidence in `evidence`):
1. Read the `dag:` block's `route.preflight` array (live yaml, repo root). 1. Read the `dag:` block's `route.preflight` array (live yaml, repo root).
@@ -407,7 +407,7 @@ external contract). This is what lets the REQMAP "需求覆盖" (requirement
coverage) check mechanically verify that external-integration requirements map coverage) check mechanically verify that external-integration requirements map
to nodes. (The `ARCH 1.1` system-context diagram is discarded only for to nodes. (The `ARCH 1.1` system-context diagram is discarded only for
process-infrastructure-type Epics; product Epics get this alternative rule process-infrastructure-type Epics; product Epics get this alternative rule
instead.) [org-internal #2905]: this rule is the 外部系统集成 category of the breadth instead.) [TT-2905]: this rule is the 外部系统集成 category of the breadth
coverage matrix held at its original strength — see Breadth Coverage above. coverage matrix held at its original strength — see Breadth Coverage above.
## Exec-Resource Configuration (spec-07 §4 — mechanical destination of folded checklist rows) ## Exec-Resource Configuration (spec-07 §4 — mechanical destination of folded checklist rows)
@@ -433,7 +433,7 @@ observe:
`> DAG 工件状态: draft`. `> DAG 工件状态: draft`.
2. After the single-gate (`review-dag`) PASS, the **aggregator agent** (main 2. After the single-gate (`review-dag`) PASS, the **aggregator agent** (main
session / Orchestrator — not analyze-dag) asks the freeze confirmation session / Orchestrator — not analyze-dag) asks the freeze confirmation
question ([org-internal #3379]), then on confirmation flips the page to question ([TT-3379]), then on confirmation flips the page to
`> DAG 工件状态: frozen` and stamps version `v1`. The confirmation is an `> DAG 工件状态: frozen` and stamps version `v1`. The confirmation is an
OPTIONIZED `question` call (stage `review-dag`, never `destructive` — OPTIONIZED `question` call (stage `review-dag`, never `destructive` —
freeze is a process gate, not a business decision): options freeze is a process gate, not a business decision): options
@@ -454,7 +454,7 @@ observe:
the version stamp `vN → vN+1` (no re-confirmation — only the initial the version stamp `vN → vN+1` (no re-confirmation — only the initial
freeze gates on a decision). freeze gates on a decision).
## Backfill Input Mode (Kind/MVP graduation & big-bug relabels, [org-internal #3061]) ## Backfill Input Mode (Kind/MVP graduation & big-bug relabels, [TT-3061])
When a `Kind/MVP` ticket graduates (relabel → `Kind/Feature` → Step 0 → this 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 skill), the DAG is derived from **what was actually built**, not from greenfield
@@ -500,4 +500,4 @@ decomposition:
- `dag-pipeline/spec-06` — dag_metrics derivation + thresholds - `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-07` — dag.route landing row (entry skill, skip set, single-gate) + §4 landing list
- `dag-pipeline/spec-08` — DAG artifact lifecycle / version stamp - `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) - `<instance-root>/archive/skills/roadmap/SKILL.md` — legacy route (archived 2026-08-21, [TT-3072] phase 3; this skill replaces it for all Epics)
+2 -2
View File
@@ -185,7 +185,7 @@ When a `verify` work item has an E2E or UI DoD entry:
## Session cleanup (mandatory) ## Session cleanup (mandatory)
A Playwright MCP browser is a real Chrome with a `/tmp` user-data-dir — its A Playwright MCP browser is a real Chrome with a `/tmp` user-data-dir — its
mode follows `mcp.playwright.headless` (`headless-field-v1`, [org-internal #4393]): the repo mode follows `mcp.playwright.headless` (`headless-field-v1`, [TT-4393]): the repo
default `auto` spawns headed on desktop (win32/darwin; linux only with default `auto` spawns headed on desktop (win32/darwin; linux only with
DISPLAY/WAYLAND_DISPLAY set) and headless otherwise; an explicit `true`/`false` DISPLAY/WAYLAND_DISPLAY set) and headless otherwise; an explicit `true`/`false`
or `OCTOPUS_MCP_HEADLESS=1|0` pins it. The mode is fixed per new session — or `OCTOPUS_MCP_HEADLESS=1|0` pins it. The mode is fixed per new session —
@@ -194,7 +194,7 @@ stays alive as long as its MCP server runs, and the MCP server stays alive as
long as its parent octopus backend runs. When a browser-debug session ends long as its parent octopus backend runs. When a browser-debug session ends
without an explicit `browser_close`, OR the octopus session times out mid-task, without an explicit `browser_close`, OR the octopus session times out mid-task,
the Chrome + its MCP server are orphaned and accumulate across sessions — the Chrome + its MCP server are orphaned and accumulate across sessions —
burning CPU and leaving dead profile dirs (issue [org-internal #1315]); in headed mode the burning CPU and leaving dead profile dirs (issue [TT-1315]); in headed mode the
orphan is a visible stray window. orphan is a visible stray window.
**Iron rule: every browser-debug session MUST close its browser before ending.** **Iron rule: every browser-debug session MUST close its browser before ending.**
+1 -1
View File
@@ -171,7 +171,7 @@ Disable the watcher on slow filesystems (WSL2 `/mnt` drives, network mounts):
codegraph serve --mcp --no-watch codegraph serve --mcp --no-watch
``` ```
### Workflow worktrees get their own index ([org-internal #2561] / TD-006) ### Workflow worktrees get their own index ([TT-2561] / TD-006)
The main checkout's `.codegraph/` does NOT cover git worktrees — they live The main checkout's `.codegraph/` does NOT cover git worktrees — they live
outside the repo path, so nearest-`.codegraph/` resolution finds nothing under outside the repo path, so nearest-`.codegraph/` resolution finds nothing under
+1 -1
View File
@@ -315,7 +315,7 @@ Present the report to the user. Route to code review if > 20 lines or ≥ 3 file
- `core/checklists/frontend.md` — Frontend self-check checklist - `core/checklists/frontend.md` — Frontend self-check checklist
- `core/skills/implement/SKILL.md` — General + pipeline implementation workflow - `core/skills/implement/SKILL.md` — General + pipeline implementation workflow
- `core/skills/review-code/SKILL.md` — Code review (next step) - `core/skills/review-code/SKILL.md` — Code review (next step)
- `<instance-root>/archive/skills/design/SKILL.md` — Design document production (legacy upstream, archived [org-internal #3072] phase 3) - `<instance-root>/archive/skills/design/SKILL.md` — Design document production (legacy upstream, archived [TT-3072] phase 3)
- `core/skills/browser-debug/SKILL.md` — Interactive browser verification (invoke during Phase 3 / 4 for visual + interaction evidence) - `core/skills/browser-debug/SKILL.md` — Interactive browser verification (invoke during Phase 3 / 4 for visual + interaction evidence)
- `core/rules/testing.md`, `core/rules/type-checking.md` — Repository conventions (test commands, typecheck) - `core/rules/testing.md`, `core/rules/type-checking.md` — Repository conventions (test commands, typecheck)
- `core/rules/code-graph.md` — Code graph first - `core/rules/code-graph.md` — Code graph first
+3 -3
View File
@@ -158,9 +158,9 @@ history. If a token leaks into a remote URL, rewrite the remote
**Create a release** — `POST .../releases {"tag_name":"v1.2.0","target":"main",...}` **Create a release** — `POST .../releases {"tag_name":"v1.2.0","target":"main",...}`
**Create a wiki page** — `POST .../wiki/new {"title":"My Page","content_base64":"<b64>","message":"add page"}`. **`content_base64` is the ONLY field that writes body text** — this fork **silently ignores** the upstream-style `content` field on wiki create/update (no error, `201` returned, page saved 0 bytes; evidence [org-internal #3944]: commits f5eaf18/4f0217d/bad5880). `content` is valid only on the file API, never on wiki. **Create a wiki page** — `POST .../wiki/new {"title":"My Page","content_base64":"<b64>","message":"add page"}`. **`content_base64` is the ONLY field that writes body text** — this fork **silently ignores** the upstream-style `content` field on wiki create/update (no error, `201` returned, page saved 0 bytes; evidence [TT-3944]: commits f5eaf18/4f0217d/bad5880). `content` is valid only on the file API, never on wiki.
**Read / edit / delete a wiki page** — `GET|PATCH|DELETE .../wiki/page/{pageName}`. **Read by the mangled name, not the logical title**: this fork rewrites stored filenames for titles containing `/`, spaces, or `:` (slash percent-encoded into the filename + a `.-` suffix — see [org-internal #3218]), so `GET /wiki/page/bugfix-3204/bugfix-report` 404s. Always `GET .../wiki/pages` first and use the returned `sub_url` **verbatim** (it already carries the `%2F` encoding and `.-` suffix). PATCH/DELETE take the same mangled `pageName`. For PATCH, **omit `title` to keep the page name** and send only `content_base64`+`message` (fixed in gitea `dev-421-g7ff56aec08`, [org-internal #3510] — before that a title-less PATCH silently renamed the page to `unnamed.md` and later edits deleted target pages). Same trap as create: a PATCH carrying `content` instead of `content_base64` returns `200` with a **0-byte page** ([org-internal #3944]) — always base64-encode the body and verify non-empty via a follow-up `GET`. **Read / edit / delete a wiki page** — `GET|PATCH|DELETE .../wiki/page/{pageName}`. **Read by the mangled name, not the logical title**: this fork rewrites stored filenames for titles containing `/`, spaces, or `:` (slash percent-encoded into the filename + a `.-` suffix — see [TT-3218]), so `GET /wiki/page/bugfix-3204/bugfix-report` 404s. Always `GET .../wiki/pages` first and use the returned `sub_url` **verbatim** (it already carries the `%2F` encoding and `.-` suffix). PATCH/DELETE take the same mangled `pageName`. For PATCH, **omit `title` to keep the page name** and send only `content_base64`+`message` (fixed in gitea `dev-421-g7ff56aec08`, [TT-3510] — before that a title-less PATCH silently renamed the page to `unnamed.md` and later edits deleted target pages). Same trap as create: a PATCH carrying `content` instead of `content_base64` returns `200` with a **0-byte page** ([TT-3944]) — always base64-encode the body and verify non-empty via a follow-up `GET`.
## This fork's specifics ## This fork's specifics
@@ -171,7 +171,7 @@ history. If a token leaks into a remote URL, rewrite the remote
GET/PATCH/DELETE, `pages`, `revisions/{pageName}`). This fork has **no** GET/PATCH/DELETE, `pages`, `revisions/{pageName}`). This fork has **no**
upstream `raw/{pageName}` or `pages/{pageName}` single-page endpoints, and upstream `raw/{pageName}` or `pages/{pageName}` single-page endpoints, and
`page/{pageName}` only matches the mangled filename (see the wiki recipe `page/{pageName}` only matches the mangled filename (see the wiki recipe
above and [org-internal #3218]) — clone the wiki git repo (default branch `main`) only if above and [TT-3218]) — clone the wiki git repo (default branch `main`) only if
you need history beyond `/wiki/revisions` or bulk filename surgery. you need history beyond `/wiki/revisions` or bulk filename surgery.
- The authoritative route table is `routers/api/v1/api.go` in the Gitea - The authoritative route table is `routers/api/v1/api.go` in the Gitea
source; the human-readable docs UI is `<BASE>/api/swagger`. source; the human-readable docs UI is `<BASE>/api/swagger`.
+58 -58
View File
@@ -33,7 +33,7 @@ triggers:
- launch session for issue - launch session for issue
- launch session for ticket - launch session for ticket
- spawn session for ticket - spawn session for ticket
# English — patrol mode (delayed self-wake polling loops, [org-internal #3937]). # English — patrol mode (delayed self-wake polling loops, [TT-3937]).
- patrol loop - patrol loop
- patrol mode - patrol mode
- delayed wake - delayed wake
@@ -42,28 +42,28 @@ triggers:
- 拉起会话 - 拉起会话
- 自治会话 - 自治会话
- 无头会话 - 无头会话
# Chinese — patrol mode ([org-internal #3937]). # Chinese — patrol mode ([TT-3937]).
- 巡检模式 - 巡检模式
- 延迟唤醒 - 延迟唤醒
- 会话不生成 - 会话不生成
- 会话卡死 - 会话卡死
- 为工单拉起会话 - 为工单拉起会话
- 工单拉起会话 - 工单拉起会话
# English — lifecycle (hung rescue, stale-worldview correction, [org-internal #2459]). # English — lifecycle (hung rescue, stale-worldview correction, [TT-2459]).
- abort session - abort session
- revive session - revive session
- session rescue - session rescue
- fact baseline - fact baseline
# English — quota-wall recovery ([org-internal #3669]): worker killed by provider usage limit. # English — quota-wall recovery ([TT-3669]): worker killed by provider usage limit.
- quota wall - quota wall
- usage limit reached - usage limit reached
- quota exhausted - quota exhausted
- switch provider - switch provider
# Chinese — lifecycle ops ([org-internal #2459]). # Chinese — lifecycle ops ([TT-2459]).
- 唤醒会话 - 唤醒会话
- 会话挂死 - 会话挂死
- 事实基线 - 事实基线
# Chinese — quota-wall recovery ([org-internal #3669]). # Chinese — quota-wall recovery ([TT-3669]).
- 配额墙 - 配额墙
- 配额耗尽 - 配额耗尽
- 用量上限 - 用量上限
@@ -89,7 +89,7 @@ and worktree discipline are **orthogonal**: this skill only opens a session
record pointed at a directory; whether the launched session later creates its record pointed at a directory; whether the launched session later creates its
own worktree is a _workflow_ decision (per the worktree-discipline rule) it own worktree is a _workflow_ decision (per the worktree-discipline rule) it
makes when it starts actual work — not something the launcher does. One makes when it starts actual work — not something the launcher does. One
exception: the **ticket-driven recipe** below, where claim-first ([org-internal #2297]) exception: the **ticket-driven recipe** below, where claim-first ([TT-2297])
requires the launcher to push the workflow branch before launch, making a requires the launcher to push the workflow branch before launch, making a
pre-built worktree the claim carrier + ready workspace (see Pitfall #10 pre-built worktree the claim carrier + ready workspace (see Pitfall #10
carve-out). So, unless a different repo / path is specifically targeted, carve-out). So, unless a different repo / path is specifically targeted,
@@ -122,7 +122,7 @@ carve-out). So, unless a different repo / path is specifically targeted,
seed prompt, not the directory field (sidebar visibility, see bullet 1). The seed prompt, not the directory field (sidebar visibility, see bullet 1). The
owner-check (`GET /session?directory=$DIR`) is scoped per directory, so owner-check (`GET /session?directory=$DIR`) is scoped per directory, so
rooting the session at the correct code checkout is also what makes the rooting the session at the correct code checkout is also what makes the
duplicate-session guard meaningful. Server-side backstop ([org-internal #3190]): creating a duplicate-session guard meaningful. Server-side backstop ([TT-3190]): creating a
session whose directory IS a linked git worktree answers with an session whose directory IS a linked git worktree answers with an
`X-Session-Directory-Warning` response header and a server warn log naming `X-Session-Directory-Warning` response header and a server warn log naming
the owning main repo — if you see that header, the session will be invisible the owning main repo — if you see that header, the session will be invisible
@@ -131,8 +131,8 @@ carve-out). So, unless a different repo / path is specifically targeted,
> **Authoritative reference:** `rules/headless-session-ops` wiki page > **Authoritative reference:** `rules/headless-session-ops` wiki page
> (<<instance-base-url>/Octopus/octopus/wiki/rules%2Fheadless-session-ops>). > (<<instance-base-url>/Octopus/octopus/wiki/rules%2Fheadless-session-ops>).
> This skill is its runtime carrier. Provenance: issue **[org-internal #1695]** (which > This skill is its runtime carrier. Provenance: issue **[TT-1695]** (which
> corrected the misdiagnosed [org-internal #1691], see comment 9205). Code citations below were > corrected the misdiagnosed [TT-1691], see comment 9205). Code citations below were
> verified against `<harness-package>` at HEAD. > verified against `<harness-package>` at HEAD.
## The `model` field — always provide a known-good model (read this first) ## The `model` field — always provide a known-good model (read this first)
@@ -166,7 +166,7 @@ section). Two reasons:
`handlers/session.ts`) and never reaches the HTTP `handlers/session.ts`) and never reaches the HTTP
caller — so the session looks healthy (HTTP 204, user message persisted) yet caller — so the session looks healthy (HTTP 204, user message persisted) yet
**never generates**. This is exactly the "silent stall" observed empirically **never generates**. This is exactly the "silent stall" observed empirically
in [org-internal #1695]: a session with a 1-message transcript (user only) and frozen in [TT-1695]: a session with a 1-message transcript (user only) and frozen
`time.updated`. `time.updated`.
| payload | result | | payload | result |
@@ -280,10 +280,10 @@ curl -s -X POST "$BASE/session/$SID/prompt_async?directory=$DIR" \
queued behind a session that is generating with no live runner in this queued behind a session that is generating with no live runner in this
process (wedge/zombie shape — stored and re-driven on restart drain or the process (wedge/zombie shape — stored and re-driven on restart drain or the
next runner), **202** when `delay_sec` defers delivery to an in-memory next runner), **202** when `delay_sec` defers delivery to an in-memory
delayed wake ([org-internal #3937] A — see "巡检模式 / Patrol mode" below), and **409** delayed wake ([TT-3937] A — see "巡检模式 / Patrol mode" below), and **409**
when the session is paused (message NOT stored) or the maintenance-mode when the session is paused (message NOT stored) or the maintenance-mode
hold queue is full. hold queue is full.
- **Global route alternative ([org-internal #4307]):** when the client only knows the - **Global route alternative ([TT-4307]):** when the client only knows the
sessionID (no `?directory=` routing), `POST /prompt_async` (no path prefix) sessionID (no `?directory=` routing), `POST /prompt_async` (no path prefix)
resolves the instance from the app database by the body's `sessionID` and resolves the instance from the app database by the body's `sessionID` and
delegates to the same delivery core — same 204/202/409 semantics, same delegates to the same delivery core — same 204/202/409 semantics, same
@@ -294,17 +294,17 @@ curl -s -X POST "$BASE/session/$SID/prompt_async?directory=$DIR" \
- `delay_sec` (optional, integer 0..86400, else 400) schedules the prompt for - `delay_sec` (optional, integer 0..86400, else 400) schedules the prompt for
a one-shot delayed self-wake: the server holds the prompt in memory and a one-shot delayed self-wake: the server holds the prompt in memory and
fires it exactly once after `delay_sec` seconds, only for an idle session fires it exactly once after `delay_sec` seconds, only for an idle session
at intake. **Precedence ([org-internal #3937] review):** `delay_sec` applies only when the at intake. **Precedence ([TT-3937] review):** `delay_sec` applies only when the
intake would otherwise start processing now (immediate class). For the intake would otherwise start processing now (immediate class). For the
queued-behind-wedge 202 member and under maintenance queue mode it is queued-behind-wedge 202 member and under maintenance queue mode it is
stripped — retention semantics win (the server logs the drop; the delay is stripped — retention semantics win (the server logs the drop; the delay is
NOT honored). Pending wakes are **in-memory only — a server restart abandons NOT honored). Pending wakes are **in-memory only — a server restart abandons
them**; a patrol loop must therefore tolerate a missed wake and re-arm. them**; a patrol loop must therefore tolerate a missed wake and re-arm.
Never use `sleep <big>; curl ...` in a bash tool call to wait — that blocks Never use `sleep <big>; curl ...` in a bash tool call to wait — that blocks
the turn with zero output (the [org-internal #3937] incident shape); the bash tool now the turn with zero output (the [TT-3937] incident shape); the bash tool now
warns on bare sleeps > 120s (long-sleep guard, [org-internal #3937] C). warns on bare sleeps > 120s (long-sleep guard, [TT-3937] C).
- `model` is `{ providerID, modelID }` or the shorthand string - `model` is `{ providerID, modelID }` or the shorthand string
`"providerID/modelID"` (split on the FIRST `/`; accepted since [org-internal #4307] — `"providerID/modelID"` (split on the FIRST `/`; accepted since [TT-4307] —
e.g. `"zai-coding-plan/glm-5.2"`). **Do not omit it.** Fill the values from e.g. `"zai-coding-plan/glm-5.2"`). **Do not omit it.** Fill the values from
your own session's model (see "Reuse the current session's model" above) — your own session's model (see "Reuse the current session's model" above) —
never hardcode a specific model. A string without a `/` is rejected with never hardcode a specific model. A string without a `/` is rejected with
@@ -335,7 +335,7 @@ curl -s "$BASE/session/$SID/message?directory=$DIR&limit=1" \
Verdict: `latest_role == "assistant"` → the first generation completed (the Verdict: `latest_role == "assistant"` → the first generation completed (the
seed is `user`; the newest message flips to `assistant` only once the model seed is `user`; the newest message flips to `assistant` only once the model
answered — an errored turn also persists an assistant message carrying the ⚠️ answered — an errored turn also persists an assistant message carrying the ⚠️
usage-limit part, [org-internal #2912], so check the tail text before declaring success). usage-limit part, [TT-2912], so check the tail text before declaring success).
Stays `user` across 2–3 polls spaced 10–30 s → **apparent silent stall**; Stays `user` across 2–3 polls spaced 10–30 s → **apparent silent stall**;
almost certainly the model did not resolve to a usable one (fallback landed almost certainly the model did not resolve to a usable one (fallback landed
badly, or you omitted `model`). Redeliver Step 2 with an explicit known-good badly, or you omitted `model`). Redeliver Step 2 with an explicit known-good
@@ -351,33 +351,33 @@ just never omit `limit`.
The common case: an agent (or cron/CI) spins up a fresh main session to work a The common case: an agent (or cron/CI) spins up a fresh main session to work a
tracked issue — seed prompt composed **from the issue body**, launched on the tracked issue — seed prompt composed **from the issue body**, launched on the
current session's model. **Step-0 owner check is MANDATORY ([org-internal #1803])**: four data current session's model. **Step-0 owner check is MANDATORY ([TT-1803])**: four data
sources (session-title scan, assignee/claim, open PRs, remote branches); any sources (session-title scan, assignee/claim, open PRs, remote branches); any
live claim → ABORT the launch (`session-scope-guard.md` points here for that live claim → ABORT the launch (`session-scope-guard.md` points here for that
pre-step). Full recipe — owner-check scan script with `X-Total-Count` / pre-step). Full recipe — owner-check scan script with `X-Total-Count` /
`X-Has-More` pagination handling ([org-internal #3190]), claim-first atomic 3-step ([org-internal #2297], `X-Has-More` pagination handling ([TT-3190]), claim-first atomic 3-step ([TT-2297],
+ one-command provisioning via `script/claim-provision.sh`, [org-internal #3642]), + one-command provisioning via `script/claim-provision.sh`, [TT-3642]),
seed-prompt MUSTs, backend duplicate-ticket hard guard ([org-internal #1989], on by default seed-prompt MUSTs, backend duplicate-ticket hard guard ([TT-1989], on by default
[org-internal #2350]), launch + poll commands: `reference/ticket-recipe.md` (read BEFORE [TT-2350]), launch + poll commands: `reference/ticket-recipe.md` (read BEFORE
creating any ticket-driven session). creating any ticket-driven session).
## Completion-report protocol (完成回报协议, [org-internal #2374]) ## Completion-report protocol (完成回报协议, [TT-2374])
`prompt_async` is fire-and-forget **for the launcher too**: without this `prompt_async` is fire-and-forget **for the launcher too**: without this
protocol the orchestrator has NO push channel and must poll forever ([org-internal #2366]). protocol the orchestrator has NO push channel and must poll forever ([TT-2366]).
The worker actively reports `status=done|blocked|handoff` back into the The worker actively reports `status=done|blocked|handoff` back into the
orchestrator's session via `prompt_async`, with an issue-comment fallback. orchestrator's session via `prompt_async`, with an issue-comment fallback.
Default report format is `branch=<ref>`-based — workers never open PRs Default report format is `branch=<ref>`-based — workers never open PRs
(TD-678/[org-internal #4425]); `pr=#N` appears only on `uncoordinated` self-opens. (TD-678/[TT-4425]); `pr=#N` appears only on `uncoordinated` self-opens.
Hard constraints: a headless worker MUST NOT call the `question` tool Hard constraints: a headless worker MUST NOT call the `question` tool
([org-internal #2378] — directional/irreversible decisions are `status=blocked` reports, ([TT-2378] — directional/irreversible decisions are `status=blocked` reports,
then STOP), and MUST NOT self-merge its PR / self-close the issue / touch then STOP), and MUST NOT self-merge its PR / self-close the issue / touch
`main` ([org-internal #2386] — keep the PR open; the orchestrator merges and closes). Full `main` ([TT-2386] — keep the PR open; the orchestrator merges and closes). Full
protocol — orchestrator-side seed block (verbatim template), worker-side protocol — orchestrator-side seed block (verbatim template), worker-side
steps, decision-authority layering: `reference/completion-report.md` (read steps, decision-authority layering: `reference/completion-report.md` (read
BEFORE composing a seed prompt for any worker you need to hear back from). BEFORE composing a seed prompt for any worker you need to hear back from).
## Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([org-internal #2459]) ## Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([TT-2459])
Launching is half the job — a headless worker can hang silently or wake with Launching is half the job — a headless worker can hang silently or wake with
a stale worldview. Health check = two polls 30–60 s apart (`.state` + `progress` a stale worldview. Health check = two polls 30–60 s apart (`.state` + `progress`
@@ -386,19 +386,19 @@ samples = hung → abort FIRST (`POST /session/:id/abort`), then re-wake with a
known-good model + the anti-re-hang clause. Stale worldview → fact-baseline known-good model + the anti-re-hang clause. Stale worldview → fact-baseline
injection (only the CURRENT authority injects; if YOU might be the stale one, injection (only the CURRENT authority injects; if YOU might be the stale one,
verify identity against the durable record first). Full runbooks — verdict verify identity against the durable record first). Full runbooks — verdict
table + [org-internal #3215] dual-sample rule, abort + re-wake sequence, fact-baseline table + [TT-3215] dual-sample rule, abort + re-wake sequence, fact-baseline
structure, authorization asymmetry: `reference/lifecycle-ops.md` (read when structure, authorization asymmetry: `reference/lifecycle-ops.md` (read when
managing a launched session). Quota wall — the worker's turn killed by a managing a launched session). Quota wall — the worker's turn killed by a
terminal usage-limit error (looks like silent completion: no report, ticket terminal usage-limit error (looks like silent completion: no report, ticket
stalled) — has its own runbook: detection signals (finish=error ⚠️ tail, stalled) — has its own runbook: detection signals (finish=error ⚠️ tail,
provider quota markers), provider-switch re-wake, fact-baseline template, provider quota markers), provider-switch re-wake, fact-baseline template,
pre-dispatch provider check: `reference/quota-wall-recovery.md` ([org-internal #3669], evidence pre-dispatch provider check: `reference/quota-wall-recovery.md` ([TT-3669], evidence
[org-internal #3627]; read when a worker goes silent mid-task). [TT-3627]; read when a worker goes silent mid-task).
## 巡检模式 / Patrol mode (delayed self-wake, [org-internal #3937]) ## 巡检模式 / Patrol mode (delayed self-wake, [TT-3937])
A patrol loop periodically nudges a headless session without holding a A patrol loop periodically nudges a headless session without holding a
connection or burning a turn on a blocking sleep. Since [org-internal #3937] A the server connection or burning a turn on a blocking sleep. Since [TT-3937] A the server
supports this natively via `delay_sec` on `prompt_async`. supports this natively via `delay_sec` on `prompt_async`.
```sh ```sh
@@ -427,16 +427,16 @@ Rules of the road:
- **Restart abandons pending wakes.** They are in-memory server fibers — no - **Restart abandons pending wakes.** They are in-memory server fibers — no
persistence, no drain. After any server restart the patrol driver owns persistence, no drain. After any server restart the patrol driver owns
re-arming the next wake; treat a missed wake as expected, not as an error. re-arming the next wake; treat a missed wake as expected, not as an error.
- **Latest wake wins, per session ([org-internal #4069]).** Arming `delay_sec` on a session - **Latest wake wins, per session ([TT-4069]).** Arming `delay_sec` on a session
that already has a pending wake SUPERSEDES it: the previous countdown is that already has a pending wake SUPERSEDES it: the previous countdown is
cancelled, only the latest wake fires. Re-arming each turn is the intended cancelled, only the latest wake fires. Re-arming each turn is the intended
patrol pattern — a superseded wake never delivers its prompt and publishes patrol pattern — a superseded wake never delivers its prompt and publishes
no error. (Pre-[org-internal #4069] stacks both FIFO — on old binaries, re-arm only after no error. (Pre-[TT-4069] stacks both FIFO — on old binaries, re-arm only after
the previous wake fired.) the previous wake fired.)
- **Never emulate a delay with the bash tool.** `sleep 900; curl ...` blocks - **Never emulate a delay with the bash tool.** `sleep 900; curl ...` blocks
the turn with zero output and gets manually aborted as a hang (the [org-internal #3937] the turn with zero output and gets manually aborted as a hang (the [TT-3937]
incident). The bash tool now prepends a `<shell_warning>` on bare sleeps incident). The bash tool now prepends a `<shell_warning>` on bare sleeps
beyond 120s ([org-internal #3937] C) — treat that warning as a redirect to this section. beyond 120s ([TT-3937] C) — treat that warning as a redirect to this section.
## Do NOT use this skill when ## Do NOT use this skill when
@@ -461,15 +461,15 @@ Rules of the road:
| 6 | Using synchronous `prompt` for headless launch | `prompt` blocks until done — wrong for fire-and-forget; use `prompt_async` | | 6 | Using synchronous `prompt` for headless launch | `prompt` blocks until done — wrong for fire-and-forget; use `prompt_async` |
| 7 | Shell-escaping errors in a multi-line seed prompt | Build the payload with `jq -n --rawfile` from a file | | 7 | Shell-escaping errors in a multi-line seed prompt | Build the payload with `jq -n --rawfile` from a file |
| 8 | Verifying models via `GET /model` — no such endpoint (404) | Use `GET /provider` → `.connected` (provider live check); `list-models` tool also works. `GET /config/providers` lists _configured_ models only | | 8 | Verifying models via `GET /model` — no such endpoint (404) | Use `GET /provider` → `.connected` (provider live check); `list-models` tool also works. `GET /config/providers` lists _configured_ models only |
| 9 | Launching a session for a ticket another live session already owns → conflicting diffs, duplicate work ([org-internal #1744]/[org-internal #1753]) | Run the Step-0 owner check (`GET /session` title scan + worktree/branch/PR scan); ABORT and report on conflict | | 9 | Launching a session for a ticket another live session already owns → conflicting diffs, duplicate work ([TT-1744]/[TT-1753]) | Run the Step-0 owner check (`GET /session` title scan + worktree/branch/PR scan); ABORT and report on conflict |
| 10 | Creating a worktree / fresh checkout for the new session (unnecessary `bun install` + `.codegraph/` rebuild cost) | Don't — for _general_ launches: a session is a conversation pointed at a directory, so reuse the current workspace; worktree creation is a separate _workflow_ decision the launched session makes if/when it starts a workflow. **Ticket-recipe carve-out ([org-internal #2297]):** the ticket's work happens in a dedicated worktree anyway (worktree discipline), and claim-first pushes the workflow branch before launch — so the launcher pre-builds the worktree as the claim carrier + ready workspace, and the session reuses it (cost is front-loaded, not wasted). The worktree path goes in the claim comment + seed prompt; `?directory=` stays on the creator's workspace | | 10 | Creating a worktree / fresh checkout for the new session (unnecessary `bun install` + `.codegraph/` rebuild cost) | Don't — for _general_ launches: a session is a conversation pointed at a directory, so reuse the current workspace; worktree creation is a separate _workflow_ decision the launched session makes if/when it starts a workflow. **Ticket-recipe carve-out ([TT-2297]):** the ticket's work happens in a dedicated worktree anyway (worktree discipline), and claim-first pushes the workflow branch before launch — so the launcher pre-builds the worktree as the claim carrier + ready workspace, and the session reuses it (cost is front-loaded, not wasted). The worktree path goes in the claim comment + seed prompt; `?directory=` stays on the creator's workspace |
| 11 | Launching a worker and never hearing back — orchestrator polls a few times, stops, loses visibility ([org-internal #2374]) | Append the completion-report block to the seed prompt (Completion-report protocol section): worker `prompt_async`s a one-line status back into the orchestrator session on done/blocked/handoff, with issue-comment fallback | | 11 | Launching a worker and never hearing back — orchestrator polls a few times, stops, loses visibility ([TT-2374]) | Append the completion-report block to the seed prompt (Completion-report protocol section): worker `prompt_async`s a one-line status back into the orchestrator session on done/blocked/handoff, with issue-comment fallback |
| 12 | Headless worker calls the `question` tool → no attached client: the question deadlocks in a queue, or `auto_approve` silently auto-approves a direction-setting decision ([org-internal #2378]) | NEVER call `question` from a headless worker. Decision boundary (Completion-report protocol section): directional/irreversible decision → `status=blocked` report + one-line decision point, then STOP; the orchestrator is the sole human-decision entry point | | 12 | Headless worker calls the `question` tool → no attached client: the question deadlocks in a queue, or `auto_approve` silently auto-approves a direction-setting decision ([TT-2378]) | NEVER call `question` from a headless worker. Decision boundary (Completion-report protocol section): directional/irreversible decision → `status=blocked` report + one-line decision point, then STOP; the orchestrator is the sole human-decision entry point |
| 13 | Headless worker self-merges its PR / self-closes the issue once the PR looks ready, despite a seed instruction to keep it open ([org-internal #2386]; N-02 [org-internal #2367] / N-03 [org-internal #2368], commits `d1565c99` / `040f21b7`) | Self-merge / self-close / touching `main` are irreversible directional actions → blocked by the Decision boundary. PR ready → keep it OPEN, report `status=done branch=<ref>`; the orchestrator opens/admits the PR, merges and closes uniformly | | 13 | Headless worker self-merges its PR / self-closes the issue once the PR looks ready, despite a seed instruction to keep it open ([TT-2386]; N-02 [TT-2367] / N-03 [TT-2368], commits `d1565c99` / `040f21b7`) | Self-merge / self-close / touching `main` are irreversible directional actions → blocked by the Decision boundary. PR ready → keep it OPEN, report `status=done branch=<ref>`; the orchestrator opens/admits the PR, merges and closes uniformly |
| 14 | Trusting `state=generating` as "alive" — a hung stream goes unrescued (session A, 2026-08-16: `generating` 6+ min, count frozen at 478) | Poll state AND message count twice 30–60 s apart; frozen count = hung → abort + re-wake (Post-launch lifecycle section) | | 14 | Trusting `state=generating` as "alive" — a hung stream goes unrescued (session A, 2026-08-16: `generating` 6+ min, count frozen at 478) | Poll state AND message count twice 30–60 s apart; frozen count = hung → abort + re-wake (Post-launch lifecycle section) |
| 15 | Re-sending a wake prompt to a hung session and waiting — queued prompts are never consumed while the stream is dead | Abort FIRST (`POST /session/:id/abort` → 200, verify `idle`), THEN re-send; a prompt queued before the abort may still never fire — always re-deliver | | 15 | Re-sending a wake prompt to a hung session and waiting — queued prompts are never consumed while the stream is dead | Abort FIRST (`POST /session/:id/abort` → 200, verify `idle`), THEN re-send; a prompt queued before the abort may still never fire — always re-deliver |
| 16 | A worker woken from restart / long idle acts on its stale worldview — re-dispatches superseded work or claims authority it no longer holds (2026-08-16: revived worker re-ran an already-published FAIL verify; ops session announced an inherited "orchestrator" takeover) | Fact-baseline injection (Post-launch lifecycle section): authoritative facts + invalidated assumptions + one concrete re-assignment. Only the CURRENT authority injects; a session that suspects IT is stale verifies identity against the durable record first (`rules/compact.md` identity clause) | | 16 | A worker woken from restart / long idle acts on its stale worldview — re-dispatches superseded work or claims authority it no longer holds (2026-08-16: revived worker re-ran an already-published FAIL verify; ops session announced an inherited "orchestrator" takeover) | Fact-baseline injection (Post-launch lifecycle section): authoritative facts + invalidated assumptions + one concrete re-assignment. Only the CURRENT authority injects; a session that suspects IT is stale verifies identity against the durable record first (`rules/compact.md` identity clause) |
| 17 | Worker goes silent mid-task: provider quota wall killed the turn (usage limit / 429) — no completion-report, no blocked report; from the issue side indistinguishable from silent completion (2026-08-29 [org-internal #3627]: opencode-go `weekly usage limit reached` after the 13:18 Round-1 FAIL; ticket stalled until manually re-woken) | Detect via tail probe (`finish=error` + ⚠️ usage-limit part, `metadata.reason` in the quota family) + `GET /provider` quota markers; re-wake on a known-good provider with the fact-baseline template — `reference/quota-wall-recovery.md` ([org-internal #3669]). Prevent: pre-dispatch provider check + the seed's 配额自报 clause (`reference/completion-report.md`, [org-internal #3669]) — quota exhaustion is a `status=blocked reason=quota-exhausted` report, not a silent death | | 17 | Worker goes silent mid-task: provider quota wall killed the turn (usage limit / 429) — no completion-report, no blocked report; from the issue side indistinguishable from silent completion (2026-08-29 [TT-3627]: opencode-go `weekly usage limit reached` after the 13:18 Round-1 FAIL; ticket stalled until manually re-woken) | Detect via tail probe (`finish=error` + ⚠️ usage-limit part, `metadata.reason` in the quota family) + `GET /provider` quota markers; re-wake on a known-good provider with the fact-baseline template — `reference/quota-wall-recovery.md` ([TT-3669]). Prevent: pre-dispatch provider check + the seed's 配额自报 clause (`reference/completion-report.md`, [TT-3669]) — quota exhaustion is a `status=blocked reason=quota-exhausted` report, not a silent death |
## Known limitation (separate from this workaround) ## Known limitation (separate from this workaround)
@@ -482,9 +482,9 @@ catches that cause (`forkPromptDelivery` in `handlers/session.ts`) so the HTTP
caller never sees it. The proper fix is to surface the error (or reject unusable caller never sees it. The proper fix is to surface the error (or reject unusable
models at the boundary) so a stalled session is diagnosable. Until then, **always models at the boundary) so a stalled session is diagnosable. Until then, **always
provide an explicit known-good `model`** — this skill is the documented provide an explicit known-good `model`** — this skill is the documented
workaround (see [org-internal #1695] "遗留 minor"). workaround (see [TT-1695] "遗留 minor").
**Update ([org-internal #2912], 2026-08-20)**: usage-limit turn failures (HTTP 429 / **Update ([TT-2912], 2026-08-20)**: usage-limit turn failures (HTTP 429 /
FreeUsageLimitError / GoUsageLimitError) are no longer silent shells. When such FreeUsageLimitError / GoUsageLimitError) are no longer silent shells. When such
a turn terminates (retry schedule ends or the spin is aborted), the errored a turn terminates (retry schedule ends or the spin is aborted), the errored
assistant message persists `finish=error` plus a human-readable ⚠️ text part assistant message persists `finish=error` plus a human-readable ⚠️ text part
@@ -494,23 +494,23 @@ the web UI like any assistant text. Pitfall #14's double-poll is still the
liveness check while a 429 retry spin is IN progress (the spin itself retries liveness check while a 429 retry spin is IN progress (the spin itself retries
with backoff until interrupted); the explicit error part only appears once the with backoff until interrupted); the explicit error part only appears once the
turn ends. The general async-path observability gap above remains tracked by turn ends. The general async-path observability gap above remains tracked by
[org-internal #1695]. [TT-1695].
## See also ## See also
- Source issue / full manual: **[org-internal #1695]** (this skill adds the ticket-driven recipe - Source issue / full manual: **[TT-1695]** (this skill adds the ticket-driven recipe
- current-model reuse, and corrects the endpoint/claim against current code). - current-model reuse, and corrects the endpoint/claim against current code).
- Completion-report protocol: **[org-internal #2374]** (worker-side active report back to the - Completion-report protocol: **[TT-2374]** (worker-side active report back to the
launching orchestrator session; fallback to issue comment). launching orchestrator session; fallback to issue comment).
- Quota-wall recovery recipe: **[org-internal #3669]** (evidence instance [org-internal #3627]) — detect a - Quota-wall recovery recipe: **[TT-3669]** (evidence instance [TT-3627]) — detect a
worker killed by a provider usage limit, re-wake on a known-good provider, worker killed by a provider usage limit, re-wake on a known-good provider,
pre-dispatch prevention. pre-dispatch prevention.
- Decision boundary: **[org-internal #2378]** (headless worker MUST NOT call `question`; - Decision boundary: **[TT-2378]** (headless worker MUST NOT call `question`;
directional decisions go through `status=blocked` reports to the directional decisions go through `status=blocked` reports to the
orchestrator) and **[org-internal #2386]** (the worker MUST NOT self-merge its PR, orchestrator) and **[TT-2386]** (the worker MUST NOT self-merge its PR,
self-close the issue, or touch `main` — the orchestrator merges and closes self-close the issue, or touch `main` — the orchestrator merges and closes
uniformly). uniformly).
- Correction of the prior misdiagnosis: **[org-internal #1691]** (closed Invalid), comment 9205. - Correction of the prior misdiagnosis: **[TT-1691]** (closed Invalid), comment 9205.
- Synchronous client always sends `model`: - Synchronous client always sends `model`:
`packages/app/src/components/prompt-input/submit.ts:158-165`. `packages/app/src/components/prompt-input/submit.ts:158-165`.
- Code citations: `<harness-package>/src/session/prompt.ts:858,804-822,1399`, - Code citations: `<harness-package>/src/session/prompt.ts:858,804-822,1399`,
@@ -525,15 +525,15 @@ turn ends. The general async-path observability gap above remains tracked by
specific ticket (#N)`): read BEFORE creating any session for issue #N — specific ticket (#N)`): read BEFORE creating any session for issue #N —
Step-0 owner check, seed-prompt composition, launch + poll commands. Step-0 owner check, seed-prompt composition, launch + poll commands.
- `reference/completion-report.md` — completion-report protocol (完成回报协议, - `reference/completion-report.md` — completion-report protocol (完成回报协议,
[org-internal #2374]): read BEFORE composing a seed prompt for a worker you need to hear [TT-2374]): read BEFORE composing a seed prompt for a worker you need to hear
back from — orchestrator block template, worker-side report steps, decision back from — orchestrator block template, worker-side report steps, decision
boundary ([org-internal #2378] / [org-internal #2386]), quota self-report clause ([org-internal #3669]). boundary ([TT-2378] / [TT-2386]), quota self-report clause ([TT-3669]).
- `reference/lifecycle-ops.md` — post-launch lifecycle ([org-internal #2459]): read when - `reference/lifecycle-ops.md` — post-launch lifecycle ([TT-2459]): read when
managing a launched session — health-check polling, hung-stream diagnosis managing a launched session — health-check polling, hung-stream diagnosis
(state=generating + frozen counters), abort + re-wake rescue, (state=generating + frozen counters), abort + re-wake rescue,
fact-baseline injection, authorization asymmetry. fact-baseline injection, authorization asymmetry.
- `reference/quota-wall-recovery.md` — quota-wall recovery ([org-internal #3669], evidence - `reference/quota-wall-recovery.md` — quota-wall recovery ([TT-3669], evidence
[org-internal #3627]): read when a worker goes silent mid-task (suspected provider usage [TT-3627]): read when a worker goes silent mid-task (suspected provider usage
limit) or BEFORE dispatching a long-running worker — detection signals limit) or BEFORE dispatching a long-running worker — detection signals
(finish=error ⚠️ tail, provider quota markers, log grep patterns), (finish=error ⚠️ tail, provider quota markers, log grep patterns),
provider-switch re-wake + fact-baseline template, pre-dispatch provider provider-switch re-wake + fact-baseline template, pre-dispatch provider
@@ -1,6 +1,6 @@
> Extracted from headless-session-ops/SKILL.md (Completion-report protocol (完成回报协议, [org-internal #2374])) — moved verbatim 2026-08-26, ticket [org-internal #3480]. > Extracted from headless-session-ops/SKILL.md (Completion-report protocol (完成回报协议, [TT-2374])) — moved verbatim 2026-08-26, ticket [TT-3480].
## Completion-report protocol (完成回报协议, [org-internal #2374]) ## Completion-report protocol (完成回报协议, [TT-2374])
`prompt_async` is fire-and-forget **for the launcher too**: once the worker `prompt_async` is fire-and-forget **for the launcher too**: once the worker
session starts generating, the orchestrator receives NO event when it finishes session starts generating, the orchestrator receives NO event when it finishes
@@ -8,8 +8,8 @@ or blocks. The `task` tool auto-returns `task_result` for subagents; a
`prompt_async`-launched independent main session has no equivalent — the `prompt_async`-launched independent main session has no equivalent — the
orchestrator's only built-in channel is bare polling of orchestrator's only built-in channel is bare polling of
`GET /session/:id/message?limit=1` (tail probe — the no-`limit` form loads the `GET /session/:id/message?limit=1` (tail probe — the no-`limit` form loads the
whole transcript server-side), which it eventually stops doing ([org-internal #2366]: worker ran whole transcript server-side), which it eventually stops doing ([TT-2366]: worker ran
~1h past the orchestrator's last poll, merged PR [org-internal #2371] and closed [org-internal #2366] while ~1h past the orchestrator's last poll, merged PR [TT-2371] and closed [TT-2366] while
the orchestrator had zero visibility). the orchestrator had zero visibility).
The protocol below closes that gap WITHOUT changing server semantics: the The protocol below closes that gap WITHOUT changing server semantics: the
@@ -24,21 +24,21 @@ parallel chunk work, any long-running delegated ticket), append a
completion-report block to the seed prompt. It MUST state: completion-report block to the seed prompt. It MUST state:
- the orchestrator's **session id** (`$LAUNCHER_SID`) and **directory**; - the orchestrator's **session id** (`$LAUNCHER_SID`) and **directory**;
- the report endpoint: `POST $BASE/session/$LAUNCHER_SID/prompt_async?directory=$DIR` (or, when the directory is unknown to the worker, the global route `POST $BASE/prompt_async` with the sessionID in the body — [org-internal #4307]); - the report endpoint: `POST $BASE/session/$LAUNCHER_SID/prompt_async?directory=$DIR` (or, when the directory is unknown to the worker, the global route `POST $BASE/prompt_async` with the sessionID in the body — [TT-4307]);
- the exact report format (one-line, machine-greppable); - the exact report format (one-line, machine-greppable);
- the fallback (issue comment) if the report call fails. - the fallback (issue comment) if the report call fails.
Template (include verbatim in `seed.txt` when you are the launcher): Template (include verbatim in `seed.txt` when you are the launcher):
```text ```text
## 完成回报协议 (mandatory, [org-internal #2374]) ## 完成回报协议 (mandatory, [TT-2374])
你由编排会话 (orchestrator) 启动。完成、阻塞、或将工单移交他人时,必须向编排会话回报: 你由编排会话 (orchestrator) 启动。完成、阻塞、或将工单移交他人时,必须向编排会话回报:
POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR> POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR>
body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]} body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]}
<report> 格式(单行,machine-greppable): <report> 格式(单行,machine-greppable):
[#<ticket>] [<node-or-slug>] status=done|blocked|handoff branch=<ref> [pr=#<N>] verify=<changed+typecheck> risk=<high|low> summary=<one line> [#<ticket>] [<node-or-slug>] status=done|blocked|handoff branch=<ref> [pr=#<N>] verify=<changed+typecheck> risk=<high|low> summary=<one line>
默认(TD-678 / [org-internal #4425]):worker 只推分支不开 PR——交付推送前置本地验证 默认(TD-678 / [TT-4425]):worker 只推分支不开 PR——交付推送前置本地验证
(<harness-package> 下 test:changed 全绿 + typecheck 0 error,verify 字段回执); (<harness-package> 下 test:changed 全绿 + typecheck 0 error,verify 字段回执);
risk 按 risk-classifier 冻结表(HIGH_RISK_GLOBS)自报。PR 由编排按容量串行开 risk 按 risk-classifier 冻结表(HIGH_RISK_GLOBS)自报。PR 由编排按容量串行开
1:1(正文携 worker 报告),或 batch 模式 epic 经 land-batch 技能按迭代统一合成 1:1(正文携 worker 报告),或 batch 模式 epic 经 land-batch 技能按迭代统一合成
@@ -46,15 +46,15 @@ risk 按 risk-classifier 冻结表(HIGH_RISK_GLOBS)自报。PR 由编排按
若回报调用失败(HTTP 非 2xx / 连接拒绝 — orchestrator 会话可能已结束或实例重启), 若回报调用失败(HTTP 非 2xx / 连接拒绝 — orchestrator 会话可能已结束或实例重启),
退而在源 issue(或父 Epic)发同内容评论作为兜底(fallback, 非主通道)。 退而在源 issue(或父 Epic)发同内容评论作为兜底(fallback, 非主通道)。
回报是你的 mandatory step,与 issue-checklist-sync 并列;不得静默结束。 回报是你的 mandatory step,与 issue-checklist-sync 并列;不得静默结束。
决策边界([org-internal #2378]):headless worker 禁止调用 `question` 工具 —— 遇方向性/不可逆 决策边界([TT-2378]):headless worker 禁止调用 `question` 工具 —— 遇方向性/不可逆
决策点 → `status=blocked` + 一行决策点描述后 STOP,勿调 question(无人应答死锁 / 决策点 → `status=blocked` + 一行决策点描述后 STOP,勿调 question(无人应答死锁 /
被 auto_approve 静默自动批准)。 被 auto_approve 静默自动批准)。
配额自报([org-internal #3669]):若收到配额/用量上限错误(usage limit / 429 / 402 配额自报([TT-3669]):若收到配额/用量上限错误(usage limit / 429 / 402
insufficient_quota),立即回报 status=blocked reason=quota-exhausted insufficient_quota),立即回报 status=blocked reason=quota-exhausted
summary=<provider 与 ⚠️ 部分中的重置提示>(branch=<ref> 必带)后停止 summary=<provider 与 ⚠️ 部分中的重置提示>(branch=<ref> 必带)后停止
——勿自行换模型重试;换供应商重唤醒由编排者执行 ——勿自行换模型重试;换供应商重唤醒由编排者执行
(reference/quota-wall-recovery.md)。 (reference/quota-wall-recovery.md)。
PR 就绪后保持 open:不自行合并 PR、不关闭 issue、不动 main([org-internal #2386]); PR 就绪后保持 open:不自行合并 PR、不关闭 issue、不动 main([TT-2386]);
合并与 issue 关闭由编排者统一执行。 合并与 issue 关闭由编排者统一执行。
``` ```
@@ -73,7 +73,7 @@ final step (before idling):
done); `pr=#N` only for an `uncoordinated` self-open; use done); `pr=#N` only for an `uncoordinated` self-open; use
`status=blocked` + the blocker description when stuck; use `status=blocked` + the blocker description when stuck; use
`status=handoff` when deliberately transferring the ticket. `status=handoff` when deliberately transferring the ticket.
1. **Quota exhaustion is a blocked report, not a silent death ([org-internal #3669]).** A 1. **Quota exhaustion is a blocked report, not a silent death ([TT-3669]).** A
worker whose turn is killed by a usage-limit error (429 / 402 quota worker whose turn is killed by a usage-limit error (429 / 402 quota
family) cannot finish the turn — but per the seed's 配额自报 clause it family) cannot finish the turn — but per the seed's 配额自报 clause it
reports `status=blocked reason=quota-exhausted summary=<provider + reports `status=blocked reason=quota-exhausted summary=<provider +
@@ -93,7 +93,7 @@ final step (before idling):
remains the stakeholder-facing record; the report is the remains the stakeholder-facing record; the report is the
orchestrator-facing wake-up signal. orchestrator-facing wake-up signal.
### Orchestrator side — serial PR admission on done reports ([org-internal #4425]) ### Orchestrator side — serial PR admission on done reports ([TT-4425])
On a `status=done branch=<ref> verify=… risk=…` report: On a `status=done branch=<ref> verify=… risk=…` report:
@@ -103,16 +103,16 @@ On a `status=done branch=<ref> verify=… risk=…` report:
code; keep the queue shallow. code; keep the queue shallow.
2. Open the 1:1 PR (title from the ticket node, body carrying the worker 2. Open the 1:1 PR (title from the ticket node, body carrying the worker
report: branch / files / self-test / verify), apply the `Risk/*` label report: branch / files / self-test / verify), apply the `Risk/*` label
from the report's `risk=` hint, merge via `script/pr-merge.sh` ([org-internal #3864]). from the report's `risk=` hint, merge via `script/pr-merge.sh` ([TT-3864]).
Batch-mode epics: one `land-batch` PR per iteration instead ([org-internal #3731]). Batch-mode epics: one `land-batch` PR per iteration instead ([TT-3731]).
3. A first red on the opened PR goes back through the report fallback 3. A first red on the opened PR goes back through the report fallback
channel (issue comment) — the worker may already be idle; the issue channel (issue comment) — the worker may already be idle; the issue
comment is the durable re-entry point. comment is the durable re-entry point.
Prose discipline on the orchestrator session only — no new daemon, no Prose discipline on the orchestrator session only — no new daemon, no
mergeable-state automation (merge-coordinator retired, [org-internal #4385]). mergeable-state automation (merge-coordinator retired, [TT-4385]).
### Decision boundary (决策边界, [org-internal #2378]) ### Decision boundary (决策边界, [TT-2378])
The report channel defines how the worker *answers*; this subsection defines The report channel defines how the worker *answers*; this subsection defines
the boundary of what it may *ask*. A headless worker session has NO attached the boundary of what it may *ask*. A headless worker session has NO attached
@@ -134,15 +134,15 @@ authority is layered instead:
point, then STOPs. The orchestrator is the sole human-decision entry point: point, then STOPs. The orchestrator is the sole human-decision entry point:
it interacts with the user, then replies to the worker (or acts on its it interacts with the user, then replies to the worker (or acts on its
behalf). behalf).
- **No self-merge / no self-close / never touch main ([org-internal #2386])**: a headless - **No self-merge / no self-close / never touch main ([TT-2386])**: a headless
worker MUST NOT merge its own PR, close the source issue, or rebase / worker MUST NOT merge its own PR, close the source issue, or rebase /
force-push `main`. These are irreversible directional actions of exactly force-push `main`. These are irreversible directional actions of exactly
the class this boundary blocks — even when the seed prompt's instruction the class this boundary blocks — even when the seed prompt's instruction
to "keep the PR open" is absent or the worker judges the PR ready. When to "keep the PR open" is absent or the worker judges the PR ready. When
the PR is ready the worker keeps it OPEN and reports the PR is ready the worker keeps it OPEN and reports
`status=done pr=#N` to the orchestrator; the orchestrator performs the `status=done pr=#N` to the orchestrator; the orchestrator performs the
merge and the issue close uniformly. (Counter-example: N-02 [org-internal #2367] / merge and the issue close uniformly. (Counter-example: N-02 [TT-2367] /
N-03 [org-internal #2368] self-merged their PRs — commits `d1565c99` / `040f21b7` — N-03 [TT-2368] self-merged their PRs — commits `d1565c99` / `040f21b7` —
despite a seed instruction to keep them open.) despite a seed instruction to keep them open.)
- **Local implementation decisions within the AC scope** (pattern choice, - **Local implementation decisions within the AC scope** (pattern choice,
helper extraction, test shape) → the worker decides autonomously and notes helper extraction, test shape) → the worker decides autonomously and notes
@@ -150,7 +150,7 @@ authority is layered instead:
Rule of thumb: the worker's only way to "ask" is a `status=blocked` report. Rule of thumb: the worker's only way to "ask" is a `status=blocked` report.
A genuine ambiguity left by the seed prompt that would change scope is a A genuine ambiguity left by the seed prompt that would change scope is a
blocked report, NOT a `question` call. (Field sample: N-04 [org-internal #2369] — the blocked report, NOT a `question` call. (Field sample: N-04 [TT-2369] — the
worker spontaneously did NOT merge its own PR and left merging to the worker spontaneously did NOT merge its own PR and left merging to the
orchestrator; this subsection codifies that behavior.) orchestrator; this subsection codifies that behavior.)
@@ -1,10 +1,10 @@
> Extracted from headless-session-ops/SKILL.md (Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([org-internal #2459])) — moved verbatim 2026-08-26, ticket [org-internal #3480]. > Extracted from headless-session-ops/SKILL.md (Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([TT-2459])) — moved verbatim 2026-08-26, ticket [TT-3480].
## Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([org-internal #2459]) ## Post-launch lifecycle: health check, hung rescue, stale-worldview correction ([TT-2459])
Launching is half the job — a headless worker can hang silently or wake up Launching is half the job — a headless worker can hang silently or wake up
with an outdated worldview. All three failure modes below were observed in with an outdated worldview. All three failure modes below were observed in
production on 2026-08-16 during Epic [org-internal #2459] (ops-restart window); the runbooks production on 2026-08-16 during Epic [TT-2459] (ops-restart window); the runbooks
are extracted from that incident record. are extracted from that incident record.
### Health check — three states, one poll pattern ### Health check — three states, one poll pattern
@@ -24,7 +24,7 @@ server-side:
| idle | `state=idle` AND `progress` absent-or-stale across both polls | turn ended — read the LAST message (same `limit=1` fetch): task unfinished → wake prompt; `status=done` report → harvest | | idle | `state=idle` AND `progress` absent-or-stale across both polls | turn ended — read the LAST message (same `limit=1` fetch): task unfinished → wake prompt; `status=done` report → harvest |
| **hung** | `state=generating` AND `progress.stepCount`/`lastStepAt` AND newest message id ALL frozen across both polls | the generation stream is dead; queued prompts will NEVER be consumed — rescue required | | **hung** | `state=generating` AND `progress.stepCount`/`lastStepAt` AND newest message id ALL frozen across both polls | the generation stream is dead; queued prompts will NEVER be consumed — rescue required |
`state` alone lies in BOTH directions ([org-internal #3215]): a hung session still reports `state` alone lies in BOTH directions ([TT-3215]): a hung session still reports
`generating` (field sample: session A, 2026-08-16 — `state=generating` for 6+ `generating` (field sample: session A, 2026-08-16 — `state=generating` for 6+
minutes with the message count frozen at 478), and a healthy mid-step worker minutes with the message count frozen at 478), and a healthy mid-step worker
can read `idle`/empty message tails in a single snapshot (2026-08-23 W3 wave: can read `idle`/empty message tails in a single snapshot (2026-08-23 W3 wave:
@@ -32,7 +32,7 @@ can read `idle`/empty message tails in a single snapshot (2026-08-23 W3 wave:
discriminator; a single snapshot is NEVER an abort basis.** discriminator; a single snapshot is NEVER an abort basis.**
`progress` (`stepCount` cumulative LLM-round counter, `lastStepAt` epoch-ms `progress` (`stepCount` cumulative LLM-round counter, `lastStepAt` epoch-ms
heartbeat — [org-internal #3215]) moves on every round even when message tails are heartbeat — [TT-3215]) moves on every round even when message tails are
transiently empty or `state` flickers; it is absent for sessions that never transiently empty or `state` flickers; it is absent for sessions that never
ran since instance start (treat absent = no signal, fall back to count ran since instance start (treat absent = no signal, fall back to count
deltas). `lastStepAt` freshness alone does NOT prove liveness (a long tool deltas). `lastStepAt` freshness alone does NOT prove liveness (a long tool
@@ -77,7 +77,7 @@ claim authority it does not hold (field samples, 2026-08-16: a revived worker
re-ran an M-01 verify another session had already published as FAIL — re-ran an M-01 verify another session had already published as FAIL —
deduplicated via flag #comment-21590; an ops-notification session inherited an deduplicated via flag #comment-21590; an ops-notification session inherited an
"orchestrator" identity from a compaction summary and announced a takeover — "orchestrator" identity from a compaction summary and announced a takeover —
corrected via 勘误 #comment-21654/[org-internal #21668]). corrected via 勘误 #comment-21654/[TT-21668]).
When you detect a stale-worldview session, do not wait for it to finish being When you detect a stale-worldview session, do not wait for it to finish being
wrong — inject a fact-baseline prompt immediately (regular `prompt_async`), wrong — inject a fact-baseline prompt immediately (regular `prompt_async`),
@@ -1,6 +1,6 @@
> Added from headless-session-ops/SKILL.md (triggers `quota wall` / `配额墙`, > Added from headless-session-ops/SKILL.md (triggers `quota wall` / `配额墙`,
> Post-launch lifecycle section, pitfall #17, References) — new runbook > Post-launch lifecycle section, pitfall #17, References) — new runbook
> 2026-08-29, ticket [org-internal #3669] (evidence instance [org-internal #3627]). Companion runbooks: > 2026-08-29, ticket [TT-3669] (evidence instance [TT-3627]). Companion runbooks:
> `lifecycle-ops.md` (hung rescue, fact-baseline structure) and > `lifecycle-ops.md` (hung rescue, fact-baseline structure) and
> `completion-report.md` §"Orchestrator side" (the quota self-report clause); > `completion-report.md` §"Orchestrator side" (the quota self-report clause);
> §Prevention is this file's own closing section. > §Prevention is this file's own closing section.
@@ -14,15 +14,15 @@ it looks EXACTLY like silent completion: no completion-report, no
equals the orchestrator's polling interval, and without this runbook the equals the orchestrator's polling interval, and without this runbook the
recovery was improvised. recovery was improvised.
**Evidence instance ([org-internal #3627], 2026-08-29)** — the shapes below are field-verified: **Evidence instance ([TT-3627], 2026-08-29)** — the shapes below are field-verified:
|时刻 (+08)| 事件 | |时刻 (+08)| 事件 |
|---|---| |---|---|
| 08-29 13:18 | review-code Round-1 synthesis (FAIL) posted on [org-internal #3627]; worker session `ses_fb46e705bffe9kYbSoHayoJ1OQ` (builder, opencode-go model, branch `workflow/session/3627-wedge-promptasync`) entered its revision loop | | 08-29 13:18 | review-code Round-1 synthesis (FAIL) posted on [TT-3627]; worker session `ses_fb46e705bffe9kYbSoHayoJ1OQ` (builder, opencode-go model, branch `workflow/session/3627-wedge-promptasync`) entered its revision loop |
| ~13:18–16:00 | worker hit the provider's `weekly usage limit reached` mid-revision — turn killed, **no** completion-report, **no** blocked report; issue side silent | | ~13:18–16:00 | worker hit the provider's `weekly usage limit reached` mid-revision — turn killed, **no** completion-report, **no** blocked report; issue side silent |
| detection | orchestrator noticed the `/session` state stall, then confirmed via the quota error in the session log (message tail carries the ⚠️ usage-limit part, [org-internal #2912]) | | detection | orchestrator noticed the `/session` state stall, then confirmed via the quota error in the session log (message tail carries the ⚠️ usage-limit part, [TT-2912]) |
| recovery | re-wake via `prompt_async` on a known-good provider (`zhipuai-coding-plan`/glm-5.3 — since renamed `zai-coding-plan`) **plus a fact-baseline injection** (what happened / what is done / where to resume) | | recovery | re-wake via `prompt_async` on a known-good provider (`zhipuai-coding-plan`/glm-5.3 — since renamed `zai-coding-plan`) **plus a fact-baseline injection** (what happened / what is done / where to resume) |
| 16:26 / 16:51 | Round-2 synthesis PASS; `status=done pr=[org-internal #3675]` report received | | 16:26 / 16:51 | Round-2 synthesis PASS; `status=done pr=[TT-3675]` report received |
## Detection — three signals, in this order ## Detection — three signals, in this order
@@ -35,7 +35,7 @@ SID=<worker session id>
``` ```
**Signal 1 — tail probe (primary; survives restarts, lives in the DB).** Since **Signal 1 — tail probe (primary; survives restarts, lives in the DB).** Since
[org-internal #2912]/[org-internal #3190] a quota-killed turn persists an assistant message with [TT-2912]/[TT-3190] a quota-killed turn persists an assistant message with
`finish=error` plus a human-readable ⚠️ text part whose metadata names the `finish=error` plus a human-readable ⚠️ text part whose metadata names the
quota family. Probe the TAIL (`limit=1`, never the no-`limit` full transcript): quota family. Probe the TAIL (`limit=1`, never the no-`limit` full transcript):
@@ -52,10 +52,10 @@ rate_limit}` (metadata also carries `provider`). The ⚠️ text is one of — a
strings observed in this repo's runtime (`session/retry.ts`): strings observed in this repo's runtime (`session/retry.ts`):
- `` `weekly usage limit` reached. It will reset in … `` / `Go limit reached` - `` `weekly usage limit` reached. It will reset in … `` / `Go limit reached`
(GoUsageLimitError — the [org-internal #3627] shape; `weekly` is the body's `limitName`) (GoUsageLimitError — the [TT-3627] shape; `weekly` is the body's `limitName`)
- `Free limit reached` (FreeUsageLimitError) - `Free limit reached` (FreeUsageLimitError)
- `Account-level usage limit — switching API keys does not reset it. You can - `Account-level usage limit — switching API keys does not reset it. You can
continue after HH:mm.` ([org-internal #3407], zhipu/zai code 1308 — account-level) continue after HH:mm.` ([TT-3407], zhipu/zai code 1308 — account-level)
- `Provider <id> rate limited (HTTP 429)` (generic 429) - `Provider <id> rate limited (HTTP 429)` (generic 429)
- `Generation failed — …` with a 402 `insufficient_quota` body (balance, not - `Generation failed — …` with a 402 `insufficient_quota` body (balance, not
window — recovery is top-up, not provider switch) window — recovery is top-up, not provider switch)
@@ -73,9 +73,9 @@ curl -s "$BASE/session?directory=$DIR" | jq -r --arg s "$SID" \
30–60 s apart → the 429 retry spin is still running (it retries with backoff 30–60 s apart → the 429 retry spin is still running (it retries with backoff
until the schedule ends) OR the stream is hung — treat exactly like the hung until the schedule ends) OR the stream is hung — treat exactly like the hung
shape in `lifecycle-ops.md`: abort FIRST, then re-wake. A single snapshot is shape in `lifecycle-ops.md`: abort FIRST, then re-wake. A single snapshot is
never an abort basis ([org-internal #3215]). never an abort basis ([TT-3215]).
**Signal 3 — provider-level confirmation ([org-internal #2911] quota markers).** `GET **Signal 3 — provider-level confirmation ([TT-2911] quota markers).** `GET
/provider` overlays active usage-limit cooldowns, so the dead provider is /provider` overlays active usage-limit cooldowns, so the dead provider is
visible without reading logs: visible without reading logs:
@@ -86,7 +86,7 @@ date -d @$(($(curl -s "$BASE/provider?directory=$DIR" | jq '[.all[].quota.resetA
``` ```
**Log grep (fallback; the dev log is restart-truncated).** Patterns actually **Log grep (fallback; the dev log is restart-truncated).** Patterns actually
seen in the wild — [org-internal #3627] produced the first: seen in the wild — [TT-3627] produced the first:
```sh ```sh
grep -E "usage limit reached|Go limit reached|Free limit reached|Account-level usage limit|GoUsageLimitError|FreeUsageLimitError|rate limited \(HTTP 429\)|insufficient_quota" \ grep -E "usage limit reached|Go limit reached|Free limit reached|Account-level usage limit|GoUsageLimitError|FreeUsageLimitError|rate limited \(HTTP 429\)|insufficient_quota" \
@@ -96,7 +96,7 @@ grep -E "usage limit reached|Go limit reached|Free limit reached|Account-level u
``` ```
The wall is only terminal after failover has exhausted the same-name pools The wall is only terminal after failover has exhausted the same-name pools
([org-internal #2911] failover); the `retrying … on …` WARNs above tell you the pool was ([TT-2911] failover); the `retrying … on …` WARNs above tell you the pool was
already draining before it died. already draining before it died.
## Recovery — abort (only if needed), re-wake on a known-good provider, inject facts ## Recovery — abort (only if needed), re-wake on a known-good provider, inject facts
@@ -130,7 +130,7 @@ curl -s "$BASE/provider?directory=$DIR" | jq -r \
# own current model — it is generating by definition). # own current model — it is generating by definition).
``` ```
([org-internal #3627]: opencode-go dead → re-woken on zhipuai-coding-plan/glm-5.3, since ([TT-3627]: opencode-go dead → re-woken on zhipuai-coding-plan/glm-5.3, since
renamed `zai-coding-plan`. Do NOT "wait for reset" as the default — weekly renamed `zai-coding-plan`. Do NOT "wait for reset" as the default — weekly
windows mean days.) windows mean days.)
@@ -159,9 +159,9 @@ curl -s "$BASE/provider?directory=$DIR" | jq -r \
**Step 3 — re-wake with a fact-baseline prompt.** Build the payload from a file **Step 3 — re-wake with a fact-baseline prompt.** Build the payload from a file
(`jq --rawfile`, SKILL.md pitfall #7), same wake shape as (`jq --rawfile`, SKILL.md pitfall #7), same wake shape as
`lifecycle-ops.md` but with the quota facts. The template also restates the `lifecycle-ops.md` but with the quota facts. The template also restates the
completion-report protocol ([org-internal #2374]) so the recovery is self-contained: it completion-report protocol ([TT-2374]) so the recovery is self-contained: it
assumes the original seed still contains the protocol block — if you are assumes the original seed still contains the protocol block — if you are
unsure it does (e.g. the worker was dispatched before [org-internal #3669] added the quota unsure it does (e.g. the worker was dispatched before [TT-3669] added the quota
clause), the template's own block below carries it; fill clause), the template's own block below carries it; fill
`<BASE>`/`<LAUNCHER_SID>`/`<DIR>` with the orchestrator session's values: `<BASE>`/`<LAUNCHER_SID>`/`<DIR>` with the orchestrator session's values:
@@ -176,7 +176,7 @@ cat > wake.txt <<'EOF'
3. 从哪继续:<一件具体的下一步任务>。 3. 从哪继续:<一件具体的下一步任务>。
4. 证据规则:逐条到引用来源(issue 评论 / PR / 工件)核实后再行动, 4. 证据规则:逐条到引用来源(issue 评论 / PR / 工件)核实后再行动,
勿仅凭本基线行动。 勿仅凭本基线行动。
## 完成回报协议(重申 [org-internal #2374]/[org-internal #3669];不确定原始 seed 是否含协议块时以本节为准) ## 完成回报协议(重申 [TT-2374]/[TT-3669];不确定原始 seed 是否含协议块时以本节为准)
完成、阻塞或移交时,必须回报编排会话(你的唤醒者): 完成、阻塞或移交时,必须回报编排会话(你的唤醒者):
POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR> POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR>
body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]} body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]}
@@ -195,7 +195,7 @@ jq -n --rawfile p wake.txt '{agent:"builder",
Then poll the tail (`limit=1`) until an assistant message appears, and keep Then poll the tail (`limit=1`) until an assistant message appears, and keep
expecting the completion-report per protocol — the re-woken worker owes you expecting the completion-report per protocol — the re-woken worker owes you
`status=done|blocked` like any other (the restated block in the template `status=done|blocked` like any other (the restated block in the template
makes this hold even when the original seed predates [org-internal #3669]). makes this hold even when the original seed predates [TT-3669]).
## Prevention — before dispatch, and in the seed ## Prevention — before dispatch, and in the seed
@@ -213,7 +213,7 @@ If the intended provider is already quota-marked, dispatch on a different one
**Quota self-report clause (turns a silent death into a harvestable **Quota self-report clause (turns a silent death into a harvestable
blocked).** The canonical clause text lives in `completion-report.md` blocked).** The canonical clause text lives in `completion-report.md`
§"Orchestrator side" (配额自报, [org-internal #3669]) — append it VERBATIM to the seed §"Orchestrator side" (配额自报, [TT-3669]) — append it VERBATIM to the seed
prompt's completion-report block. Single source of truth: do not fork or prompt's completion-report block. Single source of truth: do not fork or
restate the clause here; its blocked payload already follows the one-line restate the clause here; its blocked payload already follows the one-line
key=value spec (`status=blocked reason=quota-exhausted summary=<provider + key=value spec (`status=blocked reason=quota-exhausted summary=<provider +
@@ -1,4 +1,4 @@
> Extracted from headless-session-ops/SKILL.md (Launch a session for a specific ticket (#N)) — moved verbatim 2026-08-26, ticket [org-internal #3480]. > Extracted from headless-session-ops/SKILL.md (Launch a session for a specific ticket (#N)) — moved verbatim 2026-08-26, ticket [TT-3480].
## Launch a session for a specific ticket (#N) ## Launch a session for a specific ticket (#N)
@@ -7,13 +7,13 @@ work a tracked issue. Compose the seed prompt **from the issue itself** so the
new session starts with real context, and launch it on **the current session's new session starts with real context, and launch it on **the current session's
model**. model**.
0. **Owner check (MANDATORY pre-step, [org-internal #1803]).** Before creating anything, 0. **Owner check (MANDATORY pre-step, [TT-1803]).** Before creating anything,
verify no other live session already owns this ticket or code area — verify no other live session already owns this ticket or code area —
duplicate ownership is how [org-internal #1744]/[org-internal #1753] collided. The check spans four duplicate ownership is how [TT-1744]/[TT-1753] collided. The check spans four
data sources; any live claim → **ABORT the launch and report the data sources; any live claim → **ABORT the launch and report the
conflict**. conflict**.
**Mechanized ([org-internal #3667])**: `bash script/session-conflicts.sh <N>` runs the **Mechanized ([TT-3667])**: `bash script/session-conflicts.sh <N>` runs the
session-title scan (a), the branch scan (d), and the open-PR check (c) session-title scan (a), the branch scan (d), and the open-PR check (c)
in one read-only pass (exit 4 = conflict, `--json` for a machine in one read-only pass (exit 4 = conflict, `--json` for a machine
summary); the assignee/claim check (b) is `claim.sh`'s compare-and-swap summary); the assignee/claim check (b) is `claim.sh`'s compare-and-swap
@@ -23,7 +23,7 @@ model**.
**a. Session-title scan (live session check).** The listing endpoint **a. Session-title scan (live session check).** The listing endpoint
returns at most `limit` (default 100) sessions — on busy repos (300+ live returns at most `limit` (default 100) sessions — on busy repos (300+ live
sessions in one directory) that silently truncates and the scan misses sessions in one directory) that silently truncates and the scan misses
owners ([org-internal #3190]). Non-range listing responses carry `X-Total-Count` (full owners ([TT-3190]). Non-range listing responses carry `X-Total-Count` (full
filter population, untruncated) and `X-Has-More: true` (only when the filter population, untruncated) and `X-Has-More: true` (only when the
page is truncated). Scan procedure: fetch page 1, and when page is truncated). Scan procedure: fetch page 1, and when
`X-Has-More: true` is present re-fetch once with `limit=$TOTAL` — treat `X-Has-More: true` is present re-fetch once with `limit=$TOTAL` — treat
@@ -57,7 +57,7 @@ model**.
the launch and report the conflict** (issue comment naming the owning the launch and report the conflict** (issue comment naming the owning
session id). Do not launch a second session for the same ticket. session id). Do not launch a second session for the same ticket.
**b. Assignee / claim check ([org-internal #2297]).** Read the issue via **b. Assignee / claim check ([TT-2297]).** Read the issue via
`工单 API(见 TERMINOLOGY)get(owner, repo, index: N)` (or `GET /api/v1/repos/$OWNER/$REPO/issues/$N`): `工单 API(见 TERMINOLOGY)get(owner, repo, index: N)` (or `GET /api/v1/repos/$OWNER/$REPO/issues/$N`):
- If `assignee` is set and is **not** the launching agent → **ABORT** and - If `assignee` is set and is **not** the launching agent → **ABORT** and
report (the ticket is already claimed). report (the ticket is already claimed).
@@ -68,7 +68,7 @@ model**.
`GET <gitea-base-url>/api/v1/repos/issues/search?q="#N"&type=pulls&state=open` `GET <gitea-base-url>/api/v1/repos/issues/search?q="#N"&type=pulls&state=open`
(API source) — and **ABORT** if an open PR already covers the ticket. (API source) — and **ABORT** if an open PR already covers the ticket.
**d. Remote branch check ([org-internal #2297]).** A local branch is invisible to other **d. Remote branch check ([TT-2297]).** A local branch is invisible to other
sessions — check the remote too: sessions — check the remote too:
`git ls-remote origin 'workflow/*'` and scan for a branch tail covering `#N`. `git ls-remote origin 'workflow/*'` and scan for a branch tail covering `#N`.
Also check the repo side locally: `git worktree list` + Also check the repo side locally: `git worktree list` +
@@ -76,7 +76,7 @@ model**.
- A stale hit (session idle for hours / clearly abandoned) → do NOT - A stale hit (session idle for hours / clearly abandoned) → do NOT
hand-post a takeover comment (retired admin workaround — unauditable); hand-post a takeover comment (retired admin workaround — unauditable);
dead-claim takeover is mechanized ([org-internal #3668]): `bash script/claim.sh dead-claim takeover is mechanized ([TT-3668]): `bash script/claim.sh
takeover <ticket> <branch> --session-id <id>`. It enforces the takeover <ticket> <branch> --session-id <id>`. It enforces the
evidence gate (branch ABSENT on origin AND (session 404 OR comment at evidence gate (branch ABSENT on origin AND (session 404 OR comment at
least CLAIM_TAKEOVER_STALE_DAYS old)) and exits 10 when the evidence least CLAIM_TAKEOVER_STALE_DAYS old)) and exits 10 when the evidence
@@ -87,13 +87,13 @@ model**.
§"Dead-claim takeover" (claim.sh header is normative). §"Dead-claim takeover" (claim.sh header is normative).
The runtime counterpart of this check is `core/rules/session-scope-guard.md` The runtime counterpart of this check is `core/rules/session-scope-guard.md`
("One task, one owner"), injected into every session's prompt. ("One task, one owner"), injected into every session's prompt.
- **Backend hard guard ([org-internal #1989]):** `POST /session` hard-rejects duplicate-ticket - **Backend hard guard ([TT-1989]):** `POST /session` hard-rejects duplicate-ticket
session creation with HTTP 400. The backend guard is **on by default ([org-internal #2350])**; session creation with HTTP 400. The backend guard is **on by default ([TT-2350])**;
set `enabled: false` in config to opt out. It fails open ONLY on defect set `enabled: false` in config to opt out. It fails open ONLY on defect
paths (DB / config errors), never as a configured disable. The front-end paths (DB / config errors), never as a configured disable. The front-end
soft check above is now backed by this backend hard check for defense in soft check above is now backed by this backend hard check for defense in
depth. depth.
- **Claim-first ([org-internal #2297]).** Claiming a ticket is one atomic 3-step action: - **Claim-first ([TT-2297]).** Claiming a ticket is one atomic 3-step action:
(1) set the issue assignee to the working account, (2) post a claim comment (1) set the issue assignee to the working account, (2) post a claim comment
naming the workflow branch and session id, (3) push the workflow branch to naming the workflow branch and session id, (3) push the workflow branch to
remote (`git push -u origin workflow/...`). The claim is valid ONLY when all remote (`git push -u origin workflow/...`). The claim is valid ONLY when all
@@ -101,7 +101,7 @@ model**.
session until all three steps are done (see session until all three steps are done (see
`core/rules/session-scope-guard.md` §"Claim-first"). If a collision HAS `core/rules/session-scope-guard.md` §"Claim-first"). If a collision HAS
already happened, follow `rules/ownership-collision-runbook` (wiki, L2 on-demand). already happened, follow `rules/ownership-collision-runbook` (wiki, L2 on-demand).
- **Provisioning after claim ([org-internal #3642]) is ONE command** — claim + worktree + - **Provisioning after claim ([TT-3642]) is ONE command** — claim + worktree +
Tier-1 runs scaffold: Tier-1 runs scaffold:
`bash script/claim-provision.sh <N> workflow/<branch>` (runs claim.sh with `bash script/claim-provision.sh <N> workflow/<branch>` (runs claim.sh with
exit codes passed through, attaches the session worktree to the claimed exit codes passed through, attaches the session worktree to the claimed
@@ -123,7 +123,7 @@ model**.
- restate the **goal** in one sentence; - restate the **goal** in one sentence;
- list the **constraints** and **acceptance criteria**; - list the **constraints** and **acceptance criteria**;
- cite every **wiki artifact path** / related issue referenced in the body - cite every **wiki artifact path** / related issue referenced in the body
(e.g. `{epic-slug}/dag`, `{epic-slug}/dag-nodes/{node-id}`, `[org-internal #1691]`); (e.g. `{epic-slug}/dag`, `{epic-slug}/dag-nodes/{node-id}`, `[TT-1691]`);
- tell the new agent to follow the right pipeline skill for the work type - tell the new agent to follow the right pipeline skill for the work type
(implement / bugfix / design / …). (implement / bugfix / design / …).
Write it to a file (handles newlines): Write it to a file (handles newlines):
@@ -141,16 +141,16 @@ your change — classify (pre-existing/flaky), file a BF/FT issue per
core/rules/session-scope-guard.md, and continue this task. Do NOT fix core/rules/session-scope-guard.md, and continue this task. Do NOT fix
unrelated failing tests in place. unrelated failing tests in place.
## 完成回报协议 (mandatory, [org-internal #2374]) ## 完成回报协议 (mandatory, [TT-2374])
完成、阻塞、或移交时,向编排会话回报: 完成、阻塞、或移交时,向编排会话回报:
POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR> POST <BASE>/session/<LAUNCHER_SID>/prompt_async?directory=<DIR>
(编排目录未知时可用全局路由 POST <BASE>/prompt_async,body 携 sessionID,[org-internal #4307]) (编排目录未知时可用全局路由 POST <BASE>/prompt_async,body 携 sessionID,[TT-4307])
body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]} body: {"agent":"builder","model":{...},"parts":[{"type":"text","text":"<report>"}]}
<report>: [#N] [<node-or-slug>] status=done|blocked|handoff branch=<ref> [pr=#<PR>] verify=<changed+typecheck> risk=<high|low> summary=<one line> <report>: [#N] [<node-or-slug>] status=done|blocked|handoff branch=<ref> [pr=#<PR>] verify=<changed+typecheck> risk=<high|low> summary=<one line>
约束:worker 只推分支不开 PR(PR 由编排串行开);交付推送前 test:changed+typecheck 须绿。若再遇配额/用量上限错误,立即回报 status=blocked reason=quota-exhausted summary=<provider 与重置提示>(branch=<ref> 必带)后停止,勿自行换模型重试。 约束:worker 只推分支不开 PR(PR 由编排串行开);交付推送前 test:changed+typecheck 须绿。若再遇配额/用量上限错误,立即回报 status=blocked reason=quota-exhausted summary=<provider 与重置提示>(branch=<ref> 必带)后停止,勿自行换模型重试。
回报失败(非 2xx / 连接拒绝)→ 在本 issue(或父 Epic)发同内容评论兜底。 回报失败(非 2xx / 连接拒绝)→ 在本 issue(或父 Epic)发同内容评论兜底。
决策边界([org-internal #2378]):遇方向性决策点 → status=blocked 回报,勿调 question。 决策边界([TT-2378]):遇方向性决策点 → status=blocked 回报,勿调 question。
EOF EOF
``` ```
@@ -179,4 +179,4 @@ EOF
6. **Add the completion-report block to the seed prompt** (see next section) so 6. **Add the completion-report block to the seed prompt** (see next section) so
the worker reports back when it finishes or blocks — without it, this the worker reports back when it finishes or blocks — without it, this
orchestrator has no push channel and must poll forever ([org-internal #2374]). orchestrator has no push channel and must poll forever ([TT-2374]).
+4 -4
View File
@@ -3,7 +3,7 @@ name: image-interpret
description: > description: >
Use ONLY when the agent needs to read or analyze an image (screenshot, Use ONLY when the agent needs to read or analyze an image (screenshot,
design mockup, UI capture, .png/.jpg/.webp file) but the active model lacks design mockup, UI capture, .png/.jpg/.webp file) but the active model lacks
vision capability. Delegates to the Image Interpreter role (vision-capable vision capability. Delegates to the Tool role (image interpretation) (vision-capable
model) which returns a structured text spec — layout regions, colors (hex), model) which returns a structured text spec — layout regions, colors (hex),
spacing (px), typography, component hierarchy, and responsive breakpoints. spacing (px), typography, component hierarchy, and responsive breakpoints.
Do not use for non-image tasks or when the active model already supports Do not use for non-image tasks or when the active model already supports
@@ -31,7 +31,7 @@ role: Tool
You (the calling agent) cannot read images — your model has no vision. Any You (the calling agent) cannot read images — your model has no vision. Any
task that requires *seeing* a visual artifact must be delegated to the task that requires *seeing* a visual artifact must be delegated to the
**Image Interpreter** role, which runs on a vision-capable model and returns a **Tool** role (image interpretation), which runs on a vision-capable model and returns a
structured text description you can act on. structured text description you can act on.
Trigger situations: Trigger situations:
@@ -64,7 +64,7 @@ Trigger situations:
) )
``` ```
4. **Consume the returned text spec.** The Image Interpreter returns a 4. **Consume the returned text spec.** The Tool sub-agent (image interpretation) returns a
structured description only — it cannot write code or artifacts. Use the structured description only — it cannot write code or artifacts. Use the
returned spec to drive your own work (code generation, design review, returned spec to drive your own work (code generation, design review,
planning). planning).
@@ -74,7 +74,7 @@ Trigger situations:
## Notes ## Notes
- The Image Interpreter is **read-only** — it describes images, it does not edit - The Tool sub-agent (image interpretation) is **read-only** — it describes images, it does not edit
files or write code. files or write code.
- One delegation per distinct visual question. Batch multiple images into a - One delegation per distinct visual question. Batch multiple images into a
single delegation only when they must be compared. single delegation only when they must be compared.
+13 -13
View File
@@ -8,7 +8,7 @@ description: >
self-checks against the relevant checklist before handing off to code self-checks against the relevant checklist before handing off to code
review. review.
# `stage` is intentionally omitted: `implement` is a production-phase name the # `stage` is intentionally omitted: `implement` is a production-phase name the
# stage registry rules invalid post-[org-internal #3072] phase 3 (see # stage registry rules invalid post-[TT-3072] phase 3 (see
# core/schemas/workflow-routing.schema.json stage enum — production-phase # core/schemas/workflow-routing.schema.json stage enum — production-phase
# names are "no longer valid anywhere"). The implement skill has no registry # names are "no longer valid anywhere"). The implement skill has no registry
# gate id; the gates it feeds into are `review-code` and `verify`. # gate id; the gates it feeds into are `review-code` and `verify`.
@@ -77,7 +77,7 @@ In **pipeline mode** (work item from iteration plan), follow the standard precon
**On-demand references**: each mode's phase-by-phase detail (templates, prompts, orchestration flows, historical notes) lives in `reference/{mode}-mode.md`, NOT injected — read it at mode entry. Full read-timing table: References section. **On-demand references**: each mode's phase-by-phase detail (templates, prompts, orchestration flows, historical notes) lives in `reference/{mode}-mode.md`, NOT injected — read it at mode entry. Full read-timing table: References section.
> **Progressive disclosure ([org-internal #3734])**: when dispatching a Developer scoped to > **Progressive disclosure ([TT-3734])**: when dispatching a Developer scoped to
> one mode, pass `skills: ["implement:mode-bugfix"]` (preamble + that > one mode, pass `skills: ["implement:mode-bugfix"]` (preamble + that
> mode's workflow only) instead of the full body; pipeline-mode dispatches > mode's workflow only) instead of the full body; pipeline-mode dispatches
> should also carry `pipeline-detection` > should also carry `pipeline-detection`
@@ -97,12 +97,12 @@ The Developer is responsible for:
- Writing code that faithfully implements the design. - Writing code that faithfully implements the design.
- Running typecheck, lint, and tests to self-verify. - Running typecheck, lint, and tests to self-verify.
- Self-checking against the relevant checklist before handoff. - Self-checking against the relevant checklist before handoff.
- Persisting the final report to disk before returning — worker-report persistence ([org-internal #2847], see `../_shared/worker-report-persistence.md`). - Persisting the final report to disk before returning — worker-report persistence ([TT-2847], see `../_shared/worker-report-persistence.md`).
- Writing no more and no less than the work item scope — no opportunistic refactoring of unrelated code. - Writing no more and no less than the work item scope — no opportunistic refactoring of unrelated code.
The Builder's role is to validate the implementation output and pass it to code review. The Builder MUST NOT write or revise implementation code. The Builder's role is to validate the implementation output and pass it to code review. The Builder MUST NOT write or revise implementation code.
### Pre-flight checklist injection ([org-internal #2599]) ### Pre-flight checklist injection ([TT-2599])
Before dispatching ANY Developer (or Tester) sub-agent — in every mode (implement / bugfix / refactor / port; pipeline or standalone) — the orchestrator resolves the ticket's route (the Process Assessment Gate Step 0 already resolves the Kind/* route) and reads `<instance-root>/workflow-routing.yaml` `routes.{Kind}.preflight`. When the list is non-empty, prepend it to the sub-agent's task prompt as: Before dispatching ANY Developer (or Tester) sub-agent — in every mode (implement / bugfix / refactor / port; pipeline or standalone) — the orchestrator resolves the ticket's route (the Process Assessment Gate Step 0 already resolves the Kind/* route) and reads `<instance-root>/workflow-routing.yaml` `routes.{Kind}.preflight`. When the list is non-empty, prepend it to the sub-agent's task prompt as:
@@ -162,7 +162,7 @@ Standard workflow for work items from an approved iteration plan. Full phase det
> >
> At Phase 6 handoff, pass `mode: "dag-task"` to review-code (its DAG Task Mode keys off the same frozen-DAG-copy detection). > At Phase 6 handoff, pass `mode: "dag-task"` to review-code (its DAG Task Mode keys off the same frozen-DAG-copy detection).
> **Legacy pipeline preconditions retired ([org-internal #3072] phase 3, 2026-08-21)**: tiered artifact-existence and review-convergence checks belonged to the archived legacy pipeline. Live input modes: DAG task mode (above) and standalone modes (the request itself is the spec). Historical tiered publish targets: `reference/implement-mode.md` § Legacy notes. > **Legacy pipeline preconditions retired ([TT-3072] phase 3, 2026-08-21)**: tiered artifact-existence and review-convergence checks belonged to the archived legacy pipeline. Live input modes: DAG task mode (above) and standalone modes (the request itself is the spec). Historical tiered publish targets: `reference/implement-mode.md` § Legacy notes.
Before starting implementation, confirm: Before starting implementation, confirm:
@@ -186,13 +186,13 @@ Every gate below is hard — agents rationalize skipping exactly these. Full det
4. **Phase 4 — Self-Check** (all mandatory): 4. **Phase 4 — Self-Check** (all mandatory):
1. `bun typecheck` (or project-equivalent) — zero errors. 1. `bun typecheck` (or project-equivalent) — zero errors.
2. `bun oxlint --deny-warnings` (repo root — the review-code mechanical gate's canonical lint invocation; `bun lint` is the package-script alias) — zero errors. 2. `bun oxlint --deny-warnings` (repo root — the review-code mechanical gate's canonical lint invocation; `bun lint` is the package-script alias) — zero errors.
3. `bun run test:changed` (or project-equivalent; full suite `bun run test:parallel` is verify's job, not a per-revision gate, [org-internal #2598]) — all tests pass. 3. `bun run test:changed` (or project-equivalent; full suite `bun run test:parallel` is verify's job, not a per-revision gate, [TT-2598]) — all tests pass.
4. Post-deletion cleanup (when any code was removed): re-run lint + typecheck to catch orphaned imports/variables/type references. 4. Post-deletion cleanup (when any code was removed): re-run lint + typecheck to catch orphaned imports/variables/type references.
Then self-check `core/checklists/implementation.md`; every new function/method/exported API has ≥ 1 test; interface promises cross-checked against the node's edge contracts. **Review-readiness GATE**: self-attest `core/checklists/code-review.md` (COR, DGN, SEC, PERF, TST, STY, DBT, A11Y, DOC, TRC), record pass/fail per dimension in the Phase 5 report; handoff requires **0 BLOCKERs and 0 MAJORs** — if you can find a MAJOR, the formal review will too; fix it now. Then self-check `core/checklists/implementation.md`; every new function/method/exported API has ≥ 1 test; interface promises cross-checked against the node's edge contracts. **Review-readiness GATE**: self-attest `core/checklists/code-review.md` (COR, DGN, SEC, PERF, TST, STY, DBT, A11Y, DOC, TRC), record pass/fail per dimension in the Phase 5 report; handoff requires **0 BLOCKERs and 0 MAJORs** — if you can find a MAJOR, the formal review will too; fix it now.
5. **Phase 4.5 — Iteration Completion Commit**: after ALL work items in the iteration pass Phase 4, commit with format `[{chunk-id}][{iteration}] {summary}`; commit body REQUIRED for non-trivial commits (> 1 file or > 20 LOC): What (files + purpose + the `WI-{NNN}` ID — code-review TRC 10.1), Why (design/REQ motivation), Evidence (test names / verification commands). Full rules: `reference/implement-mode.md` § Phase 4.5. 5. **Phase 4.5 — Iteration Completion Commit**: after ALL work items in the iteration pass Phase 4, commit with format `[{chunk-id}][{iteration}] {summary}`; commit body REQUIRED for non-trivial commits (> 1 file or > 20 LOC): What (files + purpose + the `WI-{NNN}` ID — code-review TRC 10.1), Why (design/REQ motivation), Evidence (test names / verification commands). Full rules: `reference/implement-mode.md` § Phase 4.5.
6. **Phase 4.6 — Issue Checklist Sync (progressive)**: after committing, mark items this iteration delivered `- [x]` + `_(commit {sha}: file/component)_` per the `issue-checklist-sync` L1 rule; do NOT touch items outside this iteration's scope. 6. **Phase 4.6 — Issue Checklist Sync (progressive)**: after committing, mark items this iteration delivered `- [x]` + `_(commit {sha}: file/component)_` per the `issue-checklist-sync` L1 rule; do NOT touch items outside this iteration's scope.
7. **Phase 4.7 — PR-Creation Sync**: the session pushes its branch and reports `status=done branch=<ref> verify=… risk=…` — the orchestrator opens the PR (serially per TD-678/[org-internal #4425]) and applies the `Risk/*` label from the report's `risk=` hint, computed per the risk-classifier frozen table (`HIGH_RISK_GLOBS` in `.gitea/scripts/risk-classifier.ts`: core/migrations/deploy/`core/rules/**`/`.gitea/workflows/**` → `Risk/High`, else `Risk/Low`); `Risk/High` PRs merge manually by design. Once the PR exists, ensure `## 当前状态` exists (PR / 代码评审 / CI rows are written by the `status-sync` poller, NOT by hand); append the PR reference to the matching Epic task-list row. **Never hand-sync main into the PR branch** — that is the keep-mergeable workflow's job. Detail: `reference/implement-mode.md` § Phase 4.6 / § Phase 4.7. 7. **Phase 4.7 — PR-Creation Sync**: the session pushes its branch and reports `status=done branch=<ref> verify=… risk=…` — the orchestrator opens the PR (serially per TD-678/[TT-4425]) and applies the `Risk/*` label from the report's `risk=` hint, computed per the risk-classifier frozen table (`HIGH_RISK_GLOBS` in `.gitea/scripts/risk-classifier.ts`: core/migrations/deploy/`core/rules/**`/`.gitea/workflows/**` → `Risk/High`, else `Risk/Low`); `Risk/High` PRs merge manually by design. Once the PR exists, ensure `## 当前状态` exists (PR / 代码评审 / CI rows are written by the `status-sync` poller, NOT by hand); append the PR reference to the matching Epic task-list row. **Never hand-sync main into the PR branch** — that is the keep-mergeable workflow's job. Detail: `reference/implement-mode.md` § Phase 4.6 / § Phase 4.7.
8. **Phase 5 — Report**: implementation report with AC → test traceability (template: `reference/implement-mode.md` § Phase 5). **Persist before returning ([org-internal #2847])** — the Developer's LAST action before returning the report: write it to `<runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md` (Tier 1 run workspace) else `/tmp/octopus/{chunk-id}-worker-{seq}.md` (`../_shared/worker-report-persistence.md`). The persisted copy is the report of record — applies to EVERY mode's report phase. 8. **Phase 5 — Report**: implementation report with AC → test traceability (template: `reference/implement-mode.md` § Phase 5). **Persist before returning ([TT-2847])** — the Developer's LAST action before returning the report: write it to `<runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md` (Tier 1 run workspace) else `/tmp/octopus/{chunk-id}-worker-{seq}.md` (`../_shared/worker-report-persistence.md`). The persisted copy is the report of record — applies to EVERY mode's report phase.
9. **Phase 6 — Handoff to Code Review**: present the report; signal readiness via `signal_stage_done`. Do NOT mark the work item complete until code review passes. 9. **Phase 6 — Handoff to Code Review**: present the report; signal readiness via `signal_stage_done`. Do NOT mark the work item complete until code review passes.
#### Tester focus & Common Rationalizations #### Tester focus & Common Rationalizations
@@ -216,7 +216,7 @@ The regression test MUST fail before the fix — the Tester dispatches between P
2. **Phase 2 — Isolate Root Cause**: trace symptom → proximate cause → root cause (RCA template: `reference/bugfix-mode.md` § Phase 2); fixing a symptom → stop, go deeper; not found after 3 levels of indirection → pause and report, no surface-level patch. Then evaluate routing (below). 2. **Phase 2 — Isolate Root Cause**: trace symptom → proximate cause → root cause (RCA template: `reference/bugfix-mode.md` § Phase 2); fixing a symptom → stop, go deeper; not found after 3 levels of indirection → pause and report, no surface-level patch. Then evaluate routing (below).
3. **Phase 3 — Write a Regression Test**: exercise the exact bug path with the failing inputs; it MUST fail with the bug's symptom NOW, before the fix (already passing → the test does not cover the bug, rewrite it; no failing test possible → most targeted test, marked `[flaky]`). 3. **Phase 3 — Write a Regression Test**: exercise the exact bug path with the failing inputs; it MUST fail with the bug's symptom NOW, before the fix (already passing → the test does not cover the bug, rewrite it; no failing test possible → most targeted test, marked `[flaky]`).
4. **Phase 4 — Fix**: minimum change resolving the root cause; one conceptual change per fix — no bundled refactoring, style changes, or "while I'm here" improvements (root cause in a different file → fix it there). Run the regression test (MUST pass) + relevant unit tests. 4. **Phase 4 — Fix**: minimum change resolving the root cause; one conceptual change per fix — no bundled refactoring, style changes, or "while I'm here" improvements (root cause in a different file → fix it there). Run the regression test (MUST pass) + relevant unit tests.
5. **Phase 5 — Self-Check & Report**: `bun typecheck`; `bun oxlint --deny-warnings`; `bun run test:changed` (all pass; full suite belongs to verify); verify `core/checklists/bugfix.md`; publish the bugfix report as wiki page `{slug}/bugfix-report` (template: `reference/bugfix-mode.md` § Bugfix Report); persist per the Phase 5 persistence rule (Mode: implement, [org-internal #2847]). 5. **Phase 5 — Self-Check & Report**: `bun typecheck`; `bun oxlint --deny-warnings`; `bun run test:changed` (all pass; full suite belongs to verify); verify `core/checklists/bugfix.md`; publish the bugfix report as wiki page `{slug}/bugfix-report` (template: `reference/bugfix-mode.md` § Bugfix Report); persist per the Phase 5 persistence rule (Mode: implement, [TT-2847]).
6. **Phase 5.5 — Issue Checklist Sync (standalone bugfix)**: sync the source issue at each transition (commit / PR / review / CI / close) per the `issue-checklist-sync` L1 rule and its standalone-flow table. 6. **Phase 5.5 — Issue Checklist Sync (standalone bugfix)**: sync the source issue at each transition (commit / PR / review / CI / close) per the `issue-checklist-sync` L1 rule and its standalone-flow table.
7. **Phase 6 — Approval**: present the report (prompt: `reference/bugfix-mode.md` § Phase 6 — Approval). 7. **Phase 6 — Approval**: present the report (prompt: `reference/bugfix-mode.md` § Phase 6 — Approval).
@@ -224,14 +224,14 @@ The regression test MUST fail before the fix — the Tester dispatches between P
Full escalate/stay criteria: `reference/bugfix-mode.md` § Routing Decision. In short — **escalate to pipeline** on ANY of: ≥ 5 files · ≥ 2 modules/components · design-level root cause · data migration / schema change · public-API / contract change · dependency change · > 50 lines · user requests full-process; **stay standalone** only when ALL the opposites hold. If uncertain, escalate — a false escalation costs review rounds; a false standalone decision skips quality gates. Full escalate/stay criteria: `reference/bugfix-mode.md` § Routing Decision. In short — **escalate to pipeline** on ANY of: ≥ 5 files · ≥ 2 modules/components · design-level root cause · data migration / schema change · public-API / contract change · dependency change · > 50 lines · user requests full-process; **stay standalone** only when ALL the opposites hold. If uncertain, escalate — a false escalation costs review rounds; a false standalone decision skips quality gates.
**Big-bug relabel rule ([org-internal #3061])** — before the generic escalation above, split the triggers by kind: **Big-bug relabel rule ([TT-3061])** — before the generic escalation above, split the triggers by kind:
- **Design-level triggers** (root cause is a design decision — protocol / schema / architecture; shared-contract or public-API change; data migration): do NOT push through bugfix — **relabel the ticket `Kind/Feature`** and reroute via Step 0 (DAG route; 1–3 node small DAG expected); repro + root-cause notes become node input. - **Design-level triggers** (root cause is a design decision — protocol / schema / architecture; shared-contract or public-API change; data migration): do NOT push through bugfix — **relabel the ticket `Kind/Feature`** and reroute via Step 0 (DAG route; 1–3 node small DAG expected); repro + root-cause notes become node input.
- **Mechanical size triggers only** (many files / lines, same design): stay in bugfix — batch into iterations, keep review-code + verify. Scale alone never justifies a relabel. - **Mechanical size triggers only** (many files / lines, same design): stay in bugfix — batch into iterations, keep review-code + verify. Scale alone never justifies a relabel.
#### Pipeline Mode (bugfix) #### Pipeline Mode (bugfix)
> **Legacy path retired ([org-internal #3072] phase 3)**: the requirements → design → review → plan front-end was archived; a big bug needing a design-level decision relabels `Kind/Feature` into the DAG route (big-bug relabel rule above). > **Legacy path retired ([TT-3072] phase 3)**: the requirements → design → review → plan front-end was archived; a big bug needing a design-level decision relabels `Kind/Feature` into the DAG route (big-bug relabel rule above).
When a bugfix escalates beyond standalone scope, the bug report becomes a pipeline input; the bugfix phases (reproduce, root cause, regression test, fix) are embedded within the implement stage, and review-code + verify remain mandatory. On the DAG route the node spec lives in `{epic-slug}/dag`; the Developer follows bugfix Phases 1–6 as the implementation method, then produces the standard implementation report (Mode: implement, Phase 5). When a bugfix escalates beyond standalone scope, the bug report becomes a pipeline input; the bugfix phases (reproduce, root cause, regression test, fix) are embedded within the implement stage, and review-code + verify remain mandatory. On the DAG route the node spec lives in `{epic-slug}/dag`; the Developer follows bugfix Phases 1–6 as the implementation method, then produces the standard implementation report (Mode: implement, Phase 5).
@@ -259,7 +259,7 @@ Restructure existing code without changing observable behavior — the existing
1. **Phase 1 — Scope & Baseline**: map exact files + dependents; run `bun run test:parallel` (the refactor baseline legitimately needs the full suite) — ANY pre-existing failure → stop ("Cannot begin refactoring with failing tests. Fix them first."). Capture baseline: test count, coverage, optional complexity (template: `reference/refactor-mode.md` § Baseline). 1. **Phase 1 — Scope & Baseline**: map exact files + dependents; run `bun run test:parallel` (the refactor baseline legitimately needs the full suite) — ANY pre-existing failure → stop ("Cannot begin refactoring with failing tests. Fix them first."). Capture baseline: test count, coverage, optional complexity (template: `reference/refactor-mode.md` § Baseline).
2. **Phase 2 — Define Target Pattern**: Extract / Inline / Rename / Move / Replace / Simplify / Upgrade, with one-sentence goal + success criteria (all tests pass unchanged; structural goal met; coverage does not decrease). Pipeline mode: align with the node spec + contracts, or justify in the report. 2. **Phase 2 — Define Target Pattern**: Extract / Inline / Rename / Move / Replace / Simplify / Upgrade, with one-sentence goal + success criteria (all tests pass unchanged; structural goal met; coverage does not decrease). Pipeline mode: align with the node spec + contracts, or justify in the report.
3. **Phase 3 — Decompose into Steps**: smallest individually-verifiable steps (each reversible, suite-passing, ONE conceptual transformation); present the plan before executing (user may approve / reorder / reject). **If > 10 steps, the scope is too large — split into multiple sessions.** 3. **Phase 3 — Decompose into Steps**: smallest individually-verifiable steps (each reversible, suite-passing, ONE conceptual transformation); present the plan before executing (user may approve / reorder / reject). **If > 10 steps, the scope is too large — split into multiple sessions.**
4. **Phase 4 — Incremental Execution**: per step — transform, run `bun run test:changed` (ALL pass; per-step scoped reruns — full suite is verify's job, [org-internal #2598]), commit `refactor: {what} from {where}`. **If FAIL: revert immediately** — do NOT fix the test or code within the same step; find a smaller decomposition (exception: fix a flaky test first as a prerequisite step, then retry). 4. **Phase 4 — Incremental Execution**: per step — transform, run `bun run test:changed` (ALL pass; per-step scoped reruns — full suite is verify's job, [TT-2598]), commit `refactor: {what} from {where}`. **If FAIL: revert immediately** — do NOT fix the test or code within the same step; find a smaller decomposition (exception: fix a flaky test first as a prerequisite step, then retry).
5. **Phase 5 — Final Validation**: `bun run test:parallel` all pass; `bun typecheck` zero errors; `bun oxlint --deny-warnings` zero errors; coverage MUST NOT decrease vs baseline (±1% noise). 5. **Phase 5 — Final Validation**: `bun run test:parallel` all pass; `bun typecheck` zero errors; `bun oxlint --deny-warnings` zero errors; coverage MUST NOT decrease vs baseline (±1% noise).
6. **Phase 6 — Report**: before/after metrics, steps executed, verification results, design deviations (template: `reference/refactor-mode.md` § Refactor Report). 6. **Phase 6 — Report**: before/after metrics, steps executed, verification results, design deviations (template: `reference/refactor-mode.md` § Refactor Report).
7. **Phase 7 — Approval**: present the report (prompt: `reference/refactor-mode.md` § Phase 7 — Approval). Route to code review if > 50 lines or ≥ 5 files. 7. **Phase 7 — Approval**: present the report (prompt: `reference/refactor-mode.md` § Phase 7 — Approval). Route to code review if > 50 lines or ≥ 5 files.
@@ -336,7 +336,7 @@ Not all work items involve writing new code — some are refactoring, bugfix, or
- `core/skills/browser-debug/SKILL.md` — Interactive browser verification (for frontend work items) and UI bug reproduction (bugfix Phase 1) - `core/skills/browser-debug/SKILL.md` — Interactive browser verification (for frontend work items) and UI bug reproduction (bugfix Phase 1)
- `core/skills/review-code/SKILL.md` — Code review (next step after implementation) - `core/skills/review-code/SKILL.md` — Code review (next step after implementation)
- `core/skills/verify/SKILL.md` — Integration + fidelity verification (pipeline-mode bugfix, large port) - `core/skills/verify/SKILL.md` — Integration + fidelity verification (pipeline-mode bugfix, large port)
- `<instance-root>/archive/skills/` — Legacy requirements/design/plan/roadmap skills (archived [org-internal #3072] phase 3; their templates moved to `<instance-root>/archive/templates/`) - `<instance-root>/archive/skills/` — Legacy requirements/design/plan/roadmap skills (archived [TT-3072] phase 3; their templates moved to `<instance-root>/archive/templates/`)
- `reference/source-analysis.md` — Port Phase A1, A1.5, A1.7, A1.8 detailed processes & templates - `reference/source-analysis.md` — Port Phase A1, A1.5, A1.7, A1.8 detailed processes & templates
- `reference/mapping-and-design.md` — Port Phase A2, A3, A4 detailed processes & templates - `reference/mapping-and-design.md` — Port Phase A2, A3, A4 detailed processes & templates
- `reference/large-port-pipeline.md` — Port Phase B1–B4 detailed processes - `reference/large-port-pipeline.md` — Port Phase B1–B4 detailed processes
@@ -1,4 +1,4 @@
> Extracted from implement/SKILL.md (Mode: bugfix) — moved verbatim 2026-08-25, ticket [org-internal #3381]. > Extracted from implement/SKILL.md (Mode: bugfix) — moved verbatim 2026-08-25, ticket [TT-3381].
### Mode: bugfix ### Mode: bugfix
@@ -182,7 +182,7 @@ If the Developer is uncertain, escalate. A false pipeline escalation costs a few
extra review rounds. A false standalone decision risks missing a quality gate on extra review rounds. A false standalone decision risks missing a quality gate on
a complex change. a complex change.
**Big-bug relabel rule ([org-internal #3061])** — before the generic escalation below, split **Big-bug relabel rule ([TT-3061])** — before the generic escalation below, split
the triggers by kind: the triggers by kind:
- **Design-level triggers** (root cause is a design decision — protocol / - **Design-level triggers** (root cause is a design decision — protocol /
@@ -449,7 +449,7 @@ resolves it by permitting triage but forbidding deferral.
#### Pipeline Mode (bugfix) #### Pipeline Mode (bugfix)
> **Legacy path retired ([org-internal #3072] phase 3, 2026-08-21)**: the full > **Legacy path retired ([TT-3072] phase 3, 2026-08-21)**: the full
> requirements-elicitation → design → review-artifact(design-space) → > requirements-elicitation → design → review-artifact(design-space) →
> plan-iterations → review-artifact(plan) front-end was archived > plan-iterations → review-artifact(plan) front-end was archived
> (`<instance-root>/archive/skills/`). A big bug that needs a design-level decision > (`<instance-root>/archive/skills/`). A big bug that needs a design-level decision
@@ -1,4 +1,4 @@
> Extracted from implement/SKILL.md (Mode: implement) — moved verbatim 2026-08-25, ticket [org-internal #3381]. > Extracted from implement/SKILL.md (Mode: implement) — moved verbatim 2026-08-25, ticket [TT-3381].
### Mode: implement (default) ### Mode: implement (default)
@@ -8,7 +8,7 @@ and self-verify before passing to code review.
#### Pre-flight #### Pre-flight
The pre-flight self-check prompt format ([org-internal #2599]), prepended to the Developer The pre-flight self-check prompt format ([TT-2599]), prepended to the Developer
sub-agent's task prompt when `routes.{Kind}.preflight` is non-empty: sub-agent's task prompt when `routes.{Kind}.preflight` is non-empty:
``` ```
@@ -75,7 +75,7 @@ Developer is structurally biased to miss.
#### Preconditions #### Preconditions
> **Publish target (tiered targeting retired, [org-internal #3072] phase 3)**: the > **Publish target (tiered targeting retired, [TT-3072] phase 3)**: the
> `Size/*`-tiered publish rule (`rules/workflow-routing.md` §"Publish target > `Size/*`-tiered publish rule (`rules/workflow-routing.md` §"Publish target
> by Size/* tier — RETIRED") was retired with the legacy producer skills. > by Size/* tier — RETIRED") was retired with the legacy producer skills.
> Artifacts publish where the live mode puts them: DAG task mode → node spec > Artifacts publish where the live mode puts them: DAG task mode → node spec
@@ -125,7 +125,7 @@ Developer is structurally biased to miss.
Before starting implementation, confirm: Before starting implementation, confirm:
> **Legacy pipeline preconditions retired ([org-internal #3072] phase 3, 2026-08-21)**: the > **Legacy pipeline preconditions retired ([TT-3072] phase 3, 2026-08-21)**: the
> tier-dependent requirements/design/plan artifact-existence checks and the > tier-dependent requirements/design/plan artifact-existence checks and the
> design-space / iteration-plan review-convergence checks that used to head > design-space / iteration-plan review-convergence checks that used to head
> this list belonged to the archived legacy pipeline (`<instance-root>/archive/`). > this list belonged to the archived legacy pipeline (`<instance-root>/archive/`).
@@ -162,7 +162,7 @@ the work-item list from the frozen DAG copy: the ready/pending task nodes in
`{epic-slug}/dag` (via `wiki 读写 API(见 TERMINOLOGY)`), cross-checked against the `{epic-slug}/dag` (via `wiki 读写 API(见 TERMINOLOGY)`), cross-checked against the
node tickets on the Epic's `## DAG 状态` table. (Legacy tier-based resolution node tickets on the Epic's `## DAG 状态` table. (Legacy tier-based resolution
via `{slug}/04-plan-04-iteration-assignment` was archived 2026-08-21, via `{slug}/04-plan-04-iteration-assignment` was archived 2026-08-21,
[org-internal #3072] phase 3.) Present the current ready nodes for selection: [TT-3072] phase 3.) Present the current ready nodes for selection:
``` ```
Current iteration: Iteration {N}: {Goal} Current iteration: Iteration {N}: {Goal}
@@ -346,7 +346,7 @@ a one-pass implementation into a multi-round review.
| "Design is ambiguous here, I'll pick the obvious option" | Inventing a design decision is a Phase 2 abort condition. Flag the gap; do not guess. | | "Design is ambiguous here, I'll pick the obvious option" | Inventing a design decision is a Phase 2 abort condition. Flag the gap; do not guess. |
| "Already manually verified it works" | Manual ≠ systematic — no record, can't re-run, can't bisect. `bun run test:changed` is the evidence the report demands. | | "Already manually verified it works" | Manual ≠ systematic — no record, can't re-run, can't bisect. `bun run test:changed` is the evidence the report demands. |
| "Report is busywork, the diff speaks for itself" | No report → review-code cannot trace AC→test. Phase 5 is the handoff contract; skip it and the review stalls. | | "Report is busywork, the diff speaks for itself" | No report → review-code cannot trace AC→test. Phase 5 is the handoff contract; skip it and the review stalls. |
| "X× improvement — assumed, no measurement" | Quick-measure before it becomes an AC. Unverified assumptions in ACs waste framing cost ([org-internal #1932]: YAML token density assumed 2-3×, measured 0.95 — hypothesis rejected by data). | | "X× improvement — assumed, no measurement" | Quick-measure before it becomes an AC. Unverified assumptions in ACs waste framing cost ([TT-1932]: YAML token density assumed 2-3×, measured 0.95 — hypothesis rejected by data). |
--- ---
@@ -463,14 +463,14 @@ waiting for the final verify gate.
The session pushes its branch and reports `status=done branch=<ref> verify=… The session pushes its branch and reports `status=done branch=<ref> verify=…
risk=…`; the orchestrator admits the PR (serially, one open at a time) — risk=…`; the orchestrator admits the PR (serially, one open at a time) —
workers never open PRs (TD-678/[org-internal #4425]; `uncoordinated` self-open only when workers never open PRs (TD-678/[TT-4425]; `uncoordinated` self-open only when
the orchestrator is unreachable). Once that PR exists, update the source the orchestrator is unreachable). Once that PR exists, update the source
issue so stakeholders see the mergeable state without waiting for code issue so stakeholders see the mergeable state without waiting for code
review. Mandated by the `issue-checklist-sync` L1 rule; skip if no source review. Mandated by the `issue-checklist-sync` L1 rule; skip if no source
issue exists. issue exists.
> PR shape per mode: default = one 1:1 PR per task (body carries the worker > PR shape per mode: default = one 1:1 PR per task (body carries the worker
> report); batch-mode epics ([org-internal #3731], per-epic opt-in) = the orchestrator > report); batch-mode epics ([TT-3731], per-epic opt-in) = the orchestrator
> composes ONE batch PR per iteration via the `land-batch` skill. This phase > composes ONE batch PR per iteration via the `land-batch` skill. This phase
> then runs per member issue as usual (N times), each pointing at its PR > then runs per member issue as usual (N times), each pointing at its PR
> (batch: the single batch PR); the poller writes the PR/CI/review rows > (batch: the single batch PR); the poller writes the PR/CI/review rows
@@ -549,7 +549,7 @@ Produce an implementation report:
**Handoff**: Ready for `core/skills/review-code/SKILL.md` **Handoff**: Ready for `core/skills/review-code/SKILL.md`
``` ```
**Persist before returning ([org-internal #2847])**: the Developer MUST write the final **Persist before returning ([TT-2847])**: the Developer MUST write the final
report above to disk as its LAST action, BEFORE returning it — report above to disk as its LAST action, BEFORE returning it —
`<runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md` when the Tier 1 `<runs-root>/{slug}/workers/{chunk-id}-worker-{seq}.md` when the Tier 1
run workspace exists, else `/tmp/octopus/{chunk-id}-worker-{seq}.md` run workspace exists, else `/tmp/octopus/{chunk-id}-worker-{seq}.md`
@@ -582,7 +582,7 @@ To notify workflow completion, call the `signal_stage_done` tool.
#### Legacy notes #### Legacy notes
> **Publish target (tiered targeting retired, [org-internal #3072] phase 3)**: the > **Publish target (tiered targeting retired, [TT-3072] phase 3)**: the
> `Size/*`-tiered publish rule (`rules/workflow-routing.md` §"Publish target > `Size/*`-tiered publish rule (`rules/workflow-routing.md` §"Publish target
> by Size/* tier — RETIRED") was retired with the legacy producer skills. > by Size/* tier — RETIRED") was retired with the legacy producer skills.
> Artifacts publish where the live mode puts them: DAG task mode → node spec > Artifacts publish where the live mode puts them: DAG task mode → node spec
@@ -155,7 +155,7 @@ analysis:
## Phase B3 — Handoff to DAG Decomposition ## Phase B3 — Handoff to DAG Decomposition
> Legacy note ([org-internal #3072] phase 3, 2026-08-21): this handoff used to target the > Legacy note ([TT-3072] phase 3, 2026-08-21): this handoff used to target the
> archived `roadmap` skill; it now targets `analyze-dag`. > archived `roadmap` skill; it now targets `analyze-dag`.
Present the source analysis and request task-DAG decomposition: Present the source analysis and request task-DAG decomposition:
@@ -194,7 +194,7 @@ core/skills/implement/SKILL.md
(The legacy per-chunk `requirements-elicitation` → `design` → (The legacy per-chunk `requirements-elicitation` → `design` →
`review-artifact(design-space)` → `plan-iterations` → `review-artifact(plan)` `review-artifact(design-space)` → `plan-iterations` → `review-artifact(plan)`
front-end was archived 2026-08-21, [org-internal #3072] phase 3 — `<instance-root>/archive/`.) front-end was archived 2026-08-21, [TT-3072] phase 3 — `<instance-root>/archive/`.)
### implement ### implement
+4 -4
View File
@@ -1,4 +1,4 @@
> Extracted from implement/SKILL.md (Mode: port) — moved verbatim 2026-08-25, ticket [org-internal #3381]. > Extracted from implement/SKILL.md (Mode: port) — moved verbatim 2026-08-25, ticket [TT-3381].
### Mode: port ### Mode: port
@@ -274,7 +274,7 @@ port (source analysis)
→ verify (integration + fidelity) → verify (integration + fidelity)
``` ```
> Legacy diagram (archived [org-internal #3072] phase 3): the former per-chunk pipeline ran > Legacy diagram (archived [TT-3072] phase 3): the former per-chunk pipeline ran
> requirements-elicitation → design → review (target: design-space) → > requirements-elicitation → design → review (target: design-space) →
> plan-iterations → review (target: plan) → implement → review-code. Those > plan-iterations → review (target: plan) → implement → review-code. Those
> skills/targets are archived (`<instance-root>/archive/`); the live path is the > skills/targets are archived (`<instance-root>/archive/`); the live path is the
@@ -286,7 +286,7 @@ port (source analysis)
| B1.5 | **GATE** — 10-dimensional peer review of source analysis | `reference/large-port-pipeline.md` | | B1.5 | **GATE** — 10-dimensional peer review of source analysis | `reference/large-port-pipeline.md` |
| B1.7+B1.8 | Target surface & capability boundary as formal artifacts for peer review | `reference/large-port-pipeline.md` | | B1.7+B1.8 | Target surface & capability boundary as formal artifacts for peer review | `reference/large-port-pipeline.md` |
| B2 | Self-check source analysis against port checklist | `reference/large-port-pipeline.md` | | B2 | Self-check source analysis against port checklist | `reference/large-port-pipeline.md` |
| B3 | Handoff to analyze-dag — decompose by source module into DAG nodes (legacy: roadmap skill, archived [org-internal #3072] phase 3) | `reference/large-port-pipeline.md` | | B3 | Handoff to analyze-dag — decompose by source module into DAG nodes (legacy: roadmap skill, archived [TT-3072] phase 3) | `reference/large-port-pipeline.md` |
| B4 | Per-node DAG task route: implement → review-code (the review-dag single gate replaces the legacy design-space + plan reviews at the Epic level) | `reference/large-port-pipeline.md` | | B4 | Per-node DAG task route: implement → review-code (the review-dag single gate replaces the legacy design-space + plan reviews at the Epic level) | `reference/large-port-pipeline.md` |
| B5 | Verify — integration + fidelity, every `FID-*` traced to a passing test | `reference/fidelity-verification.md` | | B5 | Verify — integration + fidelity, every `FID-*` traced to a passing test | `reference/fidelity-verification.md` |
| B6 | **Final Approval** — consolidated port report | *(inline below)* | | B6 | **Final Approval** — consolidated port report | *(inline below)* |
@@ -324,7 +324,7 @@ Present source analysis summary and request task-DAG decomposition. The
Builder routes to `core/skills/analyze-dag/SKILL.md` with slug Builder routes to `core/skills/analyze-dag/SKILL.md` with slug
`port-{name}` (nodes per source module; the source analysis supplies node `port-{name}` (nodes per source module; the source analysis supplies node
ACs and edge contracts). (Legacy: this handed off to the archived `roadmap` ACs and edge contracts). (Legacy: this handed off to the archived `roadmap`
skill — `<instance-root>/archive/skills/roadmap/`, [org-internal #3072] phase 3.) See skill — `<instance-root>/archive/skills/roadmap/`, [TT-3072] phase 3.) See
`reference/large-port-pipeline.md` for the handoff format. `reference/large-port-pipeline.md` for the handoff format.
##### Phase B4 — Per-Node Pipeline ##### Phase B4 — Per-Node Pipeline
@@ -1,4 +1,4 @@
> Extracted from implement/SKILL.md (Mode: refactor) — moved verbatim 2026-08-25, ticket [org-internal #3381]. > Extracted from implement/SKILL.md (Mode: refactor) — moved verbatim 2026-08-25, ticket [TT-3381].
### Mode: refactor ### Mode: refactor
@@ -1,4 +1,4 @@
> Extracted from implement/SKILL.md (Pipeline Work Item Detection) — moved verbatim 2026-08-25, ticket [org-internal #3381]. > Extracted from implement/SKILL.md (Pipeline Work Item Detection) — moved verbatim 2026-08-25, ticket [TT-3381].
## Pipeline Work Item Detection ## Pipeline Work Item Detection
+10 -10
View File
@@ -2,7 +2,7 @@
name: land-batch name: land-batch
description: > description: >
Use ONLY when the orchestrator lands the finished task branches of one DAG Use ONLY when the orchestrator lands the finished task branches of one DAG
iteration as a single batch PR ([org-internal #3731] batch-landing pilot). Composes iteration as a single batch PR ([TT-3731] batch-landing pilot). Composes
path-disjoint member branches via the deterministic batch-compose script, path-disjoint member branches via the deterministic batch-compose script,
pre-validates locally, opens ONE PR for N tasks (one CI fan-out instead of pre-validates locally, opens ONE PR for N tasks (one CI fan-out instead of
N on the single-runner pool), pastes each member's review synthesis into N on the single-runner pool), pastes each member's review synthesis into
@@ -27,18 +27,18 @@ role: Producer
(single writer at iteration close — the same role that already owns uniform (single writer at iteration close — the same role that already owns uniform
merge/close). `workflow/batch/*` branches are NOT claim branches: no merge/close). `workflow/batch/*` branches are NOT claim branches: no
`claim.sh` interaction, no assignee; the orchestrator is the only composer. `claim.sh` interaction, no assignee; the orchestrator is the only composer.
Pilot charter: the decision comment on [org-internal #3731] (scope, opt-in protocol, cap, Pilot charter: the decision comment on [TT-3731] (scope, opt-in protocol, cap,
success criteria) — this skill implements that charter, not the epic's success criteria) — this skill implements that charter, not the epic's
frozen DAG v1 (which covers only the merge-coordinator nodes N-01..04). frozen DAG v1 (which covers only the merge-coordinator nodes N-01..04).
## Applicability: post-hoc composition only (topology B) ## Applicability: post-hoc composition only (topology B)
Two batch shapes exist ([org-internal #3731] charter addendum, comment 39347): Two batch shapes exist ([TT-3731] charter addendum, comment 39347):
- **Topology A — single-session mono-branch batch**: one session owns every - **Topology A — single-session mono-branch batch**: one session owns every
ticket from inception and writes them on ONE branch (instance: PR [org-internal #3861], ticket from inception and writes them on ONE branch (instance: PR [TT-3861],
audit-h1). Hand composition is natural there — do NOT force this skill on audit-h1). Hand composition is natural there — do NOT force this skill on
it; record the outcome on [org-internal #3731] as a manual-batch datum instead. it; record the outcome on [TT-3731] as a manual-batch datum instead.
- **Topology B — parallel workers, post-hoc composition**: workers finish on - **Topology B — parallel workers, post-hoc composition**: workers finish on
SEPARATE branches at different times; the orchestrator composes at SEPARATE branches at different times; the orchestrator composes at
iteration close. This is the skill's ONLY applicability — cross-branch iteration close. This is the skill's ONLY applicability — cross-branch
@@ -173,7 +173,7 @@ Do NOT hand-merge, do NOT hand-sync main into the batch branch.
Member issues auto-close via the English keywords; their `## 当前状态` Member issues auto-close via the English keywords; their `## 当前状态`
PR/代码评审/CI rows fan out to EVERY close ref (status-sync poller Wide PR/代码评审/CI rows fan out to EVERY close ref (status-sync poller Wide
behavior — requires [org-internal #3867], merged 2026-08-31). `task done ≡ PR merged` behavior — requires [TT-3867], merged 2026-08-31). `task done ≡ PR merged`
still holds, transitively still holds, transitively
through the batch PR; verify milestones fire unchanged. through the batch PR; verify milestones fire unchanged.
@@ -189,15 +189,15 @@ through the batch PR; verify milestones fire unchanged.
Any fallback preserves today's behavior — batch landing is an optimization, Any fallback preserves today's behavior — batch landing is an optimization,
never a dependency. never a dependency.
## Measurement (pilot duty — revised per [org-internal #3731] charter addendum 39347) ## Measurement (pilot duty — revised per [TT-3731] charter addendum 39347)
Per-iteration attribution only; the global 7-day ratio is trend context, Per-iteration attribution only; the global 7-day ratio is trend context,
never a pass/fail judge (same-window confounders: test-slim [org-internal #3855] / never a pass/fail judge (same-window confounders: test-slim [TT-3855] /
test-dedupe [org-internal #3854] / the pilot's own PRs). On the server, test-dedupe [TT-3854] / the pilot's own PRs). On the server,
`bun .gitea/scripts/ci-run-stats.ts --days 7 --json /tmp/<slug>-ci-stats.json` `bun .gitea/scripts/ci-run-stats.ts --days 7 --json /tmp/<slug>-ci-stats.json`
(the `--json` flag takes a filename — bare, it is a silent no-op; the human (the `--json` flag takes a filename — bare, it is a silent no-op; the human
summary still prints). Same methodology as the checklist-merge-gate.yml summary still prints). Same methodology as the checklist-merge-gate.yml
2026-08-27 note. Record on [org-internal #3731]: (a) this batch iteration's per-workflow 2026-08-27 note. Record on [TT-3731]: (a) this batch iteration's per-workflow
trigger counts vs a historically similar 1:1 iteration, and (b) one trigger counts vs a historically similar 1:1 iteration, and (b) one
fallback drill (construct a path-overlap group → exit-3 split executed). fallback drill (construct a path-overlap group → exit-3 split executed).
Baseline, trend only: 2026-08-31, 5,081 runs / TOTAL 2.75x single runner. Baseline, trend only: 2026-08-31, 5,081 runs / TOTAL 2.75x single runner.
+4 -4
View File
@@ -8,7 +8,7 @@ description: >
project scaffolding. Do not use for application-level configuration — project scaffolding. Do not use for application-level configuration —
this skill covers the octopus project lifecycle, not user application code. this skill covers the octopus project lifecycle, not user application code.
triggers: triggers:
# High-discrimination phrases only ([org-internal #4525]): bare "setup"/"init"/"配置" fire # High-discrimination phrases only ([TT-4525]): bare "setup"/"init"/"配置" fire
# on any configuration mention, and the skill gate folds the previous # on any configuration mention, and the skill gate folds the previous
# assistant turn on approval turns — one stray "配置" in a reply re-fires # assistant turn on approval turns — one stray "配置" in a reply re-fires
# the gate every turn. Keep triggers to phrases that name THIS workflow; # the gate every turn. Keep triggers to phrases that name THIS workflow;
@@ -36,7 +36,7 @@ This skill activates when the user's text matches any of the trigger keywords:
- `project setup` — asking how to set up a project in octopus - `project setup` — asking how to set up a project in octopus
- `项目初始化` / `项目配置` — asking how to initialize or configure an octopus project (Chinese) - `项目初始化` / `项目配置` — asking how to initialize or configure an octopus project (Chinese)
Generic "setup"/"init"/"配置" mentions are deliberately NOT triggers ([org-internal #4525]): they collide with everyday configuration talk, and the hard skill gate folds the previous assistant turn into its match text on approval turns — a passing "或配置x: false" in a reply would re-fire the gate every turn. `/init` note: `/init` generates AGENTS.md via LLM; kickoff uses the managed template from `octopus setup` — the Builder distinguishes based on context. Generic "setup"/"init"/"配置" mentions are deliberately NOT triggers ([TT-4525]): they collide with everyday configuration talk, and the hard skill gate folds the previous assistant turn into its match text on approval turns — a passing "或配置x: false" in a reply would re-fire the gate every turn. `/init` note: `/init` generates AGENTS.md via LLM; kickoff uses the managed template from `octopus setup` — the Builder distinguishes based on context.
Typical user intents include: encountering a readiness prompt at session start, wondering how to initialize a project, or wanting to understand the kickoff workflow steps. Typical user intents include: encountering a readiness prompt at session start, wondering how to initialize a project, or wanting to understand the kickoff workflow steps.
@@ -74,14 +74,14 @@ The kickoff workflow runs in four automated steps:
- [2/5] **Scaffold** — Creates the `<instance-root>/` skeleton (`core/skills/` directory + default `octopus.jsonc` template if absent); domain skills content arrives via the [5/5] overlay pull - [2/5] **Scaffold** — Creates the `<instance-root>/` skeleton (`core/skills/` directory + default `octopus.jsonc` template if absent); domain skills content arrives via the [5/5] overlay pull
- [3/5] **Config stub + MCP wiring** — Writes the `mcp.codegraph` block into `octopus.jsonc` - [3/5] **Config stub + MCP wiring** — Writes the `mcp.codegraph` block into `octopus.jsonc`
- [4/5] **Codegraph init** — Initializes and builds the per-project `.codegraph/` index - [4/5] **Codegraph init** — Initializes and builds the per-project `.codegraph/` index
- [5/5] **Skills remote + overlay pull** — Opt-in semantics ([org-internal #4370]); branches by flags when no `overlay.remotes` entry is configured: - [5/5] **Skills remote + overlay pull** — Opt-in semantics ([TT-4370]); branches by flags when no `overlay.remotes` entry is configured:
- no flags (interactive run) — **safe default**: nothing is written; a remediation hint is printed (pass `--skills-remote`, or edit `overlay.remotes`), and the readiness skills item stays not-ready - no flags (interactive run) — **safe default**: nothing is written; a remediation hint is printed (pass `--skills-remote`, or edit `overlay.remotes`), and the readiness skills item stays not-ready
- `--yes` — legacy behavior kept: writes the default skills remote, then pulls domain skills content (`octopus skills pull` equivalent) - `--yes` — legacy behavior kept: writes the default skills remote, then pulls domain skills content (`octopus skills pull` equivalent)
- `--skills-remote <owner/repo>` (+ optional `--skills-remote-base-url <url>`) — writes the specified remote instead (ref `main`; base URL defaults to `<instance-base-url>`), then pulls from it - `--skills-remote <owner/repo>` (+ optional `--skills-remote-base-url <url>`) — writes the specified remote instead (ref `main`; base URL defaults to `<instance-base-url>`), then pulls from it
- `overlay.remotes` already configured — the write is skipped (idempotent; an explicit `--skills-remote` is ignored with a warning) - `overlay.remotes` already configured — the write is skipped (idempotent; an explicit `--skills-remote` is ignored with a warning)
4. **Post-kickoff verification** — Run `octopus kickoff --check-only` again. After a `--yes` or `--skills-remote` run it reports all 5 items as ready; after a no-flag interactive run it reports 4 of 5 — the skills item stays not-ready until a remote is configured (`--skills-remote`, `--yes`, or a manual `overlay.remotes` edit + `octopus skills pull`). 4. **Post-kickoff verification** — Run `octopus kickoff --check-only` again. After a `--yes` or `--skills-remote` run it reports all 5 items as ready; after a no-flag interactive run it reports 4 of 5 — the skills item stays not-ready until a remote is configured (`--skills-remote`, `--yes`, or a manual `overlay.remotes` edit + `octopus skills pull`).
### First-ticket hint ([org-internal #3061]) ### First-ticket hint ([TT-3061])
For a brand-new project still validating its concept, open the FIRST ticket as For a brand-new project still validating its concept, open the FIRST ticket as
`Kind/MVP` — the interactive no-pipeline mode (decision log + debt register in `Kind/MVP` — the interactive no-pipeline mode (decision log + debt register in
+37 -34
View File
@@ -1,12 +1,11 @@
--- ---
name: release name: release
description: > description: >
Use ONLY when ready to cut a release. The Release Manager (Worker) inspects Use ONLY when ready to cut a release. The Producer (Worker) inspects
project state (git log, version files, build) to determine the semver bump, project state (git log, version files, build) to determine the semver bump,
generate the changelog, tag, and produce a release artifact. Works on any generate the changelog, tag, and produce a release artifact. Works on any
project state — no pipeline artifacts required. project state — no pipeline artifacts required.
triggers: triggers:
- release
- cut release - cut release
- 发版 - 发版
- publish release - publish release
@@ -14,7 +13,6 @@ triggers:
role: Producer role: Producer
--- ---
> Core 中立版(Increment 6a 改写,原 deferHard verbatimDir)。机制、结构与 frontmatter 保持;实例术语(工具名、路径、工单号)按 `core/adapters/TERMINOLOGY.md` 绑定到具体实例。
# Release # Release
Prepare and tag a release based on project facts — git history since the last Prepare and tag a release based on project facts — git history since the last
@@ -28,14 +26,14 @@ produced here is the input to project-specific deployment workflows.
## Agent Role ## Agent Role
The release is owned and executed by the **Release Manager** (Worker). The release is owned and executed by the **Producer** (Worker).
**Context compaction**: release is a pipeline stage boundary. The main session **Context compaction**: release is a pipeline stage boundary. The main session
compacts at this clean boundary ONLY when a capacity/projection trigger holds, compacts at this clean boundary ONLY when a capacity/projection trigger holds,
per `core/rules/compact.md` §"Stage-boundary compaction" (long multi-stage per `.octopus/rules/compact.md` §"Stage-boundary compaction" (long multi-stage
runs — DAG Epic orchestration — keep the legacy every-boundary compaction; runs — DAG Epic orchestration — keep the legacy every-boundary compaction;
short runs — bugfix / DAG task — and standalone runs default to NOT short runs — bugfix / DAG task — and standalone runs default to NOT
compacting). The Release Manager itself is single-phase and compacting). The Producer itself is single-phase and
artifact-driven (version files, changelog, tag); a mid-run compaction loses artifact-driven (version files, changelog, tag); a mid-run compaction loses
nothing — re-read the release checklist state and git log to resume. nothing — re-read the release checklist state and git log to resume.
@@ -46,7 +44,7 @@ nothing — re-read the release checklist state and git log to resume.
Before starting the release: Before starting the release:
- [ ] Working tree is clean (`git status` has no uncommitted changes). - [ ] Working tree is clean (`git status` has no uncommitted changes).
- [ ] `core/checklists/release.md` is accessible. - [ ] `.octopus/checklists/release.md` is accessible.
--- ---
@@ -65,14 +63,14 @@ Run each check against the live project. Stop and report failures.
- No new HIGH or CRITICAL CVEs block the release. - No new HIGH or CRITICAL CVEs block the release.
- Pre-existing HIGH/CRITICAL CVEs do NOT block but **MUST be filed as - Pre-existing HIGH/CRITICAL CVEs do NOT block but **MUST be filed as
tech-debt** before the release lands. File them in TWO TIERS (batching tech-debt** before the release lands. File them in TWO TIERS (batching
rule, [org-internal #3846] — a single release audit once fanned out to 14 TDs → 14 PRs → rule, [TT-3846] — a single release audit once fanned out to 14 TDs → 14 PRs →
56-84 CI runs on a saturated runner pool): Tier A below is the general 56-84 CI runs on a saturated runner pool): Tier A below is the general
mechanical-change batching rule; Tier B and the escape hatch follow it. mechanical-change batching rule; Tier B and the escape hatch follow it.
<a id="phase-1-tier-a"></a> <a id="phase-1-tier-a"></a>
### Tier A — 通用机械变更并单规则 / Universal mechanical-change batching rule ### Tier A — 通用机械变更并单规则 / Universal mechanical-change batching rule
Origin [org-internal #3846] (audit-batch pilot, generalized in place): the rule covers ANY Origin [TT-3846] (audit-batch pilot, generalized in place): the rule covers ANY
single-source fan-out of mechanical changes, not just dependency audits. single-source fan-out of mechanical changes, not just dependency audits.
Two source types today: (a) dependency bump audits; (b) docs 批量修订 Two source types today: (a) dependency bump audits; (b) docs 批量修订
(batch docs revisions). (batch docs revisions).
@@ -83,10 +81,10 @@ Two source types today: (a) dependency bump audits; (b) docs 批量修订
source are filed as ONE batch issue + ONE batch PR — never N×issue + source are filed as ONE batch issue + ONE batch PR — never N×issue +
N×PR. The batch body keeps one row per item (per-CVE / per-doc mapping), N×PR. The batch body keeps one row per item (per-CVE / per-doc mapping),
so per-item traceability is unchanged; work the batch as a single PR. so per-item traceability is unchanged; work the batch as a single PR.
- **(a) Dependency bump audits** (the [org-internal #3846] origin case): advisories whose - **(a) Dependency bump audits** (the [TT-3846] origin case): advisories whose
remediation is a plain version bump (lockfile-only diff, no semver-major remediation is a plain version bump (lockfile-only diff, no semver-major
jump, no overrides/catalog surgery, no API or adapter fallout) are filed jump, no overrides/catalog surgery, no API or adapter fallout) are filed
together via `工单 API(见 TERMINOLOGY)create` with together via REST `POST .../issues` with
`title="[{origin}] audit-batch@{version}: mechanical bumps for {N} advisories (TD-{NNN})"` `title="[{origin}] audit-batch@{version}: mechanical bumps for {N} advisories (TD-{NNN})"`
and labels `[tech_debt_label_id, severity_label_id, kind_bug_label_id]` and labels `[tech_debt_label_id, severity_label_id, kind_bug_label_id]`
(severity = highest in the batch). One row per advisory — CVE/GHSA ID, (severity = highest in the batch). One row per advisory — CVE/GHSA ID,
@@ -101,7 +99,7 @@ Two source types today: (a) dependency bump audits; (b) docs 批量修订
`title="[{origin}] docs-batch: {class} revisions for {N} files"`, with one `title="[{origin}] docs-batch: {class} revisions for {N} files"`, with one
row per file (path, correction, reason); same ONE-batch-PR landing. row per file (path, correction, reason); same ONE-batch-PR landing.
- **Landing**: when members live on separate branches, compose the single - **Landing**: when members live on separate branches, compose the single
batch PR via the `land-batch` skill (`core/skills/land-batch/SKILL.md` batch PR via the `land-batch` skill (`.octopus/skills/land-batch/SKILL.md`
— cross-branch batch composition, topology B). For dependency-bump — cross-branch batch composition, topology B). For dependency-bump
batches pass `batch-compose --convergent bun.lock` (script batches pass `batch-compose --convergent bun.lock` (script
`.gitea/scripts/batch-compose.ts`): the regenerable lockfile is exempt `.gitea/scripts/batch-compose.ts`): the regenerable lockfile is exempt
@@ -110,14 +108,14 @@ Two source types today: (a) dependency bump audits; (b) docs 批量修订
#### 适用边界 / Applicability boundary #### 适用边界 / Applicability boundary
- **非mechanical(含判断成分的变更,不并单)** — items requiring judgment - **非 mechanical(含判断成分的变更,不并单)** — items requiring judgment
(wording decisions, behavior/API changes, review-dependent edits) are (wording decisions, behavior/API changes, review-dependent edits) are
never batched; file each as its own issue. never batched; file each as its own issue.
- **路径重叠(batch 成员触碰相同文件 → 不并单;唯一豁免 = - **路径重叠(batch 成员触碰相同文件 → 不并单;唯一豁免 =
可再生共享文件`bun.lock` 经batch-compose `--convergent` 收敛)** — the sole 可再生共享文件 `bun.lock` 经 batch-compose `--convergent` 收敛)** — the sole
path-overlap exemption is the regenerable shared lockfile under path-overlap exemption is the regenerable shared lockfile under
`--convergent`; every other same-file collision stays un-batched. `--convergent`; every other same-file collision stays un-batched.
- **semver-major 跳变 / overrides·catalog 手术 / adapter·peer 联动(→ - **semver-major 跳变 / overrides·catalog 手术 / adapter·peer 联动(→
Tier B 独立单,维持 per-package)** — these stay per-package Tier B Tier B 独立单,维持 per-package)** — these stay per-package Tier B
issues. Tier B and the escape hatch (below) survive this generalization issues. Tier B and the escape hatch (below) survive this generalization
unchanged. unchanged.
@@ -134,7 +132,7 @@ Two source types today: (a) dependency bump audits; (b) docs 批量修订
along the reported pairs (or land the overlapping member 1:1) and re-run along the reported pairs (or land the overlapping member 1:1) and re-run
per group; `4` merge conflict / `5` transport/git error → fall back to per group; `4` merge conflict / `5` transport/git error → fall back to
1:1 PRs for the whole batch. 1:1 PRs for the whole batch.
- **Preflight hedge ([org-internal #3846])**: run `bun install --dry-run` before opening - **Preflight hedge ([TT-3846])**: run `bun install --dry-run` before opening
a dependency-batch PR — the resolver accepting the composed version set a dependency-batch PR — the resolver accepting the composed version set
is a cheap pre-CI rejection of impossible bump combinations. is a cheap pre-CI rejection of impossible bump combinations.
@@ -157,12 +155,12 @@ template and `_shared/gitea-write-patterns.md` Pattern 3.
| Check | Status | | Check | Status |
| ----------------- | ----------------------------------------------------- | | ----------------- | ----------------------------------------------------- |
| Clean workspace | ✅/ ❌ | | Clean workspace | ✅ / ❌ |
| Branch | {branch name} | | Branch | {branch name} |
| Build | ✅/ ❌ | | Build | ✅ / ❌ |
| Typecheck + Lint | ✅/ ❌ | | Typecheck + Lint | ✅ / ❌ |
| Tests | ✅/ ❌(N passed, M failed) | | Tests | ✅ / ❌ (N passed, M failed) |
| Dependency audit | ✅/ ⚠️ N known CVEs (pre-existing) / ❌N new CVEs | | Dependency audit | ✅ / ⚠️ N known CVEs (pre-existing) / ❌ N new CVEs |
``` ```
If any gate fails except known CVEs, stop and report what failed. If any gate fails except known CVEs, stop and report what failed.
@@ -294,7 +292,7 @@ Write to root `CHANGELOG.md` (prepend section).
> the goal is identical (turn the tag into downloadable assets). > the goal is identical (turn the tag into downloadable assets).
The CI publish pipeline (`.gitea/workflows/publish.yml`) was **retired by The CI publish pipeline (`.gitea/workflows/publish.yml`) was **retired by
[org-internal #2003]** (138/138 historical runs cancelled; the pipeline sat unused for 35+ [TT-2003]** (138/138 historical runs cancelled; the pipeline sat unused for 35+
days). Releasing octopus is now a **manual local process**. All former CI days). Releasing octopus is now a **manual local process**. All former CI
steps live in repo scripts, runnable from a maintainer machine with the right steps live in repo scripts, runnable from a maintainer machine with the right
credentials in the environment. credentials in the environment.
@@ -309,7 +307,7 @@ credentials in the environment.
- `NODE_AUTH_TOKEN` — only if publishing to npm. - `NODE_AUTH_TOKEN` — only if publishing to npm.
- `AUR_KEY` — only if pushing the AUR package. - `AUR_KEY` — only if pushing the AUR package.
- Docker logged in to the Gitea container registry: - Docker logged in to the Gitea container registry:
`echo "$GITEA_TOKEN" | docker login <instance-registry-host> -u <user> --password-stdin`. `echo "$GITEA_TOKEN" | docker login eightarms.net -u <user> --password-stdin`.
### Steps ### Steps
@@ -323,7 +321,7 @@ credentials in the environment.
```bash ```bash
OCTOPUS_VERSION={version} OCTOPUS_RELEASE={release-id} \ OCTOPUS_VERSION={version} OCTOPUS_RELEASE={release-id} \
GH_REPO=Octopus/octopus GITEA_TOKEN=<pat> \ GH_REPO=Octopus/octopus GITEA_TOKEN=<pat> \
bun <harness-package>/script/build.ts bun packages/octopus/script/build.ts
``` ```
`build.ts` attaches the 12 release assets to the draft release. `build.ts` attaches the 12 release assets to the draft release.
@@ -339,14 +337,14 @@ credentials in the environment.
4. **Undraft the release** (makes it public): 4. **Undraft the release** (makes it public):
```bash ```bash
curl -fsS -X PATCH \ curl -fsS -X PATCH \
"<instance-base-url>/api/v1/repos/Octopus/octopus/releases/{release-id}" \ "https://eightarms.net/api/v1/repos/Octopus/octopus/releases/{release-id}" \
-H "Authorization: token $GITEA_TOKEN" \ -H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" -d '{"draft": false}' -H "Content-Type: application/json" -d '{"draft": false}'
``` ```
5. **Verify assets** — the release must carry 12 assets: 5. **Verify assets** — the release must carry 12 assets:
```bash ```bash
curl -sS "<instance-base-url>/api/v1/repos/Octopus/octopus/releases/tags/v{version}" \ curl -sS "https://eightarms.net/api/v1/repos/Octopus/octopus/releases/tags/v{version}" \
-H "Authorization: token $GITEA_TOKEN" | jq '.assets | length' -H "Authorization: token $GITEA_TOKEN" | jq '.assets | length'
``` ```
@@ -360,11 +358,11 @@ credentials in the environment.
### Notes ### Notes
- **Windows code-signing** is not provisioned (no Windows runner / Azure - **Windows code-signing** is not provisioned (no Windows runner / Azure
Trusted Signing); the CLI ships unsigned, as before ([org-internal #252]). Trusted Signing); the CLI ships unsigned, as before ([TT-252]).
- **Rollback**: if a step fails mid-release, the draft release + tag can be - **Rollback**: if a step fails mid-release, the draft release + tag can be
deleted and re-run; every script above is idempotent or safely re-runnable. deleted and re-run; every script above is idempotent or safely re-runnable.
- If a future CI pipeline replaces this manual flow, update this section and - If a future CI pipeline replaces this manual flow, update this section and
reference [org-internal #2003] for the retirement rationale. reference [TT-2003] for the retirement rationale.
--- ---
@@ -375,9 +373,14 @@ Document how to undo this release:
1. **Git rollback**: 1. **Git rollback**:
- `git tag -d v{version}` (if not yet pushed). - `git tag -d v{version}` (if not yet pushed).
- `git revert {commit_hash}` (if already merged). - `git revert {commit_hash}` (if already merged).
- If the release includes DB migrations, confirm the `down` migration exists. - If the release includes DB migrations, confirm the `down` migration exists
**when the project's migration tooling provides one**. This repo's Drizzle
convention is forward-only (`migration.sql` + `snapshot.json`, no `down`
files) — there, record the reversal plan (manual SQL / restore) or mark the
change irreversible instead of waiting on a `down` file that never comes.
2. **Data rollback** (if applicable): 2. **Data rollback** (if applicable):
- For each migration, confirm the `down` migration exists and has been tested. - For each migration, confirm the `down` migration exists and has been tested
where the tooling offers one; otherwise document the manual reversal steps.
- If the release changes data format without a reversible migration, mark - If the release changes data format without a reversible migration, mark
`⚠️ IRREVERSIBLE DATA CHANGE`. `⚠️ IRREVERSIBLE DATA CHANGE`.
@@ -390,7 +393,7 @@ git tag -d v{version}
# or: git revert {hash} # or: git revert {hash}
### Data Rollback ### Data Rollback
- Migration `{name}`: down {exists / NOT FOUND} - Migration `{name}`: down {exists / NOT FOUND / N/A — forward-only tooling}
- {additional risks} - {additional risks}
### Rollback Triggers ### Rollback Triggers
@@ -419,7 +422,7 @@ git tag -d v{version}
**Version**: {old} → {new} (MAJOR / MINOR / PATCH) **Version**: {old} → {new} (MAJOR / MINOR / PATCH)
**Tag**: v{version} **Tag**: v{version}
**Commits**: {N} since last tag ({feat} features, {fix} fixes) **Commits**: {N} since last tag ({feat} features, {fix} fixes)
**Typecheck**: ✅| Lint: ✅| Tests: ✅ **Typecheck**: ✅ | Lint: ✅ | Tests: ✅
### Changelog ### Changelog
@@ -435,13 +438,13 @@ git tag -d v{version}
**Deploy**: {manual step — "merge to main triggers CI", etc.} **Deploy**: {manual step — "merge to main triggers CI", etc.}
**Rollback**: see Phase 5 above **Rollback**: see Phase 5 above
**Next**: `core/skills/retrospective/SKILL.md` (optional — run on any project state) **Next**: `.octopus/skills/retrospective/SKILL.md` (optional — run on any project state)
``` ```
--- ---
## References ## References
- `core/checklists/release.md` — Release checklist - `.octopus/checklists/release.md` — Release checklist
- Semver spec: https://semver.org - Semver spec: https://semver.org
- Conventional Commits: https://www.conventionalcommits.org - Conventional Commits: https://www.conventionalcommits.org
+21 -21
View File
@@ -232,7 +232,7 @@ review findings not actionable upstream]`.
archive-at-close; (b) the committed archive bundles archive-at-close; (b) the committed archive bundles
`<runs-root>/archive/{slug}.json`, where per-review round counts are `<runs-root>/archive/{slug}.json`, where per-review round counts are
reconstructed from the documented `reviews/{stage}/round{N}/` layout in reconstructed from the documented `reviews/{stage}/round{N}/` layout in
`index.artifacts[].path` ([org-internal #2591] — the archive source is what makes M3 `index.artifacts[].path` ([TT-2591] — the archive source is what makes M3
durable instead of structurally emptying as runs close). Available once durable instead of structurally emptying as runs close). Available once
any run has closed. any run has closed.
- Rework fraction: 🟢 <15% / 🟡 15–30% / 🔴 >30%. - Rework fraction: 🟢 <15% / 🟡 15–30% / 🔴 >30%.
@@ -245,7 +245,7 @@ or upstream design unclear]`.
- 🟢 cache_read/input > 10:1 / 🟡 3–10:1 / 🔴 < 3:1. - 🟢 cache_read/input > 10:1 / 🟡 3–10:1 / 🔴 < 3:1.
- < 3:1 → `[SIGNAL: cache hit <3:1 — context re-read, code-graph-first - < 3:1 → `[SIGNAL: cache hit <3:1 — context re-read, code-graph-first
not followed]`. not followed]`.
- **Compact frequency ([org-internal #2601] pilot data)**: report the token-telemetry - **Compact frequency ([TT-2601] pilot data)**: report the token-telemetry
"Compactor Activity" line (compactor messages/tokens in window) and the "Compactor Activity" line (compactor messages/tokens in window) and the
zero-compact share of short runs (bugfix / DAG task) — the capacity-driven compaction zero-compact share of short runs (bugfix / DAG task) — the capacity-driven compaction
pilot metrics. A rising zero-compact share with NO late-stage pilot metrics. A rising zero-compact share with NO late-stage
@@ -259,7 +259,7 @@ not followed]`.
- < 1:1 → `[SIGNAL: explore/execute <1:1 — workers doing explorers' job, - < 1:1 → `[SIGNAL: explore/execute <1:1 — workers doing explorers' job,
exploration skipped or under-delegated]`. exploration skipped or under-delegated]`.
### 2.8 Gate defect-escape analysis (single metric, [org-internal #3061]) ### 2.8 Gate defect-escape analysis (single metric, [TT-3061])
Gates earn their cost by what they CATCH, and the honest test is what slips Gates earn their cost by what they CATCH, and the honest test is what slips
past them: a gate that runs clean while the same defect resurfaces downstream past them: a gate that runs clean while the same defect resurfaces downstream
@@ -297,7 +297,7 @@ status` CLI or commit-status inspection. Final reports at
downstream sources for an escape. downstream sources for an escape.
3. Tally per `gate_id`: `clean_runs`, `escapes`, `escape_rate`. 3. Tally per `gate_id`: `clean_runs`, `escapes`, `escape_rate`.
4. Reading (thresholds are this skill's own policy — the `gate_trim:` block 4. Reading (thresholds are this skill's own policy — the `gate_trim:` block
they once deferred to was retired 2026-08-21, [org-internal #3072] phase 3; nothing they once deferred to was retired 2026-08-21, [TT-3072] phase 3; nothing
trims gates anymore, so the trim-candidate branch below is gone): trims gates anymore, so the trim-candidate branch below is gone):
- `escape_rate ≥ 0.3` → the gate is - `escape_rate ≥ 0.3` → the gate is
**UNDER-POWERED**: route the escape causes into §2.9 pre-flight **UNDER-POWERED**: route the escape causes into §2.9 pre-flight
@@ -305,12 +305,12 @@ status` CLI or commit-status inspection. Final reports at
propose trimming it. propose trimming it.
- `escape_rate < 0.3` → healthy; report the numbers, no further verdict. - `escape_rate < 0.3` → healthy; report the numbers, no further verdict.
**DAG single-gate exclusion ([org-internal #2267])**: `review-dag` is structurally **DAG single-gate exclusion ([TT-2267])**: `review-dag` is structurally
non-trimmable (`dag.route.single_gate.never_trim: true` — self-contained in non-trimmable (`dag.route.single_gate.never_trim: true` — self-contained in
the `dag:` block); `verify` and `merge-pr` were `never_trim` in the retired the `dag:` block); `verify` and `merge-pr` were `never_trim` in the retired
`gate_trim` block and stay untouchable by convention. `gate_trim` block and stay untouchable by convention.
**keep_gates exclusion (TD-390, [org-internal #3061]) — RETIRED with gate_trim**: the **keep_gates exclusion (TD-390, [TT-3061]) — RETIRED with gate_trim**: the
rule that a trim candidate's gate must not be a member of the target route's rule that a trim candidate's gate must not be a member of the target route's
`keep_gates` guarded a landing field (`sizing.tiers.*.additional_skip`) `keep_gates` guarded a landing field (`sizing.tiers.*.additional_skip`)
that no longer exists. Historical record: wiki `rules/gate-trim`. that no longer exists. Historical record: wiki `rules/gate-trim`.
@@ -331,10 +331,10 @@ runs for a gate → report the raw numbers with
- [NOTE: insufficient sample for gate X] where clean runs < 5. - [NOTE: insufficient sample for gate X] where clean runs < 5.
- UNDER-POWERED gates (escape_rate ≥ 0.3) feed §2.9 pre-flight — never a - UNDER-POWERED gates (escape_rate ≥ 0.3) feed §2.9 pre-flight — never a
unilateral trim: the only exit is a furlough entry in unilateral trim: the only exit is a furlough entry in
`<instance-root>/gate-ledger.yaml` (evidence + reopen condition, [org-internal #3607]). `<instance-root>/gate-ledger.yaml` (evidence + reopen condition, [TT-3607]).
``` ```
### 2.9 Pre-flight defect-prevention analysis ([org-internal #2599]) ### 2.9 Pre-flight defect-prevention analysis ([TT-2599])
First-round FAIL/WARN findings are the pipeline's cost multiplier: every First-round FAIL/WARN findings are the pipeline's cost multiplier: every
multi-round review pays for them twice (review round + revision round). multi-round review pays for them twice (review round + revision round).
@@ -348,13 +348,13 @@ code.
reports for the cycle's tickets (`{slug}/reviews/{stage}/final/report` — reports for the cycle's tickets (`{slug}/reviews/{stage}/final/report` —
round-1 findings with severity FAIL/WARN, their dimension codes, and the round-1 findings with severity FAIL/WARN, their dimension codes, and the
finding text for root-cause categorization) + the source issues' finding text for root-cause categorization) + the source issues'
`Kind/*` labels. For DAG-routed Epics ([org-internal #2905] 方案 3), two further `Kind/*` labels. For DAG-routed Epics ([TT-2905] 方案 3), two further
read-only sources feed the `REQ × late-discovery` root cause (step 1): read-only sources feed the `REQ × late-discovery` root cause (step 1):
(a) **DAG oversize-signal events** — `node_split` / registry-row additions (a) **DAG oversize-signal events** — `node_split` / registry-row additions
recorded on the Epic's issue timeline / `## DAG 状态` whose trigger is a NEW recorded on the Epic's issue timeline / `## DAG 状态` whose trigger is a NEW
requirement rather than a refactor; (b) **demo-period feedback** — requirement rather than a refactor; (b) **demo-period feedback** —
stakeholder comments naming functionality the frozen DAG never covered. For browser-evidence stakeholder comments naming functionality the frozen DAG never covered. For browser-evidence
cycles ([org-internal #4499], contract `browser-evidence-4486/shared/evidence-ref-v1` §3), a cycles ([TT-4499], contract `browser-evidence-4486/shared/evidence-ref-v1` §3), a
third read-only third read-only
source: (c) **browser session rows** — per browser-debug session source: (c) **browser session rows** — per browser-debug session
`{session_id, outcome: evidence-captured | env-unavailable | replay-failed, `{session_id, outcome: evidence-captured | env-unavailable | replay-failed,
@@ -373,7 +373,7 @@ Rows are currently Task-DAG cycle products by default (the helper's
Bug- or Feature-cycle session to its own landing slot). The replay Bug- or Feature-cycle session to its own landing slot). The replay
success-rate baseline (N-03 BENCH) is exposed as a consumable metric — a SEEDED CONVENTION (fixture-authored outcomes, channel health), success-rate baseline (N-03 BENCH) is exposed as a consumable metric — a SEEDED CONVENTION (fixture-authored outcomes, channel health),
NOT a live-browser trend baseline. Mechanical helper: NOT a live-browser trend baseline. Mechanical helper:
`<harness-package>/scripts/browser-retro-tally.ts`. Boundary rules ([org-internal #4499] `<harness-package>/scripts/browser-retro-tally.ts`. Boundary rules ([TT-4499]
AC-3): out-of-enum or empty categories fall into an explicit `other` bucket AC-3): out-of-enum or empty categories fall into an explicit `other` bucket
with provenance (recorded, never silently swallowed, never a crash); rows with provenance (recorded, never silently swallowed, never a crash); rows
missing replay/attribution fields yield structured errors in the tally missing replay/attribution fields yield structured errors in the tally
@@ -395,10 +395,10 @@ late-discovery` — 冻结后才被发现的需求 (a requirement that surfaced
oversize signal or demo comment — count it from sources (a)/(b) above, oversize signal or demo comment — count it from sources (a)/(b) above,
not only from review findings. not only from review findings.
2. Tally per **route-class** — `Bug`, `Feature-DAG`, `Epic-DAG-route`, 2. Tally per **route-class** — `Bug`, `Feature-DAG`, `Epic-DAG-route`,
`Task-DAG` (Kind/Feature routes to the DAG pipeline since [org-internal #3061] Phase 2 / `Task-DAG` (Kind/Feature routes to the DAG pipeline since [TT-3061] Phase 2 /
TD-388 — `Feature-legacy` survives only as a historical bucket for tickets TD-388 — `Feature-legacy` survives only as a historical bucket for tickets
closed before 2026-08-20; the Size dimension is retired from retro keying, closed before 2026-08-20; the Size dimension is retired from retro keying,
[org-internal #3061]: DAG-routed tickets derive depth instead of carrying `Size/*` [TT-3061]: DAG-routed tickets derive depth instead of carrying `Size/*`
(spec-06), and `Kind/Bug` carries no ladder). First-round hit count (spec-06), and `Kind/Bug` carries no ladder). First-round hit count
and distinct-ticket count per cause per class. and distinct-ticket count per cause per class.
3. A cause is a **pre-flight candidate** when ALL hold (thresholds from 3. A cause is a **pre-flight candidate** when ALL hold (thresholds from
@@ -408,7 +408,7 @@ late-discovery` — 冻结后才被发现的需求 (a requirement that surfaced
A qualifying `Epic × DAG-route` cause (e.g. `REQ × late-discovery`) lands A qualifying `Epic × DAG-route` cause (e.g. `REQ × late-discovery`) lands
on `<instance-root>/workflow-routing.yaml` `dag.route.preflight` — NOT on `<instance-root>/workflow-routing.yaml` `dag.route.preflight` — NOT
`routes.Kind/Epic.preflight` (legacy-roadmap-era landing; the legacy route `routes.Kind/Epic.preflight` (legacy-roadmap-era landing; the legacy route
was archived [org-internal #3072] phase 3) ([org-internal #2905] 方案 3). The analyze-dag skill reads was archived [TT-3072] phase 3) ([TT-2905] 方案 3). The analyze-dag skill reads
`dag.route.preflight` before decomposition. `dag.route.preflight` before decomposition.
4. Aging: for causes ALREADY landed in `routes.{Kind}.preflight` or 4. Aging: for causes ALREADY landed in `routes.{Kind}.preflight` or
`dag.route.preflight`, count `dag.route.preflight`, count
@@ -423,7 +423,7 @@ Sample-sufficiency guard mirrors 2.8: zero qualifying tickets → emit
| route-class | Cause (checklist-qualified dim × root-cause) | 1st-round hits | tickets | qualify? | | route-class | Cause (checklist-qualified dim × root-cause) | 1st-round hits | tickets | qualify? |
| -------------- | ------------------------------------------- | -------------- | --------------------------- | -------------------------------- | | -------------- | ------------------------------------------- | -------------- | --------------------------- | -------------------------------- |
| Bug | code-review.md COR × unhandled-null | 5 | 4 ([org-internal #2400] [org-internal #2429] [org-internal #2471] [org-internal #2488]) | ✅ PROPOSE | | Bug | code-review.md COR × unhandled-null | 5 | 4 ([TT-2400] [TT-2429] [TT-2471] [TT-2488]) | ✅ PROPOSE |
| Bug | code-review.md STY × wrong-import-order | 6 | 2 | ⛔ tickets <3 | | Bug | code-review.md STY × wrong-import-order | 6 | 2 | ⛔ tickets <3 |
| Feature-DAG | code-review.md TST × missing-boundary-test | 3 | 3 | ⛔ hits <5 | | Feature-DAG | code-review.md TST × missing-boundary-test | 3 | 3 | ⛔ hits <5 |
| Epic-DAG-route | REQ × late-discovery | 5 | 3 (#27xx #28xx #29xx) | ✅ PROPOSE → dag.route.preflight | | Epic-DAG-route | REQ × late-discovery | 5 | 3 (#27xx #28xx #29xx) | ✅ PROPOSE → dag.route.preflight |
@@ -433,7 +433,7 @@ Sample-sufficiency guard mirrors 2.8: zero qualifying tickets → emit
- Landed-item aging: `cor-unhandled-null clean streak 5 ≥ aging 5` → REMOVAL row. - Landed-item aging: `cor-unhandled-null clean streak 5 ≥ aging 5` → REMOVAL row.
``` ```
### 2.10 Derived-ticket health ([org-internal #3061]) ### 2.10 Derived-ticket health ([TT-3061])
Derived tickets (TD promotions, BF umbrellas, FT tickets) are the pipeline's Derived tickets (TD promotions, BF umbrellas, FT tickets) are the pipeline's
exhaust. Unmanaged they accumulate into flush cycles (2026-08 evidence: 122 exhaust. Unmanaged they accumulate into flush cycles (2026-08 evidence: 122
@@ -477,7 +477,7 @@ this probe checks whether the system DIGESTS what it records:
- rows marked [COLD] this cycle: {list or "none"} - rows marked [COLD] this cycle: {list or "none"}
``` ```
### 2.11 Threshold calibration tally ([org-internal #3380]) ### 2.11 Threshold calibration tally ([TT-3380])
Process prose constants (round caps, D1–D4 thresholds, preflight knobs, Process prose constants (round caps, D1–D4 thresholds, preflight knobs,
escape-rate cutoffs, quotas — full index: escape-rate cutoffs, quotas — full index:
@@ -665,7 +665,7 @@ Each item MUST specify:
- Action items that modify SKILLs or templates are applied immediately (the - Action items that modify SKILLs or templates are applied immediately (the
Retrospective Lead can edit `<instance-root>/` files). Retrospective Lead can edit `<instance-root>/` files).
- Action items MUST NOT be vague ("try harder", "be more careful"). - Action items MUST NOT be vague ("try harder", "be more careful").
- **Layering question** (injection-budget ruling item 3, [org-internal #3547]): every action - **Layering question** (injection-budget ruling item 3, [TT-3547]): every action
item that encodes a lesson as a process constraint MUST answer **"which item that encodes a lesson as a process constraint MUST answer **"which
layer carries this lesson?"** — options in ascending per-turn cost, pick layer carries this lesson?"** — options in ascending per-turn cost, pick
the cheapest that actually enforces it: the cheapest that actually enforces it:
@@ -682,7 +682,7 @@ Each item MUST specify:
corpus — do not casually re-grow it; the rule-GC report in that same check corpus — do not casually re-grow it; the rule-GC report in that same check
flags aging L1 rules for L2 retirement). flags aging L1 rules for L2 retirement).
**TRIM PROPOSAL rows — RETIRED ([org-internal #3072] phase 3, 2026-08-21)**: the **TRIM PROPOSAL rows — RETIRED ([TT-3072] phase 3, 2026-08-21)**: the
gate-trim landing machinery (`gate_trim.action` → gate-trim landing machinery (`gate_trim.action` →
`sizing.tiers.{Size}.additional_skip` / `routes.{Kind}.skip` / `sizing.tiers.{Size}.additional_skip` / `routes.{Kind}.skip` /
`auto_approve.stages`) was removed with the `gate_trim:` and `sizing:` `auto_approve.stages`) was removed with the `gate_trim:` and `sizing:`
@@ -691,12 +691,12 @@ Gate health findings flow exclusively through §2.8's escape-rate verdict
(UNDER-POWERED → §2.9 pre-flight) and ordinary action items. Historical (UNDER-POWERED → §2.9 pre-flight) and ordinary action items. Historical
spec: wiki `rules/gate-trim` (L2). spec: wiki `rules/gate-trim` (L2).
**PRE-FLIGHT PROPOSAL rows** (from Phase 2.9 defect-prevention, [org-internal #2599]): format **PRE-FLIGHT PROPOSAL rows** (from Phase 2.9 defect-prevention, [TT-2599]): format
the What cell as the What cell as
`Add pre-flight '{id}' to {Kind} ({hits} first-round FAIL/WARN hits, {tickets} tickets — {evidence})` `Add pre-flight '{id}' to {Kind} ({hits} first-round FAIL/WARN hits, {tickets} tickets — {evidence})`
and the Where cell as and the Where cell as
`<instance-root>/workflow-routing.yaml` `routes.{Kind}.preflight` — or, for causes `<instance-root>/workflow-routing.yaml` `routes.{Kind}.preflight` — or, for causes
keyed `Epic × DAG-route` (e.g. `REQ × late-discovery`, [org-internal #2905] 方案 3), keyed `Epic × DAG-route` (e.g. `REQ × late-discovery`, [TT-2905] 方案 3),
`<instance-root>/workflow-routing.yaml` `dag.route.preflight` (consumed by `<instance-root>/workflow-routing.yaml` `dag.route.preflight` (consumed by
analyze-dag before decomposition). analyze-dag before decomposition).
Aging removal rows: `Remove pre-flight '{id}' from {Kind} (clean streak {N} ≥ aging threshold)`. Aging removal rows: `Remove pre-flight '{id}' from {Kind} (clean streak {N} ≥ aging threshold)`.
+18 -9
View File
@@ -1,7 +1,7 @@
--- ---
name: review-artifact name: review-artifact
description: >- description: >-
Use ONLY after analyze-dag has produced the DAG artifact — review the task DAG (review-dag single gate) — OR when auditing the <instance-root>/ process infrastructure itself (audit-process). Spawns N parallel Explorer reviewers (1 dimension each) against the matching checklist, synthesizes findings with a Worker Synthesizer, and iterates with a Worker reviser until convergence. The legacy roadmap / design-space / iteration-plan targets were archived 2026-08-21 ([org-internal #3072] phase 3, <instance-root>/archive/). Do NOT use for code review — use the review-code skill for that. Use ONLY after analyze-dag has produced the DAG artifact — review the task DAG (review-dag single gate) — OR when auditing the <instance-root>/ process infrastructure itself (audit-process). Spawns N parallel Explorer reviewers (1 dimension each) against the matching checklist, synthesizes findings with a Worker Synthesizer, and iterates with a Worker reviser until convergence. The legacy roadmap / design-space / iteration-plan targets were archived 2026-08-21 ([TT-3072] phase 3, <instance-root>/archive/). Do NOT use for code review — use the review-code skill for that.
triggers: triggers:
- audit-process - audit-process
- review-dag - review-dag
@@ -25,7 +25,7 @@ role: Reviewer
## Tool Availability & Path Resolution ## Tool Availability & Path Resolution
This skill's reviewers (parallel Explorer subagents) read two kinds of files. This skill's reviewers (parallel Explorer subagents) read two kinds of files.
Some runs cannot reach the Gitea REST API (cross-repo scenario, [org-internal #2115]); the Some runs cannot reach the Gitea REST API (cross-repo scenario, [TT-2115]); the
fallbacks below keep reviews working without it. fallbacks below keep reviews working without it.
The Orchestrator probes REST reachability **before dispatching reviewers** (Phase A The Orchestrator probes REST reachability **before dispatching reviewers** (Phase A
@@ -74,7 +74,7 @@ This skill reviews different artifact types. Identify the target from the pipeli
| **review-dag** | `review-dag` | `core/checklists/dag-single-gate.md` | 3 | Analyst | `{epic-slug}/reviews/review-dag/` | | **review-dag** | `review-dag` | `core/checklists/dag-single-gate.md` | 3 | Analyst | `{epic-slug}/reviews/review-dag/` |
> **Retired targets (historical)**: the `roadmap`, `design-space`, and `plan` > **Retired targets (historical)**: the `roadmap`, `design-space`, and `plan`
> targets were archived on 2026-08-21 per [org-internal #3072] phase 3 (ruling: > targets were archived on 2026-08-21 per [TT-3072] phase 3 (ruling:
> `docs/workflow-refactor/phase3-retirement-ruling.md`) — the legacy > `docs/workflow-refactor/phase3-retirement-ruling.md`) — the legacy
> production skills they gated no longer exist (see `<instance-root>/archive/`). > production skills they gated no longer exist (see `<instance-root>/archive/`).
> Their stage ids (`review-roadmap`, `review-design-space`, > Their stage ids (`review-roadmap`, `review-design-space`,
@@ -84,7 +84,7 @@ This skill reviews different artifact types. Identify the target from the pipeli
The stage IDs remain as-is — they are used by the stage registry and auto-approve system. The skill name is `review-artifact`, but the stage IDs do not change. The stage IDs remain as-is — they are used by the stage registry and auto-approve system. The skill name is `review-artifact`, but the stage IDs do not change.
> **Progressive disclosure ([org-internal #3734])**: this skill has two disjoint live > **Progressive disclosure ([TT-3734])**: this skill has two disjoint live
> targets — dispatch an auditor/reviewer with > targets — dispatch an auditor/reviewer with
> `skills: ["review-artifact:target-process"]` or > `skills: ["review-artifact:target-process"]` or
> `["review-artifact:target-review-dag"]` (preamble + that target only) > `["review-artifact:target-review-dag"]` (preamble + that target only)
@@ -148,7 +148,7 @@ Before launching any review, confirm:
Each target adds specific preconditions listed in its section below. If any precondition is unmet, abort and inform the user. Each target adds specific preconditions listed in its section below. If any precondition is unmet, abort and inform the user.
> ## Retired targets (historical, [org-internal #3072] phase 3) > ## Retired targets (historical, [TT-3072] phase 3)
The three legacy production-review targets — **roadmap** (stage The three legacy production-review targets — **roadmap** (stage
`review-roadmap`, checklist `roadmap.md`, revision role Analyst), `review-roadmap`, checklist `roadmap.md`, revision role Analyst),
@@ -187,6 +187,15 @@ The audit target is the **SDLC factory itself** — the set of skills, checklist
- [ ] `core/skills/` exists and contains at least one `SKILL.md`. - [ ] `core/skills/` exists and contains at least one `SKILL.md`.
- [ ] `core/checklists/audit-process.md` is accessible. - [ ] `core/checklists/audit-process.md` is accessible.
- [ ] `core/schemas/` contains the shared review schemas (`reviewer-output`, `synthesis`, `review-status`). - [ ] `core/schemas/` contains the shared review schemas (`reviewer-output`, `synthesis`, `review-status`).
- [ ] **Process-tests-green gate ([TT-4787] STD 8.8)**: before dispatching
auditors, the Orchestrator (bash-capable; Explorer auditors have none by
construction) runs the process's own suite and guards — from
`<harness-package>`: `bun run test:parallel`, plus the repo-root `check:*`
guard family — and writes the commands, baseline SHA, and per-command result
summary to `<runs-root>/audit/reviews/audit-process/process-tests-green.md`
(Tier 1). The read-only STD 8.8 auditor verifies that record against the
current baseline; any red test/guard is itself a process defect and MUST be
filed as a finding.
No `.artifacts/{slug}/` inputs are required — the audit reads `<instance-root>/` itself. Audit outputs are published as Gitea wiki pages under `audit/{date}/`. No `.artifacts/{slug}/` inputs are required — the audit reads `<instance-root>/` itself. Audit outputs are published as Gitea wiki pages under `audit/{date}/`.
@@ -201,7 +210,7 @@ No `.artifacts/{slug}/` inputs are required — the audit reads `<instance-root>
| 5 | FLOW | Pipeline Cohesion | FLOW 5.1–5.6 | Preconditions + output sections of every `SKILL.md` | | 5 | FLOW | Pipeline Cohesion | FLOW 5.1–5.6 | Preconditions + output sections of every `SKILL.md` |
| 6 | SCH | Schema Contract | SCH 6.1–6.5 | `core/schemas/*.json` + skills that reference them | | 6 | SCH | Schema Contract | SCH 6.1–6.5 | `core/schemas/*.json` + skills that reference them |
| 7 | DUP | Duplication & Drift | DUP 7.1–7.4 | ALL `SKILL.md` + ALL `checklists/*.md` | | 7 | DUP | Duplication & Drift | DUP 7.1–7.4 | ALL `SKILL.md` + ALL `checklists/*.md` |
| 8 | STD | Audit Standards (ISO/IEEE) | STD 8.1–8.7 | `review-*` skills, `review-artifact` (target: `audit-process`) itself | | 8 | STD | Audit Standards (ISO/IEEE) | STD 8.1–8.8 | `review-*` skills, `review-artifact` (target: `audit-process`) itself |
| 9 | AGT | AGENTS.md Conformance | AGT 9.1–9.5 | ALL `SKILL.md` + `AGENTS.md` | | 9 | AGT | AGENTS.md Conformance | AGT 9.1–9.5 | ALL `SKILL.md` + `AGENTS.md` |
| 10 | TRC | Traceability | TRC 10.1–10.5 | `review-*` skills, schemas, status artifacts | | 10 | TRC | Traceability | TRC 10.1–10.5 | `review-*` skills, schemas, status artifacts |
@@ -357,9 +366,9 @@ from `Size/*` labels.
| D1 | 1 | `all` | | D1 | 1 | `all` |
| D2 | 3 | `TOPO:1 REQMAP:1 RELEASE:1` | | D2 | 3 | `TOPO:1 REQMAP:1 RELEASE:1` |
| D3 | 5 | `TOPO:2 REQMAP:2 RELEASE:1` | | D3 | 5 | `TOPO:2 REQMAP:2 RELEASE:1` |
| D4 | 5 ([org-internal #3061] cap) | `TOPO:2 REQMAP:2 RELEASE:1` | | D4 | 5 ([TT-3061] cap) | `TOPO:2 REQMAP:2 RELEASE:1` |
> **D4 cap ([org-internal #3061])**: D4 keeps its own rounds budget (4) but its fanout is > **D4 cap ([TT-3061])**: D4 keeps its own rounds budget (4) but its fanout is
> capped at D3 level (5 reviewers) — under the 3-dimension + checklist-bound > capped at D3 level (5 reviewers) — under the 3-dimension + checklist-bound
> review the marginal coverage of 9 reviewers was redundancy, and round > review the marginal coverage of 9 reviewers was redundancy, and round
> iteration is the backstop. > iteration is the backstop.
@@ -381,7 +390,7 @@ file (concurrent write race):
`core/schemas/reviewer-output.schema.json`. Finding ids inside slot `core/schemas/reviewer-output.schema.json`. Finding ids inside slot
files MUST be slot-prefixed (`{DIM}R{k}-F{NNN}`, e.g. `TOPOR1-F001`) so ids files MUST be slot-prefixed (`{DIM}R{k}-F{NNN}`, e.g. `TOPOR1-F001`) so ids
stay unique across a dimension's slot files. This preserves per-reviewer stay unique across a dimension's slot files. This preserves per-reviewer
attribution (retrospective overlap analysis, [org-internal #2996] step ①a) and makes the attribution (retrospective overlap analysis, [TT-2996] step ①a) and makes the
write race impossible by construction. write race impossible by construction.
- Synthesis input for a dimension = ALL `findings-{DIM}*.json` in the round - Synthesis input for a dimension = ALL `findings-{DIM}*.json` in the round
directory — the synthesizer already globs every `findings-*.json`; the slot directory — the synthesizer already globs every `findings-*.json`; the slot
+27 -253
View File
@@ -5,7 +5,7 @@ description: >
ticket under a DAG-routed parent) against the node spec + frozen ticket under a DAG-routed parent) against the node spec + frozen
cross-session contracts of the frozen DAG copy (`{epic-slug}/dag`), or in cross-session contracts of the frozen DAG copy (`{epic-slug}/dag`), or in
standalone-bugfix mode without a design baseline. (The legacy standalone-bugfix mode without a design baseline. (The legacy
approved-design pipeline mode was archived 2026-08-21, [org-internal #3072] phase 3.) Spawns up to 10 parallel Explorer reviewers (risk-tier scaled; approved-design pipeline mode was archived 2026-08-21, [TT-3072] phase 3.) Spawns up to 10 parallel Explorer reviewers (risk-tier scaled;
fewer in standalone-bugfix mode where DGN may be skipped) against core/checklists/code-review.md, synthesizes fewer in standalone-bugfix mode where DGN may be skipped) against core/checklists/code-review.md, synthesizes
findings with a Worker Synthesizer (the main-session Orchestrator aggregates), and iterates with a Worker developer until findings with a Worker Synthesizer (the main-session Orchestrator aggregates), and iterates with a Worker developer until
convergence. convergence.
@@ -57,7 +57,7 @@ abstract best practices.
Before launching this review, confirm: Before launching this review, confirm:
> **Legacy pipeline preconditions retired ([org-internal #3072] phase 3, 2026-08-21)**: the > **Legacy pipeline preconditions retired ([TT-3072] phase 3, 2026-08-21)**: the
> design-document / design-space-convergence / iteration-plan-convergence > design-document / design-space-convergence / iteration-plan-convergence
> checks that used to head this list belonged to the archived legacy pipeline > checks that used to head this list belonged to the archived legacy pipeline
> (`design` / `plan-iterations` skills — `<instance-root>/archive/`). Live entry > (`design` / `plan-iterations` skills — `<instance-root>/archive/`). Live entry
@@ -66,7 +66,7 @@ Before launching this review, confirm:
> runs' design pages stay readable via `_shared/gitea-read-patterns.md`. > runs' design pages stay readable via `_shared/gitea-read-patterns.md`.
- [ ] Code files to review are specified (list of file paths or use `git diff`). - [ ] Code files to review are specified (list of file paths or use `git diff`).
- [ ] Mechanical-green gate PASSED (L0-enforced, [org-internal #2598]): run - [ ] Mechanical-green gate PASSED (L0-enforced, [TT-2598]): run
`bun core/skills/review-code/scripts/precondition-gate.ts {slug}` — `bun core/skills/review-code/scripts/precondition-gate.ts {slug}` —
CI-aligned checks (`bun oxlint --deny-warnings` + `bun turbo typecheck` CI-aligned checks (`bun oxlint --deny-warnings` + `bun turbo typecheck`
+ `test:changed` with `CI=true TEST_SHARDS=3`, mirroring ci.yml). + `test:changed` with `CI=true TEST_SHARDS=3`, mirroring ci.yml).
@@ -83,7 +83,7 @@ Before launching this review, confirm:
- [ ] 跨阶段门控清单: `core/checklists/pipeline-gate.md` is accessible and - [ ] 跨阶段门控清单: `core/checklists/pipeline-gate.md` is accessible and
its Upstream Review Convergence section has been confirmed item by item. its Upstream Review Convergence section has been confirmed item by item.
**Kind/MVP graduation chokepoint ([org-internal #3061])**: when this skill is invoked ad hoc **Kind/MVP graduation chokepoint ([TT-3061])**: when this skill is invoked ad hoc
on a `Kind/MVP` ticket's changes (no mode, no pipeline), the mechanical-green on a `Kind/MVP` ticket's changes (no mode, no pipeline), the mechanical-green
gate applies, and the Orchestrator additionally checks the diff for gate applies, and the Orchestrator additionally checks the diff for
**graduation triggers** — changes crossing ≥2 modules, touching a shared **graduation triggers** — changes crossing ≥2 modules, touching a shared
@@ -110,9 +110,9 @@ no design doc exists at `.artifacts/{slug}/design/index.md`(存量只读,不
**Weakened preconditions** for standalone mode: **Weakened preconditions** for standalone mode:
- Design doc existence → NOT required (the legacy design pipeline is archived, [org-internal #3072] phase 3). - Design doc existence → NOT required (the legacy design pipeline is archived, [TT-3072] phase 3).
- **Instead require**: `.artifacts/{slug}/repro-notes.md`(存量只读,不迁移;Gitea 等效:wiki page `{slug}/repro-notes`,`_shared/gitea-read-patterns.md` Pattern 1)exists (bugfix Phase 1-2 output: reproduction steps + root cause) OR `.artifacts/{slug}/impl-notes.md`(存量只读,不迁移;Gitea 等效:wiki page `{slug}/impl-notes`,`_shared/gitea-read-patterns.md` Pattern 1)exists (post-fix behavior contract). - **Instead require**: `.artifacts/{slug}/repro-notes.md`(存量只读,不迁移;Gitea 等效:wiki page `{slug}/repro-notes`,`_shared/gitea-read-patterns.md` Pattern 1)exists (bugfix Phase 1-2 output: reproduction steps + root cause) OR `.artifacts/{slug}/impl-notes.md`(存量只读,不迁移;Gitea 等效:wiki page `{slug}/impl-notes`,`_shared/gitea-read-patterns.md` Pattern 1)exists (post-fix behavior contract).
- All other Preconditions (code files specified, mechanical-green gate green ([org-internal #2598]), checklist accessible) STILL APPLY. - All other Preconditions (code files specified, mechanical-green gate green ([TT-2598]), checklist accessible) STILL APPLY.
- The `core/checklists/pipeline-gate.md` cross-stage gate (Upstream Review Convergence section) → NOT required; the bugfix-specific Pre-Design Falsification Gate section still applies if relevant. - The `core/checklists/pipeline-gate.md` cross-stage gate (Upstream Review Convergence section) → NOT required; the bugfix-specific Pre-Design Falsification Gate section still applies if relevant.
**DGN dimension handling**: In standalone-bugfix mode, the DGN (Design Compliance & Dependencies) reviewer is SKIPPED because there is no design to comply with. The Orchestrator dispatches 9 reviewers (all 10 dimensions except DGN). **DGN dimension handling**: In standalone-bugfix mode, the DGN (Design Compliance & Dependencies) reviewer is SKIPPED because there is no design to comply with. The Orchestrator dispatches 9 reviewers (all 10 dimensions except DGN).
@@ -120,7 +120,7 @@ no design doc exists at `.artifacts/{slug}/design/index.md`(存量只读,不
**What standalone bugfix review focuses on**: code correctness, error handling & compatibility (COR), regression coverage (TST), security (SEC), performance (PERF), style & conventions (STY), database & data (DBT), accessibility & browser compatibility (A11Y), documentation (DOC), traceability (TRC) — everything that does not depend on a design baseline. **What standalone bugfix review focuses on**: code correctness, error handling & compatibility (COR), regression coverage (TST), security (SEC), performance (PERF), style & conventions (STY), database & data (DBT), accessibility & browser compatibility (A11Y), documentation (DOC), traceability (TRC) — everything that does not depend on a design baseline.
**Historical**: the legacy pipeline mode (design doc + design-space/plan **Historical**: the legacy pipeline mode (design doc + design-space/plan
review convergence as preconditions) was archived 2026-08-21 ([org-internal #3072] phase 3). review convergence as preconditions) was archived 2026-08-21 ([TT-3072] phase 3).
Historical design pages remain readable via `_shared/gitea-read-patterns.md`. Historical design pages remain readable via `_shared/gitea-read-patterns.md`.
### DAG Task Mode ### DAG Task Mode
@@ -147,7 +147,7 @@ table and implement's §"DAG-mode input path"):
| Iteration-plan review converged (`--stage iteration-plan`) | REMOVED (DAG has no plan review; the single review-dag gate replaces both) | | Iteration-plan review converged (`--stage iteration-plan`) | REMOVED (DAG has no plan review; the single review-dag gate replaces both) |
| `slug` matches the design slug | N/A (review is scoped to the node ticket; run slug = `{epic-slug}-task-{node-id}` — the same node-task run namespace verify's task mode archives to — so review outputs are node-scoped and never clobber sibling nodes' reports. Note: this namespace covers review + verify runs only; the node's implement report below lives in the Epic run workspace `{epic-slug}/workers/` — implement worker runs keep the Epic run slug (implement §Preconditions: "DAG: `{epic-slug}`"), a different run from this review run) | | `slug` matches the design slug | N/A (review is scoped to the node ticket; run slug = `{epic-slug}-task-{node-id}` — the same node-task run namespace verify's task mode archives to — so review outputs are node-scoped and never clobber sibling nodes' reports. Note: this namespace covers review + verify runs only; the node's implement report below lives in the Epic run workspace `{epic-slug}/workers/` — implement worker runs keep the Epic run slug (implement §Preconditions: "DAG: `{epic-slug}`"), a different run from this review run) |
| `core/checklists/pipeline-gate.md` Upstream Review Convergence | NOT required — the review-dag convergence check above stands in its place | | `core/checklists/pipeline-gate.md` Upstream Review Convergence | NOT required — the review-dag convergence check above stands in its place |
| All other preconditions (code files specified, mechanical-green gate green ([org-internal #2598]), checklist accessible) | KEEP — unconditional; plus the implement report (AC → test traceability) present — Tier 1 at `<runs-root>/{epic-slug}/workers/{node-id}-worker-{seq}.md` (implement Phase 5 persistence; `{chunk-id}` = the node id) | | All other preconditions (code files specified, mechanical-green gate green ([TT-2598]), checklist accessible) | KEEP — unconditional; plus the implement report (AC → test traceability) present — Tier 1 at `<runs-root>/{epic-slug}/workers/{node-id}-worker-{seq}.md` (implement Phase 5 persistence; `{chunk-id}` = the node id) |
The `{BASELINE_SECTION}` for DAG-task mode uses the node spec + cross-session The `{BASELINE_SECTION}` for DAG-task mode uses the node spec + cross-session
edge contracts from `{epic-slug}/dag` instead of the design index; the 5-Check edge contracts from `{epic-slug}/dag` instead of the design index; the 5-Check
@@ -228,7 +228,7 @@ file is a test file.
- Design-space review convergence → NOT required. - Design-space review convergence → NOT required.
- Iteration-plan review convergence → NOT required. - Iteration-plan review convergence → NOT required.
- All Preconditions from the pipeline checklist are bypassed. - All Preconditions from the pipeline checklist are bypassed.
- Only requires: the mechanical-green gate ([org-internal #2598]) — same script as the full - Only requires: the mechanical-green gate ([TT-2598]) — same script as the full
mode; on a test-only changeset `test:changed` selects exactly the changed mode; on a test-only changeset `test:changed` selects exactly the changed
tests, so the gate cost stays proportional to the diff. tests, so the gate cost stays proportional to the diff.
@@ -263,7 +263,7 @@ fall back to the appropriate full mode (pipeline or standalone-bugfix).
## Agent Roles ## Agent Roles
> **Progressive disclosure ([org-internal #3722])**: when dispatching a Reviewer / > **Progressive disclosure ([TT-3722])**: when dispatching a Reviewer /
> Synthesizer / Developer scoped to one phase, pass > Synthesizer / Developer scoped to one phase, pass
> `skills: ["review-code:phase-a"]` (preamble — incl. dimensions, JSON > `skills: ["review-code:phase-a"]` (preamble — incl. dimensions, JSON
> schema, prompt template — plus that phase only) instead of the full body; > schema, prompt template — plus that phase only) instead of the full body;
@@ -338,7 +338,7 @@ audit (`review-artifact` targets):
| `core/schemas/synthesis.schema.json` | Orchestrator round synthesis (Tier 2 — synthesis comment) | | `core/schemas/synthesis.schema.json` | Orchestrator round synthesis (Tier 2 — synthesis comment) |
| `core/schemas/review-status.schema.json` | Review lifecycle tracking | | `core/schemas/review-status.schema.json` | Review lifecycle tracking |
> **Findings sink: `tier1-local`** ([org-internal #1988]). `review-code` writes raw > **Findings sink: `tier1-local`** ([TT-1988]). `review-code` writes raw
> per-dimension findings to Tier 1 local files (`<runs-root>/{slug}/reviews/code/`), > per-dimension findings to Tier 1 local files (`<runs-root>/{slug}/reviews/code/`),
> not Gitea issue comments. The synthesis comment + commit status stay Tier 2. > not Gitea issue comments. The synthesis comment + commit status stay Tier 2.
> See `_shared/review-pipeline-phases.md` "Output model — two findings sinks" > See `_shared/review-pipeline-phases.md` "Output model — two findings sinks"
@@ -362,7 +362,7 @@ table).
- `{REVIEWER_ROLE}`: code reviewer - `{REVIEWER_ROLE}`: code reviewer
- `{BASELINE_SECTION}`: - `{BASELINE_SECTION}`:
**Legacy pipeline mode** (archived 2026-08-21, [org-internal #3072] phase 3 — the design **Legacy pipeline mode** (archived 2026-08-21, [TT-3072] phase 3 — the design
doc at `{slug}/03-design-*` / `{slug}/02-03-req-design` it read is doc at `{slug}/03-design-*` / `{slug}/02-03-req-design` it read is
historical; live modes use the two baselines below): historical; live modes use the two baselines below):
@@ -464,7 +464,7 @@ table).
When invoked from the `implement` skill in bugfix mode (caller passes When invoked from the `implement` skill in bugfix mode (caller passes
`mode: "standalone-bugfix"` — the legacy "detect absence of a design doc" `mode: "standalone-bugfix"` — the legacy "detect absence of a design doc"
fallback is retired with the design pipeline, [org-internal #3072] phase 3): fallback is retired with the design pipeline, [TT-3072] phase 3):
1. The Orchestrator dispatches **9 reviewers** (all 10 dimensions **except DGN** — Design Compliance & Dependencies), because there is no design baseline to audit compliance against. 1. The Orchestrator dispatches **9 reviewers** (all 10 dimensions **except DGN** — Design Compliance & Dependencies), because there is no design baseline to audit compliance against.
2. For any dimension that would normally receive design reference files (COR, DGN, SEC, PERF, TST, DBT, A11Y, DOC, TRC), substitute the bugfix baseline docs: 2. For any dimension that would normally receive design reference files (COR, DGN, SEC, PERF, TST, DBT, A11Y, DOC, TRC), substitute the bugfix baseline docs:
@@ -480,7 +480,7 @@ fallback is retired with the design pipeline, [org-internal #3072] phase 3):
``` ```
5. The `{CONTRADICTION_RULE}` is weakened: code that contradicts repro-notes/impl-notes is a MAJOR — there is no design to elevate to BLOCKER. 5. The `{CONTRADICTION_RULE}` is weakened: code that contradicts repro-notes/impl-notes is a MAJOR — there is no design to elevate to BLOCKER.
6. All other Phase A dispatch rules (reviewer comment posting, commit status, reviewer prompt template, temperature, permissions, worktree-path rule) apply unchanged. 6. All other Phase A dispatch rules (reviewer comment posting, commit status, reviewer prompt template, temperature, permissions, worktree-path rule) apply unchanged.
7. Efficiency optimization (round 2+, [org-internal #2598]): follows the shared Phase D rule (`_shared/review-pipeline-phases.md` Phase D "Efficiency optimization") with no standalone-mode deviation — partial re-dispatch, full sweep every 2 rounds, delta-scoped reviewer input. 7. Efficiency optimization (round 2+, [TT-2598]): follows the shared Phase D rule (`_shared/review-pipeline-phases.md` Phase D "Efficiency optimization") with no standalone-mode deviation — partial re-dispatch, full sweep every 2 rounds, delta-scoped reviewer input.
**Orchestrator actions**: **Orchestrator actions**:
@@ -498,7 +498,7 @@ fallback is retired with the design pipeline, [org-internal #3072] phase 3):
2. Initialize or update review status by posting a commit status via `POST /api/v1/repos/Octopus/octopus/statuses/{sha}` (`_shared/gitea-write-patterns.md` Pattern 8) with context `pipeline/review-code`. The commit-status payload carries `state` and `description`; the full review lifecycle state is documented in `core/schemas/review-status.schema.json` and tracked by the `octopus review status` CLI. 2. Initialize or update review status by posting a commit status via `POST /api/v1/repos/Octopus/octopus/statuses/{sha}` (`_shared/gitea-write-patterns.md` Pattern 8) with context `pipeline/review-code`. The commit-status payload carries `state` and `description`; the full review lifecycle state is documented in `core/schemas/review-status.schema.json` and tracked by the `octopus review status` CLI.
2.5. **Mechanical-green gate (mandatory, [org-internal #2598])** — before spawning ANY reviewer, 2.5. **Mechanical-green gate (mandatory, [TT-2598])** — before spawning ANY reviewer,
run `bun core/skills/review-code/scripts/precondition-gate.ts {slug} --round {N}` run `bun core/skills/review-code/scripts/precondition-gate.ts {slug} --round {N}`
from the worktree root. Exit 0 → continue to step 3. Exit 1 → the script has from the worktree root. Exit 0 → continue to step 3. Exit 1 → the script has
appended a PRECONDITION-BLOCK record (Tier 1, appended a PRECONDITION-BLOCK record (Tier 1,
@@ -516,7 +516,7 @@ fallback is retired with the design pipeline, [org-internal #3072] phase 3):
3. Spawn **all reviewers in parallel** (10 in pipeline mode at Large tier; fewer at Small/Medium tiers; DGN skipped in standalone-bugfix mode). Each reviewer receives: 3. Spawn **all reviewers in parallel** (10 in pipeline mode at Large tier; fewer at Small/Medium tiers; DGN skipped in standalone-bugfix mode). Each reviewer receives:
- The standardized prompt (above) with dimension-specific values filled in. - The standardized prompt (above) with dimension-specific values filled in.
- For round ≥ 2 ([org-internal #2598] delta scoping): `{FILE_SECTIONS}` lists ONLY the - For round ≥ 2 ([TT-2598] delta scoping): `{FILE_SECTIONS}` lists ONLY the
files revised since the previous round plus their 3–5 convention-comparison files revised since the previous round plus their 3–5 convention-comparison
neighbors — not the round-1 full file set. Round 1 keeps the full set. neighbors — not the round-1 full file set. Round 1 keeps the full set.
- Agent type: Explorer. - Agent type: Explorer.
@@ -607,7 +607,7 @@ fallback is retired with the design pipeline, [org-internal #3072] phase 3):
- Updates review status by posting a commit status via `POST /api/v1/repos/Octopus/octopus/statuses/{sha}` (`_shared/gitea-write-patterns.md` Pattern 8)with context `pipeline/review-code`. - Updates review status by posting a commit status via `POST /api/v1/repos/Octopus/octopus/statuses/{sha}` (`_shared/gitea-write-patterns.md` Pattern 8)with context `pipeline/review-code`.
- Persists its return summary to - Persists its return summary to
`<runs-root>/{slug}/reviews/code/round{N}/synthesis-return.md` (Tier 1, `<runs-root>/{slug}/reviews/code/round{N}/synthesis-return.md` (Tier 1,
worker-report persistence [org-internal #2847] — see worker-report persistence [TT-2847] — see
`_shared/worker-report-persistence.md`) BEFORE returning, and registers `_shared/worker-report-persistence.md`) BEFORE returning, and registers
the `index.json` row (type `other`, schema null, stage `review-code`, the `index.json` row (type `other`, schema null, stage `review-code`,
produced_by `Synthesizer`). The persisted copy is the report of record — produced_by `Synthesizer`). The persisted copy is the report of record —
@@ -633,240 +633,14 @@ fallback is retired with the design pipeline, [org-internal #3072] phase 3):
--- ---
<!-- section:phase-c --> <!-- section:phase-c -->
## Phase C — Developer Revision ### Phase C+D — Developer Revision & Re-review Loop — see `reference/revision-loop.md`
If `overall_verdict` is PASS, skip to Phase E. > Phase C (Developer revision: task-file preparation, revision survival via
> `task_id` resume, convergence tracking) and Phase D (re-review loop until
> convergence or round budget exhaustion) live in
> `reference/revision-loop.md`. Read it when `overall_verdict` is not PASS.
> On PASS, skip both phases and proceed to Phase E.
Otherwise:
**Orchestrator actions**:
1. Prepare the Developer's input as a structured task file,
created as a wiki page via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1)with page_name `{slug}/reviews/code/round{N}/task-developer`.
This file must contain:
- Paths to all code files that need revision.
- Reference to the synthesis comment on the ticket (posted via `工单评论 API(见 TERMINOLOGY)` in Phase B — Tier 2).
- References to the Tier 1 finding files for dimensions that have FAIL or WARN
verdicts (`<runs-root>/{slug}/reviews/code/round{N}/findings-{DIMENSION_CODE}.json`).
- The Developer MUST NOT receive the full text of all reviewer findings
inline — use finding-file path references only to avoid context explosion.
- Convergence status: blockers/majors remaining vs. previous round.
- **Revision survival ([org-internal #2601]) — primary path**: the task tool's completion
output includes a `task_id`; passing it back resumes the SAME Developer
subagent session instead of creating a fresh one. Round 1: persist the
returned `task_id` with the round's working-notes entry (it must survive
round-boundary compaction). Round ≥ 2: dispatch with `task_id` set to the
previous revision round's — the Developer continues in-session with its
prior diff/context; the round's task page then carries only the findings
delta, not a full re-derivation. Reviewers are NEVER resumed — per-round
freshness is their independence.
- **Revision survival — fallback** (task_id lost to compaction before it
was persisted): prepend the current `<runs-root>/{slug}/working-notes.md`
content (run narrative memory — prior decisions, dead ends, reviewer
feedback from earlier rounds) and reference the previous round's revision
summary (`{slug}/reviews/code/round{N-1}/revision-summary`), stating
explicitly that this revises code a prior round already wrote — do NOT
re-read the full design/acceptance artifacts unless a finding requires
them.
2. Spawn the Developer (Worker) with the prompt
template at `core/skills/_shared/review-revision-prompt.md`, substituting:
- `{ROLE}`: Developer
- `{TASK_FILE}`: task-developer
- `{REVISION_SCOPE}`: Apply the Developer Revision Protocol (see Protocol
subsection below) — evaluate each finding against codebase reality:
Explorer reviewers are automated LLM sub-agents that can hallucinate
citations, misapply rules, or miss design context. Verify cited code
exists, the rule applies, and the fix does not break existing
functionality. WAIVE technically-incorrect findings with justification
(`WAIVED-{finding-id}` → one-line reason; canonical definition of the
`WAIVED-{id}` convention, incl. the round-2+ cosmetic-MINOR waiver
rule: `_shared/review-revision-prompt.md`). Revise code minimally and
surgically — do NOT refactor unrelated code or introduce new behavior.
- `{RESOLUTION_RULE}`: Do NOT silently deviate from the approved baseline
(DAG task mode: the node spec + frozen cross-session contracts in
`{epic-slug}/dag`; the legacy `{slug}/03-design-*` baseline is archived
historical, [org-internal #3072] phase 3). If a finding exposes a design flaw, mark it
as deferred with justification and suggest a design amendment — do not
change the code against the baseline.
- `{COSMETIC_MINOR_EXAMPLES}`: naming, comments, dead code, import
ordering, style
- `{WAIVED_EXAMPLE}`: `WAIVED-COR-R2-001`
- `{CHECKLIST_REF}`: `core/checklists/code-review.md`
- `{FILES_MODIFIED_LINE}`: {list}
- `{RETURN_FILE}`:
`<runs-root>/{slug}/reviews/code/round{N}/revision-return.md`
(Tier 1 return persistence — [org-internal #2847],
`_shared/worker-report-persistence.md`)
3. The Developer revises the code files in place. The Developer creates a
revision summary as a wiki page via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1)with page_name `{slug}/reviews/code/round{N}/revision-summary`,
and persists its final return summary to
`<runs-root>/{slug}/reviews/code/round{N}/revision-return.md` (Tier 1,
worker-report persistence [org-internal #2847] — see
`_shared/worker-report-persistence.md`) BEFORE returning. If the
completion notification is lost, the Orchestrator recovers the revision
outcome from the persisted return (wiki page for the full summary,
Tier 1 file for the conclusion of record).
4. **Pre-handoff gate** — before reporting completion, the Developer MUST run
the same mechanical gate the Orchestrator will re-run at Phase D re-entry
(the tree-fingerprint cache turns the re-run into a cache hit — one real
execution per tree state, no double-paying):
- Run `bun core/skills/review-code/scripts/precondition-gate.ts {slug} --round {N}`
from the worktree root (oxlint + typecheck + `test:changed`, CI-aligned —
`bun run test:parallel` is verify's job, not a per-revision
requirement ([org-internal #2598])).
- Exit 0 required; a new test failure, lint error, or type error introduced
by the revision must be fixed before the Orchestrator proceeds to Phase D.
- Report the gate's per-check results in the revision summary.
---
### Phase C — Developer Revision: Protocol
The Developer applies this cognitive protocol before implementing any finding.
**Core principle:** reviewer findings are claims to evaluate, not orders to
execute. Verify before implementing. Technical correctness over performative
agreement.
#### Response Pattern
1. **READ** — Load every FAIL/WARN dimension finding file
(`<runs-root>/{slug}/reviews/code/round{N}/findings-{DIMENSION_CODE}.json`,
Tier 1 local). Do not react item-by-item.
2. **UNDERSTAND** — Restate each finding's requirement in your own words.
If you cannot, the finding is unclear — see STOP rule below.
3. **VERIFY** — Check the finding against codebase reality: does the cited
code exist at the given file:line? Does the cited rule apply?
4. **EVALUATE** — Is the finding technically correct for THIS codebase?
Does the proposed fix break existing functionality? Does it conflict
with the approved baseline (DAG task mode: the node spec + contracts in
`{epic-slug}/dag`)?
5. **RESPOND** — Fix it (correct), WAIVE it (`WAIVED-{finding-id}` →
one-line reason), or flag it (unclear / design-level question).
6. **IMPLEMENT** — One verified finding at a time, test each individually.
#### Evaluating Findings — 5-Check Gate
Before implementing any finding, run these checks:
1. **Cited code is real** — Open the file:line. Does the code exist and say
what the finding claims?
2. **Rule applies** — Does the cited checklist rule actually match this issue?
3. **Reason for current implementation** — Is the flagged behavior
intentional? Check the baseline (node spec + contracts in
`{epic-slug}/dag` for DAG task mode) for rationale.
4. **Fix does not break existing functionality** — Will the proposed change
cause a regression?
5. **Reviewer has full context** — Did the reviewer see the baseline (node
spec + acceptance criteria) and the diff context? An isolated diff review
can miss architectural intent.
```
IF a finding seems wrong:
WAIVE it: WAIVED-{finding-id} → <one-line technical reason>
IF you cannot easily verify a finding:
State the limitation in revision_summary.md and request direction.
IF a finding conflicts with the approved design:
Flag as a design-level question — do NOT silently change code against the design.
```
#### Unclear Findings — STOP Rule
```
IF any finding is unclear:
STOP — do not implement ANY finding yet.
Flag the unclear items in revision_summary.md and request clarification.
WHY: findings may be related. Partial understanding produces wrong
implementation across multiple items.
```
**Example:** The synthesis lists findings F1–F6. You understand F1, F2, F3, F6.
F4 and F5 are ambiguous about what change is expected.
- **WRONG:** implement F1, F2, F3, F6 now; ask about F4, F5 later.
- **RIGHT:** "Understand F1, F2, F3, F6. Need clarification on F4, F5 before
proceeding — they may interact with the same module."
#### YAGNI Check
```
IF a reviewer suggests "implementing this properly" (full abstraction,
generic API, configurable layer):
Check actual usage (codegraph callers / grep) BEFORE expanding scope.
IF unused: WAIVE — "No call sites found. Leaving as-is (YAGNI)."
IF used: Then implement properly.
```
#### Forbidden Responses in revision_summary.md
**NEVER** write:
- "You're absolutely right!" / "Great point!" / "Excellent catch!" — performative.
- "Thanks for catching that!" / any gratitude expression.
- "Let me implement that now" — before verification.
**INSTEAD:**
- Restate the technical requirement concisely.
- State the fix factually: `Fixed {finding-id}: <what changed> at <file:line>`.
- Just fix it and show the result in the diff.
#### Gracefully Correcting a WAIVE
If you WAIVEd a finding and were wrong:
```
"Verified {finding-id} — the reviewer is correct. My initial read missed
<reason>. Implementing now."
```
State the correction factually. No lengthy apology.
#### Implementation Order
For multi-finding revisions, after clarifying all unclear items:
1. **Blocking issues** — security, data loss, breaks existing functionality.
2. **Simple fixes** — typos, imports, naming, dead code.
3. **Complex fixes** — logic changes, refactoring within minimal-surgical scope.
Test each fix individually.
#### Rationalization-Anticipation Quick Reference
| Trap | Hold to |
|------|---------|
| "The reviewer flagged it as BLOCKER, so it must be real." | VERIFY cited code exists and rule applies before any edit. |
| "Just fix everything to avoid a re-review round." | EVALUATE each finding; WAIVE the wrong ones with reasoning. |
| "This finding looks plausible — I'll fix it without checking." | Open the file:line, confirm the behavior. |
| "I'll implement the clear findings and ask about unclear ones later." | STOP. Clarify ALL unclear items before implementing any. |
| "The reviewer wants it done 'properly' — full abstraction." | Check call sites first. If unused, WAIVE (YAGNI). |
| "I shouldn't push back — the reviewer is probably right." | Push back with technical reasoning. The diff is the acknowledgment. |
---
<!-- section:phase-d -->
## Phase D — Re-review Loop
After the Developer completes revision:
1. Increment the round counter (the Synthesizer updates the commit status in Phase B
with the new round's results).
2. Re-enter Phase A at step 2.5 — the mechanical-green gate re-runs on the
revised tree before any reviewer spawn (a red gate blocks dispatch exactly
as on round-1 entry) — then spawn the new round of reviewers against the
revised files.
**Convergence criteria**: see `core/skills/_shared/review-pipeline-phases.md` Phase D for the canonical table (stop conditions). `{MAX_ROUNDS}` is per-skill — code review binds the routing budget: **2** rounds default, **3** for high risk (a BLOCKER survived a round, or the diff touches a frozen cross-session contract) — `<instance-root>/workflow-routing.yaml` `review.max_rounds` ([org-internal #3567]). The code-review-specific addition is inheritance of the shared INFO-disposition rule. The shared Round-3 Escalation Guardrail is scoped to the `review-artifact` skill targets only and does not apply here.
**Round budget (mandatory, [org-internal #3567])**: when `current_round` reaches the budget (2; 3 for high risk) without convergence, do NOT enter another round. STOP: register every remaining BLOCKER/MAJOR finding as TD registry rows (`rules/ticket-lifecycle.md`), record the verdict (FAIL if any BLOCKER remains, else PASS — the debt is carried by the TD registry rows just registered), and close the loop. A review that cannot converge within budget is a design-level stall wearing review clothes (retro 2026-08-21 / [org-internal #3050]): in DAG task mode, map it to the DAG oversize signals (`<instance-root>/workflow-routing.yaml` `dag.size_derivation.oversize_signals`) and let the aggregator agent drive re-derivation + a `review-dag` re-run; otherwise record the design-level finding on the Epic, or open `{slug}/03-design-amendments` via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1).
**Efficiency optimization**: see `core/skills/_shared/review-pipeline-phases.md` Phase D (same rule — from round 2 onward ([org-internal #2598]), only spawn reviewers for FAIL/WARN/UNRESOLVED dimensions; full sweep every 2 rounds). Round ≥2 reviewer input is delta-scoped to the revised files + their neighbors.
<!-- inject: ../_shared/compaction-round-boundary.md -->
---
<!-- section:phase-e --> <!-- section:phase-e -->
## Phase E — Final Report & Approval ## Phase E — Final Report & Approval
@@ -912,11 +686,11 @@ After the Developer completes revision:
the findings JSONs are deleted at Tier 1 archive-at-close, so the final the findings JSONs are deleted at Tier 1 archive-at-close, so the final
report is the ONLY durable carrier of round-1 findings — retrospective report is the ONLY durable carrier of round-1 findings — retrospective
M7 (§2.9 first-round root-cause analysis) reads this table instead of M7 (§2.9 first-round root-cause analysis) reads this table instead of
relying on commit messages (retro 2026-08-21 / [org-internal #3120]). relying on commit messages (retro 2026-08-21 / [TT-3120]).
2.56. **Inline-ization — post the final round's findings as PR inline 2.56. **Inline-ization — post the final round's findings as PR inline
comments** (consumer of frozen contract comments** (consumer of frozen contract
`{epic-slug}/shared/review-inline-v1`, epic [org-internal #3533]; REQ-F-001/002/004). `{epic-slug}/shared/review-inline-v1`, epic [TT-3533]; REQ-F-001/002/004).
After the final report page exists (step 1), post the FINAL round's After the final report page exists (step 1), post the FINAL round's
findings as Gitea PR inline comments so review conclusions land findings as Gitea PR inline comments so review conclusions land
line-level on the diff. Run the runner from the repo root: line-level on the diff. Run the runner from the repo root:
@@ -980,7 +754,7 @@ After the Developer completes revision:
> THEN ask the human to approve. Approving before the reviewer is > THEN ask the human to approve. Approving before the reviewer is
> registered produces `official: false` on the approval — the gate > registered produces `official: false` on the approval — the gate
> treats the PR as unapproved and the approval must be re-done. See > treats the PR as unapproved and the approval must be re-done. See
> `_shared/review-pipeline-phases.md` Phase E step 3.5. ([org-internal #1931]: audit > `_shared/review-pipeline-phases.md` Phase E step 3.5. ([TT-1931]: audit
> R2→R3 re-loop + re-approve, ~30min wasted on exactly this ordering.) > R2→R3 re-loop + re-approve, ~30min wasted on exactly this ordering.)
``` ```
@@ -1058,7 +832,7 @@ To notify workflow completion, call the `signal_stage_done` tool.
- Legacy design path (historical note, FLOW-F001 / audit-20260901): the - Legacy design path (historical note, FLOW-F001 / audit-20260901): the
design-document precondition row formerly in the DAG task-mode table design-document precondition row formerly in the DAG task-mode table
(legacy `{slug}/03-design-index` / `{slug}/02-03-req-design` → node spec + frozen DAG (legacy `{slug}/03-design-index` / `{slug}/02-03-req-design` → node spec + frozen DAG
copy) referenced the legacy design pipeline, archived 2026-08-21 with [org-internal #3072] copy) referenced the legacy design pipeline, archived 2026-08-21 with [TT-3072]
phase 3 (see `<instance-root>/archive/skills/design/`); the live design baseline is phase 3 (see `<instance-root>/archive/skills/design/`); the live design baseline is
the node spec + cross-session edge contracts in the frozen DAG copy the node spec + cross-session edge contracts in the frozen DAG copy
`{epic-slug}/dag`. `{epic-slug}/dag`.
@@ -1,7 +1,7 @@
# Code Review Output Artifacts # Code Review Output Artifacts
> Output tree for code review artifacts. Read on-demand for reference. > Output tree for code review artifacts. Read on-demand for reference.
> Output model ([org-internal #1988] Tier 1 migration): Tier 1 local files (raw dimension findings) + Tier 2 wiki pages (task prompts, revision summaries, final reports) + Tier 2 synthesis comment. Status tracking via commit status `pipeline/review-code`. > Output model ([TT-1988] Tier 1 migration): Tier 1 local files (raw dimension findings) + Tier 2 wiki pages (task prompts, revision summaries, final reports) + Tier 2 synthesis comment. Status tracking via commit status `pipeline/review-code`.
``` ```
<runs-root>/{slug}/reviews/code/ <runs-root>/{slug}/reviews/code/
@@ -0,0 +1,240 @@
> Extracted from review-code/SKILL.md (Phase C — Developer Revision +
> Phase D — Re-review Loop) — moved verbatim; read on-demand when
> `overall_verdict` is not PASS (skipped entirely on PASS, which jumps
> straight to Phase E).
<!-- section:phase-c -->
## Phase C — Developer Revision
If `overall_verdict` is PASS, skip to Phase E.
Otherwise:
**Orchestrator actions**:
1. Prepare the Developer's input as a structured task file,
created as a wiki page via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1)with page_name `{slug}/reviews/code/round{N}/task-developer`.
This file must contain:
- Paths to all code files that need revision.
- Reference to the synthesis comment on the ticket (posted via `工单评论 API(见 TERMINOLOGY)` in Phase B — Tier 2).
- References to the Tier 1 finding files for dimensions that have FAIL or WARN
verdicts (`<runs-root>/{slug}/reviews/code/round{N}/findings-{DIMENSION_CODE}.json`).
- The Developer MUST NOT receive the full text of all reviewer findings
inline — use finding-file path references only to avoid context explosion.
- Convergence status: blockers/majors remaining vs. previous round.
- **Revision survival ([TT-2601]) — primary path**: the task tool's completion
output includes a `task_id`; passing it back resumes the SAME Developer
subagent session instead of creating a fresh one. Round 1: persist the
returned `task_id` with the round's working-notes entry (it must survive
round-boundary compaction). Round ≥ 2: dispatch with `task_id` set to the
previous revision round's — the Developer continues in-session with its
prior diff/context; the round's task page then carries only the findings
delta, not a full re-derivation. Reviewers are NEVER resumed — per-round
freshness is their independence.
- **Revision survival — fallback** (task_id lost to compaction before it
was persisted): prepend the current `<runs-root>/{slug}/working-notes.md`
content (run narrative memory — prior decisions, dead ends, reviewer
feedback from earlier rounds) and reference the previous round's revision
summary (`{slug}/reviews/code/round{N-1}/revision-summary`), stating
explicitly that this revises code a prior round already wrote — do NOT
re-read the full design/acceptance artifacts unless a finding requires
them.
2. Spawn the Developer (Worker) with the prompt
template at `core/skills/_shared/review-revision-prompt.md`, substituting:
- `{ROLE}`: Developer
- `{TASK_FILE}`: task-developer
- `{REVISION_SCOPE}`: Apply the Developer Revision Protocol (see Protocol
subsection below) — evaluate each finding against codebase reality:
Explorer reviewers are automated LLM sub-agents that can hallucinate
citations, misapply rules, or miss design context. Verify cited code
exists, the rule applies, and the fix does not break existing
functionality. WAIVE technically-incorrect findings with justification
(`WAIVED-{finding-id}` → one-line reason; canonical definition of the
`WAIVED-{id}` convention, incl. the round-2+ cosmetic-MINOR waiver
rule: `_shared/review-revision-prompt.md`). Revise code minimally and
surgically — do NOT refactor unrelated code or introduce new behavior.
- `{RESOLUTION_RULE}`: Do NOT silently deviate from the approved baseline
(DAG task mode: the node spec + frozen cross-session contracts in
`{epic-slug}/dag`; the legacy `{slug}/03-design-*` baseline is archived
historical, [TT-3072] phase 3). If a finding exposes a design flaw, mark it
as deferred with justification and suggest a design amendment — do not
change the code against the baseline.
- `{COSMETIC_MINOR_EXAMPLES}`: naming, comments, dead code, import
ordering, style
- `{WAIVED_EXAMPLE}`: `WAIVED-COR-R2-001`
- `{CHECKLIST_REF}`: `core/checklists/code-review.md`
- `{FILES_MODIFIED_LINE}`: {list}
- `{RETURN_FILE}`:
`<runs-root>/{slug}/reviews/code/round{N}/revision-return.md`
(Tier 1 return persistence — [TT-2847],
`_shared/worker-report-persistence.md`)
3. The Developer revises the code files in place. The Developer creates a
revision summary as a wiki page via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1)with page_name `{slug}/reviews/code/round{N}/revision-summary`,
and persists its final return summary to
`<runs-root>/{slug}/reviews/code/round{N}/revision-return.md` (Tier 1,
worker-report persistence [TT-2847] — see
`_shared/worker-report-persistence.md`) BEFORE returning. If the
completion notification is lost, the Orchestrator recovers the revision
outcome from the persisted return (wiki page for the full summary,
Tier 1 file for the conclusion of record).
4. **Pre-handoff gate** — before reporting completion, the Developer MUST run
the same mechanical gate the Orchestrator will re-run at Phase D re-entry
(the tree-fingerprint cache turns the re-run into a cache hit — one real
execution per tree state, no double-paying):
- Run `bun core/skills/review-code/scripts/precondition-gate.ts {slug} --round {N}`
from the worktree root (oxlint + typecheck + `test:changed`, CI-aligned —
`bun run test:parallel` is verify's job, not a per-revision
requirement ([TT-2598])).
- Exit 0 required; a new test failure, lint error, or type error introduced
by the revision must be fixed before the Orchestrator proceeds to Phase D.
- Report the gate's per-check results in the revision summary.
---
### Phase C — Developer Revision: Protocol
The Developer applies this cognitive protocol before implementing any finding.
**Core principle:** reviewer findings are claims to evaluate, not orders to
execute. Verify before implementing. Technical correctness over performative
agreement.
#### Response Pattern
1. **READ** — Load every FAIL/WARN dimension finding file
(`<runs-root>/{slug}/reviews/code/round{N}/findings-{DIMENSION_CODE}.json`,
Tier 1 local). Do not react item-by-item.
2. **UNDERSTAND** — Restate each finding's requirement in your own words.
If you cannot, the finding is unclear — see STOP rule below.
3. **VERIFY** — Check the finding against codebase reality: does the cited
code exist at the given file:line? Does the cited rule apply?
4. **EVALUATE** — Is the finding technically correct for THIS codebase?
Does the proposed fix break existing functionality? Does it conflict
with the approved baseline (DAG task mode: the node spec + contracts in
`{epic-slug}/dag`)?
5. **RESPOND** — Fix it (correct), WAIVE it (`WAIVED-{finding-id}` →
one-line reason), or flag it (unclear / design-level question).
6. **IMPLEMENT** — One verified finding at a time, test each individually.
#### Evaluating Findings — 5-Check Gate
Before implementing any finding, run these checks:
1. **Cited code is real** — Open the file:line. Does the code exist and say
what the finding claims?
2. **Rule applies** — Does the cited checklist rule actually match this issue?
3. **Reason for current implementation** — Is the flagged behavior
intentional? Check the baseline (node spec + contracts in
`{epic-slug}/dag` for DAG task mode) for rationale.
4. **Fix does not break existing functionality** — Will the proposed change
cause a regression?
5. **Reviewer has full context** — Did the reviewer see the baseline (node
spec + acceptance criteria) and the diff context? An isolated diff review
can miss architectural intent.
```
IF a finding seems wrong:
WAIVE it: WAIVED-{finding-id} → <one-line technical reason>
IF you cannot easily verify a finding:
State the limitation in revision_summary.md and request direction.
IF a finding conflicts with the approved design:
Flag as a design-level question — do NOT silently change code against the design.
```
#### Unclear Findings — STOP Rule
```
IF any finding is unclear:
STOP — do not implement ANY finding yet.
Flag the unclear items in revision_summary.md and request clarification.
WHY: findings may be related. Partial understanding produces wrong
implementation across multiple items.
```
**Example:** The synthesis lists findings F1–F6. You understand F1, F2, F3, F6.
F4 and F5 are ambiguous about what change is expected.
- **WRONG:** implement F1, F2, F3, F6 now; ask about F4, F5 later.
- **RIGHT:** "Understand F1, F2, F3, F6. Need clarification on F4, F5 before
proceeding — they may interact with the same module."
#### YAGNI Check
```
IF a reviewer suggests "implementing this properly" (full abstraction,
generic API, configurable layer):
Check actual usage (codegraph callers / grep) BEFORE expanding scope.
IF unused: WAIVE — "No call sites found. Leaving as-is (YAGNI)."
IF used: Then implement properly.
```
#### Forbidden Responses in revision_summary.md
**NEVER** write:
- "You're absolutely right!" / "Great point!" / "Excellent catch!" — performative.
- "Thanks for catching that!" / any gratitude expression.
- "Let me implement that now" — before verification.
**INSTEAD:**
- Restate the technical requirement concisely.
- State the fix factually: `Fixed {finding-id}: <what changed> at <file:line>`.
- Just fix it and show the result in the diff.
#### Gracefully Correcting a WAIVE
If you WAIVEd a finding and were wrong:
```
"Verified {finding-id} — the reviewer is correct. My initial read missed
<reason>. Implementing now."
```
State the correction factually. No lengthy apology.
#### Implementation Order
For multi-finding revisions, after clarifying all unclear items:
1. **Blocking issues** — security, data loss, breaks existing functionality.
2. **Simple fixes** — typos, imports, naming, dead code.
3. **Complex fixes** — logic changes, refactoring within minimal-surgical scope.
Test each fix individually.
#### Rationalization-Anticipation Quick Reference
| Trap | Hold to |
|------|---------|
| "The reviewer flagged it as BLOCKER, so it must be real." | VERIFY cited code exists and rule applies before any edit. |
| "Just fix everything to avoid a re-review round." | EVALUATE each finding; WAIVE the wrong ones with reasoning. |
| "This finding looks plausible — I'll fix it without checking." | Open the file:line, confirm the behavior. |
| "I'll implement the clear findings and ask about unclear ones later." | STOP. Clarify ALL unclear items before implementing any. |
| "The reviewer wants it done 'properly' — full abstraction." | Check call sites first. If unused, WAIVE (YAGNI). |
| "I shouldn't push back — the reviewer is probably right." | Push back with technical reasoning. The diff is the acknowledgment. |
---
<!-- section:phase-d -->
## Phase D — Re-review Loop
After the Developer completes revision:
1. Increment the round counter (the Synthesizer updates the commit status in Phase B
with the new round's results).
2. Re-enter Phase A at step 2.5 — the mechanical-green gate re-runs on the
revised tree before any reviewer spawn (a red gate blocks dispatch exactly
as on round-1 entry) — then spawn the new round of reviewers against the
revised files.
**Convergence criteria**: see `core/skills/_shared/review-pipeline-phases.md` Phase D for the canonical table (stop conditions). `{MAX_ROUNDS}` is per-skill — code review binds the routing budget: **2** rounds default, **3** for high risk (a BLOCKER survived a round, or the diff touches a frozen cross-session contract) — `<instance-root>/workflow-routing.yaml` `review.max_rounds` ([TT-3567]). The code-review-specific addition is inheritance of the shared INFO-disposition rule. The shared Round-3 Escalation Guardrail is scoped to the `review-artifact` skill targets only and does not apply here.
**Round budget (mandatory, [TT-3567])**: when `current_round` reaches the budget (2; 3 for high risk) without convergence, do NOT enter another round. STOP: register every remaining BLOCKER/MAJOR finding as TD registry rows (`rules/ticket-lifecycle.md`), record the verdict with the shared three-tier ladder (`core/schemas/synthesis.schema.json` `overall_verdict` + `core/skills/_shared/review-orchestrator-rules.md` rule 3): FAIL if any BLOCKER or FAIL dimension remains, else WARN, PASS only if every remaining dimension is PASS ([TT-4786]: the prior binary "else PASS" wording silently upgraded WARN-eligible outcomes to PASS), and close the loop. The debt is carried by the TD registry rows just registered, not by the recorded verdict. A review that cannot converge within budget is a design-level stall wearing review clothes (retro 2026-08-21 / [TT-3050]): in DAG task mode, map it to the DAG oversize signals (`<instance-root>/workflow-routing.yaml` `dag.size_derivation.oversize_signals`) and let the aggregator agent drive re-derivation + a `review-dag` re-run; otherwise record the design-level finding on the Epic, or open `{slug}/03-design-amendments` via `wiki 读写 API(见 TERMINOLOGY)` (`_shared/gitea-write-patterns.md` Pattern 1).
**Efficiency optimization**: see `core/skills/_shared/review-pipeline-phases.md` Phase D (same rule — from round 2 onward ([TT-2598]), only spawn reviewers for FAIL/WARN/UNRESOLVED dimensions; full sweep every 2 rounds). Round ≥2 reviewer input is delta-scoped to the revised files + their neighbors.
<!-- inject: ../_shared/compaction-round-boundary.md -->
---
+26 -674
View File
@@ -60,10 +60,10 @@ digraph verify {
## Agent Role ## Agent Role
> **Progressive disclosure ([org-internal #3722], [org-internal #3734], [org-internal #3745])**: when dispatching a Verifier > **Progressive disclosure ([TT-3722], [TT-3734], [TT-3745])**: when dispatching a Verifier
> scoped to one phase, pass `skills: ["verify:phase-2"]` (preamble + that > scoped to one phase, pass `skills: ["verify:phase-2"]` (preamble + that
> phase only) instead of the full body; multi-phase dispatches may union. > phase only) instead of the full body; multi-phase dispatches may union.
> Phase 5 is subdivided ([org-internal #3734]): `phase-5` covers the report template only; > Phase 5 is subdivided ([TT-3734]): `phase-5` covers the report template only;
> each mandatory filing subsection carries its own marker (`phase-5.5` tech > each mandatory filing subsection carries its own marker (`phase-5.5` tech
> debt, `phase-5.55` baseline failures, `phase-5.56` flaky tests, > debt, `phase-5.55` baseline failures, `phase-5.56` flaky tests,
> `phase-5.6` checklist sync, `phase-5.7` CI sync). Dispatch recipes: > `phase-5.6` checklist sync, `phase-5.7` CI sync). Dispatch recipes:
@@ -71,7 +71,7 @@ digraph verify {
> / `phase-5.56` when baseline failures / flaky tests are present); PASS > / `phase-5.56` when baseline failures / flaky tests are present); PASS
> close-out → > close-out →
> `"verify:phase-5,phase-5.5,phase-5.55,phase-5.56,phase-5.6,phase-5.7,phase-6"`. > `"verify:phase-5,phase-5.5,phase-5.55,phase-5.56,phase-5.6,phase-5.7,phase-6"`.
> The DAG branch is separately marked ([org-internal #3745]): `phase-6` narrows to > The DAG branch is separately marked ([TT-3745]): `phase-6` narrows to
> Approval + Commit Gate, and the tail References rides `dag-branch` (same > Approval + Commit Gate, and the tail References rides `dag-branch` (same
> tail rule as review-code's phase-e). Non-DAG dispatches thereby drop the > tail rule as review-code's phase-e). Non-DAG dispatches thereby drop the
> ~175-line DAG branch; DAG milestone/task verify → union `dag-branch` onto > ~175-line DAG branch; DAG milestone/task verify → union `dag-branch` onto
@@ -155,7 +155,7 @@ Before starting verification, confirm:
node spec, its `acceptance_criteria` + `test_id` declarations, and the node spec, its `acceptance_criteria` + `test_id` declarations, and the
DoD slice. (Legacy tier rule — `{slug}/04-plan-*` wiki pages / issue DoD slice. (Legacy tier rule — `{slug}/04-plan-*` wiki pages / issue
comment, and the design-space + iteration-plan convergence checks that comment, and the design-space + iteration-plan convergence checks that
used to follow here — was archived 2026-08-21, [org-internal #3072] phase 3; historical used to follow here — was archived 2026-08-21, [TT-3072] phase 3; historical
plan/AC pages stay readable via `_shared/gitea-read-patterns.md`.) plan/AC pages stay readable via `_shared/gitea-read-patterns.md`.)
- [ ] `core/checklists/verification.md` is accessible. - [ ] `core/checklists/verification.md` is accessible.
- [ ] `slug` matches the run's slug (DAG: `{epic-slug}`). - [ ] `slug` matches the run's slug (DAG: `{epic-slug}`).
@@ -223,7 +223,7 @@ the DAG branch below for its read map):
(The legacy `Size/*`-tiered locations — `{slug}/04-plan-*`, (The legacy `Size/*`-tiered locations — `{slug}/04-plan-*`,
`{slug}/02-requirements-index`, `{slug}/02-03-req-design`, `{slug}/02-requirements-index`, `{slug}/02-03-req-design`,
`{slug}/03-design-06-non-functional-design` — were archived 2026-08-21, `{slug}/03-design-06-non-functional-design` — were archived 2026-08-21,
[org-internal #3072] phase 3; historical pages stay readable for legacy-run verification [TT-3072] phase 3; historical pages stay readable for legacy-run verification
via `_shared/gitea-read-patterns.md`.) via `_shared/gitea-read-patterns.md`.)
5. **Code review final report** — `{slug}/reviews/code/final/report` 5. **Code review final report** — `{slug}/reviews/code/final/report`
@@ -277,7 +277,7 @@ before. This section saves redundant typecheck/lint/security re-runs; it
never weakens a gate. never weakens a gate.
**Second evidence source — the review-code precondition-gate cache **Second evidence source — the review-code precondition-gate cache
(eff-gate-cache [org-internal #2598] / [org-internal #2990])**. The mechanical checks this phase would re-run (eff-gate-cache [TT-2598] / [TT-2990])**. The mechanical checks this phase would re-run
(oxlint / typecheck / `test:changed`) are exactly the precondition-gate's (oxlint / typecheck / `test:changed`) are exactly the precondition-gate's
check-set, and the gate caches GREEN results keyed on a tree fingerprint check-set, and the gate caches GREEN results keyed on a tree fingerprint
(HEAD + tracked diff + untracked contents) in (HEAD + tracked diff + untracked contents) in
@@ -394,8 +394,8 @@ For each DoD entry with verification method "Security scan":
every failing test, run it on the last known-green commit (or the base every failing test, run it on the last known-green commit (or the base
branch) in isolation. **Never use `git stash` for this** — the stash stack branch) in isolation. **Never use `git stash` for this** — the stash stack
is shared across all worktrees of this repo and a parallel session can is shared across all worktrees of this repo and a parallel session can
overwrite your entry mid-flight (issue [org-internal #1655]). Instead, use the overwrite your entry mid-flight (issue [TT-1655]). Instead, use the
lifecycle-managed scratch-worktree script ([org-internal #2790]) — it registers the lifecycle-managed scratch-worktree script ([TT-2790]) — it registers the
worktree for the sweep backstop, symlinks `node_modules` from the source worktree for the sweep backstop, symlinks `node_modules` from the source
checkout when `bun.lock` matches (dropping the per-instance cost from checkout when `bun.lock` matches (dropping the per-instance cost from
~170k inodes to ~7k), and deregisters on removal: ~170k inodes to ~7k), and deregisters on removal:
@@ -435,7 +435,7 @@ For each DoD entry with verification method "Security scan":
### 2.7 — Browser Evidence Reference Validation (UI-touching PR) ### 2.7 — Browser Evidence Reference Validation (UI-touching PR)
For DoD entries of the「UI 主张 ↔ 可复现浏览器证据」type — contract For DoD entries of the「UI 主张 ↔ 可复现浏览器证据」type — contract
`browser-evidence-4486/shared/evidence-ref-v1` (frozen 2026-09-10, [org-internal #4498]). `browser-evidence-4486/shared/evidence-ref-v1` (frozen 2026-09-10, [TT-4498]).
Applicable ONLY to UI-touching PRs (changes under `packages/app`, Applicable ONLY to UI-touching PRs (changes under `packages/app`,
`packages/ui`, or `packages/console/*` frontend surfaces): `packages/ui`, or `packages/console/*` frontend surfaces):
@@ -493,7 +493,7 @@ Browser-evidence rows (UI-touching PRs only, Phase 2.7): ✅ PASS requires a
mechanically validated, replayable pack-ref; `unregistered` / `manifest-missing` / mechanically validated, replayable pack-ref; `unregistered` / `manifest-missing` /
`manifest-corrupt` / `not-replayable` / `over-limit` references are `manifest-corrupt` / `not-replayable` / `over-limit` references are
⚠️ UNVERIFIABLE at best — the reference channel fails explicitly, never ⚠️ UNVERIFIABLE at best — the reference channel fails explicitly, never
silently green ([org-internal #4498] AC-4). silently green ([TT-4498] AC-4).
### Iteration Verdict ### Iteration Verdict
@@ -619,501 +619,20 @@ issue close) is performed later in Phase 5.6 — see
`rules/issue-checklist-sync.md` § 归档动作. `rules/issue-checklist-sync.md` § 归档动作.
<!-- section:phase-5.5 --> <!-- section:phase-5.5 -->
### Phase 5.5 — Tech Debt Registry Filing (mandatory before PASS) ### Phase 5.5–5.6 — Issue Filing Protocols (TD registry / baseline / flaky / checklist sync)
Tech debt is filed **registry-first** (`core/rules/ticket-lifecycle.md`, > The four mandatory-before-PASS filing protocols — Phase 5.5 Tech-Debt
[org-internal #3002] G1): new items become ROWS in the source ticket's `## TD 登记` comment; > registry filing (sprint-mode override), Phase 5.55 baseline-failure
an independent ticket is created only at **promotion** (claim/schedule). There > registration, Phase 5.56 flaky-test registration, Phase 5.6 issue
is no `tech-debt.md` file and no `{slug}/tech-debt` wiki page — both remain > checklist final sweep — live in `reference/issue-filing.md`. Read each at
retired. The registry preserves the three guarantees of the old > its boundary during Phase 5; PASS is blocked until all applicable filings
one-issue-per-item model: visible (the comment lives on a tracker ticket), > report completion. Phase 5.7 (CI state sync) stays inline below.
individually closeable (row-level checkbox), de-duplicated across sessions
(the TD index is stronger than title-keyword matching).
**Sprint-mode override ([org-internal #3002] G5/[org-internal #3007])**: read `filing.sprint-mode` from
`<instance-root>/workflow-routing.yaml` at the START of this phase (no caching). When
`true`, ALL severities file registry-only — registration rows are written as
normal (severity included, nothing lost) but promotion to standalone tickets
is FROZEN until the switch returns to `false`. Rationale: the 2026-08-12
sprint zeroed fix capacity while filing kept running (the 125-fragment
backlog's direct trigger); an explicit debt-side downshift beats hoping for
discipline. BF/FT phases 5.55/5.56 are NOT covered by this switch — failure
evidence must stay immediately visible. Flipping the switch is a human
decision recorded on the sprint tracker; semantics in
`rules/workflow-routing.md` §立案降档.
**Adjacency quota ([org-internal #3002] G3/[org-internal #3005])**: while collecting inputs, also check the
AREAS this iteration touched (packages/modules with commits this iteration).
If the source tickets for those areas carry applicable `## TD 登记` rows, at
least ONE row must be taken along and disposed this iteration (fixed, or
explicitly re-deferred with a reason — silence is not a disposition). Record
`consumed X / applicable Y` (or `0 applicable`) in the TD report section;
verification checklist §8.4 cross-checks it against the run's debt-quota
record (historically the roadmap's per-chunk debt-quota line). This gives debt digestion a steady capacity source tied to
touch, not to cleanup campaigns.
**Promotion quota + pull event ([org-internal #3061])**: promotion to a standalone ticket
requires (a) a **pull event** — the row's Reactivation Trigger fired (state
the observed event) OR a named claimer/schedule; "it seemed important" is not
a pull event — recorded in the promotion body's `## 拉动事件 / Pull Event`
section; and (b) the origin module's OPEN promoted-TD count is below the
quota (**default 10** — counted **per origin module**: resolve the row's
module from the ticket body's `Origin` field, then count that module's OPEN
`tech-debt` tickets; retro §2.10 reports breaches). At or above quota →
register-only until the count drops; before each Phase 5.5 promotion
re-check the owning module's count, and a row whose module is at or above
quota is NOT promoted — defer it and annotate the registry row with
`quota-held` (re-checked on the next verify run, retro 2026-08-21). A row
marked `[COLD]` by retrospective §2.10
(unclaimed >3 retro cycles) promotes only after the pull event clears the
mark.
**Collect inputs** — every tech-debt item to register this iteration:
1. Every UNVERIFIABLE row in the DoD matrix (Phase 3), with its Reactivation
Trigger.
2. Every ACCEPTED_RISK finding in the code-review final report
(`{slug}/reviews/code/final/report`), with its Recommended Reactivation
Trigger.
3. Every `[OPEN: <short-id>]` marker the Developer left in code this iteration
(per implementation checklist POST-6.2).
If the code-review final report does not exist, warn the user — ACCEPTED_RISK
items cannot be captured. This is itself a process gap that must be flagged.
**Step 1 — De-duplicate against the registry index and promoted issues.**
1. Read the source ticket's `## TD 登记` comment (create the comment if this
is its first row) and match each candidate against existing rows by
`TD-NNN` and reactivation trigger. Same-source re-reporting is the
anti-pattern this step exists to prevent (the visual-cluster incident: 18
fragments from one source under the old keyword matching).
2. Query OPEN promoted tech-debt issues for cross-source duplicates:
```
工单 API 检索(见 TERMINOLOGY)
(owner/repo 按实例绑定,labels="tech-debt", state="open")
```
**Step 2 — Assign `TD-NNN` via the ledger mutex ([org-internal #3322]).** One script call
per batch: `bash script/td-alloc.sh <count = new items> <source-slug>
[--ticket N]` returns a contiguous range from the TD allocation ledger
(append-only comments, earliest-comment-id wins; the seed comment pins the
historical floor). Split the returned range across the Step 3 rows in order.
**Any allocation — manual included — must land a `**td-alloc**` comment on
the ledger before the registry row is written; hand-computed `max + 1` is
forbidden** (the 2026-08-24 three-way collision). On exit 5 (retry
exhaustion) abort this phase's filing and retry — never hand-assign. The id is **reserved for life**: promotion reuses it, never
renumbers. Run `--check` (reconciliation) here if the last check predates
this batch.
**Step 3 — Append one registry row per new item.** Append to the source
ticket's `## TD 登记` comment (no source ticket → the owning Epic's tracker
ticket; no Epic → the standing `TD 冷存档` tracker):
```markdown
- [ ] TD-{NNN} · {UNVERIFIABLE | ACCEPTED_RISK | DEFERRED} · {HIGH | MEDIUM | LOW}
· {origin chunk-id/iter-N} — {one-line summary}
· trigger: {objectively verifiable reactivation condition — never "when ready";
if no trigger can be defined this is NOT tech debt and the iteration verdict
becomes FAIL}
```
**Step 4 — Cross-link (adapted).** The registry comment already lives on the
source issue — the source → debt navigation the old body-edit provided. When
filing went to an Epic tracker or the 冷存档 (no source ticket), reference the
originating slug in each row so the trail survives.
**Step 5 — Record the mapping in the verification report.** The report's
"Tech Debt" section records `TD-NNN → registry row` (source `#NNNN` +
`## TD 登记` comment); promoted items record `TD-NNN → #NNNN` as before.
**Promotion (认领升票) — when a row is scheduled or picked up.** Create the
independent ticket THEN, carrying the reserved `TD-NNN`:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Tech debt: {short description} (TD-{NNN})",
"body":<promotion template below>,
"labels":[tech_debt_label_id, severity_label_id]}
```
- **Severity → label** (reuse the existing exclusive Priority set):
| Severity | Label |
| -------- | ----------------- |
| HIGH | `Priority/High` |
| MEDIUM | `Priority/Medium` |
| LOW | `Priority/Low` |
- **Promotion body template** (the pre-[org-internal #3002] issue template, now used only at
promotion):
```markdown
## Parent / 父级
{#source_issue carrying the ## TD 登记 row}
## Summary
{one-paragraph description of the debt}
| Field | Value |
| -------- | ------------------------------------------- |
| TD ID | TD-{NNN} (reserved at registration) |
| Type | {UNVERIFIABLE \| ACCEPTED_RISK \| DEFERRED} |
| Origin | {chunk-id/iter-N/phase or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
## Reactivation Trigger
{from the registry row}
## 拉动事件 / Pull Event
{trigger fired: {observed event} | claimed by {who} for {when}}
## Acceptance Criteria (how to close this issue)
- [ ] {specific action that resolves the debt}
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
- Code review report: `{slug}/reviews/code/final/report` (if ACCEPTED_RISK)
```
- After creating the promoted ticket: tick the registry row (`- [x]`) and
append `→ #NNNN` to it.
If no new tech-debt items were found this iteration, the phase is a no-op —
record "0 tech-debt items" in the report and proceed.
<!-- section:phase-5.55 -->
### Phase 5.55 — Baseline-Failure Issue Registration (mandatory before PASS when pre-existing failures exist)
Pre-existing test failures (BF) are tracked as **root-cause family umbrella
tickets** (`core/rules/ticket-lifecycle.md`, [org-internal #3002] G1; precedents [org-internal #2585]
umbrella + [org-internal #2925] cluster) — one `BF-NNN` ticket per failure-signature family,
labeled `baseline-failure`, with each occurrence's evidence attached as
comments. There is no `baseline-failures.md` file and no
`{slug}/baseline-failures` wiki page. A pre-existing failure does not block
the iteration that _discovered_ it (it pre-dates that work), but it MUST be
filed against (or into) a family; an un-filed baseline failure is a process
gap and the iteration is NOT Done.
**Birth triage SLA ([org-internal #3061])**: a BF umbrella is born with `Kind/Bug` (it IS a
bug — of the baseline) and must be triaged the SAME DAY it is filed:
assigned, scheduled, or explicitly deferred with a reason on the ticket.
Untriaged-next-day BF umbrellas are named individually in retro §2.10
(compliance %), not averaged away.
**Collect inputs** — every pre-existing failure to register this iteration:
1. Every failure classified **pre-existing** in Phase 2.6 (fails on the base
branch / last-green commit too).
2. Any baseline-run failures noted in the brownfield pre-check (Greenfield vs.
Brownfield section).
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
retro [org-internal #2696]). Query `baseline-failure` issues in ALL states:
```
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=baseline-failure&state=all&page=N&limit=50
```
Match each candidate by **failure signature** — the error/assertion signature
plus the affected surface, not just `file::test-name` (one root-cause family
may span several tests; several tests failing with the same assertion shape
are ONE family). On a signature hit, do NOT create a new ticket: attach the
new run evidence (run, commit, failing output, sibling tests observed) as a
comment on the FAMILY umbrella ticket. Filing a second ticket inside a known
root-cause family is the anti-pattern this phase exists to prevent. If a
tracked family is now FIXED by this iteration's work, close its umbrella with
a comment citing the fixing commit (a bonus, not a requirement). If the query
itself errors (API failure — not "no matches"), retry once; on the second
failure proceed to file with the literal marker `dedup-unverified` in the
umbrella's first evidence comment (query-failure ruling, [org-internal #3383] — fail-open,
visible; rationale in `core/rules/ticket-lifecycle.md`).
**Step 2 — Assign the next `BF-NNN`** per `core/rules/testing.md`
§ "Pre-existing test failures must be filed, not silently logged" (the L1 rule
owns the repo-wide sequential numbering invariant — `max + 1`, duplicate ids
forbidden incl. closed tickets). `BF-NNN` names the FAMILY; the Gitea issue
number `#NNNN` is the tracker handle.
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
no existing family matches the signature:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Baseline failure: {test identifier} (BF-{NNN})",
"body":<issue body template below>,
"labels":[baseline_failure_label_id, severity_label_id, kind_bug_label_id]}
```
- **Title**: `[{origin}] Baseline failure: {signature summary} (BF-{NNN})`
where `{origin}` is `chunk-{id}/iter-{N}` or the bugfix slug, and
`{signature summary}` is the family's error/assertion shape (not a single
test name — sibling tests observed later join this umbrella as evidence
comments).
- **Severity → label** (reuse the existing exclusive Priority set; a failing
test defaults to at least MEDIUM, HIGH if on a critical path):
| Severity | Label |
| -------- | ----------------- |
| HIGH | `Priority/High` |
| MEDIUM | `Priority/Medium` |
| LOW | `Priority/Low` |
- Also attach `Kind/Bug` so the failure is discoverable in the bug tracker
alongside manually-reported bugs.
- **Issue body template**:
````markdown
## Parent / 父级
{#source_issue, or "no source issue — discovered during iteration baseline"}
## Summary
A test was already failing before this iteration's work began. It does not
block the discovering iteration but must be tracked to closure.
| Field | Value |
| -------------- | ---------------------------------------------- |
| BF ID | BF-{NNN} (family) |
| Signature | {error/assertion shape} |
| Tests affected | `{file::test-name}`, … (initial members) |
| Origin | {chunk-id/iter-N or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
| First observed | {base commit / date the failure reproduces on} |
## Reproduction
```
git checkout {base commit}
(cd <harness-package> && bun test --timeout 120000 {test file}) # or project-equivalent
```
Failing output:
```
{paste the relevant assertion / error}
```
## Acceptance Criteria (how to close this issue)
- [ ] The named test passes on a clean checkout of the target branch.
- [ ] If the test is deleted/renamed, the replacement covers the same
behavior and passes.
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
````
**Step 4 — Cross-link to the source issue (mandatory).** Per the
issue-cross-linking rule, every baseline-failure issue MUST link back to its
source:
- The issue body already carries `## Parent` (above).
- Update the source/parent issue body to reference each new baseline-failure
issue by `#NNNN` in its task list (e.g.
`- [ ] #NNNN — BF-{NNN} {test identifier}`), so reviewers can navigate from
source → failure.
**Step 5 — Record the mapping in the verification report.** The
`BF-NNN → #NNNN` mapping is written ONLY in the Phase 5 verification report's
"Baseline Failures" section (and in the issue title itself). There is no local
file to update.
If no new baseline failures were found this iteration, the phase is a no-op —
record "0 baseline failures" in the report and proceed.
<!-- section:phase-5.56 -->
### Phase 5.56 — Flaky-Test Issue Registration (mandatory before PASS when flaky tests are unfixed)
Flaky tests (intermittent pass/fail) are tracked as **root-cause family
umbrella tickets** (`core/rules/ticket-lifecycle.md`, [org-internal #3002] G1) — one
`FT-NNN` ticket per failure-signature family, labeled `flaky-test`, with each
occurrence's evidence (run count, failure rate, commit) attached as comments.
A flaky test that is not fixed within this iteration MUST be filed against
(or into) a family; otherwise it evaporates at iteration end and the
"compare flaky count against baseline" check (TST-2.5) has no persistent
register to compare against. Filing does not block the verdict, but an unfixed
flaky test left un-filed is a process gap and the iteration is NOT Done.
**Expiry SLA ([org-internal #3061])**: an FT umbrella is born with `Kind/Testing` and a
**fix-or-isolate window** (default 7 days) recorded in its body (isolating =
quarantining/skipping the test with the family id in the skip reason, which
keeps the register comparable). Past the window without fix or isolation, the
umbrella is escalated on the ticket (comment naming the owner); retro §2.10
reports fix-or-isolate compliance per cycle.
**Collect inputs** — every flaky test to register this iteration:
1. Every flaky test surfaced in Phase 2.1 (intermittent pass/fail across
reruns) that was NOT fixed by the Developer this iteration.
2. Any flaky test carried over from a prior iteration's report that is still
intermittently failing.
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
retro [org-internal #2696]). Query `flaky-test` issues in ALL states:
```
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=flaky-test&state=all&page=N&limit=50
```
Match each candidate by **failure signature** — the flakiness mode (timeout /
race / order-dependence / env-leak) plus the affected surface, not just
`file::test-name` (one root cause may flake several tests). On a signature
hit, do NOT create a new ticket: attach the new run evidence (run count,
failure rate, commit, sibling tests) as a comment on the FAMILY umbrella
ticket. Filing a second ticket inside a known root-cause family is the
anti-pattern this phase exists to prevent. If a tracked family now passes
deterministically, close its umbrella citing the fixing commit. If the query
itself errors (API failure — not "no matches"), retry once; on the second
failure proceed to file with the literal marker `dedup-unverified` in the
umbrella's first evidence comment (query-failure ruling, [org-internal #3383] — fail-open,
visible; rationale in `core/rules/ticket-lifecycle.md`).
**Step 2 — Assign the next `FT-NNN`** per `core/rules/testing.md`
§ "Flaky tests must be filed, not silently tolerated" (the L1 rule owns the
repo-wide sequential numbering invariant — `max + 1`, duplicate ids forbidden
incl. closed tickets). `FT-NNN` names the FAMILY.
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
no existing family matches the signature:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Flaky test: {test identifier} (FT-{NNN})",
"body":<issue body template below>,
"labels":[flaky_test_label_id, severity_label_id, kind_testing_label_id]}
```
- **Title**: `[{origin}] Flaky test: {signature summary} (FT-{NNN})` — the
family's flakiness mode + surface (sibling tests join later as evidence
comments, not new tickets).
- **Severity** → a flaky test defaults to MEDIUM (HIGH if on a critical path
or blocking CI); reuse the exclusive Priority set.
- Also attach `Kind/Testing` so it is discoverable in the testing tracker.
- **Issue body template**:
````markdown
## Parent / 父级
{#source_issue, or "no source issue — discovered during iteration verification"}
## Summary
A test passes and fails intermittently across runs. It undermines the
reliability of the suite and must be stabilized or quarantined.
| Field | Value |
| ------------ | ------------------------- |
| FT ID | FT-{NNN} (family) |
| Signature | {flakiness mode + surface} |
| Tests affected | `{file::test-name}`, … (initial members) |
| Origin | {chunk-id/iter-N or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
| Failure rate | {e.g. 3/10 runs} |
## Reproduction
```
for i in $(seq 1 10); do (cd <harness-package> && bun test --timeout 120000 {test file}) || echo "run $i FAILED"; done
```
## Acceptance Criteria (how to close this issue)
- [ ] The test passes deterministically across 10 consecutive runs.
- [ ] If it cannot be stabilized, it is quarantined (`test.skip` /
`test.todo` with a comment citing FT-{NNN}) and a stable replacement
is filed as tech-debt (TD-NNN).
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
````
**Step 4 — Cross-link to the source issue (mandatory).** Every flaky-test
issue links back to its source via `## Parent`, and the source/parent issue
task list references each by `#NNNN`
(`- [ ] #NNNN — FT-{NNN} {test identifier}`).
**Step 5 — Record the mapping in the verification report.** The
`FT-NNN → #NNNN` mapping is written ONLY in the Phase 5 report's "Flaky Tests"
section (and the issue title). No local file.
If no unfixed flaky tests exist this iteration, the phase is a no-op — record
"0 flaky tests" in the report and proceed.
<!-- section:phase-5.6 -->
### Phase 5.6 — Issue Checklist Sync (final sweep, mandatory before PASS)
This is the **final** checklist sync — the last of the progressive sync
points (requirements exit, design exit, plan exit, each iteration commit, PR
creation, review convergence, CI transitions, and here — per the sync-point
table in `core/rules/issue-checklist-sync.md`). Earlier syncs may have
already checked off completed items; this phase catches everything remaining
and ensures no `- [ ]` item is left without an annotation.
1. **Identify the source issue** per `core/rules/issue-checklist-sync.md`
§ "How to sync (each point)" step 1 (find `Closes #N` / `Fixes #N` in the
PR body or commit messages). If no source issue exists (e.g. standalone
bugfix with no tracking issue), skip this phase.
2. **Fetch the issue body** via `工单 API(见 TERMINOLOGY)get` (rule step 2).
3. **Map every remaining `- [ ]` checklist item** to one of three states:
- **Done** (missed by earlier syncs) → mark `- [x]` and append
`_(PR #NNN: <file/component>)_`.
- **Deferred** → keep `- [ ]` and append `_(Deferred: TD-NNN <reason>)_`.
- **Pending** → keep `- [ ]` and append `_(Pending: <blocker>)_`.
4. **Fold the `## 当前状态` live-status section** (if present). Rows that have
a checklist counterpart (review, process-ACs) are already reflected as
checklist annotations at their sync points. Rows with no checklist
counterpart in a non-Epic issue (PR opened/merged) are folded as follow-up
evidence on the issue narrative (e.g. `_(PR #NNN merged: <summary>)_` on the
item it delivered, or in the report). Once every row is accounted for,
remove the section from the issue body.
5. **archive-at-close: mark the `## 工件索引` comment archived** (归档动作 — [org-internal #1929]). Issue
closing IS the archive-at-close action; it is explicit, not implicit. Edit the index
comment in place per `_shared/gitea-write-patterns.md` Pattern 10 Archive-at-close
(mechanism — banner + every row's 重读 → ARCHIVE + invariants — is defined there,
do not restate; sequence/actor per `rules/issue-checklist-sync.md` § 归档动作).
- Skip if no source issue exists.
- **Tier 1 run archive** ([org-internal #1988] two-tier artifacts — only if a Tier 1 run
workspace exists): if `<runs-root>/{slug}/` exists (a stage in this run
produced Tier 1 local artifacts, e.g. review-code findings), archive the
run workspace per `core/rules/two-tier-artifacts.md` § Archive-at-close
(the L1 rule is authoritative — do NOT restate its steps here).
The archived bundle must pass
`core/schemas/runs-bundle.schema.json` validation (the generator
validates by default; a red exit blocks close).
Verify deltas only: skip in milestone/task DAG mode (the aggregator agent
performs it at Epic/task-ticket close — see the DAG branch below).
6. **Update the issue body** via `工单 API(见 TERMINOLOGY)update` with the annotated
checklist. Preserve all non-checklist content unchanged.
7. **Verify**: re-read the issue and confirm no `- [ ]` item lacks an
annotation. Every unchecked item MUST have a `(Deferred: ...)` or
`(Pending: ...)` note explaining why it is not done.
8. **Close the issue** (completes the archive-at-close loop): if the flow has
no PR (no `Closes #N` on merge), the Verifier closes the issue after PASS
approval via `工单 API(见 TERMINOLOGY)update(state="closed")` — the banner date is
corrected to the actual close date if it differs from today. If a PR carries
`Closes #N`, the merge closes it; no further action.
If a checklist item cannot be mapped to evidence, deferral, or pending
status, the iteration is NOT Done — the item represents untracked scope.
<!-- section:phase-5.7 --> <!-- section:phase-5.7 -->
### Phase 5.7 — CI State Transition Sync (progressive) ### Phase 5.7 — CI State Transition Sync (progressive)
Process-type acceptance criteria (e.g. "ci.yml passes N consecutive runs", Process-type acceptance criteria (e.g. "ci.yml passes N consecutive runs",
AC#3 in [org-internal #1668]) have no single moment of completion — their progress lives on AC#3 in [TT-1668]) have no single moment of completion — their progress lives on
the issue. The `CI` row in `## 当前状态` is written by the `status-sync` poller the issue. The `CI` row in `## 当前状态` is written by the `status-sync` poller
(`.gitea/scripts/status-sync-poll.ts`), NOT this skill — do NOT manually (`.gitea/scripts/status-sync-poll.ts`), NOT this skill — do NOT manually
`工单 API(见 TERMINOLOGY)update` it. When verification observes a CI state transition `工单 API(见 TERMINOLOGY)update` it. When verification observes a CI state transition
@@ -1121,7 +640,7 @@ the issue. The `CI` row in `## 当前状态` is written by the `status-sync` pol
process-AC's progress note in place via `工单 API(见 TERMINOLOGY)update` (per the process-AC's progress note in place via `工单 API(见 TERMINOLOGY)update` (per the
`issue-checklist-sync` L1 rule § Automated sync — the poller owns the CI row; `issue-checklist-sync` L1 rule § Automated sync — the poller owns the CI row;
the checklist annotation remains manual). Do NOT wait for Phase 5.6: a the checklist annotation remains manual). Do NOT wait for Phase 5.6: a
transition left unsynced for tens of minutes is exactly the staleness [org-internal #1689] transition left unsynced for tens of minutes is exactly the staleness [TT-1689]
targets. Skip if no source issue exists. targets. Skip if no source issue exists.
--- ---
@@ -1213,181 +732,14 @@ To notify workflow completion, call the `signal_stage_done` tool.
--- ---
<!-- section:dag-branch --> <!-- section:dag-branch -->
## DAG branch (milestone + task modes) ## DAG branch (milestone + task modes) — see `reference/dag-branch.md`
> This branch OVERRIDES the Preconditions table, Phase 1 read inputs, Phase 5 > This branch (milestone mode / task mode / no-milestone Epic gate) lives in
> report index, Phase 5.5 ACCEPTED_RISK source, Phase 5.6 final sweep, and > `reference/dag-branch.md`, read it on-demand when the Epic is DAG-shaped:
> Phase 6.5 commit gate for a DAG-ticket-pipeline Epic. It applies when the > frozen DAG at `{epic-slug}/dag` + `task_route.keep_gates` includes `verify`.
> routed Epic is DAG-shaped: a frozen DAG copy exists at `{epic-slug}/dag` and > Legacy iteration verify (the sections above) remains authoritative for
> the DAG's `task_route.keep_gates` includes `verify`. Legacy iteration verify > non-DAG iterations. Spec: `dag-pipeline/spec-05` §5.
> (the sections above) remains authoritative for non-DAG iterations. Spec:
> `dag-pipeline/spec-05` §5. commit status stays
> `pipeline/verify` in both modes.
### Milestone mode (verify runs on a milestone M when `all_incoming_done_and_green`)
A milestone node (`type: milestone`) has no implementation work and no ticket;
its verify is the integration verification welded at a DAG convergence point
(`cross_session_in ≥ 2`). Trigger: the aggregator agent (main
session/Orchestrator) detects `all_incoming_done_and_green` — every fan-in
source node at its terminal state (task source `done` / milestone source
`green`) — and initiates this verify run; the milestone never self-triggers.
**Precondition replacements** (vs legacy iteration verify):
| Legacy verify precondition | Milestone-mode replacement |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| design-space review converged (`review status --stage design-space` success) | review-dag converged (`review status --stage review-dag` success) |
| iteration-plan review converged | REMOVED (DAG has no plan review; the single review-dag gate replaces it) |
| legacy iteration plan at `{slug}/04-plan-index` | DAG artifact + milestone fan-in slice (no `04-plan-*` page) |
| legacy NFR targets from `{slug}/03-design-06-non-functional-design` | REMOVED (product NFRs live in node AC, handled by per-task review-code) |
| upstream roadmap chunk done+verified | all milestone fan-in source nodes at terminal state (task source `done` / milestone source `green`, i.e. `all_incoming_done_and_green`) |
| code review converged (`pipeline/review-code` success) | ALL fan-in node tickets review-code PASS + PR merged (implied by `done`) |
| code review final report exists | REMOVED (no Epic-level final report; per-node review-code reports live on task tickets) |
| carried items from previous iteration closed | REMOVED (vacuous — no iteration) |
| `core/checklists/verification.md` accessible | KEEP (unconditional) |
| Acceptance criteria exist | from DAG-slice-generated DoD matrix (fan-in node AC + integration/contract-conformance/regression/NFR-coverage items) |
| `slug` matches the plan slug | N/A (output naming frozen to `{epic-slug}`) |
**Phase 1 read inputs** → the DAG slice: read the milestone's fan-in subgraph
(fan-in nodes + their cross-session edges + contracts) from the frozen DAG copy
`{epic-slug}/dag`, and generate the DoD matrix from it (integration items,
contract-conformance items, regression items, NFR-coverage items) instead of
reading `04-plan-*` pages.
**Output naming**: `{epic-slug}/05-verify-milestone-{M-id}` (distinct from
iteration verify `05-verify-iteration-{N}`).
**Phase 5 report index**: append a `VERIFY-M-{M-id}` row to the `## 工件索引`
comment with 重读 = `ON-DEMAND` (NOT `ARCHIVE`). The milestone verify does NOT
edit the comment directly — it reports the row-payload to the aggregator agent
(main session/Orchestrator), which is the SINGLE WRITER appending in place
(`工单评论 API(见 TERMINOLOGY)`). `ARCHIVE` is never written by milestone verify
(Epic close is the sole archive point).
**Phase 5.5 ACCEPTED_RISK source**: fan-in node task-ticket review-code reports
(located in each task ticket's review annotations / `## 当前状态` review row),
not an Epic-level final report. A missing Epic-level final report does NOT
trigger the "code-review final report does not exist" warn (that warn is
legacy-iteration-only). tech-debt / baseline-failure / flaky-test registration
proceeds as usual, sourced from the milestone DoD matrix's regression /
baseline-classification results.
**Phase 5.6 milestone mode** (restricted semantics — skip archive-at-close and
issue close):
1. **Checklist final sweep** only — object = each fan-in task ticket's row 6
(`verify里程碑`) + the milestone DoD matrix, NOT the Epic body checklist.
Verify each fan-in node's row 6 is checked or annotated
`_(Pending: M-{M-id} 未 green)_`. Do NOT flip a still-Pending row 6 — that
flip belongs to the aggregator agent (main session/Orchestrator), which
performs the node-ticket close action. Write the milestone DoD matrix final
sweep to `{epic-slug}/05-verify-milestone-{M-id}`.
2. **Do NOT fold/remove any Epic-body `## 当前状态` / `## DAG 状态` section** —
milestone verify is read-only on Epic body state.
3. **SKIP archive-at-close** (the `## 工件索引` archive banner + row-level
`ARCHIVE`) and **SKIP issue close** — both belong to the aggregator agent at
Epic close.
4. **SKIP Tier 1 run archive** (Phase 5.6 step 5, Tier 1 run archive sub-bullet) — the aggregator agent
performs it at Epic close.
**Milestone verify execution context (pinned)**: run the
integration/regression/contract-conformance/NFR suite on a checkout CONTAINING
all fan-in nodes' merged code — the aggregator agent syncs main (containing the
merged fan-in PRs) into the execution worktree, or builds a temp verify worktree
from main HEAD, before triggering; the verify report
`{epic-slug}/05-verify-milestone-{M-id}` records the actual execution commit
SHA.
**M→green status transition**: NOT done by milestone verify (read-only on Epic
body). The aggregator agent (main session/Orchestrator) reads the verify report
and sets the aggregator table M row 状态 = `green`, 重读 = `ON-DEMAND`, and
syncs the frozen DAG copy `{epic-slug}/dag` node `status` to `green`.
**Phase 6.5 milestone mode**: vacuous skip — a milestone has no implementation
commit. Commit existence is evidenced by the fan-in node verify PASS + PR
merged (already implied by `all_incoming_done_and_green`).
**Milestone verify FAIL recovery**: FAIL → M `status` = `blocked`. Fix
responsibility = the fan-in node owning the failing integration/regression item
(the last-done fan-in node's session) or the Epic-level session (DAG author) if
un-attributable. Re-run is triggered ONLY by a "fix-landed event" (fix commit
merged + CI green, or an explicit re-done report from the owning session) —
NOT status polling (done nodes are never reset; `all_incoming_done_and_green`
stays true after FAIL). M stays `blocked` until a fix event, then returns to
`pending` and verify re-runs. No review-dag re-run unless the fix changes a
cross-session contract or the node/edge set.
### Task mode (verify on a task node ticket, because `task_route.keep_gates` includes `verify`)
Each task ticket closes only after its own verify run, but legacy verify
preconditions do not hold in DAG mode — this node-level branch reuses the
`verify` skill with the following node-scoped semantics (so the `verify` gate is
not silently downgraded to CI-only).
**Verification object**: the node's own `acceptance_criteria` → the `test_id`
suite (`file-path::test-name` / `MANUAL` / `BENCH:`) all passing fresh + that
node's review-code PASS recorded + CI green. NOT milestone fan-in
integration/contract/regression items (those are milestone verify's). Spec
authority = the node in the frozen DAG copy `{epic-slug}/dag`.
**Precondition replacements** (task mode — mirror the milestone table, scoped to
the node):
| Legacy verify precondition | Task-mode replacement |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| design-space review converged | review-dag converged (this Epic already passed the single gate; do NOT re-run it) |
| iteration-plan review converged | REMOVED (DAG has no plan review) |
| legacy iteration plan at `{slug}/04-plan-index` | the node in the frozen DAG copy `{epic-slug}/dag` (no `04-plan-*` page) |
| legacy NFR targets from `{slug}/03-design-06-non-functional-design` | REMOVED (product NFRs live in node AC, handled by per-task review-code) |
| upstream roadmap chunk done+verified | this node's cross-session in-edge source nodes at terminal state (task source `done` / milestone source `green`) |
| code review converged (`pipeline/review-code` success) | this node's ticket review-code PASS + PR merged |
| code review final report exists | REMOVED (this node's review-code report lives on the task ticket) |
| carried items from previous iteration closed | REMOVED (vacuous — no iteration) |
| `core/checklists/verification.md` accessible | KEEP |
| Acceptance criteria exist | from node AC + `test_id` suite |
| `slug` matches the plan slug | N/A (Tier 1 run slug = `{epic-slug}-task-{node-id}` — the same node-task run namespace review-code runs in and this mode's archive bundle uses below; the Phase 2 precondition-gate cache read MUST use this slug. Only the wiki output naming stays Epic-scoped: `{epic-slug}/05-verify-task-{node-id}`) |
**Phase 1 read inputs** → the node's AC + `test_id` suite from the frozen DAG
copy `{epic-slug}/dag`, generating the DoD matrix.
**Output naming**: `{epic-slug}/05-verify-task-{node-id}`.
**Phase 5 report index**: append a `VERIFY-TASK-{node-id}` row, 重读 =
`ON-DEMAND` (NOT `ARCHIVE`), via the aggregator agent as single writer (task
verify does not edit the comment directly).
**Phase 5.5 task mode**: ACCEPTED_RISK source = this node's task-ticket
review-code report (no Epic-level final report → no "does not exist" warn).
tech-debt / baseline-failure / flaky-test registration proceeds as usual.
**Phase 5.6 task mode**: only checklist final sweep — object = this ticket's
5-row checklist (NOT row 6 `verify里程碑` — row 6 is flipped ONLY by the
aggregator agent). SKIP archive-at-close (`## 工件索引` row-level `ARCHIVE`) and
issue close (both belong to the aggregator agent). SKIP Tier 1 run archive — the
aggregator agent collects it cross-worktree at task-ticket close (archive to
`<runs-root>/archive/{epic-slug}-task-{node-id}.json` and commit to the
workflow branch). Do NOT fold Epic body status sections.
**Phase 6.5 task mode**: object = this node ticket's commit; semantics = "node
implementation commit exists". Baseline = the task worktree's creation-commit
SHA (`git log {creation-SHA}..HEAD`), NOT a generic base-branch (post-merge
there are no new commits vs base). The task worktree is retained until ticket
close (the aggregator agent removes it after collecting task-level Tier 1
archive); the task session must NOT remove its own worktree.
**commit status**: still `pipeline/verify` in both modes.
### No-milestone DAG Epic-level verify gate
When the routed Epic's DAG has NO milestone (no `cross_session_in ≥ 2`
convergence point), the Epic-level `keep_gates: verify` is satisfied
AGGREGATELY by all task-ticket verify runs (each with commit status
`pipeline/verify` success) — NO independent Epic-level verify run, NO
`{epic-slug}/05-verify-milestone-{M-id}` artifact, NO `VERIFY-M-{M-id}` index
row. The Epic close condition degenerates to "all task nodes `done`".
---
## References ## References
+180
View File
@@ -0,0 +1,180 @@
> Extracted from verify/SKILL.md (section:dag-branch) — moved verbatim; read
> on-demand ONLY when the routed Epic is DAG-shaped (frozen DAG at
> `{epic-slug}/dag` and `task_route.keep_gates` includes `verify`).
<!-- section:dag-branch -->
## DAG branch (milestone + task modes)
> This branch OVERRIDES the Preconditions table, Phase 1 read inputs, Phase 5
> report index, Phase 5.5 ACCEPTED_RISK source, Phase 5.6 final sweep, and
> Phase 6.5 commit gate for a DAG-ticket-pipeline Epic. It applies when the
> routed Epic is DAG-shaped: a frozen DAG copy exists at `{epic-slug}/dag` and
> the DAG's `task_route.keep_gates` includes `verify`. Legacy iteration verify
> (the sections above) remains authoritative for non-DAG iterations. Spec:
> `dag-pipeline/spec-05` §5. commit status stays
> `pipeline/verify` in both modes.
### Milestone mode (verify runs on a milestone M when `all_incoming_done_and_green`)
A milestone node (`type: milestone`) has no implementation work and no ticket;
its verify is the integration verification welded at a DAG convergence point
(`cross_session_in ≥ 2`). Trigger: the aggregator agent (main
session/Orchestrator) detects `all_incoming_done_and_green` — every fan-in
source node at its terminal state (task source `done` / milestone source
`green`) — and initiates this verify run; the milestone never self-triggers.
**Precondition replacements** (vs legacy iteration verify):
| Legacy verify precondition | Milestone-mode replacement |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| design-space review converged (`review status --stage design-space` success) | review-dag converged (`review status --stage review-dag` success) |
| iteration-plan review converged | REMOVED (DAG has no plan review; the single review-dag gate replaces it) |
| legacy iteration plan at `{slug}/04-plan-index` | DAG artifact + milestone fan-in slice (no `04-plan-*` page) |
| legacy NFR targets from `{slug}/03-design-06-non-functional-design` | REMOVED (product NFRs live in node AC, handled by per-task review-code) |
| upstream roadmap chunk done+verified | all milestone fan-in source nodes at terminal state (task source `done` / milestone source `green`, i.e. `all_incoming_done_and_green`) |
| code review converged (`pipeline/review-code` success) | ALL fan-in node tickets review-code PASS + PR merged (implied by `done`) |
| code review final report exists | REMOVED (no Epic-level final report; per-node review-code reports live on task tickets) |
| carried items from previous iteration closed | REMOVED (vacuous — no iteration) |
| `core/checklists/verification.md` accessible | KEEP (unconditional) |
| Acceptance criteria exist | from DAG-slice-generated DoD matrix (fan-in node AC + integration/contract-conformance/regression/NFR-coverage items) |
| `slug` matches the plan slug | N/A (output naming frozen to `{epic-slug}`) |
**Phase 1 read inputs** → the DAG slice: read the milestone's fan-in subgraph
(fan-in nodes + their cross-session edges + contracts) from the frozen DAG copy
`{epic-slug}/dag`, and generate the DoD matrix from it (integration items,
contract-conformance items, regression items, NFR-coverage items) instead of
reading `04-plan-*` pages.
**Output naming**: `{epic-slug}/05-verify-milestone-{M-id}` (distinct from
iteration verify `05-verify-iteration-{N}`).
**Phase 5 report index**: append a `VERIFY-M-{M-id}` row to the `## 工件索引`
comment with 重读 = `ON-DEMAND` (NOT `ARCHIVE`). The milestone verify does NOT
edit the comment directly — it reports the row-payload to the aggregator agent
(main session/Orchestrator), which is the SINGLE WRITER appending in place
(`工单评论 API(见 TERMINOLOGY)`). `ARCHIVE` is never written by milestone verify
(Epic close is the sole archive point).
**Phase 5.5 ACCEPTED_RISK source**: fan-in node task-ticket review-code reports
(located in each task ticket's review annotations / `## 当前状态` review row),
not an Epic-level final report. A missing Epic-level final report does NOT
trigger the "code-review final report does not exist" warn (that warn is
legacy-iteration-only). tech-debt / baseline-failure / flaky-test registration
proceeds as usual, sourced from the milestone DoD matrix's regression /
baseline-classification results.
**Phase 5.6 milestone mode** (restricted semantics — skip archive-at-close and
issue close):
1. **Checklist final sweep** only — object = each fan-in task ticket's row 6
(`verify里程碑`) + the milestone DoD matrix, NOT the Epic body checklist.
Verify each fan-in node's row 6 is checked or annotated
`_(Pending: M-{M-id} 未 green)_`. Do NOT flip a still-Pending row 6 — that
flip belongs to the aggregator agent (main session/Orchestrator), which
performs the node-ticket close action. Write the milestone DoD matrix final
sweep to `{epic-slug}/05-verify-milestone-{M-id}`.
2. **Do NOT fold/remove any Epic-body `## 当前状态` / `## DAG 状态` section** —
milestone verify is read-only on Epic body state.
3. **SKIP archive-at-close** (the `## 工件索引` archive banner + row-level
`ARCHIVE`) and **SKIP issue close** — both belong to the aggregator agent at
Epic close.
4. **SKIP Tier 1 run archive** (Phase 5.6 step 5, Tier 1 run archive sub-bullet) — the aggregator agent
performs it at Epic close.
**Milestone verify execution context (pinned)**: run the
integration/regression/contract-conformance/NFR suite on a checkout CONTAINING
all fan-in nodes' merged code — the aggregator agent syncs main (containing the
merged fan-in PRs) into the execution worktree, or builds a temp verify worktree
from main HEAD, before triggering; the verify report
`{epic-slug}/05-verify-milestone-{M-id}` records the actual execution commit
SHA.
**M→green status transition**: NOT done by milestone verify (read-only on Epic
body). The aggregator agent (main session/Orchestrator) reads the verify report
and sets the aggregator table M row 状态 = `green`, 重读 = `ON-DEMAND`, and
syncs the frozen DAG copy `{epic-slug}/dag` node `status` to `green`.
**Phase 6.5 milestone mode**: vacuous skip — a milestone has no implementation
commit. Commit existence is evidenced by the fan-in node verify PASS + PR
merged (already implied by `all_incoming_done_and_green`).
**Milestone verify FAIL recovery**: FAIL → M `status` = `blocked`. Fix
responsibility = the fan-in node owning the failing integration/regression item
(the last-done fan-in node's session) or the Epic-level session (DAG author) if
un-attributable. Re-run is triggered ONLY by a "fix-landed event" (fix commit
merged + CI green, or an explicit re-done report from the owning session) —
NOT status polling (done nodes are never reset; `all_incoming_done_and_green`
stays true after FAIL). M stays `blocked` until a fix event, then returns to
`pending` and verify re-runs. No review-dag re-run unless the fix changes a
cross-session contract or the node/edge set.
### Task mode (verify on a task node ticket, because `task_route.keep_gates` includes `verify`)
Each task ticket closes only after its own verify run, but legacy verify
preconditions do not hold in DAG mode — this node-level branch reuses the
`verify` skill with the following node-scoped semantics (so the `verify` gate is
not silently downgraded to CI-only).
**Verification object**: the node's own `acceptance_criteria` → the `test_id`
suite (`file-path::test-name` / `MANUAL` / `BENCH:`) all passing fresh + that
node's review-code PASS recorded + CI green. NOT milestone fan-in
integration/contract/regression items (those are milestone verify's). Spec
authority = the node in the frozen DAG copy `{epic-slug}/dag`.
**Precondition replacements** (task mode — mirror the milestone table, scoped to
the node):
| Legacy verify precondition | Task-mode replacement |
| ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| design-space review converged | review-dag converged (this Epic already passed the single gate; do NOT re-run it) |
| iteration-plan review converged | REMOVED (DAG has no plan review) |
| legacy iteration plan at `{slug}/04-plan-index` | the node in the frozen DAG copy `{epic-slug}/dag` (no `04-plan-*` page) |
| legacy NFR targets from `{slug}/03-design-06-non-functional-design` | REMOVED (product NFRs live in node AC, handled by per-task review-code) |
| upstream roadmap chunk done+verified | this node's cross-session in-edge source nodes at terminal state (task source `done` / milestone source `green`) |
| code review converged (`pipeline/review-code` success) | this node's ticket review-code PASS + PR merged |
| code review final report exists | REMOVED (this node's review-code report lives on the task ticket) |
| carried items from previous iteration closed | REMOVED (vacuous — no iteration) |
| `core/checklists/verification.md` accessible | KEEP |
| Acceptance criteria exist | from node AC + `test_id` suite |
| `slug` matches the plan slug | N/A (Tier 1 run slug = `{epic-slug}-task-{node-id}` — the same node-task run namespace review-code runs in and this mode's archive bundle uses below; the Phase 2 precondition-gate cache read MUST use this slug. Only the wiki output naming stays Epic-scoped: `{epic-slug}/05-verify-task-{node-id}`) |
**Phase 1 read inputs** → the node's AC + `test_id` suite from the frozen DAG
copy `{epic-slug}/dag`, generating the DoD matrix.
**Output naming**: `{epic-slug}/05-verify-task-{node-id}`.
**Phase 5 report index**: append a `VERIFY-TASK-{node-id}` row, 重读 =
`ON-DEMAND` (NOT `ARCHIVE`), via the aggregator agent as single writer (task
verify does not edit the comment directly).
**Phase 5.5 task mode**: ACCEPTED_RISK source = this node's task-ticket
review-code report (no Epic-level final report → no "does not exist" warn).
tech-debt / baseline-failure / flaky-test registration proceeds as usual.
**Phase 5.6 task mode**: only checklist final sweep — object = this ticket's
5-row checklist (NOT row 6 `verify里程碑` — row 6 is flipped ONLY by the
aggregator agent). SKIP archive-at-close (`## 工件索引` row-level `ARCHIVE`) and
issue close (both belong to the aggregator agent). SKIP Tier 1 run archive — the
aggregator agent collects it cross-worktree at task-ticket close (archive to
`<runs-root>/archive/{epic-slug}-task-{node-id}.json` and commit to the
workflow branch). Do NOT fold Epic body status sections.
**Phase 6.5 task mode**: object = this node ticket's commit; semantics = "node
implementation commit exists". Baseline = the task worktree's creation-commit
SHA (`git log {creation-SHA}..HEAD`), NOT a generic base-branch (post-merge
there are no new commits vs base). The task worktree is retained until ticket
close (the aggregator agent removes it after collecting task-level Tier 1
archive); the task session must NOT remove its own worktree.
**commit status**: still `pipeline/verify` in both modes.
### No-milestone DAG Epic-level verify gate
When the routed Epic's DAG has NO milestone (no `cross_session_in ≥ 2`
convergence point), the Epic-level `keep_gates: verify` is satisfied
AGGREGATELY by all task-ticket verify runs (each with commit status
`pipeline/verify` success) — NO independent Epic-level verify run, NO
`{epic-slug}/05-verify-milestone-{M-id}` artifact, NO `VERIFY-M-{M-id}` index
row. The Epic close condition degenerates to "all task nodes `done`".
---
@@ -0,0 +1,495 @@
> Extracted from verify/SKILL.md (phase 5.5 / 5.55 / 5.56 / 5.6) — moved
> verbatim; read on-demand during Phase 5 execution, before PASS. Each phase
> is mandatory-before-PASS in its trigger condition; the main flow stops at
> each boundary until the referenced protocol reports completion.
<!-- section:phase-5.5 -->
### Phase 5.5 — Tech Debt Registry Filing (mandatory before PASS)
Tech debt is filed **registry-first** (`core/rules/ticket-lifecycle.md`,
[TT-3002] G1): new items become ROWS in the source ticket's `## TD 登记` comment;
an independent ticket is created only at **promotion** (claim/schedule). There
is no `tech-debt.md` file and no `{slug}/tech-debt` wiki page — both remain
retired. The registry preserves the three guarantees of the old
one-issue-per-item model: visible (the comment lives on a tracker ticket),
individually closeable (row-level checkbox), de-duplicated across sessions
(the TD index is stronger than title-keyword matching).
**Sprint-mode override ([TT-3002] G5/[TT-3007])**: read `filing.sprint-mode` from
`<instance-root>/workflow-routing.yaml` at the START of this phase (no caching). When
`true`, ALL severities file registry-only — registration rows are written as
normal (severity included, nothing lost) but promotion to standalone tickets
is FROZEN until the switch returns to `false`. Rationale: the 2026-08-12
sprint zeroed fix capacity while filing kept running (the 125-fragment
backlog's direct trigger); an explicit debt-side downshift beats hoping for
discipline. BF/FT phases 5.55/5.56 are NOT covered by this switch — failure
evidence must stay immediately visible. Flipping the switch is a human
decision recorded on the sprint tracker; semantics in
`rules/workflow-routing.md` §立案降档.
**Adjacency quota ([TT-3002] G3/[TT-3005])**: while collecting inputs, also check the
AREAS this iteration touched (packages/modules with commits this iteration).
If the source tickets for those areas carry applicable `## TD 登记` rows, at
least ONE row must be taken along and disposed this iteration (fixed, or
explicitly re-deferred with a reason — silence is not a disposition). Record
`consumed X / applicable Y` (or `0 applicable`) in the TD report section;
verification checklist §8.4 cross-checks it against the run's debt-quota
record (historically the roadmap's per-chunk debt-quota line). This gives debt digestion a steady capacity source tied to
touch, not to cleanup campaigns.
**Promotion quota + pull event ([TT-3061])**: promotion to a standalone ticket
requires (a) a **pull event** — the row's Reactivation Trigger fired (state
the observed event) OR a named claimer/schedule; "it seemed important" is not
a pull event — recorded in the promotion body's `## 拉动事件 / Pull Event`
section; and (b) the origin module's OPEN promoted-TD count is below the
quota (**default 10** — counted **per origin module**: resolve the row's
module from the ticket body's `Origin` field, then count that module's OPEN
`tech-debt` tickets; retro §2.10 reports breaches). At or above quota →
register-only until the count drops; before each Phase 5.5 promotion
re-check the owning module's count, and a row whose module is at or above
quota is NOT promoted — defer it and annotate the registry row with
`quota-held` (re-checked on the next verify run, retro 2026-08-21). A row
marked `[COLD]` by retrospective §2.10
(unclaimed >3 retro cycles) promotes only after the pull event clears the
mark.
**Collect inputs** — every tech-debt item to register this iteration:
1. Every UNVERIFIABLE row in the DoD matrix (Phase 3), with its Reactivation
Trigger.
2. Every ACCEPTED_RISK finding in the code-review final report
(`{slug}/reviews/code/final/report`), with its Recommended Reactivation
Trigger.
3. Every `[OPEN: <short-id>]` marker the Developer left in code this iteration
(per implementation checklist POST-6.2).
If the code-review final report does not exist, warn the user — ACCEPTED_RISK
items cannot be captured. This is itself a process gap that must be flagged.
**Step 1 — De-duplicate against the registry index and promoted issues.**
1. Read the source ticket's `## TD 登记` comment (create the comment if this
is its first row) and match each candidate against existing rows by
`TD-NNN` and reactivation trigger. Same-source re-reporting is the
anti-pattern this step exists to prevent (the visual-cluster incident: 18
fragments from one source under the old keyword matching).
2. Query OPEN promoted tech-debt issues for cross-source duplicates:
```
工单 API 检索(见 TERMINOLOGY)
(owner/repo 按实例绑定,labels="tech-debt", state="open")
```
**Step 2 — Assign `TD-NNN` via the ledger mutex ([TT-3322]).** One script call
per batch: `bash script/td-alloc.sh <count = new items> <source-slug>
[--ticket N]` returns a contiguous range from the TD allocation ledger
(append-only comments, earliest-comment-id wins; the seed comment pins the
historical floor). Split the returned range across the Step 3 rows in order.
**Any allocation — manual included — must land a `**td-alloc**` comment on
the ledger before the registry row is written; hand-computed `max + 1` is
forbidden** (the 2026-08-24 three-way collision). On exit 5 (retry
exhaustion) abort this phase's filing and retry — never hand-assign. The id is **reserved for life**: promotion reuses it, never
renumbers. Run `--check` (reconciliation) here if the last check predates
this batch.
**Step 3 — Append one registry row per new item.** Append to the source
ticket's `## TD 登记` comment (no source ticket → the owning Epic's tracker
ticket; no Epic → the standing `TD 冷存档` tracker):
```markdown
- [ ] TD-{NNN} · {UNVERIFIABLE | ACCEPTED_RISK | DEFERRED} · {HIGH | MEDIUM | LOW}
· {origin chunk-id/iter-N} — {one-line summary}
· trigger: {objectively verifiable reactivation condition — never "when ready";
if no trigger can be defined this is NOT tech debt and the iteration verdict
becomes FAIL}
```
**Step 4 — Cross-link (adapted).** The registry comment already lives on the
source issue — the source → debt navigation the old body-edit provided. When
filing went to an Epic tracker or the 冷存档 (no source ticket), reference the
originating slug in each row so the trail survives.
**Step 5 — Record the mapping in the verification report.** The report's
"Tech Debt" section records `TD-NNN → registry row` (source `#NNNN` +
`## TD 登记` comment); promoted items record `TD-NNN → #NNNN` as before.
**Promotion (认领升票) — when a row is scheduled or picked up.** Create the
independent ticket THEN, carrying the reserved `TD-NNN`:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Tech debt: {short description} (TD-{NNN})",
"body":<promotion template below>,
"labels":[tech_debt_label_id, severity_label_id]}
```
- **Severity → label** (reuse the existing exclusive Priority set):
| Severity | Label |
| -------- | ----------------- |
| HIGH | `Priority/High` |
| MEDIUM | `Priority/Medium` |
| LOW | `Priority/Low` |
- **Promotion body template** (the pre-[TT-3002] issue template, now used only at
promotion):
```markdown
## Parent / 父级
{#source_issue carrying the ## TD 登记 row}
## Summary
{one-paragraph description of the debt}
| Field | Value |
| -------- | ------------------------------------------- |
| TD ID | TD-{NNN} (reserved at registration) |
| Type | {UNVERIFIABLE \| ACCEPTED_RISK \| DEFERRED} |
| Origin | {chunk-id/iter-N/phase or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
## Reactivation Trigger
{from the registry row}
## 拉动事件 / Pull Event
{trigger fired: {observed event} | claimed by {who} for {when}}
## Acceptance Criteria (how to close this issue)
- [ ] {specific action that resolves the debt}
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
- Code review report: `{slug}/reviews/code/final/report` (if ACCEPTED_RISK)
```
- After creating the promoted ticket: tick the registry row (`- [x]`) and
append `→ #NNNN` to it.
If no new tech-debt items were found this iteration, the phase is a no-op —
record "0 tech-debt items" in the report and proceed.
<!-- section:phase-5.55 -->
### Phase 5.55 — Baseline-Failure Issue Registration (mandatory before PASS when pre-existing failures exist)
Pre-existing test failures (BF) are tracked as **root-cause family umbrella
tickets** (`core/rules/ticket-lifecycle.md`, [TT-3002] G1; precedents [TT-2585]
umbrella + [TT-2925] cluster) — one `BF-NNN` ticket per failure-signature family,
labeled `baseline-failure`, with each occurrence's evidence attached as
comments. There is no `baseline-failures.md` file and no
`{slug}/baseline-failures` wiki page. A pre-existing failure does not block
the iteration that _discovered_ it (it pre-dates that work), but it MUST be
filed against (or into) a family; an un-filed baseline failure is a process
gap and the iteration is NOT Done.
**Birth triage SLA ([TT-3061])**: a BF umbrella is born with `Kind/Bug` (it IS a
bug — of the baseline) and must be triaged the SAME DAY it is filed:
assigned, scheduled, or explicitly deferred with a reason on the ticket.
Untriaged-next-day BF umbrellas are named individually in retro §2.10
(compliance %), not averaged away.
**Collect inputs** — every pre-existing failure to register this iteration:
1. Every failure classified **pre-existing** in Phase 2.6 (fails on the base
branch / last-green commit too).
2. Any baseline-run failures noted in the brownfield pre-check (Greenfield vs.
Brownfield section).
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
retro [TT-2696]). Query `baseline-failure` issues in ALL states:
```
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=baseline-failure&state=all&page=N&limit=50
```
Match each candidate by **failure signature** — the error/assertion signature
plus the affected surface, not just `file::test-name` (one root-cause family
may span several tests; several tests failing with the same assertion shape
are ONE family). On a signature hit, do NOT create a new ticket: attach the
new run evidence (run, commit, failing output, sibling tests observed) as a
comment on the FAMILY umbrella ticket. Filing a second ticket inside a known
root-cause family is the anti-pattern this phase exists to prevent. If a
tracked family is now FIXED by this iteration's work, close its umbrella with
a comment citing the fixing commit (a bonus, not a requirement). If the query
itself errors (API failure — not "no matches"), retry once; on the second
failure proceed to file with the literal marker `dedup-unverified` in the
umbrella's first evidence comment (query-failure ruling, [TT-3383] — fail-open,
visible; rationale in `core/rules/ticket-lifecycle.md`).
**Step 2 — Assign the next `BF-NNN`** per `core/rules/testing.md`
§ "Pre-existing test failures must be filed, not silently logged" (the L1 rule
owns the repo-wide sequential numbering invariant — `max + 1`, duplicate ids
forbidden incl. closed tickets). `BF-NNN` names the FAMILY; the Gitea issue
number `#NNNN` is the tracker handle.
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
no existing family matches the signature:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Baseline failure: {test identifier} (BF-{NNN})",
"body":<issue body template below>,
"labels":[baseline_failure_label_id, severity_label_id, kind_bug_label_id]}
```
- **Title**: `[{origin}] Baseline failure: {signature summary} (BF-{NNN})`
where `{origin}` is `chunk-{id}/iter-{N}` or the bugfix slug, and
`{signature summary}` is the family's error/assertion shape (not a single
test name — sibling tests observed later join this umbrella as evidence
comments).
- **Severity → label** (reuse the existing exclusive Priority set; a failing
test defaults to at least MEDIUM, HIGH if on a critical path):
| Severity | Label |
| -------- | ----------------- |
| HIGH | `Priority/High` |
| MEDIUM | `Priority/Medium` |
| LOW | `Priority/Low` |
- Also attach `Kind/Bug` so the failure is discoverable in the bug tracker
alongside manually-reported bugs.
- **Issue body template**:
````markdown
## Parent / 父级
{#source_issue, or "no source issue — discovered during iteration baseline"}
## Summary
A test was already failing before this iteration's work began. It does not
block the discovering iteration but must be tracked to closure.
| Field | Value |
| -------------- | ---------------------------------------------- |
| BF ID | BF-{NNN} (family) |
| Signature | {error/assertion shape} |
| Tests affected | `{file::test-name}`, … (initial members) |
| Origin | {chunk-id/iter-N or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
| First observed | {base commit / date the failure reproduces on} |
## Reproduction
```
git checkout {base commit}
(cd <harness-package> && bun test --timeout 120000 {test file}) # or project-equivalent
```
Failing output:
```
{paste the relevant assertion / error}
```
## Acceptance Criteria (how to close this issue)
- [ ] The named test passes on a clean checkout of the target branch.
- [ ] If the test is deleted/renamed, the replacement covers the same
behavior and passes.
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
````
**Step 4 — Cross-link to the source issue (mandatory).** Per the
issue-cross-linking rule, every baseline-failure issue MUST link back to its
source:
- The issue body already carries `## Parent` (above).
- Update the source/parent issue body to reference each new baseline-failure
issue by `#NNNN` in its task list (e.g.
`- [ ] #NNNN — BF-{NNN} {test identifier}`), so reviewers can navigate from
source → failure.
**Step 5 — Record the mapping in the verification report.** The
`BF-NNN → #NNNN` mapping is written ONLY in the Phase 5 verification report's
"Baseline Failures" section (and in the issue title itself). There is no local
file to update.
If no new baseline failures were found this iteration, the phase is a no-op —
record "0 baseline failures" in the report and proceed.
<!-- section:phase-5.56 -->
### Phase 5.56 — Flaky-Test Issue Registration (mandatory before PASS when flaky tests are unfixed)
Flaky tests (intermittent pass/fail) are tracked as **root-cause family
umbrella tickets** (`core/rules/ticket-lifecycle.md`, [TT-3002] G1) — one
`FT-NNN` ticket per failure-signature family, labeled `flaky-test`, with each
occurrence's evidence (run count, failure rate, commit) attached as comments.
A flaky test that is not fixed within this iteration MUST be filed against
(or into) a family; otherwise it evaporates at iteration end and the
"compare flaky count against baseline" check (TST-2.5) has no persistent
register to compare against. Filing does not block the verdict, but an unfixed
flaky test left un-filed is a process gap and the iteration is NOT Done.
**Expiry SLA ([TT-3061])**: an FT umbrella is born with `Kind/Testing` and a
**fix-or-isolate window** (default 7 days) recorded in its body (isolating =
quarantining/skipping the test with the family id in the skip reason, which
keeps the register comparable). Past the window without fix or isolation, the
umbrella is escalated on the ticket (comment naming the owner); retro §2.10
reports fix-or-isolate compliance per cycle.
**Collect inputs** — every flaky test to register this iteration:
1. Every flaky test surfaced in Phase 2.1 (intermittent pass/fail across
reruns) that was NOT fixed by the Developer this iteration.
2. Any flaky test carried over from a prior iteration's report that is still
intermittently failing.
**Step 1 — De-duplicate by failure SIGNATURE against existing families (open
AND closed), per `core/rules/testing.md`** (de-duplicate BEFORE filing,
retro [TT-2696]). Query `flaky-test` issues in ALL states:
```
GET <gitea-base-url>/api/v1/repos/Octopus/octopus/issues?labels=flaky-test&state=all&page=N&limit=50
```
Match each candidate by **failure signature** — the flakiness mode (timeout /
race / order-dependence / env-leak) plus the affected surface, not just
`file::test-name` (one root cause may flake several tests). On a signature
hit, do NOT create a new ticket: attach the new run evidence (run count,
failure rate, commit, sibling tests) as a comment on the FAMILY umbrella
ticket. Filing a second ticket inside a known root-cause family is the
anti-pattern this phase exists to prevent. If a tracked family now passes
deterministically, close its umbrella citing the fixing commit. If the query
itself errors (API failure — not "no matches"), retry once; on the second
failure proceed to file with the literal marker `dedup-unverified` in the
umbrella's first evidence comment (query-failure ruling, [TT-3383] — fail-open,
visible; rationale in `core/rules/ticket-lifecycle.md`).
**Step 2 — Assign the next `FT-NNN`** per `core/rules/testing.md`
§ "Flaky tests must be filed, not silently tolerated" (the L1 rule owns the
repo-wide sequential numbering invariant — `max + 1`, duplicate ids forbidden
incl. closed tickets). `FT-NNN` names the FAMILY.
**Step 3 — Create one umbrella ticket per NEW root-cause family.** Only when
no existing family matches the signature:
```
POST <gitea-base-url>/api/v1/repos/Octopus/octopus/issues
body: {"title":"[{origin}] Flaky test: {test identifier} (FT-{NNN})",
"body":<issue body template below>,
"labels":[flaky_test_label_id, severity_label_id, kind_testing_label_id]}
```
- **Title**: `[{origin}] Flaky test: {signature summary} (FT-{NNN})` — the
family's flakiness mode + surface (sibling tests join later as evidence
comments, not new tickets).
- **Severity** → a flaky test defaults to MEDIUM (HIGH if on a critical path
or blocking CI); reuse the exclusive Priority set.
- Also attach `Kind/Testing` so it is discoverable in the testing tracker.
- **Issue body template**:
````markdown
## Parent / 父级
{#source_issue, or "no source issue — discovered during iteration verification"}
## Summary
A test passes and fails intermittently across runs. It undermines the
reliability of the suite and must be stabilized or quarantined.
| Field | Value |
| ------------ | ------------------------- |
| FT ID | FT-{NNN} (family) |
| Signature | {flakiness mode + surface} |
| Tests affected | `{file::test-name}`, … (initial members) |
| Origin | {chunk-id/iter-N or slug} |
| Severity | {HIGH \| MEDIUM \| LOW} |
| Failure rate | {e.g. 3/10 runs} |
## Reproduction
```
for i in $(seq 1 10); do (cd <harness-package> && bun test --timeout 120000 {test file}) || echo "run $i FAILED"; done
```
## Acceptance Criteria (how to close this issue)
- [ ] The test passes deterministically across 10 consecutive runs.
- [ ] If it cannot be stabilized, it is quarantined (`test.skip` /
`test.todo` with a comment citing FT-{NNN}) and a stable replacement
is filed as tech-debt (TD-NNN).
## Context
- Verification report: `{slug}/05-verify-iteration-{N}`
````
**Step 4 — Cross-link to the source issue (mandatory).** Every flaky-test
issue links back to its source via `## Parent`, and the source/parent issue
task list references each by `#NNNN`
(`- [ ] #NNNN — FT-{NNN} {test identifier}`).
**Step 5 — Record the mapping in the verification report.** The
`FT-NNN → #NNNN` mapping is written ONLY in the Phase 5 report's "Flaky Tests"
section (and the issue title). No local file.
If no unfixed flaky tests exist this iteration, the phase is a no-op — record
"0 flaky tests" in the report and proceed.
<!-- section:phase-5.6 -->
### Phase 5.6 — Issue Checklist Sync (final sweep, mandatory before PASS)
This is the **final** checklist sync — the last of the progressive sync
points (requirements exit, design exit, plan exit, each iteration commit, PR
creation, review convergence, CI transitions, and here — per the sync-point
table in `core/rules/issue-checklist-sync.md`). Earlier syncs may have
already checked off completed items; this phase catches everything remaining
and ensures no `- [ ]` item is left without an annotation.
1. **Identify the source issue** per `core/rules/issue-checklist-sync.md`
§ "How to sync (each point)" step 1 (find `Closes #N` / `Fixes #N` in the
PR body or commit messages). If no source issue exists (e.g. standalone
bugfix with no tracking issue), skip this phase.
2. **Fetch the issue body** via `工单 API(见 TERMINOLOGY)get` (rule step 2).
3. **Map every remaining `- [ ]` checklist item** to one of three states:
- **Done** (missed by earlier syncs) → mark `- [x]` and append
`_(PR #NNN: <file/component>)_`.
- **Deferred** → keep `- [ ]` and append `_(Deferred: TD-NNN <reason>)_`.
- **Pending** → keep `- [ ]` and append `_(Pending: <blocker>)_`.
4. **Fold the `## 当前状态` live-status section** (if present). Rows that have
a checklist counterpart (review, process-ACs) are already reflected as
checklist annotations at their sync points. Rows with no checklist
counterpart in a non-Epic issue (PR opened/merged) are folded as follow-up
evidence on the issue narrative (e.g. `_(PR #NNN merged: <summary>)_` on the
item it delivered, or in the report). Once every row is accounted for,
remove the section from the issue body.
5. **archive-at-close: mark the `## 工件索引` comment archived** (归档动作 — [TT-1929]). Issue
closing IS the archive-at-close action; it is explicit, not implicit. Edit the index
comment in place per `_shared/gitea-write-patterns.md` Pattern 10 Archive-at-close
(mechanism — banner + every row's 重读 → ARCHIVE + invariants — is defined there,
do not restate; sequence/actor per `rules/issue-checklist-sync.md` § 归档动作).
- Skip if no source issue exists.
- **Tier 1 run archive** ([TT-1988] two-tier artifacts — only if a Tier 1 run
workspace exists): if `<runs-root>/{slug}/` exists (a stage in this run
produced Tier 1 local artifacts, e.g. review-code findings), archive the
run workspace per `core/rules/two-tier-artifacts.md` § Archive-at-close
(the L1 rule is authoritative — do NOT restate its steps here).
The archived bundle must pass
`core/schemas/runs-bundle.schema.json` validation (the generator
validates by default; a red exit blocks close).
Verify deltas only: skip in milestone/task DAG mode (the aggregator agent
performs it at Epic/task-ticket close — see the DAG branch below).
6. **Update the issue body** via `工单 API(见 TERMINOLOGY)update` with the annotated
checklist. Preserve all non-checklist content unchanged.
7. **Verify**: re-read the issue and confirm no `- [ ]` item lacks an
annotation. Every unchecked item MUST have a `(Deferred: ...)` or
`(Pending: ...)` note explaining why it is not done.
8. **Close the issue** (completes the archive-at-close loop): if the flow has
no PR (no `Closes #N` on merge), the Verifier closes the issue after PASS
approval via `工单 API(见 TERMINOLOGY)update(state="closed")` — the banner date is
corrected to the actual close date if it differs from today. If a PR carries
`Closes #N`, the merge closes it; no further action.
If a checklist item cannot be mapped to evidence, deferral, or pending
status, the iteration is NOT Done — the item represents untracked scope.
+1 -1
View File
@@ -2,7 +2,7 @@
name: writing-skills name: writing-skills
description: Use ONLY when creating, editing, or evaluating an octopus skill — writing the SKILL.md body, deciding whether a skill needs baseline testing, or running a blind A/B eval of a behavior-shaping technique. Use BEFORE first deployment of any skill that must hold a process gate under pressure. description: Use ONLY when creating, editing, or evaluating an octopus skill — writing the SKILL.md body, deciding whether a skill needs baseline testing, or running a blind A/B eval of a behavior-shaping technique. Use BEFORE first deployment of any skill that must hold a process gate under pressure.
triggers: triggers:
# High-discrimination phrases only ([org-internal #4525]). We deliberately do NOT use: # High-discrimination phrases only ([TT-4525]). We deliberately do NOT use:
# - bare "skill" / 技能 — collides with every skill discussion. Worse: the # - bare "skill" / 技能 — collides with every skill discussion. Worse: the
# hard skill gate folds the previous assistant turn into its match text on # hard skill gate folds the previous assistant turn into its match text on
# approval turns, so any model reply containing 技能 (e.g. a gate # approval turns, so any model reply containing 技能 (e.g. a gate
+4 -4
View File
@@ -15,7 +15,7 @@
| 项 | 内容 | | 项 | 内容 |
|---|---| |---|---|
| slug / 源 DAG 父级 | `{epic-slug}` / #N(`## 父级 / Parent`;DAG 父级 = `Kind/Epic` 或 `Kind/Feature`,[org-internal #3061] 阶段 2——文中「Epic scope」泛指源工单 scope) | | slug / 源 DAG 父级 | `{epic-slug}` / #N(`## 父级 / Parent`;DAG 父级 = `Kind/Epic` 或 `Kind/Feature`,[TT-3061] 阶段 2——文中「Epic scope」泛指源工单 scope) |
| 单门 | `review-dag`(TOPO / REQMAP / RELEASE 三维,深度由 `dag_metrics` 导出) | | 单门 | `review-dag`(TOPO / REQMAP / RELEASE 三维,深度由 `dag_metrics` 导出) |
| 评审深度 | `D1 | D2 | D3 | D4`(`dag_metrics.review_depth`) | | 评审深度 | `D1 | D2 | D3 | D4`(`dag_metrics.review_depth`) |
@@ -24,13 +24,13 @@
> 仅登记功能性需求(Epic scope 项中的功能性条目)。产品 NFR 不占 `REQ-F` 编号、 > 仅登记功能性需求(Epic scope 项中的功能性条目)。产品 NFR 不占 `REQ-F` 编号、
> 不登记入表、以 `NFR:` 前缀条目落节点 AC(见 §3 `acceptance_criteria`)。 > 不登记入表、以 `NFR:` 前缀条目落节点 AC(见 §3 `acceptance_criteria`)。
> 登记表登记的是「提出者写了什么」;§2.1 类目覆盖矩阵补上「还有什么该问的」 > 登记表登记的是「提出者写了什么」;§2.1 类目覆盖矩阵补上「还有什么该问的」
> ([org-internal #2905]:legacy elicitation 广度扫描被折叠后的补偿层——`表 ↔ 现实` 完备性)。 > ([TT-2905]:legacy elicitation 广度扫描被折叠后的补偿层——`表 ↔ 现实` 完备性)。
| id | title | source | refs_by | | id | title | source | refs_by |
|---|---|---|---| |---|---|---|---|
| REQ-F-001 | {需求标题} | {Epic scope 项} | {引用节点 id 集} | | REQ-F-001 | {需求标题} | {Epic scope 项} | {引用节点 id 集} |
### 2.1 类目覆盖矩阵([org-internal #2905] 方案 1) ### 2.1 类目覆盖矩阵([TT-2905] 方案 1)
> 固定类目集(≤10 类,自 legacy `.octopus/archive/checklists/requirements-analysis.md` CMP/SAF 维抽取)。 > 固定类目集(≤10 类,自 legacy `.octopus/archive/checklists/requirements-analysis.md` CMP/SAF 维抽取)。
> 每类目状态 ∈ {已覆盖, 明确排除, 待确认}: > 每类目状态 ∈ {已覆盖, 明确排除, 待确认}:
@@ -55,7 +55,7 @@
| 错误与边界场景(CMP 1.11:空输入/边界值/异常状态,Epic 级;节点级路径覆盖由 REQMAP「AC 路径覆盖」承担) | {已覆盖/明确排除/待确认} | {证据/指针} | | 错误与边界场景(CMP 1.11:空输入/边界值/异常状态,Epic 级;节点级路径覆盖由 REQMAP「AC 路径覆盖」承担) | {已覆盖/明确排除/待确认} | {证据/指针} |
| 假设与依赖(CMP 1.9:列出并评估影响) | {已覆盖/明确排除/待确认} | {证据/指针} | | 假设与依赖(CMP 1.9:列出并评估影响) | {已覆盖/明确排除/待确认} | {证据/指针} |
### 2.2 排除账本([org-internal #2905] 方案 1) ### 2.2 排除账本([TT-2905] 方案 1)
> 「明确排除」的唯一凭证登记处。每行一条 `E-n`:条目 — out of scope、理由、确认人。 > 「明确排除」的唯一凭证登记处。每行一条 `E-n`:条目 — out of scope、理由、确认人。
> 排除可逆:重开时删行并把 §2.1 矩阵状态改为「已覆盖/待确认」,同一次修订内完成。 > 排除可逆:重开时删行并把 §2.1 矩阵状态改为「已覆盖/待确认」,同一次修订内完成。
+24 -24
View File
@@ -5,17 +5,17 @@ Normative layout for **Tier 1 local structured artifacts**. Authoritative
boundary rule: `core/rules/two-tier-artifacts.md`. Schemas that validate boundary rule: `core/rules/two-tier-artifacts.md`. Schemas that validate
the structured files below live in `core/schemas/runs-*.schema.json`. the structured files below live in `core/schemas/runs-*.schema.json`.
This document is the **foundation** (MVP slice, [org-internal #1968]). It defines the This document is the **foundation** (MVP slice, [TT-1968]). It defines the
container, the manifest, and the metadata. Stage-specific artifact schemas container, the manifest, and the metadata. Stage-specific artifact schemas
(design detail dumps, plan items, review dimension findings, synthesis (design detail dumps, plan items, review dimension findings, synthesis
prompts, draft contracts) are added incrementally as each skill migrates its prompts, draft contracts) are added incrementally as each skill migrates its
transient output here — the follow-up iteration ([org-internal #1988]) has landed: `review-artifact` / transient output here — the follow-up iteration ([TT-1988]) has landed: `review-artifact` /
`audit-process` raw findings and producer working drafts are now Tier 1. `audit-process` raw findings and producer working drafts are now Tier 1.
([org-internal #3072] phase 3, 2026-08-21: the legacy producer stages whose drafts are listed ([TT-3072] phase 3, 2026-08-21: the legacy producer stages whose drafts are listed
below were archived — their rows and artifact dirs are kept for reading below were archived — their rows and artifact dirs are kept for reading
historical run bundles.) See the migrated stages table below. historical run bundles.) See the migrated stages table below.
## Kind/MVP mode ([org-internal #3061]) ## Kind/MVP mode ([TT-3061])
`Kind/MVP` tickets write **nothing** to `<runs-root>/` by design — no stage `Kind/MVP` tickets write **nothing** to `<runs-root>/` by design — no stage
dirs, no `index.json`, no manifest. The ticket body is the doc (`## 决策日志` dirs, no `index.json`, no manifest. The ticket body is the doc (`## 决策日志`
@@ -47,8 +47,8 @@ for human-visible decisions.
└── {active-slug}/ # GITIGNORED — one subdir per active run └── {active-slug}/ # GITIGNORED — one subdir per active run
├── meta.json # run metadata (runs-meta.schema.json) ├── meta.json # run metadata (runs-meta.schema.json)
├── index.json # artifact manifest (runs-index.schema.json) ├── index.json # artifact manifest (runs-index.schema.json)
├── working-notes.md # cross-stage narrative memory ([org-internal #2600], schema-less md) ├── working-notes.md # cross-stage narrative memory ([TT-2600], schema-less md)
├── workers/ # worker final-return reports ([org-internal #2847], schema-less md — ├── workers/ # worker final-return reports ([TT-2847], schema-less md —
│ └── ... # see _shared/worker-report-persistence.md) │ └── ... # see _shared/worker-report-persistence.md)
└── {stage}/ # per-stage transient artifacts (added by skills) └── {stage}/ # per-stage transient artifacts (added by skills)
└── ... # json (structured) / md (prompt files) └── ... # json (structured) / md (prompt files)
@@ -61,7 +61,7 @@ for human-visible decisions.
- **Gitignored** while active — subagents share the worktree, not the git - **Gitignored** while active — subagents share the worktree, not the git
history, so active-run content stays local (no repo bloat, no merge noise). history, so active-run content stays local (no repo bloat, no merge noise).
- **Initialized at run start** by `bun <harness-package>/script/runs-init.ts - **Initialized at run start** by `bun <harness-package>/script/runs-init.ts
--slug {slug} --ticket N [--branch …] [--worktree …]` ([org-internal #3642]) — the --slug {slug} --ticket N [--branch …] [--worktree …]` ([TT-3642]) — the
producing role / Orchestrator runs the script (hand-writing the files is the producing role / Orchestrator runs the script (hand-writing the files is the
legacy path): it creates the `{active-slug}/` workspace, writes `meta.json` legacy path): it creates the `{active-slug}/` workspace, writes `meta.json`
with `state: "active"` and the run's slug/branch/worktree/ticket (branch with `state: "active"` and the run's slug/branch/worktree/ticket (branch
@@ -118,7 +118,7 @@ issue comment: the former is the agent's compact-recovery entry; the latter is
the human-visible traceability hub. They are kept in sync by the producing the human-visible traceability hub. They are kept in sync by the producing
role but serve different consumers. role but serve different consumers.
### `working-notes.md` — cross-stage narrative memory ([org-internal #2600]) ### `working-notes.md` — cross-stage narrative memory ([TT-2600])
`index.json` is a MANIFEST: it records WHAT artifacts exist. It does not `index.json` is a MANIFEST: it records WHAT artifacts exist. It does not
carry WHY code was written that way, which paths were tried and abandoned, or carry WHY code was written that way, which paths were tried and abandoned, or
@@ -148,7 +148,7 @@ is that narrative memory, in-file, append-only:
decision ✓, never referenced cross-worktree ✓, archivable at close ✓ — all decision ✓, never referenced cross-worktree ✓, archivable at close ✓ — all
four Tier 1 conditions hold (`core/rules/two-tier-artifacts.md` 判据). four Tier 1 conditions hold (`core/rules/two-tier-artifacts.md` 判据).
### `workers/` — worker final-return reports ([org-internal #2847]) ### `workers/` — worker final-return reports ([TT-2847])
Every worker sub-agent dispatch (`agent: worker` roles — Producer Every worker sub-agent dispatch (`agent: worker` roles — Producer
sub-roles, Verifier, Synthesizer) persists its **final return report** sub-roles, Verifier, Synthesizer) persists its **final return report**
@@ -164,7 +164,7 @@ generic name. `index.json` row: `type: "other"`, `schema: null`, `stage` =
producing stage, `produced_by` = role. Full convention: producing stage, `produced_by` = role. Full convention:
`core/skills/_shared/worker-report-persistence.md`. `core/skills/_shared/worker-report-persistence.md`.
### `browser/` — browser evidence packs ([org-internal #4497] N-03) ### `browser/` — browser evidence packs ([TT-4497] N-03)
A browser-debug session writes one evidence pack per session under A browser-debug session writes one evidence pack per session under
`browser/{session-id}/` (contract `browser-evidence-4486/shared/pack-manifest-v1`, `browser/{session-id}/` (contract `browser-evidence-4486/shared/pack-manifest-v1`,
@@ -204,20 +204,20 @@ Conventions established by this foundation:
- A stage that has not yet migrated continues to write to Gitea (Tier 2) per its - A stage that has not yet migrated continues to write to Gitea (Tier 2) per its
existing skill body — the two tiers coexist during the migration. existing skill body — the two tiers coexist during the migration.
**Migrated stages ([org-internal #1988]):** **Migrated stages ([TT-1988]):**
| Stage | Skill | Tier 1 artifacts | Schema | Notes | | Stage | Skill | Tier 1 artifacts | Schema | Notes |
|---|---|---|---|---| |---|---|---|---|---|
| `review-code` | review-code | `reviews/code/round{N}/findings-{DIM}.json` (raw dimension findings), `reviews/code/round{N}/task-synthesizer.md` (synthesis prompt) | `reviewer-output.schema.json` (findings) | synthesis comment + commit status stay Tier 2 | | `review-code` | review-code | `reviews/code/round{N}/findings-{DIM}.json` (raw dimension findings), `reviews/code/round{N}/task-synthesizer.md` (synthesis prompt) | `reviewer-output.schema.json` (findings) | synthesis comment + commit status stay Tier 2 |
| `review-roadmap` | review | `reviews/roadmap/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([org-internal #3072] phase 3) — row kept for historical bundles | | `review-roadmap` | review | `reviews/roadmap/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([TT-3072] phase 3) — row kept for historical bundles |
| `review-design-space` | review | `reviews/design-space/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([org-internal #3072] phase 3) — row kept for historical bundles | | `review-design-space` | review | `reviews/design-space/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([TT-3072] phase 3) — row kept for historical bundles |
| `review-iteration-plan` | review | `reviews/plan/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([org-internal #3072] phase 3) — row kept for historical bundles | | `review-iteration-plan` | review | `reviews/plan/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | legacy target archived ([TT-3072] phase 3) — row kept for historical bundles |
| `review-dag` | review | `reviews/review-dag/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | synthesis comment + commit status stay Tier 2 | | `review-dag` | review | `reviews/review-dag/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | synthesis comment + commit status stay Tier 2 |
| `audit-process` | review | `reviews/audit-process/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | synthesis wiki page + commit status stay Tier 2 | | `audit-process` | review | `reviews/audit-process/round{N}/findings-{DIM}.json` | `reviewer-output.schema.json` | synthesis wiki page + commit status stay Tier 2 |
| `requirements` (drafts) | requirements-elicitation | `requirements/` (schema-less `.md`/`.json`) | — | legacy skill archived ([org-internal #3072] phase 3) — historical bundles only | | `requirements` (drafts) | requirements-elicitation | `requirements/` (schema-less `.md`/`.json`) | — | legacy skill archived ([TT-3072] phase 3) — historical bundles only |
| `design` (drafts) | design | `design/` (schema-less or `design-detail.schema.json`) | `design-detail.schema.json` (moved to `<instance-root>/archive/schemas/` [org-internal #3072] phase 3) | legacy skill archived ([org-internal #3072] phase 3) — historical bundles only | | `design` (drafts) | design | `design/` (schema-less or `design-detail.schema.json`) | `design-detail.schema.json` (moved to `<instance-root>/archive/schemas/` [TT-3072] phase 3) | legacy skill archived ([TT-3072] phase 3) — historical bundles only |
| `plan-iterations` (drafts) | plan-iterations | `plan-iterations/` (schema-less or `plan-items.schema.json`) | `plan-items.schema.json` (moved to `<instance-root>/archive/schemas/` [org-internal #3072] phase 3) | legacy skill archived ([org-internal #3072] phase 3) — historical bundles only | | `plan-iterations` (drafts) | plan-iterations | `plan-iterations/` (schema-less or `plan-items.schema.json`) | `plan-items.schema.json` (moved to `<instance-root>/archive/schemas/` [TT-3072] phase 3) | legacy skill archived ([TT-3072] phase 3) — historical bundles only |
| `roadmap` (draft contracts) | roadmap | `roadmap/contracts/{name}.json` | `draft-contract.schema.json` (moved to `<instance-root>/archive/schemas/` [org-internal #3072] phase 3) | legacy skill archived ([org-internal #3072] phase 3) — historical bundles only | | `roadmap` (draft contracts) | roadmap | `roadmap/contracts/{name}.json` | `draft-contract.schema.json` (moved to `<instance-root>/archive/schemas/` [TT-3072] phase 3) | legacy skill archived ([TT-3072] phase 3) — historical bundles only |
Every review/audit stage additionally maintains a per-stage lifecycle file Every review/audit stage additionally maintains a per-stage lifecycle file
`reviews/{stage}/status.json` (schema `review-status.schema.json`) — live `reviews/{stage}/status.json` (schema `review-status.schema.json`) — live
@@ -241,24 +241,24 @@ enters git history:
2. Write `archive/{slug}.json` — a compact bundle carrying `meta` + the 2. Write `archive/{slug}.json` — a compact bundle carrying `meta` + the
`index.json` manifest (the durable trace; bulk artifacts are summarized by `index.json` manifest (the durable trace; bulk artifacts are summarized by
digest, not copied wholesale, to keep the archive small). One exception digest, not copied wholesale, to keep the archive small). One exception
([org-internal #2600]): when `working-notes.md` exists, its final content is inlined as ([TT-2600]): when `working-notes.md` exists, its final content is inlined as
the bundle's top-level `working_notes` field — the narrative memory is the the bundle's top-level `working_notes` field — the narrative memory is the
single artifact whose content (not just digest) rides in the bundle, single artifact whose content (not just digest) rides in the bundle,
feeding later retro probes and the notes-injection degradation path feeding later retro probes and the notes-injection degradation path
([org-internal #2601]). The bundle is validated by `runs-bundle.schema.json`. ([TT-2601]). The bundle is validated by `runs-bundle.schema.json`.
Offline review verifiability (TD/TRC-F006, [org-internal #2688]): for each review stage Offline review verifiability (TD/TRC-F006, [TT-2688]): for each review stage
the run executed, also embed a top-level `review_history` entry in the the run executed, also embed a top-level `review_history` entry in the
bundle — `{stage, rounds, final_verdict, per_round[]}` (per-round: bundle — `{stage, rounds, final_verdict, per_round[]}` (per-round:
round/overall_verdict/blockers/majors/minors) — derived from that stage's round/overall_verdict/blockers/majors/minors) — derived from that stage's
live `reviews/{stage}/status.json` `history[]`. Closed-run probes can then live `reviews/{stage}/status.json` `history[]`. Closed-run probes can then
reconstruct round counts and verdicts from the bundle alone, without the reconstruct round counts and verdicts from the bundle alone, without the
removed workspace or artifact-path reconstruction ([org-internal #2591]). removed workspace or artifact-path reconstruction ([TT-2591]).
3. `git add archive/{slug}.json` and commit on the workflow branch (rides into 3. `git add archive/{slug}.json` and commit on the workflow branch (rides into
main via the `--no-ff` merge). main via the `--no-ff` merge).
4. Remove the `{active-slug}/` workspace from the worktree (its durable record 4. Remove the `{active-slug}/` workspace from the worktree (its durable record
now lives in the archive bundle). now lives in the archive bundle).
Steps 1–4 collapse into ONE command ([org-internal #3642]): `bash script/archive-run.sh Steps 1–4 collapse into ONE command ([TT-3642]): `bash script/archive-run.sh
{slug} [--pr N]` — run from the session worktree, it resolves the PR by branch {slug} [--pr N]` — run from the session worktree, it resolves the PR by branch
head, generates + validates the bundle via `gen-run-bundle.ts` (recording head, generates + validates the bundle via `gen-run-bundle.ts` (recording
`closed_at` / `close_commit_sha` and the `--branch` workflow branch), commits `closed_at` / `close_commit_sha` and the `--branch` workflow branch), commits
@@ -274,7 +274,7 @@ Gitea tax.
## Relationship to existing mechanisms ## Relationship to existing mechanisms
- **`/tmp/octopus/` embryo** — `review-code` ([org-internal #1988] MVP) now writes its - **`/tmp/octopus/` embryo** — `review-code` ([TT-1988] MVP) now writes its
synthesis prompt under `<runs-root>/{slug}/reviews/code/` instead of synthesis prompt under `<runs-root>/{slug}/reviews/code/` instead of
`/tmp/octopus/synthesis_task_*`. Other skills still using the `/tmp/octopus/` `/tmp/octopus/synthesis_task_*`. Other skills still using the `/tmp/octopus/`
embryo coexist until their own migration iteration. embryo coexist until their own migration iteration.
+3 -1
View File
@@ -3,7 +3,9 @@
import fs from "node:fs" import fs from "node:fs"
import path from "node:path" import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..") const scriptDir = (import.meta as { dir?: string }).dir
?? new URL(".", import.meta.url).pathname
const ROOT = path.resolve(scriptDir, "..")
const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json") const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json")
const CORE_ROOT = path.join(ROOT, "core") const CORE_ROOT = path.join(ROOT, "core")
+3 -1
View File
@@ -3,7 +3,9 @@
import fs from "node:fs" import fs from "node:fs"
import path from "node:path" import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..") const scriptDir = (import.meta as { dir?: string }).dir
?? new URL(".", import.meta.url).pathname
const ROOT = path.resolve(scriptDir, "..")
const CORE_ROOT = path.join(ROOT, "core") const CORE_ROOT = path.join(ROOT, "core")
const EXEMPT = new Set(["core/schemas/id-aliases.json"]) const EXEMPT = new Set(["core/schemas/id-aliases.json"])
+3 -1
View File
@@ -3,7 +3,9 @@
import fs from "node:fs" import fs from "node:fs"
import path from "node:path" import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..") const scriptDir = (import.meta as { dir?: string }).dir
?? new URL(".", import.meta.url).pathname
const ROOT = path.resolve(scriptDir, "..")
const CORE_DIR = path.join(ROOT, "core") const CORE_DIR = path.join(ROOT, "core")
const SCAN_EXTENSIONS = new Set([".md", ".json", ".ts", ".tsx", ".js", ".mjs", ".cjs", ".yaml", ".yml", ".txt"]) const SCAN_EXTENSIONS = new Set([".md", ".json", ".ts", ".tsx", ".js", ".mjs", ".cjs", ".yaml", ".yml", ".txt"])
+23 -3
View File
@@ -3,12 +3,20 @@
import fs from "node:fs" import fs from "node:fs"
import path from "node:path" import path from "node:path"
const ROOT = path.resolve(import.meta.dir, "..") // Runtime-neutral: works under bun and node>=20.9 (--experimental-strip-types).
const scriptDir = (import.meta as { dir?: string }).dir
?? new URL(".", import.meta.url).pathname
const ROOT = path.resolve(scriptDir, "..")
const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json") const MANIFEST_PATH = path.join(ROOT, "core", "CORE-MANIFEST.json")
const CHECK = process.argv.includes("--check") const CHECK = process.argv.includes("--check")
// --strip: rewrite remaining `[org-internal #NNNN]` annotations to a compact
// provenance form `[TT-NNNN]` (org ticket id, non-navigable in the standalone
// repo) and fold the wordy placeholder away. Idempotent like the base pass.
const STRIP = process.argv.includes("--strip")
const REF_RE = /\B#(\d{3,5})\b/g const REF_RE = /\B#(\d{3,5})\b/g
const PLACEHOLDER = "org-internal" const PLACEHOLDER = "org-internal"
const STRIP_RE = /\[org-internal[ \t]*#(\d{3,5})\]/g
interface Mapping { interface Mapping {
core: string core: string
@@ -61,6 +69,16 @@ function transformContent(content: string): { next: string; count: number } {
return { next, count } return { next, count }
} }
// --strip pass: `[org-internal #NNNN]` → `[TT-NNNN]` (provenance-only ticket id).
function stripContent(content: string): { next: string; count: number } {
let count = 0
const next = content.replace(STRIP_RE, (_match, digits: string) => {
count++
return `[TT-${digits}]`
})
return { next, count }
}
export function transformContentForTest(content: string): { next: string; count: number } { export function transformContentForTest(content: string): { next: string; count: number } {
return transformContent(content) return transformContent(content)
} }
@@ -73,7 +91,8 @@ let replacedTotal = 0
for (const rel of files) { for (const rel of files) {
const fullRel = `core/${rel}` const fullRel = `core/${rel}`
const content = fs.readFileSync(path.join(ROOT, "core", rel), "utf8") const content = fs.readFileSync(path.join(ROOT, "core", rel), "utf8")
const { next, count } = transformContent(content) const result = STRIP ? stripContent(content) : transformContent(content)
const { next, count } = result
if (count === 0) continue if (count === 0) continue
if (byteLocked.has(fullRel)) { if (byteLocked.has(fullRel)) {
deferredLocked.push({ file: fullRel, count }) deferredLocked.push({ file: fullRel, count })
@@ -101,7 +120,8 @@ if (CHECK) {
process.exit(0) process.exit(0)
} }
console.log(`delink-core: replaced ${replacedTotal} refs across ${perFile.length} file(s)`) const mode = STRIP ? "stripped" : "replaced"
console.log(`delink-core: ${mode} ${replacedTotal} refs across ${perFile.length} file(s)`)
const top = [...perFile, ...deferredLocked].sort((a, b) => b.count - a.count).slice(0, 10) const top = [...perFile, ...deferredLocked].sort((a, b) => b.count - a.count).slice(0, 10)
for (const p of top) console.log(` ${p.file}: ${p.count}`) for (const p of top) console.log(` ${p.file}: ${p.count}`)
process.exit(0) process.exit(0)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "octopus-workflow", "name": "octopus-workflow",
"version": "0.1.3", "version": "0.1.4",
"description": "Standalone workflow core: provider-neutral agent workflow corpus (skills / rules / checklists / templates / schemas) with drift guards, extracted from the octopus agent platform.", "description": "Standalone workflow core: provider-neutral agent workflow corpus (skills / rules / checklists / templates / schemas) with drift guards, extracted from the octopus agent platform.",
"license": "MIT", "license": "MIT",
"private": false, "private": false,
+78
View File
@@ -0,0 +1,78 @@
# 项目复盘 — wechat-ops 个人微信 GUI 自动化值守 Agent
> 迭代周期:2026-09-29 一天(迭代0 环境搭建 → 迭代1 五功能 → 迭代2 DAG 就位)
> 方法:Loong Workflow 复盘清单(DATA / ANAL / ACT / LOOP / SAFE)
> 复盘人:kenyang + ZCode Agent
---
## 0. 项目快照
| 项 | 值 |
|---|---|
| 交付物 | GitHub + Loong Gitea 双远端 wechat-ops(skILL 包 + 服务器部署版,md5 一致) |
| 代码规模 | agent.py ~650 行 + vision.py + setup-server.sh + 守卫脚本 |
| 运行状态 | 阿里云 2核2G,auto/draft 值守中,可用内存 ~720Mi |
| 版本轨迹 | v0.1.0 初版 → v0.2.x 安全加固 → v0.3.x ima 知识库 → v0.4.x Loong 工作流捆绑 |
## 1. 数据(DATA)
**功能交付**:迭代1 五项全部实现并验证(独立Prompt/记忆/群@检测/链接阅读/图标模板匹配);ima OpenAPI 当天逆向对接(官方文档缺字段不一致,实测修正)。
**真实流量拦截记录**(守卫闸门的实战证据):
- 标题核验拦截误发:6+ 次(误定位到 第一财经/大刘家/杨家小极客/张秀英/纯臻群/刘家四兄弟姐妹)
- 白名单外跳过:9+ 次(张秀英门店运营群、2组1号、Service Accounts 等)
- 群 @ 闸门:未@消息全部仅记录不响应
**事故清单**(每条有日志/截图证据):
1. 私聊消息误发 227 人群(坐标偏移+无核验,用户手动撤回)
2. Escape 键打崩微信渲染→透明壳→自愈误判重启→登录会话丢失(被迫重扫码 3 次)
3. 定时任务队列被清空且重复触发 20 秒循环(FT 收到 ~50 条测试消息)
4. 工单误关 4 张(#6/#7/#8/#9 号映射错误,事后纠正)
5. linux-server.md 被存根覆盖丢失 90 行(git 历史恢复)
6. ima 官方文档字段与实际 API 不一致(id/name vs kb_id/kb_name)
## 2. 优点(可复用模式)
1. **安全闸门代码化且实战有效**:标题核验(空标题拒绝)、白名单、限速、静默、敏感词回退——全部误发被拦,零事故外泄。模式:闸门必须写成函数,不写成散文。
2. **自愈状态机**:托盘隐匿/透明壳/登录过期/过渡态保护,一夜之间无人工干预恢复值守。模式:每种故障先做"最坏情况审查"再加处理分支。
3. **像素级兜底 + 自学习模板**:FT 图标颜色候选 + 9×9 模板最小距离(校准:真身<10万,误配 270万+),核验成功后自学习存模板。
4. **知识库两级接入**:文件导出兜底 + OpenAPI 直连优先,当天完成无官方文档接口的逆向对接(实测修正字段名)。
5. **诚实文化**:幻觉试答拒绝发送;错误关票发状态修正评论;证据分级表述(已验证:证据 / 未验证:待确认)。
6. **真实用户即时反馈**:群里演示后,当晚有成员尝试部署、有成员购入服务器——开源定位(纯视觉替代付费 Proxy API)得到验证。
## 3. 缺点与根因(归因流程/工具,不归因个人)
| # | 缺点 | 根因(流程/工具缺口) |
|---|---|---|
| 1 | GUI 自动化固有脆弱:窗口自发隐匿、渲染透明壳、Escape 打崩渲染,全天 5+ 次异常 | 微信 Qt 客户端不可控;缺"故障注入"式预防测试,只有事后补丁 |
| 2 | 免费视觉模型定位误读(臻→甄、槽位名字偏差),需模板/模糊匹配补丁补偿 | 无离线评测集:视觉提示词从未做过基线测试,每个误读都是第一次见 |
| 3 | 定时任务重复触发 20 秒循环,根因未明(run_due_tasks 曾将未到期任务判为 due) | 缺"决策日志→断言"的最小复现方法论;护栏先于根因分析上线,护栏自身又制造新循环 |
| 4 | 群发误投事故 | 无"发送目标 dry-run"预检步骤;核验闸门是事故后补的 |
| 5 | 工单误关 4 张(映射错误) | 关票动作无"工单号↔标题"双重校验;单人无评审 |
| 6 | 文档被存根覆盖 90 行 | 文件同步用 cp 而非 git,缺 pre-commit 保护 |
| 7 | 测试污染真实会话(FT ~50 条消息) | 无测试专用会话/账号隔离机制 |
## 4. 行动项(ACT,≤5,每条有文件路径与完成判据)
| # | 行动项 | 文件 | 完成判据 |
|---|---|---|---|
| 1 | N-04:定时任务重复触发复现(利用 save_tasks([]) 溯源栈日志) | scripts/agent.py run_due_tasks | 同一任务 3 次评估仅触发 1 次发送 |
| 2 | N-05:白名单 difflib≥0.6 模糊匹配(已实现待回归) + 群名 OCR 变体测试用例集 | scripts/agent.py handle_trigger | 「纯甄AI赋能1688」命中白名单 |
| 3 | N-01:图片发送链路(表情包前置) | scripts/agent.py send_image | 测试图片送达 File Transfer |
| 4 | 上架前置:守卫脚本增加"凭证/隐私 HARD 扫描"进 CI(双远端推送前自动跑) | scripts/check-skill.sh + Loong Gitea workflow | push 即自动扫描 |
| 5 | ima 检索评测集:收集 10 条真实问题-期望文档对,做召回率基线 | references/ima-eval.md(新建) | 召回率报告存在且 ≥8/10 |
## 5. 闭环(LOOP)
- 本文写入 loong-workflow 仓库 retrospectives/
- ACT#1/#2 相关坑已沉淀 pitfalls-linux.md(#18/#19/#20)
- 迭代2 DAG 已发布 Loong Gitea wiki(wechat-ops-iter2/dag),N-01 工单已建(#14)
## 6. 无指责声明(SAFE)
所有失误(群发误投、误关工单、文档覆盖、护栏制造循环)归因于:**流程缺口**(无 dry-run、无双人评审、无离线测试集、护栏先于根因分析),不归因于任何人的能力或态度。相应修复均已落入上述 ACT 项。
## 7. 一句话总结
**一天内从裸机到开源值守 Agent,安全闸门零失效,但稳定性工程(故障注入测试、离线评测集、双人评审)仍是单人项目的最大短板——这三样是迭代2 的主攻方向。**