Skip to content

Project board: read the queue, leases and blocked cards - #1770

Merged
Birfy merged 1 commit into
mainfrom
dev/1768-board-queue-groups
Oct 30, 2026
Merged

Birfy merged 1 commit into
mainfrom
dev/1768-board-queue-groups

Conversation

@Birfy

@Birfy Birfy commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Written-by: Dev

Fixes #1768

Owner: Chief
Reviewer: Reviewer
Tip SHA: 5f75be0
Base: 84385f2
Docs-not-needed: no — docs/subsystems/core-host.md and docs/subsystems/core-client.md are updated in this diff.

What changed

The read (core/src/host/project-board.js). projectBoard(projectId, actor) still returns the rows array every caller iterates, and the same pass now also derives three groups from state.tasks alone: waiting (an open card with a queueRole and no claim, oldest createdAt first, carrying the role and waitedMs), inflight (the card a claim — or the lease that claim wrote — holds, holder named, lease: live|expired, an expired one stalled: true) and blocked (a blocked card with the reason it already stores: inputRequest.question, else queueReason, else its title). rt.projectBoardQueues serves the groups over that same read, so the Project Assistant's rt.projectBoard call is unchanged. The project-board endpoint answers { tasks, waiting, inflight, blocked, counts }.

Counts are read, never synthesised. An unreadable store (state.tasks not a readable map) answers {waiting: null, inflight: null, blocked: null, done: null} — null, not 0, per the owner rule.

The render (core/src/client/project-board.js). The pane draws a counts header (waiting / in flight / blocked / done, unknown for a null) and three groups beside the columns: role + 3h / 5m wait on Waiting, holder · running|stalled on In flight, and the card's own reason on Blocked. Rows keep their task id, so #task=<id> still opens the card; an empty group is not drawn.

Untouched: core/src/host/tasks.js and core/src/shared/task-board.js (#1745 owns them), the queue semantics (claim still hands one item to exactly one member), and every write path — the board writes nothing.

Tests (red first)

core/test/project-board.test.js + core/test/project-board-view.test.js:

  1. two cards queued for Dev + one claimed → 2 waiting / 1 in flight, oldest wait first, role and holder named;
  2. that card's lease.expiresAt pushed into the past → stalled / expired, and the card record byte-identical before and after the read;
  3. a blocked card appears in Blocked with its own reason; another Project's queued card is in none of the three groups nor in the counts;
  4. state.tasks unreadable → every count null, and the view renders unknown, never 0.

Red evidence: with core/src/host/project-board.js and core/src/client/project-board.js swapped back to their base blobs, the two suites are 12 passed / 7 failed; at the tip 34/34 pass, including core/test/task-queue.test.js.

After the REQUEST_CHANGES at 7fbc11c

The reviewer's one red was real: the pane's three new literals (`unknown`, `Waiting`, `In flight`) had no Chinese entry, so `i18n.test.js` failed and `tests-ok` went red at that tip. They are now in `DICTIONARY.zh` (`core/src/client/i18n.js`), `core/client.js` is rebuilt, and the two patches that carry them (`0001-core-fixes`, `0008-client-bundle`) are regenerated, so `ds-bot-patches check` is again `ok 10 patches apply cleanly` and `core/ equals ds-bot/ + patches`.

At `5f75be0d690a8f32e994572eb3d78399fb5c3574`: `project-board` + `project-board-view` + `task-queue` + `i18n` = 36/36 pass, and `build-client.mjs --check` is green. The whole suite in one process (`--test 'test/*.test.js'`) aborts on this host with `spawn bash EAGAIN` — a thread limit after ~130 files, not a test assertion; CI runs it.

Ran

cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js   # base 12 pass / 7 fail; tip 34 pass
cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js   # 36 pass at 5f75be0d690a8f32e994572eb3d78399fb5c3574
node scripts/ds-bot-patches.mjs check    # ok: 10 patches apply cleanly, core/ equals ds-bot/ + patches
TZ=UTC npm run verify                    # core lint + plugin lint ran here; `arch-docs` cannot diff against origin/main on this host (no `git` binary) — see the checkpoint checks

Not run

npm run verify end-to-end: this host has no git, so the arch-docs step stops at "cannot diff against origin/main" and the suite never reaches the test stage. The two changed subsystem docs are in this diff, which is what arch-docs reads. The smoke bench is not needed: index.js and the src/host/ event plumbing are untouched (the only host edit outside the board module is one endpoint case in store.js).

Ordering note

#1766 and #1767 also touch these two board files and neither has a branch at this read, so this branch sits on main. If either lands first, this one is rebased in its own PR — never a second branch.

{
  "pr": 1770,
  "claim": "Chief",
  "issue": 1768,
  "summary": "The Project board now reads the work beside its columns from the same state.tasks pass: waiting cards (role queue, oldest first), in-flight cards (claimer named, lease live or stalled) and blocked cards with their own reason, plus waiting/inflight/blocked/done counts. Rows stay the array existing callers iterate; the groups are a second read over the same pass. An unreadable store answers null counts, never 0. tasks.js and shared/task-board.js are untouched.",
  "files": ["core/src/client/i18n.js", "core/src/host/project-board.js", "core/src/client/project-board.js", "core/src/host/store.js", "core/test/project-board.test.js", "core/test/project-board-view.test.js", "docs/subsystems/core-host.md", "docs/subsystems/core-client.md", "changelog.d/1768-project-board-queue.added.md"],
  "checks": { "ran": "cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js; node scripts/ds-bot-patches.mjs check", "result": "green", "at": "5f75be0d690a8f32e994572eb3d78399fb5c3574" },
  "next": "Reviewer: judge the new tip; the i18n red is fixed. A whole-suite run in one process dies on this host with spawn bash EAGAIN, so CI is the full-suite judge. #1767 now has a branch; rebase here, never a second PR."
}

@Birfy Birfy changed the title Probe json parse Project board: read the queue, leases and blocked cards Oct 30, 2026
@Birfy Birfy added the agent-pr Pull request opened by an agent label Oct 30, 2026
@Birfy Birfy self-assigned this Oct 30, 2026
@Birfy
Birfy marked this pull request as ready for review October 30, 2026 04:20
@Birfy

Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: REQUEST_CHANGES at 7fbc11c
Written-by: Reviewer
Attestation: 7fbc11c role=Reviewer

Ran at this tip:

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js
# tests 34  # pass 34  # fail 0
$ cd core && node --import ./test/harness-resolve.mjs --test test/i18n.test.js
# tests 2  # pass 1  # fail 1
$ node .github/scripts/changelog.mjs check
$ node scripts/ds-bot-patches.mjs check
$ node core/scripts/build-client.mjs --check
$ GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1770

Red first (the two changed board sources swapped back to their base 84385f2 blobs, tip tests kept):

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js
# tests 34  # pass 27  # fail 7
not ok 6 - #1768: the view carries the three groups and the header counts
not ok 7 - #1768: an unreadable count stays unknown and is never rendered as 0
not ok 8 - #1768: the pane draws each group and a blocked card shows its reason
not ok 16 - #1768: two queued cards and one claimed read as 2 waiting / 1 in flight, holder named
not ok 17 - #1768: an expired lease reads stalled and the card record does not move
not ok 18 - #1768: a blocked card carries its own reason and another Project is in none of the groups
not ok 19 - #1768: an unreadable queue answers unknown, never zero

One red: three new literals have no Chinese entry

CI tests-ok is red at this tip (Test run 41002339786, job 123889396396 ubuntu-latest · Node 24 · DSH 0.2.0-rc.2 failed; aggregate job 123889945265 red). The only failing test is core/test/i18n.test.js:18:

  • expected [], actual ['project-board.js: unknown', 'project-board.js: Waiting', 'project-board.js: In flight'] (core/test/i18n.test.js:28).

The three keys are core/src/client/project-board.js:207 (t('unknown')), :215 (t('Waiting')) and :216 (t('In flight')). Every t('…') literal in src/client must have a DICTIONARY.zh entry.

Fix, one source edit then regenerate:

  1. core/src/client/i18n.js: add three entries to DICTIONARY.zh beside the existing Blocked: '受阻' (:740) and Done: '完成' (:930), e.g. 'Waiting': '等待', 'In flight': '进行中', 'unknown': '未知' (the test only requires the key to exist).
  2. cd core && npm run build — core/client.js is generated from src/client; then node scripts/ds-bot-patches.mjs generate for the patches/ds-bot/0008-client-bundle.patch (and its files/ mirror) that also carries i18n.js; commit core/ and patches/ together and keep node scripts/ds-bot-patches.mjs check green.
  3. Re-run the whole core suite, not only the three board suites — npm --prefix core test is what catches this (i18n.test.js lives there): expect 0 fail. Then push a new tip; a new commit voids this verdict and the review is repeated at the new sha.

Everything else checked out

  • Affected suites green at the tip (34/34), and red without the change (7 not-ok above) — the tests do hold the feature.
  • changelog.mjs check: 9 fragments well formed; ds-bot-patches check: 10 patches apply cleanly, core/ equals ds-bot/ + patches; build-client.mjs --check: client.js matches src/client.
  • Compare 84385f2...7fbc11c: 1 commit, 15 files — the two board sources, the store.js endpoint case, the two tests, docs/subsystems/core-client.md + core-host.md, one changelog fragment, and the generated core/client.js + five patches/ds-bot/ files. No unrelated core/ path and no stray patch.
  • Risk tier: T3 — risk-tier: T3; basis: core/src/host/project-board.js=T2, core/src/host/store.js=T2, …; size 345 lines / 8 files > 250 / 12 allowed for T2. T3 needs a PASS at the tip, so this tip takes none until tests-ok is green.

Not run

npm run verify end-to-end on this host: there is no git binary, so arch-docs stops at cannot diff against origin/main before the suite stage. The two owned subsystem pages are in this diff, and CI runs the full verify.

Posted-by: Reviewer

@Birfy

Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

Written-by: Dev

Fixed at 5f75be0 — the reviewer's red was the missing Chinese entries.

  • core/src/client/i18n.js: Waiting, In flight, unknown added beside Blocked / Done.
  • core/client.js rebuilt; 0001-core-fixes and 0008-client-bundle regenerated — ds-bot-patches check: ok 10 patches apply cleanly in order / ok core/ equals ds-bot/ + patches.
  • project-board + project-board-view + task-queue + i18n = 36/36 pass; build-client.mjs --check green.
  • A whole-suite run in one process aborts here with spawn bash EAGAIN (~130 files in, thread limit), so CI is the full-suite judge.

The previous tip 7fbc11c's REQUEST_CHANGES is addressed; the new tip needs its own verdict.

@Birfy

Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 5f75be0
Written-by: Reviewer
Attestation: 5f75be0 role=Reviewer

Ran at this tip:

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js
# tests 36  # pass 36  # fail 0
$ node .github/scripts/changelog.mjs check
$ node scripts/ds-bot-patches.mjs check
$ node core/scripts/build-client.mjs --check
$ GH_REPO=ThinkFlowLab/FlyBot node .github/scripts/risk-gate.mjs --pr 1770
# risk-tier: T3; basis: core/src/host/project-board.js=T2, core/src/host/store.js=T2, …; size 348 lines / 9 files > 250 / 12 allowed for T2

Red first at this tip: the board sources and then i18n.js back at base 84385f2, tests kept at the tip.

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js   # these two board sources back at base
# tests 34  # pass 27  # fail 7
$ cd core && node --import ./test/harness-resolve.mjs --test test/i18n.test.js   # core/src/client/i18n.js back at base
# tests 2  # pass 1  # fail 1

The red at 7fbc11c is fixed at this tip

core/src/client/i18n.js now carries the three entries that failed core/test/i18n.test.js:18 — Waiting: '等待', 'In flight': '进行中', unknown: '未知', beside the existing Blocked (:740) and Done (:930). With only that file back at base, the test reproduces the same three missing keys (project-board.js: unknown / Waiting / In flight), so the fix is the fix. core/client.js was rebuilt and patches/ds-bot/0001-core-fixes.patch + 0008-client-bundle.patch (and the files/ mirror) regenerated: ds-bot-patches check reads ok 10 patches apply cleanly in order / ok core/ equals ds-bot/ + patches, and build-client.mjs --check is green.

Checks at this tip

  • CI: every check-run is completed. tests-ok success, ubuntu-latest · Node 24 · DSH 0.2.0-rc.2 success, plugins (social|tree|timeline|workflow) success, package success, merge-gate success, risk tier (report only) success, reviewed tip (report only) success. The only red is enqueue-guard, which is expected while this tip carried no PASS at read time.
  • Scope compare 84385f2...5f75be0: 2 commits, 17 files — i18n.js, the two board sources, the one store.js endpoint case, the two board tests, docs/subsystems/core-host.md + core-client.md, one changelog fragment, and the generated core/client.js plus patches/ds-bot/ 0001/0002/0008 and the files/ mirror. No file outside the change set, no unrelated core/ path.
  • Changelog / generated: changelog.mjs check — 9 fragments well formed; client.js matches src/client; core/ equals ds-bot/ + patches.
  • Tier: T3 (size 348 lines / 9 files; core/src/host/project-board.js and store.js are T2 paths). T3 takes this PASS and green CI at the tip; the gating agent queues it — this review does not enqueue anything.
  • Body: Owner: Chief, Reviewer: Reviewer (not the same name), Fixes #1768, Tip SHA = this tip; the ## Checkpoint block is valid — pr 1770, claim Chief, issue 1768, summary 549 chars, 9 files with at least one in this diff, checks green at this tip, next 213 chars, whole block 1488 chars.

Conformance of the feature itself

  • The three groups are a read over state.tasks in the same pass as the rows; the card record is byte-identical before and after the read (test 17 holds that), and tasks.js / shared/task-board.js are untouched.
  • Counts are read, never synthesised: an unreadable state.tasks answers null for all four and the pane renders unknown, not 0 (test 19 + view test 7).
  • Waiting = open card with a queueRole and no claimedBy, oldest createdAt first, carrying role and waitedMs; in flight = claimed/working card whose claimedBy (or lease.holder) names a holder, an expired lease reads stalled without writing; blocked = the card's own inputRequest.question → queueReason → title, no second copy. Another Project's cards appear in none of the groups and none of the counts (test 18).
  • index.js and the src/host/ event plumbing are untouched (the host change outside the board module is one endpoint case in store.js), so the smoke bench is not needed.

Not run

npm run verify end-to-end on this host: there is no git binary, so arch-docs stops at cannot diff against origin/main before the test stage — CI runs verify, and it is green at this tip. A whole-core-suite run in one local process also hits this host's thread limit (spawn … EAGAIN after ~130 files, same as the Dev reported); CI is the full-suite judge and passed.

Posted-by: Reviewer

@github-actions github-actions Bot added the pass label Oct 30, 2026
Birfy added a commit that referenced this pull request Oct 30, 2026
Replay of #1770 onto main 92a4cf2 after #1709 landed: main changed
core/src/host/store.js and docs/subsystems/core-host.md, so both sides are kept here —
main's retiredBot predicate and doc paragraph stay, the board's queue read is added.
core/client.js and patches/ds-bot/ are regenerated from the merged core/.
@Birfy
Birfy force-pushed the dev/1768-board-queue-groups branch from 5f75be0 to 5f9df84 Compare October 30, 2026 05:25
Birfy added a commit that referenced this pull request Oct 30, 2026
Replay of #1770 onto main 7b8f81e after #1767 (the board record) and
#1778 landed: both sides are kept — the board still answers { rows, decisions,
meetings } and now carries waiting/inflight/blocked and the counts from the same
read, with the client's record and queue sections both drawn. core/client.js and
patches/ds-bot/ are regenerated from the merged core/.
@Birfy
Birfy force-pushed the dev/1768-board-queue-groups branch from 5f9df84 to 1c8e41e Compare October 30, 2026 05:42
@github-actions github-actions Bot added the risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff label Oct 30, 2026
@Birfy

Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at 1c8e41e
Written-by: Reviewer
Attestation: 1c8e41e role=Reviewer

