A day in the life of `/challenger`: 4 bugs, 4 hypotheses falsified before the fix

Published: (May 28, 2026 at 09:15 PM EDT)
7 min read
Source: Dev.to

Source: Dev.to

The morning I thought it was one single day

Saturday May 16 – 08:10 am
Lukewarm coffee in Françoise’s mug — inherited from an office birthday. The overnight Sentry board shows an isolated red dot on a 3 am cron, and a voicemail from Catherine that arrived at 7:50 am:

“Hum, it bugs. But it’s quickly fixed.”

Seven words in her usual tone, neither urgent nor worried, the obviousness of a day that starts with a ticket to close before the others.

Catherine is almost never wrong on the first half of her sentence, and she’s sometimes wrong on the second. Today’s “bug” isn’t a bug; it’s four. Between the 8 am and the 6 pm incidents lies a whole day that looks like one thing from afar and four very different things up close.

We tend to count incidents by tickets, messages, sessions – i.e., by symptoms. Counting them by falsifiable hypotheses means finding four where we thought we only had one.

1️⃣ 08:00 am – Duplicate signatures in the attendance PDF

Catherine reports that one of the branch’s courses shows each student signed twice in the PDF.

Productive reflex: “The form double‑posts on double‑click; add a unique‑constraint and move on.”
Result: Fifteen lines of migration – wrong.

/challenger skill

Hypothesis (one sentence):

“The emargements ↔ seances join returns N × M rows when a course has multiple sessions generated for the same date.”

Three probes (to refute, not to confirm):

  1. How many sessions for this course on this date?

    SELECT cours_id,
           date_seance,
           COUNT(*) AS n_seances
    FROM   seances
    WHERE  date_seance = '2026-05-16'
    GROUP BY cours_id, date_seance
    HAVING COUNT(*) > 1;

    Result: 4 courses affected, 18 doubled sessions (school‑year filter mis‑wired).

The output refutes the double‑click hypothesis and confirms a deeper drift: the session generator ran two passes because the getAnneeScolaire(date) filter was mis‑wired between 2025‑2026 and 2026‑2027 at the start of the new school year.

Cost: probe ≈ 90 s.
Avoided rollback: ≈ 30 min (commit → deploy → Sentry → Catherine → callback).
Ratio: 6 : 1.

2️⃣ 11:00 am – Missing pedagogical notes after trainer replacement

A trainer reports that the pedagogical notes entered at the end of an attendance form don’t reappear when another trainer replaces her for the next session.

Surface hypothesis (seductive): “The form doesn’t preload the previous attendance’s notes.” → a useEffect fix.

/challenger hypothesis (reformulated)

“The notes_formateur field is bound to the signing user’s identifier, not to the course or session, so a replacement by another signatory legitimately masks the notes entered by the regular trainer.”

Three probes:

a. Read the schema.
b. Read the component.
c. Ask the trainer herself (no technical probe can decide if it’s a bug or a business choice).

/ask‑3‑options‑before‑code (doctrine v0.7)

Before writing a line, formulate three non‑technical options to arbitrate:

  1. Notes are per‑session and visible to all successive signatories.
  2. Notes are private to the signatory and never shared.
  3. Notes are shared within a course’s pedagogical team but hidden from occasional replacements.

Decision: The trainer chooses option 2.

Result: No bug, just a design choice that deserves a written decision (mini‑ADR).
Outcome: 0 lines of code, 2 min discussion.

Note – A rushed solo dev would have implemented option 1, causing three user complaints the following week (trainer’s notes exposed branch‑wide).

3️⃣ 02:00 pm – Unexpected vertical line in the planning editor

The planning editor displays a thin vertical black line on a single column, crossing the grid from top to bottom.

Eye‑test hypothesis: “CSS leak.”

/challenger hypothesis

“An orphan event surfaces an empty row that renders as a thick border because a course deletion didn’t cascade‑delete its sessions.”

Three probes:

  1. Inspect the DOM.
  2. Run a consistency query on orphan seances.
  3. git blame on the component.

Result: The third probe wins. A recent commit added a conditional to visually separate branches, branching on an isLastOfAtelier variable mis‑calculated at the table edge. It’s an interface border, not a database ghost.

Fix: One TypeScript line, no migration, ≈ 2 min.

Had I started by searching the database, I would have wasted an hour inspecting courses and sessions that had nothing to reproach.

4️⃣ 06:00 pm – Wrong day printed on emergency paper attendance sheet

An emergency paper attendance sheet prints “Thursday 2 pm” whereas the course is “Wednesday 2 pm.”

Self‑diagnosis: “The PDF prints the session date, not the course date.” → commit without a probe.

Rollback (25 min later): All sheets now say “Wednesday,” including Thursday courses. Sentry raises three alerts in five minutes. Catherine, on her end, didn’t call back; she wrote “hum, it bugs” and left me alone with the fatigue.

Real cause (detectable with a 90‑second probe)

creneau_label is stored in LSC Cache without a refresher, diverging for three weeks for courses whose jour_semaine was corrected without propagating the label.

Lesson: Even under fatigue, a quick probe can prevent costly rollbacks.

Take‑aways

TimeIssue/challenger hypothesisProbes usedFix typeTime saved
08:00 amDuplicate signaturesJoin returns N×M rowsSQL count queryDB migration (incorrect) → deeper fix~30 min
11:00 amMissing notesField bound to user IDSchema, component, user interviewADR (no code)2 min
02:00 pmVertical lineOrphan event → empty rowDOM, DB query, git blame1 TS line~1 h
06:00 pmWrong day on sheetPDF uses session date– (none) → rollbackCache refresh needed25 min rollback + alerts

Key principles

  1. Formulate a falsifiable hypothesis before diving into code.
  2. Run quick, targeted probes (SQL, DOM, git blame, stakeholder interview).
  3. Prefer non‑technical arbitration when the issue may be a design decision.
  4. Document decisions (mini‑ADR) to avoid future “patch‑by‑ear” fixes.

By treating each incident as a hypothesis‑testing exercise, the day that looked like a single bug turned into a disciplined, four‑step investigation—saving time, code churn, and user frustration.

Overview

The issue isn’t a PDF bug; it’s a Live/Snapshot/Cache categorisation bug that was already documented in the doctrine and flagged by the ADR‑0024 audit a month earlier as a structural incident class.

“An agent that doesn’t contradict us isn’t a counterpart, it’s a faster typist; a skill we skip in the evening is no longer a skill, it’s an abandoned rigour.
The cost isn’t in the occasional skip, it’s in what the skip reveals — that the protocol relies on human discipline, not on a material mechanism still blocking enough to intercept end‑of‑day fatigue.”

Skill definition (excerpt)

File: ~/.claude/skills/challenger/SKILL.md

name: challenger
description: |
  Force the formulation of a hypothesis in 1 sentence
  then the execution of 3 material probes designed to REFUTE
  this hypothesis before any fix code.

Daily bug‑handling summary

Bug #ObservationActionTime saved
1Probe heldFix correct½ hour
2Protocol diverted toward the business question2 minutes (instead of a user regression)
3Probe heldOne‑line fix1 hour
4Protocol skipped25 minutes rollback + Sentry alert + journal note

Key insight: Three fixes prevented one rollback. The ratio speaks louder than the average. The skill doesn’t eliminate the error; it prevents the third hour of the same error.

Metaphor

“You don’t fire a piece before checking the slip layer.
The firing is the commit.
The slip is the probe.
Skipping the slip because you’re in a hurry is what makes the piece crack in the kiln.”

Time‑impact calculation

  • 5–10 minutes of probing → 20–30 minutes avoided in the fix‑then‑rollback cycle.
  • On a single day the math is trivial; over 60 days it becomes crushing.
  • If even one of the four probes saves you the rollback you experienced yesterday evening, the protocol has already paid for itself.

References

  • Skill: /challenger, Counterpart Toolkit v0.7 R4 – Falsify before fix
  • Public repo:
  • Article #54 of the series My ERP with Claude Code – Autopsy of one day of four chained incidents.
0 views
Back to Blog

Related posts

Read more »