Files
pi-skills/.agents/skills/evolve/references/metronome-gate.md
T

64 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Metronome Gate — Detecting Productive-Looking Repetition
The work-selection ladder treats "tests passed + commit landed" as productive. That signal is necessary but not sufficient: it cannot tell apart a cycle that *applied an existing template again* from one that *closed a new lane of work*. Cycles 144-154 in this repo were 7 consecutive CLI-wiring template applications — every cycle green, every commit clean, every gate happy. Only operator override at cycle 154 stopped the run.
The metronome gate adds a structural detector: when the same `mode` value repeats N times, the next rung of the ladder is forced.
## State
`mode_repeat_streak` is computed by `scripts/evolve-update-session-state.sh` from the trailing run of identical `mode` values in `cycle-history.jsonl`. It is derived, not authored — running the script after every cycle keeps it coherent.
## Thresholds
| `mode_repeat_streak` | Action |
|---|---|
| 02 | No gate. The selection ladder runs normally. |
| 34 | **Soft block.** If the selected work would produce the same `mode` value, skip to the next rung of the selection ladder. Do not abort — try the rung below. |
| 5+ | **Hard block.** Record the gap as bead/provenance evidence and require operator override (write `.agents/evolve/RESCOPE` with a new directive). The cycle is logged as `unchanged` with `selected_source: "metronome-gate-blocked"`. |
## Why the threshold is 3, not 2
A 2-cycle streak is normal: harvested work often comes in pairs (port + adapter, R + W, parent + child). A 3-cycle streak is the earliest signal that the *template* has become the work, not the *problem*. Stopping at 3 catches the failure mode early without blocking legitimate harvested-pair cycles.
## Naming discipline (operator instruction)
For the gate to work, cycle entries must use *distinguishable* `mode` values. Anti-patterns observed before this gate existed:
- `template-applied-cli-wiring-5th`, `template-applied-cli-wiring-6th`, `template-applied-cli-wiring-7th` — the suffix `-Nth` made these technically unique strings but obviously the same mode. The gate canonicalizes by stripping trailing `-Nth` / `-N` patterns before comparison.
- `wire-up-BC1`, `wire-up-BC2`, `wire-up-BC3` — the BC suffix changes but the work shape is identical. This is a *legitimate harvested-pair sequence* — three separate BCs, three real ports — and the gate correctly does NOT block here because the streak counts identical strings only. Operator distinguishes "BC-pair work" from "template metronome" by intent.
When in doubt, the operator override at threshold 5+ is the safety net.
## Worked example — cycles 144-154
```
cycle 144: wire-up-BC1 (streak: 1)
cycle 145: wire-up-BC1-pair (streak: 1, different)
cycle 146: wire-up-complete (streak: 1)
cycle 147: template-applied-cli-wiring-4th (streak: 1)
cycle 148: template-applied-cli-wiring-5th (streak: 2 after canonicalization)
cycle 149: template-applied-cli-wiring-6th (streak: 3 — SOFT BLOCK fires)
cycle 150: template-applied-cli-wiring-7th (streak: 4 — still blocked, next rung)
cycle 151..154: ... (operator override at 154)
```
With the gate active at threshold 3, cycle 149 would have skipped to the next rung of the selection ladder, probably surfacing the latent narrowness problem 5 cycles sooner.
## Interaction with idle_streak
The metronome gate fires on *productive* cycles; the dormancy gate fires on *idle* cycles. They are orthogonal:
- `idle_streak >= 2 AND generator_empty_streak >= 2` → dormancy (see Step 3 hard-gate)
- `mode_repeat_streak >= 3 AND candidate.mode == last_mode` → metronome block (skip rung)
- Both can never fire on the same cycle: idle cycles produce no work, so they cannot extend the metronome.
## Why this lives in /evolve, not /rpi
`/rpi` runs one cycle's worth of work. It has no visibility into prior cycles. The metronome is a *cross-cycle* pattern, only visible from the loop driver. `/evolve` is the only place that has both the ledger and the next-cycle decision.
## See also
- `docs/rescope/2026-05-13-ddd-hex-architecture-rescope.md` — the original operator override that prompted this gate.
- `references/cycle-history.md` — the ledger this gate reads.
- `references/scout-mode.md` — what to do with work that hits the soft-block (read + annotate, no execution).