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.

console header: the "Search ⌘K" trigger on /home (and the other frames outside an app) opens nothing — no command palette is mounted there #11912

Closed

Description

@objectstack-fleet

Filing gate ① — product defect with a named location and a reproduction. It is an out-of-scope finding, class a (user-visible wrong result), from the dev report on objectui#11863 (comment 6053561282).

Who acts on it:

  • objectui triage first-grades and routes it.
  • Then a domain:ui execution seat dispatches the fix in packages/app-shell/src/layout/AppHeader.tsx (the search trigger, about :684 / :702 on main 0855fc6) and/or the palette's mount point.

⛔ Not a claim.

Seam: renderer AppHeader search trigger → useCommandPalette() (packages/app-shell/src/context/CommandPaletteProvider.tsx) → no provider outside ConsoleLayout

What happens

On /home, the header shows a Search ⌘K trigger. Clicking it opens nothing, and Ctrl+K opens nothing either.

The trigger calls useCommandPalette().openCommandPalette. Outside a CommandPaletteProvider that hook returns a no-op (CommandPaletteProvider.tsx about :95–:112, documented as "the trigger is then inert"). Only ConsoleLayout mounts the provider, and only AppContent mounts the palette.

AppHeader's home variant is mounted by HomeLayout and AiChatPage. Its orgs variant is mounted by OrganizationsLayout and OrganizationLayout. So by source, the same inert trigger shows on /ai, /organizations and /organizations/SLUG.

Reach

  • Measured: in Chromium at 1440x900, with the console served from objectui 0855fc6 and the API mocked. On /home, a click left the URL at /home with 0 palette overlays, and Ctrl+K gave 0 overlays as well. Control: the same trigger at /apps/probe_app/probe_task opened the palette (?palette=1, 1 overlay). There were no page errors.
  • Read from source, not measured: /ai, /organizations and /organizations/SLUG.

Expected

A control the header shows does something. Either the trigger opens a search that works in that frame, or the header does not show it there.

The palette is scoped to an app today: its links start with /apps/APP, and with no active app its full-search command builds /apps/undefined/search. So "mount it everywhere" also needs a no-app mode. objectui#11863 (Studio landing) asks for search outside apps as well, and is back with triage as a Clause-②: yes question. Triage may route this card with it or before it.

Duplicate check

  • Semantic issue search on objectstack-ai/objectui (open and closed).
    • Query: home header search button command palette does nothing outside app ctrl k not mounted. 1 hit, not the same defect: objectui#3047 (closed), ⌘K scope truncated to 8 nav objects.
    • Second query: CommandPaletteProvider only mounted in ConsoleLayout search trigger home organizations inert. 0 hits.
  • Positive control: the first query reached a closed ⌘K card, objectui#3047, so the population is searchable.

Dedupe words: home header search button does nothing · command palette not mounted outside apps · ctrl k inert on home

