fix(backlog): recover items wedged in review by an idle-but-alive reviewer - #342
fix(backlog): recover items wedged in review by an idle-but-alive reviewer#342tstapler wants to merge 7 commits into
Conversation
Sessions (like this one) had no way to actually create a backlog item directly — filing a GitHub issue and hoping someone imports it later was the only path. Both new tools call the same storage.CreateBacklogItem / github.GetIssue the web UI's "New Idea" and "Import from GitHub" actions already use, just exposed as MCP tools. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba
Adds two sections to /review-queue: backlog items awaiting plan approval (same gate BacklogItemDetail's Approve Plan button uses), and sessions that are simply active/creating but not needing attention — so it's clear at a glance what needs interaction versus what's just running. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba
…-fix-idle-reviewer-wedge
…-fix-idle-reviewer-wedge
Found while running make ci for the idle-reviewer-wedge fix — unrelated to that change (confirmed already unformatted on origin/main), fixed as collateral debt per repo convention rather than left blocking CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS
…iewer A reviewer session that submits a verdict via submit_review_verdict and then never exits (process alive, no further output) was invisible to both handleReviewSessionExited (session-exit only) and reconcileUnprocessedReviewVerdicts' crash-recovery sweep (requires the session confirmed dead via SessionLivenessChecker) — wedging the item in "review" forever. - submitReviewVerdict now drives the review->in_progress transition eagerly for FAIL/PARTIAL/UNVERIFIABLE verdicts via the existing AutoReopenSpawner (server/mcp/tools_backlog.go), reusing AutoReopenAfterFailedReview's CAS-guarded (ExpectedStatus: review) transition, rework-cap/circuit-breaker checks, and work-session respawn logic rather than reimplementing them. PASS stays deferred to handleReviewSessionExited, unchanged. - reconcileUnprocessedReviewVerdicts gets an idle-timeout OR condition: a verdict older than reviewVerdictIdleThreshold (2h, matching maxWorkSessionStaleness) is now actionable even when SessionLivenessChecker reports the session alive — covers PASS verdicts and any case the eager path doesn't reach (e.g. no AutoReopenSpawner wired). - The review-role prompt (BuildReviewPrompt, get_backlog_item's review-role guidance, and the sdd pipeline mode's review template) now instructs the reviewer to end its session immediately after calling submit_review_verdict, symmetric to the work-role prompt's existing "Do NOT end your session" instruction — closing the root behavioral cause. - BUG-051 (session/tmux flaking under make ci's parallel load) is fixed on main and verified green here; docs/bugs marked fixed and moved accordingly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS
✅ Registry ValidationTest Coverage: 31/184 features have
|
Go Benchmarks (Tier 1) |
E2E RPC Latency |
📊 Feature E2E CoverageFeature coverage report unavailable
|
… fix Four-agent parallel review (testing, code quality, architecture, security) on PR #342 surfaced two real MAJOR correctness gaps and three MAJOR test coverage gaps; security review found nothing. Addressing all five here: - server/server.go: nil-guard deps.BacklogService before boxing it into the session.AutoReopenSpawner interface param passed to NewHTTPHandler, mirroring the other three nil-checks already on this same field in this function. A nil *services.BacklogService boxed directly into the interface produces a non-nil interface value around a nil pointer (the classic Go typed-nil trap) — submitReviewVerdict's own `h.autoReopener != nil` guard would read true and the call would panic on the nil receiver instead of being skipped. - server/mcp/tools_backlog.go: the eager AutoReopenAfterFailedReview call now runs on a context.WithoutCancel + 30s-bounded context instead of the live request ctx. AutoReopenAfterFailedReview's only other callers run on long-lived background contexts; its own rollback-on-spawn-failure path reuses whatever ctx it's given, so inheriting the request ctx meant a client-side disconnect could cancel both the transition attempt and its own safety-net rollback together. - Added 3 test cases: nil-autoReopener now asserts the item stays in review (not just "no crash"), a just-under-threshold idle-timeout subtest guards the strict `>` comparison's boundary, and a PASS-outcome idle-timeout subtest covers the idle-timeout branch's stated primary remaining purpose (PASS stays deferred to session-exit by design, so this sweep is the only path back out of review for a PASS verdict whose reviewer went idle). make ci green (build, full suite incl. -race/integration, lint, registry regen, no drift). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS
✅ Registry ValidationTest Coverage: 31/184 features have
|
Frontend Terminal Throughput |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes backlog items getting stuck in review when a reviewer submits a verdict but never exits, by adding an eager FAIL/PARTIAL/UNVERIFIABLE reopen path and an idle-timeout sweep fallback, plus updating reviewer prompts and wiring AutoReopenSpawner through MCP server construction.
Changes:
- Eagerly trigger
review → in_progresson reject verdicts viaAutoReopenAfterFailedReview, with nil-safe wiring through MCP server constructors. - Add idle-timeout handling in
reconcileUnprocessedReviewVerdictsso old verdicts are actionable even if the session appears alive. - Update review prompts/templates and add/extend unit tests covering wedge recovery and guidance text.
Reviewed changes
Copilot reviewed 15 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| session/pipeline_mode_seed.go | Updates review template to instruct exiting immediately after submitting verdict. |
| session/backlog_review.go | Adds explicit “end session after verdict” instruction to the generated review prompt. |
| session/backlog_review_test.go | Adds regression test asserting review prompt includes the new instruction. |
| session/backlog_lifecycle.go | Adds idle-timeout OR-path to treat old verdicts as actionable even if session is “alive”; defines threshold constant. |
| session/backlog_lifecycle_test.go | Adds helper to create backdated verdicts for idle-threshold tests. |
| session/backlog_lifecycle_stuck_test.go | Expands reconcile tests to cover idle-timeout behavior (including PASS) while session reports alive. |
| server/mcp/tools_backlog.go | Implements eager auto-reopen call on reject outcomes and updates review-role guidance text. |
| server/mcp/tools_backlog_test.go | Adds tests for eager auto-reopen behavior and review-role guidance text. |
| server/mcp/server.go | Threads optional AutoReopenSpawner through NewCore/NewHTTPHandler/RunServer and into handlers. |
| server/server.go | Wires BacklogService into MCP handler safely (avoids nil-interface trap). |
| server/mcp/server_integration_test.go | Updates NewCore invocation for new parameter. |
| server/mcp/feature_flag_test.go | Updates NewCore invocation for new parameter. |
| main.go | Passes nil autoReopener on stdio MCP path with documentation. |
| server/services/backlog_service_triage_test.go | Adds CAS/double-call and “spawn new session” coverage around AutoReopenAfterFailedReview behavior. |
| docs/bugs/fixed/BUG-051-session-tmux-package-flaky-under-parallel-quick-check.md | Updates BUG-051 status and adds recurrence/resolution notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| reopenCtx, reopenCancel := context.WithTimeout(context.WithoutCancel(ctx), 30*time.Second) | ||
| if reopenErr := h.autoReopener.AutoReopenAfterFailedReview(reopenCtx, itemID); reopenErr != nil { | ||
| log.WarningLog.Printf("[submitReviewVerdict] AutoReopenAfterFailedReview item=%s: %v", itemID, reopenErr) | ||
| } | ||
| reopenCancel() |
| sb.WriteString("1. Check each AC criterion against the implementation\n") | ||
| sb.WriteString("2. Call submit_review_verdict with per-criterion verdicts (PASS/FAIL/PARTIAL) + evidence\n") | ||
| sb.WriteString(" PASS → item transitions to done. FAIL → item sent back for rework.\n") | ||
| sb.WriteString("3. End your session immediately after calling submit_review_verdict. Do not wait, poll, or do further work — an idle-but-alive reviewer session leaves the item stuck.\n") |
| you read. End your session immediately after calling submit_review_verdict - do not | ||
| wait, poll, or do further work. |
| # BUG-051: `session/tmux` Package Tests Flake Under `make quick-check`'s Parallel Load [SEVERITY: Low] | ||
|
|
||
| **Status**: 🐛 Open | ||
| **Status**: ✅ Fixed (main@dccee742a, 2026-08-04) |
|
|
||
| ## Recurrence log | ||
|
|
||
| - 2026-08-05, while running `make ci`/`make test` as the AC-7 gate for `stapler-squad-fix-idle-reviewer-wedge`: `TestEnsureServerRunning_NoOp` failed identically (`tmux start-server failed: exit status 1 (output: server exited unexpectedly)`) under the full-suite parallel run, passed 5/5 in isolation (`go test ./session/tmux -run TestEnsureServerRunning_NoOp -count=5`), and — to positively rule out this session's own diff — reproduced identically after `git stash`-ing every change back to the unmodified base branch and re-running `make test`. Confirmed still open and still purely load-triggered, not tied to any particular diff, on `main` as of that point. |
|
Closing as superseded: this branch's last known commit (1a75172) is already present on main, so this item's work has already shipped through another path. No further fix is needed here. |
Picks up the three base-vs-latest consumer corrections found in self-review (review_gate.go's directory-mode diff base, GetBaseCommitSHAsForSessions, and the last_progress_at clock) so this branch is tested against the final form of the reconciler fix it stacks on.
…session's own base commit (#346) * fix(backlog): stop auto-closing live PRs as "superseded" against the session's own base commit ItemSession.LastCommitSha was written exactly once — at session spawn, with the worktree's pre-work HEAD — and never refreshed as the agent committed. A session's base commit is by construction already an ancestor of main, so git.IsCommitOnMain on it is unconditionally true. Two consumers trusted the field as "the session's latest commit": - closeIfSupersededByMain (session/backlog_lifecycle.go) closed the item's open PR unmerged and marked the item done. - GetBacklogItemShipStatus, which backs the item detail page's Ship PR status. Live blast radius, from backlog_status_events in the deployed instance: 15 PRs were auto-closed as "superseded". Four distinct items cite the identical SHA 654c601, three cite 4eca0ed — a 2026-06-01 benchmark-baseline chore commit used to close three PRs on 2026-07-29 — and one cites cc66c0b, a 2026-04-09 test commit. Unrelated items cannot all ship in one such commit; these are spawn-time base SHAs. The most recent, PR #342 (BUG-047's own fix, reviewed and CI-green), was closed against base SHA 1a75172 from ~24h before that work started. Fix, in three parts: 1. Split the concept. New ItemSession.base_commit_sha holds the spawn-time baseline for the review gate's base..HEAD diff; the three spawn write sites now call SetItemSessionBaseCommit instead of overloading the git-activity fields. 2. Make LastCommitSha true to its name. refreshWorkSessionGitActivity re-reads each live work session's real HEAD (go-git via the new git.CommitInfo, per .claude/rules/prefer-go-git-over-subshells.md) and recomputes commit_count_since_spawn. It is wired into the existing reconciliation sweep's detector list rather than adding a poller, and is registered first so same-tick consumers read fresh values. 3. Fix both consumers to resolve the session's real tip via resolveLatestWorkCommit — the remedy already applied to this file's reconcileBouncingItems and to isCodeShippedToMain, which closeIfSupersededByMain was never migrated to — plus an explicit BaseCommitSha guard so the fallback path can never re-enter the bug for rows already in production databases. Also fixes a consistency bug this exposed: ship status resolved the SHA live but captioned it with the stored (stale) commit message and timestamp. ent schema regenerated with --feature sql/upsert per .claude/rules/ent-schema-generation.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba * fix(backlog): correct three base-vs-latest consumers the field split exposed Self-review of the LastCommitSha split found three places that read the field for its *base* meaning, which the live refresh would have silently broken: - review_gate.go's directory-mode branch passed LastCommitSha as GetGitDiff's base. Once that field tracks the tip, this diffs the tip against itself and every directory-mode review gets an EMPTY diff — a silent review bypass. - GetBaseCommitSHAsForSessions (despite its name) selected last_commit_sha to restore dirBaseSHA at startup, giving those sessions a moving diff base. - UpdateItemSessionGitActivity set last_progress_at from the commit's author timestamp. Author dates survive rebases, and this repo rebases session worktrees onto main routinely, so a rebase would push the staleness clock backwards and hand a healthy, actively-committing session to stale_work remediation. Progress is recorded when observed; last_commit_at keeps the true author time for display. The first two read base_commit_sha with a fallback to last_commit_sha for rows written before the split. That fallback is only safe because the original bug meant both fields held the same value on every legacy row — it is explicitly not extended to rows that have a base_commit_sha. Adds TestUpdateItemSessionGitActivity_should_RecordProgressAtObservationTime_When_CommitIsBackdated, verified to fail against the author-timestamp version. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…iewer (recovers #342) (#347) * fix(backlog): stop auto-closing live PRs as "superseded" against the session's own base commit ItemSession.LastCommitSha was written exactly once — at session spawn, with the worktree's pre-work HEAD — and never refreshed as the agent committed. A session's base commit is by construction already an ancestor of main, so git.IsCommitOnMain on it is unconditionally true. Two consumers trusted the field as "the session's latest commit": - closeIfSupersededByMain (session/backlog_lifecycle.go) closed the item's open PR unmerged and marked the item done. - GetBacklogItemShipStatus, which backs the item detail page's Ship PR status. Live blast radius, from backlog_status_events in the deployed instance: 15 PRs were auto-closed as "superseded". Four distinct items cite the identical SHA 654c601, three cite 4eca0ed — a 2026-06-01 benchmark-baseline chore commit used to close three PRs on 2026-07-29 — and one cites cc66c0b, a 2026-04-09 test commit. Unrelated items cannot all ship in one such commit; these are spawn-time base SHAs. The most recent, PR #342 (BUG-047's own fix, reviewed and CI-green), was closed against base SHA 1a75172 from ~24h before that work started. Fix, in three parts: 1. Split the concept. New ItemSession.base_commit_sha holds the spawn-time baseline for the review gate's base..HEAD diff; the three spawn write sites now call SetItemSessionBaseCommit instead of overloading the git-activity fields. 2. Make LastCommitSha true to its name. refreshWorkSessionGitActivity re-reads each live work session's real HEAD (go-git via the new git.CommitInfo, per .claude/rules/prefer-go-git-over-subshells.md) and recomputes commit_count_since_spawn. It is wired into the existing reconciliation sweep's detector list rather than adding a poller, and is registered first so same-tick consumers read fresh values. 3. Fix both consumers to resolve the session's real tip via resolveLatestWorkCommit — the remedy already applied to this file's reconcileBouncingItems and to isCodeShippedToMain, which closeIfSupersededByMain was never migrated to — plus an explicit BaseCommitSha guard so the fallback path can never re-enter the bug for rows already in production databases. Also fixes a consistency bug this exposed: ship status resolved the SHA live but captioned it with the stored (stale) commit message and timestamp. ent schema regenerated with --feature sql/upsert per .claude/rules/ent-schema-generation.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba * chore(fmt): fix pre-existing gofmt drift in session/git/worktree_ops.go Found while running make ci for the idle-reviewer-wedge fix — unrelated to that change (confirmed already unformatted on origin/main), fixed as collateral debt per repo convention rather than left blocking CI. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS * fix(backlog): recover items wedged in review by an idle-but-alive reviewer A reviewer session that submits a verdict via submit_review_verdict and then never exits (process alive, no further output) was invisible to both handleReviewSessionExited (session-exit only) and reconcileUnprocessedReviewVerdicts' crash-recovery sweep (requires the session confirmed dead via SessionLivenessChecker) — wedging the item in "review" forever. - submitReviewVerdict now drives the review->in_progress transition eagerly for FAIL/PARTIAL/UNVERIFIABLE verdicts via the existing AutoReopenSpawner (server/mcp/tools_backlog.go), reusing AutoReopenAfterFailedReview's CAS-guarded (ExpectedStatus: review) transition, rework-cap/circuit-breaker checks, and work-session respawn logic rather than reimplementing them. PASS stays deferred to handleReviewSessionExited, unchanged. - reconcileUnprocessedReviewVerdicts gets an idle-timeout OR condition: a verdict older than reviewVerdictIdleThreshold (2h, matching maxWorkSessionStaleness) is now actionable even when SessionLivenessChecker reports the session alive — covers PASS verdicts and any case the eager path doesn't reach (e.g. no AutoReopenSpawner wired). - The review-role prompt (BuildReviewPrompt, get_backlog_item's review-role guidance, and the sdd pipeline mode's review template) now instructs the reviewer to end its session immediately after calling submit_review_verdict, symmetric to the work-role prompt's existing "Do NOT end your session" instruction — closing the root behavioral cause. - BUG-051 (session/tmux flaking under make ci's parallel load) is fixed on main and verified green here; docs/bugs marked fixed and moved accordingly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS * fix(backlog): address code-review findings on the idle-reviewer-wedge fix Four-agent parallel review (testing, code quality, architecture, security) on PR #342 surfaced two real MAJOR correctness gaps and three MAJOR test coverage gaps; security review found nothing. Addressing all five here: - server/server.go: nil-guard deps.BacklogService before boxing it into the session.AutoReopenSpawner interface param passed to NewHTTPHandler, mirroring the other three nil-checks already on this same field in this function. A nil *services.BacklogService boxed directly into the interface produces a non-nil interface value around a nil pointer (the classic Go typed-nil trap) — submitReviewVerdict's own `h.autoReopener != nil` guard would read true and the call would panic on the nil receiver instead of being skipped. - server/mcp/tools_backlog.go: the eager AutoReopenAfterFailedReview call now runs on a context.WithoutCancel + 30s-bounded context instead of the live request ctx. AutoReopenAfterFailedReview's only other callers run on long-lived background contexts; its own rollback-on-spawn-failure path reuses whatever ctx it's given, so inheriting the request ctx meant a client-side disconnect could cancel both the transition attempt and its own safety-net rollback together. - Added 3 test cases: nil-autoReopener now asserts the item stays in review (not just "no crash"), a just-under-threshold idle-timeout subtest guards the strict `>` comparison's boundary, and a PASS-outcome idle-timeout subtest covers the idle-timeout branch's stated primary remaining purpose (PASS stays deferred to session-exit by design, so this sweep is the only path back out of review for a PASS verdict whose reviewer went idle). make ci green (build, full suite incl. -race/integration, lint, registry regen, no drift). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS * fix(backlog): correct three base-vs-latest consumers the field split exposed Self-review of the LastCommitSha split found three places that read the field for its *base* meaning, which the live refresh would have silently broken: - review_gate.go's directory-mode branch passed LastCommitSha as GetGitDiff's base. Once that field tracks the tip, this diffs the tip against itself and every directory-mode review gets an EMPTY diff — a silent review bypass. - GetBaseCommitSHAsForSessions (despite its name) selected last_commit_sha to restore dirBaseSHA at startup, giving those sessions a moving diff base. - UpdateItemSessionGitActivity set last_progress_at from the commit's author timestamp. Author dates survive rebases, and this repo rebases session worktrees onto main routinely, so a rebase would push the staleness clock backwards and hand a healthy, actively-committing session to stale_work remediation. Progress is recorded when observed; last_commit_at keeps the true author time for display. The first two read base_commit_sha with a fallback to last_commit_sha for rows written before the split. That fallback is only safe because the original bug meant both fields held the same value on every legacy row — it is explicitly not extended to rows that have a base_commit_sha. Adds TestUpdateItemSessionGitActivity_should_RecordProgressAtObservationTime_When_CommitIsBackdated, verified to fail against the author-timestamp version. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W3683CH7Fs9zYR2yP3Dpba --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
…tale LastCommitSha d6ddbef3 shows done/PR-closed-as-superseded, but the "superseded by" commit predates the branch's own fix commits by almost a day. LastCommitSha is only ever set once, at session-start, as the pre-work baseline SHA for review-gate diffing (SpawnSessionFromItem step 12b, AttachSessionToItem) and never refreshed — so IsCommitOnMain trivially matches for any item, real work or not. BUG-047's actual fix (PR #342) never merged; the two live wedged reviews this doc's prior update said would self-heal will not. Also affects GetBacklogItemShipStatus (same field, same trust boundary).
Summary
A reviewer session that submits a verdict via
submit_review_verdictand then never exits (process alive, no further output) was invisible to bothhandleReviewSessionExited(session-exit only) andreconcileUnprocessedReviewVerdicts's crash-recovery sweep (requires the session confirmed dead viaSessionLivenessChecker) — wedging the item inreviewforever. Live evidence: backlog item4c71d3a3-1dd5-4d82-86ec-694a98835d2fcurrently shows a recorded PARTIAL verdict with status still stuck inreview.Fixes backlog item
d6ddbef3-238e-43dc-8a69-c3700cc440bf.What Changed
submitReviewVerdict(server/mcp/tools_backlog.go) now drives thereview -> in_progresstransition eagerly for FAIL/PARTIAL/UNVERIFIABLE verdicts, routed through the existingAutoReopenSpawnerinterface (AutoReopenAfterFailedReview) rather than reimplemented — CAS-guarded (ExpectedStatus: review), rework-cap/circuit-breaker checks and work-session respawn logic reused as-is. PASS stays deferred tohandleReviewSessionExited, unchanged.reconcileUnprocessedReviewVerdicts(session/backlog_lifecycle.go) gets an idle-timeout OR condition: a verdict older thanreviewVerdictIdleThreshold(2h, matchingmaxWorkSessionStaleness) is now actionable even whenSessionLivenessCheckerreports the session alive — covers PASS verdicts and any case the eager path can't reach (e.g. noAutoReopenSpawnerwired).BuildReviewPrompt,get_backlog_item's review-role guidance block, and thesddpipeline mode's review template) now instructs the reviewer to end its session immediately after callingsubmit_review_verdict, symmetric to the work-role prompt's existing "Do NOT end your session" instruction.NewCore/NewHTTPHandler/RunServer(server/mcp/server.go) take a new optionalautoReopener session.AutoReopenSpawnerparam, wired fromdeps.BacklogServicein the HTTP server path (server/server.go); the stdio--mcpfallback path (main.go) has noBacklogServiceavailable (Phase 1CoreDepsonly) and passesnil— documented in-code.gofmtdrift insession/git/worktree_ops.go(unrelated, already broken onorigin/main), and closed outBUG-051(session/tmuxflaking undermake ci's parallel load — fixed upstream onmain, verified green here after merging).Test plan
make ci(build, fullgo test ./...,-race -short,-race -tags integration, lint, registry regen) — green, no regressions.autoReopenersafety, CAS-harmless double-call (AutoReopenAfterFailedReviewcalled twice), no-active-work-session spawn path, idle-timeout sweep (both under and over threshold), review-prompt content assertions.get_backlog_itemon the live wedged item4c71d3a3-1dd5-4d82-86ec-694a98835d2fconfirms it currently reproduces the exact bug (PARTIAL verdict, stillreview) — will recover automatically within one sweep interval, or immediately on its next verdict, once this deploys. Not force-verified via a live service restart in this session (would restart the shared production instance and disrupt other active sessions on this machine).🤖 Generated with a Claude Code backlog automation session.
https://claude.ai/code/session_01UcM8eWZdxXsxqSFyteMZUS