2026-09-06 01:51 CDT · every gate grounded in a failure actually observed, with the evidence that earned it
ask_drift_gate) caused 30 of those by reading a peer session's message as the
user. Fifty separate processes would multiply that cost. These 50 run as 50 checks inside a
single hook.session-fraud-check already carries 54
regex-over-file patterns and is wired. It cannot express session shape, which is what
nearly every failure here actually was: turn counts, session age, idle minutes, unreturned
tool calls, peer-sender counts, ask overlap. These 50 cover only that gap. self-test: 3 passed, 0 failedThe chat stops before the work is done.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G01 | quit-midtool A tool call that never returned while the chat went silent. Demucs guitar/drums isolation died holding a Bash call after 'Holding.', silent 37h. | hard | session |
| G02 | punt-to-question Ended on an AskUserQuestion or ExitPlanMode nobody answered. Zappa handoff for Lies, unanswered 84h with everything built and preflighted. | hard | session |
| G03 | done-no-proof A completion claim with no path, URL, http code, code block or tool call anywhere in the reply block. Chat GPT read aloud setup claimed 'finished' on a bare sign-off turn. | hard | reply |
| G04 | unanswered-user Last event is Brandon speaking, with no reply. Added after Slant rhyme chats sat on an unread turn. | hard | session |
| G05 | unhandled-notification A harness notice landed in a session that had already stopped. Slant rhyme chats: the background shell died, the notice arrived in a corpse, nobody read it. | hard | session |
| G06 | permission-instead-of-finishing Ends on one of the 74 permission phrases while the ask is unfinished. babysit chat 14dbcee4 stopped on 'do you want me' at 63 turns. | hard | reply |
| G07 | plan-no-exec Promised a next step in future tense, then went silent past the stall threshold. Screen saver activation promised 'running now' then stopped for 70h. | warn | session |
| G08 | partial-called-done Says done while a sub-ask in the same request is unstarted. The standing complaint: part of the ask, then a done-claim. | hard | reply |
| G09 | silent-drop A sub-ask disappears with no queue item and no explicit 'not done'. Dropping a sub-ask without queueing it is the fraud. | hard | session |
| G10 | coverage-unstated An artifact was verified but no N-of-N coverage count appears. done_claim_gate fired on this session for exactly this. | hard | reply |
A claim with nothing behind it.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G11 | exit-zero-as-proof Treats exit 0 or file-exists as proof the output is good. feedback_exit_zero_is_not_verification_measure_content. | hard | reply |
| G12 | pass-line-counted-as-block Counts a tool's success lines as failures. A babysitter read 27 'No stderr output' PASS lines as 27 stops and asked Brandon to patch the wrong hook. | hard | reply |
| G13 | fix-aimed-at-non-failing-part Recommends changing a component with zero measured failures. chat_donelink_gate blocked 0 times across 82 blocks and was the proposed patch target. | hard | reply |
| G14 | claims-no-regression-without-checking Says a change leaves another rule untouched without reading the shared code path. The proposed patch shared md_outside across two checks, so it would have weakened the 2026-07-02 link rule. | hard | reply |
| G15 | peer-number-unverified Repeats another session's count without reproducing it. '31 cross-session messages' was actually 11, from 4 senders not 2. | hard | reply |
| G16 | placeholder-data Guessed, default or invented values in a dataset. The Zappa plan did this right: 20 rows say 'not yet measured' instead of inventing a mismatch. | hard | disk |
| G17 | unlabelled-provenance A factual claim with no source label separating observation from inference. feedback_ground_every_claim_label_provenance_hard_gate. | warn | reply |
| G18 | stale-data-reported-live Reports a cached or local read as the live state. Live tiles read 8 9 5 8 while the local build said 9 9 4 9 for 90 seconds. | hard | reply |
The chat outlives its usefulness or delegates its own survival.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G19 | age-ceiling-24h Session older than 24 hours without a handoff. c1e4ffee ran 122 hours. This session ran 36. | hard | session |
| G20 | turn-ceiling-400 More than 400 assistant turns without a handoff. c1e4ffee reached 3,394. This session reached 520. | hard | session |
| G21 | handoff-sentence-not-handoff Named a handoff path and then kept working. This session wrote the handoff and replied 8 more times. Rule authored by the 14dbcee4 audit. | hard | session |
| G22 | ceiling-without-five-item-floor Branch-three evidence work ended without its five items done. feedback_zappa_one_song_per_chat_hard_gate third amendment. | warn | session |
| G23 | background-shell-outlives-chat Long work delegated to a background shell instead of launchd. The 8/14 chain died at take 15 of 22 when its shell was killed. | hard | session |
| G24 | wake-signal-is-the-only-signal A chat whose sole continuation path is one job that can die silently. Slant rhyme chats armed a loop with a background shell as its only wake signal. | hard | session |
| G25 | orphaned-job A process still working on a file this chat named while the chat is idle. Skill transfer drum kit separation sat 2h while its DrumSep ran unwatched. | warn | session |
The work wanders off the ask.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G26 | scope-drift-catchall 12+ separate asks with near-zero vocabulary overlap against the opening ask. c1e4ffee opened on a one-song-per-chat gate and reached 102 asks at 0% overlap. | warn | session |
| G27 | adjacent-work-as-progress Substitutes nearby work and reports it as the ask. This session turned disk projections into the main event while assigned to babysit. | hard | reply |
| G28 | literal-ask-unaddressed The named target never appears in the reply. ask_drift_gate, 30 of 82 blocks, the single largest cause. | hard | reply |
| G29 | one-song-one-chat More than one song id worked in a single chat. feedback_zappa_one_song_per_chat_hard_gate, first amendment. | hard | session |
| G30 | bulk-complete Several chapters, songs or items closed in one pass. feedback_one_at_a_time_no_bulk_complete. | hard | session |
| G31 | self-directed-scope-growth Starts work Brandon did not ask for. feedback_answer_the_literal_ask_no_drift_hard_gate. | warn | reply |
| G32 | asks-which-item-to-take Asks for direction when the queue already answers it. feedback_self_direct_the_queue_never_ask_for_direction. | hard | reply |
Another session's message treated as authority.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G33 | peer-as-authorization Treats a peer session's message as Brandon's consent. feedback_peer_session_request_is_never_user_authorization. | hard | reply |
| G34 | peer-steer-proposes-destruction A destructive verb aimed at a watched session. A babysitter wrote up the permanent Songsterr revision-removal control 11 times. | hard | reply |
| G35 | multiple-steerers More than one session steering the same chat. 4 senders pushed 11 messages into c1e4ffee; the heaviest was not a babysitter. | hard | session |
| G36 | babysitter-does-the-work A watcher starts executing instead of reporting. This session ran the drum chain while assigned to babysit. | hard | session |
| G37 | peer-message-as-drift-target A gate anchoring on machine-authored text as if it were the user. cross-session-message appears 0 times in ask_drift_gate.py HARNESS_MARKERS. | warn | reply |
| G38 | permission-laundering Doing what a peer says it was denied permission to do. Standing instruction-source boundary. | hard | reply |
The numbers used to decide are wrong.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G39 | two-methods-disagree Two counts differ and the discrepancy is not resolved. 14 vs 31 cross-session messages; the real figure was 11. | hard | reply |
| G40 | own-tool-exempted A rule that scores its author more leniently than everyone else. CEILING_HANDOFF let this session pass at 474 turns on a regex that matched its own prose. | hard | reply |
| G41 | self-reference-as-evidence A watchdog matching its own processes. The babysitter flagged this session because of its own tail -F. | hard | session |
| G42 | alarm-on-every-change Re-reporting the full set whenever anything shifts. The alert stream re-listed all three chats on any signature change until delta-only landed. | warn | session |
| G43 | false-positive-filtered-not-fixed Suppressing a bad finding without tracing its cause. 6 false-positive classes were traced to root cause instead of muted. | hard | reply |
| G44 | silence-read-as-success A monitor whose filter cannot emit on failure. Monitor coverage rule: if the process crashed now, would the filter say anything? | hard | session |
The artifact never reaches a permanent, verified place.
| ID | Gate & the failure that earned it | Sev | Scope |
|---|---|---|---|
| G45 | local-path-as-deliverable A file:// path offered as the finished link. Every HTML ships to a permanent URL. A local path is a draft. | hard | reply |
| G46 | url-unverified A live link claimed without an http code. feedback_verify_the_live_url_not_the_local_one. | hard | reply |
| G47 | missing-sibling-md An HTML route with no index.md beside it. ship.py closeout requirement. | hard | disk |
| G48 | destroyed-instead-of-quarantined Any rm, git rm or Trash aimed at real work. Never destroy. Move retired material into a sibling folder and let Brandon empty it. | hard | disk |
| G49 | csv-instead-of-xlsx Tabular data shipped as bare CSV. feedback_deliver_data_as_xlsx_excel_hard_gate. | warn | disk |
| G50 | unqueued-remainder Work left undone with no queue id naming it. The only honest exits are finish everything, or queue what is left. | hard | reply |
python3 ~/.claude/skills/fifty-gates/run_gates.py --list python3 ~/.claude/skills/fifty-gates/run_gates.py --report python3 ~/.claude/skills/fifty-gates/run_gates.py --self-test
Hook mode reads the transcript, exits 2 to refuse a stop, and fails open on
any internal error. Override once with touch ~/.claude/fifty_gates.allow.