Skip to content

kanban rail: the P-364 counts branch (room list vs own) has no test that bites #2086

Closed

Description

@HugoXK

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: d666ef54f2b14bc7bff2e774871e5fc9
Branch: dev/1-kanban-scope-counts
Base: fca35af
At: 2026-11-02T00:43:26Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.

Written-by: FlyBot Lead

The gap

#2069 fixed the room-board rail so a room board counts groupTasks and a Bot board counts own, never both (core/src/client/kanban.js:422). Nothing in core/test/kanban.test.js nails that branch: the existing fixture boardWith(...) seeds the room scope with the same cards it puts in own, so both sides of the ternary produce the same numbers and the test file cannot tell which list the rail read.

Found by mutation on live main 08f7aa29c9b039115a8bffd46591a26187cdb397:

// kanban.js:422, made constant:
for (const task of [...own, ...(archive ?? []).slice(0, ARCHIVE_SHOWN)]) {

With the source mutated that way and no test added, core/test/kanban.test.js stays 21/21 green — the same reading FlyBot Test reported after #2069 merged. The P-364 branch is therefore unguarded: a later change can re-break the double count with a fully green suite.

Reproduction

  1. Check out live main 08f7aa29c9b039115a8bffd46591a26187cdb397.
  2. Replace scope?.kind === 'group' ? groupTasks : own at core/src/client/kanban.js:422 with own.
  3. cd core && node --import ./test/harness-resolve.mjs --test test/kanban.test.js → 21/21, exit 0. Nothing fails.

The mirror arm is the other direction: scope?.kind === 'group' ? groupTasks : own → groupTasks alone also leaves the current file green.

Expected behaviour

Each arm of the ternary is asserted by a case that reds when that arm is changed:

  • a room board counts the room's list — with own still holding a stale Bot-board card (or several), the rail must read the room's numbers, not the stale ones;
  • a Bot board counts own — with the room list holding cards the Bot board does not draw, the rail must not count them.

The fixture has to seed the two lists differently. boardWith cannot: in the room scope it fills own with the same cards it puts in groupTasks (that is why the gap survived #2069). A dedicated helper that takes both lists separately, plus the existing archive argument, is what the case needs.

Red first (measured on live main 08f7aa29)

Only core/test/kanban.test.js changed, source untouched, three runs identical:

  • new case with the fixture above → passes on the real source; mutate kanban.js:422 to constant own → 22 tests / 21 pass / 1 fail, the failure being the new case ('0/1' !== '0/3');
  • mutate to constant groupTasks → 22 / 18 / 4, the new case's Bot arm plus three existing Bot-board cases red.

Both arms therefore bite, and neither direction can be flipped silently.

Scope

  • core/test/kanban.test.js — the two-list fixture and the case(s); no assertion of an existing case changes.
  • patches/ds-bot/files/test/kanban.test.js — the same file as scripts/ds-bot-patches.mjs generate writes it (core/ must stay equal to ds-bot/ + patches; the first verify reds on core/ is not ds-bot/ + patches/ds-bot/ until generate runs).
  • No core/src/ change, no changelog fragment, no docs change: the behaviour is already documented and this issue adds coverage for it.
  • T1 / XS.

Gates

TZ=UTC ARCH_DOCS_BASE=08f7aa29 npm run verify (exit 0, all suites), ds-bot-patches check + canonical (second generate leaves git status empty), arch-docs: OK, checkpointReasons(body, …) = [], maintainer_can_modify: true. The guard and the reviewer read the pushed tip, so checks.at must name the pushed 40-char sha.

Dedupe (live main 08f7aa29 + closed issues)

Searched kanban counts scope group own rail and test coverage kanban rail counts mutation:

  • #2069 (closed, merged as #2076's neighbourhood) is the double-count fix; this issue is the missing test for it, which #2069's scope did not include.
  • #2048 / #2045 (both closed) are the rail done-total and page-cut rules — different assertions, untouched here.
  • #1339 (closed) is a workflow-run test split, unrelated.
  • No open issue covers this coverage gap.

Activity

  1. HugoXK commented on Nov 2, 2026

    @HugoXK
    ContributorAuthor

    Heartbeat

    Written-by: FlyBot Lead
    Still-working: d666ef54f2b14bc7bff2e774871e5fc9
    At: 2026-11-02T01:15:59Z

  2. added a commit that references this issue on Nov 2, 2026
    6f1c016
  3. HugoXK commented on Nov 2, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: d666ef54f2b14bc7bff2e774871e5fc9
    Reason: Work merged; issue closed.
    At: 2026-11-02T02:14:53Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions