John Drift-Prevention v3
John Drift-Prevention v3 (2026-05-02/03)
Genesis
On 2026-05-02, CEO asked "ovi hooks u kojem jeziku" (a QUESTION). John amplified this into a Kotlin port chain, opening MC #10586 and emergent MC #10589 before CEO intervened with "otisao si u rabbit hole again." This occurred despite v2 hooks (MC #10570) being live and registered. The root cause is structural: v2 gates fire at tool-invocation time (PreToolUse/PostToolUse), but the LLM's planning trajectory commits before the first gate fires. Both drift incidents (Kotlin rabbit-hole + AWS phantom earlier same day) unfolded across multiple turns, each individually compliant with v2 per-turn rules.
Context: feedback_john_kotlin_rabbit_hole_2026-05-02.md
v2 → v3 Progression
v2 (MC #10570) provided:
- Per-turn MC counter (one-ceo-turn-mc-cap.sh) — caps mc.js add per turn
- CEO_APPROVED token rate limit — blocks John self-issuing overrides
- Turn boundary reset (mc-turn-reset.sh) — clears MC counter on UserPromptSubmit
- Depth/emergent spawn gates (john-max-depth-gate.sh) — 3 trip-wires on Task/Agent dispatch
v2 gaps:
- No intent classification before planning — QUESTION/CRITIQUE turns treated same as DIRECTIVE
- MC counter reset did NOT clear CEO_APPROVED token counter — re-issuance mechanically impossible
- No cap on Task/Agent dispatch — Kotlin incident dispatched codecraft + sentinel-tester in same turn, both uncapped
- Per-turn enforcement only — multi-turn accumulation (MC #10586 → #10589 across two turns) not detected
v3 adds:
- Rank 1: Fix CEO_APPROVED counter reset — now resets on every UserPromptSubmit (unconditional)
- Rank 2: Intent classifier at UserPromptSubmit — emits STOP reminder to LLM context before planning on QUESTION/CRITIQUE turns; blocks mc.js add unless [CEO_APPROVED]
- Rank 3: Task/Agent dispatch cap — per-turn limit derived from Mehanik approved_subtask_count (fallback: 1)
Three Hooks
Rank 1: mc-turn-reset.sh (UPDATED)
Path: ~/.claude/hooks/mc-turn-reset.sh
Event: UserPromptSubmit (fires on every new CEO message)
What it does: Resets three counters to zero on every new CEO turn:
/tmp/john-mc-turn-counter.json(per-turn MC count)/tmp/ceo-approved-token-uses-${SESSION_ID}.count(CEO_APPROVED token uses — v3 FIX)/tmp/john-dispatch-turn-counter.json(Task/Agent dispatch count — v3 NEW)
Sample output: Silent (exit 0). Counters visible via cat /tmp/john-mc-turn-counter.json → {"count":0, "turn_id":"...", "ts":"..."}
Override: None. This is a mandatory reset per documented contract ("token valid for one turn").
Rank 2: ceo-intent-classifier.sh (NEW) + pre-mc-add-gate.sh (UPDATED)
Paths:
~/.claude/hooks/ceo-intent-classifier.sh(NEW, UserPromptSubmit)~/.claude/hooks/pre-mc-add-gate.sh(UPDATED, PreToolUse Bash)
Event: UserPromptSubmit (classifier) + PreToolUse Bash when tool=mc.js (gate)
What it does: Classifies CEO message intent into five classes:
- DIRECTIVE — action request (default, fail-open)
- QUESTION — inquiry (ends with ?, starts with Bosnian/English question word)
- CRITIQUE — rhetorical negative ("to ne radi", "broken", "nije ok")
- CONFIRM — short affirmative ("da", "ok", "yes")
- REISSUE — contains [CEO_APPROVED]
Writes result to /tmp/ceo-intent-${SESSION_ID}.json. On QUESTION or CRITIQUE, emits STOP system reminder to LLM context before planning begins. pre-mc-add-gate.sh blocks mc.js add on QUESTION/CRITIQUE unless [CEO_APPROVED] is in the command.
Sample output (stderr):
[ceo-intent-classifier] intent=QUESTION SYSTEM REMINDER [intent-gate/QUESTION]: CEO message classified as QUESTION. MANDATORY RESPONSE PATTERN: 1. Answer the question or acknowledge the critique in plain text. 2. Do NOT open MCs, dispatch agents, or run Mehanik in this turn. 3. If action seems warranted, surface a ONE-LINE option menu and STOP. 4. Wait for explicit CEO DIRECTIVE before any mc.js add or Task/Agent dispatch.
Override: Include [CEO_APPROVED] in the mc.js add command or Task/Agent dispatch prompt.
Rank 3: one-ceo-turn-dispatch-cap.sh (NEW)
Path: ~/.claude/hooks/one-ceo-turn-dispatch-cap.sh
Event: PreToolUse Task|Agent
What it does: Caps Task/Agent dispatches per CEO turn. Cap derived from most recent Mehanik marker file (/tmp/mehanik-cleared-*) field approved_subtask_count. If no marker: cap=1. Reads and increments /tmp/john-dispatch-turn-counter.json. Blocks on count > cap unless [CEO_APPROVED] in prompt.
Sample output (stderr):
BLOCKED [one-ceo-turn-dispatch-cap]: dispatch #2 in this CEO turn (cap=1 from Mehanik marker). Multi-dispatch from a single ambiguous CEO turn = drift signal (Kotlin incident 2026-05-02). If CEO explicitly authorized N agents: include [CEO_APPROVED] in dispatch prompt.
Override: Include [CEO_APPROVED] in Task/Agent dispatch prompt, OR obtain Mehanik clearance with multi-agent plan (marker will contain approved_subtask_count > 1).
Live Evidence
Proveo validation: /tmp/v3-proveo-validation.md (2026-05-02)
Suite scores:
- Suite A (Rank 1 — mc-turn-reset.sh): 4/4 PASS
- Suite B (Rank 2 — intent classifier + pre-mc-add-gate): 9/10 PASS (1 NOTE: "a" correctly defaults to DIRECTIVE per spec — not a defect)
- Suite C (Rank 3 — dispatch cap): 5/5 PASS
- Suite D (Deviations): 3/3 ACCEPT (all low-risk broadening of patterns)
- Suite E (E2E regression): 4/4 PASS
Verdict: PASS. No blocking defects. All 3 ranked recommendations correctly implemented and verified with real hook execution.
Override Tokens Table
| Token | Usage | Scope | Reset |
|---|---|---|---|
[CEO_APPROVED] | Override any single gate (MC cap, dispatch cap, intent gate, emergent spawn) | One turn | Every UserPromptSubmit (mc-turn-reset.sh) |
[CEO_APPROVED_MULTIPLE_MC] | Explicitly authorize multiple MC adds in one turn (bypasses one-ceo-turn-mc-cap.sh) | One turn | Every UserPromptSubmit |
Note: v3 Rank 1 fix ensures both tokens reset unconditionally on new CEO turn, making re-issuance mechanically possible (was structurally broken in v2).
Known Limitations
- Intent classifier keyword list: Initial set covers common Bosnian + English patterns. False-negatives possible on idiomatic phrasing. Fails open to DIRECTIVE (no regression). Tune iteratively from live incidents.
- Rank 2 john-max-depth-gate.sh intent integration: Spec section T1-A4 describes piggybacking intent check onto depth-gate Branch A. NOT implemented in v3. Explicitly ranked below top-3 (optional enhancement). Core Rank 1/2/3 fully functional.
- Drift-pressure score (T2-A1): Deferred to v3.1. Formula weights unvalidated; shipping guesses would cause false WARN floods.
- Trip-wire 3 elevation (T2-B3): Deferred. Root cause fix (intent classifier) is upstream; elevating downstream symptom adds CEO friction without addressing cause.
References
- v3 spec:
~/system/specs/john-drift-prevention-v3-spec.md - Parent ZAKON:
~/system/rules/zakon-28-max-depth-boundary.md - v2 implementation: MC #10570 (2026-05-02)
- Genesis incident: MC #10586 + #10589 (closed parked), feedback_john_kotlin_rabbit_hole_2026-05-02.md
Last updated: 2026-05-03. Owner: Skillforge. Status: Live in production.
No comments to display
No comments to display