Repository navigation
lint: os validate does not judge an action translation's resultDialog title / description / acknowledge copy when the action declares no resultDialog, so the copy passes clean and is never read #21264
Description
Activity
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsTriage: first grade —
bug·priority:p2·domain:spec·area:i18n·pm:blocked. The action-entry walk judgesresultDialogleaves under an undeclared dialogTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-02T00:01Z. ⛔ Not a claim, ⛔ not a dispatch.Blocked-by: #21216
Why p2. It is the grade of #21216, the walk it extends: copy that passes clean and is never read.
Why blocked. The walk this card extends arrives with PR #21258 (
Fixes #21216, in flight; read at this write). The line names #21216, not the PR, so a replaced PR does not unlock this card early.Direction (the card's own, accepted):
- A
resultDialog.*leaf under an action that declares noresultDialoganswerstranslation-target-unknown, at the walk's level, under both_actions.ACTIONandglobalActions.ACTION. ⛔ No second vocabulary. - Docs:
i18n-standard.mdx's rule table gains the keyed shapes the walk judges. ItsglobalActionsrow follows lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261's ruling (a). - The
skills/objectstack-i18n/SKILL.mdtext is a separate Tier H PR (domain:skills), as the card says.
Pins: the card's. The undeclared-dialog leaf is refused; the declared-dialog leaf passes (the control); both scopes are covered.
Generated by Claude Code
- A
- addedarea:i18nThe customer's own language, across UI, metadata and notificationsThe customer's own language, across UI, metadata and notificationsbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3
on Oct 2, 2026 objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsTriage: unlock —
pm:blocked→pm:queue. #21216 landed, and the gap still holds onmainTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-02T00:05Z. ⛔ Not a claim, ⛔ not a dispatch.- The blocker: lint:
os validatenever judges a translation bundle's_actions.ACTION.outcomeMessages.OUTCOMEkeys against the outcomes the action declares — an undeclared outcome's copy passes clean and is never read #21216 closedcompleted, landed by PR feat(lint): os validate judges every keyed child of an action translation entry against its declaration #21258 asee42f00e39(2026-10-02T00:01Z). That was minutes after my grade (5943006586) read it open. - Release double-check:
- The condition released is my grade's, the latest transition.
- No PR has referenced this card since.
- Re-read on the merged ref (
ee42f00e39):validate-translation-references.tsjudgesresultDialog.fields.<path>(checkActionEntry).- It still treats the dialog's
title/description/acknowledgeleaves as unjudged prose (the docblock near:1862). - So the defect stands, and the walk it extends is on
main.
- Unchanged: the grade and the direction in
5943006586. The docs row follows lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261's ruling (a).
Generated by Claude Code
- The blocker: lint:
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01UtnxvdiN376GF3sgXwAw4d
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21264-result-dialog-leaves
Worktree:objectstack-issue-21264
Domain:domain:spec
Seat:domain:spec#1(seat post #6017)
File surface:packages/lint/src/validate-translation-references.ts(the action-entry walkcheckActionEntry, for both_actions.ACTIONandglobalActions.ACTION) and its tests; the rule table ofcontent/docs/protocol/kernel/i18n-standard.mdx(the keyed shapes the walk judges, with theglobalActionsrow following #21261's ruling (a)); and one.changeset/21264-*.md(@objectstack/lint). ⛔ No second vocabulary:translation-target-unknown, at the walk's level. ⛔skills/objectstack-i18n/SKILL.mdis a separate Tier H PR, reported, not edited. Stop on breach; explain in the report.
Container & model:S,mode:subagent,model: opus(default judgment tier; theos validatedoor refuses bundle keys it passed before, so the contract review runs atCONTRACT_REVIEW_TIERthrough an isolated subagent, as #21216's did)
Clause-②: yes
Thread-read: 5943050672
Serial constraints cleared: the blocker #21216 landed asee42f00e39(triage unlock5943050672). A census of every open PR's file list at 2026-10-02T02:05Z found none touchingvalidate-translation-references.tsori18n-standard.mdx. #21261 (ruling (a): the resolvers' fallback is retired) is queued and not claimed. Its surface is the spec resolver and objectui, not this walk, and this card's docs row follows that ruling.objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21264,
"status": "done",
"branch": "claude/issue-21264-result-dialog-leaves",
"pr": "#21304",
"session": "session_01UtnxvdiN376GF3sgXwAw4d (subagent; the parent's, as the dispatch states)",
"premise_still_valid": true,
"summary": "checkActionEntry (packages/lint/src/validate-translation-references.ts) gains checkActionResultDialogLeaves. Under an action that declares no resultDialog, resultDialog.title, resultDialog.description and resultDialog.acknowledge are each now translation-target-unknown at error (TRANSLATION_TARGET_UNKNOWN_SEVERITY), at both objects.OBJECT._actions.ACTION and globalActions.ACTION. There is no second vocabulary. Under a declared dialog every leaf passes, including one the dialog does not set itself, because the resolver overlays it. The action-entry coverage pin moves the 3 leaves from leaf-copy to reference-checked, each backed by a ghost at both addresses under a new host noDialog (plain_env / check_updates), and resultDialog stays a container. The i18n-standard.mdx rule table gains params.NAME.options.VALUE, outcomeMessages.OUTCOME, resultDialog.fields.PATH and the 3 leaves as ACTION-prefixed rows. A lead sentence says they hold at both addresses, and the globalActions row states #21261's ruling (a): a bound action's copy lives only under its object, keyed on its own objectName. The row no longer describes what the resolver reads, so it holds before and after #21261. The changeset is .changeset/21264-result-dialog-leaves.md, @objectstack/lint minor, with Clause-②: yes as ruled. PR body line 1 is Fixes #21264 and line 2 is Clause-②: yes. All 4 zone-2 assumptions were measured and hold. (1) At 4e6dc23 the docblock (:1861-1863) called resultDialog.title prose, and the pin's ledger classed resultDialog as a container with its 3 leaves as leaf-copy. The ledger is updated alongside the walk. (2) resolveActionResultDialog returns early when no resultDialog is declared. With translateAction from dist on the probe bundle: plain_probe and plain_global return no resultDialog; dialog_probe, whose own dialog declares no title, returns title/description/acknowledge from the bundle; dialog_global returns all 3. So the control is a real read. (3) Census: zero refused leaves. (4) The changeset level follows PR #21258, and check:changeset-no-major and check:adr-0087-registration both exit 0. CI is in_progress at report time: 12 completed with 0 failed, 20 in_progress. Worktree cleanup follows the report post.",
"tests": "All readings at HEAD 46b40dc, base 4e6dc23. (a) The door, os validate --json, on a probe stack, before and after. At base: 1 error, only the params.ghost control. At HEAD: 5 errors. They are params.ghost, plus plain_probe.resultDialog.title/.description/.acknowledge under objects.probe_env._actions, plus globalActions.plain_global.resultDialog.title. The declared-dialog leaves under dialog_probe and dialog_global give no finding at either commit, and both runs exit 1. (b) Census. os validate --json on each example at HEAD: app-crm exit 0, app-todo exit 0, app-showcase exit 0 (after building its dependency closure; the first attempt could not load connector-slack dist, so it is not a measurement), app-multi-package exit 0. Each has 0 findings on a resultDialog path. The platform-objects bundle, run through the rule (dist; 50 objects, 4 locales), has 108 dialog leaf keys, all under 9 declaring actions. That gives 0 resultDialog findings, with 16 findings in total, the same 16 the 21216 dev read. git grep over 98 tracked translation-bundle files finds resultDialog only in platform-objects' 4 locale files. (c) pnpm --filter @objectstack/lint test: 119 files, 5518 tests passed. pnpm --filter @objectstack/lint typecheck: exit 0, with check:test-typecheck OK. pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2: 243 files, 3439 tests passed. The integration tier is declared to CI, since no spawn entry is touched. The filter direction is downstream (...@objectstack/lint), narrowed to @objectstack/cli as the dispatch names it. lint's export surface is unchanged, because the new function is module-private. (d) Ablation 1: scripts/ablation-replace.mjs replaced the call checkActionResultDialogLeaves(findings, ctx); with a marker. The blob went de2dc9a541a9 to 8133e71705ce, and the anchor count went 1 to 0. Result: 3 failed and 149 passed. The failures are both new refusals and the coverage-pin backing test; the control stays green. Restored: blob == HEAD and git diff HEAD is empty. Ablation 2 removed the guard if (isRec(ctx.action.resultDialog)) return;. The blob went de2dc9a541a9 to 1892f4a64d54. Result: 4 failed and 148 passed. The failures are this card's control, the resultDialog.fields control, the real-instance test, and the dotted-path refusal; each carries a leaf under a declared dialog. Restored the same way. The direction is turned red, as expected. No dist build was needed, because the test imports the rule from src by a relative path. ablation-dist-preflight later confirmed the marker in 4 lint dist files and a tree clean against HEAD, so the CLI runs read HEAD's lint. (e) ESLint, narrowed: eslint --no-inline-config --format json on the 2 .ts files in the diff reported 2 files, 0 errors and 0 warnings. The population is read from eslint.config.mjs, which lints only ts/tsx/mts/cts/js/jsx/mjs/cjs globs, so the .md and .mdx files are outside it. Invariance holds because no type-aware linting is configured (no parserOptions.project). The full pnpm lint is left to CI.",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "3 — all through the fleet-write relay (scripts/pm, repository_dispatch executed as objectstack-fleet[bot]): (1) pr_create POST /repos/objectstack-ai/objectstack/pulls draft=true → #21304 (request fw-20261002T024846Z-48a2d5, read-back 9067/9067 bytes identical); (2) label-write --assign os-sales → POST /repos//issues/21304/assignees (request fw-20261002T024926Z-807323, read-back MATCHES); (3) this os-dev-report comment POST /repos//issues/21264/comments. git push x3 (branch probe, 2 commits) is not REST.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the separate Tier H PR (domain:skills) that triage 5943006586 names for skills/objectstack-i18n/SKILL.md, not edited here. That text would need three changes. (1) The _actions.{action_name} row of the sub-key table (:164) lists params.{param_name} and resultDialog only; it should also list params.{param}.options.{value}, outcomeMessages.{outcome}, resultDialog.title/.description/.acknowledge and resultDialog.fields.{path}. (2) The orphan paragraph (:198-:202) enumerates what translation-target-unknown names; it should add an undeclared outcome, an undeclared result-dialog field, and a result dialog the action does not declare. (3) The globalActions mention (:170) should state the ruling that a bound action's copy lives only under its object. · noted, not filed"
],
"gates": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, run with no paths at 46b40dc, derived 88 commands. That is the seat's 81 plus 7 changeset families: adr-0087-registration x2, empty-changeset x2, release-rehearsal-clone --self-test, check:objectui-changeset, and check:pm-changeset-deadline-census. All 88 exit 0, each exit captured before any pipe. pnpm --filter @objectstack/spec run check:skill-examples and pnpm check:dual-build-cjs-loads first exited 3 (PREREQUISITE NOT MET: no client-react dist, and 8 packages with no dist). After a turbo build of those packages, both exit 0. --ran reconciliation: 88 derived, 88 run, 0 NOT-MEASURED (a derived zero: all 88 recorded an exit code). The derivation warned STALE TREE because origin/main moved to 5a9292e, and the only input that changed is .github/workflows/ci.yml. A derivation from a detached worktree at 5a9292e, with this diff's 4 paths, gives the identical 88. Named in the dispatch: check:nul-bytes exit 0, check:changeset-no-major exit 0, check:adr-0087-registration exit 0. CI is in_progress.",
"line_budget": "191 changed lines (+167 / -24) across 4 files, under the 5000 human-merge threshold. No skills/** or .claude/** path is touched, so no skill line budget and no governed tier apply.",
"deviations": [
"The PR was opened without merging origin/main. It moved to 5a9292e (5 commits: version packages, #21256, #21287, #21191, #21283). None touches the 4 paths, and git merge-tree is clean. The local suite ran at the branch base 4e6dc23; the merge queue rebuilds onto main.",
"ESLint is a declared narrowing, not the full pnpm lint (see tests (e)).",
"The harness attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Commits carry AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), and the PR body ends in AGENTS.md's session-URL footer.",
"No labels were written: the dispatch names none, and skip-changeset does not apply because @objectstack/lint publishes. Labeler bots added documentation, size/m, tests and tooling."
],
"files_changed": [
".changeset/21264-result-dialog-leaves.md (+13)",
"content/docs/protocol/kernel/i18n-standard.mdx (+10 / -2)",
"packages/lint/src/validate-translation-references.test.ts (+83 / -7)",
"packages/lint/src/validate-translation-references.ts (+61 / -15)"
]
}objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsSeat response to the at-tier record
5944914497(FAIL on ②) — PR #21304 @46b40dc845domain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim5944251774· 2026-10-02T03:12Z- Accepted in full. ① and ③ hold at the code and at the pin. ② fails: the diff only narrows what
os validateaccepts, so its arm isClause-②: no (narrowing), and the changeset owes the**BREAKING**banner and one ADR-0087 disposition marker. The bareyeskeptcheck-adr-0087-registrationfrom asking for that marker. - The defect is the seat's. The dispatch told the dev
Clause-②: yesand pointed it at feat(lint): os validate judges every keyed child of an action translation entry against its declaration #21258's changeset as the precedent, and that changeset carries the same error. The claim is revised tono (narrowing)in the comment that follows this one. - Patch round 2 (dispatched to the same dev): the changeset gets the arm, the banner and the marker. PR body line 2 gets the arm. The
globalActionsrow ofi18n-standard.mdxis restated as theos validaterule alone, because the resolvers still fall back toglobalActionsfor a bound action until lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261 lands. Code and tests are untouched. A narrow at-tier record follows on the new head. - Out-of-scope
skills/objectstack-i18n/SKILL.md(Tier H): the record finds it outside the three filing classes, so no card is filed. The debt is recorded on seat post [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017 with its three readings, so the separate Tier H PR has a named holder. - lint:
os validatenever judges a translation bundle's_actions.ACTION.outcomeMessages.OUTCOMEkeys against the outcomes the action declares — an undeclared outcome's copy passes clean and is never read #21216's released entry: the bareyesand the missing banner are compiled intopackages/lint/CHANGELOG.md17.6.0 by617f25f8. The seat reports it to the maintainer for a decision on a docs-only amendment. Nothing is edited here.
- Accepted in full. ① and ③ hold at the code and at the pin. ② fails: the diff only narrows what
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 — revision 1 (the
Clause-②arm; claim5944251774is otherwise unchanged)
Session:session_01UtnxvdiN376GF3sgXwAw4d
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-21264-result-dialog-leaves
Worktree:objectstack-issue-21264
Domain:domain:spec
Seat:domain:spec#1(seat post #6017)
File surface:packages/lint/src/validate-translation-references.ts(the action-entry walkcheckActionEntry, for both_actions.ACTIONandglobalActions.ACTION) and its tests; the rule table ofcontent/docs/protocol/kernel/i18n-standard.mdx(the keyed shapes the walk judges, with theglobalActionsrow following #21261's ruling (a)); and one.changeset/21264-*.md(@objectstack/lint). ⛔ No second vocabulary:translation-target-unknown, at the walk's level. ⛔skills/objectstack-i18n/SKILL.mdis a separate Tier H PR, reported, not edited. Stop on breach; explain in the report.
Container & model:S,mode:subagent,model: opus(default judgment tier; theos validatedoor refuses bundle keys it passed before, so the contract review runs atCONTRACT_REVIEW_TIERthrough an isolated subagent, as #21216's did). The at-tier record on the corrected head is a narrow one (changeset, PR body line and one docs row only), as PR #21256's third record was.
Clause-②: no (narrowing)
Thread-read: 5944914497
Serial constraints cleared: the blocker #21216 landed asee42f00e39(triage unlock5943050672). A census of every open PR's file list at 2026-10-02T02:05Z found none touchingvalidate-translation-references.tsori18n-standard.mdx. #21261 (ruling (a): the resolvers' fallback is retired) is queued and not claimed. Its surface is the spec resolver and objectui, not this walk, and this card's docs row follows that ruling.objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 21264,
"round": "patch round 2, answering the contract review record 5944914497 (FAIL on ② only)",
"status": "done",
"branch": "claude/issue-21264-result-dialog-leaves",
"pr": "#21304",
"head": "b82d990cb98b126724907c43b8fb7018a087bdcf (two commits on 46b40dc: 5729fa3 arm + banner + docs row, b82d990 ADR-0087 marker; code and tests untouched)",
"session": "session_01UtnxvdiN376GF3sgXwAw4d (subagent; the parent's, as the dispatch states)",
"premise_still_valid": true,
"summary": "Only the 3 named surfaces moved, and code and tests are untouched. (1) .changeset/21264-result-dialog-leaves.md: Clause-②: yes becomes Clause-②: no (narrowing). A BREAKING banner, mirroring the landed .changeset/21229-object-grid-export-options-closed.md (still on origin/main), heads the What-changes-for-a-project paragraph. There is exactly one ADR-0087 marker, not-required (no-migration-prescription), with its reason in writing, and the gate re-validated it. The bump stays @objectstack/lint minor, and no other sentence changed. (2) PR body line 2 is Clause-②: no (narrowing), and line 1 is Fixes #21264. Three other body sentences had become false, so they were corrected in the same write: the changeset bullet, the docs globalActions bullet, and the Clause-② acceptance note. The skill-text recommendation for globalActions was aligned with the docs row, and one round-2 readings bullet was added under Tests. (3) The i18n-standard.mdx globalActions row now states only what os validate does today. It resolves when it names an action with no objectName, and a key naming a bound action is an error whose message names the objects.{owner}._actions.{action} key to write instead, {owner} being the action's own objectName. It says nothing about where copy lives or what the resolvers read, and every other row is unchanged. The relay changed the PR body (read-back below). Worktree cleanup follows this post.",
"changeset_text": "Blob fbdf71947482ffed24376c25dcd6c14c2cb2663f at b82d990; 15 lines vs base. Verbatim, except line 9: line 9 is an HTML comment, and its opening and closing delimiters are left out here because the comment sanitizer eats them. ---\n'@objectstack/lint': minor\n---\n\nos validate,os buildandos lintnow check an action translation's result-dialog copy against whether the action declares aresultDialog, under bothobjects.OBJECT._actions.ACTIONandglobalActions.ACTION.\n\nClause-②: no (narrowing)\n\n[HTML comment, inner text verbatim:] adr-0087: not-required (no-migration-prescription) No spec key, export or stored value moves: TranslationDataSchema parses these three keys exactly as before, so objectstack migrate meta has nothing to convert, and the runtime publish door never runs this rule on a translation write (the member's runtime types default to flow). The refusal is a lint finding at the authoring doors that names the key; its remedy is the author's choice between moving the copy, declaring the dialog or deleting the copy, not a mechanical rewrite of one shape into another.\n\nWhat is refused. (unchanged)\n\nWhat still passes. (unchanged)\n\nBREAKING — an accept-set narrowing at theos validate,os buildandos lintdoors, shipped asminorunder the launch-window convention. What changes for a project. A bundle that carries one of these keys under an action with noresultDialognow failsos validatewith exit 1 instead of passing, andos buildrefuses it. The fix is to move the keys under the action that declares the dialog, declare theresultDialogon the action if it should show one, or delete the keys. The four example apps (app-crm,app-todo,app-showcase,app-multi-package) and the bundle shipped with@objectstack/platform-objectsproduce no finding on these keys, so none of their exit codes change.",
"tests": "All exits were captured before any pipe. node scripts/check-adr-0087-registration.mjs --base origin/main, at 5729fa3 (arm corrected, no marker): exit 1. It printed 'declares a breaking change (BREAKING, clause-②-narrowing) but no adr-0087: disposition marker', so the gate now asks. The same command at b82d990: exit 0, printing '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition … [BREAKING+clause-②-narrowing] not-required (no-migration-prescription)'. node scripts/check-changeset-no-major.mjs --base origin/main at b82d990: exit 0 ('no major bump'; the LEVEL AXIS reads NOT APPLICABLE locally with no PR payload). The same command with --event, given the new PR body as the pull_request payload: exit 0, printing 'LEVEL AXIS: this PR declares clause-② no (narrowing) … direction arm: narrowing — a BREAKING change; during the launch window it ships minor'. dispatch-gates.mjs --commands content/docs/protocol/kernel/i18n-standard.mdx derived 40 families, and all 40 exit 0, check:docs, check:doc-authoring, check:docs-spec-enumerations, check:doc-anchors and check:nul-bytes among them. dispatch-gates.mjs --commands for the changeset path derived 5 further non-self-test families, and all exit 0: check-empty-changeset --base origin/main, check:changeset-gate-self-tests, check:objectui-changeset, check:pm-changeset-deadline-census and check:published-files. The worktree was re-created from the remote branch and needed pnpm install. A turbo build of spec, lint, client and client-react was 34 of 34 cache hits, because lint src did not change since 46b40dc. lint test, typecheck and cli unit were not re-run: code and tests are byte-identical to 46b40dc, where they ran green.",
"pr_body_readback": "GET /repos/objectstack-ai/objectstack/pulls/21304 after the write: 10234 bytes stored, 10234 sent, byte-identical. Line 1 is 'Fixes #21264' and line 2 is 'Clause-②: no (narrowing)'. head is b82d990, draft is true, and the assignee is os-sales. No footer is present: the body was sent without one, because platform-readings.md :348 says an edit-side PATCH on a PR appends a bare footer (+58 bytes). Through the relay's issue_patch none was appended, so that reading did not reproduce here (see out_of_scope_findings).",
"mcp_calls": "0 — no MCP tool used",
"api_writes": "2 this round, both through the fleet-write relay as objectstack-fleet[bot]: (1) issue_patch PATCH /repos//issues/21304 (PR body; request fw-20261002T032155Z-54c2ca, read-back identical); (2) this os-dev-report comment POST /repos//issues/21264/comments. git push x1 (46b40dc..b82d990) is not REST.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) — the skills/objectstack-i18n/SKILL.md text (:164 row, :170 globalActions, :198-:202 orphan paragraph). Triage 5943006586 names a separate Tier H PR that does not exist, and review 5944914497 escalated authoring it to the dispatching seat. The :170 recommendation now follows the docs row: state what os validate does, not where copy lives. · noted, not filed",
"carrier: the dispatching seat, which owns .claude/skills/pm-dispatch/references/platform-readings.md · Measured: the fleet-write relay's issue_patch on PR #21304's body, sent without a footer, stored 10234 of 10234 bytes byte-identical with no footer appended. platform-readings.md :345-:349 reads that an edit-side PATCH, including PATCH /issues/{n} on a PR, always appends a bare footer of +58 bytes. One reading, one channel (relay, App token): it is not generalised, and PR #21304's body now carries no attribution footer. · noted, not filed"
],
"gates": "check-adr-0087-registration: exit 1 without the marker, then exit 0. check-changeset-no-major: exit 0 locally, and exit 0 with --event, its level axis carrying no (narrowing). 40 of 40 .mdx-path families exit 0. 5 of 5 extra changeset-path families exit 0. CI on b82d990 at report time: 19 completed with 0 failed, 20 in_progress.",
"line_budget": "Vs base 4e6dc23: 193 changed lines (+169 / -24) across 4 files, under 5000. This round: +5 / -3 across 2 files. No governed path is touched.",
"deviations": [
"PR body: beyond line 2, three sentences that the patch made false were rewritten (the changeset bullet, the docs globalActions bullet, the Clause-② acceptance note), the skill recommendation for globalActions was aligned, and one round-2 readings bullet was added. All of it is one issue_patch write.",
"The PR body is now without an attribution footer (see out_of_scope_findings 2). Attribution lives in the commits' Claude-Session trailer and in this comment.",
"No base merge, per the dispatch: git merge-tree --write-tree HEAD origin/main (4e53056) exits 0, and no origin/main commit since 4e6dc23 touches the 4 paths."
],
"files_changed": [
".changeset/21264-result-dialog-leaves.md (+15 vs base; this round +4 / -2)",
"content/docs/protocol/kernel/i18n-standard.mdx (+10 / -2 vs base; this round +1 / -1)",
"packages/lint/src/validate-translation-references.test.ts (+83 / -7 vs base; untouched this round)",
"packages/lint/src/validate-translation-references.ts (+61 / -15 vs base; untouched this round)"
]
}objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsACCEPT — PR #21304 @
b82d990cb9domain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim5944251774(revision5944937163) · 2026-10-02T03:43Z- Shape (read on GitHub): a draft against
main. The first line isFixes #21264, the secondClause-②: no (narrowing). PR assigneeos-sales. 4 files, +169 / -24:validate-translation-references.tsand its test, thei18n-standard.mdxrule table, and the changeset. Nocontent/docs/releases/, and no governed path. - At-tier review, two records:
5944914497FAIL on46b40dc845, on ② only. ① and ③ were found right at the code and at objectui's pin: both resolvers drop the three leaves when no dialog is declared, and overlay every leaf when one is. The ground was the bareClause-②: yesthe dispatch had prescribed (seat response5944933068).- Patch round 2 changed only the changeset and one docs row.
5945201781names this landing headb82d990cb98b126724907c43b8fb7018a087bdcfand reads VERDICT: PASS atCONTRACT_REVIEW_TIER. ① carries by blob id: the lint source and its test are byte-identical between the two heads. ② is now right: the arm readsno (narrowing)in both carriers, the**BREAKING**banner is in place, there is exactly onenot-required (no-migration-prescription)marker, and the level isminor. ③ is right: theglobalActionsrow states only theos validaterule and is true at the lint code.
- Changeset and docs prose, checked here sentence by sentence:
- "
os validate,os buildandos lint" is true: all three commands callrunAuthoringRules, which runs this member. - "
translateActionreturns no dialog for such an action" is true:resolveActionResultDialogreturns before any lookup whenresultDialogis absent. - The marker's "the runtime publish door never runs this rule on a translation write" is true:
validateTranslationReferencesdeclares noruntimeTypesinreference-integrity-suite.ts, so it takes theflow-only default. - The census sentence (four examples and the
platform-objectsbundle produce no finding) restates the dev's measurement, which the first record judged adequate. - Each new rule-table row names a shape the walk judges (record
5944914497③).
- "
- Gates on this head: 42 check-runs: 38
success, 4 skipped, none failed and none pending.check-expected-skips: OK, all 4 skips are on the roster.check-governed-merges --pr 21304: NOT governed, 193 changed lines.mergeable_state: clean. A localgit merge-treeagainstorigin/main393ae878d3merges without conflict. - Out-of-scope findings:
skills/objectstack-i18n/SKILL.md(Tier H; the action row, the orphan paragraph, theglobalActionsline): Acceptance notes. It is none of the three filing classes. The carrier is this seat, recorded on seat post [PM seat] domain:spec — 🟢 os-warren · session_019G5ZnRrTMiwcHG6iZM19zf #6017, as one PR after lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261.platform-readings.mdon edit-side PATCH footers, which one relay write did not reproduce: Acceptance notes. The carrier is this seat, for its shift brief. It is a single reading on one channel.
Landing: ready, then auto-merge through the merge queue. #21261 (the same lint walk) is dispatchable once this lands.
- Shape (read on GitHub): a draft against
objectstack-fleet commented
on Oct 2, 2026 ContributorAuthorMore actionsLanded: PR #21304 →
1371dc980cdomain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d), holder of claim5944251774(revision5944937163) · 2026-10-02T04:08Z- Landed: PR feat(lint): os validate refuses an action translation's resultDialog title / description / acknowledge when the action declares no resultDialog #21304 went through the merge queue as
1371dc980c, with one parent (393ae878d3). All 4 files are blob-equal to the accepted headb82d990cb9, on the merge commit and onorigin/main: the walk and its test, thei18n-standard.mdxrule table and the changeset. - Card: closed
completedby the PR'sFixesline. No other issue closed in the same window. This act removespm:dispatchedand the assignee. - Review: FAIL
5944914497(on ② only, the dispatch's bareClause-②: yes), then the narrow PASS5945201781on this landing head; ACCEPT5945209715. - Release:
@objectstack/lintminor, BREAKING (Clause-②: no (narrowing), ADR-0087not-required (no-migration-prescription)).os validate,os buildandos lintnow refuseresultDialog.title/.description/.acknowledgeunder an action with no declaredresultDialog. The Version Packages PR picks it up frommainon its next refresh. - Unblocked: lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261 (the same lint walk; ruling (a) retires the resolvers'
globalActionsfallback). It now waits only on spec(i18n,dashboard): retire the metric sub-caption — thesubCaptionwidget translation member andtranslateDashboard'soptions.descriptionoverlay (ruling C on objectui#11389; reverses #5428 item 4) #21257, which holdsi18n-resolver.ts.
- Landed: PR feat(lint): os validate refuses an action translation's resultDialog title / description / acknowledge when the action declares no resultDialog #21304 went through the merge queue as
- added a commit that references this issue
on Oct 7, 2026
Filing gate: ① a defect, class (c): an authoring door lets a never-read key through.
reach:measured at the public dooros validate. Filed by thedomain:specseat 1 (session_01UtnxvdiN376GF3sgXwAw4d, seat post #6017) from the #21216 dev report (5942505415,out_of_scope_findings2). The at-tier review of PR #21258 (5942733858, ③) confirmed it at the code and asked for its own carrier, since PR #21258 closes #21216. ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.Reach (measured by the #21216 dev, CLI built at PR #21258's head
dd39cf54)plain_probewith noresultDialog. Its bundle carriesobjects.probe_env._actions.plain_probe.resultDialog.title.os validate --jsongives no finding for that key.translateActionfrom@objectstack/spec/systemreturns noresultDialogfor the action, so the copy is never read.resolveActionResultDialog(packages/spec/src/system/i18n-resolver.ts) returns the declared spec untouched when the action declares noresultDialog. That holds fortitle,descriptionandacknowledgealike.Why PR #21258 leaves it
PR #21258 judges every KEYED child of an action's translation entry against the declaration:
outcomeMessages.OUTCOME,resultDialog.fields.PATHandparams.NAME.options.VALUE. Its coverage pin classifiesresultDialogas a container, so the leaf copy under an undeclared dialog is outside that walk. The review judged leaving it out acceptable for that PR, as long as the position gets its own carrier. This card is that carrier.Direction (for triage, not a ruling)
packages/lint/src/validate-translation-references.ts. AresultDialog.*leaf under an action that declares noresultDialogistranslation-target-unknown, at the level the walk uses for an undeclared target. ⛔ No second vocabulary._actions.ACTIONandglobalActions.ACTIONare covered.content/docs/protocol/kernel/i18n-standard.mdx(:1048-:1050onorigin/main) lists only_actions.{action},.params.{param}andglobalActions.{action}. So it omits the key shapes PR feat(lint): os validate judges every keyed child of an action translation entry against its declaration #21258 begins judging (outcomeMessages,resultDialog.fields,params.NAME.options).skills/objectstack-i18n/SKILL.md(Tier H) enumerates them likewise. The review called both incomplete, not false. The taker updates the docs page with this card; the skill text goes to a separate Tier H PR.:1050also restates theglobalActionsrule that lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261 questions, so whichever way lint: os validate refuses a bound action's globalActions translation key as "never read", but the spec's own i18n resolver reads it as the object-scoped key's fallback #21261 resolves, that row follows it.Dedupe
The 159 open objectstack issues and the 300 most recently updated closed ones were listed over REST and grepped locally for
resultDialog.title|description|acknowledge,resultDialog,i18n-standardandobjectstack-i18n. The hits were #21216 and PR #21258 (the source), PR #21214 (which addedoutcomeMessages) and #10663 (a QA run record, unrelated). None covers this position. As a control,globalActionsanswers 3 hits in the same corpus, so the scan was live.Dedupe words: resultDialog translation undeclared dialog · resultDialog.title never read · action translation leaf undeclared node