dsh-completion-guard 0.5.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,335 @@
2
2
 
3
3
  All notable changes to this project are documented here. The project is pre-1.0; release versions track the plugin lifecycle, not stabilised API promises.
4
4
 
5
+ ## 0.6.0 third repair round after targeted review (2026-09-14)
6
+
7
+ Two findings from the targeted review of `fcc3813`, both fixed.
8
+
9
+ - **A certificate minted after adoption can no longer ratify the adoption.** The
10
+ closure check compared the certificate's revision with the revision frozen at
11
+ adoption, which a later log entry could satisfy: adopting a contract that
12
+ named a certificate that did not exist yet, then producing that certificate
13
+ afterwards, was granted. The adoption now resolves and freezes the closure
14
+ certificate's IDENTITY (its certification digest, epoch and revision) at the
15
+ adoption watermark, and the gate requires exactly that certificate. An
16
+ unresolvable reference is recorded as unresolved rather than left open for a
17
+ future entry to satisfy. A later release obligation still does not invalidate
18
+ the frozen candidate closure. The frozen certificate must also match the
19
+ candidate revision at adoption; a certificate already stale before adoption
20
+ is refused.
21
+ - **Invalid adoption input no longer poisons a valid contract.** A root
22
+ `/context-guard release adopt` with a malformed payload was treated as damaged
23
+ persisted state, so one typo permanently blocked every later publication. A
24
+ root command the user typed badly is a usage diagnostic; only an unreadable
25
+ persisted reservation, settlement or contract record marks the release state
26
+ damaged. A malformed plugin-notice record still fails closed.
27
+
28
+ New regression cases: a certificate minted after adoption is refused (with the
29
+ projection still valid), a certificate that existed at adoption is frozen by
30
+ identity and survives a later obligation,
31
+ and invalid/mistyped adopt input leaves a valid contract usable.
32
+
33
+ ## 0.6.0 second repair round after follow-up review (2026-09-14)
34
+
35
+ A follow-up review of the repair commit found five remaining defects in the new
36
+ wiring. All five reproduced and are fixed. The reviewer's counterexamples are
37
+ kept as permanent regression cases in the suites they belong to.
38
+
39
+ ### Fixed
40
+
41
+ - **Adding the v5 boundary no longer answers a pre-v5 question.** Deliveries were
42
+ only gated by the watermark of their own turn; appending the boundary at the
43
+ end of a v4 log therefore made an old turn's answer retroactively close an
44
+ obligation the old rules had left open. A delivery now counts only when its
45
+ turn ended AFTER the boundary, and only obligations captured after the
46
+ boundary can be closed by one.
47
+ - **The real publish producer now observes everything the contract names.** The
48
+ trusted reader fills the registry from the canonicalized resolution (it was
49
+ simply missing, so any contract naming a registry could never be granted), and
50
+ the ref is resolved by the runtime from the ADOPTED CONTRACT with the audited
51
+ git executable — a closed, reachable path, instead of a command-manifest field
52
+ the publish manifest schema rejects. A ref that resolves to a commit different
53
+ from the artifact's embedded `gitHead` is refused.
54
+ - **A new release instruction no longer invalidates the certificate it needs.**
55
+ The closure check demanded the CURRENT contract revision, so capturing the
56
+ publish obligation invalidated the very certificate the release was about to
57
+ use, and certifying afterwards required the publish to be complete first. The
58
+ contract now freezes the candidate scope's revision at adoption and requires
59
+ the closure certificate to be the one that certified exactly that revision.
60
+ A later obligation does not re-validate a moved candidate, and a certificate
61
+ minted after adoption is still refused.
62
+ - **Read-only release queries no longer poison the release state.** `release
63
+ status` (and an omitted verb) is a read-only command; an unknown verb is a
64
+ usage diagnostic. Only an unreadable persisted record marks the release state
65
+ damaged, so a plain query can no longer block every future publication
66
+ irreversibly.
67
+ - **There is now a callable trusted recovery entry.** `context_guard_release`
68
+ reads the release state and, for `reconcile`, reads the external identity
69
+ through the same audited registry adapter the publish path uses and settles
70
+ the reservation only when the readback names the bytes the contract — or the
71
+ reservation's recorded SRI — froze. It never re-sends a release, and it works
72
+ after a restart and for a revoked-but-in-flight attempt, because revocation
73
+ withdraws future authority rather than the duty to reconcile an effect that
74
+ may already have happened. A contract that froze only the byte SHA-256 stays
75
+ reconcilable and can still DETECT a mismatched readback.
76
+ - **A presented proof is now part of the persisted contract.** The checkpoint
77
+ call records its `proof` manifest, and the replay re-binds it at that call's
78
+ own watermark and requires the recorded proof state to match what the log
79
+ implies. A tampered or omitted proof — with a result that still claims it was
80
+ bound — now fails closed with `proof_replay_mismatch` instead of restoring a
81
+ valid certificate. Signing, persistence and replay use the same call argument,
82
+ and the Goal gate consumes only a certificate whose proof still binds.
83
+
84
+ ### Verification
85
+
86
+ - The reviewer's five follow-up counterexamples pass and remain as regression
87
+ cases: pre-v5 delivery, read-only status, the frozen candidate closure, the
88
+ observed registry, and persisted proof tampering.
89
+ - New: `tests/tools/v060-release-chain.test.ts` — the acceptance the review asked
90
+ for. One test drives a real root publish instruction, a real certified
91
+ preparation closure, a real contract adoption, a real tgz and resolution
92
+ through the registered evidence tool, and then the registered action tool
93
+ consulting the RUNTIME's own release gate: it reserves, executes once, leaves
94
+ the attempt in flight, reconciles it through the registered recovery tool, and
95
+ refuses the replay as a consumed ticket. Only the npm executor and the
96
+ registry HTTP client are replaced; the authorization gate, records, producers
97
+ and replay are production code. Two further cases cover the revoked-but-in-
98
+ flight restart recovery and a mismatching readback.
99
+ - The proof suite gained the missing-proof, Goal-consumption and
100
+ accurate-evidence-boundary cases.
101
+
102
+ ### Evidence boundary
103
+
104
+ The release chain test pins the audited host cohort through an explicit
105
+ `RuntimeExecutorSeams.hostLock` acceptance seam, because the host-lock
106
+ migration revalidation reads real filesystem roots. That replaces ONLY the
107
+ host-lock evaluation; the release gate, the reservation and settlement records,
108
+ the evidence producers and the replay are the production ones, and the host lock
109
+ keeps its own suites and native acceptance.
110
+
111
+ ## 0.6.0 repairs after concentrated review (2026-09-14)
112
+
113
+ A concentrated review of the `0dce898` candidate produced fifteen targeted
114
+ counterexamples; all fifteen reproduced a real defect. This section records the
115
+ repair. The stable finding numbers (`F01`–`F08`, `R1`–`R15`) are the reviewer's.
116
+
117
+ ### Fixed
118
+
119
+ - **F01 certificate replay was timing-dependent.** Deliveries were applied after
120
+ the whole log was replayed, so a checkpoint recorded in a later turn was
121
+ re-verified while the delivered answer still looked open, and the v5 rule set
122
+ was applied to the whole log rather than from the boundary onwards. Delivery
123
+ is now applied at the watermark of the turn that produced it and the rule mode
124
+ switches at the boundary event, which makes a projection equal to the
125
+ projection of its own prefix. Certificate comparison is also field-semantic
126
+ now: identical certificates replay identically regardless of JSON property
127
+ order, while an extra, missing, or tampered field still fails.
128
+ - **F02 delivery accepted late and non-final answers.** The final answer must
129
+ appear before the turn's own `turn/end`, must sit in the highest step the host
130
+ actually entered, and the turn must have exactly one completed end and a
131
+ recorded start. Late text, an intermediate step, a repeated or abnormal end,
132
+ and an aborted turn all deliver nothing.
133
+ - **F03 the switch test ignored descendants, and an item reference crashed.**
134
+ The handover test now uses the same closure as the certificate, so a parent
135
+ with a pending delegated child is not treated as finished, and the item-ID
136
+ pattern is a global capture that distinguishes live lineage references from
137
+ unknown or historical IDs.
138
+ - **F04 release identity was not really bound.** A candidate now has separate,
139
+ named identities — commit, ref, repository, package, version, artifact
140
+ SHA-256, npm SRI, registry — and each is compared with its own observed value
141
+ read from a trusted producer (the exact tgz bytes and the local repository),
142
+ never with a model-supplied string. Readiness and closure references must
143
+ resolve to real certified facts, the resolved target must be the artifact the
144
+ contract names, and a contract that names no artifact digest is refused
145
+ outright so omitting one cannot be a bypass. A registry readback that names
146
+ different bytes is not a settlement.
147
+ - **F05 an unknown effect could be re-sent, and a late readback was discarded.**
148
+ Outcomes are distinguished: `not_effected` is a proven pre-effect refusal and
149
+ releases the one-shot lock, while `failed`/`unknown`/`unconfirmed` keep it and
150
+ refuse a re-send. Settlements are reconciled rather than de-duplicated, so a
151
+ trusted readback settles an earlier unconfirmed attempt, and a settled release
152
+ is never downgraded. Damaged release state now blocks release operations
153
+ (`release_state_damaged`) without touching ordinary work.
154
+ - **F06 adoption reported an error and revocation did not exist.** The public
155
+ command validates and reports exactly what the durable root command adopts,
156
+ and `/context-guard release revoke <contract_id>` records a durable revocation
157
+ that keeps the audit trail, denies the next effect, and still shows an
158
+ in-flight reservation whose readback is owed.
159
+ - **F07 proof could be satisfied about the wrong subject.** Binding now runs the
160
+ whole chain: the item's own frozen subject and scope, the fact's qualification
161
+ under the ordinary evidence rules, the declared source, the declared operation
162
+ for every kind, the order of an input check before the effect, and the real
163
+ coverage set behind a declared scope digest. A manifest and a fact that agree
164
+ with each other but not with the user's obligation are rejected.
165
+ - **F08 the proof entry was not reachable from production.** The v2 binder is now
166
+ wired into `context_guard_checkpoint` (an optional `proof` manifest is bound
167
+ before any certificate and its state is reported), the v2 fixture evaluates
168
+ each release probe at its own point in the log, mints real closure
169
+ certificates, and carries a real read fact for S09, and a dedicated
170
+ production-chain suite drives producer → persisted log → derive → checkpoint →
171
+ replay.
172
+
173
+ ### Scope rulings (coordinator, 2026-09-14)
174
+
175
+ Two scope facts were decided once, and both are recorded as fact rather than as
176
+ a general parity claim:
177
+
178
+ 1. **The v2 shared fixture stays a DSH-authored candidate and cross-language
179
+ parity stays open.** The upstream repository has not frozen a v2
180
+ specification, so there is nothing to mirror. The plan's shared gate is
181
+ therefore recorded as a cross-repository pending item owned by the upstream.
182
+ 2. **The release profile's protectable surface is `npm_publish` only.** The
183
+ `git_tag` and GitHub Release routes are NOT claimed to be blocked by the
184
+ host: the plugin reports them as `release_operation_unrouted` with
185
+ `attribution: scope_reduction`, because building the Guard-owned route is the
186
+ work that would make them protectable. Only a composite runner is reported as
187
+ an opaque host boundary. The coverage table is machine-readable so this
188
+ distinction cannot be lost in prose.
189
+
190
+ The plugin therefore does not claim "C01–C12 core alignment" with Codex Context
191
+ Guard, and it does not claim a complete release coverage surface.
192
+
193
+ ### Verification
194
+
195
+ The reviewer's fifteen counterexamples are kept as
196
+ `tests/domain/review-counterexamples.test.ts` and now pass; the expectations
197
+ that the repair deliberately changed are marked in place with the reason. New
198
+ coverage: `tests/domain/v060-proof-production-chain.test.ts` (the proof entry
199
+ through real tool registration), the rewritten release/migration suite (26
200
+ cases, including a real certified closure and every identity refusal), and the
201
+ extended v2 fixture (S09 proof binding, per-timeline release probes, and the
202
+ scope-attribution table).
203
+
204
+ ## 0.6.0 - 2026-09-14
205
+
206
+ This release makes ordinary DSH work enter, execute, deliver, and resume under
207
+ one set of rules. It also closes the substantive gaps against the shared
208
+ Context Guard semantics. Everything before the new protocol boundary keeps its
209
+ old meaning; nothing is re-read or re-labelled.
210
+
211
+ ### Added
212
+
213
+ - **Answer delivery is tracked separately from execution certification.** A
214
+ question or explanation is closed only by the host's own evidence: an
215
+ `assistant/message` in the turn's final step, with no interrupted marker,
216
+ followed by `turn/end` with `reason.kind: "completed"`. A status summary, a
217
+ draft, an intermediate reply, another turn's answer, a subagent's answer, or
218
+ an aborted turn never closes anything. `answered` means "the answer was
219
+ handed over" — never that it was right, complete, or executed.
220
+ - **Work units with a required-descendant closure.** Tasks are grouped into
221
+ derived units. A delegation-marked instruction opens a child unit whose open
222
+ work is required by the parent's closure, so delegating a sub-task can never
223
+ drop the parent's own work; an ordinary task switch opens a sibling that does
224
+ not block the newer task. A subagent's result is bounded evidence: it is
225
+ recorded and visible, and it never closes a parent obligation.
226
+ - **Ancestor constraints stay in force.** A prohibition or an unsatisfied
227
+ condition the root declared in an earlier unit continues to govern the same
228
+ action and target in a later one, and the certifier refuses those bindings
229
+ before examining evidence.
230
+ - **Proof v2 with a real capability matrix.** Five new proof kinds — input
231
+ asset check, output visual readback, object/URL readback, execution fact, and
232
+ external fact — each bind a current subject, a declared source, and a real
233
+ operation. A successful tool call is only ever an execution fact: a browser
234
+ call that merely returned cannot prove an image was looked at, an input asset
235
+ check must be a prior-state fact, and a delegated subagent result is never a
236
+ proof source. When the installed host exposes no producer, the result is
237
+ `unavailable`, never a silent pass. The old three-kind manifest and its digest
238
+ domain are unchanged and remain readable.
239
+ - **Explicit release tickets.** A release contract is adopted only by an
240
+ explicit root command. Once adopted, each operation spends one reservation,
241
+ written before the effect and settled afterwards from a trusted readback.
242
+ Wrong candidate SHA, ref, artifact digest or version, an expired or
243
+ unevaluable ticket, a consumed ticket, a replay, an operation that is already
244
+ in flight, an unresolved target, and an opaque runner are all refused before
245
+ any effect. A "release" keyword, a loaded Skill, or an installation never
246
+ adopts a contract.
247
+ - **A strict proof tier.** On top of the default `standard` tier, a visual or
248
+ complete-scope verification the user explicitly asked for must be discharged
249
+ by a real readback fact. Strict adds no approval step to ordinary actions, and
250
+ installing never enters the `release` tier.
251
+ - **One diagnosis language.** Every incomplete item now reports one of seven
252
+ classes — parameter missing, source insufficient, condition unmet, producer
253
+ capability unavailable, historical gap, integrity failure, policy boundary —
254
+ next to its exact reason code. `/context-guard migration` reports which rule
255
+ set is in force, which obligations keep their pre-0.6.0 rules, and what a
256
+ rollback requires.
257
+ - **A host-neutral v2 conformance fixture** covering S01–S12 through the real
258
+ derive/delivery/closure/Goal chains. Every expectation is compared against a
259
+ value computed from the events and the production projection alone; the runner
260
+ never reads an expectation to decide an actual result.
261
+
262
+ ### Changed
263
+
264
+ - A document "update" or "modify" is decided by the object, not by the verb:
265
+ a recognized document noun becomes a bounded `modify` the assistant may
266
+ resolve to an exact file inside the captured scope and type, while an
267
+ unrecognized object keeps its honest unresolved reading instead of being
268
+ forced into an action.
269
+ - A trusted answer from the host's own question tool now narrows where a
270
+ bounded file choice may land, and is recorded separately from sandbox
271
+ approvals. Pasted or restated answer text forms nothing.
272
+ - A later root instruction that contains a pending generic obligation verbatim
273
+ supersedes it atomically, keeping both revisions. Explanations, prohibitions
274
+ and waits never delete an obligation by similar wording.
275
+ - `/context-guard status` reports the active policy tier, the reason-class
276
+ histogram, the migration facts, and the release state.
277
+
278
+ ### Fixed
279
+
280
+ - The first step of a session now sees the input persisted in that same step,
281
+ and a failed durability flush reports an explicit unavailability instead of
282
+ serving a stale projection.
283
+ - The v2 conformance runner computes `interpreted`, `closure`, `delivery`,
284
+ `turn_bound` and the correction decision from production state instead of from
285
+ the fixture's own expectations.
286
+ - A malformed release record is reported as a bounded diagnostic and never
287
+ marks the whole session corrupt, so damaged release state cannot block
288
+ unrelated ordinary work.
289
+
290
+ ### Migration and rollback
291
+
292
+ - The 0.6.0 semantics start at the new `Context Guard protocol boundary:
293
+ v5.0.0` notice, written at the first real root-input step of a new session.
294
+ An older binary ignores that notice, so a rollback fails closed instead of
295
+ misreading new records.
296
+ - A session that never wrote the boundary keeps the previous whole-session
297
+ contract, version-1 certificates, and its old digest domains.
298
+ - A session that wrote it keeps pre-boundary obligations under their birth
299
+ rules while new work uses units, delivery and version-2 certificates.
300
+ - Rolling back to 0.5.x requires restoring a 0.5.x state snapshot. Replaying a
301
+ 0.6.0 log with 0.5.x fails closed with `certificate_replay_mismatch`; never
302
+ migrate new-schema data down by hand.
303
+
304
+ ### Not yet established
305
+
306
+ - **Cross-language parity and the canonical mirror are not done.** The
307
+ upstream `codex-context-guard` repository has not landed a frozen v2 fixture,
308
+ so the v2 file here is explicitly a DSH-authored *candidate*
309
+ (`2.0.0-candidate.1`, `status: "dsh-candidate"`). `UPSTREAM_PIN.json` still
310
+ pins the unchanged v1 mirrors and is not refreshed by this release.
311
+ - The `release` tier protects only surfaces Guard itself routes. Publishing an
312
+ npm artifact through the Guard-owned action tool is protected; `git tag`, the
313
+ GitHub Release operations, and any composite runner have no interception
314
+ point in this host and are refused before effect rather than pretended to be
315
+ covered. A trusted in-process caller that bypasses Guard entirely is a host
316
+ trust boundary, documented rather than denied.
317
+ - After a publish, the settlement stays `unconfirmed` unless the registry
318
+ readback producer answers; an unconfirmed operation is never re-sent.
319
+ - Deterministic tests, CI, native macOS/Windows acceptance, publication and
320
+ installation are separate evidence scopes. This release records source and
321
+ deterministic evidence; native acceptance and publication follow separately.
322
+
323
+ ## 0.5.3 - 2026-09-14
324
+
325
+ ### Fixed
326
+
327
+ - Preparation succeeds when the host capability check has no reason code. Real tool-registry regressions cover the previously invalid nested optional field.
328
+ - Git preparation lists the required inputs and call sequence. Missing evidence inputs identify their exact fields; producer-computed Git identities are no longer presented as missing user targets. Execution and certification checks remain unchanged.
329
+
330
+ ### Planned
331
+
332
+ - Track answer delivery separately from execution certification. The design and remaining semantic coverage are recorded in [next-version repair notes](docs/NEXT_VERSION_REPAIR_NOTES.md); question closure is not changed by this patch.
333
+
5
334
  ## 0.5.2 - 2026-09-11
6
335
 
7
336
  ### Changed
@@ -2,6 +2,119 @@
2
2
 
3
3
  本项目的重要变化记录在这里。项目仍处于 1.0 之前;版本号跟踪插件生命周期,不代表 API 已稳定。
4
4
 
5
+ ## 0.6.0 定向复核后的第三轮修复(2026-09-14)
6
+
7
+ 针对 `fcc3813` 定向复核的两项发现,均已修复。
8
+
9
+ - **采用之后签发的证书不再能追认该次采用。** 闭包检查只比较证书 revision 与采用时冻结的 revision,而后续日志条目可以满足它:先采用一个引用了尚不存在证书的契约,事后再产生那张证书,会被放行。现在采用在**采用水位**解析并冻结闭包证书的**身份**(certification digest、epoch、revision),门要求必须正是那一张;无法解析的引用被记为未解析,而不是留给未来条目补齐。后续发布义务仍不会使冻结的候选闭包失效。冻结证书还必须匹配采用时的候选 revision;采用前已经过期的证书会被拒绝。
10
+ - **无效的采用输入不再毒化有效契约。** 根命令 `/context-guard release adopt` 载荷畸形时被当作损坏的持久状态,一次笔误即永久阻断后续所有发布。用户手输的根命令错误属于用法诊断;只有**无法读取的持久**预约/结算/契约记录才标记发布状态损坏。畸形的 plugin notice 记录仍 fail-closed。
11
+
12
+ 新增回归:采用后签发 → 拒绝(投影仍 valid);采用时已存在的证书按身份冻结,且后续新增义务不会使其失效;无效/错字段 adopt 输入不影响有效契约可用。
13
+
14
+ ## 0.6.0 跟进复核后的第二轮修复(2026-09-14)
15
+
16
+ 对修复提交的跟进复核在新接线中发现 5 个残留缺陷,全部复现并已修复。复核者的反例按归属保留为常驻回归用例。
17
+
18
+ ### 修复
19
+
20
+ - **追加 v5 边界不再回答 v5 之前的问题。** 交付此前只受自身 turn 水位约束;在 v4 日志末尾追加边界,会让旧 turn 的回答追溯性关闭旧规则下仍开放的义务。现在只有 turn 在边界**之后**结束的交付才算数,且只有边界之后捕获的义务才可能被交付关闭。
21
+ - **真实发布生产者补齐合同声明的全部身份。** 可信读取器现在从规范化后的 resolution 填充 registry(此前完全缺失,凡声明 registry 的合同都无法被授权);ref 改由运行时依据**已采用契约**用审计过的 git 可执行程序解析——这是一条闭合且可达的路径,而不是发布 manifest schema 会拒绝的 command-manifest 字段。解析出的提交与制品内嵌 `gitHead` 不一致时拒绝。
22
+ - **新的发布指令不再使它自己需要的证书失效。** 闭包检查原本要求**当前**合同 revision,因此捕获发布义务会使发布即将使用的证书失效,而"先签后发"又要求发布已经完成。现在契约在采用时**冻结候选范围 revision**,并要求闭包证书正是认证该 revision 的那一张。后续义务不会为已变化的候选重新背书,采用之后签发的证书仍被拒绝。
23
+ - **只读发布查询不再毒化发布状态。** `release status`(以及省略动词)是只读命令;未知动词只是用法诊断。只有**无法读取的持久记录**才标记发布状态损坏,因此一次普通查询不再不可逆地阻断后续所有发布。
24
+ - **新增可调用的可信恢复入口。** `context_guard_release` 读取发布状态;`reconcile` 通过与发布路径相同的审计 registry 适配器读取外部身份,并且只在回读指向合同(或预约记录中的 SRI)所冻结的字节时才结算。它绝不重发发布,且在重启后、以及对**已撤销但仍在执行中**的尝试都可用——撤销收回的是后续授权,而不是对可能已发生效果的核对义务。仅冻结字节 SHA-256 的合同仍可被核对,并且仍能**检测**回读不一致。
25
+ - **递交的证明现在属于持久合同。** checkpoint 调用会记录其 `proof` manifest,重放在该调用自身水位处重新绑定,并要求记录中的证明状态与日志蕴含的一致。被篡改或被省略、而结果仍声称已绑定的证明,现在以 `proof_replay_mismatch` fail-closed,而不是恢复出一张有效证书。签发、落盘与重放使用同一份调用参数,Goal 门也只消费证明仍能绑定的证书。
26
+
27
+ ### 验证
28
+
29
+ - 复核者的 5 个跟进反例全部通过,并按归属保留为回归用例:pre-v5 交付、只读 status、冻结的候选闭包、观测到的 registry、持久证明篡改。
30
+ - 新增 `tests/tools/v060-release-chain.test.ts`——复核要求的验收:同一个测试串起真实 root 发布指令、真实已认证准备闭包、真实契约采用、经注册取证工具产生的真实 tgz 与 resolution,随后由注册的动作工具调用**运行时自身的发布门**:写入预约、执行一次、保持 in-flight、经注册恢复工具结算,并把重放作为已消费票据拒绝。只替换 npm 执行器与 registry HTTP 客户端;授权门、记录、生产者与重放都是生产代码。另有两例覆盖"已撤销但在执行中"的重启恢复与回读不一致。
31
+ - 证明套件新增遗漏证明、Goal 消费,以及准确的证据边界说明。
32
+
33
+ ### 证据边界
34
+
35
+ 发布链路测试通过显式的 `RuntimeExecutorSeams.hostLock` 验收接缝固定审计队列,因为宿主锁迁移复核会读取真实文件系统根。该接缝**只**替换宿主锁求值;发布门、预约与结算记录、证据生产者与重放仍是生产代码,宿主锁也有自己的套件与原生验收。
36
+
37
+ ## 0.6.0 集中复核后的修复(2026-09-14)
38
+
39
+ 针对 `0dce898` 候选的集中复核给出 15 个定向反例,15 个全部复现出真实缺陷。本节记录修复。编号(`F01`–`F08`、`R1`–`R15`)沿用复核者原编号。
40
+
41
+ ### 修复
42
+
43
+ - **F01 证书重放依赖时间点。** 交付原本在整个日志重放后统一应用,因此后续 turn 记录下来的证书在重放时,已交付的回答仍显示为未决;v5 规则也按整段日志生效,而不是从边界开始。现在交付在其所属 turn 的结束水位处应用,规则档在边界事件处切换,投影因此等于自身前缀的投影。证书比较改为按字段语义:字段顺序不同的同一证书重放结果一致,而多字段、少字段或被篡改仍然失败。
44
+ - **F02 交付接纳迟到与中间回答。** 最终回答必须出现在该 turn 自己的 `turn/end` 之前、位于宿主实际进入的最高 step,且该 turn 只能有一个 completed 结束并有 start 记录。迟到文本、中间 step、重复或异常结束、被中止的 turn 都不产生交付。
45
+ - **F03 切换判断漏掉后代,条目引用会抛异常。** 交接判断现在使用与证书相同的闭包:父项自身完成但委派子项仍未完成时不再被当作已完成;条目 ID 正则改为全局捕获,并区分仍在世系中的活条目与不存在或历史条目。
46
+ - **F04 发布身份未真正绑定。** 候选现在拆成独立命名的身份——commit、ref、repository、包名、版本、制品 SHA-256、npm SRI、registry——每一项都与可信生产者(精确 tgz 字节与本地仓库)实际观测到的同名值比较,绝不与模型提供的字符串比较。readiness/closure 引用必须解析到真实的已认证事实;解析出的目标必须就是契约所指制品;未绑定任何制品摘要的契约直接被拒绝,因此"省略摘要"不构成绕过。回读若指向不同字节,不构成结算。
47
+ - **F05 未知效果可能重发,迟到的回读被丢弃。** 结果状态被区分:`not_effected` 是效果前被证实的拒绝,释放一次性锁;`failed`/`unknown`/`unconfirmed` 保留锁并拒绝重发。结算改为"归并"而非按 callId 去重,因此可信回读可以把此前的 unconfirmed 尝试结算为 settled,而 settled 永不被降级。损坏的发布状态现在只封锁发布操作(`release_state_damaged`),不影响普通工作。
48
+ - **F06 采用命令报错,撤销不存在。** 公开命令现在校验并如实报告持久根命令实际采用的内容;`/context-guard release revoke <contract_id>` 记录持久撤销,保留审计、拒绝下一次效果,并继续显示仍欠回读的 in-flight 预约。
49
+ - **F07 证明可能被错误主体满足。** 绑定改为完整链路:条目自身冻结的主体与范围、事实按普通证据资格规则校验、声明的来源、每一类声明的操作、输入检查相对效果的先后、以及范围摘要背后真实的覆盖集合。manifest 与事实互相自洽但与用户义务不符时一律拒绝。
50
+ - **F08 证明入口未接入生产。** v2 绑定器已接入 `context_guard_checkpoint`(可选 `proof` manifest 在签发任何证书之前绑定并报告状态);v2 fixture 在每个 release 探针自己的时间点求值、铸造真实闭包证书、为 S09 携带真实读事实;并新增专职生产链路测试:producer → 持久日志 → derive → checkpoint → 重放。
51
+
52
+ ### 范围裁定(协调者,2026-09-14)
53
+
54
+ 两项范围事实一次裁定,均按事实记录,而不是作为整体 parity 声明:
55
+
56
+ 1. **v2 共享 fixture 保持 DSH 产出的候选身份,跨语言 parity 保持待办。** 上游尚未冻结 v2 规范,因此没有可镜像的对象;计划中的共享门因此记录为归上游所有的跨仓库待办项。
57
+ 2. **发布档可保护表面仅 `npm_publish`。** `git_tag` 与 GitHub Release 路由**不**声称被宿主阻断:插件把它们报告为 `release_operation_unrouted` 且 `attribution: scope_reduction`,因为补建 Guard 自有路由才是让它们可保护的工作。只有复合 runner 报告为不透明宿主边界。覆盖面表是机器可读的,这一区分不会在文字中丢失。
58
+
59
+ 因此本插件不宣称与 Codex Context Guard "C01–C12 核心对齐",也不宣称完整的发布覆盖面。
60
+
61
+ ### 验证
62
+
63
+ 复核者的 15 个反例保留为 `tests/domain/review-counterexamples.test.ts`,现已全部通过;本次修复刻意改动的期望在原位标注了原因。新增覆盖:`tests/domain/v060-proof-production-chain.test.ts`(经真实工具注册的证明入口)、重写的发布/迁移套件(26 例,含真实已认证闭包与逐项身份拒绝)、以及扩展后的 v2 fixture(S09 证明绑定、逐时间点 release 探针、范围归因表)。
64
+
65
+ ## 0.6.0 - 2026-09-14
66
+
67
+ 本版让普通 DSH 任务在进入、执行、交付与恢复时遵循同一套规则,并补齐与共享 Context Guard 语义之间的实质差距。新协议边界之前的一切保持原有含义,既不重解释也不重新贴标签。
68
+
69
+ ### 新增
70
+
71
+ - **回答交付与执行认证分开记录。** 问答或讲解只由宿主的自身事实关闭:同一 turn 最大 step 的 `assistant/message`、无 interrupted 标记,且其后存在 `reason.kind: "completed"` 的 `turn/end`。状态汇报、草稿、中间回复、其它 turn 的回答、子代理回答和中止的 turn 都不会关闭任何条目。`answered` 只表示"回答已交付",不表示正确、完整或已执行。
72
+ - **工作单元与必需后代闭包。** 任务被归入派生的单元。带委派标记的指令会开启一个子单元,其未完成义务进入父单元闭包,因此委派子任务绝不会丢掉父任务自身的工作;普通任务切换开启的是同级单元,不阻塞更新的任务。子代理结果是**有界证据**:记录并可见,但永远不能关闭父项。
73
+ - **祖先约束持续生效。** 根用户在前一单元声明的禁止项或未满足条件,对后续单元中同一动作与目标的义务继续生效;认证器在检查证据之前就拒绝这类绑定。
74
+ - **证明 v2 与真实能力矩阵。** 新增输入资产检查、生成结果视觉回读、对象/URL 回读、执行事实、外部事实五类证明,每类都绑定当前主体、声明的来源和真实操作。工具调用成功只构成执行事实:一次仅仅返回的浏览器调用不能证明看过图,输入资产检查必须是前置状态事实,子代理结果不能作为证明来源。已安装宿主没有对应生产者时结论是 `unavailable`,绝不静默通过。原有三类 manifest 及其摘要域不变,仍可读取。
75
+ - **显式发布票据。** 发布契约只能由用户显式根命令采用。采用后每个操作消耗一次预约记录:效果前写入,效果后依据可信回读结算。错候选 SHA、错 ref、错制品摘要或版本、过期或无法评估的有效期、已消费票据、重放、已在执行中的操作、未解析目标和不透明 runner 都在任何副作用之前被拒绝。"release" 关键词、加载 Skill 或安装不会采用契约。
76
+ - **strict 证明档位。** 在默认 `standard` 之上,用户明确要求的视觉或完整范围验证必须由真实回读事实兑现。strict 不为普通动作新增审批,安装也绝不隐式进入 `release` 档。
77
+ - **统一诊断语言。** 每个未完成条目在精确原因码之外,还会给出七类标签之一:参数缺失、来源不足、条件未满足、生产者能力缺失、历史缺口、完整性失败、策略边界。`/context-guard migration` 报告当前生效的规则集、仍按 0.6.0 之前规则保留的义务,以及回滚所需的动作。
78
+ - **宿主中立的 v2 一致性 fixture**,覆盖 S01–S12,且全部经过真实 derive/交付/闭包/Goal 链路。每条期望都只与"由事件和生产投影独立算出"的实际值比较;runner 绝不读取期望来决定实际值。
79
+
80
+ ### 变化
81
+
82
+ - 文档"更新/修改"由对象决定,而不由动词决定:可识别的文档名词变成 `modify`,助手可在捕获的范围与类型内解析到具体文件;无法识别的对象保持诚实的未决读法,而不是被强行归为某个动作。
83
+ - 宿主自身问答工具返回的可信答案现在会收窄有界文件选择的落点,并与沙箱审批分开记录。转贴或复述的回答文本不构成任何东西。
84
+ - 后续根指令逐字包含某条未决通用义务时,会原子替换它并保留新旧 revision;解释、禁止和等待绝不因相似措辞删除义务。
85
+ - `/context-guard status` 报告当前策略档、原因类直方图、迁移事实与发布状态。
86
+
87
+ ### 修复
88
+
89
+ - 会话首步现在能看到同步持久化的输入;flush 失败会明确报告不可用,而不是返回陈旧投影。
90
+ - v2 一致性 runner 的 `interpreted`、`closure`、`delivery`、`turn_bound` 与纠正判断改为从生产状态计算,不再取自 fixture 自身的期望。
91
+ - 损坏的发布记录只产生一条有界诊断,不再把整个会话标为 corrupt,因此损坏的发布状态不会阻塞无关的普通工作。
92
+
93
+ ### 迁移与回滚
94
+
95
+ - 0.6.0 语义从新的 `Context Guard protocol boundary: v5.0.0` notice 开始,写在新会话首个真实根输入步之前。旧二进制会忽略该 notice,因此回滚方向是 fail-closed,而不是误读新记录。
96
+ - 从未写过该边界的会话继续沿用整会话契约、版本 1 证书与旧摘要域。
97
+ - 写过该边界的会话中,边界之前的义务保留出生规则,新工作使用工作单元、交付与版本 2 证书。
98
+ - 回滚到 0.5.x 必须恢复 0.5.x 的状态快照。用 0.5.x 重放 0.6.0 日志会以 `certificate_replay_mismatch` fail-closed;切勿手工把新 schema 数据降级。
99
+
100
+ ### 尚未成立
101
+
102
+ - **跨语言 parity 与正式镜像尚未完成。** 上游 `codex-context-guard` 尚未落地冻结的 v2 fixture,因此本仓库的 v2 文件明确是 DSH 产出的**候选**(`2.0.0-candidate.1`、`status: "dsh-candidate"`)。`UPSTREAM_PIN.json` 仍绑定未变的 v1 镜像,本次发布不刷新它。
103
+ - `release` 档只保护 Guard 自身路由的表面:经 Guard 自有动作工具发布 npm 制品受保护;`git tag`、GitHub Release 各操作和复合 runner 在本宿主没有拦截点,会在效果前拒绝,而不是假装已覆盖。完全绕过 Guard 的可信进程内调用属于宿主信任边界,只能披露,不能否认。
104
+ - 发布后若 registry 回读生产者没有回应,结算保持 `unconfirmed`;未确认的操作绝不重发。
105
+ - 确定性测试、CI、macOS/Windows 原生验收、发布与安装是相互独立的证据范围。本次记录源码与确定性证据;原生验收与发布另行进行。
106
+
107
+ ## 0.5.3 - 2026-09-14
108
+
109
+ ### 修复
110
+
111
+ - 宿主能力检查没有原因码时,准备工具也能正常返回。通过真实工具注册入口覆盖此前非法的嵌套可选字段。
112
+ - Git 准备结果列出所需参数与调用顺序,取证缺参时指出具体字段;不再把生产者读取的 Git 身份列为用户缺少的目标。执行与认证校验保持原有要求。
113
+
114
+ ### 后续计划
115
+
116
+ - 将回答交付与执行认证分开记录。设计及剩余语义覆盖见[下版修复记录](docs/NEXT_VERSION_REPAIR_NOTES.md);本次补丁未改变问答关闭规则。
117
+
5
118
  ## 0.5.2 - 2026-09-11
6
119
 
7
120
  ### 变化
package/README.md CHANGED
@@ -8,10 +8,10 @@ An add-on for DeepSeek Harness (DSH) that keeps a task's requirements and checks
8
8
 
9
9
  ## Quick start
10
10
 
11
- Install the published **0.5.2** release into the DSH Web environment:
11
+ Install the published **0.6.0** release into the DSH Web environment:
12
12
 
13
13
  ```sh
14
- dsh plugin --profile web add dsh-completion-guard@0.5.2
14
+ dsh plugin --profile web add dsh-completion-guard@0.6.0
15
15
  ```
16
16
 
17
17
  **Upgrade and restart DSH before running the host-lock checks below.** The lock records the package versions and installation directories DSH actually uses. A lock generated before an upgrade describes the old packages and will fail against the new runtime. `inject` writes to `<profile>/cordis.patch.yml`, so back up that file first.
@@ -28,7 +28,7 @@ GUARD_HOST_LOCK="$DSH_PROFILE_ROOT/node_modules/.bin/dsh-completion-guard-host-l
28
28
  dsh --profile web --dump-config | "$GUARD_HOST_LOCK" verify-dump --runtime-root "$DSH_RUNTIME_ROOT" --profile-root "$DSH_PROFILE_ROOT" --dump-config -
29
29
  ```
30
30
 
31
- On Windows, run the same three subcommands through `dsh-completion-guard-host-lock.cmd` in the Web settings directory's `node_modules\.bin` directory and use Windows absolute paths. The preceding 0.5.1 package passed separate macOS and Windows native acceptance on DSH `0.1.5-rc.2`; each 0.5.2 artifact keeps its own acceptance identity in the [acceptance record](docs/LOCAL_ACCEPTANCE.md). Other host versions and artifacts need their own native evidence. Repeat this check after changing DSH, Guard or the profile location; an ordinary market-only update does not require reinjection. The Guard stays unavailable if the active package set is missing, mixed, duplicated, or different from a checked setup.
31
+ On Windows, run the same three subcommands through `dsh-completion-guard-host-lock.cmd` in the Web settings directory's `node_modules\.bin` directory and use Windows absolute paths. The published 0.5.3 package passed separate macOS and Windows native acceptance on DSH `0.1.5-rc.2`; both runs are bound to its exact bytes in the [acceptance record](docs/LOCAL_ACCEPTANCE.md). The 0.6.0 candidate has not yet had its own native or publication run, so treat its source and deterministic evidence as separate from any installed-artifact claim. Other host versions and artifacts need their own native evidence. Repeat this check after changing DSH, Guard or the profile location; an ordinary market-only update does not require reinjection. The Guard stays unavailable if the active package set is missing, mixed, duplicated, or different from a checked setup.
32
32
 
33
33
  Restart DSH Web, open a session, and enable the Guard:
34
34
 
@@ -37,7 +37,7 @@ Restart DSH Web, open a session, and enable the Guard:
37
37
  /context-guard status
38
38
  ```
39
39
 
40
- Activation is opt-in by default. `status` shows whether the Guard is on, its startup phase (`armed` means waiting for your first message), and how many checks remain. `off` stops protection for the current session without deleting its history. `clear` closes the current checklist while keeping prohibitions. `diagnose` explains why a completion check passed or failed.
40
+ Activation is opt-in by default. `status` shows whether the Guard is on, its startup phase (`armed` means waiting for your first message), the active policy tier, how many checks remain, and a summary of why the rest are open. `off` stops protection for the current session without deleting its history. `clear` closes the current checklist while keeping prohibitions. `diagnose` explains why a completion check passed or failed. `migration` reports which rule set the session is under and what an upgrade or rollback would mean. `release` reports the explicit release contract, its coverage, and anything in flight.
41
41
 
42
42
  ## What it protects
43
43
 
@@ -49,7 +49,7 @@ Activation is opt-in by default. `status` shows whether the Guard is on, its sta
49
49
 
50
50
  ## Status and compatibility
51
51
 
52
- Version 0.5.2 supports exactly **DSH `0.1.5-rc.2` or `0.1.5-rc.1`** with Cordis `4.0.2`. These are the latest registered release and the verified minimum. The previous Session API, V2 event vocabulary, and every older host package set remain removed. If you are upgrading from DSH `0.1.2-rc.1`, **start a new session**: Guard does not migrate old logs, proposals or certificates, and it never deletes or reinterprets your old data.
52
+ Version 0.6.0 supports exactly **DSH `0.1.5-rc.2` or `0.1.5-rc.1`** with Cordis `4.0.2`. These are the latest registered release and the verified minimum. The previous Session API, V2 event vocabulary, and every older host package set remain removed. If you are upgrading from DSH `0.1.2-rc.1`, **start a new session**: Guard does not migrate old logs, proposals or certificates, and it never deletes or reinterprets your old data.
53
53
 
54
54
  Package discovery and npm installation now publish the same newest-first exact union, `0.1.5-rc.2 || 0.1.5-rc.1`. Older versions, unregistered stable `0.1.5`, and future versions are not advertised as supported. Every admitted version must still match its complete 33-package DSH core graph; missing, mixed, or unknown graphs fail closed.
55
55
 
@@ -112,6 +112,95 @@ Use `context_guard_rebind` to propose an exact, complete split of the old text.
112
112
 
113
113
  The default `context_guard_checkpoint` call uses `bindings: []` for diagnosis. It shows at most eight current items/constraints and ten evidence rows, within 12 KiB of plugin JSON. `pagination` reports totals and a separate `next_cursor` for each list; the first page is not the whole contract. Use `item_ids` or `evidence_ids` to focus a query, or `evidence_scope: "history"` for the complete evidence history, including rows marked unavailable. Keep the query unchanged when following a cursor; a changed contract or evidence snapshot requires a fresh query. Large rows expose `detail_id`; retrieve chunks with `detail_offset` and return the first response's `snapshot` as `detail_snapshot` on later chunks. All queries remain read-only and never shrink the certification set.
114
114
 
115
+ ## What 0.6.0 changes for ordinary work
116
+
117
+ The following behaviours are what you will actually notice. Everything before
118
+ the new protocol boundary keeps its old meaning; nothing is re-read.
119
+
120
+ **Asking a question no longer leaves a permanent to-do.** A question or an
121
+ explanation is closed by the host's own record: the final assistant message of a
122
+ turn that completed normally. A status summary, a draft, an intermediate reply,
123
+ another turn's answer, a subagent's answer, or an interrupted turn never closes
124
+ it. "Answered" means the answer reached you — it says nothing about whether it
125
+ was correct or whether any work was done.
126
+
127
+ **A document "update" is decided by the object, not the verb.** "Update the
128
+ docs" becomes a bounded modification whose exact file you leave to the
129
+ assistant, inside the directory and file type your instruction captured.
130
+ Something the Guard cannot recognize as a file keeps an honest "I could not
131
+ determine this" state instead of being forced into an action or silently closed.
132
+
133
+ **Answering a question does not complete the rest of the sentence.**
134
+ "Check for updates and also create report.txt" closes the question when the
135
+ answer is delivered and leaves the file creation open until it has its own
136
+ evidence.
137
+
138
+ **Tasks are tracked as units.** Delegating a sub-task to a subagent opens a
139
+ child unit whose open work counts towards the parent, so delegating never drops
140
+ the parent's own work. A subagent's answer is recorded as bounded evidence and
141
+ never closes the parent on its own. A prohibition or a wait you declared earlier
142
+ continues to govern the same action in later tasks.
143
+
144
+ **Corrections replace what they refine.** A later instruction that contains a
145
+ pending obligation verbatim supersedes it atomically and keeps both revisions.
146
+ Explanations, prohibitions and waits never delete an obligation by similar
147
+ wording, and nothing is removed just because a new sentence looks alike.
148
+
149
+ **A trusted answer to the host's own question narrows a target.** When the
150
+ assistant asks you where a file should go and you pick a directory, that answer —
151
+ from the host's own question tool, with its call and result both on record —
152
+ narrows where the file may land. Text pasted into the conversation does not.
153
+ Sandbox approvals are recorded separately and never grant a target.
154
+
155
+ ## Policy tiers
156
+
157
+ Three tiers change how much proof is required at completion. They are separate
158
+ from the `opt-in` / `always` activation modes, and installing never enters the
159
+ release tier.
160
+
161
+ | Tier | What it demands |
162
+ | --- | --- |
163
+ | `standard` (default) | Work must be supported by durable evidence; ordinary tools are not gated behind extra Guard approval. |
164
+ | `strict` | On top of standard, a visual or complete-scope verification you explicitly asked for must be discharged by a real readback fact, not by a tool that merely succeeded. |
165
+ | `release` | Only an explicitly adopted release contract authorizes a release operation. Until you adopt one, release operations are refused rather than performed under the standard rules. |
166
+
167
+ Set the tier in the same `cordis.patch.yml` entry as `activation`:
168
+
169
+ ```yaml
170
+ - id: context-guard
171
+ name: dsh-completion-guard
172
+ config:
173
+ activation: always
174
+ policy: strict
175
+ ```
176
+
177
+ ### Explicit release contracts
178
+
179
+ A release is never implicit. A "release" keyword in a message, a loaded Skill,
180
+ or an installation does not adopt anything; only this command does:
181
+
182
+ ```text
183
+ /context-guard release adopt {"operations":["npm_publish"],"candidate":{"ref":"refs/heads/main","fullSha40":"<40 hex characters>","version":"0.6.0","artifactDigest":"<64 hex characters>"}}
184
+ ```
185
+
186
+ After adoption, `/context-guard release` reports the contract, its candidate, its
187
+ per-operation coverage, what has been consumed, and anything still in flight.
188
+ Each operation spends exactly one reservation, written before the effect and
189
+ settled afterwards from a trusted readback. A wrong candidate SHA, ref, artifact
190
+ digest or version, an expired ticket, a consumed ticket, a retry of a request
191
+ that is still in flight, and an opaque runner are all refused before any effect.
192
+
193
+ **Coverage is stated honestly, and the gap is attributed.** This release
194
+ protects only the surface Guard itself routes: publishing an npm artifact
195
+ through `context_guard_action`. `git tag` and the GitHub Release operations have
196
+ no Guard-owned route yet, so a contract requiring them is refused before any
197
+ effect and reported as `release_operation_unrouted` — a scope reduction this
198
+ release explicitly took, not a claim that the host makes them impossible. A
199
+ composite runner is refused as an opaque host boundary. `/context-guard release`
200
+ prints this table in machine-readable form. A trusted in-process caller that
201
+ bypasses the Guard entirely is a host trust boundary; the plugin reports what it
202
+ can see and does not claim to stop what it cannot see.
203
+
115
204
  ## Boundaries
