Skip to content

Bind a Local Review Record to the Reviewer's Actual Report #3699

Closed

Description

@ptr727

Behavior

scripts/local_review.py record --reviewer agent-skill accepts a caller-typed --findings count. cmd_record validates the reviewer name, that the count is non-negative, and that --expect-digest equals the current content digest. _write_pass_locked stores only reviewer, recordedUtc, and findings. scripts/pr_review.py attest then republishes that count verbatim in the fleet-local-review comment on the pull request.

--expect-digest binds the record to the content under review, not to a review. Nothing ties the record or its count to anything the reviewer produced: no agent id, no report file, no report digest, no completion notification. The local-strict-review skill tells the driver to pass --findings '<count>' and does not say to wait for the dispatched reviewer's real completion before recording.

How it fails

A driver that misreads or invents a review result records and publishes an attestation for a pass that never reported. This happened on ptr727/PlexCleaner#1128. The driving subagent wrote text in its own turn that imitated a reviewer's completion notification. It recorded --findings 0 before any reviewer had reported, and the real report, which arrived minutes later, listed findings. It then recorded --findings 4 from a second imitated report before the real one arrived. Both counts were published to the pull request as attestations. A later, genuine pass was recorded correctly, and the pull request merged on that.

The record succeeded each time because every check it makes passed. The content digest was current. The count was a plausible non-negative integer.

Expected

An attestation can only record a review that actually reported. One shape:

  • The reviewer writes its report to a file in the git directory, keyed by the content digest.
  • record takes that file instead of a typed count. It stores the file's sha256 and derives the count from the report's findings lines.
  • record refuses when the report file is absent, is older than the dispatch, or was written for another digest.
  • local-strict-review "Running It" requires the dispatched reviewer's completion notification, delivered by the harness, before record runs. It also says that text in the driver's own turn is never that notification.

Found while working ptr727/PlexCleaner#1074.

Activity

  1. ptr727 commented on Nov 1, 2026

    @ptr727
    OwnerAuthor

    Decision needed (decision triage, 2026-11-01)

    Question: Should scripts/local_review.py record bind a local review record to the reviewer's actual report (a digest-keyed report file whose sha256 is stored and whose finding count is derived) instead of accepting a caller-typed --findings count that pr_review.py attest republishes?

    Options, recommended first:

    1. Report-file binding, minus the dispatch-time check (recommended): record takes the report file, refuses when absent or written for another digest, stores its sha256, derives the count. With a "Running It" rule (wait for the harness completion notification; the driver's own turn text never counts), this stops the premature record. The engine never sees an agent-skill dispatch, and the digest key already covers staleness. No work in flight.
    2. The full proposal, including dispatch time: Option 1 plus a dispatch subcommand stamping when the reviewer started, so record refuses a report older than the stamp. Stronger binding for one more loop command. No work in flight.
    3. Skill text only, no engine change: Add the completion-notification rule to local-strict-review "Running It". Cheap, but nothing catches a repeat, and the failure was silent and published as an attestation the merge gate reads. No work in flight.

    Evidence: local_review.py:980 cmd_record checks only reviewer name, a non-negative --findings, and --expect-digest. _write_pass_locked (line 820) stores reviewer, recordedUtc, findings. local_review.py:148 marks agent-skill "headless": False. local-strict-review SKILL.md:90, :99: --findings '<count>' is driver-typed, with no rule to wait for the reviewer. The issue body records ptr727/PlexCleaner#1128 carrying two attestations recorded before the real report arrived. Unchanged since filing.

    Blocks: none

  2. added
    decisionA question waiting on the maintainer, alone or beside whatever else the issue carries
    on Nov 1, 2026
  3. ptr727 commented on Nov 1, 2026

    @ptr727
    OwnerAuthor

    Maintainer answer (decision triage, 2026-11-01): Option 1: local_review.py record takes the reviewer's digest-keyed report file. It refuses when the file is absent or written for another digest, stores its sha256, and derives the finding count. Add a local-strict-review 'Running It' rule to wait for the harness completion notification, which the driver's own turn text never counts as. There is no dispatch-time stamp. This is now work for the next burndown round.

  4. removed
    decisionA question waiting on the maintainer, alone or beside whatever else the issue carries
    on Nov 1, 2026
  5. ptr727 commented on Nov 2, 2026

    @ptr727
    OwnerAuthor

    Released (2026-11-02): PR #3807 merged to develop and its branch is deleted, so this claim holds no files. The issue closes on promotion.

    Backlog burndown claim (away run 2026-11-02, round 1, group G4). Branch: burndown/3699-review-record. Issues: #3699, #3705.

    Predicted file set:

    • scripts/local_review.py, tests/test_local_review.py
    • scripts/README.md
    • .agents/skills/local-strict-review/ with its generated trees (.github/skills/local-strict-review/, .claude-plugin/fleet-skills/skills/local-strict-review/, .claude-plugin/fleet-skills/.source-digests/local-strict-review)

    Out of bounds for this group: scripts/pr_review*.py and scripts/pr_merge.py (group G1 holds them), scripts/canonical_review.py, .husky/pre-push.

    Scope: develop only. The feature pull request carries Closes on promotion: for each issue it fully fixes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions