Skip to content

fix(source-control): the nesting-invariant claim is restated undated at 13 sites, its recheck triggers cannot fire, and it asserts a sole ownership it no longer has #2213

Description

@kyle-sexton

skills/worktree/SKILL.md is held up across the fleet as the model of as-of discipline, and sibling audits recommend other surfaces point at it because of that discipline. The discipline covers exactly one paragraph. The same mechanism claim is restated as an undated absolute at 13 other sites; the one site that asserts freshness ("It is the live constraint, not a historical one") is the one with no date on that assertion, so a pointer lands the reader precisely there. Meanwhile both recheck triggers guarding the claim demonstrably did not fire and structurally could not, and the skill declares a sole canonical ownership that is no longer true, with no channel by which a consumer could tell it so.

Rows

  • I7 D-F3 — 13 sites, listed below (skills/worktree/SKILL.md:54, :106; .claude-plugin/plugin.json:183; README.md:310; skills/worktree/context/create.md:5, :43, :99; scripts/worktree-create.sh:23, :62, :309, :474, :520; hooks/worktree-create-gate.sh:9) — the mechanism claim is restated as an undated absolute at every one of them, against exactly two dated statements.
  • I7 D-F4plugins/source-control/skills/worktree/SKILL.md:58 — both recheck triggers verifiably did not fire and structurally could not; there is no expiry clause of any kind.
  • I7 D-F5plugins/source-control/skills/worktree/SKILL.md:54 — "no external prose doc" is a false bare absolute, and the skill states no back-channel by which a consumer files a contradicting measurement.

Evidence

D-F3 — the census, corrected to 13 at HEAD

git grep for the mechanism sentence and "parent/PARENT/ancestor/enclosing checkout", CHANGELOG excluded. The count is 13, not the 11 originally filed nor the 12 the packet's own addendum corrected it to — the packet's table omitted README.md. F3 is the one finding whose argument is the count, so ship 13.

# Site at HEAD Note
1 plugins/source-control/skills/worktree/SKILL.md:54 the freshness-asserting, undated one
2 skills/worktree/SKILL.md:106
3 .claude-plugin/plugin.json:183 worktree_root description (packet said :177)
4 README.md:310 not in the packet's table — the same description mirrored into the options table
5–7 skills/worktree/context/create.md:5, :43, :99
8–12 scripts/worktree-create.sh:23, :62, :309, :474, :520 header comment; --help; exit-3 "no usable root" heredoc; containment-guard rationale; exit-3 "placement rejected" heredoc
13 hooks/worktree-create-gate.sh:9

Against exactly two dated statements, both in SKILL.md: :56 ("measured on 2.1.224") and :58 ("As-of 2026-08-07", plus method, plus recheck trigger).

SKILL.md:54 verbatim:

… It is the live constraint, not a historical one: from a worktree nested inside a checkout, a read matching a path-scoped rule's glob also loads the parent checkout's copy of that rule.

Fix direction: pointers must cite SKILL.md § "The nesting invariant, verified" and restate the as-of at the pointer site; date or de-assert :54; reduce the other 12 to pointers (the plugin already did this once for create.md's dead issue citations, per CHANGELOG 0.46.x); add a repo test asserting the mechanism sentence appears at most once outside CHANGELOG.

D-F4 — the recheck triggers cannot fire

plugins/source-control/skills/worktree/SKILL.md:58:

"Recheck trigger: a Claude Code release note naming worktree rule-file loading or path-scoped rule resolution, or upstream anthropics/claude-code #16600 changing state."

No expiry clause of any kind. Both arms are dead:

  • Issue arm — re-verified independently on 2026-08-11. gh api repos/anthropics/claude-code/issues/16600{"state":"open","state_reason":null,"updated_at":"2026-04-24T08:11:47Z","title":"[FEATURE] Claude Code memory traversal should respect git worktree boundaries"} — unchanged since well before the skill's 2026-08-07 as-of date, so that trigger demonstrably has not fired.
  • Changelog arm — packet-sourced, not re-run. No 2.1.225–2.1.227 entry names rule-file loading; 2.1.226's entire stanza is "Bug fixes and reliability improvements." An event-keyed trigger cannot fire on an opaque stanza.

The trigger set is not merely unfired — it is structurally incapable of detecting this class of staleness, and it guards the plugin's most consequential claim.

Fix, and the most propagable output of this whole audit: add an unconditional expiry alongside the event trigger, stating the measured-on version so the arithmetic is doable ("measured on 2.1.224; expires at 2.1.244 or 2026-11-07"), and adopt the pair (event trigger + unconditional version/time expiry) as a fleet-wide convention for any measured harness-behavior claim.

Adjacent: #1971 (OPEN) — same upstream-coverage question.

D-F5 — the SSOT inversion

plugins/source-control/skills/worktree/SKILL.md:54:

This skill is the canonical owner of the parallel-session worktree convention going forward — no external prose doc.

The clause is a bare absolute and it is false: a consumer doc now defers mechanism to this skill and is more current than it (2026-08-10 vs 2026-08-07) while contradicting :54. Canonical ownership with no inbound back-channel makes the owner the last to know.

Scope correction the fix must observe. The contradicting consumer is a machine-local file in the operator's home directory, not a file in this repository, and it was deliberately not read (outside the working domain). Do not scope a fix that requires editing the consumer. Exactly two things are fixable here: the false "no external prose doc" clause, and the missing back-channel by which a consumer files a contradicting measurement.

Interacts with the sibling cluster: landing that cluster's modality downgrade at :56/:58 is what stops the two surfaces contradicting, and a pointer that restates the owner's as-of (D-F3) makes an inversion visible at the pointer site.

What must NOT be refactored away while fixing this

The five-element as-of discipline this skill already has is the reason it is held up as a model, and it should be propagated as a set, not thinned: P1 a named instrument with a stated reason; P2 arm decomposition (which is why the disputed claim can be scoped rather than declared total); P3 dead citations retired by name with closure reasons; P4 volunteered gaps; P5 a repo-wide dating habit. The two elements it is missing are a recorded fixture (sibling cluster) and an unconditional expiry (D-F4 above).

Provenance

Severity: MED · Provenance: AUDITOR_VERIFIED — the #16600 arm of D-F4 was independently re-verified via gh api on 2026-08-11; the changelog arm is packet-sourced and was not re-run.
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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions