dsh-completion-guard 0.8.4 → 0.10.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.
@@ -0,0 +1,171 @@
1
+ # Session activation migration / 会话启用模式迁移
2
+
3
+ This guide covers upgrades to **0.10.0**, including upgrades from **0.9.0**. Since 0.9.0, `always` has been the default for **new unseeded root sessions**. A write-once private binding preserves each old session's pre-upgrade effective mode. Mode is independent of `standard` policy, execution/publication authority and completion certificates. Empty old sessions belong in the inventory too. Recorded off/on continues to control enablement; neither configuration nor adoption re-signs history.
4
+
5
+ 本指南用于升级到 **0.10.0**,包括从 **0.9.0** 升级。自 0.9.0 起,**新建无继承根会话**的默认模式为 `always`,旧会话通过不可覆盖私有绑定保留升级前有效模式。模式独立于 `standard` 策略、执行与发布权限及完成证书。旧空会话也必须清点,已记录的 off/on 继续控制启用状态;配置及 adoption 都不重签历史。
6
+
7
+ ## Prepare before changing the installed version / 升级前准备
8
+
9
+ Stop the relevant Web, Headless and Desktop session writers. Preserve their installed old package and effective configuration readback before upgrade. The new toolkit may run from an independently prepared candidate directory while the old Guard remains installed. Do not read the upgraded default and label it an old mode. Do not include credential values or session bodies in the readback.
10
+
11
+ 先停止相关 Web、Headless、Desktop 会话写者,在升级前保留旧安装包身份及有效配置回读。可从独立准备的候选工具目录运行新工具,此时旧 Guard 仍安装在原位。不能把升级后的新缺省当作旧模式,不得在回读中包含凭据或会话正文。
12
+
13
+ Prepare an operator-owned JSON file in the following format. `previousPackage.sha256` identifies the preserved old package bytes; `sourceSha256` hashes the relevant sanitized, pre-upgrade source readback. Cohort names describe that verified source. If all relevant cohorts have one known mode, that uniform mode can cover the inventory. If modes differ, each session needs an explicit `sessionIds` mapping based on verified old provenance; absent or contradictory mappings stay `pending`. Profile paths, dates, event counts and `on` markers cannot supply that mapping. A checksum checks integrity; it is not an issuer signature or proof that an operator's asserted mapping is correct. Use the verified old mode in the example; package version alone does not establish whether it is `opt-in` or `always`.
14
+
15
+ 准备以下格式的操作者 JSON 文件。包摘要指向保留的旧包字节,来源摘要指向相关的脱敏升级前回读。来源组名描述已核验来源。所有相关来源模式一致时可覆盖库存;模式不同则必须提供基于已核验旧来源的 `sessionIds` 映射,缺失或冲突保持 `pending`。不能用 profile 路径、日期、事件数量或 on 标记替代来源映射。摘要核验完整性,不是发行签名,也不能证明操作者的映射断言正确。示例中的 `opt-in` 应按已核验的旧模式填写,不能仅按包版本判断。
16
+
17
+ ```json
18
+ {
19
+ "schema": "dsh-activation-prior-modes/v1",
20
+ "previousPackage": {
21
+ "name": "dsh-completion-guard",
22
+ "version": "0.9.0",
23
+ "sha256": "<64 lowercase hex characters>"
24
+ },
25
+ "sourceSha256": "<64 lowercase hex characters>",
26
+ "cohorts": [{ "name": "verified-old-web", "mode": "opt-in" }]
27
+ }
28
+ ```
29
+
30
+ The 0.10.0 toolkit accepts verified prior-mode records for predecessor versions `0.0.x`–`0.9.x`, including `0.9.0`. It refuses `0.10.0` as a prior package.
31
+
32
+ 0.10.0 工具接受前驱版本 `0.0.x`–`0.9.x` 的已核验旧模式来源,包括 `0.9.0`;不能把 `0.10.0` 本身作为旧包。
33
+
34
+ ## Official old-format refusals and an explicit readable subset / 官方旧格式拒绝与显式可读子集
35
+
36
+ The official persistence reader may reject an older session with `SessionFormatUnsupportedError`. This names a host format-support boundary; it does not by itself prove corruption or a Guard regression. Do not delete, rewrite, rename or repair the raw log to force acceptance. Preserve it, the old package and its verified effective-mode source. `inventory` can record this **specific official open refusal** as pending. Other failures (corruption, permissions, missing files, unknown errors, list/stat failure or drift) abort; they are not automatically skipped. Default `inspect/adopt/verify` still requires the whole inventory to be readable.
37
+
38
+ 官方 persistence 可能以 `SessionFormatUnsupportedError` 拒绝旧格式会话。这说明宿主格式支持的边界,本身不证明日志损坏或 Guard 回归。不要删除、重写、改名或“修复”原日志来绕过拒绝;保留原日志、旧包和已核验的旧有效模式来源。inventory 只将这类**官方 open 拒绝**记为 pending;损坏、权限、丢失、未知异常、list/stat 失败或库存变化均中止,不会被自动跳过。默认 inspect/adopt/verify 仍要求整库可读。
39
+
40
+ Suppose an inventory contains N sessions, of which M are readable. First freeze the full report, then review the local `rows` and write a JSON array containing only the readable IDs you explicitly choose, for example `["chosen-a", "chosen-b"]`. The example IDs are placeholders; use exact report IDs. No automatic “all readable” selection is made. The report and manifests contain private IDs and metadata hashes, but no event bodies or credentials; keep them local and owner-only. Run this phase before replacing either the host or Guard, with writers stopped. You can copy the preserved logs into a separate, access-controlled workspace for later host-format diagnosis; never change the authoritative originals or share their contents.
41
+
42
+ 假设库存共 N 个会话,其中 M 个可读。先冻结全库报告,查看本地 rows,再将明确选中的可读 ID 写入 JSON 数组,如 `["chosen-a", "chosen-b"]`。示例 ID 是占位符,必须换成报告中的精确 ID;工具不会自动选择“所有可读”。报告与清单含私有 ID 和元数据摘要,不含正文或凭据,应仅在本地以所有者权限保存。替换宿主或 Guard 前、写者停止时完成这一阶段。后续宿主格式诊断可使用另行受控保管的日志副本,不能改动权威原件或外传正文。
43
+
44
+ ```sh
45
+ # POSIX shell; use distinct unused output paths. Match compression to the real config.
46
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs inventory \
47
+ --runtime-anchor /path/to/runtime/package.json \
48
+ --persistence-root /path/to/active-session-storage \
49
+ --output /path/to/inventory.json
50
+
51
+ # chosen-ids.json is an operator-reviewed JSON array of exact readable IDs.
52
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs select \
53
+ --inventory /path/to/inventory.json \
54
+ --include-file /path/to/chosen-ids.json \
55
+ --output /path/to/selection.json
56
+
57
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs inspect \
58
+ --runtime-anchor /path/to/runtime/package.json \
59
+ --persistence-root /path/to/active-session-storage \
60
+ --selection /path/to/selection.json \
61
+ --prior-modes /path/to/old-mode-source.json \
62
+ --output /path/to/selected-receipt.json
63
+
64
+ # After replacement, before upgraded host startup:
65
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs adopt \
66
+ --runtime-anchor /path/to/runtime/package.json \
67
+ --persistence-root /path/to/active-session-storage \
68
+ --selection /path/to/selection.json \
69
+ --receipt /path/to/selected-receipt.json \
70
+ --dsh-home /path/to/actual-dsh-home
71
+
72
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs verify \
73
+ --runtime-anchor /path/to/runtime/package.json \
74
+ --persistence-root /path/to/active-session-storage \
75
+ --selection /path/to/selection.json \
76
+ --receipt /path/to/selected-receipt.json \
77
+ --dsh-home /path/to/actual-dsh-home
78
+ ```
79
+
80
+ `inventory_scanned` reports total/readable/unsupported counts and creates the frozen report. `selection_ready` creates the explicit scope manifest; empty, duplicate, unknown or unsupported IDs refuse. Selected `inspect` reports `ready` only when all included identities have verified old sources, then writes a receipt. Mixed-mode sources need exact per-session mappings. Source mappings may cover excluded IDs too, but exclusions never acquire a mode binding. Never infer a mode from format, date, path, event count or a new default.
81
+
82
+ inventory_scanned 表示已生成全库报告及总数/可读/拒绝数量;selection_ready 表示已冻结显式范围,空选、重复、未知或被拒绝 ID 都会拒绝。子集 inspect 仅在所有包含会话的旧来源均可核验时返回 ready 并创建收据。混合模式需逐会话映射;旧来源映射可以包含排除项,但排除项不会被写入模式绑定。不得按格式、日期、路径、事件数或新默认值猜模式。
83
+
84
+ Every selected `inspect/adopt/verify` rescans the **whole** inventory and checks all listed header/revision hashes, readable birth identities and refusal statuses against the selection. Added, removed, replaced or changed rows—including excluded ones—or changed readability invalidate the scope before adoption. Supplying the same manifest is mandatory on all three commands; full and selected receipts cannot be substituted. An integrity digest binds the asserted inputs; it is not authority or proof that an old-source assertion is true. A host upgrade that changes the scan requires a fresh report and reviewed scope before proceeding.
85
+
86
+ 每次子集 inspect/adopt/verify 都重扫**全库**,核对全部 list header/revision 摘要、可读出生身份及拒绝状态。新增、删除、替换、变化(包括排除项)或可读性变化,会在 adoption 前使范围失效。三条命令均须携带同一 selection,不能混用全库与子集收据。摘要只绑定断言输入,不提供权限,也不能证明旧来源断言正确。宿主升级若改变清点结果,必须重新生成报告并审核范围后再继续。
87
+
88
+ `selected_complete` means that **only the receipt-selected rows** completed or verified. `selected_partial` means one or more of those rows refused. Both report `scope: receipt_selected`, `wholeInventoryStatus: not_claimed`, and a pending list for all exclusions (`session_format_unsupported` or `not_selected`). Pending remains visible even if the command exits zero. Repeat adoption for the same unchanged scope: completed rows are byte-identical no-ops; missing rows can continue, conflicts remain refused and intact. `verify` never writes. Preserve all existing reports and receipts; `activation_output_exists` requires a new output name, not deleting the old evidence. Drift requires new inventory/selection/inspect, not editing a digest or reusing a stale scope. The older full-inventory path below remains available without `--selection`.
89
+
90
+ selected_complete **仅表示收据选中行**完成或核验通过;selected_partial 表示其中至少一行拒绝。两者均输出 scope: receipt_selected、wholeInventoryStatus: not_claimed,以及所有排除项的 pending 清单(session_format_unsupported 或 not_selected)。命令即使零退出,也不能隐藏 pending 或称为整库完成。相同且未变的范围可重复 adopt:完成行字节不变,缺失行可继续,冲突拒绝且原状保留;verify 从不写入。保留旧报告和收据;activation_output_exists 应换一个输出文件名,而不是删除证据。库存变化后重新 inventory/selection/inspect,不能改摘要或复用过期范围。下方不带 --selection 的原整库路径仍可用。
91
+
92
+ When a later official host supports the pending format, use its **read-only** persistence reader on the preserved log, generate a fresh inventory, compare actual birth identity and re-establish the preserved old-mode source. Confirm that the existing user authorization covers the newly included scope; ask only if it does not. Create a new selection and receipt, then adopt and verify. A previous migration receipt or certificate grants no new migration/publication authority. If the reader still refuses or the source cannot be recovered, retain pending and continue new work in a fresh qualified root session; do not fabricate origin, inherited cut, old mode or receipt. The original history remains available for later support.
93
+
94
+ 以后官方宿主支持这些格式时,用该宿主的**只读** persistence 读取保留日志,生成新库存,核对实际出生身份并重新核验保留的旧模式来源;核对已有用户授权是否覆盖新增范围,仅在未覆盖时补充确认;随后生成新 selection/收据,再 adopt 和 verify。旧收据或证书不授予新迁移或发布权限。仍拒绝或无可恢复来源时保持 pending,可在新的合格根会话继续工作;不能伪造 origin、继承 cut、旧模式或收据。原历史保留以等待后续支持。
95
+
96
+ ### Copyable migration prompts / 可复制迁移提示词
97
+
98
+ > Help me migrate session activation to DSH Completion Guard 0.10.0. Lifecycle constraint: [fill in which writers may be stopped and whether restart is allowed]. Reuse scope, write and lifecycle authorization already supplied in this conversation; ask only for missing or materially changed decisions. First report the current host/persistence/compression settings, preserved predecessor package identity (for example 0.9.0) and sanitized pre-upgrade effective-mode sources. If they cannot be verified, keep affected sessions pending. Do not replace packages, stop/restart processes or write bindings before that lifecycle and mutation authority is established. Run the packaged read-only inventory command; show total/readable/official-format-refused counts and a local pending report. Use my existing explicit selection, or ask me to choose the included scope if none was supplied; do not silently expand it or treat readability alone as authorization. Bind that explicit selection through inspect/adopt/verify, detect all inventory changes, preserve raw logs and old sources, and never infer modes/origin/cuts from paths, dates or event counts. No log bodies, credentials or private IDs leave my machine. Once the scope and writes are covered by my authorization, adopt, repeat to check no-op, and verify; report selected completion and remaining pending separately. For unsupported rows, give the future official-reader/re-inventory/source-validation route; without a recoverable source, keep pending or use a new session. Do not treat old certificates as new authority.
99
+
100
+ > 帮我迁移到 DSH Completion Guard 0.10.0 的会话启用模式。生命周期约束:[填写允许停止的写者及是否允许重启]。沿用本会话已给出的范围、写入及生命周期授权,仅询问缺失或实质变化的决定。先报告现有宿主、持久化目录/压缩配置、保留的前驱包(如 0.9.0)身份及脱敏的升级前有效模式来源;不能核验就将受影响会话保持 pending。取得明确生命周期和写入权限前,不替换包、不停/重启进程、不写绑定。运行打包工具的只读 inventory,报告总数/可读/官方格式拒绝数量并保存本地 pending 报告;沿用我已明确选择的范围,尚未选择时再请我决定;不静默扩大范围,也不把可读性本身当作授权。让显式 selection 贯穿 inspect/adopt/verify,检测全部库存变化,保留原日志和旧来源,不按路径、日期、事件数猜模式/origin/cut。正文、凭据、私有 ID 不离开本机。范围和写入已有授权覆盖后 adopt、重复检查 no-op,再 verify,分别报告选中行完成及剩余 pending。被拒绝项给出未来官方读取器支持后重盘点、核验身份/旧来源的方案;没有可恢复来源就保留 pending 或改用新会话。旧证书不当作新权限。
101
+
102
+
103
+ ## Full-inventory inspect, adopt, verify / 整库清点、采纳、核验
104
+
105
+ The entry `node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs` below uses the independently prepared 0.10.0 toolkit; it does not assume a new command is installed on PATH while the old Guard remains installed. The tool mounts only the official JSONL persistence service, without starting the agent loop, UI or model. `--runtime-anchor` is a file in the physical official runtime; the tool resolves its real path before loading dependencies. `--persistence-root` and optional `--compression none|zstd` must match the active persistence configuration. No storage path or encoding is guessed. Inspection uses public `list`, read-only `open`, exact header/inherited-cut metadata and revision readback; it outputs no event bodies. Keep writers stopped through the sequence.
106
+
107
+ 下方使用独立准备的 0.10.0 工具入口 `node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs`,不假定旧 Guard 仍安装时新命令已在 PATH。工具只挂载官方 JSONL persistence 服务,不启动 agent loop、界面或模型。runtime anchor 必须是官方 runtime 中的文件,加载依赖前先解析物理路径。持久目录及可选压缩格式必须匹配实际配置,不推测目录或编码。清点使用公开 list、只读 open、精确 header/cut 元数据及 revision 回读,不输出事件正文。整个操作期间保持写者停止。
108
+
109
+ The following example is for a POSIX shell. Run `inspect` before replacement; run `adopt` and `verify` before starting the upgraded host. Keep the prepared toolkit path explicit throughout.
110
+
111
+ 以下示例使用 POSIX shell:替换前执行 inspect,升级后的宿主启动前执行 adopt 和 verify,全程使用明确的候选工具路径。
112
+
113
+ ```sh
114
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs inspect \
115
+ --runtime-anchor /path/to/runtime/package.json \
116
+ --persistence-root /path/to/active-session-storage \
117
+ --prior-modes /path/to/old-mode-source.json \
118
+ --output /path/to/frozen-migration.json
119
+
120
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs adopt \
121
+ --runtime-anchor /path/to/runtime/package.json \
122
+ --persistence-root /path/to/active-session-storage \
123
+ --receipt /path/to/frozen-migration.json \
124
+ --dsh-home /path/to/actual-dsh-home
125
+
126
+ node /absolute/prepared-package/bin/dsh-completion-guard-activation.mjs verify \
127
+ --runtime-anchor /path/to/runtime/package.json \
128
+ --persistence-root /path/to/active-session-storage \
129
+ --receipt /path/to/frozen-migration.json \
130
+ --dsh-home /path/to/actual-dsh-home
131
+ ```
132
+
133
+ `inspect` creates a new owner-only receipt with exclusive creation, or reports exact unresolved session IDs and exits nonzero without creating an adoptable receipt. `adopt` first checks receipt identities against the current public inventory, then writes each binding separately; `verify` never writes. A conflict leaves the other completed rows intact and reports `partial`. Repeating adoption is a byte-identical no-op for completed rows and continues missing rows. Claim completion only after all receipt rows verify. A newly appearing session is not silently included in an old receipt.
134
+
135
+ inspect 排他创建仅所有者可访问的新收据,或报告未解决会话 ID 并非零退出,不生成可采纳收据。adopt 先用当前公开库存核对身份,再逐会话写绑定;verify 不写入。冲突保留其他已完成行并报告 partial,重复采纳对已完成行字节不变,继续缺失行。所有收据行核验通过后才可报告该收据迁移完成;新出现的会话不会被静默加入旧收据。
136
+
137
+ ## Restore, diagnosis and rollback / 恢复、诊断与回退
138
+
139
+ Bindings live under `DSH_HOME/completion-guard/activation-bindings-v1` (`~/.dsh` when unset), with one hashed slot per SessionId. Birth identity includes createdAt, parent, seeded flag, exact inherited cut, origin and delegation depth; preset, cwd, profile and host lock do not change it. Existing mode overrides defaults. A contradictory explicit configuration refuses `activation_mode_conflict`; removing that contradictory override restores the original binding semantics. To choose another initial mode, create a new root session. Restore/clear/compact/late attach never create a missing binding.
140
+
141
+ 绑定位于上述私有目录,一个 SessionId 对应一个摘要槽。出生身份包含 createdAt、父会话、seed 标记、精确继承 cut、来源及委派深度;preset、cwd、profile、宿主锁不改变模式身份。已有模式覆盖缺省,显式矛盾报具名拒绝;移除矛盾覆盖可恢复原绑定语义,选择另一初始模式请新建根会话。恢复、清空、压缩、迟挂载不补建缺失记录。
142
+
143
+ Missing/corrupt/changed records invalidate cached projections and certification. Inspect the named reason, then use the preserved verified receipt to adopt the same missing old identity/mode. Corrupt or conflicting final slots refuse automatic repair; preserve them for diagnosis. If no trusted old source remains, keep the session unknown and establish new work in a fresh qualified session. This does not delete history or trigger an endless correction loop. Forks require a parent binding and inherit its mode; the exact cut is supplied and validated by the official Session/persistence contract, without mode inference from prefix length.
144
+
145
+ 缺失、损坏或变化的记录使缓存投影和认证失效。根据具名原因诊断,再使用保留且已核验的收据采纳同一缺失旧身份与模式。损坏或冲突的 final 拒绝自动修复,请保留诊断;无可信旧来源时保持 unknown,在新合格会话中建立新工作。不删除历史,也不触发无穷纠正。fork 需核验父绑定并继承父模式;精确 cut 由官方 Session/persistence 合同提供及验证,不由前缀长度推断模式。
146
+
147
+ A fresh creation that leaves `.pending`, including a fresh 0.10.0 session, has no general recovery command in this toolkit. `inspect` accepts verified pre-upgrade predecessor sources (`0.0.x`–`0.9.x`, including `0.9.0`), but `adopt` still requires a verified migration receipt for the same old session identity and mode. Predecessor support does not authorize treating a failed fresh creation as a legacy migration or inventing a receipt to repair it. Without an existing trusted legacy receipt, keep the mode unknown, diagnose the retained state, or continue new work in another qualified fresh session. The exported same-value writer is a programmatic controlled recovery primitive, not an operator CLI. Do not delete `.pending` merely to make the final readable.
148
+
149
+ 新建会话(包括 0.10.0 新会话)留下 .pending 时,本工具仍没有通用恢复命令。inspect 可使用已核验的旧版本模式来源(`0.0.x`–`0.9.x`,包括 `0.9.0`),但 adopt 仍需针对同一旧会话身份与模式的已核验迁移收据。支持这些前驱版本不意味着可以把失败的新建会话当作旧会话迁移,或编造收据来修复它。没有既有可信旧收据时,保持模式 unknown、诊断保留状态,或在另一合格新会话中继续新工作。导出的同值 writer 是程序受控恢复原语,不是操作者 CLI;不能为了让 final 可读而删除 .pending。
150
+
151
+ For rollback, stop writers, retain the receipt and bindings, and select the previous mode explicitly in each old profile before reinstalling the old Guard. A pre-0.9.0 Guard does not read these bindings; mixed-mode inventories need separate correctly mapped profiles or remain unsuitable for rollback. Keep host-lock and certificate identities separate: re-inspect the actual installed host as required, and never re-sign old certificates merely to change mode. Cross-machine transfer includes only verified bindings/receipts, with owner permissions restored; it transfers no host lock, credentials or native authority.
152
+
153
+ 回退先停写者,保留收据与绑定,为旧 profile 显式选择原模式再恢复旧 Guard。0.9.0 之前的 Guard 不读取绑定,混合模式库存需正确映射的独立 profile,否则不适合回退。宿主锁及证书身份另行核验,不为改变模式重签旧证书;跨机仅迁移核验过的绑定与收据并恢复所有者权限,不转移宿主锁、凭据或原生权限。
154
+
155
+ ## Storage capability limits / 存储能力边界
156
+
157
+ POSIX writes reuse the private writer lock, exclusive temporary creation, full write/file fsync, non-overwriting hard-link publication, directory fsync and final readback. Same identity/mode is a strict no-op preserving provenance. Readers reject malformed/duplicate-key JSON, bad digest/schema, unsafe owner/access modes, leaf links and user-owned ancestor links. Root-owned macOS `/var` and `/tmp` system aliases are the only permitted ancestor link exceptions; writable non-sticky ancestry refuses. These checks do not claim resistance to hostile same-owner processes racing the filesystem.
158
+
159
+ POSIX 复用私有 writer 锁、排他临时文件、完整写入及文件 fsync、不可覆盖 hard-link 发布、目录 fsync 与 final 回读。同身份同模式严格不改写来源。读取拒绝坏 JSON、重复键、摘要/schema 错误、错误所有者/权限、叶链接及用户祖先链接;仅允许 root 所有的 macOS 系统别名 /var、/tmp,非 sticky 可写祖先拒绝。它不是防御同 owner 恶意并发文件系统操作的绝对保证。
160
+
161
+ Windows uses the adopted **published-file flush barrier** on qualified local storage supporting same-volume hard links: flush the complete exclusive temporary, publish the non-overwriting link, open the existing final with read/write permissions without create/truncate, verify regular-file identity and exact bytes, fsync that final handle, close it and independently read back. No final bytes or permissions are normalized. Directory fsync remains an observed EPERM capability gap. Microsoft documents file data/metadata flush; applying that file flush to the newly published link is an explicitly bounded engineering inference, not POSIX-directory equivalence, power-loss proof, hardware-cache guarantees or durability of the whole ancestor namespace. Native candidate acceptance must record filesystem/runtime identity, this barrier and the directory gap separately.
162
+
163
+ Windows 在合格且支持同卷 hard-link 的本地存储上采用**发布后文件 flush 屏障**:完整排他临时文件 flush,不可覆盖 link 发布,以不创建/不截断的可写句柄打开现有 final,核对 regular-file 身份及精确字节,fsync 该句柄,关闭后独立回读。不规范化 final 字节或权限。目录 fsync 的 EPERM 能力缺口保留。Microsoft 说明文件数据/metadata flush;将其应用于刚发布的 link 是具名、有界工程推论,不是 POSIX 目录等价、断电、硬件缓存或整个祖先 namespace 持久性证明。候选原生验收须分别记录文件系统/runtime、文件屏障及目录缺口。
164
+
165
+ A post-publication failure retains the exclusive `.pending` temporary hard link; readers refuse `activation_publication_incomplete` even when final is visible. Controlled same-value writing reopens and successfully flushes retained temporary bytes, then can verify the exact pending/final identity, complete the barrier and remove the temporary. Recovery does not rewrite bytes or provenance. Temporary cleanup occurs after the required barrier/readback and its crash durability is a separate limit, not covered by that earlier flush. A malformed retained temporary or identity/mode conflict refuses automatic recovery. This is one per-session temporary publication, with no global transaction or birth WAL.
166
+
167
+ 发布后失败保留排他的 .pending 临时 hard-link;即使 final 可见,读者仍拒绝未完成发布。受控同值写入须重新打开并成功 flush 保留临时字节,再核对 pending/final 精确身份、补完屏障并移除临时项,不改字节或来源。临时清理在必需屏障与回读之后,它的 crash 持久性独立,不能借用此前 flush。坏临时项或身份/模式冲突拒绝自动恢复;这是逐会话临时发布,无全局事务或 birth WAL。
168
+
169
+ The official file-tool guard denies explicit private-storage targets (including resolved path aliases), and shell-tool calls naming the private roots or mode entrypoint. Operator migration runs independently. This is bounded tool-surface protection, not arbitrary command interpretation, a general subprocess sandbox or protection against hostile in-process plugins/encoded shell commands. No broader host interception is claimed.
170
+
171
+ 官方文件工具 guard 拒绝明确的私有目标(含解析后的路径别名),shell 工具拒绝指向私有根或模式入口的调用;操作者迁移独立执行。这是有界工具表面保护,不是任意命令解释、通用子进程 sandbox,也不防御同进程恶意插件或编码 shell 绕过,不声称更广的宿主拦截。
@@ -16,33 +16,36 @@ Context Guard does not own Goal, Todo, Compaction, or continuation. It intervene
16
16
  ## Call-time Host working-directory evidence
17
17
 
18
18
  For an ordinary named `npm test` or `pnpm test` Host call that omits `workdir`,
19
- the Guard captures a read-only working-directory receipt before execution and
20
- defers its provider-visible plugin context until the host has persisted the
21
- complete tool-result batch. This is a call-time derivation from the original Session header, the scoped sandbox
22
- policy, the active shell service, and exact audited DSH `0.1.5-rc.2` producer
23
- bytes. It is **not** a working directory returned by the Host process. The
24
- notice binds the original call ID, sequence, turn, arguments digest, root
25
- source, Session digest, Host-lock digest, physical directory, and policy root.
26
- On replay it is accepted only after the matching result and before the next
27
- assistant step, with the same source and Host identity. A legacy notice between
28
- a call and result is not upgraded. The observer always lets the Host tool proceed;
29
- it grants no ordinary mutation or execution qualification.
30
-
31
- The Bash producer chooses the scoped policy workspace root, or the Session
32
- header cwd when no policy is mounted; this candidate only certifies the
33
- audited policy route when its physical root equals the immutable header cwd.
34
- PowerShell uses the immutable header cwd under its separately audited local
35
- executor. An explicit `workdir` is checked on its own merits. Missing or
36
- ambiguous provider identity, a lexical filesystem alias, absent physical
37
- directory, changed policy or graph bytes, background execution, or missing
38
- call-time notice leaves target attribution insufficient. Historical logs
39
- without such a notice cannot be upgraded by reading today's Host config.
19
+ Guard observes the proposed default directory before execution. The observation
20
+ binds the original Session header, committed cwd epoch, scoped policy and
21
+ `WorkingDirectoryService`, active shell service, and audited DSH `0.2.1-rc.2`
22
+ implementation bytes and dependency routes. Its provider-visible context is
23
+ deferred until the host has persisted the complete tool-result batch. It is
24
+ not a directory returned by the executed process.
25
+
26
+ Bash and PowerShell obtain their default from the host's asynchronous
27
+ `workingDirectory.ensure()`. That service can recover a missing directory after
28
+ `tool/call`. Guard therefore withholds the receipt if the current service readback
29
+ disagrees or the directory history changes while the call is in flight. The
30
+ ordinary call still proceeds; its cwd-dependent result stays unconfirmed and
31
+ retains the call-epoch target. An explicit absolute workdir or file target is
32
+ bound independently; a relative shell workdir resolves against the call epoch only under the epoch reader. Historical logs with no cwd-change events retain the exact 0.9.0 projection under the same host binding and its frozen evidence/digests, including relative workdir spelling. The reader version is chosen from effective epochs committed through the result, so a future change cannot rewrite a completed legacy fact.
33
+
34
+ A receipt binds call ID, sequence, turn, arguments digest, root source, Session
35
+ and host-lock digests, physical directory and policy root. Replay accepts v1
36
+ only in unchanged header history. V2 additionally binds the governing epoch
37
+ and the original cwd supplied by the actual Session header, and refuses
38
+ in-flight directory changes and transplanted histories. Neither version
39
+ creates permission to execute or proves resource cleanup. Missing or ambiguous
40
+ provider identity, a lexical filesystem alias, background execution or an absent
41
+ receipt leaves the omitted-workdir completion shortcut unavailable. Historical
42
+ logs cannot acquire a missing receipt from today's configuration.
40
43
 
41
44
  ## Durable state model
42
45
 
43
- The effective plugin configuration and the DSH Session append-only log are the ordinary inputs to the rebuildable Guard projection. Context Guard **appends no custom session event types**: the persisted event vocabulary is harness-owned and the current persistence layer refuses unknown event types. The explicit release and restart paths additionally use the provider-invisible private ledger described below. The `activation` configuration supplies the initial enablement state, while ordinary session state is derived from the natively persisted events DSH already writes:
46
+ The resolved session mode binding, effective policy configuration and DSH Session append-only log are the ordinary inputs to the rebuildable Guard projection. Context Guard **appends no custom session event types**: the persisted event vocabulary is harness-owned and the current persistence layer refuses unknown event types. The explicit release and restart paths additionally use the provider-invisible private ledger described below. The `activation` configuration selects only a fresh unseeded root binding; the resolved immutable binding supplies initial enablement, while ordinary session state is derived from the natively persisted events DSH already writes:
44
47
 
45
- - effective plugin configuration — initial enablement (`opt-in` starts disabled; `always` starts enabled before log replay);
48
+ - immutable session mode binding — initial enablement (`always` is the new-root default; adopted old modes persist; `opt-in` starts disabled and `always` starts enabled before replay);
46
49
  - `command/run` — later enablement (`/context-guard on|off|clear`) and epoch transitions;
