Apply the mechanically-repairable fixes to the .minerva/knowledge/ wiki, behind a
confirmation gate. minerva:lint-fix is the mutating companion to the read-only
minerva:lint: where minerva:lint reports drift, this skill repairs the subset
that is deterministically fixable. All mutation happens inside the unit-tested
scripts/knowledge_fix.py — this skill orchestrates and gates; it does not edit
files itself (its allowed-tools omits Edit/Write).
This skill changes files. It is not read-only. Every change is shown as a plan and applied only after you confirm.
Target
The .minerva/knowledge/ corpus of the current working tree, resolved by the
fixer from git rev-parse --show-toplevel — the same per-branch semantics as the
unit-021 CI drift gate and minerva:lint.
Default-branch guard (mutating path only)
Refuse to apply fixes when the working tree is not on the default branch. Resolve
it the way ship and cleanup do (git symbolic-ref refs/remotes/origin/HEAD, then
fall back to main, then master); if the current branch differs, report and stop:
"
minerva:lint-fixonly applies fixes on<default-branch>— you're on<branch>. Wiki aggregates are reconciled on the default branch byminerva:cleanup; applying them here would put anindex.mdrewrite and neighbor edits on a work-unit branch, which is exactly the conflict that add-only promotes exist to avoid. Runminerva:lintfor a read-only report instead."
This is not a style preference. plan_index rewrites index.md wholesale and
plan_reciprocals edits neighbor entries —
the two highest-frequency merge-conflict surfaces in the repo. Doing that on a
work-unit branch silently reintroduces both.
Step 1 (--dry-run) is exempt — it writes nothing, so planning on any branch is
safe and useful. The guard gates Step 2 onward.
Step 1 — Plan (dry run, no writes)
Show what would change, via the fixer's --dry-run:
ROOT="$(git rev-parse --show-toplevel)"; PLUGIN_SCRIPTS=$(find -L "${HOME}/.claude/plugins/minerva" "${HOME}/.claude/plugins/cache/agent-marketplace/minerva" -maxdepth 2 -type d -name "scripts" 2>/dev/null | head -1); [ -n "$PLUGIN_SCRIPTS" ] && { python3 "$PLUGIN_SCRIPTS/plugin_guard.py" || exit 1; }; python3 "${PLUGIN_SCRIPTS:-$ROOT/scripts}/knowledge_fix.py" --dry-run "$ROOT/.minerva/knowledge"
It re-derives every edit from the detector's structured output (parse_index /
parse_entry), never from message text. The plan lists, per item: an index.md
rewrite (stale-line / Type-section / ordering) and/or per-entry
reciprocal-link additions, plus any REFUSED items (e.g. a forward ## Related
line with no label at all, or one whose label reads as a supersession claim without
being the exact term).
Step 2 — Gate
Present the plan to the user and wait for explicit confirmation before applying.
If the plan is empty (no mechanical fixes needed), report that and stop.
Step 3 — Apply
On confirmation, apply (the script recomputes the batch from the live corpus, so the plan can't go stale between dry-run and apply):
ROOT="$(git rev-parse --show-toplevel)"; PLUGIN_SCRIPTS=$(find -L "${HOME}/.claude/plugins/minerva" "${HOME}/.claude/plugins/cache/agent-marketplace/minerva" -maxdepth 2 -type d -name "scripts" 2>/dev/null | head -1); [ -n "$PLUGIN_SCRIPTS" ] && { python3 "$PLUGIN_SCRIPTS/plugin_guard.py" || exit 1; }; python3 "${PLUGIN_SCRIPTS:-$ROOT/scripts}/knowledge_fix.py" "$ROOT/.minerva/knowledge"
The script applies the batch atomically and then re-runs the detector to verify the corpus is clean. Report the result.
What it fixes vs. surfaces
Auto-fixed (deterministic, gated):
- Stale catalog line — an
index.mdentry whose stem has no file. - Wrong Type section — a catalog line under the wrong
## Typeheader (relocated verbatim, summary preserved, id-sorted). - Missing reciprocal — a one-way
## Relatedlink; the reciprocal label is derived from the forward label (builds on→see also;supersedes↔superseded by;contradicts/see alsosymmetric; any other label →see also). A supersession also writes the banner, always: the marker carries the superseding entry's full stem, so it can name which entry retired this one even when several entries share a date.
Safety: entry edits change only the ## Related block / banner span (a
body_complement byte-identity guard aborts the run otherwise — knowledge 016);
index.md edits preserve the canonical skeleton (H1 + the four headers incl. the
empty ## Patterns) and ascending-id order.
NOT auto-fixed — surfaced for you to handle by hand:
- Missing catalog line — needs a one-line summary (a judgment call).
- Broken
## Relatedlink — the target doesn't exist; remove it or create the entry. - Orphans / contradictions / stale claims — the LLM-judged advisory dimensions
from
minerva:lint; advisory only, never auto-applied (knowledge 013).
Out of scope
- Editing the frozen detector (
scripts/knowledge_lint.py) or the read-onlyminerva:lintskill. - Running in CI / auto-applying without the gate.
- Synthesis /
log.md(Phase C).