Twinned from https://github.com/cfsh/ninefold/issues/624 by tools/beads/import_github.py's reconcile pass.
Three actively-worked chunk issues carry no labels at all, which silently disables the half of poll.py's stop condition that is supposed to keep a session from wrapping up early. Found on my own chunk; it is not specific to it.
| issue | chunk | labels |
|---|---|---|
| #572 | nf-dev-probe-divergence | *(none — now fixed, see below)* |
| #599 | nf-dev-f5-docs | none |
| #576 | nf-dev-bork | none |
| #601 | nf-dev-spawn-box | active, session:spawn-box |
| #557 | nf-dev-office-spawn | tier:1, active, session:office-spawn |
| #545 | nf-dev-publish-header | tier:1, active, session:publish-header |
The split is not random: the three unlabelled ones are all CTO-spawned chunks where the session: label was never created. gh label list had session:a … session:e, session:argo, session:office-spawn, session:spawn-box, session:publish-header — and nothing for the other three.
1. CLAUDE.md's own rule reads them as free work.
> No label → inert backlog. Explicitly nobody's job, however obvious it looks. If it matters, triage activates it.
So by the written rule these three are unowned, and /triage regenerates the board *"from live GitHub state — labels, CLAIM markers and open PRs are the source of truth."* A triage round could hand a live chunk to a second session. The CLAIM comment is the only thing standing between that and a collision, and CLAUDE.md is explicit that it is the weaker of the two: *"The label is the assignment; the claim is the possession."*
2. It silently degrades poll.py's stop condition — measured, not theorised.
poll.py <file> <sid> <session-label> scopes its issue sweep by the label. With #572 unlabelled the digest had no ISSUES CLAIMED BY THIS SESSION section at all. Adding active + session:probe-divergence and re-running the identical command, same sid, same file:
``` ════ ISSUES CLAIMED BY THIS SESSION · LAST 3 COMMENTS ════ #572 jcantsp-bot 2026-08-06T07:00:11Z: CLAIM session=nf-dev-probe-divergence sid=... ```
That section is the input to the wrap-up gate:
> Stop — gate on EXISTENCE, every run. No open tracked PRs and no open claimed issues → wrap up and delete the cron.
⚠️ So an unlabelled chunk issue contributes zero to that test. For a session whose last PR merges while its issue is still open — extra scope found in review, a follow-up commit, an issue deliberately left open pending a check on another box — the gate reads "no open tracked PRs and no open claimed issues" as satisfied and instructs it to wrap up and delete its cron. The issue is then live with nobody polling it, and the board says wrapped.
This is the same failure CLAUDE.md already documents one layer down, for the sid rather than the label:
> a missing sid degrades the live-work test to "do I have open PRs?", which tells a session its chunk is done while its issue is still open.
Identical outcome, different missing argument, and this one is not written down anywhere.
session:probe-divergence and applied it plus active to #572, my own claimed chunk, matching the scope my poll command already passes and the pattern already used for the other spawned sessions. Verified the digest section appears.session:spawn-box and session:publish-header were. Closest to the existing convention.poll.py refuses a label that matches no open issue, or warns loudly — the same fail-loud posture it already takes for scope mismatches (SCOPE-CHANGED / LEGACY-STATE). A session-label argument that resolves to nothing is almost always a mistake, and today it is silent./triage reconciles CLAIM comments against labels and reports issues claimed-but-unlabelled, since it already reads both.Related: #398 (the board), #418 (poll.py digest scoping), design 001.
Unclaimed.
None.
No comments.