mcpField
A
accelint-archive-synthesis

accelint-archive-synthesis

github.com/gohypergiant开发2590 次安装2 周前更新
代码仓库

关于 accelint-archive-synthesis

这是一个用于审查 OpenSpec 归档的一致性 skill,可检查历史变更及实时规格索引与文件是否相符。它报告决策漂移、结构耦合和索引差异,后续操作与修改均由人工确认。

主要功能

  1. 01扫描归档决策中的矛盾
  2. 02标记结构耦合的能力
  3. 03核对规格索引行与文件
  4. 04按严重程度生成发现报告
  5. 05针对性修改须经人工确认

适用场景

  1. 01定期审查 OpenSpec 归档
  2. 02查找历史变更间的决策冲突
  3. 03发现过时的能力索引条目
  4. 04检查规格中的潜在过度耦合

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/gohypergiant/agent-skills --skill accelint-archive-synthesis

安装后在 Claude Code 中输入/accelint-archive-synthesis确认已加载。

附带文件CHANGELOG.mdREADME.md

详细介绍

Accelint Archive Synthesis

反向通读整个已归档变更历史,检查它是否仍自洽,核对运行中的索引本身与其声称所汇总的实时文件是否一致,并浮现出那些累积关系表明已超出自身边界的 capability。这就是 Karpathy 的 LLM Wiki 模式中的 "lint" 操作:ingest 已由 accelint-qrspi-archive 承担,query 已由 propose/apply 时的 artifact 加载承担,但没有任何东西会定期重读整个语料库来检查它是否仍然内部一致。这一技术栈中现有的每一项漂移检查,包括 accelint-qrspi-apply 第 5 步自身的 hub-doc 刷新,都是前瞻性的,且范围仅限单个变更自身的提案与设计。本技能是唯一朝相反方向看的技能 —— 而且,由于 accelint-qrspi-archive 为提高自身效率已转向行级索引修补,它也是唯一会重新核对 specs/INDEX.md 与其所汇总的 spec.md 文件的技能。

这种向后看的范围也正是本技能占用面小且刻意为之的原因。它读取两个索引,并且仅对真正的候选对象读取少量 design.md 文件,对于对账检查,则对每个 spec.md 做一次轻量的文件开头读取。它从不直接重写 hub doc,而它所做的每一次写入 —— 在任一索引上 —— 都是单条针对性行修改,且以人类对该具体发现的明确确认为前提,绝不自行发起。由人类始终决定哪些发现会被处理。

本技能做什么

自动化:对每个已归档的 OpenSpec 变更进行周期性、全语料库范围的一致性检查,浮现过往决策之间的矛盾,标记已在结构上过度耦合的 capability,并标记已与其所汇总的 spec.md 文件发生漂移的 specs/INDEX.md 行。 范围:openspec/changes/archive/INDEX.md、openspec/specs/INDEX.md,以及 —— 仅用于对账检查 —— 对每个 spec.md 的 ## Purpose 标题和 related: frontmatter 做一次轻量读取。本技能从不发起变更、从不实施修复,也从不自行编辑 hub doc。 输出:一份与 openspec-verify-change 同语域的 CRITICAL / WARNING / SUGGESTION 报告,此外,仅在人类确认某个具体发现之后,对相关归档行进行 Status 列更新、在 specs/INDEX.md 上进行单行修补或删除,和/或通过共享的 findings: 接口独立调用受影响的 writer 技能 —— 哪些发现类型对应哪些操作,见第 8 步。 不做:自动运行、作为任何其他技能工作流中的阻塞步骤运行、直接重写任何文档、写入 archive/INDEX.md 中 Status 之外的任何列、对 specs/INDEX.md 的写入超出单条已确认行的修补或删除、引入 CRITICAL/WARNING/SUGGESTION 与 current/superseded 之外的任何严重性或状态、或在没有人类确认哪一方成立的情况下凭自身判断对矛盾进行对账。

前提条件

  • 已安装并初始化 OpenSpec CLI,且 accelint-qrspi-archive 已在常规使用中 —— 本技能是该技能生成的索引的消费者,而非其替代品。
  • openspec/changes/archive/INDEX.md 和 openspec/specs/INDEX.md 均存在,且至少包含一行。参见验证任务 B。
  • 需要子 Agent 支持,原因与 accelint-qrspi-archive 的步骤 2 和步骤 5 要求该支持相同:打开候选变更的 design.md,或打开某个能力的 spec.md 以进行核对时,应返回结构化摘要给父级,而非原始文件内容。本技能的步骤 3 和步骤 4 始终将这些有针对性的读取委托给子 Agent。
  • 对 openspec/specs/ 下每个能力目录具有读取权限 —— 普通的文件读取即可,无需通过 shell 调用 OpenSpec CLI,这与 accelint-qrspi-archive 对其自身本地 spec 读取所采用的推理相同。除两个索引文件之外,只有步骤 4 需要此权限。
  • 若要让路由真正落到报告本身之外的任何地方,四个写入技能的 Mode 3 Refresh 路径需要接受一个 findings: 列表(与 accelint-qrspi-apply 步骤 5 使用的同一共享接口)。如果某个目标写入技能尚不支持此接口,本技能仍会生成该 finding —— 只是无法自动将其交接(参见错误处理)。

构建顺序背景

本技能被有意设计为四个部分中最后存在的一个,而其他三个中的每一个都是硬依赖,而非锦上添花:

  1. accelint-qrspi-archive 必须已处于常规使用中。正是它生成本技能读取的两个索引,以及步骤 3、4 和 5 所依赖的 related:/frontmatter 字段 —— 没有它,这里根本不存在任何语料库。
  2. accelint-qrspi-propose 的 Phase 2 扩展(在 propose 时读取 specs/INDEX.md)需要存在,这样 specs/INDEX.md 才真正是工作流中承重的产物,而不仅仅是归档的副产品 —— 否则,即便本技能的结构耦合标记指向了陈旧数据,下游也不会有人注意或在意。
  3. 共享的 findings: 接口 —— 四个写入技能中的 Mode 3 Refresh 扩展,与 accelint-qrspi-apply 步骤 5 相应的提示词变更配对 —— 必须先行落地,本技能才有地方路由已确认的决策漂移或结构耦合 finding。没有它,步骤 8 虽有报告和人工决策,但这两类 finding 无处可去。索引核对 finding(步骤 4)完全不依赖此接口 —— 无论是否确认,它们从不路由到任何地方,因此无论该接口是否存在,该检查的工作方式都相同。

实际后果是:如果这三者中任何一个尚未就位,本技能仍可运行步骤 1 到 7(扫描、检测、报告)并生成有效报告,但步骤 8 会降级为对缺失的那一半接口,仅针对决策漂移和结构耦合 finding,“告诉人工手动该怎么做”。这绝不是直接拒绝运行的理由。

本技能读取的两个索引(归他处所有)

在一般情况下,下面两个索引均不由本技能写入。二者均由 accelint-qrspi-archive 写入和维护;本技能只读取它们,仅有两个狭窄的例外,二者都在步骤 8 下详细说明:对 archive/INDEX.md 的 Status 列更新,以及对 specs/INDEX.md 的单行补丁或删除。

openspec/changes/archive/INDEX.md, one row per archived change:

| Change        | Date       | Decision                                               | Specs touched                      | Status  |
|---------------|------------|---------------------------------------------------------|-------------------------------------|---------|
| add-live-sync | 2026-03-02 | polling with 5s interval, no infra budget this quarter   | sync/protocol, ui/status-indicator  | current |

openspec/specs/INDEX.md, one row per capability, rebuilt on every archive:

| Capability    | Purpose                                                | Related              | Last touched by            |
|---------------|----------------------------------------------------------|------------------------|------------------------------|
| sync/protocol | Defines how client and server exchange live state       | ui/status-indicator   | add-live-sync (2026-03-02)  |

Decision 列是该变更 design.md frontmatter(choice + rationale)的浓缩单行摘要。本技能的步骤 3 首先廉价地基于该摘要工作,仅针对被标记为可能矛盾的特定候选者,才打开完整的 design.md —— 以获取其 alternatives: 字段以及单行摘要压缩掉的任何细微之处。这呼应了 accelint-qrspi-archive 在其自身索引标记某变更相关之前推迟打开该变更文件夹时所用的同一成本控制纪律。

本技能所拥有的日志

上面两个索引都没有记录综合检查点——这是意料之中的,因为它们都完全归 accelint-qrspi-archive 所有,而且都没有理由知道本技能的存在。因此,本技能维护自己的一个小文件 openspec/changes/archive/SYNTHESIS-LOG.md,纯粹是为了回答两个索引都无法回答的问题:“自上次运行以来归档了多少变更”,以及“是否已经有人看过这个特定的决策漂移对,并判定它不是真的”。它就是一个简单的只追加列表,每次完成的运行一行,包含日期以及当时检查到的 archive/INDEX.md 行数,外加一个可选的 dismissed: 子列表,记录该次运行中人类明确驳回的决策漂移对。

这个文件不是任一索引的一列,也永远不会被 accelint-qrspi-archive 触碰——它的存在只是为了让下面的 Step 2 和 Step 1, Task A 可以读取它,并让 Step 3 可以针对其累积的 dismissed: 历史进行过滤。Step 9 是唯一会向其中追加内容的步骤,而且它只会追加——本技能自身永远不会移除某次运行中记录的驳回;如果人类想重新考虑某个被驳回的对,那是对日志文件的手动编辑,在本技能自身的写入路径之外。确切的行的格式,包括 dismissed: 子列表,会在 Step 9 写入它的地方展示。

只有决策漂移的驳回会得到这种处理——结构耦合的驳回不会,这是有意为之。 一个决策漂移对锚定于两个具体的、不可变的已归档变更;人类判定某个特定对不是真正的矛盾,这个判断会永远成立,因为底层的 design.md 文件从不改变。结构耦合发现是 related: 计数的一个实时快照,每次 accelint-qrspi-archive 运行时它都会变动——永久地让“sync/protocol 过度耦合”不再出现,会让本技能对 sync/protocol 的计数进一步攀升视而不见,而这正是这个信号存在的意义所在。因此,结构耦合发现无论之前是否被驳回,每次运行都会重新出现;只有决策漂移的驳回才会被写入日志。

Findings 接口(共享契约,并非新增)

将一个已确认的发现路由到某个写入方技能,使用的正是 accelint-qrspi-apply Step 5 已经在用的同一个 findings: 形状——本技能是该接口的第二个调用者,而不是一个新调用者:

Invoke the accelint-architecture-doc skill.

We found the following during periodic archive synthesis. Treat this as known
context and refresh the affected section(s).

