Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
bump: patch
---

### Fixed

- `/harness-config:audit-permission-state`: the reader takes the project file from the primary
working directory rather than the repository root. Below the repository root, where it cannot tell a
session started there from one that ran a Bash `cd`, it also reads the root's file as
`project toplevel`, so a root-started session's deny rules survive a `cd`; run it from the session's
start directory, since after a `cd` from another subdirectory that directory's file is not read. The
output names both directories,
the lint checks each file's values, and `--merge-only` keeps the note that one may be over-reported.
Its cloud-session note also covers self-hosted runner images and project cloud threads.
- `/harness-config:audit`: the baseline drops the `Bash(git push)` ask row, which `Bash(git push *)`
already covers, so a project with the wider rule is no longer flagged for lacking the bare one. An
absent `effort:` no longer reads as the session level, the family alias record no longer rests on a
stale probe. The `fallbackModel` chain cap is read from model-config's Fallback model chains section,
where the page now states it, so the check no longer skips every chain. The effort pin check finds the defaults item by what it says, so a renumbered list no
longer hides a changed default, and its baseline matches the current page, with the listed levels
unchanged.
- `/harness-config:audit-instructions`: harness thinking-disable forms no longer fire the rejected
pairing row on models where they have no effect, exit-2 stderr is no longer stated as always
reaching Claude, and the first-run hold and a wrong settings pointer are gone.
- `/harness-config:audit-permission-grants` and the plugin README: the user settings file is no
longer named as where a prompt approval lands.
- `/harness-config:audit-pass`: the handoff no longer compares a `/doctor` version floor its pointer
has stopped stating, names `skillOverrides` as a documented suppression channel, and the report
location record points at the plugin data rules instead of quoting them.
8 changes: 0 additions & 8 deletions .claude/audit-pass.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,4 @@ suppressions:
anchor/v1: "e:b40d4d51d2c2:6e340b9c"
reason: "Cloud sessions on this repository push their working branch as the harness instructs; an ask-gate on git push would prompt on every run and is never answered. The GitHub proxy does not limit which branch a push updates (https://code.claude.com/docs/en/cloud-environments#github-proxy, Push restrictions, as of 2026-10-11; recheck when that bullet changes), so the default branch is held by the repository ruleset's pull-request rule, not by this gate. Local operators keep whatever ask rule they want in their user settings."
date: 2026-09-08
52bccf5cafa7fd59:
check: harness-config/audit/B/baseline-ask-rules
claim: "missing-pattern:Bash(git push)"
sites:
- surface: .claude/settings.json
anchor/v1: "e:b40d4d51d2c2:6e340b9c"
reason: "Same posture as the argument-bearing form: the harness mandates the push in cloud sessions."
date: 2026-09-08
```
8 changes: 0 additions & 8 deletions docs/conventions/harness-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,3 @@ suppressions:
"anchor/v1": "e:b40d4d51d2c2:6e340b9c"
reason: "Cloud sessions on this repository push their working branch as the harness instructs; an ask-gate on git push would prompt on every run and is never answered. The GitHub proxy does not limit which branch a push updates (https://code.claude.com/docs/en/cloud-environments#github-proxy, Push restrictions, as of 2026-10-11; recheck when that bullet changes), so the default branch is held by the repository ruleset's pull-request rule, not by this gate. Local operators keep whatever ask rule they want in their user settings."
date: "2026-09-08"
52bccf5cafa7fd59:
check: harness-config/audit/B/baseline-ask-rules
claim: "missing-pattern:Bash(git push)"
sites:
- surface: .claude/settings.json
"anchor/v1": "e:b40d4d51d2c2:6e340b9c"
reason: "Same posture as the argument-bearing form: the harness mandates the push in cloud sessions."
date: "2026-09-08"
9 changes: 5 additions & 4 deletions plugins/harness-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ make a grant silently do nothing: interpreter-wildcard / blanket rules that Clau
entering auto mode, hardcoded absolute machine/user paths (Bash rules match literally, no expansion),
and inert plugin self-grants. A deterministic detector scans skill/command/agent frontmatter
`allowed-tools` and the project, local, and user-global `permissions.allow` arrays, and recommends the
bare-command-on-PATH pattern. The user-global file
(`${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json`) is where Claude Code's own "Always allow" path
writes, so on a long-lived machine expect it to carry most of the findings. Their remediation is
the operator's, since no skill can write that file. The principle and citations live in the marketplace
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).
Report-only.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ current the claim is, not authority.

| Claim | Basis | As of | Recheck trigger |
|---|---|---|---|
| `PostToolUse` cannot block: the tool has already run, and exit code 2 shows the hook's stderr to Claude as a system reminder | [Claude Code hooks reference](https://code.claude.com/docs/en/hooks), exit-code-2 behavior per event | 2026-09-13 | A re-fetch finds the per-event exit-code table no longer matching this row |
| `PostToolUse` cannot block: the tool has already run, and exit code 2 only shows the hook's stderr to Claude | [Claude Code hooks reference](https://code.claude.com/docs/en/hooks#exit-code-2-behavior-per-event), exit-code-2 behavior per event | 2026-11-04 | A re-fetch finds the per-event exit-code table no longer matching this row |
| `PermissionRequest` does not honor exit code 2: "the permission flow proceeds unchanged. Deny through the `decision` object instead" | [Claude Code hooks reference](https://code.claude.com/docs/en/hooks), `PermissionRequest` exit-code behavior | 2026-09-13 | A re-fetch finds `PermissionRequest` honoring exit code 2, or the `decision` object renamed or removed |
| The hooks reference documents 33 hook events | [Claude Code hooks reference](https://code.claude.com/docs/en/hooks), the hook-events section headings, counted 2026-09-13 | 2026-09-13 | A re-fetch returns a different number of documented events |
| We leave hook enumeration to the native `/hooks` menu, which lists the resolved set with each hook's source; when you need its exact contents, read the section live | [The /hooks menu](https://code.claude.com/docs/en/hooks#the-/hooks-menu) | 2026-10-11 | That section stops showing each hook's source, or the menu stops listing the resolved set of configured hooks |
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ shapes without this gate produces noise, because most surface pairs never co-loa
| User `CLAUDE.md` | Every session, unless the file is over the size limit the second pointer names, which skips it | [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load); [memory: how it works](https://code.claude.com/docs/en/memory#how-it-works) |
| Project `CLAUDE.md` / `CLAUDE.local.md` | Every session in that tree, after user scope, under the same size limit | [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load) |
| Project `AGENTS.md` / `.claude/AGENTS.md`, where no `CLAUDE.md` name displaces it, **and, under `claude-md-and-agents-md`, even where one does**, in both cases only where the session reads `AGENTS.md` natively at all | Every session in that tree | [memory: AGENTS.md](https://code.claude.com/docs/en/memory#agents-md); [memory: choose which instruction files load](https://code.claude.com/docs/en/memory#choose-which-instruction-files-load) |
| Nested `CLAUDE.md` in a subdirectory | On demand, when Claude works with a file there | [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load) |
| Nested `CLAUDE.md` in a subdirectory | On demand, once Claude works with a file there | [memory: how CLAUDE.md files load](https://code.claude.com/docs/en/memory#how-claude-md-files-load) |
| `.claude/rules/*` without `paths` | Every session | [memory: set up rules](https://code.claude.com/docs/en/memory#set-up-rules) |
| `.claude/rules/*` with `paths` | Only when a matching file is read | [memory: path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules) |
| `.claude/rules/*` with `paths` | Only once Claude works with a matching file; read the triggers from the pointer | [memory: path-specific rules](https://code.claude.com/docs/en/memory#path-specific-rules) |
| Skill body | Only once invoked, then for the rest of the session | [skills: skill content lifecycle](https://code.claude.com/docs/en/skills#skill-content-lifecycle) |
| Auto memory `MEMORY.md` | Every **main** session, only its loaded portion, and **not** in a subagent, except a fork | [memory: how it works](https://code.claude.com/docs/en/memory#how-it-works) |
| A subagent's **own** auto memory `MEMORY.md` (its `memory` field) | Every dispatch of **that** subagent, only its loaded portion, never the main session, and never another agent's | [subagents: enable persistent memory](https://code.claude.com/docs/en/sub-agents#enable-persistent-memory) |
Expand All @@ -162,7 +162,7 @@ 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-10-11
- **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.

Expand Down Expand Up @@ -306,13 +306,12 @@ Three consequences for residency, and each one bounds a pair rather than admitti
[hooks: SessionStart](https://code.claude.com/docs/en/hooks#sessionstart) live (as of 2026-10-11;
recheck when its matcher values change).
- **Exit-2 stderr is turn-scoped error feedback, not a standing directive, and only some events
have an act to block.** Exit-2 stderr reaches Claude as an error message
([hooks: exit code 2](https://code.claude.com/docs/en/hooks#exit-code-2), as of 2026-10-11;
recheck when that section stops feeding exit-2 stderr back to Claude), so it is not nothing;
but it is a one-turn message, never a standing rule. Whether it also carries a *gate* is
event-specific, and the sole authority on that is the hooks page's
have an act to block.** Where exit-2 stderr goes varies by event, so read whether Claude, the user
or nobody sees it from the table below; at most it is a one-turn message, never a standing rule.
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-10-11; recheck when the table is renamed, removed or restructured, or its
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
copied into this file becomes a closed partition that silently misgrades the next event added.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,11 @@ each only on the surfaces its row names.
and where thinking may not be disabled):
<https://platform.claude.com/docs/en/build-with-claude/effort>
- Model configuration (the harness-side thinking-display and thinking-disable surfaces, which effort
levels each surface accepts, the per-model calibration of the effort scale, the first-run
default hold, and the adaptive-reasoning / fixed-thinking-budget partition):
levels each surface accepts, the per-model calibration of the effort scale, and the
adaptive-reasoning / fixed-thinking-budget partition):
<https://code.claude.com/docs/en/model-config>
- Settings (the `effortLevel` value set): <https://code.claude.com/docs/en/settings>
- Settings reference (the `effortLevel` value set):
<https://code.claude.com/docs/en/settings-reference#effortlevel>
- Environment variables (`CLAUDE_CODE_EFFORT_LEVEL`, `MAX_THINKING_TOKENS`, and
`CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` with the models it reaches):
<https://code.claude.com/docs/en/env-vars>; read it whole per the
Expand Down Expand Up @@ -1169,15 +1170,15 @@ since each prescribes a request the model refuses.
`Alt+T` / `Option+T` session toggle, or API `thinking: {"type": "disabled"}`, together with
`xhigh` or `max` effort, on Claude Opus 5 or a later model, or, in the API form only, on Claude
Haiku 5.5 (see the `haiku-5-5` widening below). Both operands are configuration
literals. Fire on the API form and on the harness forms alike: in neither does the prescribed
level reach the model, so the finding and its remediation are the same for both. What Claude
Code sends in place of the prescribed level is behind the pointer.
Pointer: for the harness outcome, see
literals. Fire on the API form and, on a model where thinking can be turned off, on the harness
forms alike: the finding and its remediation are the same for both. On a model in I17-a's no-effect
set the harness forms change nothing, so this arm does not fire on them there.
Pointer: for the harness outcome and that set, see
[model configuration: extended thinking](https://code.claude.com/docs/en/model-config#extended-thinking)
and [errors: effort isn't available with thinking turned
off](https://code.claude.com/docs/en/errors#effort-isnt-available-with-thinking-turned-off).
As of: 2026-10-01. Recheck trigger: either section changes what Claude Code sends when thinking
is off and the prescribed level is `xhigh` or `max`.
As of: 2026-11-04. Recheck trigger: either section changes what Claude Code does when thinking
is off and the prescribed level is `xhigh` or `max`, or changes which models accept thinking off.
- **Effort literals do not all reach every surface, and the literal set is not the whole set.**
Count `max` wherever text sets it through `CLAUDE_CODE_EFFORT_LEVEL`, `--effort`, `/effort`, or
skill and subagent `effort` frontmatter, the frontmatter case being a surface this skill already
Expand All @@ -1203,7 +1204,7 @@ since each prescribes a request the model refuses.
**Only the API form belongs to this arm.** On **the models in I17-a's no-effect
set** the harness thinking-disable surfaces fail differently, and that failure is I17-a's, not
this row's: we treat thinking as unable to be turned off there, and the session toggle,
`alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` as silent no-ops rather than errors. **For
`alwaysThinkingEnabled` and `MAX_THINKING_TOKENS=0` as having no effect rather than as errors. **For
the Mythos models the harness pages state nothing**, so this row makes no claim about their
harness surfaces in either direction; the API reject is the whole of what is stated for them.
Pointer: for the per-model accepted values, see [thinking: configuring
Expand All @@ -1212,7 +1213,7 @@ since each prescribes a request the model refuses.
table](https://platform.claude.com/docs/en/build-with-claude/thinking-troubleshooting#supported-models);
for the harness no-ops, see
[model configuration: extended thinking](https://code.claude.com/docs/en/model-config#extended-thinking).
As of: 2026-10-01. Recheck trigger: a model gains or loses a 400 for `"disabled"` in either
As of: 2026-11-04. Recheck trigger: a model gains or loses a 400 for `"disabled"` in either
table, or the harness no-op list changes.
- **Third arm, API requests only: `between_tools` at a level or with a change it refuses.** Flag
instruction text that prescribes, or a code sample it tells the reader to send, a request to
Expand Down
Loading
Loading