From 9607d4b3079a88e6e296e784a714f59f6bd17615 Mon Sep 17 00:00:00 2001 From: mAi Date: Fri, 29 May 2026 15:17:24 +0200 Subject: [PATCH] =?UTF-8?q?docs+skeleton:=20Phase=206=20Slice=20B=20prep?= =?UTF-8?q?=20=E2=80=94=20read-path=20adapter=20interface=20contract?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per head's parallel-prep brief while m/mBrian#73 (migration script + [schema] node) is being built mBrian-side. NO mBrian-MCP-backed implementation yet — the migration worker may refine the landed node/edge shape and building the impl now risks rework. Built ONLY the parts stable regardless of mBrian internals: 1. CONSUMER INVENTORY (docs/plans/slice-b-adapter-contract.md §1) - Every *store.Store read method (15 methods) with signature + semantics - Every call site across web/, internal/aggregate/, mcp/ — table form - Item / ItemLink field-by-field shape contract: which fields come direct from node columns, which from edge-walk, which from metadata-unpack - Direct pgxpool access flagged out-of-scope (admin counts, bulk tx, links event-date update — slice C reworks those) - Views (5j) explicitly NOT in scope per m's Q5=(a) 2. INTERFACE CONTRACT (store/adapter.go) - ItemReader Go interface — 15 methods, pure projax-shaped structs in/out, zero mBrian type leakage - var _ ItemReader = (*Store)(nil) compile-time assertion proving the existing pgx-backed *Store satisfies the contract today 3. SKELETON (store/adapter.go MBrianReader) - Empty struct (mBrian client choice deferred to slice B impl) - All 15 methods stubbed, return errNotImplementedSliceB - var _ ItemReader = (*MBrianReader)(nil) keeps the stubs in lockstep with the interface as slice B grows - Each stub carries a one-line comment naming the §3 gap(s) it resolves at impl time - `go build ./...` green; `go vet ./store/` green 4. GAP FLAGS (docs/plans/slice-b-adapter-contract.md §3) - item_links.rel free-form annotation → mBrian edge.note (add to m/mBrian#73 §1 for the migration script) - ItemLink.RefID per-rel-type extraction rule (caldav URL vs gitea owner/repo vs mai project uuid) - paths[] recomputation cost (per-request memoisation) - AllTags aggregation (full-scan ok at m's scale; tag-graph deferred per m's Q8) - Roots / MaiOrphans "no outbound child_of edge" predicate - ItemsCreatedInRange scoped to projax_origin marker - Item.Source / SourceRefID constant + mai-edge-derived fields - ItemLinkWithItem join shape (two queries + in-memory join vs bulk MCP helper) - Admin counts — recommend adding Counts(ctx) to ItemReader for cohesion Stays parked after this. Slice B IMPL (mBrian-MCP client wiring + per- method bodies + handler rename from s.Store.X to s.Items.X) waits on the migration completing and uuid map landing. --- docs/plans/slice-b-adapter-contract.md | 228 +++++++++++++++++++++++++ store/adapter.go | 158 +++++++++++++++++ 2 files changed, 386 insertions(+) create mode 100644 docs/plans/slice-b-adapter-contract.md create mode 100644 store/adapter.go diff --git a/docs/plans/slice-b-adapter-contract.md b/docs/plans/slice-b-adapter-contract.md new file mode 100644 index 0000000..69936ae --- /dev/null +++ b/docs/plans/slice-b-adapter-contract.md @@ -0,0 +1,228 @@ +# Phase 6 Slice B — read-path adapter contract + +**Status**: prep work (this doc). No implementation. +**Branch**: `mai/kahn/phase-6-sliceB-prep`. +**Author**: kahn (coder, prep mode), 2026-05-29. +**Parent plan**: `docs/plans/mbrian-backend-migration.md` (on `main`). +**Scope boundary**: contract + compile-checking skeleton only. The mBrian-backed implementation waits on m/mBrian#73 landing the migration + handing over the uuid map. + +--- + +## §1 — Consumer inventory + +Every read-path call site against `*store.Store` and the projax-shaped `Item` / `ItemLink` types. The interface (§2) is the union of these. + +### §1.1 — `*store.Store` read methods (source: `store/store.go`) + +| method | signature | semantics | +|---|---|---| +| `ListAll` | `(ctx) ([]*Item, error)` | every live item, ordered by `paths NULLS FIRST, slug` | +| `GetByID` | `(ctx, id) (*Item, error)` | single item by uuid | +| `GetByPath` | `(ctx, path) (*Item, error)` | resolve `dev.paliad` style path to leaf item | +| `GetByPathOrSlug` | `(ctx, key) (*Item, error)` | path first, fall back to bare slug | +| `Roots` | `(ctx) ([]*Item, error)` | items with `cardinality(parent_ids) = 0` | +| `MaiOrphans` | `(ctx) ([]*Item, error)` | mai-managed root items needing classify | +| `ListByFilters` | `(ctx, SearchFilters) ([]*Item, error)` | structured search (status / mgmt / has-link / paths-prefix) | +| `Search` | `(ctx, q, limit) ([]*Item, error)` | trigram + FTS title/content/aliases | +| `AllTags` | `(ctx) ([]string, error)` | union of every item's tags | +| `LinksByType` | `(ctx, itemID, refType) ([]*ItemLink, error)` | one item's links of a given `ref_type` (empty = all) | +| `LinksByRefType` | `(ctx, refType) ([]*ItemLink, error)` | every link of a given ref_type across items | +| `DatedLinks` | `(ctx, itemID) ([]*ItemLink, error)` | one item's links anchored to a date (PER artifacts) | +| `DatedLinksRange` | `(ctx, from, to) ([]*ItemLinkWithItem, error)` | dated links within window, joined with their item | +| `RecentDocuments` | `(ctx, since, limit) ([]*ItemLinkWithItem, error)` | recent dated docs, joined with their item | +| `ItemsCreatedInRange` | `(ctx, from, to) ([]*Item, error)` | items created within window | + +### §1.2 — Consumer call sites (by file) + +Each row = one read-path call site. Direct Pool access (admin.go counts, bulk.go filter-tx, links.go event-date update) is flagged separately at the bottom — those rework targets are out of slice B's read-path scope. + +| consumer | method | use case | +|---|---|---| +| `web/server.go handleTree` | `ListAll`, `AllTags`, `linkKindsByItem` (LinksByRefType ×N) | render /views/tree with chip-counted forest | +| `web/server.go handleDetail` | `GetByPath` ×2 (PER fallback), `LinksByType` (caldav), `DatedLinks` | render /i/{path} detail page | +| `web/server.go parentOptions` | `ListAll` | populate parent