47
50
  - `user/message` — captured contract clauses;
48
51
  - `tool/call` + `tool/result` — bounded evidence and completion-certificate attempts;
@@ -52,7 +55,7 @@ The effective plugin configuration and the DSH Session append-only log are the o
52
55
 
53
56
  Everything else in the DSH log is deliberately ignored. In particular a V3 `system/message` is a plugin-sourced surface node rather than root authority, a compaction checkpoint `user/message` stays plugin context, and `request/header`, `request/context`, `assistant/attempt`, `session/end-seed` and raw `assistant` streams carry no contract state.
54
57
 
55
- The in-memory `GuardProjection` is a rebuildable cache: `deriveProjection` applies the effective activation configuration, replays the native log deterministically, recomputes every contract, evidence, and certificate, and flags `corrupt` when a recorded certificate no longer re-derives from the evidence in the log. The projection and its evidence are session-scoped: a new DSH session starts a new projection and cannot import, look up, or certify evidence IDs from another session. A completed workflow that needs a certificate must therefore produce its evidence and call `context_guard_checkpoint` in the same session. Under `always`, replay begins enabled; changing an existing profile from `opt-in` to `always` can therefore bring earlier persisted user messages into the derived contract. A recorded `/context-guard off` disables capture from that point until a later `on`. A recorded `/context-guard clear` supersedes every pending requirement and acceptance under a `CLEAR:<revision>` sentinel (prohibitions are retained) and bumps the contract revision, so a fresh empty-binding checkpoint can certify while the guard stays enabled. Captured contracts always carry a concrete subject/surface, so no unrelated evidence can close a requirement.
58
+ The in-memory `GuardProjection` is a rebuildable cache: `deriveProjection` applies the resolved session activation mode, replays the native log deterministically, recomputes every contract, evidence, and certificate, and flags `corrupt` when a recorded certificate no longer re-derives from the evidence in the log. The projection and its evidence are session-scoped: a new DSH session starts a new projection and cannot import, look up, or certify evidence IDs from another session. A completed workflow that needs a certificate must therefore produce its evidence and call `context_guard_checkpoint` in the same session. Under a bound `always` mode, replay begins enabled. Changing a profile default does not change old bindings; a contradictory explicit setting refuses rather than replaying that session under another mode. A recorded `/context-guard off` disables capture from that point until a later `on`. A recorded `/context-guard clear` supersedes every pending requirement and acceptance under a `CLEAR:<revision>` sentinel (prohibitions are retained) and bumps the contract revision, so a fresh empty-binding checkpoint can certify while the guard stays enabled. Captured contracts always carry a concrete subject/surface, so no unrelated evidence can close a requirement.
56
59
 
57
60
  ## Session lifecycle: silent start, first-message activation
58
61
 
@@ -219,3 +222,9 @@ Checkpoint certification runs over the complete contract before display filterin
219
222
  The serializer reserves metadata space before selecting rows and returns at most 12 KiB of valid UTF-8 JSON. Oversized rows identify omitted detail; `detail_id` retrieves bounded JSON-text chunks. Later chunks require the initial `snapshot` as `detail_snapshot`. A long ID may use a SHA-256 lookup token in the summary; its original ID remains unchanged in the detail. Explicit `item_ids` can inspect passed and superseded provenance as well as current work. None of these views changes the certificate's scope.
220
223
 
221
224
  Recovery reserves its rules, query pointer and folding totals before filling item summaries. Separate category slots retain a key prohibition and the newest pending requirement before optional rejection details or evidence; many constraints cannot hide the current work. Long IDs are summarized independently of the reason and next step. Small packets distinguish capability restoration from requirement rebinding. Its default budget is 4,000 characters; values below 512 or non-integers are rejected. The 512-character form keeps a constraint, the current limitation, and a query pointer. Full constraint enforcement remains in the ledger and execution checks. The runtime re-derives binding refusals from persisted calls and deduplicates guidance against the current contract and relevant evidence. A real compact/resume boundary always resets that context-local deduplication.
225
+
226
+ ### Session initial activation (0.9.0)
227
+
228
+ The real Cordis schema preserves omitted activation; qualified public startup binds only fresh unseeded roots. Existing sessions read their write-once birth binding, and pre-upgrade sessions need independent inventory/adoption. Resume, compact, clear and late attach cannot guess a mode. Every sync freshly calls `readActivationBinding`; missing/changed/conflicting files invalidate fast paths and certification. This store is independent of the certificate identity and private release ledger, with no global birth WAL or mode transaction. Exact parent cut comes from the host contract; no factory issuer token is assumed. See [storage, migration and Windows capability limits](ACTIVATION_MIGRATION.md).
229
+
230
+ 真实 Cordis schema 保留省略来源,合格 startup 只绑定新建无继承根。旧会话读取不可覆盖出生绑定,升级前库存需独立 adoption;恢复等入口不猜模式。每次 sync 新鲜读取绑定,缺失、变化、冲突使缓存及认证失效。存储独立于证书身份和私有发布账本,无全局 birth WAL 或模式事务。父 cut 来自宿主合同,不假设 issuer token;平台能力边界见迁移说明。
@@ -2,9 +2,51 @@
2
2
 
3
3
  Guard binds each accepted installation to its exact package identities, implementation bytes and dependency routes. Version admission and implementation qualification are separate checks; a matching version alone does not establish compatibility.
4
4
 
5
- ## 0.8.2–0.8.4: DSH >=0.2.0-rc.2 and official Desktop
5
+ ## 0.10.0: DSH >=0.2.1-rc.2
6
6
 
