--- title: ACK 设计评审记录 date: "2026-07-31T17:15:37+08:00" updated: "2026-07-31T23:31:48+08:00" --- # ACK 设计评审记录 > 这是对 ACK v0.8.1 的设计评审快照,用于推动后续版本改进。文中的文件行号对应 > 2026-07-31 的仓库状态,不作为 ACK 的运行规范。 本文同时记录后续方案和实施结果。带“建议”“目标”或“待验证”的内容默认是设计 方向,不代表当前版本已经具备;实际运行契约仍以 `skills/ack/SKILL.md`、schema、 校验器和测试为准。知识护栏方案的 v0.9.0 落地边界、model-routing v0.10.0 的 实施结论见下文状态表。 ## 背景 本轮评审覆盖 `skills/ack/` 的入口、角色规范、闭环流程、项目模板、任务板 schema、校验脚本、Orca 适配器,以及 `pouch init ack` 的真实运行路径。 评审主要回答两个问题: - ACK 的三角色协作方向是否合理。 - 当前实现是否已经能稳定完成初始化、派发、独立复测、状态恢复和结果审计。 ## 结论 ACK 的核心方向合理。显式触发、三角色分权、可观测验收、用户确认、Test 独立 复测、Coordinator 单写任务板和三轮止损都值得保留。 当前版本适合描述为“任务级受监督验收闭环”。它可以组织单个工作空间里的实现和 复测,但还没有覆盖批准状态持久化、跨 worktree 交接、编排状态恢复、目标分支集成 和交付状态,因此暂时不应把 `verified` 等同于“已集成”或“已交付”。 概念设计约为 8/10,当前可操作性约为 5 至 6/10。下一阶段应该补齐控制面契约, 不需要推翻三角色模型。 ## 值得保留的设计 - Coordinator、Developer 和 Test 的职责分开,Developer 不能给自己的实现做最终 判定。 - 新需求先写产品文档、任务拆分和可观测验收信号,用户确认后再派发。 - `tasks.yaml` 由 Coordinator 单写,worker 消息只负责传递证据。 - Test 在复测前核对 worktree、服务实例和构建产物,减少测错代码和旧进程造成的 假通过。 - 每个任务最多三轮,失败后进入 `leftover`,不会无限消耗同一个 worker。 - 通用规范留在 Skill,项目只保存覆盖层与任务状态。 - 闭环核心不依赖 Orca,手动模式仍能保留相同的角色与验收逻辑。 ## P0:状态和证据必须先成为可验证协议 ### `verified` 目前可以没有证据 `roles-and-permissions.md` 定义的完成条件包括 Developer 白盒证据、Test 独立证据、 环境对齐和 Coordinator 终检,但任务 schema 只强制 `id`、`title` 和 `status`。 内置校验器同样没有检查 `verified` 所需的证据。 本轮探针确认,下面这种任务可以通过内置校验: ```yaml version: 1 project: name: demo tasks: - id: T-1 title: hollow green status: verified ``` 相关位置: - `skills/ack/templates/tasks.schema.json:76` - `skills/ack/scripts/validate_tasks.py:70` - `skills/ack/references/roles-and-permissions.md:140` 建议为不同状态定义语义约束。`verified` 至少要求: - Developer 的修改文件、验证命令和结果。 - 独立 Test 的身份、逐条验收结果和原始证据。 - 被测代码或构建产物的不可变指纹。 - worktree、服务进程、Base URL 和测试时间。 - Coordinator 的 gate 结果与写入时间。 ### 用户确认没有持久化 Skill 要求用户确认后再派发,但状态机从 `open` 直接进入 `dispatched`。会话在确认前 中断后,新的 Coordinator 无法知道任务是待确认,还是已经批准。 建议增加 `proposed` 和 `approved`,并记录 `approvedAt`、`approvedBy` 与验收版本。 ### 推荐状态流 ```text proposed -> approved -> implementing -> retesting -> verified_in_workspace -> integrated -> verified blocked -> approved -> cancelled product_failed x 3 -> leftover ``` `verified_in_workspace` 只说明指定工作空间中的代码已经通过独立复测。只有目标分支 集成并完成集成后验证,才能进入最终 `verified`。 ## P0:Orca 适配器需要改成双任务模型 当前文档让 Developer 对一个 Orca task 发送 `worker_done`,然后把同一个 task 再次 派给 Test。截至评审日期,当前 Orca 的 orchestration 规则会在收到有效 `worker_done` 后自动把 task 和 dispatch 标记为 completed。第二次派发同一个 task 缺少可靠的生命周期语义。 相关位置: - `skills/ack/references/orca-adapter.md:144` - `skills/ack/references/orca-adapter.md:164` - `skills/ack/references/orca-adapter.md:199` 建议每个 ACK attempt 创建两个 Orca 子任务: ```text ACK task Developer task Test task, depends on Developer task ``` 任务板分别保存: ```yaml devTaskId: null devDispatchId: null testTaskId: null testDispatchId: null ``` Developer 和 Test 都对自己的 dispatch 发送 `worker_done`,Coordinator 最后只读 证据并执行 gate。 ## P0:明确 worktree 和代码交接方式 当前流程先在 Coordinator worktree 写 PRD 和 `tasks.yaml`,随后才决定是否创建隔离 worktree。权威任务板只保留在 Coordinator worktree,但 worker prompt 又要求在自己 的 worktree 读取相对路径。Developer 的未提交代码如何传给独立的 Test worktree 也没有定义。 相关位置: - `skills/ack/references/kickoff.md:30` - `skills/ack/references/closed-loop.md:65` - `skills/ack/references/closed-loop.md:87` - `skills/ack/references/prompt-templates.md:31` - `skills/ack/references/orca-adapter.md:74` 建议默认让 Developer 和 Test 串行使用同一个 worktree。必须隔离时,在 attempt 中 明确: ```yaml transfer: type: commit | patch | artifact source: "" digest: "" ``` 派发内容应携带验收快照和规范的绝对路径,不能假设每个 worktree 都有同一份未提交 文档。 ## P0:Worker 启动策略改为安全默认 > v0.10 已以结构化 profile 和可信 launcher 取代本节描述的自由 command。下方是 > 当时的评审记录,不再代表当前实现;其中“full-access 写入任务板授权”的建议已被 > v0.10 决策取代,当前明确为 Deferred。 当前校验器强制 Codex 使用 bypass、Cursor 使用 YOLO,并写死模型和 CLI。项目文档 允许收紧权限或替换模型,但合法的安全覆盖会被校验器拒绝。 校验器还只检查自由 shell 字符串里的部分 token。本轮探针确认,带有 shell 控制符 和额外命令的字符串仍可通过校验。这样的结果会给调用方错误的安全感。 相关位置: - `skills/ack/scripts/validate_worker_command.py:49` - `skills/ack/references/model-routing.md:98` - `skills/ack/templates/project.template.md:31` 建议把项目覆盖层改成结构化配置: ```yaml orchestration: mode: orca workers: developer: cli: codex model: "" effort: medium permissionMode: sandbox test: cli: codex model: "" effort: low permissionMode: sandbox ``` 可信代码根据这些字段构造 argv,不接受自由 shell 拼接。安全模式默认通过。 原建议设想 full-access 由用户单独授权并写入任务板;v0.10 没有实现这条授权通道, 项目文件也不能充当授权证据。full-access 的可信授权、期限、撤销和外层隔离均为 Deferred,当前 launcher 必须 fail closed。 ## P0:初始化需要原子化 `pouch init ack` 会先写 `project.md` 和 `tasks.yaml`,再运行任务板校验。缺少 PyYAML 时,命令会失败但保留两个文件。再次运行又会因为拒绝覆盖而失败。 相关位置: - `requirements.txt:1` - `skills/ack/scripts/validate_tasks.py:37` - `pouch/cli.py:1144` - `pouch/cli.py:1156` 本轮在不含第三方包的隔离 Python 环境中复现了这个状态。 建议: - 在临时目录渲染和校验,全部通过后再原子 rename。 - 失败时只清理由本次调用创建的临时文件。 - 提供 `pouch init ack --repair` 或等价恢复路径。 - 默认模板使用 `tasks: []`,完整示例继续放在 `examples/`。 - CLI 输出“脚手架已创建,待配置”,检查通过后再称为“初始化完成”。 ## P1:任务板改成追加式 attempts 当前 `dispatch.rounds` 只记录轮次、结果和一段证据,无法支持恢复、并发和审计。 建议改成追加式 `attempts[]`: ```yaml attempts: - id: "T-1-A1" round: 1 idempotencyKey: "" startedAt: "" workspace: path: "" baseCommit: "" diffHash: "" developer: worker: "" taskId: "" dispatchId: "" evidence: {} test: worker: "" taskId: "" dispatchId: "" evidence: {} gate: result: pending | passed | failed failureKind: null ``` `failureKind` 建议区分: - `product_failed`:实现不满足验收,消耗三轮预算。 - `environment_blocked`:环境或服务不可用,不消耗轮次。 - `needs_decision`:需要用户决定范围,不消耗轮次。 - `acceptance_invalid`:验收标准有误,返回 `proposed`。 - `worker_lost`:worker 消失,由 Coordinator 重新派发。 外部 dispatch 前先持久化 intent。Coordinator 重启后,用 `idempotencyKey` 和 runtime ID 查询 Orca,再决定继续等待、恢复状态或重新派发。 ## P1:统一 schema 和语义校验 安装 `jsonschema` 时,`validate_tasks.py` 只运行 schema;未安装时只运行内置规则。 两条路径的约束不同。schema 会放过重复 ID、四轮 dispatch 和空 `leftoverReason`,内置规则也会放过部分错误结构。 建议: - 始终先执行 schema,再无条件执行语义 invariant。 - 为 `structural` 和 `ready` 提供两个显式模式。 - `ready` 模式检查状态对应的证据、环境、批准和轮次。 - 显式传入的 schema 路径不存在时直接失败,不能静默降级。 - `summary` 从 `tasks` 派生,避免双写。 - 收紧 `additionalProperties`,扩展字段统一放入 `extensions`。 ## P1:补齐完成边界和批次验证 ACK 默认不提交、不推送。隔离 worktree 中的任务即使复测通过,也可能尚未进入目标 分支。最终报告需要明确区分: - 已在指定工作空间验证。 - 已集成到目标分支。 - 已完成集成后回归。 - 已提交、已推送或已发布。 多个任务分别通过后,还需要一次批次级集成回归,避免组合后出现冲突或行为变化。 ## P2:减少规范重复和模型漂移 - 保留一份权威状态机、一份角色权限表和一份模型档位规则。 - `kickoff.md` 只做一页运行手册,adapter 只保存工具命令。 - 具体模型名称放到可更新的映射或项目覆盖层,稳定核心只描述能力档位和升级条件。 - `ackVersion` 不能只记录旧版本。需要独立的 `schemaVersion`、兼容范围和迁移命令。 - 用真实运行数据观察首轮通过率、环境失败率、平均轮次、`leftover` 原因、耗时和 token,再决定三轮规则是否需要按任务风险调整。 - 为低风险文档或机械改动提供轻量模式,高风险和用户可见行为继续使用完整三角色 闭环。 ## 低成本清理 - `skills/ack/SKILL.md:66` 的旧字段应为 `kitVersion`。 - `skills/ack/templates/project.template.md:8` 建议修改或替换 `AGENTS.md`,与 Skill 的禁止规则冲突。 - `skills/ack/references/orca-adapter.md:201` 应引用 prompt §4。 - `skills/ack/scripts/validate_worker_command.py:2` 残留 “Music Pilot”。 - `skills/ack/examples/tasks.example.yaml` 缺少 checklist 要求的 `overlayFile`。 - Test 负责黑盒与集成测试,Developer 负责单元测试;当前优化文档对单元测试所有权 的表述需要统一。 ## 建议实施顺序 1. 收紧任务状态、批准状态和 `verified` 证据门。 2. 把 Orca adapter 改成每轮 Developer/Test 双任务。 3. 定义同 worktree 默认策略和跨 worktree transfer。 4. 改造 worker launcher 与安全授权。 5. 原子化 `pouch init ack`,空任务板作为默认模板。 6. 引入追加式 attempts、幂等恢复和失败分类。 7. 统一 schema 与语义校验,补齐对抗性 fixture。 8. 区分工作空间验证、集成验证和发布状态。 9. 去重文档,补版本迁移和运行指标。 ## 验证记录 本轮执行了: - `pouch check ack`:通过。这个命令只证明 Skill 的元数据和基础结构有效。 - `validate_tasks.py examples/tasks.example.yaml`:通过,当前机器使用内置规则。 - `validate_worker_command.py --self-test`:7 项通过。 - `python3 -m unittest discover -s tests -v`:58 项通过。 - 隔离全局安装 smoke:通过,安装结果为指向 ACK SSOT 的 symlink。 - 隔离初始化探针:缺少 PyYAML 时失败,留下半初始化文件,重试被拒绝。 - 对抗性任务板探针:无证据的 `verified` 可以通过。 - 对抗性 worker 命令探针:附加 shell 控制符的命令字符串可以通过。 - 当前 Orca orchestration 指南复核:有效 `worker_done` 会自动完成对应 task 和 dispatch。 现有 ACK 测试主要覆盖字符串、Skill 元数据和初始化冒烟,没有覆盖状态机语义、 schema 与 fallback 一致性、Orca 双阶段生命周期、Coordinator 崩溃恢复和跨 worktree 代码交接。 ## 待验证 - [ ] 用真实项目跑一轮同 worktree 的 Developer/Test 闭环。 - [ ] 用独立 worktree 验证 commit、patch 和 artifact 三种交接方式。 - [ ] 验证 Coordinator 在 task-create、dispatch 和 Test 完成三个时间点崩溃后的 恢复行为。 - [ ] 为安全 worker profile、路径 containment 和 shell 注入增加对抗性测试。 - [ ] 定义 ACK v0.9 的 schema 迁移策略,再决定是否保留旧状态名称。 ## 扩展方案:项目知识护栏库 ### v0.9.0 落地边界 | 能力 | v0.9.0 状态 | |------|-------------| | `knowledge.yaml` 模板、schema、初始化和跨文件校验 | 已实现 | | active/stale/superseded/archived、作用域、冲突、复查时间和来源校验 | 已实现 | | 确定性选择、全项目规则优先、固定 revision 引用 | 已实现 | | registry ID + 结构化 argv + fd 固定根目录的安全检查入口 | 已实现 | | Developer candidate、Test check、Coordinator 单写的协作约定 | 已实现为协议和校验字段 | | 不同 revision 的历史内容不可篡改或可独立恢复 | 延后;v0.9.0 没有外部不可变账本 | | 依赖或路径变化后自动转 stale | 延后;当前由 `reviewAfter` 和人工复核驱动 | | 在运行时强制只有获授权身份能写入或激活知识 | 延后;当前依赖 Coordinator 单写边界 | | 自动识别任意提示注入、PII 或所有秘密 | 延后;当前只有结构禁区和常见秘密模式 | | `approved`、追加式 attempts、崩溃恢复和最终集成 gate | 延后到控制面改造 | ### 定位 ACK 需要增加第三类项目事实,用来保存跨任务复用、会改变后续开发或验证行为的已 验证知识。它不保存聊天记忆,也不承担项目 Wiki 的职责。 | 项目事实 | 保存内容 | 写入者 | |----------|----------|--------| | `project.md` | 相对稳定的项目配置、路径和命令 | Coordinator 或项目维护者 | | `tasks.yaml` | 当前任务状态、attempt 和执行证据 | Coordinator | | `knowledge.yaml` | 跨任务复用的已验证经验 | Coordinator | 建议新增项目级 SSOT:`.pouch/ack/knowledge.yaml`。知识归项目所有,与 Orca 等编排 工具无关;ACK 负责在任务闭环中生产、选择和消费这些知识。 这项设计会修改当前“`.pouch/ack/` 只保存 `project.md` 与 `tasks.yaml`”的边界。 新增文件保存项目事实,不复制 ACK Skill 的通用规范,因此不违反 Skill 内容仍以 `skills/ack/` 为 SSOT 的原则。 ### 知识类型 第一版只支持三类知识: | 类型 | 含义 | 例子 | |------|------|------| | `guardrail` | 必须执行或明确禁止的项目约束 | 修改数据库迁移时必须验证回滚 | | `pitfall` | 已证实的失败模式、触发条件和避免方法 | Test 连到了另一个 worktree 的旧服务 | | `verification` | 特定条件下必须增加的检查 | 修改缓存键后执行跨版本兼容测试 | 架构决策正文继续写入 ADR 或正式规格,知识项只引用决策及其适用条件。任务进度和 单次失败证据继续留在 `tasks.yaml`。通用且可跨项目复用的规则应回流 ACK Skill, 不能作为某个项目的知识长期保存。 ### 生命周期 ```text Developer / Test 发现经验 -> candidate -> Test 独立验证 + Coordinator gate -> active -> stale -> superseded | archived ``` - Developer 和 Test 只能提交 candidate,不能直接写入或激活知识。 - candidate 保存在当前 task 或 attempt 的证据中,不参与后续任务的自动选择。 - 根因得到证实、修复通过独立 Test、Coordinator 完成 gate 后,candidate 才能转为 `active`。 - 全项目范围的 `must`、`never` 或权限类规则需要 User 或 Decision Owner 确认。 - 依赖、配置、路径或适用版本发生变化后,相关知识转为 `stale`,默认不再派发。 - 新知识替代旧知识时必须记录 `supersedes`,不能静默改写历史。 - 临时 workaround 必须有复查时间和移除条件,不能无限期保持 `active`。 同一 Agent 不能把自己读到的旧知识直接作为新证据再次激活。新的 candidate 必须 包含当前任务产生的独立观测,避免形成自我强化的错误闭环。 ### 最小数据结构 每条知识至少包含: ```yaml id: K-001 revision: 1 kind: pitfall status: active title: "复测前确认服务来自当前 worktree" scope: components: [web] paths: ["web/**"] dependencies: [] versions: [] tags: [long-running-service] appliesWhen: "修改常驻 Web 服务或前端构建产物" directive: "复测前重启服务,并核对服务实例对应的 commit" rationale: "曾因复测旧进程产生假通过" verification: ref: service-worktree-alignment expected: "服务实例、worktree 和 commit 一致" provenance: taskId: BUG-017 attemptId: BUG-017-A2 codeRef: "" evidenceRef: "tasks.yaml#BUG-017" owner: "" author: "" reviewer: "" createdAt: "" lastValidatedAt: "" reviewAfter: "" removalCondition: null supersedes: [] conflictsWith: [] ``` `revision` 是逻辑版本标识。修改知识的约束含义时必须新增 revision,并保留被引用 的旧条目;任务引用 `K-001@1` 后,可以说明当时选择的逻辑版本。v0.9.0 尚未用 content hash、签名或外部账本封存条目内容,因此不能只凭这个字符串证明历史字节 不可变;项目需要把状态纳入版本控制,强不可变审计留待后续实现。 `directive` 只能描述应采取的动作。需要执行命令时,`verification.ref` 应引用项目中 已审查的测试或检查 ID,由可信配置解析成结构化 argv。知识库不保存可自动执行的 自由 shell 命令。 ### 与三角色闭环的集成 | 角色 | 权限和职责 | |------|------------| | Coordinator | 单写 `knowledge.yaml`;选择本轮适用知识;激活、废弃和处理冲突 | | Developer | 只读本轮知识;回报遵守情况;提交 `knowledgeCandidates` | | Test | 只读本轮知识;执行额外检查;独立验证 candidate | | User / Decision Owner | 批准全项目强制规则、权限规则和无法通过测试证明的政策 | `prepare(task)` 时,Coordinator 按 component、path、dependency、version、tag 和失败 特征筛选 `active` 知识。匹配结果只作为候选,Coordinator 确认后把固定版本引用 写入本轮上下文: ```yaml knowledgeRefs: - K-001@1 - K-014@2 ``` 引入前文建议的追加式 `attempts[]` 后,引用和回报建议放在: ```text attempts[].context.knowledgeRefs attempts[].developer.knowledgeApplied attempts[].developer.knowledgeCandidates attempts[].test.knowledgeChecks ``` 派发时把已引用知识的必要内容内联到 Developer 和 Test 的 prompt,避免 worker 因 worktree 不同而读不到 Coordinator worktree 中未提交的知识文件。每次只派发当前 任务命中的少量条目,不全量注入知识库。 Developer 回报实际遵守了哪些知识,以及新发现的 candidate。Test 对每条适用的 `verification` 回报 pass、fail 和证据。要求执行的知识检查没有覆盖时, Coordinator 不得把任务写成 `verified_in_workspace` 或 `verified`。 ### 检索和冲突规则 第一版使用确定性匹配,不引入向量数据库、Embedding 或语义 RAG: - 先按 path、component、dependency、version 和 tag 选择条目。 - 失败排查时可以额外匹配错误签名和相关 symbol。 - 只返回 `active` 且适用条件成立的条目。 - 设置条目数和上下文预算,详情按需读取。`scope.all=true` 的全项目规则优先占用 预算;全项目规则本身超过预算时显式失败,不能静默丢弃。 - `stale`、`superseded` 和 `archived` 默认不返回。 - 没有匹配结果只表示本轮没有找到知识,不能据此声称项目没有相关约束。 同一 subject 和 scope 不能存在互相矛盾的 `active` 条目。校验器发现冲突时应阻止 进入 ready 状态,由 Coordinator 或 Decision Owner 选择保留项并记录 `supersedes`。运行时不能使用“最后写入者获胜”解决冲突。 自动匹配只负责推荐。Coordinator 写入当前 attempt 的显式 `knowledgeRefs` 才是 本轮权威上下文。这个边界可以降低作用域标注不准造成的漏选和误选。 ### 知识晋升后的去向 知识库不是所有经验的最终归宿。不同内容应继续进入对应的权威载体: | 内容 | 最终位置 | |------|----------| | 当前任务状态和单次验证证据 | `tasks.yaml` | | 稳定项目路径、命令和运行配置 | `project.md` | | 架构或产品决策及其取舍 | ADR 或正式规格 | | 安全、正确性和兼容性约束 | 测试、lint、CI 或正式规范 | | 原始日志、截图和构建产物 | 受控 artifact 存储 | | 跨项目通用规则 | ACK Skill | | 项目特有且跨任务复用的经验 | `knowledge.yaml` | 关键 `verification` 应逐步转成可执行测试或 CI gate。知识项继续保存触发条件、原因 和证据引用,不能用自然语言规则替代可执行控制。 ### 禁止写入的内容 - Token、密钥、Cookie、含凭据 URL、生产数据、PII、客户内容和未脱敏日志。 - 系统提示、开发者提示、角色或权限覆盖,以及绕过审批、测试和安全限制的指令。 - 可自动执行的破坏性命令或生产命令。 - 原始聊天、整段 issue 或网页内容、巨量日志、截图和构建产物。 - 未复现猜测、LLM 单方推断、一次性巧合和个人评价。 - PID、临时端口、个人 worktree 绝对路径等短命机器状态。 - 对代码、配置和正式文档的重复抄写。 - 没有作用域、证据和失效条件的 `always`、`never` 或 workaround。 - 需要权限隔离的漏洞 PoC、敏感内部拓扑和安全调查材料。 issue、日志和外部网页只能作为不可信 evidence。进入知识库前必须提炼为可审查的 项目结论,不能原样晋升,也不能获得高于用户指令、批准规格、当前代码、配置和测试 的优先级。 ### 第一版范围 第一版只实现一个 `.pouch/ack/knowledge.yaml`,不拆目录。活跃条目达到几十条、单文件 开始影响审阅和选择时,再平滑迁移为 `.pouch/ack/knowledge/index.yaml` 加独立知识卡, 条目 schema 和引用格式保持不变。 第一版包括: 1. `knowledge.yaml` schema 与语义校验。 2. task 或 attempt 的 `knowledgeRefs`。 3. Developer 的 `knowledgeApplied` 与 `knowledgeCandidates`。 4. Test 的 `knowledgeChecks`。 5. Coordinator 在 prepare、gate 和任务收尾三个节点处理知识。 6. 基于 scope 的确定性匹配。 7. stale、冲突、revision 和 supersedes 校验。 第一版不包括: - 自动抓取或总结全部对话。 - Agent 自动激活、删除或提交知识。 - 向量数据库、Embedding 和语义 RAG。 - 自动改写 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。 - 从知识正文直接执行 shell 命令。 - 组织级、跨仓库知识同步。 ### 目标验收与当前状态 | 目标 | v0.9.0 状态 | |------|-------------| | candidate 不会作为 active 派发 | 已实现 | | 未授权 worker 不能激活、废弃或删除知识 | 协议约束;运行时身份授权延后 | | path、component、version 只返回匹配条目 | 已实现确定性匹配;准确率仍取决于 scope 标注 | | 非 active 条目默认不返回 | 已实现 | | 冲突 active 规则被拒绝 | 已实现显式冲突和相同 subject/scope 检查 | | 历史 attempt 的知识内容不可变 | 延后;当前只有 revision 约定,没有不可变账本 | | `verification.ref` 无法解析时校验失败 | 已实现 | | evidence 中的提示注入不会变成命令 | 部分实现;禁止自由执行字段,语义晋升仍需人工 gate | | 秘密和生产数据不能进入知识库 | 部分实现;常见秘密模式会阻断,不能替代完整 DLP | | 依赖、路径变化后自动转 stale | 延后;当前依赖复查日期和 Coordinator | | 增长后仍在预算内且不漏全项目规则 | 已实现;全项目规则超预算时显式失败 | ### 与 ACK 改造顺序的关系 知识护栏库最终仍依赖可信的任务状态、attempt、证据来源和 ready 校验。v0.9.0 先 落地存储、选择和基础 gate,不能据此声称前述控制面问题已经解决。后续应继续: 1. 确定知识 schema、生命周期和角色权限。 2. 在 attempt 中固定 `knowledgeRefs` 和 candidate 证据。 3. 接入 Coordinator 的匹配、派发和晋升流程。 4. 增加 stale、冲突、权限、注入和敏感信息的对抗性 fixture。 5. 选一个真实项目试运行,再根据活跃条目数量决定是否拆分存储。 这套方案最依赖 scope 标注的质量。项目知识如果很难用组件、路径、依赖、版本或 触发条件限定,自动匹配会漏掉关键项或产生大量噪声。这类知识应继续由人维护在 ADR 或项目文档中,不能强行进入自动派发流程。 ## v0.10.0 实施结论:结构化 model-routing ### 当前决策 旧的 `validate_worker_command.py --command ''` 只能检查少量 token,无法证明 整段 shell 没有追加命令、重复参数、环境注入或 cwd 漂移。v0.10 删除这条自由命令 配置面:旧脚本只保留 fail-closed 迁移提示;自动 worker 的唯一入口是 `launch_worker.py profile-hash|plan|launch`。 机器 SSOT 固定为 `tasks.yaml.project.orchestration`。profile 只声明 role、CLI、 tier、model、reasoning effort 和 permission mode;model 必须命中按 CLI/role/tier 分组的 allowlist。自动权限只允许 `read-only` 与 `workspace-write`,full-access、Codex bypass、Cursor YOLO/force 和关闭 sandbox 全部 fail closed。 ### 已落地约束 | 控制面 | v0.10.0 实现 | |--------|--------------| | 自由 command / extra argv / env / cwd | schema 与语义校验拒绝;旧 validator fail closed | | Agent argv | 由 `worker_profiles.py` 按 profile 生成唯一 argv;子进程 `shell=False` | | plan → launch 漂移 | `launch` 强制接收刚审阅的 `--expected-launch-fingerprint`,slot 也纳入 hash | | PATH / loader / 凭据串用 | 不按调用者 PATH 找可执行文件;固定可信目录;控制进程无供应商凭据,worker 使用 `per-cli-allowlist-v1` | | worktree 冒充 | 绝对规范路径、无 symlink、同 Git common-dir,并命中 `git worktree list -z` | | Orca command 注入 | `--command` 只含固定 bootstrap 和随机 launch ID | | bootstrap 抢跑 | 先绑定 runtime/handle/incarnation/worktree,再用 terminal stdin nonce/proof 授权 | | cleanup / bootstrap 竞态 | Popen 前在同一 record lock 内复核 awaiting 状态;cleanup 先发生则拒绝启动 Agent | | create 部分失败 | 取得确定 handle 前的超时、transport/解码异常、中断、非零、畸形/缺字段响应均记为 indeterminate,禁止自动重试 | | handle 后失败清理 | record 写失败不阻断 close;只有 `terminal close --tab --json` 完整匹配且最终 failed 状态可靠落盘才记普通失败,否则保持 indeterminate/reconcile-required | | receipt 漂移 | 规范化 profileHash、argvHash、slot、launchFingerprint 与 receiptHash 交叉校验 | | dispatch 旧 receipt 改挂 | 每个角色显式记录 attemptId;receipt 必须绑定当前 ACK task.id、同 role/profile/attempt,receiptId/attemptId 同空同填 | | 配置兼容 | ackVersion 必须是合法 SemVer;v0.10+ 的 orchestration/workerReceipts 必须同时存在,v0.9 旧板仍可只读校验和手动协作 | ### 不能被弱证明掩盖的边界 `receiptHash` 是无密钥 checksum,不是签名。项目内可写方能修改 receipt 后重算 hash;而当前 Orca terminal metadata 不提供原始 Agent argv、模型或权限 attestation。因此 v0.10 **不根据持久化 receipt 自动复用旧终端**。每次自动派发都 重新执行 plan,并用 expected fingerprint 启动 fresh worker;持久化 receipt 只作 审计和 dispatch 关联。 `launchFingerprint` 只证明完整计划没有漂移,不是一次性授权或幂等键;同一计划重复 执行仍会创建新的 fresh terminal。成功后不得重放,结果不确定时必须先 reconcile。 自动防重放要依赖后端原子 idempotency/claim 或项目外可信 launch intent,不能由 checksum 伪装提供。 任务板里的 dispatch 关联也不是宽松的历史索引。`dispatch.` 显式记录 `profileId`、`receiptId` 和 `attemptId`,校验器要求 receipt 的 `createdFor` 精确绑定 当前 ACK `tasks[].id`、同一角色和同一 attempt,并要求 profile 一致。该约束阻止把 旧任务、旧角色或旧轮次 receipt 改挂到当前 dispatch,但不会把无密钥 receipt 升级成 可信 attestation。 同样,receipt 证明的是 launcher 请求和本地 CLI/runtime 绑定,不证明模型供应商最终 执行的模型。开放自动复用需要 Orca/ACP 提供启动参数 attestation,或项目外可信签发 与校验通道。开放 full-access 还需要不可由项目文本伪造的用户授权、期限、撤销和外层 隔离。这两项均留待后续版本。 威胁模型也明确到 Coordinator 账户边界:v0.10 防止任务板、任务内容、普通环境和 受限 worker 把数据变成第二个启动命令入口;不抵御已经完全控制 Coordinator OS 账户、Orca runtime、受信 Agent/Orca 可执行文件或用户级 Agent 配置/插件/MCP 的 攻击者。`permissionMode` 也不是模型供应商或外部工具能力 attestation;后者必须依赖 独立 OS 身份、受控 Agent 配置或平台能力。 ## 后续版本提案:ACP 与可替换编排后端 ### 当前决策 ACK 当前版本继续以 **Orca** 作为唯一自动编排后端。闭环语义保持工具无关,但 worker 创建、终端身份绑定、dispatch 和 wait 的可执行适配仍由 Orca 完成。 ACP(Agent Client Protocol)作为后续版本的优先候选,当前只记录方案,不加入运行 时依赖、不新增半成品 adapter,也不让现有流程在 Orca 与 ACP 之间自动猜测。 | 能力 | 当前版本 | 后续方向 | |------|----------|----------| | 自动创建并监督 worker | Orca | ACP capability negotiation 后可增加 ACP adapter | | 结构化模型与权限 profile | ACK 自己定义,Orca 只承载启动 | 保持为 ACK 稳定契约,不交给后端自由解释 | | dispatch / wait / terminal identity | Orca runtime handle | 映射到 ACP session / request / event identity | | 无自动后端时运行闭环 | 手动模式 | 可增加 PTY / Zellij 类低层 fallback,但不冒充语义协议 | | 后端选择 | 项目显式配置 | 未来仍需显式配置,不按已安装命令静默切换 | ### 后端无关的最小语义 未来 adapter 只应实现以下能力,不应接管 ACK 的角色、状态机或安全策略: 1. `createWorker(profile, worktree)`:按 ACK 已验证的结构化 profile 创建 worker。 2. `inspectWorker(identity)`:返回可绑定的 runtime、session/incarnation 和活性。 3. `dispatch(identity, taskContext)`:把一个明确任务投递给已验证 worker。 4. `wait(identity, eventTypes)`:等待完成、复测、升级或 decision gate 事件。 5. `closeWorker(identity)`:只关闭本次创建且身份仍匹配的 worker。 模型、reasoning effort、权限模式、worktree 和 receipt hash 仍由 ACK 校验。adapter 不能重新开放自由 shell、任意 argv、任意环境变量或“后端默认模型”作为旁路。 ### ACP 采用门槛 满足以下条件后再实现 ACP adapter: - 目标 Agent CLI 对 ACP 的启动、会话身份、取消和事件语义足够稳定。 - 能把 Developer/Test 的独立身份、worktree 和结构化 profile 映射到可核对字段。 - 能区分“已请求的模型/权限”和“运行时可观测事实”,不把客户端请求冒充供应商证明。 - 超时、重连、重复 dispatch 和 runtime 重启具有明确的幂等或恢复语义。 - 与 Orca adapter 使用同一组 ACK conformance tests,且不会降低安全默认。 在这些门槛满足前,ACP 保持 **Deferred**。PTY 或 Zellij 一类方案只能作为较低层的 进程/终端承载,不提供 session 语义、模型证明或任务状态机;如果以后加入,也必须 经过独立 adapter,不能散落为文档中的自由命令。 ### 参考依据 - [GitHub 仓库自定义指令](https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/add-custom-instructions/add-repository-instructions) 区分仓库级、路径级和就近生效的 Agent 指令。 - [Claude Code 项目记忆](https://code.claude.com/docs/zh-CN/memory)区分持久指令与 自动记忆,并建议把较大的内容按作用域拆分、按需加载。 - [Architectural Decision Records](https://adr.github.io/)用于保存单个重要决策的 理由、取舍和后果,适合承载不应混入项目知识库的决策正文。