docs: add ADR-0029, ADR-0030; update README index (guard — from commits 1c5e216, a59640)
This commit is contained in:
29
docs/adr/0029-domain-command-builder-pattern.md
Normal file
29
docs/adr/0029-domain-command-builder-pattern.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0029"
|
||||
title: "Domain command builder pattern for useCommandRegistry"
|
||||
status: active
|
||||
date: 2026-03-30
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
`useCommandRegistry` was a 224-line "brain method" (CodeScene hotspot) that defined all command palette commands inline: navigation, note actions, git operations, view toggles, settings, type management, and filter controls. This monolithic structure scored 39 on CodeScene's complexity scale (target: ≤9.5 for hotspots), making it increasingly hard to add new commands without touching the central file.
|
||||
|
||||
## Decision
|
||||
|
||||
**Split command definitions into focused domain modules under `src/hooks/commands/`, each exporting a `build*Commands(config)` factory function. `useCommandRegistry` becomes a thin assembler that calls each builder and merges the results.** Domain modules: `navigationCommands`, `noteCommands`, `gitCommands`, `viewCommands`, `settingsCommands`, `typeCommands`, `filterCommands`. Shared types live in `commands/types.ts`; public API re-exported from `commands/index.ts`.
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): Domain builder modules — each module owns its command shape and receives typed config. `useCommandRegistry` is pure assembly. All new files score 9.58–10.0. Downside: more files to navigate.
|
||||
- **Option B**: Split by file but keep one large hook calling sub-hooks — sub-hooks still need shared state passed down, similar coupling. No real complexity win.
|
||||
- **Option C**: Register commands imperatively via a global registry — decouples callers entirely. Downside: harder to trace, no TypeScript inference at the registration site, over-engineering for current scale.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Adding a new command means editing the relevant domain module (e.g. `noteCommands.ts`) only, not touching the assembler.
|
||||
- Each domain module receives only the config it needs — explicit, typed interface, no hook dependency.
|
||||
- `useCommandRegistry` reduced from 224 lines to a thin assembler.
|
||||
- Pattern is consistent with the Rust commands/ module split (ADR-0030).
|
||||
- Re-evaluation trigger: if command count grows to the point where the assembler itself becomes a complexity hotspot.
|
||||
29
docs/adr/0030-rust-commands-module-split.md
Normal file
29
docs/adr/0030-rust-commands-module-split.md
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
type: ADR
|
||||
id: "0030"
|
||||
title: "Rust commands/ module split by domain"
|
||||
status: active
|
||||
date: 2026-03-30
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
`src-tauri/src/commands.rs` grew to 937 lines as Tauri command handlers accumulated for vault CRUD, git/GitHub sync, AI, system, and window operations. All commands shared a single file with no domain separation, making it hard to navigate, review, and extend. The file was a CodeScene hotspot dragging down overall code health.
|
||||
|
||||
## Decision
|
||||
|
||||
**Replace `commands.rs` with a `commands/` module split by domain: `vault.rs`, `git.rs`, `github.rs`, `ai.rs`, `system.rs`, and `mod.rs` (shared utilities + re-exports).** Each file owns the Tauri command handlers for its domain and the `#[cfg(desktop)]` / `#[cfg(mobile)]` stubs for platform-conditional availability. `mod.rs` is kept thin (≤100 lines) with no command logic — only re-exports and shared helpers (`expand_tilde`, `parse_build_label`).
|
||||
|
||||
## Options considered
|
||||
|
||||
- **Option A** (chosen): Domain-based module split — mirrors the TypeScript `hooks/commands/` pattern (ADR-0029). Each file is independently reviewable and scores well on code health. Downside: more files to navigate.
|
||||
- **Option B**: Split by platform (`desktop.rs`, `mobile.rs`) — aligns with `#[cfg(...)]` guards but mixes domain concerns. Harder to find a specific command.
|
||||
- **Option C**: Keep monolith but add section comments — zero file-count cost, but doesn't solve complexity or reviewability.
|
||||
|
||||
## Consequences
|
||||
|
||||
- `github.rs` separates GitHub OAuth/API commands from git sync commands (`git.rs`), matching the underlying Rust module split (`github/` vs `git/`).
|
||||
- Platform stubs (`#[cfg(mobile)]` error returns) live alongside the desktop implementation in the same domain file.
|
||||
- `mod.rs` re-exports all command functions so `lib.rs` `invoke_handler!` registration is unchanged.
|
||||
- New Tauri commands go into the appropriate domain file; if no domain fits, create a new one rather than putting it in `mod.rs`.
|
||||
- Re-evaluation trigger: if a single domain file (e.g. `vault.rs`) itself grows beyond ~300 lines and becomes a hotspot.
|
||||
@@ -82,4 +82,7 @@ proposed → active → superseded
|
||||
| [0024](0024-cache-outside-vault.md) | Vault cache stored outside vault directory | active |
|
||||
| [0025](0025-type-field-canonical.md) | type: as canonical field (replacing Is A:) | active |
|
||||
| [0026](0026-props-down-no-global-state.md) | Props-down callbacks-up (no global state) | active |
|
||||
| [0027](0027-dual-ai-architecture.md) | Dual AI architecture (API chat + CLI agent) | active |
|
||||
| [0027](0027-dual-ai-architecture.md) | Dual AI architecture (API chat + CLI agent) | superseded |
|
||||
| [0028](0028-cli-agent-only-no-api-key.md) | CLI agent only — no direct Anthropic API key | active |
|
||||
| [0029](0029-domain-command-builder-pattern.md) | Domain command builder pattern for useCommandRegistry | active |
|
||||
| [0030](0030-rust-commands-module-split.md) | Rust commands/ module split by domain | active |
|
||||
|
||||
Reference in New Issue
Block a user