WRAP_UP can fire with an open PR: tracked-prs.txt lives on tmpfs, and a missing file reads as an empty one nf-s66u ← Beads

closed priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/575 by tools/beads/import_github.py's reconcile pass.

The wrap-up predicate is no open tracked PRs AND no open claimed issues. Half of it is answered by GitHub, which is durable. The other half is answered by a file in the session scratchpad, which on the WSL office box is /tmp, and /tmp is tmpfs:

``` $ df -h /tmp tmpfs 3.8G 154M 3.6G 5% /tmp ```

tmpfs is RAM-backed, so tracked-prs.txt does not survive a reboot — not "might be cleaned up", *cannot* survive. And a missing file is read as an empty one, silently:

```python def tracked_numbers(tracked: Path) -> list[str]: # poll.py:505 if not tracked.is_file(): return [] ```

Two consequences, and the second is the expensive one

1. The loop silently stops watching. After a reboot every tick reports zero tracked PRs, so review comments on a real open PR are never surfaced. Nothing errors; --check exits 0 and prints a normal decision line. That is the #352 shape — stops producing signal while looking healthy.

2. WRAP_UP can fire with an open PR. Reach the state "claimed issues closed, PR still open awaiting merge" — which is *exactly* where a dev on the office box sits, since it cannot merge its own work — then reboot. tracked_numbers() returns [], no claimed issues remain, and poll.py:946 prints:

> WRAP_UP: no live work — no open tracked PRs, no claimed issues. … *DELETE the poll cron, set your row on the board (#398) to wrapped*

The session then wraps correctly-by-its-own-lights and the PR belongs to nobody. notes/poll-loop.md:54 already warns *"A session archived with open PRs still in its tracked-prs.txt orphans them"* — this is the same orphan arriving by a route the warning does not cover, because the file is *empty* rather than populated.

The fix already exists in the same function, for the sibling input

poll.py:938 refuses to evaluate the predicate at all when the sid is missing, and the comment says exactly why:

> *"Without a sid, claimed issues could not be checked and the predicate degrades to 'do I have open PRs?' … Refuse."*

That is the right call, and the tracked file is the same class of degraded input getting the opposite treatment. Suggested shape, in order of preference:

What is already mitigated, and what is not

The office runbook (cfsh/nf-office, "Resuming after the box goes down") does say *"ask a resumed session to re-check its tracked PRs before trusting its picture"* — a human-instruction mitigation, on one box, for the resume path only. CLAUDE.md says nothing about the file being volatile; step 4 says only *"The poll cron reads exactly this file."* A session reading the durable copy has no reason to think the file can vanish.

Same directory, same volatility, lower stakes: seen-issue-comments.txt (notes/poll-loop.md:43) losing its timestamps makes the next digest re-report every comment as new. Noisy, self-correcting, worth one line in whatever fixes the above.

⚠️ Not reachable on the Windows sandbox box in the same way — its scratchpad is not tmpfs — which is why this is filed now rather than earlier: it is a property the move to WSL introduced. Directly relevant to #566 and the garage-Linux-server plan in it.

Filed unclaimed by nf-dev-office-spawn while working #557. Not on my chunk. Related: #560, #566, notes/poll-loop.md.

Dependencies

None.

Comments

No comments.

Add a comment