Summary
plugins/discipline/skills/sweep-all/SKILL.md step 1 carries a stop-rule:
if forks are unavailable, report that the inheriting audit fan-out cannot run and stop, rather than auditing blind
Nothing in the plugin defines how to determine that forks are unavailable. A grep across
plugins/discipline for fork|inherit|canary|probe|CLAUDE_CODE_ returns no detection mechanism.
A rule whose guard cannot be evaluated is inert, not merely under-specified.
Why this is HIGH, not cosmetic
With no way to evaluate the guard, the default path is the one that runs: N blind ledgers, merged
at step 3, and acted on at step 4, which instructs "correct forward … on the main thread now"
and therefore writes to the working tree. A correctness skill whose failure mode is confident,
fabricated corrections applied to real files.
This is observed, not hypothetical. A real full-batch invocation (plugin-quality:audit post-use
run, session 0666d581, 2026-07-26) dispatched eight subagent_type: "fork" audits and all
eight came back with no inherited conversation — fork mode was off and the request silently
produced fresh subagents. Two of the eight refused to fabricate a ledger from their system prompt;
that refusal is the only reason the run did not merge eight invented ledgers.
The plugin already declares the right degraded mode — in a file a sweep never loads
skills/setup/SKILL.md step 6:
Where it is off, only the session-start posture digest runs; note this so an unavailable fan-out
is expected, not a misconfiguration.
That contradicts sweep-all's "report and stop". Two contracts for one condition, and the better
one lives where a sweep never reads it — so the operator got nothing at all rather than a posture
digest.
This refutes the framing the audit was commissioned with. The commissioning brief asserted "no
degraded mode exists" and proposed building a three-rung fallback ladder. At plugin scope that is
wrong: a degraded mode is already the plugin's declared position. The fix is to stop the two files
disagreeing — not to build a ladder. The artifacts-only / main-thread-sequential ladder is
explicitly out of scope here; it re-creates the salience dilution the declared delta exists to
prevent.
Proposed fix
- A preflight step in
sweep-all, before the fan-out, in two stages:
-
Stage 1 — zero-dispatch, diagnostic only. A paired tool-schema check. Two documented
sentences combine:
So Agent lacking the parameter while Bash retains it rules out the disabled-background-
tasks cause and leaves fork mode as the documented explanation; Agent carrying it means fork
mode is not env-var-enabled. Neither branch is conclusive — the server-side rollout path is
unstated in the docs — so stage 1 never gates. It explains what stage 2 finds.
-
Stage 2 — the decider: one inheritance-proof canary, at zero extra cost. Fold the canary
into the lowest-ranked in-scope member's real audit fork: require an inheritance proof before
any audit content, and only fan out the rest once the main thread verifies it. Fail closed —
ambiguous, absent, or unverifiable proof is treated as not-inherited.
- Move the degraded mode into
sweep-all — on a failed preflight, run the session-start
posture digest, report that the inheriting fan-out could not run and which signal said so, and
name the direct-invocation path. setup keeps a one-line pointer instead of a second contract.
- Define "failure" for the existing retry rule ("retry only a failed subset, once"): a
returned ledger without valid inheritance proof is a failure. Today a fabricated ledger is not
a "failure", so the retry rule misses the actual exposure.
Verification
Verified this session against pages fetched today: https://code.claude.com/docs/en/sub-agents
and https://code.claude.com/docs/en/env-vars. Plus a first-hand probe in a fork-enabled session:
a subagent_type: "fork" dispatch inherited the conversation, and its own schemas showed Agent
without run_in_background and Bash with it — the paired inference above, observed.
Unverified and to be flagged as such in the fix: what the harness actually does when the fork
subagent type is requested while fork mode is off. The current skill states it "falls back to a
fresh general-purpose subagent"; that behavior appears on no page fetched this session. It is an
observation from the failed run, and must be labelled observed-not-documented — in a plugin whose
flagship corrector is do-your-research.
Source: plugin-quality:audit post-use audit of discipline@0.9.0 (F1/F2, F10, F13).
Summary
plugins/discipline/skills/sweep-all/SKILL.mdstep 1 carries a stop-rule:Nothing in the plugin defines how to determine that forks are unavailable. A grep across
plugins/disciplineforfork|inherit|canary|probe|CLAUDE_CODE_returns no detection mechanism.A rule whose guard cannot be evaluated is inert, not merely under-specified.
Why this is HIGH, not cosmetic
With no way to evaluate the guard, the default path is the one that runs: N blind ledgers, merged
at step 3, and acted on at step 4, which instructs "correct forward … on the main thread now"
and therefore writes to the working tree. A correctness skill whose failure mode is confident,
fabricated corrections applied to real files.
This is observed, not hypothetical. A real full-batch invocation (
plugin-quality:auditpost-userun, session
0666d581, 2026-07-26) dispatched eightsubagent_type: "fork"audits and alleight came back with no inherited conversation — fork mode was off and the request silently
produced fresh subagents. Two of the eight refused to fabricate a ledger from their system prompt;
that refusal is the only reason the run did not merge eight invented ledgers.
The plugin already declares the right degraded mode — in a file a sweep never loads
skills/setup/SKILL.mdstep 6:That contradicts
sweep-all's "report and stop". Two contracts for one condition, and the betterone lives where a sweep never reads it — so the operator got nothing at all rather than a posture
digest.
This refutes the framing the audit was commissioned with. The commissioning brief asserted "no
degraded mode exists" and proposed building a three-rung fallback ladder. At plugin scope that is
wrong: a degraded mode is already the plugin's declared position. The fix is to stop the two files
disagreeing — not to build a ladder. The artifacts-only / main-thread-sequential ladder is
explicitly out of scope here; it re-creates the salience dilution the declared delta exists to
prevent.
Proposed fix
sweep-all, before the fan-out, in two stages:Stage 1 — zero-dispatch, diagnostic only. A paired tool-schema check. Two documented
sentences combine:
run_in_backgroundparameter from the
Agenttool"CLAUDE_CODE_DISABLE_BACKGROUND_TASKS: "Set to1to disable all background task functionality, including therun_in_backgroundparameter on Bash and subagent tools"
So
Agentlacking the parameter whileBashretains it rules out the disabled-background-tasks cause and leaves fork mode as the documented explanation;
Agentcarrying it means forkmode is not env-var-enabled. Neither branch is conclusive — the server-side rollout path is
unstated in the docs — so stage 1 never gates. It explains what stage 2 finds.
Stage 2 — the decider: one inheritance-proof canary, at zero extra cost. Fold the canary
into the lowest-ranked in-scope member's real audit fork: require an inheritance proof before
any audit content, and only fan out the rest once the main thread verifies it. Fail closed —
ambiguous, absent, or unverifiable proof is treated as not-inherited.
sweep-all— on a failed preflight, run the session-startposture digest, report that the inheriting fan-out could not run and which signal said so, and
name the direct-invocation path.
setupkeeps a one-line pointer instead of a second contract.returned ledger without valid inheritance proof is a failure. Today a fabricated ledger is not
a "failure", so the retry rule misses the actual exposure.
Verification
Verified this session against pages fetched today: https://code.claude.com/docs/en/sub-agents
and https://code.claude.com/docs/en/env-vars. Plus a first-hand probe in a fork-enabled session:
a
subagent_type: "fork"dispatch inherited the conversation, and its own schemas showedAgentwithout
run_in_backgroundandBashwith it — the paired inference above, observed.Unverified and to be flagged as such in the fix: what the harness actually does when the
forksubagent type is requested while fork mode is off. The current skill states it "falls back to a
fresh general-purpose subagent"; that behavior appears on no page fetched this session. It is an
observation from the failed run, and must be labelled observed-not-documented — in a plugin whose
flagship corrector is
do-your-research.Source:
plugin-quality:auditpost-use audit ofdiscipline@0.9.0(F1/F2, F10, F13).