Skip to content

discipline:sweep-all — the fork stop-rule is inert (no detection mechanism) and contradicts setup's declared degraded mode #1621

Description

@kyle-sexton

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

  1. 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.

  2. 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.
  3. 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).

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: highSignificant impact, or blocks an imminent release; staff this cycle.status: needs-decisionAwaiting a human or maintainer judgment call.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions