{
  "schemaVersion": "reqproof.evidence-package.v1",
  "canonicalizationVersion": "1",
  "packageIdentity": "epkg-13b2393abc1d2d9e77b3c7a5f1a500405cb37615af5da5e135929f398b57f3df",
  "canonicalDigest": "sha256:79221f8151241721b832fdd2a57e80bd63217405a4dc733c42113d601cc73e62",
  "createdAt": "2026-10-03T09:32:06Z",
  "producerRunId": "run-1f0ef807aaf3ade8d71bf8851ac3b96af47cbf9f0868504a159629425a2c7919",
  "subject": {
    "repo": "https://example.invalid/teaching/retained-obligation",
    "provider": "github",
    "prNumber": null,
    "headSha": "1cec89a6e69f7633e73a77e3dda945c332460f81",
    "baseSha": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
    "mergeBaseSha": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
    "treeKind": "head",
    "forge": {
      "provider": "generic",
      "host": "example.invalid",
      "project": "teaching/retained-obligation"
    },
    "changeKind": "commit",
    "changeId": "1cec89a6e69f7633e73a77e3dda945c332460f81",
    "changeKey": "commit/1cec89a6e69f7633e73a77e3dda945c332460f81",
    "specRevision": "565502407126b1c07d0130db9eadacbd637f52ac",
    "policyRevision": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
    "approvedPolicyDigest": "sha256:4fb2f50f138de6051427fa0e6ad47fb2ef2a6f58e372159e09eb317e097e2453",
    "engineVersion": "0.1.0-teaching-b845ff313bac",
    "assemblerVersion": "0.1.0-teaching-b845ff313bac"
  },
  "readiness": "blocked",
  "auditVerdictAtHead": "error",
  "readinessBasis": "introduced",
  "gates": [
    {
      "id": "tests_pass",
      "scope": "project",
      "outcome": "failed_behavior",
      "rawStatus": "fail",
      "severity": "error",
      "required": true,
      "requirednessSource": "approved_policy_blocking_check",
      "policyPath": "proof.yaml:project.checks.tests_pass",
      "applicable": true,
      "reason": "tests failed: 2 failing test case(s) across 1 package(s)",
      "failingTests": {
        "tests": [
          {
            "name": "verify.retry-at-12h",
            "file": "verify.py",
            "firstError": "Expected 1 reservation, observed 2"
          },
          {
            "name": "verify.retry-at-23h",
            "file": "verify.py",
            "firstError": "Expected 1 reservation, observed 2"
          }
        ],
        "total": 2,
        "source": "structured"
      }
    }
  ],
  "evidenceRecords": [],
  "review": {
    "baseBranch": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
    "summary": {
      "added": 0,
      "modified": 0,
      "deleted": 0,
      "total": 0
    },
    "changes": [],
    "codeChanges": {
      "totalFiles": 1,
      "mappedFiles": 0,
      "unmappedFiles": [
        "config.json"
      ],
      "byStatus": {
        "modified": 1
      },
      "mappingGranularity": "file"
    },
    "diff": {
      "files": [
        {
          "path": "config.json",
          "status": "modified",
          "hunks": [
            {
              "startLine": 1,
              "endLine": 1
            }
          ]
        }
      ]
    },
    "diffCoverage": {
      "source": "none",
      "measured": false
    },
    "risk": {
      "level": "medium",
      "reasons": [
        "Coverage of the changed code was not measured (no fresh coverage artifact for the changed files).",
        "1 changed code file(s) map to no requirement: config.json.",
        "The tests_pass gate is failing at the evaluated head; without a baseline run it cannot be attributed to (or cleared of) this change."
      ]
    },
    "scope": {
      "method": "changed units from review.diff (function-granular where a parser exists, else file-granular) traced against the requirements' implemented_by/verified_by targets and local annotations; touched requirements clustered in the intent graph (satisfies/parent incl. siblings under a parent with <= 20 children, shared component, interface contracts); uncodified connections from call-level impact paths (review.changes impactPath); removed-code traces from trace targets and removed diff lines",
      "intentGraph": {
        "available": true,
        "requirements": 1,
        "parentEdges": 0,
        "components": 1,
        "contracts": 0,
        "maxSiblingFanout": 20
      },
      "units": [
        {
          "path": "config.json",
          "granularity": "file",
          "kind": "modified",
          "mapping": "none",
          "flags": [
            "untraced"
          ]
        }
      ],
      "clusters": [],
      "coherence": "no_requirements",
      "coherenceNote": "The PR touches no traced requirement (no spec change and no changed code traced to a requirement).",
      "specGapCandidates": [],
      "approximations": [
        "Units are function-granular only where a parser extracts function boundaries (tree-sitter languages, plus C/C++ function-like macros); other changed files are one file-granular unit, and hunks outside any function are attributed to the file only when no function of that file changed.",
        "Renamed/moved detection is best effort: a removed and an added function with the same name in different files are \"moved\"; a different name with >= 80% identical normalized body lines (>= 3 lines) is \"renamed\"; anything else is removed + added.",
        "Function-level mapping comes from trace targets `path:symbol` / line ranges (authored + derived) and function-local annotations; a whole-file trace is file-level (weak) and says nothing about which function a requirement needs.",
        "Intent relations: requirement level = satisfies/parent or siblings under a parent with <= 20 children; component level = shared component (incl. traces.components); contract level = an interface requirement naming both components. A missing spec edge can make a real dependency look uncodified, and a broad contract can make an uncodified dependency look related — every candidate is a question for a reviewer, not a verdict on the code or the spec.",
        "When a changed function is traced only at FILE level, every requirement of its file is a from-side seed: a relation through any of them counts as codified, so a coarse trace can MASK an uncodified connection (and inflate scope clusters — see coarse_trace).",
        "Scope clusters are seeded only by directly touched requirements (spec changes and code_changed); behavior_affected requirements are what the change reaches and are judged by the uncodified-connection rule instead.",
        "Removed-code traces: targets naming a removed/renamed/moved function or a deleted file, and requirement ids cited on removed diff lines that the evaluated file no longer cites. remainingTraces counts the requirement's other code targets at the evaluated revision without re-checking that each still resolves.",
        "Uncodified connections need call-level impact (review.effects — C/C++ only today): this package has none, so NO uncodified connection could be detected. Absence of such candidates proves nothing here."
      ]
    },
    "behaviorDiff": {
      "status": "not_checked",
      "reason": "no behaviour-diff harness is configured (project.review.behavior_diff)",
      "base": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
      "head": "1cec89a6e69f7633e73a77e3dda945c332460f81",
      "harness": {
        "command": ""
      },
      "corpus": {
        "sources": [],
        "partitions": []
      },
      "inputsRun": 0,
      "inventory": [],
      "differences": []
    },
    "compat": {
      "state": "not_checked",
      "sources": [
        {
          "source": "test_diff",
          "status": "checked",
          "reason": "the change modifies or deletes no existing test file",
          "findings": 0
        },
        {
          "source": "mcdc_diff",
          "status": "not_applicable",
          "reason": "the project records no MC/DC evidence",
          "findings": 0
        },
        {
          "source": "removed_behavior",
          "status": "checked",
          "findings": 0
        },
        {
          "source": "differential",
          "status": "not_checked",
          "reason": "no behaviour-diff harness is configured (project.review.behavior_diff)",
          "findings": 0
        }
      ],
      "findings": []
    }
  },
  "policyBasis": {
    "source": "base_revision",
    "revision": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
    "digest": "sha256:4fb2f50f138de6051427fa0e6ad47fb2ef2a6f58e372159e09eb317e097e2453",
    "files": [
      {
        "path": "proof.waivers.yaml",
        "present": false
      },
      {
        "path": "proof.yaml",
        "present": true,
        "digest": "sha256:d439c9b3341cc20a684ef51a52d4c39e939103d43a69725b710e8432db520229"
      }
    ],
    "candidateRevision": "1cec89a6e69f7633e73a77e3dda945c332460f81",
    "candidateDigest": "sha256:4fb2f50f138de6051427fa0e6ad47fb2ef2a6f58e372159e09eb317e097e2453",
    "status": "unchanged",
    "verificationScope": {
      "status": "whole_repository"
    }
  },
  "testResults": {
    "status": "ingested",
    "reportPath": ".evidence/tests.xml",
    "format": "junit",
    "reportDigest": "sha256:60724197ee7bb0683951acba5af1b006743c01ba6959f4bd66d7a4b649e62827",
    "currency": "current",
    "currencyDetail": "run record (full run, tests failed at 2026-10-03T09:32:05Z) matches the current test inputs",
    "total": 5,
    "passed": 3,
    "failed": 2,
    "skipped": 0,
    "taggedTests": 0,
    "joinedTests": 0,
    "failingTests": [
      {
        "id": "verify.py::retry-at-12h",
        "location": "verify.py",
        "message": "AssertionError: Expected 1 reservation, observed 2",
        "outputDigest": "sha256:1c11dd168c676902b76cb597a038091a43091e75780b4e52941fb6eeeec883e9",
        "inScope": false
      },
      {
        "id": "verify.py::retry-at-23h",
        "location": "verify.py",
        "message": "AssertionError: Expected 1 reservation, observed 2",
        "outputDigest": "sha256:1c11dd168c676902b76cb597a038091a43091e75780b4e52941fb6eeeec883e9",
        "inScope": false
      }
    ]
  },
  "decisionSummary": {
    "schemaVersion": "reqproof.decision-summary.v1",
    "readiness": "blocked",
    "readinessBasis": "introduced",
    "evaluatedRevision": {
      "evaluatedCommit": "1cec89a6e69f7633e73a77e3dda945c332460f81",
      "headSha": "1cec89a6e69f7633e73a77e3dda945c332460f81",
      "baseSha": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
      "mergeBaseSha": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
      "treeKind": "head",
      "policyRevision": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
      "policyDigest": "sha256:4fb2f50f138de6051427fa0e6ad47fb2ef2a6f58e372159e09eb317e097e2453",
      "producerRunId": "run-1f0ef807aaf3ade8d71bf8851ac3b96af47cbf9f0868504a159629425a2c7919"
    },
    "intendedChange": {
      "status": "undeclared",
      "sources": [],
      "changedRequirements": []
    },
    "preservedBehaviour": {
      "requirements": [],
      "total": 0
    },
    "scope": {
      "coherence": "no_requirements",
      "directRequirements": 0,
      "reachedRequirements": 0,
      "clusters": 0,
      "changedFiles": 1,
      "unmappedFiles": 1,
      "mappingGranularity": "file",
      "approximations": [
        "Function-level mapping comes from trace targets `path:symbol` / line ranges (authored + derived) and function-local annotations; a whole-file trace is file-level (weak) and says nothing about which function a requirement needs.",
        "Intent relations: requirement level = satisfies/parent or siblings under a parent with <= 20 children; component level = shared component (incl. traces.components); contract level = an interface requirement naming both components. A missing spec edge can make a real dependency look uncodified, and a broad contract can make an uncodified dependency look related — every candidate is a question for a reviewer, not a verdict on the code or the spec.",
        "Removed-code traces: targets naming a removed/renamed/moved function or a deleted file, and requirement ids cited on removed diff lines that the evaluated file no longer cites. remainingTraces counts the requirement's other code targets at the evaluated revision without re-checking that each still resolves.",
        "Renamed/moved detection is best effort: a removed and an added function with the same name in different files are \"moved\"; a different name with >= 80% identical normalized body lines (>= 3 lines) is \"renamed\"; anything else is removed + added.",
        "Scope clusters are seeded only by directly touched requirements (spec changes and code_changed); behavior_affected requirements are what the change reaches and are judged by the uncodified-connection rule instead.",
        "Uncodified connections need call-level impact (review.effects — C/C++ only today): this package has none, so NO uncodified connection could be detected. Absence of such candidates proves nothing here.",
        "Units are function-granular only where a parser extracts function boundaries (tree-sitter languages, plus C/C++ function-like macros); other changed files are one file-granular unit, and hunks outside any function are attributed to the file only when no function of that file changed.",
        "When a changed function is traced only at FILE level, every requirement of its file is a from-side seed: a relation through any of them counts as codified, so a coarse trace can MASK an uncodified connection (and inflate scope clusters — see coarse_trace)."
      ],
      "uncertaintyDisclosures": [
        "effects_unavailable",
        "intent_undeclared",
        "unmapped_code"
      ]
    },
    "claimEvidence": [],
    "routineEvidence": {
      "gatesPassed": 0,
      "gatesAdvisory": 0,
      "gatesNotApplicable": 0,
      "testsPassed": 0,
      "claimsObservedPass": 0
    },
    "disclosures": [
      {
        "id": "check_failed:tests_pass",
        "kind": "unresolved_finding",
        "reason": "check_failed",
        "severity": "high",
        "consequence": "blocks",
        "summary": "Required check tests_pass failed at the evaluated revision. 2 failing tests: verify.retry-at-12h, verify.retry-at-23h.",
        "sourceRecords": [
          "gate:tests_pass",
          "test:verify.py::verify.retry-at-12h",
          "test:verify.py::verify.retry-at-23h"
        ],
        "preExistingBasis": "no_baseline_run",
        "actor": "change_author",
        "policyRule": {
          "path": "proof.yaml:project.checks.tests_pass",
          "revision": "33e282532163634bb0137fc66fa6fa3fab00c8fe"
        }
      },
      {
        "id": "unmapped_code",
        "kind": "missing_evidence",
        "reason": "unmapped_code",
        "severity": "high",
        "consequence": "prevents_ready",
        "summary": "1 changed code file traces to no requirement: that behaviour has no stated intent and no claim to check.",
        "sourceRecords": [
          "file:config.json"
        ],
        "actor": "change_author"
      },
      {
        "id": "intent_undeclared",
        "kind": "partial_input",
        "reason": "intent_undeclared",
        "severity": "medium",
        "consequence": "prevents_ready",
        "summary": "Neither the change request nor the specification states what this change intends, so its effects cannot be judged against an intent.",
        "sourceRecords": [
          "changeRequest",
          "review.changes"
        ],
        "actor": "change_author"
      },
      {
        "id": "no_verifying_test",
        "kind": "missing_evidence",
        "reason": "no_verifying_test",
        "severity": "medium",
        "consequence": "prevents_ready",
        "summary": "The change touches no traced requirement, so no behavioural claim could be checked against observed evidence.",
        "sourceRecords": [
          "review.changes"
        ],
        "actor": "change_author"
      },
      {
        "id": "coverage_unmeasured",
        "kind": "missing_evidence",
        "reason": "coverage_unmeasured",
        "severity": "low",
        "consequence": "informs",
        "summary": "No fresh coverage artifact measured the changed code, so it is unknown whether tests exercise it.",
        "sourceRecords": [
          "review.diffCoverage"
        ]
      },
      {
        "id": "failing_tests_out_of_scope",
        "kind": "unresolved_finding",
        "reason": "failing_tests_out_of_scope",
        "severity": "low",
        "consequence": "informs",
        "summary": "2 failing tests verify no requirement in this change's scope; listed so the failure is not lost.",
        "sourceRecords": [
          "test:verify.py::retry-at-12h",
          "test:verify.py::retry-at-23h"
        ]
      },
      {
        "id": "compat_not_checked",
        "kind": "missing_evidence",
        "reason": "compat_not_checked",
        "severity": "info",
        "consequence": "informs",
        "summary": "Backward compatibility was not fully checked (differential not_checked: no behaviour-diff harness is configured (project.review.behavior_diff)), so a compatibility change can go unnoticed.",
        "sourceRecords": [
          "compat.source:differential"
        ]
      },
      {
        "id": "effects_unavailable",
        "kind": "partial_input",
        "reason": "effects_unavailable",
        "severity": "info",
        "consequence": "informs",
        "summary": "Change effects (new calls, side effects, reachability) were not analyzed for this change.",
        "sourceRecords": [
          "review.effects"
        ]
      }
    ],
    "disclosureCounts": {
      "blocks": 1,
      "preventsReady": 3,
      "requiresJudgement": 0,
      "informs": 4
    },
    "nextDecision": {
      "kind": "intent_clarification",
      "reason": "intent_undeclared",
      "question": "What behaviour is this change intended to change, and what must it preserve?",
      "disclosureIds": [
        "intent_undeclared"
      ]
    },
    "requiredAuthority": {
      "role": "change_author",
      "basis": "approved_policy",
      "policyRevision": "33e282532163634bb0137fc66fa6fa3fab00c8fe",
      "policyDigest": "sha256:4fb2f50f138de6051427fa0e6ad47fb2ef2a6f58e372159e09eb317e097e2453",
      "acceptedIdentitySources": [
        "github_login",
        "portal_user"
      ],
      "enforcement": "portal_or_forge"
    },
    "compatibility": {
      "state": "not_checked",
      "intended": 0,
      "undeclared": 0,
      "fixed": 0,
      "partitions": 0,
      "inputs": 0
    }
  }
}
