Repository navigation
feat(example-showcase): host record_header / record_more / record_related for showcase_task - #22036
Merged
objectstack-fleet[bot] merged 3 commits intoOct 6, 2026
Conversation
…ated for showcase_task Task Detail (kind 'full') now composes a page:header listing the task's record_header / record_more action ids, so the title bar and its overflow menu exist. Project Detail keeps its record:line_items Tasks tab and adds a Related tab with the Tasks record:related_list, whose rows carry the record_related actions. A new showcase test pins both hosts. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
…nd the FK declaration Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Oct 6, 2026
Picks up the checkout-wall fix (099a94d) so the cancelled Type Check source-gates job can run to completion. Claude-Session: https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw Co-authored-by: Claude <noreply@anthropic.com>
objectstack-fleet
Bot
deleted the
claude/issue-22030-showcase-record-action-hosts
branch
October 6, 2026 21:19
This was referenced Oct 6, 2026
akarma-synetal
pushed a commit
to akarma-synetal/framework
that referenced
this pull request
Oct 7, 2026
…the showcase hosts record_header / record_more / record_related (objectstack-ai#22040) Fixes objectstack-ai#22039 Clause-②: no The showcase change carded as objectstack-ai#22030 landed as PR objectstack-ai#22036 (`60ccda5a24`). It hosts `record_header`, `record_more` and `record_related` for `showcase_task` on stock showcase pages. This PR lifts the row-7 fixture knownGap on `records-forms.action-location-matrix` that parked those three locations, and A3's url / api dispatch legs, on that card. It is a checklist-only diff: one item in `docs/qa/platform-checklist/areas/records-forms.json`, no other item, no code. ## What changed (item `records-forms.action-location-matrix`, revision 8 to 9) | Key | Before | After | |---|---|---| | `revision` | 8 | 9 | | `fixtures.knownGaps[1]` | "the showcase hosts NO surface for three of the six locations on showcase_task …"; score them blocked(fixture); park on objectstack-ai#22030 | Opens with a closed marker citing objectstack-ai#22030 / PR objectstack-ai#22036 / `60ccda5a24` and this card, then says where each location now lives on a stock boot (below) | | `steps[1]` | surfaces listed as "a not-done task's detail title bar / its ⋯ menu / a related-list section", plus "A location with no hosting surface at this fixture (record_header / record_more / record_related) is recorded blocked(fixture)" | Names each host: the Task Detail title bar, that title bar's ⋯ menu, and the rows of the Tasks related list on Project Detail's Related tab, "not the Tasks tab's line-items grid". The blocked(fixture) sentence is gone | | `acceptance[0].clause` | "… a parent record page that renders the synthesized Tasks related list …" | "… renders the Tasks related list …" (one word dropped) | | `acceptance[0].verify` | "At this fixture record_header, record_more and record_related are not hosted: record those three blocked(fixture), never as missing placements" | "The stock fixture hosts all six (fixtures.knownGaps names the page and tab …): an expected action absent from its host is a missing placement, never blocked(fixture)" | | `acceptance[2].clause` | "The url (open_docs) and api (recalc_selection) legs live on record_more and share its fixture gap: record them blocked(fixture) with it, never as dispatch failures" | "The url (open_docs) and api (recalc_selection) legs live on record_more, under the ⋯ overflow of the Task Detail title bar" | | `history` | 8 entries | plus one: revision 9, 2026-10-06, ref `objectstack-ai#22039`, citing objectstack-ai#22030 / PR objectstack-ai#22036 | `fixtures.knownGaps[0]` (the objectui-pinned automation) is byte-identical. No other key and no other item changed. A structural diff of all 43 items against `60ccda5a24` shows exactly one changed item. ### The rewritten knownGap: where each location lives - **`record_header` / `record_more`: Task Detail** (`showcase_task_detail`, the record page the console opens for any task). Its first node is a `page:header`. The header renders the action ids it lists, each placed by its own `locations`, and the host's Edit / Share / Delete come after them. - Inline on a desktop viewport: `showcase_mark_done` (script, shown only while the task is not done), `showcase_log_time` (form) and `showcase_archive_task` (script, disabled until done). - Under the ⋯ overflow: `showcase_open_docs` (url), `showcase_recalc_estimate` (api) and `showcase_recalc_selection` (api). - The default inline budget is 3 (1 on mobile), and a `record_header` action past it folds into ⋯. Read from the `page:header` renderer at the objectui pin `a58626c88dc8`. The knownGap names this so that a runner on a narrow viewport does not score a folded action as an extra `record_more` placement. - **`record_related`: Project Detail** (`showcase_project_detail`), on the **Related tab** (`?tab=related`). The tab holds the Tasks related list, a `record:related_list` for `showcase_task` through its `project` FK. As PR objectstack-ai#22036 noted, this is an authored node, not the synthesizer's strip. The page's `tabs` override still replaces that strip, and the tab puts the list back with no `actions` key, so its rows carry `showcase_log_time` beside the task's `list_item` actions. The Tasks tab next to it is the `record:line_items` grid, which hosts no `record_related` action. - A missing action on any of these hosts is now a missing placement, not blocked(fixture). The knownGap says the hosts were read from objectui source and served metadata, not from a browser render, because PR objectstack-ai#22036 left the browser render NOT MEASURED. The first run against these hosts will be their first browser evidence. ### Scope reading, declared The dispatch scopes edits to `fixtures.requires`, `steps` and acceptance `verify` lines that still send the runner to a surface that does not host the leg. Two of the lines above are acceptance `clause` texts, not `verify` lines. Revision 7 added the gap's blocked(fixture) instructions in five places: knownGaps[1], step 2, clause 1, clause 1's verify, and clause 3. The item diff between `ff29410ed2` and `18c7dfd2e6` shows them. Clause 3's last sentence parks the url / api legs by itself, so leaving it would keep A3 parked after the lift. Clause 1's "synthesized" sends a runner to look for a strip that the page's `tabs` override removes. The edit to each clause is the minimum that undoes revision 7's gap text. Nothing else in either clause changed. `fixtures.requires` is unchanged: it describes the fleet and does not point the runner at any surface. ## Verification (head `d99f1f57ee`, after the final commit) - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on the actual diff derived 13 commands. The list is the same at both commits. Each was run with its exit code recorded before any pipe, and all 13 exited 0. `--ran`: "13 derived famil(ies) accounted for — 13 run, 0 NOT-MEASURED (a DERIVED zero — all 13 recorded an exit code and none of them is 3)". - `check:platform-checklist`: "OK — 15 areas, 276 items (272 active, 2 planned) …". - `check:doc-authoring`, `check:cross-package-test-inputs` and `check:nul-bytes` are green. - On the first commit, `check:doc-formula-expressions` answered PREREQUISITE NOT MET (exit 3: `@objectstack/formula` and `@objectstack/lint` were unbuilt). Both were then built under `os-verify-lock.sh` (VERDICT command-exit 0), and the gate ran green at both commits. - **The two checklist-reading package tests** run on the final head. These are the only tests declared as reading these files: `scripts/cross-package-test-inputs.mjs` names `docs/qa/platform-checklist/areas/*.json` for plugin-auth and `docs/**` for rest, and nothing else. - `pnpm --filter @objectstack/plugin-auth exec vitest run --maxWorkers=2 src/checklist-refusal-envelope-consistency.test.ts`: exit 0, 1 file / 5 tests passed. - `pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/meta-state-route-doc-spelling.test.ts`: exit 0, 1 file / 8 tests passed. - **Lint:** `eslint --no-inline-config --format json` on the changed file returns 1 file and 0 errors. The one message is "File ignored because no matching configuration was supplied". No block in `eslint.config.mjs` covers `.json` under `docs/`, so this diff cannot move any lint verdict. The full `pnpm lint` run is CI's. - **Changeset:** 69 published workspace manifests. None has a `files[]` entry naming `docs/qa` or the checklist (0 hits). Positive control: all 69 name `dist` (69 hits). The path is outside every package directory, so this diff publishes nothing. Hence `skip-changeset`. - **Typecheck / package tests:** no package source changed, so neither is owed locally. CI's Test Core reruns plugin-auth and rest because their declared inputs moved. ## Acceptance notes - **The empty-locations probe cannot discriminate on two authored-list surfaces.** The Task Detail `page:header` renders only the ids it lists (objectui `containers.tsx`, `resolvedHeaderActions`). The `record:quick_actions` bar is also an explicit `actionNames` list. So the step-7 probe action, and `showcase_new_task`, are absent from the record header, the ⋯ overflow and the quick-actions bar because those lists leave them out. That absence is decided before any `locations` predicate runs. The probe's verdict therefore rests on the list toolbar, the row menu and the related-list rows. The quick-actions half predates this card. The header half is new, because before PR objectstack-ai#22036 the header did not exist. Not filed: this is an item-design observation, not a runtime defect, a contract violation or an authoring trap. Carrier: none. - `fixtures.requires[0]` and clause 4 spell mark_done's predicate as `'!record.done'`. The fixture's actual predicate is `has(record.done) && record.done != true`. `requires[0]` also leaves out `showcase_recalc_estimate` and `showcase_archive_task`, which the header now carries. Neither points the runner at a wrong surface, so both are outside this card's edit rule and are left as they are. Carrier: none. - NOT MEASURED: the browser render of the new hosts, as in PR objectstack-ai#22036. No console bundle is built in this checkout. The knownGap says so. ## Labels `skip-changeset`: checklist-only diff, measured above. --- _Generated by [Claude Code](https://claude.ai/code/session_01VF48aw8RPG6wzDnMgp6rtw)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
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.
Fixes #22030
Clause-②: no
The showcase now hosts the three record action locations for
showcase_taskon stock pages, sorecords-forms.action-location-matrixA1 (record_header / record_more / record_related) and A3 (the url and api dispatch from the ⋯ overflow) can be run on a stock showcase boot. This is a fixture change inexamples/app-showcaseonly: no product code, no checklist edit, and no new action.What changed
showcase_task)record_headershowcase_task_detail): a newpage:headernode, first in the pageshowcase_mark_done(script),showcase_log_time(form),showcase_archive_task(script), as inline buttonsrecord_moreshowcase_open_docs(url),showcase_recalc_estimate(api),showcase_recalc_selection(api)record_relatedshowcase_project_detail): a newrelatedtab with the Tasksrecord:related_listshowcase_log_timeon each row (beside thelist_itemactions)src/ui/pages/task-detail.page.ts: addspage:headerwithactionsset to the task's sixrecord_header/record_moreaction ids, which is the set the synthesized header would carry. Notitle, so the heading still comes from the record. The host's Edit / Share / Delete (order 100 to 120) still append after the authored actions.src/ui/pages/project-detail.page.ts: keeps thetaskstab and itsrecord:line_itemsgrid unchanged. Adds a third tab,related, withrecord:related_listforshowcase_taskthroughproject. It has noactionskey, so the rows carry the host bridge's actions.src/ui/actions/index.ts: comment only. The note onshowcase_reopen_tasksaid the Task Detail page "renders no header action bar". That is no longer true, so the comment now points to the header's id list and to the pin that holds it.test/record-action-location-hosts.test.ts(new, 9 cases) pins both hosts on the page the console picks for each object. It also holds the authored lists equal to the declarations they copy: the header ids against the task'srecord_header/record_moreset, and the related list'stitle/columnsagainst the FK'srelatedListTitle/relatedListColumns.test/project-detail-tabs.test.ts: the tab strip is nowdetails, tasks, related(3 items, was 2).Why this shape (measured at the objectui pin
a58626c88dc8)usePageAssignmentrenders the FIRSTtype: 'record'page bound to an object, in declaration order, so a second page for either object would never be reached.kind: 'full'page renders only what it declares (objectui#7298 ruling,RecordDetailView). With nopage:headernode, the page had no title bar.PageHeaderProps.actionsis spec-declared (z.array(z.string()), "Action IDs to show in header"). The renderer (containers.tsx,resolvedHeaderActions) looks the ids up in the object's metadata and places each one by itslocations:record_headeractions go inline, and an action that declaresrecord_morewithoutrecord_headeralways goes under ⋯.os validate(validate-action-name-refs) checks the same ids.tabsslot is a full replacement, so overriding it removed the synthesized related-list strip.showcase_task.projectis the task's only parent relationship.RelatedRecordActionsBridgewraps the whole record-page body, authored or synthesized, and placeslist_item+record_relatedon the rows of anyrecord:related_listunder a parent record (ROW_LOCATIONS_IN_RECORD). For an authored node with noactions, the record-related-list renderer leaves those host actions untouched.tabstodetails, which would keep the synthesized strip itself. It would remove the authoredpage:tabsthat the showcase 的 project-detail 页在page:tabs上授权items[].key,renderer 读的是items[].value—— 两个 tab 的稳定 URL token 从未生效 #5776 pin exists for, drop the?tab=taskstoken, and move the editable grid into the Details tab.record:related_listnode, the same component and the same bridge as the synthesizer's output, withtitle/columnscopied from the FK (only the synthesizer readsrelatedListTitle/relatedListColumns). The follow-up knownGap lift should say "the Tasks related list".Guard:
record:line_itemsstayedIt was not removed from project-detail.
git grep -n 'record:line_items'overdocs/qa/platform-checklistandexamples/app-showcase/testat HEAD:docs/qa/platform-checklist/areas/records-forms.json:1547and:1661(this item's knownGap and its revision-7 history row, both describing the gap)examples/app-showcase/test/project-detail-line-items.test.ts:13, :22, :56, :89(the finding(showcase): project-detail'srecord:line_itemsblock keys its five columns asfield, while the line-items grid bindsname— the Tasks grid renders empty cells #21142 column pin, still green)examples/app-showcase/test/record-action-location-hosts.test.ts:20(this PR's docblock)Verification (HEAD
3ae68e530c)pnpm --filter @objectstack/example-showcase testexit 0, 33 files / 408 tests.validateandtypecheck:pnpm --filter @objectstack/example-showcase validateexit 0 ("Validation passed"). None of its 72 warnings names either page,showcase_task.*orrelatedList*.typecheckexit 0;tsc --listFilesincludes both pages and both test files.scripts/ablation-replace.mjsWRAP mode, every leg restored with blob == HEAD and an emptygit diff HEAD):page:card: 4 failed / 5 passed;record:highlights: 4 failed / 5 passed (re-run after hardening two cases that passed vacuously the first time, 2 failed / 7 passed);record_headeradded toshowcase_reopen_taskwithout adding it to the header: 1 failed, the set-equality case, namingshowcase_reopen_task.node scripts/pm/dispatch-gates.mjs --commandson the actual diff derived 42 commands. All 42 ran, each with a recorded exit code, and all exit 0.--ran: "42 derived famil(ies) accounted for — 42 run, 0 NOT-MEASURED (a DERIVED zero)".check:dual-build-cjs-loadsfirst answered PREREQUISITE NOT MET (8 packages unbuilt); it was re-run after building them and answered exit 0. Named in the dispatch and green:check:page-declaration-shape,check:examples-live-imports,check:i18n-coverage("none new"),check:react-page-adapter-contract,check:cross-package-test-inputs,check:org-identifier,check-undeclared-dep-imports(+--self-test),check:nul-bytes.--no-inline-config --format jsonover the 5 changed files: 5 files, 0 errors, 0 warnings. These files fall under the config block forexamples/**/*.{ts,tsx,mts,cts}. The config never enables type-aware linting (noparserOptions.project), so this diff cannot change the verdict on any untouched file. The fullpnpm lintrun is CI's.pnpm dev:showcase -- --freshon a random port, torn down afterwards): from the servedGET /api/v1/meta/pagelist andGET /api/v1/meta/object/showcase_task:showcase_project_detail, thenshowcase_task_detail, each the first for its object;record_header/record_moreset. Three are inline-eligible (script, form, script) and three are overflow-only (url, api, api);details, tasks, related, withrecord:line_itemskept;record_relatedon the task isshowcase_log_time, and a seeded project has 2 tasks.Acceptance notes
records-forms.action-location-matrixis a follow-up that cites this PR, after this PR and docs(qa): park the 24 partial-coverage gaps of the 17.7 pre-release runs — 2 recipes, 9 pins, 6 re-pointed clauses, 7 recorded knownGaps #22029 are both onmain. docs(qa): park the 24 partial-coverage gaps of the 17.7 pre-release runs — 2 recipes, 9 pins, 6 re-pointed clauses, 7 recorded knownGaps #22029 holdsrecords-forms.json, and this PR does not touch it.packages/spec/src/ui/component.test.tscitestask-detail.page.ts:40and:76in comments. Both were already stale at the base (:76readlocation: 'record_section'), and this diff shifts them by a further 35 lines. Comment drift only: noted here, not filed. Carrier: none.Relatedand list titleTaskshave no zh-CN entry. The same is true of the existingDetails/Taskstab labels: slot content is outside the extractor's walk, andcheck:i18n-coveragereports none new.showcase_task.project's comment ("Tasks are added later from the Project DETAIL page's Tasks related list") was untrue onmainand is true again with this PR.Labels
skip-changeset:@objectstack/example-showcaseisprivateand publishes nothing.Generated by Claude Code