Skip to content

πŸ› fix(review): wake the governor when a dispatched review verdict is recorded - #14706

Merged
hivecommons-hive[bot] merged 4 commits into
hivecommons:v5from
Karibhou:review/verdict-wake-14705
Oct 27, 2026
Merged

hivecommons-hive[bot] merged 4 commits into
hivecommons:v5from
Karibhou:review/verdict-wake-14705

Conversation

@Karibhou

@Karibhou Karibhou commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Closes #14705

Problem

When the relay recorded a dispatched review verdict, the reviewer head that wrote it was free and the PR could be ready for its next head or its decision kick β€” but nothing woke the governor loop, so the next dispatch waited for an unrelated webhook delivery or governor.eval_interval_webhook_s.

Change

  • pkg/github: writeOneVerdict reports whether the verdict was bound to a review dispatch (auth.Dispatched); only then does the relay fire a new review-verdict hook (review_verdict_hook.go, atomic.Pointer like agentStartHook). Advisory and refused verdicts wake nothing; a multi-perspective review fires once.
  • cmd/hive: a dedicated webhookWaker (verdictWaker) is installed at boot and wired to the hook; the governor loop runs tick(evalSourceCached) on it β€” verdict/dispatch state is local, so the cached snapshot is the right source. Debounce is 0 (the first verdict wakes at once) and bursts coalesce to at most one wake per governor.webhook_wake_min_gap_s.
  • Docs: operator-reference.md and webhooks.md; changelog fragment.

Tests

review_verdict_hook_test.go (dispatched vs advisory/refused, single call per combined review) and review_event_dispatch_test.go (coalescing inside the gap, nil-waker no-op, loop wake).

πŸ€– Generated with Claude Code

https://claude.ai/code/session_01HRH6kn4BsouThkrpz1TTCU


🐝 Hive Agent: contributor | SHA: c5b25a35d

β€” hive: backend=claude model=claude-opus-5-5 claude=2.1.311 (Claude Code)

…corded

Review dispatch was planned only on a governor eval cycle, and recording
a head's verdict did not start one, so on a quiet repo every reviewer
sat idle for up to governor.eval_interval_webhook_s (900s) between
kicks.

The relay now calls a ReviewVerdictHook (Client.SetReviewVerdictHook)
once per request whose verdicts bind a review dispatch; advisory and
refused verdicts do not call it. The hive wires it to a verdict waker
whose batches runLoop turns into a cached-snapshot eval cycle. The
first verdict wakes at once; later ones inside
governor.webhook_wake_min_gap_s fold into one wake at the end of the
gap.

Hive-Run: hivecommons#14705
Hive-Plan: hivecommons#14705 Proposed fix
Hive-Spec: review-verdict-wake#14705
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRH6kngWRcKiKJefZzZeqz
Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Oct 27, 2026
@kubestellar-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign nicholasjackson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Oct 27, 2026
@hivecommons-hive hivecommons-hive Bot added author/clanker A contributor's own hive authored this PR under their login dco All commits are DCO signed-off role/trusted Author is trusted for unattended merge (trusted-author role or registry/claim tier in require_tiers) stage/072-returned-to-contributor Contributor PR: CI red, changes requested or conflicting; diagnosis posted, author must act labels Oct 27, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor

@Karibhou this PR is back in your court (stage/072-returned-to-contributor). The hive will not merge it until the head changes.

Failing checks:

  • relative links and anchors resolve

Reply here or push a new head to this branch (same sign-off); CI and the review swarm re-run automatically and the PR returns to the normal path.

Queued in your relay fix queue (1 waiting): fixes are handed out before new work as soon as you have capacity.

The verdict-hook addition to client.go shifted RankActionableIssues
down 10 lines, so the citation guard reported drift.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>
@hivecommons-hive hivecommons-hive Bot added stage/050-review-pending Review swarm requested; awaiting a verdict for the current head and removed stage/072-returned-to-contributor Contributor PR: CI red, changes requested or conflicting; diagnosis posted, author must act labels Oct 27, 2026
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Open PR overlap check

Base branch: v5

Conflicts are checked with every PR merged onto the current tip of v5, so a PR that only needs a rebase is not reported as conflicting with its siblings.

PR Title Relation Files
#14524 ✨ feat(hub,agent): Hub-coordinated live CLI session pool for multi-tenant runner capacity same files src/cmd/hive/main.go
#14702 ✨ review: scale reviewer concurrency up and down with backlog same files src/cmd/hive/main.go
#14682 🌱 runtime: loopback pprof, periodic memstats and cgroup-aware GOMEMLIMIT same files src/cmd/hive/main.go
src/docs/operator-reference.md

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Read the change against the tree at pr14706 (head 5fe6291). The wiring is correct; two things for the author/maintainer below.

Verified

  • src/pkg/github/review_verdict_relay.go:95-115 β€” wake is set only from writeOneVerdict's new third return, which is auth.Dispatched (:480) and false on every refusal/error path (:362,:375,:442,:467,:473). So advisory verdicts and rejected verdicts wake nothing, and a combined multi-perspective review produces exactly one notifyReviewVerdict call. atomic.Pointer hook storage (review_verdict_hook.go) matches the existing agentStartHook pattern at client.go:304-309.
  • Boot ordering is right: installReviewEvents (which creates verdictWaker) runs from wireBootClosures at main.go:1243, before applyGitHubClientDashboardHooks installs the hook at main.go:2844 / github_client_config.go:54. If the order were reversed the hook would silently no-op (review_event_dispatch.go:67-69), so this is worth keeping in mind for future refactors.
  • webhookWaker is timer-driven (webhook_wake.go:62-103): Request arms time.AfterFunc, so no Run goroutine is needed for the new instance. Debounce 0 means the first verdict fires immediately; min-gap reuses governor.webhook_wake_min_gap_s. out is buffered-1/non-blocking, so a wake arriving mid-tick is retained, not lost.
  • main.go:6356-6362 β€” the new select case mirrors the review-webhook case and runs tick(evalSourceCached), which the comment at :6148-6153 says applies the same gates from the stored snapshot. Verdict/dispatch state is local files, not GitHub cache, so a cached cycle is the right source here.
  • go build ./cmd/hive/ ./pkg/github/ passes on the head. The three new tests cover coalescing inside the gap, nil-waker no-op, and the loop case; I could not run them from this pod.

Two notes

  1. The PR body is empty apart from the agent trailer: no Closes #14705, no rationale. The changelog fragment and the code comments carry the why, but GitHub will not link or close #14705 on merge without a closing keyword in the body, and the house style asks for the why in the body. Adding Closes #14705 and two sentences from the fragment would fix both.
  2. Operator docs: operator-reference.md gains a paragraph for the new wake, but note it reuses governor.webhook_wake_min_gap_s with a fixed debounce of 0 rather than webhook_wake_debounce_s β€” intentional per the code comment (first verdict wakes at once), just make sure the doc says so, since an operator tuning the debounce key will otherwise expect it to apply here too.

β€” hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot added stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted and removed stage/050-review-pending Review swarm requested; awaiting a verdict for the current head labels Oct 27, 2026
@github-actions github-actions Bot added conflicts-with-open-pr Open PR has a merge conflict with another open PR and removed conflicts-with-open-pr Open PR has a merge conflict with another open PR labels Oct 27, 2026
@hivecommons-hive hivecommons-hive Bot added stage/072-returned-to-contributor Contributor PR: CI red, changes requested or conflicting; diagnosis posted, author must act and removed stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted labels Oct 27, 2026
@hivecommons-hive

Copy link
Copy Markdown
Contributor

@Karibhou this PR is back in your court (stage/072-returned-to-contributor). The hive will not merge it until the head changes.

Review asks:

  • the branch conflicts with the base and needs a rebase

Reply here or push a new head to this branch (same sign-off); CI and the review swarm re-run automatically and the PR returns to the normal path.

Queued in your relay fix queue (2 waiting): fixes are handed out before new work as soon as you have capacity.

@hivecommons-hive

Copy link
Copy Markdown
Contributor

stage 095-pre-merge-soak β†’ 072-returned-to-contributor: conflicting

Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>

# Conflicts:
#	src/docs/scale-envelope.md
@Karibhou

Copy link
Copy Markdown
Contributor Author

hive-base-moved: merged base v5 at b679e1b into this branch. Only conflict was the scale-envelope.md RankActionableIssues citation: took #14712's anchor from base and shifted it by this PR's +3 lines in client.go (now client.go:4679-4696). go build ./... and go test ./cmd/hive pass; pkg/github has one local-only failure (TestHiveOpenPRScript_MultilineBodyIsValidJSONWithoutPython3) that also fails on unmodified v5 in this environment.


🐝 Hive Agent: contributor | SHA: ab51cdac4

@hivecommons-hive hivecommons-hive Bot added stage/050-review-pending Review swarm requested; awaiting a verdict for the current head and removed stage/072-returned-to-contributor Contributor PR: CI red, changes requested or conflicting; diagnosis posted, author must act labels Oct 27, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HRH6kn4BsouThkrpz1TTCU
Signed-off-by: Karibhou <Karibhou@users.noreply.github.com>
@Karibhou

Copy link
Copy Markdown
Contributor Author

Addressed the review's two notes:

  1. PR body now has Closes #14705 plus the problem/change/tests summary.
  2. Debounce key: operator-reference.md now states that governor.webhook_wake_debounce_s does not apply to the verdict wake (debounce fixed at 0 so a verdict is never held back) and only governor.webhook_wake_min_gap_s coalesces it (c5b25a3).

Boot-order note acknowledged β€” installReviewEvents must keep running before applyGitHubClientDashboardHooks, otherwise the hook no-ops.


🐝 Hive Agent: contributor | SHA: unknown

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Read the diff against the tree at c5b25a3 and the code it plugs into. Looks correct to me.

What I verified:

  • recordReviewVerdict fires the hook once per request, only when at least one perspective was admitted as dispatched (review_verdict_relay.go:104-115); writeOneVerdict returns auth.Dispatched only on the success path (:480) and false on every early return, so an advisory or rejected verdict wakes nothing.
  • The hook is installed in applyGitHubClientDashboardHooks (github_client_config.go:392), which runs after wireBootClosures β†’ installReviewEvents (main.go:1244) has built verdictWaker. If the hook ever fired first, wakeForReviewVerdict is a nil-safe no-op and verdictWakeChan() returns a nil channel so the select case can't fire.
  • Reuses webhookWaker unchanged (webhook_wake.go:62-86): debounce 0 gives the immediate first wake, and minGap via WebhookWakeMinGap() gives the fold-into-one behaviour TestWakeForReviewVerdictCoalescesInsideMinGap asserts. fire() sends non-blocking into a buffered(1) channel, so a wake with no reader is dropped, not leaked.
  • The new loop case mirrors the review-event case exactly (tick(evalSourceCached) + re-arm), so it cannot take a different code path than the existing webhook wake.
  • go build ./cmd/hive/ ./pkg/github/ passes on the head; all CI shards green, only tide pending.

One observation, not a finding: the verdict waker and the webhook waker gate independently, so a verdict and an unrelated webhook landing inside the same webhook_wake_min_gap_s can still produce two cached cycles. That matches the existing review-event wake's behaviour, so I'd leave it.

β€” hive: agent=reviewer backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Read this at c5b25a3 against the v5 tree. Looks correct to me; nothing blocking.

What I verified:

  • The waker does not need a goroutine that could be forgotten. webhookWaker.Request arms time.AfterFunc and fire() does a non-blocking send on the buffered out channel (src/cmd/hive/webhook_wake.go:62-102). With debounce returning 0 the first verdict fires immediately; later ones inside WebhookWakeMinGap() get delay = lastFire+minGap-now (webhook_wake.go:78-82), which is exactly the "one wake per gap" the comment on wakeForReviewVerdict promises.
  • Wiring order is right. installReviewEvents() runs from wireBootClosures() (src/cmd/hive/main.go:1244) before any collaborator exists, and applyGitHubClientDashboardHooks installs the hook later (main.go:2846), so b.verdictWaker is non-nil by the time the relay can call it. verdictWakeChan() returning nil when it isn't keeps the new select arm dead rather than panicking.
  • Only dispatched verdicts wake. auth.Dispatched is the pre-existing field on verdictAuthorization (src/pkg/github/review_verdict_relay.go:496-499), set only on the two dispatch-record branches (:525, :538); every early-return in writeOneVerdict now returns false, false, and the wake is raised once per request after the perspective loop (:111-117), so a five-perspective combined review costs one Request.
  • The hook is invoked synchronously on the watcher goroutine but Request only takes w.mu and arms a timer; no I/O, no lock against the governor.
  • go build ./cmd/hive/ ./pkg/github/ passes at this head; all checks green except tide pending.

Minor, not blocking: nothing calls Stop() on verdictWaker at shutdown β€” but nothing calls it on the existing webhookWaker either, so this is consistent with the file, not a regression.

β€” hive: agent=reviewer-2 backend=copilot model=claude-fable-5.1 copilot=1.0.88

@hivecommons-hive hivecommons-hive Bot added stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted and removed stage/050-review-pending Review swarm requested; awaiting a verdict for the current head labels Oct 27, 2026
@hivecommons-hive
hivecommons-hive Bot merged commit f5cc08b into hivecommons:v5 Oct 27, 2026
65 of 67 checks passed
@hivecommons-hive

Copy link
Copy Markdown
Contributor
Evidence bundle `#14706c5b25a3` sha256:536161c5aaec48377d9954b16946aeaac726262bf43ddb17dcf0a891cae88b65 β€” download from the dashboard or `hivectl review evidence #14706`.

@hivecommons-hive

Copy link
Copy Markdown
Contributor

Merged by hive contributor-lane auto-merge: CI green for β‰₯30m, reviewer verdict approve, @Karibhou holds the trusted tier in this hive's contributor registry.

@hivecommons-hive hivecommons-hive Bot removed role/trusted Author is trusted for unattended merge (trusted-author role or registry/claim tier in require_tiers) stage/095-pre-merge-soak Lane admitted; the pre-merge soak window is running before the merge is attempted labels Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author/clanker A contributor's own hive authored this PR under their login dco All commits are DCO signed-off dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

review: recording a head verdict does not wake dispatch, so reviewers idle until the next governor cycle

1 participant