findings:
- [Confirmed finding, rephrased as a plain factual statement, e.g., "add-live-sync
  (2026-03-02) chose polling for sync/protocol citing no infra budget for a
  message broker, but adopt-websocket-gateway (2026-09-14) later adopted a
  message broker for an unrelated capability — worth confirming the original
  budget constraint still holds before sync/protocol's spec is next touched"]

写入方技能会在向人类呈现任何内容之前,将其与自己的代码库扫描合并——与手动运行会走的同一条 Mode 3 Refresh 路径。在这里调用它没有任何针对本技能的特殊处理。这个接口只用于决策漂移和结构耦合发现——索引对账发现(Step 4)从不经过它,因为一个过期的 specs/INDEX.md 行并不是中心文档的内容缺口;关于这些会发生什么,请参见 Step 8。

改写纪律。 findings: 中的每一行都是关于归档所显示内容的朴素事实陈述,绝不是指令,也绝不是写入方技能尚未自行得出的结论。“sync/protocol 所声明的预算约束可能不再成立,因为后来的某个变更采用了消息代理”是正确的措辞;“更新 sync/protocol 的规范以移除预算约束”则不是——第二种措辞抢在了写入方技能自己的 Mode 3 访谈之前,而这正是本技能的 Step 7/8 拆分旨在留给人类、而不是作为既成结论交给下游技能的那个判断。

与 openspec-verify-change 的关系

本技能刻意沿用了 openspec-verify-change 的 CRITICAL/WARNING/SUGGESTION 分级方式,因此无论哪一方生成的报告,读起来都像一份熟悉的产物——但两者检查的内容在根本上并不相同。openspec-verify-change 在每个变更归档之前,针对该变更运行一次:它向前看,范围限定于某一次实现是否与自己的 design.md 和 tasks.md 相符。本技能则定期运行,覆盖整个归档,在变更早已落地之后:它向后看,范围限定于整个归档是否仍然自洽。一个变更可以在归档当天顺利通过 openspec-verify-change,两年后却仍会出现在一条决策漂移的发现中——只要此后有足够多的变更触及了相关能力。两者是互补的,而非重复的,任何一方都不能替代另一方。

工作流概览

┌───────────────────────────────────────────────────────────────────────────────┐
│  Step             Action                                            Output    │
├───────────────────────────────────────────────────────────────────────────────┤
│  1 Preflight      Read SYNTHESIS-LOG.md, verify dependencies        Go / no-go│
│                   exist, sanity-check the two reasoned-default      + notes   │
│                   thresholds (Tasks A, B, C)                                  │
│  2 Scan indexes   Read archive/INDEX.md + specs/INDEX.md, load      In-memory │
│                   prior dismissed: pairs from the log               model     │
│  3 Decision drift Coarse-scan Decision column for same/related-     Candidate │
│                   capability collisions, skipping already-dismissed findings  │
│                   pairs; SUBAGENT opens design.md for the rest                │
│  4 Reconciliation Confirm every spec.md still exists; read Purpose  Candidate │
│                   + related: from each and diff against its         findings  │
│                   specs/INDEX.md row                                          │
│  5 Structural     Median related-count across specs/INDEX.md,       Candidate │
│    coupling       flag outliers ≥5 and ≥2× median                   findings  │
│  6 Compile report Assemble CRITICAL / WARNING / SUGGESTION          Draft     │
│                   findings, openspec-verify-change register         report    │
│  7 Human review   Present report; human confirms, dismisses, or     Confirmed │
│                   defers each finding                               findings  │
│  8 Route          Update Status, or patch/remove a specs/INDEX.md   Docs +    │
│                   row (confirmed findings only) + invoke affected   Status +  │
│                   writer skill(s) via findings:                     specs row │
│  9 Log + report   Append run checkpoint + any new dismissed:        Summary   │
│                   pairs to SYNTHESIS-LOG.md, summarize                        │
└───────────────────────────────────────────────────────────────────────────────┘

Step 3's design.md reads and Step 4's spec.md reads both always delegate to
a subagent, one per candidate, regardless of how many candidates surface. This
keeps raw design.md and spec.md contents out of the parent's context on every
run, the same discipline accelint-qrspi-archive applies to its own Step 2
and Step 5.

实现步骤

按顺序执行以下步骤,除非发生错误,否则不要在步骤之间停顿:

  1. 预检——在阅读任何其他内容之前,先确认本次运行有东西可查,且其两个基于推理的默认阈值看起来仍然合理。

    验证任务 A——触发节奏合理性检查。 阅读 openspec/changes/archive/SYNTHESIS-LOG.md(上文"本技能所拥有的日志"一节中已介绍),找出上一次已完成运行的日期,以及它检查到的归档行数。如果该文件尚不存在,这就是有史以来的第一次运行——完全跳过节奏计算,而不是去除以一段尚不存在的历史,并在报告中注明不存在先前的检查点。否则,取该检查点之后追加的每一行 archive/INDEX.md 中的 Date 列,推导出归档之间的平均间隔时间。"自上次运行以来已归档 15 个变更"这一触发条件是经推理得出的起点,而非实测值;因此,如果实际节奏意味着 15 个变更相当于一年检查两次,或每隔几天检查一次,就把这一点作为信息性说明呈现在最终报告中——绝不要自动调整阈值。是否更改它,是阅读报告的人的决定,而不是本技能的决定。此任务从不阻塞运行:如果有人在距上次运行仅一天后手动调用本技能,且自检查点以来没有任何新行,也照样继续——明确说明这一点("自上次运行以来有 0 个变更,应你要求继续"),因为新鲜度只是信息,而非门槛。

    验证任务 B——依赖检查。 确认 openspec/changes/archive/INDEX.md 和 openspec/specs/INDEX.md 均存在,且各自至少包含一行。如果任一文件缺失或为空,则停止,并报告需要先运行 accelint-qrspi-archive——本技能目前没有任何可读内容,而猜测索引内容比拒绝运行更糟。如果归档总行数少于大约 10 行,只有在该人明确仍想要一次低信号运行时才继续;并在报告中明确注明,如此小的语料库几乎没有什么可供跨归档综合去发现——这与把本技能排在构建顺序最后所依据的推理相同。

    验证任务 C——结构耦合阈值合理性检查。 "至少 5 个且至少为索引中位数的两倍"与任务 A 的触发计数一样,属于基于推理而非实测的默认值。计算 specs/INDEX.md 中每一行 related: 数量的实际中位数,并仅以信息性方式注明:固定下限 5 或 2× 乘数,相对于本项目真实的分布而言,看起来是会标记出过多能力,还是一个都标记不出来。与任务 A 的规则相同:报告观察结果,绝不悄悄更改阈值。

    如果任务 A 和 C 都没有发现异常,就简短说明后继续——这些是合理性检查,而非每次运行都必须有的发现。

  2. 扫描索引——先在内存中构建归档模型,暂不打开任何一个变更文件夹。 完整读取 archive/INDEX.md:每一行的 Change、Date、Decision 摘要、Specs touched 列表以及当前 Status。完整读取 specs/INDEX.md:每一行的 Capability、Purpose、Related 列表以及 Last touched by/日期。无论归档已经增长到多大,这两个文件的读取成本都很低——这正是维护它们的全部意义所在——因此本阶段永远不需要越过它们去查看其他内容。

    还要读取 SYNTHESIS-LOG.md 完整历史中的每一个 dismissed: 子列表(不只是最近一次运行——三次运行前被忽略的一对变更仍然需要保持抑制状态),并构建一个扁平的已忽略变更对身份集合,每个身份的形式为 <change-A slug>|<change-B slug>|<capability>,其中两个 slug 按字母顺序排序,这样同一对变更无论首次比较发生在哪次运行或按何种顺序,都会始终产生相同的身份。如果日志尚不存在,该集合从空开始——与 Task A 的首次运行处理方式相同。

  3. 决策漂移检测——找出彼此不再协调的已归档决策,而无需为此打开语料库中的每一个 design.md。

第 1 步——按共享或相关能力分组。 使用 archive/INDEX.md 中的 Specs touched 和 specs/INDEX.md 中的 related:,将直接触及同一能力的已归档变更聚类,或将彼此的 related: 列表所连接的能力聚类。

第 2 步——粗扫描。 在比较任何内容之前,先丢弃已存在于第 2 步的已忽略变更对集合(在 Scan Indexes 步骤中加载)中的任何变更对——人类已经查看过那一对确切的变更并判定它不是真实问题,而且这一判断不会过期。对于其余所有内容,在每个聚类内,比较 Decision 单行描述以寻找紧张信号。以下是一份值得进行模式匹配的对立选择对初始列表(随着项目自身的词汇揭示出其自身的对立关系,可对此进行扩展——这并非详尽无遗):

  • 轮询 vs. 推送/websocket
  • 同步 vs. 异步
  • 进程内 vs. 外部服务/消息代理
  • 单体 vs. 微服务/拆分
  • 急切 vs. 惰性(加载、求值、初始化)
  • 集中式 vs. 分布式
  • 客户端侧 vs. 服务端侧(验证、渲染、状态)

除了直接的对立对之外,还要标记:此前陈述的理由后来被更近期、触及相关能力的变更中的理由所反驳;以及某个能力在时间上有多项变更聚集在附近,而其自身 spec 的 Last touched by 日期却明显更早。此步骤完全基于已在内存中的索引文本工作——无需文件 I/O。粗扫描命中出错成本很低:它只会消耗第 3 步中的一次子代理调用,而不会在最终报告中产生错误发现,因此此列表有意偏向于过度标记而非标记不足。

第 3 步——定向验证。 对于粗扫描标记出的每个候选项,为每个候选变更对生成一个子代理,打开每个所涉变更的完整 design.md,并使用完整的 choice/rationale/alternatives 字段来确认或排除矛盾,而不仅仅是索引的压缩摘要。例如,给定以下两个 frontmatter 块:

# openspec/changes/archive/2026-03-02-add-live-sync/design.md
---
change: add-live-sync
specs_touched: [sync/protocol, ui/status-indicator]
decisions:
  - id: D1
    choice: polling with 5s interval
    rationale: no infra budget for a message broker this quarter
    alternatives: [websocket push, long polling]
---
# openspec/changes/archive/2026-06-18-adopt-notification-gateway/design.md
---
change: adopt-notification-gateway
specs_touched: [notifications/dispatch]
decisions:
  - id: D1
    choice: message broker (RabbitMQ)
    rationale: notification fan-out needed guaranteed delivery and retry
    alternatives: [polling, webhook callbacks]
---

子代理直接读取这两个 choice/rationale 对,并确认一个真实的矛盾候选项:add-live-sync 陈述的约束(“没有用于消息代理的基础设施预算”)现在与后来一项为不同能力清除了恰好这一障碍的变更存在紧张关系。这是否真的会升级为一项发现,以及处于何种严重程度,由下面的规则决定——而不是仅由本步骤决定。只向父级返回结构化的裁决(已确认/已排除,外加一个不含引用的支持性摘要)——绝不返回原始 design.md 内容。 步骤 4 — 陈旧标记。 另外,对于 specs/INDEX.md 中 Last touched by 日期相对于附近一组近期相关活动(按步骤 1 的分组)而言已显陈旧的任何能力,单独标记出来——这不需要打开任何 design.md,因为这只是纯粹的日期比较,而相关数据在步骤 2 中已从索引里加载好了。

分类规则。 如果受影响能力的 specs/INDEX.md 中 Last touched by 日期落在两个相互矛盾的变更日期中较早的那个之后——意味着某个东西是在一个可能已不再成立的决策之上构建或修改的——那么已确认的矛盾即为 CRITICAL。否则为 WARNING:矛盾是真实存在的,但自那以后没有任何东西主动依赖过已解决的版本。这个比较的两部分都直接来自步骤 2 已构建的索引模型,因此该规则无需新的查找,并且在给定相同数据的情况下重新运行时会产生相同的分类。陈旧标记(步骤 4)始终是 SUGGESTION 级别,因为它们是提示你去查看的信号,而非已确认的矛盾。

  1. 索引核对——检查 specs/INDEX.md 是否仍与其声称汇总的实际 spec.md 文件一致——这是本流水线中其他任何环节都不会验证的一件事。accelint-qrspi-archive 的步骤 6 只修补当前批次变更在 specs_touched 中声明过的能力所对应的行,并且只在引导时(索引尚不存在时)执行一次全语料库范围的扫描。此后每次归档都会让每一行未被触及的行永远保持原样——一个在归档工作流之外被手工编辑的 spec.md,或一个被直接重命名或删除的能力目录,在这个技术栈中的任何地方都没有机制会注意到,除非该特定能力恰好被未来的某个变更触及。accelint-qrspi-archive 自己的 SKILL.md 明确指出了这一空白,并指出本技能是填补它的天然位置,因为定期的、全语料库范围的检查正是本技能的职责所在。

步骤 1 — 存在性检查(每一行,不读取内容)。 对于 specs/INDEX.md 中的每一行,确认 openspec/specs/<capability>/spec.md 仍存在于磁盘上。这是文件存在性检查,而非内容读取,因此即使面对庞大的语料库,其成本也微不足道。文件或目录缺失是立即的 CRITICAL 发现——本工作流中触及该行的其他所有步骤(步骤 3 的聚类、步骤 5 的中位数)都在基于一个不再解析到任何内容的引用来工作。

步骤 2 — 内容检查(每一行文件存在的能力)。 只读取每个 spec.md 的顶部——其 ## Purpose 标题正文和 related: frontmatter 列表,而非完整的 spec 正文——并与该行的 Purpose 和 Related 列进行比较。任何一项不匹配都是 WARNING 发现:"specs/INDEX.md 中 <capability> 的行与其自身的 spec.md 不一致——索引显示 <X>,文件当前显示 <Y>。" 这是一次小规模、有界的读取(frontmatter 加一个标题,与步骤 3 对 design.md 所做的详细验证读取形态相同),而非全语料库内容扫描——它像步骤 5 的中位数计算一样与语料库规模保持相称,只是每行有成本而非零成本。

本步骤不做什么。 它自身从不写入任何内容——步骤 4 仅用于检测。它也从不将已确认的发现路由到写入技能,因为这不是 hub 文档的内容缺口——而是索引本身出错了。在人类确认核对发现之后会发生什么,是步骤 8 的职责,而非本步骤;关于本技能针对此情况对 specs/INDEX.md 所拥有的、以确认为前提的狭窄写入权限,参见步骤 8。

  1. 结构耦合信号——浮现出那些 related: 数量表明其可能已超出自身边界的能力——零额外成本,因为这些数量已因其他原因存在于 specs/INDEX.md 中。 计算 Step 2 中加载的每一行 related: 列表长度的中位数。将任何计数既至少为 5、又至少为该中位数两倍的能力标记为 SUGGESTION 级发现,并以平实事实的方式表述:例如,“sync/protocol relates to 14 other capabilities, more than double the index median of 6。”这是对流水线本就维护的数据的第二次读取,而非新增的记录工作,并且它从不需要打开任何 design.md。

    示例演算:在 22 个能力行中,related 计数 [1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 10, 11, 14, 14] 排序后的中位数为 6(22 个值中的第 11 个和第 12 个,均为 6)。下限为 max(5, 2 × 6) = 12,因此只有两个为 14 的行越过了它——从 11 往下的一切,包括已经为 6 的那两行,都不被标记。这正是 Verification Task C 所检查的那类分布:如果每个项目的中位数都聚集在 1 或 2 附近,那么仅固定下限 5 本身就会标记语料库中的大多数,无论 2× 乘数如何,而这正是 Task C 存在所要揭示的那种不匹配。

  2. Compile Report — 将 Step 3、Step 4 和 Step 5 发现的一切汇总为一份报告,使用 openspec-verify-change 已经在用的同一 CRITICAL / WARNING / SUGGESTION 分级,使其读起来像一份熟悉的产物,而不是要学习的新报告格式。

## Archive Synthesis Report — <date>

Corpus: <N> archived changes, <M> capabilities, checked back to <last synthesis
checkpoint or "project start">.

### CRITICAL
- [Confirmed decision contradiction with a live, actively-touched capability]
- [Index reconciliation: a specs/INDEX.md row's capability directory or
  spec.md no longer exists]

### WARNING
- [Confirmed decision contradiction on a dormant capability]
- [Index reconciliation: a specs/INDEX.md row's Purpose or related:
  disagrees with its own spec.md]

### SUGGESTION
- [Staleness flag]
- [Structural coupling flag]

### Threshold notes (informational only, Tasks A & C)
- [Any cadence or median mismatch worth a human's attention]

绝不要在此将发现呈现为已解决——每个 CRITICAL/WARNING 项都是 Step 7 的候选,而不是结论。

  1. Human Review — 让人类决定每个发现实际会怎样处理——此技能绝不凭自身权威解决矛盾。

按严重程度顺序逐个呈现每个发现。三个选项始终是 Confirm / Dismiss / Defer,但对于决策漂移发现,“Confirm”和“Dismiss”所做的事与它们对结构耦合或索引对账发现所做的事不同,而标签必须说明这一点——在两者之间做选择的人不应必须事先了解此技能的内部机制才能知道自己选的是什么:

Finding 1 [CRITICAL]: add-live-sync's stated budget constraint for
sync/protocol may no longer hold, given adopt-notification-gateway's
later message-broker adoption.
  (a) Confirm — I'll ask which change stands, then update Status and
      notify the relevant doc skill(s)
  (b) Dismiss — Recorded permanently; this exact pair won't be
      flagged again
  (c) Defer  — Left as-is; resurfaces next run

Finding 2 [SUGGESTION]: sync/protocol relates to 14 capabilities,
over double the index median of 6.
  (a) Confirm — Routes to ARCHITECTURE.md's Known Technical Debt review
  (b) Dismiss — Not persisted; will still be re-checked and may
      resurface next run if still elevated
  (c) Defer  — Left as-is; resurfaces next run

Finding 3 [CRITICAL]: specs/INDEX.md row for cache/layer points at
openspec/specs/cache/layer/spec.md, which no longer exists.
  (a) Confirm — I'll remove this row from specs/INDEX.md; if this
      was a rename, the new capability gets its own row automatically
  (b) Dismiss — Not persisted; will still be re-checked and may
      resurface next run if still unresolved
  (c) Defer  — Left as-is; resurfaces next run

只有已确认的发现才会进入 Step 8;对于决策漂移发现,“Confirm”是一个决策的开始,而不是结束——它只告诉此技能该矛盾是真实的;Step 8 仍必须询问矛盾的哪一方成立,然后才会写入任何内容(参见 Step 8 和 Error Handling)。Defer 绝不写入任何内容——被推迟的发现会在下一次运行时完全像之前一样重新出现,因为底层索引数据没有任何变化来阻止 Step 3、Step 4 或 Step 5 重新检测到同一模式。Dismiss 的行为因发现类型而异,这正是其上面的标签在三种类型中并不相同的原因:忽略一个 决策漂移发现会持久化——Step 9 将该特定配对的标识记录到 SYNTHESIS-LOG.md,Step 3 将在未来每次运行时跳过它。忽略一个 结构耦合或索引对账发现不会持久化——两者都会像 defer 一样在下一次运行时重新出现,因为两者都是当前状态的实时快照(一个 related: 计数,或一个 spec.md 是否仍与其索引行匹配),而非固定的历史事实(完整推理见“The Log This Skill Owns”)。

如果人类在列表中途停止审查——结束会话,或继续前进而没有回应每个发现——则将每个未处理的发现默认视为已推迟,绝不视为已确认。Step 9 仍会记录本次运行并报告到目前为止已确认的内容;未触及的任何内容只会在下次重新出现,和显式 defer 一样。

  1. Route Confirmed Findings — 将已确认的发现交接给任何它们实际能改变某些东西的地方,使用共享的 findings: 接口;并且,对于此技能被允许做出的那一小部分写入,执行这些写入。 对于已确认的决策矛盾:确认并不指明矛盾中哪一方成立,因此要先直接询问这一点——绝不能仅凭新旧程度来推断,尽管“较晚的变更”往往是合理的猜测(关于为何此处猜错比本技能中几乎任何其他地方猜错都更糟,参见 Error Handling)。一旦人类指明哪一方成立,就把 archive/INDEX.md 中该行的 Status 列更新为 superseded by <slug> (<date>),其中 <slug> 和 <date> 标识成立的变更。这是本技能对该文件所做的唯一写入,且只会发生在初次确认和这次后续回答都完成之后——绝不自动、绝不臆测、绝不猜测。然后,使用上述 Findings Interface 格式,调用其 hub doc 涵盖受影响能力的 writer 技能。

某个 finding 指向哪个 writer 技能遵循 accelint-qrspi-apply Step 5 已经用于在四个 hub doc 之间做决定的同一目的划分——decision-drift finding 很少恰好只属于其中一个,因此要路由到真正涵盖该矛盾所涉及内容的那个:

  • 关于技术栈、依赖项或编码/架构模式的矛盾 → accelint-onboard-openspec(openspec/config.yaml)。
  • 关于系统结构、组件或数据流的矛盾 → accelint-architecture-doc(ARCHITECTURE.md)。这也始终是结构性耦合 finding 的目标,落在该技能现有的 Known Technical Debt 访谈槽位中。
  • 关于Agent 工作流或行为的矛盾 → accelint-onboard-agents(AGENTS.md)。
  • 关于面向用户的设置或用法的矛盾 → accelint-readme-writer(README.md)。

单个 finding 可以合理地指向多个目标——分别调用每个相关的 writer 技能,并在每次调用时把同一个 finding 改写一次以贴合该 doc 自身的重点,正如 accelint-qrspi-apply Step 5 已经把每个 hub doc 视为独立目标,而不是单次合并更新。每次调用各自独立成功或失败——某个 writer 技能不可用或报错,绝不会阻塞或回滚另一个独立且成功的调用(关于 Status 已经写入之后出现路由失败的具体情况,参见 Error Handling)。

对于已确认的陈旧标记或结构性耦合标记:不适用 Status 更新——这些不是两个特定行之间的矛盾,因此没有任何东西需要标记为被取代。通过相同的 findings: 接口,把该 finding 路由到 accelint-architecture-doc 现有的 Known Technical Debt 访谈槽位。

对于已确认的索引对账 finding——内容不匹配(WARNING):与 decision-drift finding 不同,这不需要用以消歧的问题——按构造而言 spec.md 就是事实来源,因此一旦人类确认该差异真实存在,正确取值就不是一个需要判断的决定。修补 specs/INDEX.md 中的那一行:定位第一个单元格与能力名称完全匹配的行——锚定在前导 | 与下一个 | 之间,使用 accelint-qrspi-archive 自身 Step 6 所用的同样精确匹配,因此 cache/layer 永远不会匹配 cache/layer-v2——并且只用 spec.md 的当前值替换 Purpose 和 related: 单元格。让 last_touched_by 完全保持原样。该字段记录的是哪个已归档变更最后触及此能力,而对账修补并不是已归档变更——覆盖它会把手动编辑修复错误归因于一个从未发生过的变更。按照 accelint-qrspi-archive 自身的格式规则构建替换行:单元格之间单空格分隔、不跨行填充、文件中其他每一行均保持不变。写入后报告前后差异。 对于已确认的索引核对发现 —— 缺失目录或文件(CRITICAL):一旦确认同样明确无歧义 —— 该行指向的内容已不复存在,因此正确的操作就是删除该行,无论该能力是被重命名还是确实已退役。用同样的锚定匹配定位到该行并删除;其他所有行保持不动。如果事实证明这是重命名而非移除,本技能不会尝试猜测新名称或为其插入一行 —— 第 4 步从未核实过该新能力的内容,因此在这里为它写一行,无异于把猜测包装成发现。该新能力会在下次 accelint-qrspi-archive 归档触及它的变更时,以常规方式获得自己的行。

本技能对 specs/INDEX.md 的写入权限恰好就是这两种操作 —— 修补或删除单行 —— 且只有在第 7 步对该具体差异做出明确的人工确认之后才会触发。它复用 accelint-qrspi-archive 自身的行修补机制,而不是另造一套可能随时间与其产生偏差的逻辑;两个技能以相同方式写入同一文件,只是触发时机不同。

对于被驳回的决策漂移发现:不写入 Status,但第 9 步会将该对的标识记录到 SYNTHESIS-LOG.md 的 dismissed: 子列表中,因此第 3 步在之后的每次运行中都会跳过它。这是驳回真正会改变下次行为的唯一情形。

对于被驳回的结构耦合或索引核对发现,或任何被延后的发现:不在任何地方写入。它们都会在下一次综合运行时原样重新出现 —— 被延后的发现是因为底层索引没有任何变化,被驳回的耦合或核对发现则是因为两者都是实时快照,无论此前是否被驳回,都值得每次运行重新检查(参见“本技能拥有的日志”)。

  1. 记录与报告 —— 为下次 Task A 的节奏计算留下检查点,持久化任何新被驳回的决策漂移对,并总结本次运行。

向 openspec/changes/archive/SYNTHESIS-LOG.md(首次运行时新建)追加一行,记录日期以及本次运行检查到的 archive/INDEX.md 行数,如果本次运行驳回了任何决策漂移发现,则其后跟一个缩进的 dismissed: 子列表(如果一条都没有,则完全省略该子列表):

2026-07-06 — checked through row 42 — 2 confirmed, 1 dismissed, 1 deferred
  dismissed: [add-live-sync|adopt-notification-gateway|sync/protocol]

该日志是本技能完全拥有的一个全新的独立文件 —— 它不是任一索引的一列,因此写入它绝不会与 archive/INDEX.md 上的单次写入权限规则冲突。它存在的唯一目的,是让第 1 步的下一次运行无需猜测就能计算“自上次运行以来的变更”,并让第 3 步能跳过人工已排除的对,因为这两个索引本身都不记录这两类信息。每次运行只会追加一行 —— 本技能绝不会编辑或删除已有的 dismissed: 条目;想要重新考虑某个被驳回对的人,只需直接编辑日志文件,而不是通过本技能。

最后以简短总结收尾:每种类型各有多少项发现,有多少项被确认/驳回/延后,以及由此调用了哪个(哪些)写入方技能。

明确不在范围内

  • 在任何情况下都不自动重写文档。 本技能生成一份报告,并在确认后生成一个 findings: 交接——它本身从不直接编辑 hub 文档。
  • 除 Status 外,不写入任何 archive/INDEX.md 列。 其他所有列永久归 accelint-qrspi-archive 所有,包括本技能的 Status 更新所触及的行。
  • 没有第三种严重级别或状态。 Findings 保持为 CRITICAL/WARNING/SUGGESTION;Status 保持为双值字段,current 或 superseded by <slug> (<date>)。
  • 不自动调整阈值。 验证任务 A 和 C 报告不匹配;它们从不自行更改 15 次变更的触发条件或 5 与 2× 中位数的耦合下限。
  • 不主动自行运行。 始终要么是直接调用,要么是来自 accelint-qrspi-archive 的提议建议,且由人工单独接受。
  • 不做跨仓库综合。 本技能仅作用于本地项目的 openspec/changes/archive/ 和 openspec/specs/。OpenSpec 用于跨仓库规范引用的独立存储功能不受此处任何内容影响——将综合扩展到跨仓库是一个不同的、更大的问题,本技能不予尝试。
  • 永远不写入任何 design.md。 步骤 3 打开已归档的 design.md 文件,严格是为了读取 choice/rationale/alternatives 以进行验证——绝不注释、更正或向其追加任何内容。已归档变更对其自身推理的记录保持原样,即使之后的综合运行确认它现已被取代。
  • 除单个已确认行的补丁或移除之外,不写入 specs/INDEX.md。 这与 archive/INDEX.md 规则完全一致:一个狭窄的、以确认为前提的例外,使用 accelint-qrspi-archive 自身的行格式逻辑,而非可能与其产生偏差的单独逻辑。不做批量编辑,不做完整重写,不为本技能从未验证过的重命名能力做推测性插入。
  • 永远不写入任何 spec.md。 步骤 4 读取 ## Purpose 和 related: 以与索引比较——它从不更正、注释或触及它所检查的文件。
  • 在对账期间不全文读取 spec.md。 步骤 4 仅读取 ## Purpose 标题和 related: frontmatter——与步骤 5 自身源数据已假定的相同的有界、文件顶部读取,而非完整规范审查。

错误处理

任一索引缺失或为空(任务 B):在步骤 2 之前停止;告诉用户先运行 accelint-qrspi-archive。

SYNTHESIS-LOG.md 尚不存在:这不是错误,也不等同于上述情况——这是本技能首次运行时的预期状态。任务 A 跳过其节奏计算并继续;步骤 9 会新建该文件。

语料库小于约 10 个已归档变更:不要阻塞,但明确说明此规模的语料库可供跨归档综合发现的内容很少,并在以低信号运行继续之前询问。

被标记的写入方技能未安装,或在其 Mode 3 路径中尚不支持 findings::不要让整个运行失败。仍在报告中生成并呈现该 finding;对于步骤 8 的路由,告诉用户此特定交接需要手动进行,并总结该 finding 的内容,以便他们自行粘贴。

没有可用的 subagent 支持:回退到在父上下文中直接打开被标记的 design.md 候选,用于步骤 3 步骤 3。明确警告用户,本次运行的原始 design.md 内容将因此留在上下文中——这是降级的回退方案,而非默认方式。

索引行引用的 design.md 不再存在(被移动、重命名,或归档文件夹被本技能自身写入之外的操作以其他方式扰动):在步骤 3 的针对性验证中跳过该行,在报告中将其记为不可验证,并且不要将其缺失本身视为一个 finding。 任一索引中的某一行格式有误(Specs touched 或 Related 列表无法解析、缺少 Date,或类似情况):对需要该缺失字段的任一阶段,跳过这一行,在报告中如实注明其无法解析,然后继续处理其余所有行。一行有问题只是给人类看的数据质量提示,而不是放弃整个运行的理由。

SYNTHESIS-LOG.md 中的某条 dismissed: 条目引用了已不再出现在 archive/INDEX.md 中的 slug(该日志被手工编辑过,或归档在本技能的流程之外被改动过):在本次运行的内存已忽略配对集合中删除这一条身份,并在报告中注明一次——如果它的两个 slug 之一已不再对应真实的行,它就无法压制任何东西,而猜测它原本的含义比将其视为惰性条目更糟。

specs/INDEX.md 中少于 2 行:完全跳过 Step 5——中位数需要足够的行才有意义,这与上文中归档大小检查的低语料量推理一致。

Step 3 的 Step 1 聚类产生了不合理的大量候选集(某个能力有非常长的 related: 列表,或语料中有许多变更触及它):不要无条件地为每一对生成一个子代理。优先处理最近归档的配对,先验证这些,并在报告中注明同一聚类中有多少较旧的候选因数量原因本次运行未检查——它们仍是候选,并会像任何其他未确认的发现一样在下次运行中重新出现。这是为控制成本而设的数量上限,不是正确性上的捷径:这里没有任何东西是凭本技能自身的权限被忽略的。

某个已确认发现的写入器技能路由调用失败或超时:这不会撤销已为同一发现做出的 Status 更新——这两次写入是独立的,Status 反映的是人类的确认,而不是交接是否成功。明确告诉用户 Status 更新已落地,但写入器技能交接未成功,并给他们同样的 findings: 格式文本,以便他们手动调用。

人类对 Step 8 的"哪个变更仍然成立"追问回答含糊,或根本没有回答:绝不要仅凭新旧程度推断,即使"较晚的变更"往往是合理的猜测。应再次询问,而不是继续——这里猜错会把一个永久性的、面向人类的断言写入审计追踪文件,而这正是本技能的"每次写入都需许可"规则所要保持的那种深思熟虑的写入。在答案明确之前,保持该发现未解决(等同于 deferred)。

人类为 Status 的 superseded by 值指定了一个实际上未出现在 archive/INDEX.md 中的 slug:停下来并询问正确的 slug,而不是写入一个无法验证的引用——该字段的全部价值就在于它始终能对应到真实的行。

spec.md 存在但没有 ## Purpose 标题(accelint-qrspi-archive 自身的前置条件要求在该能力被修补行之前必须有此标题,但手工编辑仍可能事后将其删除):将其与内容不匹配同等对待——一条 WARNING 发现,注明该标题完全缺失,而不是 CRITICAL,因为目录和文件都仍能对应到真实存在的东西。

语料中的能力数量远超一次运行中合理可做内容检查的范围:优先处理 Last touched by 变更相对归档自身历史最久远的能力——这些是长时间完全未被修补的行,因此未检测到漂移的风险最高。在报告中注明本次运行因数量原因跳过了多少个能力的内容检查;Step 1 中的存在性检查仍会对每一行运行,因为该检查几乎不费成本。 已确认的对账发现在 Step 4 检测与 Step 8 写入之间,其目标行发生了变化(一种罕见的竞态——期间运行了 accelint-qrspi-archive,或在评审会话期间有人手动编辑了该行):在写入前立即重新检查该行。如果它已经与 spec.md 匹配(其他东西已经修复了它),则跳过写入,并将其报告为已解决,而不是已确认并修补。如果它仍然需要同样的修复,则继续。如果 Step 4 所见的内容已不再是实际存在的内容,则绝不要基于它进行写入。

specs/INDEX.md 的补丁或移除写入本身失败:如实报告,就像报告失败的写入技能交接一样——该发现保持未解决(等同于已推迟),并在下一次运行时重新出现,因为实际上什么都没有写入。

绝不要这样做

绝不要在未经明确的人类调用或接受的建议的情况下运行——此技能本身没有自动触发机制;accelint-qrspi-archive 只会建议,它从不强制运行。

绝不要写入任何 archive/INDEX.md 中除 Status 以外的列——其他每个字段都永久属于 accelint-qrspi-archive,在此技能触及的每一行上都是如此。

绝不要为 Status 引入第三种状态——它始终是 current 或 superseded by <slug> (<date>),绝无其他。

绝不要在未获得对该特定矛盾明确的人类确认的情况下更新 Status——在 Step 3 中出现一个候选项,与人类同意它是真实的,并不是一回事。

绝不要直接重写 hub 文档——始终通过 findings: 接口,将已确认的发现路由到相关写入技能自己的 Mode 3 Refresh 路径,就像 accelint-qrspi-apply 的 Step 5 已经做的那样。

绝不要整体打开语料库中的每个 design.md——Step 3 只打开 Step 2 中仅索引的廉价扫描所标记的具体候选项,每个候选项一个子代理。

绝不要悄悄调整 15 次更改的触发器或 5 次且 2× 中位数的耦合下限——Task A 和 Task C 只报告不匹配;更改这两个数字中的任何一个都是人类的决定。

绝不要将缺失或移动的 design.md 本身视为一个发现——它只意味着该行本次运行无法被验证;记录它并继续。

绝不要告诉人类,一个被驳回的结构性耦合发现会被永久抑制——只有决策漂移类的驳回才会持久化到 SYNTHESIS-LOG.md;一个被驳回的耦合发现会在下一次运行时重新出现,完全和一个被推迟的一样,因为其底层计数是一个移动的快照。要如实说明这一点,而不是暗示一个此技能并不提供的保证。

绝不要让此技能本身编辑或移除现有的 dismissed: 条目——Step 9 只会追加。重新考虑一个先前被驳回的配对,是对 SYNTHESIS-LOG.md 的手动编辑,刻意处于此技能自身写入路径之外。

绝不要因为之后的某个路由调用失败而回滚 Status 更新——这两次写入是相互独立的。一个已确认发现的 Status 变更反映的是人类的确认,而不是写入技能交接是否成功;一次失败的交接会被报告并手动交给人类,它绝不会逆转一个已经落地的写入。

绝不要写入 specs/INDEX.md,除了单个已确认行的补丁或移除——与 archive/INDEX.md 上 Status 例外相同的纪律:一次狭窄的、以确认为门控的写入,绝不是批量编辑或整文件重写。

绝不要在修补对账发现时触及 last_touched_by——该字段记录的是哪个已归档更改最后触及了该能力;对账补丁不是一次已归档更改,覆盖它会将一次手动编辑修复错误地归因于一次从未发生的更改。

绝不要猜测一个被重命名能力的新名称,或为它插入一个推测性的行——一个缺失文件的 CRITICAL 发现只会移除过时的行。Step 4 从未验证新能力的内容,因此为它写入一行将是一个伪装成发现的猜测。 在修补或删除 specs/INDEX.md 中的一行时,绝不要重新填充或重新对齐现有行 —— 这与 accelint-qrspi-archive 对其自身行级写入所遵循的规则相同。单元格填充是按行进行的,而不是对齐到表格中最宽的值;为了让列在视觉上对齐而改动每一行的空白,会把一行 diff 重新变成整文件重写。

绝不要告诉人类,被驳回的索引核对发现会被永久抑制 —— 这与结构性耦合遵循的规则相同,原因也相同:比较是针对实时文件状态,而不是固定的历史事实,因此无论此前是否被驳回,每次运行都会重新检查。

绝不要将原本存在的 spec.md 中缺失 ## Purpose 标题视为目录级 CRITICAL —— 该文件和目录都指向真实存在的内容;这是内容级 WARNING,与 Purpose/related: 不匹配属于同一类。

术语

本技能精确使用若干术语,且不会将它们混用 —— 值得一次性确定下来,而不是在每个阶段重复解释:

  • 候选 (Candidate):粗扫描(第 3 步第 2 阶段)、存在性/内容检查(第 4 步)或中位数检查(第 5 步)标记出的可能矛盾、漂移或耦合信号,在任何验证发生之前。尚不是发现。
  • 已确认 (Confirmed):一个候选,已由第 3 步第 3 阶段的定向子代理针对完整的 design.md 内容验证,或一个第 4 步差异,它就是对 spec.md 进行直接比较所显示的结果(无需单独的验证步骤,因为它已经是直接读取),或一个第 5 步结构信号,它就是索引所显示的那样(同样理由)。
  • 发现 (Finding):一个已确认的候选,以平铺直叙的事实措辞,准备好用于第 5 步的报告和第 6 步的人工审查。只有发现会出现在报告中 —— 第 3 步驳回的原始候选永远不会出现。
  • 已确认(人工):与上文验证步骤的“已确认”不同 —— 这是人类在第 6 步做出的决定,即某个给定发现值得采取行动。上下文会消除歧义,指明所指的是哪种含义;在无法消除歧义的地方,本文档会明确写“人工确认”。
  • 已驳回 (Dismissed):人类在第 6 步做出的决定,即某个发现不真实或无需采取行动。对于决策漂移发现会持续生效(该对被记录,且永不再被标记);对于结构性耦合或索引核对发现则不会持续生效(两者无论此前如何,每次运行都会重新检查,因为两者读取的都是当前状态的实时、移动快照,而不是固定的历史事实)。关于它们为何不同,参见第 6 步和“本技能拥有的日志”。
  • 已推迟 (Deferred):人类在第 6 步做出的决定,即某个发现是真实的,但尚未准备好采取行动。对于任何发现类型都永不持续生效 —— 被推迟的发现会在下次运行时与之前一模一样地重新出现。
  • Status = current:accelint-qrspi-archive 为每一行写入的默认状态 —— 不是断言该行肯定正确,只是断言尚无综合运行确认存在影响它的矛盾。
  • Status = superseded by <slug> (<date>):该字段唯一会持有的另一种状态,仅由本技能的第 8 步写入,且仅在人工确认的决策矛盾之后写入。索引核对发现永远不会产生 Status 写入 —— 参见第 8 步。
  • specs/INDEX.md 行修补或删除:本技能的另一项写入权限,仅在第 8 步、且仅在人工确认的索引核对发现之后使用。修补只触及 Purpose 和 related:;删除会删除整行。两者都永远不会触及 last_touched_by,也都不是 Status 式的状态 —— 该行要么存在且为当前,要么已消失。

示例用法

场景:建议运行,一个已确认的矛盾,一个结构标记

[accelint-qrspi-archive, at the end of its own summary output]
ℹ 15 changes have archived since the last synthesis run (2026-01-10).
  Consider running accelint-archive-synthesis.

User: Yes, run archive synthesis.

Skill: Preflight —
✓ Task B: both indexes present, 47 archived changes, 22 capabilities
✓ Task A: actual cadence ~1.1 changes/week; 15-change trigger implies
  checking roughly every 10 weeks — no mismatch worth flagging
✓ Task C: index median related-count is 6; 5-and-2× floor looks reasonable
  against this distribution

Scanning archive/INDEX.md and specs/INDEX.md...

Decision drift —
[spawns subagent: verify sync/protocol candidate]
✓ Confirmed: add-live-sync (2026-03-02) chose polling for sync/protocol,
  citing no infra budget for a message broker. adopt-notification-gateway
  (2026-06-18) later adopted a message broker for an unrelated capability.
  sync/protocol has been touched twice since — CRITICAL.

Index reconciliation —
✓ Existence check: 22/22 capability directories present.
[spawns subagent: content-check cache/layer]
✓ Confirmed: cache/layer's specs/INDEX.md row lists related: [cli-core],
  but cache/layer/spec.md's actual related: frontmatter currently reads
  [cli-core, rule-engine] — added by a hand-edit, no archived change
  touched this capability since — WARNING.

Structural coupling —
✓ sync/protocol relates to 14 other capabilities, more than double the
  index median of 6 — SUGGESTION.

## Archive Synthesis Report — 2026-07-06
Corpus: 47 archived changes, 22 capabilities, checked back to 2026-01-10.

### CRITICAL
Finding 1: add-live-sync's stated budget constraint for sync/protocol may
no longer hold, given adopt-notification-gateway's later message-broker
adoption.
  (a) Confirm — I'll ask which change stands, then update Status and
      notify the relevant doc skill(s)
  (b) Dismiss — Recorded permanently; this exact pair won't be flagged again
  (c) Defer  — Left as-is; resurfaces next run

### WARNING
Finding 2: cache/layer's specs/INDEX.md row disagrees with its own
spec.md — index says related: [cli-core], file currently says
related: [cli-core, rule-engine].
  (a) Confirm — I'll patch this row directly (Purpose + related:
      only, last_touched_by stays as-is)
  (b) Dismiss — Not persisted; will still be re-checked and may
      resurface next run if still unresolved
  (c) Defer  — Left as-is; resurfaces next run

### SUGGESTION
Finding 3: sync/protocol relates to 14 capabilities, over double the
median of 6.
  (a) Confirm — Routes to ARCHITECTURE.md's Known Technical Debt review
  (b) Dismiss — Not persisted; will still be re-checked and may
      resurface next run if still elevated
  (c) Defer  — Left as-is; resurfaces next run

User: Confirm all three findings.

Skill: For Finding 1 — which change should Status reflect as the one
that stands: add-live-sync's original budget constraint, or
adopt-notification-gateway's later message-broker adoption?

User: adopt-notification-gateway — the budget constraint's gone now.

Skill:
✓ archive/INDEX.md: add-live-sync row Status → "superseded by
  adopt-notification-gateway (2026-06-18)"

Invoke the accelint-architecture-doc skill.

We found the following during periodic archive synthesis. Treat this as known
context and refresh the affected section(s).

findings:
- sync/protocol budget constraint may be stale

✓ Finding 2 confirmed.
✓ specs/INDEX.md: cache/layer row patched — related: [cli-core] →
  [cli-core, rule-engine] (Purpose unchanged, last_touched_by left
  exactly as it was — this patch isn't an archived change, so
  attribution doesn't move)
✓ Finding 3 confirmed.

Invoke the accelint-architecture-doc skill.

We found the following during periodic archive synthesis. Treat this as known
context and refresh the affected section(s).

findings:
- sync/protocol structural coupling, routed to Known Technical Debt review

Appending checkpoint to openspec/changes/archive/SYNTHESIS-LOG.md...

✅ Synthesis complete: 3 confirmed, 0 dismissed, 0 deferred.

场景:首次运行,小型语料库,无需报告

User: Run archive synthesis on this repo, I don't think it's ever been done.

Skill: Preflight —
✓ Task B: both indexes present, 6 archived changes, 4 capabilities
ℹ openspec/changes/archive/SYNTHESIS-LOG.md doesn't exist yet — this is the
  first-ever run. Task A's cadence math needs a prior checkpoint, so it's
  skipped this time rather than computed against nothing.
⚠ 6 archived changes is a small corpus — cross-archive synthesis has little
  to work with yet. Continue anyway with a low-signal run?

User: Yes, go ahead.

Skill: Scanning archive/INDEX.md and specs/INDEX.md...

Decision drift — no candidate collisions found across 4 capabilities.
Index reconciliation — 4/4 directories present; all 4 spec.md files match
  their specs/INDEX.md rows.
Structural coupling — only 4 specs/INDEX.md rows; Step 5 needs at least 2
  to compute a median, but a corpus this small has nothing meaningful to
  flag either way.

## Archive Synthesis Report — 2026-07-06
Corpus: 6 archived changes, 4 capabilities, checked back to project start.

No CRITICAL, WARNING, or SUGGESTION findings this run.

Appending checkpoint to openspec/changes/archive/SYNTHESIS-LOG.md
  (file created fresh)...

✅ Synthesis complete: nothing to confirm. Re-run once more changes have
   archived — this corpus is too small yet for the signal to be meaningful.

场景:先前被驳回的一对在下次运行时保持抑制

[Run 1, three months earlier]
Skill: Finding 1 [WARNING]: legacy-cache-warmer (2025-11-02) chose eager
  cache warming for cache/layer, citing predictable traffic patterns.
  adopt-lazy-init (2026-01-14) later chose lazy initialization for an
  unrelated capability.
  (a) Confirm — I'll ask which change stands, then update Status and
      notify the relevant doc skill(s)
  (b) Dismiss — Recorded permanently; this exact pair won't be
      flagged again
  (c) Defer  — Left as-is; resurfaces next run

User: Dismiss — these two were never actually in tension, different
teams, different constraints.

Skill: ✓ Recorded as dismissed.
Appending checkpoint to openspec/changes/archive/SYNTHESIS-LOG.md...
  dismissed: [adopt-lazy-init|legacy-cache-warmer|cache/layer]

[Run 2, today]
Skill: Preflight —
✓ Task A: reading SYNTHESIS-LOG.md — last run 2026-04-02, checked
  through row 31; 1 dismissed pair on record
✓ Task B: both indexes present, 53 archived changes, 24 capabilities

Scanning archive/INDEX.md and specs/INDEX.md...
Loading dismissed-pair history — 1 entry found.

Decision drift —
- legacy-cache-warmer / adopt-lazy-init / cache/layer: matches a
  dismissed pair on record, skipped without re-verification.
- [new candidates, if any, proceed through Steps 2-4 as normal]

## Archive Synthesis Report — 2026-07-06
Corpus: 53 archived changes, 24 capabilities, checked back to 2026-04-02.
(cache/layer's legacy-cache-warmer/adopt-lazy-init pair previously
dismissed — not re-surfaced this run)

No new CRITICAL or WARNING findings.

评论

支持 Markdown