| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 1 | 18 | 6 | 4% |
| Commands | 6 | 19 | 0 | 24% |
| Section tags | 4 | 9 | 0 | 31% |
What each file covers
Sections
1 shared · 18 only in A · 6 only in B- − CLAUDE.md
- − Conventions
- − Project Shape
- − State Rules
- − Package Boundaries
- − Sharing Rules
- − Database and Migration Rules
- − Coding Rules
- − API Compatibility
- − Backend UUID Rules
- − Web/Desktop Features
- − Desktop Rules
- − Mobile Rules
- − UI Rules
- − Testing
- − Verification
- − Commits and Releases
- − Domain Reminders
- + Repository Guidelines
- + Quick Reference
- + Architecture
- + State Management (critical)
- + Package Boundaries (hard rules)
- + Database Migrations (hard rules)
- Commands
Commands
6 shared · 19 only in A · 0 only in B- − make start
- − make stop
- − make server
- − make daemon
- − make sqlc
- − pnpm install
- − pnpm dev:web
- − pnpm dev:desktop
- − pnpm build
- − pnpm lint
- − pnpm exec playwright test
- − pnpm ui:add badge
- − make worktree-env
- − make setup-worktree
- − make start-worktree
- − go vet
- − pnpm generate:reserved-slugs
- − pnpm ui:add <component>
- − pnpm ui:add @reui/<name>
- make dev
- make test
- pnpm typecheck
- pnpm test
- make check
- pnpm-workspace.yaml
Section tags
4 shared · 9 only in A · 0 only in B- − setup
- − lint-format
- − code-style
- − types
- − testing-strategy
- − git-pr
- − api
- − ui
- − agent-behaviour
- test
- security
- database
- do-not
Line diff
multica-ai/multica · CLAUDE.md
@@ −1 @@
1# CLAUDE.md
2
3Guidance for Claude Code when working in this repository. Keep this file short and authoritative: rules here should be hard to infer from code or easy to get wrong.
4
5## Conventions
6
7The source of truth for code naming, i18n glossary, and Chinese product voice is:
8
9- `apps/docs/content/docs/developers/conventions.mdx`
10- `apps/docs/content/docs/developers/conventions.zh.mdx`
11
12Read it before editing translations in `packages/views/locales/`, naming routes/packages/files/DB columns/types, or writing Chinese UI/docs copy. Do not rely on `packages/views/locales/glossary.md`; it is only a redirect stub.
13
14## Project Shape
15
16Multica is an AI-native task management platform for small teams, with agents as first-class assignees that can own issues, comment, and change status.
17
18- `server/`: Go backend, Chi router, sqlc, gorilla/websocket.
19- `apps/web/`: Next.js App Router.
20- `apps/desktop/`: Electron desktop app.
21- `apps/mobile/`: Expo / React Native iOS app. Read `apps/mobile/CLAUDE.md` before touching it.
22- `packages/core/`: headless business logic, API client, React Query hooks, Zustand stores.
23- `packages/ui/`: atomic UI components only.
24- `packages/views/`: shared business pages/components for web and desktop.
25- `packages/tsconfig/`: shared TypeScript config.
26
27Shared packages export raw `.ts` / `.tsx` and are compiled by consuming apps. Dependency direction is `views -> core + ui`; `core` and `ui` must stay independent.
28
29## State Rules
30
31Keep server state and client state separate.
32
33- TanStack Query owns server state: issues, users, workspaces, inbox, agents, members, and anything fetched from the API.
34- Zustand owns client/view state: filters, drafts, modals, tab layout, and navigation history. Current workspace identity is route-driven; platform stores/singletons may mirror slug/id only for headers, persistence namespaces, and reconnects.
35- Shared Zustand stores live in `packages/core/`, never in `packages/views/` or app directories.
36- React Context is for platform plumbing only, such as `WorkspaceIdProvider` and `NavigationProvider`.
37- Only auth/workspace stores may call `api.*` directly. Other server interaction belongs in queries/mutations.
38- Workspace-scoped query keys must include `wsId`.
39- Optimistic updates only when ALL hold: outcome locally predictable, user stays on the same screen (no navigation), failure is rare, rollback is trivial. Canonical: status/assignee/toggle field patches — patch determinate caches, roll back on failure, invalidate uncertain projections on settle.
40- Flows that navigate or confirm (create, delete, leave) must await the server before navigating or cleaning up; never optimistically remove an entity from cache.
41- Chat/message send uses the pending-message pattern: render immediately with a visible pending state and retry on failure, not silent optimism.
42- WebSocket events invalidate or patch Query cache for server data. They must never mirror server payload data into Zustand; clearing client-owned pointers (active session, selection, current workspace) is allowed only with a single responder and a self-initiated guard when this client can cause the event.
43- Persist durable preferences/drafts/layout. Do not persist server data or ephemeral UI state.
44- Zustand selectors must return stable references. Do not return freshly allocated objects/arrays from selectors without shallow comparison.
45- Hooks that need workspace context should accept `wsId`; do not call `useWorkspaceId()` internally unless the hook is guaranteed to run under the provider.
46
47## Package Boundaries
48
49These are hard constraints:
50
51- `packages/core/`: no `react-dom`, `localStorage` (use `StorageAdapter`), `process.env`, or UI libraries.
52- `packages/ui/`: no `@multica/core` imports and no business logic.
53- `packages/views/`: no `next/*`, no `react-router-dom`, no stores. Use `NavigationAdapter`, `useNavigation()`, and `<AppLink>`.
54- `apps/web/platform/`: only place for Next.js navigation/platform APIs.
55- `apps/desktop/src/renderer/src/platform/`: only place for `react-router-dom` navigation wiring.
56- Every workspace under `apps/` and `packages/` must declare directly imported external packages in its own `package.json`.
57- Shared dependencies use `catalog:` from `pnpm-workspace.yaml`; `apps/mobile/` pins Expo/React Native related versions directly.
58
59## Sharing Rules
60
61Web and desktop share business logic, hooks, stores, components, and views through `packages/core/`, `packages/ui/`, and `packages/views/`.
62
63If the same logic exists in both web and desktop, extract it unless it depends on platform APIs:
64
651. Next.js, Electron, or router APIs stay in the app/platform layer.
662. Headless logic belongs in `packages/core/`.
673. Shared UI or business views belong in `packages/views/`.
684. Shared primitives belong in `packages/ui/`.
69
70Mobile is independent. It may import types and pure functions from `@multica/core`, with `import type` for types, but owns its UI, state, hooks, providers, i18n, React version, build pipeline, and release cadence.
71
72## Commands
73
74Use the repo scripts as the source of truth. Common commands:
75
76```bash
77make dev # auto-setup and start the app
78make start # start backend + frontend
79make stop # stop app processes for this checkout
80make server # run Go server only
81make daemon # run local daemon
82make test # Go tests
83make sqlc # regenerate sqlc code after SQL changes
84pnpm install
85pnpm dev:web
86pnpm dev:desktop
87pnpm build
88pnpm typecheck
89pnpm lint
90pnpm test # TS/Vitest tests through Turborepo
91pnpm exec playwright test
92pnpm ui:add badge # shadcn/Base UI component into packages/ui
93```
94
95Worktrees share one PostgreSQL container and get isolated DB names/ports via `.env.worktree`. `make dev` auto-detects this. For manual setup use `make worktree-env`, `make setup-worktree`, and `make start-worktree`. `pnpm dev:desktop` additionally self-isolates per worktree (its own renderer port + app name) automatically, independent of `.env.worktree`.
96
97CI runs Node 22, Go 1.26.1, and a `pgvector/pgvector:pg17` PostgreSQL service.
98
99## Database and Migration Rules
100
101These are hard requirements for every new or modified database design and production migration:
102
103- Do not add database foreign keys (`FOREIGN KEY` / `REFERENCES`), cascading deletes, or cascading updates. Resolve relationships, validation, and dependent cleanup explicitly in application code. Use an application transaction when cleanup and the parent operation must commit or roll back atomically.
104- Every index created by a migration must use `CREATE INDEX CONCURRENTLY` or `CREATE UNIQUE INDEX CONCURRENTLY`, including indexes on newly created tables. PostgreSQL rejects concurrent index creation inside a transaction or a multi-command string, so keep each concurrent index build in its own single-statement migration file. The repository migration runner executes migration files outside an explicit transaction to support this.
105
106## Coding Rules
107
108- TypeScript strict mode is enabled; keep types explicit.
109- Go follows standard conventions: `gofmt`, `go vet`, checked errors.
110- Code comments must be English.
111- Prefer existing patterns/components over new parallel abstractions.
112- Avoid broad refactors unless required by the task.
113- For internal, non-boundary code, do not add compatibility layers, fallback paths, dual writes, legacy adapters, or temporary shims unless explicitly requested.
114- API boundaries are different: installed desktop clients can talk to newer backends, so response parsing must follow the API compatibility rules below.
115- If a flow or API is being replaced and the product is not live, prefer removing the old path instead of preserving both.
116- New global pre-workspace routes must be a single word (`/login`, `/inbox`) or `/{noun}/{verb}` (`/workspaces/new`). Do not add hyphenated root routes like `/new-workspace`.
117- Reserved slugs live in `server/internal/handler/reserved_slugs.json`. Edit it, run `pnpm generate:reserved-slugs`, and commit the generated `packages/core/paths/reserved-slugs.ts`.
118- When changing CLI commands/flags, API fields, or product behavior documented by built-in skills under `server/internal/service/builtin_skills/*`, update the relevant `SKILL.md` and `references/*-source-map.md` in the same PR.
119
120## API Compatibility
121
122Frontend code must survive backend response drift, especially in installed desktop builds.
123
124- Parse API JSON with `parseWithFallback` in `packages/core/api/schema.ts` and a zod schema. Do not cast network JSON to `T`.
125- Endpoint responses consumed by UI logic must pass through a schema before returning.
126- Downstream UI should optional-chain and default fields defensively.
127- Prefer explicit boolean checks (`=== true`) over truthy/falsy checks on server fields.
128- Do not pin critical affordances to one backend boolean; combine signals when possible.
129- Server-driven enum switches need a `default` branch.
130- When adding or changing an endpoint, add/update the schema and include a malformed-response test.
131
132## Backend UUID Rules
133
134In `server/internal/handler/`, always know where a UUID came from before using it in write queries.
135
136- Resource path params that may be UUIDs or human-readable IDs must be resolved through loaders such as `loadIssueForUser`, `loadSkillForUser`, `loadAgentForUser`, or `requireDaemonRuntimeAccess`; subsequent writes use the resolved `entity.ID`.
137- Pure UUID inputs from request boundaries use `parseUUIDOrBadRequest(w, s, fieldName)` and return immediately on `ok=false`.
138- Trusted UUID round-trips from sqlc results or test fixtures use `parseUUID(s)`, which panics on invalid input.
139- Outside handlers, `util.ParseUUID(s) (pgtype.UUID, error)` is the safe variant; always check the error.
140
141## Web/Desktop Features
142
143When adding a shared page or feature for web and desktop:
144
1451. Put the page/component in `packages/views/<domain>/`.
1462. Add platform wiring in both `apps/web/app/` and the desktop router, unless the desktop flow is a transition overlay.
1473. Use `useNavigation().push()` or `<AppLink>` in shared code.
1484. Use shared guards/providers such as `DashboardGuard` from `packages/views/layout/`.
1495. Keep platform-only UI in the app or inject it through props/slots.
1506. Hooks that need workspace context should accept `wsId`.
151
152CSS for web/desktop is shared from `packages/ui/styles/`. Use semantic tokens such as `bg-background` and `text-muted-foreground`; avoid hardcoded Tailwind colors and duplicated base styles.
153
154## Desktop Rules
155
156Desktop routing has three categories:
157
158- Session routes: workspace-scoped tab destinations such as `/:slug/issues`.
159- Transition flows: pre-workspace one-shot actions such as create workspace or accept invite. These are `WindowOverlay` state, not routes.
160- Error/stale states: stale workspace tabs should auto-heal by dropping stale tab groups, not render desktop error pages.
161
162More desktop constraints:
163
164- New pre-workspace desktop flows register a `WindowOverlay` type in `stores/window-overlay-store.ts`; do not add them to `routes.tsx`.
165- `setCurrentWorkspace(slug, uuid)` from `@multica/core/platform` mirrors the active route for headers, storage namespaces, and reconnects; workspace route layouts own setting it.
166- Code that leaves workspace context must call `setCurrentWorkspace(null, null)` explicitly.
167- Workspace delete must await the server before navigation/cleanup. Workspace leave currently clears/navigates before mutation only to avoid the `member:removed` realtime race; treat that as known debt, not a reusable pattern.
168- Cross-workspace navigation must go through the navigation adapter so it can call `switchWorkspace(slug, targetPath)`.
169- Full-window desktop views outside the dashboard shell must mount `<DragStrip />` from `@multica/views/platform` as the first flex child. Interactive controls in the top 48px need `WebkitAppRegion: "no-drag"`.
170
171## Mobile Rules
172
173Read `apps/mobile/CLAUDE.md` before touching `apps/mobile/`. It contains the mandatory pre-flight process, import limits, parity rules, tech stack, UI rules, data helpers, realtime strategy, and mobile release flow.
174
175Root-level reminders:
176
177- Mobile shares only `@multica/core` types and pure functions.
178- Mobile must match web/desktop product semantics: counts, permissions, enums/transitions, and data identity.
179- Mobile may differ in UI/interaction when the phone context requires it.
180
181## UI Rules
182
183- Prefer shadcn/Base UI components over custom implementations. Add them with `pnpm ui:add <component>` from the repo root.
184- The Pro `@reui` registry is configured in `packages/ui/components.json`; add items with `pnpm ui:add @reui/<name>` and answer `n` to every overwrite prompt so local component customizations survive. It reads `REUI_LICENSE_KEY` from the environment — agents get it from their Multica agent environment, humans export it in their own shell. Never write the key into a repo file.
185- ReUI ships source, not a dependency: route the vendored output to our layout (new primitives to `packages/ui/components/ui/`, compositions to `packages/views/<domain>/`) and rewrite it to our conventions before committing.
186- Use design tokens and semantic classes; avoid hardcoded colors.
187- Do not introduce extra local state unless the design requires it.
188- Handle overflow, long text, scrolling, alignment, and spacing deliberately.
189- If a component is identical between web and desktop, it belongs in a shared package.
190
191## Testing
192
193Tests follow the code:
194
195| What is tested | Location |
196| --- | --- |
197| Shared business logic, stores, queries, hooks | `packages/core/*.test.ts` |
198| Shared UI components, pages, forms, modals | `packages/views/*.test.tsx` |
199| Platform wiring such as cookies, redirects, search params | `apps/web/*.test.tsx` or `apps/desktop/` |
200| End-to-end flows | `e2e/*.spec.ts` |
201| Backend | `server/` Go tests |
202
203Rules:
204
205- Never test shared component behavior in an app test file.
206- `packages/views/` tests must not mock `next/*` or `react-router-dom`.
207- Mock `@multica/core` stores with the Zustand callable-store shape (`selectorFn` plus `getState`).
208- Mock `@multica/core/api` for API calls.
209- E2E tests should use `TestApiClient` for setup/teardown.
210- Prefer writing the failing test in the correct package before implementation when the change is behavioral.
211- Default tests must never resolve or execute user-installed agent CLIs. Pass a test-created fake executable path or a test-created missing path to agent subprocess code.
212- Real-agent smoke tests belong behind the `agentintegration` build tag and must check `MULTICA_RUN_REAL_AGENT_SMOKE=1` before executable lookup or account access.
213- Run an explicitly authorized real-agent smoke test with `(cd server && MULTICA_RUN_REAL_AGENT_SMOKE=1 go test -tags=agentintegration ./pkg/agent -run '<test-name>' -count=1 -v)`. This command may access an authenticated account and consume quota.
214- When adding a default agent command, add it to `scripts/agent-cli-command-names.txt`; the normal Linux/macOS test entry points fail on ambient agent CLI execution.
215
216## Verification
217
218For code changes, run the narrowest useful checks while iterating, then run broader verification when risk justifies it or when asked.
219
220Useful checks:
221
222```bash
223pnpm typecheck
224pnpm test
225make test
226pnpm exec playwright test
227make check
228```
229
230Do not claim verification passed unless you ran it. If you skip checks because the change is docs-only or the user asked not to run them, say so.
231
232## Commits and Releases
233
234- Commits should be atomic and use conventional prefixes: `feat(scope)`, `fix(scope)`, `refactor(scope)`, `docs`, `test(scope)`, `chore(scope)`.
235- A production deployment requires a CLI release tag on `main`: create `v0.x.x`, push it, and let `release.yml` publish binaries and the Homebrew tap.
236- Bump patch by default unless the user specifies a version.
237
238## Domain Reminders
239
240- All queries filter by `workspace_id`; membership gates access; `X-Workspace-ID` selects the workspace.
241- Issue assignees are polymorphic: `assignee_type` plus `assignee_id` can reference a member or an agent.
242
multica-ai/multica · AGENTS.md
@@ +1 @@
1# Repository Guidelines
2
3This file provides guidance to AI agents when working with code in this repository.
4
5> **Single source of truth:** This file is a concise pointer document.
6> All authoritative architecture, coding rules, and conventions
7> live in **CLAUDE.md** at the project root. Read that file first.
8> Use `Makefile`, `package.json`, and `pnpm-workspace.yaml` as the
9> source of truth for the full command list.
10
11## Quick Reference
12
13### Architecture
14
15Go backend + monorepo frontend (pnpm workspaces + Turborepo) with shared packages.
16
17- `server/` - Go backend (Chi router, sqlc, gorilla/websocket)
18- `apps/web/` - Next.js frontend (App Router)
19- `apps/desktop/` - Electron desktop app
20- `packages/core/` - Headless business logic (Zustand stores, React Query hooks, API client)
21- `packages/ui/` - Atomic UI components (shadcn/Base UI, zero business logic)
22- `packages/views/` - Shared business pages/components
23- `packages/tsconfig/` - Shared TypeScript config
24
25### State Management (critical)
26
27- **React Query** owns all server state (issues, members, agents, inbox, workspace list)
28- **Zustand** owns client/view state (view filters, drafts, modals, desktop tab state); current workspace identity is route-driven and only mirrored for platform plumbing
29- All Zustand stores live in `packages/core/` - never in `packages/views/` or app directories
30- WS events update React Query for server data; store writes are only for clearing client-owned pointers with a single responder/self-event guard
31
32### Package Boundaries (hard rules)
33
34- `packages/core/` - zero react-dom, zero localStorage, zero process.env
35- `packages/ui/` - zero `@multica/core` imports
36- `packages/views/` - zero `next/*`, zero `react-router-dom`, use `NavigationAdapter` for routing
37- `apps/web/platform/` - only place for Next.js APIs
38
39### Database Migrations (hard rules)
40
41- Never add database foreign keys or cascading actions. Enforce relationships and perform dependent cleanup explicitly in the application layer, using transactions when the operation must be atomic.
42- Every index created by a migration, including unique indexes and indexes on new tables, must use `CREATE [UNIQUE] INDEX CONCURRENTLY`. Keep each concurrent index build in its own single-statement migration file.
43
44### Commands
45
46```bash
47make dev # Auto-setup + start everything
48pnpm typecheck # TypeScript check
49pnpm test # TS unit tests (Vitest)
50make test # Go tests
51make check # Full verification pipeline
52```
53
54See CLAUDE.md for the authoritative rules and common commands.
55
@@ −1 +1 @@
1−# CLAUDE.md
1+# Repository Guidelines
22
3−Guidance for Claude Code when working in this repository. Keep this file short and authoritative: rules here should be hard to infer from code or easy to get wrong.
3+This file provides guidance to AI agents when working with code in this repository.
44
5−## Conventions
5+> **Single source of truth:** This file is a concise pointer document.
6+> All authoritative architecture, coding rules, and conventions
7+> live in **CLAUDE.md** at the project root. Read that file first.
8+> Use `Makefile`, `package.json`, and `pnpm-workspace.yaml` as the
9+> source of truth for the full command list.
610
7−The source of truth for code naming, i18n glossary, and Chinese product voice is:
11+## Quick Reference
812
9−- `apps/docs/content/docs/developers/conventions.mdx`
10−- `apps/docs/content/docs/developers/conventions.zh.mdx`
13+### Architecture
1114
12−Read it before editing translations in `packages/views/locales/`, naming routes/packages/files/DB columns/types, or writing Chinese UI/docs copy. Do not rely on `packages/views/locales/glossary.md`; it is only a redirect stub.
15+Go backend + monorepo frontend (pnpm workspaces + Turborepo) with shared packages.
1316
14−## Project Shape
17+- `server/` - Go backend (Chi router, sqlc, gorilla/websocket)
18+- `apps/web/` - Next.js frontend (App Router)
19+- `apps/desktop/` - Electron desktop app
20+- `packages/core/` - Headless business logic (Zustand stores, React Query hooks, API client)
21+- `packages/ui/` - Atomic UI components (shadcn/Base UI, zero business logic)
22+- `packages/views/` - Shared business pages/components
23+- `packages/tsconfig/` - Shared TypeScript config
1524
16−Multica is an AI-native task management platform for small teams, with agents as first-class assignees that can own issues, comment, and change status.
25+### State Management (critical)
1726
18−- `server/`: Go backend, Chi router, sqlc, gorilla/websocket.
19−- `apps/web/`: Next.js App Router.
20−- `apps/desktop/`: Electron desktop app.
21−- `apps/mobile/`: Expo / React Native iOS app. Read `apps/mobile/CLAUDE.md` before touching it.
22−- `packages/core/`: headless business logic, API client, React Query hooks, Zustand stores.
23−- `packages/ui/`: atomic UI components only.
24−- `packages/views/`: shared business pages/components for web and desktop.
25−- `packages/tsconfig/`: shared TypeScript config.
27+- **React Query** owns all server state (issues, members, agents, inbox, workspace list)
28+- **Zustand** owns client/view state (view filters, drafts, modals, desktop tab state); current workspace identity is route-driven and only mirrored for platform plumbing
29+- All Zustand stores live in `packages/core/` - never in `packages/views/` or app directories
30+- WS events update React Query for server data; store writes are only for clearing client-owned pointers with a single responder/self-event guard
2631
27−Shared packages export raw `.ts` / `.tsx` and are compiled by consuming apps. Dependency direction is `views -> core + ui`; `core` and `ui` must stay independent.
32+### Package Boundaries (hard rules)
2833
29−## State Rules
34+- `packages/core/` - zero react-dom, zero localStorage, zero process.env
35+- `packages/ui/` - zero `@multica/core` imports
36+- `packages/views/` - zero `next/*`, zero `react-router-dom`, use `NavigationAdapter` for routing
37+- `apps/web/platform/` - only place for Next.js APIs
3038
31−Keep server state and client state separate.
39+### Database Migrations (hard rules)
3240
33−- TanStack Query owns server state: issues, users, workspaces, inbox, agents, members, and anything fetched from the API.
34−- Zustand owns client/view state: filters, drafts, modals, tab layout, and navigation history. Current workspace identity is route-driven; platform stores/singletons may mirror slug/id only for headers, persistence namespaces, and reconnects.
35−- Shared Zustand stores live in `packages/core/`, never in `packages/views/` or app directories.
36−- React Context is for platform plumbing only, such as `WorkspaceIdProvider` and `NavigationProvider`.
37−- Only auth/workspace stores may call `api.*` directly. Other server interaction belongs in queries/mutations.
38−- Workspace-scoped query keys must include `wsId`.
39−- Optimistic updates only when ALL hold: outcome locally predictable, user stays on the same screen (no navigation), failure is rare, rollback is trivial. Canonical: status/assignee/toggle field patches — patch determinate caches, roll back on failure, invalidate uncertain projections on settle.
40−- Flows that navigate or confirm (create, delete, leave) must await the server before navigating or cleaning up; never optimistically remove an entity from cache.
41−- Chat/message send uses the pending-message pattern: render immediately with a visible pending state and retry on failure, not silent optimism.
42−- WebSocket events invalidate or patch Query cache for server data. They must never mirror server payload data into Zustand; clearing client-owned pointers (active session, selection, current workspace) is allowed only with a single responder and a self-initiated guard when this client can cause the event.
43−- Persist durable preferences/drafts/layout. Do not persist server data or ephemeral UI state.
44−- Zustand selectors must return stable references. Do not return freshly allocated objects/arrays from selectors without shallow comparison.
45−- Hooks that need workspace context should accept `wsId`; do not call `useWorkspaceId()` internally unless the hook is guaranteed to run under the provider.
41+- Never add database foreign keys or cascading actions. Enforce relationships and perform dependent cleanup explicitly in the application layer, using transactions when the operation must be atomic.
42+- Every index created by a migration, including unique indexes and indexes on new tables, must use `CREATE [UNIQUE] INDEX CONCURRENTLY`. Keep each concurrent index build in its own single-statement migration file.
4643
47−## Package Boundaries
44+### Commands
4845
49−These are hard constraints:
50−
51−- `packages/core/`: no `react-dom`, `localStorage` (use `StorageAdapter`), `process.env`, or UI libraries.
52−- `packages/ui/`: no `@multica/core` imports and no business logic.
53−- `packages/views/`: no `next/*`, no `react-router-dom`, no stores. Use `NavigationAdapter`, `useNavigation()`, and `<AppLink>`.
54−- `apps/web/platform/`: only place for Next.js navigation/platform APIs.
55−- `apps/desktop/src/renderer/src/platform/`: only place for `react-router-dom` navigation wiring.
56−- Every workspace under `apps/` and `packages/` must declare directly imported external packages in its own `package.json`.
57−- Shared dependencies use `catalog:` from `pnpm-workspace.yaml`; `apps/mobile/` pins Expo/React Native related versions directly.
58−
59−## Sharing Rules
60−
61−Web and desktop share business logic, hooks, stores, components, and views through `packages/core/`, `packages/ui/`, and `packages/views/`.
62−
63−If the same logic exists in both web and desktop, extract it unless it depends on platform APIs:
64−
65−1. Next.js, Electron, or router APIs stay in the app/platform layer.
66−2. Headless logic belongs in `packages/core/`.
67−3. Shared UI or business views belong in `packages/views/`.
68−4. Shared primitives belong in `packages/ui/`.
69−
70−Mobile is independent. It may import types and pure functions from `@multica/core`, with `import type` for types, but owns its UI, state, hooks, providers, i18n, React version, build pipeline, and release cadence.
71−
72−## Commands
73−
74−Use the repo scripts as the source of truth. Common commands:
75−
7646 ```bash
77−make dev # auto-setup and start the app
78−make start # start backend + frontend
79−make stop # stop app processes for this checkout
80−make server # run Go server only
81−make daemon # run local daemon
47+make dev # Auto-setup + start everything
48+pnpm typecheck # TypeScript check
49+pnpm test # TS unit tests (Vitest)
8250 make test # Go tests
83−make sqlc # regenerate sqlc code after SQL changes
84−pnpm install
85−pnpm dev:web
86−pnpm dev:desktop
87−pnpm build
88−pnpm typecheck
89−pnpm lint
90−pnpm test # TS/Vitest tests through Turborepo
91−pnpm exec playwright test
92−pnpm ui:add badge # shadcn/Base UI component into packages/ui
51+make check # Full verification pipeline
9352 ```
9453
95−Worktrees share one PostgreSQL container and get isolated DB names/ports via `.env.worktree`. `make dev` auto-detects this. For manual setup use `make worktree-env`, `make setup-worktree`, and `make start-worktree`. `pnpm dev:desktop` additionally self-isolates per worktree (its own renderer port + app name) automatically, independent of `.env.worktree`.
96−
97−CI runs Node 22, Go 1.26.1, and a `pgvector/pgvector:pg17` PostgreSQL service.
98−
99−## Database and Migration Rules
100−
101−These are hard requirements for every new or modified database design and production migration:
102−
103−- Do not add database foreign keys (`FOREIGN KEY` / `REFERENCES`), cascading deletes, or cascading updates. Resolve relationships, validation, and dependent cleanup explicitly in application code. Use an application transaction when cleanup and the parent operation must commit or roll back atomically.
104−- Every index created by a migration must use `CREATE INDEX CONCURRENTLY` or `CREATE UNIQUE INDEX CONCURRENTLY`, including indexes on newly created tables. PostgreSQL rejects concurrent index creation inside a transaction or a multi-command string, so keep each concurrent index build in its own single-statement migration file. The repository migration runner executes migration files outside an explicit transaction to support this.
105−
106−## Coding Rules
107−
108−- TypeScript strict mode is enabled; keep types explicit.
109−- Go follows standard conventions: `gofmt`, `go vet`, checked errors.
110−- Code comments must be English.
111−- Prefer existing patterns/components over new parallel abstractions.
112−- Avoid broad refactors unless required by the task.
113−- For internal, non-boundary code, do not add compatibility layers, fallback paths, dual writes, legacy adapters, or temporary shims unless explicitly requested.
114−- API boundaries are different: installed desktop clients can talk to newer backends, so response parsing must follow the API compatibility rules below.
115−- If a flow or API is being replaced and the product is not live, prefer removing the old path instead of preserving both.
116−- New global pre-workspace routes must be a single word (`/login`, `/inbox`) or `/{noun}/{verb}` (`/workspaces/new`). Do not add hyphenated root routes like `/new-workspace`.
117−- Reserved slugs live in `server/internal/handler/reserved_slugs.json`. Edit it, run `pnpm generate:reserved-slugs`, and commit the generated `packages/core/paths/reserved-slugs.ts`.
118−- When changing CLI commands/flags, API fields, or product behavior documented by built-in skills under `server/internal/service/builtin_skills/*`, update the relevant `SKILL.md` and `references/*-source-map.md` in the same PR.
119−
120−## API Compatibility
121−
122−Frontend code must survive backend response drift, especially in installed desktop builds.
123−
124−- Parse API JSON with `parseWithFallback` in `packages/core/api/schema.ts` and a zod schema. Do not cast network JSON to `T`.
125−- Endpoint responses consumed by UI logic must pass through a schema before returning.
126−- Downstream UI should optional-chain and default fields defensively.
127−- Prefer explicit boolean checks (`=== true`) over truthy/falsy checks on server fields.
128−- Do not pin critical affordances to one backend boolean; combine signals when possible.
129−- Server-driven enum switches need a `default` branch.
130−- When adding or changing an endpoint, add/update the schema and include a malformed-response test.
131−
132−## Backend UUID Rules
133−
134−In `server/internal/handler/`, always know where a UUID came from before using it in write queries.
135−
136−- Resource path params that may be UUIDs or human-readable IDs must be resolved through loaders such as `loadIssueForUser`, `loadSkillForUser`, `loadAgentForUser`, or `requireDaemonRuntimeAccess`; subsequent writes use the resolved `entity.ID`.
137−- Pure UUID inputs from request boundaries use `parseUUIDOrBadRequest(w, s, fieldName)` and return immediately on `ok=false`.
138−- Trusted UUID round-trips from sqlc results or test fixtures use `parseUUID(s)`, which panics on invalid input.
139−- Outside handlers, `util.ParseUUID(s) (pgtype.UUID, error)` is the safe variant; always check the error.
140−
141−## Web/Desktop Features
142−
143−When adding a shared page or feature for web and desktop:
144−
145−1. Put the page/component in `packages/views/<domain>/`.
146−2. Add platform wiring in both `apps/web/app/` and the desktop router, unless the desktop flow is a transition overlay.
147−3. Use `useNavigation().push()` or `<AppLink>` in shared code.
148−4. Use shared guards/providers such as `DashboardGuard` from `packages/views/layout/`.
149−5. Keep platform-only UI in the app or inject it through props/slots.
150−6. Hooks that need workspace context should accept `wsId`.
151−
152−CSS for web/desktop is shared from `packages/ui/styles/`. Use semantic tokens such as `bg-background` and `text-muted-foreground`; avoid hardcoded Tailwind colors and duplicated base styles.
153−
154−## Desktop Rules
155−
156−Desktop routing has three categories:
157−
158−- Session routes: workspace-scoped tab destinations such as `/:slug/issues`.
159−- Transition flows: pre-workspace one-shot actions such as create workspace or accept invite. These are `WindowOverlay` state, not routes.
160−- Error/stale states: stale workspace tabs should auto-heal by dropping stale tab groups, not render desktop error pages.
161−
162−More desktop constraints:
163−
164−- New pre-workspace desktop flows register a `WindowOverlay` type in `stores/window-overlay-store.ts`; do not add them to `routes.tsx`.
165−- `setCurrentWorkspace(slug, uuid)` from `@multica/core/platform` mirrors the active route for headers, storage namespaces, and reconnects; workspace route layouts own setting it.
166−- Code that leaves workspace context must call `setCurrentWorkspace(null, null)` explicitly.
167−- Workspace delete must await the server before navigation/cleanup. Workspace leave currently clears/navigates before mutation only to avoid the `member:removed` realtime race; treat that as known debt, not a reusable pattern.
168−- Cross-workspace navigation must go through the navigation adapter so it can call `switchWorkspace(slug, targetPath)`.
169−- Full-window desktop views outside the dashboard shell must mount `<DragStrip />` from `@multica/views/platform` as the first flex child. Interactive controls in the top 48px need `WebkitAppRegion: "no-drag"`.
170−
171−## Mobile Rules
172−
173−Read `apps/mobile/CLAUDE.md` before touching `apps/mobile/`. It contains the mandatory pre-flight process, import limits, parity rules, tech stack, UI rules, data helpers, realtime strategy, and mobile release flow.
174−
175−Root-level reminders:
176−
177−- Mobile shares only `@multica/core` types and pure functions.
178−- Mobile must match web/desktop product semantics: counts, permissions, enums/transitions, and data identity.
179−- Mobile may differ in UI/interaction when the phone context requires it.
180−
181−## UI Rules
182−
183−- Prefer shadcn/Base UI components over custom implementations. Add them with `pnpm ui:add <component>` from the repo root.
184−- The Pro `@reui` registry is configured in `packages/ui/components.json`; add items with `pnpm ui:add @reui/<name>` and answer `n` to every overwrite prompt so local component customizations survive. It reads `REUI_LICENSE_KEY` from the environment — agents get it from their Multica agent environment, humans export it in their own shell. Never write the key into a repo file.
185−- ReUI ships source, not a dependency: route the vendored output to our layout (new primitives to `packages/ui/components/ui/`, compositions to `packages/views/<domain>/`) and rewrite it to our conventions before committing.
186−- Use design tokens and semantic classes; avoid hardcoded colors.
187−- Do not introduce extra local state unless the design requires it.
188−- Handle overflow, long text, scrolling, alignment, and spacing deliberately.
189−- If a component is identical between web and desktop, it belongs in a shared package.
190−
191−## Testing
192−
193−Tests follow the code:
194−
195−| What is tested | Location |
196−| --- | --- |
197−| Shared business logic, stores, queries, hooks | `packages/core/*.test.ts` |
198−| Shared UI components, pages, forms, modals | `packages/views/*.test.tsx` |
199−| Platform wiring such as cookies, redirects, search params | `apps/web/*.test.tsx` or `apps/desktop/` |
200−| End-to-end flows | `e2e/*.spec.ts` |
201−| Backend | `server/` Go tests |
202−
203−Rules:
204−
205−- Never test shared component behavior in an app test file.
206−- `packages/views/` tests must not mock `next/*` or `react-router-dom`.
207−- Mock `@multica/core` stores with the Zustand callable-store shape (`selectorFn` plus `getState`).
208−- Mock `@multica/core/api` for API calls.
209−- E2E tests should use `TestApiClient` for setup/teardown.
210−- Prefer writing the failing test in the correct package before implementation when the change is behavioral.
211−- Default tests must never resolve or execute user-installed agent CLIs. Pass a test-created fake executable path or a test-created missing path to agent subprocess code.
212−- Real-agent smoke tests belong behind the `agentintegration` build tag and must check `MULTICA_RUN_REAL_AGENT_SMOKE=1` before executable lookup or account access.
213−- Run an explicitly authorized real-agent smoke test with `(cd server && MULTICA_RUN_REAL_AGENT_SMOKE=1 go test -tags=agentintegration ./pkg/agent -run '<test-name>' -count=1 -v)`. This command may access an authenticated account and consume quota.
214−- When adding a default agent command, add it to `scripts/agent-cli-command-names.txt`; the normal Linux/macOS test entry points fail on ambient agent CLI execution.
215−
216−## Verification
217−
218−For code changes, run the narrowest useful checks while iterating, then run broader verification when risk justifies it or when asked.
219−
220−Useful checks:
221−
222−```bash
223−pnpm typecheck
224−pnpm test
225−make test
226−pnpm exec playwright test
227−make check
228−```
229−
230−Do not claim verification passed unless you ran it. If you skip checks because the change is docs-only or the user asked not to run them, say so.
231−
232−## Commits and Releases
233−
234−- Commits should be atomic and use conventional prefixes: `feat(scope)`, `fix(scope)`, `refactor(scope)`, `docs`, `test(scope)`, `chore(scope)`.
235−- A production deployment requires a CLI release tag on `main`: create `v0.x.x`, push it, and let `release.yml` publish binaries and the Homebrew tap.
236−- Bump patch by default unless the user specifies a version.
237−
238−## Domain Reminders
239−
240−- All queries filter by `workspace_id`; membership gates access; `X-Workspace-ID` selects the workspace.
241−- Issue assignees are polymorphic: `assignee_type` plus `assignee_id` can reference a member or an agent.
54+See CLAUDE.md for the authoritative rules and common commands.
24255
