Repository navigation
fix(workflow): the Hand a task dialog says how many cards and Bots it is not showing - #2249
Merged
Birfy merged 1 commit intoNov 3, 2026
Merged
Conversation
Collaborator
|
Verdict: PASS at c530cc1 Ran at this tip: Review points at
|
… is not showing (ThinkFlowLab#2244) Both choice lists were cut at twelve with no row saying so: `loadTasks` dropped every board card after the twelfth before the dialog saw it, and the Bot list sliced at the same point, so the thirteenth card and the thirteenth Bot could not be picked while the dialog looked complete. The dialog now caps its own two lists at twelve, draws a `Show {count} more cards` / `Show {count} more Bots` row with `aria-expanded` that unfolds to the rest and folds back to `Show less`, and the board read keeps every card it loads. A list of twelve or fewer draws no row, and the assign body is unchanged.
This was referenced Nov 3, 2026
HugoXK
added a commit
to HugoXK/FlyBot
that referenced
this pull request
Nov 3, 2026
…owLab#2252) Written-by: Dev-4 Fixes ThinkFlowLab#2245 Owner: Dev4 Reviewer: Birfy Tier: T2 Claim-Id: 80bc2786e4e247909c65d504b4f6a7ea Branch: dev/4-p461-assign-requires-target Base: a78a5cc Tree: e63f524 Verified commit: local `86b4eed9e45ee139cc52dba135f1a65fc021f8b6` (not on the remote; the same tree as Tree above, pushed as `aa5612fb2c2270dbf64c7ce580fd3431b93573ae`) Pushed head: aa5612f Files: 4 changed, +65/−1 ## The defect With no Workflow defined, step 2 of **Hand a task to a Workflow** has nothing to pick: `workflows` is empty, so `target` starts `''` (`plugins/workflow/client.js:1426`). The button was lit anyway — `canAssign` read only the task list — and its click posted `{ taskId, workflowId: '' }`, which the host answers with "No such workflow". A button that looks ready and can only fail. `plugins/workflow/client.js:1439` is the whole fix; `:1504` is the button that read it. ## Red first, on live main `a78a5cc0` Clean tree at `a78a5cc0731e645ff11a3438ca47f438868042b7` with only `plugins/workflow/test/client.test.js` carrying the new cases (base sources, so `canAssign` still without the target clause): - `plugins/workflow/test/client.test.js` → **401 tests / 399 pass / 2 fail** - `not ok 205 - no Workflow yet: step 2 offers no target and Assign stays disabled` — `so Assign must stay disabled`, `false !== true` (`expected: true`, `actual: false`) - `not ok 206 - no Workflow yet: clicking Assign posts nothing` — `a click with no target must not reach the host`, `actual [{ taskId: 'task-live-1', title: 'Real board card one', workflowId: '' }]`, `expected []` - `ok 207 - positive control: with a Workflow the first one is picked and Assign is live` — green on the base, the counter-case that must stay green The base already carries `ThinkFlowLab#2249`'s six cases, so the two new failures sit at 205/206 rather than the old 148/149; the wording and assertions are unchanged. ## The fix `canAssign` gains `target !== ''` (`plugins/workflow/client.js:1439`), with one comment saying why: ```js const canAssign = tasksStatus === 'ready' && target !== '' && tasks.some(task => task.id === taskId) ``` Nothing else moves: the Bots in the same step-2 list are still offered and still selectable, so a Bot can be picked instead of a Workflow, and the submit body for a picked target is byte-identical to before (the positive-control test pins both). - `plugins/workflow/test/client.test.js` (+58): the two failing cases and the writable positive control, appended after `ThinkFlowLab#2237`'s cases. - `docs/subsystems/workflow.md` (+2): one sentence stating the rule next to the other assign-dialog rules. - `changelog.d/2245-assign-requires-target.fixed.md` (+1). ## Delta, file by file | file | +/- | kind | | --- | --- | --- | | `plugins/workflow/client.js` | +4/−1 | written | | `plugins/workflow/test/client.test.js` | +58 | written (new cases) | | `docs/subsystems/workflow.md` | +2 | written | | `changelog.d/2245-assign-requires-target.fixed.md` | +1 | written (new) | | **total** | **+65/−1** | 4 files, no generated file | `plugins/` carries no generated bundle, so nothing here is produced by `npm run build` or `ds-bot-patches generate`; `patches/ds-bot/**` and `core/client.js` are untouched. ## What I ran at local `86b4eed9e45ee139cc52dba135f1a65fc021f8b6` (pushed as `aa5612fb2c2270dbf64c7ce580fd3431b93573ae`) `TZ=UTC ARCH_DOCS_BASE=a78a5cc0731e645ff11a3438ca47f438868042b7 npm run verify` → **exit 0** | suite | tests / pass / fail | | --- | --- | | core | 2675 / 2675 / 0 | | plugins/social | 570 / 570 / 0 | | plugins/tree | 132 / 132 / 0 | | plugins/timeline | 140 / 140 / 0 | | plugins/workflow | 401 / 401 / 0 | | `.github/scripts` | 599 / 599 / 0 | | interop | 37 / 37 / 0 | | live-e2e | 26 / 26 / 0 | | **total** | **4580 / 4580 / 0** | - After the fix, `plugins/workflow/test/client.test.js` on its own: **401 / 401 / 0** (the base's 399 plus the two that were red). - `arch-docs: OK (4 changed file(s))`; oxlint **0 errors** in every suite (74/36/9/2/16 warnings, the same counts as live main; interop 1, live-e2e 0). - `ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)`; `ok 10 patches apply cleanly in order`; `ok core/ equals ds-bot/ + patches/ds-bot/`; `ok patches/ds-bot/ is what generate writes (generate is a no-op)`; `build-client --check` silent. ## Tier, by path (not by a label) `createGate(risk-rules).judge(files)` over exactly these four paths, from `a78a5cc0`'s `.github/agent/risk-rules.json`: `risk-tier: T2; basis: plugins/workflow/client.js=T2, plugins/workflow/test/client.test.js=T2, changelog.d/2245-assign-requires-target.fixed.md=T1, docs/subsystems/workflow.md=T0` ## Not run - The smoke bench (`dev/bench.sh smoke`): this box has no `deepseek-harness` checkout for it, so it cannot start. `core/index.js` and `core/src/host/` are untouched by this change. - No browser was available, so the dialog states are exercised through the modules and the tests rather than by clicking. ## Checkpoint <!-- flybot:checkpoint --> { "pr": 2252, "claim": "Dev4", "issue": 2245, "summary": "The Hand a task dialog lit Assign even when no Workflow existed, and that click posted workflowId '' which the host refuses with \"No such workflow\"; canAssign now also requires a picked target. The Bots listed in step 2 still work as targets, so a Bot can be picked instead, and the submit body for a picked target is unchanged. Two tests pin the disabled button and the empty post, and a third keeps the writable path live. Only plugins/workflow changes; no generated file is in this diff.", "files": [ "plugins/workflow/client.js", "plugins/workflow/test/client.test.js", "docs/subsystems/workflow.md", "changelog.d/2245-assign-requires-target.fixed.md" ], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=a78a5cc0 npm run verify (4580/4580/0)", "result": "green", "at": "86b4eed9e45ee139cc52dba135f1a65fc021f8b6" }, "next": "T2: waiting for a PASS naming this tip; enqueue-guard will refuse until one exists" } <!-- /flybot:checkpoint -->
HugoXK
added a commit
to HugoXK/FlyBot
that referenced
this pull request
Nov 3, 2026
…hinkFlowLab#2258) Fixes ThinkFlowLab#2256 Owner: Dev Written-by: Dev-1 Reviewer: Birfy Claim-Id: c7a4c6620c844d34ab9fef0f120ca56b Branch: dev/1-p464-held-tasks-more Base: 8f5107c Tier: T2 (gate reading at this tip: `computedTier = T2`, `exemptFromPass = false`; `plugins/workflow/**` matches, and the highest matching path tier wins) Tree: 576641d Verified tree: 576641d — `npm run verify` ran on this tree in local commit b13fd0c2469e3692d3535146ba092b8c54b54a19, which was never pushed Pushed head: dde9744 (same tree 576641d, generated from it by the push path) Files: 7 changed, +233/−14 Single parent: 8f5107c ## What changes Row 21 of a lane's held list did not exist. `workflow/state` served `heldTasks` as the first 20 sorted ids beside `heldTaskCount`, the whole count, and the Stage drew those 20 and then a plain `<div class="wf-held-more">3 more held tasks</div>`: no control, no `aria-expanded`, and `task-held-21` was not in the DOM at all, so a card past the page could not even be re-matched. The read now takes a bounded page. `heldLimit` (20 by default, 200 at most, anything that is not a positive integer falls back to 20) slices the ids; `heldTaskCount` stays the whole truth. `plugins/workflow/index.js` hands the request body to `service.state`, and the default read is unchanged — the 2 s poll keeps asking for the same 20 ids until somebody unfolds. On the client the div becomes the ThinkFlowLab#2249 primitive: a `wf-more` button with `data-more="held"` and `aria-expanded`, reading `Show 3 more held tasks` and folding to `Show less`. Unfolding asks the Section for `heldLimit: 200` and the 2 s poll keeps that page while it stays unfolded — otherwise the next read would fold it back; folding returns to 20. Another lane is another page, so switching folds the list (the Stage resets on `workflow.id`, the Section resets `heldWideRef` on `openId`), and a lane that is not open cannot keep the wider read alive. At 20 or fewer held tasks the row is absent and the block is byte-identical to today (the second test pins it). Nothing else moves: no claim, route, assign body or poll cadence changes. Plugin source only — `core/client.js` and `patches/ds-bot/` are untouched, so there is nothing to regenerate. Docs: the `src/service.js`, `client.js` and Tests rows of `docs/subsystems/workflow.md` now name the page and the unfold control. Changelog: `changelog.d/2256-held-tasks-page.fixed.md`. ## Red first Run on the live base `8f5107cd` with the branch's two test files and the source at that base: ``` $ TZ=UTC node --test plugins/workflow/test/held-page.test.js plugins/workflow/test/client.test.js not ok 163 - \ThinkFlowLab#2256: the held list draws its rest behind a wf-more button that asks for the wider page the rest is a control, not a dead line 0 !== 1 ok 164 - \ThinkFlowLab#2256: a lane within one page draws no more-row and keeps its held block as it was not ok 165 - \ThinkFlowLab#2256: the state read pages held ids, 20 by default and every one when asked heldLimit: 200 lists every held id + actual - expected ... Skipped lines 'task-held-20', - 'task-held-21', - 'task-held-22', - 'task-held-23' not ok 166 - \ThinkFlowLab#2256: heldLimit is capped at 200, so a reader never turns the poll into a full read the widest page is 200 ids 20 !== 200 # tests 166 # pass 163 # fail 3 ``` TAP escapes the leading `#` in a test name; the names themselves are `ThinkFlowLab#2256: …`. Read against the issue: `not ok 163` is the dead div (the base draws zero `wf-more` rows for held ids), `not ok 165` is the missing ids (the base serves 20 whatever is asked), `not ok 166` is the cap the read does not have, and `ok 164` (≤20 ids: no row, block unchanged) is already green at the base and must stay so. The numbers moved because `client.test.js` on main carries ThinkFlowLab#2255's three button-copy cases: this branch keeps them as they are and appends its two held cases after them, so the same two files run 166 tests at this base and the three failures are the ones above. With the fix in place the same two files run `# tests 166 / # pass 166 / # fail 0`. ## Files 7 files, +233/−14: `plugins/workflow/src/service.js` (+16/−4 — `MAX_HELD_LIMIT`, `heldLimitOf`, `present(heldLimit)`, `state(body)`), `plugins/workflow/client.js` (+29/−6 — the `wf-more` row, the wider read on the poll, the fold on lane switch, one zh string), `plugins/workflow/index.js` (+1/−1 — the read handler passes its body), `plugins/workflow/test/held-page.test.js` (+83), `plugins/workflow/test/client.test.js` (+100), `docs/subsystems/workflow.md` (+3/−3), `changelog.d/2256-held-tasks-page.fixed.md` (+1). ## Ran - Red first above on `8f5107cd`, then `TZ=UTC node --test plugins/workflow/test/held-page.test.js plugins/workflow/test/client.test.js` → `166/166/0` on the fixed tip, and `npm --prefix plugins/workflow test` → `408/408/0` (404 at the base; the four new cases are this diff's, ThinkFlowLab#2255's three button-copy cases still run in the same file). - `TZ=UTC ARCH_DOCS_BASE=8f5107cdcb876a1774187e325e150797c5577253 npm run verify` → **exit 0**, **4587/4587/0**: core 2675, social 570, tree 132, timeline 140, workflow 408, `.github/scripts` 599, interop 37, live-e2e 26. - In that chain: `arch-docs: OK (7 changed file(s))`; `ok 10 patches apply cleanly in order`; `ok core/ equals ds-bot/ + patches/ds-bot/`; `ok patches/ds-bot/ is what generate writes (generate is a no-op)`; `ok 272 client.js is the build of src/client`; the `changelog.d/` check green and all four packed plugins imported. - `git status --porcelain` empty on the committed tree. ## Not run - The CI `package` job's typecheck, actionlint and pack check — `npm run verify` does not run them. - The smoke test against a live instance: `core/index.js` and `core/src/host/` are untouched. - `npm_config_cache` pointed at a workspace directory for this run: `~/.npm` is read-only in this sandbox and the plugin lint's `npm pack` step writes a cache. Nothing else depends on it. ## Checkpoint <!-- flybot:checkpoint --> { "pr": 2258, "claim": "Dev", "issue": 2256, "summary": "The Stage's held list is now a page: workflow/state takes a bounded heldLimit (20 by default, 200 at most, a non-positive or non-integer value falls back to 20) while heldTaskCount stays the whole truth. The dead '3 more held tasks' div becomes the ThinkFlowLab#2249 wf-more button (data-more=held, aria-expanded) that asks for heldLimit 200, keeps that page on the 2 s poll, folds back to Show less, and folds when the lane changes. At 20 or fewer held tasks the row is absent and the block is unchanged.", "files": [ "plugins/workflow/src/service.js", "plugins/workflow/client.js", "plugins/workflow/index.js", "plugins/workflow/test/held-page.test.js", "plugins/workflow/test/client.test.js", "docs/subsystems/workflow.md", "changelog.d/2256-held-tasks-page.fixed.md" ], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=8f5107cdcb876a1774187e325e150797c5577253 npm run verify", "result": "green", "at": "dde974485db3e4859f9e1ee0f2354890b0254987" }, "next": "T2: waiting for Birfy's PASS naming the pushed head; the pushed head carries the identical tree 576641d." } <!-- /flybot:checkpoint -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Written-by: Dev-3
Fixes #2244
Owner: Dev3
Reviewer: Birfy
Tier: T2
Claim-Id: ee75138bc0004492b4115edc39e13f62
Branch: dev/3-p459-assign-dialog-truncation
Base: 6f862cd
Tree: 03e7936a2f73b6b1afcae3d5802de341d74aa32f
Verified commit: c530cc1
Pushed head: c530cc1
Single parent: 6f862cd
Files: 4 changed, +156/−6 (three handwritten files, one of them a new changelog fragment)
The defect
Hand a task to a Workflowcut both choice lists at twelve with nothing saying so:loadTaskskept only the first twelve filtered board cards before the dialog ever saw them (rows.filter(...).slice(0, 12)), and the dialog only doestasks.map, so it could not know a cut had happened. A card at position 13+ could not be picked at all.bots … .slice(0, 12), so the thirteenth local Bot never appeared.The dialog looked complete while picks were missing, and the file already carried the primitives for the fix (
{count} more held tasksat:590,Show more/Show lesswitharia-expandedat:1221).Accepted shape: a twelve-item default plus an explicit row
This is the issue's first option, not "always draw all twenty": the default view keeps today's length, and a row says how many are not shown so every card and every local Bot stays reachable. A list of twelve or fewer draws no row at all, so nothing grows for the ordinary case.
Red first, on live main
6f862cd0Clean tree at
6f862cd0a95206497052dc61330692e3cfb7a713with onlyplugins/workflow/test/client.test.jsfrom this branch:The two
okare the counter-cases, green on the base: a twelve-card board draws no row and posts the same assign body, and three Bots draw no row and still postbot:2. The four reds are the hole: no row exists, so there is nothing to expand and no way to reach the twentieth card or Bot. After the change the same file is 156 / 156 / 0.The fix
loadTasksno longer pre-slices: the board read keeps every open card, so a card past the twelfth can be selected and itsid/titlereach the unchanged submit body.AssignModalcaps its own two lists at twelve (ASSIGN_VISIBLE = 12) and draws one row per list when there is more:className: 'wf-more',data-more: 'tasks' | 'bots',aria-expandedfollowing the expanded state, labelledShow {count} more cards/Show {count} more Botsand folding back to the existingShow less. Both counters arelength - shown, so the row says exactly what is hidden.length > ASSIGN_VISIBLE), so today's view keeps its length; nothing else in the dialog moves, and the submitted assign body is untouched ({ workflowId | botId, taskId, title }).Show {count} more cardsandShow {count} more Botsget their Chinese wording in the plugin's ownZHmap besideShow more/Show less;.wf-moretakes its style from the same accent and small type as.wf-term-more.docs/subsystems/workflow.mdsays what the dialog does now, andchangelog.d/2244-assign-dialog-lists-expandable.fixed.mdis new.What I ran at
c530cc16a871608a133a803d2260472eefdc9076TZ=UTC ARCH_DOCS_BASE=6f862cd0a95206497052dc61330692e3cfb7a713 npm run verify→ exit 0.github/scriptsarch-docs: OK (4 changed file(s));build-client --checksilent; oxlint 0 errors in every suite (74/36/9/2/16 warnings, the same pre-existing counts as live main; interop 1, live-e2e 0).ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5);ok 10 patches apply cleanly in order;ok core/ equals ds-bot/ + patches/ds-bot/;ok patches/ds-bot/ is what generate writes (generate is a no-op).node .github/scripts/changelog.mjs check→ fragments well formed;git status --porcelainempty at the tip.Tier, by path (not by a label)
createGate(risk-rules).judge(files)over exactly these four paths answers:risk-tier: T2; basis: plugins/workflow/client.js=T2, plugins/workflow/test/client.test.js=T2, changelog.d/2244-assign-dialog-lists-expandable.fixed.md=T1, docs/subsystems/workflow.md=T0So this one needs a
Verdict: PASSnaming this tip.Policy-signis not required:policy/gates.jsonlistsgateFilesas.github/scripts/merge-gate.mjs,.github/scripts/review-gate.mjs,.github/scripts/pass-label.mjs,.github/scripts/risk-gate.mjs,scripts/self-test-catalog.mjs,.github/scripts/policy-sign.mjs,.github/workflows/test.ymlandpolicy/, and this diff touches none of them.Not run
The smoke bench (
dev/bench.sh smoke): this box has nodeepseek-harnesscheckout (DSH_HARNESSunset,../deepseek-harnessabsent). No browser was available, so the row was exercised through the modules and the tests rather than in a real click.Checkpoint
{
"pr": 2249,
"claim": "Dev3",
"issue": 2244,
"summary": "The Hand a task dialog cut both choice lists at twelve with nothing saying so: loadTasks dropped every board card after the twelfth before the dialog saw it, and the Bot list sliced at the same point, so the thirteenth card and the thirteenth Bot could not be picked. The dialog now caps its own two lists at twelve and draws a Show {count} more cards / Show {count} more Bots row with aria-expanded that unfolds to the rest and folds back to Show less; a list of twelve or fewer draws no row, the board read keeps every card, and the assign body is unchanged.",
"files": [
"plugins/workflow/client.js",
"plugins/workflow/test/client.test.js",
"docs/subsystems/workflow.md",
"changelog.d/2244-assign-dialog-lists-expandable.fixed.md"
],
"checks": {
"ran": "TZ=UTC ARCH_DOCS_BASE=6f862cd0a95206497052dc61330692e3cfb7a713 npm run verify (4577/4577); node .github/scripts/changelog.mjs check",
"result": "green",
"at": "c530cc16a871608a133a803d2260472eefdc9076"
},
"next": "T2: waiting for Birfy's PASS at c530cc1; no further writes from this branch until then"
}