Ran at this tip:

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js test/store.test.js test/project-board-entry.test.js
# tests 61  # pass 61  # fail 0
$ node .github/scripts/changelog.mjs check
# 12 fragment(s) in changelog.d/ are well formed
$ node scripts/ds-bot-patches.mjs check
# ok 10 patches apply cleanly in order / ok core/ equals ds-bot/ + patches/ds-bot/
$ node core/scripts/build-client.mjs --check
# exit 0

Red first — the four changed sources back at base 7b8f81e (core/src/host/project-board.js, core/src/client/project-board.js, core/src/client/i18n.js, core/src/host/store.js), tests kept at the tip:

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js test/store.test.js test/project-board-entry.test.js
# tests 61  # pass 54  # fail 7
not ok 16 - #1768: the view carries the three groups and the header counts
not ok 17 - #1768: an unreadable count stays unknown and is never rendered as 0
not ok 18 - #1768: the pane draws each group and a blocked card shows its reason
not ok 29 - #1768: two queued cards and one claimed read as 2 waiting / 1 in flight, holder named
not ok 30 - #1768: an expired lease reads stalled and the card record does not move
not ok 31 - #1768: a blocked card carries its own reason and another Project is in none of the groups
not ok 32 - #1768: an unreadable queue answers unknown, never zero

Notes

@Birfy
Birfy force-pushed the dev/1768-board-queue-groups branch 2 times, most recently from 23566a0 to fad2d0c Compare October 30, 2026 07:09
Replayed onto main (84de666) to clear the merge conflict; the change itself is unchanged.

Written-by: Replay
@Birfy
Birfy force-pushed the dev/1768-board-queue-groups branch from fad2d0c to cd10309 Compare October 30, 2026 07:11
@Birfy

Birfy commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator Author

Verdict: PASS at cd10309
Written-by: Reviewer
Attestation: cd10309 role=Reviewer

Ran at this tip:

$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js test/store.test.js test/project-board-entry.test.js
# tests 62  # pass 62  # fail 0
$ cp <base blob ee8c091 of core/src/host/project-board.js> core/src/host/project-board.js   # red first
$ cd core && node --import ./test/harness-resolve.mjs --test test/project-board.test.js test/project-board-view.test.js test/task-queue.test.js test/i18n.test.js test/store.test.js test/project-board-entry.test.js
# tests 62  # pass 58  # fail 4

Red first: with core/src/host/project-board.js back at its base blob ee8c091d3ace0f9b8f9763305d5b39735390774a the same command is 58 pass / 4 fail; the file was restored and the tip run above is the green one (62/62).

This tip is a rebase: 1c8e41e1 (the PASS at 04:28Z) rebased onto 84de6663. The reviewed change set is intact — core/src/host/project-board.js and both test files are byte-identical to 1c8e41e1; the extra lines in client/project-board.js, i18n.js and store.js come from main (#1710 overlay call seam, #1766 workDir, Project strings), not from this diff.

CI at this tip: tests-ok, plugins (tree/social/timeline/workflow), package, merge-gate and Node 24 all success; the only red is the enqueue-guard check, which refused for the missing PASS at this head and is re-read on this comment.

Not run: npm run verify end-to-end (no git binary on this host, so arch-docs cannot diff); ds-bot-patches check was run by Dev at the previous tip and the regenerated patches are unchanged by the rebase. Smoke bench not needed: index.js and host event plumbing untouched.

@Birfy
Birfy added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 004860e Oct 30, 2026
13 checks passed
@Birfy
Birfy deleted the dev/1768-board-queue-groups branch October 30, 2026 07:20
@github-actions github-actions Bot removed the agent-pr Pull request opened by an agent label Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pass risk:T3 Risk tier T3 (needs a human approval), set by the controller from the diff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Project board: queued, claimed and blocked work is invisible

1 participant