Files
.pouch/skills/ack/references/closed-loop.md
T

298 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 闭环流程(稳定核心,编排无关)
本文件定义**与具体编排工具无关**的三角色协作闭环。运行时调度可以用 Orca(见 `orca-adapter.md`),也可以手动跑(见下方「手动模式」)。
原则:调度消息只是运行时载体,任务结论必须回写到 `tasks.yaml`;已经验证且可跨
任务使用的项目经验必须由 Coordinator 回写到 `knowledge.yaml`。不要把消息当最终记录。
角色定义见 `roles-and-permissions.md`Coordinator 只编排、Test 只验证、
Developer 只实现。
---
## 编排抽象
无论用什么工具,闭环都由这几个能力组成。注意 `dispatch` 有两个目标(Developer 与 Test):
| 抽象动作 | 含义 | Orca 实现 | 手动实现 |
|----------|------|-----------|----------|
| `prepare(task)` | Coordinator 把任务和验收信号写进 `tasks.yaml`,按 scope 推荐知识并确认显式 `knowledgeRefs` | 同左 | 同左 |
| `dispatch(task, developer)` | 把修复任务连同上下文交给 Developer | `orca orchestration dispatch` | 复制 prompt 到 Developer 终端/会话 |
| `dispatch(task, test)` | 把复测任务连同验收信号交给 Test | `orca orchestration dispatch` | 复制 prompt 到 Test 终端/会话 |
| `wait()` | 等待 `worker_done` / `retest_result` / `escalation` / `decision_gate` | `orca orchestration check --wait` | 人工等待回报 |
| `gate(task)` | Coordinator 读 Test 证据、`knowledgeChecks` 并对齐原始意图(不重测) | 同左 | 同左 |
| `writeback(task, result)` | Coordinator 把任务结果写回 `tasks.yaml`,把验证通过的跨任务经验按权限写入 `knowledge.yaml` | 同左 | 同左 |
派发用的 prompt 见 `prompt-templates.md`。状态流转见 `roles-and-permissions.md` §「任务状态机」。**独立复测由 Test 执行,不是 Coordinator**Coordinator 只做读证据的终检。
---
## 标准闭环
```text
Coordinator 发现或读取 open 任务
-> prepare:写/补全 tasks.yaml 验收信号
-> 从 knowledge.yaml 按 scope 推荐 active 知识,Coordinator 确认固定 revision 的 knowledgeRefs
-> 为新轮次生成稳定 attemptId<task-id>-A<round>),Developer 与 Test 共用
-> 决定 worktree:当前 worktree 起子 agent,还是新建隔离 worktree(见下节「子任务放哪」)
-> 解析安全 profile:机器配置只读 tasks.yaml.project.orchestration
-> 运行 launcher plan 并审阅 launchFingerprint
-> 带 expected fingerprint 启动 fresh worker,把 receipt 写回 tasks.yaml(见 orca-adapter.md
-> dispatch 给 Developer--to <worker handle>
-> waitDeveloper 的 worker_done / escalation(含 knowledgeApplied / knowledgeCandidates
-> writeback fixed_by_dev
-> 为 Test 独立解析安全 profile,重新 plan/launch fresh worker 并写回 receipt
-> dispatch 给 Testretesting
-> waitTest 的 retest_result(含 knowledgeChecks 和 candidate 独立证据)
-> Test 通过:gateCoordinator 读证据对齐意图)
-> 通过 gatewriteback verified
-> gate 不满足意图:writeback failed_retest,带意图差异再派发 Developer
-> Test 失败:writeback failed_retest,追加证据,再派发 Developer(最多累计三轮)
-> 累计三轮失败:writeback leftover,继续下一个任务
```
一次派发只修一个明确问题(细则见 `optimization-method.md` §「每轮派发只修一个明确问题」)。
「决定 worktree」「解析 profile/receipt」几步的决策见下节与 `model-routing.md` /
`orca-adapter.md`。v0.10 不自动复用历史 receipt 或既有终端;标题、preview、分支名、
worker 自报和无密钥 receipt checksum 都不能代替可信启动 attestation。
Coordinator 默认给新逻辑轮次生成 `<task-id>-A<round>`,并在记录轮次结果时写入
`tasks[].dispatch.rounds[].attemptId`。它独立于编排工具产生的 `taskId`
`dispatchId`:前者用于知识来源追溯,后两者只用于查询运行时。0.9.0 之前的历史
轮次允许暂时缺省;但要把该轮证据晋升为知识前,必须按确定性格式补齐。晋升时,
`provenance.taskId``provenance.attemptId` 必须能精确回到该任务及轮次。
### 知识选择与晋升
`prepare(task)` 时可以使用 Skill 自带的 `scripts/select_knowledge.py`
component、path、dependency、version 和 tag 确定性推荐条目。选择器只返回
`active`,并受条目数限制;`stale``superseded``archived` 不默认派发。自动
匹配只是推荐。条目中每个非空 scope 维度都必须被任务上下文命中,因此调用时应
提供当前任务已知的全部 component、path、dependency、version、tag、symbol 和错误
特征。Coordinator 确认并写入当前任务的显式 `knowledgeRefs` 后才成为本轮权威
上下文。
`scope.paths` 使用 POSIX 路径 glob`*` 不跨目录分隔符,`**` 才能跨目录。多个
pattern 是同一维度内的 OR,候选越多表示范围越宽;超过选择预算时,选择器优先保留
命中维度更多、OR 候选更少、字面约束更多且通配符更少的条目。
派发时只内联本轮引用的少量知识,不要求 worker 全量读取 `knowledge.yaml`。这也
避免隔离 worktree 读不到 Coordinator 工作树中尚未提交的项目状态。
进行中的任务只能引用 `active` 条目。已经进入 `verified``leftover` 的终态任务
可以继续保留固定 revision 的历史引用,即使对应知识后来变成 `stale`
`superseded``archived`;这些旧条目不会再次被选择器派发。
Developer 或 Test 发现经验时只能通过 `knowledgeCandidates` 提名,并带上当前任务
的独立观测、scope、触发条件和证据。candidate 留在任务证据中,不进入知识选择器,
也不能被下一轮当作 active 指令。只有 Test 独立验证、Coordinator gate 通过后,
Coordinator 才能写入或更新 `knowledge.yaml`;全项目强制或权限类规则还需
User / Decision Owner 确认。
Test 对显式引用回报 `not_applicable` 时,说明 Coordinator 的选择需要纠正。该引用
仍在 `knowledgeRefs` 中就不能把任务标为 `verified`Coordinator 应记录原因、移除
误选引用并重新校验,或继续补充验证。
知识中的 `verification.ref` 只能引用
`knowledge.yaml.verificationRegistry` 里已审查的仓库内相对 path 和结构化 args,
不能从知识正文拼接或执行自由 shell。Developer/Test 只把 `verification.ref` 交给
`<ack-skill-dir>/scripts/run_verification.py`;该入口从项目根目录逐段安全打开检查
文件,拒绝 symlink 路径,并从匿名稳定快照执行。关键约束应下沉为测试、lint、CI
或正式规范。检查进程从固定的项目根 fd cwd 运行;检查脚本应使用 cwd 或
`ACK_PROJECT_ROOT` 定位资源。后者是 fd 路径,原始展示路径只在
`ACK_PROJECT_ROOT_DISPLAY` 中用于日志;不能依赖 `$0` / `__file__` 的目录。
---
## 子任务放哪:新 worktree 还是当前 worktree
Coordinator 派发前先决定 Developer/Test 在哪工作。两种方式:
**方式 1:当前 worktree 起 fresh 子 agent(终端)**
```bash
# v0.10 不自动复用既有终端;先审阅 plan:
python3 <ack-skill-dir>/scripts/launch_worker.py plan \
--project-root <project-root> --task-id <task-id> \
--attempt-id <task-id>-A<round> --role <developer-or-test> \
--profile-id <profile-id> --worktree <absolute-current-worktree> --slot <1..99>
python3 <ack-skill-dir>/scripts/launch_worker.py launch \
--project-root <project-root> --task-id <task-id> \
--attempt-id <task-id>-A<round> --role <developer-or-test> \
--profile-id <profile-id> --worktree <absolute-current-worktree> --slot <1..99> \
--expected-launch-fingerprint <plan 中的 sha256:...>
```
- 适合:串行闭环、一次一个 Developer 任务、小改动、Test 要复测的正是 Developer 改的那棵树。
- 优点:单一服务实例、无跨 worktree 对齐困扰、开销小。
- 风险:多个 agent 同时改同一棵树会互相踩(半构建状态、git 冲突)。
- 记录:`launch` 成功后把 receipt 追加到权威 `tasks.yaml.workerReceipts`,并把
`receipt.id` 写入 `dispatch.<role>.receiptId`、把 `profileId` 写入
`dispatch.<role>.profileId`、把本轮稳定 ID 写入 `dispatch.<role>.attemptId`
receipt 的 task/role/profile/attempt 必须与当前 dispatch 完全一致,不能只记录
一个裸 handle,也不能引用旧任务或旧轮次 receipt。
**方式 2:新建隔离 worktree,再在其中起子 agent**
创建成功后,先把 Orca 返回的绝对路径加入权威任务板的
`project.orchestration.allowedWorktrees` 并重新运行 `validate_tasks.py`;未进入
allowlist 的路径不能交给 launcher。
```bash
orca worktree create --name <feature> --base-branch <base> --json
# 对返回的绝对路径调用 ACK launcher
python3 <ack-skill-dir>/scripts/launch_worker.py plan \
--project-root <project-root> --task-id <task-id> \
--attempt-id <task-id>-A<round> --role <developer-or-test> \
--profile-id <profile-id> --worktree <absolute-new-worktree> --slot <1..99>
python3 <ack-skill-dir>/scripts/launch_worker.py launch \
--project-root <project-root> --task-id <task-id> \
--attempt-id <task-id>-A<round> --role <developer-or-test> \
--profile-id <profile-id> --worktree <absolute-new-worktree> --slot <1..99> \
--expected-launch-fingerprint <plan 中的 sha256:...>
```
- 适合:并行多个互不依赖的子任务、大/高风险/实验性改动、要保持基线分支干净(如 prod 不动、feature 走独立分支)、要独立 build 或跑独立服务实例、best-of-N 尝试。
- 优点:隔离 + 并行 + 易回滚(删 worktree 即可)。
- 成本:各自 build/依赖、服务要用不同端口、必须处理下节的 worktree/服务对齐。
**决策速查:**
| 情况 | 选择 |
|------|------|
| 一次一个任务、串行修复 | 当前 worktree 子 agent |
| 多个任务并行、互不依赖 | 每个任务一个新 worktree |
| 高风险 / 实验 / 可能整体丢弃 | 新 worktree |
| 要保持基线分支干净 | 新 worktreefeature 分支)|
| 小改动、追求快 | 当前 worktree |
**项目状态(SSOT)只落一处**:无论开几个 worktree`tasks.yaml`
`knowledge.yaml` 都只认一个权威副本(通常在基线/协调所在 worktree),由
Coordinator 单写。`project.orchestration`、顶层 `workerReceipts` 和任务 dispatch
也只写入这个副本;不要每个 worktree 各留一份会分叉的项目状态。profile 解析、
launcher 与 receipt 规则见 `model-routing.md``orca-adapter.md`
两种 worktree 方式都只允许 profile 中的 `read-only` / `workspace-write` 安全权限。
v0.10 的 full-access 授权与撤销机制仍是 Deferredlauncher 遇到 full-access 或等价
的 sandbox 绕过请求必须 fail closed。
---
## 手动模式(无 Orca
没有编排工具时,闭环不变,只是 `dispatch` / `wait` 由人工承担:
1. Coordinator 在 `tasks.yaml` 写好任务和验收信号。
2.`knowledge.yaml` 推荐相关 active 知识,Coordinator 确认固定 revision 的
`knowledgeRefs`;用 `prompt-templates.md` §1 的初始派发模板生成 prompt,
手动发给 Developer(另一个会话/终端/人)。
3. Developer 完成后按 worker_done 模板回报。
4. Coordinator 写回 `fixed_by_dev`,用 `prompt-templates.md` §3 的复测派发模板把任务发给 Test。
5. Test 独立复测后按复测报告模板回报证据和 `knowledgeChecks`
6. Coordinator 做终检并回写 `tasks.yaml`:通过 `verified`,不过 `failed_retest`
7. 失败则用「复测失败再派发模板」重新发给 Developer,最多累计三轮。
手动模式下同样遵守:worker_done / 复测报告都不等于最终结论、只有 Coordinator
`tasks.yaml``knowledge.yaml`、三轮失败留档。
手动交给用户已打开的会话不等于产生 ACK receipt。该会话可以完成本次显式 handoff,
但不能因此进入 Orca 自动派发信任路径;后续自动派发仍需重新通过 ACK launcher
创建 fresh worker。
---
## Test 复测(编排无关)
即使 Developer 的 worker_done 写了"全部通过"Test 仍必须独立复测:
```bash
git status --short
<test_commands>
curl -s <base_url>/health-or-summary
```
浏览器复测建议记录:
```text
BASE_URL:
page:
steps:
expected:
actual:
snapshot evidence:
```
Test 只回传证据,不写 `tasks.yaml``knowledge.yaml`;由 Coordinator 落盘。
每条适用的显式 `knowledgeRef` 还应报告 `passed``failed`
`not_applicable` 及证据。
---
## Coordinator 终检(gate
Test 报通过后,Coordinator 不重测,而是做一次读证据的终检:
- Test 证据是否覆盖了任务的**每一条**验收信号(见 `optimization-method.md` §1)。
- 当前任务显式 `knowledgeRefs` 的必需 `knowledgeChecks` 是否全部覆盖,检查引用
是否能解析到项目已审查的入口。
- 结果是否符合任务的**原始意图**,而不只是通过了字面文案。
- 运行环境是否对齐(见下方「服务与 worktree 对齐」)。
终检不通过(例如意图漂移、验收信号写漏)时,回写 `failed_retest` 并把意图差异带给下一轮 Developer,必要时先补全验收信号。
---
## 服务与 worktree 对齐(防假通过/假失败)
Test 复测前记录运行环境:
```bash
pwd
git rev-parse --abbrev-ref HEAD
git rev-parse --short HEAD
```
```text
serverPid:
serverCommand:
BASE_URL:
frontendDir:
worktreePath:
```
如果开发在 `<dev_worktree>` 修复,但服务跑的是另一个 worktree,必须**停止并重启正确服务**后再测。长跑服务或静态前端尤其要确认加载的是最新构建产物。
---
## 结果回写
Coordinator 回写 `tasks.yaml` 时按状态填写(字段结构见 `templates/tasks.schema.json`):
```yaml
# 通过(Test 复测 + Coordinator 终检)
status: verified
resolution:
verifiedAt: "<timestamp>"
verifiedBy: "test"
evidence:
verification: "<commands passed>"
browser: "<snapshot or API evidence>"
```
```yaml
# 失败但未满三轮
status: failed_retest
dispatch:
rounds:
- round: 1
result: failed
evidence: "<latest evidence from Test or gate>"
```
```yaml
# 累计三轮失败
status: leftover
resolution:
leftoverReason: "failed after 3 supervised developer rounds"
evidence:
final: "<latest failing evidence>"
```