Claude Code (CLI). Implementation - the session that wrote this repo's
code - ran on Claude Sonnet 5. Two independent Claude Code sessions, both
Claude Opus 5, ran as adversarial reviewers of code I'd already accepted:
a correctness audit, a consistency audit, and later a coverage audit.
Between them they found 9 confirmed bugs and flagged 16 more consistency
issues, acting on the 6 most load-bearing the same night - including a
stale project file silently analyzing empty data and a total tracking
failure scoring a perfect search-strategy verdict. A separate Claude.ai
(web) session, also Opus 5, drafted audit specs/prompts and did initial
design/planning - the coverage-audit checklist and
docs/COHORT_AGGREGATOR_DESIGN.md both started there. Project rules
live in CLAUDE.md: hard rules (never interpolate a failed track, never
assume a frame rate), the CV parameters already validated against all
three clips, and the working style I asked for - one piece at a time,
explain before writing code, stop so I can test it in a browser.
Nothing was configured in .claude/ - no persistent subagent configs,
hooks, slash commands, or MCP servers. Ad-hoc forked subagents (a
transient Task-tool call, not a saved config) ran browser-automation
stress tests, for the timing and race-condition bugs a Node test suite
structurally cannot catch.
It misread the brief. It scoped the export as CSV-only, reading the brief's "CSV/XLSX" as "either." The tell came from outside the model: a separate Claude session reviewing the plan flagged that XLSX might be mandatory. I checked the verbatim source myself rather than trusting either - it says "CSV and XLSX." A real misread, not a defensible reading of ambiguous wording. XLSX shipped the same day.
It explained something confidently and wrongly. A large gap in detected error counts between a Chrome-generated and a Firefox-generated result drew a plausible theory: decode-level variance between the browsers' video pipelines. The tell was that it was plausible and untested. I had it pull the actual per-hole signal data from the committed files and compare directly. The real cause had nothing to do with either browser - the two files simply had different amounts of manual review applied.
Its own test lied to it. It ran an automated timing test against a change it had just deployed and reported a third-party library initializing unusually slowly, which read as a real performance regression. The tell was that the finding came from an automated browser tab I couldn't see. I asked it to audit its own test conditions rather than the code; it identified that its tab was very likely being throttled as an unfocused background tab. I confirmed that myself, in a focused tab, before accepting either conclusion.
- Never accepted "it should work now" - screenshotted or logged the real output at each step, and re-verified after risky CV changes (confirming two frames it claimed were now distinct had actually visibly moved, not just stopped throwing an error).
- Required every stress-testing pass to drive the real DOM, not mocks. The bugs this project actually shipped with were timing races and cross-feature interactions - the class a pure-function suite cannot see.
- Hand-labeled real events by watching the tracking overlay frame by frame rather than reading trajectory numbers. That caught a blob-centroid excursion that was not a tracking failure, and an automated event window that started 37 frames after the animal's actual engagement with the hole.
- Spot-checked the independent audits before acting on them - ran
new Blob([Uint8Array])in Node to confirm a code comment's claim really was wrong, rather than trusting the audit's assertion.
Full trace of every wrong turn, not just the fixes that worked, is in DECISIONS.md - kept visible on purpose, including audit findings not yet acted on.