读者与用途 :你要基于 Claude Code / Codex 等 harness,为某个应用场景(知识库、数据分析、运维、文档处理......任意领域)搭一个 agent-native 应用------能力以 skill / hook / MCP 工具形式寄居在 harness 里,由会话中的 agent 执行,而不是一个独立应用。本文是这类项目的决策清单与方法论 ,按"你会先后遇到的决策"组织。
来源:一个真实项目(基于 Claude Code 的轻量知识检索系统 kb)一个月的建设过程。文中实例全部来自该项目及其评测的实测记录,每条经验先给一般化原则与适用条件,实例只作一行佐证。本文独立可读,无需查阅任何外部记录。
0. 这类项目的通用命题
不管领域是什么,agent-native 应用都面对同样四个命题,全部经验都挂在它们下面:
- 规范如何被执行------执行者是 LLM,写在文档里的规范靠自觉遵守,必然漂移;
- 指令与机械防线的分工------LLM 的顺手工具(Read/Write/正则)天然诱导错误行为,只有指令没有校验的规则迟早被违反;
- 行为如何被度量------被测对象是"文件系统 + 工具 + 会话纪律"的组合而非 API 服务,评测与观测都要另起一套;
- 经验如何沉淀------踩坑与约定随会话消散,需要机制化的沉淀,否则每个月重学一遍。
1. 项目形态决策
1.1 能力寄居形态:先问"用户在哪工作"
原则:如果用户的工作现场是会话(对 agent 说话、丢文件、提要求),就把能力做成 skill(场景入口)+ hook(自动触发)+ MCP 工具(确定性操作),不要做独立应用/服务。判断标准:用户是否本来就要装一个 coding agent harness?是→寄居;否→寄居形态反而增加门槛,需要重新评估。
实例:kb 面向"在任何会话里检索知识库"的场景,整个系统没有独立进程------两个 skill、三个 MCP 工具、一组 hook 就是全部。
1.2 数据权威源:与用户数据同层的普通文件
原则 :如果应用要处理的数据本来就是用户的文件,让文件系统做唯一权威源,不引入数据库权威源------用户可以直接用任何工具查看/编辑/备份,agent 可以用 Read/Grep/Glob 原生操作,"系统"只是文件上的一个加工层。随之而来的分工铁律:
- 用户数据永不修改、永不删除(系统的输出写进单独的派生层目录);
- 派生层可整体删除、可全量重建------这是任何"文件加工型"应用的通用自愈模式:权威源与派生物分离,系统就永远可恢复、可迁移、可 debug(出问题删掉派生层重跑即可);
- 派生物带生产者标记(谁、何时生成)------被人工改动的派生物不覆盖,是"系统尊重人工介入"的机械表达。
适用条件反面:数据本身是流式/高并发/事务性的(日志接入、实时消息)时,文件权威源不成立,此节跳过。
1.3 进程模型:无常驻状态写者,允许常驻触发器
原则 :判定一个常驻进程该不该存在,看它死掉时系统处于什么状态:
- 写状态的常驻进程死了→状态腐坏、需要监督/重启/防重入,永久成本;
- 无状态触发器死了→系统静默退化为"没有它之前的样子",安全性等价。
所以身份条款要精确到禁的东西:"无常驻状态写者"而非笼统的"无常驻服务" ------定时器、文件监听这类触发器可以常驻,但它们只传递"该跑了"的事实,不写状态、不与流水线共享状态 。真正的加工由短进程完成(跑完即退,无腐坏态),短进程间互斥用锁------跨平台锁的正确做法是找满足同一锁契约的各平台原语 (如 Linux 的 flock 对应 Windows 的 msvcrt.locking 加 Job Object:持有进程死亡时内核自动释放),而不是试图抽象掉平台差异。
实例:kb 曾辩论"用 Python/Rust 自写常驻调度守护进程抹平 Windows/Linux 差异",否决------差异在 OS 设施层(cron/schtasks、flock/LockFileEx、信号/Job Object 互不兼容),换语言只是把分支藏进别人的依赖库里;而 OS 定时器的监督是免费的,自写守护的监督(崩溃重启、防重入、日志轮转)是永久成本。
推翻旧决策的方式 :收窄表述而非整体推翻,且精确划界取代范围(写明只废哪一条、哪些结论仍然有效);同时勘误"引文转述漂移"------文档 A 引用文档 B 的话往往不是 B 的原字面,修订时把新表述直接写进源头文档,消灭二手转述层。
1.4 事件与扫描:watcher 只是唤醒,比对才是权威
原则 :任何"感知外部变化"的子系统(同步、索引、监听部署......),事件通知都会丢(内核缓冲溢出时静默丢弃全部积压事件 、网络存储没有事件、进程重启窗口期的变更无事件),所以架构必须是事件层提前唤醒 + 全量比对兜底,权威判定永远在比对侧。事件触发的价值只在"降低时延下限",不在正确性。
配套否决经验:"把轮询周期缩短"不是事件驱动的等价替代------空转成本固定发生(与有没有变更无关)、事件风暴期间反复无效启动、失去"真有变化且静默后跑一次"的语义。周期轮询的时延下限靠堆频率买,事件触发的时延下限天然贴着真实变更。
实例:调研 Dropbox/Syncthing 等网盘产品后确认这是全行业共识------Syncthing 的架构一句话就是"watcher 只是提前唤醒 scanner,扫描才是权威";Dropbox 在 inotify 上限不足时报错但依然能同步(只是变慢),恰好暴露了扫描兜底层的存在。
1.5 快慢分离:确定性先行,判断力接力
原则 :流水线按"是否需要 LLM 判断"切成两段------确定性部分(探测、机械生成、簿记写入)做成可无人值守执行(定时器/钩子触发),判断力部分由会话内 agent 接力补完。两层之间用显式的接力状态(如"待补完清单")衔接:定时器做能做的,入口场景被触发时先检查接力状态、清完积压再接新任务。用户由此获得"日常零手动命令"的体验。
实例:kb 的向量簿记由外部定时器无人值守完成,wiki 学习这类判断力工作只在会话内做;ingest 技能的入口固定第一步是"清接力积压"。
1.6 语言/技术选型的唯一反例判据
原则 :见 1.3------换语言抹平平台差异不成立。唯一的例外判据是分发形态:要给外部用户发一个独立单二进制时,编译型语言(Rust/Go)才是正解,因为那时你分发的就是那个进程本身。
实例:kb 同一个项目里两次选型方向相反------调度层否决了自写守护进程(用 OS 定时器),文件监听层却选了 Rust------因为监听器要作为独立单二进制随安装包分发。同一条经验两面用,判据始终是分发形态。
1.7 价值论证必须回答"谁在等"
原则 :为一个组件/优化找价值锚点时,枚举全部使用场景并找出唯一真实受益窗口------"时延从 5 分钟降到 1 分钟"不算论证,除非写明谁在等这 4 分钟。无等待者场景的优化无可观察差异。
实例:kb 的事件监听方案评审时被抓出这个问题------会话启动场景本来就有开场钩子补跑同步(监听器无增益)、纯无人值守场景没有等待者(早 4 分钟无可观察差异),唯一真实受益窗口是"会话进行中落文件后立刻检索"。价值锚点改写为这个窗口后,论证才闭合。
2. 纪律工程:LLM 执行者的保证层
2.1 散文规范必然漂移
原则 :写在 skill/文档里给 agent 看的规范是散文,机器不可判定、靠自觉、可被跳过------漂移不是是否问题而是何时问题。两类漂移都要预设:
- 新发漂移:执行时被跳过/打折;
- 存量漂移 :规范升级后,已生成的存量产物不会自动重写------事件驱动流水线的触发条件只有数据变化,规范/依赖版本变化不是事件。升级规范后必须显式安排迁移轮(机械迁移消化存量),并接受"跑一次什么都没做"是正确行为而非故障。
实例:kb 的生成物头部格式规范升级后,跑"更新索引"得到空操作------因为流水线只看知识文件有没有变,规范变了知识文件没变,变更集永远为空。曾误以为"存量会随下次流水线自然迁移",实测证明那是错误预期。
2.2 解法定式:确定性校验器 + 三层接入
原则 :把规范里机器可判定的形态不变式(键名、事件形状、逐字一致、深度上限、路径规则......)抽出来做成确定性校验器(纯代码,零 LLM),三层接入:
- PostToolUse hook 拦新发------把"相信剧本"换成"harness 保证";
- 定时器周期跑检存量------hook 是写后反馈不是写前阻止,坏产物可短暂落盘,第二层必要;
- 违规清单作为迁移轮的输入------形成发现→修复闭环。
两条不可破的界线:
- 形态 vs 质量:凡需要判断力的一律不进校验器(否则膨胀成内容审查),判断力类检查保留在剧本里做抽检;
- 单一权威源:校验器是形态规范的权威,剧本只写意图与流程并显式引用它------否则"散文规范"只是层级抬升重演。
推广定式------"软约束给判断力,硬上限给代码" :需要灵活性的约束("最好不超过 2 层")写剧本靠自觉,硬边界("超 3 层直接 fail")进校验器;硬边界的数值要先量现状再定(实测一下现有产物的分布,让选型有数据依据),不要拍脑袋。
实例:kb 的生成物规范(头部键名、锚点逐字一致、wiki 概念树深度)抽成了 conformance 校验器,hook 在每次写入后拦截、定时器周期全检;wiki 深度上限 3 层是先实测"现有 23 篇零嵌套"才定的数。
2.3 执行漂移:不变量 + 原语命令 + 机械校验
原则:当 LLM 的顺手工具能完成一个"语义正确但方式错误"的操作时(用 Read+Write 实现"移动"、用重写实现"改名"),指令写得再清楚也会被执行漂移侵犯。修法三件套:
- 不变量:把本质说成可校验的物理事实("内容永不经过模型,字节级不变");
- 首选原语命令:直接给出正确的原语(mv、git mv、shutil.move),并说明为什么不能用重写;
- 事后机械校验 :选重写不可伪造的签名------哈希 + 文件修改时间的纳秒级全等(重写必然改变 mtime,文件系统层证据不可伪造)。
实例:kb 明令"目录归类时移动必须是 mv",agent 仍用 Read+Write 重写------因为读了正文之后重写是零成本顺手路径。补上"移动前后 sha256 比对 + mtime 纳秒全等校验"后防线才成立。重写的危害不只是 token 浪费:内容可能被模型改写、下游锚点(行号)全部失效,而且 mtime 变化会被变动探测当成用户编辑------内容损坏被伪装成正常输入,静默放行。
2.4 行为测试方法论:测"自然执行"而非"被提醒时"
原则:验证 agent 是否遵守纪律的沙箱测试,效度毁于三种常见设计错误:
- 提示里含校验要求→制造 demand characteristics(被试猜到你想观测什么,测的是"被提醒时能否遵守",不是自然执行时是否遵守);
- 替被试做了判断("把 X 移到 Y")→恰好绕过"为判断而读内容→内容已在上下文→顺手重写"这一最高诱惑路径;
- 依赖被试自报→只能用纯外部字节级证据判定。
正确形态:自然环境布置(把材料散放着)+ 只说用户会说的话("整理一下")+ 外部签名判定。测试污染(沙箱残留线索被被试发现并利用)要主动披露并给结论打折。
实例:kb 的"移动不变重写"沙箱测试经三轮返工才有效------第一版提示"汇报校验细节",第二版直接指定移动目标,都测出了假阳性 PASS;改成平铺文件+宽泛提示+外部 sha256 判定后,才测到真实行为。
2.5 跨文档约定单源化 + 接口自解释
原则:
- 同一约定写在多处,必然漂移------升格单一权威定义(代码或某一份剧本),其余位置只留一行指针;
- 对外输出(CLI stdout、日志、报告)必须自解释------不出现"rule:R7"这类要查码表才懂的符号,直接写"问题+修复"的人话;
- 机器口径与人类口径分开:exit code 反映机制面成败,文字结论反映人的观感,两者分开计算分开陈述------警告(⚠)不该被算进"N/N 通过"的分子。
实例:kb 的一条约定曾在六份文档里各写一遍,当天就被发现不一致;安装自检曾输出"18/18 通过"但同时带 5 个 ⚠------退出码语义正确(首装无数据不该拦安装),但给人看的计数把 ⚠ 算进分子就是失真,改为"13 ✓ / 5 ⚠ / 0 ✗"三项分列。
3. Skill 设计
3.1 结构:路由表 + 机制剧本(渐进式披露)
原则 :skill 主文件只放三样------角色定义、场景路由表 (用户会说什么话→走哪条流程)、红线;一切执行细节下沉到 references/ 机制剧本,主文件每步只留一行"Read 哪个剧本"。目的:主文件可扫描(装载时省上下文),剧本按需加载。配套纪律:改 agent 行为优先改剧本,不动主文件------主文件是对用户的契约,剧本是对 agent 的实现。
实例:kb 的入库技能主文件是 7 步路由表,每步一行指针;细节全在七个剧本文件里,执行到哪步才读哪个。
3.2 按场景切技能,不按机制切
原则 :技能入口对齐用户会说的话("入库"、"查找"),不对齐内部机制("索引"、"向量同步"、"学习")------流水线环节是技能内的剧本步骤,不是独立技能。用户不应该需要理解你的机制分层才能找到入口。项目文档里只有场景表、没有"编排"概念。
3.3 剧本措辞即代码,可 TDD
原则 :skill 文本约束 agent 行为,地位等同代码,应该用评测失败案例驱动迭代(RED-GREEN-REFACTOR):失败分解=RED 基线→改措辞→复测。第一版规则几乎必然有措辞漏洞,两种已知漏洞形态要专门检查:
- 绑定对象错位:规则说"枚举完整答案",真正要约束的是候选集------绑定到哪个对象必须精确对齐失败模式;
- 廉价逃逸口 :"补上引用或删掉该要点"给了 escape hatch------约束条款里的每个"或"都要审查是否存在免除路径。
实例:kb 的检索纪律剧本第一版修复后复测回退(引用召回 0.653→0.621),诊断出正是这两个漏洞------"枚举完整"绑在了答案集合上(多选题该枚举的是候选),"补引或删要点"让 agent 用删要点来免债。堵洞后第二版全绿(0.677)。教训:修剧本必须复测,第一版措辞几乎必然有洞。
3.4 纪律条目的挤出效应
原则 :给 agent 的纪律清单不是越长越好------条目越多,排序型/流程型纪律越被挤出 。因此:流程纪律写成条件规则("当 X 未命中时才做 Y")而非固定顺序;每次加条目前想清楚它挤掉什么。
实例:kb 检索剧本第一版加长后,20 个测试会话全部直接用向量检索起手、"先读导航索引"步骤执行数从 2/20 掉到 0/20------新增条目把入场步骤挤没了。
3.5 触发描述要对抗 undertrigger
原则:skill 的 description 决定何时被触发,普遍偏保守------要显式写入"即使用户没说关键词也应用本技能"的推力与典型场景枚举。检验方法:收集"本该触发却没触发"的真实提问,把它们写进描述。
实例:用户问"什么是自一致性与多数表决"------没提"知识库"三个字,但答案就在库里;这类问题后来写进了检索技能的触发描述。
4. Harness 机制组合
4.1 三层自动化分工
| 层 | 承载 | 特征 |
|---|---|---|
| 确定性层 | 外部定时器/触发器 + 短进程 | 无人值守、可失败重跑、只做机械工作 |
| 播报层 | SessionStart/PostToolUse hook | 把系统状态自动注入会话上下文(agent 开场就知道现状) |
| 判断力层 | 会话内 skill + MCP 工具 | 用户驱动的全部场景工作 |
并明确文档化一件事:哪些变更是自动驱动的、哪些必须用户显式触发------规则/剧本的变更不属于自动触发范围,agent 对它报"无事可做"是正确行为,别让用户误判为故障。
4.2 分发:走宿主原生机制,不自建第二通道
原则 :安装/更新用宿主自己的 CLI(如 claude plugin install/update、claude mcp add)完成注册,绝不由安装脚本拷贝文件到宿主目录------拷贝等于第二分发通道,必然与宿主缓存漂移。
注意边界的精确含义:禁的是"脚本把宿主管辖的内容(skills/hooks)拷进宿主目录",不是"不许有安装脚本"。安装脚本作为编排者不仅合法而且必要------宿主 CLI 只管 harness 内的内容,Python 运行时、定时任务注册、数据目录 seed、体检这些宿主一概不管。正确分工是:脚本做编排 + 一切宿主外的设施;凡涉及宿主的步骤,脚本退化为驱动宿主 CLI。
最大的隐形坑:宿主插件缓存按版本号决定是否刷新------代码改了、版本清单没 bump,宿主永远报"已是最新",会话读到的还是旧技能。纪律:改 skill 必 bump 版本清单并重跑安装,要成为肌肉记忆。此外 scope 要对齐使用现场:技能的使用现场是任意会话时,装 project scope 等于技能只在仓库目录里生效------默认 user scope。
实例:kb 曾在改完技能后疑惑"怎么没生效",排查发现正是版本号未 bump 导致宿主缓存永不刷新;另一次升级时,一个目录链接让拷贝器静默死掉但安装报告成功------宿主缓存相关的一切都要实测验证,不能信"报成功"。
4.3 Agent-native 的配置与提示写法
- 用户不手改配置文件,而是对 agent 说"把 X 配成 Y"------所以一切配置提示(README、doctor、报错信息)都写成精确路径+键名,让 agent 能照提示代改;
- 配置引导"指路而非向导":配置是用户数据,安装器只 seed 缺失、永不覆盖、永不代填;设施/数据分离------安装目录可整体重拷/整体删除,数据根只 seed 永不删除(放错位置意味着重装覆盖配置、卸载删数据);破坏性操作(清数据)要输完整路径二次确认;
- 配置分文件的教条要过场景检验:"密钥单独 .env"的最佳实践服务于"配置会共享、密钥不能跟着走";当配置与密钥同在私有 gitignore 目录时,分文件只换来两处查找两种格式------合并成单一权威文件 + 环境变量覆盖,配唯一解析器,调用方禁止各自读环境变量;
- 卸载顺序有语义:先摘除调度任务并复核真删掉,再动安装目录------否则任务对着已删运行时反复空跑报错;
- "失败宁报错不静默"的设计要预先在文档里解释,否则用户把预期行为当故障(如"端点未配置时报 error 状态"是任务活着、自检如实拒跑,不是崩溃)。
4.4 利用宿主的会话轨迹(重要且常被忽略)
headless(claude -p)与会话的全部执行轨迹 (带时间戳的每次工具调用)落在宿主的项目目录下(如 ~/.claude/projects/**/*.jsonl)------这是免费的 ground truth 观测面:执行时长、工具调用次数、流程遵守情况都可以离线确定性提取。评测(§5)与行为审计都建在它上面。
5. 评测体系
5.1 选框架先看被测对象的形态
原则 :被测对象是"文件系统+工具+会话纪律"的组合,不是 API 服务------假设"被测对象是模型 API"的评测框架不适用。选择判据:①能否承载确定性自定义指标 (零 LLM 的程序计算)与 LLM 裁判指标在同一 runner/缓存/报告里;②是否库形态(如 pytest 骨架)而非黑盒服务。端到端测法:headless 跑 harness 本身(claude -p "<问题>")捕获回答与引用。项目本身就是被测系统和端到端驱动,需要补的只是一个薄适配层,不是另一个 harness。
实例:kb 弃了一个主流模型评测框架、选了 pytest 骨架的库------决定性判据是"golden 引用的精确命中率"这种纯程序指标能与 LLM 裁判指标共享同一个 runner。
5.2 归因靠控制变量轮次,不靠单轮分数
原则 :系统由多层机制叠加(基底→行为纪律→加工机制)时,单轮分数无解释力。设计三轮同数据同题 :A(裸基底)→B(+行为纪律)→C(+加工机制),每轮只改一个变量,差值即该层净贡献。诚实登记方法论缺口:headless 会话有随机性,"增益"与"抖动"未切割------用重复轮估会话级方差底噪(样本小也能做符号检验/bootstrap 置信区间)。
5.3 不替被测对象做它该被测的决策
原则 :端到端评测里,被测系统该自己做的决策(组织、分类、规划)留给它自己做------测试侧只负责布置环境(把原料散放着倒进去)。替它组织好,等于把被测变量固化成测试代码常量,测出来永远是好的。
实例:kb 的建库评测中,物化脚本只"倒垃圾"(把语料平铺倒进根目录),目录归类、索引、摘要全部留给被测的建库 agent 自己决策------"它分错了,分数会替你说话"。
5.4 golden 锚定用内容指纹,不写死路径
原则 :被测系统会移动/改写文件时,期望结果不能锚定路径------存"内容指纹"(如剥去生成性头部后的正文哈希),打分时实时解析现路径。丢失/改写自动暴露为扣分 ,这同时是产品侧的保真审计。配套纪律:指纹预检------加工开始前趁原料还是原始布局先跑一次解析,全部可解析才开跑(避免几小时加工后才发现 golden 口径不一致)。
实例:kb 靠指纹审计抓到"229 篇语料在加工搬移中丢了 1 篇"------这类缺陷只有把加工对象放进受控实验才能抓到;也抓到引用锚点被 agent 改写(语义对但非逐字)的高频违规。
5.5 过程指标必须宿主侧观测,不信 agent 自报
原则:从 agent 的回答文本里提取过程数据("共 N 轮"这类自报)极度脆弱------换语言/语料风格立即断裂。正解:过程指标全部来自 §4.4 的轨迹文件(时间戳差、工具调用计数),确定性可提取、跨语言稳定。观测量作为诊断指标随记录下发,不做阈值断言(时长与轮次没有及格线概念)。
实例:kb 的中文评测里 79 个会话有 77 个自发写"共 N 轮"(可正则提取),换英文语料后 100 个里只剩 6 个------三轮抢救后放弃,"样本只有 6 题,报均值就是编数据";改从轨迹文件提取后成为稳定的硬指标。
5.6 读数纪律
- 均值与 Pass Rate 度量不同的东西:均值奖赏"做得满",门槛计数奖赏"及格面宽",分布形状不同时两者可反向------下结论前看逐题分布;
- 逐题打分明细必须落盘,不只是打印------对照组环境一变,不落盘的明细永远不可重建;
- 指标混装要拆:一个指标混着两种责任方不同的失败(格式违规 vs 实质无效)时,修复复测后分不清哪个生效了------拆成子指标;
- 缓存(会话/结果按 id 跳过)要加版本印记(prompt/skill 的 hash),让过期从"靠记忆"变成"可检测"。
实例:kb 一轮评测中 B 轮均值高于 C 轮但 Pass Rate 反向------原因是 B 靠满分题拉均值、C 过线题面更宽,3 题之差在裁判抖动噪声内,读作持平;同轮一张对照表因建库后重算 B 轮、按旧路径读文件全部落空,成为无效计算。
5.7 归因到可行动:缺口分类 + 探针查询
原则 :评测分数不足时,把每个期望命中的目标逐个归类(命中未跟进/全程未出现/格式伪影/读取未引用......),再对"全程未出现"类跑探针查询 (用理想查询直接查基底)------以此鉴别"基底检索问题 vs agent 行为问题"。这一步廉价且关键。归因结论要回答"增益为什么没兑现":增益空间 ≈ 该机制节省的成本 × 该成本在任务中的占比------占比趋零的任务上,再好的机制也没有兑现渠道。
实例:kb 一轮评测 9 篇期望文档全程未出现,探针查询发现其中 6 篇用对查询就能进 top-8------证明大头在 agent 检索行为层,修复靶点是剧本措辞而不是检索引擎。另一轮:建库机制在单跳语料上省 22% 检索轮次,在多跳语料上无质量增益------因为多跳任务一次检索就收工,寻路成本占比趋零,瓶颈在导航管不着的段落级证据覆盖。
5.8 迭代节奏:小回归轮 + 发现清单
- 全量评测贵,建一个分层抽样的小回归集(20 题量级、含干扰项、~1.5h 可闭环),机制改动后先跑它再上全量;
- 评测产出的发现清单(编号 F1...Fn)每条对应明确责任方与修复面(剧本/指标/runner/产品代码),修复后同架构复测------"评测发现瓶颈→改机制→小回归轮证实增益"的闭环要真的走通一轮,评测体系才算建成;
- 机制有效性看消费侧证据,不看产出侧合规:产物全部合规但零消费=机制没起作用;有消费且消费对应增益,才算数。
实例:kb 的知识沉淀层(wiki)一度 22 页产物全部通过合规校验,但 100 个测试会话里 0 个读过------机制实际没起作用;改版后 20 个会话里 3 个消费了聚合页、且消费的恰是升幅最大的题,这才算"机制起作用了"。
6. 文档与沉淀体系
6.1 文档分层:四文档 + 三级读者
原则:项目文档固定分工,防一份文档膨胀成什么都装:
| 文档 | 装什么 | 不装什么 |
|---|---|---|
| 方案/设计正文 | 当前阶段可执行的设计 | 成本模型、评测细节、外部项目叙事、工作量说明、对撰写者的元要求 |
| 开放问题(OQ,编号立案) | 证据与延后项 | ------(缺口先立案再消灭,不许静默丢弃) |
| 决策记录(ADR) | 每次定案:决策、理由、被否的备选 | ------ |
| 调研报告(证据库) | 外部实现逐字原文+证据路径 | 结论转述 |
外加三级读者分层:README(用户:行为与效果)/ 贡献指南(开发者:约定)/ ADR+docs(设计论证)。正文瘦身是常态动作 :细节外置到对应文档,正文留一行摘要+指针防失锚。两条防自相矛盾机制:新决策收窄旧决策时不删旧文、旧处补"由 X 收窄"指针;立场反转后全文档走查承载旧立场的落点(章节、图、TL;DR),否则留下"标题与内容相反"的结构债。
实例:kb 的设计文档曾把某机制定为主形态后又反转,反转时没重排受影响章节------留下"章节标题写 A、内容讲 B、主形态排在从形态后面"的结构债,后来专门一轮重排才还清。正文瘦身也反复发生:助手两次论证某内容"该留正文",用户两次裁决移出------现行定案是"正文只留当前阶段可执行的设计"。
6.2 README 选材两步筛选
原则 :第一步筛内容------用户需要知道才能正确使用/形成正确预期的才进 (用户无需动作的内部选型一律删,哪怕它很"机制有趣");第二步才谈写得通俗。README 围绕一句用户契约组织(一句话说清系统对用户的承诺),章节各答一个问题:这是什么/怎么装/日常怎么用/坏了怎么办。
实例:kb 的 README 第一版保留了监听器实现语言这类"有趣的机制",被指出"用户需要知道这些吗?"------监听器装不装、用什么写,用户都不用做事,全删;保留的是"最迟 5 分钟可检索"这类用户要据此形成预期的行为承诺。用户契约一句话:"放进 knowledge/ 的文件最迟约 5 分钟可检索,问问题得到带出处的回答。"
6.3 CLAUDE.md 写"最容易做错的事"
原则:项目指令文件(CLAUDE.md/AGENTS.md)的有效成分,按实测价值排序:
- 负向指令:把最容易犯的错写成禁止项(如"不要把已归档的旧路线带回现行方案"------归档物放着就会被翻出来模仿);
- 定案直陈:关键架构约束直接写入,不让未来实例翻方案文档;
- 反假定声明:"选型未钉死,实现前先查待定清单"------防止未来实例凭训练直觉假定技术选型;
- 发现性指引:新增的沉淀目录(经验库、词汇表)必须在 CLAUDE.md 有入口,否则沉淀等于丢失;
- 克制:没有的东西不编造(无构建系统时不写 build 命令);
- 修正仓库定性错误优先级最高------一句话定性偏差("这是文档仓库"vs"这是实验仓库")影响所有后续实例的行为。
6.4 经验沉淀机制
原则:项目自身的踩坑与约定也是知识,要机制化沉淀:
- 单次会话的重要学习(约定、坑、方法论)固化为结构化归档 (带 frontmatter:模块/标签/问题类型,可检索),仓库根维护一份共享词汇表(项目特有概念的权威定义,种子只覆盖真实调查过的区域,不预设);
- 沉淀要做双接地校验:机械接地(提到的代码/文件存在)+ 语义接地(断言与实物一致)------能抓出文档与代码不符的断言;
- 沉淀的约定要反向刷新旧文档与写作规范(新约定生效时,扫一遍存量文档是否违反);
- 分析类结论(如评测归因)同样归档,README 只留结论摘要+链接。
实例:kb 第 10 天才建立沉淀机制,前 9 天的教训险些随会话消散;首条沉淀是"架构图的线型语义约定",沉淀时的接地校验当场抓出一份旧图违反新约定,随即修正。
6.5 外部调研的交付形态
原则 :调研同类实现必须拉到逐字原文(提示词、常量、配置)+证据路径,不信转述------"涌现黑盒"往往是没读到 prompt/常量层。固定交付三件套:调研文档(含"确认不存在"节)+ 可移植件清单(按契合度排序)+ 开放问题状态回填。
实例:kb 调研两个成熟开源项目的"知识抽取机制",文档层只看到概念定义,一度以为是无规则的涌现行为;下钻到源码的提示词与常量层才发现抽取规则全部成文(实体/概念二分、三档粒度、目录深度代码硬截断)------"黑盒"只是没读到 prompt。
6.6 架构图
原则 :图合格的判据是承载了关键信息(权威方向、时序、循环、决策论证),不是画得对更不是美观。五条具体标准:
- 每张图回答一个读者问题,图型匹配信息形态------剖面表达"嵌在谁里面"、时间轴表达时延渐变、单向图表达权威与禁止方向、对照带表达"被否→定案"的论证结构;流程图表达不了这些;
- 线型语义全局编码:写入、只读查询、装配接力三种操作不能共用线型("语义相反的操作画法相同"是标签救不了的冲突);一条边承载两种操作要拆边;
- 带序多回边的图,自动布局是错误工具,手排坐标(纯文本可 diff);
- 在新媒介里复刻旧媒介是被点名批评的反模式------放开工具限制是为了表达旧工具表达不了的东西;
- 可交付性:动画要有 reduced-motion 降级与打印样式;再生物(GIF)的生成脚本入库,一条命令可重生成,防与源漂移。
实例:kb 的总体结构图经历三阶段------基础流程图被批"没用基础元素之外的表达,没起到说明系统的作用";换成 HTML 里复刻 mermaid 又被批"复刻旧媒介";最终每个面板选该信息形态专属的图型才过关。线型语义的教训:一条"只读查询"连线与"数据写入"同款实线,读者必然误读为"会话触发了写入"------拆线型后成为首条沉淀经验。
6.7 写作五律
- 面向技术读者,通俗=直陈要点,不用类比("我们的读者都是有技术背景的",图书馆类比全删);
- 概述给思路与层次递进(底座→使用面→闭环),不是要点罗列------"这只是罗列具体的点,缺乏思路和全局视角";
- 面向什么语言的读者就用什么语言直述,不堆缩写黑话(写"唯一事实来源"不写 SSOT);
- 对外文档必须独立可读------绝不写"见记录 xxx / 见决策 xxx"这类要读者翻外部材料才能理解的引用;证据一律改写成内嵌的一两句叙事,读者当场读懂。引用标注对写作者是溯源便利,对阅读者是断链;
- 总结/经验类文档只收可泛化的经验------目的是让读者照着搭起自己场景的同类项目;本项目特有的机制细节(具体产物名、领域规则)要么剔除,要么抽象成一般模式+适用条件。
实例:本文自身就是按四、五两律返工的------初稿每条经验后挂"会话编号+ADR 编号"的溯源引用,读者必须翻原始会话记录才能明白在说什么;且混入了项目特有细节(派生物清单、领域规则)。返工后:引用全部改为内嵌叙事,特有细节抽象为通用模式,并注明适用条件的反面。
6.8 与用户的协作经验
- 文档缺口就藏在用户的提问链里(连续问安装/使用/卸载=文档没覆盖),但不能只按提问补 FAQ------主动按新用户完整生命周期(装→配→用→排障→停→卸)重组;
- 用户常以"弄懂而非推进"为目的------回答要可复现(step by step、数据样例),不是结论交付;
- 多评审人(多 persona subagent)评审的真实收益在交叉印证:高置信发现几乎总由多个独立 persona 同时命中;findings 要有 schema(严重级/自动修分级/置信锚点/逐字证据);跨模型投票在受限环境(缺依赖、平台限制)会整链失效,设计"跳过不失败"的降级路径。
实例:kb 的方案文档评审跑 5 个 persona 并行,最终确认的高严重级问题全部由 2-4 个 persona 同时命中,单人独有的发现多是低置信的遗漏类;跨模型独立评审因运行环境缺依赖整链降级为跳过,未影响本轮其余结论。
7. 治理
- 提交纪律 :diff 自己会说话,正文只写 diff 推不出的东西(动机/取舍/验证证据);字段枚举是流水账变体;无 AI 尾注(若用户明令);一次工作=一个总结式提交,边界按工作单元而非会话划分(跨会话完成的一件事拆一个提交,两件事在同一个会话收尾也拆两个提交);无关工作区改动永不裹挟;
- 单人开发无 CI 时,PR 的价值是留档(决策与验证证据的一生记录)不是流程卡点;已推送历史不重写,走合并不变基;
- 完成态宣称诚实分层:机器口径(exit code)与人类口径(措辞)分开;主动声明反作用、回退、小样本置信度------"机制属性不是缺陷"与"真实缺口"分开陈述,残余问题立案(OQ)不静默丢弃。
实例:kb 一次剧本修复复测出现指标回退,如实报告回退+诊断出两个措辞漏洞+堵洞后复测通过,全链记录在案;一次样本仅 20 题的增益声明"方向明确但幅度置信度有限,值得跑全量确认"------诚实分层不削弱结论,反而让结论可信。
8. 搭建清单
给一个新场景起项目时,按此顺序做决策(每项指向本文对应节):
- 定现场(§1.1):用户在会话里工作吗?是→skill+hook+MCP 形态;列出用户会说的场景话术(未来 skill 的入口)。
- 定数据权威源(§1.2):数据是用户文件吗?是→文件权威源+派生层分离,写下"用户数据永不修改/派生层可重建"两条铁律。
- 定进程模型(§1.3-1.5):哪些工作是确定性的(→定时器/触发器+短进程+锁)、哪些需要判断力(→会话内 skill);变化感知用"事件唤醒+比对权威";两层间设计接力状态。
- 最小闭环:先打通一条"用户丢入→系统加工→可回答"的最短链路,别先建全部机制。
- 纪律层(§2):列出 agent 执行中"顺手工具会做错"的操作,每个配不变量+原语命令+机械校验;把形态规范抽成确定性校验器+hook 拦截。
- 评测基线(§5):headless 端到端 + 内容指纹 golden + 控制变量轮次(基底/行为/加工三层);建 20 题量级小回归集;过程指标走轨迹文件。
- 文档与沉淀(§6):四文档分工 + OQ 立案 + CLAUDE.md 负向指令 + 经验归档机制,从第一天就开(kb 的沉淀机制第十天才建立,之前的教训险些丢失)。
- 分发(§4.2):安装脚本驱动宿主 CLI;确定版本 bump 纪律;设施/数据分离目录布局。
- 迭代节奏:评测发现清单→修复(剧本措辞按 TDD)→小回归轮复测→全量;立场反转时全文档走查。
9. 反模式速查
- 靠散文规范约束 agent 行为(机器不可判定→必漂移);
- 只有指令没有机械校验的关键不变式("移动"被执行成"重写");
- 规范升级指望"下次流水线自然迁移"(规范变化不是事件,空操作是正确行为);
- 自写常驻守护进程抹平平台差异(换语言藏分支+永久监督成本;唯一例外是独立二进制分发);
- 轮询缩周期冒充事件驱动(失去静默语义);
- 过程指标依赖 agent 自报(换语言/风格即断裂);
- 替被测对象做它该被测的决策;
- golden 锚定路径而非内容指纹(被测系统一动文件就失效);
- 单轮分数下结论(无归因)、均值与过线率混读、逐题明细不落盘;
- 自设计语义清单当选型需求集(构造性预定结论)、PoC 只测最商品化部分;
- 指标混装两种责任方的失败;
- 安装脚本拷贝文件进宿主目录(第二分发通道)+ 忘 bump 版本(缓存永不刷新);
- 在新媒介复刻旧媒介(HTML 里画 mermaid);README 堆用户无需知道的机制;
- 教条正确场景错误的配置拆分(私有目录里密钥另立文件);
- 纪律清单越长越好(排序型纪律被挤出);流程写成固定顺序而非条件规则;
- 立场反转后不走查存量文档(结构债:标题与内容相反);
- 行为测试带校验提示/替被试做判断(demand characteristics、绕过最高诱惑路径);
- 对外输出要查码表才懂;警告被算进"N/N 通过"。
10. 一条主线
这类项目的建设本质上在回答一个问题:当软件的执行者是 LLM 时,"正确性"靠什么保证? 答案是三层递进------先靠纪律(skill 剧本措辞,用评测失败驱动迭代到精确对齐失败模式),再靠机械防线(确定性校验器 + hook + 不可伪造签名,只收硬不变式),最后靠评测闭环(控制变量归因 + 内容指纹 + 轨迹观测 + 小回归轮,用差值证据说话)。文档与沉淀体系保证这些答案本身不随会话消散。这套东西没有一件依赖具体业务领域,全部可以搬走。