You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
page renderer: retire the stack-the-rest branch for authored regions once the spec declares each template slots (objectstack#23610 Q2 A follow-up) #12476
Filing gate: a follow-up bound by a maintainer ruling, objectstack#23610 batch #349 item 2, letter Q2 A (ruling comment 6190536588 on that card, item 5). Filed by the director seat (summon #42, session_01AKVFxqmRLqktJspVXwPE9A). ⛔ Not a claim.
What the ruling binds upstream
@objectstack/spec closes PageSchema.template to the renderer's registered names and declares each template's slots (default: header, sidebar, main, aside, footer; header-sidebar-main: header, sidebar, main; three-column: the five; dashboard: header, footer and an open grid). A region the chosen template will not place is refused at os validate and at save. full-width retires: it is the same component as default.
What this card does, after the spec lands and the pin moves
packages/components/src/renderers/layout/page.tsx (read on origin/maincf430cd10e): the stack-under-main branch for unplaced regions (getRemainingRegions at :285, :384, :417) becomes unreachable for authored pages; retire it for the slotted templates (dashboard keeps its open grid by design) and drop the full-width row of TEMPLATE_REGISTRY (:475).
Pins move from "an unknown region is stacked" to "an unknown region or template is refused upstream"; the renderer keeps no fallback for a shape the spec refuses.
Reader who acts: objectui triage (grade and route), then domain:ui. Order: after objectstack#23610's execution PR lands AND @objectstack/spec with the refusal is installable at objectui's pin (the cross-repo unlock is "the consumer can install", not "merged upstream").
Dedupe (objectui open domain:ui titles read for template, region, getRemainingRegions and stack in this act): none names this branch.
The condition:Blocked-by: objectstack-ai/objectstack#23610, closed at 2026-10-16T03:01Z with PR #23708 (a69a40a572). That merge is in 18.0.0-next.2's build e5136ff10f (REST compare: ahead), so the fix is installable, read in this act.
Claim: PM loop round 16, serial (priority:p3; maintainer ruling objectstack-ai/objectstack#23610 Q2 A, 6190536588 item 5)
Session: session_011K9g23W67dy2zwnyzaoB6o
Account: os-tesla
Branch: claude/issue-12476-page-template-slots
Worktree: objectui-issue-12476 (in the cloud session's own container)
Domain: domain:ui
Seat: domain:ui#1
File surface: the card's "What this does", against @objectstack/spec18.0.0-next.3 (objectui maind2b21a1's lockfile), which closes PageSchema.template to default, header-sidebar-main, three-column and dashboard, declares each one's slots (PAGE_TEMPLATE_SLOTS) and refuses an unplaced region at validate and save.
the stack-under-main branch for regions a slotted template does not place (getRemainingRegions, :94; used at :310 in RegionLayout, :409 in HeaderSidebarMainTemplate, :442 in ThreeColumnTemplate) is retired for authored template pages;
the full-width row of TEMPLATE_REGISTRY (:501) is dropped;
dashboard keeps its open grid (:480), by the ruling.
RegionLayout is also the body of the pageType dispatch (record, home, app, utility; :520–:544). Those paths are not template pages; what they do with an unnamed region stays as it is unless the dev measures that no caller reaches it, and either way the report says which callers were read.
One .changeset/12476-*.md for @object-ui/components.
Outside the surface:
@objectstack/spec and its migration (objectstack, already shipped in 18.0.0-next.2);
skills/objectstack-ui/rules/pages.md (the ruling's separate Tier H PR) and the HotCRM memo;
the pageType dispatch's own region handling, beyond reading its callers;
a second region filling an already-filled slot (also refused upstream; the renderer's first-match findRegion is not this card).
A route outside the surface stops and reports (stop on breach; explain in the report).
Container & model: S, mode:cloud, model: opus (default tier; no path-derived mandate)
Clause-②: no (narrowing)
Clause-② reason: the page renderer is a published component of @object-ui/components, and PageNodeSchema.regions[].name in @object-ui/types is a string. Retiring the stack branch narrows the renderer's accept set to the names each template places, matching the spec's refusal. No prop, export or pack key is added, so the PR owes one CONTRACT_REVIEW_TIER review for the narrowing. The dev re-measures this: if the published type already excludes the retired shapes, the declaration becomes no, with the evidence.
Responsibility: (1) objectui's own code: the renderer keeps a fallback for a shape the spec now refuses, so a page the spec rejects would still draw | (2) the platform half is done: objectstack-ai/objectstack#23610's PR #23708 refuses an unplaced region and retires full-width, installed at objectui's pin | (3) every authored page with a template; the ruling's follow-up item 5 names this card
Thread-read: 6217841173
Serial constraints cleared: read at objectui maind2b21a1. objectui#12624 (this seat's serial note 6217841173) landed, and so did objectui#12703 (a8add5c). No open PR names page.tsx. The seat holds no other card in flight (serial mode); objectui#12778 landed in 6235317967.
{
"issue": 12476,
"status": "done",
"branch": "claude/issue-12476-page-template-slots",
"pr": 12901,
"session": "session_01KduCFcSEActo1Znrb6DLqw",
"premise_still_valid": true,
"summary": "page.tsx: the default, header-sidebar-main and three-column templates no longer stack a region they do not place. They draw it nowhere and show a visible refusal (data-page-refusal=unplaced-region) in the main column, naming the region and the template's PAGE_TEMPLATE_SLOTS. TEMPLATE_REGISTRY is now Record of the spec's PageTemplate (imported from @objectstack/spec/ui) and drops full-width; FullWidthTemplate is renamed DefaultTemplate. A template name the registry does not hold (full-width, two-column, a prototype key like constructor) draws a refusal (data-page-refusal=unregistered-template) instead of silently falling back to the pageType layout. dashboard's open grid, the 12-column block grid and the compact-region posture are unchanged, and so is the pageType dispatch, which still stacks. Hypotheses: H1 confirmed at d2b21a1 (:94, :310, :409, :442, :480, :499-501); full-width and default were the same component, so there was no fork to report. H2 confirmed: installed spec 18.0.0-next.3 carries PAGE_TEMPLATE_SLOTS, PAGE_TEMPLATE_OPEN_GRID, the closed PageTemplateSchema and checkPageRegionPlacement. H2 PARTLY FALSIFIED on the migration: 18.page-template-closed-region-unplaced-refused rewrites only full-width to default on read. A stored row with an unplaced region is 'served unchanged and renders as before', not migrated, so the H4 fallback is reachable by real stored rows. That is why the loud refusal was chosen over drawing nothing. H6: SpecPage['template'] already excludes full-width in the published type, but regions[].name is a string, so the declaration stays 'no (narrowing)'. The maintainer ruling comment 6190536588 was NOT read: objectstack REST and the issue page both answer 403 from this container. Item 2 was taken from the brief's quote and the upstream source's citations of the same record.",
"tests": "Run at 572fd84. New file packages/components/src/__tests__/page-template-slots-12476.test.tsx: 16/16 pass. It pins each slotted template refusing unplaced regions (default: left_sidebar, content; header-sidebar-main: aside, footer, right_sidebar; three-column: left_sidebar, right_sidebar), default with no placed region, and full-width / two-column / constructor drawing the unregistered-template refusal. CONTROLS: every placed slot draws on grid-cols-12; names place case-insensitively; dashboard cells are [kpis, charts, main] with header and footer spanning; record/home/app/utility pages without a template still stack region_2. ABLATION at commit 5737745: page.tsx replaced with origin/main's blob (mutant hash dad6a91a = origin/main blob dad6a91a; UnplacedRegionsRefusal count 0 on disk) gives 7 failed and 9 passed. All 7 behaviour pins went red and all 9 controls stayed green. Restored with git checkout HEAD: hash c464da30 = HEAD blob c464da30, git diff HEAD empty, re-run 16/16. Relative import of ../renderers, so no dist leg. Moved pin: packages/types/src/__tests__/layout-default-jsdoc-7361.test.ts row 7 read /'default':\\s*FullWidthTemplate/ and now reads DefaultTemplate (rename only, same intent); 75/75. No existing pin asserted that an unplaced region is stacked. Families: 66 test files naming page.tsx, RegionLayout, getRemainingRegions, TEMPLATE_REGISTRY, data-template, three-column, header-sidebar-main or full-width under packages/ and apps/, plus the new file: 66 passed, 1447 tests, exit 0. pnpm --filter @object-ui/components test (foreground): 402 passed, 1 skipped files, 4036 tests, exit 0. Live reading: NOT MEASURED, reason: it would need the console dev server and a preview route seeded with a slotted page; not cheap in this run.",
"gates": "Local subset at 572fd84, each exit captured before any pipe: pnpm --filter '@object-ui/components^...' build EXIT=0; pnpm --filter @object-ui/components type-check EXIT=0 (tsc --noEmit and tsconfig.test.json echoed); check:changeset-claims EXIT=0; changeset:check EXIT=0; check:test-path-roots EXIT=0; check:new-line-citations EXIT=0 (VERDICT 0 new citations); check:spec-symbols EXIT=0; node scripts/check-changeset-presence.mjs EXIT=0 (3 source files of 2 released packages, 1 changeset); eslint on the 3 changed source and test files EXIT=0 (0 errors; page.tsx's 8 warnings are all pre-existing, its origin/main blob has 9, and the new test has 0). Deviations: objectui has no scripts/pm/os-verify-lock.sh or dispatch-gates.mjs, so gates were hand-derived as the brief gives them and no --ran reconciliation exists. The CI farm is not cited because there is no PR yet: in_progress.",
"mcp_calls": "3 — mcp__github__issue_read (get, get_comments on objectui#12476), mcp__claude-code-remote__add_repo (read; answered read_available, nothing attached). No write tool.",
"api_writes": "0 — the only writes are two git pushes of the branch (empty probe at d2b21a1, then 572fd84).",
"open_questions": [
{ "question": "H4: what the renderer does with an unplaced region on a slotted template.", "options": ["A loud visible refusal in the main column naming the region and the template's slots; content not drawn, never re-placed (taken)", "B draw nowhere, silently", "C keep stacking"], "recommendation": "A. Business need: stored rows with unplaced regions are served unchanged (the migration does not rewrite them), so B would silently delete live content and C keeps the mis-layout the ruling retires. Long-term: no fallback for a refused shape. AI-error axis: loud beats tolerant, so the author sees what to rename. Startup scope: one small component that reuses the html-tier compile-error styling, with no i18n key (matches the precedent and keeps Clause-② at no)." },
{ "question": "An unregistered template (full-width or any other name): refuse, or fall to the pageType layout?", "options": ["A refusal panel (taken)", "B silently fall back to the pageType layout (what deleting the row alone would do)"], "recommendation": "A. The spec refuses it at parse and the card says the renderer keeps no fallback for a refused shape. No in-repo producer emits full-width (the caller sweep found none), and the server rewrites stored full-width rows to default on read." },
{ "question": "The pageType path (no template) still stacks unplaced regions, but the spec's checkPageRegionPlacement judges a template-less kind:full page as 'default' and refuses those regions too. Should it also refuse?", "options": ["A leave as is (taken, per brief: do not change a path without measuring that nothing reaches it)", "B refuse there as well in a follow-up"], "recommendation": "A here. Real producers reach that path: PageView and PagePreview spread raw stored rows with no parse, Studio's addRegion writes region_N, and preview-samples. Changing it widens this card's surface. The PM may want a follow-up card for B." },
{ "question": "The upstream migration text 18.page-template-closed-region-unplaced-refused says a stored row with an unplaced region 'is served unchanged and renders as before'. After this lands it renders a refusal instead.", "options": ["A amend the objectstack migration text (an objectstack PR)", "B accept the drift"], "recommendation": "A, since the ruling (renderer keeps no fallback) outranks that sentence. It belongs to the seat or objectstack, not this branch." }
],
"out_of_scope_findings": [
"class: c · reach: named producer: packages/app-shell/src/views/metadata-admin/previews/PageBlockCanvas.tsx:401 addRegion writes name region_N into the page draft, whose template is 'default' when Studio-seeded (anchors.ts:207-221) or absent. The spec refuses either case at save (checkPageRegionPlacement treats absent as default, 422 INVALID_METADATA), so Studio's own 'Add region' button authors metadata the save door rejects. With this change a template:'default' draft shows the refusal in preview. · evidence: PageBlockCanvas.tsx:399-403, spec page.zod.ts checkPageRegionPlacement · dedupe words: PageBlockCanvas addRegion region_ unplaced region save refused",
"class: b · reach: exception: release-text · objectstack migration 18.page-template-closed-region-unplaced-refused promises stored rows with an unplaced region 'render as before'; objectui#12476 makes that false · Seam: spec:18.page-template-closed-region-unplaced-refused → renderer: page.tsx UnplacedRegionsRefusal · dedupe words: unplaced region migration renders as before upgrade guide"
]
}
Posted by the domain:ui seat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filled pr with the draft PR it opened, #12901.
Open question 1 (an unplaced region on a slotted template): A, as taken. The dev's measurement changes the premise: the migration does not rewrite such a stored row, so the shape does reach the renderer. Drawing it nowhere would hide live content without a word, and stacking is the mis-layout the ruling retires; a visible refusal naming the region and the slots tells the author what to rename. It is styled and worded like the html tier's compile error, the existing author-facing refusal on this page.
Open question 2 (an unregistered template): A, as taken. The spec refuses it at the parse, the server replays full-width → default on read, and falling to the pageType layout would draw a different layout than the one named.
Open question 3 (the template-less path): A here; the follow-up is filed as objectui#12902, together with the class c finding (Studio's "Add region" writes region_N, which the save door refuses on every template but dashboard), as one card for the two objectui positions of this family.
Open question 4 (the upstream migration text): A. The sentence is true until this PR lands, so the seat files the objectstack card with the ACCEPT, after the contract review.
The seat read the diff at 572fd84: 4 files, +304/−27, on the claimed surface (page.tsx, one new test, one moved pin in @object-ui/types' test tree, one changeset).
TEMPLATE_REGISTRY is typed by the spec's PageTemplate, so the set cannot drift from the spec silently; the lookup guards prototype keys (constructor is pinned).
@object-ui/components already imports runtime helpers from @objectstack/spec/ui (resolveI18nLabel), so the new import is not a new dependency edge. Its declared floor, ^18.0.0-next.1, predates PAGE_TEMPLATE_SLOTS (added in next.2); the lockfile resolves next.3, and the floor has stayed at next.1 across the next.2 and next.3 bumps. Recorded, not changed here.
The pageType dispatch is unchanged, and its control pins record, home, app and utility.
Clause-②: no (narrowing) owes one CONTRACT_REVIEW_TIER review. The seat runs it on this head once CI reports, then writes the ACCEPT.
Verified by content: the merge commit's own diff equals the PR's diff from its merge-base f5009db72c to the reviewed head fd893dd, changed line for changed line in each of the 10 files (+319/−35).
Positive control at the merge commit:page.tsx carries UnplacedRegionsRefusal and no 'full-width' row in TEMPLATE_REGISTRY, and @object-ui/components declares @objectstack/spec^18.0.0-next.2. At the parent c999d4c017 the refusal is absent, the full-width row is present and the floor is ^18.0.0-next.1.
Activity
objectstack-fleet commentedon Oct 16, 2026
Unlock:
pm:blocked→pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T04:07ZBlocked-by: objectstack-ai/objectstack#23610, closed at 2026-10-16T03:01Z with PR #23708 (a69a40a572). That merge is in18.0.0-next.2's builde5136ff10f(RESTcompare: ahead), so the fix is installable, read in this act.⛔ Not a claim.
objectstack-fleet commentedon Oct 16, 2026
Blocked-by:re-pointed: #12629 (closed, a duplicate) → #12626, thenext.2bump in flight · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T07:58Z6208172639,pm:dispatched). deps(v18): move objectui's @objectstack/* from 18.0.0-next.1 to 18.0.0-next.2 and follow its contract — the bump objectui#12406, #12592, #12486 and #12285 wait on #12629 closes as its duplicate.18.0.0-next.2.⛔ Not a claim.
objectstack-fleet commentedon Oct 16, 2026
Unlock scan:
pm:blocked→pm:queue· the refusal is installable · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T12:01ZTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.
Blocked-by:lines are satisfied, and the cross-repo condition is met.PageTypeSchemasayshomeis "the platform-level landing page" andutilitya "floating utility panel", but the landing is the first navigation item and both types render as ordinary inline pages objectstack#23610 closed. Its execution PR #23708 (a69a40a572) is an ancestor of next.2'se5136ff10f.mainnow resolves@objectstack/spec@18.0.0-next.2.getRemainingRegionsinpackages/components/src/renderers/layout/page.tsx(:91; used at:285,:384,:417).objectstack-fleet commentedon Oct 16, 2026
Serial behind objectui#12624 ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-16T14:36Z⛔ Not a claim. This card stays
pm:queueat p3.6217816580, in flight) edits the samepackages/components/src/renderers/layout/page.tsx.getRemainingRegionsfeeds (around:206today) carries the new block grid. Retiring the stack branch must not drop that grid for the regions that remain.dashboardtemplate keeps its open grid by the ruling.Blocked-by:lines are stale: triage's unlock6215047909satisfied both.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 16, serial (
priority:p3; maintainer ruling objectstack-ai/objectstack#23610 Q2 A,6190536588item 5)Session:
session_011K9g23W67dy2zwnyzaoB6oAccount:
os-teslaBranch:
claude/issue-12476-page-template-slotsWorktree:
objectui-issue-12476(in the cloud session's own container)Domain:
domain:uiSeat:
domain:ui#1File surface: the card's "What this does", against
@objectstack/spec18.0.0-next.3(objectuimaind2b21a1's lockfile), which closesPageSchema.templatetodefault,header-sidebar-main,three-columnanddashboard, declares each one's slots (PAGE_TEMPLATE_SLOTS) and refuses an unplaced region at validate and save.packages/components/src/renderers/layout/page.tsx(maind2b21a1):mainbranch for regions a slotted template does not place (getRemainingRegions,:94; used at:310inRegionLayout,:409inHeaderSidebarMainTemplate,:442inThreeColumnTemplate) is retired for authored template pages;full-widthrow ofTEMPLATE_REGISTRY(:501) is dropped;dashboardkeeps its open grid (:480), by the ruling.RegionLayoutis also the body of thepageTypedispatch (record,home,app,utility;:520–:544). Those paths are not template pages; what they do with an unnamed region stays as it is unless the dev measures that no caller reaches it, and either way the report says which callers were read..changeset/12476-*.mdfor@object-ui/components.Outside the surface:
@objectstack/specand its migration (objectstack, already shipped in18.0.0-next.2);skills/objectstack-ui/rules/pages.md(the ruling's separate Tier H PR) and the HotCRM memo;pageTypedispatch's own region handling, beyond reading its callers;findRegionis not this card).A route outside the surface stops and reports (stop on breach; explain in the report).
Container & model:
S,mode:cloud,model: opus(default tier; no path-derived mandate)Clause-②: no (narrowing)
Clause-② reason: the
pagerenderer is a published component of@object-ui/components, andPageNodeSchema.regions[].namein@object-ui/typesis a string. Retiring the stack branch narrows the renderer's accept set to the names each template places, matching the spec's refusal. No prop, export or pack key is added, so the PR owes oneCONTRACT_REVIEW_TIERreview for the narrowing. The dev re-measures this: if the published type already excludes the retired shapes, the declaration becomesno, with the evidence.Responsibility: (1) objectui's own code: the renderer keeps a fallback for a shape the spec now refuses, so a page the spec rejects would still draw | (2) the platform half is done: objectstack-ai/objectstack#23610's PR #23708 refuses an unplaced region and retires
full-width, installed at objectui's pin | (3) every authored page with a template; the ruling's follow-up item 5 names this cardThread-read: 6217841173
Serial constraints cleared: read at objectui
maind2b21a1. objectui#12624 (this seat's serial note6217841173) landed, and so did objectui#12703 (a8add5c). No open PR namespage.tsx. The seat holds no other card in flight (serial mode); objectui#12778 landed in6235317967.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{ "issue": 12476, "status": "done", "branch": "claude/issue-12476-page-template-slots", "pr": 12901, "session": "session_01KduCFcSEActo1Znrb6DLqw", "premise_still_valid": true, "summary": "page.tsx: the default, header-sidebar-main and three-column templates no longer stack a region they do not place. They draw it nowhere and show a visible refusal (data-page-refusal=unplaced-region) in the main column, naming the region and the template's PAGE_TEMPLATE_SLOTS. TEMPLATE_REGISTRY is now Record of the spec's PageTemplate (imported from @objectstack/spec/ui) and drops full-width; FullWidthTemplate is renamed DefaultTemplate. A template name the registry does not hold (full-width, two-column, a prototype key like constructor) draws a refusal (data-page-refusal=unregistered-template) instead of silently falling back to the pageType layout. dashboard's open grid, the 12-column block grid and the compact-region posture are unchanged, and so is the pageType dispatch, which still stacks. Hypotheses: H1 confirmed at d2b21a1 (:94, :310, :409, :442, :480, :499-501); full-width and default were the same component, so there was no fork to report. H2 confirmed: installed spec 18.0.0-next.3 carries PAGE_TEMPLATE_SLOTS, PAGE_TEMPLATE_OPEN_GRID, the closed PageTemplateSchema and checkPageRegionPlacement. H2 PARTLY FALSIFIED on the migration: 18.page-template-closed-region-unplaced-refused rewrites only full-width to default on read. A stored row with an unplaced region is 'served unchanged and renders as before', not migrated, so the H4 fallback is reachable by real stored rows. That is why the loud refusal was chosen over drawing nothing. H6: SpecPage['template'] already excludes full-width in the published type, but regions[].name is a string, so the declaration stays 'no (narrowing)'. The maintainer ruling comment 6190536588 was NOT read: objectstack REST and the issue page both answer 403 from this container. Item 2 was taken from the brief's quote and the upstream source's citations of the same record.", "tests": "Run at 572fd84. New file packages/components/src/__tests__/page-template-slots-12476.test.tsx: 16/16 pass. It pins each slotted template refusing unplaced regions (default: left_sidebar, content; header-sidebar-main: aside, footer, right_sidebar; three-column: left_sidebar, right_sidebar), default with no placed region, and full-width / two-column / constructor drawing the unregistered-template refusal. CONTROLS: every placed slot draws on grid-cols-12; names place case-insensitively; dashboard cells are [kpis, charts, main] with header and footer spanning; record/home/app/utility pages without a template still stack region_2. ABLATION at commit 5737745: page.tsx replaced with origin/main's blob (mutant hash dad6a91a = origin/main blob dad6a91a; UnplacedRegionsRefusal count 0 on disk) gives 7 failed and 9 passed. All 7 behaviour pins went red and all 9 controls stayed green. Restored with git checkout HEAD: hash c464da30 = HEAD blob c464da30, git diff HEAD empty, re-run 16/16. Relative import of ../renderers, so no dist leg. Moved pin: packages/types/src/__tests__/layout-default-jsdoc-7361.test.ts row 7 read /'default':\\s*FullWidthTemplate/ and now reads DefaultTemplate (rename only, same intent); 75/75. No existing pin asserted that an unplaced region is stacked. Families: 66 test files naming page.tsx, RegionLayout, getRemainingRegions, TEMPLATE_REGISTRY, data-template, three-column, header-sidebar-main or full-width under packages/ and apps/, plus the new file: 66 passed, 1447 tests, exit 0. pnpm --filter @object-ui/components test (foreground): 402 passed, 1 skipped files, 4036 tests, exit 0. Live reading: NOT MEASURED, reason: it would need the console dev server and a preview route seeded with a slotted page; not cheap in this run.", "gates": "Local subset at 572fd84, each exit captured before any pipe: pnpm --filter '@object-ui/components^...' build EXIT=0; pnpm --filter @object-ui/components type-check EXIT=0 (tsc --noEmit and tsconfig.test.json echoed); check:changeset-claims EXIT=0; changeset:check EXIT=0; check:test-path-roots EXIT=0; check:new-line-citations EXIT=0 (VERDICT 0 new citations); check:spec-symbols EXIT=0; node scripts/check-changeset-presence.mjs EXIT=0 (3 source files of 2 released packages, 1 changeset); eslint on the 3 changed source and test files EXIT=0 (0 errors; page.tsx's 8 warnings are all pre-existing, its origin/main blob has 9, and the new test has 0). Deviations: objectui has no scripts/pm/os-verify-lock.sh or dispatch-gates.mjs, so gates were hand-derived as the brief gives them and no --ran reconciliation exists. The CI farm is not cited because there is no PR yet: in_progress.", "mcp_calls": "3 — mcp__github__issue_read (get, get_comments on objectui#12476), mcp__claude-code-remote__add_repo (read; answered read_available, nothing attached). No write tool.", "api_writes": "0 — the only writes are two git pushes of the branch (empty probe at d2b21a1, then 572fd84).", "open_questions": [ { "question": "H4: what the renderer does with an unplaced region on a slotted template.", "options": ["A loud visible refusal in the main column naming the region and the template's slots; content not drawn, never re-placed (taken)", "B draw nowhere, silently", "C keep stacking"], "recommendation": "A. Business need: stored rows with unplaced regions are served unchanged (the migration does not rewrite them), so B would silently delete live content and C keeps the mis-layout the ruling retires. Long-term: no fallback for a refused shape. AI-error axis: loud beats tolerant, so the author sees what to rename. Startup scope: one small component that reuses the html-tier compile-error styling, with no i18n key (matches the precedent and keeps Clause-② at no)." }, { "question": "An unregistered template (full-width or any other name): refuse, or fall to the pageType layout?", "options": ["A refusal panel (taken)", "B silently fall back to the pageType layout (what deleting the row alone would do)"], "recommendation": "A. The spec refuses it at parse and the card says the renderer keeps no fallback for a refused shape. No in-repo producer emits full-width (the caller sweep found none), and the server rewrites stored full-width rows to default on read." }, { "question": "The pageType path (no template) still stacks unplaced regions, but the spec's checkPageRegionPlacement judges a template-less kind:full page as 'default' and refuses those regions too. Should it also refuse?", "options": ["A leave as is (taken, per brief: do not change a path without measuring that nothing reaches it)", "B refuse there as well in a follow-up"], "recommendation": "A here. Real producers reach that path: PageView and PagePreview spread raw stored rows with no parse, Studio's addRegion writes region_N, and preview-samples. Changing it widens this card's surface. The PM may want a follow-up card for B." }, { "question": "The upstream migration text 18.page-template-closed-region-unplaced-refused says a stored row with an unplaced region 'is served unchanged and renders as before'. After this lands it renders a refusal instead.", "options": ["A amend the objectstack migration text (an objectstack PR)", "B accept the drift"], "recommendation": "A, since the ruling (renderer keeps no fallback) outranks that sentence. It belongs to the seat or objectstack, not this branch." } ], "out_of_scope_findings": [ "class: c · reach: named producer: packages/app-shell/src/views/metadata-admin/previews/PageBlockCanvas.tsx:401 addRegion writes name region_N into the page draft, whose template is 'default' when Studio-seeded (anchors.ts:207-221) or absent. The spec refuses either case at save (checkPageRegionPlacement treats absent as default, 422 INVALID_METADATA), so Studio's own 'Add region' button authors metadata the save door rejects. With this change a template:'default' draft shows the refusal in preview. · evidence: PageBlockCanvas.tsx:399-403, spec page.zod.ts checkPageRegionPlacement · dedupe words: PageBlockCanvas addRegion region_ unplaced region save refused", "class: b · reach: exception: release-text · objectstack migration 18.page-template-closed-region-unplaced-refused promises stored rows with an unplaced region 'render as before'; objectui#12476 makes that false · Seam: spec:18.page-template-closed-region-unplaced-refused → renderer: page.tsx UnplacedRegionsRefusal · dedupe words: unplaced region migration renders as before upgrade guide" ] }Posted by the
domain:uiseat 1 PM (session_011K9g23W67dy2zwnyzaoB6o) verbatim from the cloud session's final message, because a cloud session cannot comment from its container. The seat filledprwith the draft PR it opened, #12901.The seat's answers:
6190536588on spec:PageTypeSchemasayshomeis "the platform-level landing page" andutilitya "floating utility panel", but the landing is the first navigation item and both types render as ordinary inline pages objectstack#23610. Item 2 is as the brief quotes it, item 5 names this card ("retires the stack-the-rest branch for authored pages"), and nothing in it keeps a fallback for a refused shape.full-width→defaulton read, and falling to thepageTypelayout would draw a different layout than the one named.region_N, which the save door refuses on every template butdashboard), as one card for the two objectui positions of this family.572fd84: 4 files, +304/−27, on the claimed surface (page.tsx, one new test, one moved pin in@object-ui/types' test tree, one changeset).TEMPLATE_REGISTRYis typed by the spec'sPageTemplate, so the set cannot drift from the spec silently; the lookup guards prototype keys (constructoris pinned).@object-ui/componentsalready imports runtime helpers from@objectstack/spec/ui(resolveI18nLabel), so the new import is not a new dependency edge. Its declared floor,^18.0.0-next.1, predatesPAGE_TEMPLATE_SLOTS(added innext.2); the lockfile resolvesnext.3, and the floor has stayed atnext.1across thenext.2andnext.3bumps. Recorded, not changed here.pageTypedispatch is unchanged, and its control pinsrecord,home,appandutility.Clause-②: no (narrowing)owes oneCONTRACT_REVIEW_TIERreview. The seat runs it on this head once CI reports, then writes the ACCEPT.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed ·
domain:uiseat 1 ·session_011K9g23W67dy2zwnyzaoB6o· 2026-10-17T16:49Zmain044f231930, with one parent,c999d4c017. It is an ancestor oforigin/main.f5009db72cto the reviewed headfd893dd, changed line for changed line in each of the 10 files (+319/−35).page.tsxcarriesUnplacedRegionsRefusaland no'full-width'row inTEMPLATE_REGISTRY, and@object-ui/componentsdeclares@objectstack/spec^18.0.0-next.2. At the parentc999d4c017the refusal is absent, thefull-widthrow is present and the floor is^18.0.0-next.1.completedbyFixes #12476. Ondefault,header-sidebar-mainandthree-column, a region the template does not place is no longer stacked undermain: it is refused on the page by name, with the template's slots, as maintainer ruling Q2 A (spec:PageTypeSchemasayshomeis "the platform-level landing page" andutilitya "floating utility panel", but the landing is the first navigation item and both types render as ordinary inline pages objectstack#23610, item 5) binds. The contract review of record is6236677561(PASS onfd893dd; the first head failed at6236121598and was reworked). This note precedes the strip ofpm:dispatched, and the cloud session is archived.region_N, which the save door refuses, and a page that names no template still stacks such a region) and [finding] spec(migrations): the published entry page-template-closed-region-unplaced-refused says a stored page with an unplaced region or an unregistered template "renders as before"; objectui#12476 makes it render a refusal objectstack#24195 (the spec migration's "renders as before" sentence, now false for both an unplaced region and an unregistered template).Generated by Claude Code