Skip to content

1.0.10 — minions: fan out to gather, and keep the thinking

Choose a tag to compare

@ReidenXerx ReidenXerx released this 17 Aug 15:34

Added — Minions, a fifth module: fan out to gather

The README carries a generated diagram for it like every other module — the fan-out is only half
the picture, so it shows what comes BACK (citations, not opinions) and where the conclusion is
drawn.

Your agent can already spawn subagents. What it does not know is when it should — so it grinds
through forty files serially, or samples five and generalises. That judgment is the module; the
fan-out is plumbing.

Fan out when the work is bounded, verifiable, independent and wide (3+ units): every call site
of a symbol, every file still on the old API, every migration site, every route to audit against one
rule. Don't when the judgment is the work, when the answer only survives verbatim, or when the
unit needs context the subagent was never in.

Each subagent carries the project's north-stars and pinned persona, and returns a fixed shape:

FOUND    src/fees.ts:88 — const fee = gross * RATE
CHECKED  rg "\* RATE" src/ --type ts
MISSED   dynamic dispatch in src/plugins/ — could not resolve

Minions gather; your agent concludes — they do minimal or zero reasoning. A subagent returning a
verdict puts a cheaper model's summary between the evidence and your decision, which is the drift
this product exists to prevent. And the CHECKED/FOUND split is load-bearing: CHECKED filled
with FOUND empty means it looked and there was nothing; both empty means it never understood the
task
. In prose those are the same sentence — the same error as reading a graph zero as absence.

Claude Code only, since it is the only runtime that can spawn subagents with a model choice — the
README says so rather than implying parity.

Added — the fan-out trigger is now enforced, and citations are checkable

Four follow-ups that turn minions from instructions into something with feedback.

  • A nudge when you are grinding. The trigger lived only in the always-on contract, which means
    it fired when the agent happened to recall it. A PostToolUse hook now notices 8 distinct gather
    targets in a row with no delegation and suggests fanning out — once per session, advisory, never a
    block (NS-5). Distinct targets, not calls: re-reading one file while editing it is not grinding,
    and a nudge that fires during every edit loop gets ignored forever. minionFanoutThreshold: 0
    disables it.
  • node .bearing/lib/verify-citations.mjs src/a.ts:88 prints what is actually on each cited
    line and exits non-zero if any do not resolve. "Spot-check one per minion" was advice; a
    fabricated file:line is the one failure the return shape cannot catch by itself. Deliberately
    not an npm script — those are all owned by the GitNexus module, so a minions-only install could
    not run it.
  • Fan-outs and grind-nudges are counted in the scorecard, so the module can be measured rather
    than assumed — the same reason the gates keep a tally instead of asserting they help.
  • Subagents inherit graph-first. A minion grepping for call sites in a repo with a graph is
    doing the exact thing the gates exist to redirect, one level down where no gate can see it.

Also fixed: the context-pressure nudge still named the old shared .bearing/.task-core.md, so it
sent the agent to write a core its own recovery would not read.

Added — minions run on a middle tier, and wanting a smarter one is a smell

sonnet by default, overridable per machine via minionModel in .bearing/hooks.local.json. If
the tier is unavailable the fan-out runs anyway — a costlier minion is a nuisance, a skipped unit is
a hole in the answer.

The tier is not a cost setting, it is a consequence: a middle model is sufficient precisely
because minions do no reasoning (NS-24). Which makes it a diagnostic. If you want a smarter
minion, you delegated judgment
— the fix is the split, not the model. Same when a unit keeps
returning MISSED: do that unit yourself rather than re-running it on a bigger model.

Changed — one spawn harness, shared by microscope and minions

Both modules send work to anchored subagents, and the mechanics are identical: the same pinned
persona from .bearing/domain.json, the same north-star subset, parallel where the runtime allows
it, and the duty to say what went unchecked. That is now authored once and rendered into both
skills, with a test that fails if a copy goes stale.

The return contract stays separate, deliberately — the two are opposite on the axis that
matters. A microscope lens must reason; opinions are the entire point of it. A minion must not
(NS-24). Unifying those would either silence the lenses or let the minions editorialise.

The fan-out threshold is now 3 units, not 5 — at three they already run concurrently, so the
round-trip is paid once rather than three times.

Fixed — domain inference read the wrong things, and a missing persona stayed quiet

Found by pinning personas on real repos, and all three failures pointed the same way: a
screen-capture app and a patient-facing health platform were both branded developer-tooling.

  • Dependencies are not identity. package.json's dependency list counted as the repo
    describing itself, so a jwt dependency scored as a strong identity signal — overriding the
    package's own description. Almost every web app depends on an auth library; almost none are
    identity products. Name, description and keywords only.
  • \bhealth\b does not match "Healthcare". The word boundary fails on the trailing care, so
    a package naming its own domain scored zero for it. A repo naming its domain should be the
    strongest signal there is.
  • The analyzer's block is not the repo's voice. bearing's own contract was stripped before
    inference, but the stats block analyze writes into CLAUDE.md — "indexed by GitNexus… use the
    MCP tools" — was not, and that alone suggested developer-tooling for a claims platform.

And an unresolved domain is now raised where it will be seen: the installer prints the
consequence ("reviews here will be generic") rather than one warn line, and the always-on
contract carries the ask so the agent meets it every session — phrased as a job it can usually
answer from the code, asked once, taking no for an answer.

Fixed — "would be committed" sent you to a .gitignore that was already correct

Found updating a real repo installed back at 1.0.6. The machine-local check reported
.bearing/.bearing-session-primed.flag as committable, but the ignore rule was present and
correct — the file had been COMMITTED before that rule existed, and git never ignores a tracked
file however good the rule is.

The check now separates the two causes and names the exit for the one you cannot fix by editing a
file: already COMMITTED, so the ignore rule cannot help — run git rm --cached <path> (NS-6).