Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ permissions:
contents: read

jobs:
test:
python:
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
Expand All @@ -24,3 +24,15 @@ jobs:
- run: python -m mnel demo --workspace build/demo
- run: python -m mnel ledger verify build/demo/evidence.jsonl
- run: git diff --check

rust-provider-runtime:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@1.79.0
with:
components: rustfmt, clippy
- run: cargo fmt --all --check
- run: cargo clippy --workspace --all-targets -- -D warnings
- run: cargo test --workspace
- run: git diff --check
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,13 @@
boosted-tree, hidden-state, and reservoir architectures.
- Add learned-provider CLI inspection, JSON schema, catalog example, architecture and
roadmap documentation, and negative tests.
- Establish Rust as the default production language for learned micro-provider hosting,
dispatch, SDKs, and CPU-first provider implementations while retaining Python for
training, calibration, experimentation, and high-level orchestration.
- Add accepted ADR 0001, the learned-provider runtime specification, and an explicit
evidence-backed exception path for specialized non-Rust native implementations.
- Add a versioned allocation-neutral C ABI, matching public header, safe Rust SDK,
persistent-host admission policy, reusable snapshot cache, and runtime manifest schema.
- Add Python runtime-manifest validation, a checked-in example, negative tests, and Rust
formatting, Clippy, and test jobs in CI.
- Add schema, deterministic reference workflow, tests, CI, documentation, and roadmap.
27 changes: 27 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[workspace]
members = [
"crates/mnel-provider-api",
"crates/mnel-provider-sdk",
"crates/mnel-provider-host",
]
resolver = "2"

[workspace.package]
version = "0.1.0-alpha.0"
edition = "2021"
rust-version = "1.79"
license = "Apache-2.0"
repository = "https://github.com/epi13/Machine-Native-Experimental-Learning"

[workspace.lints.rust]
unsafe_code = "deny"

[workspace.lints.clippy]
expect_used = "deny"
unwrap_used = "deny"

[profile.release]
lto = "thin"
codegen-units = 1
strip = "symbols"
panic = "abort"
53 changes: 42 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,9 @@ conventional neural-weight training.
> **Current status:** functional `0.1.0a0` foundation. The repository implements the
> core local lifecycle, deterministic evidence ledger, hard-gate evaluator, recursion
> governor, investigator contracts, a diagnostic-only learned micro-provider registry,
> distillation proposal checks, reference adapters, command-line interface, schemas,
> tests, and CI. It does not yet train or execute learned micro-providers, provide
> unattended model execution, distributed scheduling, protected final custody, formal
> MNCS/MNCDS conformance, or automatic RAVEL promotion.
> and a testable Rust-first provider runtime contract. It does not yet train or execute
> learned micro-providers, provide unattended model execution, distributed scheduling,
> protected final custody, formal MNCS/MNCDS conformance, or automatic RAVEL promotion.

## Core rule

Expand Down Expand Up @@ -84,6 +83,9 @@ copy their authority or silently create substitute implementations.
- typed learned micro-provider declarations and diagnostic observations;
- deterministic capability matching, cost filtering, and diversity-aware selection;
- an initial 12-family architecture catalog with declared advantages and limitations;
- accepted Rust-first runtime architecture decision and versioned C ABI;
- safe Rust provider SDK, host admission policy, reusable snapshot cache, and runtime
manifest validation;
- deterministic reference workflow, JSON schemas, mutation-oriented tests, and CI.

