diff --git a/.changes/harness-config/docs-drop-pointer-stamps-harness-config-memory-3b9e41c7.md b/.changes/harness-config/docs-drop-pointer-stamps-harness-config-memory-3b9e41c7.md new file mode 100644 index 00000000000..b6bdc3f861e --- /dev/null +++ b/.changes/harness-config/docs-drop-pointer-stamps-harness-config-memory-3b9e41c7.md @@ -0,0 +1,7 @@ +--- +bump: patch +--- + +### Changed + +- Pointer records no longer carry an as-of date or recheck trigger; stored values keep theirs. diff --git a/.changes/harness-memory/docs-drop-pointer-stamps-harness-config-memory-8d2a5f16.md b/.changes/harness-memory/docs-drop-pointer-stamps-harness-config-memory-8d2a5f16.md new file mode 100644 index 00000000000..b6bdc3f861e --- /dev/null +++ b/.changes/harness-memory/docs-drop-pointer-stamps-harness-config-memory-8d2a5f16.md @@ -0,0 +1,7 @@ +--- +bump: patch +--- + +### Changed + +- Pointer records no longer carry an as-of date or recheck trigger; stored values keep theirs. diff --git a/plugins/harness-config/README.md b/plugins/harness-config/README.md index f53279769cc..f61a80a8925 100644 --- a/plugins/harness-config/README.md +++ b/plugins/harness-config/README.md @@ -82,9 +82,8 @@ and inert plugin self-grants. A deterministic detector scans skill/command/agent bare-command-on-PATH pattern. A broad rule in the user-global file (`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json`) reaches every project. The remediation of a finding there is the operator's, since no skill can write that file. Where a prompt approval is -saved is in [permissions: permission system](https://code.claude.com/docs/en/permissions#permission-system) -(as of 2026-11-04; recheck when that section changes the file). The principle and citations live in the marketplace -[permission-rule-hygiene convention](../../docs/contracts/permission-rule-hygiene/README.md). +saved is in [permissions: permission system](https://code.claude.com/docs/en/permissions#permission-system). +The principle and citations live in the marketplace [permission-rule-hygiene convention](../../docs/contracts/permission-rule-hygiene/README.md). Report-only. ```shell diff --git a/plugins/harness-config/reference/agents-md-liveness.md b/plugins/harness-config/reference/agents-md-liveness.md index 6a951768a2e..88caa396266 100644 --- a/plugins/harness-config/reference/agents-md-liveness.md +++ b/plugins/harness-config/reference/agents-md-liveness.md @@ -30,9 +30,6 @@ For such a session the remedy we recommend is a `CLAUDE.md` that imports the `AG - **Pointer**: when deciding whether `AGENTS.md` support is available, fetch [memory: when AGENTS.md support is unavailable](https://code.claude.com/docs/en/memory#when-agents-md-support-is-unavailable) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: a condition is added to or removed from that section's list, or its remedy - changes. **No hooks setting is an availability condition.** The built-in plugin that reads `AGENTS.md` is a built-in mod, so our @@ -47,10 +44,8 @@ it. A session that loads no instruction files at all (`--bare` without `--add-di live; for the plugin's own statement, read its [README](https://github.com/anthropics/claude-code/blob/main/mods/agents-md/README.md) at commit `2282079d6ac8`. -- **As of**: 2026-10-18 for the two docs sections; 2026-10-01 for the README commit. -- **Recheck trigger**: the overview's built-in-mods section or the settings reference's - `allowManagedHooksOnly` section changes which settings stop built-in mods, or the README's - settings paragraph changes. +- **As of**: 2026-10-01 for the README commit. +- **Recheck trigger**: the README's settings paragraph changes. **Two of the three kinds resolve from what this plugin already reads.** A version condition is a comparison against the floor the pointer states, plus the provider and telemetry configuration diff --git a/plugins/harness-config/skills/audit-automation-gaps/SKILL.md b/plugins/harness-config/skills/audit-automation-gaps/SKILL.md index 1a80a415c92..b76623a83fd 100644 --- a/plugins/harness-config/skills/audit-automation-gaps/SKILL.md +++ b/plugins/harness-config/skills/audit-automation-gaps/SKILL.md @@ -50,9 +50,6 @@ call. This paragraph is a boundary, not a routing verdict. - **Pointer**: when you need what `/hooks` lists, or what it shows for a selected hook, fetch [the /hooks menu](https://code.claude.com/docs/en/hooks#the-/hooks-menu) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section stops showing each hook's source, or the menu stops listing - the resolved set of configured hooks. ## Adapting to your environment (graceful degrade) @@ -172,8 +169,6 @@ control upstream says it never fires, which no local reading surfaces. - **Pointer**: when a candidate gates on a hook event's exit code, fetch that event's decision control live, for example [hooks: PermissionRequest decision control](https://code.claude.com/docs/en/hooks#permissionrequest-decision-control). -- **As of**: 2026-11-10 -- **Recheck trigger**: that section changes which exit codes or decision fields the event honors. **Conditional: facts the harness does not own.** Third-party tool performance, an ecosystem's standard formatter, server stability and auth, known issues in a tool the candidate would run. Fetch @@ -296,8 +291,6 @@ hook type reaches, **Already enforced** to a deterministic finding already escal - **Pointer**: before proposing a `prompt` or `agent` hook, fetch its status and fields live at [hooks: prompt and agent hook fields](https://code.claude.com/docs/en/hooks#prompt-and-agent-hook-fields). -- **As of**: 2026-11-10 -- **Recheck trigger**: that section changes either type's status or the fields it accepts. Produce a verdict per candidate: @@ -384,7 +377,6 @@ script exits 2 rather than guessing when it is missing. - **Pointer**: when deciding how a script receives a plugin path variable, fetch [plugins manifest reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live. -- **As of**: 2026-11-10 - **Recheck trigger**: that section starts exporting the variable to commands run through the Bash tool. @@ -403,9 +395,6 @@ only durable copy, and an uninstall can delete it. - **Pointer**: when deciding whether the findings survive an uninstall, fetch [plugins CLI reference: what an uninstall deletes and keeps](https://code.claude.com/docs/en/plugins/cli-reference#what-an-uninstall-deletes-and-keeps) live. -- **As of**: 2026-11-10 -- **Recheck trigger**: that section changes whether the plugin data directory survives an - uninstall. ## Phase 4: Implement (if `--implement` or user requests) diff --git a/plugins/harness-config/skills/audit-automation-gaps/context/gap-analysis.md b/plugins/harness-config/skills/audit-automation-gaps/context/gap-analysis.md index c543195f1f4..3f1ea464a09 100644 --- a/plugins/harness-config/skills/audit-automation-gaps/context/gap-analysis.md +++ b/plugins/harness-config/skills/audit-automation-gaps/context/gap-analysis.md @@ -11,12 +11,8 @@ The placement rules above, the 1 s and 60 s lines among them, are this marketplace's house rules, not upstream guidance: [check-placement](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/contracts/check-placement/README.md#the-rubric). A consuming repo that documents its own placement rules overrides them. - **Pointer**: for what `PostToolBatch` receives and when it fires, fetch [hooks: PostToolBatch](https://code.claude.com/docs/en/hooks#posttoolbatch) live. -- **As of**: 2026-10-15 -- **Recheck trigger**: that section adds a matcher or `if` support, or stops firing once per batch of parallel tool calls. - **Pointer**: when deciding whether a need calls for a mod rather than a settings hook, a skill or an MCP server, fetch [mods overview: compare mods, settings hooks, skills, and MCP servers](https://code.claude.com/docs/en/plugins/mods/overview#compare-mods-settings-hooks-skills-and-mcp-servers) live; for status entries, toasts and tools, read the built-in `plugin-authoring` skill's "From the ask to the shape" table. -- **As of**: 2026-10-18 -- **Recheck trigger**: either "Pick it when" cell for mods or settings hooks changes, or a release lets a settings hook draw in the interface. **MCP Servers**: For each external service the repo interacts with: diff --git a/plugins/harness-config/skills/audit-instructions/SKILL.md b/plugins/harness-config/skills/audit-instructions/SKILL.md index 9f02b2034b4..f12589a0c56 100644 --- a/plugins/harness-config/skills/audit-instructions/SKILL.md +++ b/plugins/harness-config/skills/audit-instructions/SKILL.md @@ -39,8 +39,7 @@ Phase D's `persist-report.sh`. Either can mutate a file this skill has already r this is an instruction-held contract with a narrowed accident surface, not an enforced one. Never describe it to an operator as a guarantee. We treat the restriction as clearing on the operator's next message, so whoever accepts a diff can apply it (Pointer: the -[skills frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference). -As of: 2026-08-12. Recheck trigger: that section changes how long the restriction lasts). `audit-prompting-postures` carries the identical declaration and caveat: both state one contract. +[skills frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference)). `audit-prompting-postures` carries the identical declaration and caveat: both state one contract. ## Scope boundary (route out) @@ -259,7 +258,7 @@ the budget as a line count: the line figure is derived per run from the bytes pe We size a lane by the context window of the model the lane runs on, never the parent's (Pointer: when deciding whose window sizes a lane, fetch [subagents: what loads at startup](https://code.claude.com/docs/en/sub-agents#what-loads-at-startup) -live. As of: 2026-10-11. Recheck trigger: that section changes how a subagent's window is sized). +live). `` is the `--window-tokens` value: the context window in tokens of the model the lane runs on. When the lane's model resolves to no documented window, pass 200000, our setting for @@ -348,7 +347,7 @@ what belongs to `harness-memory:audit`'s C6 instead. Every removal or rewrite proposal is re-judged before it reaches the report, at the `standard` and `strict` verification levels: resolve the level with `bash "${CLAUDE_PLUGIN_ROOT}/lib/read-verification.sh" --plugin harness-config --skill audit-instructions` and copy its line into the report header ([levels](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/contracts/verification-level/README.md)). Under `light`, and `off`, which acts as `light` here, dispatch no Phase C verifier and never re-judge inline in its place: follow "When dispatch is unavailable" below with every verification mode `skipped` for the reason `verification: skipped ()`. Dispatch **fresh-context, non-fork** subagents, since this is a self-grade of the audit's own proposals and a fork that inherits the producing context would not be independent (pointer: when checking what a fork inherits, fetch [How forks differ from other subagents](https://code.claude.com/docs/en/sub-agents#how-forks-differ-from-other-subagents) -live; as of 2026-11-01, recheck when that table changes what a fork inherits), prompted to refute: "would removing this instruction cause Claude to make mistakes? Argue that it is still load-bearing." Where the removal call is +live), prompted to refute: "would removing this instruction cause Claude to make mistakes? Argue that it is still load-bearing." Where the removal call is high-stakes and correlated blind spots are the risk, prefer a cross-vendor advisor **when one is installed and set up**, e.g. the OpenAI Codex plugin, invoked per its own docs, with the fresh-context same-vendor subagent as the stated fallback, never a route to a command that may not @@ -373,7 +372,7 @@ gate fails, dropped for that named reason. ### When dispatch is unavailable Phases B and C **require** fresh-context, non-fork subagent dispatch. When the Agent tool is -blocked, unavailable, or the session cannot spawn subagents (including a nested session at the spawn-depth limit; Pointer: when this skill runs inside a subagent, fetch [subagents: let subagents spawn their own subagents](https://code.claude.com/docs/en/sub-agents#let-subagents-spawn-their-own-subagents) live. As of: 2026-10-11. Recheck trigger: that section changes the depth limit or what a subagent at it can spawn): +blocked, unavailable, or the session cannot spawn subagents (including a nested session at the spawn-depth limit; Pointer: when this skill runs inside a subagent, fetch [subagents: let subagents spawn their own subagents](https://code.claude.com/docs/en/sub-agents#let-subagents-spawn-their-own-subagents) live): 1. **Disclose in the report header** which phases ran inline, which were skipped, and why dispatch was unavailable, so a run that skipped verification is distinguishable from a verified one. @@ -475,7 +474,7 @@ plainly that nothing has been applied. - **Examples are not scaffolding.** Flag an example block only when it pins the model's *approach* to a task, never when it steers output format; for how many to keep, fetch [use examples effectively](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#use-examples-effectively) - live (as of 2026-11-03; recheck when that section changes how many examples or what they should steer). + live. - **Bare-prohibition rewrites go positive first.** The primary remediation is "say what to do instead of what not to do"; adding a rationale is the fallback where a genuine hard "never" survives. Do not mechanically delete every prohibition the pre-scan flags. diff --git a/plugins/harness-config/skills/audit-instructions/context/phase-a-inventory.md b/plugins/harness-config/skills/audit-instructions/context/phase-a-inventory.md index f6390c3153b..e81c8b53fc0 100644 --- a/plugins/harness-config/skills/audit-instructions/context/phase-a-inventory.md +++ b/plugins/harness-config/skills/audit-instructions/context/phase-a-inventory.md @@ -11,14 +11,12 @@ official memory and `.claude`-directory docs (cited in the report's Sources line - User: resolve the root as `${CLAUDE_CONFIG_DIR:-~/.claude}`, never a hardcoded `~/.claude`, then: `CLAUDE.md`, `rules/`, `skills/`, `agents/`, `output-styles/` under that root. When deciding what the variable relocates, fetch - [env vars: variables](https://code.claude.com/docs/en/env-vars#variables) live (as of - 2026-11-03; recheck when its `CLAUDE_CONFIG_DIR` row changes what the variable moves). + [env vars: variables](https://code.claude.com/docs/en/env-vars#variables) live. - Project: `./CLAUDE.md` or `./.claude/CLAUDE.md`, `./CLAUDE.local.md`, and every nested `CLAUDE.md` / `CLAUDE.local.md` in subdirectories of the project tree (Claude loads these on demand once it works with a file in those directories, so walk the tree and do not stop at the root; what counts is at - [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load), - as of 2026-11-04, recheck when that section changes what loads a nested file); + [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load)); `.claude/rules/`, `.claude/skills/`, `.claude/agents/`, `.claude/output-styles/`. - **A natively read `AGENTS.md`**: `./AGENTS.md` and `./.claude/AGENTS.md`, each its own record, and every nested `AGENTS.md` in subdirectories of the project tree, on the same on-demand footing as @@ -26,8 +24,7 @@ official memory and `.claude`-directory docs (cited in the report's Sources line instruction-files mode and on the CLAUDE.md files along its own path, so **test it per file, never once at the root**. When deciding whether a file is displaced, fetch [memory: choose which instruction files load](https://code.claude.com/docs/en/memory#choose-which-instruction-files-load) - live (as of 2026-11-03; recheck when that section changes which files displace an - `AGENTS.md`). A displaced file that an import or a symlink brings in is covered by the importing + live. A displaced file that an import or a symlink brings in is covered by the importing record, not a record of its own. The root case is the condition `harness-memory`'s `skills/audit/scripts/lib/agents-md.sh` encodes. **Displacement is that mode's answer, not the only one, and this bullet does not restate the @@ -67,8 +64,7 @@ official memory and `.claude`-directory docs (cited in the report's Sources line frontmatter hook can register under a different event than the one it names, so resolve the effective event from [subagents: hooks in subagent frontmatter](https://code.claude.com/docs/en/sub-agents#hooks-in-subagent-frontmatter) - before pairing (both pointers as of 2026-10-11; recheck when either section changes a frontmatter - hook's lifetime or the event it registers under). Two kinds, and the discriminator is **whether + before pairing. Two kinds, and the discriminator is **whether the handler's output reaches this session's context, never the handler's `type`** ([reference/conflict-criteria.md](../reference/conflict-criteria.md) owns the distinction and its citations): @@ -140,8 +136,7 @@ involving one still carries the no-change representation and its routing recomme `CLAUDE_CODE_DISABLE_AUTO_MEMORY` first, then `autoMemoryEnabled` across the settings scopes. When deciding what each value means, which one wins and what the default is, fetch [memory: enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory) - live (as of 2026-11-03; recheck when that section changes the variable, the setting or how they - combine). Reading a lower-scope `false` as decisive would drop a `MEMORY.md` a + live. Reading a lower-scope `false` as decisive would drop a `MEMORY.md` a higher-precedence scope re-enabled, and inventorying unconditionally would pair live instructions against a file left on disk after auto memory was turned off, the same defect as reading a disabled plugin's cache. `/harness-memory:stateless` owns this resolver; its `status` action reports @@ -151,8 +146,7 @@ involving one still carries the no-change representation and its routing recomme I15 precisely because `harness-memory`'s C6 does not read it, so excluding it outright would leave a `MEMORY.md`-versus-`CLAUDE.md` contradiction audited by neither skill. Only the content that actually loads is compared, the loaded portion - [memory: how it works](https://code.claude.com/docs/en/memory#how-it-works) names (as of - 2026-10-11; recheck when that portion changes); topic files beside it are read on demand and are + [memory: how it works](https://code.claude.com/docs/en/memory#how-it-works) names; topic files beside it are read on demand and are not resident. Ownership is unchanged: `harness-memory` still owns auto memory, and a finding here routes there rather than editing it. - **Each enabled agent's own memory, under that same gate**: an agent definition carrying a @@ -160,15 +154,15 @@ involving one still carries the no-change representation and its routing recomme per agent, and that subagent reads and writes its own `MEMORY.md` there. The field's value is the scope, and each scope has its own location; read the scope-to-directory mapping from [subagents: enable persistent memory](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory) - live (as of 2026-10-11; recheck when a scope or its directory changes), and resolve a user-scope + live, and resolve a user-scope directory under the **resolved** user root above, never a hardcoded `~/.claude`. [reference/conflict-criteria.md](../reference/conflict-criteria.md) keeps an agent-definition-versus- its-own-memory contradiction in scope precisely because those two *do* co-reside in that subagent, so this inventory has to reach it: enumerate that `MEMORY.md` for every inventoried agent whose definition enables the field, under the same loaded-portion bound. The gate is the effective state resolved just above: enumerate agent memory only when auto memory is on, for the dependency - recorded at [sub-agents](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory) - (as of 2026-10-07; recheck trigger: that section's auto-memory dependency changes); an agent + recorded at [sub-agents](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory); an + agent memory left on disk after the switch flipped is not inventoried. Read-only and `harness-memory`-owned exactly as the main entrypoint is. - **Org-managed policy**: the managed-policy `CLAUDE.md`, any `claudeMd` value in managed settings, @@ -189,8 +183,8 @@ involving one still carries the no-change representation and its routing recomme ship styles in an `output-styles/` directory, and a plugin style with `force-for-plugin` can be active without the user selecting it - ([output styles: create a custom output style](https://code.claude.com/docs/en/output-styles#create-a-custom-output-style), - as of 2026-10-11; recheck when that section changes how `force-for-plugin` applies). Resolve + ([output styles: create a custom output style](https://code.claude.com/docs/en/output-styles#create-a-custom-output-style)). + Resolve which style is actually active, a `force-for-plugin` style from the enabled set first, else the `outputStyle` value, which may itself name a plugin-supplied style, and inventory that one. Only the active style is resident, so the others stay out of the corpus. Enablement is diff --git a/plugins/harness-config/skills/audit-instructions/context/report-keying.md b/plugins/harness-config/skills/audit-instructions/context/report-keying.md index 494c15f09c7..0914fafb0f1 100644 --- a/plugins/harness-config/skills/audit-instructions/context/report-keying.md +++ b/plugins/harness-config/skills/audit-instructions/context/report-keying.md @@ -18,9 +18,8 @@ command of your own, against the plugin data directory. [plugins manifest reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live; for why an inline command against the data directory is avoided, read the eval-trace evidence in #12039. -- **As of**: 2026-11-01 -- **Recheck trigger**: that section changes which environments receive `${CLAUDE_PLUGIN_DATA}`, or - a later eval trace shows an inline command against the data directory running undenied. +- **Recheck trigger**: a later eval trace shows an inline command against the data directory + running undenied. The key is `/`, implemented once in the shared `lib/state-key.sh` that @@ -35,8 +34,6 @@ yours to evaluate. Derive the key from the command. - **Pointer**: when deciding how a skill placeholder reaches the body, fetch [skills: available string substitutions](https://code.claude.com/docs/en/skills#available-string-substitutions) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section changes where or when `${CLAUDE_PROJECT_DIR}` is substituted. ## Why the key matters in this skill specifically @@ -52,9 +49,6 @@ larger one. - **Pointer**: when deciding what `${CLAUDE_PLUGIN_DATA}` is keyed to, fetch [plugin manifest reference: environment variables](https://code.claude.com/docs/en/plugins/manifest-reference#environment-variables) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section keys the data directory to anything beyond the plugin, such as - the project. ## Two absent-prior cases, and they are not the same diff --git a/plugins/harness-config/skills/audit-instructions/reference/conflict-criteria.md b/plugins/harness-config/skills/audit-instructions/reference/conflict-criteria.md index 7d8cf887afd..0dece8d5580 100644 --- a/plugins/harness-config/skills/audit-instructions/reference/conflict-criteria.md +++ b/plugins/harness-config/skills/audit-instructions/reference/conflict-criteria.md @@ -33,23 +33,12 @@ surface. That governance question is recorded as rejected for this repository in `docs/out-of-scope/shared-surface-instruction-governance.md` (#3568). `instruction-exception-register` governs deletions only, not ownership. **Claim:** I15 does not assign shared-surface ownership. **Basis:** this file's pair-detection -charter; the rejected-concept ledger entry for #3568. **As of:** 2026-09-28. **Recheck:** when -that ledger's recheck fires. +charter; the rejected-concept ledger entry for #3568. **Recheck:** when that ledger's recheck +fires. The three shared axes (evidence tier, authority, severity) are defined once in [criteria.md](criteria.md) and are not restated here. -**Recheck triggers** (as of 2026-10-11). Re-verify against live docs when any fires: a change to the memory page's -precedence or load-order text; a change to the skills page's statements about instruction authority; -any new instruction surface added to the product; a change to how permission rules or permission -modes remove a tool from Claude's pool; a change to **which hook events inject handler output into -the session's context**, to the events `additionalContext` is accepted on, or to the handler types -that can return it; the removal, renaming, or restructuring of the hooks page's **per-event exit-2 -table** this file defers to for blockability, or a change to the set of locations a hook may be -declared in; a change to the table's `SubagentStop`, `PostToolUse`, or `PreToolUse` rows, the -three the worked examples below cite. A row added to the table, or a change to any row this file -does not cite, needs no recheck, because the partition itself is never restated here. - ## Sources Every residency and precedence decision below points at the section it rests on, and the pass reads @@ -128,8 +117,8 @@ corpus of realistic prompts to test instruction surfaces against is a different filed separately, not as an I15 extension. **Claim:** I15 does not adjudicate standing instructions against plausible user requests. **Basis:** this file's Prerequisite: co-residency section and the owner decision on #3565. -**As of:** 2026-09-29. **Recheck:** when the co-residency prerequisite changes or a bounded, -enumerable request corpus is filed as its own artifact. +**Recheck:** when the co-residency prerequisite changes or a bounded, enumerable request corpus is +filed as its own artifact. ## Prerequisite: co-residency @@ -162,9 +151,6 @@ preload limit from those sections when it runs. This table copies none of them, moved without an edit here. - **Pointer**: when deciding whether a surface is resident, fetch the section its row names live. -- **As of**: 2026-11-04 -- **Recheck trigger**: a row's section is renamed or removed, or it adds or drops a condition on - when that surface loads. **The `AGENTS.md` row's residency is conditional on availability and the mode, not on displacement alone.** Availability comes first: a session that reads no `AGENTS.md` at all, for any of the @@ -175,7 +161,7 @@ question would report a conflict against a surface nothing loads. Resolve both, condition stays unresolved, **do not assert residency for it**: I15 is a finding lane, so an unestablished residency is a leave-alone rather than a pair to judge, exactly as the record's finding-lane rule says and as gate 1 already treats every other surface whose residency is not -established. Both carry their dated records, with the settings scopes and the key the +established. Both are recorded, with the settings scopes and the key the mode lives under, in [agents-md-liveness.md](../../../reference/agents-md-liveness.md). **An agent definition co-resides with the CLAUDE.md files its subagent loads, and by default that @@ -202,9 +188,6 @@ restate the rule in the delegation prompt rather than to reconcile the two surfa - **Pointer**: when deciding which CLAUDE.md files and which auto memory reach a subagent, fetch [subagents: what loads at startup](https://code.claude.com/docs/en/sub-agents#what-loads-at-startup) and [memory: how it works](https://code.claude.com/docs/en/memory#how-it-works) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: the startup section adds or drops an agent that skips CLAUDE.md, changes what - the opt-out field leaves loaded, or adds another per-agent control over it. **Only the active output style is resident, and only in the main conversation.** A style becomes active through the `outputStyle` setting or a plugin's `force-for-plugin`; every other style on disk @@ -219,17 +202,12 @@ for the turn in question. [output styles: change your output style](https://code.claude.com/docs/en/output-styles#change-your-output-style) and [subagents: what loads at startup](https://code.claude.com/docs/en/sub-agents#what-loads-at-startup) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: one of those sections changes whether a style reaches a subagent or when a - switch takes effect. **A prompt hook's text is not an instruction to the main session.** A `type: "prompt"` handler's text goes to a separate evaluator model call that returns a decision, and is never injected into the main conversation -([hooks: prompt and agent hook fields](https://code.claude.com/docs/en/hooks#prompt-and-agent-hook-fields), -as of 2026-10-11; recheck when that section lets a prompt handler's text reach the session's -context). Comparing that raw -prompt against a `CLAUDE.md`, a skill, or an output style manufactures conflicts between two models +([hooks: prompt and agent hook fields](https://code.claude.com/docs/en/hooks#prompt-and-agent-hook-fields)). +Comparing that raw prompt against a `CLAUDE.md`, a skill, or an output style manufactures conflicts between two models that satisfy their own instructions independently: an evaluator told to *return JSON only* does not contradict a main-session rule requiring Markdown output. @@ -266,9 +244,6 @@ stdout channel, while it may still use the `additionalContext` channel on an eve [hooks: add context for Claude](https://code.claude.com/docs/en/hooks#add-context-for-claude) and the event's own section (for example [hooks: SessionStart](https://code.claude.com/docs/en/hooks#sessionstart)) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: the handler types change, an event is added to or dropped from either - channel's event set, or an event changes which handler types it accepts. So **a handler whose output is injected as context enters the comparison set as that text**, on the same terms as any other instruction surface. A `SessionStart` command hook printing a standing @@ -292,8 +267,6 @@ comparison set, so read its hook rows for the residency consequences below and n - **Pointer**: when deciding what hook-injected text survives a compaction, fetch [context window: what survives compaction](https://code.claude.com/docs/en/context-window#what-survives-compaction) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: the table adds, drops or changes a row about hooks or hook-added context. Three consequences for residency, and each one bounds a pair rather than admitting it wholesale: @@ -311,9 +284,7 @@ Three consequences for residency, and each one bounds a pair rather than admitti Whether it also carries a *gate* is event-specific too, and the sole authority on both is the hooks page's [Exit code 2 behavior per event](https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event) - table (as of 2026-11-04; recheck when the table is renamed, removed or restructured, or its - `SubagentStop`, `PostToolUse` or `PreToolUse` row changes, the three cited below). Its rows are not - reproduced here in either direction: the event set grows, so any list + table. Its rows are not reproduced here in either direction: the event set grows, so any list copied into this file becomes a closed partition that silently misgrades the next event added. Resolve the handler's event, read that event's row, and pair on the row's own `Can block?` cell: - **The cell says yes.** The conflict-bearing content is whatever that row states is prevented, @@ -510,16 +481,13 @@ precedence the docs decline to state. - **Pointer**: when grading a pair's precedence, fetch the section its row names live; a row whose section now states a winner, or no longer states one, moves between the two tables. -- **As of**: 2026-10-11 -- **Recheck trigger**: one of those sections adds, removes or changes a statement of which - instruction surface wins. **The escape hatch worth naming.** Because a mechanism outranks instruction text, an instruction-level conflict that keeps recurring is often best resolved by moving one side to a mechanism rather than by rewriting prose: a `PreToolUse` hook, a `permissions.deny` rule, or, for a tool a specific skill must never call, the skill's own `disallowed-tools` frontmatter (what it removes and for how long: -[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference), as of -2026-10-11; recheck when that field's row changes). Offer this as an option; the choice is the +[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference)). +Offer this as an option; the choice is the operator's. **Check first that the mechanism resolves the pair rather than breaking one side.** Both tool-removal @@ -684,8 +652,8 @@ exists on its own grounds, because a mandate naming a tool that can be absent (p away; see [permission modes: dontAsk](https://code.claude.com/docs/en/permission-modes#allow-only-pre-approved-tools-with-dontask-mode), [permissions: manage permissions](https://code.claude.com/docs/en/permissions#manage-permissions) and -[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference), as of -2026-10-11; recheck when one of them stops removing or denying the tool) is unsatisfiable in exactly +[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference)) is +unsatisfiable in exactly the sessions that most need a gate. It is not a verdict on the pair. Run the gates against the current text as you would for any pair, and do not assume that the pair dissolved because one side acquired a condition (gate 5 is unaffected; see above) or that a softened verb settles gate 3, whose deciding branch is the one where diff --git a/plugins/harness-config/skills/audit-instructions/reference/criteria.md b/plugins/harness-config/skills/audit-instructions/reference/criteria.md index a17337ab098..c1f79d5998a 100644 --- a/plugins/harness-config/skills/audit-instructions/reference/criteria.md +++ b/plugins/harness-config/skills/audit-instructions/reference/criteria.md @@ -225,13 +225,9 @@ each only on the surfaces its row names. - Skills (what loads when, how supporting files are referenced, the listing budget, invocation-control fields): - How features layer (per-surface precedence): - . - As of: 2026-10-11 (anchor as recorded by the pointer audit of that date, not re-fetched since). - Recheck trigger: the layering section starts covering routing between surfaces, or is renamed. + - Routing between surfaces: - . - As of: 2026-10-11 (anchor as recorded by the pointer audit of that date, not re-fetched since). - Recheck trigger: the compare section is renamed, or stops comparing where content belongs. + - Context window (what survives compaction): - Hooks (handler types, and which events inject handler output into context): @@ -378,10 +374,7 @@ Tier `mechanical` · Authority `ANTHROPIC-DOCS` · Severity `warning` · Surface (`skillOverrides` and plugin skills); subagents, the `skills:` field (preloaded skill content). Pointer: , and - . As of: 2026-08-31. Recheck trigger: either page - changes the listing cap, which field keeps a description out of context, whether - `skillOverrides` reaches plugin skills, or what a `skills:` preload injects; that re-derives - this check's Remediate mechanics. + . ### I4: Inferable or redundant content @@ -492,16 +485,16 @@ disagrees with it. subagent spawning"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5#controlling-subagent-spawning) live; for the unattested `opus-4-8` arm, fetch [Opus 4.8 guide, "Controlling subagent spawning"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-4-8#controlling-subagent-spawning) - live. As of: 2026-11-03. Recheck trigger: the Opus 5 section stops advising caps on delegation, + live. Recheck trigger: the Opus 5 section stops advising caps on delegation, or the Opus 4.8 section starts advising them. Pointer for the two Fable arms: on a `fable-5` target, fetch [Fable 5 guide, "Parallel subagents"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5#parallel-subagents) live; on a `fable-5-1` target, fetch [Fable 5.1 guide, "Let the lead agent keep working while subagents run"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#let-the-lead-agent-keep-working-while-subagents-run) - live. As of: 2026-11-01. Recheck trigger: either section is renamed or stops advising against + live. Recheck trigger: either section is renamed or stops advising against blocking on each subagent before dispatching the next. The `fable-5-2` arm stays unattested because the Fable 5.2 guide's subagent section does not advise against blocking on each subagent; its advice runs toward reviewing lines that invite delegation. Pointer: fetch [Fable 5.2 guide, "Set expectations for subagents"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#set-expectations-for-subagents) - live. As of: 2026-11-09. Recheck trigger: that section starts advising against blocking on each + live. Recheck trigger: that section starts advising against blocking on each subagent before dispatching the next. - **The general principle, and why it is cited separately.** The migration-framed sources above point a reader at what looks like leftover prior-model scaffolding, walking straight past @@ -546,14 +539,14 @@ disagrees with it. 5.1](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1) and [Prompting Claude Opus 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5), - so it names no section. As of: 2026-10-01. Recheck trigger: a current model's guide stating that + so it names no section. Recheck trigger: a current model's guide stating that verification instructions cause over-verification. - **Considered for `haiku-5-5` on 2026-10-10 and declined**, on the same ground as `sonnet-5-5`: on our reading the section below backs the verification lines this row would remove, so the row stays inert on a `haiku-5-5` target. Pointer: [Haiku 5.5 guide, tell coding agents to verify their changes](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#tell-coding-agents-to-verify-their-changes). - As of: 2026-10-10. Recheck trigger: the Haiku 5.5 guide stating that verification instructions + Recheck trigger: the Haiku 5.5 guide stating that verification instructions cause over-verification. **Row I8-b: conservative-reporting detection** · Tier `behavioral`. Unscoped. Promotion gate MET @@ -619,9 +612,8 @@ choice, on the same reasoning I10 applies to a declined widening. - **Source:** Opus 5 guide, "Running with thinking disabled" (the removal, and the general form over naming thinking tags). Corroborated at troubleshooting thinking, "Tool calls or XML tags appear in the text output", which reaches the same claim from the symptom side and is the source of the - condition and consequence above. **As of 2026-08-04** (that page read as raw markdown). - **Recheck trigger:** a second model name appearing beside Claude Opus 5 in either section that - states the claim: the Opus 5 guide's "Running with thinking disabled", or this page's "Tool + condition and consequence above. **Recheck trigger:** a second model name appearing beside + Claude Opus 5 in either section that states the claim: the Opus 5 guide's "Running with thinking disabled", or this page's "Tool calls or XML tags appear in the text output". A new name re-opens the scoping question, not the gate itself: the added model joins as a named Detect condition, and unscoping still requires what the gate has always required, an unqualified model-agnostic statement or convergent model @@ -644,7 +636,7 @@ choice, on the same reasoning I10 applies to a declined widening. models](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#review-instructions-written-for-earlier-models) and [calibrate effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#calibrate-effort). - As of: 2026-11-09. Recheck trigger: either section stops prescribing the removal, or narrows the + Recheck trigger: either section stops prescribing the removal, or narrows the effort levels where such a line fails to stop thinking. - **Considered for `sonnet-5-5` on 2026-10-01 and declined.** We read the Sonnet 5.5 guide as covering this directive only under the `between_tools` thinking setting (pointer below), and no @@ -661,7 +653,7 @@ choice, on the same reasoning I10 applies to a declined widening. [settings](https://code.claude.com/docs/en/settings), [settings reference](https://code.claude.com/docs/en/settings-reference) and [environment variables](https://code.claude.com/docs/en/env-vars#variables) whole as raw markdown and found - no control for that setting (no artifact stored). As of: 2026-10-01. Recheck trigger: Claude + no control for that setting (no artifact stored). Recheck trigger: Claude Code gains a `between_tools` control, or the Sonnet 5.5 guide states the claim outside `between_tools`. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** Our read of the Haiku 5.5 guide that @@ -669,7 +661,7 @@ choice, on the same reasoning I10 applies to a declined widening. row stays inert on a `haiku-5-5` target. Pointer, the section nearest the topic: [Haiku 5.5 guide, use effort to control thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking). - As of: 2026-10-10. Recheck trigger: that guide states the leakage claim, or prescribes removing a + Recheck trigger: that guide states the leakage claim, or prescribes removing a don't-think directive. - **Re-justified 2026-10-01 against the current models:** `opus-5` stays (see "Tokens of models that are no longer current"), and both sections the trigger above watches still name Claude Opus @@ -677,8 +669,8 @@ choice, on the same reasoning I10 applies to a declined widening. disabled](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5#running-with-thinking-disabled) and [troubleshooting thinking: tool calls or XML tags appear in the text output](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#tool-calls-or-xml-in-text) - (the rendered page gives this heading the id `tool-calls-or-xml-in-text`). As of: 2026-10-01. - Recheck trigger: the same as this row's trigger above. + (the rendered page gives this heading the id `tool-calls-or-xml-in-text`). Recheck trigger: the + same as this row's trigger above. **Row I8-d: short-turn assumptions** · Tier `behavioral` · Model scope: `fable-5, fable-5-1`. @@ -721,7 +713,7 @@ choice, on the same reasoning I10 applies to a declined widening. [Prompting Claude Fable 5.1](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1), the text above its first heading, which carries no heading id on the rendered page, so the link - is to the page. As of: 2026-10-01. Recheck trigger: the Fable 5.1 guide naming a turn-length + is to the page. Recheck trigger: the Fable 5.1 guide naming a turn-length difference from Fable 5, or its opening changing what it says about Fable 5 prompts. - **Re-justified 2026-11-09 against the current models:** `fable-5` and `fable-5-1` stay while Claude Code can still put a session on either model (see "Tokens of models that are no longer @@ -731,14 +723,14 @@ choice, on the same reasoning I10 applies to a declined widening. 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5) and [Prompting Claude Sonnet 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5), - whole pages, since the probe is a negative over every section. As of: 2026-10-01. Recheck - trigger: either guide gains a section on turn length. + whole pages, since the probe is a negative over every section. Recheck trigger: either guide + gains a section on turn length. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** Our read of the Haiku 5.5 guide that day (whole page, raw markdown; no artifact stored) found no statement of the short-turn claim. Pointer: [Prompting Claude Haiku 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5), - the whole page, since the probe is a negative over every section. As of: 2026-10-10. Recheck - trigger: that guide gains a section on turn length. + the whole page, since the probe is a negative over every section. Recheck trigger: that guide + gains a section on turn length. - **Considered for `fable-5-2` on 2026-11-09 and declined.** Our read of both Fable 5.2 pages that day (whole pages) found no advice to remove short-turn assumptions and no statement that Fable 5 or Fable 5.1 guidance carries over, which is the ground the `fable-5-1` widening rested on. The @@ -751,8 +743,8 @@ choice, on the same reasoning I10 applies to a declined widening. turns](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#keep-users-informed-during-long-turns) and [What's new in Claude Fable 5.2, behavior differences](https://platform.claude.com/docs/en/models/fable-5-2/whats-new-fable-5-2#behavior-differences). - As of: 2026-11-09. Recheck trigger: either - page advises removing short-turn assumptions, or says that earlier Fable guidance carries over. + Recheck trigger: either page advises removing short-turn assumptions, or says that earlier Fable + guidance carries over. **Row I8-e: forced interim-status cadence** · Tier `behavioral`. Unscoped. Promotion gate MET: two model guides state the claim (see Source). @@ -793,7 +785,7 @@ report one finding per line rather than two. surface no person watches mid-run, such as an unattended lane, is still a finding there. Pointer: [Fable 5.2 guide, keep users informed during long turns](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#keep-users-informed-during-long-turns). - As of: 2026-11-09. Recheck trigger: that section stops recommending the line, or limits it to + Recheck trigger: that section stops recommending the line, or limits it to something other than a person watching the work. - **Source:** Sonnet 5 guide, "User-facing progress updates" (removing forced status scaffolding, and the Remediate line's second half). Convergent second model guide (the gate-meeting one): Opus @@ -838,12 +830,11 @@ general think-thoroughly prompt over a hand-written plan, so an unscoped row wou Pointer: [Sonnet 5.5 guide, reasoning tasks with JSON output](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#reasoning-tasks-with-json-output). - As of: 2026-10-01. Recheck trigger: either guide changes its position on thinking instructions. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** Our read of the Haiku 5.5 guide that day found no position on a standing think-carefully line, so the row stays inert on a `haiku-5-5` target. Pointer, the section nearest the topic: [Haiku 5.5 guide, use effort to control thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking). - As of: 2026-10-10. Recheck trigger: that section takes a position on think-carefully + Recheck trigger: that section takes a position on think-carefully instructions. **Row I8-g: standing keep-going exhortation** · Tier `behavioral`. Unscoped. Promotion gate MET: @@ -944,7 +935,7 @@ per model; promotion gate unmet, see "Unscoping considered" below). The widening now rests on the refusals section of Fable 5.1's own model page. Pointer: [What's new in Claude Fable 5.1, refusals, fallback, and billing](https://platform.claude.com/docs/en/models/fable-5-1/whats-new-fable-5-1#refusals-fallback-and-billing). - As of: 2026-10-01. Recheck trigger: that section stops covering the `reasoning_extraction` + Recheck trigger: that section stops covering the `reasoning_extraction` category for Fable 5.1. - **Widened to `opus-5-5` on 2026-09-23:** the Opus 5.5 guide, "Safeguard refusals", documents the `reasoning_extraction` category for that model, and how server-side fallback handles those @@ -954,7 +945,7 @@ per model; promotion gate unmet, see "Unscoping considered" below). - **Widened to `sonnet-5-5` on 2026-10-01.** On a `sonnet-5-5` target, fire on the same Detect and remediate as above. Pointer: [Sonnet 5.5 guide, safeguard refusals](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#safeguard-refusals). - As of: 2026-10-01. Recheck trigger: that section drops the `reasoning_extraction` category. + Recheck trigger: that section drops the `reasoning_extraction` category. - **Widened to `fable-5-2` on 2026-11-09.** The Fable 5.2 guide lists `reasoning_extraction` among that model's refusal categories and prescribes removing instructions that ask for reasoning in the response; the What's new page states the refusal stands with no fallback for that category. @@ -962,13 +953,13 @@ per model; promotion gate unmet, see "Unscoping considered" below). refusals](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#safeguard-refusals) and [What's new in Claude Fable 5.2, refusals, fallback, and billing](https://platform.claude.com/docs/en/models/fable-5-2/whats-new-fable-5-2#refusals-fallback-and-billing). - As of: 2026-11-09. Recheck trigger: either section drops the `reasoning_extraction` category. + Recheck trigger: either section drops the `reasoning_extraction` category. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** Our read of the section below that day put Haiku 5.5 outside the scope rule this row follows, so the row stays inert there. Pointer: [Haiku 5.5 guide, safeguard refusals](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#safeguard-refusals). - As of: 2026-10-10. Recheck trigger: that refusal section lists `reasoning_extraction`. + Recheck trigger: that refusal section lists `reasoning_extraction`. - **Unscoping considered on 2026-10-01 and declined.** Four model guides now name the category (Sonnet 5.5, Opus 5.5, Fable 5.1 and Fable 5), which on its face meets the convergent-guides arm of the promotion gate. We keep the row scoped because we read the category as a per-model @@ -985,7 +976,7 @@ per model; promotion gate unmet, see "Unscoping considered" below). changes](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5#recommended-scaffolding-changes); for the categories themselves, see [refusals and fallback: refusal response](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#refusal-response). - As of: 2026-10-01. Recheck trigger: a model-agnostic page stating that every current model + Recheck trigger: a model-agnostic page stating that every current model declines reasoning extraction. - **Re-justified 2026-11-09 against the current models:** `fable-5` and `fable-5-1` stay while Claude Code can still put a session on either model (see "Tokens of models that are no longer @@ -1150,8 +1141,7 @@ skill bodies. This exemption covers such an agent only when it is spawned as a subagent; when the agent runs as the session's main agent, fetch the `omitClaudeMd` row and [Invoke subagents explicitly](https://code.claude.com/docs/en/sub-agents#invoke-subagents-explicitly) - live. As of: 2026-11-01. Recheck trigger: either section changes when the field applies, or the - field is renamed. + live. - **Source:** subagents, "What loads at startup": we treat a non-fork subagent's initial context as holding every level of the CLAUDE.md hierarchy *the main conversation loads*, except an agent whose definition sets `omitClaudeMd: true` (see the Must NOT flag above), and that qualifier @@ -1240,8 +1230,7 @@ by `--opinion`. - **Source:** none. No official page states definition-site locality, which is why this check is `OPINION`-tier. The *routing* half, which surface a class of content belongs in, is documented at [features-overview, "Compare similar features"](https://code.claude.com/docs/en/features-overview#compare-similar-features), - and is I3's concern, not this check's. As of: 2026-10-18. Recheck trigger: that section is - renamed, or starts stating where a rule's definition site belongs. + and is I3's concern, not this check's. ### I17: Thinking disabled where the model forbids it @@ -1384,9 +1373,8 @@ since each prescribes a request the model refuses. frontmatter, and model configuration for `/effort`, the session and global thinking toggles, and ultracode, the last enumerating the three routes that turn the *setting* on (`/effort`, `--effort`, `--settings` / Agent SDK). The keyword's separation from the setting is read from - [workflows, "Ask for a workflow in your prompt"](https://code.claude.com/docs/en/workflows#ask-for-a-workflow-in-your-prompt) - (as of 2026-11-01; recheck when that section changes what the keyword does to the session's - effort level). The second arm is thinking's per-model table, + [workflows, "Ask for a workflow in your prompt"](https://code.claude.com/docs/en/workflows#ask-for-a-workflow-in-your-prompt). + The second arm is thinking's per-model table, where those models refuse `"disabled"` with no effort qualifier while Opus 5 refuses it only at the top levels: that is what makes the arm unconditional rather than a wider pairing, and why the two are read as separate arms rather than one range. @@ -1425,11 +1413,6 @@ Severity `warning`. variables](https://code.claude.com/docs/en/env-vars#variables), those two rows (read whole per the fetch route under Sources), and [model configuration: extended thinking](https://code.claude.com/docs/en/model-config#extended-thinking). -- **As of 2026-10-02** for the extended-thinking section (read as raw markdown that day; this row - names no model and takes the no-effect set from it at audit time), **2026-10-01** for the - environment-variable rows. **Recheck trigger:** the extended-thinking anchor moving or that - section no longer listing which models cannot have thinking turned off, or the third-party - behavior changing. **Row I17-b: mid-session thinking or effort change prescribed without its cost** · Tier `mechanical` · Severity `info`. @@ -1443,8 +1426,6 @@ Severity `warning`. flag a change prescribed *with* its cost stated, which is the remediation. Pointer: for how Claude Code handles an effort change, see [prompt caching: changing effort level](https://code.claude.com/docs/en/prompt-caching#changing-effort-level). - As of: 2026-10-01. Recheck trigger: that section stops covering how Claude Code handles the - cache cost of an effort change, or Claude Code's changelog names a change to that handling. - **On an API surface, the remediation may offer the per-message effort route, never with `between_tools`.** Offer it where the model supports it. Never offer it to a surface that sends `between_tools`: that combination is I17's third arm, not this row. Pointer: for the @@ -1452,15 +1433,11 @@ Severity `warning`. (beta)](https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta); for the `between_tools` combination, see the [Sonnet 5.5 guide, calibrate effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#calibrate-effort). - As of: 2026-10-01. Recheck trigger: per-message effort leaves beta or changes its cache - behavior, or `between_tools` starts accepting it. - **Nor with thinking disabled where the model's docs refuse that pairing.** Never recommend a per-message effort change to a surface whose request disables thinking on a model whose docs refuse that pairing; that combination is I17's second `haiku-5-5` widening, not this row. Pointer: [effort: change effort mid-conversation (beta)](https://platform.claude.com/docs/en/build-with-claude/effort#change-effort-mid-conversation-beta). - As of: 2026-10-10. Recheck trigger: that section changes which models or thinking settings it - names alongside a per-message effort change. - **Reach differs by half, and this is the whole of it.** The effort half reaches every surface, with Claude Code surfaces carved out above. **The thinking half reaches API and Agent SDK surfaces only.** A Claude Code surface prescribing a mid-session thinking toggle is **out of reach of @@ -1491,10 +1468,6 @@ Severity `warning`. - **Source:** prompt caching, "Changing effort level" (the effort half in Claude Code). The thinking half, and the API effort half, point at [thinking: thinking and prompt caching](https://platform.claude.com/docs/en/build-with-claude/thinking#thinking-and-prompt-caching). -- **As of 2026-08-04** for the thinking half (that page read as raw markdown); the carve-out and the - API per-message route carry their own 2026-10-01 records above. **Recheck trigger:** effort or - the thinking configuration leaving the cache key on the thinking page, or a Claude Code page - starting to cover what a mid-session thinking change costs. **Row I17-c: fixed thinking budget prescribed where adaptive reasoning ignores or rejects it** · Tier `mechanical` · Severity `warning`. Unscoped. Promotion gate MET: the claim is stated on @@ -1557,8 +1530,7 @@ ranges below are Detect conditions, not a `Model scope` annotation**, for the re replacement, and treat it as a control separate from a thinking budget. Pointer: when weighing effort against a thinking budget, fetch [effort, "Effort with thinking"](https://platform.claude.com/docs/en/build-with-claude/effort#effort-with-thinking) - live. As of: 2026-11-01. Recheck trigger: that section starts treating effort as a thinking - budget or as a substitute for `budget_tokens`. + live. - **Source:** environment variables, the `MAX_THINKING_TOKENS` and `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` rows (nonzero values ignored on adaptive-reasoning models). Model configuration, "Adaptive reasoning @@ -1585,8 +1557,7 @@ Severity `warning` · Model scope: `sonnet-5`. why, or leave thinking on. Effort is a second lever: we treat `high` or `xhigh` as raising tool use in agentic search and coding. Pointer: when sizing that lever, fetch [effort, "Effort with tool use"](https://platform.claude.com/docs/en/build-with-claude/effort#effort-with-tool-use) - live. As of: 2026-11-01. Recheck trigger: that section stops tying higher effort to more tool - calls. + live. - **Must NOT flag:** a thinking-disable with no tool dependence. A tool-dependent surface that already instructs its tool use explicitly. That is the remediation, present. A surface with no control over and no claim about the thinking configuration, whose tool reliance runs under the @@ -1612,7 +1583,7 @@ Severity `warning` · Model scope: `sonnet-5`. thinking](https://code.claude.com/docs/en/model-config#extended-thinking) for the no-effect set; [Prompting Claude Sonnet 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5), - the whole page, for the negative. As of: 2026-10-01. Recheck trigger: Sonnet 5.5 leaves the + the whole page, for the negative. Recheck trigger: Sonnet 5.5 leaves the no-effect set, or its guide states a thinking-off tool-reach coupling. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** On our reading the section below is narrower than half (b) of Detect, so widening would flag tool-reliant surfaces it does not speak @@ -1620,7 +1591,7 @@ Severity `warning` · Model scope: `sonnet-5`. 5.5 guide, use adaptive thinking with JSON output and your own tools](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#json-output-with-your-own-tools). - As of: 2026-10-10. Recheck trigger: that guide states a thinking-off tool-reach coupling with no + Recheck trigger: that guide states a thinking-off tool-reach coupling with no output-format condition. ### I18: Thinking blocks altered on the way back to the model @@ -1732,9 +1703,6 @@ Tier `mechanical` · Severity `warning`. own `type` rather than by position, so it is correct by construction rather than by this rule. Stated as an as-of measurement, not a passed check. **Re-measure when** a history-assembly or replay path lands here. -- **As of 2026-08-04** (the Steering thinking page read as raw markdown). **Recheck - trigger:** the turn-validation relaxation narrowing, or the set of models that enforce a leading - thinking block changing. ### I19: Restated external benchmark figure with no recheck trigger @@ -1834,9 +1802,8 @@ not a `Model scope` annotation**, for the reason I17 states. defaults to `high` such a pin carries no measured calibration that could go stale. **The exemption keys to the resolved target, never to the wording.** Read the resolved target's default live from the per-model defaults in - [Adjust effort level](https://code.claude.com/docs/en/model-config#adjust-effort-level) - (as of 2026-10-10; recheck when that section adds a model or moves a default); when it is not - `high`, the exemption lifts and a `high` pin is a finding, **including a broad model-agnostic + [Adjust effort level](https://code.claude.com/docs/en/model-config#adjust-effort-level); when it + is not `high`, the exemption lifts and a `high` pin is a finding, **including a broad model-agnostic "always use `high`" that names no model at all**. That broad pin is the sharper case rather than the excluded one: written where `high` was the no-op default and then carried to a model whose default differs, it silently becomes a step nobody measured, which is this row's subject exactly. A resolved target @@ -1852,13 +1819,12 @@ not a `Model scope` annotation**, for the reason I17 states. `effort:` fence below still applies). Where nothing names a different model or effort for the subagents, they run on the session's resolved target, which stays the fallback. Pointer: [Choose the subagent's model](https://code.claude.com/docs/en/sub-agents#choose-a-model) - and [Choose an effort level](https://code.claude.com/docs/en/sub-agents#choose-an-effort-level) - (as of 2026-10-17; recheck when either order gains a source or changes precedence). **The exemption speaks to + and [Choose an effort level](https://code.claude.com/docs/en/sub-agents#choose-an-effort-level). + **The exemption speaks to calibration staleness only, never to level adequacy:** a model guide may recommend running above the default for named lanes (for one such guide, fetch [Opus 4.8 guide, "Calibrating effort and thinking depth"](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-4-8#calibrating-effort-and-thinking-depth) - live; as of 2026-11-01, recheck when that section stops recommending a level above the default - for any lane), and whether a `high` pin under-serves such a lane is that surface's sizing decision, + live), and whether a `high` pin under-serves such a lane is that surface's sizing decision, outside this row's subject. - **Must NOT flag: a per-task or single-turn effort choice**, such as "reach for `xhigh` on hard problems", `ultrathink`, or `ultracode`, which selects a level for one piece of work rather than @@ -2009,12 +1975,10 @@ confident removals. - **Residency is a severity input, not an admission test.** A trigger in a `description` is resident whenever the skill listing admits it, which is the default, since `disable-model-invocation: true` also suppresses the description from context (pointer: - [Skills](https://code.claude.com/docs/en/skills#frontmatter-reference), as of 2026-08-08). A + [Skills](https://code.claude.com/docs/en/skills#frontmatter-reference)). A body-borne trigger costs context only once the skill loads, or at startup in a subagent with the skill preloaded. Both are findings; the resident one is the more expensive to - leave. **Second-source recheck trigger:** that page's invocation-control table changing which - fields keep a description in context, which would re-rank the two residencies and is the only fact - this clause and the remediation below rest on. + leave. - **Remediate by moving the trigger, never by withdrawing the skill.** Flipping continuation skills to `disable-model-invocation: true` is the considered alternative and is refused: it costs every model-side invocation the skill has, including the ones a user asks for in the words its @@ -2047,7 +2011,7 @@ confident removals. Fable 5 claim for `fable-5-1`. Pointer: [Prompting Claude Fable 5.1](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1), the text above its first heading, which carries no heading id on the rendered page, so the link - is to the page. As of: 2026-10-01. Recheck trigger: the Fable 5.1 guide naming a context-budget + is to the page. Recheck trigger: the Fable 5.1 guide naming a context-budget difference from Fable 5, or its opening changing what it says about Fable 5 prompts. - **Re-justified 2026-11-09 against the current models:** `fable-5` and `fable-5-1` stay while Claude Code can still put a session on either model (see "Tokens of models that are no longer @@ -2060,14 +2024,14 @@ confident removals. 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5) and [Prompting Claude Sonnet 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5), - whole pages, since the probe is a negative over every section. As of: 2026-10-01. Recheck - trigger: either guide states this row's claim, which meets the promotion gate. + whole pages, since the probe is a negative over every section. Recheck trigger: either guide + states this row's claim, which meets the promotion gate. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** Our read of the Haiku 5.5 guide that day (whole page, raw markdown; no artifact stored) found no statement of this row's claim. Pointer: [Prompting Claude Haiku 5.5](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5), - the whole page, since the probe is a negative over every section. As of: 2026-10-10. Recheck - trigger: that guide states this row's claim, which meets the promotion gate. + the whole page, since the probe is a negative over every section. Recheck trigger: that guide + states this row's claim, which meets the promotion gate. - **Considered for `fable-5-2` on 2026-11-09 and declined.** The Fable 5.2 guide's nearest item is a token budget a harness writes into the prompt: it reports that the budget's size changes how much the model spends and asks for a test without it. It does not say the model stops, @@ -2075,7 +2039,7 @@ confident removals. stays inert on a `fable-5-2` target. Pointer: [Fable 5.2 guide, review instructions written for earlier models](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#review-instructions-written-for-earlier-models). - As of: 2026-11-09. Recheck trigger: that guide states that a remaining-context count leads the + Recheck trigger: that guide states that a remaining-context count leads the model to stop, summarize or hand off. ### I24: Instruction relying on silent generalization @@ -2251,12 +2215,12 @@ gate is unmet). effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#calibrate-effort) and [Sonnet 5.5 guide, calibrate effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#calibrate-effort). - As of: 2026-10-01. Recheck trigger: either section starts stating that effort does not reliably + Recheck trigger: either section starts stating that effort does not reliably shorten the response, or stops tying higher effort to longer output. - **Considered for `haiku-5-5` on 2026-10-10 and declined**, on the same ground: on our reading the section below supports the line this row would flag. Pointer: [Haiku 5.5 guide, use effort to control thinking](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#use-effort-to-control-thinking). - As of: 2026-10-10. Recheck trigger: that section starts stating that effort does not reliably + Recheck trigger: that section starts stating that effort does not reliably shorten the response, or stops tying higher effort to longer output. ### I28: Over-aggressive trigger emphasis and blanket tool defaults @@ -2290,9 +2254,8 @@ guide reverses it; the Sonnet 5 and Opus 4.8 literalism sections corroborate the - **Source:** prompting best practices, "Tool usage" (dialing back aggressive trigger language, with a worked example), "Overthinking and excessive thoroughness" (targeted instructions over blanket defaults), and "Migration considerations" (anti-laziness prompting). -- **As of 2026-08-08** (that page read as raw markdown). **Recheck trigger:** those - three sections changing, or any model guide stating that a current model undertriggers and needs - emphasis restored, which would re-open the scoping question. +- **Recheck trigger:** those three sections changing, or any model guide stating that a current + model undertriggers and needs emphasis restored, which would re-open the scoping question. - **That trigger fired on 2026-10-01, and the arms stand.** Two current guide sections on tool and search triggering (pointers below) were re-read that day; neither asks for emphasis or a blanket default back. So the row stays unscoped and keeps both arms, with one fence added: @@ -2304,7 +2267,7 @@ guide reverses it; the Sonnet 5 and Opus 4.8 literalism sections corroborate the work](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#tool-use-in-chat-and-knowledge-work) and [Fable 5.1 guide, search triggering at low effort](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-1#search-triggering-at-low-effort). - As of: 2026-10-01. **Recheck trigger, restated:** a model guide asking for forced-compliance + **Recheck trigger, restated:** a model guide asking for forced-compliance emphasis or a blanket tool default to be restored on a current model, which re-opens the scoping question; a guide describing under-triggering and prescribing a targeted condition does not. - **Re-read against the Haiku 5.5 guide on 2026-10-10; the arms stand.** On our reading the @@ -2312,7 +2275,7 @@ guide reverses it; the Sonnet 5 and Opus 4.8 literalism sections corroborate the stays unscoped with no change. Pointer: [Haiku 5.5 guide, accurate search results](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#accurate-search-results). - As of: 2026-10-10. Recheck trigger: the restated trigger above. + Recheck trigger: the restated trigger above. - **Routes to the findings relay.** I28 and I29 (scanner-fed) and I30 to I33 (lane-fed, admitted through `--from-lane`) are the checks in this catalog whose findings reach `review:fanout`'s apply relay, behind `--persist-findings`. I28's two arms carry one @@ -2393,9 +2356,10 @@ I19 from benchmark figures to every dated claim about a harness, a tool, an upst measurement. - **Detect:** a claim carrying an as-of date ("verified 2026-07-13", "as of 2.1.240") but no - observable event that would re-open it. The record is the decision, a pointer to the exact - source section, an as-of date, and a recheck trigger beside the decision; a dated stamp that - lacks the trigger is the finding, whether or not its pointer is present. + observable event that would re-open it. A pointer record (the decision and a pointer to the + exact source section) carries no stamp. A stored value, a recorded number or string copied or + measured from upstream, carries an as-of date and a recheck trigger beside it; a dated stamp + that lacks the trigger is the finding, whether or not its pointer is present. - **Must NOT flag:** a dated stamp whose trigger lives in a named owner record the site points at ("recheck per `reference/parent-contract.md`"); a CHANGELOG entry or ADR, which are history by design; a date that is data (a release date in a table) rather than a verification stamp. @@ -2535,7 +2499,7 @@ do not converge; promotion gate unmet, see the `fable-5-2` widening below). models](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#review-instructions-written-for-earlier-models) and [Opus 5.5 guide, thinking instructions in chat system prompts](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5-5#thinking-instructions-in-chat-system-prompts). - As of: 2026-11-09. Recheck trigger: either section drops the cost, the Fable 5.2 section starts + Recheck trigger: either section drops the cost, the Fable 5.2 section starts recommending the line on a surface, or a third model guide states the cost. ### I36: Tool-discouraging language @@ -2560,13 +2524,13 @@ Tier `behavioral` · Authority `ANTHROPIC-DOCS` · Severity `warning` · Surface - **Source:** Sonnet 5.5 guide, "Tool use in chat and knowledge work". Pointer: [Sonnet 5.5 guide, tool use in chat and knowledge work](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#tool-use-in-chat-and-knowledge-work). - As of: 2026-10-01. Recheck trigger: a second model guide stating the claim, which meets the + Recheck trigger: a second model guide stating the claim, which meets the promotion gate and unscopes the row, or the section dropping it. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** On our reading the section below does not state this row's claim, so it neither widens nor unscopes the row. Pointer: [Haiku 5.5 guide, accurate search results](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#accurate-search-results). - As of: 2026-10-10. Recheck trigger: that section asks for tool-discouraging language to be + Recheck trigger: that section asks for tool-discouraging language to be removed. ### I37: Harness text after every tool result @@ -2597,21 +2561,21 @@ states the claim; promotion gate unmet). messages](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#mid-turn-user-messages-and-task-budgets) and [hooks: PostToolUse decision control](https://code.claude.com/docs/en/hooks#posttooluse-decision-control). - As of: 2026-10-01. Recheck trigger: a second model guide covering the same topic, which meets + Recheck trigger: a second model guide covering the same topic, which meets the promotion gate and unscopes the row, or that section changing which kinds of per-step text it covers. - **Considered for `haiku-5-5` on 2026-10-10 and declined.** The trigger above fired on the same-titled section below; on re-read it does not cover this row's topic, text added after every tool result, so the gate stays unmet and the row neither widens nor unscopes. Pointer: [Haiku 5.5 guide, mid-turn user messages](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-haiku-5-5#mid-turn-user-messages). - As of: 2026-10-10. Recheck trigger: that section covers per-step text added after tool results. + Recheck trigger: that section covers per-step text added after tool results. - **Considered for `fable-5-2` on 2026-11-09 and declined.** The Fable 5.2 guide asks a harness to append a reminder only after several tool-calling steps in a row gave the user nothing to read. That is text gated on a condition, which this row's Must NOT flag already admits, and the guide says nothing against text added after every tool result, so the gate stays unmet and the row neither widens nor unscopes. Pointer: [Fable 5.2 guide, keep users informed during long turns](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#keep-users-informed-during-long-turns). - As of: 2026-11-09. Recheck trigger: that section covers text added after every tool result. + Recheck trigger: that section covers text added after every tool result. ### I38: Progress-update suppressor @@ -2676,9 +2640,7 @@ Tier `behavioral` · Authority `ANTHROPIC-DOCS` · Severity `warning` · Surface - **Source:** memory, "Write effective instructions", its consistency guidance (contradicting instructions and an arbitrary pick), which names no same-file limit. Pointer: [memory: write effective - instructions](https://code.claude.com/docs/en/memory#write-effective-instructions). As of: - 2026-10-04. Recheck trigger: that guidance gains a same-file limit, or stops calling a - contradiction a defect. + instructions](https://code.claude.com/docs/en/memory#write-effective-instructions). ### I40: Own-repository history reference in an agent definition @@ -2705,8 +2667,8 @@ is `/skill-quality:check`'s; this row covers the agents it does not read. definitions; skill authoring best practices, "Avoid time-sensitive information". Pointer: [avoid time-sensitive information](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#avoid-time-sensitive-information). - As of: 2026-10-07. Recheck trigger: `/playbooks:skill-authoring` `## Agents` changes its history - rule or its exemptions, which re-derives this row's Must NOT flag set and the scanner's. + Recheck trigger: `/playbooks:skill-authoring` `## Agents` changes its history rule or its + exemptions, which re-derives this row's Must NOT flag set and the scanner's. ### I41: Unneeded text in an agent definition @@ -2730,7 +2692,6 @@ Unscoped. key". Correlate: the vendor `prompt-audit` procedure's Step 3 deletion rule, read at the commit [bundled-claude-api.md](bundled-claude-api.md) pins. Pointer: [concise is key](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#concise-is-key). - As of: 2026-10-07. Recheck trigger: that section drops the "does Claude really need this" test. ### I42: Rigid step script for judgment work in an agent definition @@ -2751,8 +2712,6 @@ Unscoped. - **Source:** `/playbooks:skill-authoring` `## Agents`; skill authoring best practices, "Set appropriate degrees of freedom". Pointer: [set appropriate degrees of freedom](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices#set-appropriate-degrees-of-freedom). - As of: 2026-10-07. Recheck trigger: that section changes which tasks it assigns high or low - freedom. --- diff --git a/plugins/harness-config/skills/audit-pass/SKILL.md b/plugins/harness-config/skills/audit-pass/SKILL.md index 7f20f76f296..80e976856c4 100644 --- a/plugins/harness-config/skills/audit-pass/SKILL.md +++ b/plugins/harness-config/skills/audit-pass/SKILL.md @@ -52,7 +52,7 @@ with a narrowed accident surface, never an enforced guarantee. `Write` is kept, the report persist under `${CLAUDE_PLUGIN_DATA}`, and it can mutate a file, so never describe the restriction to an operator as mechanical. `audit-instructions` states the same posture. -- **Pointer**: when deciding how long the restriction lasts, fetch [skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference) live. **As of**: 2026-10-11. **Recheck trigger**: that section changes what `disallowed-tools` removes or how long it lasts. +- **Pointer**: when deciding how long the restriction lasts, fetch [skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference) live. **`scripts/run-state.sh` writes under that same plugin data directory and nowhere else**, never inside a target repository. It takes the data directory as an argument rather than discovering one, @@ -126,7 +126,7 @@ bash "$S" lease acquire --run-dir "" --run-id "" --plugin-data ``` `paths` derives `/runs//` through the plugin's own `lib/state-key.sh`, -the library whose header records the keying scheme. Pass `--plugin-data` explicitly with the `${CLAUDE_PLUGIN_DATA}` value from this text; never rely on the shell to expand it (Pointer: fetch [manifest reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live. As of: 2026-11-10. Recheck trigger: that section exports the variable to Bash-tool commands). +the library whose header records the keying scheme. Pass `--plugin-data` explicitly with the `${CLAUDE_PLUGIN_DATA}` value from this text; never rely on the shell to expand it (Pointer: fetch [manifest reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live). `acquire` takes it too, and refuses a `--run-dir` that is not under `/runs/`. It is the only command that *creates* a directory, so it is where the write tree is pinned; a wrong or invented run dir would otherwise be created and written into. @@ -193,13 +193,13 @@ Claude receives, and the live style can differ from the one the user's settings plus settings can report a selection as live when it is not. Report the resolved live style and what resolved it. -- **Pointer**: when resolving the live style and what it changes, fetch [output styles: how output styles work](https://code.claude.com/docs/en/output-styles#how-output-styles-work) and [create a custom output style](https://code.claude.com/docs/en/output-styles#create-a-custom-output-style) live. **As of**: 2026-10-11. **Recheck trigger**: either section changes what `keep-coding-instructions` keeps or how `force-for-plugin` interacts with `outputStyle`. +- **Pointer**: when resolving the live style and what it changes, fetch [output styles: how output styles work](https://code.claude.com/docs/en/output-styles#how-output-styles-work) and [create a custom output style](https://code.claude.com/docs/en/output-styles#create-a-custom-output-style) live. **Shadowed definitions fall out of this inventory, not out of a catalog.** Where skills, subagents or MCP servers share a name across scopes, the pass compares names across the precedence order read live, deterministic, model-free and derived tier, and reports at `info` in its own section naming the live definition and the shadowed one, never as a conflict finding or merged into one. -When deciding which same-named definition is live, fetch [skills: resolve skills that share a name](https://code.claude.com/docs/en/skills#resolve-skills-that-share-a-name), [subagents: choose the subagent scope](https://code.claude.com/docs/en/sub-agents#choose-the-subagent-scope) and [MCP: scope hierarchy and precedence](https://code.claude.com/docs/en/mcp#scope-hierarchy-and-precedence) live (as of 2026-11-03; recheck when any of the three changes how a name collision resolves or its scope order). +When deciding which same-named definition is live, fetch [skills: resolve skills that share a name](https://code.claude.com/docs/en/skills#resolve-skills-that-share-a-name), [subagents: choose the subagent scope](https://code.claude.com/docs/en/sub-agents#choose-the-subagent-scope) and [MCP: scope hierarchy and precedence](https://code.claude.com/docs/en/mcp#scope-hierarchy-and-precedence) live. ## Phase 2: Derive the exclusion set @@ -285,7 +285,7 @@ overrun costs the lanes still running rather than the whole pass. This pass builds no replacement for `/doctor` and hands the instruction-file audit to `/doctor prompt-audit` rather than running it; for what each owns, fetch [memory: audit your instruction files](https://code.claude.com/docs/en/memory#audit-your-instruction-files) -live (as of 2026-11-03; recheck when that section changes what either covers). **Both are +live. **Both are operator-run, so neither is dispatched.** Their records (version floors, write posture), what the presence check verifies versus probes, and the absence classification are in [reference/doctor-handoff.md](reference/doctor-handoff.md). @@ -464,8 +464,7 @@ The `reference/` files write this skill's directory as ``, which is writing one into a brief. Those files arrive through the Read tool as plain bytes, so a `${…}` token in them would reach the Bash tool unsubstituted, and the Bash tool's environment has no `CLAUDE_SKILL_DIR` or `CLAUDE_PLUGIN_ROOT` to expand it from. Basis: the plugins reference, -, verified -2026-10-07; recheck when that table adds supporting files to where a `${…}` reference resolves. +. ## Gotchas @@ -481,7 +480,7 @@ in them would reach the Bash tool unsubstituted, and the Bash tool's environment judging whether a split saves context, fetch [memory: import additional files](https://code.claude.com/docs/en/memory#import-additional-files) and [memory: my CLAUDE.md is too large](https://code.claude.com/docs/en/memory#my-claude-md-is-too-large) - live. As of: 2026-10-11. Recheck trigger: either section says imported files load lazily. + live. ## What this skill does NOT do diff --git a/plugins/harness-config/skills/audit-pass/reference/doctor-handoff.md b/plugins/harness-config/skills/audit-pass/reference/doctor-handoff.md index 66332500c21..15dc1d442f6 100644 --- a/plugins/harness-config/skills/audit-pass/reference/doctor-handoff.md +++ b/plugins/harness-config/skills/audit-pass/reference/doctor-handoff.md @@ -13,8 +13,6 @@ the operator's behalf. - **Pointer**: when deciding whether `/doctor` can run unattended, fetch [skills: check your setup with /doctor](https://code.claude.com/docs/en/skills#check-your-setup-with-/doctor) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section says `/doctor` applies a fix without asking first. **The handoff is therefore an operator instruction.** The pass finishes its own phases, then tells the operator to run `/doctor` themselves. Nothing in this pass invokes it, waits on it, or drives it. @@ -23,8 +21,6 @@ pass never dispatches. - **Pointer**: for its scope, write posture and version floor, see . -- **As of**: 2026-10-01 -- **Recheck trigger**: that section changes its write posture or version floor, or moves. **What it does not do is refuse the result the operator brings back.** "Never parses its output as a lane result" would make the `delegated` tier unreachable. The lane could never leave `open`, and @@ -48,8 +44,6 @@ from what it does not. - **Pointer**: when checking the floor, fetch [memory: my CLAUDE.md is too large](https://code.claude.com/docs/en/memory#my-claude-md-is-too-large) live. - - **As of**: 2026-11-04 - - **Recheck trigger**: that section states a floor, or moves. 2. **`DISABLE_DOCTOR_COMMAND`: documented.** The variable's row is on the environment-variables page again, so it is a documented suppression channel, and its scope is the row's: read which surface it hides, and which it leaves alone, from the row rather than from here. @@ -67,8 +61,6 @@ bundled skill. [skills: bundled skills](https://code.claude.com/docs/en/skills#bundled-skills) and [skills: override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings) live. -- **As of**: 2026-11-04 -- **Recheck trigger**: either section stops letting an override hide a bundled skill. So the pass **detects absence rather than predicting it**: it checks whether `/doctor` actually resolves in this environment, and reports the outcome. If it does not resolve, the run says so and @@ -76,9 +68,8 @@ names these channels as the suspected causes, `DISABLE_DOCTOR_COMMAND` and a `sk naming the skill, rather than asserting either as the reason. Detecting beats predicting either way: the variable's presence in the list says an operator *could* have set it, never that they did. -**Recheck trigger:** any Claude Code minor release, or any change to how bundled skills are -suppressed. Re-verify against current official documentation before -treating a failed prerequisite as authoritative. A stale *absence* claim reads exactly like a fresh +Re-verify against current official documentation before treating a failed prerequisite as +authoritative. A stale *absence* claim reads exactly like a fresh one. ## Absence classification: optional capability @@ -111,11 +102,8 @@ reads. and [managed settings: keys only a managed source can set](https://code.claude.com/docs/en/managed-settings#keys-only-a-managed-source-can-set) live. Those sections cover the policy line only; this file has found no docs section for the - helper-failure or credential lines as of 2026-10-11, so hand them to the operator as lines to look - for, not as documented output. -- **As of**: 2026-10-11 -- **Recheck trigger**: the `Organization policy` line moves off `claude doctor` or `/status`, or a - docs section starts covering the helper-failure or credential lines. + helper-failure or credential lines, so hand them to the operator as lines to look for, not as + documented output. ## Its output is the delegated tier @@ -130,5 +118,3 @@ run does not have. - **Pointer**: when deciding whether `/doctor` still runs as a model-driven skill, fetch [skills: check your setup with `/doctor`](https://code.claude.com/docs/en/skills#check-your-setup-with-doctor) live. -- **As of**: 2026-11-03 -- **Recheck trigger**: that section stops listing `/doctor` among the bundled skills, or moves. diff --git a/plugins/harness-config/skills/audit-pass/reference/finding-identity.md b/plugins/harness-config/skills/audit-pass/reference/finding-identity.md index 56cbec6e0d2..de23ca075dd 100644 --- a/plugins/harness-config/skills/audit-pass/reference/finding-identity.md +++ b/plugins/harness-config/skills/audit-pass/reference/finding-identity.md @@ -123,7 +123,7 @@ content and the same defect. churning the whole report on an unrelated edit. The anchor field name carries its algorithm version: findings emit **`anchor/v1`**, and two sides compare on the **greatest anchor version both carry** (the versioned-fingerprint discipline of SARIF -[§3.27.17](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html), verified 2026-07-24; recheck when a SARIF release changes fingerprint versioning). +[§3.27.17](https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html)). That is the escape hatch: a later algorithm ships as `anchor/v2` alongside `v1`, and a record written under `v1` keeps matching until both sides have moved. diff --git a/plugins/harness-config/skills/audit-pass/reference/liveness-sources.md b/plugins/harness-config/skills/audit-pass/reference/liveness-sources.md index 0644371daa9..131ccd25528 100644 --- a/plugins/harness-config/skills/audit-pass/reference/liveness-sources.md +++ b/plugins/harness-config/skills/audit-pass/reference/liveness-sources.md @@ -60,7 +60,7 @@ So Phase 1 takes the sources it can hold: [hooks: InstructionsLoaded input](https://code.claude.com/docs/en/hooks#instructionsloaded-input) live for the payload fields and the `load_reason` values. Basis beside it: first-party measurement in this marketplace (2026-09-13, Claude Code 2.1.268). - - **As of**: 2026-10-11 (pointer); 2026-09-13 (measurement) + - **As of**: 2026-09-13 (measurement) - **Recheck trigger**: that section changes the event's payload fields or its `load_reason` set. Only the `session_start` half is out of reach at dispatch time, because those events fired before @@ -81,7 +81,7 @@ the run could not observe rather than left to read as coverage: which skill descriptions were dropped from the listing; route that question, and how drops are chosen, to `/harness-ops:audit-skill-visibility`. For whether a session can see its drops, fetch [skills: skill descriptions are cut short](https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short) - live (as of 2026-11-03; recheck when that section names a way to see them). + live. - **Custom-agent registration liveness**, which degrades from observed to **configured-not-observed**: the inventory can say an agent is defined and cannot say the session registered it. - **The clean-room comparison.** Relocating `CLAUDE_CONFIG_DIR` and diffing a bare session is what diff --git a/plugins/harness-config/skills/audit-pass/reference/report-location-and-schema.md b/plugins/harness-config/skills/audit-pass/reference/report-location-and-schema.md index 99e665956c5..64a0730daad 100644 --- a/plugins/harness-config/skills/audit-pass/reference/report-location-and-schema.md +++ b/plugins/harness-config/skills/audit-pass/reference/report-location-and-schema.md @@ -50,9 +50,6 @@ while excluding its `findings.json`, which is the same unfalsifiable-idempotence [plugin manifest reference: environment variables](https://code.claude.com/docs/en/plugins/manifest-reference#environment-variables) and [where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live. - - **As of**: 2026-11-04 - - **Recheck trigger**: either section changes the character rule, or exports the variable to the - Bash tool. It is therefore **outside** a target below `~` and **inside** any target at or above it. The default path is *usually* outside the scan set and is **not diff --git a/plugins/harness-config/skills/audit-permission-grants/SKILL.md b/plugins/harness-config/skills/audit-permission-grants/SKILL.md index 73db5b66690..dd6c2da45d3 100644 --- a/plugins/harness-config/skills/audit-permission-grants/SKILL.md +++ b/plugins/harness-config/skills/audit-permission-grants/SKILL.md @@ -112,8 +112,7 @@ skill cannot write that file. When deciding where an approval-prompt grant lands [permissions: permission system](https://code.claude.com/docs/en/permissions#permission-system) live; when deciding whether anything prunes it, fetch [permissions: manage permissions](https://code.claude.com/docs/en/permissions#manage-permissions) -live (as of 2026-11-04; recheck when the first section changes where a prompt approval is saved or -the second changes how saved rules are removed). +live. If a scope filter was given, run the full detector and present only the matching checks. P1, P2, P2b and P4 are all emitted by the same rule scan, which runs over frontmatter `allowed-tools` and over @@ -158,7 +157,7 @@ P4 does not flag `${CLAUDE_PLUGIN_ROOT}` or `${CLAUDE_PLUGIN_DATA}` in a **plugi `allowed-tools`; in a `Bash(...)` rule anywhere else it does. See [reference/criteria.md](reference/criteria.md), P4. When deciding where those variables resolve, fetch [plugins reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) -live (as of 2026-11-03; recheck when that section changes the fields a plugin variable resolves in). +live. A clean scan ("No fragile permission grants found.") is a valid outcome. Report it as such, with the denominator beside it. `NOTHING TO AUDIT` is **not** that outcome; see "Report the denominator". @@ -169,8 +168,7 @@ the denominator beside it. `NOTHING TO AUDIT` is **not** that outcome; see "Repo - **`/permissions` (built-in command)**: the person's tool for editing rules; the model does not invoke it. When describing what it does, fetch its row in - [commands: all commands](https://code.claude.com/docs/en/commands#all-commands) live (as of - 2026-11-03; recheck when that row changes or leaves the table). + [commands: all commands](https://code.claude.com/docs/en/commands#all-commands) live. - **This skill (marketplace plugin).** Audits grants for portability and auto mode durability across frontmatter and every settings scope, and writes nothing. @@ -196,8 +194,7 @@ The `reference/` files write this skill's directory as ``, which is it into a brief. Those files arrive through the Read tool as plain bytes, so a `${…}` token in them would reach the Bash tool unsubstituted, and the Bash tool's environment has no `CLAUDE_SKILL_DIR` to expand it from. Basis: the plugins reference, -, verified -2026-10-07; recheck when that table adds supporting files to where a `${…}` reference resolves. +. ## Next @@ -216,8 +213,7 @@ a PreToolUse hook). Read those when present; this skill does not assume them. them.** The docs warn that a checked-in skill can grant itself tool access (Pointer: when weighing a repository's own grants, fetch [skills: pre-approve tools for a skill](https://code.claude.com/docs/en/skills#pre-approve-tools-for-a-skill) -live. As of: 2026-10-11. Recheck trigger: that section drops its warning about reviewing checked-in -skills' grants), and an exemption read out of the audited tree is input from the subject of the +live), and an exemption read out of the audited tree is input from the subject of the audit: 1. **Disclosure.** Every declaration the run read is named in the report, with the file it came from diff --git a/plugins/harness-config/skills/audit-permission-grants/reference/criteria.md b/plugins/harness-config/skills/audit-permission-grants/reference/criteria.md index 2ea9005d1be..6c1943d14df 100644 --- a/plugins/harness-config/skills/audit-permission-grants/reference/criteria.md +++ b/plugins/harness-config/skills/audit-permission-grants/reference/criteria.md @@ -23,8 +23,7 @@ project-only scan would miss every grant kept there, and a user-global finding n absolute path rather than `~/.claude/settings.json`. When deciding where prompt approvals are saved and where the user settings file lives, fetch [settings: find or create your settings files](https://code.claude.com/docs/en/settings#find-or-create-your-settings-files) -live (as of 2026-11-03; recheck when that section changes the user file's location or what writes -to it). Frontmatter files under a `vendor/` path segment are skipped: they are +live. Frontmatter files under a `vendor/` path segment are skipped: they are vendored upstream references, not loadable skills/agents/commands, so their `allowed-tools` never take effect and a finding on them would be a false positive. Findings are advisory in the default report mode and under `--count`, which always exit 0 however many findings they print. They are gating under @@ -60,9 +59,6 @@ same record). live; for other settings files, fetch [settings: fix a broken settings file](https://code.claude.com/docs/en/settings#fix-a-broken-settings-file) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: either section changes what Claude Code does when a settings source fails to - parse. The coverage block also counts plugin manifests and plugin `settings.json` files parsed, paths the walk could not open, and files an exclusion rule removed. `No fragile permission grants found.` is printed only against a non-zero @@ -168,7 +164,7 @@ blanket form is false for the file tools. Match the mechanism to the rule class: | Rule class | What actually happens | | --- | --- | -| `Bash(...)` | Read how it matches from [permissions: Bash](https://code.claude.com/docs/en/permissions#bash) live (as of 2026-11-03; recheck when that section changes how a Bash rule matches), and the two exceptions below. | +| `Bash(...)` | Read how it matches from [permissions: Bash](https://code.claude.com/docs/en/permissions#bash) live, and the two exceptions below. | | `Read(...)` / `Edit(...)` | gitignore pattern syntax, which **does** resolve anchors: `~/path` from the home directory, `//path` from the filesystem root, `/path` from the settings source ([permissions](https://code.claude.com/docs/en/permissions#read-and-edit)). The page's own example: `Read(~/Documents/*.pdf)` matches `/Documents/*.pdf`. | The two exceptions on Bash rules: @@ -176,16 +172,14 @@ The two exceptions on Bash rules: 1. **Token substitution in `allowed-tools`.** Some `${CLAUDE_*}` tokens are substituted in Bash rules in `allowed-tools`, some only in a plugin skill, and one only from a minimum Claude Code version. Read which tokens, where, and from which version live from - [skills](https://code.claude.com/docs/en/skills#available-string-substitutions), as of 2026-10-07; - recheck trigger: that section changes which tokens it substitutes in `allowed-tools`. A grant whose + [skills](https://code.claude.com/docs/en/skills#available-string-substitutions). A grant whose token that section substitutes in the grant's own context is the documented way to run a bundled script without a prompt, e.g. `allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)`; a token it does not substitute there, or below its version floor, stays a literal string, and the grant never matches. 2. **Leading env-assignment stripping**, which is scoped, and scoped differently for allow rules than for deny or ask rules. Read which variables are stripped and how each rule kind matches live from - [permissions](https://code.claude.com/docs/en/permissions#process-wrappers), as of 2026-10-07; - recheck trigger: that section's env-assignment paragraph changes. Never assume an allow rule + [permissions](https://code.claude.com/docs/en/permissions#process-wrappers). Never assume an allow rule matches past an assignment that section does not cover. Full doctrine, and the source this row syncs from: the @@ -200,8 +194,7 @@ bare-name command on PATH, or for `Read`/`Edit` rules the `~/` home anchor. **What**: A `Bash(...)` allow rule whose payload begins a path with `~username/` (not the portable `~/` home anchor). We treat such a payload as naming one account, whatever the shell would expand. When deciding how a Bash rule reads a tilde, fetch -[permissions: Bash](https://code.claude.com/docs/en/permissions#bash) live (as of 2026-11-03; -recheck when that section changes how a Bash rule matches a path). +[permissions: Bash](https://code.claude.com/docs/en/permissions#bash) live. **How to check**: run the detector. `Read(~/notes.md)` and other `~/` anchors are not flagged. A URL user-directory segment such as `Bash(curl https://example.com/~alice/index.html)` is not flagged. @@ -262,8 +255,7 @@ declares a `permissions` block. **Why**: we treat a self-granted permission rule as inert, so the operative rule must be added by the operator to user settings. See convention anti-pattern 3. When deciding which keys a plugin `settings.json` honors, fetch -[plugin manifest reference: settings](https://code.claude.com/docs/en/plugins/manifest-reference#settings) live (as -of 2026-11-03; recheck when that section adds `permissions` to the keys it honors). +[plugin manifest reference: settings](https://code.claude.com/docs/en/plugins/manifest-reference#settings) live. **Recommend**: remove the inert block; document an operator-setup note for the bare-name rule instead. @@ -281,8 +273,7 @@ remainder that is not another rule. **Why**: Claude Code reports this shape as invalid settings. A scan that kept only the token would call `Bash(ls) x` a narrow `Bash(ls)` grant. Pointer: when deciding a rule's shape, fetch [permissions: permission rule syntax](https://code.claude.com/docs/en/permissions#permission-rule-syntax) -live. As of: 2026-10-11. Recheck trigger: that section changes how parentheses in a specifier or -trailing text after one are read. +live. **Recommend**: delete the trailing text, or rewrite the rule as one `Tool(specifier)`. diff --git a/plugins/harness-config/skills/audit-permission-state/SKILL.md b/plugins/harness-config/skills/audit-permission-state/SKILL.md index be840006b53..babfd2960fa 100644 --- a/plugins/harness-config/skills/audit-permission-state/SKILL.md +++ b/plugins/harness-config/skills/audit-permission-state/SKILL.md @@ -19,7 +19,6 @@ script can read, and it reports a scope it could not read apart from one that wa - **Pointer**: when deciding whether a built-in surface already exports the merged set, fetch [CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands) and the `/permissions` row of [commands: all commands](https://code.claude.com/docs/en/commands#all-commands) live. -- **As of**: 2026-11-03 - **Recheck trigger**: a release note mentions a permissions export or a `/permissions` export action, or either section adds one. @@ -80,8 +79,6 @@ read-only by construction: it reads the managed sources and never authors them. - **Pointer**: when deciding which managed sources exist and who can write each, fetch [managed settings: where each mechanism stores the policy](https://code.claude.com/docs/en/managed-settings#where-each-mechanism-stores-the-policy) live. -- **As of**: 2026-11-10 -- **Recheck trigger**: that section adds a managed mechanism or a store a plugin or user can write. ## Arguments @@ -159,8 +156,7 @@ These mechanics decide those records, and conflating them produces confident wro across scopes, and records which rule made another inert.** That `inert` record is what answers "why is my allow rule ignored". When checking that order and whether scope rank enters it, fetch [settings: permission rules combine differently than you expected](https://code.claude.com/docs/en/settings#permission-rules-combine-differently-than-you-expected) - live (as of 2026-11-03; recheck when that section changes the evaluation order or how scopes - combine). + live. - **The merge treats a bare tool name as reaching every call of that tool.** A whole-tool deny makes every other rule naming that tool inert, other denies included, with the one exception `reference/criteria.md` names. A whole-tool ask leaves no scoped allow for that tool in effect. @@ -172,13 +168,9 @@ These mechanics decide those records, and conflating them produces confident wro does not model. - **Pointer**: when you need what a carve-out reaches, fetch [permissions: Read and Edit](https://code.claude.com/docs/en/permissions#read-and-edit) live. - - **As of**: 2026-10-10 - - **Recheck trigger**: that section changes what a carve-out reaches, or starts covering a bare - `!` pattern. `reference/criteria.md` maps every `precedence_basis` token to the docs section it follows from, -with that record's as-of date and recheck trigger, and states the two standing bounds the run -prints. +and states the two standing bounds the run prints. ## Phase 3: What entering auto mode drops @@ -290,7 +282,7 @@ nothing surfaces which. Stage: `managed-conformance.sh`, fed the inventory. lower-scope rule of an earlier-evaluated kind outranks a managed rule, because an administrator reads the managed rule as policy. When deciding how managed rules rank and evaluate, fetch [permissions: settings precedence](https://code.claude.com/docs/en/permissions#settings-precedence) - live (as of 2026-11-03; recheck when that section changes managed rank or the evaluation order). + live. - **`managed loosenable autoMode`**: we report a managed `autoMode` section as **additive, not a policy boundary**, since a developer's own entries can loosen it. - **`managed loosenable lockout`**: `disableAutoMode` set to anything but the string `"disable"`. @@ -305,8 +297,7 @@ every rule string it prints came from a file it read. It ships no security floor fold the server-managed cache into the effective set, and do not treat it as the live policy. When deciding where the cache lives and how current it is, fetch [server-managed settings: fetch and caching behavior](https://code.claude.com/docs/en/server-managed-settings#fetch-and-caching-behavior) -live (as of 2026-11-03; recheck when that section changes where the cache is kept or how it is -refreshed). A surface that could not be read gets its own note saying so, because an administrator +live. A surface that could not be read gets its own note saying so, because an administrator reading silence as "no policy deployed" is the failure this report exists to prevent. The note routes that diagnosis to the Organization policy line in `/status` and `claude doctor`. @@ -336,8 +327,8 @@ collapse it in the report: line in `/status` as the failure read. The script says so on every run; carry it into the report rather than implying completeness. - **An `ask` finding names where the contract lives**: the auto mode config page, and the - upstream issue #83766 against it. Carry the caveat `reference/criteria.md` §"Ask rules under auto - mode" words, with its pointer and dated record, when reporting an `ask` result, and point at + upstream issue anthropics/claude-code#83766 against it. Carry the caveat `reference/criteria.md` §"Ask rules under auto + mode" words, with its pointer, when reporting an `ask` result, and point at `permissions.deny` where the outcome must hold regardless. - **`invalid-json` is not `absent`.** A malformed settings file contributes no rules to the inventory. Report the parse failure, not an empty scope, and do not describe a managed parse @@ -349,16 +340,13 @@ collapse it in the report: live; for other settings files, fetch [settings: fix a broken settings file](https://code.claude.com/docs/en/settings#fix-a-broken-settings-file) live. - - **As of**: 2026-10-11 - - **Recheck trigger**: either section changes what Claude Code does when a settings source fails - to parse. ## Scopes Five: `managed`, `user`, `project`, `local` and `startdir-local`. `local` and `startdir-local` are the two easy to get wrong; when deciding where the local file is read from, fetch [settings: where Claude Code keeps the local file in a git repository](https://code.claude.com/docs/en/settings#where-claude-code-keeps-the-local-file-in-a-git-repository) -live (as of 2026-11-04; recheck when that section changes where the local or shared file is kept). +live. The reader takes its own working directory as the session's primary working directory, the one input for `project` and `local`. Run it from the directory the session started in (or last moved to with `/cd`). Below the repository root it reads two shared files, `project settings` from its own @@ -368,7 +356,7 @@ start directory's file is not read unless it is the root's: a session started in can over-report the one not in force. Say which directory the session started in when that decides the answer. When judging whether a `cd` still carries over, fetch [tools reference: what persists between commands](https://code.claude.com/docs/en/tools-reference#what-persists-between-commands) -live (as of 2026-11-04; recheck when that section changes what a `cd` does to the working directory). +live. `managed` is four admin surfaces per OS, not one file, plus a `remote-cache` record for the server-managed cache that is not folded into the effective set. `reference/criteria.md` §Scopes has the full table @@ -383,7 +371,7 @@ conditions, and the one that is not detectable" holds the list and its pointer. **A cloud session reads a different scope set, and the run says so.** We treat a user-scope record in a cloud session as describing the container, not the operator. The reader detects a cloud session by `CLAUDE_CODE_REMOTE`, the only entrypoint variable it branches on. -`reference/criteria.md` §Scopes holds both dated records. +`reference/criteria.md` §Scopes holds both records. ## Prerequisites diff --git a/plugins/harness-config/skills/audit-permission-state/reference/criteria.md b/plugins/harness-config/skills/audit-permission-state/reference/criteria.md index de29941c6d5..02a1b689550 100644 --- a/plugins/harness-config/skills/audit-permission-state/reference/criteria.md +++ b/plugins/harness-config/skills/audit-permission-state/reference/criteria.md @@ -23,11 +23,11 @@ pointer to the section that documents the mechanic; read the wording there. The contract lives in `SKILL.md`; the per-check grant vocabulary lives in the sibling `audit-permission-grants`. Neither is restated here. -Pointers, both read 2026-08-11: +Pointers: [settings precedence](https://code.claude.com/docs/en/settings#settings-precedence), and [Manage permissions](https://code.claude.com/docs/en/permissions#manage-permissions) and [Settings precedence](https://code.claude.com/docs/en/permissions#settings-precedence) on the -permissions page. Recheck when either page's precedence list adds, drops or reorders a scope. +permissions page. --- @@ -62,9 +62,6 @@ else reports that directory's file. fetch the same section and [permissions: permission system](https://code.claude.com/docs/en/permissions#permission-system) live. -- **As of**: 2026-11-04 -- **Recheck trigger**: that section moves the shared file away from the primary working directory, - or the permissions section changes which file a prompt approval is saved to. ### The four start-directory conditions, and the one that is not detectable @@ -80,8 +77,6 @@ than guessing at it. - **Pointer**: [Where Claude Code keeps the local file in a git repository](https://code.claude.com/docs/en/settings#where-claude-code-keeps-the-local-file-in-a-git-repository) and [Environment variables](https://code.claude.com/docs/en/env-vars). -- **As of**: 2026-09-12 -- **Recheck trigger**: either page documents an entrypoint variable or changes the condition list. ### Cloud sessions read a different scope set @@ -118,9 +113,6 @@ either section as a change the reader's scripts owe. and [managed settings: compose every managed source](https://code.claude.com/docs/en/managed-settings#compose-every-managed-source) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: the drop-in section changes how two drop-in files combine a key, or the - compose table gains, drops or reclassifies a key kind. Two are **declared optional platform integrations**: the Windows policy registry keys and the macOS managed-preferences domain. Each is read where it is native and readable; where its tool is missing the surface reports @@ -212,7 +204,7 @@ run of `inert` records. lock only when a managed `conf` record carries `allowManagedPermissionRulesOnly true`. Pointer: when deciding what the lock drops, fetch [settings reference: allowManagedPermissionRulesOnly](https://code.claude.com/docs/en/settings-reference#allowmanagedpermissionrulesonly) - live. As of: 2026-10-11. Recheck trigger: that entry changes what the lock ignores or keeps. + live. - **Rules are compared by exact text, and the error direction is known.** A deny like `Bash(aws *)` wins over each call it covers, a call that a narrower allow like `Bash(aws s3 ls)` also covers included (pointer: [Manage permissions](https://code.claude.com/docs/en/permissions#manage-permissions)). @@ -238,8 +230,6 @@ run of `inert` records. managed settings, since sign-in state is not read here. Where the guard loads, what its options do, and which calls deny rules cover are read live. Pointer: [mods admin: know what happens by default](https://code.claude.com/docs/en/plugins/mods/admin#know-what-happens-by-default). - As of: 2026-10-17. Recheck trigger: that section changes where the guard loads, what deny rules - take precedence over, or which mod calls they cover. ## The auto-mode entry diff @@ -264,9 +254,6 @@ mode it never enters. - **Pointer**: for which mode a session starts in, see [Which mode a session starts in](https://code.claude.com/docs/en/permission-modes#which-mode-a-session-starts-in) (correlate with [the announcement](https://claude.com/blog/auto-mode-default-in-claude-code), 2026-08-14). -- **As of**: 2026-10-01 -- **Recheck trigger**: that section changes a starting mode, adds or removes a run shape, or moves - a version floor. Five documented classes, and every dropped rule is reported as exactly one of them: `blanket`, `interpreter-wildcard`, `package-manager-run`, `agent`, `monitor`. The shell-shape patterns are not @@ -292,8 +279,7 @@ to share, so the diff driver tests them on the tool token instead. which is why the reader inventories it as a `conf` record. Pointer: when deciding what the key does and from which version, fetch [auto mode config: route all shell commands through the classifier](https://code.claude.com/docs/en/auto-mode-config#route-all-shell-commands-through-the-classifier) - live. As of: 2026-10-11. Recheck trigger: that section changes what the key suspends or its - version floor. + live. - **The key is resolved only from scopes the classifier reads**, and the reader implements that set: user settings, managed settings, and inline `--settings`/SDK JSON, never `.claude/settings.json` or `.claude/settings.local.json`. A project- or local-scope occurrence is reported as having no @@ -359,8 +345,8 @@ fixed all three. | `C6-contentField` | Fires on a `Tool(param:value)` rule naming the tool's primary content field. The fields the lint checks, by tool: Bash and PowerShell `command`; Read, Edit, Write `file_path`; Grep, Glob `path`; NotebookEdit `notebook_path`; WebFetch `url`. We treat such a rule as ignored with a startup warning. Pointer: [Match by input parameter](https://code.claude.com/docs/en/permissions#match-by-input-parameter) | | `C6-allowParam` | Fires on an **allow** rule in `Tool(param:value)` form, since we treat parameter matching as a deny-and-ask feature only; allow rules keep each tool's own specifier syntax. Pointer: [Match by input parameter](https://code.claude.com/docs/en/permissions#match-by-input-parameter). An operator writing one believes they narrowed a grant and has not. Fires only on parameters the page names for tools whose own syntax is a path or a command. `WebFetch(domain:host)` is the documented WebFetch form and `Bash(npm:*)` is a command prefix, so neither is distinguishable from a parameter by shape and neither fires | | `C6-uncoveredPath` | Fires on a path rule whose tool is `Write`, `NotebookEdit`, `Glob`, or the retired `MultiEdit`, since we treat file access as decided by `Read(path)` and `Edit(path)` rules alone; such a rule is accepted, never consulted, and warned about at startup (v2.1.210+; a `Glob` rule passed in `--allowedTools` is the stated exception). Pointer: [Read and Edit](https://code.claude.com/docs/en/permissions#read-and-edit). **As of** 2026-10-13. **Recheck when** that section stops naming `MultiEdit` or changes which tools path rules cover | -| `C6-colonStar` | Fires on a mid-pattern `:*`, as in `Bash(git:* push)`, since we treat `:*` as prefix syntax only at the end of a pattern: mid-pattern, the colon is a literal and the `*` a wildcard, so `Bash(git:* push)` matches `git: push` and none of the git commands its author meant. We saw no startup warning for such a rule in a `-p` run, so the lint reports it. **Pointer**: when the mid-pattern colon matters, fetch [Wildcard patterns](https://code.claude.com/docs/en/permissions#wildcard-patterns) live. **As of** 2026-10-10. **Recheck when** that section changes how a mid-pattern `:*` matches, or a release makes it prefix syntax. **Probe**: probed on Claude Code 2.1.296, 2026-10-10; evidence in the pull request that carries this change. The mechanic is about **command-prefix** patterns, so a documented parameter form is exempt: WebFetch's `domain:` prefix takes `*` wildcards ([WebFetch](https://code.claude.com/docs/en/permissions#webfetch)), and firing on `WebFetch(domain:*.example.com)` called a documented, working rule broken. A body that starts with `*` and holds no space, as in `PowerShell(*env:*lefthook*)`, is exempt too: it has no command prefix, so the literal colon is what it means to match. A space restores the prefix-then-words shape, so `Bash(* git:* push)` and `Bash(*foo:* rm)` still fire. **Ambiguous form:** in a deny or ask rule a mid-pattern `:*` with NO space after it, as in `Bash(git:*push)`, does not fire this error; unless its tool and prefix are a known parameter, it is reported as the warning `C6-colonStarAmbiguous`, asking the author to say which they meant. It is structurally identical to the parameter form `Agent(model:*-haiku)`, so once the space is gone nothing in the rule text distinguishes them; the space was the only signal. The documented example is the space form, and the pages show no no-space mid-pattern rule anywhere. The exemption is by **grammar**, where in a deny or ask rule an `identifier:value` body is the parameter form, not by a list of parameter names: we treat parameter matching as working for any scalar parameter on any built-in tool, and an `mcp__` rule with parentheses in a settings file as a separate case this row does not judge ([Match by input parameter](https://code.claude.com/docs/en/permissions#match-by-input-parameter), as of 2026-11-04; recheck when that section changes which tools it covers or how settings files treat such a rule), so an allowlist could only ever chase it and would flag documented forms such as `Agent(model:*-haiku)` | -| `C6-malformed` | Fires on text after a specifier's closing parenthesis, as in `Bash(ls) x`, and on an unclosed specifier. A parenthesis inside the specifier does not fire, so `Edit(./Finance (2024)/**)` is one rule. The lint used to keep only the token and treat `Bash(ls) x` as `Bash(ls)`. **Pointer**: when deciding which rule shapes are accepted and how trailing text is treated, fetch [permissions: permission rule syntax](https://code.claude.com/docs/en/permissions#permission-rule-syntax) live. **As of** 2026-11-03. **Recheck when** that section changes how parentheses in a specifier or text after one are read | +| `C6-colonStar` | Fires on a mid-pattern `:*`, as in `Bash(git:* push)`, since we treat `:*` as prefix syntax only at the end of a pattern: mid-pattern, the colon is a literal and the `*` a wildcard, so `Bash(git:* push)` matches `git: push` and none of the git commands its author meant. We saw no startup warning for such a rule in a `-p` run, so the lint reports it. **Pointer**: when the mid-pattern colon matters, fetch [Wildcard patterns](https://code.claude.com/docs/en/permissions#wildcard-patterns) live. **As of** 2026-10-10. **Recheck when** that section changes how a mid-pattern `:*` matches, or a release makes it prefix syntax. **Probe**: probed on Claude Code 2.1.296, 2026-10-10; evidence in the pull request that carries this change. The mechanic is about **command-prefix** patterns, so a documented parameter form is exempt: WebFetch's `domain:` prefix takes `*` wildcards ([WebFetch](https://code.claude.com/docs/en/permissions#webfetch)), and firing on `WebFetch(domain:*.example.com)` called a documented, working rule broken. A body that starts with `*` and holds no space, as in `PowerShell(*env:*lefthook*)`, is exempt too: it has no command prefix, so the literal colon is what it means to match. A space restores the prefix-then-words shape, so `Bash(* git:* push)` and `Bash(*foo:* rm)` still fire. **Ambiguous form:** in a deny or ask rule a mid-pattern `:*` with NO space after it, as in `Bash(git:*push)`, does not fire this error; unless its tool and prefix are a known parameter, it is reported as the warning `C6-colonStarAmbiguous`, asking the author to say which they meant. It is structurally identical to the parameter form `Agent(model:*-haiku)`, so once the space is gone nothing in the rule text distinguishes them; the space was the only signal. The documented example is the space form, and the pages show no no-space mid-pattern rule anywhere. The exemption is by **grammar**, where in a deny or ask rule an `identifier:value` body is the parameter form, not by a list of parameter names: we treat parameter matching as working for any scalar parameter on any built-in tool, and an `mcp__` rule with parentheses in a settings file as a separate case this row does not judge ([Match by input parameter](https://code.claude.com/docs/en/permissions#match-by-input-parameter)), so an allowlist could only ever chase it and would flag documented forms such as `Agent(model:*-haiku)` | +| `C6-malformed` | Fires on text after a specifier's closing parenthesis, as in `Bash(ls) x`, and on an unclosed specifier. A parenthesis inside the specifier does not fire, so `Edit(./Finance (2024)/**)` is one rule. The lint used to keep only the token and treat `Bash(ls) x` as `Bash(ls)`. **Pointer**: when deciding which rule shapes are accepted and how trailing text is treated, fetch [permissions: permission rule syntax](https://code.claude.com/docs/en/permissions#permission-rule-syntax) live. | | `C6-literalPath` | A Read or Edit path that is not a usable gitignore pattern, such as an unclosed `[`. As a deny or ask rule it protects only that literal path; as an allow rule it grants nothing. One such deny used to fail every file edit; that is not the current behavior | The version boundaries and field lists a row names are the ones its script emits; before acting @@ -396,7 +382,7 @@ Prose judgment belongs to `claude auto-mode critique`, which is surfaced rather | Check | What it means | | --- | --- | -| `C4-defaults` | a customized section omits `"$defaults"`. The finding names how many built-in entries are gone, because "you dropped N soft_deny rules" is actionable where "missing $defaults" is not. **Pointer**: when deciding what omitting `"$defaults"` does, fetch [auto mode config: override the block and allow rules](https://code.claude.com/docs/en/auto-mode-config#override-the-block-and-allow-rules) live. **As of** 2026-11-03. **Recheck when** that section changes what a section without `"$defaults"` keeps | +| `C4-defaults` | a customized section omits `"$defaults"`. The finding names how many built-in entries are gone, because "you dropped N soft_deny rules" is actionable where "missing $defaults" is not. **Pointer**: when deciding what omitting `"$defaults"` does, fetch [auto mode config: override the block and allow rules](https://code.claude.com/docs/en/auto-mode-config#override-the-block-and-allow-rules) live. | | `C2b-contradiction` | the same label subject appears in `allow` and in a deny section | | `C3-shadowed` | an entry whose subject is already in `hard_deny`, which cannot be overridden, so the entry can never change an outcome | @@ -456,9 +442,6 @@ surviving auto mode. Treat `ask` as a prompt you *expect*, not a guarantee you * - **Pointer**: [Add a human checkpoint](https://code.claude.com/docs/en/auto-mode-config#add-a-human-checkpoint) and [Compound commands](https://code.claude.com/docs/en/permissions#compound-commands). -- **As of**: 2026-10-11 -- **Recheck trigger**: #83766 closes, or the auto-mode config page changes whether a content-scoped - ask rule always prompts. ## Managed policy, and what it does not buy @@ -480,7 +463,7 @@ any scope**. So a lower-scope deny changes the outcome of a managed allow withou | `enforced deny` | a managed deny, which no other level can allow. The strongest thing an administrator can write | | `enforced allow` / `enforced ask` | the managed rule is highest and nothing beneath it outranks its kind | | `loosenable rule` | a lower scope carries an earlier-evaluated kind for the same rule text | -| `loosenable autoMode` | a managed `autoMode` block, which we treat as additive, not a policy boundary: lower scopes can add to it and can outweigh some of its entries, and auto mode has no exclusivity lock of the kind other surfaces have. How the scopes layer is read live (pointer: when grading a managed `autoMode` block, fetch [auto mode config: where the classifier reads configuration](https://code.claude.com/docs/en/auto-mode-config#where-the-classifier-reads-configuration); as of 2026-10-11; recheck when that section changes how scopes combine or adds an exclusivity lock for auto mode) | +| `loosenable autoMode` | a managed `autoMode` block, which we treat as additive, not a policy boundary: lower scopes can add to it and can outweigh some of its entries, and auto mode has no exclusivity lock of the kind other surfaces have. How the scopes layer is read live (pointer: when grading a managed `autoMode` block, fetch [auto mode config: where the classifier reads configuration](https://code.claude.com/docs/en/auto-mode-config#where-the-classifier-reads-configuration)) | | `enforced` / `loosenable lockout` | `disableAutoMode` is a real lock only when it carries the documented string `"disable"` | The remedy the `autoMode` finding names is `permissions.deny` in managed settings, for an action that diff --git a/plugins/harness-config/skills/audit-permission-state/reference/gotchas.md b/plugins/harness-config/skills/audit-permission-state/reference/gotchas.md index 011f469bd07..7b3b4d2cb7a 100644 --- a/plugins/harness-config/skills/audit-permission-state/reference/gotchas.md +++ b/plugins/harness-config/skills/audit-permission-state/reference/gotchas.md @@ -38,8 +38,7 @@ platform is not. rather than guessing; `criteria.md` §Scopes owns the conditions it resolves. - **Pointer**: when checking where the file lives, fetch [settings: where Claude Code keeps the local file in a git repository](https://code.claude.com/docs/en/settings#where-claude-code-keeps-the-local-file-in-a-git-repository) - live. **As of**: 2026-11-03. **Recheck trigger**: that section changes where the file is kept, - or which conditions keep it elsewhere. + live. - **An empty merge is not an empty machine.** The merge exits 2 when the input carries no scope records at all, so a reader that died cannot feed it a clean "nothing in effect"; if you build your own pipeline around these scripts, check the status rather than the output. @@ -48,12 +47,10 @@ platform is not. its dated record are in `criteria.md` §Scopes. - **Pointer**: when deciding how the two copies combine, fetch [settings: where Claude Code keeps the local file in a git repository](https://code.claude.com/docs/en/settings#where-claude-code-keeps-the-local-file-in-a-git-repository) - live. **As of**: 2026-11-03. **Recheck trigger**: that section changes whether, or how, a second - copy of the file applies. + live. - **A cloud session's user scope is not the operator's.** The run emits a note whenever `CLAUDE_CODE_REMOTE` says it is in a cloud session; carry it into the report rather than presenting the cloud container's user file as the operator's configuration. - **Pointer**: when deciding which settings a cloud session reads, fetch [settings: settings in cloud sessions](https://code.claude.com/docs/en/settings#settings-in-cloud-sessions) - live. **As of**: 2026-11-03. **Recheck trigger**: that section changes which settings files or - managed sources reach a cloud session. + live. diff --git a/plugins/harness-config/skills/audit-prompting-postures/SKILL.md b/plugins/harness-config/skills/audit-prompting-postures/SKILL.md index 19d3152dced..d0ed192fb36 100644 --- a/plugins/harness-config/skills/audit-prompting-postures/SKILL.md +++ b/plugins/harness-config/skills/audit-prompting-postures/SKILL.md @@ -33,9 +33,8 @@ Phase D's persist script, and a shell mutates files too. That closes the likelie capability, and a skill auditing assurance must not overstate its own. We treat the restriction as clearing on the human's next message, so whoever accepts a proposal can apply it (Pointer: when deciding how long the restriction lasts, fetch -[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference) live. -As of: 2026-10-11. Recheck trigger: that section or a release note changes how long -`disallowed-tools` lasts). +[skills: frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference) +live). ## Scope boundary (route out) @@ -104,7 +103,7 @@ importing record already covers. - **Pointer**: when deciding which files a mode loads, fetch [memory: choose which instruction files load](https://code.claude.com/docs/en/memory#choose-which-instruction-files-load) - live. **As of**: 2026-11-03. **Recheck trigger**: that section adds, removes or changes a mode. + live. **The inventory bounds what may produce a finding, not what counts as evidence.** Phase C's mechanical-gate rule reads outside it to establish PRESENCE, which can only turn a MISSING into a @@ -189,8 +188,7 @@ of your own, against the plugin data directory.** (Pointer: when deciding where resolves, fetch [plugins manifest reference: where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) live; for why an inline command against the data directory is avoided, read the eval-trace -evidence in #12039. As of: 2026-11-01. Recheck trigger: that section changes which environments -receive `${CLAUDE_PLUGIN_DATA}`, or a later eval trace shows an inline command against the data +evidence in melodic-software/claude-code-plugins#12039. Recheck trigger: a later eval trace shows an inline command against the data directory running undenied.) We key the report per project because one data directory serves every project on the machine, so @@ -198,7 +196,7 @@ a fixed `last-audit.md` would be silently overwritten by the next run from any o skill's only durable deliverable, destroyed by ordinary use of it (Pointer: when deciding the data directory's scope, fetch [plugins manifest reference: environment variables](https://code.claude.com/docs/en/plugins/manifest-reference#environment-variables) -live. As of: 2026-11-10. Recheck trigger: that section makes the data directory per project). The scheme is `/`, defined by the +live). The scheme is `/`, defined by the marketplace's `plugin-data-report-keying` convention and reused rather than reinvented, and it lives in one executable rather than being restated per skill, [`lib/state-key.sh`](../../lib/state-key.sh), with `lib/state-key.test.sh` beside it, which the @@ -208,8 +206,7 @@ An uninstall can delete the plugin's data directory, so when a report must outli closing line says to copy it out of the data directory (Pointer: when deciding whether a report survives an uninstall, fetch [plugins CLI reference: what an uninstall deletes and keeps](https://code.claude.com/docs/en/plugins/cli-reference#what-an-uninstall-deletes-and-keeps) -live. As of: 2026-10-11. Recheck trigger: that section or a release note changes what uninstalling -does with `${CLAUDE_PLUGIN_DATA}`). +live). Let the script derive the key. Do **not** express the path as a condition over `${CLAUDE_PROJECT_DIR}` "when set": where that placeholder is substituted (pointer below) makes the condition not yours @@ -218,8 +215,6 @@ to evaluate. Derive the key from a command you run. - **Pointer**: when deciding where a skill placeholder is substituted, fetch [skills: available string substitutions](https://code.claude.com/docs/en/skills#available-string-substitutions) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section changes where or when `${CLAUDE_PROJECT_DIR}` is substituted. **Open the report with a three-line header**, so a file that survives is self-describing: diff --git a/plugins/harness-config/skills/audit-prompting-postures/reference/postures.md b/plugins/harness-config/skills/audit-prompting-postures/reference/postures.md index 49212836ddb..586b75c2d85 100644 --- a/plugins/harness-config/skills/audit-prompting-postures/reference/postures.md +++ b/plugins/harness-config/skills/audit-prompting-postures/reference/postures.md @@ -2,8 +2,7 @@ Fourteen postures. Each row: the applicability predicate (which component purposes it binds), what counts as present, and the guide pointer that owns the recommended wording. Pointers only. -Wording is fetched live per SKILL.md Phase A; the recheck trigger for every row is a change to its -cited section. +Wording is fetched live per SKILL.md Phase A. Guide root: (sections cited by heading). Model subpages cited by page + heading where a row needs one. @@ -29,14 +28,10 @@ Rows cite the subpages of the current models first. A subpage name in a row mean We keep them in P1 while Claude Code can still put a session on either model. Pointer: for the models a session can fall back to, see [model configuration: automatic model fallback](https://code.claude.com/docs/en/model-config#automatic-model-fallback). - As of: 2026-10-01. Recheck trigger: either model leaves Claude Code's model page. + Recheck trigger: either model leaves Claude Code's model page. - **Pointer**: for which model each subpage covers, see the [model-specific guidance table](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices#model-specific-guidance). -- **As of**: 2026-10-01 (each subpage read as raw markdown that day); the Fable 5.2 subpage read - whole on 2026-11-09. -- **Recheck trigger**: a row's cited heading disappears from its subpage, or that table gains or - drops a row. A row's "correlate:" note names a heading in the Opus 5.5 usage guide (correlate with , published 2026-09-22), @@ -64,7 +59,6 @@ carries the Sonnet 5.5 condition. (P8) and [verification on coding tasks](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-sonnet-5-5#verification-on-coding-tasks) (P13). -- **As of**: 2026-10-01 - **Recheck trigger**: a cited heading disappears from that subpage, or another model's subpage covers self-started review rounds, which re-opens P12's model condition. @@ -76,7 +70,6 @@ nothing in the section recommends a steer on where the run ends. - **Pointer**: the Fable 5.2 subpage's [set expectations for subagents](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-fable-5-2#set-expectations-for-subagents). -- **As of**: 2026-11-09 - **Recheck trigger**: that section starts recommending a steer on where the run ends, which extends P12's condition to Fable 5.2. @@ -154,8 +147,7 @@ Classify each component by what its body has the model DO (multiple or none): On 2026-10-01 that was the only docs section covering this check: we read the Fable 5.1, Opus 5.5 and Sonnet 5.5 subpages that day (raw markdown, no artifact stored) and none of them covers tying progress claims to tool-result evidence; the Fable 5.2 subpage, read whole on 2026-11-09, does - not either. As of: 2026-11-09. Recheck trigger: a current model's subpage starts covering the - check (repoint there), or that Fable 5 section disappears. + not either. ### P6: Autonomy or checkpoint posture @@ -201,7 +193,6 @@ Classify each component by what its body has the model DO (multiple or none): model condition. Read the model list on the run's live fetch; this file keeps no copy. Pointer: for which models the capability covers, see [context windows: context awareness](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-awareness). - As of: 2026-10-01. Recheck trigger: that section's model list changes. - **Present when:** the surfaced figure is accompanied by do-not-wrap-up-early framing (or the component deliberately avoids surfacing raw countdowns at all, the stronger form). - **Pointer:** main page, diff --git a/plugins/harness-config/skills/audit/SKILL.md b/plugins/harness-config/skills/audit/SKILL.md index d9d7b93a0b3..b2a5400ded8 100644 --- a/plugins/harness-config/skills/audit/SKILL.md +++ b/plugins/harness-config/skills/audit/SKILL.md @@ -78,7 +78,7 @@ A row the engine marks `skip` or `not-inspectable` is exactly that in the report | `.mcp.json` | the engine, or `jq` | Project-level MCP server definitions | | `~/.claude/settings.json` | the engine, or the Read tool | User-level defaults (optional; checked when it exists) | | start-directory `.claude/settings.local.json` | `check-structure.sh` (structure only) | Only when the session's start directory is not the repository root AND a copy is there. We treat it as live beside the repository-root copy; how the two combine, and the version boundary behind the copy, are the dated record in `audit-permission-state/reference/criteria.md` §Scopes | -| `managed-settings.json` + `managed-settings.d/` | `check-structure.sh` (structure only) | Machine-scope managed policy, the highest-precedence layer. OS-specific path resolved by the script (Pointer: for each OS's location, fetch [managed settings: where each mechanism stores the policy](https://code.claude.com/docs/en/managed-settings#where-each-mechanism-stores-the-policy) live. As of: 2026-11-10. Recheck trigger: that section moves a file location). Findings on it are report-only routing; managed policy is the administrator's, never edited by `--fix` | +| `managed-settings.json` + `managed-settings.d/` | `check-structure.sh` (structure only) | Machine-scope managed policy, the highest-precedence layer. OS-specific path resolved by the script (Pointer: for each OS's location, fetch [managed settings: where each mechanism stores the policy](https://code.claude.com/docs/en/managed-settings#where-each-mechanism-stores-the-policy) live). Findings on it are report-only routing; managed policy is the administrator's, never edited by `--fix` | | managed policy outside the filesystem | not read | The OS-level policy stores (Windows registry policy keys, the macOS managed-preferences domain) listed at the same pointer. `check-structure.sh` names them so an absent `managed-settings.json` is never read as "no managed policy deployed", but it does not read them | | `docs/conventions/harness-config.yaml` (`suppressions`, the team layer of three cascade layers) | the engine | The consumer's suppression record, keyed by `finding_id`, in the convention home the repository binds (default `docs/conventions`). A finding it carries is reported as suppressed with its reason and the layer and file that supplied it; only the team layer suppresses, a personal-only entry is reported as not applied, and a malformed entry is reported and never suppresses. `suppressions.layers` in the engine's output names each file read | @@ -147,9 +147,8 @@ Each category writes an `audit-engine: ` line to stderr as it starts; Pass `--debug-log` when you know where this session's debug log is; otherwise the engine looks in the documented locations (the debug-log variable first, then the newest file under `/debug/`; Pointer: for that variable and what it names, fetch -[environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live. As -of: 2026-11-10. Recheck trigger: the debug-log variable is renamed or changes what it names). A log it found rather than was given settles the row only when the log -names this project. +[environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live). A +log it found rather than was given settles the row only when the log names this project. ### 1.0 Hook inventory @@ -160,8 +159,7 @@ checkout first, the installed-plugin registry otherwise), plus the levers (`disa `allowManagedHooksOnly`, `strictPluginOnlyCustomization` in the forms that cover hooks; Pointer: for those forms, fetch [settings reference: strictPluginOnlyCustomization](https://code.claude.com/docs/en/settings-reference#strictpluginonlycustomization) -live. As of: 2026-11-10. Recheck trigger: that section changes which values lock hooks) that -switch hooks off, the mod-plane keys reported apart from them (`D/mod-plane`), and any +live) that switch hooks off, the mod-plane keys reported apart from them (`D/mod-plane`), and any divergence between the loaded directory and the registry's cache snapshot. **Read the inventory state, not just the rows.** `complete` means every enabled plugin resolved. @@ -272,9 +270,6 @@ The script never rewrites the baseline itself. - **Pointer**: for the levels, per-model defaults and level guidance the check reads, see [Adjust effort level](https://code.claude.com/docs/en/model-config#adjust-effort-level) and [Choose an effort level](https://code.claude.com/docs/en/model-config#choose-an-effort-level). -- **As of**: 2026-10-10 -- **Recheck trigger**: the check reports `table status=unparsed`, or either section is renamed or - moved. ### 3.1 Official docs check @@ -468,8 +463,7 @@ Put that path in place of the placeholder before running a command or writing it files arrive through the Read tool as plain bytes, so a `${…}` token in them would reach the Bash tool unsubstituted, and the Bash tool's environment has no `CLAUDE_SKILL_DIR` to expand it from. Basis: the plugins reference, -, verified -2026-10-07; recheck when that table adds supporting files to where a `${…}` reference resolves. +. ## Next diff --git a/plugins/harness-config/skills/audit/context/procedures.md b/plugins/harness-config/skills/audit/context/procedures.md index 6407ad36879..9436809acab 100644 --- a/plugins/harness-config/skills/audit/context/procedures.md +++ b/plugins/harness-config/skills/audit/context/procedures.md @@ -19,8 +19,6 @@ baseline. - **Pointer**: when deciding which commands a `Read` deny blocks, fetch [permissions: read and edit](https://code.claude.com/docs/en/permissions#read-and-edit) live. - **As of**: 2026-11-03. **Recheck trigger**: that section changes which Bash commands or - subprocesses a `Read` deny covers. **Counts are not guaranteed.** Where the project also enables the sandbox, a `Read` deny on the file can block `check-structure.sh` too. The script distinguishes that case: it reports @@ -31,8 +29,7 @@ anyway. A `Present: yes` / `Readable: no` pair is a correct result, not a broken - **Pointer**: when deciding whether the sandbox blocks the script, fetch [sandboxing: how sandboxing relates to permissions and permission modes](https://code.claude.com/docs/en/sandboxing#how-sandboxing-relates-to-permissions-and-permission-modes) - live. **As of**: 2026-11-03. **Recheck trigger**: that section changes how permission deny rules - feed the sandbox boundary. + live. ```bash # Key inventory (no values) @@ -79,8 +76,7 @@ back; never retry around the refusal. The probe record of which operations were - **Pointer**: when deciding what the classifier blocks, fetch [permission modes: what the classifier blocks by default](https://code.claude.com/docs/en/permission-modes#what-the-classifier-blocks-by-default) - live. **As of**: 2026-11-03. **Recheck trigger**: that section changes what it blocks for edits to - settings or agent configuration. + live. **The judgment on a baseline deny addition, stated.** Two things have to be checked before the rule is added, and neither is mechanical: @@ -93,8 +89,7 @@ added, and neither is mechanical: [validation-categories.md](validation-categories.md) Category D, and which `strictPluginOnlyCustomization` values cover hooks from [settings reference: strictPluginOnlyCustomization](https://code.claude.com/docs/en/settings-reference#strictpluginonlycustomization) - live, as of 2026-11-03; recheck when that entry changes which values cover hooks), - a `Bash` hook does not cover the `Read`-pattern family, and one command family's coverage says + live), a `Bash` hook does not cover the `Read`-pattern family, and one command family's coverage says nothing about another's. **The inventory half is a lookup**: Phase 1.0's `scripts/check-hook-coverage.sh` enumerates settings-declared *and* plugin-declared hooks, resolving each enabled plugin through the installed-plugin registry. What stays a judgment is @@ -106,8 +101,7 @@ added, and neither is mechanical: security one. See "Interaction with hook-based gates" in the same file. Whether a hook's outcome survives a deny or ask rule is read from [permissions: precedence among rules, hooks, and mods](https://code.claude.com/docs/en/permissions#precedence-among-rules-hooks-and-mods) - live (as of 2026-11-03; recheck when that section changes how deny or ask rules rank against a - hook's result). + live. *Moving* an existing deny rule from local to project stays mechanical, since it is bug #8961 placement, not a policy change. diff --git a/plugins/harness-config/skills/audit/context/validation-categories.md b/plugins/harness-config/skills/audit/context/validation-categories.md index 15fccc138ad..b0636ae04c7 100644 --- a/plugins/harness-config/skills/audit/context/validation-categories.md +++ b/plugins/harness-config/skills/audit/context/validation-categories.md @@ -113,15 +113,12 @@ complete set. - Flag a recognizably millisecond-scale `timeout` figure (a round thousands multiple like `30000` or `120000`), not merely a large one. Read the field's unit and limits from [hooks: timeouts](https://code.claude.com/docs/en/hooks#timeouts) and the `timeout` row of - [hooks: common fields](https://code.claude.com/docs/en/hooks#common-fields) live (as of 2026-11-03; - recheck when either changes the unit or adds a maximum) + [hooks: common fields](https://code.claude.com/docs/en/hooks#common-fields) live - Timeouts are reasonable: 5-15s for simple formatters, 30s for slow-startup tools (pwsh) - Matchers take their intended evaluation path. The characters a matcher holds decide whether it is read as an exact-string list or as a regex, and a regex may match more than the author meant (`Edit.*` can also match `NotebookEdit`). Read the character rule and the anchoring behavior from - [hooks: matcher patterns](https://code.claude.com/docs/en/hooks#matcher-patterns) live (as of - 2026-10-11; recheck when that section changes which characters select each path or how a regex is - anchored) + [hooks: matcher patterns](https://code.claude.com/docs/en/hooks#matcher-patterns) live - A shell-form hook quotes each path placeholder; exec form is the docs' preference but shell form is correct when the hook needs pipes, `&&`, redirects, or a `.cmd`/`.bat` shim, so do not flag it - On a Windows-targeting repo, judge exec-form `command` resolution from the Category D @@ -135,8 +132,7 @@ complete set. a blanket value or a per-surface list; read which values switch hooks off, and what each other surface value blocks, from [settings reference: strictPluginOnlyCustomization](https://code.claude.com/docs/en/settings-reference#strictpluginonlycustomization) - live (as of 2026-10-11; recheck when that entry adds a surface value or changes what one blocks). - Report each as set or unset, name the surfaces a customization array + live. Report each as set or unset, name the surfaces a customization array locks, and say which of the inventoried hooks each one switches off. This is a state reading, not a finding on its own. Category B's third baseline narrowing depends on this reading: it may not downgrade a missing deny @@ -208,8 +204,6 @@ never turns a removed row into a rename to `null`. It still removes only an orph exactly `false`. - **Pointer**: when a catalog rename's effect on a settings file is in question, fetch [Migrate users with a renames map](https://code.claude.com/docs/en/plugins/host-marketplace#migrate-users-with-a-renames-map) live. -- **As of**: 2026-10-03 -- **Recheck trigger**: that section changes what a renames entry points at, how a chain is followed, or which settings files a session rewrites. | Mode | Definition | Fix policy | |---|---|---| @@ -300,8 +294,7 @@ and names the levers. What governs the category: This file keeps no copy of either upstream value: read them in Phase 3 from the pointers in [audit-checklist.md](../reference/audit-checklist.md) row G, and how the budget is set from [settings reference: skillListingBudgetFraction](https://code.claude.com/docs/en/settings-reference#skilllistingbudgetfraction) - live (as of 2026-11-03; recheck when that entry changes how the budget is set or overridden), - before publishing a number + live, before publishing a number - **Overflow check: an existing debug log first, then two routes, and only one of those survives a headless run.** The engine looks for a debug log this session already wrote, at the path `--debug-log` names, else `CLAUDE_CODE_DEBUG_LOGS_DIR`, else the newest file under @@ -313,8 +306,7 @@ and names the levers. What governs the category: the user to run `/doctor` or read `/context`. When this audit runs headless, under `-p`, a spawned agent, or a background job, use the debug-log route instead. Read what each route reports from [skills: skill descriptions are cut short](https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short) - live (as of 2026-11-03; recheck when that section changes which commands report the listing or - where the over-budget warning is written). Report which route was taken; a category that names + live. Report which route was taken; a category that names only `/doctor` yields nothing in a headless run. Repos with large skill rosters overflow routinely - **Measure the roster composition before naming a lever.** Count listing entries by origin: plugin skills, project skills (`.claude/skills/`), user skills (`${CLAUDE_CONFIG_DIR:-~/.claude}/skills/`). @@ -352,7 +344,7 @@ and names the levers. What governs the category: override belongs in `settings.json`, and the entry may still be intended for home-rooted sessions. Read that file's scope from [settings: compare the scope of each settings file](https://code.claude.com/docs/en/settings#compare-the-scope-of-each-settings-file) - live (as of 2026-11-03; recheck when that section changes the local file's scope). The engine + live. The engine lists that read in its `scopes` block as `user-local` (absent, unreadable, invalid or ok), except in a home-rooted run, where the file is the local scope @@ -385,9 +377,8 @@ effort settings". What governs the category: - **Placement is out of reach.** Where `availableModels` and `enforceAvailableModels` must sit, and whether a lower managed source's value survives, depend on how the organization combines its managed sources, a mode the files this skill reads do not decide - ([managed settings: how Claude Code combines managed sources](https://code.claude.com/docs/en/managed-settings#how-claude-code-combines-managed-sources), - as of 2026-10-11; recheck when that section adds or drops a combining mode or changes how a mode - treats these keys). So report the value-level finding and leave placement to the administrator. `deniedModels` and `availableModelsMatch` are the exception: + ([managed settings: how Claude Code combines managed sources](https://code.claude.com/docs/en/managed-settings#how-claude-code-combines-managed-sources)). + So report the value-level finding and leave placement to the administrator. `deniedModels` and `availableModelsMatch` are the exception: every file this skill reads is outside managed settings, so finding either key in one settles it ## Category I: Deep-link registration @@ -408,8 +399,7 @@ registration". What governs the category: reads a file that violates it. Where the schema and the docs page disagree, the docs page states the behavior: read it from [settings reference: disableDeepLinkRegistration](https://code.claude.com/docs/en/settings-reference#disabledeeplinkregistration) - live (as of 2026-11-03; recheck when that entry changes the accepted value or when registration - happens) + live - **Value first, then placement.** A key that is **present** and not the string `"disable"` is a prevention that was never invoked (warning); gate on `has(…)`, since an absent key is a consumer accepting the default on purpose. Where an organization requires enforcement and the key sits with diff --git a/plugins/harness-config/skills/audit/reference/audit-checklist.md b/plugins/harness-config/skills/audit/reference/audit-checklist.md index 916164f9108..928d2d6e196 100644 --- a/plugins/harness-config/skills/audit/reference/audit-checklist.md +++ b/plugins/harness-config/skills/audit/reference/audit-checklist.md @@ -48,7 +48,7 @@ permission floor" in the same file. | Check | Severity | How to verify | | --- | --- | --- | -| Deny rules are in settings.json, NOT settings.local.json | error | Put deny rules in `settings.json`; for why, read upstream issue [#8961](https://github.com/anthropics/claude-code/issues/8961) live (as of 2026-11-03; recheck when that issue closes) | +| Deny rules are in settings.json, NOT settings.local.json | error | Put deny rules in `settings.json`; for why, read upstream issue [#8961](https://github.com/anthropics/claude-code/issues/8961) live (recheck when that issue closes) | | No blanket `Bash(git *)` in allow (too broad) | warning | Should be split into specific git operations | ### B.5 Completeness @@ -97,13 +97,13 @@ permission floor" in the same file. | `timeout` is a seconds value, not milliseconds | warning | We read `timeout` as seconds. Flag a **recognizably millisecond-scale** value: a round thousands multiple such as `30000` or `120000`, which read as seconds are 8 h and 33 h. Do NOT flag merely-large values: the reference sets per-type defaults, not a maximum, so a deliberately long-running hook may legitimately run longer than its default. When the value is large but not millisecond-shaped, corroborate against the hook's expected runtime before reporting anything. Pointer: for the unit and the per-type defaults, see [hooks: common fields](https://code.claude.com/docs/en/hooks#common-fields). As of: 2026-10-01. Recheck trigger: that field's unit changes, or the reference adds a maximum | | Timeouts are reasonable (5-15s for simple formatters, 30s for slow-startup tools such as pwsh) | warning | Compare against known good values. These figures are this skill's judgment, not a documented limit | | Matcher takes its intended evaluation path | warning | Classify the matcher by its characters, confirm exact-match vs regex matches intent, anchor regex-path matchers with `^…$` | -| Shell-form path placeholders are quoted | warning | Flag a shell-form hook whose project/plugin placeholder is unquoted, in **either** spelling, braced (`${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_PLUGIN_DATA}`) or bare-dollar (`$CLAUDE_PROJECT_DIR`), since both reach the shell and an unquoted path breaks on a space either way. Do **not** flag shell form itself, and do not flag quoted shell form. For a hook that names a path placeholder, the report may suggest exec form as an option; which form fits a given hook is the pointer's to say, not this row's. Pointer: for the quoting rule, see [hooks: reference scripts by path](https://code.claude.com/docs/en/hooks#reference-scripts-by-path); for when each form fits, see [hooks: exec form and shell form](https://code.claude.com/docs/en/hooks#exec-form-and-shell-form). As of: 2026-10-01. Recheck trigger: either section changes its quoting rule or its form preference | +| Shell-form path placeholders are quoted | warning | Flag a shell-form hook whose project/plugin placeholder is unquoted, in **either** spelling, braced (`${CLAUDE_PROJECT_DIR}`, `${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_PLUGIN_DATA}`) or bare-dollar (`$CLAUDE_PROJECT_DIR`), since both reach the shell and an unquoted path breaks on a space either way. Do **not** flag shell form itself, and do not flag quoted shell form. For a hook that names a path placeholder, the report may suggest exec form as an option; which form fits a given hook is the pointer's to say, not this row's. Pointer: for the quoting rule, see [hooks: reference scripts by path](https://code.claude.com/docs/en/hooks#reference-scripts-by-path); for when each form fits, see [hooks: exec form and shell form](https://code.claude.com/docs/en/hooks#exec-form-and-shell-form). | | Exec-form `command` resolves on every platform the repo targets | error | Flag only for a repo that runs on Windows: an exec-form hook whose `command` is not a real executable that runs the hook there. `bash`, `sh`, a `.sh` path, and a `.cmd`/`.bat` shim are examples, not the whole set. On macOS and Linux the same hook is not a finding. We rate it `error` because a gate hook that does not launch enforces nothing. Do not accept bare `bash` with the script in `args` as the fix. The fixes we accept: `"command": "node"` with the script path in `args`, or shell form with `"shell": "bash"`. For why each of these fails or works on Windows, follow the pointer. Pointer: for the Windows exec-form rule, see [hooks: exec form and shell form](https://code.claude.com/docs/en/hooks#exec-form-and-shell-form). As of: 2026-09-28 (our probe: raw `hooks.md`, 330,813 bytes, SHA-256 `57e3b47d55acfbae3dcdc112866c8c0f75528d8b5c4fca9bfcdaa904d4728218`). Recheck trigger: that section's Windows rule changes, or [anthropics/claude-code#90495](https://github.com/anthropics/claude-code/issues/90495) closes (args dropped, the hook still routed through `bash.exe`). This marketplace's `scripts/check-exec-form-windows-probe.sh` checks its own rows; a non-Windows skip does not clear #90495 | | No duplicate hooks (same script registered twice for same event) | info | Compare commands within each event | | Hook events are valid per official docs | error | The engine reads the Event table of the [hooks reference](https://code.claude.com/docs/en/hooks) each run (`hook-event` rows). Read the page yourself only for a `not-inspectable` row, live rather than from a recalled event list | | Hook-suppression levers are read and reported | info | Read `disableAllHooks` from the settings-declared layer and `allowManagedHooksOnly` / `strictPluginOnlyCustomization` from the managed layer. Report each as set or unset with the hooks it switches off. `info` because the reading is state, not a defect: a repo may set any of them deliberately. It is not optional, though: **B.1–B.3's third narrowing may not downgrade a missing deny rule on the strength of a hook one of these has already disabled**, so an unread lever means the narrowing is unavailable rather than assumed clear | -| Mod-plane keys are read and reported (engine: `D/mod-plane`) | info | The engine reads `prependPlugins`, `appendPlugins` and `disableSideloadFlags` at every scope, and the built-in guard's `allowManagedModsOnly` and `allowModsToOverrideDenyRules` under `pluginConfigs["cc-plugin-sec-default@builtin"].options`. None switches a settings hook off, so none feeds the lever narrowing. A copy in a scope Claude Code does not read for that key is an `info` finding, since it changes nothing. Report `allowModsToOverrideDenyRules: true` beside Category B: a user's mod can then approve a call a `deny` rule refuses. Which scopes Claude Code reads each key from, what `disableSideloadFlags` rejects, where the guard options are honored, and what a managed `disableAllHooks` stops are read live, never from this row. Pointer: when deciding whether a key's scope is read, fetch [settings reference: prependPlugins](https://code.claude.com/docs/en/settings-reference#prependplugins), [appendPlugins](https://code.claude.com/docs/en/settings-reference#appendplugins), [disableSideloadFlags](https://code.claude.com/docs/en/settings-reference#disablesideloadflags), [mods admin: set options on the built-in guard](https://code.claude.com/docs/en/plugins/mods/admin#set-options-on-the-built-in-guard) and [mods reference: settings and environment variables](https://code.claude.com/docs/en/plugins/mods/reference#settings-and-environment-variables) live. As of: 2026-10-11. Recheck trigger: a key's scope entry or the guard's option table changes, or a release note names one of these keys | -| Built-in mods under the hook levers are reported (engine: `D/builtin-mods-survive-levers`) | info | The engine prints one row quoting, verbatim with the page URL and fetch date, the mods overview's sentence that names `disableAllHooks`, `--bare`, `--safe-mode` and built-in mods. With `disableAllHooks` set in any scope read, the row is an `info` finding, since that is where an operator may believe every mod is off; otherwise it is an `ok` row. With the page unread, or no such sentence on it, the row is `not-inspectable`, saying the upstream statement could not be confirmed. The flags are runtime state, so the engine never sees them. Report-only, no `--fix`: whether and how to turn a built-in mod off is the operator's choice. Which built-in mods exist, which levers stop them, and how each is turned off are read live, never from this row. Pointer: [mods overview: mods built into Claude Code](https://code.claude.com/docs/en/plugins/mods/overview#mods-built-into-claude-code). As of: 2026-10-17. Recheck trigger: that section's built-in table or its statement on the levers changes | +| Mod-plane keys are read and reported (engine: `D/mod-plane`) | info | The engine reads `prependPlugins`, `appendPlugins` and `disableSideloadFlags` at every scope, and the built-in guard's `allowManagedModsOnly` and `allowModsToOverrideDenyRules` under `pluginConfigs["cc-plugin-sec-default@builtin"].options`. None switches a settings hook off, so none feeds the lever narrowing. A copy in a scope Claude Code does not read for that key is an `info` finding, since it changes nothing. Report `allowModsToOverrideDenyRules: true` beside Category B: a user's mod can then approve a call a `deny` rule refuses. Which scopes Claude Code reads each key from, what `disableSideloadFlags` rejects, where the guard options are honored, and what a managed `disableAllHooks` stops are read live, never from this row. Pointer: when deciding whether a key's scope is read, fetch [settings reference: prependPlugins](https://code.claude.com/docs/en/settings-reference#prependplugins), [appendPlugins](https://code.claude.com/docs/en/settings-reference#appendplugins), [disableSideloadFlags](https://code.claude.com/docs/en/settings-reference#disablesideloadflags), [mods admin: set options on the built-in guard](https://code.claude.com/docs/en/plugins/mods/admin#set-options-on-the-built-in-guard) and [mods reference: settings and environment variables](https://code.claude.com/docs/en/plugins/mods/reference#settings-and-environment-variables) live. | +| Built-in mods under the hook levers are reported (engine: `D/builtin-mods-survive-levers`) | info | The engine prints one row quoting, verbatim with the page URL and fetch date, the mods overview's sentence that names `disableAllHooks`, `--bare`, `--safe-mode` and built-in mods. With `disableAllHooks` set in any scope read, the row is an `info` finding, since that is where an operator may believe every mod is off; otherwise it is an `ok` row. With the page unread, or no such sentence on it, the row is `not-inspectable`, saying the upstream statement could not be confirmed. The flags are runtime state, so the engine never sees them. Report-only, no `--fix`: whether and how to turn a built-in mod off is the operator's choice. Which built-in mods exist, which levers stop them, and how each is turned off are read live, never from this row. Pointer: [mods overview: mods built into Claude Code](https://code.claude.com/docs/en/plugins/mods/overview#mods-built-into-claude-code). | ## E. Plugins @@ -111,8 +111,8 @@ permission floor" in the same file. | --- | --- | --- | | Every plugin's marketplace exists in `extraKnownMarketplaces` | error | Split `@marketplace` suffix, verify marketplace key exists | | No enabled plugin depends on a disabled plugin | warning | The engine merges user, project and local `enabledPlugins` and reads each enabled plugin's `.claude-plugin/plugin.json` `dependencies` (direct only). A merged `false` that an enabled plugin declares is `dependency-disabled`; every other `false` is an inventory row. See [validation-categories.md](../context/validation-categories.md) "E.1" | -| Each enabled plugin is listed in its marketplace catalog (`.plugins[].name`) and is not a key of that catalog's `renames` map; a renamed key reports the new name, a `null` entry reports removed | warning | `check-plugin-drift.sh` reads `.renames` from the catalog already in hand. A key mapped to a name is followed to the end of the chain and reported as a rename naming that final name. A `null` entry is a removed row, not an orphan. A key absent from the map stays on the name-similarity heuristic. A chain that repeats a name is reported as a cycle and is not given a final name. See [validation-categories.md](../context/validation-categories.md) "E.2". Pointer: when the map's effect on a settings file is in question, fetch [Migrate users with a renames map](https://code.claude.com/docs/en/plugins/host-marketplace#migrate-users-with-a-renames-map) live. As of: 2026-10-03. Recheck trigger: that section changes what a renames entry points at, how a chain is followed, or which settings files a session rewrites | -| Every enabled plugin has a component definition, and none has two | error | Read the [Strict mode section](https://code.claude.com/docs/en/plugins/marketplace-reference#strict-mode) and the entry rules above it on marketplace-reference; do not restate them from memory. Do not flag a plugin with no `plugin.json` whose marketplace entry declares its components, whatever `strict` says; a bare root `marketplace.json` is not by itself a finding. Error conditions: a plugin with no `plugin.json` and no entry declaring its components (nothing defines what loads), and an entry that declares component fields beside a `plugin.json` under `strict: false`. For what each case does at load, follow the pointer. Pointer: that section's result table and its conflict error, both spans pinned in `doc-citations.tsv`. As of: 2026-09-29. Recheck trigger: `check-doc-citations.sh` fails on either span, or the section's result table changes | +| Each enabled plugin is listed in its marketplace catalog (`.plugins[].name`) and is not a key of that catalog's `renames` map; a renamed key reports the new name, a `null` entry reports removed | warning | `check-plugin-drift.sh` reads `.renames` from the catalog already in hand. A key mapped to a name is followed to the end of the chain and reported as a rename naming that final name. A `null` entry is a removed row, not an orphan. A key absent from the map stays on the name-similarity heuristic. A chain that repeats a name is reported as a cycle and is not given a final name. See [validation-categories.md](../context/validation-categories.md) "E.2". Pointer: when the map's effect on a settings file is in question, fetch [Migrate users with a renames map](https://code.claude.com/docs/en/plugins/host-marketplace#migrate-users-with-a-renames-map) live. | +| Every enabled plugin has a component definition, and none has two | error | Read the [Strict mode section](https://code.claude.com/docs/en/plugins/marketplace-reference#strict-mode) and the entry rules above it on marketplace-reference; do not restate them from memory. Do not flag a plugin with no `plugin.json` whose marketplace entry declares its components, whatever `strict` says; a bare root `marketplace.json` is not by itself a finding. Error conditions: a plugin with no `plugin.json` and no entry declaring its components (nothing defines what loads), and an entry that declares component fields beside a `plugin.json` under `strict: false`. For what each case does at load, follow the pointer. Pointer: that section's result table and its conflict error, both spans pinned in `doc-citations.tsv` | ## F. Environment Variables @@ -121,7 +121,7 @@ permission floor" in the same file. | Env vars in settings.json are documented CC vars | warning | Read `code.claude.com/docs/en/env-vars` and search it for each env var name. WebSearch alone is insufficient. **Read it verbatim, not through a summarizer.** The page is long and a summarizing fetch truncates it, then reports the rows past the cutoff as absent: `bash "/../../scripts/fetch-docs.sh" --cache --max-age 0 --out env-vars` and grep `/env-vars.md`, per the [fetch route](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/contracts/upstream-drift/README.md#reading-the-basis-the-fetch-route). A truncated read supports NO finding. Say so and move on. **Absence from this page is not "unrecognized" either:** it is not the whole env-var surface, and `CLAUDE_CODE_ENTRYPOINT`, `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA`, and `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS` are all real and all absent from it (our probe, a full verbatim read; no artifact stored. Pointer: [env-vars: variables](https://code.claude.com/docs/en/env-vars#variables). As of: 2026-08-10. Recheck trigger: `env-vars` gains a row for any of them). A name missing here is at most "not documented on `env-vars`". Check `monitoring-usage`, `mcp`, and `settings` before writing anything stronger | | No secrets in settings.json (tokens, keys, passwords) | error | Scan for patterns: `ghp_`, `eyJ`, `sk-`, `AKIA`, common token prefixes. The engine's `SECRET_RE` is a literal list of vendor token shapes, not derived from the docs: neither `settings-reference` nor `env-vars` states any credential format (our probe: a full verbatim read of both found no `ghp_`, `github_pat_`, `eyJ`, `sk-`, `AKIA`, or `xox` shape), and the token shapes belong to GitHub, AWS, Slack and others. Never narrow the literal to match a doc. Pointer: [settings-reference](https://code.claude.com/docs/en/settings-reference), the whole page, since the probe is a negative over every section, and [env-vars: variables](https://code.claude.com/docs/en/env-vars#variables); no artifact stored. As of: 2026-09-29, Claude Code 2.1.284. Recheck trigger: either page documents a credential format; then derive the pattern from it and keep the literal as the fallback | | Secrets are in settings.local.json only | error | settings.local.json is gitignored. That keeps a secret out of git, not out of the session: the baseline does not deny reading the file, so a finding that moves a secret there also names a project `Read` deny on it or a credential store. See [required-permissions.md](required-permissions.md) "Relation to the standards permission floor" | -| `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS` is not set (engine: `F/function-hooks-flag-dead`) | warning | The engine flags the variable in the `env` of user, project or local settings, at any value: this audit treats it as a dead mods switch whose presence misleads the operator who set it. The finding quotes, verbatim with the page URL and fetch date, the mods overview's line naming the variable; with the page unread, or no such line on it, the row is `not-inspectable`, saying the upstream statement could not be confirmed. Report-only, no `--fix`: removing it and choosing a replacement lever are the operator's call. Whether Claude Code still reads the variable, and which levers turn mods off now, are read live, never from this row. Pointer: [mods overview: turn mods on or off](https://code.claude.com/docs/en/plugins/mods/overview#turn-mods-on-or-off) and [mods admin: stop user-installed mods from loading](https://code.claude.com/docs/en/plugins/mods/admin#stop-user-installed-mods-from-loading). As of: 2026-10-17. Recheck trigger: either section drops its note on the variable or the variable gains a new meaning | +| `CLAUDE_CODE_ENABLE_FUNCTION_HOOKS` is not set (engine: `F/function-hooks-flag-dead`) | warning | The engine flags the variable in the `env` of user, project or local settings, at any value: this audit treats it as a dead mods switch whose presence misleads the operator who set it. The finding quotes, verbatim with the page URL and fetch date, the mods overview's line naming the variable; with the page unread, or no such line on it, the row is `not-inspectable`, saying the upstream statement could not be confirmed. Report-only, no `--fix`: removing it and choosing a replacement lever are the operator's call. Whether Claude Code still reads the variable, and which levers turn mods off now, are read live, never from this row. Pointer: [mods overview: turn mods on or off](https://code.claude.com/docs/en/plugins/mods/overview#turn-mods-on-or-off) and [mods admin: stop user-installed mods from loading](https://code.claude.com/docs/en/plugins/mods/admin#stop-user-installed-mods-from-loading). | ## G. Skill-listing budget @@ -133,12 +133,12 @@ measurement at all*, and the rest only apply once one exists. | --- | --- | --- | | Overflow was measured by a route that works in this run's mode | warning | **Existing log first**: the engine reads a debug log this session already wrote (`--debug-log`, then `CLAUDE_CODE_DEBUG_LOGS_DIR`, then the newest file under `/debug/`, the locations [CLI reference: CLI flags](https://code.claude.com/docs/en/cli-reference#cli-flags) and the `DEBUG` and `CLAUDE_CODE_DEBUG_LOGS_DIR` rows of [environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) document) and parses the over-budget warning from it, skill count, characters and budget included; a log with no warning reads as fitting. Only with no log at all: **Interactive**: `/doctor` reports the listing's cost and its biggest contributors, and needs a TTY, so prompt the user to run it and paste the output. **Headless** (`-p`, spawned agent, background job): re-launch with `--debug` and look for the budget warning in the debug log ([skills: skill descriptions are cut short](https://code.claude.com/docs/en/skills#skill-descriptions-are-cut-short)). `/context`'s Skills row is a second *interactive* reading only. Name the route in the finding. As of: 2026-10-11. Recheck trigger: a debug-log location or the warning's home section changes | | No measurement is reported as "not measured", never as "no overflow" | error | An unmeasured category that reports clean is the failure mode this row exists to block, the same defect as a passing check that never ran | -| Any overflow finding names the budget constant it was measured against | warning | The budget comes from `skillListingBudgetFraction` applied to the context window, or from `SLASH_COMMAND_TOOL_CHAR_BUDGET` when set; read each one's default, fallback and conversion in Phase 3.1, never from this row. Without the constant the report cannot say *how far* over. Pointer: when computing the budget, fetch [settings reference: skillListingBudgetFraction](https://code.claude.com/docs/en/settings-reference#skilllistingbudgetfraction) and the `SLASH_COMMAND_TOOL_CHAR_BUDGET` row of [environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live. As of: 2026-10-11. Recheck trigger: either entry changes how the budget is computed, or the key or variable is renamed | +| Any overflow finding names the budget constant it was measured against | warning | The budget comes from `skillListingBudgetFraction` applied to the context window, or from `SLASH_COMMAND_TOOL_CHAR_BUDGET` when set; read each one's default, fallback and conversion in Phase 3.1, never from this row. Without the constant the report cannot say *how far* over. Pointer: when computing the budget, fetch [settings reference: skillListingBudgetFraction](https://code.claude.com/docs/en/settings-reference#skilllistingbudgetfraction) and the `SLASH_COMMAND_TOOL_CHAR_BUDGET` row of [environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live. | | Roster composition counted before any lever is recommended | warning | Count listing entries by origin: plugin skills, project skills (`.claude/skills/`), user skills (`${CLAUDE_CONFIG_DIR:-~/.claude}/skills/`). This decides which levers exist | -| Every recommended lever is reachable for the origin it targets | error | We treat `skillOverrides` as reaching project and user skills only, never plugin skills. On a plugin-heavy roster the levers are `/plugin` and upstream description trimming. Recommending `skillOverrides` for a plugin skill is a lever the operator cannot pull. Pointer: [settings-reference: `skillOverrides`](https://code.claude.com/docs/en/settings-reference#skilloverrides), the span pinned in `doc-citations.tsv`. As of: 2026-09-27. Recheck trigger: `check-doc-citations.sh` fails on that span | -| No `skillOverrides` entry targets a plugin skill (engine: `G/skill-override-plugin`) | warning | For each `skillOverrides` key holding `:` in the user, project and local settings files, the engine takes the text before the first `:` and looks it up among the plugin names in the installed registry and every `enabledPlugins` key. A match is inert, since the override does not reach plugin skills (pointer: [skills: override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings); as of: 2026-09-27; recheck trigger: that section changes whether overrides reach plugin skills). The reachable levers are `enabledPlugins` or `/plugin` for the whole plugin, or `disable-model-invocation` in the skill's frontmatter, which is the plugin author's to set. A colon key whose prefix names no plugin is a `skip` row, never clean and never a finding: it may be a nested directory-qualified skill (`apps/web:deploy`) or a claude.ai-synced skill (`anthropic-skills:`), and the docs do not settle whether an override reaches it. A key naming no skill anywhere is not detected: bundled and synced skill names are not enumerable from files | -| `skillOverrides` in the user dir's `settings.local.json` is flagged (engine: `G/skill-override-home-local`) | info | The engine reads `/settings.local.json` whatever the project root. We treat that file as the project-local settings file for sessions started in the home directory only, so its entries reach no other project (pointer: the scope table in [settings: settings files and who they affect](https://code.claude.com/docs/en/settings#settings-files-and-who-they-affect), its project-local and user rows; as of: 2026-10-01; recheck trigger: that table changes who a project-local or user settings file reaches). A user-wide override belongs in `settings.json`. The entry may be intended: we treat the `/skills` menu as writing to this file from a home-rooted session (pointer: [skills: override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings); as of: 2026-10-01; recheck trigger: that section changes which file the menu writes). Present but unreadable or invalid is `not-inspectable` | -| Per-entry text within the per-skill cap | warning | Combined `description` + `when_to_use` ≤ `skillListingMaxDescChars`. The authoring limit is stated in `/playbooks:skill-authoring` `## Descriptions`, and `/skill-quality:check` enforces it on each `SKILL.md`; this row confirms the setting in effect in Phase 3.1 and reports entries over it. This is a per-entry cap, independent of the shared budget above. Pointer: for the default, see the [frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference). As of: 2026-10-07. Recheck trigger: the default moves, which re-derives this row | +| Every recommended lever is reachable for the origin it targets | error | We treat `skillOverrides` as reaching project and user skills only, never plugin skills. On a plugin-heavy roster the levers are `/plugin` and upstream description trimming. Recommending `skillOverrides` for a plugin skill is a lever the operator cannot pull. Pointer: [settings-reference: `skillOverrides`](https://code.claude.com/docs/en/settings-reference#skilloverrides), the span pinned in `doc-citations.tsv` | +| No `skillOverrides` entry targets a plugin skill (engine: `G/skill-override-plugin`) | warning | For each `skillOverrides` key holding `:` in the user, project and local settings files, the engine takes the text before the first `:` and looks it up among the plugin names in the installed registry and every `enabledPlugins` key. A match is inert, since the override does not reach plugin skills (pointer: [skills: override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings)). The reachable levers are `enabledPlugins` or `/plugin` for the whole plugin, or `disable-model-invocation` in the skill's frontmatter, which is the plugin author's to set. A colon key whose prefix names no plugin is a `skip` row, never clean and never a finding: it may be a nested directory-qualified skill (`apps/web:deploy`) or a claude.ai-synced skill (`anthropic-skills:`), and the docs do not settle whether an override reaches it. A key naming no skill anywhere is not detected: bundled and synced skill names are not enumerable from files | +| `skillOverrides` in the user dir's `settings.local.json` is flagged (engine: `G/skill-override-home-local`) | info | The engine reads `/settings.local.json` whatever the project root. We treat that file as the project-local settings file for sessions started in the home directory only, so its entries reach no other project (pointer: the scope table in [settings: settings files and who they affect](https://code.claude.com/docs/en/settings#settings-files-and-who-they-affect), its project-local and user rows). A user-wide override belongs in `settings.json`. The entry may be intended: we treat the `/skills` menu as writing to this file from a home-rooted session (pointer: [skills: override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings)). Present but unreadable or invalid is `not-inspectable` | +| Per-entry text within the per-skill cap | warning | Combined `description` + `when_to_use` ≤ `skillListingMaxDescChars`. The authoring limit is stated in `/playbooks:skill-authoring` `## Descriptions`, and `/skill-quality:check` enforces it on each `SKILL.md`; this row confirms the setting in effect in Phase 3.1 and reports entries over it. This is a per-entry cap, independent of the shared budget above. Pointer: for the default, see the [frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference). | ### Measuring it in a repository (in-repo proxy, not the real population) @@ -173,8 +173,6 @@ document. - **Pointer**: `https://json.schemastore.org/claude-code-settings.json`, its `properties.effortLevel` and `properties.fallbackModel` entries (a JSON document has no section anchors, so the entries are named by path). -- **As of**: 2026-09-29 -- **Recheck trigger**: either type differs on a fresh fetch. The engine reads no schema: it never fetches the SchemaStore document, so a limit that only the schema states (a raw array-length limit on `fallbackModel`) is a `skip` row, not a finding, and the engine @@ -194,11 +192,11 @@ section F resolves environment variables against their own page. | Check | Severity | How to verify | | --- | --- | --- | | `effortLevel` is a value its **Type** bullet documents | warning | `jq '.effortLevel'`. The accepted values are the **Type** bullet of the [`effortLevel` section](https://code.claude.com/docs/en/settings-reference#effortlevel) on settings-reference; the engine reads that bullet each run and reports any other value. Report it as a value the page does not document; the page does not state what runs instead, so do not assert a level | -| `fallbackModel` keeps no more distinct models than the page says the chain keeps | warning | The cap is the number [model configuration: fallback model chains](https://code.claude.com/docs/en/model-config#fallback-model-chains) states for a chain after duplicate removal; the engine reads that section each run, only when a file sets `fallbackModel`, and applies no other. A section that states none gives one `skip` row; an unread page, or one without the section, gives one `not-inspectable` row. Two tests can disagree: the declared schema caps RAW array length, while the page caps the chain after duplicate removal, so with a cap of 3 `["sonnet","haiku","sonnet","opus"]` has 4 raw entries and exactly 3 distinct. Only the distinct count is a finding; a raw count above the cap is a `skip` row because the schema is not read. Dedupe in place with `jq '.fallbackModel \| reduce .[] as $m ([]; if index($m) then . else . + [$m] end)'`, since `unique` would sort away the order the chain is tried in, and name any entry past the cap as at risk of being ignored. Not "dead": allowlist-excluded entries are also dropped when the chain is read, and the page does not state whether that dropping happens before or after the cap. Pointer: for the cap and the allowlist drop, see [model configuration: fallback model chains](https://code.claude.com/docs/en/model-config#fallback-model-chains); for the raw-length limit, the SchemaStore document's `properties.fallbackModel`. As of: 2026-11-04 (that section states the cap, settings-reference's `fallbackModel` section no longer does, and neither orders the allowlist drop against it). Recheck trigger: that section drops, moves or changes its cap, or states whether the allowlist drop runs before the cap | +| `fallbackModel` keeps no more distinct models than the page says the chain keeps | warning | The cap is the number [model configuration: fallback model chains](https://code.claude.com/docs/en/model-config#fallback-model-chains) states for a chain after duplicate removal; the engine reads that section each run, only when a file sets `fallbackModel`, and applies no other. A section that states none gives one `skip` row; an unread page, or one without the section, gives one `not-inspectable` row. Two tests can disagree: the declared schema caps RAW array length, while the page caps the chain after duplicate removal, so with a cap of 3 `["sonnet","haiku","sonnet","opus"]` has 4 raw entries and exactly 3 distinct. Only the distinct count is a finding; a raw count above the cap is a `skip` row because the schema is not read. Dedupe in place with `jq '.fallbackModel \| reduce .[] as $m ([]; if index($m) then . else . + [$m] end)'`, since `unique` would sort away the order the chain is tried in, and name any entry past the cap as at risk of being ignored. Not "dead": allowlist-excluded entries are also dropped when the chain is read, and the page does not state whether that dropping happens before or after the cap. Pointer: for the cap and the allowlist drop, see [model configuration: fallback model chains](https://code.claude.com/docs/en/model-config#fallback-model-chains); for the raw-length limit, the SchemaStore document's `properties.fallbackModel`. That section states the cap, settings-reference's `fallbackModel` section does not, and neither orders the allowlist drop against it | | Any other string-valued key whose **Type** bullet lists its values holds one of them | warning | `jq 'to_entries[] \| select(.value \| type == "string")'` over `settings.json` and `~/.claude/settings.json`; `settings.local.json` is not read by value. The engine takes the values from the `string, one of:` bullets on settings-reference, treats an entry such as `custom:` as matching any text in its placeholder, and gives a key with no such list no row. A list holding a bullet that is not a literal value, such as the strftime pattern in the `timeFormat` list, is open: its literals are not the whole set, so the key has no row. `effortLevel` and `disableDeepLinkRegistration` keep their own rows. A key whose Type bullet states its values inline in a sentence is not parsed, so it has no row | -| `availableModels` does not mix a family wildcard with a specific entry of that family | warning | The engine fixes the families as `opus`, `sonnet`, `haiku` and `fable`; the record below the table says why. Flag a list that holds a family's wildcard and also an entry naming a specific model of that family; we read the pair as narrower than its author meant. A Mantle ID, or an `ANTHROPIC_CUSTOM_MODEL_OPTION` value embedding a family name, counts as such an entry. The finding is the narrowing itself. For what the list then permits, follow the pointer. Report the models they most likely still expect to be selectable. Pointer: [model configuration: merge behavior](https://code.claude.com/docs/en/model-config#merge-behavior). As of: 2026-11-04. Recheck trigger: that section changes how a specific entry interacts with its family's wildcard. This skill does not read managed settings, so say the finding assumes no managed `availableModelsMatch` or `deniedModels` applies. Pointer: when a managed match mode or deny list may apply, fetch [settings-reference: `availableModelsMatch`](https://code.claude.com/docs/en/settings-reference#availablemodelsmatch) and [settings-reference: `deniedModels`](https://code.claude.com/docs/en/settings-reference#deniedmodels) live. As of: 2026-10-10. Recheck trigger: either section changes what its key does to the models `availableModels` permits | -| `enforceAvailableModels: true` is paired with a non-empty `availableModels` | error | `jq 'select(.enforceAvailableModels == true) \| .availableModels'`. The finding requires the flag to be `true` AND the list unset or empty. An explicit `false` is someone turning enforcement off on purpose and is never a finding, so gate on the value rather than the key's presence. When it does fire: we treat the key as having no effect without a non-empty `availableModels`, so the constraint its author set is not in force. That is an enforcement bypass, which this skill's severity guide rates `error`. Where both keys must live is a managed-settings placement question this skill cannot decide from the files it reads, so report the pairing, not the placement. Pointer: [settings-reference: `enforceAvailableModels`](https://code.claude.com/docs/en/settings-reference#enforceavailablemodels). As of: 2026-10-01. Recheck trigger: that section changes what the key does with an empty or unset list | -| `deniedModels` and `availableModelsMatch` appear only in managed settings | warning | The engine reports it for the project, local and user files; by hand, `jq 'has("deniedModels"), has("availableModelsMatch")'` over `settings.json` and `~/.claude/settings.json` only. The engine fires on a rule kept in our words, reading no page; confirm it with the settings-reference fetch before reporting. We treat both keys as managed-only. Every file this skill reads is a user, project or local file, so either key there is a model policy its author believes is in force and is not. Report the key and the file, and name managed settings as where the policy belongs. Pointer: when you need which sources read these keys and how managed sources combine them, fetch [settings-reference: `availableModelsMatch`](https://code.claude.com/docs/en/settings-reference#availablemodelsmatch), [settings-reference: `deniedModels`](https://code.claude.com/docs/en/settings-reference#deniedmodels) and [managed settings: compose every managed source](https://code.claude.com/docs/en/managed-settings#compose-every-managed-source) live. As of: 2026-10-10. Recheck trigger: any of those sections reads these keys outside managed settings, or changes how managed sources combine them | +| `availableModels` does not mix a family wildcard with a specific entry of that family | warning | The engine fixes the families as `opus`, `sonnet`, `haiku` and `fable`; the record below the table says why. Flag a list that holds a family's wildcard and also an entry naming a specific model of that family; we read the pair as narrower than its author meant. A Mantle ID, or an `ANTHROPIC_CUSTOM_MODEL_OPTION` value embedding a family name, counts as such an entry. The finding is the narrowing itself. For what the list then permits, follow the pointer. Report the models they most likely still expect to be selectable. Pointer: [model configuration: merge behavior](https://code.claude.com/docs/en/model-config#merge-behavior). This skill does not read managed settings, so say the finding assumes no managed `availableModelsMatch` or `deniedModels` applies. Pointer: when a managed match mode or deny list may apply, fetch [settings-reference: `availableModelsMatch`](https://code.claude.com/docs/en/settings-reference#availablemodelsmatch) and [settings-reference: `deniedModels`](https://code.claude.com/docs/en/settings-reference#deniedmodels) live. | +| `enforceAvailableModels: true` is paired with a non-empty `availableModels` | error | `jq 'select(.enforceAvailableModels == true) \| .availableModels'`. The finding requires the flag to be `true` AND the list unset or empty. An explicit `false` is someone turning enforcement off on purpose and is never a finding, so gate on the value rather than the key's presence. When it does fire: we treat the key as having no effect without a non-empty `availableModels`, so the constraint its author set is not in force. That is an enforcement bypass, which this skill's severity guide rates `error`. Where both keys must live is a managed-settings placement question this skill cannot decide from the files it reads, so report the pairing, not the placement. Pointer: [settings-reference: `enforceAvailableModels`](https://code.claude.com/docs/en/settings-reference#enforceavailablemodels). | +| `deniedModels` and `availableModelsMatch` appear only in managed settings | warning | The engine reports it for the project, local and user files; by hand, `jq 'has("deniedModels"), has("availableModelsMatch")'` over `settings.json` and `~/.claude/settings.json` only. The engine fires on a rule kept in our words, reading no page; confirm it with the settings-reference fetch before reporting. We treat both keys as managed-only. Every file this skill reads is a user, project or local file, so either key there is a model policy its author believes is in force and is not. Report the key and the file, and name managed settings as where the policy belongs. Pointer: when you need which sources read these keys and how managed sources combine them, fetch [settings-reference: `availableModelsMatch`](https://code.claude.com/docs/en/settings-reference#availablemodelsmatch), [settings-reference: `deniedModels`](https://code.claude.com/docs/en/settings-reference#deniedmodels) and [managed settings: compose every managed source](https://code.claude.com/docs/en/managed-settings#compose-every-managed-source) live. | The engine keeps the family list fixed and reads no page for it, because a change here is a deliberate edit to one check. Compare it by hand with the page's own naming of the families when this row is @@ -219,8 +217,6 @@ Claude Code does with a key it does not recognize is the override section's to s - **Pointer**: when judging an unrecognized `modelOverrides` key, fetch [model configuration: override model IDs per version](https://code.claude.com/docs/en/model-config#override-model-ids-per-version) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: that section starts rejecting or warning on an unrecognized key. ### `bashOutputMaxChars` @@ -252,10 +248,10 @@ pointing at the other is the shape a hand-off takes when nobody closes it. | Check | Severity | How to verify | | --- | --- | --- | -| A component's `effort:` pin names the model it was calibrated against, or an event that re-opens it | info | Read the frontmatter of every `skills/*/SKILL.md` and `agents/*.md` in scope. We treat a pin as calibrated to the model it was set on, so a pin that names neither that model nor an event that re-opens it is flagged. **Do not flag a pin at the resolved model's own default level.** That pin encodes no measurement that could go stale. Read the resolved model's default from the first pointer when the audit runs; this row keeps no copy of the per-model defaults, because the list has gained models without an edit here. When the page cannot be read, report the pin's default as unresolved rather than grading it. Report the missing re-derivation, never the level itself; whether the level is high enough is the next row's question, not this one's. Pointer: when deciding a model's default effort, fetch [model configuration: adjust effort level](https://code.claude.com/docs/en/model-config#adjust-effort-level) live; for per-model calibration, see [choose an effort level](https://code.claude.com/docs/en/model-config#choose-an-effort-level). As of: 2026-10-11. Recheck trigger: that section stops stating a per-model default, or moves it to another section | -| A code-changing or verifying component's `effort:` is not pinned below `medium` | warning | Read the same frontmatter. Flag an agent or skill whose `effort:` is pinned below `medium` (today that is `low`) when its body has the model change code (edit, implement, refactor, fix) or verify a change (run the build, the tests, a review, or a check that a change works). The floor is the marketplace's [Effort floor](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/plugin-philosophy.md#effort-floor): `medium` or above for that work on every model that supports effort. Classify by what the body has the model do, not by its name or tool grants. **Do not flag:** a component with no `effort:` pin, which is not a pin whatever level it then runs at; a read-only, chat-like, or mechanical component (lookups, formatting, listing) pinned `low`; or a model the pin runs on that has no effort support, where the key has no effect. Propose `medium` as the floor and leave any higher level to the author. Pointer: the floor's own record in that section, which points at the upstream effort pages. As of: 2026-10-01. Recheck trigger: that section changes the floor level or the kinds of work it covers | +| A component's `effort:` pin names the model it was calibrated against, or an event that re-opens it | info | Read the frontmatter of every `skills/*/SKILL.md` and `agents/*.md` in scope. We treat a pin as calibrated to the model it was set on, so a pin that names neither that model nor an event that re-opens it is flagged. **Do not flag a pin at the resolved model's own default level.** That pin encodes no measurement that could go stale. Read the resolved model's default from the first pointer when the audit runs; this row keeps no copy of the per-model defaults, because the list has gained models without an edit here. When the page cannot be read, report the pin's default as unresolved rather than grading it. Report the missing re-derivation, never the level itself; whether the level is high enough is the next row's question, not this one's. Pointer: when deciding a model's default effort, fetch [model configuration: adjust effort level](https://code.claude.com/docs/en/model-config#adjust-effort-level) live; for per-model calibration, see [choose an effort level](https://code.claude.com/docs/en/model-config#choose-an-effort-level). | +| A code-changing or verifying component's `effort:` is not pinned below `medium` | warning | Read the same frontmatter. Flag an agent or skill whose `effort:` is pinned below `medium` (today that is `low`) when its body has the model change code (edit, implement, refactor, fix) or verify a change (run the build, the tests, a review, or a check that a change works). The floor is the marketplace's [Effort floor](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/plugin-philosophy.md#effort-floor): `medium` or above for that work on every model that supports effort. Classify by what the body has the model do, not by its name or tool grants. **Do not flag:** a component with no `effort:` pin, which is not a pin whatever level it then runs at; a read-only, chat-like, or mechanical component (lookups, formatting, listing) pinned `low`; or a model the pin runs on that has no effort support, where the key has no effect. Propose `medium` as the floor and leave any higher level to the author. Pointer: the floor's own record in that section, which points at the upstream effort pages. | | No effort pin rests on a model-config effort table or default that changed since the baseline | warning | Run `bash "/scripts/check-effort-pins.sh" [--root ] [--baseline ] [--docs-dir ]` and report its lines verbatim; `--print-baseline` prints a new baseline line and writes nothing. Exit 0: the page matches [`effort-table.baseline`](effort-table.baseline) and every pin names a listed level. Exit 1: the page changed (`reason=table-changed` on every pin) or a pin names an unlisted level (`reason=level-not-in-table`); a person re-decides each flagged pin. Exit 3: page unread or reshaped, no claim about any pin. Exit 2: fatal. The script never edits a pin or the baseline; the rebaseline step is in [SKILL.md](../SKILL.md) | -| A component's `effort:` and `model:` are consistent with each other | info | We read a definition's `model:` and `effort:` as the pair the author chose, not as all that a spawn runs on: other sources can override either one. Flag only the combination the author is unlikely to have intended: a cheap `model:` tier paired with a top effort level, or the reverse, with no stated reason. Report the mismatch, never a preferred pairing. Pointer: when deciding what a spawn actually runs on, fetch [choose a model](https://code.claude.com/docs/en/sub-agents#choose-a-model) and [choose an effort level](https://code.claude.com/docs/en/sub-agents#choose-an-effort-level) live. As of: 2026-11-01. Recheck trigger: either section's resolution order gains or loses a source | +| A component's `effort:` and `model:` are consistent with each other | info | We read a definition's `model:` and `effort:` as the pair the author chose, not as all that a spawn runs on: other sources can override either one. Flag only the combination the author is unlikely to have intended: a cheap `model:` tier paired with a top effort level, or the reverse, with no stated reason. Report the mismatch, never a preferred pairing. Pointer: when deciding what a spawn actually runs on, fetch [choose a model](https://code.claude.com/docs/en/sub-agents#choose-a-model) and [choose an effort level](https://code.claude.com/docs/en/sub-agents#choose-an-effort-level) live. | These rows read a set `effort:` as the level the component runs at and an absent one as no pin, never as a claim about the level it runs at: that depends on the model it runs on. A level the @@ -268,9 +264,6 @@ against its own pointer. [when a subagent has no `effort` field or parameter](https://code.claude.com/docs/en/sub-agents#when-a-subagent-has-no-effort-field-or-parameter); for the settings key, see [settings-reference: `effortLevel`](https://code.claude.com/docs/en/settings-reference#effortlevel). -- **As of**: 2026-11-04 -- **Recheck trigger**: the field's precedence or either accepted-level list changing, or the second - section changing which model an absent level follows. ## I. Deep-link registration @@ -281,8 +274,6 @@ follow the pointer. - **Pointer**: for when registration happens and where it writes, see [deep links: registration and supported platforms](https://code.claude.com/docs/en/deep-links#registration-and-supported-platforms). -- **As of**: 2026-09-29 -- **Recheck trigger**: that section changes when registration happens or where it writes. Like two of section H's rows, the value check has an authoring-time path: the declared schema constrains this key's value, so an editor validating against it flags a boolean before the file is @@ -294,8 +285,6 @@ happens. - **Pointer**: `https://json.schemastore.org/claude-code-settings.json`, its `properties.disableDeepLinkRegistration` entry (a JSON document has no section anchors, so the entry is named by path), and the deep-links section linked above. -- **As of**: 2026-09-29 -- **Recheck trigger**: the key's type or the registration wording differs on a fresh fetch. **Reach.** Read the key by value from `.claude/settings.json` and `~/.claude/settings.json`. `check-structure.sh` does not report it, so a `settings.local.json` or managed-settings occurrence @@ -304,14 +293,13 @@ reporting the key as absent. The managed gap is not one a file read would close: delivery, an MDM plist, and Windows registry policy are all managed sources with no file in the path this skill resolves, and which of them wins for this key is the managed-settings page's to say (pointer: [managed settings: precedence within the managed -tier](https://code.claude.com/docs/en/managed-settings#precedence-within-the-managed-tier); as of: -2026-10-01; recheck trigger: that section moves or changes which managed source wins). +tier](https://code.claude.com/docs/en/managed-settings#precedence-within-the-managed-tier)). Nothing about the managed layer is decidable here, present or absent. Both rows below are built only on what the readable scopes show. | Check | Severity | How to verify | | --- | --- | --- | -| `disableDeepLinkRegistration`, **when present**, is a value its **Type** bullet documents | warning | `jq 'select(has("disableDeepLinkRegistration")) \| .disableDeepLinkRegistration'`. Gate on `has(…)`, never on the value being non-`null`: a bare `jq '.disableDeepLinkRegistration'` returns `null` for an absent key and for an explicit `null` alike, and an absent key is a consumer accepting the default registration on purpose, never a finding. The check fires only on a key that is present and not a documented value. The accepted value is the **Type** bullet of the [`disableDeepLinkRegistration` section](https://code.claude.com/docs/en/settings-reference#disabledeeplinkregistration) on settings-reference; the engine reads that bullet each run. Boolean `true` is the likely author error, the key reading as a flag; the declared schema (record above) flags it too, so a schema-aware editor catches it first. Report that the documented prevention is not invoked, so nothing exempts the machine from the default registration the section pointer above covers. Do **not** assert what the harness does with an unrecognized value, or that anything surfaces when it reads one, since neither page states either. Pointer: that settings-reference section and the deep-links section linked above, read whole for this negative. As of: 2026-10-01. Recheck trigger: either page states what Claude Code does with a value other than the documented one | -| Where enforcement is required, a `disableDeepLinkRegistration` already set to `"disable"` is not left sitting in a scope that cannot enforce it | warning | We treat `"disable"` in any `settings.json` as preventing registration on that machine, and only a managed-settings entry as enforcing it across an organization (pointer: [deep links: registration and supported platforms](https://code.claude.com/docs/en/deep-links#registration-and-supported-platforms); as of: 2026-09-29; recheck trigger: that section changes where the key enforces). Only managed settings enforce, so no scope this audit reads by value can satisfy such a requirement. Both halves of the gate are therefore observable: the finding requires a declared enforcement requirement (the consuming repo's own rules, or the run's stated policy context) AND the key present with `"disable"` in `.claude/settings.json` or `~/.claude/settings.json`, a visible attempt lodged in a scope that cannot deliver it. We treat a user-scope entry as overridable by project and local scope as well as unenforcing (pointer: [settings: settings precedence](https://code.claude.com/docs/en/settings#settings-precedence); as of: 2026-10-01; recheck trigger: that section moves user scope above project or local). Report **the visible placement**, never the system: say that this entry does not enforce the requirement and that whether a managed source separately carries the key is outside this audit's reach, since server-managed delivery, MDM plist, and registry policy have no file on the path it resolves. Route the administrator to `/status`, the one documented way to see which managed source is active (pointer: [server-managed settings: settings precedence](https://code.claude.com/docs/en/server-managed-settings#settings-precedence); as of: 2026-10-01; recheck trigger: that section names a different command for seeing the active managed source). Deliberately `warning`, not the `error` its `enforceAvailableModels` sibling carries: a bypass is precisely what cannot be proven from here, and managed settings may already enforce this correctly. It becomes `error` only once an administrator confirms no managed source carries the key. Two cases that are **not** findings by design: the key absent from every readable scope (nothing visible to report on), and someone setting it in their own `~/.claude/settings.json` with no enforcement requirement in play, which is the documented single-machine usage. The two rows are sequential, not simultaneous: a key that is present but wrongly valued fails this row's `"disable"` clause and draws only the row above, and correcting the value in that same scope is what brings it into this gate. So say so when both conditions are in view, rather than reporting a placement finding the gate does not yet support | +| `disableDeepLinkRegistration`, **when present**, is a value its **Type** bullet documents | warning | `jq 'select(has("disableDeepLinkRegistration")) \| .disableDeepLinkRegistration'`. Gate on `has(…)`, never on the value being non-`null`: a bare `jq '.disableDeepLinkRegistration'` returns `null` for an absent key and for an explicit `null` alike, and an absent key is a consumer accepting the default registration on purpose, never a finding. The check fires only on a key that is present and not a documented value. The accepted value is the **Type** bullet of the [`disableDeepLinkRegistration` section](https://code.claude.com/docs/en/settings-reference#disabledeeplinkregistration) on settings-reference; the engine reads that bullet each run. Boolean `true` is the likely author error, the key reading as a flag; the declared schema (record above) flags it too, so a schema-aware editor catches it first. Report that the documented prevention is not invoked, so nothing exempts the machine from the default registration the section pointer above covers. Do **not** assert what the harness does with an unrecognized value, or that anything surfaces when it reads one, since neither page states either. Pointer: that settings-reference section and the deep-links section linked above, read whole for this negative | +| Where enforcement is required, a `disableDeepLinkRegistration` already set to `"disable"` is not left sitting in a scope that cannot enforce it | warning | We treat `"disable"` in any `settings.json` as preventing registration on that machine, and only a managed-settings entry as enforcing it across an organization (pointer: [deep links: registration and supported platforms](https://code.claude.com/docs/en/deep-links#registration-and-supported-platforms)). Only managed settings enforce, so no scope this audit reads by value can satisfy such a requirement. Both halves of the gate are therefore observable: the finding requires a declared enforcement requirement (the consuming repo's own rules, or the run's stated policy context) AND the key present with `"disable"` in `.claude/settings.json` or `~/.claude/settings.json`, a visible attempt lodged in a scope that cannot deliver it. We treat a user-scope entry as overridable by project and local scope as well as unenforcing (pointer: [settings: settings precedence](https://code.claude.com/docs/en/settings#settings-precedence)). Report **the visible placement**, never the system: say that this entry does not enforce the requirement and that whether a managed source separately carries the key is outside this audit's reach, since server-managed delivery, MDM plist, and registry policy have no file on the path it resolves. Route the administrator to `/status`, the one documented way to see which managed source is active (pointer: [server-managed settings: settings precedence](https://code.claude.com/docs/en/server-managed-settings#settings-precedence)). Deliberately `warning`, not the `error` its `enforceAvailableModels` sibling carries: a bypass is precisely what cannot be proven from here, and managed settings may already enforce this correctly. It becomes `error` only once an administrator confirms no managed source carries the key. Two cases that are **not** findings by design: the key absent from every readable scope (nothing visible to report on), and someone setting it in their own `~/.claude/settings.json` with no enforcement requirement in play, which is the documented single-machine usage. The two rows are sequential, not simultaneous: a key that is present but wrongly valued fails this row's `"disable"` clause and draws only the row above, and correcting the value in that same scope is what brings it into this gate. So say so when both conditions are in view, rather than reporting a placement finding the gate does not yet support | ## J. Known-issues fix versions diff --git a/plugins/harness-config/skills/audit/reference/known-issues.md b/plugins/harness-config/skills/audit/reference/known-issues.md index 38644b8bf3f..6424766ad33 100644 --- a/plugins/harness-config/skills/audit/reference/known-issues.md +++ b/plugins/harness-config/skills/audit/reference/known-issues.md @@ -42,8 +42,7 @@ unfixed, and the closed ones ended as not planned, as a duplicate, or with an an change. **Claim:** no tracked issue names a fix release. **Basis:** `gh api repos/anthropics/claude-code/issues/` state and `state_reason` for each row, the timeline of #6699, the duplicate chain of #37634 (#23556, then #16377, closed as not planned), and -the `anthropics/claude-code` `CHANGELOG.md` searched for each issue number and each row's symptom. **As of:** 2026-09-30. **Recheck:** a tracked issue closes as -completed, or a changelog entry names one. +the `anthropics/claude-code` `CHANGELOG.md` searched for each issue number and each row's symptom. ## When this file changes diff --git a/plugins/harness-config/skills/audit/reference/native-update-config.md b/plugins/harness-config/skills/audit/reference/native-update-config.md index c88a27f274b..e862e1627a9 100644 --- a/plugins/harness-config/skills/audit/reference/native-update-config.md +++ b/plugins/harness-config/skills/audit/reference/native-update-config.md @@ -28,6 +28,3 @@ resolves in this session" and never that it is present. - **Pointer**: when checking what removes or hides a bundled skill, fetch [settings reference: disableBundledSkills](https://code.claude.com/docs/en/settings-reference#disablebundledskills) live. -- **As of**: 2026-11-03 -- **Recheck trigger**: that entry changes what it turns off, or a release adds, removes, or renames a - setting that hides bundled skills. diff --git a/plugins/harness-config/skills/audit/reference/required-permissions.md b/plugins/harness-config/skills/audit/reference/required-permissions.md index 500e21aa3a8..26f2709685b 100644 --- a/plugins/harness-config/skills/audit/reference/required-permissions.md +++ b/plugins/harness-config/skills/audit/reference/required-permissions.md @@ -105,8 +105,6 @@ the repository's ignored entries as live. then ignores from the repository, fetch [repository settings under an admin-required sandbox](https://code.claude.com/docs/en/sandboxing#repository-settings-under-an-admin-required-sandbox) live. -- **As of**: 2026-10-10 -- **Recheck trigger**: that section changes its ignore table or the settings sources it still reads. **Platform limit. Check before recommending it.** Do not offer the sandbox as the fix on a native-Windows workstation, where we treat the OS-level remedy as unavailable. @@ -114,7 +112,6 @@ native-Windows workstation, where we treat the OS-level remedy as unavailable. - **Pointer**: before recommending the sandbox, fetch [tools reference: preview limitations](https://code.claude.com/docs/en/tools-reference#preview-limitations) live for the native-Windows status. -- **As of**: 2026-11-10 - **Recheck trigger**: that section stops listing sandboxing as unsupported on Windows. **A `PreToolUse` hook on `Bash|PowerShell` is a speed bump, not a boundary, *against this threat @@ -140,8 +137,6 @@ below, and we never report it as fencing a Python or Node script that opens the - **Pointer**: when judging what the outside-directory block covers, fetch [permissions: block file-tool reads and writes outside the working directories](https://code.claude.com/docs/en/permissions#block-file-tool-reads-and-writes-outside-the-working-directories) live. -- **As of**: 2026-11-10 -- **Recheck trigger**: that section changes which tools, modes or commands the block covers. Moving a secret outside the working directory is still not protection against a subprocess the fence does @@ -229,7 +224,6 @@ with this rule is not flagged for lacking a bare `Bash(git push)` rule. - **Pointer**: when deciding whether a rule covers the bare command, fetch [permissions: wildcard patterns](https://code.claude.com/docs/en/permissions#wildcard-patterns) live. -- **As of**: 2026-11-04 - **Recheck trigger**: that section stops treating a trailing space and `*` as covering the bare command. diff --git a/plugins/harness-config/skills/draft-auto-mode-rules/SKILL.md b/plugins/harness-config/skills/draft-auto-mode-rules/SKILL.md index c11300ed487..4c9e0f6297a 100644 --- a/plugins/harness-config/skills/draft-auto-mode-rules/SKILL.md +++ b/plugins/harness-config/skills/draft-auto-mode-rules/SKILL.md @@ -23,8 +23,6 @@ This skill applies that at authoring time instead of reporting it afterwards, th and, for the critique command, [auto mode config: inspect the defaults and your effective config](https://code.claude.com/docs/en/auto-mode-config#inspect-the-defaults-and-your-effective-config) live. -- **As of**: 2026-10-11 -- **Recheck trigger**: either section changes how entries are read or what the critique reviews. ## Report-only, permanently @@ -49,8 +47,7 @@ can mean either. - **`/auto-mode-setup` (built-in command)**: the person runs it; this skill never invokes it. What it drafts, reads and saves is read from [auto mode config: generate environment entries](https://code.claude.com/docs/en/auto-mode-config#generate-environment-entries) - live (as of 2026-11-03; recheck when that section changes what the command drafts or where it - saves). + live. - **This skill (marketplace plugin).** Interviews for entries in every section (`environment`, `allow`, `soft_deny`, `hard_deny`), each with stated exclusions and a transcript-visible condition, and prints the block without writing anything. @@ -69,8 +66,8 @@ draft. This skill writes nothing and never chains into `/auto-mode-setup` on the **Availability is never assumed.** Offer the command when it resolves in this session, never assume it is present. Read what gates it from its row of -[commands: all commands](https://code.claude.com/docs/en/commands#all-commands) live (as of -2026-11-03; recheck when that row changes what gates the command). The four-part records live in +[commands: all commands](https://code.claude.com/docs/en/commands#all-commands) live. The four-part +records live in [reference/native-auto-mode-setup.md](reference/native-auto-mode-setup.md). ## Inputs, and one deliberate omission @@ -173,8 +170,7 @@ Two things to say while handing it over: judges it. Say that rather than implying the draft is validated. - **`claude auto-mode reset` is never run.** On a chezmoi-managed home what it removes is not recoverable from the settings file alone. Read what it removes from - [CLI reference: CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands) live (as - of 2026-11-03; recheck when that table changes what the reset subcommand removes). + [CLI reference: CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands) live. - **Prose provenance does not belong in an entry.** Dates, issue numbers, and prior-draft archaeology cost classifier attention and buy nothing; the critique names stripping them explicitly. Version control owns that history. diff --git a/plugins/harness-config/skills/setup/SKILL.md b/plugins/harness-config/skills/setup/SKILL.md index 5fea2c7508d..d309a557cfd 100644 --- a/plugins/harness-config/skills/setup/SKILL.md +++ b/plugins/harness-config/skills/setup/SKILL.md @@ -93,7 +93,7 @@ speak for the plugin. run through Claude Code's Bash tool. Report the resolved interpreter; FAIL only if no bash is resolvable. Pointer: for which shell a platform's sessions get, native Windows included, fetch [tools reference: PowerShell tool](https://code.claude.com/docs/en/tools-reference#powershell-tool) - live. As of: 2026-11-10. Recheck trigger: that section changes which shell a platform gets. + live. 5. **Network reachability**, INFO only: `audit`'s drift/freshness fetches read `raw.githubusercontent.com`, and a failed fetch degrades to SKIP rather than a setup failure. Do not fetch here; `check` performs no network call. diff --git a/plugins/harness-config/skills/setup/reference/wsl-profile.md b/plugins/harness-config/skills/setup/reference/wsl-profile.md index 13c2ce68086..608cbff21e3 100644 --- a/plugins/harness-config/skills/setup/reference/wsl-profile.md +++ b/plugins/harness-config/skills/setup/reference/wsl-profile.md @@ -32,8 +32,7 @@ without a `//` prefix, so a profile you edit can be checked. ## Limits -A deny rule is not an OS-level control. Per the same permissions page section (as of 2026-10-18, -recheck when it changes): +A deny rule is not an OS-level control. Per the same permissions page section: - Read and Edit denies cover the built-in file tools, the Bash file commands Claude Code recognizes (`cat`, `head`, `tail`, `sed`, `tee`) and redirection targets. diff --git a/plugins/harness-config/skills/unhobble/SKILL.md b/plugins/harness-config/skills/unhobble/SKILL.md index 53abde874cf..8deac3a3882 100644 --- a/plugins/harness-config/skills/unhobble/SKILL.md +++ b/plugins/harness-config/skills/unhobble/SKILL.md @@ -17,7 +17,7 @@ As models improve, instruction surfaces written for older models become the ceil every standing line every session, and lines that correct mistakes it no longer makes cost context and constrain behavior. We take the official pruning test as the premise (Pointer: when citing it, fetch [best practices: keep CLAUDE.md short](https://code.claude.com/docs/en/best-practices#keep-claude-md-short) -live. As of: 2026-10-30. Recheck trigger: that section drops or changes its per-line pruning test); +live); the strongest form of that test is empirical: delete, run, watch. This skill operationalizes the experiment its sibling `audit-instructions` can only reason about: instead of judging instruction *text* against doctrine, it measures the *model* against the repo with the instructions gone, and lets observed stumbles, @@ -188,8 +188,7 @@ rendered, never a guessed level; the value changes nothing else about the experi ship, fetch [plugin manifest reference: standard layout](https://code.claude.com/docs/en/plugins/manifest-reference#standard-layout) and [plugin manifest reference: hooks](https://code.claude.com/docs/en/plugins/manifest-reference#hooks) - live. **As of:** 2026-11-03. **Recheck trigger:** that page names another hook location or - component type. + live. Classify each wired entry with the "Classifying a hook" rubric linked above; do not restate it and do not invent a second hook rubric. A plugin whose every component is policy (or behavioral with a @@ -253,15 +252,14 @@ Apply the confirmed strip plan: passed over one can end the strip with an instruction surface still loading. **Pointer:** when deciding whether removing the `CLAUDE.md` names makes an `AGENTS.md` live, fetch [memory: when Claude Code reads AGENTS.md](https://code.claude.com/docs/en/memory#when-claude-code-reads-agents-md) - live. **As of:** 2026-11-03. **Recheck trigger:** that section changes which files displace an - `AGENTS.md`. **What candidacy is conditional on is whether the strip could make the + live. **What candidacy is conditional on is whether the strip could make the file live at all.** Removing the `CLAUDE.md` names is what makes a session read an `AGENTS.md`, but only in a session where `AGENTS.md` support is available and the instruction-files mode reads one: where either condition is known to rule that out, the file stays unread after the strip, so stripping it changes nothing about the baseline being measured and only perturbs the other tools that read it. Leave it out of the candidate set only when a condition is known to rule it out **and** no `CLAUDE.md` imports or symlinks it; a merely unresolved condition keeps it, and so does a shim or import, since that import is itself a live - path into context regardless of native support. The conditions carry their dated records in this + path into context regardless of native support. The conditions are recorded in this plugin's [reference/agents-md-liveness.md](../../reference/agents-md-liveness.md); read them there rather than restating them here. What the classification then says is binding on an `AGENTS.md` exactly as on a `CLAUDE.md`: one classified `policy` or `convention` is kept and never named to @@ -291,8 +289,7 @@ Apply the confirmed strip plan: `plugin@marketplace` key. **Pointer:** when deciding which scope's `enabledPlugins` value wins, fetch [settings reference: enabledPlugins](https://code.claude.com/docs/en/settings-reference#enabledplugins) - live. **As of:** 2026-10-11. **Recheck trigger:** that section changes the precedence between - project and user settings for the key. Do not call an arm stripped until a fresh session's + live. Do not call an arm stripped until a fresh session's `claude plugin list --json` omits the plugin. One that is still listed is a confound; local or managed scope can still win. - Print the "you are bare" summary: what a fresh session will now load, which plugins were @@ -461,8 +458,8 @@ scheduling surfaces vary per consumer and are the operator's choice. the `--bare` flag's section, [headless: start faster with bare mode](https://code.claude.com/docs/en/headless#start-faster-with-bare-mode), and the two variables' rows in - [environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live. As - of: 2026-10-18. Recheck trigger: any of them starts turning off a surface the operator owns, or + [environment variables: variables](https://code.claude.com/docs/en/env-vars#variables) live. + Recheck trigger: any of them starts turning off a surface the operator owns, or two of them merge): the experiment here ablates *your* instructions, which is the part you own. (Measuring what those product-side switches buy belongs to a context-budget audit, not to this experiment.) diff --git a/plugins/harness-config/skills/unhobble/evals/evals.json b/plugins/harness-config/skills/unhobble/evals/evals.json index caf278271cd..48fb869aef8 100644 --- a/plugins/harness-config/skills/unhobble/evals/evals.json +++ b/plugins/harness-config/skills/unhobble/evals/evals.json @@ -205,12 +205,12 @@ "name": "behavioral-plugin-overlay-is-sorted-false-and-verified", "narration": true, "prompt": "/harness-config:unhobble bare — notes@tools was classified behavioral. Disable it. It is currently true in user settings. After you edit, assume claude plugin list --json still lists it.", - "expected_output": "Writes notes@tools: false into the committed project .claude/settings.json enabledPlugins map, with keys kept in byte order (LC_ALL=C), records the prior enabled set in the manifest, and restores later by removing the key, because the project had no prior value for it (it was enabled only at user scope). Cites the settings-reference claim that project settings take precedence over user settings, with the as-of date and the recheck trigger. Does not call the plugin stripped, because claude plugin list --json still lists it; records that as a confound.", + "expected_output": "Writes notes@tools: false into the committed project .claude/settings.json enabledPlugins map, with keys kept in byte order (LC_ALL=C), records the prior enabled set in the manifest, and restores later by removing the key, because the project had no prior value for it (it was enabled only at user scope). Cites the settings-reference claim that project settings take precedence over user settings, with its pointer to the settings reference. Does not call the plugin stripped, because claude plugin list --json still lists it; records that as a confound.", "files": [], "expectations": [ "Writes a project-scope enabledPlugins false entry and keeps keys in byte order", "Records the prior enabled set and restores by removing the entry, since the project had no prior value", - "States the project-over-user precedence claim with its basis, as-of date, and recheck trigger", + "States the project-over-user precedence claim with its basis (a pointer to the settings reference)", "Refuses to treat the plugin as stripped while claude plugin list --json still lists it" ] }, diff --git a/plugins/harness-memory/skills/audit/SKILL.md b/plugins/harness-memory/skills/audit/SKILL.md index ff2de33b549..35ef33d93cd 100644 --- a/plugins/harness-memory/skills/audit/SKILL.md +++ b/plugins/harness-memory/skills/audit/SKILL.md @@ -47,9 +47,6 @@ The load-model column is this audit's working model, not a restatement of the do [Organize rules with `.claude/rules/`](https://code.claude.com/docs/en/memory#organize-rules-with-claude/rules/), [When Claude Code reads AGENTS.md](https://code.claude.com/docs/en/memory#when-claude-code-reads-agents-md) and auto memory's [How it works](https://code.claude.com/docs/en/memory#how-it-works). -- **As of**: 2026-10-01 -- **Recheck trigger**: a Claude Code release note or a change to one of those sections alters which - files load at session start, on demand, or within the auto-memory limits. Auto memory's effective enabled/disabled state must be resolved before auditing it, not assumed from a single scope: [`${CLAUDE_PLUGIN_ROOT}/skills/stateless/context/status.md`](../stateless/context/status.md), @@ -112,8 +109,6 @@ carrying `CLAUDE_PLUGIN_ROOT`. - **Pointer**: for where each `${…}` reference resolves, see [Where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves) and [Available string substitutions](https://code.claude.com/docs/en/skills#available-string-substitutions). -- **As of**: 2026-09-27 -- **Recheck trigger**: either table adds supporting files to where a `${…}` reference resolves. ## Audit mode (default) @@ -152,9 +147,6 @@ with no project, checkout, worktree, or session segment. A fixed `audit/last-aud - **Pointer**: for the plugin data directory, see [Environment variables](https://code.claude.com/docs/en/plugins/manifest-reference#environment-variables). -- **As of**: 2026-10-01 -- **Recheck trigger**: that section adds a project, worktree, or session segment to the data - directory's path. Losing reports is the smaller half; the larger half is the read. `report` mode would serve whatever that file currently holds and `fix` mode would act on it, so on a machine with two repositories, @@ -206,5 +198,3 @@ Absent that plugin, the fix mode here stands on its own. - **Pointer**: for what the plugin's skill and command do, read its [README: Usage](https://github.com/anthropics/claude-plugins-official/tree/main/plugins/claude-md-management#usage). -- **As of**: 2026-11-03 -- **Recheck trigger**: that section renames, adds or drops the plugin's skill or command. diff --git a/plugins/harness-memory/skills/audit/context/update.md b/plugins/harness-memory/skills/audit/context/update.md index 06168b25d26..470d7cdf24b 100644 --- a/plugins/harness-memory/skills/audit/context/update.md +++ b/plugins/harness-memory/skills/audit/context/update.md @@ -55,8 +55,8 @@ diff as a contribution/issue against the plugin's repository so the shipped crit With that framing, the content updates are: -1. `reference/official-guidance.md`: new or changed decisions in our words, pointers, as-of dates - and recheck triggers. Never copy the page's text into the file, quoted or paraphrased. +1. `reference/official-guidance.md`: new or changed decisions in our words and pointers, plus an + as-of date and recheck trigger on each stored value. Never copy the page's text into the file, quoted or paraphrased. 2. `reference/criteria.md`: check thresholds or severity levels needing adjustment, version number, "Last updated" date diff --git a/plugins/harness-memory/skills/audit/reference/criteria.md b/plugins/harness-memory/skills/audit/reference/criteria.md index c750adbd3bb..a28081e1a22 100644 --- a/plugins/harness-memory/skills/audit/reference/criteria.md +++ b/plugins/harness-memory/skills/audit/reference/criteria.md @@ -14,8 +14,7 @@ Source: official Claude Code docs, chiefly [Keep CLAUDE.md short](https://code.claude.com/docs/en/best-practices#keep-claude-md-short), [Enable persistent memory](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory) and [Skill content lifecycle](https://code.claude.com/docs/en/skills#skill-content-lifecycle). Each check -cites the exact section it rests on beside it. As of 2026-10-11; recheck when any of those sections -is renamed or moved. +cites the exact section it rests on beside it. `` in the commands below is the parent of this file's `reference/` directory. SKILL.md "Script paths" renders its absolute path; put it in place of the placeholder before running a @@ -25,9 +24,7 @@ This file defines every check the audit runs. Each check has a severity, descrip for evaluation. The audit applies checks per-entity-type (CLAUDE.md, rules, memory). Every firing rule here is our decision, in our words; a doc-derived check names the docs section it -rests on as a **Pointer** and stores none of the page's text. Unless a check says otherwise, each -pointer's as-of date is 2026-09-20 and its recheck trigger is a -Claude Code release note or docs change touching the section it points at. +rests on as a **Pointer** and stores none of the page's text. To refresh this file against current official guidance, run the skill's `update` action. @@ -46,8 +43,6 @@ against `AGENTS.md`, not against a CLAUDE.md that is not there. - **Pointer**: for when Claude Code reads `AGENTS.md`, see [When Claude Code reads AGENTS.md](https://code.claude.com/docs/en/memory#when-claude-code-reads-agents-md); the condition discovery applies is recorded in `scripts/lib/agents-md.sh`. -- **As of**: 2026-09-20 -- **Recheck trigger**: the recheck trigger recorded in `scripts/lib/agents-md.sh` fires. ### C1: Line Budget [FAIL] @@ -147,9 +142,8 @@ future session instead of relocating them. Rather than reading a single scope, resolve the **effective** state with the algorithm the sibling `stateless` skill already owns in [Step 3: Resolve the effective state](../../stateless/context/status.md#step-3-resolve-the-effective-state), -which also holds the precedence it applies and its pointers (as of 2026-10-11; recheck when that -step is renamed or moved, or stops carrying its own precedence pointers). A `false` in a -lower-precedence scope does not by itself disable the destination. +which also holds the precedence it applies and its pointers. A `false` in a lower-precedence scope +does not by itself disable the destination. When the resolved state is off, either name a destination that does load or state that enabling auto memory is a precondition of the move, rather than proposing it unconditionally. @@ -158,8 +152,7 @@ memory is a precondition of the move, rather than proposing it unconditionally. correctly defers, so moving content into a path-scoped rule and pulling it in by import saves nothing. Reproduced first-party on Claude Code 2.1.219 (2026-07-24); no official page states it. The same caveat, with its pointer, is in -[official-guidance.md, Rules files](official-guidance.md#rules-files) (as of 2026-10-11; recheck -when that section is renamed or moved, or drops the caveat or its pointer). +[official-guidance.md, Rules files](official-guidance.md#rules-files). **Provenance**: empirical extension, not doc-derived, so the `update` action must not overwrite it with doc-sourced text, and it needs re-verification on a current version rather than a doc re-fetch. @@ -195,10 +188,6 @@ live in [official-guidance.md](official-guidance.md), not here. [Frontmatter reference](https://code.claude.com/docs/en/skills#frontmatter-reference), [Control who invokes a skill](https://code.claude.com/docs/en/skills#control-who-invokes-a-skill) and [Override skill visibility from settings](https://code.claude.com/docs/en/skills#override-skill-visibility-from-settings). -- **As of** (the listing-entry pointer): 2026-10-11 -- **Recheck trigger** (the listing-entry pointer): a fetch of those sections changes the per-entry - listing cap or how it is configured, or no longer supports the zero-cost rule or the plugin-skill - exclusion above; re-derive this paragraph and the listing-entry cost from them. ### C4: Specificity [WARN] @@ -235,7 +224,7 @@ live in [official-guidance.md](official-guidance.md), not here. 4. WARN per instance **Provenance**: the KEEP branch is a **repo extension, not doc-derived**: we found no navigation -posture in the docs' include list (checked 2026-10-30), so the `update` action must not +posture in the docs' include list, so the `update` action must not overwrite it. **Why**: Step 1 applies, in our words, the docs' test that CLAUDE.md holds only what Claude cannot @@ -246,10 +235,6 @@ and 3 are our judgment: no docs section lists them. [Keep CLAUDE.md short](https://code.claude.com/docs/en/best-practices#keep-claude-md-short); for the architecture and file-layout row, see [What you can stop doing](https://code.claude.com/docs/en/best-practices#what-you-can-stop-doing). -- **As of**: 2026-10-30 -- **Recheck trigger**: the include list gains a navigation-pointer entry, the section drops its - only-what-Claude-cannot-work-out test, or the stop-doing table drops the architecture and - file-layout row. ### C6: Consistency [FAIL] @@ -426,8 +411,7 @@ already loads would spend budget restating it), so "unreferenced" alone proves n set-difference: enumerate always-loaded rules without `description:`, `git grep` each basename across tracked files excluding the rule's own file; zero hits = orphan). Path-scoped rules are exempt: they load only on demand, so being unreferenced costs nothing per session. What fires one is read at -[Path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules) (as of 2026-11-04; -recheck when that section stops loading a rule on demand). WARN per orphan. +[Path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules). WARN per orphan. Each finding carries the file's provenance (see "Provenance routing" below): a synced rule is still a finding, but its fix line names the sync's source rather than a local edit. diff --git a/plugins/harness-memory/skills/audit/reference/official-guidance.md b/plugins/harness-memory/skills/audit/reference/official-guidance.md index 3d580d104a1..9491268d340 100644 --- a/plugins/harness-memory/skills/audit/reference/official-guidance.md +++ b/plugins/harness-memory/skills/audit/reference/official-guidance.md @@ -27,11 +27,6 @@ Each section states what this audit does, in our words, and points at the section of the official page that covers the topic. Read the page there for its wording; this file stores none of it. -Last researched: 2026-06-20; the memory page pointers re-verified 2026-08-10 (the other sources -below were not re-checked on that date). Unless a section says otherwise, each pointer's as-of date -is 2026-06-20 and its recheck trigger is a Claude Code release note or docs change touching the -section it points at. - Refresh this file from current official docs via the skill's `update` action. --- @@ -97,9 +92,6 @@ resolution, recursion depth, approval of an external import); the scripts' impor (`scripts/lib/imports.sh`) carries the depth it stops at and cites this pointer. - **Pointer**: [Import additional files](https://code.claude.com/docs/en/memory#import-additional-files). -- **As of**: 2026-10-11 -- **Recheck trigger**: the section changes how a path resolves, the recursion depth, or what an - external import asks for. ## claudeMdExcludes setting @@ -119,9 +111,6 @@ The audit reads the patterns from every settings layer as one combined list. Wha matches, which layers may set it and which files it cannot exclude are read at the pointer. - **Pointer**: [Exclude specific CLAUDE.md files](https://code.claude.com/docs/en/memory#exclude-specific-claude-md-files). -- **As of**: 2026-10-11 -- **Recheck trigger**: the section changes what a pattern matches against, which settings layers - merge, or which files cannot be excluded. ## Skills vs CLAUDE.md @@ -145,8 +134,6 @@ files), the audit points to the `InstructionsLoaded` hook, for debugging only. - **Pointer**: [`InstructionsLoaded`](https://code.claude.com/docs/en/hooks#instructionsloaded) and [Troubleshoot memory issues](https://code.claude.com/docs/en/memory#troubleshoot-memory-issues). -- **As of**: 2026-11-10 -- **Recheck trigger**: the hook section says the hook can block loading or change what loads. ## Specificity @@ -177,9 +164,6 @@ read at the pointer. [Path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules), [Share rules across projects with symlinks](https://code.claude.com/docs/en/memory#share-rules-across-projects-with-symlinks), [User-level rules](https://code.claude.com/docs/en/memory#user-level-rules). -- **As of**: 2026-10-11 -- **Recheck trigger**: any of those sections changes where rules live, their load order, or the - frontmatter key that scopes them. **Path scoping status (verified working 2026-07-24 on Claude Code 2.1.219):** Path scoping defers as documented. The audit treats a path-scoped rule as absent at session start and loaded once Claude @@ -196,8 +180,6 @@ loading, or any session in which a path-scoped rule is present at session start. - **Pointer**: when a finding depends on what loads a path-scoped rule or a nested CLAUDE.md, fetch [Path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules) and [How CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load) live. -- **As of**: 2026-10-10 -- **Recheck trigger**: either section changes the tools or commands that load the file. Caveats that do survive, each verified: @@ -223,22 +205,17 @@ Caveats that do survive, each verified: injects nothing. - A session whose `--setting-sources` leaves out `project` is a session where the audit does not count on on-demand rules loading; which rules that drops is read at - [Set up rules](https://code.claude.com/docs/en/memory#set-up-rules) (as of 2026-10-11; recheck - when that section changes what `--setting-sources` controls). + [Set up rules](https://code.claude.com/docs/en/memory#set-up-rules). ## Auto-memory limits The audit's size gate treats only the start of `MEMORY.md`, up to the documented load limit, as loaded at session start, and everything after it as unread. It applies that limit to `MEMORY.md` only, never to a CLAUDE.md. The gate's firing values and its counting rule live in -[criteria.md, M1](criteria.md#m1-index-size-fail) (relayed 2026-10-11; recheck when that section -is renamed or stops holding the gate's values). Stripping YAML frontmatter and block-level HTML comments before -counting is our gate's rule, not a documented load behavior. +[criteria.md, M1](criteria.md#m1-index-size-fail). Stripping YAML frontmatter and block-level HTML +comments before counting is our gate's rule, not a documented load behavior. - **Pointer**: [How it works](https://code.claude.com/docs/en/memory#how-it-works) (auto memory). -- **As of**: 2026-10-11 -- **Recheck trigger**: the section changes the `MEMORY.md` load limit, or what it says about loading - a CLAUDE.md. ## Auto-memory storage @@ -249,9 +226,6 @@ model. - **Pointer**: [Storage location](https://code.claude.com/docs/en/memory#storage-location), and for our model of it, the stateless reference's [Storage location](../../stateless/reference/official-guidance.md#storage-location). -- **As of**: 2026-10-11 -- **Recheck trigger**: the docs section moves the default directory or changes which scopes may - set `autoMemoryDirectory`, or the stateless section is renamed or stops holding that model. ## Subagent persistent memory @@ -261,8 +235,6 @@ applies to auto memory. It recommends `project` unless the agent's learnings mus version control. - **Pointer**: [Enable persistent memory](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory). -- **As of**: 2026-10-01 -- **Recheck trigger**: the section adds or renames a scope, moves a directory, or changes its load limit. ## HTML comments @@ -271,8 +243,6 @@ that should spend no context, and does not count them toward the file's loaded s comments are stripped, and where they stay visible, are read at the pointer. - **Pointer**: [How CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load). -- **As of**: 2026-10-11 -- **Recheck trigger**: the section changes which HTML comments are stripped before injection. ## Boris Cherny (CC creator) @@ -293,9 +263,6 @@ Practices we take from Boris Cherny's published workflow, in our words: [Add supporting files](https://code.claude.com/docs/en/skills#add-supporting-files). No docs section covers Auto-Dream; correlate with [howborisusesclaudecode.com](https://howborisusesclaudecode.com) for the practices themselves. -- **As of**: 2026-10-11 -- **Recheck trigger**: either docs section is renamed or moved, or a docs page starts covering - memory consolidation. ## Style enforcement @@ -327,15 +294,9 @@ comes back, and which bodies come back at all, is read at the pointer at run tim [Instructions seem lost after `/compact`](https://code.claude.com/docs/en/memory#instructions-seem-lost-after-/compact), and [Skill content lifecycle](https://code.claude.com/docs/en/skills#skill-content-lifecycle) (correlate with [Steering Claude Code](https://claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more)). -- **As of**: 2026-10-11 -- **Recheck trigger**: any of those sections changes what a mechanism in the table gets back after - compaction, or the skill re-attach budget; or the [Auto-memory limits](#auto-memory-limits) - section the table relays to is renamed. - -`AGENTS.md` is its own row's worth of behavior, and the row depends on the repository. The memory -page changed its `AGENTS.md` guidance between 2026-06-20 and 2026-09-19, so the row below is -derived from the page as of 2026-09-29, not from the earlier shim-only guidance. Recheck when the -memory page's `AGENTS.md` section changes again. + +`AGENTS.md` is its own row's worth of behavior, and the row depends on the repository. The row +below follows the memory page's current `AGENTS.md` guidance, not its earlier shim-only guidance. The audit models an `AGENTS.md` as loading either directly, where no `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md` in the working directory or above it displaces it and diff --git a/plugins/harness-memory/skills/stateless/SKILL.md b/plugins/harness-memory/skills/stateless/SKILL.md index e7f469ff5ef..0ab71336fc1 100644 --- a/plugins/harness-memory/skills/stateless/SKILL.md +++ b/plugins/harness-memory/skills/stateless/SKILL.md @@ -21,8 +21,7 @@ bash "${CLAUDE_PLUGIN_ROOT}/skills/stateless/scripts/scope-report.sh" || echo "( Inspect and disable Claude Code **auto memory**, the store Claude writes for itself. Where it lives is read at -[Storage location](https://code.claude.com/docs/en/memory#storage-location) (as of 2026-11-03; -recheck when that section moves the store or changes what relocates it). Governs auto-memory +[Storage location](https://code.claude.com/docs/en/memory#storage-location). Governs auto-memory only. Not in scope: CLAUDE.md / CLAUDE.local.md / `.claude/rules/` (use `/harness-memory:audit`), transcripts, history, or shell snapshots. For the official full per-project wipe, use `claude purge`. [reference/official-guidance.md](reference/official-guidance.md), "Out of scope for this skill", @@ -68,7 +67,7 @@ reports auto memory off, and `0` reports it **on** even against `autoMemoryEnabl when the env var is unset does `autoMemoryEnabled` (by settings precedence) decide. `status` must report the env var as authoritative whenever it is set. `disable` sets the env var to `1` and `autoMemoryEnabled: false` together. The reference file's "Precedence: the env var overrides the -setting (VERIFIED)" holds the pointer, as-of date and recheck trigger. +setting (VERIFIED)" holds the pointer. ## Actions @@ -88,8 +87,6 @@ carrying `CLAUDE_PLUGIN_ROOT`. - **Pointer**: for where each `${…}` reference resolves, see [Where each variable resolves](https://code.claude.com/docs/en/plugins/manifest-reference#where-each-variable-resolves). -- **As of**: 2026-10-07 -- **Recheck trigger**: that table adds supporting files to where a `${…}` reference resolves. ## Boundary, the built-in `/memory` command @@ -99,8 +96,6 @@ carrying `CLAUDE_PLUGIN_ROOT`. it. - **Pointer**: for what it opens and toggles, read [View and edit with `/memory`](https://code.claude.com/docs/en/memory#view-and-edit-with-/memory). - - **As of**: 2026-11-03 - - **Recheck trigger**: that section adds or drops what the command edits or toggles. - **This skill (marketplace plugin).** Reports the effective auto-memory state across every settings scope and the env var that overrides them, disables it durably through both levers, and purges the store behind a manifest and a confirmation gate. @@ -136,17 +131,13 @@ which `status` reports. - **Windows managed policy**: we treat it as possibly held in the registry rather than a file, which `scope-report.sh` can't read. Report managed scope as unread, don't assume empty. [Settings scopes and precedence](reference/official-guidance.md#settings-scopes-and-precedence) - points at where each location is documented (as of 2026-10-11; recheck when that section is - renamed or moved, or drops its managed-settings location pointer). + points at where each location is documented. - **`disable` leaves this session's loaded memory in place.** What auto memory loaded at startup stays in the current context whether or not the setting reloads mid-session, so tell the user a new session is the first one that starts without it. - **Pointer**: for which settings edits reach a running session, see ; for the toggle, see . - - **As of**: 2026-10-01 - - **Recheck trigger**: either section changes whether an `autoMemoryEnabled` or `env` edit - reaches a running session. - **Tracked `settings.json`**: a live edit to a dotfile-manager-tracked settings file must be backfilled to the source; never run an `apply` that could revert the edit. - **Desktop / claude.ai memory is server-side**. `purge` cannot delete it; give direction only. diff --git a/plugins/harness-memory/skills/stateless/context/desktop.md b/plugins/harness-memory/skills/stateless/context/desktop.md index 65a6e140c9f..55388248b33 100644 --- a/plugins/harness-memory/skills/stateless/context/desktop.md +++ b/plugins/harness-memory/skills/stateless/context/desktop.md @@ -33,6 +33,3 @@ UI changes, so treat these as directions to the right area, and confirm against the [Turn memory on or off for your account](https://support.claude.com/en/articles/11817273-use-claude-s-chat-search-and-memory-to-build-on-previous-context#h_c9b905eb3f) and [View and manage your memory](https://support.claude.com/en/articles/11817273-use-claude-s-chat-search-and-memory-to-build-on-previous-context#h_463c0c336e) sections. -- **As of**: 2026-10-11 -- **Recheck trigger**: the article is retitled or moved, either section is renamed, or the app's - memory controls no longer match the guided steps above. diff --git a/plugins/harness-memory/skills/stateless/context/purge.md b/plugins/harness-memory/skills/stateless/context/purge.md index c751ff88b8f..74308d7d5e9 100644 --- a/plugins/harness-memory/skills/stateless/context/purge.md +++ b/plugins/harness-memory/skills/stateless/context/purge.md @@ -27,9 +27,8 @@ included") and offer to additionally check any repos the user names. We resolve `autoMemoryDirectory` from **every** settings scope present before purging; miss one and you purge the wrong place. Which scopes it is read from is in -[`autoMemoryDirectory`](https://code.claude.com/docs/en/settings-reference#automemorydirectory) -(as of 2026-11-03; recheck when that entry changes the scopes it is read from), and -[official-guidance.md](../reference/official-guidance.md), "Storage location", holds the rest of +[`autoMemoryDirectory`](https://code.claude.com/docs/en/settings-reference#automemorydirectory), +and [official-guidance.md](../reference/official-guidance.md), "Storage location", holds the rest of the record. So: 1. Read `autoMemoryDirectory` from every present settings scope: managed, local, project, and @@ -72,11 +71,8 @@ Present to the user: If the intent is the full per-project wipe, point to `claude purge` instead, and state its scope to the user (what it deletes and what it leaves alone) from a live read of [Clear local data](https://code.claude.com/docs/en/claude-directory#clear-local-data), never - from memory (as of 2026-10-11; recheck when that section changes what `claude purge` deletes or - keeps). How this skill treats the command is in - [Out of scope for this skill](../reference/official-guidance.md#out-of-scope-for-this-skill-verified-deliberate) - (as of 2026-10-11; recheck when that section is renamed or moved, or drops its `claude purge` - record). + from memory. How this skill treats the command is in + [Out of scope for this skill](../reference/official-guidance.md#out-of-scope-for-this-skill-verified-deliberate). - If `$manifest` is empty, report that there is nothing to purge and stop (no-op). ## Step 3: Confirmation gate (with backup offer) diff --git a/plugins/harness-memory/skills/stateless/context/status.md b/plugins/harness-memory/skills/stateless/context/status.md index e8cb7ecaaad..5b4473b4444 100644 --- a/plugins/harness-memory/skills/stateless/context/status.md +++ b/plugins/harness-memory/skills/stateless/context/status.md @@ -38,24 +38,21 @@ you cannot inspect it, don't assume it is empty. - **Enabled state.** Check `CLAUDE_CODE_DISABLE_AUTO_MEMORY` first: if it is set anywhere (OS env or any `env` block), report it as authoritative whatever `autoMemoryEnabled` says, with the value it holds. For what the env var does, read - [Enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory) - (as of 2026-11-03; recheck when that section changes what the env var or its values do). If - the env var is unset, apply settings precedence to `autoMemoryEnabled`, in the order + [Enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory). + If the env var is unset, apply settings precedence to `autoMemoryEnabled`, in the order [Settings precedence](https://code.claude.com/docs/en/settings#settings-precedence) lists; a `--settings` value the snapshot cannot see ranks among those levels, so say so when the session was started with one. With no scope setting it, the default applies: read [Enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory) for which session kinds start with it off, and report off (naming that kind) when the current - session is one of them, on otherwise. Both pointers: as of 2026-10-11; recheck when the precedence list - changes or that section changes which sessions start with auto memory off. When the env var and the setting disagree, report the effective state as - the env var dictates and call out the disagreement so the user can align them. + session is one of them, on otherwise. When the env var and the setting disagree, report the + effective state as the env var dictates and call out the disagreement so the user can align them. - **Store location.** If any scope sets `autoMemoryDirectory`, the effective directory is that override (highest-precedence scope wins), not the slug-derived default the snapshot printed. Expand `~/` and report the real path, plus whether `MEMORY.md` and topic files exist there. A winning project or local value applies only under the conditions at [Storage location](https://code.claude.com/docs/en/memory#storage-location) (workspace trust and - read blocking; as of 2026-11-04; recheck when that section changes when a repository-supplied - value is honored): when one of them may not hold, report the value as configured and possibly + read blocking): when one of them may not hold, report the value as configured and possibly not in effect. - **Store contents.** Report the `MEMORY.md` line count and topic-file count at the effective directory (re-list if the effective dir differs from the default). diff --git a/plugins/harness-memory/skills/stateless/reference/official-guidance.md b/plugins/harness-memory/skills/stateless/reference/official-guidance.md index 104fbf789d4..af16e38f6f9 100644 --- a/plugins/harness-memory/skills/stateless/reference/official-guidance.md +++ b/plugins/harness-memory/skills/stateless/reference/official-guidance.md @@ -3,8 +3,6 @@ Each section states what this skill does, in our words, and points at the section of the official page that covers the topic. Read the page there for its wording; this file stores none of it. -Last researched: 2026-07-22; the claude-directory, settings and cli-reference pointers verified -2026-08-10 (the other sources below were not re-checked on that date) Sources: [Auto memory](https://code.claude.com/docs/en/memory#auto-memory), [Settings precedence](https://code.claude.com/docs/en/settings#settings-precedence), [env-vars](https://code.claude.com/docs/en/env-vars) (its rows carry no section anchors), @@ -12,21 +10,9 @@ Sources: [Auto memory](https://code.claude.com/docs/en/memory#auto-memory), [CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands). Each section below names the exact section it rests on. -- **As of**: 2026-10-11 (the four anchored sources above confirmed live on their pages) -- **Recheck trigger**: one of those four pages renames, moves or drops the section its anchor - names, or the env-vars page gains row anchors. - Refresh this file from current official docs before relying on it (re-fetch the section each pointer below names). -**Recheck trigger:** re-derive every decision below when any of these becomes observable: the -`/memory` command gains, loses or renames its auto-memory toggle; the `autoMemoryEnabled` setting -or the `CLAUDE_CODE_DISABLE_AUTO_MEMORY` environment variable changes name, default or semantics; -the per-project memory path under `~/.claude/projects//memory/` moves; or any of the five -source pages above changes its auto-memory section. A Claude Code release note touching memory, -settings or the CLI reference is the usual way one of these surfaces. The dates above record when -the decisions last matched their sources and confer no standing authority on their own. - --- ## What auto memory is @@ -48,9 +34,6 @@ written. - **Pointer**: [Enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory) and [`autoMemoryEnabled`](https://code.claude.com/docs/en/settings-reference#automemoryenabled). -- **As of**: 2026-10-11 -- **Recheck trigger**: the section changes the default, which sessions default off, or where the - toggle saves. ### Precedence: the env var overrides the setting (VERIFIED) @@ -67,9 +50,6 @@ being unset. [Environment variables](https://code.claude.com/docs/en/env-vars) (rows carry no anchor), and [Enable or disable auto memory](https://code.claude.com/docs/en/memory#enable-or-disable-auto-memory), the nearest section naming the variable. -- **As of**: 2026-10-11 -- **Recheck trigger**: the env-vars row or that section changes what a set value of the variable - does, or whether it outranks `autoMemoryEnabled`. ## Storage location @@ -85,10 +65,6 @@ at the pointer. [Name the project directory yourself](https://code.claude.com/docs/en/sessions#name-the-project-directory-yourself) and [`autoMemoryDirectory`](https://code.claude.com/docs/en/settings-reference#automemorydirectory). -- **As of**: 2026-11-04 -- **Recheck trigger**: the section changes how the project directory is derived or named, the - scopes `autoMemoryDirectory` is read from, the accepted path forms, or when a repository-supplied - value is honored. **What `purge` depends on:** because `autoMemoryDirectory` is read from *any* scope, the real memory dir may not be the slug-derived default. Purge must read that key at every scope @@ -108,8 +84,6 @@ for an `autoMemoryDirectory` override. [Storage location](https://code.claude.com/docs/en/memory#storage-location), the nearest section naming the variable, and [claude-directory](https://code.claude.com/docs/en/claude-directory#explore-the-directory). -- **As of**: 2026-10-11 -- **Recheck trigger**: the env-vars row or either section changes what the variable relocates. The directory holds a `MEMORY.md` index plus topic files; the layout is in the Storage location section. @@ -126,8 +100,7 @@ scope" below). This skill resolves settings in the precedence order the page lists, highest first, reading the order there rather than from this file. It treats a managed value as overriding every lower scope. The managed-precedence exceptions are many and are read on the page; none of them names -`autoMemoryEnabled`, `CLAUDE_CODE_DISABLE_AUTO_MEMORY`, or auto memory at all (checked -2026-10-11), so no lower settings scope overrides a managed `autoMemoryEnabled` value. That +`autoMemoryEnabled`, `CLAUDE_CODE_DISABLE_AUTO_MEMORY`, or auto memory at all, so no lower settings scope overrides a managed `autoMemoryEnabled` value. That negative governs settings scopes only: the `CLAUDE_CODE_DISABLE_AUTO_MEMORY` environment variable sits outside settings precedence and, when set, still overrides the effective value, managed or not (see "Precedence: the env var overrides the setting" above). @@ -135,8 +108,7 @@ sits outside settings precedence and, when set, still overrides the effective va Managed settings live outside the repository, in system locations and, on some platforms, in OS policy stores such as the Windows registry that this skill's scripts do not read; each location is read at -[Where each mechanism stores the policy](https://code.claude.com/docs/en/managed-settings#where-each-mechanism-stores-the-policy) -(as of 2026-10-11; recheck when that section adds, moves or drops a location). +[Where each mechanism stores the policy](https://code.claude.com/docs/en/managed-settings#where-each-mechanism-stores-the-policy). So `CLAUDE_CODE_DISABLE_AUTO_MEMORY` can be set as a real OS environment variable **or** inside a settings file's `env` block, which applies to every session and the subprocesses it spawns. @@ -144,9 +116,6 @@ settings file's `env` block, which applies to every session and the subprocesses - **Pointer**: [Settings precedence](https://code.claude.com/docs/en/settings#settings-precedence), [Exceptions to managed settings precedence](https://code.claude.com/docs/en/settings#exceptions-to-managed-settings-precedence), and [`env`](https://code.claude.com/docs/en/settings-reference#env). -- **As of**: 2026-10-11 -- **Recheck trigger**: the settings page adds, removes or reorders a level in the precedence list, - or documents a managed-settings exception for `env` or for auto memory. ## Out of scope for this skill (verified, deliberate) @@ -160,9 +129,6 @@ settings file's `env` block, which applies to every session and the subprocesses [Cleaned up automatically](https://code.claude.com/docs/en/claude-directory#cleaned-up-automatically) and [Kept until you delete them](https://code.claude.com/docs/en/claude-directory#kept-until-you-delete-them) live. - - **As of**: 2026-11-10 - - **Recheck trigger**: either claude-directory section moves a path between the cleaned and kept - lists, or the `cleanupPeriodDays` default or minimum changes. This skill names `claude purge` as the official per-project wipe, and treats it as confirming before it deletes and as covering auto memory along with other per-project data. When a user @@ -176,9 +142,6 @@ settings file's `env` block, which applies to every session and the subprocesses [CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands) live; for what it deletes and its former name, fetch [Clear local data](https://code.claude.com/docs/en/claude-directory#clear-local-data). - - **As of**: 2026-10-10 - - **Recheck trigger**: the Clear local data section changes what `claude purge` deletes or keeps, - or the CLI commands table renames or drops the command. **Source conflict**: the changelog v2.1.288 entry and [Clear local data](https://code.claude.com/docs/en/claude-directory#clear-local-data) disagree on @@ -187,8 +150,6 @@ settings file's `env` block, which applies to every session and the subprocesses - **Pointer**: when a user asks whether the former name still works, fetch the [changelog](https://code.claude.com/docs/en/changelog) (v2.1.288) and [Clear local data](https://code.claude.com/docs/en/claude-directory#clear-local-data) live. - - **As of**: 2026-10-10 - - **Recheck trigger**: either source changes what it says about the former command name. We record `CLAUDE_CODE_SKIP_PROMPT_HISTORY` as the true "no session persistence" lever, the complement to deleting the files after the fact. Recorded for that contrast; this skill acts on @@ -196,9 +157,6 @@ settings file's `env` block, which applies to every session and the subprocesses - **Pointer**: when a user asks what the variable stops being written, fetch [Plaintext storage](https://code.claude.com/docs/en/claude-directory#plaintext-storage) live. - - **As of**: 2026-11-10 - - **Recheck trigger**: that section drops the variable or stops naming it as the way to keep - sessions from being written to disk. - **Claude Desktop / claude.ai account memory.** That is a server-side account store, not local files, so this skill cannot delete it and only gives direction (see