Use ~/.pouch, the pouch CLI, and .pouch.yaml as the SSOT container. Keep the inner skills/ packages, and store ACK project state in .pouch/ack instead of docs/ack.
34 KiB
title, date, updated
| title | date | updated |
|---|---|---|
| ACK 设计评审记录 | 2026-07-31T17:15:37+08:00 | 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 所需的证据。
本轮探针确认,下面这种任务可以通过内置校验:
version: 1
project:
name: demo
tasks:
- id: T-1
title: hollow green
status: verified
相关位置:
skills/ack/templates/tasks.schema.json:76skills/ack/scripts/validate_tasks.py:70skills/ack/references/roles-and-permissions.md:140
建议为不同状态定义语义约束。verified 至少要求:
- Developer 的修改文件、验证命令和结果。
- 独立 Test 的身份、逐条验收结果和原始证据。
- 被测代码或构建产物的不可变指纹。
- worktree、服务进程、Base URL 和测试时间。
- Coordinator 的 gate 结果与写入时间。
用户确认没有持久化
Skill 要求用户确认后再派发,但状态机从 open 直接进入 dispatched。会话在确认前
中断后,新的 Coordinator 无法知道任务是待确认,还是已经批准。
建议增加 proposed 和 approved,并记录 approvedAt、approvedBy 与验收版本。
推荐状态流
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:144skills/ack/references/orca-adapter.md:164skills/ack/references/orca-adapter.md:199
建议每个 ACK attempt 创建两个 Orca 子任务:
ACK task
Developer task
Test task, depends on Developer task
任务板分别保存:
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:30skills/ack/references/closed-loop.md:65skills/ack/references/closed-loop.md:87skills/ack/references/prompt-templates.md:31skills/ack/references/orca-adapter.md:74
建议默认让 Developer 和 Test 串行使用同一个 worktree。必须隔离时,在 attempt 中 明确:
transfer:
type: commit | patch | artifact
source: "<immutable reference>"
digest: "<sha256 or diff hash>"
派发内容应携带验收快照和规范的绝对路径,不能假设每个 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:49skills/ack/references/model-routing.md:98skills/ack/templates/project.template.md:31
建议把项目覆盖层改成结构化配置:
orchestration:
mode: orca
workers:
developer:
cli: codex
model: "<project-approved-model>"
effort: medium
permissionMode: sandbox
test:
cli: codex
model: "<project-approved-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:1skills/ack/scripts/validate_tasks.py:37pouch/cli.py:1144pouch/cli.py:1156
本轮在不含第三方包的隔离 Python 环境中复现了这个状态。
建议:
- 在临时目录渲染和校验,全部通过后再原子 rename。
- 失败时只清理由本次调用创建的临时文件。
- 提供
pouch init ack --repair或等价恢复路径。 - 默认模板使用
tasks: [],完整示例继续放在examples/。 - CLI 输出“脚手架已创建,待配置”,检查通过后再称为“初始化完成”。
P1:任务板改成追加式 attempts
当前 dispatch.rounds 只记录轮次、结果和一段证据,无法支持恢复、并发和审计。
建议改成追加式 attempts[]:
attempts:
- id: "T-1-A1"
round: 1
idempotencyKey: "<stable key>"
startedAt: "<timestamp>"
workspace:
path: "<worktree>"
baseCommit: "<sha>"
diffHash: "<hash>"
developer:
worker: "<identity>"
taskId: "<runtime task id>"
dispatchId: "<runtime dispatch id>"
evidence: {}
test:
worker: "<independent identity>"
taskId: "<runtime task id>"
dispatchId: "<runtime dispatch id>"
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 负责单元测试;当前优化文档对单元测试所有权 的表述需要统一。
建议实施顺序
- 收紧任务状态、批准状态和
verified证据门。 - 把 Orca adapter 改成每轮 Developer/Test 双任务。
- 定义同 worktree 默认策略和跨 worktree transfer。
- 改造 worker launcher 与安全授权。
- 原子化
pouch init ack,空任务板作为默认模板。 - 引入追加式 attempts、幂等恢复和失败分类。
- 统一 schema 与语义校验,补齐对抗性 fixture。
- 区分工作空间验证、集成验证和发布状态。
- 去重文档,补版本迁移和运行指标。
验证记录
本轮执行了:
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,
不能作为某个项目的知识长期保存。
生命周期
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 必须 包含当前任务产生的独立观测,避免形成自我强化的错误闭环。
最小数据结构
每条知识至少包含:
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: "<commit or tree hash>"
evidenceRef: "tasks.yaml#BUG-017"
owner: "<owner>"
author: "<candidate author>"
reviewer: "<independent reviewer>"
createdAt: "<timestamp>"
lastValidatedAt: "<timestamp>"
reviewAfter: "<timestamp or null>"
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 确认后把固定版本引用
写入本轮上下文:
knowledgeRefs:
- K-001@1
- K-014@2
引入前文建议的追加式 attempts[] 后,引用和回报建议放在:
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 和引用格式保持不变。
第一版包括:
knowledge.yamlschema 与语义校验。- task 或 attempt 的
knowledgeRefs。 - Developer 的
knowledgeApplied与knowledgeCandidates。 - Test 的
knowledgeChecks。 - Coordinator 在 prepare、gate 和任务收尾三个节点处理知识。
- 基于 scope 的确定性匹配。
- 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,不能据此声称前述控制面问题已经解决。后续应继续:
- 确定知识 schema、生命周期和角色权限。
- 在 attempt 中固定
knowledgeRefs和 candidate 证据。 - 接入 Coordinator 的匹配、派发和晋升流程。
- 增加 stale、冲突、权限、注入和敏感信息的对抗性 fixture。
- 选一个真实项目试运行,再根据活跃条目数量决定是否拆分存储。
这套方案最依赖 scope 标注的质量。项目知识如果很难用组件、路径、依赖、版本或 触发条件限定,自动匹配会漏掉关键项或产生大量噪声。这类知识应继续由人维护在 ADR 或项目文档中,不能强行进入自动派发流程。
v0.10.0 实施结论:结构化 model-routing
当前决策
旧的 validate_worker_command.py --command '<shell>' 只能检查少量 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.<role> 显式记录
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 的角色、状态机或安全策略:
createWorker(profile, worktree):按 ACK 已验证的结构化 profile 创建 worker。inspectWorker(identity):返回可绑定的 runtime、session/incarnation 和活性。dispatch(identity, taskContext):把一个明确任务投递给已验证 worker。wait(identity, eventTypes):等待完成、复测、升级或 decision gate 事件。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 仓库自定义指令 区分仓库级、路径级和就近生效的 Agent 指令。
- Claude Code 项目记忆区分持久指令与 自动记忆,并建议把较大的内容按作用域拆分、按需加载。
- Architectural Decision Records用于保存单个重要决策的 理由、取舍和后果,适合承载不应混入项目知识库的决策正文。