|
2056 | 2056 | "title": "Action buttons surface at exactly their declared locations — list toolbar, list row, record header/more/related/section — and each dispatches for real", |
2057 | 2057 | "since": "v15", |
2058 | 2058 | "status": "active", |
2059 | | - "revision": 17, |
| 2059 | + "revision": 18, |
2060 | 2060 | "priority": "P1", |
2061 | 2061 | "surface": "browser", |
2062 | 2062 | "personas": [ |
|
2065 | 2065 | "fixtures": { |
2066 | 2066 | "app": "showcase", |
2067 | 2067 | "requires": [ |
2068 | | - "the per-location action fleet on showcase_task (examples/app-showcase/src/ui/actions/index.ts): showcase_bulk_reassign (list_item+list_toolbar, flow), showcase_quick_view (list_item, modal), showcase_mark_done (list_item+record_header+record_section, a declarative write on the default script route — operation 'update', patch {done: true, progress: 100} — visible 'has(record.done) && record.done != true'), showcase_log_time (record_header+record_related+record_section, form), showcase_open_docs (record_more, url), showcase_recalc_selection (record_more, api — declares record_more ONLY, which is what keeps it off the toolbar; objectui#3142), showcase_new_task (locations: [] — the fleet's headless specimen, read by the empty-locations probe), showcase_reopen_task (list_item only, operation 'update' patch {done: false}, visible 'has(record.done) && record.done == true' — Mark Done's mirror, so a done task's row menu offers Reopen where a not-done one offers Mark Done; a click on it is refused by the showcase_guard_task_reopen hook by design, which records-forms.script-action-hook-refusal-toast drives)", |
| 2068 | + "the per-location action fleet on showcase_task (examples/app-showcase/src/ui/actions/index.ts): showcase_bulk_reassign (list_item+list_toolbar, flow), showcase_quick_view (list_item, modal), showcase_mark_done (list_item+record_header, a declarative write on the default script route — operation 'update', patch {done: true, progress: 100} — visible 'has(record.done) && record.done != true'), showcase_log_time (record_header+record_related, form), showcase_open_docs (record_more, url), showcase_recalc_estimate (record_section only, api — the Task Detail quick-actions bar's action), showcase_recalc_selection (record_more, api — declares record_more ONLY, which is what keeps it off the toolbar; objectui#3142), showcase_new_task (locations: [] — the fleet's headless specimen, read by the empty-locations probe), showcase_reopen_task (list_item only, operation 'update' patch {done: false}, visible 'has(record.done) && record.done == true' — Mark Done's mirror, so a done task's row menu offers Reopen where a not-done one offers Mark Done; a click on it is refused by the showcase_guard_task_reopen hook by design, which records-forms.script-action-hook-refusal-toast drives)", |
2069 | 2069 | "seeded tasks in both done and not-done states for the CEL visibility both-sides check" |
2070 | 2070 | ], |
2071 | 2071 | "provisioning": { |
|
2074 | 2074 | }, |
2075 | 2075 | "knownGaps": [ |
2076 | 2076 | "NO PIN COVERS A FULL CLAUSE — `automated` was dropped at revision 13, so this P1 item is hand-driven (Tier 2). The two objectui live specs it cited are adjacent: e2e/live/list-row-action-cel.spec.ts opens the first task row's menu and asserts only that at most one Mark Done renders (not both sides of acceptance[3], nor its fail-closed half), and e2e/live/action-modal.spec.ts only that the host's row Edit opens and closes a modal (one dispatch kind of acceptance[2], on no declared action). Tier 1 run #24598 scored every clause not-run on them. Re-add `automated` only with a pin that asserts a full clause.", |
2077 | | - "[CLOSED by #22030 (PR #22036, 60ccda5a24), lifted by #22039 — the gap text is rewritten to say where each location now lives] a stock showcase boot hosts all six locations on showcase_task, including the three this gap used to block. record_header and record_more: Task Detail (showcase_task_detail, the record page the console opens for any task), whose first node is a page:header. That header renders the action ids it lists, each placed by its own locations, followed by the host's Edit / Share / Delete. Inline (record_header) on a desktop viewport, where the header's default inline budget is 3 (1 on mobile; a record_header action past the budget folds into ⋯): showcase_mark_done (script, shown only while the task is not done), showcase_log_time (form) and showcase_archive_task (script, disabled until the task is done). Under the ⋯ overflow (record_more without record_header): showcase_open_docs (url), showcase_recalc_estimate (api) and showcase_recalc_selection (api). The Task Detail quick-actions bar (record_section) names its actions explicitly (actionNames: mark_done, log_time and archive_task, in examples/app-showcase/src/ui/pages/task-detail.page.ts), so showcase_recalc_estimate, which declares record_section too, is absent there by page authoring, not a missing placement (run #25817). record_related: Project Detail (showcase_project_detail, the record page for any project) → the Related tab (?tab=related), which holds the Tasks related list, a record:related_list for showcase_task through its project FK; open a project that has tasks. It is an authored node, not the synthesizer's strip: the page's tabs override still replaces that strip, and this tab puts the list back with no actions key, so its rows carry showcase_log_time beside the task's list_item actions, and its header renders the list_toolbar action (Reassign…), as in 18.1 (run #25817): that list's own toolbar placement, not an extra one. The Tasks tab beside it is the record:line_items grid, which hosts no record_related action. An expected action missing from one of these hosts is a missing placement, never blocked(fixture). The hosts were read from objectui source at pin a58626c88dc8 and from the served metadata, not from a browser render, so the first run against them is their first browser evidence", |
| 2077 | + "[CLOSED by #22030 (PR #22036, 60ccda5a24), lifted by #22039 — the gap text is rewritten to say where each location now lives] a stock showcase boot hosts all six locations on showcase_task, including the three this gap used to block. record_header and record_more: Task Detail (showcase_task_detail, the record page the console opens for any task), whose first node is a page:header. That header renders the action ids it lists, each placed by its own locations, followed by the host's Edit / Share / Delete. Inline (record_header) on a desktop viewport, where the header's default inline budget is 3 (1 on mobile; a record_header action past the budget folds into ⋯): showcase_mark_done (script, shown only while the task is not done), showcase_log_time (form) and showcase_archive_task (script, disabled until the task is done). Under the ⋯ overflow (record_more without record_header): showcase_open_docs (url) and showcase_recalc_selection (api). The Task Detail quick-actions bar (record_section) names the task's record_section set, showcase_recalc_estimate (api), in examples/app-showcase/src/ui/pages/task-detail.page.ts; no action the header draws is also in the bar, so each action renders once on the page (#27520 row 9). record_related: Project Detail (showcase_project_detail, the record page for any project) → the Related tab (?tab=related), which holds the Tasks related list, a record:related_list for showcase_task through its project FK; open a project that has tasks. It is an authored node, not the synthesizer's strip: the page's tabs override still replaces that strip, and this tab puts the list back with no actions key, so its rows carry showcase_log_time beside the task's list_item actions, and its header renders the list_toolbar action (Reassign…), as in 18.1 (run #25817): that list's own toolbar placement, not an extra one. The Tasks tab beside it is the record:line_items grid, which hosts no record_related action. An expected action missing from one of these hosts is a missing placement, never blocked(fixture). The hosts were read from objectui source at pin a58626c88dc8 and from the served metadata, not from a browser render, so the first run against them is their first browser evidence", |
2078 | 2078 | "CLOSED by the qaact-placement-specimen recipe (#26625) for acceptance[4] half (a) and acceptance[3]'s fail-closed half. A runtime-authored action is still not joined into the served object's actions[] (QA run #23163 A4: its positive control, the same probe with a location, rendered nowhere), and authoring refuses a throwing `visible` (QA run #26456), so ⛔ do not author either probe at runtime. The recipe installs both specimens through the package loader, whose actions the served object does carry. Score half (a) on qaact_no_locations and the fail-closed half on qaact_visible_throws, each only on a surface where the recipe's qaact_control renders: the list row menu and the Project Detail Related-tab row menus. Task Detail's header, ⋯ overflow and quick-actions bar list their action ids, so the control is absent there and they are no evidence for either half (the recipe's knownGaps[0]). Half (b) stays on showcase_new_task as before." |
2079 | 2079 | ] |
2080 | 2080 | }, |
|
2084 | 2084 | "record_header — showcase_mark_done / showcase_log_time in the detail title bar", |
2085 | 2085 | "record_more — showcase_open_docs / showcase_recalc_selection under the ⋯ overflow", |
2086 | 2086 | "record_related — showcase_log_time on each row of the related-list section inside a record (the Tasks related list on a showcase_project record), and on no row of the showcase_task list view", |
2087 | | - "record_section — showcase_mark_done / showcase_log_time in the Task Detail quick-actions bar (record:quick_actions resolves through the location filter)", |
| 2087 | + "record_section — showcase_recalc_estimate in the Task Detail quick-actions bar (record:quick_actions resolves through the location filter)", |
2088 | 2088 | "empty-locations semantics probe — an action with NO locations key renders on NO surface, and `locations: []` likewise (objectui#3142 collapsed the renderers onto one membership predicate, `actionRendersAt`; placement is a declaration, which is why recalc_selection has to name record_more)" |
2089 | 2089 | ], |
2090 | 2090 | "steps": [ |
|
2247 | 2247 | "date": "2026-10-31", |
2248 | 2248 | "change": "fixtures.requires[0], steps[5] and acceptance[3]'s clause name Mark Done's real predicate and list showcase_reopen_task. From QA run #27441 (W3-C3b, at c4c515ad; wave anchor #27377, wave-3 accuracy slice S1). showcase_mark_done's `visible` has been 'has(record.done) && record.done != true' since #8990 (has() guards the sparse list_item face, and != true never faults on a projected null), not '!record.done', and it is a declarative operation 'update' write on the default script route. showcase_reopen_task, the hook-refusal specimen, is its list_item-only mirror ('has(record.done) && record.done == true'), so a done task's row menu shows Reopen where the not-done one shows Mark Done; steps[5] says not to count it. Read at base a0f865491d: examples/app-showcase/src/ui/actions/index.ts. The both-sides contract is unchanged", |
2249 | 2249 | "ref": "#27441" |
| 2250 | + }, |
| 2251 | + { |
| 2252 | + "revision": 18, |
| 2253 | + "date": "2026-11-01", |
| 2254 | + "change": "The Task Detail page draws each task action once (#27520 row 9: the walkthrough saw Mark Done, Log Time and Archive both in the header and as a button row in the body). The quick-actions bar now carries the task's record_section set alone, showcase_recalc_estimate, which declares record_section only, and Mark Done, Log Time and Archive drop record_section. fixtures.requires[0], the record_section variant and knownGaps[1] re-pointed: record_section is still hosted on showcase_task, by Recalculate Estimate in the bar, and the ⋯ overflow keeps open_docs (url) and recalc_selection (api). Read from the examples source at this branch, not a browser run; no clause changed", |
| 2255 | + "ref": "#27520" |
2250 | 2256 | } |
2251 | 2257 | ], |
2252 | 2258 | "enumSource": { |
|
0 commit comments