>- corrections, classify them, choose the cheapest layer that would have prevented them (instruction, skill, lint/CI check, test, automation, or product bug report), open a PR with an evidence block, then re-measure after K days and keep, escalate or revert. Opens PRs, so it runs only on `/lever steer` or an explicit ask ("mine my corrections", "why do I keep telling you X", "didn't I give you a skill for this"), or when prompt-mirror reports the same correction class in 3+ sessions and you say go.
npx skills add https://github.com/github/lever --skill steer-once
Correct an agent once; the repo remembers. An apology from the agent changes nothing next session. A merged rule does. This skill takes corrections you have typed more than once, finds the layer that would have prevented them, lands the smallest durable change there with evidence, and checks a week later whether the correction actually stopped. If it didn't, it climbs one layer; if the rule made things worse, it proposes a revert.
prompt-mirror report listing a class with ≥N hits across ≥3 sessions.Not for one-off preferences, a single bad turn, or anything already handled by an open steer-once PR.
prompt-mirror's extractor (local, redacted, source-filtered):python3 <skills-dir>/prompt-mirror/scripts/mine_sessions.py --since 21d [--repo owner/name].
Use correction_classes, repeated_correction_phrases, and each message's classes/flags. Read messages.jsonl for the instances.
changes_requested reviews and review comments on agent-authored PRs (for example gh pr list --author app/copilot-swe-agent --state all, then gh api repos/{owner}/{repo}/pulls/{n}/reviews). Same pipeline, no local history needed.docs/autonomy.md. State the scope and autonomy level in one line.| Class | The agent… | Typical correction |
|---|---|---|
| gate | invented approvals, locks, preflights, "exact GO" phrases | "you don't need authorization" |
| over_ask | asked for what it already had | "don't ask, just do it" |
| premature_stop | treated a milestone as done | "why did you stop?" |
| polling | waited or slept instead of doing parallel work | "why are you waiting?" |
| status_gap | made the human poll for state | "status? ETA?" |
| verification_theatre | let checking replace shipping | "what did you spend 3 hours on?" |
| stale_claim | reasoned from a proxy (stale clone, cache) | "that's not true, check the live source" |
| shallow_fix | suppressed the symptom | "actually fix it instead of disabling lint" |
| letter_of_law | shrank an ambitious ask | "I asked for the orchestrator pattern" |
| scope_creep | did unrequested side quests | "why did you open a PR there?" |
| process_default | lacked a team default procedure | "breaking changes are always two-phase" |
| runtime_gap | hit something no prompt can fix | "rekick the stalled sessions", quota, leaked processes |
.github/copilot-instructions.md, .github/instructions/*.instructions.md (applyTo scope), AGENTS.md, .github/skills/*/SKILL.md, .github/lever.yml, and personal ~/.copilot/copilot-instructions.md. If a rule exists and the class still recurs, the finding is "rule exists but is weak, misplaced or not loaded". Fix placement or wording, or escalate a layer, before adding more prose.| The expectation is… | Layer | Example |
|---|---|---|
| A personal posture (tone, verbosity, how you like updates) | Personal instructions | "Report as x → y (Δz%); no preamble" |
| A repo-wide default posture | .github/copilot-instructions.md (one line, with the why) | "Pre-launch service: ship and monitor; don't add approval gates" |
| Authority or autonomy | A dial in .github/lever.yml, not prose | autonomy: L3 with the grant recorded |
| A task-specific procedure | Scoped instruction or skill rule | expand → migrate → contract for breaking changes |
| Mechanically detectable | Lint or CI check | no new eslint-disable without a linked issue |
| Behavioural | A test that fails today | the service recovers from a stuck lease by itself |
| Timing or liveness | Hook or automation (see automate-it) | resume idle child sessions on wake |
| Outside the agent's control | Product or infra bug report | sessions don't auto-resume after sleep |
Corrections that cluster on one dial (merge authority, stop policy, status cadence, validation depth) become a dial change, not a new rule.
10. Record in the ledger: class, rule, layer, PR, baseline rate, re-measure date.
11. Re-measure after K days (and at least M typed messages in scope). Re-run the extractor for the same scope. Compare the class rate per 100 typed messages with the baseline, and with the week-to-week spread of that class over the previous 4 weeks.
### steer-once evidence
- **Class:** premature_stop: agent treated a milestone as done while ready work remained
- **Window / scope:** 2026-10-01 → 2026-10-21, this repo, typed messages only
- **Count:** 9 corrections in 4 sessions = 1.6 per 100 typed messages (baseline)
- **Agent concessions on this class:** 5 ("You're right…"), followed by repeats
- **Existing rule:** none | `path:line` exists but recurred (placement/wording issue)
- **Quotes** (redacted, dated, ≤20 words each, 3–5):
- 2026-10-04 "why did you stop? there is more in the queue"
- 2026-10-09 "if you're idle, take the next ready item"
- **Layer:** repo instruction. Cheaper layer insufficient because: … Costlier layer unnecessary because: …
- **Keep bar:** rate ≤ 50% of baseline and outside 4-week noise, re-measured on 2026-10-28 (K=7) or after 150 typed msgs
- **If not met:** escalate to <next layer>
| Dial | Default | Options |
|---|---|---|
| Detection threshold | N=3 hits across ≥2 sessions in 21 days | any N / window |
| Mode | open PR (L2, human lands) | propose in chat; draft PR (L1); self-merge per docs/autonomy.md grant |
| Destination | repo for shared expectations, personal for posture | repo only; personal only |
| Evidence | redacted quotes + counts, shown to user before publishing | counts only; paraphrase |
| Re-measure | K=7 days and ≥150 typed messages in scope | any K / M |
| Keep bar | ≤50% of baseline and outside noise | any threshold |
| Max open steer-once PRs | 3 | any |
| Severity weighting | off | weight mid-turn steers and heated messages higher (never quote heated ones) |
steer-once, with the evidence block. The label is the team ledger.~/.copilot/lever/steer-once.ledger.md, format per templates/ledger.md): keep, escalate or revert, with before/after rates.Per rule: class rate per 100 typed messages, before and after. Across rules: share kept versus escalated versus reverted; concession openers per 100 agent replies (should fall); time from first occurrence to merged fix (should shrink). If most rules escalate, the skill is choosing layers too cheaply. If any rule raises a neighbour class, the skill is writing over-broad rules.
Take github/steer-once from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.