Skip to content

feat(spec): an action's param dialog can name its own submit verb — submitText - #28188

Merged
objectstack-fleet[bot] merged 15 commits into
mainfrom
claude/issue-27944-action-submit-label
Oct 31, 2026
Merged

objectstack-fleet[bot] merged 15 commits into
mainfrom
claude/issue-27944-action-submit-label

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

🤖 Generated with Claude Code

https://claude.ai/code/session_017ihL2fi9zfJhUTubyJYb6V

Fixes #27944

Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: follow-up owed — skills/objectstack-ui/rules/actions.md, skills/objectstack-ui/evals/views-apps-actions-pages.json, skills/objectstack-i18n/SKILL.md

维护者速读

  • 改了什么: 动作元数据新增一个可选键 submitText:动作收集参数的对话框里提交按钮上的文字(可翻译,字符串或内联多语言映射)。翻译位在 objects.OBJECT._actions.ACTION.submitText,translateAction 会套用译文。没有 params 的动作写这个键会被拒绝(它根本不会打开参数对话框),空字符串也被拒绝;翻译包里给无参数动作写这个键,os validate 报 translation-target-unknown。
  • 为什么改: 参数对话框的按钮永远写「Confirm / 确认」,发邮件、记录通话这类动作没法说「Send」「Log Call」。这是规格的一半;控制台对话框读取这个键在后续卡 Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158,本 PR 先落地。
  • 风险与回滚: 只加可选键,不写它的动作解析与显示都不变。控制台读取落地前没有渲染方读它(存活账本记为 planned,作者会收到 planned 提示)。回滚即 revert 本 PR。键名需要你批准: 我用了 submitText 而不是派发时提议的 submitLabel,理由见下文 The name;submitLabel 与 confirmLabel 作为别名改名到它。若你要 submitLabel,改名是机械的一次提交。
  • 先看: packages/spec/src/ui/action.zod.ts(新键、空白拒绝、无 params 拒绝、别名),packages/spec/src/system/i18n-resolver.ts(translateAction 只在有 params 时套用译文),packages/lint/src/validate-translation-references.ts(checkActionSubmitText)。
  • 两分钟验证: pnpm --filter @objectstack/spec exec vitest run src/ui/action-submit-text.test.ts,预期 18 个用例全部通过,其中一条断言无 params 的动作写 submitText 被拒、路径为 submitText。
  • 需要你做的: 批准键名 submitText(或指定 submitLabel),之后席位落地。

What changes

ActionSchema.submitText (packages/spec/src/ui/action.zod.ts), an optional key declared beside params. It is the label of the submit button in the dialog an action opens to collect its params ("Send", "Log Call"), in place of the dialog's default "Confirm".

  • The name (the maintainer approves it here). The order proposed submitLabel; measured on 549203d040, the protocol already has a word for a submit button's copy, object-form's submitText (I18nLabelSchema, beside cancelText / nextText / prevText, component.zod.ts). submitLabel is a spelling the platform retired twice in favour of that one: the element:form prop (18.ui__ElementFormProps__submitLabel tombstone) and the page component-copy translation key (translation-component-submit-label-removed, whose refusal tells the author "the live form surface's submit copy is object-form's submitText"). Reintroducing submitLabel as a live key here would teach the word those refusals point away from. It does not collide with confirmText: that is the MESSAGE of the confirm dialog a param-LESS action opens; this is the BUTTON of the param dialog, and the two never meet on one registered action (see the refusals).
  • The shape. An I18nLabel: a plain string with the NON_BLANK_STRING refinement (so the JSON Schema carries minLength + a \S pattern too), or InlineLocaleMapSchema. A blank string is refused, since it would replace "Confirm" with an empty button.
  • Only beside a non-empty params. The console's action runner opens the param dialog only for a non-empty params array, so submitText on any other registered action would parse clean and never show: refused at path submitText (ADR-0078's authoring-time rule, the mirror of the existing confirmText-beside-params refusal). Not picked onto InlineActionSchema, which does not pick description either.
  • Aliases. Exactly two, both measured on a neighbouring surface and neither reachable by distance (probed: the fallback offers nothing for either): submitLabel (above) and confirmLabel, the same button's spelling on a view's bulkActionDefs dialog. Both rename onto submitText on the action and in a translation bundle.
  • Translation. actionTranslationSchema declares submitText at both addresses (objects.OBJECT._actions.ACTION, globalActions.ACTION). translateAction overlays it like description, but only for an action that declares a non-empty params, the way resolveActionResultDialog reads nothing for an action with no dialog.
  • Lint. validateTranslationReferences gains checkActionSubmitText: a submitText translation under an action that declares no params is translation-target-unknown at error (the result-dialog leaves' rule, with params as the declaration). The action-entry coverage pin classifies the new key as reference-checked, backed by a ghost at both addresses.
  • Liveness. Row submitText is planned + authorWarn until the console reads it (Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 flips it). The metadata form ledger records the key as an omit row ("planned, not yet rendered", the page.print / field.conditionalFormatting precedent), so the Studio action form does not offer a control nothing draws; Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 deletes that row and adds the form row.
  • Forced neighbours. ui/packages/core/src/actions/actionKeys.ts lists submitText in SPEC_ACTION_KEYS (its pin walks the spec's ActionSchema; without it Test UI reds). packages/metadata-protocol's /meta/types action key count pin moves 48 → 49 and its sample names the key.
  • Docs. content/docs/protocol/objectui/actions.mdx gains "Naming the submit button: submitText" under Action Parameters and the property listing line; content/docs/ui/translations.mdx's action row names the new copy.
  • Changesets. @objectstack/spec minor (both declaration lines), @objectstack/lint patch, @object-ui/core patch (Metadata-protocol: none on both).

The console half is #28158 (domain:ui, label finding): both param-collection handlers resolve the key, ActionParamDialog draws it with actionDialog.confirm as the fallback, UIActionSchema derives it, the ledger row flips to live, and the action form offers it. It lands after this PR.

Independent review: none run (quota); the PR waits for the seat's contract-review hand-off.

Tests

  • packages/spec/src/ui/action-submit-text.test.ts (new, 18): string and locale-map parse; optional; non-I18nLabel shapes refused as label refuses them; blank and whitespace refused (code custom, path submitText, message first sentence); refused without params and with params: []; both aliases rename (unrecognized_keys, → submitText); not on the inline action; translation slot at both addresses, alias inside a bundle; translateAction overlays per locale, reads globalActions, falls back to the authored label, resolves a bundle label for an action that authors none, and gives no button to an action without params.
  • packages/lint/src/validate-translation-references.test.ts: submitText under param-less actions errors at both addresses (rule, severity, path, message first sentence); accepted under an action with params (control); coverage table entry + the all-keys real-instance control.
  • packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts: count 49, sample names submitText.
  • packages/spec/src/system/metadata-form-zod-reconciliation.test.ts: action / submitText omit row.

Acceptance notes

  • os i18n extract (packages/cli/src/utils/i18n-extract.ts) does not scaffold submitText yet; description and disabledReason are scaffolded there. Left out because packages/cli is outside this card's claimed file surface; a bundle written by hand resolves today. The seat decides whether it rides Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 or its own card.
  • A view's bulkActionDefs dialog already has its own button label key, confirmLabel (a plain string, not an I18nLabel); this PR does not touch that surface.

Verification

Local readings, all on head 734502240e (branch merged with origin/main once before opening; packages/spec rebuilt after the merge).

Targeted tests
  • @objectstack/spec: vitest run src/ui src/system: 229 files, 7942 tests, 1 failure, the metadata form reconciliation pin asking for the submitText row. Fixed by the omit row; re-run of that file plus action-submit-text.test.ts: 2 files / 94 tests passed.
  • @objectstack/spec typecheck: exit 0 (check:test-typecheck: OK).
  • @objectstack/lint: validate-translation-references.test.ts + lint-liveness-properties.test.ts: 2 files / 332 tests passed.
  • @objectstack/metadata-protocol (dependency closure built first): protocol.meta-types-degenerate-derivation.test.ts: 18 tests passed.
  • ui/ packages/core/src/actions/__tests__/actionKeys.pin.test.ts (from the ui/ root): 19 tests passed.
  • pnpm --filter @objectstack/spec check:generated: exit 0 after --fix regenerated content/docs/references/** (4 pages) and the build wrote authorable-surface/ui.json; gen:liveness-counts moved action to planned 1 / classified 50.
Derived gate families (dispatch-gates --commands, 109)

--ran reconciliation: 109 derived, 105 run, 4 NOT-MEASURED, 0 UNRUN. 104 exited 0.

  • NOT MEASURED (exit 3, prerequisite: unbuilt workspace packages in this container): check:skill-examples, check:dual-build-cjs-loads, check:i18n-walk-parity, check:lean-entry-closure. CI builds and runs them.
  • pnpm --dir ui exec vitest run scripts/: exit 1, 3 of 4903 tests. Two are 15 s timeouts on the shared box (check-hand-rolled-comment-mask process run, js-comment-mask type-check program); one is unit-registry-absence-collision, which could not import modules whose @objectstack/client dist is not built here. None reads a file this diff changes; read as NOT MEASURED, Test UI in CI is the reading.

Generated by Claude Code

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/lint, @objectstack/spec, touching 17 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/spec/authorable-surface/ui.json, packages/spec/liveness/action.json, packages/spec/liveness/state-counts/action.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

14 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/ai/actions-as-tools.mdx (via confirmText (literal, a string literal in lookupActionField))
  • content/docs/ai/connect-mcp.mdx (via confirmText (literal, a string literal in lookupActionField))
  • content/docs/automation/flows.mdx (via successMessage (literal, a string literal in lookupActionField))
  • content/docs/deployment/troubleshooting.mdx (via ActionSchema (symbol, a top-level const))
  • content/docs/frontend/architecture-overview.mdx (via ActionSchema (symbol, a top-level const), successMessage (literal, a string literal in lookupActionField))
  • content/docs/frontend/layout.mdx (via confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))
  • content/docs/frontend/plugins/plugin-view.mdx (via submitText (symbol, a field of interface ActionLike), submitText (literal, a string literal in ActionSchema; a string literal in actionObject; a string literal in actionTranslationSchema; a string literal in lookupActionField; a string literal in translateAction))
  • content/docs/frontend/troubleshooting.mdx (via ActionSchema (symbol, a top-level const))
  • content/docs/getting-started/build-with-claude-code.mdx (via successMessage (literal, a string literal in lookupActionField))
  • content/docs/protocol/kernel/i18n-standard.mdx (via confirmText (literal, a string literal in lookupActionField))
  • content/docs/protocol/objectui/actions.mdx (via ActionSchema (symbol, a top-level const), submitText (symbol, a field of interface ActionLike), confirmText (literal, a string literal in lookupActionField), disabledReason (literal, a string literal in lookupActionField), submitText (literal, a string literal in ActionSchema; a string literal in actionObject; a string literal in actionTranslationSchema; a string literal in lookupActionField; a string literal in translateAction), successMessage (literal, a string literal in lookupActionField))
  • content/docs/protocol/objectui/record-alert.mdx (via confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))
  • content/docs/ui/actions.mdx (via confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))
  • content/docs/ui/translations.mdx (via confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))

⛔ 6 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-1.mdx (via ActionSchema (symbol, a top-level const), confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))
  • content/docs/releases/v17/17-3.mdx (via ActionSchema (symbol, a top-level const))
  • content/docs/releases/v17/17-7.mdx (via successMessage (literal, a string literal in lookupActionField))
  • content/docs/releases/v17/index.mdx (via ActionSchema (symbol, a top-level const))
  • content/docs/releases/v18/18-1.mdx (via confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))
  • content/docs/releases/v18/18-2.mdx (via ActionSchema (symbol, a top-level const), confirmText (literal, a string literal in lookupActionField), successMessage (literal, a string literal in lookupActionField))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/authorable-surface/ui.json, packages/spec/liveness/action.json, packages/spec/liveness/state-counts/action.md) — pages documenting those are invisible to this run
  • the SDK route bridge reached 59 of 211 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 501c864dd5918a7bab1f3a59e1246b8a0ddff48c → packageMentionDocs.

Which tree this was computed on

This run read content/docs from e0ea8d88153a87cfd73692c265412c302afc2bcf — the merge of head 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4 into base 501c864dd5918a7bab1f3a59e1246b8a0ddff48c, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e0ea8d88153a87cfd73692c265412c302afc2bcf && git checkout e0ea8d88153a87cfd73692c265412c302afc2bcf
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 501c864dd5918a7bab1f3a59e1246b8a0ddff48c 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4 && git checkout -B drift-repro 501c864dd5918a7bab1f3a59e1246b8a0ddff48c && git merge --no-ff 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4

node scripts/docs-audit/affected-docs.mjs --json 501c864dd5918a7bab1f3a59e1246b8a0ddff48c

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 501c864dd5918a7bab1f3a59e1246b8a0ddff48c → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

维护者速读(席位终稿 · head 73450224)

  • 改了什么: 动作新增可选键 submitText:动作弹出“填写参数”对话框时,提交按钮上的字(如「发送」「记录通话」),不写就仍是「确认」。可翻译,翻译位 objects.OBJECT._actions.ACTION.submitText(无对象动作在 globalActions)。没有 params 的动作写它会被拒(那种动作根本不弹参数框),空字符串也被拒;旧写法 submitLabel / confirmLabel 会提示改名。
  • 为什么改: 现在所有参数对话框的按钮都写「确认」,用户分不清这一下是发邮件还是只保存。本 PR 是规格一半;控制台真正把字画到按钮上在 Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158,之后落地。
  • 风险与回滚: 只加可选键,不写它的动作完全不变。控制台读取之前,写了这个键也看不到效果,os validate 会提示作者“已声明、尚未显示”。回退本 PR 即可。
  • 先看: packages/spec/src/ui/action.zod.ts(新键与两条拒绝);packages/spec/src/system/i18n-resolver.ts(只对有 params 的动作套译文)。
  • 两分钟验证: pnpm --filter @objectstack/spec exec vitest run src/ui/action-submit-text.test.ts,应全部通过。
  • 需要你做的: 批准键名 submitText(卡里原提议 submitLabel)。契约复审 PASS 在案后才请批。

席位意见: 按卡交付,ACCEPT(车道部分)。键名席位赞成 submitText:表单组件的提交按钮已经叫 submitText,平台两次把 submitLabel 退役并指向它,再用 submitLabel 会教作者一个被拒过的词。

席位核对 · ACCEPT (lane part) · card #27944 · 2026-10-30T15:55Z

  1. 形态: 21 files, +457 / −13 at head 73450224 (own diff), draft, Fixes #27944 once, Clause-②: yes (widening) / Metadata-protocol: added. Changesets: @objectstack/spec minor; @objectstack/lint and @object-ui/core patch with Metadata-protocol: none. check-governed-merges.mjs --pr 28188: not governed, 470 lines.
  2. 前提实测: holds on origin/main. ActionSchema had no submit-button key, and the param dialog's button is the fixed actionDialog.confirm. The dev measured the naming precedent: object-form's submitText (beside cancelText), plus the two submitLabel retirements (the element:form tombstone and translation-component-submit-label-removed).
  3. 门禁 check-runs: on 73450224: 13 success, 7 skipped, 22 in progress, 0 failed at this record; the seat re-reads them before any landing stroke. Dev: spec src/ui + src/system 7942 tests (1 red fixed by the form-ledger omit row), typecheck exit 0, lint 332, metadata-protocol pin 18, ui actionKeys.pin 19, check:generated exit 0. Gates 109 derived, 0 unrun, 104 exit 0; 4 exit 3 on the unbuilt workspace (check:skill-examples, check:dual-build-cjs-loads, check:i18n-walk-parity, check:lean-entry-closure), and the ui scripts/ vitest had 3 of 4903 red that read no changed file (2 timeouts, 1 unbuilt @objectstack/client). CI answers those. os-dev-report 6527066768.
  4. 接受的偏差:
    • Key name submitText, not the card's submitLabel. Measured above. ⛔ Not final until the maintainer approves it in this PR.
    • A refusal beyond the card: submitText on an action without a non-empty params (ADR-0078, the mirror of the existing confirmText-beside-params rule). For the contract reviewer to judge.
    • File surface beyond the claim, each forced by a gate: translation.zod.ts, i18n-resolver.ts, the liveness/action.json row, an omit row in metadata-form-zod-reconciliation.test.ts, the metadata-protocol key-count pin (48 → 49), ui/packages/core/src/actions/actionKeys.ts (SPEC_ACTION_KEYS), content/docs/ui/translations.mdx.
    • No Studio form row: an omit row ("planned, not yet rendered", the page.print precedent); Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 swaps it for the real row.
  5. 范围外去向: the console reader, the Studio form row and the os i18n extract scaffold → Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 (extract half added by seat note on that card). bulkActionDefs.confirmLabel being a plain string rather than an I18nLabel is named in the PR's Acceptance notes, not filed (no repro). Skills-docs: the PR body says "follow-up owed"; the relay cannot rewrite a PR body, so this record is the current line: Skills-docs: #28190 (skills/objectstack-ui actions rule + eval, skills/objectstack-i18n slot list).
  6. 落地条款: Tier S path (no governed path). Owed before any landing stroke: green CI on the landing head, a same-shape CONTRACT_REVIEW_TIER PASS (packages/spec/src/** non-test), and the maintainer's approval of the key name. This seat cannot serve that tier now and hands the review over below.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 "You've reached your Fable limit", 2026-10-30T04:26Z) · head 7345022

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

CI note · 2026-10-30T16:06Z · head 734502240e111e087821cdc9297c880e3ca0cd0f. Test UI (9/16) is red on ui/packages/app-shell/src/views/metadata-admin/inspectors/flow-value-envelope.test.ts:77: the pin lists the flow expression ledger's value slots and the received list has one more, connector_action:input.*. That entry comes from #28150 (3cc45cc466) on main, which this PR's head does not contain; the PR check runs on the merge with current main, so it inherits the red. This diff touches no flow ledger or app-shell file. It is the main-red #28185 (p0, claimed by domain:ui seat 3) and #28189 (the queue twin). No fix has landed yet, so nothing is ported here; once #28185's fix is on main the seat merges main into this branch and CI re-runs.

…fter merging main

The merge took the branch's side of two regenerated files and dropped
main's `KanbanConfig:lanes` and `ReportChart:seriesBy` entries; gen:schema
and gen:docs put them back.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2fi9zfJhUTubyJYb6V
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

New head · 2026-10-30T17:54Z · f485240a2969f6fa5400faa50afeff7edc3b39e8. The main-red #28185 (the flow-value-envelope pin) is fixed on main, so the seat merged origin/main into this branch to re-run Test UI. The merge (9e376a4ac8) dropped main's KanbanConfig:lanes and ReportChart:seriesBy from two regenerated files; f485240a29 regenerates them (gen:schema, gen:docs). No hand-written line of this PR moved. Local: spec check:generated 14/14 (dist rebuilt), check:authorable-surface and check:liveness exit 0. The seat record 6527138419 stands, with this head.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 "You've reached your Fable limit", 2026-10-30T04:26Z) · head f485240

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

CI note · 2026-10-30T18:13Z · head f485240a2969f6fa5400faa50afeff7edc3b39e8. Test UI (1/16) is red on ui/packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx:211: the test expects the node config finding's where prose (node 'write') and receives the key path flows[0].nodes[1].config.fields.id. That wording comes from #28192 (3efccfd522) on main; this diff touches neither packages/lint's flow node findings nor that Studio page. It is the main-red #28219 (p0, claimed by domain:ui seat 3). No fix has landed yet, so nothing is ported here; once it is on main the seat merges main again and CI re-runs.

…tion-submit-label

# Conflicts:
#	packages/spec/src/system/metadata-form-zod-reconciliation.test.ts
…erging main

Main's side of the three regenerated files, re-derived from the merged
tree so this branch's `submitText` rows sit beside main's new entries.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2fi9zfJhUTubyJYb6V
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

New head · 2026-10-30T20:40Z · 528f8bf5f21b3a6feeb2988c99f24b9d3558e10b. The second main-red (#28219, the Studio Problems test against #28192's key path) is closed, so the seat merged origin/main again through os-regen-merge.sh. One hand conflict, in metadata-form-zod-reconciliation.test.ts: main added a percentDisplay omit row (#27973) beside this PR's submitText row; both rows are kept. 528f8bf5f2 regenerates the three generated files from the merged tree. No hand-written line of this PR changed. Local: spec src/system 66 files / 2087 tests and action-submit-text.test.ts pass, lint validate-translation-references 224 pass, tsc --noEmit exit 0, check:generated 14/14, check:liveness and check:authorable-surface exit 0. The seat record 6527138419 stands, with this head.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 "You've reached your Fable limit", 2026-10-30T04:26Z) · head 528f8bf

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract-review-claim: session_01L9qibw58ehQ2gRHP2h2Puz · head 528f8bf5f21b3a6feeb2988c99f24b9d3558e10b · 2026-10-31T02:28Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 528f8bf5f21b3a6feeb2988c99f24b9d3558e10b
Local-runs: none
Scope: packages/spec/src/ui/action.zod.ts (actionSubmitText, SUBMIT_TEXT_BLANK, the two aliases, the submitText member and the no-params refinement on ActionSchema), packages/spec/src/system/translation.zod.ts (the submitText slot and aliases on actionTranslationSchema at both addresses), packages/spec/src/system/i18n-resolver.ts (ActionLike.submitText, lookupActionField, the guarded overlay in translateAction), packages/lint/src/validate-translation-references.ts (checkActionSubmitText) and its test, packages/spec/src/ui/action-submit-text.test.ts, packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (omit row), packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts (count pin), packages/spec/liveness/action.json and state-counts/action.md, packages/spec/authorable-surface/ui.json, ui/packages/core/src/actions/actionKeys.ts (SPEC_ACTION_KEYS), the five reference and protocol docs pages, the three changesets.

Inputs: card #27944 (body, claim 6522879044, os-dev-report 6527066768), the seat's ACCEPT record 6527138419, its CI notes 6527387954 and 6530150750 (two main-reds inherited through the merge check, both since fixed on main) and its new-head notes 6529753660 and 6533023900 (two merges of main, regenerated files only, one hand conflict kept both omit rows), the PR body, the 21-file diff against merge base 49a078e, main's own movement since that base (265 files, sixteen shared with this diff, see ③), the head's check-runs (read 2026-10-31T02:31Z: check-runs on 528f8bf: 65 total, 58 success (Auto Label, Build & E2E UI, Build Core, Build Docs, Build UI Deps, Check Changeset, Check Documentation Links, Check PR Size, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint & Repo Gates, Lint UI, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, Live E2E UI, PR-body guards (claim · duplicate · Part-of · single-writer path), Plan Test Core shards, Spec property liveness, Test Core, Test Core (all 8), Test UI, Test UI (all 16), Type Check UI, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, TypeScript Type Check, filter); 7 skipped path-filtered (18.x upgrade harness (opt-in), Dogfood Regression Gate (matrix shard/3), Dogfood Verify CLI, Packed-tarball smoke (opt-in), Schedule gate · skip when a green push run covers the commit, Temporal Conformance (live PG + MySQL), UI Published Artifacts); 0 failure, 0 in progress; these ran on the merge with the main of that time, before #28235 landed). Author user.login is objectstack-fleet[bot]; the drafter is session_017ihL2fi9zfJhUTubyJYb6V on claude/issue-27944-action-submit-label; the reviewer is not the drafter.

① Derived judgments

  • The accept set: ActionSchema gains one optional key submitText, an I18nLabel (a non-blank string through NON_BLANK_STRING, so the published JSON Schema carries the rule, or InlineLocaleMapSchema), declared beside params and refused by a refine at path submitText on any registered action whose params is absent or empty, the mirror of the existing confirmText-beside-params rule. submitLabel and confirmLabel are aliases that rename onto it, on the action and in a bundle. InlineActionSchema does not pick the key, as it does not pick description. Absence stays absent. RIGHT, and each arm is pinned by the 18-case test file.
  • Translation follows description exactly: the slot sits on actionTranslationSchema at objects.OBJECT._actions.ACTION and globalActions.ACTION; lookupActionField takes the new field name; translateAction overlays the bundle value only for an action with a non-empty params and otherwise passes the authored value through, which the schema has already refused, so the guard decides only that a bundle can never give a button to a dialog that never opens. RIGHT.
  • Lint: checkActionSubmitText reports translation-target-unknown at error for a submitText translation under an action declaring no params, at both addresses, with the result-dialog leaves' rule and params as the declaration; the coverage table classifies the key as reference-checked with a ghost at both addresses, and the all-keys real-instance control names it. RIGHT.
  • The new-key ripple is complete on this head: the liveness row is planned with authorWarn and a hint; the state-counts table moves planned 0 to 1, classified 49 to 50; the metadata-form ledger carries an omit row so the Studio action form offers no control nothing draws; SPEC_ACTION_KEYS lists the key; the /meta/types action count pin moves 48 to 49 and its sample names the key; authorable-surface/ui.json gains exactly ui/Action:submitText; the four reference tables and the protocol page carry the describe. No expression ledger is owed: the key is copy, not a predicate.

② Semver level

@objectstack/spec: minor with Clause-②: yes (widening) and Metadata-protocol: added; @objectstack/lint and @object-ui/core: patch with Metadata-protocol: none. A new accepted key on a metadata schema is added and takes at least minor on the moved package; the lint rule and the key inventory are additive. The same split #28235 took for pressed. The three carriers agree: PR body, claim and changesets.

③ Boundary flags

  • Landing blocker, not a contract finding: this head is no longer mergeable. Since the seat's last merge of main, feat(spec): an action can show the reader already pressed it (pressed, a per-reader CEL predicate) #28235 landed ActionSchema.pressed (card A record_header action cannot show per-reader state (an active / pressed predicate) #27946) and the same ripple files moved; git merge-tree reports content conflicts in packages/spec/src/ui/action.zod.ts, packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts (main now pins 49 for pressed, so the merged tree pins 50 and the sample names both keys) and packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (keep both omit rows), and the regenerated copies (liveness/action.json, state-counts/action.md, authorable-surface/ui.json, actionKeys.ts, the docs tables) need both keys. GitHub reports mergeable_state: dirty. The seat merges main once more through the regen script, resolves those three by hand, and the lane re-claims the merged head and posts a delta on it; the hand-written content of this PR does not change.
  • Name approval owed to the maintainer: submitText (the protocol's existing word, with submitLabel retired twice) instead of the card's submitLabel; the seat asks in the PR. A rename is one token plus regeneration and would not move this verdict.
  • Should-fix, not blocking: os i18n extract (packages/cli i18n-extract) does not scaffold submitText while it scaffolds description and disabledReason; the seat routes it to Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158 or its own card, as its record says.
  • Should-fix, not blocking: the PR body's Skills-docs: follow-up owed line is superseded by the seat's Skills-docs: #28190; PR-body guards pass either way.
  • Out of scope, carried on Action param dialog: draw the action's submitText on the submit button, falling back to Confirm #28158: the param dialog reader, the two handlers, UIActionSchema, the Studio form row and the ledger flip.

④ Design judgment

Scenario: an author of a registered action with params (HotCRM send_email, log_call, log_meeting) names the verb on the param dialog's submit button, translated per locale; the console's param dialog (#28158) draws it with actionDialog.confirm as the fallback. Judged against ADR-0078 (declared but never read), Prime Directive 12 (one key per concept), the description precedent the card asked for, and the two dialogs an action can open.

  • action.zod.ts, submitText: the key is on the right dialog. A param-less action opens a confirm dialog whose message is confirmText; an action with params opens the param dialog whose line under the title is description and whose button is now submitText. The two refinements make the pair exclusive on one registered action, so an author cannot author copy for a dialog that will not open. Holds.
  • The spelling: submitText is the word the form component already uses for the same button, and the platform has twice refused submitLabel with a pointer to it, so admitting submitLabel here would teach a refused word; keeping it as an alias with a rename is the right shape. confirmLabel as an alias is sound too: on a view's bulkActionDefs it is the same button, and an author who copies that shape onto an action is told the action's spelling. Holds, subject to the maintainer's word on the name.
  • The planned marking is complete at every surface an author meets: the describe, the liveness hint through os validate, the omit row in the Studio form, the docs line. Holds.
  • Tried and did not break: the blank and whitespace refusal on both I18nLabel forms; the no-params refusal with params absent and params: [], with a locale map too; the aliases on the action and in a bundle; the inline action's refusal; the overlay for an action that authors no label; the global address for an object-less action; no button for a param-less action whatever the bundle carries; the lint control under an action with params.

Verdict on ④: no must-fix; two should-fixes in ③.

Implemented-by: claude/issue-27944-action-submit-label
Reviewed-by: session_01L9qibw58ehQ2gRHP2h2Puz

VERDICT: PASS

…tion-submit-label

# Conflicts:
#	packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts
#	packages/spec/src/system/metadata-form-zod-reconciliation.test.ts
#	packages/spec/src/ui/action.zod.ts
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 5f7d84af8dc541e5e3b58277e8580bc63eae1bdf
Local-runs: none
Scope: packages/spec/src/ui/action.zod.ts, packages/metadata-protocol/src/protocol.meta-types-degenerate-derivation.test.ts, packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (the three hand-resolved conflicts), packages/spec/authorable-surface/ui.json, content/docs/references/ui/action.mdx, content/docs/references/kernel/metadata-plugin.mdx, content/docs/references/data/object.mdx, packages/spec/liveness/state-counts/action.md (the two regeneration commits) + the files of record 6537832125, unchanged by the delta

Inputs: PR #28188 (body, all ten comments, the file list of 21 files, the thirteen commits from the merge-base 3fd4d6b), the seat's hand-off 6537940517 naming this head and the three conflicts, my record 6537832125 (PASS on 528f8bf with the landing blocker: the head was dirty against main after #28235's pressed ripple, and the three files named there are exactly the three resolved here), the 70 check-runs on this head (read 2026-10-31T03:06Z: all 70 runs completed, none failed, none cancelled, none in progress; success: Build & E2E UI, Build Core, Build Docs, Build UI Deps, Check Changeset, Check Documentation Links, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint & Repo Gates, Lint UI, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, Live E2E UI, PR-body guards (claim · duplicate · Part-of · single-writer path), Plan Test Core shards, Spec property liveness, Test Core, Test Core (all 8), Test UI, Test UI (all 16), Type Check UI, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, TypeScript Type Check, filter; skipped: 18.x upgrade harness (opt-in), Auto Label, Check PR Size, Dogfood Regression Gate (matrix shard/3), Dogfood Verify CLI, Packed-tarball smoke (opt-in), Schedule gate · skip when a green push run covers the commit, Temporal Conformance (live PG + MySQL), UI Published Artifacts), and the tree. This is a delta review of record 6537832125 on the head that merged main: the PR-only diff at 528f8bf (against its merge-base) and the PR-only diff at this head (against today's main 6285203) were compared line by line with index and hunk-position lines stripped, and the merge commit d61dbb2 was read in combined form, which shows only the hunks that differ from both parents. The judgments of record 6537832125 on every hand-written line stand, because none moved.

① Derived judgments

  • The delta is the merge, three resolved conflicts and two regenerations; no hand-written line of the PR moved - right. The interdiff of the two PR-only diffs is 775 lines against 775, differing only where main's pressed (feat(spec): an action can show the reader already pressed it (pressed, a per-reader CEL predicate) #28235) now sits beside submitText: the /meta/types count pin, the action state-counts row, the omit-row context and the alias-table context, plus one context line in content/docs/ui/translations.mdx where feat(spec): a page object-form's thank-you panel is translated through pages.PAGE.components.ID.submitBehavior #28269's thank-you row landed above this PR's edited row. action-submit-text.test.ts, i18n-resolver.ts, translation.zod.ts, the lint rule and its test, actionKeys.ts, the three changesets and the docs pages are byte-identical in both PR-only diffs.
  • action.zod.ts: both alias lines stay - right. The combined diff shows this PR's submitLabel: 'submitText', confirmLabel: 'submitText' line directly above main's active: 'pressed', activeWhen: 'pressed', pressedWhen: 'pressed' line, each with its own comment; neither key set overlaps the other, so the near-miss table steers both families.
  • protocol.meta-types-degenerate-derivation.test.ts: the pin is 50 and the sample names both keys - right. The comment chain now reads 47 to 48 disabledReason, 48 to 49 pressed, 49 to 50 submitText; the assertion is toBe(50); the sample key list carries pressed and submitText. That is the arithmetic record 6537832125 ③ asked for.
  • metadata-form-zod-reconciliation.test.ts: both omit rows stay - right. The submitText row (kind omit, type action, root path, the planned-not-rendered why) sits directly above main's pressed row; both intact.
  • The regenerations match the merged tree - right as far as the diff shows and as CI judges. 2693372 touches only the authorable surface and the three reference pages submitText already touched; 5f7d84a recounts liveness/state-counts/action.md from planned 1 to 2 and classified 50 to 51, which is main's pressed row (planned) beside this PR's submitText row (planned), the sum record 6537832125 anticipated. Spec property liveness and check:liveness are the gates and are in the check-run line above.
  • Accept-set, translation slot, lint rule and the ui SPEC_ACTION_KEYS pin - as record 6537832125 found; nothing in the delta touches them.
  • Check-runs as gate verdicts - read as above; every run on this head completed and none is red, cancelled or in progress at the read.

② Semver level

  • @objectstack/spec minor, @objectstack/lint patch, @object-ui/core patch, Clause-②: yes (widening), Metadata-protocol: added - unchanged by the delta and right, as record 6537832125 judged.

③ Boundary flags

④ Design judgment

  • The delta carries no design: three merges that stack two intents, and two regenerations whose only new counts are main's own. Nothing to add to record 6537832125's ④.

Verdict reasoning. The hand-written lines of this PR are byte-identical to the ones record 6537832125 passed; each of the three conflicts keeps both sides, with the /meta/types pin and the state-counts at the sums the merge implies; the regenerations are the merged tree's; the head is clean against main; every check on the head is green or skipped. The prior PASS carries to this head, and the blocker it named is gone.

Implemented-by: claude/issue-27944-action-submit-label
Reviewed-by: session_01L9qibw58ehQ2gRHP2h2Puz

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-tesla · session_01L9qibzC6RxMfB59EsgAoNN

Serial-overlap note · 2026-10-31T05:04Z · from the ui seat, handing over the boundary flag of contract-review record 6538888897 on #28301.

#28301 (action.pressed, ui half of #27946) merged 2026-10-31T05:02:36Z as 7eda096b. It touches four files this PR also touches: ui/packages/core/src/actions/actionKeys.ts, packages/spec/liveness/action.json, packages/spec/liveness/state-counts/action.md and content/docs/.../actions.mdx. This PR is now dirty against main.

When it next moves:

  • merge main
  • re-run gen:liveness-counts (the lane's merged truth: live 49, planned 1 for submitText, classified 51)
  • ask the contract-review lane for a delta review

The source hunks are on different keys, so only the count row should conflict. This is informational, and the ui seat does not push here.

…tion-submit-label

# Conflicts:
#	packages/spec/src/system/metadata-form-zod-reconciliation.test.ts
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

New head · 2026-10-31T05:19Z · 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4. 田騏 approved the key submitText in the seat's thread at 2026-10-31T05:05Z (「同意」 to the seat's question naming it), so the name approval owed by PASS 6537832125 is discharged. The head went dirty again when #28096 landed, so the seat merged origin/main through os-regen-merge.sh. One hand conflict, in packages/spec/src/system/metadata-form-zod-reconciliation.test.ts: #28096's currencyConfig.homeAmount omit row beside this PR's submitText row; both rows are kept. 301f5b8c5b regenerates the authorable surface and the object reference from the merged tree, and recounts liveness/state-counts/action.md: main flipped pressed to live since the last head, so this PR's submitText is now the one planned row (live 49, planned 1, classified 51). No hand-written line of this PR changed.

Local: spec src/ui + src/system + src/data 386 files / 12732 tests, the degenerate-derivation pin 18, all pass; tsc --noEmit exit 0, check:generated 14/14, check:liveness and check:authorable-surface exit 0.

Contract-review-handoff: triage — CONTRACT_REVIEW_TIER unavailable (HTTP 429 "You've reached your Fable limit", 2026-10-30T04:26Z) · head 301f5b8

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract-review-claim: session_01L9qibw58ehQ2gRHP2h2Puz · head 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4 · 2026-10-31T05:43Z

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4
Local-runs: none
Scope: packages/spec/src/system/metadata-form-zod-reconciliation.test.ts (the one hand-resolved conflict), packages/spec/liveness/state-counts/action.md, packages/spec/authorable-surface/ui.json, content/docs/references/data/object.mdx (the regeneration commit) + the files of records 6537832125 and 6538202172, unchanged by the delta

Inputs: PR #28188 (body, all fifteen comments, the file list of 21 files, the fifteen commits from the merge-base b1e1dcf), the ui seat's serial-overlap note 6539355898 (#28301 merged as 7eda096b and flipped pressed to live), the seat's hand-off 6539495622 naming this head, the one conflict and the name approval, my records 6537832125 (PASS on 528f8bf) and 6538202172 (delta PASS on 5f7d84a), the 73 check-runs on this head (read 2026-10-31T05:48Z: all 73 runs completed, none failed, none cancelled, none in progress; success: Build & E2E UI, Build Core, Build Docs, Build UI Deps, Check Changeset, Check Documentation Links, Dogfood Regression Gate, Flag docs affected by code changes, Governed Surface Queue Guard, Lint & Repo Gates, Lint UI, Lint · CI, release & engine gates, Lint · ESLint, Lint · PM dispatch-gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · scoped · query-options erasure, Lint · scoped · slot lookup & corpus, Lint · scoped · tooling self-tests, Live E2E UI, PR-body guards (claim · duplicate · Part-of · single-writer path), Plan Test Core shards, Spec property liveness, Test Core, Test Core (all 8), Test UI, Test UI (all 16), Type Check UI, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Type Check · workspace, TypeScript Type Check, filter; skipped: 18.x upgrade harness (opt-in), Auto Label, Check PR Size, Dogfood Regression Gate (matrix shard/3), Dogfood Verify CLI, Packed-tarball smoke (opt-in), Schedule gate · skip when a green push run covers the commit, Temporal Conformance (live PG + MySQL), UI Published Artifacts), and the tree. This is a delta review of record 6538202172 on the head that merged main again: the PR-only diff at 5f7d84a (against its merge-base) and the PR-only diff at this head (against today's main) were compared line by line with index and hunk-position lines stripped, and the merge commit 8a80e9d was read in combined form, which shows only the hunks that differ from both parents. The judgments of records 6537832125 and 6538202172 on every hand-written line stand, because none moved.

① Derived judgments

  • The delta is one merge, one resolved conflict and one regeneration; no hand-written line of the PR moved - right. The interdiff of the two PR-only diffs is 775 lines against 775, differing in two places only: the action state-counts row (now live 49, planned 1, classified 51) and the context below the submitText omit row, where main's homeAmount row (feat(spec): currencyConfig.homeAmount — a record-mode amount declares its stored home-currency projection by pointer (multi-currency M2-1) #28096) now sits between it and the pressed row. Every other file of the PR is byte-identical in both PR-only diffs.
  • metadata-form-zod-reconciliation.test.ts: both omit rows stay - right. The combined diff shows this PR's submitText row (kind omit, type action, root path, the planned-not-rendered why) directly above main's currencyConfig.homeAmount row (type field); both intact, neither edited.
  • The state-counts recount is main's own - right. feat(console): a header action shows the reader already pressed it (pressed drawn as aria-pressed) #28301 flipped pressed from planned to live on main, so the action shard goes live 48 to 49 and planned 2 to 1, classified 51 unchanged; this PR's submitText is now the one planned row, as the ui seat's note 6539355898 computed. Spec property liveness and check:liveness are the gates and are in the check-run line above.
  • The other two regenerated files carry only main's keys - right. object.mdx gains homeAmount in the two currencyConfig cells and ui.json gains ui/CalendarConfig:initialDate; both are already on main word for word (feat(spec): currencyConfig.homeAmount — a record-mode amount declares its stored home-currency projection by pointer (multi-currency M2-1) #28096, feat(spec): a calendar view can declare the date it opens on, calendar.initialDate #28138), so the PR-only diff against main has no hunk for them. The regeneration brought the branch's generated copies level with the merged tree; check:generated and check:authorable-surface are in the check-run line above.
  • The head is clean against today's main - right. Mergeable, merge-tree clean against a0f86549, and none of the files main moved since the merge-base is in this diff.
  • Accept-set, translation slot, lint rule, the /meta/types pin at 50 and the ui SPEC_ACTION_KEYS pin - as the two prior records found; nothing in the delta touches them.
  • Check-runs as gate verdicts - read as above; every run on this head completed and none is red, cancelled or in progress at the read.

② Semver level

  • @objectstack/spec minor, @objectstack/lint patch, @object-ui/core patch, Clause-②: yes (widening), Metadata-protocol: added - unchanged by the delta and right, as record 6537832125 judged.

③ Boundary flags

④ Design judgment

  • The delta carries no design: a merge that stacks two intents on one ledger, and a regeneration whose only new lines are main's own. Nothing to add to record 6537832125's ④.

Verdict reasoning. The hand-written lines of this PR are byte-identical to the ones records 6537832125 and 6538202172 passed; the one conflict keeps both sides; the state-counts row is the sum the merged ledger implies; the two other regenerated files match main; the head is clean against main; every check on the head is green or skipped; the name approval is discharged. The prior PASS carries to this head with nothing owed.

Implemented-by: claude/issue-27944-action-submit-label
Reviewed-by: session_01L9qibw58ehQ2gRHP2h2Puz

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#4 · marchtian · session_017ihL2fi9zfJhUTubyJYb6V

Landing stroke · 2026-10-31T05:49Z · head 301f5b8c5bde38cb4c094f02703ef429ad3ea6c4.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 31, 2026 05:50
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 31, 2026
Merged via the queue into main with commit a7bdac4 Oct 31, 2026
76 of 77 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-27944-action-submit-label branch October 31, 2026 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Action param dialog: an action key for the submit button's verb, falling back to Confirm

1 participant