Skip to content

fix(dispatcher): add process-group signal to review_near_success (#132, INV-24) - #133

Merged
zxkane merged 1 commit into
mainfrom
fix/132-review-pgrp-signal
May 15, 2026
Merged

fix(dispatcher): add process-group signal to review_near_success (#132, INV-24)#133
zxkane merged 1 commit into
mainfrom
fix/132-review-pgrp-signal

Conversation

@zxkane

@zxkane zxkane commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a fifth signal to review_near_success (skills/autonomous-dispatcher/scripts/lib-dispatch.sh): walk the review wrapper's process group via pgrep -g <pgid> + ps -o comm= -p <pid> and treat as ALIVE/skip-crash if any group member's comm matches AGENT_CMD. PGID == content of review-${ISSUE}.pid because _run_with_timeout's setsid makes session-leader PID == PGID.
  • Closes the gap reproduced on a downstream consumer's feat(autonomous-review): retry codex on transient stream-error (turn.failed) instead of opaque 'unavailable' drop — surface a codex drop reason #209 (2026-05-15 16:00:39Z): a 14-min review wrapper hit pid_alive triple miss (kill -0 / PID-file mtime / heartbeat sibling mtime all stale) AND four legacy PR-state signals all negative (PR not merged, no APPROVED, no verdict comment, defensive kill -0 missed) — dispatcher declared crashed, label flipped to pending-dev, and 4 minutes later a phantom dev-resume fired one second before the same wrapper successfully merged the PR.
  • INV-24 in docs/pipeline/invariants.md enumerates all 5 signals with a dated 2026-05-16 note explaining the gap signal 5 closes.

Why "additive, last in chain"

Signal ordering is cost-cheapest first: 1+2 share one fetch_pr_for_issue call, 3 is one gh-api call, 4 is a single kill -0, 5 hits the kernel proc table. Earlier signals short-circuit before signal 5 runs (regression-pinned by TC-RNS-009). The new signal never replaces a positive earlier signal — only augments the all-negative path. REVIEW_NEAR_SUCCESS_WINDOW_SECONDS=0 strict-knob override fires at the early numeric guard before any signal runs (TC-RNS-010 pins).

Defensive guards (all silent skips, never fail-closed)

  1. PGID must parse as positive integer (rejects empty file / pgrep -g 0 which returns kernel processes).
  2. pgrep must be on PATH.
  3. ps must be on PATH.

Substring match *${AGENT_CMD}* tolerates Linux's 15-char comm truncation. Over-match is preferred here because the signal only runs after 4 others already failed; a false positive defers crash declaration by one tick at most, while a false negative reproduces #209.

Test Plan

  • Test cases documented (docs/test-cases/review-near-success-pgrp-signal.md)
  • tests/unit/test-dispatcher-review-near-success.sh extended from 6 cases to 11 (TC-RNS-007..011: positive-alone / all-five-negative / legacy-positive-short-circuits-before-pgrep / strict-knob-overrides-pgrep / empty-PID-skips-pgrep-silently)
  • Full unit-test suite green (61 files locally)
  • shellcheck -S error clean on lib-dispatch.sh + extended test file
  • Code review passed (no findings ≥ Medium; verified helper behaviour against live process group)
  • Pipeline doc INV-24 updated in same PR (CLAUDE.md authority rule)

Checklist

  • New unit tests written for new functionality
  • Pipeline docs updated in same PR
  • No E2E required — lives entirely in shell unit-test territory

Closes #132

… INV-24)

Adds a fifth signal to `review_near_success`: walk the review wrapper's
process group (PGID == content of `review-${ISSUE}.pid`, because
`_run_with_timeout`'s `setsid` makes session-leader PID == PGID) via
`pgrep -g <pgid>` + `ps -o comm= -p <pid>` and treat as ALIVE/skip-
crash if any group member's `comm` matches `AGENT_CMD`.

Reproduced on a downstream consumer's #209 (2026-05-15 16:00:39Z): a
14-min review wrapper hit `pid_alive` triple miss (kill -0 / PID-file
mtime / heartbeat sibling mtime all stale), and the four legacy PR-state
signals (PR.mergedAt / APPROVED / verdict comment / defensive kill -0)
were all negative because the wrapper hadn't yet emitted any of those
artifacts. Dispatcher declared crashed → `reviewing → pending-dev`,
which 4 minutes later created a phantom dev-resume one second before
the same wrapper successfully merged the PR.

The new signal is additive — never replaces an existing positive
signal — and runs LAST in the cost-ordered chain (1+2: shared fetch_pr
call, 3: gh-api call, 4: kill -0, 5: pgrep+ps). Substring match against
AGENT_CMD tolerates Linux's 15-char `comm` truncation. Three defensive
guards (numeric PGID, pgrep on PATH, ps on PATH) keep the signal a
silent skip rather than fail-closed when prereqs aren't met.

Pipeline doc (CLAUDE.md authority rule): INV-24 enumerates 5 signals
with a dated 2026-05-16 note explaining the gap signal 5 closes.

Tests: extends `tests/unit/test-dispatcher-review-near-success.sh` from
6 cases to 11 (TC-RNS-007..011): new positive path alone, all-five-
negative crash path, legacy-positive-short-circuits-before-pgrep
ordering pin, strict-knob-overrides-pgrep, empty-PID-skips-pgrep-
silently. Full suite (61 files) green; lib-dispatch.sh + test file
shellcheck-clean.

Closes #132

@amazon-q-developer amazon-q-developer 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.

This PR successfully addresses the gap identified in issue #132 where long-running review wrappers could be falsely declared crashed during the window between "review wrapper is processing" and "review wrapper has emitted its first artifact."

The implementation is solid:

  • Adds a fifth signal (process-group walk) to review_near_success that checks if any descendant process in the review wrapper's process group has a comm matching AGENT_CMD
  • Properly ordered as the last (most expensive) signal, with TC-RNS-009 pinning this ordering
  • Defensive guards ensure it never fails closed (skips silently on empty PID, missing tools, etc.)
  • Comprehensive test coverage: 5 new test cases (TC-RNS-007..011) bringing total from 6 to 11
  • Thorough documentation updates in both invariants.md and dedicated test case doc

The fix closes the production gap reproduced in #209 while maintaining backward compatibility through the REVIEW_NEAR_SUCCESS_WINDOW_SECONDS=0 strict knob.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@zxkane
zxkane merged commit 4909a77 into main May 15, 2026
4 checks passed
@zxkane
zxkane deleted the fix/132-review-pgrp-signal branch May 15, 2026 16:57
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(dispatcher): review_near_success can't see a still-running review wrapper that hasn't yet posted a verdict

1 participant