Problem
backlog-digest.sh links a PR to its issue only through a closing keyword:
backlog-digest.sh:80 scan("(?i)(?:fixes|closes|resolves) #([0-9]+)")
backlog-digest.sh:168 test("(?i)(fixes|closes|resolves) #\($n)\\b")
But this project's convention forbids that keyword on any PR that is not the
final one for an issue — an intermediate or beta PR must not auto-close the
reporter's issue. The two rules are in direct conflict: following the
convention makes the work invisible to the board.
PR #490 says, in its own body:
First of two PRs tracking #409 … Issue #409 stays open until that second PR
lands.
Part of #409 — this PR covers PredictionSnapshotStore only.
Three references to #409, no closing keyword, exactly as the convention
requires. The digest therefore resolves $pr == null for #409 and falls
through to:
backlog-digest.sh:339 if $pr != null then "In Review"
backlog-digest.sh:342 elif $wt_live then "In Progress"
So issue #409 derives In Progress, and this pass emitted both:
##409 move_card card is In Review but the evidence says In Progress
##409 resume_implementation worktree on disk, unlocked, no live session
Both are wrong. PR #490 is out of draft, carries two APPROVED reviews, and
merges cleanly — git merge-tree --write-tree origin/main <branch> returns a
tree with 0 conflicts, and the local branch head equals origin's. The
correct action is awaiting_maintainer: nothing to do but merge it.
Acting on the emitted actions would demote an approved PR's issue and dispatch
a paid session to "resume" finished work.
Second, related defect: mergeable: UNKNOWN is treated as final
backlog-digest.sh:404 stores pr_state: ($pr.mergeable // null) from a
single query. GitHub computes mergeable lazily — the first query returns
UNKNOWN and triggers the computation. The sweep-prs skill documents this
explicitly and retries; the digest does not.
Measured on #490 during this pass: UNKNOWN on six consecutive queries spanning
~30 minutes, while git merge-tree proved it conflict-free the whole time.
Proposed fix
- Link on any reference, not just closing keywords. Match
#N anywhere in
the PR body (Part of #N, tracking #N, a bare #N), and keep the closing
keywords only for deciding whether the issue closes. Those are two
different questions and only one of them is about linkage.
- Retry
mergeable until it leaves UNKNOWN, same as sweep-prs, and
never let UNKNOWN masquerade as a definite state.
Acceptance
Problem
backlog-digest.shlinks a PR to its issue only through a closing keyword:But this project's convention forbids that keyword on any PR that is not the
final one for an issue — an intermediate or beta PR must not auto-close the
reporter's issue. The two rules are in direct conflict: following the
convention makes the work invisible to the board.
Measured — #409 / #490
PR #490 says, in its own body:
Three references to #409, no closing keyword, exactly as the convention
requires. The digest therefore resolves
$pr == nullfor #409 and fallsthrough to:
So issue #409 derives In Progress, and this pass emitted both:
Both are wrong. PR #490 is out of draft, carries two APPROVED reviews, and
merges cleanly —
git merge-tree --write-tree origin/main <branch>returns atree with 0 conflicts, and the local branch head equals origin's. The
correct action is
awaiting_maintainer: nothing to do but merge it.Acting on the emitted actions would demote an approved PR's issue and dispatch
a paid session to "resume" finished work.
Second, related defect:
mergeable: UNKNOWNis treated as finalbacklog-digest.sh:404storespr_state: ($pr.mergeable // null)from asingle query. GitHub computes
mergeablelazily — the first query returnsUNKNOWNand triggers the computation. Thesweep-prsskill documents thisexplicitly and retries; the digest does not.
Measured on #490 during this pass:
UNKNOWNon six consecutive queries spanning~30 minutes, while
git merge-treeproved it conflict-free the whole time.Proposed fix
#Nanywhere inthe PR body (
Part of #N,tracking #N, a bare#N), and keep the closingkeywords only for deciding whether the issue closes. Those are two
different questions and only one of them is about linkage.
mergeableuntil it leavesUNKNOWN, same assweep-prs, andnever let
UNKNOWNmasquerade as a definite state.Acceptance
backlog-rhythm.shemits noresume_implementationand nomove_cardfor Consolidate PredictionSnapshotStore + ScheduleStore into the unified per-day DailyView format #409.Part of #NderivesIn Review.