Repository navigation
feat(spec): declare record:approval_decision, the approval decision panel, with an empty strict ComponentPropsMap row - #22532
Conversation
…ponentPropsMap row Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
…ary and the authoring doors; regenerate page reference Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
…c's component vocabulary Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
📓 Docs Drift CheckThis PR changes 1 package(s): 2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 5 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 139 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 956cf302f2c8769ddb9b9fd2e8c4f90209e9d2dd && git checkout 956cf302f2c8769ddb9b9fd2e8c4f90209e9d2dd
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ee8751d41e61a18f7819e4d3ad2c340f51ab2418 b101db36c7c2f10dccaa3cad818599fc7ccfd9be && git checkout -B drift-repro ee8751d41e61a18f7819e4d3ad2c340f51ab2418 && git merge --no-ff b101db36c7c2f10dccaa3cad818599fc7ccfd9be
node scripts/docs-audit/affected-docs.mjs --json ee8751d41e61a18f7819e4d3ad2c340f51ab2418
|
Contract reviewServed-tier: Read at 2026-10-09T20:53Z: card #22472 (body, the claim ① Derived judgments
② Semver level
③ Boundary flagsDev deviations, each answered:
Found by this review, not flagged by the dev:
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Standing down on a failure that is not this PR's.
|
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 37991929236 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Fixes #22472
Clause-②: yes
What this declares
record:approval_decision, the approval decision panel of asys_approval_requestrecord page, is now a declared page component type in@objectstack/spec. One node shows the request's decision progress and its declared decision actions. This is the spec-lane half of the maintainer's ruling on objectstack-ai/objectui#12045 (6079807016, letter 乙, answered 「同意」): a type with noComponentPropsMaprow passes any props bag, so the ruling asks for a row thatos validatechecks. It is an ordinary v18 widening (「17.x 不会发新版」).packages/spec/src/ui/page.zod.tsrecord:approval_decisionjoinsPageComponentType(Record Context group), andPRINT_REFUSED_PAGE_COMPONENT_TYPESgets its print reasonpackages/spec/src/ui/component.zod.tsComponentPropsMaprowemptyProps('record:approval_decision'); theemptyPropsdocblock lists itcontent/docs/references/ui/page.mdxgen:docs): thePageComponentTypelist and thetypecolumnpackages/spec/src/ui/component-record-approval-decision-22472.test.tspackages/lint/src/validate-record-approval-decision-22472.test.tsos validateruns.changeset/22472-spec-record-approval-decision.md@objectstack/specminor,Clause-②: yes (widening)Contract decisions (the spec seat's; relayed to objectui#12045)
record:approval_decision, as proposed.recordis a reserved namespace (derived from the enum), so a misspelling there is acomponent-type-unknownerror that offers the declared spelling. objectui already uses this name in its module-internal renderer and its tests, so no rename is needed on their side.mainatd03b022(packages/app-shell/src/views/approval-decision/ApprovalDecisionPanel.tsx, landed in objectuia368ccb).ApprovalDecisionRendererdiscards the schema node (schema: _schema). It draws from the record context (the bound request row, with itsvieweranddecision_progress) and fromsys_approval_request's own declared actions.classNameand the designer attributes it reads are node-level keys, neverproperties. The file is not at this repo's.objectui-shapinf0268ad78:git cat-file -eat the pin answers 128, withrecord-approvals-renderer.tsxat the same pin as the control answering 0. That is why the citation names objectuimain, not the pin. The row reuses the existingemptyProps(type)factory, the spelling of the nine other zero-prop rows (nav:menu,element:divider,mcp:connect-agent, …), so the refusal names the component.record:line_items,element:definition-listand the other row-only types entered the vocabulary through the open string arm. The vocabulary admits a type that way only on measured registration, publication and authorship (component-type-vocabulary.ts; the#20371rows write all three down). This type has none of the three yet. objectui keeps its renderer unregistered until this declaration exists (its docblock says so), and plugin-approvals authors the page after it (plugin-approvals: servesys_approval_request's detail page as a slotted page through the manifestpages, and declare the thread reply asapproval_comment(objectui#12045 B1, ruling 乙) #22473). A spec-first declaration is therefore an enum member. One consequence for objectui: its palette-coverage test (block-config.test.ts, derived fromPageComponentType.options) asks for an offer-or-exclude decision for the new member once objectui moves tonext(objectui#12030).Measured hypotheses
H1 holds.
record:approval_decison→ onecomponent-type-unknownfinding, severityerror, message offering'record:approval_decision'. The declared spelling in the same position → no finding. Both are pinned in the lint test, throughvalidateComponentTypesand throughrunAuthoringRules('validate', …).H2: every table the member must appear in. Grep for
record:history/record:line_items/record:reference_railacrosspackages/spec,packages/lint,content,scripts:PageComponentType(page.zod.ts): added.ComponentPropsMap(component.zod.ts): added.PRINTABLE_PAGE_COMPONENT_TYPES/PRINT_REFUSED_PAGE_COMPONENT_TYPES(page.zod.ts): added to the refused map.page-print.test.tsrequires every live known type to be classified exactly once, and it passes.content/docs/references/ui/page.mdx: regenerated.KNOWN_COMPONENT_TYPES,KNOWN_COMPONENT_TYPE_CANDIDATESandRESERVED_COMPONENT_TYPE_NAMESPACES(unchanged:recordwas already reserved). The lint print gate and itsit.eachiterate the map. Therecord:*-on-react-page refusal invalidate-react-page-props.tsis prefix-based.scripts/format-type.test.ts(a static fixture that still lists the retired types),validate-page-field-bindings.ts(rows for field-binding props only; this type has none),sdui.manifest.json(objectui's build output).H3 holds. A no-props row is spelled
emptyProps(type), astrictObjectwith no keys. Any key →unrecognized_keysnaming`record:approval_decision`and the key, and through lint onecomponent-props-unknown-keywarning atproperties.KEY. A node-level key written insideproperties(className) gets the "belongs on the component NODE" prescription.H4, measured and not fixed. I ran
validateComponentTypes/validateComponentPropsfrom this branch on a record page:record:approvals→component-type-unknown/error, no props finding.record:attachments→component-type-unknown/error, no props finding.record:approval_decisionandrecord:details→ no type finding, one props finding each.Both are refused outright. objectui synthesizes both nodes at render time (
buildDefaultPageSchema); no authored producer exists in this repo.Verification
Tests at
b101db36c7(the final commit), all underscripts/pm/os-verify-lock.sh:pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui/component-record-approval-decision-22472.test.ts src/ui/page-print.test.ts src/ui/component-type-vocabulary.test.ts: 3 files, 54 tests passed.pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-record-approval-decision-22472.test.ts src/validate-print-page-blocks.test.ts src/validate-component-types.test.ts: 3 files, 94 tests passed, against a specdistrebuilt from this branch. On a staledistthe declared type would read ascomponent-type-unknown, so the green lint pins also show that the rebuiltdistwas read.&&,VERDICT command-exit 0:pnpm --filter @objectstack/spec typecheck(incl.check:test-typecheckOK) ·pnpm --filter @objectstack/lint typecheck(OK) · specvitest run --project local: 632 files, 18837 passed, 1 todo · specvitest run --project repo: 54 files, 915 passed · lintvitest run: 132 files, 6003 passed.node scripts/ablation-replace.mjsdeleted the row line (anchor x1 → x0, blob583b6e1e→908d18cc). The spec pin file went to 5 failed / 3 passed. The 3 that stayed green are the vocabulary and print pins, which the enum member alone still satisfies. Restored blob = HEAD583b6e1e, andgit diff HEADis empty.node scripts/pm/dispatch-gates.mjs --commandson this diff derived 109 commands (a superset of the dispatch list, +29 from the docs and lint-test paths). Every one ran with its exit code recorded.--ranreconciliation: 109 derived, 107 run, 2 NOT-MEASURED, 0 UNRUN. Five gates first exited 3 (unbuilt@objectstack/lint/ client / objectql). They passed (exit 0) after their packages were built. NOT MEASURED:check:dual-build-cjs-loadsandcheck:type-check-debt. Reason: both refuse unless every workspace package is built (a whole-repo build), which is left to CI.pnpm --filter @objectstack/spec check:generatedis green aftergen:docs.authorable-surface/andapi-surface/did not move (the enum adds a value, not a key or an export).Acceptance notes
sys_approval_requestrecord page (objectui returnsnull), and no rule refuses the type on another object's page. The row comment and the changeset say so. Not filed: there is no producer yet, and the services child is the only planned author.content/docs/ui/pages.mdx(hand-written) introduces its list as "include", and that list already omitsrecord:line_items. It is outside this card's file surface, so it is left unchanged.component.zod.ts, butPageComponentTypelives inpage.zod.ts. That file was already on the surface for the print tables. The lint test file is the H3 pin for thecomponent-props-unknown-keyrule id, which lives in@objectstack/lint. No lint source changed: the row needed no lint hook.sys_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 (renderer registration and zod arm at its page-mount step) and plugin-approvals: servesys_approval_request's detail page as a slotted page through the manifestpages, and declare the thread reply asapproval_comment(objectui#12045 B1, ruling 乙) #22473 (plugin-approvals' request page, which carriesBlocked-by:on this card).Generated by Claude Code