Impeccable Doctor 运维指南:如何检查与修复 DESIGN.md、config.json 等设计制品漂移
Impeccable 是一套让 AI 设计工具链更可靠的设计语言与技能体系,而 doctor(/impeccable doctor)是其中专门负责"维护"而非"设计"的巡检命令:它报告并修复项目里的 Impeccable 制品与该技能安装版本实际读取规则之间产生的漂移。本文以 .trae/skills/impeccable/reference/doctor.md 为骨架,结合仓库中的技能路由与配置文档,完整讲解漂移的类型划分、诊断命令的用法、findings 数据结构、按严重度分级处理的原则、monorepo 场景的专项巡检,以及如何关闭会话启动时的廉价巡检,让读者既能独立跑通一次 doctor 检查,也能理解每一项 finding 背后的设计意图。
doctor 的职责边界:它维护什么,又不做什么
doctor 报告与修复的漂移对象是项目中以下 Impeccable 制品与"当前安装版本实际读取方式"之间的不一致:
PRODUCT.md;DESIGN.md及其.impeccable/design.jsonsidecar 文件;.impeccable/config.json(以及按开发者覆盖的.impeccable/config.local.json);- 持久化的 surface briefs(表层设计简报);
- design hook(设计钩子的安装与配置状态)。
这是一次纯粹的维护动作,不是设计动作:不要重新设计任何东西,不要打开报告点名的文件之外的任何文件,也不要顺带运行其他任何命令。在技能路由层面,skill/SKILL.src.md 中同样明确了一条规则——"永远不要把漂移修复当作设计任务的副作用":CONTEXT_STALE finding 只在用户要求时才被处理,唯一例外是标记为 auto 的 finding,它会在该文件下一次被写入时自动执行。
三种漂移要分清:版本、Schema 与"真相"
文档把口语中统称的"过时"(out of date)拆成三种性质截然不同的漂移,处理方式完全不同:
- 工具版本漂移(Tool version):安装的技能比已发布版本旧。
context.mjs在启动时用UPDATE_AVAILABLE报告这一情况,npx impeccable update可以修复它。这不是 doctor 命令的职责。 - Schema 漂移(Schema drift):某个制品是由旧版 Impeccable 写出的——存在没有读取方字段、现在才被期望的字段、位于废弃位置的旧文件。这类漂移是机械性的,doctor 命令能修复其中大部分。
- 真相漂移(Truth drift):代码演进之后,文档不再能描述现状。没有任何文件比对能判定这一点——
document技能拥有DESIGN.md,init技能拥有PRODUCT.md,doctor 的职责是把一个具体的缺口交给它们,而不是转交一个模糊的怀疑。
这条分类决定了后续所有动作的原则,尤其是"不要过度断言真相漂移"(见后文)。
Step 1:运行一次巡检
诊断入口是 doctor 脚本,命令路径以具体安装布局为准(本技能在 .trae 环境下的标准写法):
node .trae/skills/impeccable/scripts/doctor.mjs --json
指定目标:--target <path>
当用户在 monorepo 中指定了某个 workspace、文件或路由时,加上 --target <path>:
node .trae/skills/impeccable/scripts/doctor.mjs --json --target <path>
不带 --target 时,报告描述的是仓库根目录;而在 monorepo 里,根目录往往不是正确的项目,因此这一步的判断很重要。
理解输出结构
--json 输出携带:
findings:每个 finding 是一个结构化对象{ id, artifact, path, severity, summary, fix },其中id是 finding 标识、artifact指涉的制品、path相关路径、severity严重度(决定"应该发生什么")、summary摘要、fix建议的修复方式;- 在 monorepo 中还会携带
workspaces:每个 app 的 product 与 design 解析结果。
如果输出里出现 ruleRegistryAvailable: false,意味着被忽略的 rule id 无法校验(规则注册表不可用);应当如实告知用户"该忽略列表未能验证",而不要暗示该列表是干净可信的。
好的结果是什么
一个空的 findings 数组就是最好的结果。这时用一行说明"没有发现漂移"即可停止,不要为了找事而扩大动作。值得注意的是:findings 不是错误,doctor 命令不会因为存在 findings 而失败——这正是"严重度只表达应该做什么"的体现。
Step 2:按严重度分级行动
severity 表达的是"接下来应该发生什么",而不是"问题有多糟糕"。三种严重度对应三类不同的处理动作:
auto:无需决策,直接修复
auto 不携带任何决策。运行一次修复命令即可:
node .trae/skills/impeccable/scripts/doctor.mjs --fix
该命令只应用所有 auto finding(且仅限不涉及任何判断的场景),完成后用一行汇报它移动/修改了什么。修复前不需要先征求许可,修复后也不需要再追问这些项——doctor --fix 只动 auto 级且无判断参与的项,这是它在 CLAUDE.md 中被界定为"自动修复在下一次对该文件写入时发生"的实现细节。
mention:只需告知,暂不决策
mention 需要用户知晓,但不需要用户现在做出任何决定。用一句话陈述每一条 mention,并附带它给出的修复建议即可。
route:指向某个具体命令
route 需要一个特定的命令来收口:说出命令名以及它能弥合的缺口。是否执行取决于用户:init 和 document 是对话式的过程,不是可以无人值守替你执行的修复,因此只有当用户在本轮明确要求时才去运行。
三种分组要在一次巡检报告里全部汇报。报告不是错误清单,doctor 命令不会因 findings 的存在而失败。
Step 3:废弃字段具有约束力
当一个 finding 报告了废弃字段(当前例子是 ## Register)时,它不是一条风格建议。从这一刻起,所有决策都应把该字段当作不存在来处理——无论它现在存着什么样的值——并向用户提供删除该小节的建议。
文档给出的理由非常尖锐:保留它"以防万一",正是让一条已被退役的决策轴继续操控当前输出的方式。换言之,schema 漂移的修复不只是"清理旧数据",更是切断旧版本规则对当前行为残留影响的机制性手段。
Step 4:不要对真相漂移过度断言
doctor 刻意把两类 finding 的处理边界写死,防止把"数据信号"误读成"文档有错"。
design-md-drift:提交数不等于矛盾
design-md-drift 统计的是"自 DESIGN.md 上次被编辑以来,视觉源码目录产生的提交次数"。一个提交计数并不是文档与现状矛盾的证据。正确的做法是:
- 报告这个数字;
- 说明它衡量的是什么;
- 如果用户想知道文档是否真的错了,就直接拿当前 tokens 与 components 去通读 DESIGN.md,并基于阅读结果回答;
- 永远不要因为数字大就断言 DESIGN.md 已经过时。
workspace-context-inherited:继承是设计行为
同样的克制适用于 workspace-context-inherited。继承(一个 workspace 沿用根或父级的产品记录)是刻意设计的行为,不是缺陷。某一份 product 记录是否如实地描述多个 app,这是一个该由用户回答的问题,而不是一个需要 doctor 去"修复"的 bug。
Monorepo 专项发现(Monorepo notes)
在 monorepo 布局下,doctor 的输出会多出若干专项 finding,并附 workspaces 表,展示哪些 app 自带上下文、哪些继承上下文、哪些完全没有上下文。在提出任何修改建议之前,先用这张表让用户看清楚现状。
workspace-platform-native-evidence:最重要的 monorepo finding
这是 monorepo 场景里"最重要"的一条:当一个 workspace 携带原生构建文件、却继承了解析结果为 web 的根记录时,它整个生命周期都会收到 web 方向的指导,永远加载不到 ios.md 或 android.md 这两份平台参考。
修复方式是给该 workspace 添加一份子级 PRODUCT.md——因为一份被继承的记录无法同时承载两个平台。这就是"继承"在平台维度上的天然上限。
config-project-roots-match-nothing:projectRoots 全部落空
该 finding 意味着 .impeccable/config.json 中配置的每一个 projectRoots glob 都没有命中任何目录,于是仓库根目录静默地顶替成为了活跃项目。最常见的诱因是 workspace 目录被重命名。处理方式:把匹配模式(patterns)报告给用户,并询问这些模式本应指向哪些目录。
config-invalid-build-path / config-build-path-unset:同一个 buildPath 键的两面
这两条 finding 都围绕 .impeccable/config.json 中的同一个键:buildPath(在 gitignored 的 .impeccable/config.local.json 中也可以设置,且 local 文件对该开发者优先)。它只取 comp 或 code 两个值,决定新 surface 是从生成的 comp 构建(comp-first)还是直接在代码中构建(code-first):
{ "buildPath": "comp" }
config-invalid-build-path:存在一个无法被读取的值(不是comp也不是code)。需要特别指出:一个不可读的值不会回退到另一条路径——所以一个本意是code的项目,可能一直在按 comp-led 的方式构建。报告时要给出该值的确切内容。config-build-path-unset:该 finding 只在"项目做过方向性工作却从未记录偏好"时触发;只有当你的工具面(tool surface)具备图像生成能力时,它给出的"设置该值"的提议才成立。没有图像生成能力就没有可选的余地,也就没有需要说的话。
关于 buildPath 的语义,可在 README.md 中找到更完整的背景:comp-first 组合性更强但耗时更长,code-first 更精简更快;/impeccable init 会在初始化时询问一次并把答案写入 .impeccable/config.json。config.local.json 的覆盖机制专门服务于"你的 harness 没有图像生成能力"的机器场景;在 monorepo 中通常在根提交一份共享值,需要不同行为的 workspace 再各自设置。
关闭启动巡检:让报告只在被要求时出现
context.mjs 会在每次会话开始时报告这些 finding 的廉价子集,并按"每项目每周至多一次"的节奏节流。两条静默途径:
- 配置级:在
.impeccable/config.json中设置"stalenessCheck": false; - 单会话级:设置环境变量
IMPECCABLE_NO_STALENESS_CHECK=1。
注意:关闭启动巡检不会禁用 doctor 命令本身。对"只希望在用户主动询问时才拿到报告"的用户来说,"关闭 boot check + 保留 doctor 命令"正是应当推荐的组合。这一机制与 skill/SKILL.src.md 中的 CONTEXT_STALE 指令对应——Setup 输出中的 CONTEXT_STALE 就是同一份报告的子集,应按照该指令自身的说明就地处理,而不是擅自运行完整的 doctor。
为什么 doctor 独立于设计命令体系
从技能路由结构看,doctor 是有意与设计命令体系隔离的。在 skill/SKILL.src.md 中,doctor 遵循 hooks 与 pin 的"一行路由 + 独立 reference 文档"模式,而不在 IMPECCABLE_SUB_COMMANDS、command-metadata.json、SKILL_CATEGORIES 或命令白名单中,也不计入设计的 23 条命令总数——维护性工具被刻意排除在设计菜单之外。当用户调用 /impeccable doctor,或提出"什么东西过时了 / 需要刷新"之类的问题时,才加载 reference/doctor.md(源码级同文镜像见 doctor.md)。
这一隔离的意义在于:巡检是低频维护,设计是高频创作。让维护工具混入设计命令,会让它在不相干的上下文中被误触发;而让漂移问题以 CONTEXT_STALE 这样的廉价信号出现在会话开头、以 doctor 全量巡检出现在用户明确要求时,才是这套体系管理"制品保鲜度"的完整闭环。
实践速查
- 全量巡检:
node .trae/skills/impeccable/scripts/doctor.mjs --json; - 指定目标(monorepo):追加
--target <path>; - 应用无判断的自动修复:
node .trae/skills/impeccable/scripts/doctor.mjs --fix(只处理auto); - 工具版本过时:走
npx impeccable update,不归 doctor 管; - 真相漂移:不靠脚本判定,把具体缺口交接给
document/init; - 关闭每周启动巡检:
.impeccable/config.json设"stalenessCheck": false或单次会话设IMPECCABLE_NO_STALENESS_CHECK=1。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00