Blocked-by: objectstack-ai/objectstack#12580
Implementation of the objectstack#11592 ruling (maintainer, 2026-08-25, verbatim 「全部同意」 on recommendation B; full record = objectstack#11592 comment 5405065025). Filed by PM session session_01KWRU3s15AJz7PGW7a7wdCh per the confirmed checklist. Parent: objectstack#11592 (tracking).
Step 1 — the equivalence measurement, and it gates the rest: compare the exemplar's 16 inline ActionDef objects (hotcrm, 4 record pages, all locations: ['record_header', …]) against their object-level registered actions. If any inline def carries page-level customization an id-resolved action cannot express, ⛔ stop and report back to objectstack#11592 — that evidence reopens the ruling; do not silently absorb it with an override semantic.
Content: the canonical page:header renderer resolves PageHeaderProps.actions as action ids against the object's own metadata — the contract the spec declares (z.array(z.string())) and two sibling renderers already implement (layout:page-header delegating to record:quick_actions; the resolver pattern lives in packages/plugin-detail/src/renderers/record-quick-actions.tsx). Reuse that pattern, do not invent a second resolver. Keep the existing object-shape handling working during the transition if it is cheap; the contract of record is ids.
Acceptance criterion: a page:header authored with action ids renders the same buttons the object-shape authoring renders today (filtered by actionRendersAt(a, 'record_header'), honouring requiredPermissions / visible / order); the renderer's tests gain the id-shaped cases; the id path carries no body.source into the built artifact.
Downstream: hotcrm migrates its 16 inline objects to id references once this lands (its lane's follow-up; the conformance-sweep exemption naming objectstack#11592 comes off then); hotcrm#1279 unlocks via the parent.
Blocked-by: objectstack-ai/objectstack#12580
Implementation of the objectstack#11592 ruling (maintainer, 2026-08-25, verbatim 「全部同意」 on recommendation B; full record = objectstack#11592 comment 5405065025). Filed by PM session
session_01KWRU3s15AJz7PGW7a7wdChper the confirmed checklist. Parent: objectstack#11592 (tracking).Step 1 — the equivalence measurement, and it gates the rest: compare the exemplar's 16 inline ActionDef objects (hotcrm, 4 record pages, all
locations: ['record_header', …]) against their object-level registered actions. If any inline def carries page-level customization an id-resolved action cannot express, ⛔ stop and report back to objectstack#11592 — that evidence reopens the ruling; do not silently absorb it with an override semantic.Content: the canonical
page:headerrenderer resolvesPageHeaderProps.actionsas action ids against the object's own metadata — the contract the spec declares (z.array(z.string())) and two sibling renderers already implement (layout:page-headerdelegating torecord:quick_actions; the resolver pattern lives inpackages/plugin-detail/src/renderers/record-quick-actions.tsx). Reuse that pattern, do not invent a second resolver. Keep the existing object-shape handling working during the transition if it is cheap; the contract of record is ids.Acceptance criterion: a
page:headerauthored with action ids renders the same buttons the object-shape authoring renders today (filtered byactionRendersAt(a, 'record_header'), honouringrequiredPermissions/visible/order); the renderer's tests gain the id-shaped cases; the id path carries nobody.sourceinto the built artifact.Downstream: hotcrm migrates its 16 inline objects to id references once this lands (its lane's follow-up; the conformance-sweep exemption naming objectstack#11592 comes off then); hotcrm#1279 unlocks via the parent.