Skip to content

feat(review): Tripwires — passive alerts when a diff touches sensitive code#862

Open
backnotprop wants to merge 2 commits into
mainfrom
feat/tripwires
Open

feat(review): Tripwires — passive alerts when a diff touches sensitive code#862
backnotprop wants to merge 2 commits into
mainfrom
feat/tripwires

Conversation

@backnotprop
Copy link
Copy Markdown
Owner

@backnotprop backnotprop commented Jun 5, 2026

What

Tripwires let you declare slop-free zones — files and symbols that should never be casually touched. When a code-review diff crosses one, the hit surfaces passively in the review UI:

  • amber glyph on the file in the file tree and file header
  • compact amber marker in the diff gutter at the hit location (no comment card — code stays readable)
  • entry in the annotation sidebar with the rule's note, click-to-jump

No banners, no modals, no approve-gating. Tripwires are informational only: excluded from feedback sent to the agent and from annotation count badges.

Where rules live (two layers, global-first)

  1. Global (default)~/.plannotator/tripwires/<project-key>.json, private to your machine, auto-created empty on first review. Keyed by normalized remote URL so your clone, every worktree, and PR checkouts share one file (git-common-dir fallback for remote-less repos, incl. git <2.31). Nothing is ever written into your repo.
  2. Repo (team opt-in) — a committed .plannotator/tripwires.json is honored if present and merged after global rules. Plannotator only creates it via the explicit tripwires add --repo.
{
  "rules": [
    { "globs": ["src/billing/**"], "symbols": ["chargeCustomer"], "note": "Money path" }
  ]
}

Any touch trips: added/edited/deleted lines, renames, file deletions, binary changes, chmod-only changes. Symbol rules fire when the symbol appears in any changed line or its enclosing function context.

Managing rules

plannotator tripwires list        # merged rules grouped by origin + live tripped/armed status
plannotator tripwires add --glob "src/billing/**" --note "money path"   # direct write (global)
plannotator tripwires add --glob "migrations/**" --repo                 # team file (explicit)
plannotator tripwires add protect the auth core    # free text → prints agent instructions
plannotator tripwires validate    # diagnostics fail-open swallows at review time
plannotator tripwires path        # where each layer's file lives

In-agent: /plannotator-review --tripwires (-t) prints a live scan instead of opening the UI; --add-tripwire <description...> prints rule-authoring instructions for the agent. Both short-circuit before any server/browser startup, in all three runtimes (Claude Code/OpenCode/Pi); PR scans short-circuit before paying for a checkout.

How it works

  • packages/shared/tripwires.ts — pure evaluation engine (vendored to Pi). Glob matching on a linear backtracking-free NFA (ReDoS-immune; relevant since fork-PR mode can evaluate hostile configs) with a 256-char glob cap. Diff parser handles both sides, renames, /dev/null, C-quoted paths, binary stanzas, mode-only changes.
  • Hits inject as external annotations (source: "tripwire"), cleared + re-evaluated on every patch change in both runtimes. Fail-open everywhere — both layers fail independently; a malformed config never breaks a review.
  • Docs guide + launch blog post included. This repo commits a repo-layer config as the team-opt-in example (and dogfood).

Verification

  • 1,354 tests / 0 fail (102 tripwire-specific incl. ReDoS timing guards, rename/deletion/binary/chmod, key-derivation fallbacks, append-rule round-trips)
  • Multi-agent adversarial review across both phases: 20 findings raised, 13 confirmed & fixed (critical ReDoS, rename-keying, PR-checkout short-circuit ordering, git<2.31 key collision, …), rest refuted with evidence
  • E2E smokes: auto-instantiation, add/add --repo/list/validate, both review flags, no-browser short-circuit

…ode (#slop-free-zones)

A repo-committed .plannotator/tripwires.json declares sensitive files
(globs) and optional symbols. When a review diff touches them — adds,
edits, deletions, renames, even binary or chmod-only changes — the hit
surfaces passively in the review UI: an amber glyph in the diff gutter,
the file tree, and the file header, plus an entry in the annotation
sidebar with the rule's note and click-to-jump.

Core design:
- packages/shared/tripwires.ts: pure, zero-import evaluation engine.
  Glob matching runs on a linear backtracking-free NFA (immune to ReDoS
  from hostile configs — relevant in fork-PR mode) with a 256-char glob
  cap. Unified-diff parser tracks both sides, rename headers, /dev/null,
  C-quoted paths, binary stanzas, and mode-only changes. 48 unit tests.
- Hits are injected as external annotations (source "tripwire") and
  re-evaluated on every patch change: diff switch, PR switch, PR scope.
  Fail-open everywhere: a malformed config never breaks a review.
- Dual runtime: Bun server + Pi server (shared module vendored via
  vendor.sh); clearBySource added to both annotation handlers.
- Tripwires are informational only — excluded from feedback sent to the
  agent and from annotation count badges.
- Docs guide + launch blog post on the marketing site.

Includes this repo's own tripwires.json (dogfooding): annotation
pipeline, review server core, Pi vendor list, feedback submission path.
Re-orients tripwire config around a private global store with repo-level
opt-in, and adds the management surface:

- Global default: <dataDir>/tripwires/<project-key>.json, keyed by
  normalized remote URL (clones, worktrees, and PR checkouts share one
  file) with git-common-dir fallback for remote-less repos (incl. a
  git<2.31 fallback). Auto-created empty on first review.
- Repo .plannotator/tripwires.json honored as team opt-in, never created
  implicitly; merged additively after global rules with id dedup.
- plannotator tripwires list|add|validate|path. `add` is dual-mode:
  structured flags write directly (global default, --repo for the
  committed file — the one explicit repo write); free text prints agent
  instructions (explore repo -> globs/symbols -> write -> validate).
- plannotator review --tripwires/-t prints a live scan (rules + which
  wires the current diff trips) and --add-tripwire <description...>
  prints the add instructions; both short-circuit before any server or
  browser startup, in all three runtimes (Bun/OpenCode/Pi). PR scans
  short-circuit before paying for a checkout.
- Review-phase fixes: ReDoS-safe report dedup, launch-repo keying in PR
  mode, NUL bytes in dedup keys escaped (file was binary-classified).
- Docs + skill + blog updated to the global-first story.

1354 tests pass; e2e smoke covers add/add --repo/list/validate/prompt
and both review flags.
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