116
205
 
117
206
  Context Guard certifies completion; DSH still owns Goal, Todo, Compaction, continuation, permissions, and tool execution. This plugin is not a security sandbox, semantic proof system, token-pruning tool, or replacement for those DSH facilities.
@@ -124,7 +213,9 @@ This project began as a DSH port of deterministic behavior from [`GreenLv/codex-
124
213
 
125
214
  Version 0.4.0 was deliberately aligned with the shared evidence rules in Codex Context Guard 0.10.0: proof must belong to work that is still open and must show the operation, target, and result the user actually requested. This is a limited behavior-level alignment, not a claim that the two products have the same features.
126
215
 
127
- Codex Context Guard 0.11.0 was released afterward. DSH 0.4.0 already has native checks for exact mutation targets, typed waits, and quoted text, but it does not yet include the full 0.11.0 authorization-ticket, work-unit, supersession, or incident-benchmark changes. The plain-language comparison and dated delta ledger are in [`docs/SEMANTIC_COMPATIBILITY.md`](docs/SEMANTIC_COMPATIBILITY.md).
216
+ The 0.6.0 line implements the C01–C12 shared contract that pairs this release with a planned Codex Context Guard 0.14.0: source spans and coverage, one interpretation view, trusted answer delivery, work units with a required-descendant closure, per-action conditions, responsibility tiers, bounded target resolution, atomic clarification, the proof capability matrix, explicit release tickets, fresh projections, and unified migration diagnostics. The plain-language comparison, the implementation status per contract, and the dated delta ledger are in [`docs/SEMANTIC_COMPATIBILITY.md`](docs/SEMANTIC_COMPATIBILITY.md).
217
+
218
+ Two shared artifacts are deliberately incomplete, and calling them done would be false. The upstream repository had not landed a frozen v2 conformance fixture at the time of this release, so the v2 fixture here is a **DSH-authored candidate** rather than a byte mirror, and `UPSTREAM_PIN.json` still pins only the unchanged v1 fixtures. Cross-language parity and the canonical mirror therefore remain open; the delta ledger records them as such.
128
219
 
129
220
  The two repositories serve different runtimes:
130
221