Uh oh!
There was an error while loading. Please reload this page.
Scope the schedule (gantt) lens to open work - #98
Conversation
A manager opens the schedule to see an overloaded fortnight before it arrives; nothing about that question involves work that is already done. On the demo seed 151 of the 186 scheduled tasks are `done`, so the lens spent nearly all of its height drawing finished bars. Extends #91's grouped-lens scope inventory rather than adding a second mechanism: the walk now covers the kanban/gantt/timeline `groupByField` lenses alongside the grid `grouping` block, names which mechanism each line is about, and pins the two lenses whose scope is a decision. It is still a pin-and-inventory, not a rule that every grouped view must be filtered — that rule fires on `catalog_tree` and on `board`, both fine. The card's diagnosis was checked in a browser first and does NOT hold: the gantt is not page-scoped. Its chart is served by the non-grid fetch, which sends no `top`, so it drew all 186 rows and all 12 owner groups over the full span, while a separate `top=100` fetch fed the footer beneath it. No owner group was missing before this change. The view comment and the guard message say so, so that neither is later cited as evidence for something that was not measured. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SqkTcrxUFci7nqXdbBSe2p
os-warren
commented
Sep 1, 2026
Reviewed — merging. My triage asserted a mechanism and you falsified it; that is the right outcome and the report handles it correctly.Gates on the merged head The correctionI wrote in the triage that "both derivations run over the fetched page". That is wrong for the gantt. You measured, before editing anything, that one page load issues two fetches of the same set: a That also means the residual I asked you to state was not a description of today — and restating it as "what would happen if the chart ever consumed the paged fetch" is the honest form. Writing the falsification into the view comment and the guard's failure message is the part I would have missed: it stops either being cited later as evidence for something nobody measured. The remedy survives because its justification never rested on the mechanism — 151 of 186 scheduled tasks are done, and a gantt of finished work answers no question anyone opens this screen with. The filter also removes a "more data may be available" footer that was printed under a complete chart, which is its own small lie. And the near-miss is the detail that makes this more than an academic correction: Owen Pryce's single scheduled task falls outside the 100-row page, so had the chart consumed that fetch, he is precisely the owner who would have vanished. The hazard was real; the wiring just happened not to reach it. Your two judgment calls
The upstream finding is the better oneobjectui#7210 — a gantt lens fetching its rows twice, once paged into a footer that then misdescribes the chart beside it, and once unbounded with no ceiling reachable from view metadata — is a more serious report than the card that produced it. Today that unbounded fetch is 186 rows; in a real deployment it is however many scheduled tasks exist, with nothing an author can write to bound it. Searching first and confirming it is not a duplicate of #7189/#7203/#7204 (and that #6419/#6460 are closed) is what makes it worth someone's time. Commenting on #7189 to bound it to the grid rather than opening a gantt half was also right — the gantt does not share Extending #91's inventory rather than adding a second guard, and holding the line against a blanket "every grouped view must be filtered" rule, keeps that file coherent — this is the third card to measure that such a rule would fire on views that are fine. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#96
Scopes the
schedule(gantt) lens tostatus IN ('open','in_progress'), mirroring what #91 did toby_unit, and extends #91's grouped-lens scope inventory to cover thegroupByFieldlenses rather than adding a second mechanism beside it.The card's diagnosis was checked in a browser first and does not hold. That is the main thing a reviewer should read before the rest: the gantt is not page-scoped, and no owner group was missing. The filter is still right, for the reason the triage comment gave — a schedule of finished work is not what this screen is for — but it is not repairing what the card thought it was, and neither the view comment nor the guard message claims it is.
What the browser actually showed
pnpm demo, seeded store,/_console/apps/ai.objectstack.duly/duly_task/view/schedule, before any edit. One page load issues two fetches of the same filtered set:The chart is served by the non-grid fetch, which sends no
topat all, and@objectstack/restapplies no cap whenlimitis absent — so it receives the whole result set. Counted off the DOM rather than inferred: 186 task rows + 12 group rows = 198 × 40px = the 7920px the task list scrolls. The before screenshot shows the same thing without arithmetic — theDev Admingroup row reads1/31 → 12/31, and12/31is six months past the 100-row page's ownmax(due_date)of6/30.So on this console build the timeline range covered the true
2026-01-31 → 2026-12-31span, all 12 owners with scheduled work had a group, and the100 records · Showing first 100 records. More data may be available.footer was printed under a chart that was in fact complete. The footer is the ListView chrome reporting its own paged fetch; it describes neither the chart above it nor the store.Filed upstream separately — see "Upstream" below.
objectui#7189is aboutuseGroupedDatagrouping over a fetched page on a grid, which is a different code path from anything measured here, so this is not a gantt half of it.The card's second open question, settled
Enumerated by scrolling the virtualised task list end to end and collecting every
gantt-task-row-__group__*row, against the owners the seed gives scheduled open work to (counted server-side over the whole store, not off the screen):Name for name, both directions: Ana Ferreira, Dev Admin, Elin Halvorsen, Greta Lindqvist, Ibrahim Chaudhry, Marek Dvorak, Owen Pryce, Priya Raman, Rosa Delgado, Sami Okonkwo, Tomas Bergh, Yuki Tanabe. No owner is missing after the change, so this card does not halt.
Worth recording because it is the near-miss: had the gantt consumed the paged fetch, Owen Pryce is the owner who would have vanished. His single scheduled task falls outside the 100-row page, and the page's 11 owner buckets are exactly the 12 less him.
After
33 rows (27
open+ 6in_progress),hasMore: false, 12 group rows,33 recordsin the footer with the "more data may be available" line gone, and33 + 12 = 45 × 40px = 1800pxof task list.Screenshots live on a throwaway branch (
claude/issue-96-shots, an orphan commit holding the two PNGs), so no binaries enter this diff.One side effect, stated because the file explicitly warns against it. The gantt block's comment says no filter here should be narrowed to make objectui#7203's month label look better. This narrowing moves it anyway: the toolbar formats
min(visible_from) - 7d, so the label goesJanuary 2026→June 2026. It is a side effect and not a reason — the label is still wrong, only about a different month now — and objectui#7203 remains open and untouched by this PR.The guard
Extends #91's walk instead of adding a second one, and keeps its idiom: pin the named decisions, inventory the rest. No rule that every grouped view must be filtered — that rule has now been measured firing on a healthy view twice (
catalog_treegroups two levels with no filter and needs none;boardgroups bystatus, where a status scope would delete columns from the board).The walk now reads both grouping mechanisms — the grid
groupingblock and thekanban/gantt/timelinegroupByField(the same three blocks the projection guard above it already inventories) — and each inventory line names which one it is about:The two pins have different deletion conditions, which is recorded in the comment because it matters to whoever eventually removes this stopgap:
by_unitis scoped because grid grouping is page-scoped, so it retires with objectui#7189;scheduleis scoped because a gantt of finished work is not what the screen is for, and no platform fix retires that.Proven red before the fix
The fix committed first, then
src/views/task.view.tsalone restored to its pre-fix state through a script carrying anEXIT INT TERMrestore trap, with the mutation confirmed on disk by anchored counts before the run (open-work filter rules present: 4—by_unit's survives,schedule's is gone — andschedule scope block present: 0).npx vitest run test/metadata-bindings.test.tsexited 1 on exactly the two intended assertions, 53 others still passing:The restore leg was verified byte-identical to the committed file (
git diff --quiet HEAD -- src/views/task.view.ts), so the numbers above come from the tree this PR actually ships.The residual, not overclaimed
This lens is not currently page-scoped, so there is no page-scoping to remove. What stays true:
Upstream
useGroupedData's page-scoping, so #7189 stays a grid card.Gates
All four green on
b3ea92f, the merged head this PR ships (origin/mainadvanced to #97 mid-task; merged in and re-run, since #97 edits the same test file):pnpm typecheckprinted no diagnostics. No changeset: this repo has no changeset mechanism, the four gates are the whole contract.Generated by Claude Code