A coding agent can produce a convincing patch before anyone agrees what correct means. Start with a reproducible failure, then write the acceptance boundary independently. You will repair money.py, whose initial expression int(float(text)*100) produces28 cents for "0.29" on this runtime. Rounding the float repairs that example but still accepts exponents, whitespace and other inputs outside the API contract.
This course builds on Python tests and Git staging/restoring. Its final artifact is a small actual Git patch, not a claim that an agent finished work. Supplied proposals are authored worked examples so everyone can replay the same mistakes without an account or paid model session.
The complete grammar permits an optional minus, a canonical ASCII whole part of at most nine digits, a dot and exactly two fractional digits. No leading plus, spaces, exponents, Unicode digits or leading zeroes on multi-digit whole parts are accepted. Negative zero yields integer zero. The maximum magnitude is99999999999 cents.
Keep both valid and invalid vectors. Test negative values and the size boundary as well as the reported fraction. A valid result must have exact type int: Python considers False equal to0, but the API does not promise booleans. On invalid input the public failure type is ValueError; an accidental TypeError is a different behavior.
for text in ("0.29", "-0.29", "12.34"):
print(text, int(float(text)*100), round(float(text)*100))A good oracle covers both what must happen and what must be refused. Catching Exception here is limited to known, synchronous lab candidates so one failure can be recorded without stopping the rest. It is not a timeout, resource limit or safe evaluator for arbitrary Python.
The baseline and rounding proposal give useful red signals before the reference becomes green. That prevents a vacuous acceptance suite from being mistaken for evidence. In the build exercise, return stable labels for every failure rather than printing a success message or stopping at the first one.
import re
def parse_cents(text: str) -> int:
"""Parse the lab's canonical signed two-decimal amount without floats."""
if not isinstance(text, str):
raise ValueError("amount must be text")
match = re.fullmatch(r"(-?)(0|[1-9][0-9]{0,8})\.([0-9]{2})", text)
if match is None:
raise ValueError("amount is outside the canonical decimal grammar")
magnitude = int(match.group(2)) * 100 + int(match.group(3))
return -magnitude if match.group(1) else magnitude
for text in ("0.29", "-0.29", "-0.00"):
print(text, parse_cents(text))
try:
parse_cents("1e2")
except ValueError:
print("exponent rejected")Implement the acceptance runner and use the baseline, rounding and reference candidates to establish red-to-green behavior. Preserve fixture labels so later review panels can point to exact failures. Next, write a task that makes the accepted scope and evidence explicit.
A plausible patch still needs evidence.
Choose a bundled proposal to inspect its real Git diff and observed checks. This is an offline teaching replay, with no live model session. The owner’s final task permits changes only to money.py.
1 · Actual observed checks
- failedunit
python -I acceptance_runner.pyObserved exit 1 - passedsyntax
python -I syntax_check.pyObserved exit 0 - passedformat
ruff format --check money.pyObserved exit 0 - passedtype
mypy --strict money.pyObserved exit 0
Source and sealed-test snapshot
de2089e0cdc68fe40f443d6f1333e12de19fb3ad1a378424afad64f2d4dbde8aA digest identifies bytes. It does not authenticate arbitrary agent claims.
2 · Review findings
acceptance:exponentacceptance:fraction_digitsacceptance:leading_zeroacceptance:oversizeacceptance:plusacceptance:spacesacceptance:typeacceptance:unicode_digitsfailed:unitfloat_remains:money.py
3 · The real Git diff
diff --git a/money.py b/money.py
index 98feda2..2605956 100644
--- a/money.py
+++ b/money.py
@@ -1,2 +1,2 @@
def parse_cents(text: str) -> int:
- return int(float(text) * 100)
+ return round(float(text) * 100)