Skip to content

Commit cd95da9

Browse files
committed
docs: add .claude/patterns.md — SoA/DTO graph traversal patterns + crate inventory + anti-patterns + wiring recipes
Authored after a session that walked through ~10 rounds of "is X new?" → "no, X exists at Y" before finally building the workspace map. The patterns here are the cost of that walk, captured so the next session pays a tax of one read instead of ten rounds. Five traversal patterns: - P-1 CRATE-FIRST: read Cargo.toml workspace.members BEFORE proposing - P-2 REGION-FIRST: name your concept's R-id from soa-dto-fma-map - P-3 ENTROPY-FIRST: sort ledger by Entropy DESC; highest = highest leverage - P-4 APPEND-ONLY: board files never edit prior; only append dated sections - P-5 CLUSTER-AWARE: when fixing one row, check Section B siblings Crate inventory (canonical at 2026-05-06): ~22 crates listed with region(s) and what each owns — the universe of "does this exist?". Five anti-patterns observed in this session (Discovery Loop, Harvest- from-Stale, Map-Blindness, Single-Name Lookup, Plan-Doc-Without-Code- Check) with concrete cures. Equivalence map: ladybug-rs/src/spo modules ↔ lance-graph workspace locations (e.g. clam_path ≅ cam_pq, nsm_substrate ≅ deepnsm::codebook, sentence_crystal ≅ holograph::sentence_crystal, DN-tree binding ≅ holograph::{dntree,dn_sparse,navigator}). Six wiring recipes (CAM-DIST-1 register, PARSER-1 wire, DEEPNSM-NSM-1 collapse, VSA-1 methods, MEMBRANE-GATE-1 done, WATCHER-1 done) — concrete non-duplicating wirings using only existing primitives. Pre-work checklist + ledger update protocol restated. Companion to soa-dto-fma-map.md + ARCHITECTURE_ENTROPY_LEDGER.md.
1 parent c1fc1e5 commit cd95da9

1 file changed

Lines changed: 340 additions & 0 deletions

File tree

.claude/patterns.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
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

Comments
 (0)