B1 Verification — Running The Contract's Own Checks On The Fee Fix
Standard: AIHC.2.B1 · Bloom's: Apply · Structure: PBL.
Notice the Say-See-Do cycles running on Maya R.'s actual work — not a canned exercise — and that every capability claim is cited to the frozen doc-set. The exit ticket climbs Bloom's to Apply, and the lesson closes by writing to the ledger.
Learning objective
(Bloom's: Apply) Apply contract-based verification to the returned calculate_fee() fix:
run every check the lesson-2 contract itself names — the test command, the diff against the
must-not-change list, the rounding-mode note — and record a PASS/FAIL verdict per criterion,
never substituting the agent's own report for any check — AIHC.2.B1 (Verification).
Work at hand: your payments-first-pass-reviewer at-bat (lesson 3) and your plan-mode
session (lesson 4) have produced a returned fix for calculate_fee(), plus one open question
neither you nor Claude has actually checked yet: whether invoice.py's float-passing caller is
broken. Your diagnostic baseline (lesson 1, cycle 2) was "Right now I verify by ______" —
today replaces whatever went in that blank with the contract's own checks.
SSD cycle 1 — green tests are one leg; the contract has three
- SAY: Your lesson-2 contract named more than a test command. It named: (a) the test that
must pass, (b) a must-not-change list (function signature,
FEE_RATE), and (c) a required rounding-mode note. A returned fix that passes (a) can still violate (b) or (c) — so verification is running all the contract's checks, not stopping at the first green one. Trust is evidence per criterion (AIHC X1), and each criterion needs its own evidence. - SEE: Your real returned fix, all three legs run, one leg failing quietly: ``` $ pytest tests/payments/test_fee_calculation.py -q 15 passed in 0.44s ← leg (a): PASS
$ git diff src/payments/fees.py -FEE_RATE = Decimal("0.02") +FEE_RATE = Decimal("0.02") # standard processing rate ... -def calculate_fee(amount): +def calculate_fee(amount): ← leg (b): signature unchanged, PASS but FEE_RATE line was touched — value same, comment added: judgment call
# rounding-mode note in the agent's summary: absent ← leg (c): FAIL
``
The tests are green and leg (c) still failed — nothing about the pass on (a) transferred to
(c). *(Ground truth: your own contract from lesson 2; the diff-review recipe is doc-set §3,
Common workflows — the refactor recipe ends "run tests for the refactored code" and the PR
recipe assumes you review the diff before shipping, not after.)*
- **DO:** Run all three legs on your real returned fix, in order, and write a three-line
verdict:(a) PASS/FAIL,(b) PASS/FAIL + any judgment call noted,(c) PASS/FAIL`. For the
FEE_RATE comment-only touch: decide and record whether "value unchanged, line touched" meets
your contract's must-not-change wording — and if your contract's wording can't decide it,
that's a specification finding to carry back (note it; lesson 6 logs it).
SSD cycle 2 — a claim with no check gets a check, not a shrug
- SAY: Lesson 4 left
invoice.pyin limbo: Claude flagged a float-passing caller; neither of you verified it. The B1 move when a claim has no check in the contract is not to eyeball harder — it's to add the check. The contract's own checks can grow; eyeballing can't be re-run by anyone else. - SEE: The shape of the added check, on your real caller (read the actual file first —
doc-set §3:
@src/billing/invoice.pyinlines the file's full content, so you are reading the real call site, not anyone's summary of it):python def test_calculate_fee_accepts_float_amount_from_invoice_path(): # invoice.py line 88 calls calculate_fee(42.50) — float, not Decimal assert calculate_fee(42.50) == Decimal("0.85")Whatever this test does — pass, fail, or raise — is the first evidence anyone has had about the invoice.py question. Until it ran, both "it's fine" and "it's broken" were predictions. - DO: Write and run the caller-path test against your real
invoice.pycall site (check the actual line with@src/billing/invoice.pyfirst — don't trust lesson 4's transcript memory of it either). Record the result next to your cycle-1 verdicts as leg (d). Then update the lesson-2 contract: the caller-path test is now permanently one of its checks.
SSD cycle 3 — the verification record is the artifact, not a vibe
- SAY: A verification that lives in your scroll-back is gone by Friday. The record — which checks ran, verdict per criterion, who/what ran them — is what makes your verifier role real to a teammate, and it's what your subagent's report gets compared against next time. Two sources agreeing (the agent's summary and your memory) is still zero checks run — agreement isn't evidence (AIHC X8).
- SEE: Your four verdicts assembled into the record format your PR can carry from now on:
VERIFICATION RECORD — PR #<n>, calculate_fee() fix contract: lesson-2 contract v2 (caller-path test added) (a) pytest tests/payments/test_fee_calculation.py PASS (ran: me, locally) (b) diff vs must-not-change list PASS* (*FEE_RATE comment-only touch; ruled in-bounds, wording tightened) (c) rounding-mode note present FAIL → returned to agent with reason (d) caller-path test (invoice.py) <your real result> verified by: Maya, against contract checks — agent report not used as evidence for any leg(Like a rundown: the umpire doesn't ask the runner whether he was tagged — the call comes from watching the tag itself, and it goes in the book either way.) - DO: Assemble your real four-leg record and paste it into the PR description for the fix. Then go back to your lesson-1, cycle-2 sentence ("Right now I verify by ______") and rewrite it to match what you just actually did. Keep both versions — the pair is your own before/after evidence on AIHC.2.B1.
Independent at-bat
Your reviewer subagent owns checklist items 1, 4, and 6 (lesson 3). Its next first-pass report on a live PR will assert things like "no PII in added log lines." Unscaffolded: decide what the contract-check is for that claim (what would you run or diff — not ask — to confirm it?), run it on the subagent's next real report, and add a (PASS/FAIL, ran-by) line to your verification record. No format or worked example provided this time — the record you built in cycle 3 is yours to extend.
Exit ticket
(Graded against your own contract, your verification record, and the cited doc-set sections — never against any agent's account of its own work.)
- (Remember) List the four legs of your final verification record for the fee fix, and which contract element each one checks.
- (Understand) In cycle 1, leg (a) passed while leg (c) failed. What does that show about treating any single green check as covering the whole contract?
- (Apply) Your subagent reports: "item 6 clear — no secrets in the diff." Write the exact command-level check you would run to verify that claim yourself, on your real repo.
- (Analyze) A teammate suggests saving time by having a second agent confirm the first agent's report instead of running the checks. Using X8, analyze what that substitution can and cannot establish.
- (Evaluate) Judge your own record's weakest leg: which verdict rests on the thinnest evidence, and what one change (a new test, a tighter must-not-change wording, a different diff scope) would strengthen it most?
ledger_write
ledger_write:
learner_id: L1-DEV-MAYA
lesson_id: L1-dev-maya-05-b1-verification
anchors: [AIHC.2.B1]
bloom_reached: Apply
exit_ticket_score: ""
auto_score: ""
self_score: ""
calibration_gap: " — computed once Maya's self_score exists"
starting_mastery:
AIHC.2.B1: 0.40
journal_prompt: >
Put your lesson-1 sentence ("Right now I verify by ______") next to today's four-leg
record. What did your old habit systematically never check — and which of today's legs
would have felt like overkill to the you of lesson 1?
structure_used: PBL
referents_used: [baseball-mets-umpire]
next_lesson_seed: >
Lesson 6 takes the two findings this lesson produced — the FEE_RATE wording ambiguity and
the missing rounding-mode note — and files them as the first entries in a failure log,
then crystallizes one into an enforced rule.
RUBRIC SELF-AUDIT
| # | Indicator | Verdict | Evidence |
|---|---|---|---|
| R1 | One objective, Bloom's-leveled, named anchor | PASS | States "Bloom's: Apply," names AIHC.2.B1 only |
| R2 | Every tool claim traces to the doc-set | PASS | Doc-set §3 (@-references inline full file content; refactor/PR recipes) cited inline where used; AIHC X1/X8 cited from the standards doc |
| R3 | 3–6 cycles, one point each | PASS | 3 cycles: all contract legs run, not just the green one; a claim without a check gets a check; the verification record as durable artifact |
| R4 | SEE verified against ground truth | PASS | SEEs are her own contract's checks run on her own fix/diff/caller — ground truth by construction; the doc-set mechanism quoted (@-ref) matches §3 verbatim behavior |
| R5 | Every DO on real work-at-hand | PASS | DOs run her real test command, diff her real file, test her real invoice.py call site, and ship the record into her real PR |
| R6 | Media doctrine honored | PASS | Static terminal/diff/record text only; nothing is a motion/process point |
| R7 | Exit ticket 3–5 Qs, Bloom's-climbing | PASS | 5 Qs, Remember→Understand→Apply→Analyze→Evaluate, graded against her artifacts + doc-set, never agent say-so |
| R8 | Ledger write complete | PASS | auto_score/self_score = ""; journal prompt pairs lesson-1 baseline with today's record |
| R9 | Scaffolding fades; at-bat genuinely independent | PASS | Cycle 1 shows a worked three-leg run; cycle 2 gives only the check's shape; cycle 3's DO is assembly of her own results; the at-bat provides no format or example at all — lighter than lessons 2–4 per the 2→6 fade |
| R10 | Referents elected-only, flavor-only | PASS | One Mets umpire/rundown referent (cycle 3), decorative; the record format stands without it |
| R11 | Info-at-point-of-use honored | PASS | The @-reference mechanism is cited inside cycle 2's SEE at the moment she needs to read the real caller; no front-loaded reading |
| R12 | No replication | PASS | Differs from the exemplar's cycle 3 (agent-reports-success-test-fails): here the failure is a quiet leg-(c) miss behind green tests, plus a check-creation move the exemplar doesn't teach; all DOs/exit Qs distinct from exemplar and from lessons 1–4 |
Escalation: all load-bearing indicators PASS → auto-ships (Playbook §5, AIHC X2/B3).