## Install
Expand All @@ -94,8 +96,9 @@ source .venv/bin/activate
python -m pip install -e .
```

MNEL currently requires Python 3.11 or newer and has no runtime dependencies outside
the standard library.
MNEL currently requires Python 3.11 or newer and has no Python runtime dependencies
outside the standard library. Building the provider runtime contracts additionally
requires Rust 1.79 or newer.

## Quick start

Expand Down Expand Up @@ -181,6 +184,23 @@ investigator decide which bounded Forge question to ask next.

See [Learned micro-provider registry](docs/LEARNED_MICRO_PROVIDERS.md).

## Provider runtime implementation policy

Rust is the reference and default production language for the persistent provider host,
provider SDK, dispatch, budget enforcement, snapshot reuse, and CPU-first provider
implementations. Python remains the training, calibration, experimentation, export, and
high-level orchestration language.

The stable cross-language boundary is `mnel-provider-c-abi/1`. Native-trusted providers
must be Rust unless an identified benchmark and threat review justify a specialized
non-Rust implementation. WASM is reserved as a quarantine and portability tier.
Admitted providers are persistent, weight-resident, and consume identity-bound compact
binary snapshot views; process startup and JSON parsing are not part of the normal hot
path.

See [ADR 0001](docs/decisions/0001-rust-provider-runtime.md) and the
[learned-provider runtime contract](docs/LEARNED_PROVIDER_RUNTIME.md).

## Investigator roles

- **Investigator** — proposes falsifiable hypotheses and bounded interventions.
Expand Down Expand Up @@ -216,13 +236,17 @@ state, and failure modes.
## Repository map

```text
src/mnel/ executable standard-library foundation
src/mnel/ Python control plane and executable foundation
crates/mnel-provider-api/ versioned provider ABI vocabulary
crates/mnel-provider-sdk/ safe Rust provider authoring surface
crates/mnel-provider-host/ admission policy and reusable snapshot storage
include/ language-neutral provider ABI header
schemas/ machine-readable record vocabulary
docs/ architecture, method, boundaries, and roadmap
docs/ architecture, decisions, method, boundaries, roadmap
examples/reference-study/ deterministic lifecycle example
examples/learned-providers/ initial architecture catalog summary
tests/ lifecycle, integrity, registry, and negative tests
.github/workflows/ continuous verification
examples/learned-providers/ architecture catalog and runtime manifest example
tests/ lifecycle, integrity, registry, runtime, negative tests
.github/workflows/ Python and Rust continuous verification
```

## Run the checks
Expand All @@ -233,6 +257,9 @@ python -m unittest discover -s tests -v
python -m mnel learned-provider list
python -m mnel demo --workspace build/demo
python -m mnel ledger verify build/demo/evidence.jsonl
cargo fmt --all --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
```

## Safety and claim boundary
Expand All @@ -242,11 +269,15 @@ operating-system sandbox. Untrusted experiment execution belongs in a hardened r
with network restrictions, resource controls, immutable verifiers, and disposable
workspaces.

The provider runtime crates establish contracts and admission policy; they do not yet
implement a hardened dynamic loader or operating-system sandbox.

A local MNEL result or learned-provider observation can describe bounded development
context. It cannot by itself establish independent evaluation, protected custody,
real-world safety, general recursive self-improvement, formal MNCS/MNCDS status,
certification, or promotion.

See [Architecture](docs/ARCHITECTURE.md), [Learning model](docs/LEARNING_MODEL.md),
[Learned micro-providers](docs/LEARNED_MICRO_PROVIDERS.md),
[learned-provider runtime](docs/LEARNED_PROVIDER_RUNTIME.md),
[Threat model](docs/THREAT_MODEL.md), and [Roadmap](docs/ROADMAP.md).
11 changes: 11 additions & 0 deletions crates/mnel-provider-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "mnel-provider-api"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Versioned ABI types for MNEL learned micro-providers"

[lints]
workspace = true
153 changes: 153 additions & 0 deletions crates/mnel-provider-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
//! Stable, allocation-neutral ABI vocabulary for diagnostic-only learned providers.
//!
//! The ABI intentionally contains no evaluator verdict, conformance, promotion, or
//! acceptance field. Provider output is diagnostic context only.

use core::ffi::c_void;

pub const ABI_VERSION_V1: u32 = 1;
pub const ENTRY_SYMBOL_V1: &str = "mnel_provider_entry_v1";
pub const AUTHORITY_DIAGNOSTIC_ONLY: u32 = 1;
pub const VERDICT_SEMANTICS_NOT_A_VERDICT: u32 = 1;

#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Digest32 {
pub bytes: [u8; 32],
}

