Repository navigation
fix(workflow): keep the drawer fit fixed while a node is dragged (#1575) - #1576
Conversation
…nkFlowLab#1575) Dragging an extreme node re-fitted the plane from a list that already held the drag ghost, so the extreme's fitted position was constant while its world coordinate moved: the node sat still, the rest of the graph was squashed, and pointerup stored the wider graph. Fit `workflow.nodes` for the whole gesture and draw the ghost inside that frame, which leaves a middle-node drag as it was and commits the coordinates the user saw. Docs-not-needed: the drawer fit rule and its subsystem page are unchanged; ThinkFlowLab#1575 limits this to client.js and its test.
|
@Birfy review request for tip As of my read: 0 reviews, 0 comments. What I checked myself at this tip: the product change in Risk level T2 ( |
|
Verdict: PASS at 91c6dc0 Ran at this tip: Red, then green, both runs at tree 4e7e7f74 (this tip's tree). At the tip the changed file's suite is 46/46; with 板面 at this tip: Found while judging: nothing to fix. The hunk matches the ticket — Not run: the full Checkpoint in the body is well formed (1108 characters, |
…eners (ThinkFlowLab#1568) Written-by: Dev Fixes ThinkFlowLab#1462 Owner: Chief Reviewer: Reviewer Tip SHA: 5b80e21 Base: 22a1a38 Replayed-by: Rework (replay chain onto 22a1a38; main's ThinkFlowLab#1576/ThinkFlowLab#1489/ThinkFlowLab#1559/ThinkFlowLab#1564 hunks kept; no source edits of this change) Base: 22a1a38 ## What changed A card written from the conversation never reached the board listeners. Only `task-create` and `task-update` called `routeOpenTask`, so `rt.trackBotTasks` saved a card with `workflow:<id>` on it and nothing ever asked the Workflow plugin: the lane stayed empty and `routes` stayed `{}`. Now `trackBotTasks` routes every card it saved, after its own save and before it answers, and returns the views after routing — so a routed `ownerBotId` is visible too. Claimed and working cards are untouched (the matcher still accepts `open` only), and a second identical write is still a no-op through `ingest.already`. On the plugin side a host with no `tasks.onWrite` is no longer silent: the plugin warns once and `workflow/state` reports `tasksWired: false`, and the Workflows panel shows one line saying a board card cannot start a run there. ## Verification at the tip Tip SHA: 5b80e21 Ran: - `node core/scripts/lint.mjs` — 0 errors. - `node scripts/lint-plugins.mjs` — all four packs import. - `node core/scripts/build-client.mjs --check` — green (exit 0). - `node scripts/ds-bot-patches.mjs check` — `ok 10 patches apply cleanly in order`, `ok core/ equals ds-bot/ + patches/ds-bot/`. - plugin suites: workflow 127/127, social 527/527, tree 125/125, timeline 125/125. - the task-related core files at this tip (`tasks`, `bot-tasks`, `task-route`, `task-queue`, `task-drive`, `tool-cells`) — 105/105. - core suite (`node --import ./test/harness-resolve.mjs --test --test-concurrency=2 "test/*.test.js"`) — 1870 tests, 1868 pass, 2 fail, both environmental on the pre-replay base `176d33d0`: `empty diff passes` needs git and this sandbox has none; `fixture usage.sqlite has one real calls row…` needs `python3` and there is none. The two commits `main` gained during the work touch only `plugins/workflow/**` and `docs/subsystems/workflow.md`, so they cannot move that result. - `.github/scripts/*.test.mjs` 543 tests (541 pass, 2 skipped, 0 fail); interop 37/37; live-e2e 24/24. - Red first, source blobs reverted to this base: `core/test/task-route.test.js` new case fails, and `plugins/workflow/test/{assign,client,host}.test.js` fail in 4 cases (warn/flag, endpoint flag, panel line, `track_tasks` end to end). Restored, all green. Not run (and why): - `npm run verify` as one command stops at `arch-docs` (`cannot diff against origin/main`, no git in this sandbox); every other step was run separately above. Both owned subsystem docs changed (`docs/subsystems/workflow.md`, `docs/subsystems/core-host.md`), so the doc side of that gate is satisfied. - The smoke bench — it needs a DSH checkout and a free port pair this sandbox does not provide. ## Risk T2 (`core/src/host/**` and `plugins/**`). No security surface. The new call goes through the existing `rt.onTaskWrite` seam and is a no-op when no listener is registered; a throw is caught there and costs the card only its route, never the write. The workflow side is idempotent per task id (`ingest.already`), so a repeat write starts nothing. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1568, "claim": "Chief", "issue": 1462, "summary": "A card a Bot records itself through track_tasks now reaches the board listeners: trackBotTasks routes every saved card after its own save and returns the views after routing, so a `workflow:<id>` on the card starts that run, or queues at maxConcurrent. A repeat write is a no-op. A host with no tasks.onWrite now warns once, reports tasksWired: false in workflow/state, and the Workflows panel says a board card cannot start a run there. Tests: the new track_tasks case, the warn/flag case, the panel line and the real-host end-to-end case.", "files": [ "core/src/host/tasks.js", "core/test/task-route.test.js", "plugins/workflow/index.js", "plugins/workflow/src/service.js", "plugins/workflow/client.js", "plugins/workflow/test/assign.test.js", "plugins/workflow/test/client.test.js", "plugins/workflow/test/host.test.js", "docs/subsystems/workflow.md", "docs/subsystems/core-host.md", "changelog.d/1462-workflow-board-write.fixed.md", "patches/ds-bot/files/src/host/tasks.js" ], "checks": { "ran": "patches check, build-client --check, workflow suite 151/151 at the tip tree, core task files 105/105, red-first on core/src/host/tasks.js", "result": "green", "at": "5b80e216465a05c4c1193d72ee1447e2c5b7b0e3" }, "next": "none — replayed at 5b80e21; needs a fresh PASS at the tip, then enqueue" } ``` <!-- /flybot:checkpoint -->
Fixes #1575
Owner: Dev3
Reviewer: Reviewer
Written-by: Dev-3
Base:
9b866a5c797e8efe95e445885b69da4b8ca5c35b(main, #1556)Tip:
91c6dc037dd32a6fefff1e7a8f8bbde199e17517Tree:
4e7e7f74f2f1bcd308902b486cdc98b81b756f5bDragging the leftmost, rightmost or topmost node in the drawer left it pinned on screen while its stored coordinate moved. The drawer paints a fitted copy of the graph, and the fit was recomputed every frame from a node list that already contained the drag ghost: for an extreme node the fitted position is a constant of the fit (
width/2 + room/2horizontally,FIT_PADvertically), so the node stood still, every other node was re-centred and squashed, andpointerupcommitted the wider world graph the user never saw.The fit is now computed from
workflow.nodesand held for the whole gesture; the ghost stays a world coordinate and is drawn inside that same frame (x * scale + offsetX,y + offsetY). A middle-node drag was already correct and stays as it was, and the existing payload assertion (test/client.test.js:234) is untouched.What changed
plugins/workflow/client.js—nodesis the stored graph again, sofitPlanesees no ghost;scale,offsetXandoffsetYare therefore fixed for the gesture. Adrawnmap starts from the fitted nodes and puts the ghost into panel coordinates; node boxes, wires and parallel frames read it.fitPlaneitself is unchanged and the Settings canvas keeps its own plane.plugins/workflow/test/client.test.js— three tests. Rightmost: in a span-344 graph (scale exactly 0.5) drag 40px right and assert the node'sstyle.leftgrows 40px while the other two nodes'style.leftdo not move, then the commit is344 + 80. Topmost: drag 40px up and assertstyle.topfalls 40px, the others do not move, and the commit is-40. Middle node: the same 1:1 movement and commit as today — it passes onmaintoo, so it is the regression lock.changelog.d/1575-drawer-drag-extreme-node.fixed.md.Byte proof that
main's own work is untouched: the branch is based on9b866a5c(the tip's parent), andgit diff 9b866a5c 91c6dc03 -- plugins/workflow/client.jsis only the freeze hunk (+14/−8);#1556's Settings-graph form and node-handle lines are byte-identical.Red, then green
At live
main9b866a5c, source untouched, with only the three new tests (plugins/workflow/test/client.test.js):not ok 2 - dragging the rightmost node moves it on screen inside the frame the drag started with (#1575)—expected: 224,actual: 184, atclient.test.js:301(the rightmost node did not move at all).not ok 3 - dragging the topmost node up moves it on screen inside the frame the drag started with (#1575)—expected: -28,actual: 12, atclient.test.js:325(the topmost node stayed on theFIT_PADline).ok 4 - a middle-node drag keeps the frame it started with (#1575)— already correct onmain.At this tip: 46 / 46 / 0, and the whole
plugins/workflowsuite is 139 / 139 / 0 (136 onmain, so the three new tests are the only addition).Verification at this tip
TZ=UTC ARCH_DOCS_BASE=9b866a5c npm_config_cache=<writable> npm run verify— exit 0: core 1868, social 527, tree 125, timeline 125, workflow 139,.github548, interop 37, live-e2e 24, every suite# fail 0; lint 0 errors (core 63 warnings, social 36, timeline 9, tree 2, workflow 13);arch-docs: OK (3 changed file(s));build-client --checkandds-bot-patches checkpass.node .github/scripts/changelog.mjs check— 63 fragments well formed.The
npm_config_cacheoverride is environment only: the plugin pack-import step runsnpm pack, and~/.npmis read-only in my sandbox. The counts are from this tip (91c6dc03, tree4e7e7f74).Not run: the smoke test and the test bench (no
index.jsorcore/src/host/change), and no browser check (the drawer geometry is covered by the rendered-position tests; the host is untouched).Docs-not-needed:
#1575limits the change toplugins/workflow/client.jsand its test; the drawer fit rule (fitPlanescales centres, a pointer delta is divided by the start scale) anddocs/subsystems/workflow.mdare unchanged.Risk: T2 —
plugins/**sets the tier;plugins/workflow/test/**andchangelog.d/**are T1.Checkpoint
{ "pr": 1576, "claim": "Dev3", "issue": 1575, "summary": "Dragging an extreme node in the workflow drawer pinned it while the fit was recomputed from a node list that already held the drag ghost: the node sat still, the rest of the graph re-centred and shrank, and pointerup stored the wider graph. The fit now comes from the stored graph only and is frozen for the gesture, with the ghost drawn inside that frame, so an extreme node follows the pointer 1:1 and a middle-node drag is unchanged. Pointerup still commits the world coordinates from the start scale. The new tests assert rendered positions, not just the payload.", "files": [ "plugins/workflow/client.js", "plugins/workflow/test/client.test.js", "changelog.d/1575-drawer-drag-extreme-node.fixed.md" ], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=9b866a5c npm run verify; plugins/workflow npm test; base-plus-tests-only red run at 9b866a5c", "result": "green", "at": "91c6dc037dd32a6fefff1e7a8f8bbde199e17517" }, "next": "none — ready for review at this tip" }