Skip to content

Commit 6b58e17

Browse files
proof: discharge proof-obligation map Tiers 0–3 (#84) (#106)
## Proof-obligation map (#84) — Tiers 0–3, batched Full lowest-tier-first. Entire workspace: `cargo clippy --workspace --all-targets` clean, `cargo test --workspace` all green. ### Tier 0 — foundations - **0.1 panic-freedom (#86)** — 6 operational `unwrap`/`expect` removed; `cfg_attr(not(test), deny(clippy::unwrap_used, expect_used))` on every crate. - **0.2 numeric containment (#87)** — proptest no-NaN/Inf for `esn::step`, `lsm::step`, sensors IIR. - **0.3 unsafe discipline** — `deny`/`forbid` (on main). ### Tier 1 — core algorithmic correctness - **1.1 Echo State Property (#88)** — true spectral radius via power iteration (merged in #101). - **1.2 LSM bounded dynamics (#89)** — same spectral-radius fix in lsm + membrane/spike-history bounds proptest. - **1.3 bridge soundness (#90)** — totality / determinism / bounded-output proptest. ### Tier 2 — system orchestration - **2.1 lifecycle (#91)** — compile-time **typestate** (`Created→Active→Down`, terminal shutdown); illegal transitions don't compile. Matches `proofs/tla/Lifecycle.tla`. - **2.2 concurrency (#92)** — no-lost-updates stress test (8×250); data-race & deadlock freedom argued from safe-Rust + single-lock. - **2.3 resource/affine (#93)** — design spec (`proofs/affine/`); Rust ownership gives acquire-release-once today, AffineScript linear handles deferred. ### Tier 3 — trust boundary - **3.1 data-egress (#94)** — egress allow-list test (API key stays a header; no device/sensor fields in body) + neural-context-not-sent-when-disabled. - **3.2 bounded external interaction (#95)** — saturating/capped backoff (fixes a latent `pow` overflow); injection-safety via typed JSON. Closes #86 #87 #89 #90 #91 #92 #94 #95 (1.1/#88 already merged via #101; 2.3/#93 remains a tracked spec). _The two Kotlin banned-language CI checks are red from `main`'s `android/` app (tracked in #83), not from this PR._ https://claude.ai/code/session_01Gu1JFCZHuBtBhAWPr4sMQw --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 78013d5 commit 6b58e17

20 files changed

Lines changed: 674 additions & 259 deletions

File tree

.machine_readable/agent_instructions/methodology.a2ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ ring-ceiling = 2 # Hard ceiling for ring expansion (0-3)
2525
wave-cap = 2 # Max waves before requiring user "keep going"
2626
spike-required = true # Every session must ship code, not just designs
2727

28+
# ============================================================================
29+
# WORK ORDERING (ALWAYS)
30+
# ============================================================================
31+
# Complete the FULL lowest tier before moving up. General precedence:
32+
# lowest-tier (complete) -> proximal seam -> distal themes -> current focus -> other
33+
# For tiered backlogs (e.g. proof obligations): finish all of Tier 0, then all of
34+
# Tier 1, then Tier 2, then Tier 3, then other work. Never open a higher tier
35+
# while a lower tier still has open items.
36+
37+
[methodology.work-ordering]
38+
rule = "full-lowest-tier-first"
39+
order = ["lowest-tier-complete", "proximal-seam", "distal-themes", "current-focus", "other"]
40+
2841
# ============================================================================
2942
# PRIORITY WEIGHTS
3043
# ============================================================================

Cargo.lock

Lines changed: 14 additions & 61 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bridge/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! natural-language description suitable for prompt injection into an LLM.
77
88
#![forbid(unsafe_code)]
9+
#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::expect_used))]
910

1011
use ndarray::{Array1, ArrayView1};
1112
use serde::{Deserialize, Serialize};
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// SPDX-FileCopyrightText: 2025 Jonathan D.A. Jewell
3+
//! Property tests — bridge soundness (obligation 1.3, #90).
4+
//!
5+
//! The neural->symbolic encoder must be:
6+
//! * total — defined on all finite inputs (any/empty/mismatched lengths), no panic;
7+
//! * deterministic — identical input sequences yield identical outputs (incl. the
8+
//! history-dependent urgency term);
9+
//! * well-formed — salience, urgency in [0,1] and finite; active counts never
10+
//! exceed the input lengths; description never empty.
11+
12+
use bridge::{Bridge, BridgeConfig};
13+
use ndarray::Array1;
14+
use proptest::prelude::*;
15+
16+
proptest! {
17+
#[test]
18+
fn bridge_encode_deterministic_and_bounded(
19+
seq in proptest::collection::vec(
20+
(
21+
proptest::collection::vec(-1.0e3f32..1.0e3f32, 0..48),
22+
proptest::collection::vec(-1.0e3f32..1.0e3f32, 0..48),
23+
),
24+
1..40)
25+
) {
26+
let mut b1 = Bridge::new(BridgeConfig::default()).unwrap();
27+
let mut b2 = Bridge::new(BridgeConfig::default()).unwrap();
28+
29+
for (lv, ev) in seq {
30+
let lsm = Array1::from_vec(lv);
31+
let esn = Array1::from_vec(ev);
32+
33+
let c1 = b1.encode(lsm.view(), esn.view());
34+
let c2 = b2.encode(lsm.view(), esn.view());
35+
36+
// Determinism (including the last_lsm-dependent urgency).
37+
prop_assert_eq!(&c1, &c2);
38+
39+
// Well-formed, bounded outputs.
40+
prop_assert!(c1.salience.is_finite() && (0.0..=1.0).contains(&c1.salience));
41+
prop_assert!(c1.urgency.is_finite() && (0.0..=1.0).contains(&c1.urgency));
42+
prop_assert!(c1.lsm_active <= lsm.len());
43+
prop_assert!(c1.esn_active <= esn.len());
44+
prop_assert!(!c1.description.is_empty());
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)