test(heartbeat): unblock merge queue after lock invariant change - #1298
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: f082b4f
Looks good. The cleanup change drains fire-and-forget heartbeat work before serialized truncation, and the retry expectation reflects that scheduled retries do not retain an issue execution lock before claim.
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
heartbeat-finalize-cancelled-skip-dispatch.test.ts:87now uses the canonical heartbeat cleanup sequence, preventing teardown races with in-flight dispatcher writes.heartbeat-retry-scheduling.test.ts:2639verifies the intended running-only execution-lock behavior directly.
Recommended Action
- Merge when the required checks pass.
allyblockcast
left a comment
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: f082b4f
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- The retry assertion now matches the running-only issue-lock invariant.
- The finalize-cancelled test uses canonical cleanup that drains fire-and-forget heartbeat execution before serialized teardown.
Recommended Action
- Merge when required checks are green.
allyblockcast
left a comment
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: f082b4f
Looks good. The cleanup change drains fire-and-forget heartbeat work before serialized truncation, and the retry expectation reflects that scheduled retries do not retain an issue execution lock before claim.
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
heartbeat-finalize-cancelled-skip-dispatch.test.ts:87now uses the canonical heartbeat cleanup sequence, preventing teardown races with in-flight dispatcher writes.heartbeat-retry-scheduling.test.ts:2639verifies the intended running-only execution-lock behavior directly.
Recommended Action
- Merge when the required checks pass.
Superseded by the singleton Ally team approval for f082b4f.
|
Hey @kkroo! Before this PR can be reviewed, a few things need attention: Missing or incomplete:
Once updated, push a new commit and these checks will re-run automatically. — commitperclip |
f082b4f to
b6461bb
Compare
|
@ally please submit a fresh exact-head App review for @allyblockcast please independently inspect the same exact head and submit a formal User-seat approve or request-changes review for the singleton-team rule. This head is rebased onto current |
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: b6461bb
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- Replacement recovery is constrained by company, issue, participant, and review-stage identity, avoiding suppression from unrelated queued work.
- The recovery sweep applies the exact queued participant-recovery guard before escalating a terminal review run.
- The adjusted retry-lock assertion matches the claim-time lock invariant.
Recommended Action
- Safe to merge from this review's perspective.
allyblockcast
left a comment
There was a problem hiding this comment.
Ally — Consolidated PR Review
Lenses: pr-review-toolkit (code, tests, comments, errors, types) + gstack/review + native-codex.
Reviewed head: b6461bb
Critical Issues (0)
Important Issues (0)
Suggestions (0)
Strengths
- Replacement recovery is constrained by company, issue, participant, and review-stage identity, avoiding suppression from unrelated queued work.
- The recovery sweep applies the exact queued participant-recovery guard before escalating a terminal review run.
- The adjusted retry-lock assertion matches the claim-time lock invariant.
Recommended Action
- Safe to merge from this review's perspective.
|
Confirming this is the correct direction, and flagging what still blocks it. Full analysis in BLO-25610. This fix is right. The expectation it changes came from I closed #1296, which proposed the opposite fix (make scheduled session retries hold the lock). It special-cased two retry families against a deliberate invariant and would have re-created the stale-lock class that What still blocks this PR.
Those are pre-existing on master. They were invisible because the retry-scheduling failure aborted the shard before that batch ran — which is also the likely reason both offending commits landed green. Same root cause: I have not fixed that one. The plausible direction is to re-derive the participant's latest run for the stage inside the escalation transaction instead of watching the lock, but I could not confirm the replacement signal actually fires in the failing scenario, and a wrong "skip" there is silent — stranded reviews would quietly stop being escalated. That earns a second reader rather than a speculative push. Details and reproduction notes are in BLO-25610. |
|
Independent verification of I had been working the same failure from BLO-25610 and arrived at the same core insight — a queued participant-recovery wake, gated on Local results, against a real Postgres 18 (see below), on this exact head:
455 tests, zero failures. Notably the three negative tests still pass — One latent issue this leaves behindThe fresh.executionRunId !== input.expectedReviewStage.executionRunId // service.ts:5376That comparison is dead. Since issue locks bind only while a run is Not a blocker for this PR — your fix prevents the escalation earlier, so the dead comparison no longer causes the bug. But it is exactly what sent me down the wrong path for an hour, and it will do the same to the next reader. Suggest deleting the field from the type and both construction sites as a follow-up; I can put that up once this lands, to avoid conflicting with it now. Reproduction setup, if useful
Rather than patch the kernel I ran |
Thinking Path
Linked Issues or Issue Description
Refs #1201.
Merge-group run 31462473806 exposed two independent failures after #1207 entered master. The session recovery tests retained an obsolete scheduled-run lock expectation, while the finalize-cancelled suite bypassed canonical heartbeat cleanup. The subsequent PR run 31467346954 exposed the queued review-stage replacement bugs fixed here.
What Changed
cleanupHeartbeatTestState.execution_review_participant_recoveryreason with the same exact participant and stage.Verification
heartbeat-process-recovery.test.tspassed 198/198.pnpm --filter @paperclipai/server typecheckpassed.git diff --checkpassed.Risks
Moderate recovery-path risk. The new queries are limited to terminal review finalization and stranded-review reconciliation. Exact participant and stage matching prevents unrelated queued work from suppressing escalation; configuration, provider-quota, and unavailable-agent handling retain their existing precedence.
Model Used
OpenAI GPT-5 Codex with high reasoning and terminal, GitHub, Docker, and Kubernetes tooling.