impl Digest32 {
pub const ZERO: Self = Self { bytes: [0; 32] };
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ByteView {
pub data: *const u8,
pub len: usize,
}

impl ByteView {
pub const EMPTY: Self = Self {
data: core::ptr::null(),
len: 0,
};
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct MutableByteBuffer {
pub data: *mut u8,
pub capacity: usize,
pub len: usize,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ResourceBudgetV1 {
pub wall_time_ns: u64,
pub operation_limit: u64,
pub memory_bytes: u64,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct SnapshotViewV1 {
pub schema_version: u32,
pub reserved: u32,
pub snapshot_identity: Digest32,
pub feature_extractor_identity: Digest32,
pub payload: ByteView,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ProviderQueryV1 {
pub abi_version: u32,
pub reserved: u32,
pub declaration_identity: Digest32,
pub model_identity: Digest32,
pub calibration_identity: Digest32,
pub query_identity: Digest32,
pub snapshots: *const SnapshotViewV1,
pub snapshot_count: usize,
pub budget: ResourceBudgetV1,
}

pub type ProviderStatusV1 = u32;
pub const PROVIDER_STATUS_COMPLETED: ProviderStatusV1 = 0;
pub const PROVIDER_STATUS_ABSTAINED: ProviderStatusV1 = 1;
pub const PROVIDER_STATUS_INVALID_INPUT: ProviderStatusV1 = 2;
pub const PROVIDER_STATUS_BUDGET_EXCEEDED: ProviderStatusV1 = 3;
pub const PROVIDER_STATUS_OUT_OF_DISTRIBUTION: ProviderStatusV1 = 4;
pub const PROVIDER_STATUS_RUNTIME_ERROR: ProviderStatusV1 = 5;

pub type OutputKindV1 = u32;
pub const OUTPUT_LATENT_DISCREPANCY: OutputKindV1 = 1;
pub const OUTPUT_STRUCTURAL_DISCREPANCY: OutputKindV1 = 2;
pub const OUTPUT_ANOMALY_SCORE: OutputKindV1 = 3;
pub const OUTPUT_PAIR_SIMILARITY: OutputKindV1 = 4;
pub const OUTPUT_NEXT_STATE_DISTRIBUTION: OutputKindV1 = 5;
pub const OUTPUT_FEATURE_CONTRIBUTIONS: OutputKindV1 = 6;
pub const OUTPUT_CANDIDATE_RANKING: OutputKindV1 = 7;

pub const RESULT_FLAG_OUT_OF_DISTRIBUTION: u64 = 1 << 0;
pub const RESULT_FLAG_CALIBRATION_REQUIRED: u64 = 1 << 1;
pub const RESULT_FLAG_TRUNCATED_PAYLOAD: u64 = 1 << 2;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct ProviderResultV1 {
pub abi_version: u32,
pub status: ProviderStatusV1,
pub output_kind: OutputKindV1,
pub calibration_band: u32,
pub scalar_value: f64,
pub flags: u64,
pub observation_payload: MutableByteBuffer,
pub authority: u32,
pub verdict_semantics: u32,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub struct ProviderDescriptorV1 {
pub abi_version: u32,
pub reserved: u32,
pub provider_id: ByteView,
pub provider_version: ByteView,
pub declaration_identity: Digest32,
pub implementation_context: *mut c_void,
pub infer: Option<ProviderInferV1>,
}

pub type ProviderInferV1 = extern "C" fn(
context: *mut c_void,
query: *const ProviderQueryV1,
result: *mut ProviderResultV1,
) -> i32;

pub type ProviderEntryV1 = extern "C" fn() -> *const ProviderDescriptorV1;

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn diagnostic_authority_is_fixed_and_distinct() {
assert_ne!(AUTHORITY_DIAGNOSTIC_ONLY, 0);
assert_ne!(VERDICT_SEMANTICS_NOT_A_VERDICT, 0);
}

#[test]
fn abi_types_are_c_compatible_and_nonzero_sized() {
assert!(core::mem::size_of::<ProviderQueryV1>() > 0);
assert!(core::mem::size_of::<ProviderResultV1>() > 0);
assert!(core::mem::align_of::<ProviderQueryV1>() >= core::mem::align_of::<u64>());
}

#[test]
fn entry_symbol_is_versioned() {
assert_eq!(ENTRY_SYMBOL_V1, "mnel_provider_entry_v1");
}
}
14 changes: 14 additions & 0 deletions crates/mnel-provider-host/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "mnel-provider-host"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
repository.workspace = true
description = "Persistent policy host for MNEL learned micro-providers"

[dependencies]
mnel-provider-api = { path = "../mnel-provider-api" }

[lints]
workspace = true
Loading
Loading