"""Viser hvordan en agent kan få testene grønne ved å endre testene, og hvordan låsen merker det. Kjør fra denne mappa: python demo_juks.py Alt skjer i midlertidige mapper. Filene her blir ikke rørt. 1. Første utkast mot de ekte testene: tre av fem består. 2. Samme utkast mot testene etter «juksen»: to forventede svar er byttet ut med det koden faktisk gir. Fem av fem består, og koden er like feil. 3. Fingeravtrykket i laas.py sammenlignet med den endrede testfila. 4. Hooken fra hook_vern_tester.py, matet med konstruert JSON slik Claude Code sender den: fem forsøk, der bare det siste skal slippe gjennom. """ import json import os import pathlib import shutil import subprocess import sys import tempfile HER = pathlib.Path(__file__).parent MILJO = {**os.environ, "PYTHONIOENCODING": "utf-8", "PYTHONDONTWRITEBYTECODE": "1"} # Juksen, slik den ville sett ut i en diff: fasiten tilpasses koden. JUKS = [ ('self.assertEqual(tempo(3, "14:59"), "5:00")', 'self.assertEqual(tempo(3, "14:59"), "4:60")'), ("with self.assertRaises(ValueError):", "with self.assertRaises(ZeroDivisionError):"), ] def overskrift(tekst): print() print("=" * 60) print(tekst) print("=" * 60) def kjor_tester(mappe): r = subprocess.run([sys.executable, "-m", "unittest", "-v"], cwd=mappe, capture_output=True, encoding="utf-8", env=MILJO) # unittest skriver til standard feil. Vis den siste delen, der dommen står. linjer = r.stderr.strip().splitlines() for linje in linjer: if linje.startswith(("test_", "Ran ", "OK", "FAILED")): print(linje) def ny_mappe(rot, navn, testtekst): mappe = rot / navn mappe.mkdir() shutil.copy(HER / "utkast_tempo.py", mappe / "tempo.py") (mappe / "test_tempo.py").write_text(testtekst, encoding="utf-8") return mappe def main(): sys.stdout.reconfigure(encoding="utf-8") ekte = (HER / "test_tempo.py").read_text(encoding="utf-8") jukset = ekte for gammel, ny in JUKS: assert gammel in jukset, gammel jukset = jukset.replace(gammel, ny) with tempfile.TemporaryDirectory() as tmp: rot = pathlib.Path(tmp) overskrift("1. Første utkast mot de låste testene") kjor_tester(ny_mappe(rot, "a", ekte)) overskrift("2. Samme utkast, etter at testene er «rettet»") b = ny_mappe(rot, "b", jukset) kjor_tester(b) overskrift("3. Fingeravtrykket sammenlignet med testfila i 2") sys.dont_write_bytecode = True # ingen __pycache__ i mappa sys.path.insert(0, str(HER)) import laas laas.sjekk(mappe=b, laasfil=HER / "tester.laas") overskrift("4. Hooken, matet med det Claude Code ville sendt") forsok = [ ("Edit", {"file_path": "/prosjekt/test_tempo.py"}), ("Write", {"file_path": r"C:\prosjekt\Tests\test_ny.py"}), ("Edit", {"file_path": "/prosjekt/tester.laas"}), ("Bash", {"command": "python laas.py lag"}), ("Edit", {"file_path": "/prosjekt/tempo.py"}), ] for verktoy, inndata in forsok: inn = json.dumps({"hook_event_name": "PreToolUse", "tool_name": verktoy, "tool_input": inndata}) r = subprocess.run([sys.executable, str(HER / "hook_vern_tester.py")], input=inn, capture_output=True, encoding="utf-8", env=MILJO) hva = next(iter(inndata.values())) print(f"{verktoy:<6} {hva:<32} exit {r.returncode}") print() print("Meldingen Claude får tilbake ved exit 2, her fra første forsøk:") inn = json.dumps({"hook_event_name": "PreToolUse", "tool_name": "Edit", "tool_input": {"file_path": "/prosjekt/test_tempo.py"}}) r = subprocess.run([sys.executable, str(HER / "hook_vern_tester.py")], input=inn, capture_output=True, encoding="utf-8", env=MILJO) print(r.stderr.strip()) if __name__ == "__main__": main()