docs(agents): align the conceptual-integrity skill with its standalone version

Mirror the structure of Darkatse/conceptual-integrity in Chinese and
localize it to TauriTavern's contracts and docs. Adds an explicit stance
against hedging and against tests that pin implementation, plus
pile-up signatures for reviews.
This commit is contained in:
Darkatse 2026-10-05 16:15:34 -04:00
parent 0ebd9a67f1
commit 891e16ceda
2 changed files with 74 additions and 33 deletions

View file

@ -1,66 +1,107 @@
---
name: maintain-conceptual-integrity
description: "在 TauriTavern 的架构规划、实现与审阅中,从共同语义出发整理数据和行为路径,在源头统一零散实现,不以补偿层和过度防御绕开结构,以一致的概念和清晰职责降低长期维护成本。用于用户强调认知一致性、统一架构、拒绝补丁堆积或降低维护者认知负担,评审计划与设计文档,同步上游 SillyTavern,或新增能力与机制的任务。"
description: "在 TauriTavern 的架构规划、实现与审阅中保持认知一致性:同一种事情只走一条路。从共同语义出发追踪数据与行为路径,在源头统一零散实现,做完迁移并删除旧路径,果断取舍,不用补偿层、兜底、包装层、开关和平行实现绕开结构,也不写无用测试。用于规划或设计功能、重构、新增入口、集成、provider 或能力,评审计划、设计文档或 diff,决定增删哪些测试,同步上游 SillyTavern,或用户强调认知一致性、统一架构、拒绝补丁堆积、降低维护者认知负担的任务。不用于单行修复或非编码请求。"
---
# 认知一致性与维护成本
首要目标是长期可维护性:让维护者用少量连贯的概念理解系统,修改一项规则时自然知道应该改哪里,新增功能时能够沿已有结构继续生长。
做法是让同一种事情只有一条路。复杂度用于在源头把路合成一条,不要绕开现有结构做补偿。
做法是**同一种事情只走一条路**。复杂度用于在源头把路合成一条,不用于绕开现有结构做补偿。
结合当前仓库的 `AGENTS.md`、`CONTRIBUTING.md`,以及 `docs/BackendStructure.md`、`docs/FrontendGuide.md`、`docs/FrontendHostContract.md` 等相关文档应用以下判断。
Agent 容易往相反方向走:每一步只优化眼前的 diff,给新调用者加一个分支,为说不清的状态加一层兜底,给不敢碰的代码包一层,为了兼容留下旧路径。单看每一步都说得通,合在一起就成了没人敢改的代码。
## 从整体需求推导结构
## 先看事实
先理解用户希望完成的事情,再沿实际流程追踪数据、状态和行为。找出几个入口实际上共享的需求,以及当前复杂度从哪里产生。源码、实际使用和可复现行为是判断依据。
规划前先读本仓库的规则:`AGENTS.md`、`CONTRIBUTING.md` 的项目哲学与测试准入,以及与任务相关的 `docs/BackendStructure.md`、`docs/FrontendGuide.md`、`docs/FrontendHostContract.md`、`docs/CurrentState/` 和 `docs/API/`。它们记录了本项目的边界、契约和已经做过的取舍;写得具体的地方,以它们为准。
思考方案时,把现有实现(包括相关文档)也作为可以改变的设计选择。若当前问题来自职责分散、状态重复或数据路径别扭,就重新整理这段结构,让问题在共同机制中得到解决。
然后沿实际流程端到端追踪数据、状态和行为,找出几个入口实际共享的需求,以及当前复杂度从哪里产生。源码、实际使用和可复现行为是判断依据。
## 让同一种事情遵循同一套规则
## 契约是硬边界,实现不是
把共同语义放在一处实现,各入口提供自身的数据和上下文。功能模块表达实例含义,共享机制承担共同行为。状态有明确来源,其他部分围绕它工作。
硬边界是确实有人依赖的契约。在 TauriTavern 中主要有两类:
例如,Shell 与文本工具都在操作工作区,文件是否适合自动提交,应由共同的提交规则决定(`docs/Agent/Workspace.md`)。接入新工具时,让它进入已有文件与提交路径,维护者就只需理解一套工作区概念。前端控件同理:功能提供名称、内容和业务状态,浏览器与共同控件负责共同行为(`docs/FrontendAccessibility.md`)。
- **上游兼容契约**(BackendStructure §5):上游前端、扩展、脚本和角色卡能观察到的 URL、响应形状、资源路径、文件布局与 `eventSource` 事件语义。
- **宿主契约**(FrontendHostContract §1):Public Contract 对外承诺;Project Contract 可以演进,但要同步相关模块与文档;Internal 可以自由重构。
入口或写入者之间出现分歧时,修改它们,让它们遵循同一协议;不在下游用观察、同步或补偿去调和分歧。例如 API 修改数值约束后,由它发送与用户操作相同的 `input`,共同实现随之同步数字框,不另挂观察器。
确认具体消费者,把契约入口保留为转入共同机制的薄入口。TauriTavern 新能力通过 `window.__TAURITAVERN__.api.*` 暴露;只有行为确实对齐上游路由时,才进入 `/api/*` 兼容层。
用这种思路检查新增的入口或能力:
契约之外都是实现。现有代码、来自上游的代码以及描述它们的文档,都可以重新设计。上游的不一致写法和旧缺陷不是契约,应在源头改正。把每一行现有代码都当成不可触碰,正是包装层和平行路径的来源。
- 它是上游兼容行为还是 TauriTavern 新能力?前者保持 `/api/*`、资源路径、stream 与事件语义,后者通过 `window.__TAURITAVERN__.api.*` 暴露(BackendStructure §5、§10)。
- 它能否进入已有的共同路径?是否引入了第二个事实来源、第二条链路,或为某个扩展、provider、入口另写分支?按平台适配属于真实差异。
- 发现的问题能否在源头修正,让所有入口一起受益?若每个入口都需要自己的补丁,或者需要在下游补偿,应继续寻找真正共同的职责。
## 在源头收敛
共同机制的边界由语义决定。把含义相同的规则收敛起来,把真实差异清楚表达出来,形成可以持续演进的结构。
- 共同语义放在一处实现。各入口提供自身的数据和上下文,共享机制承担共同行为。例如 Shell 与文本工具都在操作工作区,文件是否自动提交由共同的提交规则决定(`docs/Agent/Workspace.md`);导入导出中,功能只提供文件类型、内容和建议名称,选取与交付由宿主负责(`docs/CurrentState/FileTransfer.md`)。
- 状态只有一个事实来源,其他部分从它派生或经过它。
- 入口或写入者之间出现分歧时,修改它们,让它们遵循同一协议;不在下游用观察、同步或补偿去调和。例如 API 修改数值约束后,由它发送与用户操作相同的 `input`,共同实现随之同步数字框,不另挂观察器。
- Bug 在所有调用者共同经过的地方修,不只修工单点名的那个入口。
- 边界由语义决定。含义相同的规则收敛起来,真实差异清楚表达。平台差异是真实差异,但只放在拥有该事实的宿主模块里,平台判断遵循 FrontendGuide §2.1 与 BackendStructure §6.4。为某个扩展、provider 或入口另写分支,通常不是真实差异。没有共同需求,就不建共同抽象。
- 同一个概念只用一个名字,贯穿代码、参数、错误和文档,并沿用使用者熟悉的约定。
## 用重构换取后续开发的简单
## 果断取舍
当重构能够减少重复链路、隐含知识和反复补偿时,就直接调整相关结构和规划。可以接受一次较大的改动,换取以后每次修改都更直接。评价的是整个系统的理解和修改成本。动手前与维护者对齐会改变行为和责任的决定,对齐后直接重构到位。
对冲是复杂度不经任何人决定就混进来的方式。
先把共同机制做完整,再按功能接入。迁移全部实际调用者,同步删除被替代的实现和旁路,更新原有说明,让新结构成为正常开发路径;只在旧结构外再加一层不算完成。分块实施应当逐步完成同一套架构。
- 推荐一个方案,用一句话说明取舍,不交回一份选项清单。
- 不用开关、选项或配置来回避决定。
- 说不出具体消费者,就不"为了兼容"保留旧路径。
- 不为看不懂的状态加兜底,约束失效时带上下文报错。预期内的恢复路径要语义明确,并让调用者知道。用户可恢复的小问题不阻塞主流程。
- 只就会改变行为、契约或职责归属的决定与维护者对齐;对齐后一次做到位。评审也一样:指出会改变这些的问题,罕见边界不追到底。
兼容的硬边界是已被使用的生态契约:上游前端、扩展、脚本和角色卡实际依赖的入口、DOM 约定与时序。确认具体消费者,把这些入口保留为转入共同机制的薄入口。契约之外都是可以重构的实现(FrontendHostContract §1),来自上游的代码也不例外;上游的不一致写法和旧缺陷不是契约,应在源头改正。
## 把迁移做完
模块通过清楚的接口隐藏内部细节。维护者理解当前功能和它依赖的少量契约,就应足以完成工作;对扩展作者而言,这份契约就是 FrontendHostContract 与 `docs/API/`。好的抽象让调用者少想几件事,也让一次规则变化集中在合适的位置。
留下两套结构并存的重构,让情况更糟。
## 让复杂度与当前问题相称
- 先把共同机制做完整,再按功能接入。
- 迁移全部实际调用者。在同一次改动中删除被替代的代码、分支、旁路,以及它们的测试、fixture 和 fake,并更新描述它们的文档。只在旧结构外再加一层不算完成。
- 必须分块时,每一块都推进同一套架构。
- 当重构能减少重复链路、隐含知识和反复补偿时,可以接受一次较大的改动。评价的是整个系统的理解和修改成本,不是这次 diff 的大小。
- 构建与实验沿用仓库和 CI 已有的入口,不另建副本或平行环境。
优先复用已有机制、标准库和平台能力,选择能够完整解决现实需求的简单方案。KISS 看概念、依赖和隐含知识;60/95 鼓励把精力投入主要使用场景。
## 测试必须证明自己的价值
不为尚未出现的问题预先建机制,也不在各层重复防御;问题真正出现时,在它的源头修正。可恢复的小问题不阻塞主流程。解决真实问题所需的机制,弄清职责后照样保留,例如工作区编辑同时需要 CAS 与锁,二者守住不同的不变式。
Agent 写测试是条件反射:每次改动一个,每层一个,每个新分支一个。其中不少钉住了实现,而钉住实现的测试会把实现变成契约,下一次重构就得先和它较劲。每个测试都是有人要维护的代码。
发现问题或评审指出漏洞时,先看能否通过推广已有规则、删除造成分歧的条件或特判来解决,再考虑新增规则。逐条追加的特例会叠加复杂度;一条推广后的规则常常能同时消解多处问题。
- 默认不写测试。只有以下情况才写:可观察的稳定行为;非平凡的不变式或边界;已经发生并修复的具体缺陷。核心仓储迁移或格式语义变更保留最小可运行测试。"改了代码"、覆盖率和"以防万一"都不是理由。
- 绝不用正则或文本断言源码,不测试字面量、显然的控制流、直接委托、实现细节或已移除的功能。不为没发生过的缺陷提前添加回归测试。
- 一个行为只守一次,放在已经能观察完整流程的最高层。先扩展已有行为测试,不在各层重复同一断言。验证落点见 `docs/Agent/TestingStrategy.md`。
- 删掉一个什么也没守护的测试,是进步,不是覆盖率的损失。
错误在负责的边界清楚表达,失败路径保持直接。性能优先从减少重复计算和数据搬运改善;进一步的复杂度由实际问题支撑。
## 让复杂度与问题相称
取舍时看长期净收益。必要的共同机制值得建设,一次重构也可以比不断追加小修补更经济。原则服务于判断,新的事实出现后,设计可以随之改变。
- 简洁看概念、依赖和隐含知识,不看行数。选择能完整解决现实问题的最简单方案。
- 60/95:用约 60% 的复杂度覆盖约 95% 的现实场景。缺少现实依据的罕见场景,等真正出现时再处理。
- 不为尚未出现的问题预先建机制,也不在各层重复防御;在负责的边界守一次。
- 现实问题需要的机制照样保留。守护不同不变式的两个机制不算重复,例如工作区编辑同时需要 CAS 与锁。
- 发现问题或评审指出漏洞时,先看能否推广已有规则,或删除造成分歧的条件。逐条追加的特判会叠加复杂度;一条推广后的规则常能同时消解多处问题。
## 让代码之外的接口也容易理解
## 堆积的特征
名称、工具参数、返回结果和文档使用一致的概念,并沿用使用者已熟悉的约定。面向用户与 Agent 的语言说明能力、结果和下一步,让内部实现细节留在合适的位置。文字简洁明了、分工明确、中正平和。
实施前用这些特征检查自己的计划。评审时每条发现报告一行:`file:line: <tag> 哪里分裂了。→ 应收敛到哪里。`
测试验证有价值的行为与不变式,随实现收敛重复和失效内容。文档保留总纲、核心契约和重要理由,让读者按需进入细节。代码、测试和文档共同承担维护成本,应当一起整理。
| 标签 | 特征 |
|---|---|
| `split-path` | 同一件事有两条链路,或为每个调用者都需要的东西按调用者写分支。 |
| `second-truth` | 缓存、镜像或标志重复了别处拥有的状态。 |
| `compensation` | 下游用观察器、同步、重试或补丁调和上游的分歧。 |
| `half-move` | 新旧结构同时存活;调用者或文档没有迁移。 |
| `special-case` | 用一次性条件处理本可由一条推广规则消解的问题。 |
| `extra-layer` | 没有共同需求的包装、适配器、接口或工厂,常包在本可直接修改的代码外面。 |
| `defensive-layer` | 在未知状态上猜测结果的兜底、吞掉新平台或新变体的通配分支,或在每一层重复的同一守卫。 |
| `hedge` | 为推迟决定而存在的开关、选项或保留的旧路径。 |
| `test-pile` | 钉住实现、重复别的层已有的断言、守护从未发生的缺陷,或只因改了代码而写的测试。 |
收尾时逐个入口核对它是否已进入共同机制,并问:维护者需要理解的路径是否少了一条?再用下一次开发检验这次设计:维护者是否更容易理解规则、找到修改位置,并沿同一条清楚的路径扩展功能?
最后一行写 `net: -<N> paths`,统计维护者不再需要理解的路径、事实来源和特判数量。没有发现分裂时写 `Coherent. Ship.`
依据:`CONTRIBUTING.md` 的项目哲学,以及上述文档中已经落地的取舍。
## 收尾
逐个核对改动涉及的入口:它是否已进入共同机制?维护者需要理解的路径是否少了一条?再用下一次开发检验这次设计:维护者能否更快找到规则和修改位置,并沿同一条清楚的路径扩展功能?
测试和 `pnpm run check` 通过只是行为核对,不代表设计已经完成。
## 边界
- 不用于错别字、单行修复或没有结构决策的任务。
- 不是重写的许可。在问题的语义范围内收敛;收敛需要越出本次任务时,用一句话提出并询问,既不悄悄扩大改动,也不悄悄跳过。
- 原则服务于判断。新事实推翻旧判断时,修改设计。
依据:`CONTRIBUTING.md` 的项目哲学,以及上述文档中已经落地的取舍。通用英文版见 [Darkatse/conceptual-integrity](https://github.com/Darkatse/conceptual-integrity)。

View file

@ -1,4 +1,4 @@
interface:
display_name: "认知一致性与维护成本"
short_description: "从共同语义出发统一 TauriTavern 的架构,减少零散规则与维护者的认知负担"
default_prompt: "请使用 $maintain-conceptual-integrity,从整体需求出发思考共同机制与数据路径,通过清晰一致的架构降低长期维护成本,并完成本次请求。"
short_description: "同一种事情只走一条路:在源头统一 TauriTavern 的架构,减少补丁堆积、无用测试与维护者的认知负担"
default_prompt: "请使用 $maintain-conceptual-integrity,从整体需求出发思考共同机制与数据路径,在源头收敛,做完迁移并删除旧路径,完成本次请求。"