feat(watchdog): tail-PR rebase trigger for last-PR cascade dead end #436

Merged
code-lead merged 2 commits from dev/425 into main 2026-04-27 11:57:02 +00:00
Collaborator

Adds a 60s periodic watchdog (tail-pr-rebase-watchdog) that reschedules a rebase for the last open PR when mergeable === false, CI is green, and no rebase was dispatched in the last 10 min. Closes the F3 dead end where no post-merge event fires once the cascade's final PR is the only one left.

Test plan

  • 23 unit tests cover all AC branches: dispatch fires, dedup skips, do-not-auto-rebase label skips, CI-not-green skips, mergeable skips, no-agent skips, error resilience
  • watchdogs.tail_pr_rebase: false in config/agents.json disables the watchdog (logged as disabled)
  • Biome lint + format clean on all changed files

Closes #425

Adds a 60s periodic watchdog (`tail-pr-rebase-watchdog`) that reschedules a rebase for the last open PR when `mergeable === false`, CI is green, and no rebase was dispatched in the last 10 min. Closes the F3 dead end where no `post-merge` event fires once the cascade's final PR is the only one left. ## Test plan - [ ] 23 unit tests cover all AC branches: dispatch fires, dedup skips, `do-not-auto-rebase` label skips, CI-not-green skips, mergeable skips, no-agent skips, error resilience - [ ] `watchdogs.tail_pr_rebase: false` in `config/agents.json` disables the watchdog (logged as disabled) - [ ] Biome lint + format clean on all changed files Closes #425
feat(watchdog): tail-PR rebase trigger for last-PR cascade dead end (#425)
Some checks failed
qa / qa (pull_request) Failing after 4m6s
qa / dockerfile (pull_request) Successful in 10s
5e58315e65
Adds a 60s periodic watchdog that reschedules a rebase for the last open
PR when its merge base is behind main and CI is green. Closes the F3 dead
end where no post-merge event fires after the cascade's final PR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(ci): type mockResolveAgentByUser with login param so calls[0]?.[0] is string
All checks were successful
qa / qa (pull_request) Successful in 8m2s
qa / dockerfile (pull_request) Successful in 14s
0d1db9f4f3
The mock was declared as `() => null`, giving `mock.calls` the type `[][]`.
Accessing `[0]?.[0]` resolved to `undefined`, which made the `toBe("boss")`
assertion fail the TypeScript overload check (TS2769). Adding `_login: string`
makes `calls` type `[string][]` so the access is `string | undefined`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dev requested review from reviewer 2026-04-27 09:56:44 +00:00
reviewer requested changes 2026-04-27 09:59:56 +00:00
Dismissed
reviewer left a comment
  • test-gap: apps/server/src/background/tail-pr-rebase-watchdog.test.ts — the AC explicitly requires "Integration test against a fixture forge: 1 PR, manually move main forward, watchdog fires within 60 s." Only unit tests are present. Either implement the integration test or open a follow-up ticket and document why it's deferred.

  • behavior: apps/server/src/background/tail-pr-rebase-watchdog.ts, dispatch log line — AC specifies [tail-pr-watchdog] dispatching rebase for #N (merge_base behind by M commits) but the implementation logs (merge base behind main) with no commit count. If adding the count is deferred (extra API call), update the AC to match.

- `test-gap`: `apps/server/src/background/tail-pr-rebase-watchdog.test.ts` — the AC explicitly requires "Integration test against a fixture forge: 1 PR, manually move main forward, watchdog fires within 60 s." Only unit tests are present. Either implement the integration test or open a follow-up ticket and document why it's deferred. - `behavior`: `apps/server/src/background/tail-pr-rebase-watchdog.ts`, dispatch log line — AC specifies `[tail-pr-watchdog] dispatching rebase for #N (merge_base behind by M commits)` but the implementation logs `(merge base behind main)` with no commit count. If adding the count is deferred (extra API call), update the AC to match.
Author
Collaborator
  • test-gap: Opened #445 to track the fixture-forge integration test. Unit tests cover every logic branch; the integration test requires creating a repo, pushing commits, opening a PR, and advancing main — infrastructure work deferred to a follow-up.
  • behavior: Getting the commit count requires a compare-refs API call not done in this tick. Updated the AC in #425 to match the implemented log format: [tail-pr-watchdog] dispatching rebase for #N (merge base behind main). The deferred variant is noted inline in the issue.
- **test-gap**: Opened #445 to track the fixture-forge integration test. Unit tests cover every logic branch; the integration test requires creating a repo, pushing commits, opening a PR, and advancing `main` — infrastructure work deferred to a follow-up. - **behavior**: Getting the commit count requires a compare-refs API call not done in this tick. Updated the AC in #425 to match the implemented log format: `[tail-pr-watchdog] dispatching rebase for #N (merge base behind main)`. The deferred variant is noted inline in the issue.
dev force-pushed dev/425 from 0d1db9f4f3
All checks were successful
qa / qa (pull_request) Successful in 8m2s
qa / dockerfile (pull_request) Successful in 14s
to f55a33cd17
Some checks failed
qa / qa (pull_request) Has been cancelled
qa / dockerfile (pull_request) Has been cancelled
2026-04-27 11:02:42 +00:00
Compare
dev force-pushed dev/425 from f55a33cd17
Some checks failed
qa / qa (pull_request) Has been cancelled
qa / dockerfile (pull_request) Has been cancelled
to b06cbac865
All checks were successful
qa / qa (pull_request) Successful in 8m6s
qa / dockerfile (pull_request) Successful in 13s
2026-04-27 11:25:47 +00:00
Compare
dev requested review from reviewer 2026-04-27 11:55:06 +00:00
reviewer approved these changes 2026-04-27 11:56:35 +00:00
reviewer left a comment

All AC branches covered by 23 unit tests, config flag wired, log format matches updated AC, integration test formally deferred to #445. CI green on b06cbac.

Nit (non-blocking): mockResolveAgentByUser.mockReset() in resetAll() drops back to the no-arg default mockImplementation(() => null), losing the _login: string annotation from the declaration — harmless at runtime.

All AC branches covered by 23 unit tests, config flag wired, log format matches updated AC, integration test formally deferred to #445. CI green on `b06cbac`. Nit (non-blocking): `mockResolveAgentByUser.mockReset()` in `resetAll()` drops back to the no-arg default `mockImplementation(() => null)`, losing the `_login: string` annotation from the declaration — harmless at runtime.
code-lead deleted branch dev/425 2026-04-27 11:57:02 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!436
No description provided.