← Maya R.'s track Lesson 05 / 12 · Maya R.

B1 Verification — Running The Contract's Own Checks On The Fee Fix

AIHC.2.B1Bloom's: ApplyPBL
● Exhibit 5 of 12 — Maya R.'s track

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.py in 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.py inlines 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.py call site (check the actual line with @src/billing/invoice.py first — 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.)

  1. (Remember) List the four legs of your final verification record for the fee fix, and which contract element each one checks.
  2. (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?
  3. (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.
  4. (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.
  5. (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).