Skip to content

Commit a0857c0

Browse files
committed
feat(contract): ada-rewrite charter + the 34-tactic recipe catalogue (green)
Charter (ada-rewrite-charter.md): the once-and-for-all settled decisions. D0 = ladybug-rs has no relation and never will (failed "empty cathedral"); we rewrite on our substrate, the cross-repo docs are spec-references only, never deps/ports. D1 substrate, D2 hardware partition (datapath/control/ gate), D3 the 34 as recipe targets on 3 mechanisms, D4 build order. Code: contract::recipes -- the 34 reasoning-tactic recipes as a working, tested catalogue. Recipe {id, code, name, Tier, Mechanism, Bucket, spo2cubed Coverage, substrate}; RECIPES[34]; recipe()/by_code()/ by_mechanism()/causal(). Each recipe names the OUR-substrate primitive that realizes it (composes our pieces, never ladybug). 4 tests green (complete-34/unique, lookups, only RCR+ICR 2^3-covered, mechanism tally 6/6/8/14); 442 existing contract tests unaffected. https://claude.ai/code/session_017GFLBnDy23AWBqvkbHHC41
1 parent 7d413a3 commit a0857c0

4 files changed

Lines changed: 237 additions & 0 deletions

File tree

.claude/board/AGENT_LOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@
8383

8484
---
8585

86+
## [Main-thread] [DONE — green] ada-rewrite charter + the 34-tactic recipe catalogue (working code)
87+
88+
**Decision (charter D0):** ladybug-rs has NO relation, never will — it's the failed "empty cathedral." We rewrite on our substrate; ladybug/ada-consciousness/neo4j-rs docs are spec-references only, never deps/ports. `.claude/knowledge/ada-rewrite-charter.md` is the once-and-for-all settled-decision record (substrate, SPOQ lattice, hardware partition, 34-as-recipe-targets, build order).
89+
90+
**Code:** `crates/lance-graph-contract/src/recipes.rs` (new, wired in lib.rs) — the **34 reasoning-tactic recipes as a working catalogue**: `Recipe {id, code, name, Tier, Mechanism, Bucket, Coverage(spo2cubed), substrate}` + `RECIPES: [Recipe;34]` + `recipe()/recipe_by_code()/by_mechanism()/causal()`. Each tagged with the OUR-substrate primitive that realizes it (composes our pieces, never ladybug). **4 tests green** (complete 34 / ids unique, lookups, only RCR+ICR are 2³-Covered, mechanism tally 6/6/8/14). 442 existing contract tests unaffected.
91+
92+
**Next (charter D4):** per-recipe evaluators tier-by-tier (Hard-tier truth/parallel first — substrate most built), then shader-driver carrier wiring for the datapath recipes.
93+
94+
---
95+
8696
## [Inventory-Opus] [DONE — writes were permission-blocked; persisted by main thread] SPO-2³ workspace list inventory
8797

8898
Catalogued **31 enumerated cognitive lists** across contract / planner / cognitive-shader-driver / thinking-engine / holograph + 3 markdown taxonomies. **2³ tally: Covered 4 / Partial 6 / Not 21** (confirms 2³ = the causal spine only — CausalMask / nars_engine masks / PearlLevel / CANONICAL_ATOMS Pearl lanes are the lattice; everything style/qualia/rung/layer/ghost/MUL is orthogonal). Gaps (reference tactics with no enumerated lance-graph home): #18 CWS, #14 M-CoT, #29/#32 intent, #16/#23/#33 meta-prompting, #12 TCA, #22/#19 dynamic-decompose, #5/#20 pruning — but ladybug-rs implements all 34 upstream. Result persisted into `.claude/knowledge/spo-2cubed-list-coverage.md`. No code edited.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Ada Rewrite Charter — the once-and-for-all decisions
2+
3+
> **READ BY:** everyone. This is the settled-decision record for the rewrite. If a later doc contradicts this, this wins unless explicitly superseded by a dated entry.
4+
> **Date:** 2026-05-27.
5+
6+
## D0 — We rewrite. ladybug-rs has no relation and never will.
7+
8+
`ladybug-rs` ran 10,000 × 10,000-D VSA and produced no meaningful output — the "empty cathedral" (E-AGICHAT-DIMENSION-CONTRACT). It is **NOT a dependency, NOT a port target, NOT consumed**. Its docs (the 34-tactics × reasoning-ladder map, the SPOQ audit) are **specification references only** — they tell us *what each capability must do and which science grounds it*, never *what code to copy*. Same for ada-consciousness and neo4j-rs. **Iron rule: restore the contract on our i4 SoA floor; never port the carrier.** "Use the ladybug implementations" = use them as the spec to write our own working recipes.
9+
10+
## D1 — The substrate (settled)
11+
12+
- **atoms → cognitive-shader-driver → SIMD.** Atoms are cognitive units (bare-metal, not human-legible); they dispatch through `cognitive-shader-driver`, which owns the ndarray i4 SIMD. No SIMD in the atom layer.
13+
- **Three layers:** atom (one lane/pole) → thinking-style (one i4 vector = molecule) → persona (composition of styles + thresholds + β). The OO style/persona objects are the metacognition; atoms are the bytes.
14+
- **The lattice is SPOQ.** SPO 2³ = the *causal* slice (8 projections, Counterfactual=`SPO`=0b111, Intervention=`_PO`). **Q (Qualia) is the 4th role** — affective overlay, orthogonal to causality. Causal reasoning rides 2³; qualia rides Q.
15+
- **Business = OGIT-inherited sidecar**, not an atom (front-door `MappingRow``Marking`).
16+
- **Markers gate implicitly** (CPU-style clock-gating): entropy = CollapseGate `SD` (FLOW<0.15/HOLD/BLOCK>0.35), free-energy = the rest-floor, rung R1–R9 = pipeline depth, temperature (Staunen↔Wisdom) = speculation width, dissonance = counterfactual-fork gate. Markers are free byproducts; expensive units stay dark by default.
17+
18+
## D2 — The hardware partition (where work lives)
19+
20+
| bucket | = CPU | holds |
21+
|---|---|---|
22+
| **datapath** | vector ALU | uniform branch-free SIMD: atom lanes, FreeEnergy, resonance (cosine sweep) — in `cognitive-shader-driver` |
23+
| **control** | microcode | branchy decisions: quorum/InnerCouncil, counterfactual fork, persona dispatch, OGIT lookup — in planner + `contract::escalation` |
24+
| **gate** | clock/power-gating | the markers above decide *whether* control/datapath fire — in `elevation/` + CollapseGate SD |
25+
26+
## D3 — The 34 tactics are the recipe targets
27+
28+
The 34 LLM tactics (ladybug spec) reduce to **three mechanisms** = the partition:
29+
1. **Parallel-Independence** (breaks Tier-2 `P=p^n` error) → datapath/redundancy. #1,2,5,20,26,30.
30+
2. **Truth-Aware-Inference** (NARS truth per step, revision, abduction, CollapseGate HOLD, Brier) → control. #3,7,10,11,17,21,28.
31+
3. **Structural-Divergence** (12 styles can't converge; counterfactual XOR world; Granger; reversible fusion) → gate+control. #4,6,9,13,23,31,34.
32+
33+
A **recipe** = a named composition over our substrate that realizes a tactic. We write them as working, tested code (`contract::recipes` = the catalogue spine; per-recipe evaluators land as substrate readiness allows). Recipes compose *our* primitives (atoms, SPO 2³ masks, NARS truth, CollapseGate SD, markers) — never call ladybug.
34+
35+
## D4 — Build order
36+
37+
1. ✅ Atom catalogue (locked 33-TSV), markers, CollapseGate SD, NARS, escalation — exist.
38+
2. **▶ Recipe catalogue** (`contract::recipes`, the 34 as working data + registry + tests) — THIS deliverable.
39+
3. Per-recipe evaluators, tier by tier (Hard-tier truth/parallel recipes first — their substrate is most built).
40+
4. cognitive-shader-driver carrier wiring (atom pack/unpack), then datapath recipes.
41+
42+
**Cross-ref:** `agi-stack-cross-repo.md` (the spec sources), `spo-2cubed-list-coverage.md` (2³ coverage + the 34 table), `atom-basis-inventory.md` (33-TSV), `EPIPHANIES.md` E-AGICHAT-DIMENSION-CONTRACT (the empty-cathedral lineage).

crates/lance-graph-contract/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub use qualia::{
7272
QUALIA_DIMS, QUALIA_I4_DIMS, QUALIA_I4_LABELS, ZERO,
7373
};
7474
pub mod reasoning;
75+
pub mod recipes;
7576
pub mod repository;
7677
pub mod scenario;
7778
pub mod sensorium;
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
//! The 34 reasoning-tactic **recipes** — the working catalogue spine.
2+
//!
3+
//! A *recipe* is a named composition over OUR substrate (atoms, SPO 2³ masks, NARS
4+
//! truth, CollapseGate SD, markers) that realizes one of the 34 LLM reasoning tactics.
5+
//!
6+
//! # Spec source, not dependency
7+
//!
8+
//! The 34 are specified by the ladybug-rs `34_TACTICS_x_REASONING_LADDER` doc and the
9+
//! Sun et al. (2025) reasoning ladder. **ladybug-rs is the failed "empty cathedral" — a
10+
//! reference for *what each tactic must do*, never a dependency or port target** (see
11+
//! `.claude/knowledge/ada-rewrite-charter.md` D0). Every recipe composes *our* primitives.
12+
//!
13+
//! This module is the **catalogue spine**: the 34 as data + registry + lookups, each
14+
//! tagged with its difficulty Tier, the structural Mechanism it uses, the hardware
15+
//! Bucket it lives in, and its SPO-2³ causal coverage. Per-recipe *evaluators* land
16+
//! incrementally as substrate readiness allows (charter D4).
17+
18+
/// Sun et al. (2025) reasoning-ladder difficulty tier the tactic addresses.
19+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20+
pub enum Tier {
21+
/// Hard tier (~65% plateau) — multiplicative error across dependent steps.
22+
Hard,
23+
/// Extremely-Hard tier (<10%) — convergent lock-in, no creative leap.
24+
ExtremelyHard,
25+
/// Cross-tier infrastructure — helps at every difficulty.
26+
CrossTier,
27+
}
28+
29+
/// The structural mechanism (the 3 that LLMs lack) the tactic relies on.
30+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31+
pub enum Mechanism {
32+
/// Parallel independence vs sequential dependency (breaks `P=p^n`).
33+
ParallelIndependence,
34+
/// Truth-aware inference (NARS truth/revision/abduction) vs next-token prob.
35+
TruthAwareInference,
36+
/// Structural divergence vs convergent optimization.
37+
StructuralDivergence,
38+
/// Cross-cutting infrastructure (memory, fusion, scaffolding, diagnostics).
39+
Infrastructure,
40+
}
41+
42+
/// The hardware-design partition the recipe executes in (charter D2).
43+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
44+
pub enum Bucket {
45+
/// Uniform, branch-free, every-cycle SIMD — runs in `cognitive-shader-driver`.
46+
Datapath,
47+
/// Branchy decision at a control point — planner + `escalation`.
48+
Control,
49+
/// A cheap marker that gates whether deeper work fires — `elevation`/CollapseGate SD.
50+
Gate,
51+
}
52+
53+
/// SPO 2³ causal-lattice coverage (see `.claude/knowledge/spo-2cubed-list-coverage.md`).
54+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
55+
pub enum Coverage {
56+
/// Maps onto the causal lattice (the projections / Pearl levels).
57+
Covered,
58+
/// Some members ride the lattice, rest orthogonal.
59+
Partial,
60+
/// Orthogonal axis (operation / meta / gate / memory / qualia).
61+
NotCovered,
62+
}
63+
64+
/// One reasoning-tactic recipe.
65+
#[derive(Debug, Clone, Copy)]
66+
pub struct Recipe {
67+
/// Tactic number 1..=34 (Stakelum/ladybug numbering).
68+
pub id: u8,
69+
/// Short code, e.g. `"RCR"`.
70+
pub code: &'static str,
71+
/// Human name.
72+
pub name: &'static str,
73+
pub tier: Tier,
74+
pub mechanism: Mechanism,
75+
pub bucket: Bucket,
76+
pub spo2cubed: Coverage,
77+
/// The OUR-substrate primitive(s) that realize it (charter D3).
78+
pub substrate: &'static str,
79+
}
80+
81+
use Bucket::*;
82+
use Coverage::*;
83+
use Mechanism::*;
84+
use Tier::*;
85+
86+
/// The 34 recipes. Order = id ascending.
87+
pub const RECIPES: [Recipe; 34] = [
88+
Recipe { id: 1, code: "RTE", name: "Recursive Thought Expansion", tier: Hard, mechanism: ParallelIndependence, bucket: Control, spo2cubed: NotCovered, substrate: "rung depth × Expand/Compress; Berry-Esseen stop" },
89+
Recipe { id: 2, code: "HTD", name: "Hierarchical Thought Decomposition", tier: Hard, mechanism: ParallelIndependence, bucket: Control, spo2cubed: NotCovered, substrate: "CLAM bipolar split / Decompose op" },
90+
Recipe { id: 3, code: "SMAD", name: "Structured Multi-Agent Debate", tier: ExtremelyHard, mechanism: TruthAwareInference, bucket: Control, spo2cubed: NotCovered, substrate: "a2a_blackboard + InnerCouncil (NARS-revised vote)" },
91+
Recipe { id: 4, code: "RCR", name: "Reverse Causality Reasoning", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Control, spo2cubed: Covered, substrate: "SPO 2³ backward S_O + Abduction + Granger" },
92+
Recipe { id: 5, code: "TCP", name: "Thought Chain Pruning", tier: Hard, mechanism: ParallelIndependence, bucket: Gate, spo2cubed: NotCovered, substrate: "CollapseGate SD BLOCK prunes branch" },
93+
Recipe { id: 6, code: "TR", name: "Thought Randomization", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Gate, spo2cubed: NotCovered, substrate: "temperature (Staunen) perturb above noise floor" },
94+
Recipe { id: 7, code: "ASC", name: "Adversarial Self-Critique", tier: ExtremelyHard, mechanism: TruthAwareInference, bucket: Control, spo2cubed: Partial, substrate: "InnerCouncil split / 5 challenge types (negation projection)" },
95+
Recipe { id: 8, code: "CAS", name: "Conditional Abstraction Scaling", tier: CrossTier, mechanism: Infrastructure, bucket: Gate, spo2cubed: NotCovered, substrate: "HDR cascade INT1/4/8/32 × Abstract↔Concretize" },
96+
Recipe { id: 9, code: "IRS", name: "Iterative Roleplay Synthesis", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Control, spo2cubed: NotCovered, substrate: "persona FieldModulation (structurally distinct kernels)" },
97+
Recipe { id: 10, code: "MCP", name: "Meta-Cognition Prompting", tier: Hard, mechanism: TruthAwareInference, bucket: Control, spo2cubed: NotCovered, substrate: "MUL DK + Brier calibration; Meta lane" },
98+
Recipe { id: 11, code: "CR", name: "Contradiction Resolution", tier: Hard, mechanism: TruthAwareInference, bucket: Control, spo2cubed: Partial, substrate: "NARS opposing-truth detect + coherence; Contradiction preserved" },
99+
Recipe { id: 12, code: "TCA", name: "Temporal Context Augmentation", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "Granger temporal lane / Markov ±5 / 24 temporal verbs" },
100+
Recipe { id: 13, code: "CDT", name: "Convergent & Divergent Thinking", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Gate, spo2cubed: NotCovered, substrate: "explore↔exploit temperature; style oscillation" },
101+
Recipe { id: 14, code: "MCT", name: "Multimodal Chain-of-Thought", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "GrammarTriangle: NSM+Causality+Qualia → one fingerprint" },
102+
Recipe { id: 15, code: "LSI", name: "Latent Space Introspection", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "CRP distribution / Mexican-hat over fingerprint clusters" },
103+
Recipe { id: 16, code: "PSO", name: "Prompt Scaffold Optimization", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "ThinkingTemplate slots + TD-learned discovery" },
104+
Recipe { id: 17, code: "CDI", name: "Cognitive Dissonance Induction", tier: CrossTier, mechanism: TruthAwareInference, bucket: Control, spo2cubed: Partial, substrate: "Festinger dissonance = opposing NARS truth on similar fp; HOLD" },
105+
Recipe { id: 18, code: "CWS", name: "Context Window Simulation", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "persistent BindSpace / WitnessCorpus / episodic memory" },
106+
Recipe { id: 19, code: "ARE", name: "Algorithmic Reverse Engineering", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "ABBA unbind: A⊗B⊗B=A (exact algebraic inverse)" },
107+
Recipe { id: 20, code: "TCF", name: "Thought Cascade Filtering", tier: Hard, mechanism: ParallelIndependence, bucket: Gate, spo2cubed: NotCovered, substrate: "N search strategies + agreement rate; SD select" },
108+
Recipe { id: 21, code: "SSR", name: "Self-Skepticism Reinforcement", tier: Hard, mechanism: TruthAwareInference, bucket: Control, spo2cubed: Partial, substrate: "challenge schedule × MUL uncertainty; truth-drop = weak" },
109+
Recipe { id: 22, code: "ETD", name: "Emergent Task Decomposition", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "CLAM cluster geometry determines subtasks (no spec)" },
110+
Recipe { id: 23, code: "AMP", name: "Adaptive Meta-Prompting", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Control, spo2cubed: NotCovered, substrate: "TD-learning on ThinkingStyle Q-values (W32-39)" },
111+
Recipe { id: 24, code: "ZCF", name: "Zero-Shot Concept Fusion", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "VSA bind(A,B): new vector valid in both spaces, recoverable" },
112+
Recipe { id: 25, code: "HPM", name: "Hyperdimensional Pattern Matching", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "the substrate: fingerprint cosine/Hamming sweep (SIMD)" },
113+
Recipe { id: 26, code: "CUR", name: "Cascading Uncertainty Reduction", tier: Hard, mechanism: ParallelIndependence, bucket: Gate, spo2cubed: NotCovered, substrate: "FreeEnergy / CRP percentiles; coarse-to-fine prune" },
114+
Recipe { id: 27, code: "MPC", name: "Multi-Perspective Compression", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "bundle = majority-vote-per-bit consensus + delta encode" },
115+
Recipe { id: 28, code: "SSAM", name: "Self-Supervised Analogical Mapping", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Datapath, spo2cubed: Partial, substrate: "NARS analogy A→B,C≈A⊢C→B; bind+similarity (Gentner)" },
116+
Recipe { id: 29, code: "IDR", name: "Intent-Driven Reframing", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "GrammarTriangle CausalityFlow agent/action/patient/reason" },
117+
Recipe { id: 30, code: "SPP", name: "Shadow Parallel Processing", tier: Hard, mechanism: ParallelIndependence, bucket: Control, spo2cubed: Partial, substrate: "independent paths + agreement (ECC/RAID); the CF majority/minority fork" },
118+
Recipe { id: 31, code: "ICR", name: "Iterative Counterfactual Reasoning", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Control, spo2cubed: Covered, substrate: "world⊗factual⊗counterfactual (XOR self-inverse); SPO=0b111; CausalEdge64 −6 mantissa" },
119+
Recipe { id: 32, code: "SDD", name: "Semantic Distortion Detection", tier: CrossTier, mechanism: Infrastructure, bucket: Datapath, spo2cubed: NotCovered, substrate: "Berry-Esseen noise floor + reciprocal A→B,B→A validation" },
120+
Recipe { id: 33, code: "DTMF", name: "Dynamic Task Meta-Framing", tier: CrossTier, mechanism: Infrastructure, bucket: Control, spo2cubed: NotCovered, substrate: "template switch on CollapseGate BLOCK (shift all modulation)" },
121+
Recipe { id: 34, code: "HKF", name: "Hyperdimensional Knowledge Fusion", tier: ExtremelyHard, mechanism: StructuralDivergence, bucket: Datapath, spo2cubed: NotCovered, substrate: "cross-domain bind(A,rel,B); reversible/auditable fusion" },
122+
];
123+
124+
/// Look up a recipe by tactic id (1..=34).
125+
#[inline]
126+
pub fn recipe(id: u8) -> Option<&'static Recipe> {
127+
RECIPES.iter().find(|r| r.id == id)
128+
}
129+
130+
/// Look up a recipe by short code (e.g. `"RCR"`).
131+
#[inline]
132+
pub fn recipe_by_code(code: &str) -> Option<&'static Recipe> {
133+
RECIPES.iter().find(|r| r.code == code)
134+
}
135+
136+
/// All recipes sharing a mechanism.
137+
pub fn by_mechanism(m: Mechanism) -> impl Iterator<Item = &'static Recipe> {
138+
RECIPES.iter().filter(move |r| r.mechanism == m)
139+
}
140+
141+
/// All recipes that ride the SPO 2³ causal lattice (Covered or Partial).
142+
pub fn causal() -> impl Iterator<Item = &'static Recipe> {
143+
RECIPES.iter().filter(|r| matches!(r.spo2cubed, Coverage::Covered | Coverage::Partial))
144+
}
145+
146+
#[cfg(test)]
147+
mod tests {
148+
use super::*;
149+
150+
#[test]
151+
fn catalogue_is_complete_34_ids_unique() {
152+
assert_eq!(RECIPES.len(), 34);
153+
for (i, r) in RECIPES.iter().enumerate() {
154+
assert_eq!(r.id as usize, i + 1, "recipes must be id-ordered 1..=34");
155+
assert!(!r.code.is_empty() && !r.name.is_empty() && !r.substrate.is_empty());
156+
}
157+
}
158+
159+
#[test]
160+
fn lookups_work() {
161+
assert_eq!(recipe(4).unwrap().code, "RCR");
162+
assert_eq!(recipe(31).unwrap().code, "ICR");
163+
assert_eq!(recipe_by_code("HPM").unwrap().id, 25);
164+
assert!(recipe(0).is_none() && recipe(35).is_none());
165+
}
166+
167+
#[test]
168+
fn only_causal_tactics_are_2cubed_covered() {
169+
// Exactly RCR (#4) and ICR (#31) fully cover the causal lattice.
170+
let covered: Vec<u8> = RECIPES.iter().filter(|r| r.spo2cubed == Coverage::Covered).map(|r| r.id).collect();
171+
assert_eq!(covered, vec![4, 31]);
172+
// 2³ is the causal spine only — the rest are Partial or orthogonal.
173+
assert!(causal().count() < RECIPES.len() / 2, "most tactics are NOT causal");
174+
}
175+
176+
#[test]
177+
fn mechanism_tally_matches_the_ladder_doc() {
178+
let count = |m: Mechanism| by_mechanism(m).count();
179+
assert_eq!(count(Mechanism::ParallelIndependence), 6); // #1,2,5,20,26,30
180+
assert_eq!(count(Mechanism::TruthAwareInference), 6); // #3,7,10,11,17,21
181+
assert_eq!(count(Mechanism::StructuralDivergence), 8); // #4,6,9,13,23,28,31,34
182+
assert_eq!(count(Mechanism::Infrastructure), 14);
183+
}
184+
}

0 commit comments

Comments
 (0)