Skip to content

fix(review): retain staged-equivalent receipts in status - #2115

Open
dnlrsls wants to merge 1 commit into
Gentleman-Programming:mainfrom
dnlrsls:fix/staged-equivalent-receipt-status
Open

fix(review): retain staged-equivalent receipts in status#2115
dnlrsls wants to merge 1 commit into
Gentleman-Programming:mainfrom
dnlrsls:fix/staged-equivalent-receipt-status

Conversation

@dnlrsls

@dnlrsls dnlrsls commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

🔗 Linked Issue

Closes #1951


🏷️ PR Type

What kind of change does this PR introduce?

  • type:bug — Bug fix (non-breaking change that fixes an issue)
  • type:feature — New feature (non-breaking change that adds functionality)
  • type:docs — Documentation only
  • type:refactor — Code refactoring (no functional changes)
  • type:chore — Build, CI, or tooling changes
  • type:breaking-change — Breaking change (fix or feature that changes existing behavior)

📝 Summary

Retains an approved compact receipt for negotiated pre-commit STATUS only when every reviewed intended-untracked path is staged byte- and mode-equivalently with unchanged candidate scope. The exact match routes to review.validate instead of a fresh review.start; partial staging, extra paths, content drift, and mode drift remain fail closed. Explicit-lineage and unqualified STATUS return the same authority.


📂 Changes

Review size: 198 additions, 0 deletions (198 changed lines).

File / Area What Changed
internal/reviewtransaction/target_status.go Reuses an approved canonical receipt only after the exact staged pre-commit target assessment succeeds.
internal/reviewtransaction/target_status_test.go Covers exact staging plus partial, extra-path, content-drift, and mode-drift rejection.
internal/cli/review_next_transition_test.go Verifies negotiated CLI STATUS selects review.validate identically with or without an explicit lineage.

🧪 Test Plan

Focused unit tests

go test ./internal/reviewtransaction -run '^TestAssessTargetStatusRetainsApprovedReceiptForExactStagedIntendedTransition$' -count=1 -timeout 2m
go test ./internal/cli -run '^TestNegotiatedPreCommitStatusRetainsApprovedStagedIntendedReceipt$' -count=1 -timeout 2m

Both commands passed, including five consecutive isolated runs.

Build and static checks

go build ./...
go vet ./...
git diff --check

All passed.

Broader package attempts

go test ./internal/reviewtransaction -count=1 -timeout 10m
go test ./internal/cli -count=1 -timeout 10m

Each timed out at 10 minutes without assertion failures in unrelated raw-fixture Git commands. The focused tests above passed independently and five consecutive times; this PR does not claim that either full package suite passed.

Go Format
Not run: the supplied verification covers git diff --check, not go run ./internal/gofmtcheck.

E2E Tests (Docker required)
Not run: this bounded review-status change was validated with focused Go tests and repository build/static checks.

Benchmark Validation
Not run: no bench/ files or benchmark claims change.

  • Unit tests pass (go test ./...)
  • Go format passes (go run ./internal/gofmtcheck)
  • E2E tests pass (cd e2e && ./docker-test.sh)
  • Manually tested locally

🤖 Automated Checks

Check Status Description
Check PR Cognitive Load 198 changed lines, within the 400-line review budget
Check Issue Reference PR body contains Closes #1951
Check Issue Has status:approved Linked issue is approved
Check PR Has type:* Label Maintainer action requested below
Unit Tests go test ./... must pass
Go Format go run ./internal/gofmtcheck must pass
E2E Tests cd e2e && ./docker-test.sh must pass

✅ Contributor Checklist

  • PR is linked to an issue with status:approved
  • PR stays within 400 changed lines, or I have requested/obtained maintainer-applied size:exception with rationale documented
  • I have added the appropriate type:* label to this PR
  • Unit tests pass (go test ./...)
  • Go format passes (go run ./internal/gofmtcheck)
  • E2E tests pass (cd e2e && ./docker-test.sh)
  • Benchmark validation completed, or this change is not applicable to the benchmark (explain why in the Test Plan).
  • I have updated documentation if necessary
  • My commits follow Conventional Commits format
  • My commits do not include Co-Authored-By trailers

💬 Notes for Reviewers

  • The exact staged pre-commit eligibility boundary is an integrity guard: all reviewed paths must be present and byte/mode-equivalent, with no extra candidate scope. The test matrix covers the exact allowed population and each fail-closed case.
  • No declared guard:population contract changes; .guard-population-baseline.txt is unchanged. Registry/declaration checks are not used as semantic proof.

↩️ Rollback Boundary

Revert commit 97176fc3794182a2acc69048b2c174b31260456e to remove only staged-equivalent receipt retention and its focused coverage; unrelated STATUS behavior remains outside this work unit.

Pending maintainer actions

  • Apply exactly type:bug to this PR.

Summary by CodeRabbit

  • Bug Fixes
    • Approved validation receipts now remain current when staged content exactly matches the reviewed intended transition.
    • Status checks now consistently report the correct validation state across explicit and unqualified queries.
    • Improved handling for partial staging, extra files, content changes, and file mode changes.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change preserves approved receipts when staged files exactly match the reviewed intended transition. Target status validates staged candidates through the pre-commit gate. Tests cover mismatched paths, content, modes, lineage selectors, receipt identity, and approval state.

Changes

Approved staged receipt retention

Layer / File(s) Summary
Staged target assessment
internal/reviewtransaction/target_status.go
Approved compact authorities can transition from workspace or unspecified projections to staged when AssessCompactGateTarget confirms an exact pre-commit match. Assessment errors return a target-status failure.
Receipt retention validation
internal/reviewtransaction/target_status_test.go, internal/cli/review_next_transition_test.go
Tests verify exact staging retains the approved receipt, while partial, extra, content-changed, and mode-changed staging does not. Explicit-lineage and unqualified status queries return consistent transitions.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

  • Gentleman-Programming/gentle-ai issue 2017 — Covers approved receipt applicability across staged or delivery projections.
  • Gentleman-Programming/gentle-ai issue 1919 — Covers exact staged approved-receipt validation, with additional merge-delivery scenarios.

Possibly related PRs

Suggested labels: type:bug

Suggested reviewers: alan-thegentleman

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation preserves approved receipts only for exact staged equivalence and aligns explicit and unqualified STATUS behavior with issue #1951.
Out of Scope Changes check ✅ Passed The changes are limited to target-status logic and focused tests required by issue #1951.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: retaining approved receipts for staged-equivalent review status.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/reviewtransaction/target_status.go`:
- Around line 247-254: Update the PRE-COMMIT targeting flow around
AssessCompactGateTarget so assessment uses the same live status snapshot
represented by the returned TargetIdentity, rather than rebuilding from the
mutable live index; alternatively reject the candidate unless the assessed
snapshot identity equals live.Identity. Add an interleaving test covering a
staged change between the initial snapshot and gate assessment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d21b583d-71c6-4051-b842-27d484ca6bda

📥 Commits

Reviewing files that changed from the base of the PR and between fdecaf5 and 97176fc.

📒 Files selected for processing (3)
  • internal/cli/review_next_transition_test.go
  • internal/reviewtransaction/target_status.go
  • internal/reviewtransaction/target_status_test.go

Comment on lines +247 to +254
assessment, assessmentErr := AssessCompactGateTarget(ctx, repo, state, NativeGateRequestInput{
Gate: GatePreCommit, LineageID: state.LineageID,
})
if assessmentErr != nil {
return targetStatusFailure(base, assessmentErr)
}
if assessment.Applicability == CompactGateTargetExact {
candidates = append(candidates, candidate)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline internal/reviewtransaction/target_status.go --items all
rg -n -C 16 '^func AssessCompactGateTarget\b|^func targetStatusForCandidate\b|BuildStoredSnapshot|TargetIdentity' internal/reviewtransaction -g '*.go'

Repository: Gentleman-Programming/gentle-ai

Length of output: 50388


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the status flow and compact gate API without reading unrelated files.
wc -l internal/reviewtransaction/target_status.go internal/reviewtransaction/compact_native_gate.go internal/reviewtransaction/compact_state.go
sed -n '1,290p' internal/reviewtransaction/target_status.go
printf '\n--- compact_native_gate.go ---\n'
sed -n '1,260p' internal/reviewtransaction/compact_native_gate.go
printf '\n--- compact_state.go relevant --\n'
rg -n -C 10 'type NativeGateRequestInput|func AssessCompactGateTarget|TargetIdentity|InitialSnapshot|BuildStoredSnapshot|AssessTargetStatusWithSnapshot' internal/reviewtransaction/compact_native_gate.go internal/reviewtransaction/compact_state.go internal/reviewtransaction/target_status.go

Repository: Gentleman-Programming/gentle-ai

Length of output: 387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- locate relevant files ---'
git ls-files internal/reviewtransaction | grep -E '(target_status|compact|native|gate|state)\.go$' | sed -n '1,120p'

printf '%s\n' '--- target_status.go top and relevant ranges ---'
sed -n '1,280p' internal/reviewtransaction/target_status.go

printf '%s\n' '--- search for NativeGateRequestInput and AssessCompactGateTarget ---'
rg -n -C 16 'type NativeGateRequestInput|func AssessCompactGateTarget|AssessCompactGateTarget\(' internal/reviewtransaction -g '*.go'

printf '%s\n' '--- search for snapshot builders/stores in target_status.go ---'
rg -n -C 8 'BuildStoredSnapshot|AssessTargetStatusWithSnapshot|targetStatusForCandidate|TargetIdentity|AssessCompactGateTarget' internal/reviewtransaction/target_status.go -g '*.go'

Repository: Gentleman-Programming/gentle-ai

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- compact_gate.go ---'
sed -n '1,180p' internal/reviewtransaction/compact_gate.go

printf '%s\n' '--- gate context/build functions ---'
rg -n -C 12 'func buildCompactGateRequest|func buildCompactLifecycleSnapshot|type GateRequest|type Stage|func.*Staged' internal/reviewtransaction -g '*.go'

printf '%s\n' '--- compact.go relevant snapshot types/functions ---'
rg -n -C 10 'type CompactState|type CompactRecord|type Snapshot|func BuildStoredSnapshot|type SnapshotBuilder|TargetIdentity|CandidateTree|PathsDigest|CandidatePathDigest' internal/reviewtransaction/compact.go internal/reviewtransaction/target_status.go -g '*.go'

Repository: Gentleman-Programming/gentle-ai

Length of output: 50388


Bind PRE-COMMIT gate targeting to the status snapshot.

assessTargetStatusSnapshot uses live as the returned TargetIdentity, but AssessCompactGateTarget rebuilds the staged target from the live index via NativeGateRequestInput. A staged change between the initial snapshot and this gate can make the exact gate accept one snapshot while STATUS reports a newer status snapshot identity. Derive this assessment from the same live snapshot, or fail closed unless the assessed snapshot identity matches live.Identity, and add an interleaving test for that TOCTOU window.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/reviewtransaction/target_status.go` around lines 247 - 254, Update
the PRE-COMMIT targeting flow around AssessCompactGateTarget so assessment uses
the same live status snapshot represented by the returned TargetIdentity, rather
than rebuilding from the mutable live index; alternatively reject the candidate
unless the assessed snapshot identity equals live.Identity. Add an interleaving
test covering a staged change between the initial snapshot and gate assessment.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(review): STATUS emits fresh START for a staged-equivalent receipt accepted by pre-commit

1 participant