Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: e4910b8f53384edcbdfb47a9540eefb9
Branch: dev/2-room-rail-double-count
Base: 5b862c6
At: 2026-11-01T17:43:55Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
The defect
A room board opened from a Bot board counts the room's active cards twice in its rail. The rail is supposed to read {done}/{total} for the cards the board actually draws; on a room board that is the room's active list plus one archive page, but the hook's own state is never reset when the scope changes from a Bot to a room, and the rail adds both lists.
Code on main 5b862c6e (core/src/client/kanban.js):
:167—const [own, setOwn] = useState([]); the effect is keyed onkey(:169), which changes when the scope changes.:180-181— the non-room read isactions?.tasks?.()with no argument; the host's default read is every task the Bot may act on (core/src/host/tasks.js:1397-1399,all.filter(mayAct || ancestorOwned)), so room cards land inownas well as ingroupTasks.:186-189—setOwn(list)only runs in thescope.kind !== 'group'branch; going Bot → room leavesownholding the Bot board's read.:401—[...own, ...(scope?.kind === 'group' ? groupTasks : []), ...(archive ?? []).slice(0, ARCHIVE_SHOWN)]therefore counts the room's active cards twice.
Reproduction
Product's probe (same harness as core/test/kanban.test.js): a room war with one active Writer card and one done card in the archive page. First read on the real path is the Bot board (the rail's first entry, :377), which fills own with [task-open-s]; then the scope switches to the room:
bot board (default scope) rail Writer = "0/1" (own holds: task-open-s)
room board after the rail click rail Writer = "1/3" drawn: not-started=1 / in-progress=0 / done=1 → true value "1/2"
control own = [] rail Writer = "1/2"
A card from another room left in own reaches a Bot rail the board does not draw at all (rail Chief = "0/1" with no Chief card drawn), which is the same bug from the other side. Read arguments confirm the split: bot board read args = [], archive read args = [{botId:'a', archive:true, limit:20}].
Expected behaviour
The rail counts what the board draws, and only that: on a room board groupTasks plus the archive page; on a Bot board own (already filtered to that Bot) plus the archive page. Minimal fix, one line plus a comment:
[...(scope?.kind === 'group' ? groupTasks : own), ...(archive ?? []).slice(0, ARCHIVE_SHOWN)]#2045's one-page cap stays as it is.
Red first — and the fixtures that must change with it
Base: live main 5b862c6e5ecdd0a472826162ebb2abab63b91544.
- New case: render the Bot board first (so
ownis filled by a real read), then switch the scope to the room;railMeta('s')must be1/2where it is1/3today. - The existing room cases are false green and must be fixed in the same PR.
boardWith({ kind: 'group', … }, [], archive, groupActive)presetsown = [], which the real path never produces: on a real board the initial scope israil.bots[0](:377), soownis always filled before any room is opened. A test that starts a room board with an emptyowncannot see this bug. Seedownfrom the Bot board read, as the new case does. - Everything already asserted stays asserted, verbatim:
1/2,2/3,0/1,1/4,3/5,19/21,20+ done,18+ done,2+ done,0/20(core/test/kanban.test.js:344-431).
Scope
core/src/client/kanban.js— the one line and its comment (P-364's comment above it needs the room branch stated correctly).core/test/kanban.test.js— the new case and the fixture correction.- The built client and
patches/ds-bot/(0008diff,files/src/client/…,files/test/…) asgeneratewrites them;build-client --checkmust be 0. docs/subsystems/core-client.md— the P-364 paragraph gains one sentence: a room board countsgroupTasksplus the archive page, neverown.changelog.d/<this issue>-room-rail-double-count.fixed.md.- T1 / XS.
Gates
TZ=UTC ARCH_DOCS_BASE=5b862c6e npm run verify, ds-bot-patches check + canonical, build-client --check, checkpointReasons = [], maintainer_can_modify: true. FlyBot Test and FlyBot Security self-tests run on the new tip before the reviewer is named; a Verdict request on a tip whose advisory is still running is how a half-checked tip reaches the merge queue.
Dedupe on live main: #2048 and #2063 (both closed, the P-364 halves) and #2045/#2058 (page-full lower bound) are the neighbourhood; no open issue covers this double count.
Activity
HugoXK commentedon Nov 1, 2026
Claim-Id: e4910b8f53384edcbdfb47a9540eefb9
Bot: FlyBot Lead
Branch: dev/2-room-rail-double-count
Base: 5b862c6 (live main)
Owner: Dev-2
Reviewer: Birfy
Claimed-at: as recorded by the claim helper at 2026-11-01T17:43:57Z
Taken by FlyBot (owner decision 2026-10-26: we implement what we report). Branch and PR follow within 24h; the PR opens with
Fixes #2069.Please do not pick this up without a
pickup-okcomment from FlyBot Lead.HugoXK commentedon Nov 2, 2026
Release
Written-by: FlyBot Lead
Released: e4910b8f53384edcbdfb47a9540eefb9
Reason: #2076 merged at 18:39:29Z as squash e36b8ae; issue closed completed 18:42:37Z.
At: 2026-11-02T00:04:30Z
A room board reached from a Bot board counts its active cards twice i…
Test that the board rail counts the list the board draws (ThinkFlowLa…