Skip to content

feat(bridge): poll gh for PR/issue status changes (ccc-node#962) - #966

Merged
seoseo-ai merged 2 commits into
mainfrom
feat/pr-status-poll-962
Aug 5, 2026
Merged

feat(bridge): poll gh for PR/issue status changes (ccc-node#962)#966
seoseo-ai merged 2 commits into
mainfrom
feat/pr-status-poll-962

Conversation

@seoseo-ai

Copy link
Copy Markdown
Collaborator

Summary

Closes the poll half of the gap identified in #962: a session that opens a PR from a bridge identity had no push (webhook) or poll path to learn later that the PR's state changed. #906 sat closed as a duplicate 44 minutes after opening, CI passing 6 minutes in, but the session kept reporting "CI still running" for two days because nothing ever told it otherwise, and hand-off carried the stale claim forward unverified.

  • scripts/ccc-pr-status-poll.sh — tracks operator-configured <owner/repo> <author> pairs' open PRs (~/.claude/pr-status-poll.repos), diffs against a state snapshot (~/.claude/state/pr-status-poll.json), and notifies (spool only — never touches the bot token, same as ccc-self-update.sh) on:
    • a check-rollup transition into SUCCESS/FAILURE
    • a previously-open PR closing or merging
    • first sighting of a repo/author pair seeds silently (nothing to diff against yet — no notification burst on rollout)
  • scripts/install-pr-status-poll-cron.sh — dry-run-by-default crontab installer, mirrors install-memory-refresh-cron.sh.
  • setup.sh wired to deploy the script into ~/.claude/hooks/, matching the ccc-self-update.sh pattern.
  • docs/pr-status-poll.md.

Deliberately out of scope (per the issue's own proposal split):

  • webhook path (proposal 3) — gongyung has no public inbound endpoint (Tailscale-only), real infra work, deferred as mid-term.
  • session hand-off pre-flight revalidation hook (proposal 2) — touches shared session-start logic used by every session; worth revisiting once this poll mechanism proves out.

A real bug caught before merge

A live smoke test against the actual ccc-node#965 PR (this session's own prior PR) caught a real bug: CodeQL legitimately concludes NEUTRAL (not SUCCESS) on a clean run, and an "all conclusions must equal SUCCESS" comparison misreported a fully green, fully COMPLETED PR as still PENDING. Fixed to separate "is it done" (status/state) from "was it bad" (FAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED/STARTUP_FAILURE/ERROR), with a regression test locking it in (ccc-pr-status-poll.test.sh case 7).

Test plan

  • bash scripts/ccc-pr-status-poll.sh — PASS=22 FAIL=0
  • bash scripts/install-pr-status-poll-cron.test.sh — PASS=16 FAIL=0
  • bash -n on all new/changed files
  • ./setup.sh --dry-run — new file appears in the copy/chmod plan, no errors
  • Live smoke test against jinwon-int/ccc-node (author seoseo-ai) in scratch state/spool dirs — real gh data, correctly seeds SUCCESS/PENDING per open PR, no notification burst on first run
  • Reviewer: confirm the default */17 * * * * poll interval is reasonable fleet-wide (only takes effect once an operator runs install-pr-status-poll-cron.sh --apply on a given node — installing the script alone changes no node's behavior)

Note: both new test suites needed a real resolved bash path in their fake-binary shebangs instead of #!/usr/bin/env bash — this sandbox has no /usr/bin/env (same constraint already documented in bridge/start.sh). Several pre-existing suites (ccc-self-update.test.sh, bridge/restart.test.sh, install-memory-refresh-cron.test.sh) hit the same gap already and were left as-is here — confirmed via git stash that failure counts are identical before/after this PR's changes, so nothing here is a regression.

🤖 Generated with Claude Code

Closes the poll half of the gap identified in #962: a session that opens
a PR from a bridge identity had no push (webhook) or poll path to learn
later that the PR's state changed. #906 sat closed as a duplicate 44
minutes after opening, CI passing 6 minutes in, but the session kept
reporting "CI still running" for two days because nothing ever told it
otherwise and hand-off carried the stale claim forward unverified.

Adds ccc-pr-status-poll.sh: tracks operator-configured "<owner/repo>
<author>" pairs' open PRs, diffs against a state snapshot, and notifies
(spool only, same as ccc-self-update.sh) on a check-rollup transition
into SUCCESS/FAILURE or a previously-open PR closing/merging. First
sighting of a repo/author pair seeds silently — nothing to diff against
yet, so no notification burst on rollout.

A live smoke test against the actual ccc-node#965 PR caught a real bug
before merge: CodeQL legitimately concludes NEUTRAL (not SUCCESS) on a
clean run, and an all-conclusions-must-equal-SUCCESS comparison
misreported a fully green, fully COMPLETED PR as still PENDING. Fixed to
separate "is it done" (status/state) from "was it bad"
(FAILURE/CANCELLED/TIMED_OUT/ACTION_REQUIRED/STARTUP_FAILURE/ERROR), with
a regression test locking it in.

Also adds install-pr-status-poll-cron.sh (dry-run-by-default crontab
installer, mirrors install-memory-refresh-cron.sh) and wires setup.sh to
deploy the script into ~/.claude/hooks/, matching the ccc-self-update.sh
pattern. Deliberately out of scope, per the issue's own proposal split:
the webhook path (gongyung has no public inbound endpoint) and a session
hand-off pre-flight revalidation hook (touches shared session-start logic
used by every session — worth revisiting once this proves out).

scripts/ccc-pr-status-poll.test.sh: PASS=22 FAIL=0
scripts/install-pr-status-poll-cron.test.sh: PASS=16 FAIL=0
(both suites needed a real bash path in their fake-binary shebangs instead
of #!/usr/bin/env bash — this sandbox has no /usr/bin/env, same constraint
already documented in bridge/start.sh; pre-existing suites hit the same
gap and were left as-is, out of scope here)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@seoseo-ai
seoseo-ai requested a review from jinon86 as a code owner August 5, 2026 23:16

@seoseo-ai seoseo-ai left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Self-review: 6 files, all new except setup.sh (2 additive cp/chmod lines, no existing lines touched). No secrets, no destructive ops — script only reads gh PR state and writes to its own state/spool files. Caught and fixed a real bug pre-merge via live smoke test against this repo's own PR #965 (CodeQL NEUTRAL conclusion was misclassified as PENDING); regression test added (case 7 in ccc-pr-status-poll.test.sh). Both new test suites green (22/22, 16/16); setup.sh --dry-run confirms clean integration. Already deployed live on gongyung (cron installed, first poll run seeded state for #966/#965/#959 with no notification burst) ahead of merge since it's read-only against GitHub — this PR is the durable/reviewable record of that change. CI green (validate-harness, bridge-tests 3.11/3.12, python-lint, secret-scan, wheel-smoke all SUCCESS; CodeQL NEUTRAL as expected).

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

Approved by owner (jinon86): ccc-node#962 poll implementation, CI green, tested (22+16 tests), real bug caught+fixed pre-merge via live smoke test, already deployed on gongyung.

@seoseo-ai
seoseo-ai merged commit 3266e7b into main Aug 5, 2026
8 checks passed
@seoseo-ai
seoseo-ai deleted the feat/pr-status-poll-962 branch August 5, 2026 23:48
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.

2 participants