mk:loop
What This Skill Does
Improves ONE scalar metric through bounded autonomous iterations: pick one atomic change -> commit -> verify -> keep if the number improved, otherwise git revert. Git history is the loop's memory; a TSV log, a summary, and a handoff JSON are the artifacts. Autonomy is boundary-gated -- one human approval before the loop starts, then hands-off iteration up to a hard cap, with hard re-gates on cap-reached, stuck/plateau, and scope-expansion. It never plans, never grades behavior, and never ships.
When to Use
- An objective, fast (<30s)
Verifycommand prints a single number - A
Scopeof editable file globs is known - You want N git-tracked trials with automatic keep-on-improve, revert-on-regress
- NOT for subjective goals ("make it cleaner") -- use
mk:cook - NOT for a known-root-cause bug -- use
mk:fix/mk:investigate - NOT for behavioral grading of a running build -- use
mk:evaluate - NOT for shipping -- use
mk:ship
Core Capabilities
- One atomic change per iteration -- attribution stays clean (one sentence, no "and")
- Commit before verify -- git is the undo mechanism, every trial is a recoverable SHA
- Keep/revert on a mechanical delta -- keep if improved >= Min-Delta, else
git revert - Noise-aware verification -- low/medium/high modes use single / worse-of-two / median
- Conventional commits --
test/refactor/perf/fix/chore(loop):classified per change - Safety screen -- refuses destructive or fetch-and-exec Verify/Guard commands; masks secrets
- Stuck / plateau detection -- shifts strategy autonomously, then escalates to a human gate
Configuration
| Field | Required | Default | Description |
|---|---|---|---|
Goal | yes | -- | What to improve |
Scope | yes | -- | Glob(s) for editable files |
Metric | yes | -- | Name + unit |
Direction | yes | -- | higher or lower is better |
Verify | yes | -- | Shell command that prints one number |
Guard | no | none | Regression check; exit 0 = pass |
Iterations | no | 10 | Hard cap before the re-gate |
Noise | no | medium | low / medium / high |
Min-Delta | no | derived | Minimum improvement to count as progress |
Stop-At | no | none | Target value; crossing it ends the loop |
Missing required fields trigger one batched question -- no command runs until they are supplied.
Hard Gates
Four human stops, at boundaries only (never per iteration):
| Gate | When | Choice |
|---|---|---|
| A -- Entry | After config parse + safety screen + git checks | Approve / Edit / Cancel |
| B -- Cap | Iteration cap reached | Stop / Approve N more |
| C -- Escalation | Stuck or plateau | Stop / Shift strategy / Approve more |
| D -- Scope expansion | A change needs a file outside Scope | Approve wider scope / Decline |
No file is edited before Gate A is approved.
Usage
/mk:loop Goal: Increase line coverage in src/utils to 80% \
Scope: src/utils/**/*.ts, tests/utils/**/*.test.ts \
Metric: line coverage % Direction: higher \
Verify: npx jest --coverage --coverageReporters=json-summary 2>/dev/null | node -e "console.log(require('./coverage/coverage-summary.json').total.lines.pct)" \
Guard: npx tsc --noEmit && npm test Iterations: 15Output
On completion the loop writes to tasks/reports/loop-{YYMMDD-HHMM}-{slug}/:
loop-results.tsv-- one row per iteration (baseline / keep / discard / guard-failed / crash / no-op)summary.md-- baseline -> final, kept/discarded counts, kept-commit SHAs, stop reasonhandoff.json-- machine-readable result for downstream skills
Secrets are masked in all three.
Handoff
mk:loop is a leaf executor -- user-invoked, suggests downstream skills, never called by orchestration skills. Upstream: mk:plan-creator / mk:scout supply the metric and scope. Guard suggestion: mk:verify. Downstream: mk:review (structural review of kept commits), mk:evaluate (optional behavioral check after the loop), mk:ship (manual PR, never auto-chained).
Pro Tips
- Wrap Verify in
| tail -1so a chatty command still yields a single trailing number - A clean git tree is mandatory -- commit or stash your own work first; the loop never auto-stashes
- Always set a Guard for code projects -- it is the main defense against "metric gaming" (moving the number while breaking intent)
- Keep the cap low -- 10 reaches Gate B sooner so you re-confirm intent before more spend
- Squash before shipping -- kept
*(loop):commits can be interactively squashed at the end
Canonical source:
.claude/skills/mk-loop/SKILL.md