关于 invariants
invariants 是用于在对话中编写架构规则的 Agent 技能,通过确定性操作将规则校验并写入目录。适合需要把规则纳入开发生命周期并由检查门执行的项目作者。
主要功能
- 01访谈作者并整理规则条目
- 02脚手架创建规则目录
- 03校验后新增或修订条目
- 04默认以 dry-run 预览变更
- 05检查并查看生效目录
适用场景
- 01为项目新增架构约束
- 02修正已提交条目的描述或适用路径
- 03将规则纳入规划与评审检查
MCP 相关
技能通过 Exarchos MCP 操作创建、校验、新增和修订目录条目,并查看最终生效的规则目录。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ lvlup-sw/ exarchos --skill invariants安装后在 Claude Code 中输入/invariants确认已加载。
附带文件references/check-mode.mdreferences/worked-example.md
详细介绍
编写不变量技能
概述
此技能将作者脑海中的架构规则转化为已注册且强制执行的目录条目。这是 docs/designs/archive/2026-05-25-invariants-authoring-wizard.md 中描述的入门流程——由 LLM 驱动的编写对话,而不是标准输入问答循环。
职责划分严格且至关重要:
- Agent(你)负责判断 + 自然语言引导。 你采访作者、起草文案、提出 glob 模式,并塑造条目。
- 动词负责验证 + 写入。 每次变更都必须通过确定性且经过架构验证的编排操作——
invariants_scaffold、invariants_add和invariants_amend。你绝不能亲自编写、追加或编辑目录 YAML。 动词负责生成;你负责确认。
这种方式是唯一符合 Agent 优先理念的做法:在架构层面约束输入(INV-5a),变更动词默认采用试运行(INV-5c),编写过程采用事件溯源(INV-1)。
适用场景
- 作者希望在自己的 SDLC 流程中强制执行一条新的架构规则(在构思阶段展示,在规划阶段转化为验收标准,在评审阶段由
check_invariant_conformance门禁进行审计)。 - 作者说“添加一个不变量”“强制执行 X”或“把这个设为规则”。
- 作者希望修正一条已提交的条目——错误的摘要、过时的 glob 模式或薄弱的
audit-prompt。这时应使用invariants_amend,这是变更已发布条目的唯一获准方式(见步骤 7)。
不适用场景
- 作者想要手动编写 YAML——请引导他们使用这些动词;此技能的存在就是为了免去这一步。
- 该规则只是一次性 lint,而非架构不变量 → 应由项目 linter 负责。
- 你正在工作流中编辑状态、执行评审或制定规划——这些属于其他技能。此技能只用于编写目录条目。
动词(你调用的操作——绝不可绕过)
| 操作(MCP) | CLI 门面 | 功能 |
|---|---|---|
invariants_scaffold | exarchos invariants scaffold | 为某个层级创建目录起始文件;以幂等方式在 .exarchos.yml 中注册。绝不覆盖现有文件。 |
invariants_add | exarchos invariants add | 根据 v3 架构验证一条新条目(包括 .strict() 强制执行 DSL——INV-4),然后追加该条目。dryRun 默认为 true:返回生成的条目 + 文件差异,不写入任何内容。仅可追加:若 id 冲突则拒绝。 |
invariants_amend | exarchos invariants amend | 就地修正一条现有条目。id 指定目标(不可修改身份);patch 指定要替换的顶层字段,未包含的字段均原样保留。合并后的条目会经过完整的重新验证。dryRun 默认为 true:返回修正后的条目 + 修改前后的差异,不写入任何内容。 |
doctor | exarchos doctor | 重用现有的 invariants-catalog 检查——即验证器。不新增验证动词。 |
invariants_effective | exarchos view invariants_effective | 门禁将强制执行的合并投影目录。用于写入后的确认。 |
Agent 绝不能凭自身判断宣称条目有效——验证工作由动词负责。invariants_add 返回 INV-5b 载体格式:成功时包含 next_actions(["doctor", "view invariants_effective"]);验证错误会返回源自 Zod 错误的 validTargets / expectedShape / suggestedFix,因此你可以自行修正并重新运行,而不必再次猜测。
访谈(6 个步骤)
按顺序引导作者完成以下步骤。用自然语言引导,绝不要让他们去想 YAML 字段名。
1. 引导——规则 → summary
请作者用一句话说明规则。将其提炼为准确的 summary。询问该规则要防止的失败情况(“违反规则会出什么问题?”)——这有助于让摘要更清晰,并改进后续的强制执行方式。
2. 定位 — dimension、applies-to、affinities
dimension:自由文本分组(例如audit-completeness、error-handling)。applies-to:规则适用的 glob — 请让作者列出路径 (src/handlers/**、**/*.ts)。这些是作者命名的 glob,绝不由 框架推断(INV-6:该表面与工作负载无关)。phase-affinity:规则生效的阶段(ideate | plan | delegate | review | synthesize)。未设置 ⇒ 所有阶段。workflow-affinity:工作流类型(feature | debug | refactor | discovery | oneshot)。未设置 ⇒ 全部。
3. 权重 — severity、integrity-class 和你要撰写到的 tier
severity.default:blocking或advisory。severity.by-workflow(可选):对成本较低的工作流降级 (例如oneshot: advisory)。integrity-class(条目字段;枚举值substrate | sdlc | authoring | user): 条目的覆盖权限,而非其命名空间。对于使用者编写的规则,此值为user。 (substrate/sdlc是 exarchos 自身的类别 — 你不会编写这些类别。)tier(动词参数)决定目录的_命名空间_,选项是 exarchos-substrate 还是项目编写,而非“哪些开发者”。 这一点最容易出错 — 搞错后会悄悄与 exarchos 自身的 ID 冲突:tier: user→U-NID — 项目自身的不变量。所有使用 exarchos 的人 默认都应选择此项。 如果你是在为自己的仓库编写规则,答案始终是此项 (即使你的项目碰巧在内部将规则命名为INV-N— 它们在此处会映射为U-N)。tier: dev→INV-NID — exarchos 自身保留的 substrate 目录。 Exarchos 在工具内部附带自己的INV-1..6,并将它们合并到每个invariants_effective投影中。在使用者的仓库中将规则写入dev会让你的INV-N与 exarchos 自身的 ID 冲突 — 这是一个静默的命名空间冲突,doctor检查无法捕获(它只会在 user 目录中标记INV-*)。仅在 exarchos 仓库内部工作时才使用dev。这些动词会强制执行此限制: 在 exarchos 仓库之外,invariants_scaffold/invariants_add会拒绝tier: dev(启发式判断:package.json名称 ≠@lvlup-sw/exarchos),并返回RESERVED_TIER错误,引导改用user; 真正的 exarchos 分支可通过allowReservedTier: true选择启用。
4. 强制执行 — 默认 mode: audit,mode: check 需选择启用
默认使用 mode: audit。 根据征询得到的规则起草 audit-prompt — 这是一个
由审查子 Agent 针对差异作答的问题。Audit 模式完全依赖判断,且始终可移植:
enforcement:
mode: audit
audit-prompt: >-
Does this diff let a request handler return before emitting an audit event?
Cite the offending file + line.
仅当规则可通过机械方式检查时,才将 mode: check 作为高级可选项提供。如果作者
选择启用,请提出一个由 grep/结构/启发式叶节点组成的声明式组合器树,并在展示前
通过 invariants_add 使用 dryRun: true 进行实时验证。组合器词汇和选择启用流程
请参阅 @references/check-mode.md。强制执行 DSL 采用 .strict(),且仅支持声明式
定义:没有 script / exec / code 逃逸入口(INV-4),因此即使有人要求,你也不能
生成可执行检查。
5. 编号 — 在目标命名空间中自动分配 ID
不要自行选择 ID。invariants_add 会在目标目录的命名空间中自动分配下一个可用
ID(user 使用 U-N,dev 使用 INV-N)。展示试运行结果时,请注明该动词分配的 ID。
6. 提交 — 试运行 → 确认 → 写入 → 验证
此步骤是一道关卡,而非形式流程。 请始终:
- 使用
dryRun: true(默认值)调用invariants_add。此操作会渲染条目和差异,但不会写入任何内容。 - 将渲染后的条目和文件差异原样展示给作者。明确征求确认:询问“提交此条目吗?”——不要在没有明确确认的情况下再次调用。
- 只有在获得明确确认后,才使用
dryRun: false再次调用invariants_add。此操作会追加条目;如果目录尚未注册,则会配置.exarchos.yml,并发出invariant.authored(首次注册时还会发出catalog.registered— INV-1)。 - 运行
doctor(invariants-catalog检查),验证解析后的目录。 - 显示
invariants_effective的变更,让作者确切了解此关卡现在将执行哪些规则。
如果 invariants_add 返回 CATALOG_NOT_FOUND 错误,则目标目录尚不存在——先运行 invariants_scaffold(错误中的 suggestedFix 会指出要调用的工具),然后从第 6 步继续。
7. 修订 — 更正已提交的条目
步骤 1–6 用于编写新条目。更正已有条目需要使用不同的操作,invariants_add 并不适用:它只会追加条目;如果使用已有的 id 再次运行,就会被拒绝(DUPLICATE_INVARIANT_ID),因为提交重复条目会导致加载器拒绝读取该目录。
请使用 invariants_amend。它按 id 定位,并限定字段范围:
id指定要更正的条目。它不可修补——修订后条目的身份保持不变,否则所有指向旧 id 的references:指针和审计记录都会失效。重命名不属于修订。patch仅指定要更改的顶层字段。未在补丁中指定的所有字段都会原样保留——无需重新陈述整个条目,修订也不能悄悄删除references列表,或作者从未提及的 affinity。被指定的字段会被整体替换(修补enforcement会替换整个 enforcement 块)。- 合并后的条目会根据完整的 v3 架构重新验证,因此修订绝不会生成在编写时本应被拒绝的条目——包括
.strict()enforcement DSL(INV-4)。
关卡流程与第 6 步相同:先使用 dryRun: true(默认值)→ 将修改前后的差异原样展示给作者 → 获得明确确认 → 使用 dryRun: false 再次调用,此操作会发出 invariant.amended 并注明更改的字段 → 运行 doctor → 显示 invariants_effective 的变更。
需要注意的两种拒绝情况:
ENTRY_NOT_FOUND— 没有条目包含该 id。错误中的validTargets列出了实际解析出的 id,请从中选择,或改为编写新条目。CATALOG_EMPTY/CATALOG_UNREADABLE— 目录解析后没有任何条目,或根本无法读取其invariants:列表。这两种情况都不会报告为普通的“未找到”:已移动或重命名的目录不能被误认为只是缺少你的条目。请确认指定的目录正确。
工具调用
生成用户目录(幂等;绝不覆盖):
exarchos:exarchos_orchestrate({
action: "invariants_scaffold",
tier: "user",
path: ".exarchos/invariants.md"
})
试运行预览(默认值 — 不写入任何内容):
exarchos:exarchos_orchestrate({
action: "invariants_add",
tier: "user",
catalog: ".exarchos/invariants.md",
entry: { /* the fields from steps 1-4; NO id — auto-assigned */ }
})
获得明确确认后提交:
exarchos:exarchos_orchestrate({
action: "invariants_add",
tier: "user",
catalog: ".exarchos/invariants.md",
entry: { /* same entry */ },
dryRun: false
})
修订已有条目 — 先试运行(注意:只指定更改的字段;其余字段都会保留):
exarchos:exarchos_orchestrate({
action: "invariants_amend",
tier: "user",
catalog: ".exarchos/invariants.md",
id: "U-3",
patch: { summary: "The corrected one-sentence rule." }
})
获得明确确认后提交修订:
exarchos:exarchos_orchestrate({
action: "invariants_amend",
tier: "user",
catalog: ".exarchos/invariants.md",
id: "U-3",
patch: { summary: "The corrected one-sentence rule." },
dryRun: false
})
使用 exarchos:exarchos_orchestrate({ action: "describe" })(或 CLI 的
--help)在运行时查看确切架构 — 标志会根据每个 action 的 Zod 架构自动生成(CLI 由架构驱动;不要假设存在手动添加的标志)。
完整示例
如需查看一个 U-* 条目从头到尾经过全部 6 个步骤编写完成的示例,请参阅
@references/worked-example.md。
反模式
| 不要 | 应改为 |
|---|---|
手动编写或用 Edit 修改目录 YAML | 通过动词路由变更:使用 invariants_add 追加新条目,使用 invariants_amend 修正已有条目 |
使用已有的 id 再次运行 invariants_add 来“更新”条目 | invariants_add 只会追加——发生 id 冲突时会被拒绝。请使用 invariants_amend |
| 为了修改一个字段而重新编写整个条目 | invariants_amend 按字段限定范围:patch 只列出要修改的内容,其余内容都会保留 |
重命名条目的 id | id 是目录的主键,不可修补——所有对旧 id 的引用都会失效 |
| 自行声明条目有效 | 由动词进行验证;你来确认 |
默认使用 mode: check | 默认使用 mode: audit;check 需显式启用(@references/check-mode.md) |
| 跳过试运行 | 先设置 dryRun: true,始终如此,然后再明确确认 |
静默地重新调用并设置 dryRun: false | 明确执行确认步骤 |
| 手动选择 id | 动词会自动分配该命名空间中下一个可用的 id |
在使用方仓库中编写到 dev/INV-N | dev 是 exarchos 保留的基底命名空间——请使用 user/U-N(动词会拒绝使用方的 tier: dev) |
| 根据框架推断 glob | 请作者明确列出 glob(INV-6) |
提交后跳过 doctor + invariants_effective | 验证解析后的目录并展示差异 |