{
  "receipt": "execution",
  "version": 1,
  "lesson": "content/courses/towards-dark-software-factories/lessons/02-run-one-delivery-loop-and-watch-it-reject-a-change.md",
  "ranWhere": "local: the operator's machine, via `uv run` against the repository lockfile (not Colab)",
  "ranAt": "2026-09-25T17:31:55+00:00",
  "environment": {
    "os": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
    "python": "3.14.3",
    "implementation": "CPython",
    "uvLockSha256": "b35f48277e62cac760792bd76cd8ec64b6557a481bd077bc4bfc8f72f300c62a"
  },
  "inputs": {
    "download": "public/courses/towards-dark-software-factories/factory-course.zip",
    "downloadSha256": "7361933607ea2a24f593e0e760a826cbe190f26666273224f8cdb52a16d01f72",
    "factorySha256": "ac5584eb1019dcdd488add7d17e9cfb1940d825f160a594582262bc43e76392b"
  },
  "script": "scripts/receipts/factory-course-v1.py",
  "steps": [
    {
      "name": "reproduce the rejection",
      "command": "python factory.py tasks/t1-insurance.json /tmp/cand runs/repro-01",
      "exitStatus": 1,
      "stdout": "REJECT - the protected acceptance suite failed: FAILED (failures=1)",
      "stderr": "",
      "expected": {
        "exitStatus": 1,
        "stdoutContains": "REJECT - the protected acceptance suite failed: FAILED (failures=1)",
        "decisionContains": "750 != 751"
      },
      "decisionSha256": "38f5a9b8d28ba7978600d6828070ffc42ad68c30b86dd8e6598bcfd14d24737f",
      "decision": "REJECT",
      "matched": true
    },
    {
      "name": "a candidate reaches for the acceptance suite",
      "command": "python factory.py tasks/t1-insurance.json candidates/tamper runs/tamper-01",
      "exitStatus": 1,
      "stdout": "REJECT - files outside the allowed paths: acceptance/t1_insurance.py",
      "stderr": "",
      "expected": {
        "exitStatus": 1,
        "stdoutContains": "REJECT - files outside the allowed paths: acceptance/t1_insurance.py",
        "decisionContains": null
      },
      "decisionSha256": "c69b65c2352f91cd5659ecaf16bc005e6707bdc1c6aa289ace91e3d2b2f79880",
      "decision": "REJECT",
      "matched": true
    },
    {
      "name": "move the goalposts",
      "command": "python factory.py tasks/t1-insurance.json candidates/good runs/goalposts-01  (after 251 -> 250 in acceptance/t1_insurance.py)",
      "exitStatus": 1,
      "stdout": "REJECT - the acceptance file does not match the hash pinned in the task",
      "stderr": "",
      "expected": {
        "exitStatus": 1,
        "stdoutContains": "REJECT - the acceptance file does not match the hash pinned in the task",
        "decisionContains": null
      },
      "decisionSha256": "6d20b6b610ef3663055d23314a68be9d5e246293f66e101154b6acbcd3133b43",
      "decision": "REJECT",
      "matched": true
    },
    {
      "name": "a correct candidate",
      "command": "python factory.py tasks/t1-insurance.json candidates/good runs/good-01",
      "exitStatus": 0,
      "stdout": "ACCEPT - protected acceptance passed",
      "stderr": "",
      "expected": {
        "exitStatus": 0,
        "stdoutContains": "ACCEPT - protected acceptance passed",
        "decisionContains": null
      },
      "decisionSha256": "1fd4e36eb6fbd70253f299d33cd48a8e573ff9fbf109ad263fbb53d5d9248b6a",
      "decision": "ACCEPT",
      "matched": true
    }
  ],
  "allMatched": true
}
