Skip to content

Studio metadata forms: 新建软件包 shows 输入无效 before any input, help text stays English in a Chinese console, and a toast covers the publish button #10287

Description

@os-zhuang

Studio metadata forms: 新建软件包 shows 输入无效 on every required field before the author types anything, and its help text is English inside a Chinese console

Measured on 17.1.0 (open edition, objectstack dev), Studio → package menu → 新建软件包(可写 base).

1. Errors before input

The dialog opens with the validation already failed:

显示名称 *   name
             Human-readable package name
             输入无效            ← before a single keystroke
软件包 ID *  id
             Unique package identifier (reverse domain style)
             输入无效            ← same

Nothing has been touched. Required-field validation is running on mount instead of on blur/submit, so the author's first impression of the form is two red errors they did not cause. It also moves the layout as it clears — each field jumps by ~one line height the moment it becomes valid, which is enough to make a click land on the wrong control while filling the form top to bottom.

2. Mixed languages in one line

Labels are translated, the help text under them is not, and both render together:

label (zh) help (en)
显示名称 Human-readable package name
软件包 ID Unique package identifier (reverse domain style)
对象命名空间 Short namespace identifier; also the mandatory prefix of every object name (e.g. "todo" → object names "todo_task", "todo_project")
版本 Package version (semantic versioning)
类型 Type of package
描述 Package description

The same split shows up elsewhere in the metadata console — the object form builder lists 所有者 next to Owning Business Unit and Search Index, and the flow node palette is fully Chinese except for one entry:

…
等待        等待事件或定时器
结束        终止流程
Revise Window   Durable pause an approval send-back parks the run on while the submitter
                reworks the record. Continues only through the approvals service (resubmit),
                which re-enters the approval node over the declared back-edge.

— an English name and a three-line English paragraph in a list where every other item is a Chinese name and a short Chinese phrase.

3. The publish panel's primary button sits under the toast

发布 → 待发布的变更 panel: the footer explains "发布将带来一次性(原子地)发布此包全部 1 个待发布草稿" and carries 全部发布. A toast from the preceding save (对象「…」已存为草稿) renders bottom-right, directly over that footer, and covers the button until it times out.

Expected

  • Validate on blur/submit, not on mount.
  • Feed the metadata-admin form generator's description/help strings through the same i18n bundle the labels already use — and add Revise Window's node name and description to it.
  • Keep toasts clear of the panel footer (or anchor the publish action above the toast layer).

Activity

  1. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 10287,
    "status": "done",
    "branch": "claude/issue-10287-navigation-designer-doc-type",
    "pr": "objectstack-ai/objectui#10315",
    "session": "session_01BA3nKVUwKQJf8DBxrSVtNC — subagent run under the PM seat's session (container CLAUDE_CODE_REMOTE_SESSION_ID cse_01BA3nKVUwKQJf8DBxrSVtNC)",
    "premise_still_valid": true,
    "summary": "The triage's located fix measured true on both legs and landed as draft PR objectui#10315 (head 6f970da0, one commit). NAV_TYPE_META in NavigationDesigner.tsx gains a doc entry (appDesigner.navTypeDoc, bg-blue-100 text-blue-700, lucide BookOpen) and is now a Record keyed by NavigationItemType | 'doc', with a code comment saying the | 'doc' is removed at the pin bump that ships doc (objectstack#19789). The key has a fallback in useDesignerTranslation and a translation in all ten locale packs. A runtime guard test reads the installed spec's NavigationItemSchema discriminants and renders every type. doc is NOT in QUICK_ADD_TYPES (that is objectui#10188). Changeset: plugin-designer and i18n patch. The claim was verified first: the newest Claim comment 5818016133 names this branch. No claim was posted and no assignee was written; the card's assignee was already empty when I read it. The gate reproduction had one incident: my first gate-leg turbo run in a linked worktree wrote 6 build entries into the SHARED turbo worktree cache at /home/user/objectui/.turbo/cache, built against the injected main spec. Their hashes are d729e66902a518d8 (types), 4455b822ef19122c (core), c7bb814ad5358f80 (providers), 40f6341f9062df00 (permissions), e48626af73a03120 (mobile) and d0ab6013751342ef (react-runtime). I stopped that run and redid every gate-leg run with a private --cache-dir. The session's auto-mode classifier refused my attempt to delete those 6 entries, so they are still there. I compared each one with the same package built against the pinned spec (diff -rq on dist): 0 differing files in all 6, so nothing wrong is being served from the cache.",
    "tests": "All runs are on head 6f970da0 unless a run says base. Heavy runs went through os-verify-lock, and every VERDICT line printed command-exit 0 unless noted. (b) GATE PATH, reproduced locally: objectstack main was 6bf7f1c when read via REST commits/main. I made a sparse, blobless, depth-1 clone of packages/spec and scripts, then ran pnpm install --filter @objectstack/spec..., pnpm --filter @objectstack/spec build (VERDICT command-exit 0), npm pack --ignore-scripts, and node scripts/spec-main-shape-gate.mjs inject into a separate detached objectui worktree (exit 0; zod re-pointed to 4.6.1, the gate's own behaviour). Then TURBO_FORCE=true turbo run type-check --continue --concurrency=2 with a private --cache-dir. RED at base 8b1f0661 with --filter=@object-ui/plugin-designer: exit 2, 16/17 tasks, 'plugin-designer:type-check: src/NavigationDesigner.tsx(82,7): error TS2741: Property doc is missing'. The gate's own report step on that log exits 1 and attributes the error to NavigationDesigner.tsx line 82 against objectstack 6bf7f1c. GREEN at 6f970da0 with --filter=...@object-ui/plugin-designer (the package and its dependents): 'Tasks: 40 successful, 40 total', 0 'error TS'; 5 type-checks (plugin-designer, app-shell, console, example-console-starter, example-byo-backend-console) plus 33 builds, including the plugin-designer and app-shell builds the failure had hidden. The report step exits 0: 'objectui type-checks against @objectstack/spec at that commit'. I narrowed the scope to plugin-designer's dependents on purpose: no package outside that set can be moved by this diff, and the full graph is the PR's own gate run. Nothing new surfaced once the build was unblocked. (a) PINNED SPEC 17.4.0: pnpm --filter @object-ui/plugin-designer --filter @object-ui/i18n type-check, exit 0, both scripts echoed 'tsc --noEmit && tsc -p tsconfig.test.json'. tsc -p tsconfig.test.json --listFiles includes the guard test. GUARD TEST: 10 passed against the pinned spec (9 types plus the non-vacuity case); 11 passed against the injected main spec (10 types). SUITES from the repo root: pnpm exec vitest run packages/plugin-designer/ packages/i18n/ packages/app-shell/src/tests/defaults-maps-mirror-en-pack.test.tsx gave 'Test Files 94 passed (94)' and 'Tests 1340 passed (1340)'. all-locales-key-parity, defaults-maps-mirror-en-pack and the guard test run by name gave 'Test Files 3 passed (3)' and 'Tests 57 passed (57)'. ABLATION, run after the commit through /home/user/objectstack/scripts/ablation-replace.mjs in wrap mode (anchor x1 to x0, blob dc6cc9b5f055 to a1ec0cb78efb, then 'ok restored: blob == HEAD (dc6cc9b5f055) and git diff HEAD is empty'; grep -c navTypeDoc was 0 during the mutation and 1 after). The subject is imported from src by relative path, so no dist is involved. Deleting the doc entry on the gate path gave TC_EXIT=2 with TS2741 'Property doc is missing', and the guard test failed 1 of 11: 'draws the doc type', TypeError: Cannot read properties of undefined (reading Icon). Deleting it on the pinned leg gave TC_EXIT=2 with TS2741, because the Record key includes 'doc'. REVERSE CHECK on the pinned leg: removing | 'doc' from the key gave TC_EXIT=2 with TS2353 'doc does not exist in type', which shows the extra union member is needed. GATES, all exit 0: check:i18n-keys; check:i18n-drift (1 key added, 0 en values changed); check:i18n-dead-keys (report only; navTypeDoc is in needs-review like its 9 siblings); check:control-bytes; check:new-line-citations (VERDICT 0 new); check-changeset-presence.mjs (13 source files of 2 released packages, 1 changeset); check:changeset-claims; check:pending-changeset-literals; check:phantom-deps; check:unused-deps; check:icon-record-names; check:spec-symbols; check:test-path-roots; check:designer-field-key-parity; check:installed-pin-claims; check:published-tsconfig-exclude; check:published-dist; check:vi-mock-inherit; check:unreferenced-sources. LINT, narrowed with three pieces of evidence: (1) the population is turbo run lint, i.e. 'eslint .' per package, and eslint --print-config resolved a config for all 13 changed ts/tsx files; (2) eslint --no-inline-config --format json counted 13 files, 0 errors and 4 warnings, all in NavigationDesigner.tsx, and the base version linted through stdin gives the same 4 warnings; (3) eslint.config.js has no parserOptions.project or projectService, and no rule under eslint-rules reads other files, so the diff cannot change any untouched file's verdict. NOT MEASURED: check:eager-locale-catalogues (PREREQUISITE NOT MET, needs apps/console/dist/eager-closure.json) and check:doc-examples (prerequisite not met, needs about 20 built packages); both are left to CI's build jobs. I hand-derived the gate list from package.json and the scripts that read the changed paths, because objectui has no dispatch-gates.mjs.",
    "mcp_calls": "0 — no MCP GitHub tool was called",
    "api_writes": "2 REST writes, both through the fleet-write relay (with-fleet.sh --via dispatch and post-stamped.mjs; each is one repository_dispatch to objectstack-ai/objectstack executed as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls with draft forced, which created #10315 (relay run 36034168332, success; the stored body read back byte-identical, 8824 bytes); (2) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/10287/comments. Plus 2 git pushes, which are not REST: the empty-branch probe and the fix commit 6f970da0. 0 label writes. 0 PR body PATCHes.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: none (a process observation, not a/b/c; not filed) · Reproducing Spec Main Shape Gate in a linked git worktree poisons the shared turbo cache. turbo 2.10 prints 'using shared worktree cache' and writes into the main checkout's .turbo/cache, which sibling worktrees read. Its hash does not cover node_modules, so build outputs compiled against the injected spec can be replayed elsewhere. The workflow's TURBO_FORCE bypasses cache reads but still writes. The remedy is to pass a private --cache-dir. This measurement is harmless: 6 entries were written and all 6 are byte-identical to pinned-spec builds. The gate script's scope is CI runners, so this is not a defect in the gate · carrier: 承接者:无 · recorded in the PR's Acceptance notes · dedupe words: turbo shared worktree cache, spec main shape gate local reproduction, injected spec turbo cache",
    "class: none (comment drift, not filed) · The doc comment on NavigationItemType in packages/types/src/app.ts describes NAV_TYPE_META as a Record keyed by exactly NavigationItemType. Until the pin bump it is keyed by NavigationItemType plus 'doc'; the point the comment makes (a new spec member breaks the compile loudly) still holds · carrier: the pin-bump PR that removes | 'doc' makes the comment exact again · recorded in Acceptance notes",
    "class: none (already routed by the triage) · The product gaps for doc all belong to objectui#10188, which builds on this PR: the NavigationRenderer and navSurface default fallthroughs, the AppNavCanvas KIND_TONE fallback, AppCreationWizard TYPE_BADGE_COLORS, the hand-written nine-member NavigationItemTypeSchema in packages/types, and quick-add or authoring of doc items · carrier: objectui#10188 · recorded in Acceptance notes"
    ]
    }


    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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions