5.5 KiB
5.5 KiB
Tasks: enterprise-browser-react-command-palette
Change ID: enterprise-browser-react-command-palette
Package: @suaveplan/react-command-palette
Target path: browser/react/react-command-palette
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/schema-registry
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree per
proposal.md. package.jsonv0.0.0,"sideEffects": false.dependencies:@suaveplan/error workspace:^,@suaveplan/events workspace:^,@suaveplan/logger workspace:^,@suaveplan/schema-registry workspace:^,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:build,react catalog:reactpeerDependencies:react,react-domdevDependencies:vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,happy-dom catalog:testing,@testing-library/react catalog:testing,@suaveplan/testing workspace:^,@suaveplan/testing-dom workspace:^- Subpath exports:
".","./utils/fuzzy-search","./core/history/history","./core/command-palette/command-palette","./components/command-palette"
tsconfig.json,vitest.config.ts(pool: forks, happy-dom environment).
2. Error codes
HISTORY_STORAGE_FAILED,COMMAND_INVALID.registerCommandPaletteErrorCodes()— call eagerly.
3. Types (src/types/common.ts)
CommandItem,CommandPaletteConfig,CommandPaletteState,CommandPaletteActions,CommandPaletteInputProps,FuzzyMatch,HistoryConfig.- Write
common.md.
4. Fuzzy search (src/utils/fuzzy-search/)
fuzzy-search.ts—fuzzySearch(items, query)returning rankedFuzzyMatch[];fuzzyScore(item, query)with configurable weights (exact-match, prefix, subsequence).- Write
fuzzy-search.test.ts(exact match, prefix, subsequence, empty, special chars). Writefuzzy-search.md.
5. StorageAdapter interface (src/core/storage-adapter/)
storage-adapter.ts—StorageAdapterinterface:get(): CommandItem[],set(items: CommandItem[]): void,clear(): void.LocalStorageAdapterdefault implementation;MemoryAdapterfor tests.- Write
storage-adapter.test.ts. Writestorage-adapter.md.
6. CommandHistory (src/core/history/)
history.ts—CommandHistory(config): injectableStorageAdapter,maxSize,add(item),get(),clear().- Validate
CommandItemviaCommandItemSchemaonadd(); throwCOMMAND_INVALIDon failure. - Throw
HISTORY_STORAGE_FAILEDon storage adapter error. - Write
history.test.ts(add, evict over max, clear, storage failure). Writehistory.md.
7. useCommandPalette hook (src/core/command-palette/)
command-palette.ts— hook: open/close, input binding, keyboard navigation, result filtering, selection.CommandPaletteInputPropsincludesrole="combobox",aria-expanded,aria-activedescendant,aria-autocomplete.- Wire OTel counters + histogram
palette.filter_ms. - Split tests into files ≤ 500 lines by responsibility: open/close, filtering, navigation, history integration, config.
- Write
command-palette.md.
8. CommandItem schema (src/schema/command-item-schema/)
command-item-schema.ts— ZodCommandItemSchema;registerCommandItemSchema()in@suaveplan/schema-registry.- Write
command-item-schema.md.
9. Reference CommandPalette component (src/components/command-palette/)
command-palette.tsx— consumesuseCommandPalette; renders input + results list.placeholderfrom props; passes through to i18n resolver for default.- Axe-core clean:
role="dialog", focus trap,aria-livestep announcement. command-palette.stories.tsx— default story, playground, variant: grouped commands, async commands, history.command-palette.test.tsx— render, keyboard navigation, a11y. Writecommand-palette.md.
10. Integration test (tests/integration.test.ts)
- Full round-trip: render component, open, type query, navigate with arrows, execute, verify history.
- Storage adapter swap:
MemoryAdapterreplacesLocalStorageAdapterwithout code change.
11. Docs + verify
- Write
.mdper module (≥200 words, API reference, examples). - Write
README.mdwith subpath table, hook API, storage-adapter guide, a11y notes. bunx turbo lint typecheck test --filter=@suaveplan/react-command-palette— green.bunx turbo test:coverage— 100%.- No
@ts-expect-errorinsrc/or tests. Noreact-domin runtime deps. - Reference component passes axe-core.
bun scripts/publish.ts --package @suaveplan/react-command-palette.- Archive to
openspec/archive/2026-04-24-enterprise-browser-react-command-palette/.