skills/worktree/SKILL.md carries the measurement that justifies a machine-wide worktree-placement rule enforced by a fail-closed hook. Three defects sit in the two sentences that carry it: the version basis is attached to the wrong clause and has already been misread by two independent readers, the measurement records no fixture so nobody can adjudicate the counter-reproduction that disputes it, and the reproduction guidance contains a parenthetical that the current hooks docs contradict. A reader following that guidance will misdiagnose a null result — which is exactly the error that produced the disputed counter-reproduction in the first place.
Rows
Evidence
D-F1 — the version basis attaches to the wrong clause
plugins/source-control/skills/worktree/SKILL.md:58, unchanged at HEAD:
"Note that #16600 concerns memory files, which 2.1.224 already handles correctly — the surface still leaking is path-scoped rules, which no open upstream issue covers."
The only "Basis:" clause in that paragraph precedes the reproduction guidance, several sentences earlier. The reader-error is independently corroborated: a separate item's own "Loose ends" section makes exactly the same drift — "source-control@0.51.6 skills/worktree/SKILL.md:58 states memory files are handled correctly 'as of 2.1.224'. The 2.1.224 changelog stanza carries no memory/worktree/rule line." That is a second careful reader making the version-fact reading, in a different item. The claim is probably true and is not refuted; the defect is attribution hygiene on a surface whose entire value is attribution hygiene. Fix by inlining the basis at the claim ("measured in the same trace — no release note covers this"). LOW.
The changelog scan behind the null result (2.1.224's stanza has 32 entries and no memory/worktree/rule/instruction-loading line) is packet-sourced and was not re-run during verification.
D-F2 — the leak arm is disputed, and the fixture is missing
SKILL.md:56 states the measurement — "measured on 2.1.224: … emits one path_glob_match naming the parent checkout's rule file". :58 states the placement-equivalence arm — "The leak is not specific to .claude/worktrees/: a worktree at a plain non-dot subdirectory leaks identically". The method note discloses hook shape and claude -p --settings <file> but not how the worktree was created or entered (claude -w / EnterWorktree versus a plain cd into a git worktree add directory). No fixture script exists under skills/worktree/ or scripts/.
Arm-by-arm status — carry this decomposition into any fix; do not weaken arms the dispute does not reach:
| Arm |
Status |
| "leak exists at all on 2.1.224" |
unreproduced on 2.1.227, undisclosed fixture |
"not specific to .claude/worktrees/" |
same status; the dot-vs-plain half is separately supported by the v2.1.69 changelog wording |
| "nested in an unrelated repo is worse" |
untested by anyone, not refuted — do not weaken |
| "lazy not eager" |
untested |
A self-correction from the audit that must survive: the counter-reproduction's session_start null was initially read as independent corroboration of the skill's suppression arm, and that was retracted — the null is equally consistent with an ordinary ancestor walk stopping at the worktree's own git root because the session was never recognized as a worktree session.
The doc-silence is confirmed and is load-bearing. https://code.claude.com/docs/en/worktrees, fetched 2026-08-11, documents the default .claude/worktrees/<name>/ placement, the three isolation checks, the non-suppressible EnterWorktree approval outside .claude/worktrees/, and what worktrees share with the main checkout (.git, project-scope plugins, permission approvals) — and says nothing about whether a nested worktree's session discovers the parent checkout's .claude/rules/. The claim is doc-unaddressed, not doc-contradicted, so measurement is the only adjudicator, which is what makes the undisclosed fixture fatal. The same page confirms the discriminator matters: "While a session is isolated in a worktree, whether you started it with --worktree, Claude entered one with EnterWorktree, or you resumed a worktree session…" — the harness's worktree-aware behavior attaches to a recognized worktree session, and a plain cd into a git worktree add directory is not obviously one.
Highest-leverage change in this cluster: downgrade the modality at :56/:58 to name the dispute, and record the fixture — creation mechanism, launch mode, exact paths: glob and its anchoring root, and whether the parent's rule file was committed — shipped as a script so a recheck is one command. That converts a recheck trigger into a recheck procedure.
Adjacent: #1971 (OPEN, "worktree: path-scoped rule inheritance in nested worktrees has no open upstream issue — decide whether to file one") — same claim, different question. Link them.
D-F6 — the reproduction parenthetical is contradicted by the docs
SKILL.md:58, inside the reproduction guidance:
reproduce by registering the hook with the `args`-array command shape ({"type":"command","command":"<bash>","args":["<script>"]} — the single-string form silently never fires) and passing it via `claude -p --settings <file>`
https://code.claude.com/docs/en/hooks, fetched 2026-08-11 — both forms documented, no event-specific carve-out. Exec form (args present): "Claude Code resolves command as an executable on PATH and spawns it directly with args as the argument vector. There is no shell…" Shell form (args absent): "The command string is passed to a shell: sh -c on macOS and Linux, Git Bash on Windows, or PowerShell when Git Bash isn't installed." The documented rule is narrower than the skill's: "Set args whenever the hook references a path placeholder, since each element is passed as one argument with no quoting." Corroborated at https://code.claude.com/docs/en/plugins-reference, fetched 2026-08-11: "In shell-form hooks and monitor commands, wrap the variables in double quotes."
This plugin's own hooks/hooks.json registers all three of its hooks in the single-string form — working counter-examples in the same repository. But note the narrowing that governs: the plugin-evidence leg corroborates rather than disposes, because the skill's claim concerns InstructionsLoaded supplied via --settings, a different event and channel. Add to the unverified list: whether the single-string form fires for an InstructionsLoaded hook supplied via claude -p --settings <file> — not probed by anyone. The likeliest true cause is a fixture-specific quoting/substitution failure generalized into a universal claim; the plugin already knows this failure mode from the other direction (CHANGELOG 0.46.x on CLAUDE_PLUGIN_OPTION_WORKTREE_ROOT versus ${user_config.worktree_root}, "which Claude Code rejects in shell-running fields").
Fix: replace the parenthetical with the documented constraint, cite the hooks page with a fetch date (as SKILL.md:34 already does for the worktrees page), and if the single-string failure was genuinely observed, record it as a fixture-specific observation with the exact string that failed.
Provenance
Severity: MED (cluster highest; D-F1 is LOW) · Provenance: AUDITOR_VERIFIED. Unconfirmed legs are named inline: the 2.1.224 changelog scan is packet-sourced and not re-run; whether the single-string form fires for InstructionsLoaded via --settings is unprobed by anyone.
Origin: handoff-inbox item 2026-08-10-plugin-quality-audit-four-components (packet nonce 20260811T023241Z)
Ledger: .work/handoff-inbox-batch-4/ledgers/I7-four-components-023241Z.md § "Lane D — source-control:worktree"
Verified against repo HEAD 685dd381. Audited at 0.51.6; anchors re-located at HEAD (0.51.7) by heading + quoted phrase.
skills/worktree/SKILL.mdcarries the measurement that justifies a machine-wide worktree-placement rule enforced by a fail-closed hook. Three defects sit in the two sentences that carry it: the version basis is attached to the wrong clause and has already been misread by two independent readers, the measurement records no fixture so nobody can adjudicate the counter-reproduction that disputes it, and the reproduction guidance contains a parenthetical that the current hooks docs contradict. A reader following that guidance will misdiagnose a null result — which is exactly the error that produced the disputed counter-reproduction in the first place.Rows
D-F1—plugins/source-control/skills/worktree/SKILL.md:58— "which 2.1.224 already handles correctly" reads as a version-fact but is a null result from the same trace; the "Basis:" clause sits several sentences earlier and attaches to the control-arm descriptions.D-F2—plugins/source-control/skills/worktree/SKILL.md:56,:58— the central leak arm is disputed, not refuted, and neither the measurement nor its counter-reproduction records the fixture, so it is not adjudicable.D-F6—plugins/source-control/skills/worktree/SKILL.md:58— "the single-string form silently never fires" is wrong as written; the hooks page documents both command forms with no event-specific carve-out.Evidence
D-F1 — the version basis attaches to the wrong clause
plugins/source-control/skills/worktree/SKILL.md:58, unchanged at HEAD:The only "Basis:" clause in that paragraph precedes the reproduction guidance, several sentences earlier. The reader-error is independently corroborated: a separate item's own "Loose ends" section makes exactly the same drift — "
source-control@0.51.6skills/worktree/SKILL.md:58states memory files are handled correctly 'as of 2.1.224'. The 2.1.224 changelog stanza carries no memory/worktree/rule line." That is a second careful reader making the version-fact reading, in a different item. The claim is probably true and is not refuted; the defect is attribution hygiene on a surface whose entire value is attribution hygiene. Fix by inlining the basis at the claim ("measured in the same trace — no release note covers this"). LOW.The changelog scan behind the null result (2.1.224's stanza has 32 entries and no memory/worktree/rule/instruction-loading line) is packet-sourced and was not re-run during verification.
D-F2 — the leak arm is disputed, and the fixture is missing
SKILL.md:56states the measurement — "measured on 2.1.224: … emits onepath_glob_matchnaming the parent checkout's rule file".:58states the placement-equivalence arm — "The leak is not specific to.claude/worktrees/: a worktree at a plain non-dot subdirectory leaks identically". The method note discloses hook shape andclaude -p --settings <file>but not how the worktree was created or entered (claude -w/EnterWorktreeversus a plaincdinto agit worktree adddirectory). No fixture script exists underskills/worktree/orscripts/.Arm-by-arm status — carry this decomposition into any fix; do not weaken arms the dispute does not reach:
.claude/worktrees/"A self-correction from the audit that must survive: the counter-reproduction's
session_startnull was initially read as independent corroboration of the skill's suppression arm, and that was retracted — the null is equally consistent with an ordinary ancestor walk stopping at the worktree's own git root because the session was never recognized as a worktree session.The doc-silence is confirmed and is load-bearing. https://code.claude.com/docs/en/worktrees, fetched 2026-08-11, documents the default
.claude/worktrees/<name>/placement, the three isolation checks, the non-suppressibleEnterWorktreeapproval outside.claude/worktrees/, and what worktrees share with the main checkout (.git, project-scope plugins, permission approvals) — and says nothing about whether a nested worktree's session discovers the parent checkout's.claude/rules/. The claim is doc-unaddressed, not doc-contradicted, so measurement is the only adjudicator, which is what makes the undisclosed fixture fatal. The same page confirms the discriminator matters: "While a session is isolated in a worktree, whether you started it with--worktree, Claude entered one withEnterWorktree, or you resumed a worktree session…" — the harness's worktree-aware behavior attaches to a recognized worktree session, and a plaincdinto agit worktree adddirectory is not obviously one.Highest-leverage change in this cluster: downgrade the modality at
:56/:58to name the dispute, and record the fixture — creation mechanism, launch mode, exactpaths:glob and its anchoring root, and whether the parent's rule file was committed — shipped as a script so a recheck is one command. That converts a recheck trigger into a recheck procedure.Adjacent: #1971 (OPEN, "worktree: path-scoped rule inheritance in nested worktrees has no open upstream issue — decide whether to file one") — same claim, different question. Link them.
D-F6 — the reproduction parenthetical is contradicted by the docs
SKILL.md:58, inside the reproduction guidance:https://code.claude.com/docs/en/hooks, fetched 2026-08-11 — both forms documented, no event-specific carve-out. Exec form (
argspresent): "Claude Code resolvescommandas an executable onPATHand spawns it directly withargsas the argument vector. There is no shell…" Shell form (argsabsent): "Thecommandstring is passed to a shell:sh -con macOS and Linux, Git Bash on Windows, or PowerShell when Git Bash isn't installed." The documented rule is narrower than the skill's: "Setargswhenever the hook references a path placeholder, since each element is passed as one argument with no quoting." Corroborated at https://code.claude.com/docs/en/plugins-reference, fetched 2026-08-11: "In shell-form hooks and monitor commands, wrap the variables in double quotes."This plugin's own
hooks/hooks.jsonregisters all three of its hooks in the single-string form — working counter-examples in the same repository. But note the narrowing that governs: the plugin-evidence leg corroborates rather than disposes, because the skill's claim concernsInstructionsLoadedsupplied via--settings, a different event and channel. Add to the unverified list: whether the single-string form fires for anInstructionsLoadedhook supplied viaclaude -p --settings <file>— not probed by anyone. The likeliest true cause is a fixture-specific quoting/substitution failure generalized into a universal claim; the plugin already knows this failure mode from the other direction (CHANGELOG 0.46.x onCLAUDE_PLUGIN_OPTION_WORKTREE_ROOTversus${user_config.worktree_root}, "which Claude Code rejects in shell-running fields").Fix: replace the parenthetical with the documented constraint, cite the hooks page with a fetch date (as
SKILL.md:34already does for the worktrees page), and if the single-string failure was genuinely observed, record it as a fixture-specific observation with the exact string that failed.Provenance
Severity: MED (cluster highest;
D-F1is LOW) · Provenance: AUDITOR_VERIFIED. Unconfirmed legs are named inline: the 2.1.224 changelog scan is packet-sourced and not re-run; whether the single-string form fires forInstructionsLoadedvia--settingsis unprobed by anyone.Origin: handoff-inbox item
2026-08-10-plugin-quality-audit-four-components(packet nonce20260811T023241Z)Ledger:
.work/handoff-inbox-batch-4/ledgers/I7-four-components-023241Z.md§ "Lane D —source-control:worktree"Verified against repo HEAD
685dd381. Audited at 0.51.6; anchors re-located at HEAD (0.51.7) by heading + quoted phrase.