7
- 0.8.4 retains the host admission and Desktop support introduced in 0.8.2. Each release still requires its own artifact acceptance.
7
+ 0.10.0 raises the host floor to `0.2.1-rc.2` (upstream release `dsh-v0.2.1-rc.2`, commit `687f282e8625c6b8d11ff58211a90524be2e4317`, cumulative over `0.2.1-rc.1`). There is no upper bound: later RCs on any tuple, stable and future releases pass VERSION ADMISSION and must still pass the graph, byte, route and contract audits. `0.2.0-rc.2`, `0.2.0` and `0.2.1-rc.1` keep their recorded-evidence rows but are refused as below the floor. Cordis keeps a separate `>=4.0.4` peer range and qualification (the reviewed baseline moved to Cordis `4.0.5` with the same range).
8
+
9
+ The reviewed host baseline is DSH `0.2.1-rc.2` / Cordis `4.0.5`, with 47 package identities and published implementation digests in `manifests/rc021-rc2-byte-audit.json`, regenerated from the published `0.2.1-rc.2` tarballs (the audited cohort id is `dsh-0.2.1-rc.2-core-v1`). Native acceptance of the final Guard artifact on each platform remains a separate gate; no native validation of a future host is claimed.
10
+
11
+ ### Official Desktop distribution bytes
12
+
13
+ The official Desktop `0.2.1-rc.2` distribution retains generated `lib/types/invariant.js` companions that the npm packages no longer contain. Guard does not load these companions. Desktop qualification additionally checks the exact released archive identities and eight critical-package file tuples in [`desktop-distribution.v1.json`](../manifests/desktop-distribution.v1.json). Each program was independently reproduced from the fixed upstream source before its removal; the manifest keeps that public source pin separate from the application's declared build identity. The local ASAR hash table cannot authorize extra code. The carrier must pass vendor-signature verification, the authenticated ASAR header must match a registered platform distribution, and registry bytes and active dependency routes must still pass their existing audits. Unknown files, changed bytes, versions, headers or routes are refused. Ordinary registry runtime qualification is unchanged. A new Desktop build requires qualification of its own bytes even when its version string is unchanged.
14
+
15
+ Desktop's physical hoisted profile reader accepts the observed pnpm `11.7.0` and `11.28.5` JSON layouts only when the profile's manager agrees with the verified carrier. Duplicate keys, unsupported YAML, linked or escaped locations and invalid dependency routes are refused. The `dsh-desktop-bound/v2` contract is unchanged: Guard's second single-package add must preserve all tracked bytes and its complete package tree; only object-key order in `.modules.yaml` may differ in the later multi-package add. Qualification and read-only preflight do not establish installation, no-op, lifecycle or real-model acceptance.
16
+
17
+ 官方 Desktop `0.2.1-rc.2` 分发包保留了 npm 包已移除的 `lib/types/invariant.js` 编译产物,Guard 不加载这些伴随插件。Desktop 另行核对固定发行包身份和八个关键包的精确文件清单;每份程序均由删除前的固定上游源码独立编译复现,公开源码 pin 与应用声明的构建标识分开记录。ASAR 自带哈希表不能授权额外代码:仍须通过官方签名、已登记平台的 archive header、registry 字节和实际依赖路由核验。未知文件、改字节、错版本、错 header 和错路由均被拒绝,普通 registry runtime 的闭合规则不变。同版本重新构建的 Desktop 也须重新核验其分发字节。
18
+
19
+ Desktop 平铺安装索引只接受已观察的 pnpm `11.7.0`、`11.28.5` JSON 布局,版本必须与已验证的 carrier 一致;重复 key、未知 YAML、链接或越界目录、错误依赖路由仍会被拒绝。v2 两步 no-op 合同不变:Guard 单包第二次 add 要求全部跟踪文件及包树字节不变;后续多包 add 仅容许 `.modules.yaml` 的对象 key 顺序变化。资格核验及只读 preflight 不等于安装、no-op、生命周期或真实模型验收通过。
20
+
21
+ ### Host-surface changes Guard 0.10.0 actually handles
22
+
23
+ - **Session V4 catalog adds `job/registered`, `job/settled`, `working-directory/change`.** Job registrations and settlements are durable lifecycle facts, not completion evidence: a `job/settled` record with `status: "completed"` refines the external-wait view only when the producer itself reported fulfilment (`cause: "producer"`, `producerReported: true`); killed and failed settlements are explicit failures, and an unreported completion is unconfirmed. A settlement never certifies resource cleanup, file readback or the completion of a user obligation. Only a validated registration/settlement pair owned by the current session may refine its wait; supplied tool/root identities must match the original persisted invocation. The host writes lifecycle records best effort, so a well-formed orphan settlement remains audit-only. Missing or malformed identity, time or optional fields and conflicting repeats fail closed. A forked history never transfers the original owner.
24
+ - **Working directory is switchable inside a session.** The immutable Session header keeps the original project; each committed `working-directory/change` opens a new cwd epoch. Captured targets, paths and receipts keep the meaning of the epoch they were bound in — a later change never re-interprets an older relative path. A cwd-dependent call keeps its call-epoch target; a directory change before its result makes execution unconfirmed, including recovery by the host after dispatch. Absolute explicit execution targets remain independently bound. Drive-root and complete Windows UNC directories preserve their original spelling. Host default-workdir receipts gained a v2 shape that binds the governing epoch and the original project; receipts replayed next to different directory history are refused. Root-locator digests bind the epoch each root was captured in. Historical logs without `working-directory/change` preserve the 0.9.0 frozen projection under the same host binding, and preserve its evidence fields and digests, including the original spelling of explicit relative shell workdirs. The epoch reader applies only once a committed effective epoch is visible through that result; it resolves relative shell workdirs against the call epoch and keeps ambiguous Windows workdirs unconfirmed. Later events never reinterpret an already completed legacy fact.
25
+ - **Plugin records exist (`appendPluginRecord`/`pluginRecordOf`, `plugin:` namespace).** They are ignorable, never model-visible, and retained on a best-effort basis across format migrations; the upstream gate restricts production callers to its own experimental packages, so this API is not a stable third-party persistence interface. Guard does NOT migrate its private hash-chained ledger onto plugin records; the ledger keeps its own storage, writer lock and loss model. Foreign plugin records are retained-and-skipped: they never trigger capture, never authorize anything, and never break seq-driven call/result pairing.
26
+ - **Session append gained a publication-reentrancy check and per-listener exception isolation.** Guard's synchronous `snapshotEvents()` reads remain valid on the pinned local Session implementation; the existing flush-before-control and boundary durability flows are unchanged.
27
+ - **The invariant companion plugin and the `./invariant` exports were removed upstream.** Guard never imported them and adds no substitute. The official Desktop distribution's retained compiled files require the separate qualification above.
28
+ - **Subagents and Teams.** The subagent tool name `subagent` stays in Guard's delegation allowlist: a subagent result remains bounded evidence and never closes a parent obligation. Team delivery moved to direct inbox acceptance (the old outbox retry/dedupe path is gone upstream); `team/message/delivered` records reception only — reception is not execution, and neither is completion. Waiting for a subtask, a plan-review end turn, or a Goal pause does not consume or fabricate a completion.
29
+ - **Search/Fetch APIs and new models** are ordinary host tools: their success is non-authoritative evidence, never proof that a user task is complete.
30
+
31
+ ### 升级、临时禁用与恢复(0.10.0 中文说明)
32
+
33
+ 最低宿主为 DSH `>=0.2.1-rc.2`,没有隐式上限。升级顺序不变:先停写者、保留旧模式来源,升级宿主到 `0.2.1-rc.2` 或更高,安装 Guard,重新注入宿主锁并回读(见[宿主锁升级](HOST_LOCK_UPGRADE.md))。已审查基线为 DSH `0.2.1-rc.2` / Cordis `4.0.5`(cohort `dsh-0.2.1-rc.2-core-v1`,47 包,见 `manifests/rc021-rc2-byte-audit.json`,上游提交 `687f282e8625c6b8d11ff58211a90524be2e4317`)。
34
+
35
+ 新宿主事件语义:`job/settled` completed 不证明资源释放,只有本会话所有、注册与结算身份一致且工具根调用匹配的配对记录,在 producer 自己报告完成(`cause: "producer"` 且 `producerReported: true`)时才把外部等待标记为完成;合法孤立结算仅保留为审计事实,畸形或冲突记录拒绝;killed/failed 是显式失败,未报告的 completed 保持未确认。`working-directory/change` 开启新的 cwd 纪元:此前捕获的目标与证据保留原含义,不会随当前目录重新解释;调用与结果之间若发生目录变化(包括宿主自动恢复),默认或相对目录的执行保持未确认;显式绝对目标独立绑定。Windows 完整 UNC 和 drive-root 路径保留拼写,drive-relative/root-relative 拒绝。没有 `working-directory/change` 的日志在同一宿主绑定下保留 0.9.0 冻结投影,并保留其证据字段与摘要,包括显式相对 shell workdir 的原始拼写。新读法只在该结果之前已有实际生效的提交纪元时使用;后来追加的事件不能重新解释已经完成的旧证据。`plugin:` 记录一律忽略且不触发捕获;Guard 私有账本不迁移到 plugin records。子代理结果仍是有界证据;Team 直投 Inbox 的接收成功不等于执行完成;Goal 等待与计划审阅的结束等待不算完成。
36
+
37
+ 临时禁用与恢复:升级窗口内可在 profile 配置中把 Guard 从 bundles 移除或保持不加载(临时禁用是独立状态,不影响 `activation=always` 与完整原有 config 的保留)。禁用期间会话事件不被捕获;重新启用时按既有规则恢复——新建无继承根会话回到默认模式,旧会话沿用 write-once 私有绑定的原模式。宿主锁在禁用期间不变质;重新启用后若宿主或 profile 图未变,原锁继续有效,若变化则按 `--rebind-registry` 流程重建。市场兼容卡片显示"兼容"不等于 Guard admission 已通过;插件加载成功也不等于审计通过。
38
+
39
+ ### Consumer prerelease semantics
40
+
41
+ The plain npm/node-semver expression `>=0.2.1-rc.2` excludes later-tuple prereleases by default. The installed DSH plugin compatibility check (`dsh-app-boot`'s `evaluatePluginCompatibility`) reads the TOP-LEVEL `engines.dsh` first and ignores the DSH peers entirely when it exists; it uses `semver.satisfies(..., { includePrerelease: true })`, so the declaration admits `0.2.1-rc.3` and later RCs on any tuple, and refuses below-floor values. Both shipped layers (`engines.dsh` and `dsh.engines.dsh`) carry the same range so consumers reading either layer agree; peers keep the same range for peers-only consumers. `benchmarks/incidents/acceptance/semver-matrix.json` records the verified matrix for the new floor, and `tests/v100-app-boot-admission.test.ts` pins the real consumer's decisions. Package installation is not a version-admission proof — Guard's own floor check rejects a below-floor host independently.
42
+
43
+ The default-workdir shortcut additionally authenticates the published `dsh-working-directory` implementation, its dependency routes and the scoped `WorkingDirectoryService`. Missing, substituted or modified providers emit no trusted receipt. A v1 receipt is valid only before any directory-change event; v2 replay binds its origin to the actual Session header supplied by derivation, rather than trusting the receipt's own origin field. A pre-execute receipt is refused if directory history changes before the result; a pre-execute observation does not prove that `ensure()` later executed in that directory.
44
+
45
+ 默认目录快捷证据还核验 `dsh-working-directory` 的发布字节、依赖路由和当前 scoped 服务身份。服务缺失、替换或修改时不发可信回执。v1 只能用于调用前没有目录变化的历史;v2 的 origin 必须绑定派生器从实际 Session header 取得的原始目录,不能只信回执自报。调用后目录发生变化时,执行前回执不再证明实际执行目录。
46
+
47
+ ## 0.8.2–0.9.0: DSH >=0.2.0-rc.2 and official Desktop
48
+
49
+ 0.9.0 retained the host admission introduced in 0.8.2 with the floor `0.2.0-rc.2`; 0.10.0 supersedes it. Historical description:
8
50
 
9
51
  Version admission uses strict SemVer precedence, including later-tuple RCs and ignoring build metadata. The floor is `0.2.0-rc.2`, with no upper limit. `0.2.0-rc.1` keeps its recorded-evidence row but is refused as below the floor. Below-floor and malformed versions are refused. Cordis has a separate `>=4.0.4` peer range and qualification; a DSH version does not establish arbitrary Cordis compatibility.
10
52
 
@@ -26,9 +68,9 @@ The lock binds the canonical archive, signed header, runtime manifest and metada
26
68
 
27
69
  `hostLockProfile: "desktop"` is preserved through composition and readback. Guard refuses Desktop restart with `host_capability_request_unsupported`; the graphical app owns its lifecycle. Exact-artifact backend acceptance, graphical-shell acceptance and real-model behavior are separate gates. Their results belong to the matching Release annexes.
28
70
 
29
- ### 0.8.2–0.8.4 中文说明
71
+ ### 0.8.2–0.9.0 中文说明
30
72
 
31
- 0.8.4 保留 0.8.2 的宿主准入范围与 Desktop 支持;各版本仍须独立核对制品验收结果。
73
+ 0.9.0 保留 0.8.2 的宿主准入范围与 Desktop 支持;各版本仍须独立核对制品验收结果。
32
74
 
33
75
  0.8.2 延续 0.8.x 的任务、证书与数据协议,主要适配 DSH RC.2、增加 Desktop 宿主锁并修复退出证据判定。最低 DSH 版本升至 `0.2.0-rc.2`;请先升级宿主,再安装 Guard、重新注入锁并回读。版本准入没有上限,但版本号相符仍不足以证明实现兼容。Cordis 的独立要求为 `>=4.0.4`。
34
76
 
@@ -151,7 +193,11 @@ Market versions do not select a core cohort. Market restart has its own protocol
151
193
 
152
194
  The package exposes a named `apply(ctx)` function and a named `inject` array (`['sessions', 'commands', 'fs']`) with no default export. Its `dsh.bundle.patch` points at `cordis.patch.yml`, which inserts the `context-guard` bundle row.
153
195
 
154
- The plugin accepts an `activation` configuration value of `opt-in` or `always`. The default is `opt-in`; `always` means every session is protected automatically from its first real user message. Since 0.5.0, session start writes nothing into the session log: the versioned protocol boundary and first-step guidance are delivered inside the same step batch as — and ahead of — the first real user message, so a new session stays blank (`seq === 0`) and a DSH preset can be selected before anything is sent. An explicit `off` suppresses `always` in that session until the next `on`. Invalid values fail during plugin configuration instead of silently falling back. A DSH profile can select `always` with an ID-targeted `config` override in its `cordis.patch.yml`; see the README quick start for the complete example.
196
+ The plugin accepts explicit `opt-in` or `always`, preserving omitted configuration through the real Cordis schema. Since 0.9.0 only newly created, unseeded root sessions default to `always`. Old sessions retain the pre-upgrade effective mode through [verified migration bindings](ACTIVATION_MIGRATION.md), including empty sessions. Existing bindings override a profile default; contradictory explicit configuration refuses with `activation_mode_conflict`. Persisted off/on controls replay enablement. Mode selection does not grant authority, certify work or change the default `standard` policy. Invalid values refuse configuration.
197
+
198
+ A qualified official `agent/created` startup path may bind fresh roots. Resume, clear, compact and late attach only read existing bindings; missing or corrupt records refuse certification. Qualification checks public live Agent/Session identity and the supported host composition. This trusts the audited host call chain; the public API provides no factory issuer token and does not defend against arbitrary hostile in-process plugins. Fork/seed mode comes from a verified parent binding; exact inherited-cut validation belongs to the official Session/persistence contract, not a guessed event count. At T0 the Guard may write its private sidecar but writes no Session log messages, preserving the blank preset picker. First real input receives the boundary and guidance in the same entered step. Blank input does not activate; attachments do.
199
+
200
+ 旧会话通过升级前模式清点及核验收据保留有效模式和重放 epoch,不重新解释旧证书。缺省变化只影响新建无继承根会话。恢复、清空、压缩及迟挂载不补建缺失记录;显式模式冲突拒绝认证。官方宿主公开身份与调用链是来源边界,不声称有逐调用 issuer token 或防御任意同进程伪造。父模式绑定和官方 persistence 的精确 cut 分别核验;未知来源保持诊断,不清历史、不重签。见[迁移说明](ACTIVATION_MIGRATION.md)。
155
201
 
156
202
  ### Host-lock setup
157
203
 
@@ -196,7 +242,7 @@ managers therefore see the same two exact host releases as the host-lock
196
242
  registry; neither an unregistered stable release nor a future version is
197
243
  implicitly admitted.
198
244
 
199
- That historical artifact retained exact `0.1.5-rc.1` development pins. The current 0.8.4 build pins DSH `0.2.0-rc.2` while public DSH peers declare the floor range. Historical peer declarations belong to their own release sections
245
+ That historical artifact retained exact `0.1.5-rc.1` development pins. The current 0.9.0 build pins DSH `0.2.0-rc.2` while public DSH peers declare the floor range. Historical peer declarations belong to their own release sections
200
246
  above and are not part of the 0.5.2 contract.
201
247
 
202
248
  ## Terminal outcome contract
@@ -0,0 +1,110 @@
1
+ # Installation and first load / 安装与首次载入
2
+
3
+ [English README](../README.md) · [中文 README](../README.zh-CN.md)
4
+
5
+ ## Before installation
6
+
7
+ Use the profile you actually run: Web, Headless or Desktop. Stop the relevant host/session writers first. If this installation has old Guard sessions, preserve the old package and effective mode sources, then prepare a frozen inventory and migration receipt using [the migration guide](ACTIVATION_MIGRATION.md) **before replacing DSH or Guard**. Empty old sessions count too. The 0.10.0 migration toolkit can run from a separately prepared package directory while the old package stays installed.
8
+
9
+ With no old Guard sessions, there is no old-mode adoption step. Upgrade the host to DSH `>=0.2.1-rc.2` if necessary, install Guard, and complete the installation checks before startup. Requires Node.js `>=22`, pnpm `>=11` and a qualified Cordis `>=4.0.4` installation. Do not load both `dsh-context-guard` and `dsh-completion-guard` in one profile; the internal entry ID remains `context-guard`.
10
+
11
+ ## 安装前
12
+
13
+ 先确认实际使用的 Web、Headless 或 Desktop profile,并停止相应宿主与会话写者。如果已有旧 Guard 会话,替换 DSH 或 Guard **之前**,按[迁移指南](ACTIVATION_MIGRATION.md)保留旧包、核验有效模式来源,冻结会话库存并准备迁移收据。旧空会话也需要清点。0.10.0 迁移工具可以从另行准备的包目录运行,旧包此时仍留在原安装位置。
14
+
15
+ 没有旧 Guard 会话时,不需要旧模式 adoption。先按需将 DSH 升级到 `>=0.2.1-rc.2`,再安装 Guard,完成安装核验后启动。需要 Node.js `>=22`、pnpm `>=11` 及通过资格验证的 Cordis `>=4.0.4`。同一 profile 不要同时加载 `dsh-context-guard` 和 `dsh-completion-guard`,内部条目 ID 仍是 `context-guard`。
16
+
17
+ ## Web installation / Web 安装
18
+
19
+ Keep the host stopped through these steps. Substitute the actual absolute runtime/profile paths. Back up the profile's `cordis.patch.yml` before `inject`, which writes the lock into that file. The three host-lock checks—`inspect`, `inject` and `verify-dump`—must each return `status: "supported"`; a nonzero exit or another status stops this path. This status requirement does not apply to `dsh plugin add`.
20
+
21
+ 以下步骤期间保持宿主停止,将目录替换为实际绝对路径。`inject` 会把锁写入 profile 的 `cordis.patch.yml`,执行前先备份。`inspect`、`inject` 和 `verify-dump` 三条宿主锁检查都须返回 `status: "supported"`;非零退出或其他状态都不能继续启动。该状态要求不适用于 `dsh plugin add`。
22
+
23
+ ```sh
24
+ dsh plugin --profile web add dsh-completion-guard@0.10.0
25
+
26
+ DSH_RUNTIME_ROOT=/absolute/path/to/.dsh-runtime
27
+ DSH_PROFILE_ROOT=/absolute/path/to/.dsh/profiles/web
28
+ GUARD_HOST_LOCK="$DSH_PROFILE_ROOT/node_modules/.bin/dsh-completion-guard-host-lock"
29
+
30
+ "$GUARD_HOST_LOCK" inspect --runtime-root "$DSH_RUNTIME_ROOT" --profile-root "$DSH_PROFILE_ROOT"
31
+ "$GUARD_HOST_LOCK" inject --runtime-root "$DSH_RUNTIME_ROOT" --profile-root "$DSH_PROFILE_ROOT"
32
+ dsh --profile web --dump-config | "$GUARD_HOST_LOCK" verify-dump --runtime-root "$DSH_RUNTIME_ROOT" --profile-root "$DSH_PROFILE_ROOT" --dump-config -
33
+ ```
34
+
35
+ The reviewed baseline is DSH `0.2.1-rc.2` / Cordis `4.0.5`. A later compatible host requires `--rebind-registry` on the three lock commands; it checks official archives and qualifies changed programs before rebuilding the lock. See [compatible-version rebinding](HOST_LOCK_UPGRADE.md#rebinding-compatible-package-versions). Changes to DSH, Guard or the profile location require fresh checks. An ordinary market-only update does not require reinjection; installing or removing the Desktop market does.
36
+
37
+ 已审查基线为 DSH `0.2.1-rc.2` / Cordis `4.0.5`。更新的兼容宿主需要在三条锁命令中添加 `--rebind-registry`,核对官方归档并验证变化的程序后重建锁,见[兼容版本重绑定](HOST_LOCK_UPGRADE.md#rebinding-compatible-package-versions)。DSH、Guard 或 profile 路径变化后需要重新检查。仅 market 的普通更新不需重新注入,Desktop 市场的安装或移除则需要。
38
+
39
+ ### Windows, Headless and Desktop / 其他入口
40
+
41
+ - **Windows Web:** run the same lock subcommands through `node_modules\.bin\dsh-completion-guard-host-lock.cmd` inside the actual Web profile directory, with Windows absolute paths. Use your shell's variable syntax; the block above is POSIX shell syntax.
42
+ - **Headless:** use the Headless profile and its own installed lock tool throughout, including `--profile headless` on DSH commands. See [the host-lock guide](HOST_LOCK_UPGRADE.md) for the profile-specific flow.
43
+ - **Desktop:** use the app's bundled CLI for installation and `--profile desktop` when building the lock. Bind the app archive and actual Desktop profile. Its CLI has no `--dump-config`; run `dump-desktop` and verify that newly generated output. The complete commands are in [official Desktop setup](HOST_LOCK_UPGRADE.md#official-desktop-profile). After installing or removing `dshmarket`, repeat `inspect`, `inject`, `dump-desktop` and `verify-dump` on the new output.
44
+
45
+ 中文对应路径:
46
+
47
+ - **Windows Web**:通过实际 Web profile 下的 `node_modules\.bin\dsh-completion-guard-host-lock.cmd` 运行相同锁子命令,使用 Windows 绝对路径和当前 shell 的变量语法;上方示例是 POSIX shell。
48
+ - **Headless**:全程使用 Headless profile 及其安装的锁工具,DSH 命令选择 `--profile headless`,完整流程见[宿主锁指南](HOST_LOCK_UPGRADE.md)。
49
+ - **Desktop**:使用应用附带 CLI 安装,以 `--profile desktop`、应用归档和实际 Desktop profile 建锁。该 CLI 没有 `--dump-config`,要用 `dump-desktop` 生成新配置,再核验这份输出。[官方 Desktop 步骤](HOST_LOCK_UPGRADE.md#official-desktop-profile)给出完整命令。安装或移除 `dshmarket` 后重新执行 `inspect`、`inject`、`dump-desktop`,并对新输出执行 `verify-dump`。
50
+
51
+ ## Finish an upgrade before startup
52
+
53
+ A host lock verifies the installation, not old session modes. While writers remain stopped, use the frozen pre-upgrade receipt for `adopt` and `verify`. Start the host only after installation/lock checks and the intended migration scope pass. Unknown old sources, missing bindings and conflicts stay pending; do not fill them with the upgraded `always` default.
54
+
55
+ If the official persistence reader refuses old formats, preserve those logs and mode sources. The [readable-subset flow](ACTIVATION_MIGRATION.md) freezes the whole report, then a user-reviewed selection of exact readable IDs. All three migration commands carry the same `--selection`; exclusions remain pending even when selected rows succeed. A zero exit or `selected_complete` does not establish whole-inventory completion. Corruption, permissions and other errors abort rather than becoming exclusions. The guide also contains [copyable migration prompts](ACTIVATION_MIGRATION.md) and recovery steps.
56
+
57
+ ## 升级核验完成后再启动
58
+
59
+ 宿主锁核验安装环境,不会迁移旧会话模式。保持写者停止,用升级前冻结的收据完成 `adopt` 和 `verify`。安装、锁核验及目标迁移范围全部通过后才能启动;旧来源未知、绑定缺失或冲突时保持待处理,不能用升级后的 `always` 默认值填补。
60
+
61
+ 官方 persistence 若拒绝旧格式,保留原日志和模式来源。按[可读子集流程](ACTIVATION_MIGRATION.md)先冻结全库报告,再明确选择精确的可读 ID。三个迁移命令都携带同一 `--selection`,选中行通过后排除项仍待处理。零退出或 `selected_complete` 不代表整库完成;损坏、权限等其他异常会中止,不会转成排除项。指南还提供[可复制迁移提示词](ACTIVATION_MIGRATION.md)和恢复步骤。
62
+
63
+ ## First load and status
64
+
65
+ When you open or restore a session that already has history, DSH loads that history and Guard reconstructs its saved state. You may see “载入历史” (loading history); wait for loading to finish before continuing. A later visit can still wait.
66
+
67
+ 0.9.0 reuses completed history checks only when it can verify that the history is unchanged and the results are safe to reuse. Each operation still checks the current mode and performs the required fresh checks of Goal state, private records and the host environment. It does not modify the official host's history-view lifecycle or decode cache and does not guarantee an instant first opening or subsequent visit.
68
+
69
+ Once loading finishes, run `/context-guard status`. With the default configuration, a new empty root session reports `armed`, waiting for the first real input; Guard has written no session events yet. DSH may have written its own initialization events. Images and attachments count as real input, blank messages do not. An explicit `activation: opt-in` instead requires `/context-guard on`. In an old session, check the retained mode and any binding diagnosis. Protection does not grant new authority; the default policy remains `standard`.
70
+
71
+ ## 首次载入与状态
72
+
73
+ 打开或恢复已有历史的会话时,DSH 载入历史,Guard 重建已保存的状态。界面可能显示“载入历史”,等加载结束后再继续;再次进入也可能需要等待。
74
+
75
+ 0.9.0 只在确认历史未变、检查结果可安全复用时,复用已经通过的历史检查。每次操作仍核对当前模式,并按需要重新核验 Goal 状态、私有记录和宿主环境。它没有修改官方宿主的历史视图生命周期或解码缓存,不能保证首次或后续打开立即完成。
76
+
77
+ 加载结束后执行 `/context-guard status`。使用默认配置的新建空根会话显示 `armed`,等待首条真实输入,此前 Guard 没有写入会话事件;DSH 可能已记录自身的初始化事件。图片、附件算真实输入,纯空白不算。显式配置的 `activation: opt-in` 则需要执行 `/context-guard on`。旧会话查看保留模式和可能的绑定诊断。保护不增加权限,默认策略仍为 `standard`。
78
+
79
+ ## Choose the default for new sessions
80
+
81
+ Profiles that omit `activation` already use `always` for new roots. To adopt that default while retaining old modes, complete the old-session migration first, back up `cordis.patch.yml`, then remove the `activation` field from the existing `context-guard` entry's `config`. Keep the entry, injected host-lock fields and all other settings. Do not replace the old field with an explicit `activation: always`: an explicit setting applies when reading existing bindings too and reports `activation_mode_conflict` if they disagree. Omitting the field lets new roots use `always` while old sessions use their bound initial modes. Forks inherit their parent's bound mode.
82
+
83
+ If you want future new roots to remain opt-in, keep `activation: opt-in`; any existing bindings must agree with that explicit setting. To choose a different initial mode, use a new root session. `/context-guard on` and `off` change the saved enabled state of the current session without changing its bound initial mode.
84
+
85
+ ## 新会话默认模式
86
+
87
+ profile 未填写 `activation` 时,新建根会话已默认采用 `always`。要采用新默认值并保留旧模式,先完成旧会话迁移、备份 `cordis.patch.yml`,再删除原 `context-guard` 条目 `config` 下的 `activation` 字段。保留整个条目、注入的宿主锁字段及其他配置。不要直接替换为显式 `activation: always`:读取已有绑定时也会核对显式配置,矛盾时报告 `activation_mode_conflict`。省略该字段,才能让新根会话使用 `always`,旧会话沿用绑定的初始模式。分叉会话继承父会话绑定的模式。
88
+
89
+ 若希望后续新根会话仍需手动开启,保留 `activation: opt-in`,但已有绑定也须与这一显式设置相符。需要不同的初始模式时应新建根会话。`/context-guard on`、`off` 改变当前会话保存的启用状态,不改变绑定的初始模式。
90
+
91
+ Default settings paths / 默认配置路径:
92
+
93
+ | System / 系统 | Profile | Settings / 配置 |
94
+ | --- | --- | --- |
95
+ | macOS / Linux | Web | `$HOME/.dsh/profiles/web/cordis.patch.yml` |
96
+ | macOS / Linux | Headless | `$HOME/.dsh/profiles/headless/cordis.patch.yml` |
97
+ | macOS | Desktop | `$HOME/.dsh/profiles/desktop/cordis.patch.yml` |
98
+ | Windows | Web | `%USERPROFILE%\.dsh\profiles\web\cordis.patch.yml` |
99
+ | Windows | Headless | `%USERPROFILE%\.dsh\profiles\headless\cordis.patch.yml` |
100
+ | Windows | Desktop | `%USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml` |
101
+
102
+ Use a custom `DSH_HOME` instead of the default `.dsh` directory when configured. Restart the appropriate host after the edit, once the required lock and migration checks have passed. Guard `on`/`off` controls this session's protection, not its DSH standard/minimal/custom preset.
103
+
104
+ 设置了自定义 `DSH_HOME` 时,使用该目录而非默认 `.dsh`。修改后在必要的锁及迁移核验通过时重启相应宿主。Guard 的 `on`、`off` 控制当前会话保护,不改变 DSH 的标准、极简或自定义 preset。
105
+
106
+ Copyable configuration prompt / 可复制配置提示词:
107
+
108
+ > Use dsh-completion-guard 0.10.0's default always mode for future new root sessions while preserving old modes. Find the cordis.patch.yml for the Web, Headless or Desktop profile I actually use. First verify that old-session mode migration is complete for the authorized scope; keep exclusions and unknown sources pending. Back up the file, then remove only the activation field from the existing context-guard config, or leave it absent. Preserve bindings, all other settings and host-lock fields. Do not rewrite bindings or restart DSH. Show the path and exact diff, and report any lock or migration checks remaining before restart.
109
+
110
+ > 让后续新根会话使用 dsh-completion-guard 0.10.0 的默认 always,保留旧模式。找到我实际使用的 Web、Headless 或 Desktop profile 的 cordis.patch.yml;先确认授权范围内的旧会话模式迁移已通过,排除项和来源未知项继续待处理。备份配置后,仅删除原 context-guard config 下的 activation 字段;原本没有该字段则保留不填。保留绑定、其他配置和宿主锁字段,不重写绑定,不重启 DSH。报告文件路径、精确差异,以及重启前尚缺的锁或迁移核验。
@@ -36,10 +36,18 @@ verdict is never inherited from a file-level or family-level green run.
36
36
  regression set, kept outside this repository; raw records, private session
37
37
  material and machine-local mappings are never copied into public files.
38
38
  The per-record table below is a historical producer statement for a former
39
- 28-record subset and is superseded for acceptance purposes by the current
40
- full-library adjudication (56 cases / 45 active — 29 Codex, 16 DSH — plus a
41
- frozen 16-record legacy lineage), whose per-case verdicts, execution lanes
42
- and candidate binding are tracked in that sanitized set.
39
+ 28-record subset. An earlier full-library snapshot recorded 56 cases / 45
40
+ active (29 Codex, 16 DSH), plus a separate frozen 16-record legacy lineage;
41
+ those counts are historical and are not the current acceptance denominator.
42
+ - The 2026-10-08 inventory review covered 70 case records / 53 active, plus
43
+ the separately counted frozen legacy lineage of 16 records / 8 active.
44
+ Every record was reviewed for lineage, DSH applicability, named source
45
+ controls and remaining inputs. This is a per-record inventory review, not
46
+ replay of every original incident or native-platform acceptance. Source
47
+ analogues, original reproductions and exact-artifact native runs remain
48
+ separate evidence; the old execution results below keep their original
49
+ dates and subjects. The maintainer's sanitized per-case review retains the
50
+ complete verdicts and candidate bindings without publishing private mappings.
43
51
 
44
52
  ## New adaptation tests added for this adjudication
45
53