Skip to content

Add 'unwritten ignore': bounded mute for persistently false rules - #16

Merged
Byggarepop merged 6 commits into
mainfrom
ignore-rules-snooze
Jul 12, 2026
Merged

Add 'unwritten ignore': bounded mute for persistently false rules#16
Byggarepop merged 6 commits into
mainfrom
ignore-rules-snooze

Conversation

@Byggarepop

Copy link
Copy Markdown
Owner

Closes the last gap in the false-positive story. The layers now are:

  1. Cosmetic/content suppression (automatic — C# trivia, JSON keys)
  2. git commit --no-verify (one commit)
  3. Statistical decay (chronic, slow)
  4. unwritten ignore <trigger> <hole> --for <n> (this PR — persistent false pairing)

Design: bounded by construction

Permanent ignores rot — one day the pairing is real again and the mute silently hides an omission. So there is no permanent variant. An ignore expires after the trigger has changed n more times (default 30). Those are exactly the commits that matter: each trigger-alone commit erodes the rule's confidence (it often dies naturally before the mute expires), while renewed co-changes mean the rule deserves to fire again.

  • Muted holes appear as suppressed with the remaining budget — never silently dropped — consistent with the content-aware layers; check --strict overrides.
  • Applies to file-level and member-level holes, in both CLI and MCP output.
  • Stored in machine-managed .unwritten/ignores.json (the tool can rewrite it freely; config.json stays hand-edited). Expired entries prune automatically; a corrupt file fails toward alerting, never toward silence.
  • ignore --list shows remaining budgets and notes; ignore --remove restores the alert.
  • Deliberately CLI-only: no MCP tool, so a coding agent cannot mute its own warnings — muting is a human judgment.

Testing

137/137 passing — 6 new tests: suppress-not-drop, expiry after N trigger changes, --strict override, list/remove round-trip, unknown-remove error, corrupt-file fail-open.

🤖 Generated with Claude Code

Byggarepop and others added 6 commits July 12, 2026 18:46
An ignore suppresses the directed pair (trigger -> hole) until the
trigger has changed --for more times (default 30) — the commits that
either erode the false rule or prove the coupling is real again.
Permanent ignores are deliberately not supported: unbounded mutes go
stale and eventually hide real omissions.

- Muted holes show as suppressed with the remaining budget (file-level
  and member-level, CLI and MCP); check --strict overrides them.
- Stored in machine-managed .unwritten/ignores.json, separate from the
  hand-edited config.json; expired entries are pruned on rewrite; a
  corrupt file fails toward alerting.
- ignore --list / --remove manage entries.
- Deliberately CLI-only: no MCP counterpart, so agents cannot mute
  their own warnings.

137 tests passing (6 new).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… alias

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ot decide

The check_holes/explain_rule descriptions and the Stop-hook feedback now
instruct agents that a rule judged persistently false must be reported
to the user with a pointer to 'unwritten ignore' — the agent cannot mute
it, and must not dismiss it silently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A failing check now ends with a decision guide listing the three
choices with ready-to-run commands, ignore lines pre-filled with the
actual trigger/hole paths. check_holes gains a per-hole ifFalsePattern
field carrying the exact command to relay to the user, so the agent
never has to construct it (and is reminded only the user may run it).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…with it

All three options are now equally concrete: option 1 lists each
forgotten file with its trigger, option 2 carries the bypass command,
option 3 the pre-filled mute command.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Option 2 now states that --no-verify skips all hooks and every hole at
once, and a footer (shown only with multiple holes) explains the
combining order: fix/mute the holes that need it, retry the commit,
and bypass only if legitimate one-time holes remain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Byggarepop
Byggarepop merged commit 7e98dc8 into main Jul 12, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant