Skip to content

fix(#7384): skip automatic review-handoff label dispatch - #7403

Open
fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/7384-dedupe-review-handoff
Open

fullsend-ai-coder[bot] wants to merge 2 commits into
mainfrom
agent/7384-dedupe-review-handoff

Conversation

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor

Summary

Stops duplicate automatic review of a code-agent PR's initial revision by treating fullsend-auto-review-handoff as explicit provenance on the automatic ready-for-review handoff. ready-for-review remains a supported state/handoff label. This PR does not change .github/workflows/ (coder app cannot push those files) and does not close the issue.

Related Issue

#7384

Changes

Completed in this PR (locally verified):

  • internal/dispatch HarnessRouter skips ready-for-review when the event snapshot includes fullsend-auto-review-handoff. Distinction is that provenance label, not a bot username, [bot] suffix, or a previous review of the same SHA.
  • Authorization is unchanged and independent of duplicate handling. The GitHub [bot] collaborator-API exemption on opened|synchronize|ready_for_review is preserved.
  • Shell helper + tests for the GitHub Route decision, including both creation/label orders, concurrent delivery, subsequent/fix-agent synchronize, and explicit same-revision /fs-review and labeled requests.
  • Maintainer patch for reusable-dispatch.yml and scaffold dispatch.yml at docs/contributing/patches/7384-review-handoff-dedup.patch.
  • Rollout and compatibility notes in docs/contributing/review-handoff-dedup.md.

Remaining integration (not in this PR):

  1. Maintainer applies the workflow patch with a token that has the workflows permission. Instructions are in the patch header and the contributing doc (git apply --check, then git apply, then the listed tests/pre-commit).
  2. Agents-repo (fullsend-ai/agents) post-code applies fullsend-auto-review-handoff before ready-for-review, strips it immediately on GitHub, and leaves it for GitLab until pre-review. Do not remove ready-for-review application.

Until both land, production still double-dispatches. Independent deploy is safe: each half is a no-op without the other.

Testing

  • go test ./internal/dispatch/ (including -race) and go test ./internal/scaffold/
  • bash .github/scripts/review-handoff-test.sh (includes git apply --check and apply-to-temp-copies)
  • gofmt, go vet, shellcheck, gitleaks (changed files), lychee --offline, ADR lints
  • make lintpre-commit could not fetch remote hook repos in this sandbox (HTTP 403); local equivalents were run instead
  • Tests added/updated for new or modified logic

Live GitHub opened+labeled one-second-apart delivery is not exercised here; it needs the maintainer patch plus the agents pin.

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — human and human-directed agent sessions only (autonomous agent commits are exempt)
  • I wrote this contribution myself and can explain all changes in it

Closes #7384

Post-script verification

  • Branch is not main/master (agent/7384-dedupe-review-handoff)
  • Secret scan passed (gitleaks — fc364841eb01c3847e0368ca31dd5fe000faa19b..HEAD)
  • PR body secret scan passed (gitleaks — no-git)

Code-agent PR creation currently fires both pull_request_target.opened
and labeled (ready-for-review) for the same head SHA. Those two events
share a per-PR review concurrency group with cancel-in-progress, so one
review cancels the other after setup has started.

This commit implements the non-workflow half of the fix:

- HarnessRouter skips ready-for-review when the event snapshot includes
  the fullsend-auto-review-handoff provenance label. Distinction is that
  label, not a bot username, [bot] suffix, or a prior review of the SHA.
- Authorization is unchanged and independent of the skip. The GitHub
  [bot] collaborator-API exemption on opened|synchronize|ready_for_review
  is preserved in the maintainer patch.
- Behavioral tests cover both creation/label orders, concurrent delivery,
  subsequent and fix-agent synchronize, and explicit same-revision
  /fs-review and labeled requests.
- Maintainer patch for reusable-dispatch.yml and scaffold dispatch.yml
  is in docs/contributing/patches/ (coder app cannot push workflows).
- Agents-repo post-code must apply provenance before ready-for-review;
  that change is not in this repository.

Note: pre-commit could not fetch remote hook repos (git fetch HTTP 403).
Local hooks plus shellcheck, gitleaks, lychee, gofmt, and go vet were
run directly on the changed files.

Related to #7384
@fullsend-ai-coder
fullsend-ai-coder Bot requested a review from a team as a code owner September 17, 2026 13:56
@fullsend-ai-coder fullsend-ai-coder Bot added the ready-for-review Triggers review agent dispatch label Sep 17, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 1:58 PM UTC · Completed 2:23 PM UTC

Commit: e5bce5c · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $8.00

@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown

Site preview

Preview: https://5349171c-site.fullsend-ai.workers.dev

Commit: 9dcdb54b32dff5a02af1f90996d32a0b01f0ee29

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Sep 17, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

Risk Assessment: moderate (2/5)

Details

Re-review of a bot-authored 'fix: address review feedback' commit that only adjusted existing content within the same 14 files (Tier1 2.630.5 + Tier2 2.430.3 + Tier3 2.0*0.2 ~= 2.44 -> 2); Tier 1 signals (file count, 2 protected .github/scripts paths, no dependency changes, bot author) are unchanged from the prior assessment, git history shows moderately churny, multi-author, fix-heavy files but no reverts or hack/workaround sentiment, and the linked high-priority issue remains well-scoped with no open discussion and an explicitly rollback-safe, currently-inert partial fix — none of which provides an articulable reason to move off the prior moderate score.

Previous run

Risk Assessment: moderate (2/5)

Details

Weighted composite (Tier1 2.630.5 + Tier2 2.430.3 + Tier3 2.0*0.2 ~= 2.44 -> 2) reflects a sizeable, bot-authored change touching two protected .github/scripts files and a moderately churny, multi-author area of the codebase, offset by zero security-sensitive paths, no dependency changes, no revert/hack history, a well-scoped high-priority issue with no open discussion, and an explicitly rollback-safe/inert partial fix that cannot affect production behavior until two companion changes land.

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

Review

Findings

High

  • [premature-closure-claim] N/A — The PR body still contains the trailing GitHub closing keyword Closes #7384 (verified via the live GitHub API body field; unchanged since the prior review despite the fix commit's stated attempt to remove it). This keyword auto-closes the linked issue on any merge method (merge, squash, rebase) once this PR lands on the default branch, independent of whether the underlying bug is actually fixed and independent of the PR being bot-authored. Issue Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384 is confirmed open with label priority/high. The PR's own "Remaining integration (not in this PR)" section and docs/contributing/review-handoff-dedup.md's Coordinated rollout / Verification sections state explicitly that production still double-dispatches review until a maintainer-applied .github/workflows/ patch (requiring a workflows-scoped token) and a separate fullsend-ai/agents change both land — "Until the workflow patch and agents-repo change are applied, this issue is not fixed in production." The fix commit's message documents that an attempt to edit the PR body via gh pr edit --body-file failed with a sandboxed 403 (policy_denied on the PR-metadata GraphQL mutation) — the contradiction was never resolved, only attempted. Separately, issue Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384 explicitly requires verification to "exercise PR creation together with automatic labeling, including either event arriving first"; the PR's own testing checklist discloses that this live race is not exercised here ("it needs the maintainer patch plus the agents pin"), reinforcing that this PR is a prerequisite step, not a verified fix, and should not auto-close the issue.
    Remediation: A maintainer must edit the PR body before merge to replace Closes #7384 with a non-closing reference (e.g. Refs #7384 or Part of #7384). This cannot be delegated back to the fix agent — the sandboxed GraphQL PR-metadata mutation is policy-blocked, so a human or the post-script must make the edit. Close Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384 manually only after the workflow patch and the fullsend-ai/agents change have both landed and the live opened+labeled race required by the issue has been verified.

Medium

  • [protected-path] .github/scripts/review-handoff.sh.github/scripts/review-handoff.sh and .github/scripts/review-handoff-test.sh are new files under the protected path prefix .github/, which requires human approval regardless of context. The PR links issue Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384 and its description (plus the accompanying docs/contributing/review-handoff-dedup.md) explains the rationale for adding these CI helper scripts (a shell mirror of the maintainer's proposed workflow YAML decision logic, used for local/CI verification since the coder app cannot push .github/workflows/ changes directly), so context is sufficient. Human approval is still mandatorily required for any change under .github/, independent of this automated review's verdict.
    Remediation: A human maintainer must explicitly review and approve the .github/scripts/ additions before merge, independent of this automated review's verdict.

Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR
Previous run

Review

Findings

High

Medium

  • [protected-path] .github/scripts/review-handoff.sh — This PR modifies files under the protected path prefix .github/.github/scripts/review-handoff.sh and .github/scripts/review-handoff-test.sh — which requires human approval regardless of context. The PR links issue Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384 and its description (plus the accompanying docs/contributing/review-handoff-dedup.md) explains the rationale for adding these CI helper scripts, so context is sufficient, but human approval is still mandatorily required for any change under .github/.
    Remediation: A human maintainer must explicitly review and approve the .github/scripts/ additions before merge, independent of this automated review's verdict.

Low

  • [test-adequacy] internal/dispatch/review_handoff_test.go:324TestGitHubLikeSynchronizeStillReviews, TestGitHubLikeExplicitLabelIgnoresBotUsername, and TestConcurrentGitHubLikeCreation do not exercise production routing. They call the test-local githubLikeReviewDecision helper, which hardcodes opened|synchronize|ready_for_review|slash-review to always dispatch and discards actor/SHA — HarnessRouter.Route has no synchronize/ready_for_review kinds, since GitHub Route logic lives only in the unapplied YAML patch. Concurrent calls to that pure function cannot fail from a real race. The same GitHub-decision table is already exercised in Bash by .github/scripts/review-handoff-test.sh, including greps of the patched YAML, so this is redundant, not-quite-real Go coverage that could be mistaken for verifying the actual patched workflow.
    Remediation: Qualify the PR's verification narrative so it only claims HarnessRouter.Route coverage for the Go skip predicate, and shell-script coverage (via assert_patched_routing) for the GitHub YAML decision table. Consider removing githubLikeReviewDecision and its tests from review_handoff_test.go in favor of the existing shell test.

  • [logic-error] .github/scripts/review-handoff.sh:50github_like_should_dispatch_review's labeled arm dispatches unless the automatic-handoff provenance label is present in the CSV, but never checks that the triggering label is actually ready-for-review (the production YAML in the maintainer patch only enters this skip/dispatch branch when TRIGGERING_LABEL == ready-for-review). The same gap exists in the Go test helper githubLikeReviewDecision's labeled case. This means the shell test helper (and its tests) would not catch a patched workflow that started reviewing on every labeled event, not just ready-for-review.
    Remediation: Pass the triggering label into the helper and only dispatch on labeled when it equals ready-for-review and should_skip_automatic_review_handoff is false; keep other labeled events as skip.

  • [edge-case] docs/contributing/review-handoff-dedup.md:68 — The GitLab contract section (lines ~68-72, ~147-149) says provenance is left in place until pre-review strips it, so a later poll snapshot still carries fullsend-auto-review-handoff. IsAutomaticReviewHandoff skips any ready-for-review add whose State.Labels still includes that provenance marker — exactly the reason GitHub strips it immediately (a leftover marker blocks explicit same-revision re-application). This is dormant today (GitLab does not yet emit MR ready-for-review label events), but if MR label discovery is added later while provenance is still left until pre-review, an explicit ready-for-review re-application in that window would be incorrectly skipped, contradicting the issue's required "deliberate ready-for-review application can request another review" behavior.
    Remediation: When specifying future MR label routing, either strip GitLab provenance earlier (once the poller could have observed both label adds, or once opened has been recorded) rather than only at pre-review, or explicitly document that explicit re-labeling is not guaranteed to dispatch until pre-review removes the marker.

  • [fail-open] docs/contributing/patches/7384-review-handoff-dedup.patch:45 — Today, pull_request_target.labeled (ready-for-review) is a second, independent review trigger, so a lost/failed opened webhook delivery still starts review via the label event. Once the maintainer patch is applied, the new skip removes that backup whenever provenance is present on the label event's snapshot — including cases where labeled is processed but opened never arrives (e.g. webhook delivery failure). This is a defense-in-depth regression to the guarantee that every code-agent PR receives at least one automatic review; it is not attacker-controlled since only the code post-script is expected to add the provenance label, but a leftover/duplicated provenance label (see the edge-case finding above) could hit the same gap.
    Remediation: Document the residual risk (missed opened delivery + provenance present ⇒ no automatic review until /fs-review or a new push), or consider only skipping labeled when there is corroborating evidence the opened event was actually processed.

  • [naming] internal/dispatch/review_handoff_test.go:83 — Existing tests of HarnessRouter methods in internal/dispatch/router_test.go follow the receiver-prefixed convention TestHarnessRouter_<Scenario> (30+ instances). Seven tests added in review_handoff_test.go construct a HarnessRouter and exercise its Route method directly but omit that prefix (TestAutomaticHandoffSkipIgnoresActorIdentity, TestExplicitReadyForReviewDoesNotUseBotName, TestExplicitReadyForReviewStillRequiresWrite, TestOpenedDispatchesEvenWhenHandoffLabelPresent, TestReviewDispatchScenarios, TestConcurrentOpenedAndAutomaticLabel, TestConcurrentOpenedAndExplicitLabel).
    Remediation: Rename these tests to use the TestHarnessRouter_ prefix (e.g. TestHarnessRouter_AutomaticHandoffSkipIgnoresActorIdentity) to match the established convention in the same package.

  • [api-shape] internal/dispatch/review_handoff.go:12AutoReviewHandoffLabel and IsAutomaticReviewHandoff are exported from package dispatch, but they are routing implementation details consumed only by (*HarnessRouter).routeLabel in the same package (plus same-package tests). Sibling internal routing markers/predicates in router.go (changesRequestedMarker, isForkOrUnknown, isObservationStage) are all unexported, so this broadens the package's public surface inconsistently with its own conventions.
    Remediation: Unexport AutoReviewHandoffLabel to autoReviewHandoffLabel and IsAutomaticReviewHandoff to isAutomaticReviewHandoff for consistency with sibling routing helpers.

  • [code-organization] .github/scripts/review-handoff.sh:17review-handoff.sh ships with executable permissions and a #!/usr/bin/env bash shebang but contains only function definitions intended to be sourced, plus a double-load guard ([[ -n "${REVIEW_HANDOFF_SH_LOADED:-}" ]] && return 0) that has no precedent elsewhere in the repo. Other .github/scripts/*.sh files (e.g. check-fix-eligibility.sh) are directly-executable scripts with set -euo pipefail, while shared source-only helpers (e.g. hack/gitlab-runner-vm/lib.sh) don't use an include guard at all. If ever invoked directly with REVIEW_HANDOFF_SH_LOADED already set, the top-level return would error.
    Remediation: If this file is strictly a sourced helper, set its mode to non-executable (0644) and drop the include guard, or otherwise align it with the repo's existing source-only script conventions.

  • [error-handling] .github/scripts/review-handoff-test.sh:122 — Existing shell test scripts under .github/scripts/ (e.g. check-fix-eligibility-test.sh, check-e2e-authorization-test.sh) create a single temp directory at script start with an EXIT trap for cleanup. review-handoff-test.sh's concurrent_count helper calls mktemp -d on each of ~32 iterations (plus once more in the patch test) without any trap, so a failed assertion or subshell under set -e can leave temp directories behind.
    Remediation: Initialize a single top-level TMPDIR at script start with trap 'rm -rf "${TMPDIR}"' EXIT, and place all scratch files/directories under it.


Next steps:

  • /fs-fix — agent addresses review findings automatically
  • /fs-fix <your instruction> — agent fixes with your specific guidance
  • Push commits directly — review re-runs automatically on push
  • /fs-fix-stop — disable automatic fix runs for this PR

fullsend-ai-review[bot]

This comment was marked as outdated.

@fullsend-ai-coder

fullsend-ai-coder Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 2:25 PM UTC · Completed 2:41 PM UTC

Commit: e5bce5c · View workflow run →

Runtime: claude · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $3.02

Addresses the review-handoff dedup review findings:

- Fix the labeled-arm logic error in review-handoff.sh: dispatch
  decisions now require the triggering label to be ready-for-review
  before evaluating the provenance skip, matching the maintainer patch's
  gating on TRIGGERING_LABEL; other labeled events now skip instead of
  dispatching. Updated all review-handoff-test.sh call sites for the new
  parameter and added a regression test for a non-ready-for-review
  labeled event.
- Remove the test-local githubLikeReviewDecision helper and its tests
  from review_handoff_test.go: it duplicated (and shared the bug in) the
  shell decision table without exercising real routing, and the same
  scenarios are already covered by review-handoff-test.sh against the
  actual shell helper and the patched YAML.
- Unexport AutoReviewHandoffLabel/IsAutomaticReviewHandoff to
  autoReviewHandoffLabel/isAutomaticReviewHandoff for consistency with
  sibling routing helpers in router.go; no external package references
  existed.
- Rename the seven tests that exercise HarnessRouter.Route directly to
  the established TestHarnessRouter_ prefix convention.
- Drop the shebang, include guard, and executable bit from
  review-handoff.sh (now 0644): it is sourced-only and never invoked
  directly, matching hack/gitlab-runner-vm/lib.sh's convention.
- Consolidate review-handoff-test.sh's scratch temp directories under a
  single top-level TMPDIR_ROOT with an EXIT trap so a failed assertion
  can't leak temp dirs across the ~32 concurrent-count iterations or the
  patch-apply test.
- Document two residual-risk edge cases in
  docs/contributing/review-handoff-dedup.md: GitLab leaving provenance in
  place until pre-review can shadow a deliberate re-labeling, and a
  lost/failed `opened` delivery combined with a leftover provenance label
  means no automatic review dispatches (new "Known limitations" section,
  referenced from the patch file header).

Disagreements / could not fix:

- [premature-closure-claim] (high): confirmed the PR body's "Closes
  #7384" contradicts its own "Remaining integration" section and the
  rollout doc's "not fixed in production" caveat. Attempted to replace it
  with "Refs #7384" via `gh pr edit --body-file`, but the sandbox network
  policy blocks PR-metadata GraphQL mutations for this agent (403
  policy_denied on POST /graphql). A maintainer or the post-script needs
  to make this edit before merge.
- [protected-path] (medium): this finding only mandates human approval
  for .github/scripts/ changes; it prescribes no content edit, so no code
  change was made for it.

Verification: go test ./internal/dispatch/... -race and
./internal/scaffold/... pass; bash .github/scripts/review-handoff-test.sh
passes; gofmt/go vet clean; go build ./... succeeds; scan-secrets clean.
pre-commit could not fetch remote hook repos in this sandbox (HTTP 403);
ran the applicable hooks directly instead (end-of-file-fixer,
trailing-whitespace, merge-conflict/CRLF checks, lint-broken-symlinks,
lint-docs-links, lychee) — all clean. shellcheck is not installed in this
sandbox and pre-commit could not fetch it, so that hook did not run.

Addresses #7403
@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 1 (bot-triggered)

Fixed 8 of 10 review findings on PR #7403: corrected the labeled-arm triggering-label logic error in review-handoff.sh (with updated tests and a new regression case), removed the redundant/misleading Go test helper duplicating that bug, renamed 7 tests to the TestHarnessRouter_ convention, unexported two dispatch-package symbols, converted review-handoff.sh to a proper sourced-only helper (0644, no shebang/guard), consolidated review-handoff-test.sh's scratch temp dirs under one EXIT-trapped TMPDIR_ROOT, and documented two residual-risk edge cases in the rollout doc (referenced from the patch file). Left the protected-path finding as a no-op (it only mandates human approval, prescribing no edit) and could not apply the PR-body 'Closes #7384' -> 'Refs #7384' fix because the sandbox blocks PR-metadata GraphQL mutations for this agent -- that one needs a maintainer or the post-script.

Fixed (8):

  1. [logic-error] github_like_should_dispatch_review's labeled arm dispatches unless provenance is present, without checking the triggering label is ready-for-review: Added a triggering_label parameter to github_like_should_dispatch_review in .github/scripts/review-handoff.sh; the labeled arm now returns skip immediately when triggering_label != "ready-for-review", only falling through to the provenance check when it is. Updated all call sites in review-handoff-test.sh (assert_route, count_pair, concurrent_count) to pass the triggering label, and added a new regression test ('non-ready-for-review labeled event skips') covering a labeled event whose triggering label is not ready-for-review even though the label snapshot includes the handoff marker.
  2. [test-adequacy] TestGitHubLikeSynchronizeStillReviews/TestGitHubLikeExplicitLabelIgnoresBotUsername/TestConcurrentGitHubLikeCreation exercise a test-local helper, not production routing, and are redundant with the shell test: Removed githubLikeReviewDecision, githubLikeEvent, countGitHubLikeConcurrent, and the three tests built on them from internal/dispatch/review_handoff_test.go. Go coverage in this file now only exercises HarnessRouter.Route (the real skip predicate); GitHub YAML decision-table coverage remains solely in .github/scripts/review-handoff-test.sh against the real github_like_should_dispatch_review shell helper and assert_patched_routing against the patched YAML.
  3. [edge-case] GitLab leaving provenance in place until pre-review could incorrectly skip a deliberate ready-for-review re-application if MR label discovery is added later: Added clarifying notes to docs/contributing/review-handoff-dedup.md: item 5 of the Agents-repo change section now states the consequence explicitly, and the GitLab paragraph under Coordinated rollout documents that explicit re-labeling is not guaranteed to dispatch until pre-review strips the leftover marker, with the two documented remediation options (strip earlier, or document the limitation).
  4. [fail-open] The maintainer patch's labeled skip removes the defense-in-depth guarantee that every PR gets at least one automatic review if the opened webhook is lost: Added a 'Known limitations' section to docs/contributing/review-handoff-dedup.md documenting the residual risk (lost opened delivery + leftover provenance => no automatic review; recover via /fs-review or a new push) and noting it is not attacker-controlled. Referenced this section from the maintainer patch's header comment in docs/contributing/patches/7384-review-handoff-dedup.patch.
  5. [naming] Seven new tests exercising HarnessRouter.Route directly omit the established TestHarnessRouter_ prefix convention used elsewhere in the package: Renamed TestAutomaticHandoffSkipIgnoresActorIdentity, TestExplicitReadyForReviewDoesNotUseBotName, TestExplicitReadyForReviewStillRequiresWrite, TestOpenedDispatchesEvenWhenHandoffLabelPresent, TestReviewDispatchScenarios, TestConcurrentOpenedAndAutomaticLabel, and TestConcurrentOpenedAndExplicitLabel to the TestHarnessRouter_ prefix in internal/dispatch/review_handoff_test.go.
  6. [api-shape] AutoReviewHandoffLabel and IsAutomaticReviewHandoff are exported but only used within package dispatch, inconsistent with sibling unexported routing helpers: Unexported both symbols to autoReviewHandoffLabel and isAutomaticReviewHandoff in internal/dispatch/review_handoff.go, and updated the one external call site in router.go plus all references in review_handoff_test.go. Confirmed via repo-wide grep that no other package referenced either symbol.
  7. [code-organization] review-handoff.sh ships executable with a shebang and an include guard despite being a sourced-only helper, unlike other source-only scripts in the repo: Removed the shebang line and the REVIEW_HANDOFF_SH_LOADED include guard, and changed the file mode from 0755 to 0644, aligning it with hack/gitlab-runner-vm/lib.sh's existing sourced-only convention. Added a comment noting the file is sourced only.
  8. [error-handling] concurrent_count calls mktemp -d on each of ~32 iterations (plus once more in the patch test) without any trap, risking leaked temp directories on a failed assertion under set -e: Added a single top-level TMPDIR_ROOT created once at script start in review-handoff-test.sh with trap 'rm -rf "${TMPDIR_ROOT}"' EXIT. concurrent_count now creates its per-call scratch directory under TMPDIR_ROOT (dropping its own rm -rf), and the maintainer-patch temp-copy test does the same, so all scratch directories are cleaned up by the single exit trap even on early failure.

Disagreed (2):

  1. [premature-closure-claim] PR body 'Closes Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384' will auto-close a still-reproducing production bug on merge: Confirmed valid: the PR body's own 'Remaining integration' section and the rollout doc's 'not fixed in production' caveat contradict the closing keyword. Attempted the fix (replace 'Closes Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384' with 'Refs Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384' via gh pr edit --body-file), but the sandbox network policy blocks PR-metadata GraphQL mutations for this agent (403 policy_denied on POST /graphql). A maintainer or the post-script must make this edit before merge.
  2. [protected-path] .github/scripts/review-handoff.sh and review-handoff-test.sh require mandatory human approval: This finding's category is the mandatory merge-gate marker itself; it prescribes no content edit, only human approval before merge. No code change was made in response to it. (Other findings on these same files that did prescribe concrete content changes -- logic-error, code-organization, error-handling -- were fixed.)

Tests: passed

Decision points
  • Whether to remove the githubLikeReviewDecision Go test helper (test-adequacy finding) versus only qualifying the PR narrative (alternatives: Qualify the PR's verification narrative to scope claims correctly, Remove githubLikeReviewDecision and its tests in favor of the existing shell coverage; rationale: The helper had the same triggering-label bug flagged separately as [logic-error], and removing it eliminates both the redundant/misleading coverage and the duplicated bug in one change, leaving the real shell helper and HarnessRouter.Route as the two sources of truth.)
  • How to fix the [logic-error] finding's labeled-arm gap without breaking existing shell test call sites (alternatives: Add a required triggering_label parameter to github_like_should_dispatch_review and update every caller, Infer the triggering label from the labels CSV heuristically; rationale: The production YAML gates on an explicit TRIGGERING_LABEL variable, not on CSV membership, so an explicit parameter is the only way to make the shell helper actually mirror the real decision and catch a patched workflow that reviews on every labeled event.)

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

@fullsend-ai-review

fullsend-ai-review Bot commented Sep 17, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:43 PM UTC · Completed 3:00 PM UTC

Commit: 9dcdb54 · View workflow run →

Runtime: pi · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $4.76

@fullsend-ai-review fullsend-ai-review 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.

See the review comment for full details.

@fullsend-ai-coder

fullsend-ai-coder Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Finished Fix · ✅ Success · Started 3:02 PM UTC · Completed 3:07 PM UTC

Commit: 9dcdb54 · View workflow run →

Runtime: claude · Model: sonnet → claude-sonnet-5 · Effort: high · Cost: $0.41

@fullsend-ai-coder

Copy link
Copy Markdown
Contributor Author

🔧 Fix agent — iteration 2 (bot-triggered)

Both findings in the current review are outside this agent's ability to address with a code commit. The high-severity finding requires editing the PR body to remove the "Closes #7384" closing keyword, which needs a PR-metadata GraphQL mutation; that call was attempted and confirmed blocked by sandbox endpoint policy (403 policy_denied), so it must be done by a human maintainer or the post-script. The medium-severity protected-path finding is the mandatory merge-gate marker for .github/ changes and only requires human approval, not a content edit. No commit was made this iteration.

Disagreed (2):

  1. [premature-closure-claim] PR body still contains the closing keyword "Closes Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384": Finding is valid on the merits, but the requested change is a PR-metadata edit, not a repository commit. Attempted gh pr edit --body-file to replace "Closes Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384" with "Refs Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews #7384" and it failed with a 403 policy_denied ("GraphQL operation blocked by endpoint policy") on the PR-metadata GraphQL mutation, matching the prior iteration's documented failure. This confirms the finding's own remediation note that the edit cannot be delegated to the fix agent and must be made by a human maintainer or the post-script.
  2. [protected-path] .github/scripts/review-handoff.sh and .github/scripts/review-handoff-test.sh require human approval: This is the mandatory protected-path merge-gate finding. Per policy, a finding categorized protected-path only demands human approval at the merge gate and never itself prescribes a content edit for the fix agent to make — the finding text here does not describe any specific code change, only that a human must approve. No code change applies; leaving the files as-is.

Tests: passed

Decision points
  • Did not attempt any code change this iteration (alternatives: Edit PR body directly, Modify .github/scripts/ files to satisfy protected-path finding, Make no commit and record disagreements; rationale: Both current findings are non-code-fixable by this agent: the closing-keyword fix requires a PR-metadata mutation blocked by sandbox network policy (verified by attempting it), and the protected-path finding is a human-approval gate with no prescribed content change.)

Next steps:

  • /fs-review — request a re-review of the changes
  • /fs-fix <your instruction> — run another fix pass with specific guidance
  • Push commits directly — review re-runs automatically on push
    Updated by fullsend fix agent

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

Labels

ready-for-review Triggers review agent dispatch risk/moderate PR risk: moderate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Review dispatch regression: code-agent PR opening and ready-for-review label start duplicate reviews

1 participant