diff --git a/CLAUDE.md b/CLAUDE.md index 7f8ffa865..d4caceafc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -2,7 +2,7 @@ ## Project Overview -Aprender is a next-generation ML framework in pure Rust — **monorepo with 80 workspace crates**. Install: `cargo install aprender` → `apr` binary (103 subcommands). 25,300+ tests, 1148 provable contracts. Core library in `crates/aprender-core/` ([lib] name = "aprender"). All 20 repos (trueno, realizar, entrenar, batuta, + 15 satellites) consolidated per APR-MONO spec. **v0.34.0 SHIPPED 2026-05-18: MODEL-2 §88 stack-existence-proof, paiml/albor-370m-v1 LIVE on HF Hub.** +Aprender is a next-generation ML framework in pure Rust — **monorepo with 82 workspace crates**. Install: `cargo install aprender` → `apr` binary (103 subcommands). 25,300+ tests, 1460 provable contracts. Core library in `crates/aprender-core/` ([lib] name = "aprender"). All 20 repos (trueno, realizar, entrenar, batuta, + 15 satellites) consolidated per APR-MONO spec. **v0.34.0 SHIPPED 2026-05-18: MODEL-2 §88 stack-existence-proof, paiml/albor-370m-v1 LIVE on HF Hub.** ## Git Workflow (Branch Protection) @@ -58,11 +58,11 @@ When using `/loop`, treat fallback wakeups as cheap and merge events as primary. ## Build Commands ```bash -cargo build --release # Optimized build (all 80 crates) +cargo build --release # Optimized build (all 82 crates) cargo test --workspace --lib # Full workspace lib tests (25,300+) cargo test -p aprender-core --lib # Core ML library only (12,975) cargo test -p apr-cli --lib # CLI tests only (4,158) -cargo check --workspace # Type-check all 80 crates +cargo check --workspace # Type-check all 82 crates cargo fmt --check # Check formatting cargo clippy -- -D warnings # Strict linting @@ -131,7 +131,7 @@ TraceSteps: `Tokenize`, `Embed`, `LayerNorm`, `Attention`, `FFN`, `TransformerBl 2. **Backend Agnostic** - CPU (SIMD), GPU, WASM via Trueno 3. **Three-Tier API**: High (`Estimator` trait), Mid (`Optimizer`/`Loss`/`Regularizer`), Low (Trueno primitives) -**Monorepo layout** (70 crates, flat `crates/aprender-*` per Polars/Burn/Nushell pattern): +**Monorepo layout** (82 crates, flat `crates/aprender-*` per Polars/Burn/Nushell pattern): - `crates/aprender-core/` — ML library ([lib] name = "aprender") - `crates/aprender-compute/` — SIMD/GPU (was trueno, [lib] name = "trueno") - `crates/aprender-serve/` — inference server (was realizar, [lib] name = "realizar") @@ -310,7 +310,7 @@ Key: `unsafe_code = "forbid"`, `clippy::all + pedantic = "warn"`, ML-specific al - `crates/aprender-core/src/text/chat_template.rs` - Chat template engine - `crates/apr-cli/` - CLI logic (82 commands) - `src/bin/apr.rs` - Root binary entry point (`cargo install aprender`) -- `contracts/` - 1134 provable contracts (merged from all 20 repos) +- `contracts/` - 1460 provable contracts (merged from all 20 repos) - `docs/specifications/aprender-monorepo-consolidation.md` - Monorepo spec ## APR CLI (`cargo install aprender`) diff --git a/README.md b/README.md index e95ecba17..cba38927d 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ publishing — all backed by YAML provable contracts that fail CI on drift. | Metric | Count | Source of truth | |-------:|------:|---| | Workspace crates | **82** workspace crates | `ls crates/` | -| Provable contracts | **1331** provable contracts | `find contracts/ -name '*.yaml'` | +| Provable contracts | **1460** provable contracts | `find contracts/ -name '*.yaml'` | | CLI commands | **103** CLI commands | `apr --help` | | Book CLI chapters | **103** chapters | `ls book/src/cli/*.md` (parity with CLI) | | Book lib chapters | **69** chapters | `ls book/src/lib/*.md` (parity with `pub mod`) | @@ -253,7 +253,7 @@ falsification_tests: prediction: apr validate bad-model.apr exits non-zero ``` -1158 contracts across inference, training, quantization, attention, FFN, +1460 contracts across inference, training, quantization, attention, FFN, tokenization, model formats, CLI safety — and this README itself. ## Migration from old crates diff --git a/crates/aprender-core/tests/readme_contract.rs b/crates/aprender-core/tests/readme_contract.rs index a8f4e33da..0c8638bad 100644 --- a/crates/aprender-core/tests/readme_contract.rs +++ b/crates/aprender-core/tests/readme_contract.rs @@ -93,6 +93,44 @@ fn test_readme_crate_count_matches_workspace() { ); } +/// FALSIFY-README-007: Contract count in README matches `find contracts/ -name '*.yaml'`. +/// +/// The "**M** provable contracts" claim was previously checked ONLY by +/// `scripts/check_readme_claims.sh`, which is executable but wired into NO +/// workflow (`grep -rn check_readme_claims .github/workflows` = 0 hits). So the +/// count drifted freely: README said **1331** while the tree held **1766** +/// (Fable rank-7, PMAT-DRIFT-GATES-001). This test rides the already-wired +/// `cargo test` job, so the claim can no longer drift without failing a PR. +/// Counts `*.yaml` recursively to match the canonical script method. +#[test] +fn test_readme_contract_count_matches_workspace() { + let readme = read_readme(); + let contracts_dir = workspace_root().join("contracts"); + + fn count_yaml(dir: &Path) -> usize { + let mut n = 0; + if let Ok(entries) = std::fs::read_dir(dir) { + for entry in entries.flatten() { + let path = entry.path(); + if path.is_dir() { + n += count_yaml(&path); + } else if path.extension().is_some_and(|ext| ext == "yaml") { + n += 1; + } + } + } + n + } + + let contract_count = count_yaml(&contracts_dir); + let count_str = format!("**{contract_count}** provable contracts"); + assert!( + readme.contains(&count_str), + "FALSIFY-README-007: README lacks `**{contract_count}** provable contracts` \ + matching `find contracts/ -name '*.yaml'` — update the README claims table row" + ); +} + /// FALSIFY-SVG-002: Hero SVG is accessible #[test] fn test_hero_svg_accessible() {