跳到正文
coograph 17

工作流

Coograph 初始化过的项目里,每个变更都走同一条五步流水线:Plan → Propose → Apply → Review → Archive。例外仅限狭义且字面的情形——拼写订正、仅改注释、用户口述的配置值调整,以及在已批准的进行中提案上的跟进。

“琐碎”、“显而易见”、“小”、“就一处调整”不是例外。拿不准就走 Propose。

工作流的意义不是仪式感。是 AI 代理特别擅长自信地交付错误的东西,而工作流强制在那之前打断一次。

一个变更通常从 /coograph-new-ticket 开始:它先调查、问清楚该问的,再交给 Propose。在一个项目的第一个工单上,它还会问一次要不要让每个代理跑在不同模型上 —— 见模型。

Plan

/coograph-plan(Claude Code)或 @Planner(VS Code Copilot)。

Planner 代理调查代码库,一次只问一个聚焦的澄清问题。它从不写代码。输出是对变更需要什么的清晰理解——文件、集成点、风险。

跳过 Plan 的情形:

Propose

coograph-propose 技能在 openspec/changes/<YYYY-MM-DD>-<slug>/ 创建一个 OpenSpec 变更目录,内含:

.openspec.yaml
proposal.md           ← Why, Goals, Non-Goals, Decisions, Impact, Risks
specs/<capability>/spec.md   ← Requirements + Scenarios
tasks.md              ← 3–8 task groups, last is Verification

用户审阅后,要么说 “proceed”,要么发回修改意见。批准前不写任何代码。

Apply

代理按顺序处理 tasks.md,每完成一项就打勾。

所有任务完成后跑质量门:typecheck、lint、format、tests。修到全绿。

Review

/coograph-review 或 @Reviewer。

Reviewer 是只读的。每条结论都必须引用一次最新文件读取里的逐字原文——diff 和对话记忆不算合法来源。

结论按严重度分级:Critical(合并前必须修)、Warning(应该修)、Suggestion(可以修)。实施者修掉 Critical/Warning,重新跑质量门,仅当修复幅度较大时再走一轮评审。

Archive

把完成的提案归档:

mv openspec/changes/<slug>/ openspec/changes/archive/<slug>/

这样 openspec/changes/ 里只剩进行中的工作——代理在会话启动时会读进行中的提案。

代理

没有单独的 @Implementer。做 Plan 的代理也负责实施。

代理用途关键约束
Planner访谈式规划一次一问。从不实施。
Reviewer严格只读的代码评审每条结论都引用逐字原文。
Debugger根因分析,最小修复Reproduce → Evidence → Fix → Verify。3 次尝试熔断。
Verifier基于证据的完成检查自己跑命令。PASS/FAIL/INCOMPLETE 三档结论。
Explore快速只读的代码库问答快 / 中 / 深三档深度。
Retro把信号报告变成一份 OpenSpec只读确定性报告。从不自造证据。

所有代理都必须先调用 code-graph。回退到 sqlite3 .code-graph/graph.db,再到 grep,只有在图数据库确实不存在时才允许。图省事不是合法理由。

生命周期钩子

Claude Code 的生命周期钩子位于 .claude/hooks/:

钩子作用
block-generated.py阻止编辑 generated/、dist/、build/ 等目录下的文件,以及前 5 行带 @generated / DO NOT EDIT 的文件。
log-bash.py把每条 bash 命令追加到 .coograph/session.log 和 .coograph/sessions/<session_id>.log(两个都在 gitignore 中)。审计日志。
report-graph.py会话启动时报告代码图状态。graph.db 缺失时打印重建提示。
warn-scope.py存在进行中的 OpenSpec 时,编辑 tasks.md 未引用的文件会发出警告。暴露范围蔓延,但不阻断工作。
capture-signals.py会话开始时、每次压缩时和会话结束时,把转录变成 .coograph/signals.jsonl 里的隐私安全信号,并打印一行 Retro 状态。见 Retro。
no-new-deps-warn.py一个会话中第一次安装依赖包或编辑依赖清单时发出警告。还原式安装(裸 npm install、pip install -r、pip install -e .)不触发,因为它调用的正是 new-dependency 检测器所用的同一个函数。
defect-warn.py会话改过源码却没有做过审查时,在 git commit 处警告一次;Skill 工具、委派给 reviewer 代理、手输 /coograph-review 或 /coograph-ultra-review 都算审查。它提示的是被跳过的审查,并不检测缺陷。
openspec-gate-warn.py当第二个源文件即将被编辑、而会话中没有触碰过任何 OpenSpec 且不存在活跃变更时,每次会话警告一次。它是 OPENSPEC OR STOP 硬性规则的实时形式。
gotcha-surface.py代理编辑某个 GOTCHAS.md 条目路径下的文件、或运行它的某条命令时,把匹配的条目摆到代理面前,每次会话一次。见指令布局。

这些自动运行:不需要代理决策,也不需要 prompt 工程。

警告通过 additionalContext 送达代理(通过 systemMessage 送达终端),退出码为 0。一个打印到 stderr 并以 1 退出的 hook 是不够的:Claude Code 会把那段文字记进转录,但模型永远不会读到它。2026-10-06 的一次嵌套会话探针证明了这一点,于是每个警告 hook 都改用了模型能看到的通道。拦截 hook 仍然使用退出码 2,它会把原因交给模型。

可靠性属性

这些不是对正确性的承诺。它们是设计上让代理出错时大声失败的约束。