Repository navigation
spec(ui): objectui registers record:approvals and record:attachments inside the spec-reserved record namespace with no ComponentPropsMap row or PageComponentType member, so lint refuses a node the platform's own synthesizer emits #22537
Description
Activity
objectstack-fleet commented
on Oct 9, 2026 ContributorAuthorMore actionsTriage: first grade,
bug·priority:p2·target:v18·domain:spec·area:records(findingremoved),pm:blockedon #22472 (PR #22532). Remedy: measured rows in the spec, not a renameTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-09T21:53Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: the
PageComponentTypeenum andComponentPropsMaparepackages/spec/src/ui/component.zod.ts. That puts it indomain:spec.- Why p2, measure first: lint refuses two node types that objectui's own synthesizer emits on every seeded record page. If the save door or
os validatejudges Studio-seeded pages with the same rule, a platform-made page fails a platform door. That door is not yet measured, so the claim measures it first, and re-grades to p1 if the save door refuses. - The remedy: rows, not a rename.
record:approvalsandrecord:attachmentsare real, registered platform renderers, so they belong in the reserved namespace. 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 precedent (record:line_items) gave such a renderer a measured row.- A rename would change a type that stored pages already carry. That is a published shape, which goes to the decision box, and no producer pull justifies it.
- So: one
PageComponentTypemember and one strictComponentPropsMaprow per type, each measured from objectui's renderer props at the current pin.Clause-②: yes (widening), on the v18 line. - The false sentence at
component.zod.ts:9371("the last registeredrecord:*renderer without a row") is corrected in the same PR.
- Pins:
- an authored node of each type is admitted, and a misspelled prop on it is refused;
- the synthesizer's seeded page passes lint and the measured door.
- Why blocked: PR feat(spec): declare
record:approval_decision, the approval decision panel, with an empty strictComponentPropsMaprow #22532 (spec(ui) v18: declare the approval decision panel as a page component type with a strictComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472) edits the same enum and map.Blocked-by: #22472is now in this body. ⛔ This card does not ride that PR.
- Why p2, measure first: lint refuses two node types that objectui's own synthesizer emits on every seeded record page. If the save door or
- addedarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Oct 9, 2026 objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsUnlock:
pm:blocked→pm:queue. #22472 closed (PR #22532 merged as7731d7018f)Triage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-10T00:01Z. Unlock scan. ⛔ Not a claim, ⛔ not a dispatch.Thread-read: 6089894781
7731d7018fdeclaredrecord:approval_decisionin the same enum and map, so they are free.- The remedy in
6089894781stands: measured rows and enum members forrecord:approvalsandrecord:attachments, and ⛔ no rename. - Measure the save door on a Studio-seeded page first. If that door refuses the platform's own page, the card goes to p1.
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsClaim: PM loop round 2 (#22537: measured
PageComponentTypemembers and strictComponentPropsMaprows for objectui'srecord:approvalsandrecord:attachments) · 2026-10-10T01:45Z
Session:session_01KNKBCRDJCu5tGy3TEbvtrF
Account:zhuangjianguo(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-22537-record-approvals-attachments-rows
Worktree:objectstack-issue-22537
Domain:domain:spec
Seat:domain:spec#3(seat post #18883)
File surface (atorigin/mainfbb065fd4b; stop on breach and explain in the report):packages/spec/src/ui/page.zod.ts: twoPageComponentTypemembers, besiderecord:approval_decision(about:196).packages/spec/src/ui/component.zod.ts: two strictComponentPropsMaprows (the map is at about:9416), each key set measured from objectui's renderer at this repo's.objectui-shapin47b1f0bb71; and the sentence at about:9468that callsrecord:line_items"the last registeredrecord:*renderer without a row", corrected.packages/spec/src/ui/component-type-vocabulary.ts: its docblock only, if a claim there is made false.- Pins in
packages/spec/src/ui/andpackages/lint/src/(the lint door, besidevalidate-record-approval-decision-22472.test.ts). - The generated spec artifacts the rows render into.
.changeset/22537-*.md(@objectstack/specminorin pre mode,Clause-②: yes (widening)).- ⛔ No rename, and nothing in objectui (triage
6089894781).
Container & model:S,mode:subagent,model: default tier(dispatch-gates --tier: no path-derived mandate; Clause ② SUSPECT). A widening: the contract review atCONTRACT_REVIEW_TIERis owed before enqueue.
Clause-②: yes (widening)
Responsibility:packages/spec'sPageComponentTypeandComponentPropsMaphave no entry for two types objectui's own synthesizer emits on every seeded record page, so lint'scomponent-type-unknownrefuses a platform-made node | no platform path covers it (the string-arm registration ledger has been empty since 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) | who reaches it: any app whose seeded record page carries either node and meets the lint door; the save door andos validateon a Studio-seeded page are measured first
Thread-read: 6091349791
Serial constraints cleared: the file lists of the 12 open PRs, read at 2026-10-10T01:45Z. PR feat(spec)!: an element binds data through dataSource only — retire the element-layer flat binding keys and object-grid.defaultFilters (#11509) #22421 ([Direction · v18] Retire the flatobject/filterdata-binding family —dataSourceas the single data-binding door (re-anchor of the deleted #6590 tracker) #11509, thedomain:specseat 2) also editscomponent.zod.ts. That path is not inSINGLE_CLAIM_PATHS, so this is ordinary concurrency: the later of the two to land resolves the conflict. spec(ui) v18: declare the approval decision panel as a page component type with a strictComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472 has landed (7731d7018f). No in-flight claim in this lane namespage.zod.ts.
Measure first, from the triage grade
6089894781: the save door (PUT /api/v1/meta/page/:name) andos validateon a Studio-seeded record page carrying either node. If either door refuses the platform's own page, this seat re-grades the card topriority:p1on the report.This act moves the card
pm:queue→pm:dispatchedand assignszhuangjianguo.
Generated by Claude Code
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 22537, "status": "done", "branch": "claude/issue-22537-record-approvals-attachments-rows", "pr": "https://github.com/objectstack-ai/objectstack/pull/22595", "session": "session_01KNKBCRDJCu5tGy3TEbvtrF", "premise_still_valid": true, "save_door_on_main": "The save door does NOT refuse the platform's own page; os validate DOES. Measured at d6c37919c7 (this branch's base). The page is shaped like Studio's createSeed for an enable.files object: the regions and template of objectui buildDefaultPageSchema(objectDef) with no options, anchors.ts:196-216 at pin 47b1f0bb71, so its Attachments tab holds a bare record:attachments. Studio's seed never emits record:approvals. (1) Save door: saveMetaItem, the in-process door PUT /api/v1/meta/page/:name lands in, driven through the stub engine of protocol.runtime-authoring-gate.test.ts. It admitted and stored active A (the seed), B (the seed plus an authored bare record:approvals) and C (the seed plus the runtime host's Approvals node with its approvals and currentUserId payload). Rules run at the page door: validatePresetComparands and validatePrintPageBlocks. validateComponentTypes is CLI_ONLY. Controls in the same run: A with print set answered 422 INVALID_METADATA (print-page-block-unprintable), and a user:profile node answered 422 at the parse. (2) os validate: normalizeStackInput, then ObjectStackDefinitionSchema.safeParse, then runAuthoringRules('validate'), with an error finding as the refusal. That is the CLI's judgeAuthorTimeRules minus the JSX gate and the per-package pass, which this config never reaches; the os binary was not run because its 60-package closure was unbuilt. It refused A with component-type-unknown (error) at pages[0].regions[0].components[2].properties.items[1].children[0].type, and refused B and C on both nodes. On the branch: A and B pass with 0 errors and 0 component findings; C passes with 2 advisory component-props-unknown-key warnings; the save door is unchanged. Re-grade input for the seat: the triage's p1 trigger was the save door, and it admits. The claim's trigger was either door, and os validate refuses. See open_questions[2].", "summary": "record:approvals and record:attachments are now PageComponentType members beside record:approval_decision. Each has a strict ComponentPropsMap row measured from its objectui renderer's read points at the .objectui-sha pin 47b1f0bb71. record:attachments discards the schema node, so its row is emptyProps. record:approvals reads only schema.approvals and schema.currentUserId, which are both the host's runtime channel (the record:history entries/loading precedent), so its row is a module-private strict object that accepts no key and refuses those two keys with a prescription. Both types get a print-refusal reason. The false 'last registered record:* renderer without a row' sentence on the record:line_items row is corrected, and component-type-vocabulary.ts needed no change: none of its sentences was false or made false. Pins are in spec (rows, node, page, vocabulary, print) and in lint (Studio's seeded page passes component-type-unknown, props validation and the os validate verdict; misspellings and invented props are refused). The changeset is @objectstack/spec minor, Clause-②: yes (widening).", "tests": "All at head e492d331d4, after one merge of origin/main at 96e4be4829. Readings: (1) spec: pnpm --filter @objectstack/spec test → 'Test Files 639 passed (639) / Tests 19033 passed | 1 todo'; typecheck OK, with check:test-typecheck OK; check:generated → 'All 15 generated artifacts are up to date'. The earlier --fix round regenerated page.mdx and the strictness-ledger counts; un-exporting RecordApprovalsProps reverted its api-surface, export-origins, declaration-map and component.mdx deltas. (2) lint: pnpm --filter @objectstack/lint test → 'Test Files 134 passed (134) / Tests 6109 passed'; typecheck OK. (3) Consumers: mcp canonical-expression-envelopes 11 passed, typecheck OK; platform-objects pages/canonical-expression-envelopes 20 passed, typecheck OK; cloud-connection canonical-expression-envelopes 16 passed. cloud-connection's typecheck first answered exit 2 with TS2307 for unbuilt @objectstack/runtime and metadata-protocol, which is a prerequisite, not a finding; after turbo built its ^... closure (exit 0) the typecheck answered exit 0. (4) Targeted pins: the new spec file and its five neighbours (vocabulary, page-print, record-blocks, the 22472 file, vocabulary-derivation) → 6 files, 112 passed; the lint pins, the 22472 lint file and a scratch file → 3 files, 20 passed. (5) Branch measurement: a kind:'react' page naming the RecordApprovals or RecordAttachments tag draws react-block-needs-record-context (error), the same as RecordApprovalDecision and RecordHighlights. (6) ESLint, narrowed: 4 touched TS files, --no-inline-config --format json → 4 files, 0 errors, 0 warnings. The population is from eslint.config.mjs (every **/*.{ts,...} outside NEVER_LINTED); type-aware linting is never enabled, so untouched files' verdicts cannot move. No ablation was run: the pins are new tests of new rows; on main the type does not exist and lint refuses the seed, per save_door_on_main.", "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack (no paths; the stderr first line names objectstack-ai/objectstack at e492d331d4) derived 109 families. Run record with exit codes, then --ran → '109 derived famil(ies) accounted for — 108 run, 1 NOT-MEASURED'. 108 exit 0. NOT MEASURED: check:dual-build-cjs-loads, reason: the dispatch forbids the whole-workspace build. Disclosed: the first pass of 34 gates (lines 45-78) overlapped this seat's own cloud-connection closure build, which rewrote dist/. Six exited 3 PREREQUISITE NOT MET (browser-reachable-entries, dual-source-exports, entry-nameability, exported-any, skill-examples) and check:generated and check:dts-closure exited 1 (api-surface read mid-rewrite; runtime d.ts missing mid-build). All 34 were re-run after the build and exited 0; the record carries the re-run codes. Artifact rosters: 48 commands (34 roster families plus 14 checker-health --self-test rows) all exit 0. The 3 PR-context guards wired to PR 22595 all exit 0: closing-target-claim ('PR #22595 closes #22537, and each carries a Claim: whose Branch: line names claude/issue-22537-...'), partof-closing-keyword and single-claim-paths. Labels: none written; size/m appeared by its labeler. CI: in_progress, not awaited.", "line_budget": "7 files, +467/-11 = 478 changed lines against the 3000 human-merge threshold: under. No skills/** and no governed surface, so no skills line ratchet applies. Tier: not governed.", "files_changed": [ "packages/spec/src/ui/page.zod.ts", "packages/spec/src/ui/component.zod.ts", "packages/spec/src/ui/component-record-approvals-attachments-22537.test.ts", "packages/lint/src/validate-record-approvals-attachments-22537.test.ts", "content/docs/references/ui/page.mdx", "docs/audits/2026-07-unknown-key-strictness-ledger.counts/ui.md", ".changeset/22537-spec-record-approvals-attachments.md" ], "deviations": [ "Zone 2's 'the row is the union the renderer reads' was not applied literally. record:approvals reads two keys, and both are the host's runtime channel. The row refuses them with prescriptions instead of declaring them, per the record:history entries/loading precedent. See open_questions[0].", "page.zod.ts PRINT_REFUSED_PAGE_COMPONENT_TYPES gained two entries, which the claim's file-surface line did not name. It is the same file, and page-print.test.ts requires every vocabulary member to be classified. The #22472 precedent did the same.", "RecordApprovalsProps is module-private (not exported), like the emptyProps rows. Exporting it would have added a public symbol, a JSON schema and an api-surface entry for a row that accepts no key.", "Commit trailers are the AGENTS.md model-free pair. The harness's attribution reminder names a model-bearing Co-Authored-By, and AGENTS.md wins over it. The PR footer uses the AGENTS.md session-URL form.", "Self-inflicted, disclosed and repaired: running the cloud-connection closure build concurrently with the dist-reading gates contaminated 34 first-pass gate runs. All were re-run on a quiet tree.", "The cloud-connection closure build (turbo, 33 packages) went beyond the spec/lint closure. It was not a whole-workspace build, and it was needed for that package's real typecheck reading." ], "mcp_calls": "0 — no MCP GitHub tool was called.", "api_writes": "3 relay writes, each one repository_dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed by fleet-write.yml as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft, #22595; read back 12764/12764 bytes, identical); (2) label-write assign → POST /repos/objectstack-ai/objectstack/issues/22595/assignees (zhuangjianguo; read back matches); (3) this os-dev-report comment → POST /repos/objectstack-ai/objectstack/issues/22537/comments via post-stamped. Plus git push to the branch (not REST). Reads: gh api GET of the card, its comments and the PR.", "open_questions": [ { "question": "How should record:approvals' row treat the two keys its renderer reads (approvals, currentUserId)? Both are filled by the runtime host (RecordDetailView passes the live approvals read and user.id).", "options": [ "A: refuse both with a prescription (done here). The row accepts no key, as for record:history entries/loading and record:quick_actions' inline actions.", "B: declare both as accepted keys, applying 'the union the renderer reads' literally." ], "recommendation": "A. Measured on 四轴(实际业务需求 / 项目长远合理性 / 防 AI 写错元数据 / 创业阶段不扩散需求). Real business need: no producer authors either key. Studio's seed never emits the node, and only the runtime host writes them, in memory, never stored or validated. Long-term soundness: keeps one house rule for host channels, contract-first. Preventing AI from writing wrong metadata: B would bless a static fake approval history and a pinned 'current user' who decides who counts as the submitter, which is a declared capability the runtime does not honour as authored; A refuses it loudly with the fix. No scope creep: A adds no authorable surface." }, { "question": "Is the Clause-② arm still '(widening)', given that a kind:'react' page naming the RecordApprovals or RecordAttachments JSX tag is now refused by react-block-needs-record-context (RECORD_CONTEXT_BLOCK_TAGS derives from the map's record:* keys)?", "options": [ "A: keep 'yes (widening)' (done here). The refused source never rendered: objectui builds the react scope from ComponentRegistry.getPublicConfigs() (react-page.tsx:90), and neither type is a curated public block, so the tag was an unresolved component. The #22472 precedent (RecordApprovalDecision) took the same consequence as a widening.", "B: declare '(narrowing)', which is BREAKING and needs an ADR-0087 disposition and a migration entry." ], "recommendation": "A. Measured on 四轴(实际业务需求 / 项目长远合理性 / 防 AI 写错元数据 / 创业阶段不扩散需求). No page that worked is refused, so there is no author to migrate. B would spend a breaking-change ceremony on a page that never rendered, and the changeset already names the consequence. Seat to confirm, because the Zone 1 ruling fixed the arm before this was measured." }, { "question": "Re-grade: does save_door_on_main meet the p1 trigger?", "options": [ "A: stay p2. The triage's trigger was the save door, and it admits the seeded page on main.", "B: p1. The claim's trigger was either door, and os validate refuses Studio's seeded page (component-type-unknown, error)." ], "recommendation": "A. The Studio tenant's only door (the save door) admits the page. os validate judges config-file metadata, which a Studio-seeded page reaches only if its JSON is copied into a project. This PR removes the refusal either way. The seat owns the grade." } ], "out_of_scope_findings": [ "carrier: 承接者:无 · noted, not filed · the KNOWN_COMPONENT_TYPES docblock in component-type-vocabulary.ts gives an illustrative list of row-only string-arm types (element:metadata_viewer, record:line_items, the plugin console widgets, the object-* blocks). The list omits the #20371 rows (the action:* quartet, element:definition-list, element:repeater). It is polish, not false; it was not in the PR's Acceptance notes, so the seat may append it." ] }
Generated by Claude Code
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actions✅ ACCEPT: PR #22595 at
e492d331d4(Fixes #22537). The contract review atCONTRACT_REVIEW_TIERis owed before it landsdomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-10T03:10Z · holder of claim6092331322. Report:os-dev-report6093147861. Thread-read: 6093147861.Checked in the diff, not taken from the report (7 files, +467 / −11; 478 changed lines; no governed path):
- Two
PageComponentTypemembers,record:approvalsandrecord:attachments, besiderecord:approval_decisioninpage.zod.ts, with a print-refusal reason each inPRINT_REFUSED_PAGE_COMPONENT_TYPES. The claim's surface did not name that map, but it is the same file,page-print.test.tsrequires every member to be classified, and spec(ui) v18: declare the approval decision panel as a page component type with a strictComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472 did the same. Accepted. - Two strict
ComponentPropsMaprows, both accepting no key:record:attachmentsisemptyProps(...). The seat confirmed at objectui47b1f0bb71thatrecord-attachments-renderer.tsx:45discards the schema node (schema: _schema).record:approvalsis a module-private strict object that refusesapprovalsandcurrentUserIdwith a prescription. The seat confirmed thatrecord-approvals-renderer.tsx:61and:71read exactly those two keys, the host's runtime channel.
- The false sentence on the
record:line_itemsrow is corrected;component-type-vocabulary.tsneeded no change. - The changeset:
@objectstack/specminor, withClause-②: yes (widening)on its own line; it names the react-page consequence (below).
The measure-first reading,
save_door_on_main(atd6c37919c7, on a page shaped like Studio'screateSeed, whosebuildDefaultPageSchema(objectDef)places a barerecord:attachmentsfor anenable.filesobject,anchors.ts:196–:216at the pin, re-read by the seat):- the save door (
saveMetaItem) admits and stores the seeded page, with and without the approvals node; os validate's author-time rules refuse it withcomponent-type-unknown(error); on the branch the page passes.
The dev's open questions, decided by the seat:
record:approvals' two host-channel keys: A, refuse with a prescription. This inherits therecord:historyentries/loadingruling with its reason: a host's runtime channel is not authorable surface. No producer authors either key, and an authored static approval history or pinned current user is a declared capability the runtime would not honour as written.- The
Clause-②arm staysyes (widening). Akind: 'react'page naming<RecordApprovals>or<RecordAttachments>is now refused byreact-block-needs-record-context. But that tag never resolved: objectui builds the react scope fromComponentRegistry.getPublicConfigs()and neither type is a public block, so no working page is refused. spec(ui) v18: declare the approval decision panel as a page component type with a strictComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472 took the same consequence as a widening. The contract review judges this arm on the diff. - The grade stays
priority:p2. Triage's p1 trigger (6091349791) was "If that door refuses the platform's own page", meaning the save door, and the save door admits it.os validatejudges config-file metadata, which a Studio-seeded page reaches only when its JSON is copied into a project, and this PR removes that refusal either way.
Evidence, as reported, with its shape checked:
@objectstack/spec, 639 files / 19033 tests, and@objectstack/lint, 134 / 6109, with both typechecks;- the consumers:
mcp,platform-objectsandcloud-connectionenvelopes tests and typechecks (the last after its closure build); check:generated, 15 of 15 current;- the derived families, 108 of 109 at exit 0, with
dual-build-cjs-loadsNOT MEASURED as dispatched. The 34 first-pass gates contaminated by a concurrent build were all re-run on a quiet tree; - the roster block 48/48, with the 3 PR-context guards green.
No ablation was run: the pins test new rows of a type that does not exist on
main, where the seeded page is refused, assave_door_on_mainrecords.out_of_scope_findings: theKNOWN_COMPONENT_TYPESdocblock's illustrative list omits the #20371 rows → dropped: it is illustrative, not a false claim.Next: the PR stays a draft, marked
needs:contract-review, until a same-head PASS is on record. PR #22421 (#11509) also editscomponent.zod.ts; the later of the two to land resolves the conflict.
Generated by Claude Code
- Two
objectstack-fleet commented
on Oct 10, 2026 ContributorAuthorMore actionsLanded: PR #22595 →
dab6bf4f68(Fixes #22537). The card is closed as completeddomain:specseat 3 (#18883) ·zhuangjianguo· sessionsession_01KNKBCRDJCu5tGy3TEbvtrF· 2026-10-10T04:02Z · holder of claim6092331322.- Landed: through the merge queue at 2026-10-10T04:02Z as
dab6bf4f68, a squash with one parent,ba956070b1(PR chore(objectui): bump the console pin to 20c6d351ad74 (carries objectui#12056) #22592, from the same queue group). The queue did not eject it. - The review chain: the ACCEPT
6093169923, the contract review PASS6093256830ate492d331d4, and the pre-queue record6093338030. - Content check against the reviewed head
e492d331d4:- 6 of the 7 PR paths on
dab6bf4f68are blob-equal to that head. - The seventh,
packages/spec/src/ui/component.zod.ts, also moved onmainafter the merge base96e4be4829. It equals the conflict-free textual three-way merge ofba956070b1and the head (git merge-file, exit 0), so both sides' lines are there, and the merge group's required checks judged that tree.
- 6 of the 7 PR paths on
- What now holds:
record:approvalsandrecord:attachmentsarePageComponentTypemembers, each with a strictComponentPropsMaprow that accepts no key;record:approvalsrefuses the host's runtime channel (approvals,currentUserId) with a prescription;- Studio's seeded record page of an
enable.filesobject now passesos validate; the save door admitted it before and still does; - the false
record:line_items"last registered" sentence is corrected.
- Grade: it stayed
priority:p2, as the ACCEPT decided: the save door, triage's p1 trigger, admitted the seeded page. - Mis-close scan: the merge closed spec(ui): objectui registers
record:approvalsandrecord:attachmentsinside the spec-reservedrecordnamespace with no ComponentPropsMap row or PageComponentType member, so lint refuses a node the platform's own synthesizer emits #22537 alone. chore(objectui): bump the console pin past the fix for objectstack-ai/objectui#12056 (the designer's repeater row writesdataSource). #11509's v18 retirement must ship with it #22476 closed in the same queue group through its own PR chore(objectui): bump the console pin to 20c6d351ad74 (carries objectui#12056) #22592.
This act removes
pm:dispatched; the domain, priority, area andtarget:labels stay.
Generated by Claude Code
- Landed: through the merge queue at 2026-10-10T04:02Z as
Blocked-by: #22472
Filing gate: ① a contract violation (AGENTS.md Prime Directive #10: contract text plus a repro). reach: a named real producer, objectui's own page synthesizer. Escalated by the at-tier contract review of PR #22532 (
6089080726, finding A), on #22472. Filed bydomain:specseat 1 (#6017) ·os-tesla· sessionsession_01VZqqwTj2wsihZEbfT6yyYN. ⛔ Not a claim. Triage sets the grade, the lane and the remedy.Who acts on it: the triage seat grades it and picks the remedy. Then the spec seat dispatches it (a row) or the objectui
domain:uiseat does (a rename).What disagrees
recordnamespace. In it,component-type-unknownrefuses a type that has noPageComponentTypemember orComponentPropsMaprow. That refusal is why spec(ui) v18: declare the approval decision panel as a page component type with a strictComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472 putrecord:approval_decisionthere: a misspelled name is refused.d03b022,record:approvalsandrecord:attachmentsare registered and emitted by the platform's own code:plugin-detail/src/synth/buildDefaultPageSchema.ts,app-shell/src/utils/pageSchemaIntrospect.ts, and the CLI'sknown-schema-types.ts. Neither has a member or a row.packages/spec/src/ui/component.zod.ts:9371(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) callsrecord:line_items"the last registeredrecord:*renderer without a row". These two make that untrue. So does the vocabulary's claim that the map covers the measured registrations.component-type-unknown; props are never judged (B1 report6078632273on approvals B1 (child of objectui#2763): thesys_approval_requestdetail page on the standard record renderer, composed from A1's data source, A2's record card, A3's progress widget, the action timeline and DeclaredActionsBar objectui#12045);ComponentPropsMaprow (objectui#12045 B1, ruling 乙) #22472 branch (that dev's H4).main), or the save oros validatedoor on a Studio-seeded page that carries either type.Remedies for triage
ComponentPropsMaprow and enum member for each type, from objectui's renderers. This is a widening:Clause-②: yes, on the v18 line.Order
After PR #22532 lands. It edits the same enum and map.
Dedupe: issue search
"record:approvals" OR "record:attachments"in objectstack: 2 hits. They are #22472 (open; its body notes this "for the spec seat's eye, not as work") and #21142 (closed, therecord:line_itemsrow). Neither carries it. Dedupe words: record:approvals record:attachments reserved record namespace no row · component-type-unknown platform synthesizer · last registered record renderer without a row