Skip to content

fix(pr-reviewer): read PR state from GitHub VFS instead of gh CLI#73

Merged
khaliqgant merged 2 commits into
mainfrom
fix/pr-reviewer-github-vfs-no-gh
Jun 18, 2026
Merged

fix(pr-reviewer): read PR state from GitHub VFS instead of gh CLI#73
khaliqgant merged 2 commits into
mainfrom
fix/pr-reviewer-github-vfs-no-gh

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Jun 18, 2026

Copy link
Copy Markdown
Member

Problem

Every pr-reviewer run was failing with spawn gh ENOENT. The sandbox snapshot ships no gh binary, but two code paths shelled out to gh pr view:

Before those commits pr-reviewer never used gh. The harness commits via the cloud writeback and is explicitly "no git/gh" — these calls violated that.

Fix

Rebuild the same PullRequestReadyState the gate evaluators consume from the GitHub adapter's VFS projection instead of gh:

Need VFS source
state, draft, labels, head.sha pulls/{n}/meta.json
CI check rollup pulls/{n}/checks/_summary.json ({total,passed,failed,pending})
latest review per author pulls/{n}/reviews/*.json
  • The adapter does not project mergeability, so conflict detection is delegated to the merge API — mergePullRequest() returns merged:false on a dirty PR and mergePr throws, so a conflicting PR can never auto-merge.
  • Every read fails closed: a missing/empty projection yields a state the gates treat as not-ready / pending, never a green light.
  • The tested pure evaluators (evaluateMergeOnGreenState, prReadyStateAllowsHumanReview) are unchanged; only the data source moved.

Behavior note

The merge-on-green gate now drops the "wait for a requested bot reviewer to approve" check (the VFS doesn't project reviewRequests). It still blocks on any bot's explicit CHANGES_REQUESTED, the merge-on-green label, and all-checks-green.

Test

  • npm run typecheck clean
  • 37/37 review tests pass (added coverage for the VFS→gate mapping: rollupFromCheckSummary, deriveReviewDecision)
  • Deploy bundle verified to contain checks/_summary.json/listReviews and zero gh references

🤖 Generated with Claude Code


Summary by cubic

Read PR state from the GitHub adapter VFS instead of gh to fix sandbox failures and restore ready pings and merge-on-green. Also hardens review/check parsing so malformed VFS entries never make a PR appear green.

  • Bug Fixes
    • Build PullRequestReadyState from VFS: pulls/{n}/meta.json (state/draft/labels/head SHA), pulls/{n}/checks/_summary.jsonstatusCheckRollup, and pulls/{n}/reviews/*.json → latest review per author.
    • Harden VFS parsing: ignore malformed reviews/*.json entries and derive total from failed+pending+passed when missing so failing/pending checks still block.
    • Missing/empty projections default to “not ready”; conflicts are handled by the merge API (no auto-merge on conflicts).
    • Behavior: removed the “requested bot reviewer must approve” check (no reviewRequests in VFS). Still blocks on any bot CHANGES_REQUESTED, requires the merge-on-green label, and all checks green.

Written for commit 4ab397c. Summary will update on new commits.

Review in cubic

The sandbox snapshot ships no `gh` binary, so the two `gh pr view` calls
added by the READY-sentinel guard (e981031) and merge-on-green (#57) failed
every run with `spawn gh ENOENT` — breaking the ready ping and auto-merge.

Rebuild the same PullRequestReadyState the gates consume from the
github adapter's VFS projection instead:
  • pulls/{n}/meta.json            → state, draft, labels, head.sha
  • pulls/{n}/checks/_summary.json → the aggregated CI rollup
  • pulls/{n}/reviews/*.json       → latest review per author

The adapter doesn't project mergeability, so conflict detection is
delegated to the merge API (mergePullRequest throws on a dirty PR — never
auto-merges). All reads fail closed: a missing/empty projection yields a
state the gates treat as not-ready/pending, never a green light. The tested
pure evaluators are unchanged; only the data source moved off gh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

review/agent.ts replaces the gh CLI subprocess path for PR ready-state acquisition with concurrent VFS reads of meta.json, checks/_summary.json, and reviews/*.json. Two new exported functions, rollupFromCheckSummary and deriveReviewDecision, derive the statusCheckRollup and reviewDecision fields. Tests covering both functions are added.

Changes

VFS-backed PR review state pipeline

Layer / File(s) Summary
VFS read pipeline and PullRequestReadyState assembly
review/agent.ts
readMergeOnGreenState delegates to readPrReviewState, which concurrently reads meta.json, checks/_summary.json, and reviews/*.json to assemble PullRequestReadyState with draft mirroring, MERGEABLE defaulting, statusCheckRollup, and reviewDecision. Imports updated to include listJsonFiles; node:child_process and execFileAsync removed.
CheckSummary model, VFS loaders, rollupFromCheckSummary, and deriveReviewDecision
review/agent.ts
Defines CheckSummary type; implements loadCheckSummary, loadReviews, and readMetaHeadSha VFS loaders; exports rollupFromCheckSummary to map aggregated check counts into the statusCheckRollup shape; exports deriveReviewDecision to derive the latest per-author review decision.
verifyReadyForHumanReview wired to VFS state
review/agent.ts
verifyReadyForHumanReview now calls readPrReviewState(pr) at entry to populate pr.headSha from adapter-projected data before downstream deduplication runs.
Unit tests for rollupFromCheckSummary and deriveReviewDecision
tests/review-agent.test.mjs
New test cases cover rollupFromCheckSummary (empty, all-pass, pending, failing) with evaluateMergeOnGreenState/prReadyStateAllowsHumanReview integration, and deriveReviewDecision supersession (no reviews, APPROVED overrides earlier CHANGES_REQUESTED, CHANGES_REQUESTED remains when latest).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • AgentWorkforce/agents#48: Directly modifies the same prReadyStateAllowsHumanReview/readiness-checking logic in review/agent.ts that this PR's VFS pipeline feeds into.
  • AgentWorkforce/agents#57: Adds evaluateMergeOnGreenState and merge-on-green Slack handling that consume the same PullRequestReadyState shape this PR now derives via VFS reads.

Suggested labels

size:L

🐇 No more CLI calls, no more shell to run,
The VFS holds what the agent needs done.
meta.json whispers the head SHA aloud,
Check summaries rollup, reviews found proud.
The rabbit hops fast through the projected tree —
Green gates and approvals, read purely! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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
Title check ✅ Passed The title clearly and accurately summarizes the main change: switching from using the gh CLI to reading PR state from the GitHub VFS adapter.
Description check ✅ Passed The description is directly related to the changeset, explaining both the problem (sandbox failures due to gh CLI calls) and the solution (reading from VFS instead).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/pr-reviewer-github-vfs-no-gh

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 and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request replaces the dependency on the gh CLI by reading PR metadata, check summaries, and reviews directly from the GitHub VFS projection. Feedback on these changes suggests adding defensive guards in loadReviews to prevent runtime errors when mapping files, and making rollupFromCheckSummary more robust by calculating the total checks from individual statuses if the total field is missing.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread review/agent.ts Outdated
'listReviews',
`/github/repos/${encodeSegment(pr.owner)}/${encodeSegment(pr.repo)}/pulls/${pr.number}/reviews`
);
return files.map((file) => file.value);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In loadReviews, mapping files directly using files.map((file) => file.value) can throw a TypeError if files is not an array, if any file is null/undefined, or if file.value is missing. Since this function is wrapped in a try-catch block, any such error will cause it to silently fail and return []. This could lead to bypassing active CHANGES_REQUESTED reviews and incorrectly merging a PR. We should defensively guard the mapping to ensure we process valid reviews even if some elements are malformed.

    return Array.isArray(files)
      ? files.map((file) => file?.value).filter((val): val is Record<string, unknown> => val !== null && typeof val === 'object')
      : [];

Comment thread review/agent.ts Outdated
Comment on lines +657 to +661
const total = typeof summary?.total === 'number' ? summary.total : 0;
if (!summary || total === 0) return [];
const failed = typeof summary.failed === 'number' ? summary.failed : 0;
const pending = typeof summary.pending === 'number' ? summary.pending : 0;
const passed = typeof summary.passed === 'number' ? summary.passed : 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

In rollupFromCheckSummary, if summary is defined but total is missing or not a number, total defaults to 0, which causes the function to immediately return []. If there are actually failed, pending, or passed checks present in the summary but total is omitted or malformed, they will be ignored, and the PR will be held with a generic reason instead of reporting the specific check statuses. We can make this more robust by defaulting total to the sum of failed, pending, and passed when it is not explicitly provided as a number.

Suggested change
const total = typeof summary?.total === 'number' ? summary.total : 0;
if (!summary || total === 0) return [];
const failed = typeof summary.failed === 'number' ? summary.failed : 0;
const pending = typeof summary.pending === 'number' ? summary.pending : 0;
const passed = typeof summary.passed === 'number' ? summary.passed : 0;
const failed = typeof summary?.failed === 'number' ? summary.failed : 0;
const pending = typeof summary?.pending === 'number' ? summary.pending : 0;
const passed = typeof summary?.passed === 'number' ? summary.passed : 0;
const total = typeof summary?.total === 'number' ? summary.total : (failed + pending + passed);
if (!summary || total === 0) return [];

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6163f8119e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread review/agent.ts
// The VFS carries no mergeability field, so default to MERGEABLE rather than
// gate on a value we can't read. A real conflict never auto-merges: the
// merge API rejects it and mergePr throws.
mergeable: 'MERGEABLE',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep merge-conflict checks fail-closed

When the VFS state is used for a PR that currently has merge conflicts, this hard-coded MERGEABLE value makes both prReadyStateAllowsHumanReview and evaluateMergeOnGreenState treat the PR as conflict-free once labels/checks/reviews are otherwise green. The merge API may still reject merge-on-green later, but the READY path does not call that API, so a conflicted PR can incorrectly ping Slack as ready for human review; merge-on-green also attempts a merge instead of holding with a conflict reason.

Useful? React with 👍 / 👎.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

PR #73 Review — fix(pr-reviewer): read PR state from GitHub VFS instead of gh CLI

Summary

This PR replaces the gh pr view shell-out (unavailable in the harness sandbox — no gh binary, no git/gh shelling) with reads from the GitHub adapter's VFS projection (meta.json, checks/_summary.json, reviews/*.json). It adds two exported, unit-tested helpers (rollupFromCheckSummary, deriveReviewDecision) that reconstruct the same PullRequestReadyState the existing gates consume. The change is well-scoped to the PR's stated purpose.

Verification (CI parity):

  • npm test (canonical: tsc --outDir .test-build && node --test tests/*.test.mjs) → 108/108 pass, build clean.
  • tsc --noEmit strict typecheck → clean (exit 0).
  • Helper signatures (listJsonFiles<T>Array<{path; value:T}>, readJsonFile<T>, encodeSegment, resolveMountRoot) verified against @relayfile/adapter-core declarations; loadReviews .map(f => f.value) matches the return shape.
  • No stale references to the removed parsePrReadyState / execFileAsync.
  • Working tree clean; I made no edits (none were warranted).

Findings

No mechanical issues found. Logic, types, and tests are internally consistent. The check-rollup path correctly fails closed: a missing/zero check summary yields an empty rollup, and the gates treat an empty rollup as ready only when mergeStateStatus === 'CLEAN' — a value the VFS path never sets, so absent CI HOLDS rather than going green (confirmed by the new test at the diff's lines 222-224).

Advisory Notes

  • Hardcoded mergeable: 'MERGEABLE' (review/agent.ts:588) — The VFS projection carries no mergeability field, so the PR defaults it to MERGEABLE. Both gates previously gated on the real value: prReadyStateAllowsHumanReview (review/agent.ts:702) and evaluateMergeOnGreenState (review/agent.ts:726). For the auto-merge path this is safe — mergePullRequest() returns merged:false on a dirty PR and mergePr throws (review/agent.ts:935), as the author documents. For the ready-announce path, a PR with merge conflicts would now be announced "ready for your review" rather than held. This is a deliberate, documented design tradeoff (a human reviewing a conflicted PR is not unsafe, and they'd see the conflict in GitHub). I am not changing it: turning this back into a hard gate would require a mergeability source the VFS doesn't provide, and editing a safety-default is outside mechanical scope. Flagging for human confirmation that announcing-on-conflict is acceptable.

Addressed comments

  • No bot or reviewer comments were present in .workforce/context.json or the .workforce/ set; there were no review threads to account for.

The PR is logically sound, fully tested, and typechecks. The single advisory item (hardcoded mergeable default on the ready-announce path) is an intentional design tradeoff that warrants a human sign-off rather than a code change. I cannot confirm live CI status or mergeability from this sandbox (those are reported separately), so I am not asserting the PR is merge-ready.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

I made no file edits — the diff is mechanically clean (typecheck + all 108 tests pass), and the only substantive findings are semantic/safety behavior changes that require human judgment, so I left the code unchanged.

Review: PR #73fix(pr-reviewer): read PR state from GitHub VFS instead of gh CLI

What the PR does

Replaces gh pr view shell-outs in review/agent.ts with reads from the GitHub adapter's VFS projection (meta.json, checks/_summary.json, reviews/*.json). Adds two exported helpers (rollupFromCheckSummary, deriveReviewDecision) with unit tests. Removes execFile/parsePrReadyState.

Verification (against current checkout)

  • npm run typecheck (tsc --noEmit): passes.
  • npm test (tsc build + node --test tests/*.test.mjs): 108/108 pass.
  • Runtime helpers listJsonFiles/readJsonFile/encodeSegment/resolveMountRoot are exported by @agentworkforce/runtime; listJsonFiles<T> returns Array<{ path; value: T }>, so files.map(f => f.value) is correct.
  • No stray callers of the removed parsePrReadyState/execFileAsync anywhere in the repo.
  • VFS snapshot in the checkout is sparse (only .relay sync metadata materialized), so the exact projected shapes of meta.json/checks/_summary.json/reviews/*.json could not be validated against a fixture here — those are fetched live at runtime.

Findings (left unchanged — semantic/safety, human judgment required)

  1. Merge-on-green: requested-bot-approval gate is now silently dropped (fail-open). readPrReviewState (review/agent.ts:582-597) never populates reviewRequests. mergeOnGreenBotReviewReason (review/agent.ts:774-779) loops over requestedBotReviewLogins(state.reviewRequests) to hold a PR until requested bot reviewers have APPROVED. With reviewRequests always empty, that requirement is now a no-op: a merge-on-green PR whose requested bot reviewer (e.g. coderabbitai) has not yet approved will no longer be held as pending. Only the "a bot's latest review is CHANGES_REQUESTED" check (via latestReviews, still populated) survives. The existing unit test at tests/review-agent.test.mjs:165 passes reviewRequests directly into the gate evaluator, so it stays green and does not cover this integration regression. Recommend the author either project reviewRequests from the VFS or consciously document dropping the requested-reviewer requirement.

  2. mergeable hardcoded to 'MERGEABLE' (fail-open at the gate, backstopped by merge API). review/agent.ts:588. The conflict gates in evaluateMergeOnGreenState (state.mergeable === 'CONFLICTING', review/agent.ts:726) and prReadyStateAllowsHumanReview (state.mergeable !== 'MERGEABLE', review/agent.ts:702) can no longer fire from read-state. The author documents that mergePullRequest() returns merged:false on a dirty PR and mergePr throws (review/agent.ts:935), so a real conflict won't auto-land — but the human-ready Slack ping (prReadyStateAllowsHumanReview) no longer suppresses on conflicts (a notification-only effect). This is central to the PR's stated design (the header comment explains the rationale), so I'm flagging it rather than treating it as out-of-scope. Confirm this trade-off is intended; the merge API backstop makes it acceptable for the merge path, less so for the ready-ping accuracy.

Addressed comments

  • No bot or human review comments were present in .workforce/context.json or the materialized GitHub VFS projection (only a content-less issue-comment receipt at issues/73/comments/...). Nothing to reconcile.

Advisory Notes

  • None. Both findings are within the PR's purpose; no unrelated changes were considered.

The PR builds and tests clean, but it carries a demonstrable fail-open regression on the requested-bot-approval merge gate (finding 1) plus a documented-but-notable mergeable default change (finding 2). These are safety-default behavior changes I won't auto-edit; they need an author/human decision. I am not printing READY.

- loadReviews: guard the map so a malformed reviews/*.json entry can't throw
  out and blank the whole review set (which would drop an active
  CHANGES_REQUESTED and risk merging a blocked PR).
- rollupFromCheckSummary: derive `total` from failed+pending+passed when it's
  missing/malformed, so a summary with real counts but no `total` still reports
  the actual check states instead of being treated as "no checks".
- Document why mergeable defaults to MERGEABLE (VFS doesn't project it) and that
  safety rests on the merge API rejecting a conflicted PR, not on this field.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@khaliqgant

Copy link
Copy Markdown
Member Author

Addressed the review feedback in 4ab397c:

  • loadReviews defensive guard (gemini, review/agent.ts:630) — done. The map now guards each entry (Array.isArray + file?.value + filter to objects), so a malformed reviews/*.json element can't throw out and blank the whole review set (which would have dropped an active CHANGES_REQUESTED and risked merging a blocked PR).
  • rollupFromCheckSummary total fallback (gemini, :661) — done. total now falls back to failed + pending + passed when missing/malformed, so a summary with real counts but no total still reports the actual check states instead of being treated as "no checks". Added a test for it.
  • Merge-conflict fail-closed (codex P1, :588) — the mergeable: 'MERGEABLE' default is deliberate: the GitHub adapter's VFS projection carries no mergeability field, so gating on it would mean the ready/merge gates could never pass. The safety guarantee doesn't rely on this field — a conflicted PR can never be auto-merged because mergePr throws when GitHub rejects the merge (merged:false). The only residual is cosmetic: a conflicted PR may still be pinged as "ready for human review" (that path doesn't hit the merge API), which a human resolves at review time. I expanded the code comment to make this explicit. True conflict-awareness needs the adapter to project mergeable/mergeStateStatus — tracked alongside the cloud projection work in AgentWorkforce/cloud#2289.

typecheck clean; 37/37 review tests pass.

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

🧹 Nitpick comments (1)
tests/review-agent.test.mjs (1)

237-242: ⚡ Quick win

Add malformed-total coverage for fallback behavior.

Line 237–242 validates missing total, but not malformed total. Add one case like total: '3' to ensure fallback still blocks when failed > 0, matching the hardened parser contract.

Suggested test addition
   assert.equal(evaluateMergeOnGreenState({
     state: 'OPEN', isDraft: false, mergeable: 'MERGEABLE', labels: [{ name: 'merge-on-green' }],
     statusCheckRollup: rollupFromCheckSummary({ failed: 1, pending: 0, passed: 2 }),
   }).outcome, 'blocked');
+
+  assert.equal(evaluateMergeOnGreenState({
+    state: 'OPEN', isDraft: false, mergeable: 'MERGEABLE', labels: [{ name: 'merge-on-green' }],
+    statusCheckRollup: rollupFromCheckSummary({ total: '3', failed: 1, pending: 0, passed: 2 }),
+  }).outcome, 'blocked');
🤖 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 `@tests/review-agent.test.mjs` around lines 237 - 242, The test case for
evaluateMergeOnGreenState only validates the behavior when total is missing, but
not when total is malformed (like a string value). Add another similar test case
using evaluateMergeOnGreenState that passes a malformed total field such as
total: '3' (as a string) in the statusCheckRollup created via
rollupFromCheckSummary or similar mechanism, and verify that the outcome is
still 'blocked' when failed check count is greater than zero, ensuring the
parser fallback behavior works correctly.
🤖 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.

Nitpick comments:
In `@tests/review-agent.test.mjs`:
- Around line 237-242: The test case for evaluateMergeOnGreenState only
validates the behavior when total is missing, but not when total is malformed
(like a string value). Add another similar test case using
evaluateMergeOnGreenState that passes a malformed total field such as total: '3'
(as a string) in the statusCheckRollup created via rollupFromCheckSummary or
similar mechanism, and verify that the outcome is still 'blocked' when failed
check count is greater than zero, ensuring the parser fallback behavior works
correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 742a48b9-67fe-478b-a287-0bc256917458

📥 Commits

Reviewing files that changed from the base of the PR and between 21cc735 and 4ab397c.

📒 Files selected for processing (2)
  • review/agent.ts
  • tests/review-agent.test.mjs

@khaliqgant khaliqgant merged commit 837ac6c into main Jun 18, 2026
2 checks passed
@khaliqgant khaliqgant deleted the fix/pr-reviewer-github-vfs-no-gh branch June 18, 2026 14:56
khaliqgant added a commit that referenced this pull request Jun 18, 2026
Reconcile #61 (opt-in comment-driven merge-conflict resolution) with #73
(VFS-based PR-state machinery):
- review/agent.ts: union github triggers (kept issues.labeled + slack from
  #73, added issue_comment.created from #61); kept #73's
  readPrReviewState/loadCheckSummary/loadReviews/rollupFromCheckSummary/
  deriveReviewDecision and #61's resolveConflicts/matchesConflictDirective/
  isAuthorizedConflictCommander; merged readPr to handle both issue_comment
  and issues.labeled payloads (single superset issue type).
- tests/review-agent.test.mjs: unioned imports so both PRs' cases coexist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant