Skip to content

i18n: the flow runner reads translation.flows.FLOW.label for its header and completion toast, falling back to the served flowLabel (stage 2 of objectstack-ai/objectstack#20318) #11092

Closed

Description

@objectstack-fleet

This card carries the objectui half (stage 2) of objectstack-ai/objectstack#20318: the flow runner reads translation.flows.FLOW.label. objectstack-ai/objectstack#20318 keeps the served label (stage 1, objectstack-ai/objectstack#20633) and the ledger flip that follows this card's landing.

Filing gate: ④ a coordination node, the per-layer child of an in-flight card. Filed by the domain:spec execution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post objectstack-ai/objectstack#18549) from the stage-1 ACCEPT on objectstack-ai/objectstack#20318. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

Why this is owed

objectstack triage graded objectstack-ai/objectstack#20318 ENFORCE by the maintainer's criterion: translating a flow's label is mainstream (the Salesforce Translation Workbench translates Flow labels). Today nothing in objectui reads translation.flows.FLOW.label, and no surface displays the flow's own label. The domain:spec seat 4 measured that on objectui 797a30f4 (objectstack-ai/objectstack#20318, comment 5880531686):

  • FlowRunner.tsx reads only flows.FLOW.screens (localizeScreen, about :219–:233).
  • The runner DialogTitle (about :462) is the screen title or flowRunner.title.
  • The completion toast (about :385) interpolates flowName, the API name.
  • The launcher's notices use the action's label or Flow "NAME".

The served shape this reader consumes (objectstack-ai/objectstack#20633, at-tier PASS)

  • data.flowLabel (optional string) is on every 200 from POST /api/v1/automation/NAME/trigger and POST /api/v1/automation/NAME/runs/RUN_ID/resume: paused, finished, refused or skipped.
  • It is not on a 400 FLOW_FAILED, nor on the 404 / 409 / 422 refusals.
  • It is the flow definition's authored label, verbatim. For a subflow chain it is the addressed parent's label, never the child's.
  • AutomationResult.flowLabel in @objectstack/spec (contracts/automation-service.ts) declares it, and TriggerFlowResponseSchema.data mirrors it.

What the reader does (the direction triage set; ⛔ not a ruling on UI design)

  • FlowRunner keeps flowLabel from the trigger and resume responses (ScreenFlowState gains it). Two hosts mount FlowRunner (useConsoleActionRuntime.tsx and RecordDetailView.tsx), so the read belongs in FlowRunner.
  • The displayed label resolves as: the active locale's translation.flows.FLOW.label, then flowLabel, then flowName.
  • It gets a display slot: the runner header, and the completion toast in place of the API name.
  • Pins: a zh bundle and an en fallback, and a flow with no translation showing its authored label.

Sequencing

Dedupe words: flows label translation FlowRunner · flowLabel runner header · translation.flows label reader


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Restart-when: npm view @objectstack/spec version answers a release whose AutomationResult declares flowLabel (objectstack PR #20633), and objectui main's pnpm-lock.yaml resolves it

    Triage: first grade — enhancement · priority:p3 · domain:ui · area:i18n · pm:on-hold. It is held on the install surface: the middle step of the label chain is not in any spec objectui can install

    Triage: lands in FlowRunner.tsx (in app-shell), the one component both hosts mount ⇒ domain:ui. It takes the p3 and area:i18n of its parent, objectstack-ai/objectstack#20318.

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-29T12:58Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why held, not queued.

    • The chain the parent's direction sets is: the active locale's translation.flows.FLOW.label, then flowLabel, then flowName.
    • flowLabel is declared by objectstack PR #20633 (AutomationResult.flowLabel, and mirrored in TriggerFlowResponseSchema.data). It merged at 2026-09-29T12:25Z, but it isn't in any published release: npm's latest is 17.5.0, and objectui's lockfile resolves 17.4.0.
    • So reading it now means a local type for a field the installed contract doesn't have, which is the consumer-side widening objectui's AGENTS.md bans.
    • The card is small enough to land whole once the release is installable. ⛔ Don't split it into a translation-only PR now and a second one later.

    Direction at restart (the card body's "What the reader does" stands):

  2. added
    area:i18nThe customer's own language, across UI, metadata and notifications
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    enhancementNew feature or request
    on Sep 29, 2026
  3. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Hold released: pm:on-hold → pm:queue. The Restart-when: condition (this card's 2026-09-29 triage grade) holds on the installed @objectstack/spec 17.6.0

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-05T00:08Z. ⛔ Not a claim, ⛔ not a dispatch. Found in a full pass over blocked and held cards.

    The condition: "npm view @objectstack/spec version answers a release whose AutomationResult declares flowLabel (objectstack PR #20633), and objectui main's pnpm-lock.yaml resolves it."

    Readings at this write:

    So the hold could have released when objectui moved to 17.6.0 (2026-10-03). The grade in this card's triage comment stands: enhancement · p3 · domain:ui · area:i18n. objectstack-ai/objectstack#20318 is blocked on this card, and it unlocks when this one closes.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_015W8GBu6sBiqus2L2xjMsAL
    Account: os-steve
    Branch: claude/issue-11092-flow-label-reader
    Worktree: objectui-issue-11092
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/views/FlowRunner.tsx (ScreenFlowState, the runner header and the completion toast), packages/app-shell/src/utils/flowResponse.ts, the hosts that build ScreenFlowState from a trigger answer (packages/app-shell/src/hooks/useConsoleActionRuntime.tsx, packages/app-shell/src/views/RecordDetailView.tsx, apps/console/src/pages/developer/FlowRunsPage.tsx), the FlowRunner tests beside them, the app-shell locale bundles only if a toast string changes, and .changeset/11092-*.md (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default tier for the build (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; floor sonnet · default opus · ceiling fable). The delivered PR owes an isolated review at CONTRACT_REVIEW_TIER (reason: Clause-②: yes, below).
    Clause-②: yes
    Thread-read: 5985889871
    Serial constraints cleared: none, read 2026-10-05T01:06Z. The open objectui PRs (#11624 plugin-form + types, #11069 packages/cli, #11600 the release PR) touch none of these files. The served half, objectstack-ai/objectstack#20633, declares AutomationResult.flowLabel in @objectstack/spec 17.6.0, which objectui main resolves (triage 5985889871).

    Why Clause-②: yes: ScreenFlowState is exported from @object-ui/app-shell (src/index.ts:224), and the card's direction adds flowLabel to it. That widens a published type.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 11092,
    "status": "done",
    "branch": "claude/issue-11092-flow-label-reader",
    "pr": "#11636",
    "session": "session_015W8GBu6sBiqus2L2xjMsAL (subagent run; the parent's harness-stamped id)",
    "premise_still_valid": true,
    "summary": "FlowRunner now names the flow by a label resolved in the card's order: the active locale's flows.FLOW.label, then the served AutomationResult.flowLabel, then flowName. The first two steps are the spec's own translateFlow, fed the existing activeFlowsBundle read. The label is drawn in a muted line above the screen heading (the DialogTitle stays the step title and the accessible name) and as the flow parameter of the existing flowRunner.completed toast, with no new i18n key. interpretFlowResponse lifts flowLabel once (paused and done arms; judgeFlowLaunch's screen follow-up), typed via Pick of AutomationResult. ScreenFlowState (published) gains optional flowLabel the same way, and all three hosts thread it: useConsoleActionRuntime, RecordDetailView, and FlowRunsPage, at both of its open sites. Zone 2 #2 was confirmed: client.automation.execute resolves to the unwrapped AutomationResult from the trigger door, so it carries flowLabel. Landing site as expected.",
    "tests": "Pins: new packages/app-shell/src/views/tests/FlowRunner.flowLabel-11092.test.tsx (zh-CN bundle → translation; en → served label; untranslated flow with bundle live for the screen → authored label; no served label → API name; paused resume answer carries label; each on header line AND toast, toast text asked of the i18n instance, not spelled). flowResponse.test.ts +4 (lift on paused/done, undefined for absent/non-string, screen follow-up). One paused-launch pin each appended to useConsoleActionRuntime.refusedLaunch-9973 and RecordDetailView.refusedLaunch-9973 harnesses, and one in FlowRunsPage.test.tsx (Run + Continue run). Runs, all through os-verify-lock, from the repo root: AT 5c65546 (pre-merge): touched files 'Test Files 5 passed (5) / Tests 51 passed (51)'; pnpm exec vitest run packages/app-shell/ 'Test Files 1001 passed | 1 skipped (1002) / Tests 9941 passed | 9 skipped (9950)' VERDICT command-exit 0; pnpm --filter @object-ui/app-shell type-check exit 0 (tsconfig.test.json --listFilesOnly lists all 4 touched app-shell test files); pnpm --filter @object-ui/app-shell lint '0 errors' and 0 warnings on the 385 added lines (warning lines intersected with git diff -U0 hunks); console type-check exit 0 (after building app-shell + 6 other dist-less deps), console lint '0 errors' and 0 warnings on the 34 added lines; FlowRunsPage.test.tsx + loadLanguage.test.tsx 'Test Files 2 passed / Tests 8 passed'. AFTER merging origin/main 1c2e2c4 (merge commit 6950ab0, = PR head): rebuilt types/plugin-form/app-shell exit 0; touched files + loadLanguage 'Test Files 6 passed (6) / Tests 56 passed (56)'; app-shell type-check exit 0; console type-check exit 0; console lint '0 errors'; whole app-shell rerun 'Test Files 1 failed | 1000 passed | 1 skipped / Tests 1 failed | 9940 passed' VERDICT command-exit 1, the one failure AppContent.deniedVsUnpublished.test.tsx (untouched by this diff; network-escape guard tripped on a real localhost:3000/api/v1/meta read; the file stubs no fetch), rerun alone at 6950ab0 'Tests 15 passed (15)' exit 0, and green in the pre-merge whole run. App-shell lint not rerun post-merge: eslint.config.js is not type-aware (0 projectService/project keys) and the merge touched no app-shell file. Ablation at 5c65546 via objectstack scripts/ablation-replace.mjs (literal anchor x1, on-disk marker 1 / anchor 0 printed inside the held child, restore from HEAD proven by blob hash == HEAD and empty git diff HEAD, plus a script-level EXIT/INT/TERM trap), expected split written down before each run, tests resolve FlowRunner/flowResponse from src by relative import (no dist in path): leg A (displayFlowLabel returns flowName) 'Tests 7 failed | 44 passed' = zh, en, untranslated, resume + 3 host pins red; no-label and 4 lift pins green, as predicted. Leg B (servedFlowLabel returns undefined) 'Tests 8 failed | 43 passed' = 3 lift pins + 2 app-shell host pins + en, untranslated, resume red; zh (bundle wins), FlowRunsPage (no flowResponse), no-label, absent/non-string green, as predicted. Post-ablation: git diff HEAD empty-exit 0, both blob hashes == HEAD, status porcelain 0.",
    "gates": {
    "check:new-line-citations": "0 (0 new citations) at 6950ab0",
    "check:control-bytes": "0 at 6950ab0",
    "check:i18n-keys": "0 at 6950ab0",
    "check:changeset-claims": "0 at 6950ab0",
    "check:pending-changeset-literals": "0 at 6950ab0",
    "check:vi-mock-specifiers": "0 at 6950ab0",
    "check:vi-mock-inherit": "0 at 6950ab0",
    "check:vi-mock-override-shape": "0 at 6950ab0",
    "check:test-path-roots": "0 at 6950ab0",
    "check:phantom-deps": "0 at 6950ab0",
    "check:installed-pin-claims": "0 at 6950ab0",
    "check:spec-symbols": "0 at 6950ab0",
    "check:esm-specifiers": "0 at 6950ab0 (specifiers leg only, by the script's own design)",
    "scripts/check-changeset-presence.mjs": "0 at 6950ab0",
    "scripts/check-changeset-no-major.mjs": "0 at 6950ab0",
    "scripts/check-governed-queue-guard.mjs --test (11 paths)": "0, NOT GOVERNED",
    "app-shell type-check": "0 at 6950ab0",
    "app-shell lint": "0 at 5c65546 (not type-aware; merge touched no app-shell file)",
    "console type-check": "0 at 6950ab0",
    "console lint": "0 at 6950ab0",
    "vitest touched files + loadLanguage": "0 at 6950ab0 (6 files / 56 tests)",
    "vitest packages/app-shell/": "0 at 5c65546; 1 at 6950ab0 (1 unrelated flake, solo rerun 0)",
    "check:i18n-drift": "not owed (no locale bundle changed)"
    },
    "files_changed": [
    ".changeset/11092-flow-label-reader.md",
    "apps/console/src/pages/developer/FlowRunsPage.tsx",
    "apps/console/src/pages/developer/FlowRunsPage.test.tsx",
    "packages/app-shell/src/hooks/useConsoleActionRuntime.tsx",
    "packages/app-shell/src/hooks/tests/useConsoleActionRuntime.refusedLaunch-9973.test.tsx",
    "packages/app-shell/src/utils/flowResponse.ts",
    "packages/app-shell/src/utils/tests/flowResponse.test.ts",
    "packages/app-shell/src/views/FlowRunner.tsx",
    "packages/app-shell/src/views/RecordDetailView.tsx",
    "packages/app-shell/src/views/RecordDetailView.refusedLaunch-9973.test.tsx",
    "packages/app-shell/src/views/tests/FlowRunner.flowLabel-11092.test.tsx"
    ],
    "line_budget": "n/a (no skills/** or governed path touched); diff vs merged main 1c2e2c4: 11 files, +438 / -19",
    "deviations": [
    "Post-merge whole-package app-shell rerun was not fully green: 1 failure in AppContent.deniedVsUnpublished.test.tsx, outside this diff, green alone and green pre-merge; reported, not fixed here.",
    "App-shell lint was measured pre-merge only (declared narrowing: eslint is not type-aware and the merge changed no app-shell file); console lint was rerun post-merge.",
    "Host pins were appended to the two existing refusedLaunch-9973 harness files (a separate describe block naming objectui#11092) instead of duplicating those harnesses in new files.",
    "Commits carry the model-free trailer pair per objectui AGENTS.md, not the harness reminder's model-named Co-Authored-By line.",
    "One relay invocation failed before sending anything (relative script path after a cwd reset, MODULE_NOT_FOUND); rerun with the absolute path. No write was made by the failed call."
    ],
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "3 — each sent through scripts/pm relay (one repository_dispatch POST /repos/objectstack-ai/objectstack/dispatches per write, executed as objectstack-fleet[bot]): (1) pr_create → POST /repos/objectstack-ai/objectui/pulls (draft, #11636; read-back 9085/9085 bytes identical); (2) label-write --assign → POST /repos//issues/11636/assignees (os-steve; read-back matches; zero label writes); (3) this os-dev-report → POST /repos//issues/11092/comments. Plus git pushes of the branch (empty probe, 3f6183a, 5c65546, merge 6950ab0), which are not REST writes.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: 承接者:无 · noted, not filed — AppContent.deniedVsUnpublished.test.tsx can trip the network-escape guard under whole-package load (its meta probe reads localhost:3000 with no fetch double; the guard's own message names the fix shape). Observed once in two whole-package runs; not reproducible alone, so not a class (a) card. Dedupe words: AppContent deniedVsUnpublished network escape · meta probe fetch double · localhost:3000 flake",
    "carrier: the PM seat (dispatch gate list) · noted, not filed — the dispatch-named whole-package app-shell run held the shared verify lock 21m42s and 22m44s on this box; the lock tool flags holds that long as a starvation risk for sibling seats."
    ]
    }

  6. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (content): PR objectui#11636, head 6950ab0. The contract review is still owed before landing

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-05T02:42Z. Reviewed against GitHub and origin/main, not against the report's prose (os-dev-report on this card).

    • Shape. The PR is a draft against main, and its assignee is os-steve. Its first line is Fixes #11092, the only line with a closing keyword next to an issue number. Clause-②: yes is on its own line. Against main the diff is 11 files, +438/−19, inside the claim's file surface.
    • The label is read once and typed by the contract. interpretFlowResponse lifts flowLabel in one place (servedFlowLabel) onto the paused and done arms and onto judgeFlowLaunch's screen follow-up. Every new member is Pick<AutomationResult, 'flowLabel'> from the installed @objectstack/spec 17.6.0, with no local re-declaration. The resolution order is the card's (bundle, then served label, then API name), and its first two steps are the spec's own translateFlow over the bundle the runner already reads.
    • Zone 2 Add automated testing infrastructure and CI/CD workflows #2 held: the card named two hosts, and there are three. FlowRunsPage.tsx threads the label at both of its open sites, with a pin.
    • Display slot (the card left it open): a muted line above the screen heading names the flow. The heading stays the step's own title and the dialog's accessible name. The completion toast passes the resolved label as the existing flowRunner.completed key's flow parameter, so no i18n key is added.
    • Changeset, sentence by sentence. @object-ui/app-shell: minor and @object-ui/console: patch match what the diff publishes. The "older server" paragraph matches the code: with no served label and no bundle entry, both slots show the API name. The Clause-② paragraph names the one widened member, ScreenFlowState.flowLabel, and says no prop, export or i18n key moves. That matches the diff.
    • Tests. The pins cover the zh bundle, the en served label, an untranslated flow, no label at all, a paused resume, and one pin per host. Two ablation legs went red exactly where predicted. The whole app-shell suite was green before the merge. After the merge, one unrelated file (AppContent.deniedVsUnpublished.test.tsx, not in this diff) tripped the network-escape guard under whole-package load, and it passed run alone. CI on this head is the verdict on it.

    Owed before landing: an isolated review at CONTRACT_REVIEW_TIER on this head, because the claim declares Clause-②: yes. needs:contract-review is added to the PR in this stroke. The PR stays a draft until a conforming PASS is on record and every check on the head is green.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11636 → main 39a3e91, verified by content

    domain:ui execution seat 1 @ objectui · session_015W8GBu6sBiqus2L2xjMsAL (os-steve) · 2026-10-05T03:21Z.

    • Merged through the merge queue as squash commit 39a3e91 (one parent, 22ddcd5), an ancestor of origin/main. Its +/- lines are identical to the PR head 6950ab0 diffed from its merge base: 11 files, +438/−19. The contract review PASS on that head is 5987358949.

    • Content check against the first parent:

      reading 22ddcd5 39a3e91
      function servedFlowLabel in utils/flowResponse.ts 0 1
      function displayFlowLabel in views/FlowRunner.tsx 0 1
      interface ScreenFlowState extends Pick<AutomationResult 0 1
      flowLabel in apps/console/.../FlowRunsPage.tsx 0 3
      export function interpretFlowResponse (control) 1 1
    • The card closed completed through the PR's Fixes line. It was the only issue closed in that window. pm:dispatched is removed in this stroke.

    • Downstream: i18n: the flow launcher and runner header read translation.flows.<flow>.label (1 key) objectstack#20318 is pm:blocked on this card. Its ledger flip waits only on objectstack's .objectui-sha covering 39a3e91; the pin reads 9dfaca6 now. A note is posted there.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions