2026-07-09 OpenRouter Interceptor Capture Consolidation
What I set out to do
Consolidate the sidebar “captures” panel in the openrouter-interceptor extension. Chatting with one JanitorAI character fires many near-identical OpenRouter requests, so the panel filled with duplicate cards for the same char. Goal: one card per character, folding scenario-only prompts (a subset) into the fullest character-card prompt (the superset), while keeping every existing capture behavior intact.
What I actually did
Ran the full brainstorm → spec → plan → subagent-driven-execution flow.
- Design decisions (via clarifying questions): display-only grouping (background keeps storing every raw capture; the sidebar collapses at render time, nothing deleted); group identity reuses the existing
characterDedupKey(resolves to chat URL in practice, since sidebar captures carry nocharacterId); representative = longestsystemPromptwith newest-timestamp tie-break; a count-only “N requests” badge. - Delete wrinkle surfaced during exploration: the panel’s “delete” button never actually removed a capture — it only resets download history so a card can be auto-downloaded again. Confirmed with the user to keep that meaning (no new
REMOVE_CAPTURESbackend), which collapsed the whole feature to three view-side pieces. - Implementation (3 commits, merged to
mainat5290cb0): movedcharacterDedupKeyintosrc/utils/; new puregroupCaptures()insrc/utils/capture-grouping.tswith vitest coverage;captures-list.tsrenders one card per group with the badge, every event still dispatching the representative’s real capture id sosidebar.tsand the background stayed untouched. - Each task ran through a fresh implementer + task reviewer; a final opus whole-branch review returned merge-ready. Verified 349/349 unit, 4/4 new grouping e2e (chromium + firefox), typecheck + lint clean.
What was striking
- The best simplification came from reading the delete path instead of trusting the button’s label — “delete” was a misnomer for “reset download history.” That discovery removed an entire backend surface from the plan.
- One editor diagnostics false alarm claimed
captures-list.tswas duplicated 4x (no-redeclare spam); the git-tracked source was a clean +41/-8. Trusting the diff over the linter daemon was correct. - The final-review subagent’s first dispatch returned corrupted no-op output (0 tool calls); a straight re-dispatch produced a real review. Worth remembering that a garbage subagent result is a retry signal, not a verdict.
Accepted follow-ups (non-blocking)
- An expanded card collapses + its filter selection resets if a strictly-longer capture arrives for the currently-expanded character (representative id changes, Lit re-keys). Documented in the spec as accepted; fix would key
repeat()oncharacterDedupKeyand track expansion by group identity. - Orphaned
filterTypesentries when a representative id changes (keyed by capture.id, never pruned) — pre-existing, tiny.
Related
- Spec:
docs/superpowers/specs/2026-07-09-consolidate-captures-by-character-design.md - Plan:
docs/superpowers/plans/2026-07-09-consolidate-captures-by-character.md - Continues the openrouter-interceptor thread from the 2026-07-04 queries UX and 2026-07-06 curated model list sessions.