Clarify recorded compatibility decisions and review output

This commit is contained in:
Yixiang Tu authored and GitHub committed 2026-10-08 20:26:57 +08:00
1 parent de4a771c72
commit fad2076073
50 files changed
+176 -167

No files matched your search

@@ -9,8 +9,8 @@
en: c11f54e24be6cc3b
zh: c1c274fbb161a57b
/agent-note-session-log-versioning-one-integer-an-upgrade-chain-and-a-per-event-ignorable-marker/decision:
en: b4b70104be3ff136
zh: 5c12e062343cd40f
en: f2c17cd6b83acdba
zh: 148162c0a8043947
/agent-note-session-log-versioning-one-integer-an-upgrade-chain-and-a-per-event-ignorable-marker/decision/writer-and-publication-authority:
en: 461eaa03c6a4f441
zh: 7e5b131326dc702c
@@ -10,17 +10,17 @@ Session logs must be upgradable after release, and the runtime that ships first
## Decision
The [reader-compatibility review decision](../process/2026-10-08-session-reader-compatibility-review.md) supersedes this note's original structural bump criterion below. The integer, unknown-event marker, direction-aware refusal, and generation-preservation decisions remain active.
The [reader-compatibility review decision](../process/2026-10-08-session-reader-compatibility-review.md) supersedes the structural bump criterion. This note owns the integer, unknown-event marker, direction-aware refusal, and generation-preservation decisions.
**One monotonic integer, no major/minor split.** Whether a version step is auto-upgradable is a property of that step — expressed by whether its upgrader exists — not something a two-level numbering scheme should promise in advance; design time rarely reveals whether the next change will turn out "major".
**Original bump criterion, superseded.** A bump is required exactly when an old runtime could no longer handle a new log with full semantic correctness. "Parses without error" is not the bar: silently skipping content that shapes reconstruction is a wrong read. Only structural changes qualify — header shape, event envelope, core event semantics, the surface mechanism (`SurfaceEventType` set, `SurfaceOp` variants). When unsure, bump: a near-identity upgrader is almost free, a missed bump silently corrupts old readers.
**Bump when existing discriminators cannot prevent unsafe interpretation.** Successful parsing alone does not establish compatibility: silently skipping content required for reconstruction is a wrong read. Same-version changes require safe old-reader handling and preservation of historical meaning by new readers. The linked reader-compatibility decision defines the review obligations.
**Read rules by direction.** Equal version: read normally. Newer than the reader: refuse, name the direction ("written by a newer harness — upgrade"), and point at the raw log artifact so the user can still see the text (`SessionFormatUnsupportedError`, distinct from `SessionPersistenceCorruptionError` because nothing is damaged). Older than the reader: every event-body operation first runs the complete adjacent chain in memory and leaves the source path, bytes, and inode unchanged. Read handles may consume that current logical result directly; a write open exclusively publishes the final current generation under its canonical versioned filename before append. Header-only listing remains non-mutating and reports the numerically highest canonical generation. Catalog generation and module initialization reject a missing adjacent step, so a published first-party build never exposes a partial historical chain. Retained lower generations are not automatic fallback or a downgrade compatibility promise.
**A per-event `ignorable` marker covers vocabulary growth, so ordinary event additions never bump the version.** The event vocabulary is decided by which plugins are mounted, which a single version integer cannot describe. A reader meeting an unrecognized event type refuses to interpret the log unless the event carries `ignorable: true` in its envelope. The default is *required*: forgetting the marker over-refuses a resumable session (an inconvenience), while a default of ignorable would make the same mistake silently resume a gutted one (a safety failure). The architecture makes this sound: model-visible content flows only through the four `surfaceOp`-marked surface event types plus the `request/header`/`request/context` folds, so the dangerous unknowns are exactly the non-surface events that change how the rest of the log is read (`session/end-seed` is the existing example).
**Original checkpoint criterion, superseded as to bump requirements.** The [accepted compatibility checkpoint](../../../../docs/session-format-status.md#finalization-record) prevents an accepted transition from reusing its header increase for later breaking changes. Backward-compatible evolution uses new acknowledgement records at the same Session version; breaking changes require a higher writer. The checkpoint does not change the unknown-event protocol.
**Accepted machine records remain immutable.** The [accepted compatibility checkpoint](../../../../docs/session-format-status.md#finalization-record) preserves accepted declarations and schemas. Later changes receive new acknowledgements, and a version-bump decision needs its own increasing header transition. The checkpoint does not change the unknown-event protocol.
### Writer and publication authority
@@ -10,17 +10,17 @@ Session log 在发布后必须能升级格式,而最先发布的运行时决
## 决定
[读取器兼容性评审决策](../process/2026-10-08-session-reader-compatibility-review.zh.md)取代下文原有的结构性升版本标准。单调整数、未知事件标记、分方向拒绝与代际保留决策仍然有效。
[读取器兼容性评审决策](../process/2026-10-08-session-reader-compatibility-review.zh.md)取代结构性升版本标准。本说明负责整数版本、未知事件标记、区分方向的拒绝与代际保留决策。
**一个单调递增的整数,不分大小版本。**某一步能不能自动升级是那一步自己的属性,由它的升级器存在与否表达,不该由两级编号方案提前承诺;设计时很少能预知下一个变更算不算"大"。
**原有升版本标准,已被取代。**当且仅当老运行时无法在语义上完全正确地处理新日志时才必须升版本。"解析不报错"不是标准:静默跳过影响重建的内容就是读错。只有结构性变更够得上这条线:header 形状、事件信封、核心事件语义、surface 机制(`SurfaceEventType` 集合、`SurfaceOp` 变体)。拿不准就升:近似恒等的升级器几乎没有成本,漏升一次会让老读取器静默读坏。
**既有判别信息无法阻止不安全解释时升版本。** 仅解析成功不能证明兼容:静默跳过重建所需内容属于错误读取。同版本变更要求旧读取器安全处理,并由新读取器保留历史含义。所链接的读取器兼容性决策定义评审义务。
**读取规则按方向区分。**版本相等:正常读。比读取器新:拒绝,说明方向("由更新的 harness 写入,请升级"),并给出原始日志文件的路径,用户仍能看到文本(`SessionFormatUnsupportedError`,与 `SessionPersistenceCorruptionError` 区分,因为数据没有损坏)。比读取器旧:每个事件正文操作先在内存中运行完整相邻链,并保持源路径、字节与 inode 不变。读句柄可以直接使用该 current 逻辑结果;写 open 则在 append 前把最终 current generation 排他发布到其规范版本文件名。仅 header 的列表保持不变更,并报告数值最高的规范 generation。catalog 生成与模块初始化会拒绝缺失的相邻步骤,因此已发布第一方 build 绝不会暴露不完整历史链。保留的低 generation 不是自动 fallback,也不构成 downgrade compatibility 承诺。
**逐事件的 `ignorable` 标记吸收词汇表增长,普通的新增事件永远不用升版本。**事件词汇表由挂载了哪些插件决定,单个版本整数描述不了它。读取器遇到不认识的事件类型时拒绝解读日志,除非该事件的信封带 `ignorable: true`。默认为必需:忘写标记的后果是把一个本可恢复的会话拒绝过头(体验问题),而默认可忽略会让同样的疏忽静默恢复出残缺会话(安全事故)。架构保证了这条规则成立:模型可见内容只经四种带 `surfaceOp` 标记的 surface 事件加 `request/header`、`request/context` 折叠进入重建,危险的未知事件恰好是那些不进 surface 但改变日志其余部分解读方式的事件(`session/end-seed` 是现存例子)。
**原有检查点标准,其升版本要求已被取代。**[已接受兼容性检查点](../../../../docs/session-format-status.zh.md#finalization-record)阻止已接受转换复用原来的头版本递增来授权后续破坏性变更。向后兼容的演进在相同 Session 版本上使用新的确认记录;破坏性变更要求更高的写入器版本。检查点不改变未知事件协议。
**已接受的机器记录保持不可变。** [已接受兼容性检查点](../../../../docs/session-format-status.zh.md#finalization-record)保留已接受的声明与 schema。后续变更获得新确认,升版本决策需要自身的递增头版本转换。检查点不改变未知事件协议。
### 写入器与发布真源
@@ -9,14 +9,14 @@
en: c8e926bfc65d7195
zh: e0e007960b68fe80
/agent-note-in-tree-persistence-type-history/decision:
en: a2a78ce5c8ae8eea
zh: ec454d682b11bb24
en: 94be3d6c7df3063b
zh: 7e8fb08d7fd95f85
/agent-note-in-tree-persistence-type-history/decision/finalized-checkpoints:
en: 83f60900b90f8a3b
zh: a00d98fa224a6764
en: b508035a163340a3
zh: ba5b2b7e8cef4b2f
/agent-note-in-tree-persistence-type-history/alternatives-considered:
en: 3a7eb7c2fb98936b
zh: 99c865ac63433424
en: 1cf6d0a5555ae50a
zh: 70ea1ba535e09442
/agent-note-in-tree-persistence-type-history/consequences:
en: 672c8cb59d291dc2
zh: cbec90fbca92320a
@@ -10,15 +10,15 @@ A persisted event can retain the same payload type expression while a referenced
## Decision
The [reader-compatibility review decision](2026-10-08-session-reader-compatibility-review.md) supersedes the automatic version floor described below. The normalized type history, per-root acknowledgements, and accepted checkpoint preservation remain active.
The [reader-compatibility review decision](2026-10-08-session-reader-compatibility-review.md) supersedes the automatic version floor. This note owns normalized type history, per-root acknowledgements, and accepted checkpoint preservation.
One normalized type model supplies the readable persistence catalog, the complete schema inventory, and transitive per-root digests. Roots identify the logical Session header, the physical JSONL header line, the event envelope, and every repository-declared event. Source locations, alias names, ordinary comments, and property order are presentation details outside the digest. Explicit compatibility annotations carry fingerprinted policy data under the [source-attribution policy](2026-09-17-persistence-schema-review.md). Historical records retain source file paths without line numbers because their selected source trees differ from the current checkout. Referenced and recursive types participate in structural comparison; opaque values retain explicit coverage limits.
The dedicated [persistence-change records](../../../../docs/persistence-changes/README.md) bind acknowledgement to the after digest of each affected root. A generated companion stores complete after schemas. The initial record covers all roots; later records name each root's predecessor. A predecessor's after schema supplies the next before schema. Verification rejects ambiguous history and requires current source to match the terminal recorded state without consulting Git history or remote services.
The original automatic classification permitted optional body additions, required-to-optional body changes, and ordinary event additions within one version. The scoped [source-attribution policy](2026-09-17-persistence-schema-review.md) also permits qualified new producer kinds when both saved schemas opt in. The [event-payload version rule](../../../../docs/persistence-changes/README.md#compatibility-rules) admits higher numeric payload versions when every old alternative remains unchanged and records the older-reader limitation. Other structural changes required a version-bump decision that included an increasing header version in that record. The [format-version procedure](../../../../docs/cookbook/adding-a-session-format-version.md) continues to own adjacent migration work. Every structural difference requires an explicit record, including additions allowed within the same version.
Automatic classification permits optional body additions, required-to-optional body changes, and ordinary event additions within one version. The scoped [source-attribution policy](2026-09-17-persistence-schema-review.md) also permits qualified new producer kinds when both saved schemas opt in. The [event-payload version rule](../../../../docs/persistence-changes/README.md#compatibility-rules) admits higher numeric payload versions when every old alternative remains readable and records the older-reader limitation. Other structural changes require an explicit same-version choice in the recording CLI or an increasing header version. Every structural difference needs an acknowledgement; its Compatibility and Verification sections explain both reader directions and executed checks. CI validates saved decisions without inferring how they were authored. The [format-version procedure](../../../../docs/cookbook/adding-a-session-format-version.md) owns adjacent migration work when a bump is required.
The new document kind preserves the compatibility reasoning and evidence for a historical type transition. Agent Notes retain mechanism-level decisions; they do not become a growing inventory of individual acknowledgements. Machine declarations remain identical across the bilingual pair and are parsed once.
The persistence-change document kind preserves compatibility reasoning and evidence for a historical type transition. Agent Notes retain mechanism-level decisions; they do not become a growing inventory of individual acknowledgements. Machine declarations remain identical across the bilingual pair and are parsed once.
Retrospective [release comparisons](../../../../docs/persistence-changes/releases/README.md) use a separate `persistence-release` kind and pinned tag manifest. They retain changed after schemas and reconstruct adjacent releases, including unchanged tags. Earlier releases predate these acknowledgement rules, so their classifications are informational and their observed versions are not rewritten to satisfy a modern version floor. Historical parsing preserves optional surface operations; the current parser and acknowledgement chain remain strict. This separation permits approximate backfills without turning them into authorization for current changes.
@@ -30,7 +30,7 @@ Explicit update refreshes an unaccepted terminal record without deleting its aut
### Finalized checkpoints
The original checkpoint policy below retains its history-preservation requirements; the successor decision owns the version criterion. Finalization records acceptance independently of publication. A terminal record must not reuse its original header increase to authorize another breaking change to already-written data. The [status record](../../../../docs/session-format-status.md#finalization-record) therefore requires a complete compatibility checkpoint: accepted record semantics remain locked, while compatible current-source changes proceed through new records and breaking changes require a higher writer. The existing classifier and unknown-event protocol are unchanged. This adds no runtime field and cannot detect behavior changes hidden behind unchanged declarations. Coordinated edits to the in-tree authority and checkpoint still require review.
Finalization records acceptance independently of publication. The [status record](../../../../docs/session-format-status.md#finalization-record) requires a complete compatibility checkpoint that locks accepted machine declarations and after schemas. Further schema changes need new acknowledgements; an explicit version-bump decision must contain its own header increase and cannot reuse an accepted transition. The checkpoint adds no runtime field, does not change unknown-event handling, and cannot detect behavior changes hidden behind unchanged declarations. Coordinated edits to the in-tree authority and checkpoint still require review.
## Alternatives considered
@@ -42,7 +42,7 @@ The original checkpoint policy below retains its history-preservation requiremen
**Treat every changed digest as a version bump.** Optional body additions, required-to-optional changes, and ordinary event additions do not always require a new persistence version. Conservative classification distinguishes these cases and leaves the compatibility explanation to review.
**Infer behavior from types or permit arbitrary compatibility overrides.** A type graph cannot prove replay semantics. The original checker confined itself to detectable structure and rejected decisions below the mechanical classification; it did not claim to detect behavior-only changes. The successor decision replaces that automatic floor with explicit reader evidence.
**Infer behavior from types or require proof of human review.** A type graph cannot establish replay semantics, and a recorded choice cannot establish how it was authored. The checker validates declared transitions and header-version constraints. Reviewers inspect actual reader behavior and the acknowledgement’s explanation independently.
## Consequences
@@ -10,15 +10,15 @@ Status: implemented
## 决策
[读取器兼容性评审决策](2026-10-08-session-reader-compatibility-review.zh.md)取代下文的自动最低版本要求。规范化类型历史、逐根确认与已接受检查点保留规则仍然有效。
[读取器兼容性评审决策](2026-10-08-session-reader-compatibility-review.zh.md)取代自动最低版本要求。本说明负责规范化类型历史、逐根确认与已接受检查点保留。
一个规范化类型模型提供可读持久化目录、完整 schema 清单和包含传递引用的逐根摘要。根标识逻辑会话头、物理 JSONL 头行、事件封装以及每个仓库内声明的事件。源码位置、别名名称、普通注释和属性顺序属于摘要之外的展示细节。历史记录保留源码文件路径而不包含行号,因为其选定的源码树与当前工作树不同。被引用类型和递归类型参与结构比较;不透明值保留明确的覆盖限制。显式兼容性标记依照[消息源归属策略](2026-09-17-persistence-schema-review.zh.md)携带纳入指纹的策略数据。
专用的[持久化变更记录](../../../../docs/persistence-changes/README.zh.md)将确认绑定到每个受影响根的变更后摘要。生成的伴随文件保存完整的变更后 schema。初始记录覆盖所有根;后续记录为每个根指定前驱。前驱的变更后 schema 提供下一次的变更前 schema。验证拒绝有歧义的历史,并要求当前源码匹配最终记录状态,无需查询 Git 历史或远端服务。
原有自动分类允许可选事件体新增、事件体属性从必选改为可选,以及普通事件新增保持同一版本。当双方保存的 schema 均声明支持时,受限的[消息源归属策略](2026-09-17-persistence-schema-review.zh.md)也允许添加符合条件的生产者 kind。[事件载荷版本规则](../../../../docs/persistence-changes/README.zh.md#compatibility-rules) 允许在原样保留所有旧分支时增加更高的数字载荷版本,并记录旧读取器限制。其他结构变更需要升版本决策,并在该记录中包含递增的头部版本。[格式版本流程](../../../../docs/cookbook/adding-a-session-format-version.zh.md)继续负责相邻迁移工作。每个结构差异都需要显式记录,包括允许保持同一版本的新增。
自动分类允许可选事件体新增、事件体属性从必选改为可选,以及普通事件新增保持同一版本。当双方保存的 schema 均声明支持时,受限的[消息源归属策略](2026-09-17-persistence-schema-review.zh.md)也允许添加符合条件的生产者 kind。[事件载荷版本规则](../../../../docs/persistence-changes/README.zh.md#compatibility-rules)允许在每个旧分支仍可读取时增加更高的数字载荷版本,并记录旧读取器限制。其他结构变更要求在记录 CLI 中显式选择同版本,或递增头版本。每个结构差异都需要确认;其兼容性与验证部分说明两个方向的读取器行为及已执行检查。CI 验证保存的决策,不推断其编写方式。需要升版本时,[格式版本流程](../../../../docs/cookbook/adding-a-session-format-version.zh.md)负责相邻迁移工作。
新文档类型保留历史类型转换的兼容性说明和证据。Agent Note 保留机制层面的决策,不积累单次确认清单。双语对中的机器声明保持相同,且只解析一次。
持久化变更文档类型保留历史类型转换的兼容性说明和证据。Agent Note 保留机制层面的决策,不积累单次确认清单。双语对中的机器声明保持相同,且只解析一次。
回溯性的[发行版本比较](../../../../docs/persistence-changes/releases/README.zh.md)使用独立的 `persistence-release` 类型和固定 tag 清单。它们保留变化后的 schema,并重建相邻版本,包括未变的 tag。早期版本先于这些确认规则,因此其分类只提供信息,观察到的版本号不会为满足当前最低版本要求而被改写。历史解析保留可选的 surface 操作;当前解析器和确认链仍保持严格。这一区分允许近似回填,同时不会将其变成当前变更的授权。
@@ -30,7 +30,7 @@ Status: implemented
### 定稿检查点
下文原有检查点政策保留其历史保存要求;后继决策负责版本标准。定稿独立于发布事实记录接受状态。末端记录不能复用原有头版本递增,继续授权对已写入数据进行破坏性变更。因此,[状态记录](../../../../docs/session-format-status.zh.md#finalization-record)要求完整兼容性检查点:已接受记录的语义保持锁定,当前源码的兼容变更通过新记录继续,破坏性变更要求更高的写入器版本。现有分类器与未知事件协议保持不变。这不会添加运行时字段,也不能检测未变声明后隐藏的行为变化。对目录内真源与检查点的协同修改仍须审阅。
定稿独立于发布事实记录接受状态。[状态记录](../../../../docs/session-format-status.zh.md#finalization-record)要求完整兼容性检查点,锁定已接受的机器声明与变更后 schema。后续 schema 变化需要新的确认;显式升版本决策必须包含自身的头版本递增,不能复用已接受转换。检查点不添加运行时字段,不改变未知事件处理,也不能检测未变声明后隐藏的行为变化。对目录内真源与检查点的协同修改仍须审阅。
## 考虑过的替代方案
@@ -42,7 +42,7 @@ Status: implemented
**把每次摘要变化都视为升版本。** 可选事件体新增、必选改可选,以及普通事件新增不一定需要新的持久化版本。保守分类区分这些情况,并将兼容性说明交给审阅。
**从类型推断行为,或允许任意兼容性豁免。** 类型图无法证明回放语义。原有检查器仅覆盖可检测结构,并拒绝低于机械分类要求的决策;它不声称能够检测纯行为变更。后继决策以明确的读取器证据取代该自动最低要求。
**从类型推断行为,或要求人类评审证明。** 类型图无法证明回放语义,所记录的选择也无法证明其编写方式。检查器验证声明的转换与头版本约束。评审者独立检查实际读取器行为与确认说明。
## 影响
@@ -9,8 +9,8 @@
en: fa4f3e56f3b22e07
zh: a8010ab822474c2c
/agent-note-session-versions-follow-reader-compatibility/decision:
en: 1cd89bd555f3cdcd
zh: e6b3e0df7511dc6b
en: ab45f42c587793e8
zh: b1c2eab9e8642824
/agent-note-session-versions-follow-reader-compatibility/migration-obligations:
en: b218b28f19c41f33
zh: 7e99314983707984
@@ -16,6 +16,8 @@ New readers preserve the meaning of supported historical records and accept vali
The schema classifier identifies structural changes requiring compatibility review instead of declaring them inherently version-breaking. Every schema difference still needs an acknowledgement. Established safe cases infer same-version; other same-version changes require an explicit decision when recording or updating. The existing Compatibility and Verification sections record reader behavior and executed checks. The checker validates the decision and recorded schemas; it cannot prove that the explanation matches runtime behavior. An explicit version-bump decision still requires its own increasing `SessionHeader.version`. Accepted machine records and checkpoints remain immutable; prose remains outside checkpoint hashes.
The user treats a recorded `same-version` decision as explicit regardless of whether the CLI or an editor produced it. The CLI requires `--decision same-version` for flagged record and update operations; CI validates the saved decision against history, schemas, and header-version constraints. Neither mechanism attests that a human reviewed the transition. Reviewers use base/head inventory comparison rather than current-tree consistency checks to inspect already acknowledged changes.
This decision partially supersedes the structural bump criterion in the [version-mechanism note](../architecture/2026-08-10-session-log-version-mechanism.md) and the automatic version floor in the [persistence-type-history note](2026-09-11-persistence-type-history.md). Their monotonic integer, required unknown-event default, type history, and immutable generation decisions remain active. The [review procedure](../../../../docs/cookbook/reviewing-persistence-type-changes.md) owns authoring and validation details.
## Migration obligations
@@ -16,6 +16,8 @@ schema 的结构差异不能证明 Session 需要新的整数版本。可选的
schema 分类器标识需要兼容性评审的结构变更,而不将其直接判定为版本破坏。每项 schema 差异仍须确认。已明确安全的情形推断为同版本;其他同版本变更在记录或更新时要求显式决策。已有的兼容性与验证部分记录读取器行为和已执行检查。检查器验证决策与所记录的 schema,但无法证明说明与运行时行为一致。显式升版本决策仍须包含其自身递增的 `SessionHeader.version`。已接受的机器记录与检查点保持不可变;说明文字不参与检查点哈希。
用户将记录中的 `same-version` 决策视为显式选择,无论它由 CLI 还是编辑器产生。CLI 对被标记的记录与更新操作要求 `--decision same-version`;CI 按历史、schema 和头版本约束验证保存的决策。两种机制都不证明人类已评审转换。评审者使用 base/head 清单比较,而非当前目录一致性检查,来检查已确认的变更。
本决策部分取代[版本机制说明](../architecture/2026-08-10-session-log-version-mechanism.zh.md)中的结构性升版本标准,以及[持久化类型历史说明](2026-09-11-persistence-type-history.zh.md)中的自动最低版本要求。它们的单调整数、未知事件默认必需、类型历史与不可变代际决策仍然有效。[评审流程](../../../../docs/cookbook/reviewing-persistence-type-changes.zh.md)负责记录编写与验证细节。
## 迁移义务
@@ -15,8 +15,8 @@
en: 5fca19ac2bb1ddac
zh: 00d78fe7e80ba4f7
/cookbook-reviewing-persistence-type-changes/optional-inspect-the-change:
en: 2b173ebeb41f37d3
zh: 6b9543d6207dc98e
en: 14049617e3de750d
zh: 200456cf72bef77b
/cookbook-reviewing-persistence-type-changes/1-record-the-change:
en: de16b6e1ac883317
zh: 21d367bb78e799d1
@@ -24,8 +24,8 @@
en: 91d39719ec40b0f7
zh: 405116ae4c91b100
/cookbook-reviewing-persistence-type-changes/update-an-unaccepted-record:
en: a95c531052d77061
zh: 9ab5f9e4b6ebe436
en: e3872db4ec9aad7d
zh: 18de4f6ebcb4b31c
/cookbook-reviewing-persistence-type-changes/dev-note:
en: 5de1d6304e00c58f
zh: 8d8225361cfa29e5
@@ -39,6 +39,8 @@ To review a PR independently of its acknowledgement history, save the base and h
pnpm --silent run persistence-review --before .artifacts/base.schema.json --after docs/persistence-schema.json
```
A recorded decision does not hide the transition from this comparison. `--check` only compares current source with acknowledged history; after recording, it cannot replace a base/head review or establish that a human reviewed the change.
Record the commits supplying those files with the report. Add `--json` for structured output. This read-only comparison groups shared changes with their affected roots and uses actual literal `kind`/`form` values instead of union positions. Ambiguous alternatives remain separate additions and removals. Its compatibility section copies every root's authoritative classifier result; the structural explanation does not replace acknowledgement checks. Current catalog labels and declaration names are descriptive metadata; structural anchors and fingerprints identify types.
The current machine inventory stores complete graphs in `roots`. A `types` entry contains `digest`, `names`, and `sources`, plus an explicit `schema` when roots cannot reconstruct that graph exactly. Readers resolve omitted graphs from root subgraphs by digest and validate explicit graphs directly, preserving every type and its metadata. Historical full entries remain readable. `formatVersion` identifies normalization rules; storage compaction does not change root fingerprints or require an acknowledgement.
@@ -103,10 +105,10 @@ The command refreshes the machine declaration, schemas, catalogs, and pairing. W
When integration creates competing terminal records, update the unaccepted record against the remaining history, then reassess the resulting diff. An unrelated root's acknowledgement does not need refreshing. The [mechanism decision](../../.agents/notes/implemented/process/2026-09-11-persistence-type-history.md) explains why complete snapshots and per-root predecessors are retained.
For an existing property value-type change requiring review, this command records the explicit same-version choice. The record’s Compatibility and Verification sections must support that choice:
For an existing property value-type change requiring review, first revise the prose file’s Compatibility and Verification sections to explain the actual new transition and its executed checks. Do not reuse the earlier required-to-optional explanation for a different change. Then update the record with that prose and the explicit same-version choice:
```sh
pnpm --silent run persistence-changes --update 2026-09-11-poc-optional --decision same-version --json
pnpm --silent run persistence-changes --update 2026-09-11-poc-optional --decision same-version --prose .artifacts/persistence-change.prose.json --json
```
<a id="dev-note"></a>
@@ -39,6 +39,8 @@ pnpm --silent run verify-persistence-changes --json
pnpm --silent run persistence-review --before .artifacts/base.schema.json --after docs/persistence-schema.json
```
记录决策不会使转换从此比较中消失。`--check` 仅比较当前源码与已确认历史;记录完成后,它不能替代 base/head 评审,也不能证明人类已评审该变更。
在报告旁记录这些文件对应的 commit。添加 `--json` 可获取结构化输出。此只读比较将共享变更与受影响的根类型归组,使用实际字面量 `kind`/`form` 值代替联合类型位置。无法唯一匹配的候选项保留为独立的新增与删除。兼容性部分复制每个根类型的权威分类结果;结构说明不替代确认检查。当前目录标签和声明名称是描述元数据;结构锚点和指纹标识类型。
当前机器清单在 `roots` 中保存完整图。每个 `types` 条目包含 `digest`、`names` 和 `sources`;若根无法精确重建该图,条目还会保存显式 `schema`。读取器按摘要从根的子图恢复省略的图,并直接验证显式图,保留每个类型及其元数据。历史完整条目仍然可读。`formatVersion` 标识规范化规则;存储压缩不改变根指纹,也不需要确认记录。
@@ -103,10 +105,10 @@ pnpm --silent run persistence-changes --update 2026-09-11-poc-optional --prose .
集成产生竞争末端记录时,根据剩余历史更新尚未接受的记录,再重新评估最终差异。无关根的确认无需刷新。[机制决策](../../.agents/notes/implemented/process/2026-09-11-persistence-type-history.zh.md)解释为何保留完整快照和逐根前驱。
若已有属性的值类型变化需要评审,以下命令记录显式的同版本选择。记录中的兼容性与验证部分必须支持该选择:
若已有属性的值类型变化需要评审,先修改说明文件中的兼容性与验证部分,解释实际的新转换及已执行检查。不要为不同变更复用先前必选改可选的说明。然后使用该说明与显式同版本选择更新记录:
```sh
pnpm --silent run persistence-changes --update 2026-09-11-poc-optional --decision same-version --json
pnpm --silent run persistence-changes --update 2026-09-11-poc-optional --decision same-version --prose .artifacts/persistence-change.prose.json --json
```
<a id="dev-note"></a>
+2 -2
View File
@@ -18,8 +18,8 @@
en: 6cd0f79a9455bdf2
zh: a5978b7834c0802b
/persistence-type-change-records/compatibility-rules:
en: 84263e868d1aaefd
zh: bbc79914bb6cd6e5
en: 218b28a5096b5e7d
zh: 5b987c852e204893
/persistence-type-change-records/history-and-limitations:
en: 705a215ce0dd5d82
zh: a3b3e46231dae6ce
+3 -1
View File
@@ -60,11 +60,13 @@ Every detected structural change requires an acknowledgement. Keep the Session v
The classifier identifies established same-version cases and changes requiring compatibility review; it cannot decide semantic safety. The latter require an explicit `--decision same-version` when recording or updating without a version increase. The acknowledgement’s Compatibility section explains actual reader behavior in both directions, and Verification records the executed checks. Review the complete transition, including simultaneous changes. An explicit `version-bump` instead requires its own increasing `SessionHeader.version` transition; a same-version decision cannot waive a header version change. Finalized records remain immutable, so a later record cannot reuse the accepted 3→4 transition.
The CLI requires that explicit choice before generating a flagged same-version record. CI reads the recorded `decision: same-version` and accepts it when the ordinary history, schema, and header-version constraints hold, whether the record was generated or edited manually. Verification cannot establish how the record was authored or whether a human reviewed it. Reviewers compare base and head inventories with [`persistence-review`](../cookbook/reviewing-persistence-type-changes.md#generate); `--check` validates current-tree consistency and cannot reveal a transition already covered by an acknowledgement.
An ordinary event may add payload alternatives with a required, nonnegative integer `data.version` greater than every existing payload version, provided every existing alternative remains readable under the established same-version rules above. Optional property additions and required-to-optional changes may accompany the new version; each retained alternative is compared separately. Other payload changes require compatibility review. Older readers may reject the new payload version. The [catalog acknowledgement](2026-09-20-unknown-child-catalog.md) records one such transition.
The extractor accepts an explicit `@persistenceSource` binding for a core-owned source property on a literal user or developer role; it does not infer a binding from an unannotated type. A producer qualifies its `MessageSourceMap` entry with `@persistenceAttribution`. Qualification promises that an unknown kind and its JSON metadata survive reading without the producer, and that the kind imposes no validation, replay, or authority requirement. A producer may inspect its own kind to resume duplicate suppression; other readers must preserve and derive the recorded messages without that projection. The recorded schema retains the binding, policy version, literal `kind` discriminator, preservation promise, and qualified kind set. Inventory format 2 stores those promises; extraction without a bound policy retains format 1. Session format versions are independent. Both compared snapshots must carry compatible policy state. Existing kind groups still receive ordinary structural comparison; removals, unmarked additions, policy changes, and unrelated structural changes require compatibility review. Multiple context-form alternatives with the same wire kind form one group.
Every same-version explanation states how old records remain readable and how older readers handle new records, including established cases that need no machine review. A feature absent from a log must retain the old behavior; dispensable features must be safe to ignore; required features need an effective refusal signal. Unsupported-feature refusal must not become corruption recovery or tail truncation. For required-to-optional changes, explain how readers handle an absent value. Reviewers assess behavior and evidence; the checker validates the declaration and type classification. A version-bump record follows the [Session-format procedure](../cookbook/adding-a-session-format-version.md).
Every same-version explanation states how old records remain readable and how older readers handle new records, including established cases that need no explicit CLI decision. A feature absent from a log must retain the old behavior; dispensable features must be safe to ignore; required features need an effective refusal signal. Unsupported-feature refusal must not become corruption recovery or tail truncation. For required-to-optional changes, explain how readers handle an absent value. Reviewers assess behavior and evidence; the checker validates the declaration and type classification. A version-bump record follows the [Session-format procedure](../cookbook/adding-a-session-format-version.md).
When a reader rejects a JSON property by name, declare the property as optional `never` and mark it with argument-free `@persistenceReserved`. The extractor retains the forbidden field, so allowing a JSON value later requires an existing-field type change. Required or JSON-valued properties cannot carry this marker. Unmarked optional `never` and `undefined` properties retain their existing omission behavior.
+3 -1
View File
@@ -60,11 +60,13 @@ description: "审阅和维护已记录的会话持久化类型变更、对应 sc
分类器识别已明确允许的同版本情形及需要兼容性评审的变更,不能判定语义安全性。后者在不升版本的记录或更新操作中要求显式提供 `--decision same-version`。确认记录的兼容性部分说明两个方向上的实际读取器行为,验证部分记录已执行的检查。评审覆盖整个转换,包括同时发生的其他变更。显式 `version-bump` 则要求自身包含 `SessionHeader.version` 递增转换;同版本决策不能豁免头版本变化。定稿记录保持不可变,因此后续记录不能复用已接受的 3→4 转换。
CLI 在生成被标记的同版本记录前要求该显式选择。CI 读取所记录的 `decision: same-version`;只要通常的历史、schema 与头版本约束成立,无论记录由工具生成还是手工编辑,都会接受。验证无法确定记录的编写方式,也无法证明人类已评审。评审者使用 [`persistence-review`](../cookbook/reviewing-persistence-type-changes.zh.md#generate) 比较 base 与 head 清单;`--check` 验证当前目录一致性,无法显示已被确认记录覆盖的转换。
普通事件可增加具有必选、非负整数 `data.version` 的载荷分支,新版本必须高于所有已有载荷版本,且所有已有分支按上述明确允许的同版本规则保持可读。可选属性新增和必选改可选可以与新版本一同引入;每个保留分支均独立比较。其他载荷变更需要兼容性评审。旧读取器可能拒绝新载荷版本。[Catalog 确认记录](2026-09-20-unknown-child-catalog.zh.md)记录了此类演进。
提取器接受核心拥有的 source 属性上针对 user 或 developer 字面量角色的显式 `@persistenceSource` 绑定,不会从未标记类型中推断绑定。生产者用 `@persistenceAttribution` 标记其 `MessageSourceMap` 成员。该标记承诺:读取器无需生产者即可保留未知 kind 及其 JSON 元数据,且该 kind 不引入校验、回放或权限要求。生产者可以检查自身 kind 来恢复去重状态;其他读取器必须无需该投影也能保留并派生已记录的消息。记录的 schema 保存绑定、策略版本、字面量 `kind` 判别字段、保留承诺及符合条件的 kind 集合。Inventory format 2 保存这些承诺;没有绑定策略的提取仍使用 format 1。Session 格式版本独立于此。比较双方的快照必须带有兼容的策略状态。已有 kind 分组仍进行常规结构比较;删除、未标记的添加、策略更改及无关结构变更需要兼容性评审。同一 wire kind 的多个上下文形式分支归为一组。
每项同版本说明都须解释旧记录如何保持可读,以及旧读取器如何处理新记录,包括无需机器评审的明确允许情形。日志未使用某功能时必须保留旧行为;可舍弃功能必须能安全忽略;必要功能需要有效的拒绝信号。不受支持功能的拒绝不能变成损坏恢复或尾部截断。对于必选改可选的变更,说明读取器如何处理缺失值。审阅者判断行为和证据;检查器校验声明及类型分类。升版本记录遵循[会话格式流程](../cookbook/adding-a-session-format-version.zh.md)。
每项同版本说明都须解释旧记录如何保持可读,以及旧读取器如何处理新记录,包括无需显式 CLI 决策的明确允许情形。日志未使用某功能时必须保留旧行为;可舍弃功能必须能安全忽略;必要功能需要有效的拒绝信号。不受支持功能的拒绝不能变成损坏恢复或尾部截断。对于必选改可选的变更,说明读取器如何处理缺失值。审阅者判断行为和证据;检查器校验声明及类型分类。升版本记录遵循[会话格式流程](../cookbook/adding-a-session-format-version.zh.md)。
当读取器按属性名拒绝 JSON 字段时,将该属性声明为可选 `never`,并添加无参数的 `@persistenceReserved` 标记。提取器保留这一禁止字段,因此后续允许 JSON 值属于已有字段类型变更。必选属性或允许 JSON 值的属性不能携带该标记。未标记的可选 `never` 和 `undefined` 属性保留现有省略行为。
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-0-1-rc-2/structural-changes:
en: 88698b759e85cd92
zh: 585d2d49d32b631f
en: 7cd96972b43b0cb0
zh: 7e61c1098f402657
/persistence-release-dsh-v0-0-1-rc-2/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -221,7 +221,7 @@ Detected 45 changed roots and 48 structural differences. The review requirement
| `event:request/context.ignorable` | `optional-property-added` | `review-required` |
| `event:request/header.ignorable` | `optional-property-added` | `review-required` |
| `event:sandbox/mode.ignorable` | `optional-property-added` | `review-required` |
| `event:schedule/change` | `root-added` | `same-version` |
| `event:schedule/change` | `root-added` | `not-required` |
| `event:session/end-seed.ignorable` | `optional-property-added` | `review-required` |
| `event:session/title.ignorable` | `optional-property-added` | `review-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
@@ -230,10 +230,10 @@ Detected 45 changed roots and 48 structural differences. The review requirement
| `event:step/start.ignorable` | `optional-property-added` | `review-required` |
| `event:subagent/descriptor.ignorable` | `optional-property-added` | `review-required` |
| `event:todo/write.ignorable` | `optional-property-added` | `review-required` |
| `event:tool-workflow/agent-end` | `root-added` | `same-version` |
| `event:tool-workflow/agent-start` | `root-added` | `same-version` |
| `event:tool-workflow/run-end` | `root-added` | `same-version` |
| `event:tool-workflow/run-start` | `root-added` | `same-version` |
| `event:tool-workflow/agent-end` | `root-added` | `not-required` |
| `event:tool-workflow/agent-start` | `root-added` | `not-required` |
| `event:tool-workflow/run-end` | `root-added` | `not-required` |
| `event:tool-workflow/run-start` | `root-added` | `not-required` |
| `event:tool/call.ignorable` | `optional-property-added` | `review-required` |
| `event:tool/code-dispatch.ignorable` | `optional-property-added` | `review-required` |
| `event:tool/code-dispatch-start.ignorable` | `optional-property-added` | `review-required` |
@@ -221,7 +221,7 @@ changes:
| `event:request/context.ignorable` | `optional-property-added` | `review-required` |
| `event:request/header.ignorable` | `optional-property-added` | `review-required` |
| `event:sandbox/mode.ignorable` | `optional-property-added` | `review-required` |
| `event:schedule/change` | `root-added` | `same-version` |
| `event:schedule/change` | `root-added` | `not-required` |
| `event:session/end-seed.ignorable` | `optional-property-added` | `review-required` |
| `event:session/title.ignorable` | `optional-property-added` | `review-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
@@ -230,10 +230,10 @@ changes:
| `event:step/start.ignorable` | `optional-property-added` | `review-required` |
| `event:subagent/descriptor.ignorable` | `optional-property-added` | `review-required` |
| `event:todo/write.ignorable` | `optional-property-added` | `review-required` |
| `event:tool-workflow/agent-end` | `root-added` | `same-version` |
| `event:tool-workflow/agent-start` | `root-added` | `same-version` |
| `event:tool-workflow/run-end` | `root-added` | `same-version` |
| `event:tool-workflow/run-start` | `root-added` | `same-version` |
| `event:tool-workflow/agent-end` | `root-added` | `not-required` |
| `event:tool-workflow/agent-start` | `root-added` | `not-required` |
| `event:tool-workflow/run-end` | `root-added` | `not-required` |
| `event:tool-workflow/run-start` | `root-added` | `not-required` |
| `event:tool/call.ignorable` | `optional-property-added` | `review-required` |
| `event:tool/code-dispatch.ignorable` | `optional-property-added` | `review-required` |
| `event:tool/code-dispatch-start.ignorable` | `optional-property-added` | `review-required` |
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-0-1-rc-3/structural-changes:
en: 6bdebcbbb335e840
zh: 6d94a3b39685385e
en: 0fd2841ea23b8cd6
zh: 1138a25ac478eaa8
/persistence-release-dsh-v0-0-1-rc-3/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -101,10 +101,10 @@ Detected 12 changed roots and 12 structural differences. The review requirement
| `event:compact/prune` | `root-removed` | `review-required` |
| `event:compact/start` | `root-removed` | `review-required` |
| `event:compact/summary` | `root-removed` | `review-required` |
| `event:compaction/end` | `root-added` | `same-version` |
| `event:compaction/prune` | `root-added` | `same-version` |
| `event:compaction/start` | `root-added` | `same-version` |
| `event:compaction/summary` | `root-added` | `same-version` |
| `event:compaction/end` | `root-added` | `not-required` |
| `event:compaction/prune` | `root-added` | `not-required` |
| `event:compaction/start` | `root-added` | `not-required` |
| `event:compaction/summary` | `root-added` | `not-required` |
| `event:hook/invoked.data.dialect` | `type-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source.kind` | `type-changed` | `review-required` |
| `event:user/message.data.source.kind` | `type-changed` | `review-required` |
@@ -101,10 +101,10 @@ changes:
| `event:compact/prune` | `root-removed` | `review-required` |
| `event:compact/start` | `root-removed` | `review-required` |
| `event:compact/summary` | `root-removed` | `review-required` |
| `event:compaction/end` | `root-added` | `same-version` |
| `event:compaction/prune` | `root-added` | `same-version` |
| `event:compaction/start` | `root-added` | `same-version` |
| `event:compaction/summary` | `root-added` | `same-version` |
| `event:compaction/end` | `root-added` | `not-required` |
| `event:compaction/prune` | `root-added` | `not-required` |
| `event:compaction/start` | `root-added` | `not-required` |
| `event:compaction/summary` | `root-added` | `not-required` |
| `event:hook/invoked.data.dialect` | `type-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source.kind` | `type-changed` | `review-required` |
| `event:user/message.data.source.kind` | `type-changed` | `review-required` |
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-0-rc-8/structural-changes:
en: 6fe06d95f9b394a9
zh: a6d0517f2c542111
en: 1909dc1b62eef347
zh: 010e53d396fc675c
/persistence-release-dsh-v0-1-0-rc-8/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -85,12 +85,12 @@ Detected 8 changed roots and 8 structural differences. The review requirement be
| Path | Change | Review requirement |
|---|---|---|
| `event:agent/inbox/spliced.data.inserted[].source` | `union-variants-changed` | `review-required` |
| `event:assistant/message.data.interrupted` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.interrupted` | `optional-property-added` | `not-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
| `event:team/member` | `root-added` | `same-version` |
| `event:team/message/delivered` | `root-added` | `same-version` |
| `event:team/message/queued` | `root-added` | `same-version` |
| `event:team/task` | `root-added` | `same-version` |
| `event:team/member` | `root-added` | `not-required` |
| `event:team/message/delivered` | `root-added` | `not-required` |
| `event:team/message/queued` | `root-added` | `not-required` |
| `event:team/task` | `root-added` | `not-required` |
| `event:user/message.data.source` | `union-variants-changed` | `review-required` |
<!-- persistence-release-changes:end -->
@@ -85,12 +85,12 @@ changes:
| 路径 | 变化 | 审查要求 |
|---|---|---|
| `event:agent/inbox/spliced.data.inserted[].source` | `union-variants-changed` | `review-required` |
| `event:assistant/message.data.interrupted` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.interrupted` | `optional-property-added` | `not-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
| `event:team/member` | `root-added` | `same-version` |
| `event:team/message/delivered` | `root-added` | `same-version` |
| `event:team/message/queued` | `root-added` | `same-version` |
| `event:team/task` | `root-added` | `same-version` |
| `event:team/member` | `root-added` | `not-required` |
| `event:team/message/delivered` | `root-added` | `not-required` |
| `event:team/message/queued` | `root-added` | `not-required` |
| `event:team/task` | `root-added` | `not-required` |
| `event:user/message.data.source` | `union-variants-changed` | `review-required` |
<!-- persistence-release-changes:end -->
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-1-rc-1/structural-changes:
en: ccbbf46733caf0b0
zh: 6dad1347c9f7c3e6
en: 69516d329a54a014
zh: 16a3c770a9ba3217
/persistence-release-dsh-v0-1-1-rc-1/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -63,7 +63,7 @@ Detected 1 changed root and 1 structural difference. The review requirement belo
| Path | Change | Review requirement |
|---|---|---|
| `event:permission/preset.data.origin` | `optional-property-added` | `same-version` |
| `event:permission/preset.data.origin` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -63,7 +63,7 @@ changes:
| 路径 | 变化 | 审查要求 |
|---|---|---|
| `event:permission/preset.data.origin` | `optional-property-added` | `same-version` |
| `event:permission/preset.data.origin` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-1-rc-2/structural-changes:
en: 330d88a97c27b7d3
zh: 4b9b2ddcd94e7a33
en: fedf3524c654f8b3
zh: 4df22b00a3981e60
/persistence-release-dsh-v0-1-1-rc-2/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -90,17 +90,17 @@ Detected 10 changed roots and 11 structural differences. The review requirement
| Path | Change | Review requirement |
|---|---|---|
| `event:agent/inbox/spliced.data.inserted[].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:assistant/chunk.data.chunk.block.attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.rawOutput[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.summary[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:agent/inbox/spliced.data.inserted[].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:assistant/chunk.data.chunk.block.attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:assistant/message.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:compaction/summary.data.rawOutput[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:compaction/summary.data.summary[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:permission/preset.data.origin` | `property-removed` | `review-required` |
| `event:session/title-llm-request.data.messages[].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:team/message/queued.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:tool/code-dispatch.data.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:tool/result.data.message.content[0].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:user/message.data.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:session/title-llm-request.data.messages[].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:team/message/queued.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:tool/code-dispatch.data.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:tool/result.data.message.content[0].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:user/message.data.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -90,17 +90,17 @@ changes:
| 路径 | 变化 | 审查要求 |
|---|---|---|
| `event:agent/inbox/spliced.data.inserted[].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:assistant/chunk.data.chunk.block.attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.rawOutput[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.summary[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:agent/inbox/spliced.data.inserted[].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:assistant/chunk.data.chunk.block.attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:assistant/message.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:compaction/summary.data.rawOutput[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:compaction/summary.data.summary[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:permission/preset.data.origin` | `property-removed` | `review-required` |
| `event:session/title-llm-request.data.messages[].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:team/message/queued.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:tool/code-dispatch.data.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:tool/result.data.message.content[0].content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:user/message.data.content[].attachment.originalDimensions` | `optional-property-added` | `same-version` |
| `event:session/title-llm-request.data.messages[].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:team/message/queued.data.message.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:tool/code-dispatch.data.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:tool/result.data.message.content[0].content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
| `event:user/message.data.content[].attachment.originalDimensions` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-2-alpha-1/structural-changes:
en: 5c0c487e21c022cc
zh: 4d4c97941321611c
en: ebe16d1afafb4cbc
zh: d80430fa60b01c29
/persistence-release-dsh-v0-1-2-alpha-1/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -223,16 +223,16 @@ Detected 52 changed roots and 61 structural differences. The review requirement
| `event:approval/asked.ignorable` | `property-removed` | `review-required` |
| `event:approval/decided.ignorable` | `property-removed` | `review-required` |
| `event:approval/policy.ignorable` | `property-removed` | `review-required` |
| `event:assistant/chunk.data.chunk.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:assistant/chunk.data.chunk.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:assistant/chunk.ignorable` | `property-removed` | `review-required` |
| `event:assistant/message.data.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:assistant/message.ignorable` | `property-removed` | `review-required` |
| `event:command/done.ignorable` | `property-removed` | `review-required` |
| `event:command/run.ignorable` | `property-removed` | `review-required` |
| `event:compaction/end.ignorable` | `property-removed` | `review-required` |
| `event:compaction/prune.ignorable` | `property-removed` | `review-required` |
| `event:compaction/start.ignorable` | `property-removed` | `review-required` |
| `event:compaction/summary.data.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:compaction/summary.ignorable` | `property-removed` | `review-required` |
| `event:feedback/record.ignorable` | `property-removed` | `review-required` |
| `event:goal/change.ignorable` | `property-removed` | `review-required` |
@@ -240,25 +240,25 @@ Detected 52 changed roots and 61 structural differences. The review requirement
| `event:hook/result.ignorable` | `property-removed` | `review-required` |
| `event:llm/retry.ignorable` | `property-removed` | `review-required` |
| `event:llm/retry-started.ignorable` | `property-removed` | `review-required` |
| `event:model/selection` | `root-added` | `same-version` |
| `event:model/selection` | `root-added` | `not-required` |
| `event:permission/preset.ignorable` | `property-removed` | `review-required` |
| `event:plan/mode.ignorable` | `property-removed` | `review-required` |
| `event:request/context.ignorable` | `property-removed` | `review-required` |
| `event:request/header.data.reason` | `union-variants-changed` | `review-required` |
| `event:request/header.data.startsSeries` | `optional-property-added` | `same-version` |
| `event:request/header.data.startsSeries` | `optional-property-added` | `not-required` |
| `event:request/header.ignorable` | `property-removed` | `review-required` |
| `event:sandbox/mode.ignorable` | `property-removed` | `review-required` |
| `event:schedule/change.ignorable` | `property-removed` | `review-required` |
| `event:session-log-deepseek/delivery-accepted` | `root-added` | `same-version` |
| `event:session-log-deepseek/delivery-accepted` | `root-added` | `not-required` |
| `event:session/end-seed.ignorable` | `property-removed` | `review-required` |
| `event:session/title.ignorable` | `property-removed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
| `event:session/title-llm-request.ignorable` | `property-removed` | `review-required` |
| `event:step/end.ignorable` | `property-removed` | `review-required` |
| `event:step/start.ignorable` | `property-removed` | `review-required` |
| `event:subagent/descriptor.data.agentReasoningEffort` | `optional-property-added` | `same-version` |
| `event:subagent/descriptor.data.agentReasoningEffort` | `optional-property-added` | `not-required` |
| `event:subagent/descriptor.ignorable` | `property-removed` | `review-required` |
| `event:subagent/model-selection-policy` | `root-added` | `same-version` |
| `event:subagent/model-selection-policy` | `root-added` | `not-required` |
| `event:team/member.ignorable` | `property-removed` | `review-required` |
| `event:team/message/delivered.ignorable` | `property-removed` | `review-required` |
| `event:team/message/queued.ignorable` | `property-removed` | `review-required` |
@@ -223,16 +223,16 @@ changes:
| `event:approval/asked.ignorable` | `property-removed` | `review-required` |
| `event:approval/decided.ignorable` | `property-removed` | `review-required` |
| `event:approval/policy.ignorable` | `property-removed` | `review-required` |
| `event:assistant/chunk.data.chunk.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:assistant/chunk.data.chunk.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:assistant/chunk.ignorable` | `property-removed` | `review-required` |
| `event:assistant/message.data.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:assistant/message.data.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:assistant/message.ignorable` | `property-removed` | `review-required` |
| `event:command/done.ignorable` | `property-removed` | `review-required` |
| `event:command/run.ignorable` | `property-removed` | `review-required` |
| `event:compaction/end.ignorable` | `property-removed` | `review-required` |
| `event:compaction/prune.ignorable` | `property-removed` | `review-required` |
| `event:compaction/start.ignorable` | `property-removed` | `review-required` |
| `event:compaction/summary.data.usage.totalTokens` | `optional-property-added` | `same-version` |
| `event:compaction/summary.data.usage.totalTokens` | `optional-property-added` | `not-required` |
| `event:compaction/summary.ignorable` | `property-removed` | `review-required` |
| `event:feedback/record.ignorable` | `property-removed` | `review-required` |
| `event:goal/change.ignorable` | `property-removed` | `review-required` |
@@ -240,25 +240,25 @@ changes:
| `event:hook/result.ignorable` | `property-removed` | `review-required` |
| `event:llm/retry.ignorable` | `property-removed` | `review-required` |
| `event:llm/retry-started.ignorable` | `property-removed` | `review-required` |
| `event:model/selection` | `root-added` | `same-version` |
| `event:model/selection` | `root-added` | `not-required` |
| `event:permission/preset.ignorable` | `property-removed` | `review-required` |
| `event:plan/mode.ignorable` | `property-removed` | `review-required` |
| `event:request/context.ignorable` | `property-removed` | `review-required` |
| `event:request/header.data.reason` | `union-variants-changed` | `review-required` |
| `event:request/header.data.startsSeries` | `optional-property-added` | `same-version` |
| `event:request/header.data.startsSeries` | `optional-property-added` | `not-required` |
| `event:request/header.ignorable` | `property-removed` | `review-required` |
| `event:sandbox/mode.ignorable` | `property-removed` | `review-required` |
| `event:schedule/change.ignorable` | `property-removed` | `review-required` |
| `event:session-log-deepseek/delivery-accepted` | `root-added` | `same-version` |
| `event:session-log-deepseek/delivery-accepted` | `root-added` | `not-required` |
| `event:session/end-seed.ignorable` | `property-removed` | `review-required` |
| `event:session/title.ignorable` | `property-removed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source` | `union-variants-changed` | `review-required` |
| `event:session/title-llm-request.ignorable` | `property-removed` | `review-required` |
| `event:step/end.ignorable` | `property-removed` | `review-required` |
| `event:step/start.ignorable` | `property-removed` | `review-required` |
| `event:subagent/descriptor.data.agentReasoningEffort` | `optional-property-added` | `same-version` |
| `event:subagent/descriptor.data.agentReasoningEffort` | `optional-property-added` | `not-required` |
| `event:subagent/descriptor.ignorable` | `property-removed` | `review-required` |
| `event:subagent/model-selection-policy` | `root-added` | `same-version` |
| `event:subagent/model-selection-policy` | `root-added` | `not-required` |
| `event:team/member.ignorable` | `property-removed` | `review-required` |
| `event:team/message/delivered.ignorable` | `property-removed` | `review-required` |
| `event:team/message/queued.ignorable` | `property-removed` | `review-required` |
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-3-alpha-1/structural-changes:
en: 435e41d730a111fe
zh: d8f6c30f1dd53184
en: 746c20adf88325e1
zh: e607c8b6e3dc8a3a
/persistence-release-dsh-v0-1-3-alpha-1/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -115,17 +115,17 @@ Detected 17 changed roots and 25 structural differences. The review requirement
| `JsonlHeaderLine.isSeeded` | `required-property-added` | `review-required` |
| `SessionHeader.version` | `type-changed` | `review-required` |
| `event:agent/inbox/spliced.data.inserted[].content[]` | `union-variants-changed` | `review-required` |
| `event:agent/inbox/spliced.data.inserted[].source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:assistant/attempt` | `root-added` | `same-version` |
| `event:agent/inbox/spliced.data.inserted[].source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
| `event:assistant/attempt` | `root-added` | `not-required` |
| `event:assistant/chunk` | `root-removed` | `review-required` |
| `event:assistant/message.data.message.content[]` | `union-variants-changed` | `review-required` |
| `event:assistant/message.data.stream` | `required-property-added` | `review-required` |
| `event:compaction/summary.data` | `union-variants-changed` | `review-required` |
| `event:session-log-deepseek/delivery-accepted.data.sessionFormatVersion` | `optional-property-added` | `same-version` |
| `event:session/end-seed.data.inherited` | `optional-property-added` | `same-version` |
| `event:session-log-deepseek/delivery-accepted.data.sessionFormatVersion` | `optional-property-added` | `not-required` |
| `event:session/end-seed.data.inherited` | `optional-property-added` | `not-required` |
| `event:session/end-seed.data` | `index-signature-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].content[]` | `union-variants-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:session/title-llm-request.data.messages[].source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
| `event:team/member.data.version` | `type-changed` | `review-required` |
| `event:team/message/delivered.data.version` | `type-changed` | `review-required` |
| `event:team/message/queued.data.message.content[]` | `union-variants-changed` | `review-required` |
@@ -135,7 +135,7 @@ Detected 17 changed roots and 25 structural differences. The review requirement
| `event:tool/code-dispatch.data.content[]` | `union-variants-changed` | `review-required` |
| `event:tool/result.data.message.content[0].content[]` | `union-variants-changed` | `review-required` |
| `event:user/message.data.content[]` | `union-variants-changed` | `review-required` |
| `event:user/message.data.source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:user/message.data.source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -115,17 +115,17 @@ changes:
| `JsonlHeaderLine.isSeeded` | `required-property-added` | `review-required` |
| `SessionHeader.version` | `type-changed` | `review-required` |
| `event:agent/inbox/spliced.data.inserted[].content[]` | `union-variants-changed` | `review-required` |
| `event:agent/inbox/spliced.data.inserted[].source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:assistant/attempt` | `root-added` | `same-version` |
| `event:agent/inbox/spliced.data.inserted[].source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
| `event:assistant/attempt` | `root-added` | `not-required` |
| `event:assistant/chunk` | `root-removed` | `review-required` |
| `event:assistant/message.data.message.content[]` | `union-variants-changed` | `review-required` |
| `event:assistant/message.data.stream` | `required-property-added` | `review-required` |
| `event:compaction/summary.data` | `union-variants-changed` | `review-required` |
| `event:session-log-deepseek/delivery-accepted.data.sessionFormatVersion` | `optional-property-added` | `same-version` |
| `event:session/end-seed.data.inherited` | `optional-property-added` | `same-version` |
| `event:session-log-deepseek/delivery-accepted.data.sessionFormatVersion` | `optional-property-added` | `not-required` |
| `event:session/end-seed.data.inherited` | `optional-property-added` | `not-required` |
| `event:session/end-seed.data` | `index-signature-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].content[]` | `union-variants-changed` | `review-required` |
| `event:session/title-llm-request.data.messages[].source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:session/title-llm-request.data.messages[].source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
| `event:team/member.data.version` | `type-changed` | `review-required` |
| `event:team/message/delivered.data.version` | `type-changed` | `review-required` |
| `event:team/message/queued.data.message.content[]` | `union-variants-changed` | `review-required` |
@@ -135,7 +135,7 @@ changes:
| `event:tool/code-dispatch.data.content[]` | `union-variants-changed` | `review-required` |
| `event:tool/result.data.message.content[0].content[]` | `union-variants-changed` | `review-required` |
| `event:user/message.data.content[]` | `union-variants-changed` | `review-required` |
| `event:user/message.data.source.references[].capturedFormatVersion` | `optional-property-added` | `same-version` |
| `event:user/message.data.source.references[].capturedFormatVersion` | `optional-property-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-3-alpha-2/structural-changes:
en: fa9bf8d8a44b8b6a
zh: 40f45050c132f76e
en: 4b866a071a7d653e
zh: a2ffe1a9ae361e2c
/persistence-release-dsh-v0-1-3-alpha-2/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -66,8 +66,8 @@ Detected 2 changed roots and 2 structural differences. The review requirement be
| Path | Change | Review requirement |
|---|---|---|
| `event:feedback/message-delete` | `root-added` | `same-version` |
| `event:feedback/message-put` | `root-added` | `same-version` |
| `event:feedback/message-delete` | `root-added` | `not-required` |
| `event:feedback/message-put` | `root-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -66,8 +66,8 @@ changes:
| 路径 | 变化 | 审查要求 |
|---|---|---|
| `event:feedback/message-delete` | `root-added` | `same-version` |
| `event:feedback/message-put` | `root-added` | `same-version` |
| `event:feedback/message-delete` | `root-added` | `not-required` |
| `event:feedback/message-put` | `root-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-5-alpha-1/structural-changes:
en: 978d9c63d58817be
zh: b69f074aa306410b
en: b5f68991a076ac50
zh: 4593e46ada9541e9
/persistence-release-dsh-v0-1-5-alpha-1/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -104,13 +104,13 @@ Detected 12 changed roots and 25 structural differences. The review requirement
| `event:assistant/message.surfaceOp.start` | `property-removed` | `review-required` |
| `event:assistant/message.surfaceOp.endSeq` | `required-property-added` | `review-required` |
| `event:assistant/message.surfaceOp.startSeq` | `required-property-added` | `review-required` |
| `event:request/context.data.systemPromptUpdate` | `optional-property-added` | `same-version` |
| `event:request/context.data.systemPromptUpdate` | `optional-property-added` | `not-required` |
| `event:request/header.data.header.system` | `property-removed` | `review-required` |
| `event:system/message` | `root-added` | `review-required` |
| `event:tool/code-dispatch` | `root-removed` | `review-required` |
| `event:tool/code-dispatch-start` | `root-removed` | `review-required` |
| `event:tool/ptc-dispatch` | `root-added` | `same-version` |
| `event:tool/ptc-dispatch-start` | `root-added` | `same-version` |
| `event:tool/ptc-dispatch` | `root-added` | `not-required` |
| `event:tool/ptc-dispatch-start` | `root-added` | `not-required` |
| `event:tool/result.surfaceOp` | `property-made-required` | `review-required` |
| `event:tool/result.surfaceOp.end` | `property-removed` | `review-required` |
| `event:tool/result.surfaceOp.start` | `property-removed` | `review-required` |
@@ -104,13 +104,13 @@ changes:
| `event:assistant/message.surfaceOp.start` | `property-removed` | `review-required` |
| `event:assistant/message.surfaceOp.endSeq` | `required-property-added` | `review-required` |
| `event:assistant/message.surfaceOp.startSeq` | `required-property-added` | `review-required` |
| `event:request/context.data.systemPromptUpdate` | `optional-property-added` | `same-version` |
| `event:request/context.data.systemPromptUpdate` | `optional-property-added` | `not-required` |
| `event:request/header.data.header.system` | `property-removed` | `review-required` |
| `event:system/message` | `root-added` | `review-required` |
| `event:tool/code-dispatch` | `root-removed` | `review-required` |
| `event:tool/code-dispatch-start` | `root-removed` | `review-required` |
| `event:tool/ptc-dispatch` | `root-added` | `same-version` |
| `event:tool/ptc-dispatch-start` | `root-added` | `same-version` |
| `event:tool/ptc-dispatch` | `root-added` | `not-required` |
| `event:tool/ptc-dispatch-start` | `root-added` | `not-required` |
| `event:tool/result.surfaceOp` | `property-made-required` | `review-required` |
| `event:tool/result.surfaceOp.end` | `property-removed` | `review-required` |
| `event:tool/result.surfaceOp.start` | `property-removed` | `review-required` |
@@ -21,8 +21,8 @@
en: af9cea43334ee692
zh: c6c8bd0d6a17718a
/persistence-release-dsh-v0-1-5-alpha-2/structural-changes:
en: 9e59c254ff49909e
zh: 59957fcede302986
en: 5a12854a5c81d51e
zh: dc924c0138b2e57a
/persistence-release-dsh-v0-1-5-alpha-2/verification:
en: 8ccca317964523b1
zh: 2c8b3e70a3320778
@@ -72,11 +72,11 @@ Detected 4 changed roots and 5 structural differences. The review requirement be
| Path | Change | Review requirement |
|---|---|---|
| `event:deliverables/presented` | `root-added` | `same-version` |
| `event:feedback/message-put.data.item.category` | `optional-property-added` | `same-version` |
| `event:feedback/record.data.text` | `property-made-optional` | `same-version` |
| `event:feedback/record.data.category` | `optional-property-added` | `same-version` |
| `event:subagent/catalog` | `root-added` | `same-version` |
| `event:deliverables/presented` | `root-added` | `not-required` |
| `event:feedback/message-put.data.item.category` | `optional-property-added` | `not-required` |
| `event:feedback/record.data.text` | `property-made-optional` | `not-required` |
| `event:feedback/record.data.category` | `optional-property-added` | `not-required` |
| `event:subagent/catalog` | `root-added` | `not-required` |
<!-- persistence-release-changes:end -->
@@ -72,11 +72,11 @@ changes:
| 路径 | 变化 | 审查要求 |
|---|---|---|
| `event:deliverables/presented` | `root-added` | `same-version` |
| `event:feedback/message-put.data.item.category` | `optional-property-added` | `same-version` |
| `event:feedback/record.data.text` | `property-made-optional` | `same-version` |
| `event:feedback/record.data.category` | `optional-property-added` | `same-version` |
| `event:subagent/catalog` | `root-added` | `same-version` |
| `event:deliverables/presented` | `root-added` | `not-required` |
| `event:feedback/message-put.data.item.category` | `optional-property-added` | `not-required` |
| `event:feedback/record.data.text` | `property-made-optional` | `not-required` |
| `event:feedback/record.data.category` | `optional-property-added` | `not-required` |
| `event:subagent/catalog` | `root-added` | `not-required` |
<!-- persistence-release-changes:end -->
+3 -7
View File
@@ -21,10 +21,9 @@ export interface PersistenceFinalizationCheckpoint {
readonly acceptedRecords: Readonly<Record<string, string>>
}
/** Latest accepted baseline schemas and the record ids locked by retained checkpoints. */
/** Latest finalized version and the record ids locked by retained checkpoints. */
export interface PersistenceFinalization {
readonly version: number
readonly roots: ReadonlyMap<string, PersistenceRoot>
readonly acceptedRecords: ReadonlySet<string>
}
@@ -105,7 +104,7 @@ function status(root: string, path: string): number | undefined {
}
/**
* Validate retained checkpoints against accepted history and reconstruct the latest accepted baseline.
* Validate retained checkpoints against accepted history and collect their locked record ids.
* @param root - checkout or isolated fixture root.
* @param history - parsed acknowledgement entries, including later successors.
* @returns finalization state, or undefined for a checkout with neither status nor checkpoints.
@@ -120,7 +119,6 @@ export function loadPersistenceFinalization(root: string, history: Pick<Persiste
if (!files.includes(`v${version}.json`)) throw new Error(`missing persistence finalization checkpoint v${version}.json`)
const entries = new Map(history.entries.map(entry => [entry.record.id, entry]))
const acceptedRecords = new Set<string>()
let latestRoots: Map<string, PersistenceRoot> | undefined
for (const file of files) {
const match = /^v(0|[1-9]\d*)\.json$/u.exec(file)
const capturedVersion = match === null ? NaN : Number(match[1])
@@ -165,8 +163,6 @@ export function loadPersistenceFinalization(root: string, history: Pick<Persiste
|| Object.entries(expected).some(([field, expectedValue]) => value[field] !== expectedValue)
})) throw new Error(`${file}: finalized roots do not match complete accepted history`)
if (writerVersion([...tips.values()]) !== capturedVersion) throw new Error(`${file}: accepted SessionHeader.version does not match finalized version`)
if (capturedVersion === version) latestRoots = tips
}
if (latestRoots === undefined) throw new Error(`missing finalized schemas for Session format ${version}`)
return { version, roots: latestRoots, acceptedRecords }
return { version, acceptedRecords }
}
+1 -1
View File
@@ -40,7 +40,7 @@ function structuralChanges(entry: PersistenceReleaseEntry, language: Language):
const heading = language === 'en' ? '| Path | Change | Review requirement |' : '| 路径 | 变化 | 审查要求 |'
const rows = entry.differences.map((change) => {
const path = change.path.replaceAll('`', '\\`').replaceAll('|', '\\|')
return `| \`${path}\` | \`${change.kind}\` | \`${change.requiresCompatibilityReview ? 'review-required' : 'same-version'}\` |`
return `| \`${path}\` | \`${change.kind}\` | \`${change.requiresCompatibilityReview ? 'review-required' : 'not-required'}\` |`
})
return [summary, '', heading, '|---|---|---|', ...rows].join('\n')
}
+1 -1
View File
@@ -344,7 +344,7 @@ describe('release facts', () => {
['difference count', '1 structural difference', '9 structural differences'],
['path', '`event:example/value.data`', '`event:example/value.wrong`'],
['kind', '`type-changed`', '`optional-property-added`'],
['review requirement', '`review-required`', '`same-version`'],
['review requirement', '`review-required`', '`not-required`'],
])('rejects stale record %s', (_label, original, replacement) => {
const data = fixture()
runPersistenceReleases(['--write'], data.root)
+1
View File
@@ -66,6 +66,7 @@ describe('persistence review', () => {
{ root: 'event:user/message', path: 'event:user/message.data.source[kind="tool-registry"]' },
] })
const markdown = renderPersistenceReview(report)
expect(markdown).toContain('## Compatibility review requirements')
expect(markdown).not.toContain('hooks-codex')
expect(markdown).not.toMatch(/source\[\d+\]/u)
for (const root of report.roots) expect(root.changes).toEqual(classifyPersistenceChange(
+2 -2
View File
@@ -199,7 +199,7 @@ export function renderPersistenceReview(report: PersistenceReview): string {
`Before: ${item.before === null ? 'absent' : code(item.before)}; after: ${item.after === null ? 'absent' : code(item.after)}.`, '',
...item.locations.map(location => `- ${code(location.path)}`), '', '</details>')
}
lines.push('', '## Authoritative compatibility results', '')
lines.push('', '## Compatibility review requirements', '')
for (const root of report.roots) {
lines.push(`### ${code(root.root)}`, '', `Assessment: **${root.changes.some(change => change.requiresCompatibilityReview) ? 'compatibility review required' : 'same-version allowed'}**.`, '',
...root.changes.map(change => `- ${code(change.path)}: ${change.description} (${code(change.kind)}; requiresCompatibilityReview: ${String(change.requiresCompatibilityReview)}).`), '')
@@ -210,7 +210,7 @@ export function renderPersistenceReview(report: PersistenceReview): string {
/**
* Read two explicit inventory files and return Markdown or JSON without mutating either.
* @param args - --before and --after paths, and optional --json.
* @returns structural evidence and exact compatibility results.
* @returns structural evidence and per-root compatibility-review requirements.
*/
export function runPersistenceReview(args: readonly string[]): string {
const { values } = parseArgs({ args: [...args], options: { before: { type: 'string' }, after: { type: 'string' }, json: { type: 'boolean' } }, strict: true, allowPositionals: false })