Skip to content

Bind carried-forward approvals to the rubrics fingerprint #95

Description

@kim-em

Approval staleness is currently bound only to the PR head: state_of() in runner/verdict.py returns green iff cf.get("approved_sha") == head_sha, and update_case_file() in runner/casefile.py records only approved_sha. The rubrics_fingerprint() hash (runner/render.py) is recorded purely as provenance — as rubrics_version on run/round archive records, in run ids and dedupe keys, and in rendered meta blocks. Nothing compares it when deciding whether an approval carries forward.

Consequence: if a rubric (or, since #93, a vendored reference document) is edited between rounds, an approval already recorded at the current head stays green. The tightened rubric only takes effect once the PR pushes a new commit. Case files store no rubrics version, so even a manual sweep cannot tell which approvals predate a rubric edit.

Fix sketch: record the fingerprint alongside approved_sha at approval time, and have state_of() treat a mismatch as stale (re-run pending), exactly like a head move.

Design question to settle first — granularity:

  • Global fingerprint (the existing rubrics_fingerprint, which hashes every rubrics/*.md plus rubrics/references/*.md): trivial to wire, but any edit to _common.md, any rubric, or any reference invalidates ALL rubrics' carried-forward approvals on every open PR, forcing a full re-review sweep for a one-line wording tweak in a single rubric.
  • Per-rubric prompt fingerprint (hash of _common.md + <rubric>.md + that rubric's RUBRIC_REFERENCES documents): invalidates exactly the approvals whose prompt text actually changed. _common.md edits still invalidate everything (correctly — every prompt embeds it). This is the targeted option; the per-run prompt_sha256 already recorded is close but includes the PR context, so a dedicated prompt-template hash is needed.

Noticed while reviewing #93, whose comments originally claimed the fingerprint already invalidated carried-forward approvals; the language has been corrected there, and this issue tracks actually building the binding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions