ACK
ACK 是一个显式调用的 Agent Skill,用三种独立角色运行工程协作闭环:
- Coordinator 拆解需求、派发任务并终检。
- Developer 实现并执行白盒验证。
- Test 独立执行黑盒复测。
关键约束是验证者不等于实现者。每个任务最多修复三轮,仍未通过时记录为
leftover,然后继续处理其它任务。
项目还可以声明一个可选的交付阶段:任务全部验证后,ACK 按项目维护的 profile 构建 DEB 或镜像、发布产物、创建 PR,并在授权范围内部署。交付配置默认关闭, 稳定发布与生产部署始终保留人工批准点。
安装
全局安装:
skiff add ack -g
或只安装到当前项目:
skiff add ack
ACK 只在用户显式调用 /ack 或 $ack 时运行。
初始化项目
skiff init ack
skiff init ack --project ~/code/my-app
初始化后,项目只保存自己的 ACK 状态:
docs/ack/
├── project.md
├── tasks.yaml
├── knowledge.yaml
└── delivery.yaml # 默认 enabled: false
不会在项目中复制或链接 ACK Skill。通用规范、模板和脚本始终从已安装的 Skill 目录读取。
ACK 从当前命令指定的 --project-root/docs/ack/ 定位项目状态,不要求在
tasks.yaml 中持久化 repoPath 或 devWorktree。自动 worker 的实际工作目录仍由
--worktree 指定,并且必须命中绝对路径白名单 allowedWorktrees。
Skill 结构
skills/ack/
├── SKILL.md
├── README.md
├── VERSION
├── references/ # 三角色规范、闭环流程和初始化说明
├── templates/ # project.md、tasks.yaml、knowledge.yaml、delivery.yaml 模板和 schema
├── examples/ # 完整示例
└── scripts/ # 状态校验、任务/知识选择、安全验证执行与结构化 worker launcher
SKILL.md 是 Agent 的工作流入口。references/ 是按需读取的稳定规范;
docs/ack/project.md 只保存当前项目的命令、路径和权限差异;
docs/ack/tasks.yaml 保存当前任务状态;docs/ack/knowledge.yaml 保存跨任务复用、
已经独立验证的项目知识护栏。
docs/ack/delivery.yaml 声明项目特有的构建、发布和部署能力;每次执行结果另记在
tasks.yaml.deliveryRuns,配置与运行状态不会混在一起。
检查项目状态
Agent 会从当前 ACK Skill 目录解析校验脚本:
python3 <ack-skill-dir>/scripts/validate_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml \
--tasks docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py docs/ack/delivery.yaml \
--tasks docs/ack/tasks.yaml --project-root <project-root>
Coordinator 可以按当前任务上下文做确定性推荐:
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml \
--task-id BUG-001
python3 <ack-skill-dir>/scripts/select_knowledge.py docs/ack/knowledge.yaml \
--component web --path web/app.py --tag long-running-service --limit 10
任务选择器会解析并执行完整任务板的内置语义校验,但只输出 project、summary、
默认可工作状态或显式 --task-id 命中的任务,以及这些任务引用的 receipt 和 delivery
run。默认最多 20 条,超过预算时显式失败;Agent 不应回退为把完整 tasks.yaml 注入
上下文。
默认 JSON 输出会同时给出固定知识引用和已解析的 verificationTarget.path/args;
选择器只输出数据,不执行检查。scope.all=true 的全项目 active 规则优先占用
--limit;如果全项目规则本身超过预算,选择器会显式失败,不会静默漏派。
需要执行知识项引用的检查时,只传 registry ID 给 ACK 的安全执行入口:
python3 <ack-skill-dir>/scripts/run_verification.py \
docs/ack/knowledge.yaml check-api-contract --project-root <project-root>
该入口会在执行前重新校验知识库,只打开一次项目根目录 fd,再从同一个 fd 逐段以
O_NOFOLLOW 打开知识库和检查文件;检查内容复制到匿名、尽可能 sealed 的稳定
快照,再以结构化 argv 和 shell=False 启动。它不接受临时命令或额外参数。
选择器输出的 path/args 只用于审阅,不应由 Agent 自行拼接执行。Runner 只读取
项目内无 symlink 的权威
docs/ack/knowledge.yaml,不接受替代知识文件或放宽后的项目根。检查进程的 cwd
和 ACK_PROJECT_ROOT 都固定到该根 fd;后者是只在检查进程存活期间有效的
/proc/self/fd/... 或 /dev/fd/... 路径。原始可读路径另放在
ACK_PROJECT_ROOT_DISPLAY,只能用于日志,不能用于资源访问。Runner 还提供
ACK_VERIFICATION_REF 和 ACK_VERIFICATION_PATH;检查脚本必须据此定位资源,
不能依赖 $0 或 __file__ 所在目录,因为实际执行的是匿名快照。
知识先由 Developer 或 Test 作为 candidate 提名,经独立验证和 Coordinator gate
后才能成为 active。Coordinator 按路径、组件、依赖、版本和标签推荐相关知识,
确认后将固定 revision 的 knowledgeRefs 写入任务上下文;每轮只派发命中的少量
条目,不全量注入知识库。
旧项目只有 project.md 和 tasks.yaml 时,不要重跑初始化。由 /ack 检查现有
状态,获得用户授权后补一个空的 knowledge.yaml;如果任务板尚未声明知识库,
同时只补 project.knowledgeFile: docs/ack/knowledge.yaml,再运行跨文件校验。
只有 Coordinator 写 tasks.yaml 和 knowledge.yaml。知识正文不能作为自由 shell
执行;关键约束应继续下沉到测试、lint、CI 或正式规范。ACK 不自动修改项目的
AGENTS.md、CLAUDE.md 或其它 Agent 指令文件。
配置与运行交付
用户可以直接向 /ack 描述项目差异,例如“这个项目用 make deb 构建 DEB,推到
preview APT 源,再部署到开发机”。ACK 会把它维护成
docs/ack/delivery.yaml 中的声明式 entrypoint、artifact、destination、environment
和 profile,校验后展示 diff;首次配置保持关闭,确认后才启用。
交付配置只允许声明式工具 target 或仓库内可执行脚本,不接受自由 shell,也不保存
凭据值。ACK 在任务进入 verified 后,按用户确认的 profile 执行,并把 revision、
PR、产物摘要、部署目标、健康检查和日志引用写入 tasks.yaml.deliveryRuns。默认
profile 只能停在 review_ready;稳定发布或生产部署必须经过对应 approval 步骤。
具体契约见 references/delivery.md。
启动 Worker
worker 的机器配置位于 tasks.yaml.project.orchestration:项目显式维护模型
allowlist、结构化 profile、默认 profile 和允许的 worktree。不得在 project.md
或任务里保存完整启动命令、额外 argv 或环境变量。
先审阅计划,不产生终端:
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 \
--profile-id codex-dev-standard \
--worktree <allowed-worktree>
确认后执行 launch,并显式绑定刚审阅的 fingerprint:
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 \
--profile-id codex-dev-standard \
--worktree <allowed-worktree> \
--expected-launch-fingerprint <plan 中的 sha256:...>
launcher 是自动创建 worker 的唯一入口:它从权威任务板重读 profile,构造固定
argv,忽略调用者 PATH、使用环境 allowlist,并验证真实 Git worktree 注册;然后
通过仓库外的单次启动记录、terminal-bound nonce/proof 和受限 bootstrap 调用 Orca。
返回的 receipt 含 runtimeId、handle、incarnation、profile hash、slot 和 worktree
identity。Coordinator 将 receipt 追加到顶层 workerReceipts,再把 receipt ID
写入任务的 dispatch.developer 或 dispatch.test,并同步写入本轮 attemptId。
校验器要求 receipt 与当前 ACK task、角色、profile 和 attempt 完全一致;历史 receipt
不能跨任务或跨轮次改挂。
v0.10 自动 launcher 仅支持 read-only 与 workspace-write。full-access、
Codex bypass、Cursor YOLO/force 和关闭 sandbox 都会 fail closed;在有可信平台
审批或独立签发通道之前,不用项目文件伪装成用户授权。旧任务板没有结构化
project.orchestration 时仍可读取和手动协作,但不得自动创建 worker。
持久化 receiptHash 是无密钥 checksum,不是 launcher 身份证明。由于 Orca 当前
不能证明旧终端的原始 argv/模型/权限,v0.10 不自动复用既有 worker;每次自动派发
都重新 plan 并用 expected fingerprint 启动 fresh worker。
fingerprint 只校验完整计划没有漂移,不是一次性令牌;成功后不得用同一 fingerprint
重复启动,结果不确定时必须先 reconcile。
若创建或关闭回执不完整,或外部 launch record 状态无法可靠持久化,launcher 会返回
indeterminate/reconcile-required;必须先核对 record 与 Orca live state,不能
直接重试。
开始一个需求
初始化完成后可以直接说:
/ack 处理这个需求:<一句话需求>
Coordinator 会先读取项目状态和 references/kickoff.md,生成产品文档、任务拆分与
可观测验收信号;用户确认后才派发实现和复测。
首次配置交付可以说:
/ack 更新项目交付配置:用 make build-deb 构建 DEB,发布到 preview APT 仓库,
部署到 test-server 并跑健康检查;完成后创建 PR,停在 review_ready 给我审核。
之后处理需求时只需在确认计划中选择 profile:
/ack 处理这个需求:<一句话需求>。任务验证通过后执行 review profile。
ACK 会自动读取 delivery.yaml,无需再逐步提醒它构建、上传、部署或开 PR;目标或
权限发生漂移、缺少凭据、进入 stable/production approval 时才停下来请求决策。
版本
当前 Skill 版本见 VERSION。新项目在 tasks.yaml 中以合法 SemVer 记录
ackVersion。从 0.10.0 起,project.orchestration 与顶层 workerReceipts 必须
同时存在;从 0.11.0 起,新项目还会生成默认关闭的 delivery.yaml,并在任务板声明
project.deliveryFile 与 deliveryRuns;从 0.13.0 起,Coordinator 使用
select_tasks.py 获取有预算的任务上下文,不再把完整任务板注入模型。旧项目可以不迁移
而继续使用原闭环。旧项目的 kitVersion 可以继续读取,但建议迁移为 ackVersion。