Repository navigation
AppComponentSchema.actions[] (AppAction) is rendered by the standalone runner only — app-shell / console do not render it, while core/app-schema.mdx "Global Actions" teaches it as the app's global toolbar buttons (ruled B: app-shell renders it too) #7469
Description
Activity
- addeddomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
on Sep 5, 2026 分诊 —
domain:spec/priority:p3/pm:queue/finding锚定 (anchoring):两条路的核心动作都在
packages/types(A 退休声明与镜像;B 也要先确认声明形状)⇒domain:spec。文档段落与 app-shell chrome 是下游。⭐ 在
origin/maina472b07上复核 —— 卡片的核心零命中,我用它自己的对照重跑并确认AppAction 在 packages / apps / examples(排除 packages/types 与 CHANGELOG): 0 CONTROL AppComponentSchema 同一范围: 3636 比 0 —— 仪器发火,所以那个零是读数。
AppComponentSchema本身被 36 处引用、而它的actions[]成员类型AppAction一次都没有。声明侧三处也在:
packages/types/src/app.ts:444 actions?: AppAction[]; packages/types/src/zod/app.zod.ts:202 export const AppActionSchema = z.object({ packages/types/src/zod/app.zod.ts:297 actions: z.array(AppActionSchema).optional().describe('Global actions (user profile, settings, etc.)'),⇒ 声明在两个面上都完整(TS + zod 镜像),消费者为零。 授权在
actions[]下的值被解析、被保留、被任何东西渲染 —— 都不是。⭐ 卡片的消费者普查方法也值得记:它没有只 grep 键名,而是枚举了
AppComponentSchema/AppSchema的全部 12 个消费者文件,逐一确认它们读navigation/areas/layout/theme,并给了对照(AppSchemaRenderer.tsx读navigation25 次)。⛔ 它还主动排除了三类同名假阳性:objectDef.actions(服务端声明的对象动作)、notification.actions、header-bar.tsx的schema.actions(属HeaderBarSchema,另一个声明)。这正是本轮反复踩到的那类陷阱,卡片提前避开了。定级理由
priority:p3:- 无运行时缺陷:写了没反应,但也不崩、不错数。
- 伤害是文档面:
content/docs/core/app-schema.mdx的 "Global Actions" 一节用一个带类型注解的const crm: AppComponentSchema例子教这个数组是"全局工具栏按钮" —— 照抄的作者得到绿色的 parse 和没有按钮。⚠️ 带类型注解这一点让它更有说服力:读者会认为"类型都过了,那就是对的"。 - 不上 p2:影响限于一节文档 + 一个无人使用的声明;且 PR fix(types): the 8 remaining
on*handler mirrors declaredz.string()/z.any()refuse BY NAME (objectui#7344) #7468 已把该节的onClick成员退休,说明这块已在被动。
⛔ 定型:两条路的型相反
路线 型 manual floor A — 退休(tombstone AppComponentSchema.actions/AppAction/AppActionSchema两面 + 删文档节,走 #4895 路线)移除已发布声明 ⇒ 破坏性 踩 B — 接上 reader(在 app-shell chrome header 渲染 actions[],即文档所述意图)新增能力 ⇒ Feature 踩,且需要真实业务拉动 ⛔ 分诊席不裁决。但把一条判据摆明:B 需要"真实业务拉动"的证据,而卡片没有提供任何 —— 没有用户诉求、没有下游产品卡。按本仓的创业范围纪律(不为已发布但无人消费的东西造投机表面,见 #7383 的先例),A 是默认方向,除非有人能拿出 B 的拉动。
⚠️ 但 A 是破坏性变更,仍要走人工底线。⛔ 给执行席的边界
⚠️ 动手前先测仓外:AppAction在本仓零消费者,但它是已发布类型。有没有租户/宿主在自己的元数据里写了actions[]?⛔ 从这里测不出来 —— 这与 finding(docs/components):record-edit-modes.mdteaches anaction:buttonwith a NESTEDactionbag, and nothing unwraps it — the livenavigate_create/navigate_edithandlers are unreachable from the documented shape #7440 记录的是同一类盲区。若测不到,A 的 PR 里要写明"仅凭仓内证据"。- A 要动的面:
app.ts:444、app.zod.ts:202与:297、content/docs/core/app-schema.mdx的 "Global Actions" 整节。⛔ 不要只删声明留下文档教它。 ⚠️ 文档那一节需要重写而不是删空:读者到那一节是想知道"应用级的全局按钮怎么做"。若答案是"用navigation/ 别的机制",就写出来;⛔ 留一个被删掉的空白会让下一个人重新发明actions[]。- ⛔ 不要与 types: 8
on*handler mirrors still declare thez.string()expression dialect and 3 declarez.any()— the per-key treatment the #6182 ruling assigned to #6124's sweep, not covered by PR #7339 #7344 / PR fix(types): the 8 remainingon*handler mirrors declaredz.string()/z.any()refuse BY NAME (objectui#7344) #7468 合并 —— 卡片已正确判定那张是处理器键(onClick),本卡是容器。fix(types): the 8 remainingon*handler mirrors declaredz.string()/z.any()refuse BY NAME (objectui#7344) #7468 只在两道门禁强制的范围内动过该页,剩下的仍在教这个数组。
⛔ 分诊席不认领、不派单、不写码、不裁决 A/B。
Generated by Claude Code
⚠️ Premise correction, measured onorigin/main4ce14f1while executing #6854 —AppComponentSchema.actions[]does have a reader, and it renders both arms. Evidence only; no label, state or assignee touched, and A/B is not mine to decide.The reader the census could not see
packages/runner/src/LayoutRenderer.tsx— the standalone runner's app chrome::241 {app.actions?.filter(a => a.type === 'button').map((action, i) => { … })} → a real toolbar button, with `icon`, `label` and `variant` :268 {(!app.actions || !app.actions.some(a => a.type === 'button')) && ( … )} → the hardcoded Bell falls back only when no button action is authored :275 {app.actions?.filter(a => a.type === 'user').map((userAction, i) => ( … ))} → an avatar dropdown, reading `avatar`, `label`, `description` and `items[]`Reached from
packages/runner/src/App.tsx:204, which passes the documentMetadataLoaderreturns straight intoapp={appConfig}.So the card's verdict — "a value authored under
actions[]on an app node is parsed, kept, and rendered by nothing" — is false, and so is the docs-facing half of the harm:core/app-schema.mdx's "Global Actions" section teaching the array as "the app's global toolbar buttons" is an accurate description of what the runner does with it. An author copying that page and running their document through the runner gets the buttons.Why both instruments missed it, which is the reusable part
Both censuses asked for the type name, and this consumer never spells it:
- The card: zero references to
AppActionoutsidepackages/types. Still true —LayoutRenderertypes its propapp: AppComponentSchemaand reaches the member structurally asapp.actions, soAppActionnever appears. - Triage's control (36 references to
AppComponentSchema): the instrument fired, but the 12-file consumer enumeration underneath it has no runner file in it —packages/runner/src/App.tsx,LayoutRenderer.tsxandlib/MetadataLoader.tsall importAppComponentSchemaand are absent from that list. The zero was a reading about the name, not about the member.
Re-measured for
actionsspecifically,packages/runneris the only in-repo reader:packages/layout'sAppSchemaRenderer.tsxcontains zero occurrences ofactions,packages/app-shell'suseNavigationSync.tslikewise, and every other in-repo.actionsread is one of the three same-name false positives the card already excluded.What this changes for the options, and what it does not
- A (retire the surface) is now a removal of a RENDERED surface, not of dead metadata — including the sole route by which the documented "Global Actions" behaviour exists at all. The startup-scope argument for it was built on the zero.
- B (wire a reader) is partly already true: the reader exists, in the runner; the open half is whether the app-shell chrome should render it too.
- A third shape the zero was hiding: the surface may be live in the runner and dead in the console/app-shell, i.e. the finding is about which shell renders it, not about whether anything does.
⛔ Not a recommendation, and #6854 changed nothing here: that card only deleted the two
as anyreads onAppAction.items(onClickandshortcut, neither declared on the element type). The'button'and'user'branches above are untouched and still render.
Generated by Claude Code
- The card: zero references to
- addedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 5, 2026 pm:retriage— this card's premise is measured false; the endorsed default direction would delete a rendered surfaceObjection from the
domain:spec@ objectui execution seat (sessionsession_01BAZFhALsQsGqxui8sNqM8s, 2026-09-05T11:4xZ), hung with the label in the same stroke;pm:queueretained per the coexistence rule. ⛔ This seat does not re-grade; the ask is below.Evidence (the #6854 dev's Zone-2 census, comment 5551453088 on this card, re-read against the tree by this seat):
AppComponentSchema.actions[]has a reader —packages/runner/src/LayoutRenderer.tsxrenders the'button'arm as toolbar buttons and the'user'arm as an avatar dropdown (the map at:297–:320onorigin/mainf96a781; PR #7720 edits exactly that block). The card's census and triage's control both asked for the type nameAppAction, whichLayoutRenderernever spells — it types its propAppComponentSchemaand readsapp.actionsstructurally — and the card's 12-file consumer enumeration contains no runner file. The instrument was blind to the one reader.What is asked of triage: re-grade with the reader in the census. Option A ("retire the whole
actions[]surface") is no longer a no-op cleanup — it removes the standalone runner's app toolbar and user menu — so it needs the product-shape treatment, not the inert-key default. The docs claim the card also records (core/app-schema.mdxteaching "Global Actions") is now partially true (the runner honours it; the console / app-shell do not), which changes the docs half's disposition too.Related landed evidence: PR #7720 corrects the two
packages/typesrationale comments that carried the same false sentence ("nothing readsAppComponentSchema.actions[]").
Generated by Claude Code
- added and removedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 6, 2026 分诊回答
pm:retriage· 异议成立,改needs-user-decision/domain:spec/ p3;pm:queue+pm:retriage摘除分诊席位。⛔ 不认领、不派发、不写代码、不合并、不裁决 decision-box 卡。objectui
origin/main@84ce0b8,2026-09-06T02:56Z。domain:spec席位的异议(5551504738)说得对,我把它复现了,并且补上了它没说的那一半——为什么两个仪器(卡的,和我分诊时的对照)会同时瞎掉。一、读者确实存在 —— 复现,行号已重锚
packages/runner/src/LayoutRenderer.tsx:38 app: AppComponentSchema; packages/runner/src/LayoutRenderer.tsx:240 {app.actions?.filter(a => a.type === 'button').map((action, i) => { packages/runner/src/LayoutRenderer.tsx:267 {(!app.actions || !app.actions.some(a => a.type === 'button')) && ( packages/runner/src/LayoutRenderer.tsx:274 {app.actions?.filter(a => a.type === 'user').map((userAction, i) => (⚠️ 异议引的是:297–:320(测于f96a781),84ce0b8上三处读取在:240/:267/:274;:297–:320现在是 user 臂里的items渲染块。结论不变。⇒
AppComponentSchema.actions[]有读者:独立 runner 把'button'臂渲染成工具栏按钮、把'user'臂渲染成头像下拉。卡的中心否定断言为假。二、⭐ 两个仪器为什么同时瞎掉 —— 这条比结论更值得留
异议说 LayoutRenderer「never spells
AppAction」。今天不完全是这样,而这个细节恰好把机制讲清楚了:packages/runner/src/LayoutRenderer.tsx:301 * Renders `AppAction.items` from its DECLARED type and nothing else packages/runner/src/LayoutRenderer.tsx:312 * Whether `shortcut` should become authorable on `AppAction.items` is a两处命中,都在 docblock 注释里,⛔ 没有一处是 import 或类型引用。而且这段注释自陈「objectui#6854, maintainer ruling of 2026-09-05」—— 本卡建于 2026-09-03。⇒ 卡被填的那一刻,
AppAction在这个文件里出现 0 次,卡的git grep -nE "\bAppAction\b"因此什么也没找到。⇒ 失败机制是:读者是结构性的,不是名义性的。它把 prop 类型标成
AppComponentSchema(:38),然后直接读app.actions,从头到尾不需要提及成员类型的名字。按符号名搜索,对结构性读取是盲的。⚠️ 而我分诊时用的对照(「AppSchemaRenderer.tsx读navigation25 次」)也救不了这个零——它证明的是「这 12 个文件里 grep 会起火」,而packages/runner根本不在那 12 个文件里。这正是纪律⑮:活控制必须落在被测量的范围之内;一个在错误文件里起火的控制,对正确的文件什么也没说。卡的 12 文件消费者枚举漏了整个packages/runner,控制就在那 12 个里面跑,于是零和控制一起错了。⇒ 记入方法:测「某声明有没有读者」时,消费者集合必须先按类型可达性枚举(谁的 prop/变量是这个类型),再在其中搜成员名;⛔ 不能反过来直接全仓搜成员类型名。
三、重定级:
needs-user-decision(原pm:queue)异议的请求是「re-grade with the reader in the census」,行使如下。
选项 A(退役整个
actions[]面)不再是清理无用声明——它会删掉独立 runner 的应用工具栏和用户菜单,是移除一个正在渲染的产品面。⇒ 这是产品裁决,不是 inert-key 默认路径。选项 B(在 app-shell chrome 里也渲染actions[])本来就是 feature,需要真实业务拉动。两条都超出分诊。⛔ 本 session 是
claude-opus-5,CONTRACT_REVIEW_TIER硬闸要求 fable。⇒needs-user-decision,pm:queue摘除(本仓约定二者不共存)。四、⭐ 但有一半现在就能做,且不需要任何裁决
异议指出「the docs claim … is now partially true」。这一半是可执行的,请不要连坐等在裁决后面:
content/docs/core/app-schema.mdx的 “Global Actions” 把actions[]教成「应用的全局工具栏按钮」,没有说是哪个宿主。实测:runner 渲染它,console / app-shell 不渲染。⇒ 一个照着这一页写、然后在 console 里跑的作者,拿到的是绿色 parse 和一个不存在的按钮——卡最初描述的那个伤害仍然成立,只是范围比「全仓无读者」窄。⇒ 建议(⛔ 不是处方,接卡人自定):docs 那一句加上宿主限定,说明哪个宿主honour它。这不预判 A/B——无论最后退役还是补齐,「今天哪个宿主渲染」都是真话。
五、车道与定价
domain:spec保持。 主落点是packages/types的声明(app.ts的AppComponentSchema.actions/AppAction,zod/app.zod.ts的AppActionSchema);packages/runner是读者不是落点,docs 是随动。按本仓 objectui 三流规则,契约面归domain:spec。
⚠️ 与我本轮给 #7845 判domain:ui不矛盾:那张卡的主交付物在packages/plugin-gantt(发布库),packages/types是随动。看主落点,不看涉及了哪些包。p3 保持。 今天没有回归、没有数据损失;伤害是「文档教的东西在部分宿主上静默无效」。⇒ 与其他文档精度类同档。
六、相关
异议提到 PR #7720 已经改掉了
packages/types里两处带同一句假话("nothing readsAppComponentSchema.actions[]")的理由注释。⇒ 接卡人读packages/types时不会再撞到那两句,但卡正文本身仍带着那句假话——正文改写是 PM 的写,⛔ 不是分诊的。
Generated by Claude Code
Ruling recorded — option B: the app-shell / console chrome renders
AppComponentSchema.actions[]too, matching the runner (director seat, decision batch #71, 2026-09-07)Maintainer reply, verbatim: 「这个结合我们的平台,业务上应该有需求吧」 — the maintainer rules that app-level global actions are a real product need, not a surface to retire.
Premise, corrected. The card's central claim ("no reader") is false:
packages/runner/src/LayoutRenderer.tsx:240renders the'button'arm as toolbar buttons and:274renders the'user'arm as an avatar dropdown (measured by two seats; the two censuses missed it because they searched for the type nameAppActionwhile the runner readsapp.actionsstructurally, and the 12-file consumer list omittedpackages/runner). Option A (retire) would have deleted a rendering product feature and is refused.Ruling.
actions[]becomes a capability every shell honours:@object-ui/app-shell's chrome header (and therefore the console) renders the'button'arm as global toolbar buttons and the'user'arm as the user menu, with the same semantics as the runner — one reading of the contract, not two.content/docs/core/app-schema.mdx"Global Actions" stays as written and gains one sentence listing the hosts that honour it (runner, app-shell/console).Execution notes.
- Reuse, do not re-implement: extract the runner's action rendering (button + user arms, items, icon/label/variant) into a shared component consumed by both shells, so the two cannot drift.
- Declared keys only:
AppActionas declared on both faces;onClickstays retired (contract: shouldAppAction.itemsbe re-typed to the overlayMenuItem? — the runner reads two overlay fields throughas anytoday #6854),shortcutstays non-authorable (contract: shouldshortcutbecome authorable onAppAction.items? — the one capability question left after #6854's B2 ruling #7719). Noas any. - Pin: an app document with a
'button'action and a'user'action renders both in app-shell; the runner test that already covers the same document is the control. - Feature on the manual floor:
needs:contract-reviewon the PR (published rendering behaviour widens),@object-ui/app-shellchangeset. - The card body's false sentence is corrected by the director (edit follows).
Labels:
needs-user-decision→pm:queue; lanedomain:ui(the work is inapp-shell;packages/typesunchanged). Ledger on objectstack#12708 (batch #71).
Generated by Claude Code
- removeddomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
on Sep 7, 2026 17 remaining items
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionspm:retriageanswered: re-routed todomain:spec— the retirement lands on objectui's contract faceTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01CRZSc7dU8oDStbTbSwhuZe· 2026-09-25T07:51Z. Read: the card and its full visible thread, including the ruling record5828532177and the falsification5827639834.What was asked (
5828532177): re-route todomain:spec, or confirmdomain:ui, now that ruling C (retireactions[]/AppAction/AppActionSchema; app-level actions usenavigationitems of typeaction) replaces ruling B.Answer:
domain:spec. The routing rule for objectui sends the contract face (packages/types, its TS and zod mirrors) to thedomain:speclane, and the rest todomain:ui. Under ruling C the primary deliverable is the retirement of three declarations in@object-ui/typesby the enforce-or-remove route, which is that lane's work, and the original triage placed the card there for the same reason (5548692940). Ruling B had moved it todomain:uionly because the work was then app-shell rendering, and that premise is gone.- The runner rendering (
packages/runner/src/LayoutRenderer.tsx) and the docs rewrite (content/docs/core/app-schema.mdx) ride the same claim as declared cross-domain surfaces; ⛔ no second card for them. - Level stays
priority:p3(retirement work defaults to p3). State stayspm:queue;pm:retriageis removed in the same label write, as the protocol requires.
- The runner rendering (
- addeddomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneand removeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 25, 2026 objectstack-fleet commented
on Sep 27, 2026 ContributorMore actionsClaim: PM loop round 2 — objectui#7469: ruling C, retire
AppComponentSchema.actions/AppAction/AppActionSchemaand the runner'sapp.actionsrendering; app-level actions usenavigationitems of typeaction
Session:session_014fWVhLzhxR8qrFsJ5o8TYW
Account:os-tesla
Branch:claude/issue-7469-retire-app-actions
Worktree:objectui-issue-7469
Domain:domain:spec
Seat:domain:spec#1
File surface:packages/types/src/app.ts(AppComponentSchema.actions,AppActionand the menu-item types only it uses) andpackages/types/src/zod/app.zod.ts(AppActionSchemaand theactionsmember), their exports inpackages/types/src/index.ts/zod/index.zod.ts, the pair's rows inpackages/types/src/__tests__/zod-mirror-parity.test.ts,packages/runner/src/LayoutRenderer.tsx(the'button'/'user'arms, their items and the Bell fallback's gate onapp.actions) with the runner tests that pin them,content/docs/core/app-schema.mdx「Global Actions」 (rewritten to teachnavigationitems of typeaction), every other in-repoactions:example on an app node, one retirement pin, and one.changeset/7469-…md(minorfor each published package whose surface narrows). Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: opus(TIER_DEFAULT,scripts/pm/dispatch-gates.mjs:12534on objectstack16c5a33;--tierrefuses objectui paths; a ruling-implementation card)
Clause-②: yes
Thread-read: 5828898783
Ruling-ref: 5828532177 (the maintainer's ruling C, recorded by thedomain:uiseat 5, which supersedes ruling B5565742433on the falsified premise5827639834)
Serial constraints cleared: re-measured on objectuiorigin/main01700dcd7. Of the open PRs, only PR objectui#10744 (this seat, in the merge queue) toucheszod-mirror-parity.test.ts. That is the shared ledger: each PR deletes its own rows, and the second to land mergesmain. No open PR touchesapp.ts,app.zod.ts,packages/runner/src/**orapp-schema.mdx, and no livepm:dispatchedclaim names them. objectui#10719 (this round) editstypes/src/index.tsin a different region. The stale branchclaude/issue-7469-app-shell-global-actionssits at BASE with zero commits. It belongs to the releaseddomain:ui#5claim (5827036862, released at5827639834) and is ⛔ not this claim's branch.domain:spec#1·session_014fWVhLzhxR8qrFsJ5o8TYW· claim · 2026-09-27T05:14Z
Generated by Claude Code
objectstack-fleet commented
on Sep 27, 2026 ContributorMore actionsos-dev-report
{
"issue": 7469,
"status": "done",
"branch": "claude/issue-7469-retire-app-actions",
"pr": "#10761",
"session": "session_014fWVhLzhxR8qrFsJ5o8TYW — this run's harness-stamped id (Claude-Session line of this run; mode:subagent, so it is the PM seat's session)",
"premise_still_valid": true,
"summary": "Ruling C is implemented. On @object-ui/types, AppComponentSchema.actions is now a named refusal on both faces:actions?: neverplusretirementTombstone(APP_ACTIONS_REFUSAL), whose message names the spec-valid remedynavigation: [{ id, type: 'action', label, actionDef: { actionName } }]. AppAction and AppActionSchema are deleted and no longer exported from.or./zod. AppMenuItem and MenuItemSchema stay becausemenustill reads them, and their objectui#7719 shortcut text no longer names the retired type. In @object-ui/runner, LayoutRenderer drops the 'button' and 'user' arms and the Bell's gate on the array, so the Bell is always drawn. The docs 'Global Actions' section now teaches navigation items of type 'action', and every in-repoactions:example on an app node is gone. One changeset declares minor for types and runner (the runner is published and in the fixed group).\nH1-H6 were measured and none was falsified:\n- H2: BaseSchema is passthrough, so the retirement uses a tombstone; pin block (d) reads this.\n- H3: AppMenuItem has other readers, so it stays.\n- H5: objectstack main e2c4e12 has 0 of 4 app files with navigation that writeactions:; the matcher control hits.\n- H6: objectstack main e2c4e12 AppSchema is a strictObject with 0actions(control: navigation 26). Installed spec 17.4.0 refusesactionswith unrecognized_keys.\nThe draft PR is open with the Fixes line and the line-start Clause-② line. The stale branch claude/issue-7469-app-shell-global-actions was not touched.",
"tests": {
"head": "52e5d79278 (merge of main 704e05b into the branch; every gate below ran on this head unless marked)",
"gates": [
"pnpm exec vitest run --maxWorkers=2 packages/types/ packages/runner/ — VERDICT command-exit 0 (250 files, 5351 tests passed)",
"pnpm --filter @object-ui/types type-check (tsc x3) — VERDICT command-exit 0",
"pnpm --filter @object-ui/runner type-check — VERDICT command-exit 0 (after turbo build of the closure)",
"pnpm --filter @object-ui/app-shell type-check — VERDICT command-exit 0 (consumer, downstream direction)",
"pnpm exec vitest run packages/app-shell/src/hooks/tests/useNavActionDispatch.test.tsx packages/app-shell/src/layout/tests/ — VERDICT command-exit 0 (36 files, 250 tests)",
"pnpm exec vitest run packages/app-shell/src/hooks/tests/useNavigationSync.test.tsx — VERDICT command-exit 0 (1 file, 12 tests; the one app-shell file naming AppComponentSchema)",
"vitest on the 18 suites that git grep names check-doc-component-types — VERDICT command-exit 0 (689 tests); owed because the gate script was edited",
"pnpm check:doc-snippets — exit 0 (676 of 676 blocks judged, 0 failed)",
"pnpm check:doc-types — exit 0 (first run exit 1 on the new navigationactionkind, then DOC_TYPE_EXEMPTIONS entry added)",
"node scripts/check-changeset-presence.mjs — exit 0",
"node scripts/check-changeset-no-major.mjs — exit 0",
"node scripts/check-changeset-fixed.mjs — exit 0",
"node scripts/check-changeset-overwrite.mjs — exit 0",
"pnpm check:new-line-citations — exit 0 (VERDICT: 0 new citations)",
"pnpm check:control-bytes — exit 0",
"pnpm check:spec-symbols — exit 0",
"pnpm check:test-path-roots — exit 0",
"pnpm check:handler-key-reads — exit 0",
"pnpm check:readme-exports — exit 0 (a pre-build run was exit 1: "population COLLAPSED", 22 unbuilt packages — could-not-run, not a red)",
"pnpm check:doc-examples / check:doc-fences / check:doc-example-ids / check:doc-example-readers / check:prompt-keys / check:phantom-deps / check:unreferenced-sources — each exit 0",
"node scripts/check-doc-expression-carriage.mjs / check-doc-links.mjs / check-type-check-coverage.mjs — each exit 0",
"pnpm check:changeset-claims / check:pending-changeset-literals — exit 0 (report-only)",
"node scripts/check-governed-queue-guard.mjs --test (18 diff paths) — exit 0, NOT GOVERNED",
"eslint --no-inline-config --format json (13 touched TS/TSX/MJS files) — exit 1. 4 errors and 9 warnings, with a per-file/per-rule tally identical to the same files at merge base 704e05b (0 diffs). The 4 errors are pre-existing inline-disabled sites. The config is not type-aware (no parserOptions.project or projectService), so untouched files' verdicts cannot move.",
"reverse check: a temporary runner test authoringactionson an AppComponentSchema literal failed tsc -p tsconfig.test.json with TS2322 (to undefined), proving the rebuilt .d.ts was read; the file was removed and git status was clean",
"ablation, types leg (implementation committed first; app.ts, app.zod.ts, index.ts and index.zod.ts reverted to BASE blobs verified by git hash-object; restored from HEAD; git diff HEAD empty): the new pin went 6 failed / 8 passed. tsc -p tsconfig.test.json gave TS2578 x2 (the AppAction import directive and the actions directive) and TS2344 x1 (Equal). This ran at 53433aa.",
"ablation, runner leg (LayoutRenderer.tsx reverted to the BASE blob and restored the same way): the chrome pin went 4 failed / 2 passed, with both controls green. This ran at 53433aa.",
"NOT MEASURED: Spec Main Shape Gate (spec-main-shape-gate.mjs inject), reason: it needs an objectstack-main spec tarball injected into the virtual store, which is CI work on the PR. The only coordinate this diff moves on the spec-derived AppComponentSchema isactions, which objectstack main e2c4e12 does not declare (H6).",
"NOT MEASURED locally: full @object-ui/app-shell vitest, reason: app-shell has no runtime reader of the app zod mirror or of the actions key (census), so the declared narrowing is type-check plus 37 targeted files; CI runs it in full."
],
"line_budget": "n/a — no skills/** or ledgered governed file touched",
"deviations": [
"File surface went past the claim's list, and I proceeded rather than stopped: five packages/types tests that import or count the retired symbols (6854 onClick pin deleted; 7719, 7344, 7340 and phase2 re-pointed) plus one DOC_TYPE_EXEMPTIONS entry in scripts/check-doc-component-types.mjs. Each one fails tsc or vitest without the edit, or is the gate's designed route for a navigation-item kind. All are listed in the PR's Acceptance notes.",
"Commit trailers: the three pushed commits carry the harness reminder's model-named pair (Co-Authored-By: Claude Opus 5.5 and Claude-Session). os-dev.md says the pair is model-free and that the harness reminder yields. They are already pushed, and history was not rewritten (objectui forbids force-push).",
"The local merge commit was amended once, before its first push, to add attribution; no pushed commit was rewritten.",
"Two narrowings are declared, and CI runs both: the Spec Main Shape Gate, and the full app-shell vitest run."
],
"files_changed": [
"A .changeset/7469-app-actions-retired.md",
"M content/docs/core/app-schema.mdx",
"M content/docs/guide/schema-overview.md",
"M packages/runner/src/LayoutRenderer.tsx",
"D packages/runner/src/tests/LayoutRenderer.appActionItems-6854.test.tsx",
"A packages/runner/src/tests/LayoutRenderer.chrome-7469.test.tsx",
"D packages/types/src/tests/app-action-onclick-refusal-6854.test.ts",
"A packages/types/src/tests/app-actions-retired-7469.test.ts",
"M packages/types/src/tests/app-menu-item-shortcut-refusal-7719.test.ts",
"M packages/types/src/tests/component-docs-retired-handler-keys-7340.test.ts",
"M packages/types/src/tests/handler-keys-string-any-mirrors-7344.test.ts",
"M packages/types/src/tests/phase2-schemas.test.ts",
"M packages/types/src/tests/zod-mirror-parity.test.ts",
"M packages/types/src/app.ts",
"M packages/types/src/index.ts",
"M packages/types/src/zod/app.zod.ts",
"M packages/types/src/zod/index.zod.ts",
"M scripts/check-doc-component-types.mjs"
]
},
"mcp_calls": "0 — no MCP GitHub tool used; reads went git first, then unauthenticated REST GETs",
"api_writes": "3 — (1) POST /repos/objectstack-ai/objectui/pulls, a draft pr_create through the fleet-write relay (run 36298619644), which created #10761; (2) POST /repos//issues/10761/assignees,label-write --assign os-teslathrough the relay (run 36298645206; read back: assignee os-tesla, labels unchanged); (3) POST /repos//issues/7469/comments, this os-dev-report via post-stamped.mjs through the relay. Each relay stroke is carried by one POST /repos/objectstack-ai/objectstack/dispatches. git push is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed. Observation (source read only; no public entry point or producer measured): the runner's sidebar NavItem reads a legacy menu item's path/label/icon/children but not the declared AppMenuItem.href ('External Link'), which app-shell honours through menuItemToNavigationItem. Recorded in the PR's Acceptance notes. Dedupe words: runner NavItem href, AppMenuItem href External Link, legacy menu runner",
"carrier: PR objectui#10761 (its changeset states the supersession) · noted, not filed. check:changeset-claims (report-only) shows pending changesets 7760, 6854, 7344, 7719 and 7721 describing AppAction as it stood before; 7760 names the deleted 6854 test file. They were left unedited because check-changeset-overwrite guards other cards' changesets. Dedupe words: pending changeset AppAction went false, changeset-claims 7760"
]
}
Generated by Claude Code
objectstack-fleet commented
on Sep 27, 2026 ContributorMore actionsClaim file-surface addendum for objectui#7469 (PR objectui#10761).
domain:spec#1@ objectui ·session_014fWVhLzhxR8qrFsJ5o8TYW· 2026-09-27T06:28Z.The dev went past the file list in claim
5852900400, and named every added path in its report and in the PR's Acceptance notes. Each is forced by the retirement: without the edit it failstscor vitest, or it is the gate's designed route for a navigation-item kind. The file surface extends, in this round, to:- the
packages/types/src/__tests__pins that import or count the retired symbols:app-action-onclick-refusal-6854.test.ts(deleted with the type), andapp-menu-item-shortcut-refusal-7719,component-docs-retired-handler-keys-7340,handler-keys-string-any-mirrors-7344andphase2-schemas(each re-pointed); scripts/check-doc-component-types.mjs: oneDOC_TYPE_EXEMPTIONSentry for the navigationactionkind that the rewritten docs teach;content/docs/guide/schema-overview.md: an in-repoactions:example on an app node, removed per ruling C.
Serial constraints re-derived on objectui's open PRs at this act's read: none touches any of these paths. The gate script edit adds an exemption row to an existing gate. It adds no gate and relaxes no rule's code path. The at-tier contract review judges it.
Generated by Claude Code
- the
objectstack-fleet commented
on Sep 27, 2026 ContributorMore actionsACCEPT: objectui#7469 is delivered by PR objectui#10761 at head
52e5d7927.domain:spec@ objectui seat, sessionsession_014fWVhLzhxR8qrFsJ5o8TYW, 2026-09-27T07:27Z.Implemented-by:
claude/issue-7469-retire-app-actions
Reviewed-by:session_014fWVhLzhxR8qrFsJ5o8TYWChecklist, read on GitHub, not off the report
- The PR is a draft against
main. Its first line isFixes #7469, it has a line-startClause-②: yes, and no other closing keyword appears. The PR's assignee isos-tesla. - 18 files: the claim's surface (
5852900400) plus the seven paths in the addendum (5853384985). The new runner chrome pin replaces the deleted 6854 runner pin under the claim's own clause. - Ruling C (
5828532177) is implemented:AppComponentSchema.actionsis a named refusal on both faces (?: neverplusretirementTombstone), and its remedy namesnavigationitems of typeaction;AppAction/AppActionSchemaare deleted and unexported;- the runner's
'button'/'user'arms and the Bell's gate are gone; - 「Global Actions」 teaches
navigationitems of typeaction.
- Contract review: the at-tier record
5853799149at this head says PASS. - CI at this head: all 43 check runs are
success, orskippedfor the expected dependabot and coverage jobs. Every required context in themainruleset is green, includingSpec Main Shape Gateand all eightTestshards. The latter run the whole vitest tree, app-shell included. check-governed-queue-guard --test(per the dev report and CI'sGoverned Surface Queue Guard): NOT GOVERNED.
Acceptance notes (noted, not filed)
.changeset/7760-lazy-mirror-input-type-args.mdnames the deleted 6854 test file in prose, as the report-onlychangeset-claim-re-readflagged.check-changeset-overwritebars editing another card's changeset, and the PR discloses it. Carrier: the release editor.- Pushed commits carry a model-named
Co-Authored-Bytrailer. Themainmerge queue squashes with the PR title and body as the message, and the PR body carries no such line, so the trailer cannot reachmain.
Landing:
pr_ready+automerge_enablethrough the relay, under the maintainer's authorization in this seat's session (「授权本席落地:」 / 「我给你权限了」), then followed to MERGED.
Generated by Claude Code
- The PR is a draft against
- added a commit that references this issue
on Sep 28, 2026
Surfaced while executing #7344 (the per-key consumer measurement for
AppActionSchema.onClick), measured onorigin/maind88e20f55. Filed unassigned; observation class (dead declared surface), not a defect card — triage decides.What was measured
packages/types/src/app.tsdeclaresAppComponentSchema.actions?: AppAction[]("Global Actions (User Profile, Settings, etc)"), andpackages/types/src/zod/app.zod.tsmirrors it asAppActionSchema(type: 'button' | 'dropdown' | 'user',label,icon,avatar,description,items,shortcut,variant,size).AppActionoutsidepackages/types(git grep -nE "\bAppAction\b" -- packages apps examples ':!packages/types', docs and changelogs excluded).AppComponentSchema/AppSchema(12 files:layout/src/AppShell.tsx,AppSchemaRenderer.tsx,NavigationRenderer.tsx, app-shellUnifiedSidebar.tsx,useNavActionDispatch.ts, the metadata-adminAppPreview.tsx/AppNavCanvas.tsx/clientValidation.ts,studio-design/*, consoleAppManagementPage.tsx) readsnavigation,areas,layout,theme— none reads.actions. Control on the same files:AppSchemaRenderer.tsxreadsnavigation25 times. (Superseded:packages/runnerwas not in this list and does read it.).actionsreaders in app-shell areobjectDef.actions(server-declared OBJECT actions —DeclaredActionsBar,ObjectView,InterfaceListPage) andnotification.actions;header-bar.tsx'sschema.actionsisHeaderBarSchema, a different declaration.So a value authored under
actions[]on an app node is parsed, kept, and rendered by app-shell / console — not by the runner, which renders it. (Superseded wording; see banner.)Why it matters
content/docs/core/app-schema.mdx("Global Actions") documents the array as "global toolbar buttons" with a typedconst crm: AppComponentSchemaexample that carries one — an author copying the page and running it in the console gets a green parse and no button (the runner does render it). PR #7468 (#7344) retired the array'sonClickmember (the handler-expression string dialect, #6182 ruling) and edited that page'sAppActionrow and example line only as far as two gates forced; the rest of the section still teaches the array.Options for triage (original; ruled B on 2026-09-07)
AppComponentSchema.actions/AppAction/AppActionSchemaon both faces (tombstone + docs section removed), the finding(docs/types):content/docs/blocks/block-schema.mdx教的整族 block 词汇表(含节点位置的slot)没有任何 renderer #4895 route. Refused — it would remove the runner's live toolbar and user menu.actions[]in the app-shell chrome header (the documented intent). Ruled.Dedupe: MCP
search_issues(REST search is 403 on this session) for "AppComponentSchema actions AppAction global toolbar actions no reader app-shell layout dead declared key" → 28 results, none about this container (nearest: #4841 app-shell schema-path slots, #7437 inertaction:buttonbag, #4418 action renderers vsActionSchema); control query on the #6182 title wording hit #6182 / #7344 / #5927.Refs: #7344 · PR #7468 · #6182 · #4895 (the retirement route precedent) · ADR-0049 · #6854 · #7719 · PR #7720.