0049: read models out of db/ — lib/read-models/ + lint-enforced component boundary #127
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "glen/0049-read-models"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements approved doc 0049 — the last item from the maintainability review. Pure type relocation + one lint rule; zero runtime change.
What changed:
db/{attention,organize,search,sandbox-view}.tstolib/read-models/{attention,sidebar,search,sandbox}.ts— 24 declarations, no barrel. The read models import nothing fromdb/(their only imports areimport typefromlib/agent/tools/evidenceandlib/plan).app/layout.tsx,lib/, workflows, tests) are untouched; the diff is component-focused — 10 component files now import from@/lib/read-models/*, zero@/dbimports remain undercomponents/.eslint.config.mjsgains the boundary rule:no-restricted-importserror on@/db+@/db/*undercomponents/**— "components never import db" is now machine-checked instead of remembered. AGENTS.md's layering note updated.Verification: pi implemented; the fresh-eyes review verified all 24 moves byte-identical (the one delta is two inline
import("…")types lifted to top imports), db diffs pure-cut, no import cycles, the lint rule firing on all three import shapes with negative controls (lib/tests unaffected), and full gates: tsc clean, eslint exactly the 2 pre-existing warnings, 764 passed / 13 skipped.Review nits (both declined, documented): the rule can't see relative
../../dbimports (none exist, no such convention in the repo);Where's re-export from the db path widens what was a private type (doc-sanctioned — it needed exporting to move).After this merges, the original review's list is complete: clip consolidation, steps/tools split, chat-session decomposition, tool-views regroup, 0048 machines purge, and this.
Types only, zero runtime change; queries and their invariants stay in db/. The UI read-model shapes a page draws (InboxData, SidebarData, NeedsYouThread, SearchHit, SandboxState …) now live where the layering rule can point: db/attention.ts -> lib/read-models/attention.ts (RequestOption, PendingRequest, AttentionState, Where — previously the private embedded base, now exported — NeedsYouThread, NeedsYouPreview, UnreadThread, InboxData) db/organize.ts -> lib/read-models/sidebar.ts (SidebarItem, AttentionCounts, FolderNode, SidebarGroup, ShelvedItem, SidebarData, AttentionFlags) db/search.ts -> lib/read-models/search.ts (SearchHit, SearchOptions) db/sandbox-view.ts -> lib/read-models/sandbox.ts (SandboxRef, SandboxState, ConversationSandboxView, SandboxSummary, SandboxUser, SandboxDetail, SandboxLink) Approach (stated per plan): each db module imports back the types its signatures need and RE-EXPORTS the moved group, so every server-side importer (app routes, lib, tests) is untouched and the diff is component-focused. Components now import from @/lib/read-models/* — 10 files: inbox/{approval-card,plan-card,preview-failure-card, question-card,unread-card, inbox-view}, sidebar/{types,search-results, use-search}, harness-session-view. No barrel index.ts (deep imports keep file-to-file tracing honest). Inheritance across the split is intact: NeedsYouThread/UnreadThread extend Where (both moved together), ShelvedItem/SidebarTreeItem build on SidebarItem (same file / existing lib/sidebar-tree), SandboxDetail extends SandboxSummary (same file). lib/read-models/attention.ts references PlanCard via lib/plan (where it actually lives) and ApprovalEvidence via lib/agent/tools/evidence — no db dependency in the read models at all. Gates: tsc clean, eslint at the same 2 pre-existing warnings, vitest 764 passed / 13 skipped (baseline unchanged).