@hasna/skills 0.10.72 → 0.10.74

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/README.md CHANGED
@@ -113,6 +113,27 @@ skills hook install --selection-profile default --json
113
113
  skills hook install --selection-profile default --apply --json
114
114
  ```
115
115
 
116
+ `--include-vendor` resolves configured plugin discovery, so it needs a reviewed
117
+ `--discovery-inputs` file when a configured plugin declares hooks. Without it,
118
+ `skills migrate native --include-unmanaged` archives user and project copies
119
+ only. Migration never archives Codex system skills (`.codex/skills/.system`),
120
+ even with `--include-vendor`. Codex refreshes its OpenAI marketplace plugin
121
+ caches on its own; retire those copies with a Codex `[[skills.config]]` rule
122
+ (`name = "<plugin>:<skill>"` or the exact `path` of the `SKILL.md`, with
123
+ `enabled = false`) rather than by archiving. The live Codex prompt hook accepts
124
+ a name rule only for a copy with no Hasna marker, its remote install receipt, a
125
+ refresh-safe plugin and no rule that enables it. Other checks (`skills hook
126
+ install` reusing a saved review, `skills hook trust`) do not accept a
127
+ hand-added name rule; for them, and for system skills, run `skills hook install
128
+ --agent codex --discovery-inputs <file> --apply` with a fresh discovery review
129
+ (no `--discovery-inputs` on an automatic binding; add a fresh
130
+ `--codex-native-catalog <file>` for a plugin Skills has enrolled), which writes
131
+ and records the disables. Run the same refresh after editing `config.toml` when
132
+ the binding's recorded configuration witness counts the edit: on automatic
133
+ bindings, after removing a rule that enables skills, and on reviewed bindings
134
+ whose witness counts disable rows. A `NATIVE_SKILL_DRIFT` refusal names the
135
+ step for each copy it lists, including that follow-up.
136
+
116
137
  Without `--agent`, hook installation selects configured or detected consumers:
117
138
  existing managed bridge bindings, provider-specific home configuration, or an
118
139
  installed native CLI found through PATH. Detection reads metadata and never
@@ -264,8 +285,8 @@ discovery-witness changes such a refresh provably makes:
264
285
  unknown keys refuse. There is no `hooks`, `commands` or `agents` directory, no
265
286
  `hooks.json` or `.mcp.json` (names compared without regard to case), no root,
266
287
  `.claude-plugin` or `.cursor-plugin` manifest, no link
267
- and no `SKILL.md` that the inventory cannot see (below a dot-named or
268
- `node_modules` directory, or nested in another skill). One exception keeps
288
+ and no `SKILL.md` below a dot-named or `node_modules` directory, or nested
289
+ in another skill. One exception keeps
269
290
  today's vendor plugins working: every current OpenAI vendor plugin declares
270
291
  its connector as `apps = "./.app.json"`, so exactly that declaration is
271
292
  allowed when `.app.json` is a regular file of at most 1 MiB, strict UTF-8, that
@@ -541,6 +562,20 @@ is bounded to 20,000 discovery entries and 4 MiB of UTF-8 path metadata before
541
562
  directory entries are retained or sorted. Unsupported special files and unsafe
542
563
  directory links are refused.
543
564
 
565
+ Codex 0.162.1 loads `SKILL.md` files below `node_modules` inside its skill
566
+ roots, so Codex inventory and the prompt guard walk `node_modules` in
567
+ `~/.codex/skills`, `~/.agents/skills`, each project's `.codex/skills` and
568
+ `.agents/skills` and configured plugin skill roots. In `~/.codex/plugins/cache`
569
+ they walk it only where it can lie in a plugin skill root: below a version's
570
+ default `skills` directory or a manifest-declared skills path, or as a
571
+ marketplace, plugin or version directory named `node_modules`; an unreadable
572
+ manifest walks every `node_modules` in its version. Dot-named directories such
573
+ as `node_modules/.pnpm`, a plugin version's own dependencies and any
574
+ `node_modules` outside a skill root stay unscanned, because Codex does not load
575
+ them; other agents' roots keep skipping `node_modules`. Depth limits are
576
+ unchanged: Codex reads six directory levels below a root, and an ordinary root
577
+ records a skill four levels down and refuses anything deeper.
578
+
544
579
  Native archives persist a version 2 recovery journal before moving payloads;
545
580
  `migrate native --json --apply` returns its `receiptPath`. The journal records
546
581
  every source, archive path, expected hash, and move status, then marks successful
@@ -626,6 +661,10 @@ non-null `sha256`, Skills also requires plain byte witnesses for that plugin's
626
661
  `hooks/hooks.json` (when present) and any string `hooks` target in the
627
662
  manifest. A manifest listed as `claude-plugin-manifest-v1` (the form Skills
628
663
  writes into the stored policy) or as `path-bytes` triggers no such requirement.
664
+ A source that the `absent-retired-claude-version` rule retains (see
665
+ [`discovery-binding`](#verify-the-stored-claude-discovery-binding-discovery-binding))
666
+ is stored exactly as listed: Skills does not project its manifest, require its
667
+ hook files or convert its marker, because the file no longer exists.
629
668
  The version-root `.orphaned_at` timestamp that Claude rewrites at startup is
630
669
  bound by presence only, as `claude-plugin-orphaned-at-v1`, and is still
631
670
  strictly validated; see
@@ -694,6 +733,27 @@ file; drift still requires a fresh explicit review. Explicit discovery inputs
694
733
  take precedence, including when their `agents` array omits a previously reviewed
695
734
  agent. The default `--agent all` still includes every supported adapter.
696
735
 
736
+ That recheck has two halves, and only one of them gates reuse. BINDING CUSTODY —
737
+ the same managed bridge, home, alias set, agent, command/profile binding and
738
+ reviewed discovery — must hold before a saved review is reused, or the plan
739
+ refuses and names a fresh explicit review. Bridge PROTECTION — the native plugin
740
+ bytes, the permission and hook rules and the bundled-skill switches — is written
741
+ by the same plan, so it is asserted in full after the writes instead of gating
742
+ the repair that fixes it; a plan that does not repair it is refused before the
743
+ receipt is written. Hermes native shell-hook trust is the exception: it is the
744
+ user's own consent and no Skills write creates it, so it stays a pre-write
745
+ condition. One implementation serves both halves, so they cannot drift apart.
746
+
747
+ Because that recheck includes the managed bridge, `hook install` cannot reuse a
748
+ saved review on a host whose bridge has since broken, and in that form it cannot
749
+ repair its own precondition. It refuses and names the reachable form,
750
+ `skills hook install --agent <agent> --discovery-inputs <review> --apply`, which
751
+ skips the retained-review precheck and rebuilds the bridge from the review in the
752
+ same transaction. A reviewed binding always carries a whole-file witness for the
753
+ agent configuration beside its projected fields, so unchanged projected fields do
754
+ not excuse a change outside them: a fresh explicit discovery review, not a
755
+ witness refresh, is the supported route.
756
+
697
757
  For reviewed Claude plugins, `skills integration plugin plan`, `admit` and
698
758
  `resolve` provide a command-source admission boundary before native discovery.
699
759
  Original packages and migrated skill/command prompts remain in private versioned
@@ -702,6 +762,25 @@ receipt permits only verified registry/cache transitions. See
702
762
  [plugin admission](docs/plugin-admission.md) for the package, review and runtime
703
763
  contracts; these commands do not change live agent registrations or settings.
704
764
 
765
+ The read-only `skills hook review-claude-candidate` check requires its reviewed
766
+ discovery inputs to bind the user settings, both project settings files and
767
+ both plugin registries. A project `.claude/settings.json` or
768
+ `.claude/settings.local.json` that the review omits is exempt only when no other
769
+ expected source shares its path and it is either absent, or present with exact
770
+ preimage bytes that parse strictly as one JSON object (strict UTF-8, no
771
+ byte-order mark, comments, trailing content or duplicate keys) and carry only
772
+ allowlisted settings: `permissions` with `allow`, `deny`, `ask` and
773
+ `defaultMode`, plus `outputStyle`, `model`, `theme`, `effortLevel`, `verbose`
774
+ and `spinnerTipsEnabled`. Any discovery key (`enabledPlugins`,
775
+ `extraKnownMarketplaces`, `additionalMarketplaces`, `skillOverrides`), `env`,
776
+ `hooks`, `permissions.additionalDirectories` or unknown key keeps the file
777
+ required. The allowlist is a reviewed list of settings, not a proof that Claude
778
+ cannot discover anything from the file. This admits the permissions-only
779
+ `~/.claude/settings.local.json` that Claude writes when it saves a permission
780
+ rule. Each exempt file is re-checked against its exact preimage until the
781
+ result; user settings and the registries are never exempt. See
782
+ [prospective Claude candidate review](docs/plugin-admission.md#prospective-claude-candidate-review).
783
+
705
784
  If your home `.claude` or `.codex` directory intentionally links to another
706
785
  directory within your home, add `--allow-root-aliases` to hook installation and
707
786
  native migration. The plan records and rechecks the exact link and target;
@@ -1009,6 +1088,216 @@ reports an incomplete outcome, inspect `sessions show` and the preserved
1009
1088
  operation receipt before retrying. The archive contains both original and
1010
1089
  prepared bytes even if the final receipt write fails.
1011
1090
 
1091
+ ### Claude installer witness CLI (`capture-claude-installer`)
1092
+
1093
+ ```text
1094
+ skills hook capture-claude-installer --request /absolute/request.json --json
1095
+ ```
1096
+
1097
+ Installers obtain Skills-owned witnesses through the configured Skills command
1098
+ instead of reimplementing them. Every request is a JSON object of at most
1099
+ 64 KiB with exactly the keys of one operation: `schema`
1100
+ (`skills.claude-installer-capture/v1`), `commandPath` (the normalized absolute
1101
+ path of the configured Skills command), `operation`, and that operation's
1102
+ inputs. The command checks that `commandPath` resolves to this installed
1103
+ `@hasna/skills` CLI and runtime, before and after the operation, and prints
1104
+ one receipt on stdout with exit status 0:
1105
+
1106
+ ```json
1107
+ {
1108
+ "schema": "skills.claude-installer-capture-result/v1",
1109
+ "producer": {
1110
+ "schema": "skills.cli-producer-identity/v1",
1111
+ "configuredCommandPath": "<commandPath>",
1112
+ "physicalLauncher": { "path": "<absolute>", "sha256": "<64 hex>" },
1113
+ "runtimeEntry": { "path": "<absolute>", "sha256": "<64 hex>" },
1114
+ "runtime": { "path": "<absolute>", "sha256": "<64 hex>" },
1115
+ "package": { "name": "@hasna/skills", "version": "<x.y.z>", "manifestSha256": "<64 hex>" }
1116
+ },
1117
+ "operation": "<operation>",
1118
+ "result": {}
1119
+ }
1120
+ ```
1121
+
1122
+ A refusal prints nothing on stdout, exits 1 and writes one line to stderr,
1123
+ `CODE: fixed text`, which never echoes request or file contents. The
1124
+ per-file operations (`settings`, `marketplace-registry`,
1125
+ `managed-plugin-registry`, `path-bytes`, `discovery-directories`,
1126
+ `plugin-manifest` and `candidate`) are described in
1127
+ [docs/plugin-admission.md](docs/plugin-admission.md#claude-installer-witness-cli).
1128
+
1129
+ #### Verify the stored Claude discovery binding (`discovery-binding`)
1130
+
1131
+ `discovery-binding` checks the Claude discovery binding stored in the Skills
1132
+ policy (`bridge.discovery.claude` in `agent-policy.json`) with the discovery
1133
+ verification the managed prompt hook runs on it: the root alias recheck,
1134
+ `verifyAgentDiscovery` and, for an automatic binding, the automatic closure
1135
+ check. It then reports every stored witness. An installer calls it once
1136
+ instead of re-capturing each stored witness. Per-file capture requires every
1137
+ file to exist, so it refuses witnesses that Skills keeps on purpose after
1138
+ Claude deletes a retired plugin-cache version; this operation reports those as
1139
+ `retained-absent`. It does not check the bridge files, hook commands or
1140
+ project-directory settings, which the hook checks separately.
1141
+
1142
+ The request has exactly these keys:
1143
+
1144
+ ```json
1145
+ {
1146
+ "schema": "skills.claude-installer-capture/v1",
1147
+ "commandPath": "/home/me/.local/bin/skills",
1148
+ "operation": "discovery-binding",
1149
+ "policyPath": "/home/me/.hasna/skills/agent-policy.json"
1150
+ }
1151
+ ```
1152
+
1153
+ `policyPath` must equal `agent-policy.json` in the data directory the installed
1154
+ package resolves (`$HASNA_SKILLS_DIR`, default `~/.hasna/skills`), as for the
1155
+ `candidate` operation.
1156
+
1157
+ The receipt's `result`:
1158
+
1159
+ ```json
1160
+ {
1161
+ "schema": "skills.claude-discovery-binding-verification/v1",
1162
+ "ok": true,
1163
+ "policySha256": "<64 hex>",
1164
+ "discoverySha256": "<64 hex>",
1165
+ "agent": "claude",
1166
+ "method": "reviewed",
1167
+ "rootCount": 2,
1168
+ "sources": [
1169
+ { "index": 0, "path": "/home/me/.claude/settings.json", "hashMode": "claude-settings-v4", "format": null, "sha256": "<64 hex>", "status": "current" },
1170
+ { "index": 3, "path": "/home/me/.claude/plugins/cache/market/plugin/1.0.0/.claude-plugin/plugin.json", "hashMode": "claude-plugin-manifest-v1", "format": null, "sha256": "<64 hex>",
1171
+ "status": "retained-absent", "retention": { "rule": "absent-retired-claude-version", "root": "/home/me/.claude/plugins/cache/market/plugin/1.0.0", "witness": "claude-plugin-manifest-v1" } }
1172
+ ],
1173
+ "directories": [ { "index": 0, "path": "/home/me/.claude/plugins/cache/market/plugin/2.0.0", "status": "current" } ],
1174
+ "failures": []
1175
+ }
1176
+ ```
1177
+
1178
+ - `policySha256` is the SHA-256 of the exact policy file bytes that were
1179
+ verified. It is the value a prospective review request passes as
1180
+ `skills.policySha256`. The policy is read again before the result is
1181
+ returned; if it changed, the request is refused.
1182
+ - `discoverySha256` is `hashClaudeDiscoveryBinding` of the stored binding, the
1183
+ same digest the `candidate` operation returns.
1184
+ - `agent`, `method` (`reviewed` or `automatic`) and `rootCount` (the number of
1185
+ stored discovery roots) come from the stored binding.
1186
+ - `sources` has one row per stored source, in stored order. `index` is the
1187
+ position in `bridge.discovery.claude.sources`. `path`, `hashMode`, `format`
1188
+ and `sha256` repeat the stored values: `hashMode` is `null` for a legacy
1189
+ full-file witness without a mode, `format` is `null` unless the source is a
1190
+ field projection (Claude reviews also keep the automatic `json` projection of
1191
+ `settings.json`), and a `null` `sha256` pins absence. `status` is one of:
1192
+ - `current`: the source's own witness reproduces the stored digest now.
1193
+ - `retained-absent`: the file was not read, because the
1194
+ `absent-retired-claude-version` rule keeps its stored digest. The rule
1195
+ holds when the whole version directory `retention.root`
1196
+ (`<...>/.claude/plugins/cache/<marketplace>/<plugin>/<version>`) is absent,
1197
+ the reviewed witnesses of `settings.json` and
1198
+ `plugins/installed_plugins.json` are current, settings enable the plugin
1199
+ and no settings hook names that directory, every registration of the
1200
+ plugin is a valid user or project row for one existing sibling version in
1201
+ the same plugin directory (with a user row among them), no registration of
1202
+ any plugin points into or contains the absent directory, and the sibling's
1203
+ `.claude-plugin/plugin.json` is bound and current. It applies only to
1204
+ reviewed bindings. `retention.witness` names the retained witness class:
1205
+ `bytes` (a full byte witness, `hashMode` `null` or `bytes`),
1206
+ `claude-plugin-manifest-v1` or `claude-plugin-orphaned-at-v1` (the typed
1207
+ presence witness of a version-root `.orphaned_at` marker). No other
1208
+ witness is retained: `path-bytes`, field projections and typed settings
1209
+ or registry witnesses stay checked. Settings and registry files are
1210
+ never retained.
1211
+ - `drift`, with `reason`: `MISSING` (the path is absent and the rule does
1212
+ not retain it), `APPEARED` (the stored witness pins absence and the path
1213
+ now exists), `CHANGED` (the path exists but its witness does not
1214
+ reproduce the stored digest or refuses the current file, for example
1215
+ edited settings or a symlink), `MARKER_INVALID` (a
1216
+ `claude-plugin-orphaned-at-v1` marker exists but is not a valid Claude
1217
+ marker; see below) or `REFUSED` (the path's presence could not be
1218
+ determined).
1219
+ - `directories` has one row per stored directory membership witness, with
1220
+ `status` `current`, or `drift` with `reason` `MEMBERSHIP_CHANGED` or
1221
+ `REFUSED`.
1222
+ - `failures` lists every drifted source and directory as
1223
+ `{ "kind": "source" | "directory", "index", "path", "reason" }`, followed by
1224
+ `{ "kind": "binding", "reason": "DISCOVERY_REFUSED" }` whenever the hook's
1225
+ own discovery verification refuses the binding. That covers checks no single
1226
+ row shows, such as a changed root alias, a retired directory that reappeared
1227
+ during verification or an invalid witness combination.
1228
+ - `ok` is `true` only when `failures` is empty: the hook's verification
1229
+ accepts the binding, every source is `current` or `retained-absent` and
1230
+ every directory is `current`.
1231
+
1232
+ `ok: false` is a completed verification and still exits 0, so the caller
1233
+ reads which witnesses drifted and why. Installers must require `ok === true`.
1234
+ To bind the result, compare each `sources` row (`index`, `path`, `hashMode`,
1235
+ `format`, `sha256`) with the binding they read themselves, compare
1236
+ `discoverySha256` with the `candidate` capture and `policySha256` with the
1237
+ policy bytes they review, and repeat the call immediately before the first
1238
+ native change, because the verdict describes one moment.
1239
+
1240
+ An installer that then passes the stored full-file sources (rows with `format`
1241
+ `null`), roots and directory witnesses back to `skills hook install --agent
1242
+ claude --discovery-inputs <file>` gets the same retention: `hook install`
1243
+ retains each `retained-absent` source with the same rule and stores it
1244
+ unchanged, so a historical `bytes` witness keeps its meaning. Every other
1245
+ source is checked and, for a fresh review, typed as usual.
1246
+
1247
+ Claude writes `.orphaned_at` at the root of a plugin-cache version it plans to
1248
+ delete (`<...>/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.orphaned_at`),
1249
+ rewrites its timestamp at each start, may replace the file, and later deletes
1250
+ the marker or the whole version. A fresh Skills discovery review binds such a
1251
+ marker as `claude-plugin-orphaned-at-v1`, a witness of its presence only, and
1252
+ `discovery-binding` reports it with that witness's own check, exactly as the
1253
+ hook does:
1254
+
1255
+ - A rewritten timestamp or a replaced file (new inode) is `current`, provided
1256
+ the marker is a regular, non-symlink file owned by the current user whose
1257
+ content is exactly 13 ASCII digits without a leading zero (no byte-order
1258
+ mark, no newline).
1259
+ - Any other content, a symlink or another owner is `drift` with
1260
+ `MARKER_INVALID`.
1261
+ - A deleted marker whose version directory still exists is `drift` with
1262
+ `MISSING`; the hook refuses this state too.
1263
+ - When Claude deletes the whole version directory and the registered sibling
1264
+ version stays bound and current, the marker and every other retainable
1265
+ witness below that directory are `retained-absent` under
1266
+ `absent-retired-claude-version`.
1267
+ - A recreated version directory is no longer absent, so each of its witnesses
1268
+ is checked again: a valid marker and an unchanged manifest are `current`,
1269
+ and a missing marker is `drift` with `MISSING`.
1270
+ - Marker witnesses stored by an older review as `bytes` or `path-bytes` keep
1271
+ their exact meaning and report `CHANGED` once Claude rewrites the marker,
1272
+ until a fresh discovery review rebinds them as typed witnesses.
1273
+
1274
+ Installers must not restore, copy back or rewrite `.orphaned_at` files, or any
1275
+ other witness file, to make a binding verify. A restored file has a new inode,
1276
+ which a `path-bytes` witness rejects, and it can hide a change Claude made. Act
1277
+ on the `discovery-binding` result instead. When it reports drift, the binding
1278
+ needs a fresh Skills discovery review (`skills hook install` with fresh
1279
+ `--discovery-inputs`), not a file repair.
1280
+
1281
+ Refusal codes for this operation, besides the shared request and producer
1282
+ codes (`INVALID_REQUEST_FILE`, `INVALID_REQUEST_JSON`, `INVALID_REQUEST`,
1283
+ `INVALID_SCHEMA`, `INVALID_REQUEST_FIELDS`, `INVALID_PATH`,
1284
+ `PRODUCER_UNVERIFIED`, `PRODUCER_CHANGED` and `CAPTURE_REJECTED`):
1285
+
1286
+ - `POLICY_PATH_MISMATCH`: `policyPath` is not the package-owned policy path.
1287
+ - `POLICY_UNAVAILABLE`: the policy file is absent.
1288
+ - `POLICY_UNREADABLE`: the policy is not a regular, bounded, valid managed
1289
+ policy file.
1290
+ - `BINDING_UNAVAILABLE`: the policy stores no Claude discovery binding.
1291
+ - `BINDING_INVALID`: the stored binding is not a Claude binding with a
1292
+ `reviewed` or `automatic` method, or its sources, directories or root
1293
+ aliases do not match the binding schema.
1294
+ - `POLICY_CHANGED`: the policy changed while it was being verified.
1295
+ - `DISCOVERY_BINDING_REJECTED`: any other failure.
1296
+
1297
+ The operation is read-only. It reads the policy and the stored witness paths
1298
+ and directories. It writes no file, cache, selection pin or policy, and it does
1299
+ not start Claude or change native state.
1300
+
1012
1301
  ## Profiles, station sync and rollback
1013
1302
 
1014
1303
  ```bash
@@ -1034,6 +1323,50 @@ for the named station; it is not a native-folder snapshot in this mode.
1034
1323
  `skills install --selection-profile default` without skill names also syncs the
1035
1324
  whole selection.
1036
1325
 
1326
+ ### Reading provenance instead of trusting one record
1327
+
1328
+ Applying a record is not adoption, and the four facts below are different. Only
1329
+ `skills provenance` reports them together, read-only:
1330
+
1331
+ - `selected` — the shared profile the authority serves right now;
1332
+ - `activated` — the snapshot this machine last verified and activated, which is
1333
+ what its hooks, `skills context` and `skills load` resolve from;
1334
+ - `applied` — the station receipt the authority holds. Only an explicit
1335
+ `skills sync` writes it; the managed hook keeps station reporting off its
1336
+ blocking lifecycle path on purpose, so this record legitimately lags the
1337
+ activation and is not by itself evidence that a machine is adrift;
1338
+ - `pinned` — the exact immutable profile revision one live session holds. A
1339
+ session keeps its revision when the profile moves on, so an older pin is
1340
+ custody by design, not drift;
1341
+ - `consumed` — the skills that session actually loaded, at their exact versions.
1342
+
1343
+ ```bash
1344
+ skills provenance --json
1345
+ skills provenance --session <session-id> --json
1346
+ skills provenance --station station-example --json
1347
+ ```
1348
+
1349
+ Every consumer is classified `current`, `behind`, `pinned` or `unverified`, and
1350
+ always carries a stable `reasonCode` and its reason. Identity is part of the
1351
+ comparison: a revision that matches under a different authority, workspace or
1352
+ profile is `IDENTITY_MISMATCH`, not `current`, so a foreign pin is never
1353
+ reported as adopted and is never diffed. Each receipt source declares the
1354
+ identity fields it must record, so a receipt that omits one — or carries `null` or
1355
+ an empty string where a nonempty string is required, which the HTTP reader also
1356
+ passes through — is `INCOMPLETE_RECEIPT`, not `current` and not `behind`: an
1357
+ absent revision is not an older revision. The local activation is named as this
1358
+ machine and the authority receipt as the station named on the command line; the
1359
+ two are never collapsed into one id. The receipt also states what it does not
1360
+ attest — published version and digest evidence, native discovery and locks, and
1361
+ live consumer adoption — rather than letting a clean-looking result imply them.
1362
+ `drift` lists the bundles whose exact versions differ. The command reads and
1363
+ never writes a pin, receipt, cache entry or station record, and it renders no
1364
+ skill payload and no credential: a reader's exception text is never carried,
1365
+ only a fixed diagnostic code, because bounding foreign text is not redacting it.
1366
+ With `--cached`, or when the authority cannot be read, the reference is the
1367
+ locally synced snapshot and every consumer is reported `unverified` rather than
1368
+ `current` — a local snapshot cannot establish adoption.
1369
+
1037
1370
  After hook installation has enabled CLI loading, pull operations obey the same
1038
1371
  profile. `--all` refreshes its selected versions rather than the full catalog,
1039
1372
  and a named pull must belong to that profile:
@@ -1438,6 +1771,7 @@ of app folders, and `XDG_CONFIG_HOME` is not consulted at all.
1438
1771
  | `skills context <prompt> --selection-profile <id>` | | Resolve instructions matching the prompt and profile triggers |
1439
1772
  | `skills hook install --selection-profile <id>` | | Plan bridges and hooks for configured/detected consumers; `--agent <agent>` selects one, explicit `--agent all` requires every adapter; `--apply` installs them, then restart and trust the hooks |
1440
1773
  | `skills sessions show <id> --json` | | Inspect one session's exact profile revision and receipt hash without loading payloads |
1774
+ | `skills provenance [--session <id>] [--station <id>] --json` | `--cached` | Read-only receipt of the selected, activated, applied, pinned and actually loaded skill versions, each with its status and reason; writes nothing |
1441
1775
  | `skills sessions reconcile <id> --from-profile <id> --from-revision <rev> --receipt-sha256 <sha> --selection-profile <id> --profile-revision <rev>` | | Plan an explicit migration of one live session; `--apply --plan-digest <digest> --plan-issued-at <time> --plan-expires-at <time>` (within five minutes) preserves its old receipt and applies the reviewed replacement |
1442
1776
  | `skills hook agents --json` | | Report maintained adapters and explicit coverage limits |
1443
1777
  | `skills migrate native` | | Inventory native copies; `--apply` archives managed copies, with explicit `--include-unmanaged`, `--include-vendor`, or reviewed `--target-manifest` selection |
@@ -2850,6 +3184,17 @@ Review the plan before adding `--apply`; the original review preimage must match
2850
3184
  its original mode, and unrelated changes refuse. This preserves the native
2851
3185
  configuration, root aliases, other witnesses and active session pins.
2852
3186
 
3187
+ Verifying a typed Codex settings witness from `codex-settings-v1` to
3188
+ `codex-settings-v5` also accepts the one write Codex 0.162.1 makes on its own
3189
+ first TUI or desktop launch: the boolean `tui.screen_reader_detection_done`
3190
+ receipt, added, removed or flipped (V6 already omits it). No digest changes
3191
+ meaning, and verification alone records or rebinds nothing. A non-boolean receipt, any other TUI key
3192
+ (including the `animations = false` Codex adds when it detects a screen
3193
+ reader) and every other change still drift, including Codex's
3194
+ `[projects."<dir>"]` trust entries. A planned Skills write to `config.toml`
3195
+ rebinds the witness to the written document, which adopts at most that
3196
+ receipt.
3197
+
2853
3198
  `claude-settings-v4` is an explicit successor to `claude-settings-v3`. It
2854
3199
  additionally ignores only a top-level `theme` whose value is exactly one of the
2855
3200
  documented built-in values (`auto`, `dark`, `light`, `dark-daltonized`,