Imported from Joe-rq/harness-lab (
AGENTS.md). Install upstream withnpx skills add Joe-rq/harness-lab. Copyright stays with the author.
AGENTS.md
Harness Lab 是一个 研发治理层模板,不是业务运行时框架。
它的目标是让任何接手该仓库的人或 agent,都能按一致的入口、状态和交付物推进工作,而不是依赖口头上下文。
项目定位
本仓库固定的是治理协议,不固定的是业务实现。
固定内容:
- REQ 生命周期
- 设计、评审、QA、发布的交付物
- 索引优先的上下文加载顺序
- 进度交接和经验沉淀机制
- 会话启动协议和实施前检查点
- SessionStart hook 强制机制
由目标项目自己决定的内容:
- 技术栈
- 目录结构
- 架构分层
- 测试、构建、发布命令
- 领域规则和安全边界
已知限制
单用户设计:本框架面向个人开发者,不具备以下能力:
- 多租户/权限系统
- 并发控制(多人同时操作会导致数据丢失)
- 认证机制
- 审计日志
如需团队协作场景,请考虑使用 Linear、Jira 等成熟的项目管理工具。
目录导航
.
├── AGENTS.md
├── CLAUDE.md
├── context/
│ ├── business/
│ ├── tech/
│ ├── experience/
│ ├── invariants/
│ └── references/
├── docs/
│ ├── plans/
│ └── specs/
├── requirements/
│ ├── INDEX.md
│ ├── REQ_TEMPLATE.md
│ ├── in-progress/
│ ├── completed/
│ └── reports/
├── scripts/
│ ├── session-start.js # 会话启动脚本
│ ├── req-check.js # PreToolUse REQ 检查
│ └── req-cli.mjs # REQ 生命周期 CLI
├── skills/
│ ├── README.md
│ ├── plan/
│ ├── review/
│ ├── qa/
│ └── ship/
└── .claude/
├── progress.txt
└── settings.example.json # hook 配置示例
强制机制
1. SessionStart Hook
为确保治理协议被执行,建议配置 SessionStart hook:
- 复制
.claude/settings.example.json到.claude/settings.local.json - 确保
scripts/session-start.js可执行(Windows 下无需 chmod) - 新会话开始时会自动显示当前 REQ 状态
状态语义契约(唯一真相源):
- 机器状态的唯一真相源是事件账本(
.claude/events/*.jsonl、.claude/worktrees/*/events/*.jsonl)。会话启动只渲染buildProgressProjection()的投影结果,不解析任何手写文件来推导状态。 Current phase只有一个语义:当前活跃 REQ 所处的阶段。无活跃 REQ 即idle;"被阻塞"由搁置列表(suspendedReqs)表达,不复用phase。Last updated只由工作事件更新。session_started/session_ended只表示会话开关,不改变它——打开会话不等于有进展。- "最近事件"是流水窗口(最近 8 条 / 共 N 条),只说明最近发生了什么,不等于当前状态。
.claude/progress.txt不参与状态判定:CLI 会在 create/start/block/complete 时改写其头部字段,其余内容是人的笔记。会话启动把该文件原文照登(含其Current phase:等行),仅供人阅读,不作为机器状态。
2. PreToolUse Hook
在 Write/Edit/NotebookEdit 操作与 Bash 写命令前强制检查 REQ 状态与写入范围:
触发条件:Write / Edit / NotebookEdit / Bash 写命令(纯读如 ls/grep/cat 放行)
检查内容:
1. 当前是否有活跃 REQ
2. REQ 是否有实际内容(非模板状态)
3. REQ 状态是否为 draft
4. 写入文件是否超出当前 REQ 的 Scope Control / 只读边界
输出:如无活跃 REQ、REQ 为模板状态或写入越界,输出阻断信息并拒绝操作
行为:硬阻断,必须先创建并填写 REQ 或使用豁免机制
不可强制边界(上游平台限制,npm run harness:doctor 会提示):subagent 工具调用不触发 PreToolUse(claude-code #21460 / #34692)、claude -p 非交互不触发(#40506)、perl -e / python -c 等解释器写(理论不可封)。heredoc 正文不参与写目标扫描:bash <<EOF 这类"正文喂解释器"的写法与解释器写同类,故正文被整段剥离——否则 git commit -F - <<'MSG' … MSG 之类正常命令会因正文里的 > / < 被判为写操作而阻断(REQ-2026-101)。剩余缺口靠 OS 级兜底(文件权限、容器化、CI 侧校验),详见 README「已知限制」。
补充说明:
req:create只负责创建骨架,不代表 REQ 已可实施- 只有补齐真实背景、目标、验收标准后,REQ 才能通过 hook 与
req:start
豁免机制:
# 临时豁免(紧急修复、小改动)
touch .claude/.req-exempt
# 完成后删除
rm .claude/.req-exempt
范围声明的解析规则(scripts/scope-guard.mjs,2026-09-23 起):
## 范围段内的反引号路径会被解析为作用域声明,出现在否定句或说明句里一样算数:在**禁止(CANNOT)**段写`tests/foo.mjs`会把该路径解析为 deny(哪怕那句话的意思是"只允许改它"),而在豁免项说明里顺手提到一个路径会把它解析为 allow。- "目录级禁止 + 单文件例外"请写在
**允许(CAN)**段里显式列举,不要用 CANNOT 表达例外。 - 豁免文件写入免检:
.claude/.req-exempt与.claude/worktrees/<id>/.req-exempt永远可写——它是人闸载体,否则"创建豁免"本身会被 scope 检查拦住,REQ 范围再也改不动(自举死锁)。 - 活跃 REQ 的约定交付物自动 allow:
requirements/in-progress/<reqId>-*、requirements/reports/<reqId>-*、context/experience/<reqId>-*、docs/plans/<reqId>-*。这四类每个 REQ 都必须写,不再要求逐条声明;只读边界 REQ 不适用(仍只允许 reports)。
3. 高级 Hooks(PostToolUse / PreCompact / Stop / SessionEnd)
| Hook 类型 | 脚本 | 用途 |
|---|---|---|
| PreToolUse | req-check.js / scope-guard.mjs |
REQ 状态检查、scope 越界阻断 |
| PostToolUse | loop-detection.mjs / risk-tracker.mjs / watchdog.mjs |
编辑后循环检测、风险追踪、停滞看门狗 |
| PreCompact | precompact-notify.mjs |
上下文压缩前生成快照 |
| Stop | stop-evaluator.mjs |
防假完成评估 |
| SessionEnd | session-reflect.mjs |
会话反思与经验沉淀 |
--with-hook默认安装 SessionStart + PreToolUse(含req-check.js与scope-guard.mjs)。PostToolUse、PreCompact、Stop、SessionEnd 等高级 hook 需手动参考.claude/settings.local.json配置。
4. Hook Timeout 配置
Hook 默认 timeout 为 10 秒。如需调整:
- 编辑
.claude/settings.local.json - 修改对应 hook 的
timeout值(单位:秒)
{
"hooks": {
"SessionStart": [{
"matcher": "*",
"hooks": [{ "type": "command", "command": "...", "timeout": 20 }]
}]
}
}
需要调整的场景:
- 项目文件数量超过 1000 个
- 机器性能较差,文件遍历耗时较长
- 文档验证链路较长
5. 实施前检查点
在写代码之前必须检查:
-
是否需要 REQ?
- 涉及 3+ 文件、新功能、架构变更 → 需要
- 单文件小改动 → 不需要
-
REQ 是否存在?
- 有活跃 REQ → 继续
- 无活跃 REQ → 先创建
-
重要:用户给出的"实施计划"不等于 REQ!
- 用户给计划 → 创建 REQ → 实施 → 生成报告
违规示例(禁止)
❌ 用户提供详细计划 → 直接实施 → 结束
✅ 用户提供详细计划 → 创建 REQ → 实施 → 生成报告
默认读取顺序
每次会话开始时,按下面顺序读取:
AGENTS.mdrequirements/INDEX.md.claude/progress.txt- 相关的
context/*/README.md - 当前 REQ、设计稿、报告和必要代码
不要默认读取整个 context/,更不要把整个仓库一次性吃进上下文。
标准工作流
1. 接手前
- 确认当前活跃 REQ
- 确认 progress 中的最新状态
- 确认目标项目是否已经绑定真实验证命令
2. 创建或继续 REQ
- 新需求进入
requirements/in-progress/ blocked / suspended的 REQ 仍保留在requirements/in-progress/,并在 REQ 与索引里写明恢复条件- 中大改动的设计稿进入
docs/plans/ - 小改动可把设计摘要直接写进 REQ
req:create后要先把 REQ 写实,再执行req:start- 变更完成后补
requirements/reports/下的 review / QA / ship 报告 - 完成后移入
requirements/completed/
3. 执行原则
- 优先读取索引,再按需深入
- 验证必须真实执行,不能只写"看起来没问题"
- 修改模板仓库的入口文档、治理脚本或自动化门禁后,至少执行
npm test、npm run docs:verify、npm run check:governance - 修改安装器或接入流程时,额外验证目标项目
package.json的自动绑定或 placeholder guard 结果 - 评审和 QA 必须有落盘结果
- 经验沉淀必须回写
context/experience/
交付物要求
一个完整 REQ 通常会产生这些文件:
requirements/in-progress/REQ-xxxx-*.md或requirements/completed/REQ-xxxx-*.mddocs/plans/REQ-xxxx-design.mdrequirements/reports/REQ-xxxx-code-review.mdrequirements/reports/REQ-xxxx-qa.mdrequirements/reports/REQ-xxxx-ship.md(需要发布时)context/experience/*.md(有复用价值时)
框架使用边界
Harness Lab 不替你做业务架构决策。 它提供的是:
- 如何组织需求推进
- 如何保存设计与验证证据
- 如何让多次会话能连续工作
- 如何把经验复用给后续的人和 agent
如果目标项目已经有自己的分层、命令和发布方式,应保留原有业务结构,只在外面套这层治理协议。