Repository navigation
command palette: navigation entries match on scattered letters, so "zzzz" returns Field Zoo and "ingest" returns Cascading Select #11812
Description
Activity
- addedbugSomething isn't workingSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seatarea:recordsBusiness objects, records, the views that show data, usable forms, searchBusiness objects, records, the views that show data, usable forms, search
on Oct 7, 2026 objectstack-fleet commented
on Oct 7, 2026 ContributorAuthorMore actionsPath: ② the capabilities an end user meets in the app — the command palette | 缺项 | P3
Triage: first grade,
bug·priority:p3·domain:ui·area:records·pm:queue. Direction: navigation entries match on word prefixes or contiguous substringsTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-07T17:36Z. ⛔ Not a claim, ⛔ not a dispatch.Triage: lands in
packages/app-shell/src/chrome/CommandPalette.tsx(the filter for the Objects and Pages groups) ⇒domain:ui; rationale: a Studio or console surface in objectui. Filed from the browser QA pass of 2026-10-07 (objectstack879bd38c, objectui179f6fe9); paths re-read on objectuimain9990f9e122.- Why p3: nonsense queries still return entries; record results are right.
- Direction:
- prefix or substring scoring, with a minimum score, for navigation entries
- record search is unchanged
- Not a defect:
?palette=1is the palette's designed deep link (CommandPalette.tsx:76, ADR-0054 C1/C3)
Clause-②: no. Patch changeset in objectui.
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsClaim: PM loop round 3
Session:session_01CGZy1BGCjdN5cXqL9cnvB8
Account:os-support-ai
Branch:claude/issue-11812-palette-nav-match
Worktree:objectui-issue-11812
Domain:domain:ui
Seat:domain:ui#3
File surface (on4e7dd56):packages/app-shell/src/chrome/CommandPalette.tsx: the matching of the navigation groups (Objects, Dashboards, Pages, Reports, Apps; theirCommandItemvalues at about:283–:360), and how the palette hands its filter tocmdk;- at most one new module-private matcher beside it;
- the tests beside them;
.changeset/11812-*.md.
⛔ Not on it:
packages/components/src/ui/**, includingui/command.tsx'sCommandDialog(objectui AGENTS.md #7: Shadcn-synced files, never edited); the record search and its server call; the?palette=1deep link (triage6043346622: by design). Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus(dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
Clause-②: no
Responsibility:objectui app-shell: the ⌘K palette's navigation groups go through cmdk's default subsequence scorer, so "zzzz" returns Field Zoo and a nonsense query never reaches "No results" | the platform path: the palette owns every navigation item's value and can match them itself (record hits already bypass the scorer by carrying the query in their value) | every console user who searches with ⌘K
Thread-read: 6043346622
Serial constraints cleared:noneblocking. No in-flight claim in the lane namesCommandPalette.tsx, and no open objectui PR touches it (read 2026-10-08T02:44Z). This seat's objectui#11839 (area:records, PR objectui#11867) holdspackages/components/src/renderers/action/, which is disjoint.Why
Clause-②: no: matching inside an app-shell chrome component. A published export, prop or type member (for example afilterpassthrough onCommandDialog), or a language-pack key, is a stop: the dev reports it before opening the PR, and the seat amends this line.
Generated by Claude Code
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11812, "status": "done", "branch": "claude/issue-11812-palette-nav-match", "pr": "https://github.com/objectstack-ai/objectui/pull/11883", "session": "session_01CGZy1BGCjdN5cXqL9cnvB8 (subagent run under the domain:ui seat 3 PM; the parent id)", "premise_still_valid": true, "summary": "The palette now matches its navigation entries (Objects, Dashboards, Pages, Reports, Switch App) and its theme and full-search commands itself, with a new module-private matcher matchesPaletteQuery in packages/app-shell/src/chrome/paletteMatch.ts (not re-exported): a word prefix of the label or machine name, or a contiguous substring of one of them from three characters on; hyphen and space read alike (cmdk's own normalisation); no typo tolerance; every Han/Hiragana/Katakana character starts a word, so a CJK substring matches anywhere. CommandPalette renders only the matches and a group only when something matched; no cmdk value changed, and since each rendered entry carries its terms in its value cmdk's scorer accepts every rendered entry, so CommandEmpty shows 'No results found.' exactly when nothing matched and the record search found nothing. Record hits untouched. Zone 2 item 1 CONFIRMED by measurement (cmdk 1.1.1 commandScore gives exactly the card's false hits a non-zero score: zzzz 9.9e-3 on Field Zoo and New Project (Wizard) via its repeated-letter skip; ingest 2.9e-3..2.3e-2 on the four entries; wayne 1.4e-4 on Styling (ADR-0065)). Item 2 CONFIRMED (CommandDialog spreads props onto the Radix Dialog; ui/ untouched); route taken = match in the palette and render only matches (neither forceMount nor query-in-value needed; forceMount rejected because a force-mounted zero-score item is not counted by cmdk's filtered.count); the Dialog+Command composition route measured (both exported) and not taken (copies CommandDialog's composition out of the Shadcn-synced file; a filter sees only a value string). Item 3: theme and full-search commands follow the rule over their existing values. Item 4: pinned with the showcase's real CJK label 'Command Center (大屏)'. Behaviour changes named in the PR body: initials (fz, sap) and the group type word (page, dashboard) no longer match. Real-browser reading (Chromium 141, temporary uncommitted probe page in the console's Vite server, the showcase's full 50-entry navigation, searchAll stub) before 5d69133 vs after a76ebb5: zzzz Field Zoo + New Project (Wizard) → 'No results found.'; ingest 4 scattered entries + the record → the record only; wayne Styling + the record → the record only; field and 大屏 unchanged.", "tests": "All at a76ebb5. New: paletteMatch.test.ts (13 cases) and CommandPalette.navMatch-11812.test.tsx (7 cases, real CommandPaletteProvider + cmdk + I18nProvider en + searchAll stub): 20 passed. Full package `pnpm exec vitest run packages/app-shell/ --maxWorkers=3` (lock, VERDICT command-exit 0): Test Files 1097 passed | 1 skipped (1098), Tests 10803 passed | 9 skipped. `pnpm --filter @object-ui/app-shell type-check` exit 0 (script echoed: tsc --noEmit && tsc -p tsconfig.test.json; --listFilesOnly of tsconfig.test.json lists all 4 touched files). `pnpm --filter @object-ui/app-shell build` exit 0 ('dist completeness: 1 package(s) complete'); dependency closure via turbo --filter '@object-ui/app-shell^...' 28/28 cached. Ablation via objectstack scripts/ablation-replace.mjs run from the worktree, HEAD holding the fix: anchor 'const matches = ... matchesPaletteQuery(inputValue, terms);' x1 → x0, replacement x0 → x1, blob 77b858975656 → 0168da5f2e1f; DOM suite 5 failed | 2 passed (the five pins red with the card's own readings, the two controls green; direction: red as expected); restore blob 77b858975656 == HEAD, git diff HEAD empty, marker grep -c 0. No dist between mutation and run (the suite imports ./CommandPalette from source). Existing palette suites 9868 and 10500 pass unchanged.", "mcp_calls": "0", "api_writes": "3 — all through scripts/pm fleet-write relay (each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): (1) pr_create POST /repos/objectstack-ai/objectui/pulls (draft forced; read-back 11039 bytes identical) → #11883; (2) label-write --assign os-support-ai: POST /repos/objectstack-ai/objectui/issues/11883/assignees (read-back matches); (3) this os-dev-report comment POST /repos/objectstack-ai/objectui/issues/11812/comments. Plus git push (not REST). Reads: gh api GETs only.", "open_questions": [], "out_of_scope_findings": [ "carrier: none · noted, not filed — the theme commands are matched by their English value words in every locale (a zh viewer typing 主题 finds none of them, because their translated labels were never in their cmdk values); pre-existing and unchanged by this PR; no declared contract says palette commands are searchable by translated label, so no filing class; recorded in the PR's Acceptance notes" ], "gates": [ { "command": "pnpm exec vitest run packages/app-shell/ --maxWorkers=3", "exit": 0, "verdict": "Test Files 1097 passed | 1 skipped (1098); Tests 10803 passed | 9 skipped (10812); os-verify-lock VERDICT command-exit 0" }, { "command": "pnpm exec vitest run packages/app-shell/src/chrome/paletteMatch.test.ts packages/app-shell/src/chrome/CommandPalette.navMatch-11812.test.tsx", "exit": 0, "verdict": "Test Files 2 passed (2); Tests 20 passed (20)" }, { "command": "pnpm --filter @object-ui/app-shell type-check", "exit": 0, "verdict": "tsc --noEmit && tsc -p tsconfig.test.json (no output); VERDICT command-exit 0" }, { "command": "pnpm --filter @object-ui/app-shell build", "exit": 0, "verdict": "dist completeness: 1 package(s) complete (1012 emitted files verified)" }, { "command": "pnpm exec eslint (4 touched files)", "exit": 0, "verdict": "0 errors, 13 warnings, all in CommandPalette.tsx and rule-for-rule identical to base 5d69133; narrowing evidence: config globs **/*.{ts,tsx} cover all 4, --format json lists 4 files none ignored, no type-aware linting in eslint.config.js" }, { "command": "pnpm check:control-bytes", "exit": 0, "verdict": "check-control-bytes: OK" }, { "command": "pnpm check:test-path-roots", "exit": 0, "verdict": "check-test-path-roots: OK" }, { "command": "pnpm check:changeset-claims", "exit": 0, "verdict": "No pending changeset names a file this change touches." }, { "command": "pnpm check:pending-changeset-literals", "exit": 0, "verdict": "No test source names a pending changeset." }, { "command": "pnpm check:new-line-citations", "exit": 0, "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s)" }, { "command": "pnpm check:i18n-keys", "exit": 0, "verdict": "Every in-scope call-site key resolves against the en pack" }, { "command": "pnpm check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape", "exit": 0, "verdict": "OK (each)" }, { "command": "pnpm check:unreferenced-sources / check:self-import / check:phantom-deps / check:esm-specifiers", "exit": 0, "verdict": "OK (each); esm-specifiers is the --specifiers-only leg" }, { "command": "node scripts/check-changeset-presence.mjs / check-changeset-no-major.mjs", "exit": 0, "verdict": "1 changeset declared for 1 released package; no major" }, { "command": "check:node-esm-load", "exit": null, "verdict": "NOT MEASURED: node-esm-load, reason: its load leg builds the tree; left to CI" }, { "command": "i18n pack gates, check:readme-exports", "exit": null, "verdict": "not applicable: no locale pack or package export changed" }, { "command": "PR checks at report time", "exit": null, "verdict": "in_progress: 20 check runs on a76ebb5 — 18 success, 1 skipped, 1 in progress (one read, not awaited)" } ], "deviations": [ "The PR was opened at head dc0a041: the second commit a76ebb5 (the DOM test reads strings under a real I18nProvider) had not been pushed; it was pushed about a minute after the PR opened. Every reading in the PR body is at a76ebb5, now the head.", "Real-browser reading: the showcase backend was not reachable (the sister objectstack checkout is not built in this container), so per Zone 3 the console was used with a stub: a temporary, uncommitted probe page in apps/console mounting the real palette over the showcase full navigation; before = the base CommandPalette.tsx (5d69133) copied beside it, also temporary. All probe files and the Vite server (own PID) were removed.", "The full app-shell package run held the shared verify lock for 24m53s on the 4-core box (the lock printed its holder-starvation warning). It is the brief's own gate list item for a touched package; noted so the PM can weigh narrowing that item.", "main moved to 04c8f56 during the run; none of its commits touches packages/app-shell/src/chrome/, ui/command.tsx, useRecordSearch or CommandPaletteProvider, git merge-tree is clean, so the branch was not merged.", "The harness's attribution reminder asked for a model-named Co-Authored-By trailer and a different PR footer; commits carry objectui AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude) and the PR body ends with the agent definition's session-URL footer." ], "files_changed": [ "packages/app-shell/src/chrome/CommandPalette.tsx", "packages/app-shell/src/chrome/paletteMatch.ts", "packages/app-shell/src/chrome/paletteMatch.test.ts", "packages/app-shell/src/chrome/CommandPalette.navMatch-11812.test.tsx", ".changeset/11812-palette-nav-match.md" ], "line_budget": "not applicable (no skills/** surface)" }objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsACCEPT —
domain:uiseat 3,session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-08T04:24Z. PR objectui#11883, heada76ebb5.-
PR shape: draft against
main, branched from5d69133, no rebase.git merge-treeof the currentmain(3035948) and this head is clean; the queue tests that merge. First lineFixes #11812, no other closing keyword.Clause-②: noat line start. Both commits carry only the model-free trailer pair. Assigned toos-support-ai. -
Scope: 5 files, +491/−42, on the claim's surface (
6051110257):chrome/CommandPalette.tsx;- one new module-private matcher,
chrome/paletteMatch.ts, whichindex.tsdoes not re-export; - two new pin files and the changeset (
patchon@object-ui/app-shell).
packages/components/src/ui/**is untouched (objectui AGENTS.md 构建一个 **Live Playground (实时演练场)** (用于展示引擎能力) #7), and so are the record search and the?palette=1deep link. Nothing is added to the package entry. No governed path. -
Diff read (the seat's own):
matchesPaletteQuery(query, terms)normalises the way cmdk does (lower case; whitespace and hyphens as a space). It accepts a word prefix of a term, or a contiguous substring from 3 characters on. Each Han, Hiragana or Katakana character starts a word. There is no typo tolerance. A blank query matches everything.CommandPalettefilters each navigation group by label and machine name, and the apps by label and name, then renders only the matches and a group only when something matched. The theme and full-search commands are matched over the values they already had.- No cmdk
valuechanged. Every rendered entry carries the query as a contiguous run of its value, so cmdk's own scorer accepts it, andCommandEmptyshows exactly when nothing matched and the record search found nothing. - The recent-records group renders only on an empty query, and the record hits are unchanged.
-
Brief readings, measured:
- Zone 2 Implement visual designer for Object UI schemas #1 is confirmed. cmdk 1.1.1's
commandScoregives the card's false hits a non-zero score:zzzzon "Field Zoo", through its repeated-letter skip. - Zone 2 Add automated testing infrastructure and CI/CD workflows #2 is confirmed:
CommandDialogspreads its props onto the RadixDialog. Of the two routes, the palette's own matching was taken.forceMountwas rejected, because cmdk does not count a force-mounted item, so "No results" would break. The composition route was measured and not taken. - Zone 2 Add default props to all components to prevent collapse in designer #4 is pinned with the showcase's real CJK label "Command Center (大屏)".
- Zone 2 Implement visual designer for Object UI schemas #1 is confirmed. cmdk 1.1.1's
-
Named behaviour changes (in the PR body; they follow triage's matching rule, "prefix or substring scoring … for navigation entries"):
- initials no longer match (
fzno longer finds "Field Zoo"); - the group's type word is not a matching term (
pagefinds entries whose label or name holds "page", not every page).
- initials no longer match (
-
Ruling honoured (triage
6043346622): "prefix or substring scoring, with a minimum score, for navigation entries" and "record search is unchanged".?palette=1is untouched. -
Changeset sentences checked against the head:
- "An entry matches when the query, ignoring case, starts a word of its label or machine name … or, from three characters on, appears anywhere in one of them";
- "each of their characters starts a word";
- "Record hits are unchanged";
- "Nothing is added to the package entry".
-
Reverse verification (dev report):
- Ablation through
ablation-replace.mjs: the matcher replaced by "always matches" gives the five pins red with the card's own readings, and the two controls green. Restored with the blob equal to HEAD. - The whole
@object-ui/app-shellsuite: 1097 files, 10803 tests passed. The existing palette suites pass unchanged. - Real browser (Chromium, the console with the showcase's full 50-entry navigation and a stubbed record search), before and after:
zzzznow shows "No results found.";ingestandwayneshow only the record;fieldand大屏are unchanged.
- Ablation through
-
Gates: CI on
a76ebb5(head_shaequals the PR head): 43 runs, 40 success, 3 skipped (Test (coverage), its shard template,dependabot), 0 failure.LintandType Checkare success. Mergeable stateclean. -
Contract review: not required (
Clause-②: no).
Findings:
- The theme commands are matched by their English value words in every locale, so a zh viewer typing 主题 finds none of them. This predates the change and no declared contract covers it →
Acceptance notes
Landing: ready + auto-merge through the queue, now.
Generated by Claude Code
-
objectstack-fleet commented
on Oct 8, 2026 ContributorAuthorMore actionsLanded —
domain:uiseat 3,session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-08T04:44Z. PR objectui#11883 merged through the queue as9cb4e29at 2026-10-08T04:43Z.- The merge:
- One parent,
4373484, an ancestor oforigin/main. - The landed tree equals
git merge-treeof that parent and the accepted heada76ebb5(tree1588caa2on both). - 5 files, +491/−42.
- One parent,
- Content check,
4373484→9cb4e29:matchesPaletteQueryinchrome/CommandPalette.tsx: 0 → 3.chrome/paletteMatch.tswent from absent to present, andpackages/app-shell/src/index.tsnames it 0 times, so the matcher stays module-private.- Control:
packages/components/src/ui/command.tsx(Shadcn-synced, objectui AGENTS.md 构建一个 **Live Playground (实时演练场)** (用于展示引擎能力) #7) is byte-identical on both sides.
- Closures: the PR's only closing keyword was
Fixes #11812, and this merge closed only objectui#11812 (04:43Z). The other issues closed since 04:02Z are other seats' merges.pm:dispatchedis removed. - Follow-ups: none filed. The theme commands are matched by their English value words in every locale; that is in the PR's Acceptance notes, predates the change, and no declared contract covers it.
Generated by Claude Code
- The merge:
- added a commit that references this issue
on Oct 9, 2026
Filing gate ① — product defect with a named location and a reproduction. reach: ⌘K command palette in the showcase app: query
zzzzreturns Field Zoo and New Project (Wizard);ingestreturns In-Progress Tasks, Cascading Select, Page Authoring, Styling (ADR-0065) besides the real hit;waynereturns Styling (ADR-0065) next to Wayne Enterprises.Who acts on it: objectui triage → the console / records owner. ⛔ Not a claim. Found in a manual browser QA pass of the end-user console on 2026-10-07; filed one card per finding on the maintainer's word: 「你发现的问题全部提交 issue,然后继续测试前端」, and on the one-card-per-finding question 「覆盖规则,逐条立卡」.
What happens
Record results are accurate (
华宁→ the account and three contacts;wayne→ Wayne Enterprises). The Objects and Pages groups, though, match letters scattered across the whole label, so nonsense queries never reach "No results" and real queries pull in unrelated entries. Opening the palette also appends?palette=1to the page URL.Expected
Navigation entries match on word prefixes or contiguous substrings (with a small typo tolerance at most); a query that matches nothing shows "No results".
Suggested direction (triage to rule)
Replace the subsequence matcher for nav entries with prefix/substring scoring and a minimum score; keep fuzzy matching for records server-side.
Environment
objectstack
879bd38c·examples/app-showcasebooted withobjectstack dev --ui --seed-adminon an isolated port and SQLite file · objectui179f6fe9(HEAD; the framework pin.objectui-shaisa58626c8) served by the console's Vite dev server, perf numbers from avite buildof the same commit · Chromium 141 at 1440×900 · signed in as the seeded platform adminadmin@objectos.aiunless stated.Duplicate check
Dedupe words: command palette fuzzy match nav entries · nonsense query results · subsequence matching search
Filed by Claude Code (session
session_01D76mrPJrSSdaKRxR2rvrMG) from that QA pass.Generated by Claude Code