Skip to content

fix(review): bind capture to canonical repository#1598

Closed
dnlrsls wants to merge 5 commits into
Gentleman-Programming:mainfrom
dnlrsls:fix/1484-review-cwd-binding
Closed

fix(review): bind capture to canonical repository#1598
dnlrsls wants to merge 5 commits into
Gentleman-Programming:mainfrom
dnlrsls:fix/1484-review-cwd-binding

Conversation

@dnlrsls

@dnlrsls dnlrsls commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

🔗 Linked Issue

Closes #1484


🏷️ PR Type

  • 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

  • Propagates the canonical review repository through negotiated lens bindings and reviewer-result transitions.
  • Routes managed capture through the task-local repository while preserving legacy four-field bindings and CWD fallback behavior.
  • Keeps the unnegotiated START wire shape backward compatible and covers nested-repository capture recovery.

📂 Changes

File / Area What Changed
internal/cli/review_* Emits canonical repository bindings only for negotiated review contracts and carries them through native transitions.
internal/assets/opencode/plugins/review-result-artifacts.ts Accepts legacy and negotiated bindings, using the canonical repository when present.
Contract fixtures and schema Defines negotiated lens_bindings with repository context.
Tests and generated goldens Covers legacy compatibility, negotiated routing, nested repositories, and rendered review instructions.

🧪 Test Plan

go test ./internal/assets -run TestReviewResultArtifactsPluginContract
go test ./internal/cli -run 'TestReviewFacadeStart(UnnegotiatedJSONFieldSetRemainsCompatible|LensBindingsCarryCanonicalRepository)|TestNegotiatedReviewStartMatchesVersionedFixture'
go test ./internal/cli -run '^TestReviewCaptureResultNestedRepositoryFailsActionablyAndStaysRetriable$'
go test ./internal/assets ./internal/cli
  • Focused asset and CLI tests pass
  • Bounded review correction validator passed R1-001 and R3-001
  • Native post-apply, pre-commit, pre-push, and pre-pr gates allow the same content-bound receipt
  • Full Windows CLI suite is green locally — three pre-existing symlink-privilege tests require elevated symlink support
  • E2E Docker suite run locally — deferred to CI

✅ Contributor Checklist

  • PR is linked to approved issue fix(review): propagate explicit review cwd into bound lens capture #1484
  • PR stays within 400 changed lines (194 total; generated goldens remain included in the snapshot)
  • Exactly one type:* label is applied (pending maintainer permission)
  • Focused tests pass
  • Generated assets and contract fixtures are updated with the behavior
  • Commit follows Conventional Commits
  • Commit contains no Co-Authored-By trailers

💬 Notes for Reviewers

This is an alternative, complete implementation to the locator-based chain currently starting at #1594. It carries the canonical repository directly in negotiated task bindings while retaining the legacy four-field contract. The two approaches should be reconciled rather than merged independently.

Bounded review lineage: review-1d9a6aec04e15459.

Summary by CodeRabbit

  • New Features
    • Negotiated review start now always returns lens_bindings including a canonical per-lens repository value (required in the response).
    • review status next-transition capture now carries repository context through to follow-up capture and finalize steps.
  • Bug Fixes
    • Lens capture now honors an explicitly provided repository, validates it when present, and improves nested/retry behavior and actionable preflight guidance.
  • Documentation
    • Updated review ledger/capture wording to use --cwd <repository> and clarified guidance for version-skew/preflight scenarios.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 165d0acd-f015-4a03-b9e6-ea4b0d3e8dec

📥 Commits

Reviewing files that changed from the base of the PR and between 0f00d12 and b213a36.

📒 Files selected for processing (1)
  • internal/cli/review_start_context_test.go

📝 Walkthrough

Walkthrough

The review integration now emits canonical repository paths in negotiated lens bindings, propagates them through status and capture transitions, and uses them for plugin preflight and artifact capture. Schemas, fixtures, orchestration instructions, and tests were updated.