Filed by domain:ui seat 2 (session_01MgfduSkFrfM3eorB3UGfAU) from the objectui#11863 dev report (out_of_scope_findings).


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    and removed on Oct 8, 2026
  2. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3
    Session: session_01CGZy1BGCjdN5cXqL9cnvB8
    Account: os-support-ai
    Branch: claude/issue-11912-inert-search-trigger
    Worktree: objectui-issue-11912
    Domain: domain:ui
    Seat: domain:ui#3
    File surface (line numbers on main 989b1908). The card's second route is the one in scope: the header does not show a search trigger in a frame where no palette is mounted. The first route, a palette that works with no active app, is objectui#11863's question (domain:spec, queued) and is not this card's.

    • packages/app-shell/src/layout/AppHeader.tsx: the search group (the desktop trigger action:command-palette:open and the mobile one action:command-palette:open-mobile, about :676–:707) renders only where a command palette is mounted.
    • packages/app-shell/src/context/CommandPaletteProvider.tsx: only an internal way for the header to tell whether a provider is mounted, if it needs one. It is not re-exported from the package entry. useCommandPalette()'s published return shape (CommandPaletteContextValue) and its no-op fallback stay as they are.
    • The tests beside these (packages/app-shell/src/layout/__tests__/AppHeader.*), and .changeset/11912-*.md.

    ⛔ Not on it:

    • a no-app palette mode, or mounting CommandPaletteProvider or the palette in more layouts (objectui#11863);
    • HomeLayout.tsx, AiChatPage.tsx, OrganizationsLayout.tsx, OrganizationLayout.tsx and ConsoleLayout.tsx;
    • the inside-app trigger's behaviour;
    • packages/i18n/** and packages/components/src/ui/**.

    Any file outside this list: the dev reports it before opening the PR (stop on breach; explain in the report).
    Container & model: S, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui over these paths: no path-derived mandate; default tier)
    Clause-②: no
    Responsibility: objectui app-shell header: the Search ⌘K trigger shows on /home, /ai and the organizations frames, where no palette is mounted, so a click or Ctrl+K does nothing | the platform path: useCommandPalette's documented no-op fallback outside CommandPaletteProvider, which only ConsoleLayout mounts | every console user on /home, /ai and /organizations
    Thread-read: none
    Serial constraints cleared: none blocking.

    • Open objectui PRs, read 2026-10-08T15:05Z (8 open): none touches AppHeader.tsx, CommandPaletteProvider.tsx or the five layouts.
    • In-flight claims, read 2026-10-08T15:05Z: none names them. objectui#11863, which asks for search outside apps, is queued in domain:spec, not claimed.

    Why Clause-②: no: no prop, export, type or language-pack key changes. AppHeader's props and useCommandPalette()'s return type stay as published, and the trigger simply does not render without a provider. Any change to the package entry's type graph is a stop: the dev reports it before opening the PR, and the seat amends this line.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 11912,
      "status": "done",
      "branch": "claude/issue-11912-inert-search-trigger",
      "pr": "https://github.com/objectstack-ai/objectui/pull/11987",
      "session": "session_01CGZy1BGCjdN5cXqL9cnvB8 (subagent mode: the parent's id, as the dispatch names it)",
      "premise_still_valid": true,
      "summary": "Premise held on origin/main 989b1908: AppHeader drew the Search trigger (desktop and compact) in every variant, but only ConsoleLayout mounts CommandPaletteProvider, so on /home and both organizations frames useCommandPalette() answered its no-op fallback and neither a click nor Ctrl+K opened anything (measured in Chromium on main, see tests). Took the claim's second route: CommandPaletteProvider.tsx gains a package-internal useCommandPaletteProviderMounted() (not re-exported from context/index.ts or the entry; useCommandPalette() return shape and fallback unchanged, only its docblock reworded), and AppHeader renders the whole search group only when it answers true, so no empty topbar group is left. Inside an app the trigger is unchanged. Draft PR objectui#11987 carries Fixes #11912, a line-start Clause-②: no, and a patch changeset on @object-ui/app-shell; all five changed files are on the claim's File surface.",
      "tests": "Head 3664e20c (last commit; nothing committed after). (1) New pin AppHeader.searchTriggerNeedsPalette-11912.test.tsx (real AppHeader + real CommandPaletteProvider + real MemoryRouter): home/orgs/app with no provider draw neither testid and no aria-keyshortcuts while the inbox bell proves the header drew; CONTROL app/home under the provider draw both, and each click flips useCommandPalette().open false to true with palette=1 in the URL. The 10899 pin's app-variant mount now sits under CommandPaletteProvider (it read the desktop trigger as its 'header rendered' check); no assertion changed. Both files: 'Test Files  2 passed (2) / Tests  8 passed (8)', exit 0. (2) Whole package: pnpm exec vitest run packages/app-shell/ --maxWorkers=2 under os-verify-lock: VERDICT command-exit 0, 'Test Files  1187 passed | 1 skipped (1188)', 'Tests  11476 passed | 9 skipped (11485)'. (3) Ablation via objectstack scripts/ablation-replace.mjs from committed HEAD, wrap mode under the lock: anchor 'return useContext(CommandPaletteContext) !== null;' replaced by 'return true; // ABLATION-11912', anchor x1 to x0, blob 3e03354a65fc to d9f466451f93; new file 'Tests  3 failed | 2 passed (5)' (the three no-provider cases red with 'expected document not to contain element, found BUTTON', both controls green); restore proven: blob after restore == HEAD blob 3e03354a65fc, git diff HEAD empty; independently re-checked marker count 0, anchor count 1. Direction observed: red, as predicted. Subject imported from src by relative path, so no dist rebuild between mutation and run. (4) Browser, Chromium 1440 and 800 wide, console served by vite from this branch and, as control, from a detached comparison worktree at 989b1908, both against a scratch objectstack dev backend (npm @objectstack/cli 17.7.0, one app probe_search_app), seeded admin. main: /home, /organizations?create=1 (OrganizationsLayout) and /organizations/default/members (OrganizationLayout) show the trigger; click leaves the URL unchanged with 0 overlay:command-palette, Ctrl+K 0. Branch: those three frames show no trigger testid and no aria-keyshortcuts, Ctrl+K 0, two data-topbar-group blocks with none empty and no left divider on the first (borderLeft 0px, marginLeft 0px), screenshot clean. In-app /apps/probe_search_app/psrch_task: on both trees both testids present, click and Ctrl+K open the palette (palette=1, 1 overlay). 0 page errors. /ai NOT MEASURED in the browser: this backend serves no AI and the route guard sends /ai to /home; AiChatPage mounts the same home variant with no provider, which the unit pin covers.",
      "mcp_calls": "0",
      "api_writes": "3 — all through the fleet 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 7424 bytes sent / 7424 stored identical; (2) label-write.mjs --assign os-support-ai = POST /repos/objectstack-ai/objectui/issues/11987/assignees, read-back MATCHES (assignee os-support-ai; labels tests and package: app-shell were applied by labeler.yml, not by me); (3) this os-dev-report comment = POST /repos/objectstack-ai/objectui/issues/11912/comments via post-stamped.mjs. Plus git push (not REST): the empty-branch probe and two commit pushes.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · noted in the PR's Acceptance notes, not filed · ConsoleLayout is a published export that mounts CommandPaletteProvider but not CommandPalette (AppContent mounts that), so a host using ConsoleLayout without CommandPalette would still get a trigger that sets palette=1 and opens nothing. Read-only inference, no named producer, zero pull.",
        "carrier: none (承接者:无) · noted in the PR's Acceptance notes, not filed · packages/app-shell/README.md ('Command palette' section) is off this card's surface and was not edited; no sentence in it became false (it names the trigger testids and does not say where the trigger renders)."
      ],
      "gates": [
        { "command": "pnpm exec vitest run packages/app-shell/ --maxWorkers=2 (os-verify-lock)", "exit": 0, "verdict": "Test Files  1187 passed | 1 skipped (1188); Tests  11476 passed | 9 skipped (11485); os-verify-lock VERDICT command-exit 0" },
        { "command": "pnpm exec vitest run (the two touched AppHeader test files) (os-verify-lock)", "exit": 0, "verdict": "Test Files  2 passed (2); Tests  8 passed (8)" },
        { "command": "pnpm --filter @object-ui/app-shell type-check (os-verify-lock; script name echoed: tsc --noEmit && tsc -p tsconfig.test.json)", "exit": 0, "verdict": "VERDICT command-exit 0; tsc --listFilesOnly on tsconfig.test.json lists both touched test files (2 hits). A first attempt before building the dependency closure exited 2 with TS2307 module-not-found only: a prerequisite miss, not a measurement" },
        { "command": "pnpm exec turbo run build --filter='@object-ui/app-shell^...' --concurrency=2 (os-verify-lock)", "exit": 0, "verdict": "Tasks: 28 successful, 28 total; Cached: 28 cached (BUILD_EXIT=0 recorded inside the command; the lock's own verdict line read the trailing echo)" },
        { "command": "pnpm --filter @object-ui/app-shell build (os-verify-lock)", "exit": 0, "verdict": "dist completeness: 1 package(s) complete (1028 emitted files verified); dist/index.d.ts re-exports useCommandPalette (control), has no export-star, and useCommandPaletteProviderMounted appears only in dist/context/CommandPaletteProvider.d.ts, reached by the entry only through named re-exports: entry type graph unchanged" },
        { "command": "pnpm exec eslint (4 touched source files) --format json", "exit": 0, "verdict": "files 4, errors 0, warnings 47 (no-explicit-any / no-unused-vars in test stubs copied from the sibling pin, plus one react-refresh/only-export-components on the new hook, the same warning useCommandPalette already carries); no gate ratchets warnings" },
        { "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), enforcement report-only -> exit 0" },
        { "command": "pnpm check:vi-mock-specifiers / check:vi-mock-inherit / check:vi-mock-override-shape", "exit": 0, "verdict": "OK / OK / OK" },
        { "command": "pnpm check:i18n-keys", "exit": 0, "verdict": "Every in-scope call-site key resolves against the en pack" },
        { "command": "pnpm check:unreferenced-sources", "exit": 0, "verdict": "OK  Every shipped source file in every covered package is reachable." },
        { "command": "node scripts/check-changeset-presence.mjs", "exit": 0, "verdict": "4 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s): .changeset/11912-inert-search-trigger.md" },
        { "command": "node scripts/check-changeset-no-major.mjs", "exit": 0, "verdict": "No changeset declares a major bump." },
        { "command": "pnpm check:readme-exports", "exit": 1, "verdict": "NOT MEASURED: prerequisite not met (unbuilt plugin-* type entries; 'run pnpm build first'); no export changed in this PR" },
        { "command": "Bundle Analysis / check:eager-closure", "exit": null, "verdict": "NOT MEASURED: CI-owned; the change adds no import and no first-load module. CI on head 3664e20c read once at report time: 42 check runs, 24 completed, 18 in_progress, 0 failed so far" }
      ],
      "deviations": [
        "Commit trailers use the model-free pair (Claude-Session + Co-authored-by: Claude) per objectui AGENTS.md and the role file, not the harness reminder's model-named Co-Authored-By line.",
        "Browser control used a second, detached worktree ../objectui-issue-11912-cmp at 989b1908 (the AGENTS.md comparison-tree form); it was served on its own port and removed afterwards.",
        "The probe backend is a scratch package in my issue-11912 scratch folder: package.json and lockfile copied (read only) from the issue-11823-s3 scratch probe, npm ci of @objectstack/cli 17.7.0, objectstack dev --fresh on port 4391; the backend, both vite servers (5191, 5192) and their children were stopped by recorded PID and its node_modules deleted.",
        "The whole-package vitest run (about 44 minutes on the shared box) was started with nohup under os-verify-lock and waited on with foreground tail --pid; its log was read after exit.",
        "The install log was first written at the scratchpad root by mistake and moved into issue-11912/ before anything else used it.",
        "/ai was not measured in the browser (backend serves no AI; route guard redirects to /home).",
        "After cleanup a fetch into a private ref to re-check the remote head failed silently; the remote head was confirmed instead with git ls-remote (3664e20c) and matches the PR's head sha read back from the API."
      ],
      "files_changed": [
        ".changeset/11912-inert-search-trigger.md (new)",
        "packages/app-shell/src/context/CommandPaletteProvider.tsx",
        "packages/app-shell/src/layout/AppHeader.tsx",
        "packages/app-shell/src/layout/__tests__/AppHeader.searchTriggerNeedsPalette-11912.test.tsx (new)",
        "packages/app-shell/src/layout/__tests__/AppHeader.designInStudioNeedsAuthoring-10899.test.tsx"
      ],
      "cleanup": "worktree ../objectui-issue-11912 removed (node_modules deleted first, tree clean, branch pushed at 3664e20c); comparison worktree removed; all servers I started stopped; no background process or monitor left running.",
      "line_budget": "not applicable (no skills/** surface)"
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-08T16:21Z. PR objectui#11987, head 3664e20c.

    • PR shape:

      • Draft against main. git merge-tree against main 4f4fc03f is clean.
      • First line Fixes #11912. Clause-②: no at line start.
      • Two commits, each carrying only the model-free trailer pair.
      • Assignee os-support-ai.
    • Scope: 5 files, +283/−37, all on the claim (6062817964):

      • layout/AppHeader.tsx (the search group);
      • context/CommandPaletteProvider.tsx (one package-internal hook, plus a docblock reworded);
      • one new pin, and the objectui#10899 pin's mount;
      • a patch changeset on @object-ui/app-shell.

      The five layouts, the palette, packages/i18n/** and packages/components/src/ui/** are untouched. No governed path.

    • Diff read (the seat's own):

      • useCommandPaletteProviderMounted() returns useContext(CommandPaletteContext) !== null.
      • AppHeader wraps the whole search data-topbar-group in it, so no empty group is left behind.
      • The trigger markup is unchanged inside an app.
      • The hook is not in context/index.ts, and the entry re-exports CommandPaletteProvider, useCommandPalette and the CommandPaletteContextValue type by name, so the entry type graph is unchanged. Clause-②: no holds.
    • The card's second route, as claimed: the trigger is not shown where no palette is mounted. A no-app palette stays objectui#11863's.

    • Pins:

      • No provider: the home, orgs and app variants draw neither trigger testid and no aria-keyshortcuts, while the inbox bell proves the header drew.
      • Control: under CommandPaletteProvider, both testids draw, and a click flips open with palette=1.
      • The objectui#10899 pin: its app-variant mount now sits under the provider, because it read the trigger as its "header rendered" check. No assertion changed. Accepted.
    • Reverse verification (dev report 6063987817): the hook forced to true turned the three no-provider cases red ("found BUTTON") and left both controls green. Restore proven (blob equals HEAD).

    • Browser (the dev's, Chromium, against a 17.7.0 backend):

      • On main, /home, /organizations and an organization's members page show the trigger, and a click or Ctrl+K opens nothing.
      • On the branch, those frames show no trigger, with clean header groups.
      • In an app, both trees open the palette.
      • /ai was not measured in the browser (no AI on that backend). The unit pin covers its home variant.
    • Tests: the whole packages/app-shell run passed (1,187 files and 11,476 tests). The app-shell type-check and build passed.

    • Gates: CI on 3664e20c: 43 runs: 40 success, 3 skipped (Test (coverage), its shard template, dependabot), 0 failure. Bundle Analysis is success: the budget bot reads 3311.5 KB against 3312.0 KB. Mergeable state clean.

    • Contract review: not required (Clause-②: no).

    Findings, recorded in the PR's Acceptance notes and not filed:

    • ConsoleLayout, a published export, mounts the provider but not the palette. A host using it without CommandPalette would still get a trigger that opens nothing. This is a read-only inference with no named producer.
    • The packages/app-shell/README.md command-palette section names the testids and stays true.

    Landing: ready + auto-merge through the queue, now.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-08T16:41Z. PR objectui#11987 merged through the queue as a920d8c at 2026-10-08T16:40Z.

    • The merge:
      • One parent, fff07fbb, an ancestor of origin/main.
      • The landed tree equals git merge-tree of that parent and the accepted head 3664e20c (tree 507ec517 on both).
      • 5 files, +283/−37.
    • Content check, fff07fbb → a920d8c, under packages/app-shell/src:
      • useCommandPaletteProviderMounted: 0 → 4.
      • hasCommandPalette: 0 → 3.
      • Control: packages/app-shell/src/layout/ConsoleLayout.tsx, the provider's mount, is byte-identical on both sides.
    • Closures: the PR's only closing keyword was Fixes #11912, and this merge closed objectui#11912 as completed at 16:40Z. pm:dispatched is removed in this pass.
    • Left with others: a search that works with no active app stays objectui#11863's question.

    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:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions