Skip to content

fix(session-flow,discipline): drop the per-session subagent cap that no longer exists, and record the doc-currency audit - #2169

Merged
kyle-sexton merged 5 commits into
mainfrom
chore/gate-doc-currency-audit
Aug 10, 2026
Merged

fix(session-flow,discipline): drop the per-session subagent cap that no longer exists, and record the doc-currency audit#2169
kyle-sexton merged 5 commits into
mainfrom
chore/gate-doc-currency-audit

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

No linked issue

Summary

Pass (a) of a doc-currency audit on this repo's gates and check skills: do the claims they make about
how Claude Code behaves still match code.claude.com/docs? One real drift found and fixed at three
sites; every other outcome graduated to a tracked issue (see Related) rather than to a document that
would outlive its task branch.

Pass (b) — whether the enforced doctrine is still best practice — is deliberately not attempted.

Fix

The per-session subagent cap no longer exists, and three sites planned around it.

plugins/session-flow/skills/orchestrate/context/sources.md, .../orchestrate/SKILL.md, and
plugins/discipline/skills/sweep-all/SKILL.md all recorded "at most 200 subagents per session"
(CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION, v2.1.212+), read from the sub-agents page on 2026-07-29.

Current: "The 200-subagent-per-session cap is removed, so long-running sessions no longer refuse new
subagents; the concurrency and depth limits still apply"
(2026-w32,
v2.1.220–v2.1.224). Both the cap and its variable are gone from the reference page, which now carries
only the concurrency limit and the depth limit.

sources.md keeps the old claim as an explicit Superseded note rather than deleting it, so a
reader who remembers the cap finds out what replaced it instead of finding silence. Two riders picked
up on the same re-read: ultracode sessions are exempt from the concurrency limit, and an in-session
/subtask fork takes a slot while it runs but is never blocked by it.

session-flow 0.22.1 → 0.22.2, discipline 0.12.0 → 0.12.1.

Verification

Method rule, because getting this wrong is worse than not looking. Each page was asked to state
its own current rule, never to confirm or deny a sentence from this repo. A fetch summarizes
through a small model, so "the page doesn't mention X" is a routine false negative — and a false
negative read as drift means editing correct doctrine on the strength of a lossy read. No verbatim
quote, no drift classification; anything without one is recorded unverifiable.

Verified current, by quote:

Claim Load-bearing where
"Each subagent starts with a fresh, isolated context window… The exception is a fork, which inherits the parent conversation instead of starting fresh." The entire fresh-eyes checkpoint rule (PLUGIN-PHILOSOPHY.md :565, :613)
Agent model: sonnet/opus/haiku/fable/full ID/inherit, "Defaults to inherit" Model tiers (:647)
Agent effort: lowmax, "Default: inherits from session" Effort tiers
name optional, "Defaults to the directory name" Naming; check-skill-leaf-names.sh derives every leaf from the directory
"The bare /fancy also invokes the skill unless another command already uses that name." Naming's bare-alias rule
"Before v2.1.216, the frontmatter name replaced the whole command name…" Naming's own history note
disable-model-invocation default false; user-invocable default true The setup contract in validate-plugin-contracts.mjs

Gates run in CI form against the committed tree: check-skill-portability.sh origin/main clean
(3 skill files), markdownlint-cli2 0 errors across 57 files.

Claim inventory: ~260 dated stamps spanning 2026-07-15 → 2026-08-08, citing 73 distinct doc pages.

Related

The audit's other outcomes were graduated to tracked issues and the topic slice pruned, per the
topic-docs Contract-tier rule that contract-slice-prune-gate enforces — a findings document merged
into docs/topics/ would have been exactly the orphaned artifact that tier exists to prevent:

Method note carried into #2176 rather than lost: two local gate runs passed vacuously during #2161
(--paths over a hand-filtered list; --check-bump before anything was committed). Run gates the way
CI runs them — base-ref form, against a committed tree.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FdBsorqGjCU4Mg5nrmgz4m

…no longer exists, and record the doc-currency audit

Pass (a) of the gate / check-skill doc-currency audit: do the claims this repo's
gates and check skills make about how Claude Code behaves still match the docs?

Method rule, because getting it wrong is worse than not looking: each page was asked
to state its OWN current rule, never to confirm a sentence from this repo. A fetch
summarizes through a small model, so "not mentioned" is a routine false negative, and
a false negative read as drift means editing correct doctrine. No verbatim quote, no
drift classification.

VERIFIED CURRENT, by quote -- including the highest-blast-radius claim in the repo,
the subagent-vs-fork context isolation the entire fresh-eyes checkpoint rule rests on:
"Each subagent starts with a fresh, isolated context window... The exception is a fork,
which inherits the parent conversation instead of starting fresh." Also confirmed: the
agent `model`/`effort` value sets and their `inherit` defaults, frontmatter `name`
optional and defaulting to the directory, the bare-alias registration, the v2.1.216
command-name history, and the `disable-model-invocation`/`user-invocable` defaults.

DRIFTED, fixed here: three sites recorded "at most 200 subagents per session"
(`CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION`, v2.1.212+) as a live constraint, read
2026-07-29. It was removed in v2.1.220-v2.1.224 -- "The 200-subagent-per-session cap
is removed, so long-running sessions no longer refuse new subagents; the concurrency
and depth limits still apply" -- and both cap and variable are gone from the sub-agents
page. session-flow's orchestrate sources and SKILL, and discipline's sweep-all budget
paragraph, were all planning against a ceiling that is not there. sources.md keeps it
as an explicit Superseded note rather than deleting it, so a reader who remembers the
cap learns what replaced it. Picked up on the same re-read: ultracode sessions are
exempt from the concurrency limit, and a `/subtask` fork takes a slot but is never
blocked by it.

The larger finding is not drift at all, and is recorded in FINDINGS.md rather than
acted on: the docs index lists 112 core pages and this repo cites 73. Among the
uncited are cross-session-messaging, agent-teams, agents, feature-availability,
sessions, and checkpointing -- a platform surface the doctrine has never evaluated
under its own Native-first adoption gate. The Delegation-mechanics dispatch ladder is
most affected: it runs generic subagent -> named agent -> cross-vendor advisor and
does not know agent teams or background sessions exist.

FINDINGS.md also records the week-32 changes that postdate most stamps and need their
own decisions (zip-archive marketplace source, auto mode becoming the default on
Aug 14, worktree isolation extending to Bash and git redirects, PreToolUse hooks no
longer bypassing restrictions in internal side tasks), a usability defect in
check-skill.sh's internal-ref extractor found by using it, and a method note about two
local gate invocations that passed vacuously during #2161.
@cursor

cursor Bot commented Aug 10, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 35s —— View job


Security Review — PR #2169

  • Gather context (diff, changed files)
  • Review each changed file for security issues
  • Report findings

Scope reviewed: git diff origin/main...HEAD (8 files, all changed files read in full).

Findings: none.

This PR is a documentation-currency fix with no executable surface:

  • 6 of 8 changed files are Markdown prose (FINDINGS.md, two CHANGELOG.mds, two SKILL.mds, sources.md) — corrected claims about a Claude Code subagent cap and citations to code.claude.com/docs. No scripts, commands, or templated content that executes.
  • The 2 plugin.json changes are version-string bumps only (0.12.00.12.1, 0.22.10.22.2); the long description fields are unchanged (context lines in the diff, not modified).
  • No GitHub Actions workflow files, hook scripts, .mcp.json entries, or ${CLAUDE_PLUGIN_ROOT}/path-handling code are touched.
  • No secrets, tokens, credentials, or external URLs beyond documentation links (code.claude.com/docs/...) are introduced.
  • No authorization, access-control, injection, or supply-chain surface is present in this diff.

Nothing here warrants a CRITICAL/IMPORTANT/SUGGESTION finding.

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 3m 9s —— View job


Review complete

  • Gather context (diff, changed files, CLAUDE.md/AGENTS.md, REVIEW.md)
  • Review docs/topics/gate-doc-currency/FINDINGS.md
  • Review plugins/discipline/skills/sweep-all/SKILL.md + plugin.json + CHANGELOG
  • Review plugins/session-flow/skills/orchestrate/SKILL.md + context/sources.md + plugin.json + CHANGELOG
  • Check version bumps and changelog consistency
  • Post findings

Summary

This is a doc-currency fix: it removes claims of a per-session subagent cap
(CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) from three sites, since the platform removed that cap in
v2.1.220–v2.1.224.

Independently verified (WebFetch against code.claude.com/docs/en/sub-agents and
.../whats-new/2026-w32 this session, not the author's claimed verification) — every material
factual claim in this PR checks out verbatim:

  • The sub-agents page now states: "There's no limit on the total number of subagents Claude can
    spawn over a session"
    — confirms the cap is gone.
  • "The 200-subagent-per-session cap is removed, so long-running sessions no longer refuse new
    subagents; the concurrency and depth limits still apply"
    — matches the PR's central quote exactly.
  • Both new riders are exact matches to current doc text: "Sessions with ultracode active are
    exempt: the limit isn't enforced there"
    and "An in-session fork you start with /subtask takes
    a slot while it runs and is never blocked by the limit."
  • Every bullet in FINDINGS.md's "Week-32 changes" section (zip-archive marketplace source, auto mode
    becoming default Aug 14, worktree isolation extending to Bash/git redirects, PreToolUse auto-allow
    hook scoping, /fork worktree change, /plugin activation, Ultraplan removal, /review alias)
    matches the current 2026-w32 page verbatim.

Mechanical checks:

  • discipline 0.12.0 → 0.12.1 and session-flow 0.22.1 → 0.22.2 version bumps in plugin.json
    both match their respective CHANGELOG.md top entries.
  • The sources.md continuation-line indentation for the new "Two caps now, not three" / "Superseded"
    paragraphs is consistent (2-space, matching the existing list style in that file).

Not independently run: check-skill-portability.sh and markdownlint-cli2, which the PR body
claims were run clean — this environment's Bash tool required interactive approval I couldn't obtain
for script execution, so I could not confirm those gate results myself. Treat the PR's own "gates run
in CI form" claim as author-reported, not independently confirmed by this review.

Findings

One 🟡 nit posted inline: plugins/discipline/CHANGELOG.md:19
— "the second constraint was fictional" slightly overstates it; the constraint was real when
written and became stale after removal, not fabricated. Purely a wording nit, doesn't affect
correctness of the fix.

No other correctness, architecture, error-handling, or maintainability issues found. This is a
tightly-scoped, well-sourced fix — the "Superseded" note pattern in sources.md (keeping the old
claim visible with what replaced it, rather than silently deleting) is good practice for a doc a
future reader might return to with the old fact in mind.

Comment thread plugins/discipline/CHANGELOG.md Outdated
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

Claude has reviewed this PR 5 times. The lane skips further automatic reviews after 5; deleting this comment resets the count.

…ntract-tier slice

contract-slice-prune-gate was right to fail this: docs/topics/<slug>/ is Contract tier
per the topic-docs convention -- committed on a task branch only, pruned before merge,
with durable outcomes graduated to an ADR, spec, or tracker item first. FINDINGS.md was
staged to merge as a permanent document, which is exactly the orphaned-artifact outcome
the tier exists to prevent.

Graduated to issues, then the slice deleted:

- #2173 check-skill.sh resolves a cross-skill reference against the citing skill's own
  directory and the error names the wrong place. Found by using the gate; hit twice in
  #2161.
- #2174 verification:measure description has no "Use when:" trigger phrasing. Pre-existing,
  carried as a footnote on two unrelated PRs; filed so it stops travelling.
- #2175 Run the Native-first adoption gate against the six platform surfaces the doctrine
  has never evaluated (cross-session-messaging, agent-teams, agents, feature-availability,
  sessions, checkpointing). Not drift -- the question has simply never been asked, and
  Native-first already owns the procedure for asking it.
- #2176 Decide the week-32 platform changes, with the Aug 14 auto-mode default as the
  time-sensitive one.

The verified-current results and the method rule that produced them are preserved in this
PR's own body and commit history rather than in a file that would outlive its task branch.

Also takes the review nit on the discipline changelog: "the second constraint was
fictional" implied the cap was never real. It was accurate when written (documented
default 200, v2.1.212+) and went stale under the platform -- which is the failure mode a
dated verification stamp exists to make findable, and worth saying precisely in a change
whose whole subject is doc currency.
@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 57s —— View job


Security Review — PR #2169

  • Gather context (diff, changed files)
  • Review each changed file for security issues
  • Report findings

Scope reviewed: gh pr diff 2169 (7 files, full diff read — no truncation).

Findings: none.

This PR is a pure documentation-currency fix with no executable or trust-boundary surface:

  • 5 Markdown files (FINDINGS.md is not part of this diff — it was pruned in the second commit; the remaining prose files are two SKILL.mds, two CHANGELOG.mds, and sources.md) — correct a stale claim about a removed Claude Code subagent cap (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) and cite code.claude.com/docs URLs. No shell snippets, no templated/interpolated content, nothing a hook or CI step would execute.
  • 2 plugin.json changes are version-string bumps only (discipline 0.12.0→0.12.1, session-flow 0.22.1→0.22.2); the large description fields are unchanged.
  • No GitHub Actions workflow files, hook scripts (.claude/hooks/*), .mcp.json entries, or ${CLAUDE_PLUGIN_ROOT}/path-handling code are touched.
  • No secrets, tokens, or credentials introduced; the only URLs added are documentation links to code.claude.com/docs/..., not user-controlled or fetched-and-executed content.
  • No authorization/access-control, injection (command/SQL/path/template), or supply-chain surface (no dependency or action-pin changes) present in this diff.

Nothing here rises to CRITICAL/IMPORTANT/SUGGENTION — this lane has nothing to flag on a docs-only change.

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 6m 10s —— View job


Review complete

  • Gather context (gh pr diff 2169, changed files, CLAUDE.md/AGENTS.md, REVIEW.md's code-review-lane scope)
  • Review each changed file for correctness and maintainability
  • Check version bump / changelog consistency
  • Post inline findings
  • Post summary

Summary

This is the doc-currency fix removing a per-session subagent cap
(CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) that the platform removed in v2.1.220–v2.1.224, across
three sites. I re-fetched code.claude.com/docs/en/sub-agents fresh this session (full page, not
truncated) and it corroborates the PR's central claims verbatim: "Two limits control subagent use,
each with its own variable... There's no limit on the total number of subagents Claude can spawn
over a session," plus exact matches for both new riders (ultracode exemption, /subtask fork
taking a slot without being blocked). No prior "three caps" wording survives anywhere in the three
edited files — grepped clean.

I also confirmed the earlier reviewer's nit (plugins/discipline/CHANGELOG.md:19, "the second
constraint was fictional") was already resolved by the second commit (6eafedc) before this pass —
it now reads "the second constraint has since been removed... It was accurate when written... and
went stale under the platform," which is the precise wording the earlier review asked for. No
action needed there.

Findings (posted inline)

  • 🟡 plugins/discipline/skills/sweep-all/SKILL.md:234
    the citation swap (env-varswhats-new/2026-w32) may leave the paragraph's
    CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY claim uncited. Confirmed absent from the current
    sub-agents page; couldn't confirm either way on env-vars (that fetch truncated before its
    alphabetical range). Worth restoring alongside the new link rather than replacing it, or
    re-verifying the var moved too.
  • 🟡 plugins/session-flow/skills/orchestrate/SKILL.md:158
    minor clarity nit on "which is itself the point this paragraph makes" (ambiguous antecedent).

Not independently run

check-skill-portability.sh and markdownlint-cli2 — the PR body's "gates run in CI form... clean"
claim is author-reported, not verified by this review; this environment's Bash tool required
interactive approval for script execution that I couldn't obtain. Version bumps
(discipline 0.12.0→0.12.1, session-flow 0.22.1→0.22.2) do match their respective
CHANGELOG.md top entries — that I did check directly.

No other correctness, architecture, or maintainability issues found. Security is out of scope for
this lane (the repo has a dedicated security-review workflow, which already ran clean on this PR).
· branch

Comment thread plugins/discipline/skills/sweep-all/SKILL.md Outdated
Comment thread plugins/session-flow/skills/orchestrate/SKILL.md Outdated
… what "the point" is

Two review nits, one substantive.

The citation swap in sweep-all replaced the env-vars link with whats-new/2026-w32,
but env-vars was what sourced the paragraph's FIRST claim --
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY, documented default 10 -- which the new link does
not cover. A re-source for one claim silently unsourced another. Link restored.

I could not re-verify that variable, and am saying so in place rather than letting it
read as freshly checked. Two independent re-fetches of env-vars truncated before its
alphabetical range, and the sub-agents page's concurrency section names only the
concurrency and depth limits. That is NOT evidence of removal: the same truncated fetch
returned ABSENT for CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS, which is quoted verbatim on
the sub-agents page -- so ABSENT means "not in the excerpt", not "not in the docs".
Calling it removed on that evidence is the false-negative-read-as-drift failure this
audit's own method rule exists to prevent, and it would have edited a correct claim.
The variable is marked carried-forward-and-unverified at the site, and tracked as an
open item on #2176 rather than left to look current.

The orchestrate nit: "which is itself the point this paragraph makes" had no clear
antecedent. Named directly -- a third cap moved out from under that list after it was
written, which is the reason to read current values rather than assume them.
@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 49s —— View job


Security Review — PR #2169

  • Gather context (gh pr diff 2169, changed files)
  • Review each changed file for security issues
  • Report findings

Scope reviewed: gh pr diff 2169 (7 files, full diff read — no truncation), against HEAD 6c39519.

Findings: none.

This PR is a pure documentation-currency fix with no executable or trust-boundary surface:

  • 5 Markdown files (two SKILL.mds, two CHANGELOG.mds, sources.md) correct a stale claim
    about a removed Claude Code subagent cap (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) and cite
    code.claude.com/docs URLs. No shell snippets, no templated/interpolated content, no instructions
    embedded in the prose that could function as a prompt injection against a future session reading
    these skill files — the added text is straightforward factual/citation content, not directive
    language aimed at an agent.
  • 2 plugin.json changes are version-string bumps only (discipline 0.12.0→0.12.1,
    session-flow 0.22.1→0.22.2); the large description fields and all other manifest fields are
    unchanged.
  • No GitHub Actions workflow files, hook scripts (.claude/hooks/*), .mcp.json entries, or
    ${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA} path-handling code are touched.
  • No secrets, tokens, or credentials introduced; the only URLs added are documentation links to
    code.claude.com/docs/..., not user-controlled input or fetched-and-executed content.
  • No authorization/access-control, injection (command/SQL/path/template), or supply-chain surface
    (no dependency, action pin, or lockfile changes) present in this diff.

Nothing here rises to CRITICAL/IMPORTANT/SUGGESTION — this lane has nothing to flag on a docs-only
PR. (Consistent with the three prior automated security-review passes on this PR, each independently
reaching the same conclusion.)
· branch

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 6s —— View job


Code Review — PR #2169

  • Gather context (gh pr diff 2169, changed files, CLAUDE.md/AGENTS.md)
  • Review each changed file for correctness/maintainability
  • Check version bump / changelog consistency
  • Post inline findings
  • Post summary

Summary

This review covers the state as of the latest commit (6c39519), which responds to the two nits
from the prior review rounds. I read both the cumulative diff and commit 6c39519 in isolation to
verify the fixes:

  • Citation restore (plugins/discipline/skills/sweep-all/SKILL.md:233-238): the env-vars link
    is back alongside the new whats-new/2026-w32 link, and the CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
    claim is now explicitly marked "carried forward from the 2026-07-29 read and NOT re-verified"
    rather than silently re-sourced by a link that doesn't cover it. This is the right fix — it avoids
    claiming verification the author didn't have, consistent with the PR's own method rule about
    false-negative reads.
  • Ambiguous antecedent (plugins/session-flow/skills/orchestrate/SKILL.md:158-160): "which is
    itself the point this paragraph makes" was replaced with an explicit statement of what moved and
    why. Resolves the ambiguity, though see the new nit below.

Both prior plugins/discipline/CHANGELOG.md:19 wording fixes ("fictional" → "since been removed")
were already in place before this round and read correctly.

New findings (posted inline)

  • 🟡 plugins/session-flow/skills/orchestrate/SKILL.md:154-160
    the antecedent fix restates the same fact ("per-session spawn total was removed" / "a third cap
    moved out from under this list") twice in one sentence. Pure wording tighten, not a correctness
    issue.
  • 🟡 plugins/discipline/CHANGELOG.md:12-21
    the 0.12.1 entry predates the follow-up commit and doesn't mention the env-vars citation
    restore or the now-open CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY verification gap, since the version
    wasn't bumped again for that commit. Minor completeness gap in the durable record of what shipped.

Mechanical checks

  • discipline 0.12.0 → 0.12.1 and session-flow 0.22.1 → 0.22.2 version bumps in plugin.json
    match their respective CHANGELOG.md top entries.
  • Grepped all three edited sites (sources.md, both SKILL.mds) for the old "three separate
    caps" / "200 subagents per session" wording — none survives outside the explicit Superseded
    note in sources.md, which is intentional.
  • No other correctness, architecture, or maintainability issues found in this pass.

Not independently run

check-skill-portability.sh and markdownlint-cli2 — this environment's Bash tool required
interactive approval for script execution that I couldn't obtain, so the PR body's "gates run in
CI form... clean" claim is author-reported and not independently confirmed by this review.
· branch

Comment thread plugins/session-flow/skills/orchestrate/SKILL.md Outdated
Comment thread plugins/discipline/CHANGELOG.md
…the citation restore in the changelog

Two review nits, both right.

The orchestrate sentence stated the same removal twice -- once as "the per-session
spawn total was removed" and again a clause later as "a third cap moved out from under
this list" -- which reads as two events rather than one restated. The second clause was
introduced fixing the previous round's ambiguous-antecedent nit and overshot. Dropped;
the preceding sentence already carries the fact, and "read the current values rather
than assuming them" is the point that needed to survive.

The discipline 0.12.1 entry was silent on what the follow-up commit actually shipped.
Since no second bump was taken, that entry is the only durable record of why the
sweep-all citation reads the way it does -- the env-vars link restored, and
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY marked carried-forward-and-not-re-verified with
its currency open rather than disproven. Now recorded there, so the changelog matches
what shipped under that version.
@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 31s —— View job


Security Review — PR #2169

  • Gather context (gh pr diff 2169, changed files)
  • Review each changed file for security issues
  • Report findings

Scope reviewed: gh pr diff 2169 (7 files, full diff read — no truncation), at HEAD 6c0ac200.

Findings: none.

This PR is a pure documentation-currency fix with no executable or trust-boundary surface:

  • 5 Markdown files (two SKILL.mds, two CHANGELOG.mds, sources.md) correct a stale claim about a removed Claude Code subagent cap (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) and cite code.claude.com/docs URLs. No shell snippets, no templated/interpolated content, and no directive language embedded in the prose that could function as a prompt injection against a future session reading these skill files — the added text is factual/citation content, not instructions aimed at an agent.
  • 2 plugin.json changes are version-string bumps only (discipline 0.12.0→0.12.1, session-flow 0.22.1→0.22.2); the large description fields and all other manifest fields are unchanged.
  • No GitHub Actions workflow files, hook scripts (.claude/hooks/*), .mcp.json entries, or ${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA} path-handling code are touched.
  • No secrets, tokens, or credentials introduced; the only URLs added are documentation links to code.claude.com/docs/..., not user-controlled input or fetched-and-executed content.
  • No authorization/access-control, injection (command/SQL/path/template), or supply-chain surface (no dependency, action pin, or lockfile changes) present in this diff.

Nothing here rises to CRITICAL/IMPORTANT/SUGGESTION — this lane has nothing to flag on a docs-only PR. Consistent with the four prior automated security-review passes on earlier commits of this PR, each independently reaching the same conclusion.
· branch

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 2m 58s —— View job


Code Review — PR #2169

  • Gather context (gh pr diff 2169, latest commit diff, CLAUDE.md/AGENTS.md, prior review threads)
  • Review latest commit (6c0ac20) against the two nits raised in the last review round
  • Review all changed files for correctness/maintainability
  • Check version bump / changelog consistency
  • Post inline findings
  • Post summary

Summary

Reviewed the current HEAD (6c0ac20) against origin/main. This is the follow-up commit responding
to the last review round's two nits ("restated removal" wording, missing changelog entry for the
citation-restore commit). I diffed 6c39519..6c0ac20 in isolation to verify exactly what changed:

  • plugins/session-flow/skills/orchestrate/SKILL.md: dropped the redundant trailing clause
    ("— a third cap moved out from under this list after it was written, which is the reason to read
    the current values rather than assume them. Read them, and") down to a single clean sentence
    ("Read the current values rather than assuming them, and"). Resolves the restated-fact nit.
  • plugins/discipline/CHANGELOG.md: added a second bullet under the still-unreleased [0.12.1]
    entry documenting the env-vars citation restore and the CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY
    carried-forward/not-re-verified marking. Since plugin.json wasn't bumped again for the follow-up
    commit, amending the same pre-merge changelog entry (rather than adding a new version) is the
    correct move — nothing has been tagged/released yet.

New finding (posted inline)

  • 🟡 plugins/session-flow/skills/orchestrate/SKILL.md:154-158
    "The ceiling moved again after that list was written" reuses "the ceiling" (scoped by the same
    paragraph's opening sentence to the depth default specifically) to describe the removal of an
    entirely different, separate cap (the per-session spawn total). The depth ceiling didn't move
    again — a different cap disappeared. This phrasing predates this commit (introduced in 6c39519,
    untouched by 6c0ac20's trim), but it's live on HEAD and in the same spirit as the antecedent nits
    from the last two rounds, so flagging it now. Wording-only, not a correctness-of-fact issue with
    the underlying claim.

Mechanical checks

  • discipline 0.12.0 → 0.12.1 and session-flow 0.22.1 → 0.22.2 version bumps in plugin.json
    still match their respective CHANGELOG.md top entries.
  • Grepped all three edited sites for the old "three separate caps" / "200 subagents per session"
    wording — none survives outside the intentional Superseded note in sources.md.
  • No other correctness, architecture, or maintainability issues found in this pass.

Not independently run

check-skill-portability.sh origin/main and markdownlint-cli2 both required interactive approval
this environment didn't grant (git fetch, bash scripts/check-skill-portability.sh, and npx markdownlint-cli2 all prompted for approval I couldn't satisfy), so the PR body's "gates run in CI
form... clean" claim remains author-reported, not independently confirmed by this review — consistent
with every prior review round on this PR.
· branch

Comment thread plugins/session-flow/skills/orchestrate/SKILL.md Outdated
kyle-sexton added a commit that referenced this pull request Aug 10, 2026
…aluated platform surfaces (#2177)

Closes #2175

## Summary

The docs index lists 112 core `/docs/en/` pages; this repository cited
73. Six of the uncited ones
are platform surfaces the doctrine had never evaluated, and its own
Native-first adoption gate had
never been run against any of them. Nothing in the repo was *wrong*
about them — the doctrine simply
predates them — but the **dispatch ladder** was handing an author a menu
of delegation mechanisms
that predated three of the platform's options, and the **cross-platform
contract** never named its
canonical availability input.

This runs the gate against all six and records a verdict for each.

## Fix

Verdicts, each recorded in `docs/PLUGIN-PHILOSOPHY.md` under
Native-first → **Recorded gate runs**,
in the
[upstream-drift](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/upstream-drift/README.md)
four-part shape (claim, basis, as-of date, recheck trigger):

| Surface | Verdict | Reason | Recheck trigger |
|---|---|---|---|
| [`agents`](https://code.claude.com/docs/en/agents) | **Adopt**, as a
citation | The upstream comparison of every way Claude Code runs
multiple agents. Becomes the dispatch ladder's canonical index — cited,
never restated, so the menu cannot go stale inside this file. | The page
adds or drops a parallelism surface. |
|
[`feature-availability`](https://code.claude.com/docs/en/feature-availability)
| **Adopt**, as a citation | Named as the cross-platform contract's
canonical input. Deliberately *not* copied: "Evidence and validation"
bars restating a volatile provider matrix. | A plugin proposes narrowing
its platform support. |
| [`agent-teams`](https://code.claude.com/docs/en/agent-teams) |
**Defer** | Fails gate 2 and stops there — "Agent teams are experimental
and disabled by default", gated behind
`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`, with limitations the page
states outright ("No nested teams: teammates cannot spawn their own
teammates"; `/resume` and `/rewind` do not restore in-process
teammates). Defer rather than decline: the gap question stays open while
the surface is opt-in and churning, and no plugin may depend on a team
meanwhile. | The page drops the experimental warning or the env-var
requirement. |
|
[`cross-session-messaging`](https://code.claude.com/docs/en/cross-session-messaging)
| **Decline** | Fails gate 1 — the page directs it at "independent
sessions that you start and steer yourself", not at skill dispatch.
Could not be a portable rung either: "Claude Code doesn't offer
cross-session messaging on native Windows" (this repo's primary dev
machine), plus absent on Bedrock, Claude Platform on AWS, Google Cloud's
Agent Platform, and Microsoft Foundry. | The availability section stops
excluding native Windows. |
| [`sessions`](https://code.claude.com/docs/en/sessions) | **Decline** |
Fails gate 1. Resume restores "the full history, including tool calls
and results" — precisely the authoring story the inline-template
conventions exist to withhold. It is the *opposite* of a fresh-eyes
rung, not a missing one. | `sessions` grows a plugin-facing seam. |
| [`checkpointing`](https://code.claude.com/docs/en/checkpointing) |
**Decline** | Nothing to adopt, and the reason is the outcome:
"Checkpointing does not track files modified by bash commands", and for
any subagent other than a foreground forked skill, "rewinding doesn't
restore the edits. Use git to revert them." The restored carve-out is
narrow (a foreground `context: fork` skill), so a skill mutating through
a shell script or a background worker states a git-based rollback and
never leans on `/rewind`. | The limitations section drops either
exclusion. |

Two adopts land doctrine text, kept to a pointer each:

- **Dispatch ladder** gains one paragraph naming `agents` as the
canonical upstream comparison and
pointing at the gate-run table for why the subagent rung is taken today.
- **Cross-platform contract** gains one paragraph naming
`feature-availability` as its canonical
input, plus the ruling this run forced: a capability the platform does
not ship on a supported OS
is the *platform's* gap, never the "narrower, inherent platform
boundary" a plugin may declare —
  the plugin still owes a portable path.

No `docs/topics/<slug>/` directory was created; the durable outcome
lives in the doctrine text, as
the Contract-tier prune rule requires.

Review rounds added three more edits, each closing a real gap a reviewer
found (all four threads
answered and resolved):

- `docs/OFFICIAL-DOCS.md` gains all six pages in its **Authoring**
table. They had become
load-bearing citations while appearing nowhere in the index whose own
warning says a needed page
  that is not listed must be added.
- `docs/conventions/upstream-drift/README.md`'s **Adopters** registry
gains a row for the gate-run
table. It is the registry's first *recorded-decision* entry carrying
per-row triggers rather than
the divergence-at-fetch trigger its sibling tables share, so the row
says so — otherwise a reader
arriving from the component-stances row carries the wrong firing rule
across. Recorded as
**1.1.0** in that convention's own `CHANGELOG.md` (additive guidance
under its stated SemVer rule).
- The cross-session-messaging recheck trigger watched only the
native-Windows premise, though the
row also rests on the channel's stated purpose and on four provider
exclusions. It now names all
  three, so the row cannot go stale with nothing firing.

## Verification

Method: each of the six pages was fetched in full and asked to state its
*own* rules — never asked
to confirm or deny a sentence from this repo. Every upstream fact quoted
above is verbatim from
those fetches. **All six fetches returned complete pages; none
truncated**, so no row rests on a
"not mentioned" inference.

The two *in-repo* claims a row leaned on were checked against the tree
rather than asserted, and
one was wrong (fixed in 4b3539a):

- `grep -rn "context: fork" plugins/` — no shipped skill declares it in
frontmatter, so the
checkpointing carve-out is correctly described as narrow. The first
draft also called the two
documented exclusions "this fleet's two mutation paths"; that was false
— `discipline`'s
`sweep-all` applies its corrections on the main thread, which rewind
*does* cover — so the row
  now states only the rule the page actually supports.
- The first draft's agent-teams row claimed "no fleet skill needs
inter-worker discussion".
`session-flow`'s `orchestrate` already names agent teams as a surface
the main session may reach
(`SKILL.md:94`), so that census was wrong and would have contradicted a
shipped skill. The row
  now rests on gate 2 alone, which is sufficient and verbatim.

Gates run the CI way, against the committed tree, base-ref form:

```
bash scripts/check-contract-slice-prune.sh --check-diff origin/main   # pass — leaves no path under docs/topics/
bash scripts/check-changed-skills.sh origin/main                      # pass — no changed skills
bash scripts/check-changelog-parity.sh --check-bump origin/main       # pass
bash scripts/check-skill-portability.sh origin/main                   # pass — no skill files in scope
npx --yes markdownlint-cli2 "docs/PLUGIN-PHILOSOPHY.md"               # 0 errors
```

Docs-only diff, so no *plugin* version bump is owed. The one versioned
surface touched — the
`upstream-drift` convention — carries its own `CHANGELOG.md` entry
(1.1.0). LF endings confirmed
clean; `markdownlint-cli2` re-run clean over all four changed files.

## Related

- Closes #2175
- Source: gate doc-currency audit, PR #2169 — graduated from that PR's
findings slice per the
  topic-docs Contract-tier prune rule.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…rent cap disappeared

Review nit, and a real one. The paragraph opens by scoping "the platform ceiling" to
DEPTH -- five layers, then nesting off, then a configurable default of three -- and its
own heading is "needs a specific depth". Reusing "the ceiling moved again" for the
per-session spawn total blurred two distinct caps into one, and read as "the depth
default changed a fourth time", which is not what happened: depth is still where
v2.1.219 left it.

A paragraph whose whole job is "do not assume a fixed value" cannot afford its own
transition sentence conflating which value moved. Now says a DIFFERENT cap disappeared
entirely, states that depth is unchanged, and names what the removal actually changes --
how many caps there are, not where any of them sits.

Pre-existing on HEAD rather than new in the last diff (introduced in 6c39519, untouched
by 6c0ac20), flagged and fixed because it is live.
@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 1m 20s —— View job


Code Review — PR #2169

  • Gather context (gh pr diff 2169, changed files, CLAUDE.md/AGENTS.md, prior review threads)
  • Review latest commit (8b24f19) against the prior round's outstanding nit
  • Review all changed files for correctness/maintainability
  • Check version bump / changelog consistency
  • Post inline findings
  • Post summary

Summary

Reviewed the cumulative diff (origin/main at f43a115HEAD 8b24f19, 7 files) and the latest
commit (8b24f19) in isolation.

8b24f19 is a direct, correct fix for the last open nit from the previous review round
(plugins/session-flow/skills/orchestrate/SKILL.md:151-163):
"the ceiling moved again" was reusing a term the same paragraph had just scoped to depth to
instead describe the removal of a completely different cap (the per-session spawn total). The new
text reserves "the ceiling" for depth throughout, states plainly that depth "is still where v2.1.219
left it," and names what actually changed — "how many caps there are," not where one sits. That's
exactly the fix requested, and it doesn't introduce the double-statement problem the prior attempt
at this same fix (in 6c39519) had — this version says the removal once, then states its
consequence once.

That was the last item still open across five prior review rounds on this PR. I re-checked the other
four previously-flagged spots and all read as resolved on this HEAD:

  • plugins/discipline/CHANGELOG.md — "fictional" → "since been removed," with the accurate-when-written / stale-under-the-platform distinction spelled out.
  • plugins/discipline/skills/sweep-all/SKILL.md:226-238env-vars citation restored alongside the new link; CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY explicitly marked carried-forward/not-re-verified rather than silently re-sourced.
  • plugins/session-flow/skills/orchestrate/SKILL.md ambiguous-antecedent nit — resolved, then the redundant restatement that fix introduced was itself trimmed in 6c0ac20.
  • plugins/discipline/CHANGELOG.md:12-21 — the 0.12.1 entry now documents the citation-restore commit's changes, so the changelog matches what actually shipped under that version.

No new findings on this pass. Nothing left open from the prior rounds.

Mechanical checks

  • discipline 0.12.0 → 0.12.1 and session-flow 0.22.1 → 0.22.2 version bumps in plugin.json match their respective CHANGELOG.md top entries.
  • Grepped all three edited sites for the old "three separate caps" / "200 subagents per session" wording — none survives outside the intentional Superseded note in sources.md.
  • Read the full surrounding paragraph (SKILL.md:140-163) after the latest edit — flows correctly, no leftover reference to a removed cap, no new ambiguity introduced.

Not independently run

check-skill-portability.sh origin/main and markdownlint-cli2 both required interactive approval
this environment didn't grant, so the PR body's "gates run in CI form... clean" claim remains
author-reported, not independently confirmed by this review — consistent with every prior round on
this PR.
· branch

@claude

claude Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Claude finished @kyle-sexton's task in 33s —— View job


Security Review — PR #2169

  • Gather context (gh pr diff 2169, changed files)
  • Review each changed file for security issues
  • Report findings

Scope reviewed: gh pr diff 2169 (7 files, full diff read — no truncation), at HEAD 8b24f19.

Findings: none.

This PR is a pure documentation-currency fix with no executable or trust-boundary surface:

  • 5 Markdown files (two SKILL.mds, two CHANGELOG.mds, sources.md) correct a stale claim about a removed Claude Code subagent cap (CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION) and cite code.claude.com/docs URLs. No shell snippets, no templated/interpolated content, and no directive language embedded in the prose that could function as a prompt injection against a future session reading these skill files — the added text is factual/citation content, not instructions aimed at an agent.
  • 2 plugin.json changes are version-string bumps only (discipline 0.12.0→0.12.1, session-flow 0.22.1→0.22.2); the large description fields and all other manifest fields are unchanged.
  • No GitHub Actions workflow files, hook scripts (.claude/hooks/*), .mcp.json entries, or ${CLAUDE_PLUGIN_ROOT}/${CLAUDE_PLUGIN_DATA} path-handling code are touched.
  • No secrets, tokens, or credentials introduced; the only URLs added are documentation links to code.claude.com/docs/..., not user-controlled input or fetched-and-executed content.
  • No authorization/access-control, injection (command/SQL/path/template), or supply-chain surface (no dependency, action pin, or lockfile changes) present in this diff.

Nothing here rises to CRITICAL/IMPORTANT/SUGGESTION — this lane has nothing to flag on a docs-only PR. Consistent with all five prior automated security-review passes on earlier commits of this PR, each independently reaching the same conclusion.
· branch

kyle-sexton added a commit that referenced this pull request Aug 10, 2026
…n misses (#2179)

Closes #2173

## Summary

`check-skill.sh` check 5 resolves every bare `context/…`-shaped path
against the **citing** skill's
own directory. A skill citing a *sibling* skill's supporting file
therefore failed as a broken
internal ref — "no such file under the skill dir" — while the file
plainly existed one directory
over, and the message pointed at the citing skill. The author's natural
next move was to look for
the file where it could never be. That misdirection cost two round trips
in a single PR (#2161),
once in each direction.

This implements issue options **(2) message** and **(1) docs**. Option
(3) (narrowing extraction to
link targets) is deliberately **not** implemented: prose and inline-code
refs are presumed-intended
coverage, and dropping them is a separate call.

## Fix

- **Sibling-aware diagnosis (check 5).** When the unresolved path *also*
resolves under a sibling
skill of the same skills root, the finding names that sibling and the
citation form that works.
Still a **FAIL** — the bare form really does resolve against the citing
skill, so it is wrong
  regardless of where the file lives; only the diagnosis gains detail.
- **The sibling hit is evidence, not proof.** Because this check
deliberately extracts prose and
inline-code refs, a generic path (`scripts/run.sh`) can collide with an
unrelated same-named
sibling file. The original message — including its `hand-verify the line
before fixing, may be an
illustrative example` instruction — is kept **verbatim**, and the
sibling evidence is appended
  conditionally, so both readings stay live:

  ```text
FAIL: broken skill-internal ref: context/suppression.md (no such file
under the skill dir; cited
at SKILL.md:7 — hand-verify the line before fixing, may be an
illustrative example). A file with
that path DOES exist under sibling skill 'host': if that is the file
meant, this is a cross-skill
citation, and a bare path always resolves against the CITING skill's dir
— write it as
${CLAUDE_PLUGIN_ROOT}/skills/host/context/suppression.md. If the names
merely collide, the ref is
  unrelated to that sibling.
  ```

- **Layout-aware suggestion.** Which form is correct depends on the
skills root, and the script's
resolution ladder deliberately bakes no layout. A plugin-shaped root
gets
`${CLAUDE_PLUGIN_ROOT}/skills/<sibling>/<path>`; outside a plugin that
variable is undefined, so
the message names the layout-free `../<sibling>/<path>` instead of
advertising a variable the
consumer does not have. The plugin-shaped test itself is hoisted to a
single `IS_PLUGIN_SKILL`
computed once after the skill dir resolves — check 1's bare-alias branch
and check 5's suggested
form now read one boolean instead of restating the same layout
convention twice.
- **No false positives.** A path no sibling hosts keeps the original
message unchanged. Sibling
enumeration reuses check 3's `"$SKILLS_ROOT"/*/SKILL.md` glob (sorted,
so a path present under
more than one sibling names the first deterministically) and skips the
citing skill.
- **The two grep generators feeding the loop are untouched** —
extraction behavior is unchanged.
- **Docs (`docs/PLUGIN-PHILOSOPHY.md`).** Two sentences in the existing
*Configuration ownership and
scope* section, directly parallel to the `${CLAUDE_PROJECT_DIR}`
project-path rule already there
and to the section's own `Bundled plugin code and assets |
${CLAUDE_PLUGIN_ROOT}` row. No new
section. `plugins/skill-quality/README.md`'s check-5 bullet and the
script's own header list are
  updated to match.

## Verification

- `plugins/skill-quality/scripts/check-skill.test.sh` — three new cases,
all confirmed passing in
CI (`plugin-gate` → `PASS:
plugins/skill-quality/scripts/check-skill.test.sh`):
- 36a: plugin-shaped root names the host sibling **and** the
`${CLAUDE_PLUGIN_ROOT}` form, **and**
still carries `hand-verify the line` — the caveat cannot be silently
dropped again.
- 36b: non-plugin root names the sibling-relative `../<sibling>/<path>`
form and not the
    plugin-root one.
- 36c: a ref no sibling hosts keeps the plain broken-internal-ref
message with no `sibling skill`
    text (false-positive guard).
- Manual reproduction against a throwaway plugin-shaped fixture
reproduces the message quoted above,
while a genuinely absent ref in the same `SKILL.md` still reports the
unmodified
  `broken skill-internal ref: context/absent-file.md (…)`.
- Repo gates, base-ref form against the committed tree:
`check-shell-portability.sh`,
`check-skill-portability.sh`, `check-changelog-parity.sh --check-bump`,
`check-changed-skills.sh`,
`check-contract-slice-prune.sh --check-diff` — all pass.
`markdownlint-cli2` clean on the changed
markdown. `shellcheck` clean and `shfmt -i 2` clean on both changed
shell files.
- Coverage note: the full suite was run to completion on Linux CI, not
locally on Windows/Git Bash
(where it is impractically slow); local Windows confirmation is limited
to targeted smoke tests of
the two new message branches. Nothing in the change is
platform-sensitive — pure bash string ops
and `-e`/`-f` tests, no `date`/`readlink`/GNU-only constructs — and
`shell-portability-lint` passes.
- `plugins/skill-quality` bumped to `0.15.1` with a matching `##
[0.15.1]` CHANGELOG entry (patch is
consistent with this plugin's history: `0.12.1` shipped a whole new
check as a patch).

## Related

- Closes #2173
- #2161 — the PR where the misfire was hit twice, once in each direction
- #2169 — the gate doc-currency audit that recorded the finding

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kyle-sexton
kyle-sexton merged commit 2329f31 into main Aug 10, 2026
33 checks passed
@kyle-sexton
kyle-sexton deleted the chore/gate-doc-currency-audit branch August 10, 2026 22:38
@kyle-sexton

Copy link
Copy Markdown
Contributor Author

Working #2176 (the week-32 sweep this PR's findings graduated into) reached the open verification item you flagged here — CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY, carried forward and marked unverified in plugins/discipline/skills/sweep-all/SKILL.md. It is current. The marker can come off.

env-vars truncated a third time, so the primary route is still closed: the fetch reached CLAUDE_CODE_DISABLE_1M_CONTEXT and stopped — alphabetically well short of the MAX range — and the summarizer duly reported that "no table rows exist whose variable name begins with CLAUDE_CODE_MAX". Same false negative, reproduced, not resolved.

The "different route to the same row" you asked for turned out to be a verbatim mirror of these docs, ericbuess/claude-code-docs, whose docs/env-vars.md was last synced 2026-08-10T21:32:29Z — today (Update Claude Code docs - 2026-08-10 | Updated: … env-vars.md …). Its row:

CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY | Maximum number of read-only tools and subagents that can execute in parallel (default: 10). Higher values increase parallelism but consume more resources

Word for word what sweep-all cites, parenthetical default included.

Two independent corroborations that the mirror is both faithful and post-2.1.224, rather than a stale copy agreeing with a stale claim:

  • The same file carries CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION as "Removed in v2.1.224 and now a no-op. Previously capped the total number of subagents Claude could spawn with the Agent tool in one session (default: 200)…" — the exact change this PR lands, which cannot be present in a pre-2.1.224 sync.
  • Its CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS row agrees with the sub-agents page fetched directly (default 20, v2.1.217+).

The honest caveat: this is a same-day third-party mirror, not code.claude.com. Strong evidence, one rung below a primary read — so if you'd rather keep the marker until someone lands a primary fetch that reaches the M range, that's a defensible call and I won't argue it. What it does rule out is the reading the marker was hedging against: the variable has not been removed or reworded, and the ABSENT the truncated fetch returned was the excerpt, not the docs.

I touched nothing in sweep-all — this PR owns that file and that region, and I kept #2180 clear of it to avoid a conflict. Full write-up, including the two verbatim quotes, is in #2180's Verification section (item 9).

kyle-sexton added a commit that referenced this pull request Aug 10, 2026
…ges against doctrine and gate the archive source (#2180)

Closes #2176

## Summary

Week 32 (v2.1.220–v2.1.224) landed after this repo's verification
stamps, which cluster
2026-08-03/04/08. Every checklist item was worked against the source
page's **own** current wording,
all fetched 2026-08-10. Four items moved doctrine; five are
checked-no-change; one was verified
through a non-primary route and is flagged as such. Nothing is silently
dropped.

## Fix

**Auto mode becomes the default on 2026-08-14** (item 1,
time-sensitive). Nothing in this repo
assumed `default` permission mode — the permission-rule-hygiene
convention and `claude-config`'s
`audit-permission-grants` already treat auto mode as live. What was
stale is the *framing*: the
convention described auto mode as a state a session **enters**, which
makes its anti-patterns read
as latent. They are not.
`docs/conventions/permission-rule-hygiene/README.md` gains a dated
section
recording three things — a dropped grant is now the **first** run's
outcome, not a later one;
"run it outside auto mode" is a downgrade rather than a remedy (kept
only for the `Agent`-rule case,
which has no bare-command analog); and neither the drop list nor the
project/local `defaultMode:
"auto"` self-grant block changes. The claim is bounded to the plans the
docs bound it to: the same
page still says provider-routed sessions (Bedrock, Google Cloud's Agent
Platform, Microsoft Foundry,
gateway) "start in your `defaultMode`, which is Manual unless you change
it."

**The `archive` marketplace source gets a decision and a gate** (item
2). Its platform floor is
transport-level only — HTTPS, no loopback/link-local/cloud-metadata
hosts, enforced on every redirect
hop — and the `sha256` that pins the bytes is documented as
**"Optional"**. Unpinned, one URL can
serve different content on every install with nothing to detect it: the
mutable-remote-artifact
surface the plugin-acceptance security review denies by default. So the
review now **requires** the
pin (`docs/MIGRATION-PLAYBOOK.md`, criterion 6), and
`scripts/validate-plugin-contracts.mjs` enforces
it over `.claude-plugin/marketplace.json` rather than leaving it to a
reviewer's eye. Recorded with
it: the digest doubles as the version when none is declared, so a
repinned archive still needs a
`version` bump; and org distribution via claude.ai admin settings
doesn't accept the source at all.
No entry uses `archive` today — the rule governs the first that does.

**Two edits replace an incident with a rule.** `source-control`'s
worktree skill justified moving git
calls out of pre-compute with one observed refusal from #1619, which
invites a future author to
retest and fold them back. v2.1.224 documented the enforcement, so the
constraint now cites it —
including that a command Claude Code "can't verify stays inside the
worktree" is blocked on the same
footing as one that would really reach the main checkout, which is why
narrowing the commands cannot
make the block safe again. And `claude-ops`' plugin-sync skill: an
in-session `/plugin` install can
now activate itself, which reads like the skill's closing reload
guidance went stale. It did not —
`sync` installs with the `claude plugin install` **shell** command,
which "doesn't run in a session".
Recording why beats leaving the next reader to relax it.

## Verification

| # | Item | Disposition |
|---|---|---|
| 1 | Auto mode default 2026-08-14 | **Fixed** —
`permission-rule-hygiene` reframed from opt-in to default; scope bounded
to Pro/Max/Team. No hook, guardrail, or skill assumed `default` mode
(searched for prompt-guaranteed phrasings; zero hits). |
| 2 | Zip-archive `archive` source | **Fixed** — security-review clause
requiring the `sha256` pin, plus a machine gate in
`validate-plugin-contracts.mjs`. Gate tested both directions locally
(unpinned entry fails, pinned passes, catalog restored). |
| 3 | Worktree isolation extended | **Fixed (docs) + checked-no-change
(guardrails)** — `guardrails` ships no worktree-boundary guard, so
nothing is redundant and nothing assumed the narrower behavior; its
hooks gate dangerous git verbs, hook bypass, commit convention,
hardcoded paths, and secrets. The `source-control` worktree skill's
constraint is now grounded in the documented three checks. |
| 4 | PreToolUse auto-allow narrowed | **Checked, no change** — no hook
in this repo emits `permissionDecision: "allow"`. The only
`permissionDecision` producer is `context-guard/hooks/zone-gate.sh`,
which emits `"deny"`. Nothing relied on the old bypass. |
| 5 | `/fork` uses its own worktree | **Checked, no change** — every
`fork` reference in this repo is the Agent-tool **subagent** fork
(`session-flow:orchestrate`, `discipline:sweep-all`,
`session-flow:handoff`), not the `/fork` slash command. No doc states or
assumes that `/fork` shares the original checkout. |
| 6 | Plugin activation on install | **Fixed** — no plugin README tells
users to restart (all use `/plugin marketplace add` + `/plugin
install`), so nothing was stale there. The substantive point is the
opposite of the obvious one and is now recorded in `claude-ops`
`context/scope-semantics.md`: the new in-session activation does **not**
apply to `claude plugin install`, so `sync`'s reload guidance stands. |
| 7 | `/review` aliases `/code-review` | **Fixed** —
`plugins/review/README.md`. The plugin's own commands are unaffected
(0.18.0 already made the namespaced form the only one it registers); the
README now names `/review` as a fourth spelling of the bundled reviewer
so the plugin isn't abbreviated onto it. |
| 8 | Ultraplan removed | **Checked, left as-is (deliberate)** — the one
reference,
`docs/topics/context-engineering-claude-5/design/official-corroboration.md:355`,
is a topic-design doc: a record of what the corroboration sweep found
when written, not a live instruction. Editing it would falsify the
record rather than correct doctrine, and `docs/topics/` is Contract tier
where an edit invites the prune gate. Left intact. |
| 9 | `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY` | **Verified current — but
not from the primary page.** See the caveat below. |
| — | 200-subagent cap removal | **Out of scope, owned by #2169** (still
OPEN). It edits the same `sweep-all` region; deliberately untouched here
to avoid a conflict. Corroborated independently: the `sub-agents` page's
concurrency section names only the concurrency and depth limits. |

### Item 9: what could not be verified from the primary source

`env-vars` truncated for a **third** time. The fetch reached
`CLAUDE_CODE_DISABLE_1M_CONTEXT` and
stopped — alphabetically well before the `MAX` range — and the
summarizer duly reported that "no
table rows exist whose variable name begins with `CLAUDE_CODE_MAX`".
That is the exact false negative
the method rule exists to catch, and it reproduces the earlier failure
rather than resolving it.

A different route reached the row. `ericbuess/claude-code-docs` is a
verbatim mirror of these docs
whose `docs/env-vars.md` was last synced **2026-08-10T21:32:29Z — the
same day** (commit message
`Update Claude Code docs - 2026-08-10 | Updated: … env-vars.md …`). It
carries the row unchanged:

> `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY` | Maximum number of read-only
tools and subagents that can
> execute in parallel (default: 10). Higher values increase parallelism
but consume more resources

That matches `plugins/discipline/skills/sweep-all/SKILL.md` word for
word, so the citation is
**current, not drifted**. Two corroborations that the mirror is both
faithful and fresh: the same
file carries `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION` as "Removed in
v2.1.224 and now a no-op" — the
week-32 change #2169 is landing, which could only appear in a
post-2.1.224 sync — and its
`CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` row agrees with the `sub-agents`
page fetched directly here.

**Stated plainly: this is a same-day third-party mirror, not
`code.claude.com`.** Strong evidence,
one rung below a primary read. No file changes on this item — the
`sweep-all` text on `main` carries
no unverified marker (that marker lives in #2169's branch), so there is
nothing here to correct. The
finding is posted to #2169 so its author can drop the marker.

### Gates run (committed tree, base-ref form)

- `check-contract-slice-prune.sh --check-diff origin/main` — pass
("leaves no path under `docs/topics/`")
- `check-changelog-parity.sh --check-bump origin/main` — pass
- `check-skill-portability.sh origin/main` — pass (2 skill files)
- `check-shell-portability.sh origin/main` — pass (no shell files in
scope)
- `check-contract-clause-coverage.py` — pass
- `validate-plugin-contracts.mjs`, `generate-catalog.mjs --check`,
`generate-cheatsheet.mjs --check` — pass
- `markdownlint-cli2` over all 8 changed markdown files — 0 errors
- `check-changed-skills.sh origin/main` — still running locally when
this PR opened; CI is the authority

Version bumps: `claude-ops` 0.28.3→0.28.4, `review` 0.18.0→0.18.1,
`source-control` 0.51.5→0.51.6.
The `docs/` and `scripts/` changes need none.

## Related

- #2169 — the doc-currency audit this graduated from; owns the 200-cap
fix and the `sweep-all` file
- Source:
[`whats-new/2026-w32`](https://code.claude.com/docs/en/whats-new/2026-w32)
- Pages fetched 2026-08-10:
[permission-modes](https://code.claude.com/docs/en/permission-modes),

[plugin-marketplaces](https://code.claude.com/docs/en/plugin-marketplaces),
  [worktrees](https://code.claude.com/docs/en/worktrees),
  [discover-plugins](https://code.claude.com/docs/en/discover-plugins),
  [code-review](https://code.claude.com/docs/en/code-review),
  [sub-agents](https://code.claude.com/docs/en/sub-agents)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 10, 2026
…n in sweep-all (#2182)

Closes #2176

Follow-on to #2180. #2176 is already closed; this lands the one edit
that only became possible after #2169 merged.

## Summary

#2169 landed the v2.1.224 subagent-cap removal with an honest in-place
marker beside it: `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY` was "carried
forward from the 2026-07-29 read and NOT re-verified … its currency is
open, tracked as its own item".

#2176 was that item, and #2180 verified it — but the marker was not on
`main` when #2180 opened (it lived on #2169's branch), and #2169 merged
minutes ahead of it. So `main` now carries a settled claim that
advertises itself as open and points at a closed issue. This closes that
gap.

## Fix

The citation is **current, not drifted**. The row reads exactly as
`sweep-all` cites it:

> `CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY` | Maximum number of read-only
tools and subagents that can execute in parallel (default: 10). Higher
values increase parallelism but consume more resources

The marker is **replaced, not deleted**, because the route is the
load-bearing part. `env-vars` truncated before the `MAX` range for a
**third** time — the fetch reached `CLAUDE_CODE_DISABLE_1M_CONTEXT` and
the summarizer duly reported no rows beginning `CLAUDE_CODE_MAX`, the
exact false negative this repo's method rule exists to catch. The row
was read verbatim from a same-day verbatim mirror of these docs
(`ericbuess/claude-code-docs`, `docs/env-vars.md`, synced
2026-08-10T21:32:29Z), whose freshness is corroborated by its carrying
the v2.1.224 cap removal that #2169 just landed — a fact that cannot
appear in a pre-2.1.224 sync.

So the new note says what is true and no more: re-verified 2026-08-10,
unchanged, **but not from the primary page** — treat it as one rung
below a primary read. That neither overclaims a fetch that did not
happen nor leaves a closed question looking open.

## Verification

- `validate-plugin-contracts.mjs`, `generate-catalog.mjs --check`,
`generate-cheatsheet.mjs --check` — pass
- `markdownlint-cli2` over both changed files — 0 errors
- `discipline` 0.12.1 → 0.12.2 with a matching `## [0.12.2]` CHANGELOG
entry
- Remaining gates: CI is the authority

## Related

- #2180 — the week-32 sweep; item 9's full write-up and both verbatim
quotes
- #2169 — landed the marker this removes, and the cap removal that
corroborates the mirror's freshness
- [`env-vars`](https://code.claude.com/docs/en/env-vars) — the primary
page, which has now truncated before this range on three independent
fetches

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 10, 2026
…rasing (#2181)

Closes #2174

## Summary

A skill `description` is the text Claude matches against to decide
whether to **load** the skill, so
a description shaped like a summary of what the skill *is* makes the
skill under-fire. The
skill-quality gate reported this on `verification:measure`:

```text
WARN: description has no 'Use when:' trigger phrasing — a description is a trigger spec, not a summary
```

This fixes `measure` and sweeps the rest of the corpus, which the issue
explicitly asks for. **All
196 skills were checked** — not a base-ref diff. 29 carried a check-12
warning; 25 are fixed here and
4 are deliberately left as-is with the reasoning below.

## Fix

Check 12 in `plugins/skill-quality/scripts/check-skill.sh` has two
branches, and the sweep found both
in the wild:

| Warning | Found | Fixed | Left |
| --- | --- | --- | --- |
| `description has no 'Use when:' trigger phrasing` | 22 | 18 | 4 |
| `'Use when:' triggers are not single-quoted` | 7 | 7 | 0 |

**No `Use when:` phrasing (22).** Most already had good routing phrases,
but behind a lowercase
`use for` the gate does not recognize (`planning:*`, `testing:*`,
`toolchain:check`,
`review:fanout`, `implementation:implement`, `verification:confirm`,
`verification:measure`). A few
named only a topic or a state and no phrase a user types
(`context7:lookup`, `toolchain:lint`).

**Unquoted triggers (7).** The gate's trigger-drop protection tracks
only `'single-quoted'` text, so
phrases written with escaped double quotes (`debugging:debug`,
`docs-hygiene:compress`,
`kindle-dedrm:manage`) or as a bare comma list (`repo-hygiene:clean`)
had **no regression cover at
all** — a later rewrite could have dropped any of them silently. Those
are quoting changes; the
wording is unchanged.

Across the 25, **108 typed trigger phrases were added and zero existing
phrases were dropped** — the
gate's keyword-preservation check sees a superset, not a rewrite. This
matters most on `measure`,
whose base-ref trigger set includes `'cannot quantify'`: that is
*prose*, not a trigger, but the
extractor tracks any single-quoted span, so the natural "clean this up"
rewrite would have dropped it
and **failed** check 3. It is preserved verbatim.

### Deliberately left as-is (4)

All four are `disable-model-invocation: true` **and** carried no
pre-existing quoted phrase. A skill
that cannot be model-invoked is never matched against its description,
so triggers would buy no
auto-invocation there — and inventing user-typed phrases for them would
invite exactly the misfire
this issue is about.

The review round below sharpened this: dmi-true alone is not sufficient
grounds, because a phrase
that lives *only* on a dmi-true skill is unreachable (that is the
`kindle-dedrm` finding). So for
each of the four, the additional question is whether some phrase a user
would type is left with no
model-invocable home. It isn't:

- `discipline:wait-what` — its description *is* the instruction ("Type
`/discipline:wait-what` the
moment you notice you are skimming; only you know when you stopped
following"). Self-observation
  is the trigger; by construction the model cannot detect it.
- `firecrawl:update`, `playbooks:update` — maintainer-only drift checks
whose descriptions say "Not
for consumers — consumers update via `/plugin marketplace update`".
There is no user phrase that
*should* route here, so nothing is stranded. Their model-invocable
siblings (`firecrawl:firecrawl`,
`playbooks:boris`) are both fixed in this PR and carry the
consumer-facing phrases.
- `github:setup` — `SKILL.md` states "User-invoked only", the plugin
README lists it as
"user-invoked only", and the only references to it are documentation. It
is a deliberate slash
  command, not an orphan and not a routing target.

Where a `disable-model-invocation: true` skill *already* had quoted
phrases (`planning:questionnaire`),
the connector is normalized to `Use when:` and nothing is invented — it
is the only dmi-true skill
among the 25 changed here.

### One deliberate cross-skill duplicate

`kindle-dedrm:manage` carries a byte-identical copy of `'set up Kindle
DRM removal'`, a trigger on
its sibling `kindle-dedrm:setup`. It was invisible while double-quoted,
and quoting it for tracking
makes two siblings claim the same typed phrase. It is kept anyway:
`setup` is
`disable-model-invocation: true`, so its description is never matched
against user text, and
`manage` — model-invocable, with an action router that delegates to
`/kindle-dedrm:setup` — is the
only skill that can receive the phrase by model invocation. Dropping the
duplicate would leave the
phrase reachable only by an explicit slash command. A collision check
over the whole corpus confirms
this is the *only* overlap: the other 107 added phrases collide with
nothing.

### Versioning

13 plugins touched, each with a patch bump and a matching `## [x.y.z]`
CHANGELOG entry:
`context7` 0.5.1, `debugging` 0.6.1, `docs-hygiene` 0.10.1, `firecrawl`
0.5.1, `implementation`
0.13.1, `kindle-dedrm` 0.7.1, `planning` 0.30.1, `playbooks` 0.8.2,
`repo-hygiene` 0.9.1, `review`
0.18.1, `testing` 0.5.2, `toolchain` 0.12.1, `verification` 0.5.2.

## Verification

How the sweep covered all 196 skills: the gate ships no `--all` mode —
`check-changed-skills.sh` maps
a base-ref diff to skill dirs — so check 12 was reimplemented against
the checker's **own**
`plugins/skill-quality/scripts/skill-frontmatter.sh` semantics
(`extract` / `field` / `strip_quotes` /
`extract_triggers`, including the intra-word-apostrophe normalization)
and run over every
`plugins/*/skills/*/SKILL.md`. Two fidelity controls:

- Spot-checked against the real `check-skill.sh` on one skill from each
warning class
(`verification:measure`, `docs-hygiene:compress`) — same classification
both times.
- The only place the reimplementation could diverge from the awk is
block-scalar / trailing-comment
handling. **No SKILL.md in the corpus uses a block-scalar `description:`
or `when_to_use:`**
(`grep -c '^description: *[|>]'` over all 196 = 0), so both take the
plain-scalar path.
- The authoritative confirmation is CI: `check-changed-skills.sh
origin/main` runs the *real*
  checker over exactly the 25 changed skills.

Gates run locally on the committed tree, base-ref form:

| Gate | Result |
| --- | --- |
| `scripts/check-changelog-parity.sh --check-bump origin/main` | pass |
| `scripts/check-changelog-parity.sh --check` | pass |
| `scripts/check-skill-portability.sh origin/main` | pass — no unexcused
coupling tokens in 25 skill files |
| `scripts/check-contract-slice-prune.sh --check-diff origin/main` |
pass |
| `markdownlint-cli2` over all 38 changed `.md` | pass — 0 errors |
| Trigger preservation + listing cap, all 25 | pass — 0 dropped, max
listing 951/1536 |
| Cross-skill trigger collision, whole corpus | pass — 0 collisions |
| Line endings | all changed files `i/lf w/lf` |

`scripts/check-changed-skills.sh origin/main` — the gate that reported
the original warning — runs
green in CI as `skill-quality-gate` over all 25 changed skills. It was
also run to completion locally
on `measure` alone, before the sweep was layered on: `PASS — 0 errors, 0
warning(s)`,
`all 4 base-ref trigger phrase(s) preserved`.

Post-change sweep: **192 of 196 skills clean**, the remaining 4 being
the documented exemptions.

## Related

- Closes #2174
- Surfaced during #2161 (touched `measure/context/metrics.md`, not the
frontmatter) and carried again
  as a noted follow-up on #2169
- Gate: `scripts/check-changed-skills.sh`,
`plugins/skill-quality/scripts/check-skill.sh` check 12
- Trigger-drop protection this relies on: `check-skill.sh` check 3

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
…rt claims, record upstream corroboration (#2184)

No linked issue

## Summary

Doc-currency **pass (b)**, never run before. Pass (a) (#2169) asked
whether the repo's claims about how Claude Code *behaves* were still
factually current. This pass asks the harder question: **is the doctrine
these gates enforce still the right rule**, given current authoritative
guidance?

Scope was doctrine a gate, check skill, or CI script actually enforces.
Every source was asked to state its own position; no supersession is
claimed without a verbatim quote from the page itself.

Two things had quietly diverged, both in `### Model tiers` / `### Effort
tiers`. The rest held, and several items are now backed by upstream text
that did not exist — or was not cited — when they were written.

### Per-item verdicts

| Item | Verdict | Basis |
|---|---|---|
| Fresh-eyes checkpoints — bias classes, mandatory fresh-context
non-fork delegation | **Still sound, now upstream-stated** |
`sub-agents`: "Each subagent starts with a fresh, isolated context
window… The exception is a fork, which inherits the parent conversation
instead of starting fresh." `best-practices` now states the *doctrine*
too: a fresh context "improves code review since Claude won't be biased
toward code it just wrote"; a verification subagent exists "so the agent
doing the work isn't the one grading it" |
| Fresh-eyes — inline-template conventions | **Sound but incomplete →
one bullet added** | `best-practices` "Add an adversarial review step"
names a failure the doc did not carry: "A reviewer prompted to find gaps
will usually report some, even when the work is sound", and chasing all
of them "leads to over-engineering" |
| Fresh-eyes — deterministic-gate exemption | **Still sound** |
`best-practices` ranks a Stop hook and a verification subagent as
distinct rungs of the same "give Claude a way to verify its work"
ladder; nothing contradicts the narrow reach |
| Naming — imperative grammar vs upstream gerunds | **Still sound;
justification re-grounded** | The doc *characterized* the upstream
position; it now quotes it. Gerunds are what that page says to "consider
using", `process-pdfs` sits under "Acceptable alternatives", and
"inconsistent patterns within your skill collection" is under Avoid |
| Naming — fixed verb table, exceptions list, leaf-name registry |
**House convention, no upstream position** | Upstream takes no position
beyond charset limits and collection consistency. Stands on its own
stated rationale; does not masquerade as backed |
| Setup contract — required-iff criteria, `check`+`apply`, closed verb
set | **House doctrine, no upstream position** — now labeled | No
official page takes a position on a consumer-facing `setup` skill.
`disable-model-invocation: true` *is* backed: upstream's own rule is
"for workflows with side effects that you want to trigger manually" |
| Setup — native init idioms (`Setup` hook event, `SessionStart`) |
**Still sound** | `Setup` event and its `--init-only` / `--init` /
`--maintenance` framing unchanged on the hooks reference |
| Instruction economy — line budgets, progressive disclosure | **Still
sound** | "Keep SKILL.md body under 500 lines for optimal performance"
verbatim, twice on the page (`check-skill.sh` check 4). The 200-line
soft target is house convention, correctly labeled advisory. "Avoid
deeply nested references" is carried, correctly attributed |
| Instruction economy — the two quoted rules | **Still sound** | Both
verbatim on `best-practices` today, unchanged |
| Delegation mechanics — dispatch ladder, named-agent bar | **Still
sound** | Subagent isolation and `tools` frontmatter unchanged; the
Agent tool still exposes `model` and no effort counterpart (live schema,
2026-08-10) |
| **Model tiers — `availableModels` blocked pin** | **Superseded →
fixed** | Doc recorded the branch as "unresolved upstream, and stated
here as such". Upstream now resolves it per surface: a subagent override
"falls back to the subagent's inherited model", except a family alias on
the Anthropic API substituting to "the newest permitted version of its
family" (v2.1.222); a skill or command override is *ignored* and "runs
on the session model" |
| **Effort tiers — `low` at the bulk rung** | **Incoherent against
current upstream → fixed** | The model ladder's bulk row is Haiku 4.5;
the effort rules told that lane to pin `low`. "Models not listed here do
not support effort" and no Haiku is in that table — corroborated
independently by the roster's adaptive-thinking column reading No for
Claude Haiku 4.5 |
| Model tiers — table rows and recheck trigger | **Still sound, trigger
re-tested negative** | Opus 5 / Sonnet 5 / Haiku 4.5 current; Opus 4.8
confirmed legacy. A further family, Claude Mythos 5, appears upstream
but "is not generally available" — invitation-only under Project
Glasswing — so the trigger has not fired |
| Model tiers — interleaved thinking | **Still sound** | "Claude Haiku
4.5 does not support interleaved thinking" and the
consecutive-tool-calls carve-out are both verbatim as cited |
| Model tiers — `CLAUDE_CODE_SUBAGENT_MODEL` | **Narrowed** | Still
overrides both, but upstream adds an off position: "Set to `inherit` to
use normal model resolution instead" (v2.1.196) |
| Effort tiers — lane rules, cache caveat, the two-dials rule | **Still
sound** | `sub-agents` frontmatter `effort` confirmed with all five
levels; the unsupported-level fallback sentence confirmed verbatim |
| Design boundary — plugins vs standalone appeal | **Sound but uncited →
citation added** | `plugins` draws exactly this line: standalone for
"project-specific customizations", plugins for "versioned releases,
reusable across projects" |
| Design boundary — horizontal decoupling, "a bare unguarded
cross-plugin reference is a defect" | **House doctrine, no upstream
position** | Upstream documents `dependencies` and namespacing but takes
no stance on optional cross-plugin coupling. Stands on its own reasoning
|
| Two-lane convention posture | **House doctrine, no upstream position**
| Attributed to `melodic-software/standards`, not to upstream. No
masquerade |
| Evidence and validation | **Still sound** | `best-practices`
independently asks for evidence over assertion: "Have Claude show
evidence rather than asserting success" |

## Fix

Two corrections and four recorded corroborations, all in
`docs/PLUGIN-PHILOSOPHY.md`. No plugin touched, so no version bump or
CHANGELOG entry is owed.

**Corrections**

1. **Effort tiers.** The bulk-sweep bullet now states that the two
ladders do not compose at their bottom rung: effort is a per-model
capability and Haiku has none, so the pin is inert rather than
downgraded — and silently, since this is *not* the documented
unsupported-level fallback (there is no supported level to fall back
to). A lane wanting the cheapest tier takes it by model and omits the
pin. Nothing in the fleet pins `haiku` today, so the defect was
doctrinal, not live.
2. **`availableModels` blocked pin.** The "unresolved upstream" framing
and the `enforceAvailableModels`-ordering derivation are replaced by the
now-documented per-surface rule, split into its subagent and
skill/command branches, which the old paragraph lumped together. The
conclusion survives intact — a blocked subagent alias can still land
below the session, and a blocked *cheap* pin lands on the session's own
model — but the recheck trigger was pointing at a sentence that no
longer carries the ambiguity, so it is rewritten too.

**Corroboration recorded**

- Fresh-eyes checkpoints gains the upstream statement of the doctrine
(not just the mechanism), plus a fourth inline-template bullet bounding
what counts as a finding.
- Naming replaces a characterization of the upstream guidance with its
actual words.
- The setup contract cites upstream for `disable-model-invocation` and
says plainly that the rest has no upstream position.
- The design boundary's vague appeal gains its citation.

**Stamps** refreshed only on pages actually fetched this session:
`sub-agents`, `model-config`, `code.claude.com` `best-practices`,
`plugins`, `hooks`, `agent-skills/best-practices`, platform `thinking`,
`models/overview`.

## Verification

```text
bash scripts/check-contract-slice-prune.sh --check-diff origin/main   # pass
bash scripts/check-changed-skills.sh origin/main                      # pass (no skills changed)
bash scripts/check-changelog-parity.sh --check-bump origin/main       # pass
bash scripts/check-skill-portability.sh origin/main                   # pass (no skills in scope)
npx --yes markdownlint-cli2 "docs/PLUGIN-PHILOSOPHY.md"               # 0 errors
```

Fleet grep confirms the effort finding is doctrinal only: `git grep -n
'^model:' -- 'plugins/*/agents/*.md'` returns no `haiku` pin, and every
`effort:` pin sits on an `opus`, `sonnet`, or `inherit` lane.

**Could not verify.** Stamps left untouched on pages not fetched:
`plugins-reference`, `code.claude.com` `skills`, `feature-availability`,
`agents`, `agent-teams`, `cross-session-messaging`, `sessions`,
`checkpointing`, `prompt-caching`, `settings`, and the platform `effort`
/ `thinking-steering-and-cost` pages. The **Recorded gate runs** and
**Component stances** tables therefore keep their existing dates. The
`SessionStart`-plus-`${CLAUDE_PLUGIN_DATA}` half of the native-init
stamp was not re-verified against `plugins-reference`, so that
2026-07-17 stamp stands even though the `Setup` half was confirmed.

One upstream rule this repo does not carry, deliberately left alone as
out of scope for a currency pass: `agent-skills/best-practices` asks for
a table of contents in reference files longer than 100 lines. Adding it
would be new doctrine, not a currency correction.

## Related

- #2169 — doc-currency pass (a), the behavior-currency pass this one
follows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01FdBsorqGjCU4Mg5nrmgz4m

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
…eferred gate calls (#2186)

No linked issue

## Summary

Three deferred judgment calls, all made here.

**The uncited doc pages were never dispositioned, and the set is larger
than recorded.** PR #2177
worked from an index of 112 core `/docs/en/` pages with ~33 uncited.
Re-derived today, the index
lists **135** core pages and this repo cites **78**, leaving **57**
unevaluated. #2177 also
demonstrated the miss rate of dismissing by eye: it took six pages that
had been written off as
irrelevant and found every one load-bearing enough to warrant a verdict.
So all 57 get a recorded
disposition here rather than a second eyeball pass.

The finding that mattered is in the **cross-platform contract**. It
reads one axis — the operating
system — and names `feature-availability` as its canonical input. That
page carries two axes,
model provider and subscription plan, and scopes itself to what runs
locally: "The Claude Code CLI
and everything that runs locally work on every provider." The **host
surface** a consumer runs in
was therefore never read at all, by either the contract or its input. It
has to be, because a host
can withhold the plugin system itself rather than one capability, and
where no plugin loads there is
no portable path for one to owe.

**`check-skill.sh` check 5** and **check 12's 4-skill warning floor**
were both left open as "a
separate call". Both are decided, at their own sites, with the reasoning
recorded so neither is
re-litigated from a false premise.

## Fix

### 1. Uncited-page disposition (57 pages)

One stated relevance test, applied to all 57 so the dismissals are
auditable rather than tacit:

> **Relevant** if the page describes a surface a plugin author can
**declare, invoke, or must
> accommodate.** Otherwise **not relevant.**

**Split: 1 adopt / 0 defer / 3 decline / 4 relevant-as-evidence / 49 not
relevant.**

Verdicts land in `docs/PLUGIN-PHILOSOPHY.md` under Native-first →
**Recorded gate runs**, in the

[upstream-drift](https://github.com/melodic-software/claude-code-plugins/blob/main/docs/conventions/upstream-drift/README.md)
four-part shape (claim, basis, as-of date, recheck trigger), following
#2177's form.

| Page | Disposition |
|---|---|
| `platforms` | **Relevant → ADOPT, as a citation.** The canonical
host-surface index; the axis `feature-availability` does not carry.
Lands doctrine. |
| `github-enterprise-server` | **Relevant → DECLINE.** A real
plugin-distribution surface ("Plugin marketplaces \| ✅ Supported") —
declines on need, not subject: nothing here documents a GHES-hosted
mirror or fork. |
| `ultrareview` | **Relevant → DECLINE.** Fails gate 1: every run is
human-confirmed and metered, so no skill can reach it. |
| `chrome` | **Relevant → DECLINE.** Ships as the built-in
`claude-in-chrome` skill; nothing to declare. Recorded because it only
*looked* cited — see the dead-link note below. |
| `desktop`, `vs-code`, `mobile`, `desktop-wsl` | **Relevant → read in
full as the evidence base for the `platforms` row**; no separate
verdict, because they are one finding seen from four pages rather than
four surfaces. Quoted verbatim in that row. |
| `jetbrains` | Not relevant — false friend: "plugin" there is the
JetBrains IDE plugin, a different sense. Ranked 2nd by `plugin`-keyword
density and is the one page where that signal is pure noise. |
| `desktop-quickstart`, `desktop-linux`, `desktop-ios-simulator`,
`web-quickstart`, `troubleshoot-install` | Not relevant — install and
first-run recipes; nothing declarable. |
| `slack`, `claude-tag` | Not relevant on their own — delegation front
ends indexed by `platforms`, which is the adopted citation; `slack` is
additionally being retired for Team/Enterprise. |
| `devcontainer` | Not relevant — container recipe; its only
`marketplace` hit is a VS Code extension link. |
| `gitlab-ci-cd`, `github-actions-cloud-providers` | Not relevant — CI
recipes and provider IAM routing; zero plugin or skill surface
(`gitlab-ci-cd`: 0 keyword hits). |
| `amazon-bedrock`, `google-vertex-ai`, `microsoft-foundry`,
`claude-platform-on-aws` | Not relevant — provider auth/IAM config; the
plugin-facing consequence is the availability matrix, already adopted as
`feature-availability`. |
| `gateways`, `llm-gateway`, `llm-gateway-connect`,
`llm-gateway-protocol`, `llm-gateway-rollout` | Not relevant — org
request-routing plane between the client and a provider; no plugin
declares or observes it. |
| `claude-apps-gateway`, `claude-apps-gateway-config`,
`claude-apps-gateway-deploy`, `claude-apps-gateway-on-aws`,
`claude-apps-gateway-on-gcp`, `claude-apps-gateway-spend-limits` | Not
relevant — deploying and operating Anthropic's gateway product;
`gateway.yaml`, Kubernetes, spend caps. |
| `self-hosted-environments`, `self-hosted-environments-quickstart`,
`self-hosted-environments-configuration`,
`self-hosted-environments-deploy`, `self-hosted-environments-identity`,
`self-hosted-environments-reference`, `self-hosted-environments-testing`
| Not relevant — standing up and operating cloud-session runners on org
infrastructure. |
| `admin-setup`, `authentication`, `legal-and-compliance`,
`third-party-integrations` | Not relevant — enterprise deployment,
identity, and policy plane; no surface a plugin declares or observes. |
| `analytics` | Not relevant — but **fetched, not assumed**, because
per-skill or per-plugin cost attribution would have bound instruction
economy. It has none: attribution is PR-level only. (The
per-skill/per-plugin usage breakdown is a consumer-side `/usage` dialog,
not an authoring input.) |
| `network-config` | Not relevant, and the third clause of the test is
why rather than the family label: proxy, custom CA, and mTLS are
**transport configured on the client**, so a skill making a network call
either succeeds or sees an ordinary failure — there is nothing to
declare or degrade. Its two plugin-adjacent lines are egress allowlist
entries a network admin sets, not a plugin (`downloads.claude.ai` for
"Plugin executable downloads"; `storage.googleapis.com` for "plugin
metadata shown in `/plugin`"). |
| `corporate-launcher` | Not relevant, checked against the page rather
than dismissed as admin tooling: `CLAUDE_CODE_PROCESS_WRAPPER` wraps
"every process Claude Code launches **from its own binary** — the
background service, every session it hosts in agent view, and Claude
Code's relaunches after an update". A plugin's
`${CLAUDE_PLUGIN_ROOT}/bin/` invocation is a Bash-tool subprocess, not a
Claude Code self-spawn, so the `bin/` stance is unaffected and owes no
change. |
| `champion-kit`, `communications-kit` | Not relevant —
internal-advocacy and rollout-comms collateral. |
| `accessibility`, `keybindings`, `terminal-config`, `voice-dictation`,
`fullscreen`, `fast-mode` | Not relevant — consumer client settings; no
plugin declares or must accommodate them. |
| `prompt-library` | Not relevant — copy-paste prompts for users, not an
authoring surface. |

**Doctrine added — one paragraph, plus four table rows.** The
cross-platform contract gains the host
axis, citing `platforms` and restating none of its facts. The three
verbatim host facts (Desktop-in-WSL
sessions lack "connectors and plugins"; `/plugin` "[doesn't] work from
the app" on mobile; Desktop's
Cowork tab sources plugins "not from the CLI's `~/.claude` directory")
live in the gate-run row, where
they carry a recheck trigger — not in the contract, which states only
the rule they establish.

**A dead citation, deliberately not fixed.** Every doc URL this repo
cites was checked live — all 81
slugs plus the 4 subpath citations (`agent-sdk/overview`,
`agent-sdk/agent-loop`, `agent-sdk/plugins`,
`whats-new/2026-w32`). **84 of 85 return 200.** One does not:
`code.claude.com/docs/en/browser` now 404s (`chrome` is the live page).
Its sole occurrence
is `plugins/playbooks/skills/boris/vendor/SKILL.md:938` — a **verbatim
upstream baseline kept for
drift detection**, which the plugin README says to treat as untrusted
and which `/playbooks:update`
owns. Hand-editing it would corrupt the vendor SHA it exists to compare.
Recorded in the `chrome` row
with that path as its recheck trigger instead.

### 2. `check-skill.sh` check 5 — KEEP the extractor as-is (decided,
recorded at the site)

Two premises are usually offered for narrowing to markdown-link targets.
Both are false, and the
comment now says so, because the premise is what keeps the question
alive:

1. **"It matches bare paths in prose."** It does not, and never did.
Both generators are delimited —
backtick-wrapped, or a `](…)` link target — and both are scoped to the
`INTERNAL_DIRS` allowlist.
Naked prose cannot match. (#2179's own summary and CHANGELOG entry
describe it as extracting
"prose and inline-code refs"; the in-script wording is corrected here to
match what the greps do.)
2. **"The backtick branch is redundant."** Measured over the 196-skill
corpus rather than argued:

   | Measure | Count |
   |---|---|
   | Backtick-form refs, all SKILL.md | 282 |
   | Link-form refs, all SKILL.md | 475 |
| **Unique backtick-form refs with no link form anywhere in the same
file** | **122** |
   | …spread across | **39 skills** |
   | …of those 122, resolving to a real file today | **122 (100%)** |

Narrowing would drop 122 real, currently-resolving supporting-file
references across 39 skills.
The link branch being the larger share is not the question; the overlap
is, and 122 refs sit
   outside it.

The false-positive risk that motivated the proposal is real but
**latent, not observed** — zero on
the current corpus. It is handled by message wording (every failure
carries `hand-verify the line
before fixing, may be an illustrative example`) rather than by deleting
coverage of 39 skills.
Reopen only if a false positive is actually observed.

### 3. Check 12's 4-skill warning floor — INTENTIONAL, no dmi carve-out
(all 4 confirmed)

#2181's reasoning holds, and upstream states the premise more strongly
than #2181 did. The skills
doc's frontmatter-behavior table gives, for `disable-model-invocation:
true`:
**"Description not in context, full skill loads when you invoke"** — so
trigger phrasing on such a
skill cannot route anything, at all. `user-invocable` defaults to `true`
(confirmed on the same page,
not assumed), so `github:setup` omitting it is slash-command-only,
exactly its declared contract.

The load-bearing half of #2181's argument is the *stranded-phrase* test,
which is an empirical claim
about the current tree, so each was re-checked against the tree rather
than against #2181's prose:

| Skill | Verdict | Confirmed against the tree |
|---|---|---|
| `discipline:wait-what` | **Right to leave** | Its description *is* the
instruction; the trigger is noticing you have stopped following. No
sibling needed — by construction the model cannot detect it. |
| `firecrawl:update` | **Right to leave** | Maintainer-only. Sibling
`firecrawl:firecrawl` **verified** to carry the consumer phrases
(`'scrape this page'`, `'crawl this site'`, `'WebFetch is blocked'`, …).
Nothing stranded. |
| `playbooks:update` | **Right to leave** | Maintainer-only. Sibling
`playbooks:boris` **verified** to carry `'how does Boris use Claude
Code'`, `'Claude Code workflow tips'`, `'optimize my CLAUDE.md'`, …
Nothing stranded. |
| `github:setup` | **Right to leave** — the weakest of the four as
originally argued, and it holds | #2181 argued from intent
("user-invoked only"). Checked instead for a stranded phrase:
model-invocable siblings `github:advise` and `github:audit` carry the
plugin's consumer-facing routing, including `'help me set up Y'`.
`setup` covers plugin *prerequisites* (gh auth, writing
`.claude/github/`), which is a deliberate slash command, not a routing
target. |

**No carve-out is added**, and that is the recorded call. Exempting
dmi-true from check 12 would
suppress a warning that is doing no harm while hiding the `kindle-dedrm`
failure mode #2181 itself
surfaced — a phrase reachable only from a skill the model can never
match. The floor stays; the
exemptions stay documented at the check-12 site.

## Verification

**Method.** Every page was fetched with `curl -sL …/<slug>.md` — the raw
markdown, not WebFetch.
That removes the summarizer and the truncation window from the loop
entirely, so the METHOD RULE
holds trivially: every upstream sentence quoted in this PR and in the
doctrine is verbatim from a
complete page, and a genuine "the page never states X" is a checkable
claim rather than a routine
false negative. Byte counts confirm no truncation (e.g. `desktop.md`
96,288 bytes, `vs-code.md`
49,764). No page was asked to confirm a sentence from this repo.

**The uncited set was re-derived, not inherited.** The grep was also
re-run with **no `--include`
filters** to be sure no citation lives in a file type the filter misses
— identical result, 81
slugs, so 57 uncited is the real number.

**Every cited URL was checked live**: 84 of 85 (81 slugs + 4 subpath
citations) return 200; the
single 404 is the vendored `browser` link described above.

**The gate-1 check that decided the headline adopt** was run against the
page rather than assumed:
`feature-availability`'s section headings are *Availability by model
provider*, *Availability by
subscription plan*, and *Model availability* — no host-surface axis —
and its only feature table
header row is `| Feature | Pro | Max | Team | Enterprise |`. Had it
carried a host axis, `platforms`
would have been a redundant second index and this would be a decline
instead.

Gates run the CI way, against the **committed** tree, base-ref form:

| Gate | Result |
|---|---|
| `bash scripts/check-contract-slice-prune.sh --check-diff origin/main`
| pass — leaves no path under `docs/topics/` |
| `bash scripts/check-changelog-parity.sh --check-bump origin/main` |
pass |
| `bash scripts/check-changed-skills.sh origin/main` | pass — no changed
skills |
| `bash scripts/check-skill-portability.sh origin/main` | pass — no
skill files in scope |
| `bash scripts/check-shell-portability.sh origin/main` | pass — no
unexcused GNU-only constructs |
| `npx --yes markdownlint-cli2` over all 3 changed `.md` | **0 errors**
|
| `shellcheck` + `shfmt -i 2 -d` on `check-skill.sh` | clean |
| `bash -n check-skill.sh` | clean |
| Line endings | all 5 changed files `i/lf w/lf` |

Because the change to `check-skill.sh` is comments only,
`check-changed-skills.sh` exercises
nothing — so the script was run directly to prove it still parses and
behaves:

- `check-skill.sh measure` → `PASS — 0 errors, 0 warning(s)`, `all 10
base-ref trigger phrase(s) preserved`.
- `check-skill.sh wait-what` → `PASS — 0 errors, 2 warning(s)`, one of
which is verbatim
`description has no 'Use when:' trigger phrasing` — confirming the
documented floor still fires as
  described rather than being silently suppressed.
- `check-skill.test.sh` runs to completion in CI (`plugin-gate`);
locally on Windows/Git Bash it is
impractically slow, per the coverage note #2179 recorded. Nothing here
is behavioral.

`plugins/skill-quality` → **0.15.2** with a matching `## [0.15.2]`
entry. The `docs/` changes are
docs-only and owe no plugin bump; the `upstream-drift` **Adopters**
registry already carries a row
for the gate-run table (added in #2177), and these rows join that table
rather than create a new
adopter, so that convention needs no version change.

`docs/OFFICIAL-DOCS.md` gains the four newly load-bearing pages, per the
rule its own warning states
and the precedent #2177's review set: a needed page that is not listed
must be added.

No `docs/topics/<slug>/` directory was created — the durable outcome is
doctrine text, as the
Contract-tier prune rule requires.

## Review rounds

Three threads, all real, all answered and resolved. Each found a defect
in the *basis* of a row
rather than in its verdict, which is the failure mode a decision record
most needs caught: a verdict
outlives the reasoning nobody re-reads.

- **The GHES row's premise was overstated and its trigger fired on
arrival** (`chatgpt-codex-connector`).
It claimed "every plugin README ships the github.com shorthand".
Re-derived from the tree: 54 of 65
carry the literal string, 9 carry no install block, `dometrain` points
at another github.com
marketplace, and `plugins/github/README.md` — deliberately
marketplace-agnostic — uses the
`<marketplace-owner>/<marketplace-repo>` placeholder. All are still
`owner/repo` shorthand, so the
trigger now names the form that actually signals a non-github.com host,
a **full git URL**, of
which the tree has none. The verdict stays Decline, but the review
surfaced a real finding that had
been waved through and is now recorded in the row: a consumer
redistributing the `github` plugin
from a GHES-hosted marketplace would follow that README and have the
shorthand silently resolve to
  github.com instead of their own instance.
- **"Platform" was doing two jobs** (`chatgpt-codex-connector`). The
existing `feature-availability`
row and `docs/OFFICIAL-DOCS.md` both described that page as covering
"platform, provider, and plan",
while this change rests on the host axis being absent from it. Both
senses of the word in one table
would let a future audit read the host axis as already covered and
retire the new row as redundant.
The page's own sense is the **provider** platform — its axis headings
are *Availability by model
provider* and *Availability by subscription plan* — and both sites now
say so explicitly.
- **The `platforms` row claimed four evidence pages and quoted three**
(`claude`). Correctly
diagnosed as a missing fact rather than an overstated page: `vs-code`
does carry a host-axis fact,
and the most directly plugin-relevant of the four — its CLI-vs-extension
table gives
`Commands and skills` as `All` for the CLI against `Subset (type / to
see available)` for the
extension, so a skill this fleet ships may not be reachable there. It is
now quoted in the row.

All gates and `markdownlint-cli2` re-run clean over the changed files
after these edits. CI is green,
including `plugin-gate` — which runs `check-skill.test.sh`, the only
executable proof that the
check-5 comment insertions changed no behavior.

## Related

- #2177 — established the Recorded-gate-runs table and its four-part row
form; this run extends it
  and corrects its page census (112 → 135 core pages, ~33 → 57 uncited)
- #2179 — deferred the check-5 extractor question as "a separate call";
decided here
- #2181 — swept 196 skills for `Use when:` phrasing and left 4 with
stated reasoning; all 4 re-reviewed
  and confirmed here
- #2169 — the gate doc-currency audit these findings trace back to

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
The repo carries ~291 dated verification stamps (`verified`/`fetched`/`as of`
2026-MM-DD) spanning 2026-07-15 to 2026-08-08. PR #2169 re-verified only the
~8 claims a gate or check skill directly enforces; the rest had gone unchecked
for up to four weeks, which is exactly the drift a dated stamp exists to
surface. A stamp nobody re-reads is worse than no stamp: it advertises a
currency the claim does not have.

WHY THE VERIFICATION IS TRUSTWORTHY THIS TIME. Previous passes fetched pages
through WebFetch, which summarizes through a small model and truncates long
pages, so "the page does not say that" was a routine false negative and no
negative claim could be settled. This pass reads
`https://code.claude.com/docs/en/<page>.md`, which returns the complete raw
markdown source (hooks alone is 249 KB), and greps it. Every CONFIRMED claim
here is backed by a verbatim string match against the full page, and the two
negatives asserted below are sound because the whole page was in hand.

WHAT MOVED. 50 stamps on claims re-confirmed by verbatim quote had their dates
refreshed to 2026-08-10. Two claims are corrected:

- `scripts/check-silent-skips.sh` said exit-0 hook stderr is "discarded
  entirely". The hooks reference says it "goes to the debug log only, never the
  transcript, and Claude never sees it". The gate's conclusion is untouched — a
  debug-only sink is not a visibility surface — but the comment now states what
  upstream states.

- `context-guard`'s reader contract quoted a statusline sentence, "Before
  v2.1.132 these were cumulative session totals", that upstream has since
  removed. The dead quote is replaced with an explicit sourcing-status note.
  The 2.1.132 floor itself is deliberately kept: it is conservative, dropping it
  could only widen which payloads the token shape trusts, and the misfire it
  prevents is silent.

WHAT WAS NOT CHECKED, AND WHY. CHANGELOG entries and `docs/topics/**` records
describe what was true when written — re-dating them would falsify the record,
so they were read only to confirm that character and left alone. `env-vars`
claims were skipped by assignment. Claims sourced to platform.claude.com,
github.com, or this repo's own gate runs are outside a Claude Code docs pass.
Full coverage table in the PR body.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdBsorqGjCU4Mg5nrmgz4m
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
The repo carries ~291 dated verification stamps (`verified`/`fetched`/`as of`
2026-MM-DD) spanning 2026-07-15 to 2026-08-08. PR #2169 re-verified only the
~8 claims a gate or check skill directly enforces; the rest had gone unchecked
for up to four weeks, which is exactly the drift a dated stamp exists to
surface. A stamp nobody re-reads is worse than no stamp: it advertises a
currency the claim does not have.

WHY THE VERIFICATION IS TRUSTWORTHY THIS TIME. Previous passes fetched pages
through WebFetch, which summarizes through a small model and truncates long
pages, so "the page does not say that" was a routine false negative and no
negative claim could be settled. This pass reads
`https://code.claude.com/docs/en/<page>.md`, which returns the complete raw
markdown source (hooks alone is 249 KB), and greps it. Every CONFIRMED claim
here is backed by a verbatim string match against the full page, and the two
negatives asserted below are sound because the whole page was in hand.

WHAT MOVED. 50 stamps on claims re-confirmed by verbatim quote had their dates
refreshed to 2026-08-10. Two claims are corrected:

- `scripts/check-silent-skips.sh` said exit-0 hook stderr is "discarded
  entirely". The hooks reference says it "goes to the debug log only, never the
  transcript, and Claude never sees it". The gate's conclusion is untouched — a
  debug-only sink is not a visibility surface — but the comment now states what
  upstream states.

- `context-guard`'s reader contract quoted a statusline sentence, "Before
  v2.1.132 these were cumulative session totals", that upstream has since
  removed. The dead quote is replaced with an explicit sourcing-status note.
  The 2.1.132 floor itself is deliberately kept: it is conservative, dropping it
  could only widen which payloads the token shape trusts, and the misfire it
  prevents is silent.

WHAT WAS NOT CHECKED, AND WHY. CHANGELOG entries and `docs/topics/**` records
describe what was true when written — re-dating them would falsify the record,
so they were read only to confirm that character and left alone. `env-vars`
claims were skipped by assignment. Claims sourced to platform.claude.com,
github.com, or this repo's own gate runs are outside a Claude Code docs pass.
Full coverage table in the PR body.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FdBsorqGjCU4Mg5nrmgz4m
kyle-sexton added a commit that referenced this pull request Aug 11, 2026
#2187)

No linked issue

## Summary

The repo carries **327 dated verification stamps** (`verified` /
`fetched` / `as of` 2026-MM-DD), spanning 2026-07-15 → 2026-08-08. PR
#2169 re-verified only the ~8 claims a gate or check skill directly
enforces. The rest had gone unread for up to four weeks — which is
exactly the drift a dated stamp exists to surface. A stamp nobody
re-reads is worse than no stamp: it advertises a currency the claim does
not have.

This PR re-verifies **72 stamps** against the live upstream pages and
reports honestly on the 49 upstream claims it did not reach.

### The method change that makes this pass different

Earlier passes fetched docs through `WebFetch`, which summarizes through
a small model and **truncates long pages**. Under that route "the page
doesn't say that" is a routine false negative, so no negative claim can
be settled and no drift classification is safe.

This pass reads **`https://code.claude.com/docs/en/<page>.md`**, which
returns the complete raw markdown source (`content-type:
text/markdown`), and greps it:

| page | raw bytes |
| :-- | --: |
| `hooks.md` | 249,026 |
| `settings.md` | 290,489 |
| `changelog.md` | 525,429 |
| `sub-agents.md` | 96,094 |
| `plugins-reference.md` | 90,982 |

Every CONFIRMED claim below is backed by a verbatim `grep -F` match
against the full page. Two **negative** claims are now assertable for
the first time, because the whole page was in hand rather than a
truncated slice:

- `docs/conventions/hook-observability/README.md` — no native "verbose
hooks" toggle exists.
-
`plugins/claude-memory/skills/stateless/reference/official-guidance.md`
— no settings-precedence exception bullet names `autoMemoryEnabled`,
`CLAUDE_CODE_DISABLE_AUTO_MEMORY`, or auto memory.

One caution for the next person: markdown **link flattening** causes
false misses. Four `sub-agents` quotes appeared to have vanished until
inspection showed the only difference was
`[fork](#fork-the-current-conversation)` becoming `a fork`. All four
were verbatim-intact. Grep on a link-free fragment.

## Fix

### Drift found and corrected (3)

**1. `scripts/check-silent-skips.sh` — exit-0 stderr is not "discarded
entirely".**

The gate comment claimed exit-0 hook stderr is "discarded entirely". The
hooks reference says:

> Stderr from a hook that exits 0 goes to the debug log only, never the
transcript, and Claude never sees it.

The debug log is the one place it survives. **The gate's conclusion is
untouched** — a debug-only sink is not a visibility surface, so a
`>&2`-only notice on an exit-0 skip path is still invisible to both user
and agent. The comment now states what upstream states, and records the
correction so the next reader does not re-derive it.

**2. `context-guard` — the 2.1.132 token-semantics floor lost its
upstream source.**

`reference/reader-contract.md` quoted the statusline page as saying
*"Before v2.1.132 these were cumulative session totals"*. That sentence
**is no longer on the page**, and the version number went with it. What
the page still states is only the present-tense semantics the floor
depends on — "Token counts currently in the context window, from the
most recent API response".

The dead quote is replaced with an explicit sourcing-status note;
`scripts/statusline-tee.sh` carries the same note at its `cli_version`
comment.

**The floor itself is deliberately unchanged.**
`TOKEN_SEMANTICS_MIN_VERSION` still gates the token shape at `>=
2.1.132`; no behaviour, test, or zone result moves. Dropping it could
only *widen* which payloads the token shape trusts, and the misfire it
guards against is silent — a pre-2.1.132 cumulative 170k in a 200k
window reads as a perfectly plausible current occupancy and resolves
`dumb` while the live context may be smart-zone. It stays as a
conservative lower bound, now labelled as retained-not-doc-backed.
Re-source before any change that relaxes it.

**3. Both `statusline-shim.sh` copies cited a plugins-reference section
that no longer exists.**

The 14-day orphaned-cache grace period was attributed to a section
titled *"Plugin cache and file access"*. Upstream renamed it to
**"Plugin caching and file resolution"** (cache root
`~/.claude/plugins/cache`). The behaviour cited is unchanged and still
stated verbatim — but a citation whose section title has vanished cannot
be followed, which is precisely the rot a dated stamp exists to expose.
Both comments now name the current title and record the former one.

### Scope correction (1)

`docs/PLUGIN-PHILOSOPHY.md` — the "Pages load-bearing for this document"
stamp covered seven bullets, one of which is a
`melodic-software/standards` file, not a Claude Code page. The refreshed
stamp now says so explicitly instead of implying the whole list was
re-checked. The six Claude Code pages were each re-fetched and confirmed
to still carry the topics named beside them (`Plugin manifest schema`,
`Version management`, `Plugin caching and file resolution`, `Persistent
data directory`, `Hooks in skills and agents`, `Tag plugin releases for
version resolution`, `pluginConfigs` read scopes).

### Confirmed and re-dated (no claim changed)

`docs/PLUGIN-PHILOSOPHY.md` ·
`docs/conventions/hook-observability/README.md` · gate/hook/script
comments in `check-silent-skips.sh`, `post-compact-mark.sh`,
`record-rate-limit-stop.sh`, `packet-seal.sh`, `destructive_guard.py`,
`skill-reference-verify.sh`, `markdown-format.sh`, `typos-format.sh`,
`check-structure.sh`, both `statusline-shim.sh` · and skill
bodies/references across `claude-config`, `claude-memory`, `claude-ops`,
`context-guard`, `discipline`, `disk-hygiene`, `guardrails`,
`implementation`, `plugin-quality`, `rate-limit-guard`, `session-flow`,
`work-items`.

The densest single block,
`session-flow/skills/orchestrate/context/sources.md` (13 stamps), was
re-checked quote by quote against `sub-agents`, `workflows`,
`changelog`, and `whats-new/2026-w32`. All still match. Its 0.22.2
finding is independently re-confirmed: the sub-agents page now states
outright *"There's no limit on the total number of subagents Claude can
spawn over a session"*, and `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION`
appears nowhere on it.

## Verification

### Coverage — all 327 stamps accounted for

**The first version of this table was wrong, and review caught it.** It
was built from a single-line regex, `(verified|fetched|as of)
2026-[0-9]{2}-[0-9]{2}`. This repo hard-wraps prose, so a stamp whose
keyword ends one line and whose date begins the next is invisible to it
— **30 stamps were hidden that way**, and the denominator I published
(291) was itself understated. The wrap-aware pattern is:

```
(verified|fetched|as of)\s*(?:
\s*(?:[#>*-]\s*)?)?(2026-\d{2}-\d{2})
```

Buckets below are disjoint and sum to the total; nothing is hidden in a
residual.

| Bucket | Count | Treatment |
| :-- | --: | :-- |
| **Dated 2026-08-10 (current)** | **104** | 72 refreshed by this PR
after verbatim confirmation; 32 already current from PR #2169, #2184 and
other in-flight work |
| CHANGELOG entries | 69 | **Left alone.** A CHANGELOG entry describes
what was true when written — re-dating it would falsify the record |
| Upstream Claude Code doc — **not re-checked** | **49** | Honest gap.
See below |
| Repo-internal claims (no external page) | 47 | Out of scope for a
docs-currency pass — recorded gate runs, this repo's own probes |
| Non-upstream sources | 25 | `platform.claude.com`, `claude.com/blog`,
`github.com`, `git-scm.com` — different corpus |
| `docs/topics/**` | 29 | **Left alone.** Records of what was true when
written; Contract tier, gated |
| `env-vars`-cited | 4 | Skipped by assignment — a parallel agent owns
that route |
| **TOTAL** | **327** | |

The brief estimated ~260; the wrap-aware regex above is the number.

### The line I drew, stated before the work started

Verify, in order: (1) every `docs/PLUGIN-PHILOSOPHY.md` claim; (2) every
code-comment claim inside a gate, hook, or script, since those are
load-bearing for behaviour; (3) skill-body and reference claims on pages
obtained in full. Deprioritize READMEs and CHANGELOGs as historical
record, and leave `docs/topics/**` alone.

**What that leaves unchecked: 49 upstream claims**, thinly spread —
`docs/conventions/loop-lane/README.md` (8), `docs/MIGRATION-PLAYBOOK.md`
(4), `docs/PLUGIN-PHILOSOPHY.md` (3, each a stamp spanning a
`platform.claude.com` page alongside Claude Code pages — see below), and
`playbooks/**` (9, mostly `platform.claude.com`-adjacent
model-calibration notes). No other file has more than 2. These are
reachable by the same method and are the natural next slice; they were
cut for depth over breadth, not because they are lower risk.

Three `PLUGIN-PHILOSOPHY` stamps cover several pages at once, at least
one of them outside this corpus. Where I verified the Claude Code pages
but not the `platform.claude.com` one under the same stamp, I left the
date alone rather than refresh a stamp that also vouches for a page I
did not open. The same rule produced the scope correction above.

**No stamp was re-dated without a verbatim quote retrieved this
session.** Every one of the 12 stamps added in the review round was
already backed by a quote pulled in the original sweep; none was newly
assumed.

**Every stamp in a file this PR claims to have verified now carries the
new date.** That was not true in the first push — review caught
CHANGELOG entries asserting more than the diff delivered — and the
wrap-aware regex above is what makes the claim checkable rather than
assertable. Bumping a date on a claim I could not locate would launder
an unverified claim into a fresh stamp — strictly worse than leaving it
stale, and invisible to review. Where a claim could not be confirmed it
kept its old date and sits in the 46.

### Gates (CI form, committed tree)

- `bash scripts/check-contract-slice-prune.sh --check-diff origin/main`
— pass
- `bash scripts/check-changelog-parity.sh --check-bump origin/main` —
pass
- `bash scripts/check-skill-portability.sh origin/main` — pass
- `npx markdownlint-cli2 <43 changed md files>` — 0 errors
- `bash scripts/check-changed-skills.sh origin/main` — pass (10 skills
checked, 0 failed)

14 plugins touched, each patch-bumped with a `## [x.y.z]` CHANGELOG
entry. Pure-`docs/` changes carry none. No `docs/topics/<slug>/`
created.

## Related

- PR #2184 — landed on `docs/PLUGIN-PHILOSOPHY.md` while this was in
flight; rebased onto it, and its richer model/effort corrections were
kept over this PR's date-only edits at every conflict
- PR #2169 — the prior audit whose ~8 gate-enforced claims are treated
here as fixed points and not redone
- The `.md`-endpoint route was shared with the parallel `env-vars`
effort, whose truncation problem it also solves

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant