name: standards-drift-scan
description: Sweep the miniforge codebase for drift against .standards/**/*.mdc, then open one focused PR per coherent
theme. Use when the user asks to "scan for standards drift", "run the drift scan", "audit against miniforge-standards",
or invokes /standards-drift-scan.
argument-hint: [theme]
allowed-tools: [Read, Edit, Write, Bash, Grep, Glob, Agent]
Standards Drift Scan
Recurring quality pass over the miniforge repo. Audits the working tree against
the canonical standards pack at .standards/**/*.mdc and opens one focused PR
per coherent drift theme. The aim is a steady stream of small, mergeable
cleanup PRs — not a single sweeping refactor.
When to invoke
- User runs
/standards-drift-scan (no arg → pick highest-signal theme).
- User runs
/standards-drift-scan <theme> to target a specific area
(localization, factories, requiring-resolve, anomalies, headers).
- User says "scan for drift", "run the drift sweep", or asks for a recurring
cleanup pass.
Working assumptions
-
Run from the repo root (whichever local checkout the invoker has).
-
.standards/ is a git submodule. Before scanning, ensure it's
initialized and at the pinned commit:
git submodule update --init --recursive .standards
Skipping this leaves .standards/ empty and the drift scan silently
finds nothing.
-
Always work in a .claude/worktrees/<short-name> git worktree branched
off origin/main. Never on main directly. Per
.standards/workflows/git-worktrees.mdc.
-
One PR per theme. Three-PR cap per run unless a clearly trivial bundled
cleanup falls out.
-
bb pre-commit must pass before every push. No --no-verify. Per
.standards/workflows/pre-commit-discipline.mdc.
-
Exceptions are data, not throws — per
.standards/foundations/exceptions-as-data.mdc.
Themes (pick the one with the most signal — or the user-specified arg)
1. Localization
Raw user-visible English strings in (println …), (display/print-* …), or
(log/info logger _ _ "raw text") sites that should resolve via a
messages/t catalog key.
Excludes:
- JSON/EDN protocol output (e.g.,
hook-eval decisions) — those are wire
formats, not UI.
- Comment blocks (
(comment …)).
- Structured logger field keys like
:lsp/started — those identify the
event, not user-visible copy. The strings adjacent to them may still
need migration; judge case by case.
For each migration:
- Add keys to the component's
resources/config/<comp>/messages/en-US.edn.
- Wire them through the existing
messages/create-translator helper if the
component already has one; otherwise add a thin messages.clj mirroring
components/gate/src/ai/miniforge/gate/messages.clj or
bases/etl/src/ai/miniforge/etl/messages.clj.
- Update call sites to
(messages/t :key {…}).
See .standards/foundations/localization.mdc for the canonical rule.
2. Factory functions in tests
Per .standards/testing/standards.mdc: any test data map constructed more
than once, or any map with more than 3 fields, must come from a defn-
factory. Look for repeated inline {:event/* …} / {:task/* …} /
{:pr/* …} shapes in a single _test.clj file.
Heuristic for picking a target:
- Run
git grep -n '{:[a-z-]\+/' components/*/test/**/*_test.clj and look
for files with 3+ matches of the same key prefix.
- Skip files that already have a factory covering the dominant shape.
- Prefer contained component-test files over integration tests.
Existing examples to mirror: code-artifact / plan-artifact factories in
components/agent/test/.../artifact_session_test.clj; pr-info factory in
components/pr-lifecycle/test/.../controller_test.clj.
3. requiring-resolve smell
Lazy-resolving around load-order issues is an agent-smell; the fix is the
underlying design, not a deferred lookup. Find call sites with
git grep -n 'requiring-resolve' components bases, filter out tests, and
surface ones that look like load-order workarounds (a hard :require would
have caused a cycle).
4. Exceptions as data
Per .standards/foundations/exceptions-as-data.mdc: component interfaces
should return anomaly data, not throw. Catch only at absolute boundaries.
Look for (throw (ex-info …)) inside component interface.clj files;
refactor to return :anomalies/... maps and propagate via the response
component.
5. Headers / copyright
Per .standards/project/header-copyright.mdc: every Clojure source / test
file and every resource EDN file under components/**, bases/**, and
projects/** needs the canonical Apache-2.0 header. Find missing headers
across the full stated scope with:
git grep -L "Apache License" -- \
'components/**/*.clj' 'components/**/*.cljc' 'components/**/*.edn' \
'bases/**/*.clj' 'bases/**/*.cljc' 'bases/**/*.edn' \
'projects/**/*.clj' 'projects/**/*.cljc' 'projects/**/*.edn'
Workflow
1. Pull latest main and ensure the .standards submodule is synced:
git fetch origin main
git submodule update --init --recursive .standards
2. Spawn an Explore agent (very thorough) to identify the top 3 candidate
files for the chosen theme. Ask for absolute paths, the violation
pattern, and any obvious blockers.
3. Pick the cleanest candidate.
4. Create a worktree on origin/main using a branch name of the form
`<your-handle>/<theme>-<scope>` (e.g. `alex/loc-cli-policy`).
5. Make the change in one focused commit.
6. Run `bb pre-commit` — bail out and fix any failure before pushing.
7. Push + open PR with a `## Summary` / `## Test plan` body in the same
shape as #719, #720, #722, #724, #725.
8. Loop steps 2–7 until you've opened up to 3 PRs or `bb review` reports
zero drift across all themes.
After the PR is open:
- If Copilot leaves comments on first CI pass, address them in a
review:
follow-up commit, then gh api reply + resolve each thread.
- Don't merge — leave that to the human reviewer.
Hard limits
- Three PRs per run, max.
- Don't touch any branch you didn't create in this run.
- If
bb review reports zero drift across every theme, post a one-line
summary ("no drift found across [themes]") and exit without opening a PR.
- If you hit a CI failure or merge conflict you can't auto-resolve, leave a
note on the worktree, skip that PR, and continue with the next theme. Do
not block the run waiting for the user.
Reference PRs (good shape to mirror)
- #719 cli/main
status-cmd — single-file localization
- #720 etl base — new translator + catalog + smoke test
- #722 cli/scan — large multi-string localization with composite templates
- #724 agent artifact-session — factory functions with overrides
- #725 pr-lifecycle controller — factory + shadowing avoidance
Output
End with a one-paragraph summary listing each opened PR, its theme, and the
review state if known. If nothing was opened, say so explicitly.