mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
CRITICAL (7): - C1: Hardcoded Wolfram Alpha API key (revoke immediately) - C2: Q16_16 rounding diverges Lean↔Python↔C (data corruption) - C3: Receipts describe non-existent files (fabrication) - C4: '3,500+ proofs' = compilation units, not theorems - C5: NaN sentinel collision Lean↔C (silent corruption) - C6: eigensolid_convergence theorem is a tautology - C7: 74% CI failure rate HIGH (12): duplicate definitions, SQL injection, command injection, 1,029 duplicate files, 66 large files in git, AGENTS.md drift MEDIUM (23): stale docs, broken cross-refs, unhandled errors LOW (31): naming violations, misplaced files, cleanup Master synthesis: audit/MASTER_AUDIT_SYNTHESIS.md Per-dimension reports: audit/*_audit.md
417 lines
19 KiB
Markdown
417 lines
19 KiB
Markdown
# Integration Audit: Research-Stack Cross-Language Boundaries
|
|
|
|
## Summary
|
|
|
|
| Category | Count | Severity |
|
|
|----------|-------|----------|
|
|
| Integration points identified | 18 | — |
|
|
| Critical type mismatches | 3 | CRITICAL |
|
|
| Error handling gaps | 7 | HIGH |
|
|
| Broken CLI contracts | 2 | HIGH |
|
|
| Workflow gaps / missing handoffs | 5 | MEDIUM |
|
|
| Race conditions | 2 | MEDIUM |
|
|
| Duplicate divergent Q16_16 libraries | 2 | HIGH |
|
|
| Generated files not properly managed | 3 | MEDIUM |
|
|
| `sorry` in proofs unchecked by CI | 1 | HIGH |
|
|
|
|
---
|
|
|
|
## Critical Issues
|
|
|
|
### C1: Q16_16 Conversion Mismatch — Lean vs. Python vs. C [CRITICAL]
|
|
|
|
**Files:**
|
|
- `0-Core-Formalism/lean/Semantics/Semantics/FixedPoint.lean` (lines 270-290)
|
|
- `0-Core-Formalism/lean/Semantics/BindServer.lean` (lines 33-44)
|
|
- `4-Infrastructure/lib/q16.py`
|
|
- `4-Infrastructure/auto/lib/q16.py`
|
|
- `0-Core-Formalism/core/include/manifold_binary.h` (lines 52-60)
|
|
|
|
**Issue:** Three different Q16_16 float conversion algorithms exist across the boundary:
|
|
|
|
1. **Lean `FixedPoint.lean`**: Uses `(f * 65536.0).floor` — rounds down (truncates toward zero)
|
|
2. **Lean `BindServer.lean`**: Uses `(f * 65536.0).floor.toUInt32` — same floor, but goes through UInt32 with saturation at 0xFFFFFFFF/0x80000000
|
|
3. **Python `q16.py`**: Uses `int(round(value * 65536))` — rounds to nearest (banker's rounding for .5)
|
|
4. **C `manifold_binary.h`**: Uses `(q16_16_t)(f * (1 << 16))` — C cast truncates toward zero
|
|
|
|
**Impact:** Values near half-LSB boundaries (e.g., 1.00001) will diverge. A value of `1.5 / 65536.0 = 0.000022888...` will be:
|
|
- Lean (floor): `1` (raw 65536)
|
|
- Python (round): `2` (raw 131072)
|
|
- C (truncation): `1` (raw 65536)
|
|
|
|
This affects all data flowing through the pipeline: spectral profiles, Sidon addresses, QUBO coefficients, and braid parameters.
|
|
|
|
**Recommendation:** Unify on a single conversion spec. The Lean `floor` approach is the most conservative and is formally specified; Python and C should match it.
|
|
|
|
---
|
|
|
|
### C2: Duplicate Divergent Q16_16 Python Libraries [CRITICAL]
|
|
|
|
**Files:**
|
|
- `4-Infrastructure/lib/q16.py` (1494 bytes, has `q16_add`, `q16_sub`, `q16_mul`, `q16_div`)
|
|
- `4-Infrastructure/auto/lib/q16.py` (910 bytes, MISSING arithmetic ops)
|
|
|
|
**Issue:** Two copies of the Q16_16 Python library exist. The `auto/` version is a strict subset — it lacks `q16_add`, `q16_sub`, `q16_mul`, `q16_div`, `q16_gt`, `q16_ge`. Scripts importing from `auto/lib/` will fail at runtime if they call any arithmetic function.
|
|
|
|
Both use the same module name `q16`, creating import ambiguity depending on `sys.path` ordering.
|
|
|
|
**Impact:** Runtime `AttributeError` when arithmetic is attempted via the `auto/` copy. The `qaoa_adapter.py` imports from `../lib` but other shims may import from `auto/lib`.
|
|
|
|
**Recommendation:** Delete the `auto/lib/q16.py` stub or make it a re-export of the canonical `lib/q16.py`.
|
|
|
|
---
|
|
|
|
### C3: Lean `BindServer` JSON Parsing Lacks Error Handling on Float Overflow [CRITICAL]
|
|
|
|
**File:** `0-Core-Formalism/lean/Semantics/BindServer.lean` (lines 33-44)
|
|
|
|
```lean
|
|
@[inline]
|
|
def q16_16_of_float (f : Float) : UInt32 :=
|
|
if f.isNaN || f >= 32768.0 then 0xFFFFFFFF
|
|
else if f <= -32768.0 then 0x80000000
|
|
else (f * 65536.0).floor.toUInt32
|
|
```
|
|
|
|
**Issue:** The `0xFFFFFFFF` sentinel for NaN/overflow is indistinguishable from the bit pattern for `-1/65536.0` in two's complement. When this UInt32 flows to C via JSON, `manifold_binary.h`'s `q16_16_from_float` does NOT check for this sentinel — it will interpret 0xFFFFFFFF as `(float)0xFFFFFFFF / 65536.0 = 65535.999985` instead of signaling an error.
|
|
|
|
**Impact:** Silent data corruption on NaN/overflow inputs. The C side has no way to detect that a sentinel value was transmitted.
|
|
|
|
**Recommendation:** Use an explicit JSON error field instead of a bit-pattern sentinel. Or, have the C side validate against 0xFFFFFFFF and return an error code.
|
|
|
|
---
|
|
|
|
### C4: `sorry` in Generated Lean Theorems Never Checked by CI [HIGH]
|
|
|
|
**Files:**
|
|
- `4-Infrastructure/shim/eigensolid_pipeline.py` (lines 270-310, Lean generation code)
|
|
- `.github/workflows/math-check.yml`
|
|
|
|
**Issue:** The `eigensolid_pipeline.py` generates Lean theorems where every proof body is `sorry`:
|
|
```lean
|
|
theorem symmetry_violation_0 : Prop := by
|
|
sorry
|
|
```
|
|
|
|
The CI `math-check.yml` validates JSON schemas, DeepSeek receipts, and claims registries — but does NOT attempt to build or lint the generated `.lean` files. The `sorry` axioms accumulate unverified claims into the codebase.
|
|
|
|
**Impact:** Generated theorems provide false confidence. A downstream proof that depends on these `sorry` theorems will silently accept any conclusion.
|
|
|
|
**Recommendation:** Add a CI step that runs `lake build` on generated Lean files and rejects files containing `sorry` in theorem bodies.
|
|
|
|
---
|
|
|
|
## Warnings
|
|
|
|
### W1: `lean_trace_bridge.py` — No Exit Code Check from Proof Worker [HIGH]
|
|
|
|
**File:** `4-Infrastructure/shim/lean_trace_bridge.py` (lines 118-140)
|
|
|
|
```python
|
|
def prove_step(code: str, timeout_s: int = 120) -> dict:
|
|
result = subprocess.run(
|
|
["curl", "-s", "--connect-timeout", "10", "-X", "POST", ...],
|
|
capture_output=True, text=True, timeout=timeout_s,
|
|
)
|
|
if result.returncode != 0:
|
|
return {"ok": False, "error": f"curl: {result.stderr[:200]}", ...}
|
|
```
|
|
|
|
**Issue:** Only checks curl's exit code, NOT the HTTP status code from the proof worker. A 500/404 from the worker would produce `returncode == 0` from curl but with non-JSON body, leading to a `JSONDecodeError` that IS caught — but an HTTP 200 with `{"ok": false, ...}` is silently recorded as a failed step without raising any alarm.
|
|
|
|
**Impact:** Network errors and worker failures are silently logged as "failure" steps with no alerting mechanism.
|
|
|
|
**Recommendation:** Check the HTTP response status code explicitly and surface non-2xx responses as distinct error categories.
|
|
|
|
---
|
|
|
|
### W2: `eigensolid_pipeline.py` — No Schema Version Validation on Input JSON [HIGH]
|
|
|
|
**File:** `4-Infrastructure/shim/eigensolid_pipeline.py` (lines 456-460)
|
|
|
|
```python
|
|
extraction = json.loads(extraction_path.read_text())
|
|
```
|
|
|
|
**Issue:** The extraction JSON is loaded without any schema validation. If the upstream CERN data format changes (e.g., renames `conservation_laws` to `conservationLaws`), the pipeline will silently produce empty outputs rather than fail.
|
|
|
|
**Impact:** Silent data loss on upstream format changes.
|
|
|
|
**Recommendation:** Add a JSON schema validation step and version check before processing.
|
|
|
|
---
|
|
|
|
### W3: `load_dependency_graph.py` — Hardcoded Gremlin Credentials from `.env` [HIGH]
|
|
|
|
**File:** `scripts/load_dependency_graph.py` (lines 43-48)
|
|
|
|
```python
|
|
ENV_FILE = ROOT / ".env.gremlin"
|
|
load_dotenv(ENV_FILE)
|
|
ENDPOINT = os.environ["GREMLIN_ENDPOINT"]
|
|
USERNAME = os.environ["GREMLIN_USERNAME"]
|
|
PASSWORD = os.environ["GREMLIN_PASSWORD"]
|
|
```
|
|
|
|
**Issue:** Requires `.env.gremlin` to exist with plaintext credentials. If the file is missing, the script crashes with `KeyError`. The credentials file is gitignored in most setups but may be accidentally committed.
|
|
|
|
**Impact:** Deployment fragility + potential credential leak.
|
|
|
|
**Recommendation:** Add graceful fallback when env vars are missing, and warn about the credential file in `.gitignore`.
|
|
|
|
---
|
|
|
|
### W4: `build_static.sh` — Executable List May Be Stale [MEDIUM]
|
|
|
|
**File:** `0-Core-Formalism/lean/Semantics/build-static/build_static.sh` (lines 26-28)
|
|
|
|
```bash
|
|
EXECUTABLES=(bindserver searchserver SemanticsCli openworm_benchmark \
|
|
ExtremeParameterTestEval NominalParameterTestEval moim_benchmark \
|
|
generate_sparkle_phi_s3c tangnano9k_emitter)
|
|
```
|
|
|
|
**Issue:** The list of executables is hardcoded. If the Lean `lakefile.lean` changes and adds/removes executables, this list will silently fail to build the new targets or crash trying to build removed ones.
|
|
|
|
**Impact:** Build inconsistency between `lake build` and the static compilation script.
|
|
|
|
**Recommendation:** Parse the executable list from `lakefile.lean` or use `lake exe --list` if available.
|
|
|
|
---
|
|
|
|
### W5: `pist_neuromorphic.c` — Stats Export Destructively Modifies Frequency Data [MEDIUM]
|
|
|
|
**File:** `6-Kernel-Shim/pist_neuromorphic.c` (lines 433-445)
|
|
|
|
```c
|
|
for (i = 0; i < 10 && pos < PAGE_SIZE - 64; i++) {
|
|
int max_idx = 0;
|
|
// ...find max...
|
|
pos += sprintf(buf + pos, " %02x=%llu", max_idx, st->byte_freq[max_idx]);
|
|
st->byte_freq[max_idx] = 0; /* zero out for next iter (destructive!) */
|
|
}
|
|
```
|
|
|
|
**Issue:** The `stats_show` sysfs handler zeroes out byte frequencies while formatting the output. A concurrent read will see corrupted (partially zeroed) data. This is a race condition within a single show call, not even requiring concurrent readers.
|
|
|
|
**Impact:** Frequency data is corrupted after the first read. Subsequent reads show only zeros for the top-10 frequencies.
|
|
|
|
**Recommendation:** Copy the frequency array before formatting, or use a non-destructive selection algorithm (e.g., min-heap for top-k).
|
|
|
|
---
|
|
|
|
### W6: `qaoa_adapter.py` — Optional Backend Imports Fail Silently [MEDIUM]
|
|
|
|
**File:** `4-Infrastructure/shim/qaoa_adapter.py` (lines 40-52)
|
|
|
|
```python
|
|
try:
|
|
import cirq
|
|
_HAS_CIRQ = True
|
|
except ImportError:
|
|
_HAS_CIRQ = False
|
|
```
|
|
|
|
**Issue:** All three quantum backends (cirq, qiskit, numpy) are optional. If none are installed, many functions will fail at call time rather than import time. The `qaoa_solve_qubo` function references `_HAS_CIRQ` and `_HAS_QISKIT` but may still proceed to use numpy-dependent code that expects `np` to exist.
|
|
|
|
**Impact:** Late failure with confusing error messages when quantum backends are missing.
|
|
|
|
**Recommendation:** Add a runtime check at module load that at least `numpy` is available, and raise a clear `ImportError` if not.
|
|
|
|
---
|
|
|
|
### W7: `batch_compute.yml` — Uses `actions/checkout@v4` (Outdated) [LOW]
|
|
|
|
**File:** `.github/workflows/batch_compute.yml` (line 31)
|
|
|
|
```yaml
|
|
uses: actions/checkout@v4
|
|
```
|
|
|
|
**Issue:** Other workflows in the same repo use `actions/checkout@v6` (e.g., `math-check.yml`). Version mismatch may lead to different behavior around LFS handling, fetch-depth, etc.
|
|
|
|
**Impact:** Inconsistent CI behavior between workflows.
|
|
|
|
**Recommendation:** Standardize on `actions/checkout@v6` across all workflows.
|
|
|
|
---
|
|
|
|
### W8: `manifold_binary.c` — Deserialization Does Not Validate Array Bounds [MEDIUM]
|
|
|
|
**File:** `0-Core-Formalism/core/src/manifold_binary.c` (lines 71-130)
|
|
|
|
**Issue:** `manifold_binary_deserialize` validates the header magic and version, but does NOT validate that `num_shells * sizeof(PistShell)` etc. won't overflow a `size_t`. On a maliciously crafted input with very large `num_shells`, the `malloc()` call may succeed (returning NULL or a wrapped size) and the subsequent `memcpy` will write out of bounds.
|
|
|
|
**Impact:** Potential buffer overflow on untrusted binary input.
|
|
|
|
**Recommendation:** Add bounds checks: `if (num_shells > MAX_SHELLS) return -5;` before allocation.
|
|
|
|
---
|
|
|
|
### W9: `eigensolid_pipeline.py` Generated Lean File Missing `end` Namespace Check [MEDIUM]
|
|
|
|
**File:** `4-Infrastructure/shim/eigensolid_pipeline.py` (lines 265-275)
|
|
|
|
```python
|
|
lines.append("end Semantics.CERNEigensolidData")
|
|
return "\n".join(lines)
|
|
```
|
|
|
|
**Issue:** The generated Lean code is always wrapped in `namespace Semantics.CERNEigensolidData` / `end Semantics.CERNEigensolidData`. However, the generated content may contain syntax errors (e.g., malformed identifiers from `lean_ident`) that cause `lake build` to fail on the entire file, blocking all other modules.
|
|
|
|
**Impact:** A single malformed theorem name can break the entire Lean build.
|
|
|
|
**Recommendation:** Run `lake build` on generated files before they are checked in, and isolate generated files into a separate lake package.
|
|
|
|
---
|
|
|
|
### W10: `load_dependency_graph.py` — Theorem Body Parsing Is Fragile [MEDIUM]
|
|
|
|
**File:** `scripts/load_dependency_graph.py` (lines 108-140)
|
|
|
|
**Issue:** The theorem body extraction uses a heuristic that walks lines until the next `theorem `, `lemma `, or `def `. This will fail for:
|
|
- Nested `def` inside a `where` clause
|
|
- `theorem` mentioned in a comment string inside a proof
|
|
- Tactics that output these keywords in error messages
|
|
|
|
**Impact:** Incorrect theorem body extraction leads to wrong dependency edges in the Gremlin graph.
|
|
|
|
**Recommendation:** Use Lean's server protocol (`lean --server`) for accurate AST-based parsing, or at minimum add a TODO acknowledging the heuristic nature.
|
|
|
|
---
|
|
|
|
## Per-Pipeline Breakdown
|
|
|
|
### Pipeline A: Equation → Eigensolid → Lean Theorems
|
|
|
|
**Files:** `eigensolid_pipeline.py` → `CERNEigensolidData.lean` → `lake build`
|
|
|
|
| Step | Output | Handoff Risk |
|
|
|------|--------|-------------|
|
|
| CERN parquet → DataFrame | `pd.DataFrame` | Medium — column names hardcoded |
|
|
| Extraction JSON → dict | `dict` | **High** — no schema validation |
|
|
| Spectral profile → Sidon address | `SidonAddress` | Medium — threshold hardcoded |
|
|
| Sidon address → Lean code | `str` (Lean text) | **High** — `sorry` in every proof |
|
|
| Lean text → file | `.lean` file | Medium — no build verification |
|
|
|
|
**Gap:** The generated Lean file is written to disk but never compiled or checked by CI. The `sorry` placeholder means no mathematical validation occurs.
|
|
|
|
**Race Condition:** If the pipeline is run concurrently with different `--alpha` values, the output `.lean` file will be overwritten without version tracking.
|
|
|
|
---
|
|
|
|
### Pipeline B: Lean Proof → Trace Capture → Gremlin Graph
|
|
|
|
**Files:** `lean_trace_bridge.py` → `trace.json` → `load_dependency_graph.py` → Gremlin
|
|
|
|
| Step | Output | Handoff Risk |
|
|
|------|--------|-------------|
|
|
| Lean code → proof worker | HTTP POST | **High** — no HTTP status check |
|
|
| Proof worker → JSON response | `dict` | Medium — malformed responses ignored |
|
|
| Trace → JSON file | `trace.json` | Low |
|
|
| All files → Gremlin | Gremlin vertices/edges | **High** — credential file dependency |
|
|
|
|
**Gap:** Phase 7 verification queries run after loading but do NOT check that theorem bodies contain valid Lean syntax — only that the graph structure is connected.
|
|
|
|
---
|
|
|
|
### Pipeline C: Q16_16 ↔ QUBO ↔ QAOA Circuit ↔ Receipt
|
|
|
|
**Files:** `qaoa_adapter.py` → `qubo_highs.py` → receipt JSON
|
|
|
|
| Step | Languages | Handoff Risk |
|
|
|------|-----------|-------------|
|
|
| Lean QUBOFormulation → Python QUBO | Lean ↔ Python | **Critical** — Q16_16 conversion mismatch |
|
|
| Python QUBO → HiGHS MIP | Python ↔ C++ | Medium — optional dependency |
|
|
| HiGHS solution → receipt | Python → JSON | Low |
|
|
|
|
**Gap:** The `qaoa_adapter.py` imports from `braid_search` which may not be available, and the fallback `_fallback_bracket_qubo` uses different coefficients than the original. This means QUBO results depend on which modules are importable, not just the input data.
|
|
|
|
---
|
|
|
|
### Pipeline D: C Kernel → Sysfs → Userspace Daemon
|
|
|
|
**Files:** `pist_compress.c` / `pist_neuromorphic.c` → `/sys/kernel/pist*/` → (daemon implied)
|
|
|
|
| Step | Output | Handoff Risk |
|
|
|------|--------|-------------|
|
|
| Kernel module → sysfs | text/binary | **Medium** — stats_show is destructive |
|
|
| sysfs → userspace | (not implemented) | **High** — no daemon in repo |
|
|
|
|
**Gap:** There is NO userspace daemon in the repository that reads from `/sys/kernel/pist_neuromorphic/dag_dump`. The `dag_generation` counter increments but nothing consumes it. The DAG export functionality is incomplete.
|
|
|
|
---
|
|
|
|
### Pipeline E: Lean Static Build → FPGA Bitstream
|
|
|
|
**Files:** `build_static.sh` → `lake exe tangnano9k_emitter` → Verilog → FPGA
|
|
|
|
| Step | Output | Handoff Risk |
|
|
|------|--------|-------------|
|
|
| Lean → C → static binary | ELF | Medium — hardcoded executable list |
|
|
| Static binary → Verilog | `.v` files | Medium — `lake exe` may fail silently |
|
|
| Verilog → FPGA bitstream | `.bit` | **High** — no CI for this path |
|
|
|
|
**Gap:** The `build_static.sh` script references `5-Applications/out/verilog/build_tangnano9k.sh` which may not exist in all environments. The FPGA synthesis path has no CI coverage.
|
|
|
|
---
|
|
|
|
## Type Mismatch Matrix
|
|
|
|
| Type | Lean Definition | Python Implementation | C Implementation | Consistent? |
|
|
|------|----------------|----------------------|------------------|-------------|
|
|
| Q16_16 scale | `65536` (`q16Scale`) | `65536` (`Q16_SCALE`) | `1 << 16` = 65536 | YES |
|
|
| Q16_16 float→raw | `(f * 65536.0).floor` | `int(round(v * 65536))` | `(int32_t)(f * 65536)` | **NO** |
|
|
| Q16_16 raw→float | `Float.ofInt q.toInt / 65536.0` | `value / 65536` | `(float)q / 65536` | YES |
|
|
| Q16_16 NaN sentinel | `infinity` = `q16MaxRaw` | None | None | **NO** |
|
|
| Q16_16 overflow | Saturates to `maxVal`/`minVal` | No saturation check | No saturation check | **NO** |
|
|
| Sidon set | `[1, 2, 4, 8, 16, 32, 64, 128]` | Same (Python) | Not in C | N/A |
|
|
| JSON Q16_16 | `{"val": <int>}` | Raw int | Not used | **NO** |
|
|
|
|
---
|
|
|
|
## Generated Files Status
|
|
|
|
| File | Generated By | Checked In? | Should Be? |
|
|
|------|-------------|-------------|------------|
|
|
| `CERNEigensolidData.lean` | `eigensolid_pipeline.py` | Likely NO | NO (regenerate in CI) |
|
|
| `eigensolid_analysis.json` | `eigensolid_pipeline.py` | Likely NO | NO (CI artifact) |
|
|
| `shared-data/data/stack_solidification/*.json` | Various shims | Partially YES | YES (receipts) |
|
|
| `4-Infrastructure/shim/burgers_chaos_game_receipt.json` | `burgers_chaos_game.py` | YES | YES (example receipt) |
|
|
| `4-Infrastructure/shim/eigensolid_analysis/` | `eigensolid_pipeline.py` | Unknown | NO (CI output) |
|
|
| `.lake/build/bin/*` | `lake build` | NO (gitignored) | NO (build output) |
|
|
|
|
**Note:** The repository contains some checked-in receipts (`shared-data/data/stack_solidification/*.json`) but the generation pipeline for these is not documented in CI. This creates a risk that checked-in receipts are stale relative to the generating code.
|
|
|
|
---
|
|
|
|
## CI Workflow Gaps
|
|
|
|
| Workflow | Tests Lean Build? | Tests Q16_16 Roundtrip? | Tests Kernel Module? | Tests Receipt Integrity? |
|
|
|----------|------------------|------------------------|---------------------|------------------------|
|
|
| `math-check.yml` | NO | NO | NO | YES (SHA-256) |
|
|
| `wolfram-verification.yml` | NO (only comments) | NO | NO | NO |
|
|
| `batch_compute.yml` | NO | NO | NO | NO |
|
|
| `lean_action_ci.yml` | YES (OTOM subproject) | NO | NO | NO |
|
|
|
|
**Gap:** No CI workflow tests the full roundtrip: Lean Q16_16 → JSON → Python → C → back to Lean. A dedicated integration test should:
|
|
1. Generate Q16_16 values in Lean
|
|
2. Export via `BindServer` JSON
|
|
3. Parse in Python with `q16.py`
|
|
4. Serialize via `manifold_binary.h` format
|
|
5. Deserialize in C
|
|
6. Roundtrip back to Lean
|
|
7. Verify bit-exact equality
|
|
|
|
---
|
|
|
|
## Recommendations (Priority Order)
|
|
|
|
1. **Unify Q16_16 conversion**: Standardize on `floor` semantics across all three languages. Add a conformance test.
|
|
2. **Deduplicate q16.py**: Remove the `auto/lib/` copy or make it re-export from `lib/`.
|
|
3. **Add NaN/error propagation**: Use JSON `{"error": "overflow"}` instead of 0xFFFFFFFF sentinel.
|
|
4. **Build generated Lean in CI**: Add `lake build` step for all generated `.lean` files. Reject `sorry`.
|
|
5. **Fix destructive stats_show**: Copy frequency array before formatting in `pist_neuromorphic.c`.
|
|
6. **Add schema validation**: Validate extraction JSON against a schema before processing.
|
|
7. **Complete the kernel userspace bridge**: Implement or document the DAG consumer daemon.
|
|
8. **Add roundtrip integration test**: Test the full Lean→Python→C→Lean data flow in CI.
|