Changes

Repository-aware review execution

Layer / File(s) Summary
Repository binding contracts
contracts/review-integration/v1/..., internal/cli/review_start_contract.go
START and status contracts define repository-bearing lens bindings and reviewer-result capture arguments.
CLI transition propagation
internal/cli/review_facade.go, internal/cli/review_next_transition.go, internal/reviewtransaction/compact_store.go
Start, status, finalize, and missing-capture flows carry repository context through bindings and transition inputs.
Binding-aware capture workspace
internal/assets/opencode/plugins/..., internal/assets/assets_test.go
The plugin validates repository bindings and uses the bound repository for capture and preflight CWD selection.
Canonical repository validation
internal/cli/*_test.go, internal/components/sdd/review_ledger_contract_test.go
Tests cover binding shapes, nested repository roots, retry behavior, normalized fixtures, status arguments, and prompt character counts.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReviewStart
  participant ReviewFacade
  participant ReviewResultArtifacts
  participant NextTransition
  ReviewStart->>ReviewFacade: create lens bindings with repository root
  ReviewFacade->>ReviewResultArtifacts: provide repository binding
  ReviewResultArtifacts->>ReviewResultArtifacts: validate binding and select capture CWD
  ReviewFacade->>NextTransition: pass repository context
  NextTransition->>ReviewResultArtifacts: emit repository capture argument
Loading

Possibly related issues

Possibly related PRs

Suggested labels: type:bug

Suggested reviewers: cobies

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: binding review capture to the canonical repository.
Linked Issues check ✅ Passed The repository context is propagated into bound capture CWD and transition payloads, addressing #1484's explicit-cwd failure path.
Out of Scope Changes check ✅ Passed The changes stay focused on repository propagation, contract updates, and related tests; no unrelated additions stand out.
✨ Finishing Touches
🧪 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.

@dnlrsls

dnlrsls commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

Maintainer action required: please add exactly one label, ype:bug. The contributor account cannot apply upstream labels, and the PR validation is currently failing only that label gate. Issue #1484 already has status:approved.

@AndySabina

Copy link
Copy Markdown
Contributor

The repository routing works when the binding comes from the negotiated status transition, but I found two blockers before this can fully close #1484:

  1. For ordinary/staged reviews, negotiated START adds repository but does not include target_identity. The orchestrator contract says to construct the bound reviewer task from START, so START alone cannot produce the complete {lineage,target,lens,order,repository} binding. The path works only after an additional status transition supplies the target.
  2. gentle-ai.review-integration/v1 now requires the new repository field. Legacy plugin parsing and unnegotiated output remain compatible, but strict existing v1 consumers may reject the changed versioned shape. This needs either an additive/optional contract rule or an explicit version negotiation strategy.

The good news is that the status-derived path succeeds from process cwd / with GENTLE_AI_REVIEW_CWD unset, and native capture still revalidates repository authority, lineage, target, lens, and order before consuming the slot. Could you update the START path and clarify the v1 compatibility guarantee? With those addressed, this looks like a much simpler complete solution than maintaining a separate locator mechanism.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
internal/cli/review_start_contract.go (1)

49-55: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Propagate target_identity for ordinary and staged STARTs.

ReviewFacadeStartResult already derives the snapshot identity, but this constructor only copies it inside the overlay branch. Consequently, negotiated workspace/staged START output has repository-bearing bindings without the target identity required to construct the reviewer task.

Copy legacy.TargetIdentity unconditionally, update Validate to accept/require it for these modes, and update the schema and golden fixture.

Proposed fix
 result := ReviewIntegrationStartResult{
 	...
-		SelectedLenses: append([]string{}, legacy.SelectedLenses...), LensBindings: append([]ReviewFacadeLensBinding{}, legacy.LensBindings...),
+		SelectedLenses: append([]string{}, legacy.SelectedLenses...), LensBindings: append([]ReviewFacadeLensBinding{}, legacy.LensBindings...),
+		TargetIdentity: legacy.TargetIdentity,
 	...
 }
🤖 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/cli/review_start_contract.go` around lines 49 - 55, Propagate
legacy.TargetIdentity unconditionally when constructing
ReviewIntegrationStartResult, not only in the overlay path, so ordinary and
staged STARTs retain the derived snapshot identity. Update
ReviewIntegrationStartResult.Validate and its schema to require/accept
target_identity for those modes, then refresh the affected golden fixture to
include the field.
internal/cli/review_start_contract_test.go (1)

53-63: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the repository on the capture argument structurally.

bytes.Contains can pass if the repository appears in another status field. Decode the transition and locate the reviewer_result argument whose name is repository, then assert its exact value.

🤖 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/cli/review_start_contract_test.go` around lines 53 - 63, Replace the
bytes.Contains check on statusOutput with structural decoding of the transition
returned by RunReview. Locate the reviewer_result argument named repository and
assert that its exact value equals repo, failing if the argument is missing or
has a different value; keep the existing status command flow unchanged.
contracts/review-integration/v1/schemas/start.schema.json (1)

34-34: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Keep the v1 wire contract additive or version the new required fields.

The START and reviewer-result changes make repository-bearing data mandatory in an existing /v1 contract. Strict consumers may reject the new top-level field, validator behavior, or capture argument. Use additive optional fields with capability negotiation, or publish and negotiate a new contract version.

  • contracts/review-integration/v1/schemas/start.schema.json#L34-L34: do not require lens_bindings in the existing v1 schema unless the contract is versioned.
  • internal/cli/review_start_contract.go#L110-L112: keep validation compatible with legacy v1 responses or gate the requirement by negotiated capability.
  • contracts/review-integration/v1/fixtures/status.fixture.json#L121-L124: version or negotiate the added repository capture argument.
🤖 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 `@contracts/review-integration/v1/schemas/start.schema.json` at line 34, Keep
the existing v1 wire contract backward compatible: in
contracts/review-integration/v1/schemas/start.schema.json at lines 34-34, make
lens_bindings optional unless introducing a new negotiated contract version; in
internal/cli/review_start_contract.go at lines 110-112, accept legacy v1
responses or enforce the requirement only after capability negotiation; and in
contracts/review-integration/v1/fixtures/status.fixture.json at lines 121-124,
version or negotiate the added repository capture argument.
🤖 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.

Outside diff comments:
In `@contracts/review-integration/v1/schemas/start.schema.json`:
- Line 34: Keep the existing v1 wire contract backward compatible: in
contracts/review-integration/v1/schemas/start.schema.json at lines 34-34, make
lens_bindings optional unless introducing a new negotiated contract version; in
internal/cli/review_start_contract.go at lines 110-112, accept legacy v1
responses or enforce the requirement only after capability negotiation; and in
contracts/review-integration/v1/fixtures/status.fixture.json at lines 121-124,
version or negotiate the added repository capture argument.

In `@internal/cli/review_start_contract_test.go`:
- Around line 53-63: Replace the bytes.Contains check on statusOutput with
structural decoding of the transition returned by RunReview. Locate the
reviewer_result argument named repository and assert that its exact value equals
repo, failing if the argument is missing or has a different value; keep the
existing status command flow unchanged.

In `@internal/cli/review_start_contract.go`:
- Around line 49-55: Propagate legacy.TargetIdentity unconditionally when
constructing ReviewIntegrationStartResult, not only in the overlay path, so
ordinary and staged STARTs retain the derived snapshot identity. Update
ReviewIntegrationStartResult.Validate and its schema to require/accept
target_identity for those modes, then refresh the affected golden fixture to
include the field.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: eb0059a9-ecb6-4e1a-bdc9-6d4b858126a0

📥 Commits

Reviewing files that changed from the base of the PR and between 4c2929e and 1e4eaa7.

📒 Files selected for processing (7)
  • contracts/review-integration/v1/fixtures/start.fixture.json
  • contracts/review-integration/v1/fixtures/status.fixture.json
  • contracts/review-integration/v1/schemas/start.schema.json
  • internal/cli/review_facade.go
  • internal/cli/review_start_contract.go
  • internal/cli/review_start_contract_test.go
  • internal/reviewtransaction/compact_store.go

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/cli/review_facade.go (1)

49-60: 🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift

Include lineage and target in each negotiated START binding.

facadeLensBindings emits only lens, order, and repository; it still lacks immutable lineage and target (target_identity). The contract in internal/assets/skills/_shared/review-ledger-contract.md Line 9 requires a complete binding, so ordinary/staged START cannot construct reviewer tasks until a later status transition supplies the target. Add those fields to the START binding or emit a complete binding object before launch.

🤖 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/cli/review_facade.go` around lines 49 - 60, The facadeLensBindings
function must emit complete START bindings by including immutable lineage and
target_identity fields alongside lens, order, and repository. Update
ReviewFacadeLensBinding and its construction so ordinary and staged START
outputs carry these values before launch, using the negotiated repository
context and existing contract-defined symbols.
🤖 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/assets/skills/_shared/review-ledger-contract.md`:
- Line 9: Update the review-ledger contract to make the repository binding field
additive and optional for v1. Document that legacy four-field START bindings
remain valid and that capture uses the process CWD when repository is absent; do
not require repository universally unless explicit version negotiation is added.

---

Outside diff comments:
In `@internal/cli/review_facade.go`:
- Around line 49-60: The facadeLensBindings function must emit complete START
bindings by including immutable lineage and target_identity fields alongside
lens, order, and repository. Update ReviewFacadeLensBinding and its construction
so ordinary and staged START outputs carry these values before launch, using the
negotiated repository context and existing contract-defined symbols.
🪄 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: 108a14fa-8965-45fe-aed6-c4cf232ced66

📥 Commits

Reviewing files that changed from the base of the PR and between 1e4eaa7 and d85ef30.

⛔ Files ignored due to path filters (13)
  • testdata/golden/combined-claude-claudemd.golden is excluded by !testdata/**
  • testdata/golden/combined-windsurf-global-rules.golden is excluded by !testdata/**
  • testdata/golden/sdd-antigravity-rulesmd.golden is excluded by !testdata/**
  • testdata/golden/sdd-claude-claudemd.golden is excluded by !testdata/**
  • testdata/golden/sdd-codex-agentsmd-lowcost.golden is excluded by !testdata/**
  • testdata/golden/sdd-codex-agentsmd-powerful.golden is excluded by !testdata/**
  • testdata/golden/sdd-codex-agentsmd.golden is excluded by !testdata/**
  • testdata/golden/sdd-cursor-rules.golden is excluded by !testdata/**
  • testdata/golden/sdd-gemini-geminimd.golden is excluded by !testdata/**
  • testdata/golden/sdd-kiro-instructions.golden is excluded by !testdata/**
  • testdata/golden/sdd-opencode-multi-settings.golden is excluded by !testdata/**
  • testdata/golden/sdd-vscode-instructions.golden is excluded by !testdata/**
  • testdata/golden/sdd-windsurf-global-rules.golden is excluded by !testdata/**
📒 Files selected for processing (3)
  • internal/assets/skills/_shared/review-ledger-contract.md
  • internal/cli/review_facade.go
  • internal/components/sdd/review_ledger_contract_test.go

Comment thread internal/assets/skills/_shared/review-ledger-contract.md Outdated
@Alan-TheGentleman

Copy link
Copy Markdown
Contributor

Closing because merged #1594 resolved #1484 with provider-owned opaque repository context. That implementation preserves the intent here while avoiding caller-owned path semantics, so there is no separate code left to merge.

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): propagate explicit review cwd into bound lens capture

3 participants