A1 Specification — Contract Specs For The Fee-Rounding Fix
Standard: AIHC.2.A1 · 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-spec discipline to your calculate_fee() rounding bug: turn
one review-checklist.md item and one CLAUDE.md rule into elements precise enough that you (or
a subagent) can be checked against them without asking a follow-up question — AIHC.2.A1
(Specification).
Work at hand: cycle 1 of your diagnostic (lesson 1) sorted review-checklist.md item 1
("Payment/fee math uses Decimal, not float; rounding mode stated in a comment") as VIBE —
true, agreed-on, and never mechanically enforced. calculate_fee() in src/payments/fees.py is
exactly the bug that VIBE rule was supposed to prevent. Today you turn that VIBE rule into a
contract, on this exact bug.
SSD cycle 1 — a task prompt is a contract, not a wish
- SAY: A vague delegation ("fix the rounding bug") isn't a spec — it's a wish, because nothing in it is checkable. A contract-spec task prompt fixes scope, success criteria, and what "done" looks like, so that later (lesson 5) you can verify the result against the contract itself instead of against whatever the agent says.
- SEE: Side-by-side, your actual bug, as a wish vs. as a contract: ``` WISH: "fix the rounding bug in fees.py"
CONTRACT: File in scope: src/payments/fees.py, calculate_fee() only
Must not change: the function signature or FEE_RATE value
Success criterion: pytest tests/payments/test_fee_calculation.py passes,
specifically test_calculate_fee_rounds_half_up
Constraint: must use Decimal arithmetic with an explicit rounding
mode (review-checklist.md item 1) — comment states which
Output format: a diff plus a one-line note on which rounding mode was used
``
Each contract line is something you (or later, a subagent's reviewer) can check by looking,
not by asking Maya what she meant. *(Doc-set §3, Common workflows: "share the error verbatim
… suggest a few ways … apply" — the recipe assumes a checkable success criterion at each
step, which is exactly what the WISH version is missing.)*
- **DO:** Rewrite your owncalculate_fee()` fix as a contract with the five elements above,
using your real file paths and your real failing test name from the CI output in lesson 1.
On-demand check: does every line name something you could verify by looking, not by
asking? Cross out any line that fails that test and rewrite it until it passes.
SSD cycle 2 — CLAUDE.md turns a one-off contract into a standing one
- SAY: The contract you just wrote covers one bug.
review-checklist.mditem 1 is supposed to cover every fee calculation, forever — that's a standing specification, and Claude Code's mechanism for a standing, always-loaded specification isCLAUDE.md, not a one-off prompt. - SEE: The doc-set's own guidance on what makes a CLAUDE.md rule work, verbatim: "be
concrete enough to verify — 'Use 2-space indentation' beats 'Format code properly'; 'Run
npm testbefore committing' beats 'Test your changes.'" (Doc-set §4, Memory.) Next to it, two drafts of the same rule forpayments-service:WEAK: "Be careful with money math." CONCRETE: "All payment/fee calculations use Decimal, never float. Round with an explicit rounding mode (ROUND_HALF_UP unless the ticket says otherwise) and state the mode in a comment on the calculation line. Run `pytest tests/payments` before committing any change under src/payments/." - DO: Draft a
payments-service/CLAUDE.mdaddition (3–5 lines) that turnsreview-checklist.mditem 1 into a standing, concrete rule — same test the doc-set names: could a teammate verify compliance by looking at a diff, without asking you? Doc-set §4 also flags CLAUDE.md files should stay under 200 lines total — note where in the project's CLAUDE.md structure this addition would go (root file, or a path-scoped file under.claude/rules/per §4, since fee math only touchessrc/payments/).
SSD cycle 3 — a subagent's own file is a specification too
- SAY: If first-pass review is going to a subagent eventually (your migration goal), that
subagent's own definition is a third kind of contract: its
descriptiontells Claude Code when to reach for it, itstools:line tells it what it's allowed to touch, and its body tells it what "reviewed" means. An underspecified subagent file is the same wish-vs-contract problem, one level up. - SEE: The doc-set's minimal subagent format, verbatim (Doc-set §8, Subagents): ```markdown
name: code-reviewer description: Reviews code for quality and best practices tools: Read, Glob, Grep model: sonnet
You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
``
Notice:tools: Read, Glob, Grep— noBash. That single line is already a specification
decision (this subagent can look, not run anything) — file this observation; lesson 6 comes
back to exactly this line.
- **DO:** Draft.claude/agents/payments-first-pass-reviewer.mdforpayments-service, scoped
to *only* the checklist items that are mechanically checkable by reading (items 1, 4, and 6 —
Decimal/rounding, PII-in-logs, secrets-in-diff): aname, adescriptionspecific enough
that Claude decides correctly when to reach for it, and a body that states which checklist
item numbers it owns. Leavetools:asRead, Grep, Globfor now — don't addBash` yet;
that decision belongs to a later lesson, not this one.
SSD cycle 4 — audit your own contract for the unverifiable line
- SAY: A contract with one unverifiable criterion isn't a weaker contract — for that criterion, it's no contract at all. The last move in specification is always: read your own draft looking for the line that can't actually be checked.
- SEE: A one-line audit test, applied to your cycle-1 contract: for each element, ask "if
someone besides me looked at the finished diff, could they confirm this line, yes or no,
without messaging me?" Apply it here:
"Must not change the function signature or FEE_RATE value" → checkable (diff) "must use Decimal arithmetic with an explicit rounding mode" → checkable (diff + comment) "a one-line note on which rounding mode was used" → checkable (present or absent) - DO: Run this same audit question against your own cycle-1 contract, your CLAUDE.md draft (cycle 2), and your subagent description (cycle 3) — three artifacts, one test each. Flag any line that fails and rewrite it now, before moving on. (Like a clave that has to hold before anything else in the arrangement can lock in — one loose beat there and every instrument after it is guessing, not playing together.)
Independent at-bat
Take one more real item from review-checklist.md — item 5 ("Ledger-table writes are
idempotent; PR states a rollback plan") — and write it as a standing CLAUDE.md rule the same
way you did for item 1 in cycle 2. No worked example this time: use the concrete-vs-weak test
from cycle 2 and the unverifiable-line audit from cycle 4 on your own.
Exit ticket
(Graded against your own contract drafts and the doc-set sections cited above — never against whether a subagent "says" it will comply.)
- (Remember) Name the five elements your contract-spec for
calculate_fee()must contain. - (Understand) Why does the doc-set's CLAUDE.md guidance prefer "Run
npm testbefore committing" over "Test your changes"? Answer in terms of what a second reader can check. - (Apply) Here is a vague line from your own review-checklist.md, item 2 ("Changed endpoints diffed against docs/api-contract.md") — rewrite it as a checkable CLAUDE.md rule.
- (Analyze) Your
payments-first-pass-reviewer.mddraft liststools: Read, Grep, Globonly. What does that one line specify that the subagent'sdescriptionalone does not? - (Evaluate) Look back at your cycle-1 contract. Which of its five elements was weakest before your cycle-4 audit, and what specifically made it weak?
ledger_write
ledger_write:
learner_id: L1-DEV-MAYA
lesson_id: L1-dev-maya-02-a1-specification
anchors: [AIHC.2.A1]
bloom_reached: Apply
exit_ticket_score: ""
auto_score: ""
self_score: ""
calibration_gap: " — computed once Maya's self_score exists"
starting_mastery:
AIHC.2.A1: 0.55
journal_prompt: >
Which of your three contract drafts today (the bug fix, the CLAUDE.md rule, the subagent
description) took the most rewriting before it passed your own unverifiable-line audit —
and what does that tell you about where your specifications tend to go soft?
structure_used: PBL
referents_used: [salsa-clave]
next_lesson_seed: >
Lesson 3 takes the payments-first-pass-reviewer.md drafted here and decides, by
reversibility/blast-radius, which review-checklist.md items it's actually allowed to own.
RUBRIC SELF-AUDIT
| # | Indicator | Verdict | Evidence |
|---|---|---|---|
| R1 | Exactly one objective, Bloom's-leveled, named anchor | PASS | Objective states "Bloom's: Apply," names AIHC.2.A1 only |
| R2 | Every tool claim traces to the doc-set | PASS | Doc-set §3 (workflows), §4 (CLAUDE.md concreteness + 200-line/rules guidance), §8 (subagent file format, tools: allowlist) all cited inline where used |
| R3 | 3–6 SSD cycles, one point each | PASS | 4 cycles: task-prompt-as-contract; CLAUDE.md as standing spec; subagent file as spec; auditing for the unverifiable line |
| R4 | SEE verified against ground truth | PASS | SEEs use the doc-set's own verbatim guidance/example plus Maya's real bug/file paths — nothing fabricated about the product |
| R5 | Every DO on real work-at-hand | PASS | All DOs operate on the real calculate_fee() bug, real review-checklist.md items, and a real subagent file for this repo |
| R6 | Media doctrine honored | PASS | All static text/code comparisons; no motion/process content, no video used |
| R7 | Exit ticket 3–5 Qs, Bloom's-climbing | PASS | 5 Qs, Remember→Understand→Apply→Analyze→Evaluate, graded against her own drafts + cited doc-set sections |
| R8 | Ledger write complete | PASS | auto_score/self_score = ""; journal_prompt supplied; standards named |
| R9 | Scaffolding matches band, fades within lesson; genuine at-bat | PASS | Cycles 1–3 give a worked comparison before each DO (heaviest scaffold in the arc, per fade design); cycle 4 and the at-bat withdraw the worked example |
| R10 | Referents elected-only, flavor-only | PASS | One salsa/clave referent (cycle 4), decorative; instructional content stands without it |
| R11 | Info-at-point-of-use honored | PASS | No front-loaded reading list; each doc-set citation appears inside the SAY/SEE step that needs it |
| R12 | No replication | PASS | Contract elements, CLAUDE.md draft, and subagent scope are all specific to payments-service's real bug and checklist; distinct from the exemplar's generic refactor scenario and from lesson 1's diagnostic content |
Escalation: all load-bearing indicators PASS → auto-ships (Playbook §5, AIHC X2/B3).