|
| 1 | +# Architecture Patterns — SoA/DTO Graph Traversal |
| 2 | + |
| 3 | +> **READ FIRST** before proposing new types, modules, plans, harvest |
| 4 | +> work, or "what's missing" analysis. This file teaches you to |
| 5 | +> navigate the lance-graph workspace without producing duplicate |
| 6 | +> work. The codebase is large and opinionated — most "interesting |
| 7 | +> ideas" are already implemented somewhere. Use these patterns to |
| 8 | +> find them before reinventing. |
| 9 | +> |
| 10 | +> Authored 2026-05-06 by a session that walked through ~10 rounds of |
| 11 | +> "is X new?" → "no, X exists at Y" before finally building the map. |
| 12 | +> The patterns here are the cost of that walk, captured so the next |
| 13 | +> session pays a tax of one read instead of ten rounds. |
| 14 | +> |
| 15 | +> Companion to: |
| 16 | +> - `.claude/knowledge/soa-dto-fma-map.md` — 8-region map (R0-R8) |
| 17 | +> - `.claude/board/ARCHITECTURE_ENTROPY_LEDGER.md` — per-component scoring |
| 18 | +> - `.claude/board/SINGLE_BINARY_TOPOLOGY.md` — three-layer invariants |
| 19 | +> - `Cargo.toml` workspace.members — canonical crate inventory |
| 20 | +
|
| 21 | +--- |
| 22 | + |
| 23 | +## TL;DR — Five traversal patterns |
| 24 | + |
| 25 | +| # | Pattern | Action | |
| 26 | +|---|---|---| |
| 27 | +| **P-1** | **CRATE-FIRST** | `cat Cargo.toml \| grep -E '^\s+"crates/'` BEFORE proposing | |
| 28 | +| **P-2** | **REGION-FIRST** | Name your concept's R-id from soa-dto-fma-map; if none fits, that's the review question | |
| 29 | +| **P-3** | **ENTROPY-FIRST** | Sort ledger Section A by Entropy DESC; pick highest-leverage cleanup | |
| 30 | +| **P-4** | **APPEND-ONLY** | Board files (PR_ARC, INTEGRATION_PLANS, EPIPHANIES, TECH_DEBT, ISSUES, ENTROPY_LEDGER, STATUS_BOARD) — never edit prior entries; only append dated sections | |
| 31 | +| **P-5** | **CLUSTER-AWARE** | When fixing a ledger row, check Section B Spaghetti Cluster — siblings need to move together | |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## The architecture as a graph |
| 36 | + |
| 37 | +The workspace is a directed graph where: |
| 38 | + |
| 39 | +- **Nodes** are (a) regions R0-R8 from the SoA-DTO map, (b) crates, (c) modules within crates. |
| 40 | +- **Edges** are (a) data flow (X feeds Y), (b) re-export (`pub use`), (c) trait impl (`impl X for Y`), (d) feature gate. |
| 41 | +- **Edge weights** are the entropy scores in the ledger — high-entropy edges are conflict zones (parallel duplicates, namespace clashes, stale stubs). |
| 42 | + |
| 43 | +The R0-R8 region partition is the **structural backbone**. Every concept in this codebase belongs to exactly one region. If you can't place a concept in a region, you're either looking at a workspace-level concern (board hygiene, governance) or genuinely-novel work that needs a new region. |
| 44 | + |
| 45 | +``` |
| 46 | + R8 Lab surface (Wire DTOs / serve / grpc) |
| 47 | + (cognitive-shader-driver/{wire,serve,grpc,…}.rs) |
| 48 | + │ decode once at REST edge |
| 49 | + ▼ |
| 50 | +R3 Cross-domain orchestration ←── R4 External boundary (BBB) ────┐ |
| 51 | +(contract::orchestration: (contract::external_membrane │ |
| 52 | + StepDomain, UnifiedStep, callcenter::lance_membrane) │ |
| 53 | + OrchestrationBridge) │ │ |
| 54 | + │ │ project() │ |
| 55 | + ▼ ▼ │ |
| 56 | +R0 BindSpace SoA ←──── R1 Per-cycle DTOs (Φ Ψ B Γ) ←──── R5 ──────┘ |
| 57 | +(driver::bindspace: (contract::cognitive_shader: Carrier algebra |
| 58 | + 8 columns, 71777B/row) ShaderDispatch/Resonance/ (Vsa16kF32 ℝ + |
| 59 | + │ Bus/Crystal) Binary16K GF(2)) |
| 60 | + │ │ │ |
| 61 | + │ ▼ ▼ |
| 62 | + │ R2 Write airgap R6 Domain catalogues |
| 63 | + │ (contract::collapse_gate: (contract::{grammar/ |
| 64 | + │ GateDecision, MergeMode) role_keys,thinking, |
| 65 | + │ │ persona,ontology,cam}) |
| 66 | + └─── written ←──────────┘ │ |
| 67 | + ▼ |
| 68 | + R7 Storage (Lance MVCC, audit, drift) |
| 69 | + (lance-graph::graph::versioned, audit, |
| 70 | + transcode::parallelbetrieb) |
| 71 | +``` |
| 72 | + |
| 73 | +**Tokio boundary** sits below R7's outbound edge, between Layer 2 and Layer 3 of the Single-Binary Topology. Tokio appears ONLY past `CycleAccumulator` flush. R0–R6 are sync; R7 has tokio inside Lance's internal runtime; R8 has tokio for HTTP/gRPC serving. |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## Crate inventory — canonical at 2026-05-06 |
| 78 | + |
| 79 | +The workspace has **~22 crates**. Listing them ALL because every "is this novel?" question collapses against this list. |
| 80 | + |
| 81 | +### Lance-graph workspace (~16 crates) |
| 82 | + |
| 83 | +| Crate | Region(s) | What it owns | |
| 84 | +|---|---|---| |
| 85 | +| **`lance-graph-contract`** | R1, R2, R3, R4, R5, R6 | Zero-dep type surface: `cognitive_shader`, `collapse_gate`, `cycle_accumulator`, `crystal`, `cam`, `external_membrane`, `grammar/*`, `nars`, `orchestration`, `persona`, `splat`, `thinking`, … 38+ modules | |
| 86 | +| **`lance-graph`** | R3, R6, R7 | Main query engine: `parser::parse_cypher_query` (1932 LOC), `graph::{spo,arigraph,versioned}`, `cam_pq/{ivf,jitson_kernel,storage,udf}`, `nsm/{encoder,parser,similarity,tokenizer,nsm_word}` | |
| 87 | +| **`lance-graph-planner`** | R3 | Pipeline DAG, executor, MUL gate, NARS algebra, thinking-style dispatch, orchestration_impl | |
| 88 | +| **`lance-graph-callcenter`** | R4, R7, R8 | `LanceMembrane`, `audit::{InMemoryAuditSink,LanceAuditSink}`, `policy::{ColumnMaskRewriter,RowEncryptionPolicy,DifferentialPrivacyPolicy,NotYetWiredHashUdf}`, `postgrest`, `rls`, `version_watcher` (sync, std-only post-WATCHER-1) | |
| 89 | +| **`lance-graph-rbac`** | R4, R6 | `Policy`, `Role`, `Operation`, `AccessDecision`, `PermissionSpec`, `smb_policy()` | |
| 90 | +| **`lance-graph-archetype`** | R3 | Archetype ECS bridge (per ADR 0001) | |
| 91 | +| **`lance-graph-catalog`** | R6, R7 | Catalog management | |
| 92 | +| **`lance-graph-cognitive`** | R6 | Grammar Triangle (`GrammarTriangle::from_text`), older 630K-LOC cognitive layer | |
| 93 | +| **`cognitive-shader-driver`** | R0, R1, R8 | `BindSpace`, `CognitiveShaderDriver` impl, Wire DTOs, `engine_bridge`, `cypher_bridge` (regex stub), `codec_research` | |
| 94 | +| **`deepnsm`** | R5, R6 | NSM crate: `codebook`, `context`, `disambiguator_glue`, `encoder`, `fingerprint16k`, `markov_bundle`, `nsm_primes`, `parser` (30 KB), `pipeline`, `pos`, `quantum_mode`, `similarity`, `spo`, `ticket_emit`, `trajectory`, `trajectory_audit`, `triangle_bridge`, `vocabulary` + 12 grammar-style YAMLs + 5 word-frequency CSVs | |
| 95 | +| **`holograph`** (workspace-EXCLUDED) | R5, R6 | Crystal stack: `sentence_crystal`, `crystal_dejavu`, `dntree`, `dn_sparse` (116 KB!), `navigator` (64 KB), `mindmap`, `epiphany`, `hamming`, `bitpack`, `hdr_cascade`, `nntree`, `neural_tree`, `representation`, `resonance`, `rl_ops`, `slot_encoding`, `storage`, `storage_transport`, `ffi`, `query/`, `width_10k/16k/32k/`, `graphblas/` | |
| 96 | +| **`bgz-tensor`** | R5 | BGZ17 codec implementation + HHTL_D doc + data + examples | |
| 97 | +| **`highheelbgz`** | R5 | High-Heel BGZ precision tier | |
| 98 | +| **`reader-lm`** | R6 | Reader-LM model: `classifier`, `inference`, `tokenizer`, `weights` | |
| 99 | +| **`jc/`** | (jc) | Justified Concentration prover: 7+ pillars (Cartan, Precond, EWA-sandwich, etc.) + examples (`prove_it`, `osint_edge_traversal`) | |
| 100 | +| **`thinking-engine`** | R6 (drift) | Older parallel ThinkingStyle (12-variant) — superseded by contract-36 but still wired | |
| 101 | +| **`neural-debug`** | (debug) | Neural debugging | |
| 102 | +| **`learning`** | R6 | Reinforcement-learning style selector (`StyleSelector` bandit) | |
| 103 | +| **`causal-edge`** | R6 | `CausalEdge64` Pearl 2³ masks, `PackedTruth`, inference type table | |
| 104 | + |
| 105 | +### Consumer-side crates (in separate repos, in MCP allowlist) |
| 106 | + |
| 107 | +| Repo / Crate | Layer | What it owns | |
| 108 | +|---|---|---| |
| 109 | +| `medcare-rs/crates/medcare-rbac` | L2 | Medcare policy (4 roles × 6 entities, BMV-Ä §57 invariants) | |
| 110 | +| `medcare-rs/crates/medcare-realtime` | L2 | `MedCareStack`, `MedCareMembraneGate` (POLICY-1 medcare-side closure) | |
| 111 | +| `medcare-rs/crates/medcare-{server,db,core,analytics,pdf}` | L2/L3 | medcare consumer surface | |
| 112 | +| `smb-office-rs/crates/smb-realtime` | L2 | `SmbStack`, `SmbMembraneGate` (POLICY-1 smb-side closure, PR #29) | |
| 113 | +| `smb-office-rs/crates/smb-{office-bin,db,core,analytics}` | L2 | smb consumer surface | |
| 114 | +| `q2/crates/cockpit-server` + `cockpit/` | L3 | Q2 Gotham-equivalent UI; SSE serving on canonical R1 surface (PR #35) | |
| 115 | + |
| 116 | +### Out-of-scope / external |
| 117 | + |
| 118 | +| Repo | Status | Purpose | |
| 119 | +|---|---|---| |
| 120 | +| `MedCareV2` | OUT-OF-MCP | C# .NET 4.8 desktop probe; calls `/api/__parity/csharp` | |
| 121 | +| `ladybug-rs` | EARLIER PROTOTYPE | Predecessor to lance-graph workspace; ALL grammar/crystal/NSM/CAM material already migrated | |
| 122 | +| `aiwar-neo4j-harvest` | DATA | Cypher/Neo4j OSINT harvest (q2 cockpit reads from this) | |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## Equivalence map: ladybug-rs ↔ lance-graph |
| 127 | + |
| 128 | +If a session is asked to harvest from ladybug-rs, the answer is **already done** unless explicitly proven otherwise. Discovered 2026-05-06 across ~10 rounds: |
| 129 | + |
| 130 | +| ladybug-rs/src/spo/ | Lance-graph equivalent | How to verify | |
| 131 | +|---|---|---| |
| 132 | +| `nsm_substrate` | `crates/deepnsm/{codebook,fingerprint16k,encoder}.rs` | `cargo doc -p deepnsm` | |
| 133 | +| `sentence_crystal` | `crates/holograph/src/sentence_crystal.rs` (27 KB) | grep workspace | |
| 134 | +| `context_crystal` | `lance-graph-contract::grammar::context_chain` + `deepnsm::context` | mod tree | |
| 135 | +| `spo` (the 5^5 crystal) | `lance-graph-contract::crystal::Structured5x5` + `holograph::representation` | contract crate src | |
| 136 | +| `spo_harvest` (238× cosine) | `bgz-tensor` + `highheelbgz` + `holograph::{hamming,bitpack,hdr_cascade}` + `ndarray::hpc::cascade` | grep `cosine` in ndarray | |
| 137 | +| `causal_trajectory` | `deepnsm::{trajectory,trajectory_audit,triangle_bridge}.rs` | deepnsm/src tree | |
| 138 | +| `gestalt`, `meta_resonance` | `deepnsm::ticket_emit` + `holograph::resonance` + `deepnsm::similarity` | grep | |
| 139 | +| `nsm_primes` | `deepnsm::nsm_primes` | exact match | |
| 140 | +| **`clam_path`** | **`crates/lance-graph/src/cam_pq/`** (5 files) | NOT obvious from name; `clam` ≅ `cam` | |
| 141 | +| `crystal_lm` | `crates/reader-lm/src/{classifier,inference,tokenizer,weights}.rs` | reader-lm crate | |
| 142 | +| `codebook_*` | `deepnsm::codebook` + `bgz-tensor` | grep | |
| 143 | +| `deepnsm_integration` | The deepnsm crate IS this | exists by name | |
| 144 | +| **DN-tree ↔ crystal binding** | **`holograph::{dntree,dn_sparse,navigator}.rs`** (~214 KB combined!) | holograph src | |
| 145 | + |
| 146 | +**Verdict:** ladybug-rs/src/spo is a SUBSET of what's in the lance-graph workspace. ladybug-rs is the earlier prototype; nothing remains to harvest. |
| 147 | + |
| 148 | +--- |
| 149 | + |
| 150 | +## Anti-patterns observed in this session |
| 151 | + |
| 152 | +### 1. The Discovery Loop |
| 153 | + |
| 154 | +Pattern: session proposes work → user says "X already exists at Y" → session proposes different work → user says "Y also exists" → repeat. |
| 155 | + |
| 156 | +**Cost:** ~10 rounds in this session. Each round consumed both user attention and session context budget. |
| 157 | + |
| 158 | +**Cause:** session didn't run CRATE-FIRST + REGION-FIRST traversal before proposing. |
| 159 | + |
| 160 | +**Cure:** before ANY proposal involving "implement X" or "harvest X from external repo", traverse: |
| 161 | +1. `Cargo.toml` workspace.members |
| 162 | +2. `soa-dto-fma-map.md` regions |
| 163 | +3. `ARCHITECTURE_ENTROPY_LEDGER.md` rows |
| 164 | +4. `LATEST_STATE.md` Contract Inventory |
| 165 | +5. MCP `search_code` for likely names |
| 166 | + |
| 167 | +### 2. Harvest-from-Stale |
| 168 | + |
| 169 | +Pattern: session treats an external repo (ladybug-rs) as canonical truth and proposes harvest plans against material that already migrated. |
| 170 | + |
| 171 | +**Cause:** session didn't realize the workspace had absorbed the prototype crate's content. |
| 172 | + |
| 173 | +**Cure:** for any external-repo harvest, the FIRST move is comparing the external repo's module list against the workspace crate inventory above. |
| 174 | + |
| 175 | +### 3. Map-Blindness |
| 176 | + |
| 177 | +Pattern: session knows about `lance-graph-contract` and `lance-graph` but misses crates like `holograph`, `bgz-tensor`, `highheelbgz`, `reader-lm`, `lance-graph/src/cam_pq` because they don't surface in obvious search paths. |
| 178 | + |
| 179 | +**Cause:** the workspace has ~22 crates but session focused on the 4-5 obvious ones. |
| 180 | + |
| 181 | +**Cure:** ALWAYS read the full `Cargo.toml` workspace.members list at session start. The crates here are the universe. |
| 182 | + |
| 183 | +### 4. Single-Name Lookup |
| 184 | + |
| 185 | +Pattern: session searches for `clam_path` and finds nothing, declares "novel". User says "clam_path ≅ cam_pq". |
| 186 | + |
| 187 | +**Cause:** session didn't try alternate spellings / domain-equivalent names. |
| 188 | + |
| 189 | +**Cure:** when searching for a concept by name, ALSO search for plausible aliases: |
| 190 | +- `clam_path` → `cam_pq` (same acronym, different layout) |
| 191 | +- `nsm_substrate` → `deepnsm::codebook` |
| 192 | +- `sentence_crystal` → `holograph::sentence_crystal` |
| 193 | +- `context_crystal` → `grammar/context_chain` |
| 194 | +- `spo_harvest` → `bgz-tensor` / `cascade` |
| 195 | +- `gestalt` → `ticket_emit` / `resonance` |
| 196 | + |
| 197 | +The pattern: **acronym match > exact-name match > domain-keyword match**. |
| 198 | + |
| 199 | +### 5. Plan-Doc-Without-Code-Check |
| 200 | + |
| 201 | +Pattern: session writes a plan PR proposing "wire X to Y" without first verifying that X and Y aren't already wired. |
| 202 | + |
| 203 | +**Cause:** plan-writing is cheaper than code-reading; session shortcuts. |
| 204 | + |
| 205 | +**Cure:** before writing a plan with deliverable D-ids, READ the actual files involved. The plan should cite `file:line` for every "currently broken" claim. |
| 206 | + |
| 207 | +--- |
| 208 | + |
| 209 | +## Pre-work checklist |
| 210 | + |
| 211 | +Run these BEFORE proposing any new type, module, plan, harvest, or wiring: |
| 212 | + |
| 213 | +``` |
| 214 | +[ ] Read Cargo.toml workspace.members (canonical crate inventory) |
| 215 | +[ ] Find concept's region (R0-R8) in soa-dto-fma-map.md; if none fits → review question |
| 216 | +[ ] Search the entropy ledger for an existing row touching this concept |
| 217 | +[ ] grep workspace for the concept name AND plausible aliases |
| 218 | +[ ] Check LATEST_STATE.md Recently Shipped (last 7 days of PRs) |
| 219 | +[ ] If proposing harvest from external repo: list workspace crates by domain |
| 220 | + (NSM=deepnsm+lance-graph/src/nsm; Crystal=holograph+contract; …) |
| 221 | +[ ] Cite file:line in any "currently broken" claim |
| 222 | +[ ] Check whether the concept's row in the ledger is part of a Section B cluster |
| 223 | + — if so, name the cluster + the suggested-order in the proposal |
| 224 | +``` |
| 225 | + |
| 226 | +If any checklist box reveals existing work, DO NOT propose new work. Either: |
| 227 | +- Update the existing row's status (state change) per ledger Update Protocol |
| 228 | +- Cite the existing as the canonical and propose ONLY the missing edge |
| 229 | +- Stop and ask the user |
| 230 | + |
| 231 | +--- |
| 232 | + |
| 233 | +## Wiring recipes (concrete examples) |
| 234 | + |
| 235 | +These are existing seams from the entropy ledger. Each is wireable using ONLY existing primitives — no new types, no duplicates. Future sessions can pick one and execute. |
| 236 | + |
| 237 | +### Recipe A — CAM-DIST-1: register `cam_distance` UDF globally |
| 238 | + |
| 239 | +**State:** UDF registered at `cam_pq/udf.rs:241,257,326`. Called from `query.rs:470` ONLY when `with_cam_codebook(...)` is opted in. `datafusion_planner/mod.rs::new()` does NOT register, so default Cypher path can't reference `cam_distance`. |
| 240 | + |
| 241 | +**Wire:** add the UDF registration in `DataFusionPlanner::new` so it's always available. Pure additive change. Closes CAM-DIST-1 (entropy 3 → 2). |
| 242 | + |
| 243 | +```rust |
| 244 | +// In datafusion_planner/mod.rs::DataFusionPlanner::new |
| 245 | +let mut state = SessionState::new_with_config_rt(config, runtime); |
| 246 | +state = lance_graph::cam_pq::udf::register_cam_distance(state); // NEW LINE |
| 247 | +``` |
| 248 | + |
| 249 | +**No duplication:** uses existing `register_cam_distance` from `cam_pq/udf.rs`. |
| 250 | + |
| 251 | +### Recipe B — PARSER-1: wire `cypher_parse::plan` to real parser |
| 252 | + |
| 253 | +**State:** Real parser at `lance-graph::parser::parse_cypher_query` (1932 LOC nom). Stub at `planner::strategy::cypher_parse.rs` (72 LOC substring matching). cypher_bridge.rs uses regex. |
| 254 | + |
| 255 | +**Wire:** replace `CypherParse::plan` body with a call to the real parser, return its AST, route via existing visitor. Closes PARSER-1 (entropy 5 → 3 once first stub is wired). |
| 256 | + |
| 257 | +```rust |
| 258 | +// planner::strategy::cypher_parse::CypherParse::plan |
| 259 | +fn plan(&self, query: &str) -> PlanResult { |
| 260 | + let ast = lance_graph::parser::parse_cypher_query(query)?; // EXISTING fn |
| 261 | + self.from_ast(&ast) |
| 262 | +} |
| 263 | +``` |
| 264 | + |
| 265 | +**No duplication:** uses existing `parse_cypher_query`. The 35 `format!("{:?}", logical_plan)` Debug-stringify sites become eliminable in a second-pass cleanup once the typed AST flows. |
| 266 | + |
| 267 | +### Recipe C — DEEPNSM-NSM-1: collapse `lance-graph/src/nsm/` |
| 268 | + |
| 269 | +**State:** `lance-graph/src/nsm/{encoder,parser,similarity,tokenizer,nsm_word}.rs` (≈2,405 LOC) parallels `crates/deepnsm/`. CLAUDE.md Phase-3 task "Consolidate nsm/ module" never ran. |
| 270 | + |
| 271 | +**Wire:** delete `lance-graph/src/nsm/`; replace with thin re-export shim: |
| 272 | + |
| 273 | +```rust |
| 274 | +// lance-graph/src/nsm/mod.rs (new shim) |
| 275 | +pub use deepnsm::encoder; |
| 276 | +pub use deepnsm::parser; |
| 277 | +pub use deepnsm::similarity; |
| 278 | +pub use deepnsm::vocabulary as tokenizer; |
| 279 | +``` |
| 280 | + |
| 281 | +**No duplication:** keeps the deepnsm canonical; gives `lance-graph::nsm::*` callers the same path. |
| 282 | + |
| 283 | +### Recipe D — VSA-1: methods on Vsa16kF32 (the FMA) |
| 284 | + |
| 285 | +**State:** 8 free functions (`vsa16k_bind`, `vsa16k_bundle`, etc.) on a type alias. Click P-1 violation: free function = reject, method = accept. |
| 286 | + |
| 287 | +**Wire:** newtype `Vsa16kF32` + `impl { fn bind, fn bundle, fn cosine, fn permute }`. Existing free fns become trivial method delegators OR get deleted with their bodies absorbed into the methods. |
| 288 | + |
| 289 | +**No duplication:** the algebra is the same; only the call shape changes. |
| 290 | + |
| 291 | +### Recipe E — MEMBRANE-GATE-1: removed (already done) |
| 292 | + |
| 293 | +State changed to **Wired** by: |
| 294 | +- SMB side: PR #29 (`SmbMembraneGate` over `Arc<lance_graph_rbac::Policy>`) |
| 295 | +- Medcare side: PR #98 (`MedCareMembraneGate` over `Arc<medcare_rbac::Policy>`) |
| 296 | + |
| 297 | +Ledger row needs the state-change append. |
| 298 | + |
| 299 | +### Recipe F — WATCHER-1: removed (already done) |
| 300 | + |
| 301 | +State changed to **Wired (sync, std-only)** by PR #337 — `LanceVersionWatcher` rewritten to `std::sync::{Arc,RwLock,Mutex,Condvar}` per topology I-2. Ledger row needs the state-change append. |
| 302 | + |
| 303 | +--- |
| 304 | + |
| 305 | +## Ledger update protocol (canonical, restated for visibility) |
| 306 | + |
| 307 | +When a row's state changes: |
| 308 | +1. Append a new dated entry below the current snapshot. Reference the row ID. |
| 309 | +2. Do NOT edit the original snapshot table — append-only. |
| 310 | +3. New section: `## YYYY-MM-DD — <ID> resolution / state change` with old-state, new-state, evidence (PR#, file:line). |
| 311 | + |
| 312 | +When a NEW SoA / DTO / bridge enters: |
| 313 | +1. Append `## YYYY-MM-DD — <ID> introduction`. |
| 314 | +2. Score Region / DupCount / DupPotential / LooseEnds / Plan / PlanStatus / Entropy. |
| 315 | +3. If part of an existing cluster, cite the cluster ID. |
| 316 | + |
| 317 | +--- |
| 318 | + |
| 319 | +## Cross-references |
| 320 | + |
| 321 | +- `.claude/knowledge/soa-dto-fma-map.md` — the 8-region structural map |
| 322 | +- `.claude/board/ARCHITECTURE_ENTROPY_LEDGER.md` — per-component scoring + clusters |
| 323 | +- `.claude/board/SINGLE_BINARY_TOPOLOGY.md` — three-layer invariants (I-1/I-2/I-3/I-4) |
| 324 | +- `.claude/board/INTEGRATION_PLANS.md` — versioned plan index |
| 325 | +- `.claude/board/STATUS_BOARD.md` — deliverable-level status |
| 326 | +- `.claude/board/LATEST_STATE.md` — current-state snapshot |
| 327 | +- `.claude/board/PR_ARC_INVENTORY.md` — per-PR decision history |
| 328 | +- `.claude/board/CROSS_REPO_PRS.md` — external-repo PRs that touch this workspace |
| 329 | +- `Cargo.toml` (workspace root) — `members = [...]` is the canonical crate list |
| 330 | +- `CLAUDE.md` — Click P-1 (carrier-method-or-reject), three iron rules |
| 331 | + |
| 332 | +## Maintenance |
| 333 | + |
| 334 | +This file is not append-only — it's a living usability guide. Edit when: |
| 335 | +1. New crate enters the workspace (extend Crate Inventory) |
| 336 | +2. New region added to soa-dto-fma-map (extend graph diagram) |
| 337 | +3. New systematic anti-pattern observed (add to Anti-Patterns) |
| 338 | +4. New wiring recipe identified (add to Recipes) |
| 339 | + |
| 340 | +When editing, preserve the TL;DR table at the top — that's the load-bearing entry point. |
0 commit comments