Five concrete deliverables absorbing patterns from the day's research
(Hermes Desktop, turbovec, Axiom Math, Valkey/Madelyn Olson, Jerry Liu)
into the JouleClaw substrate. Each lands in an existing or new crate
without rearchitecting; all pure-Rust, no external runtime deps;
composable with the triangle just shipped.
1. jouleclaw-context-store (new crate) — typed deterministic recall.
- TurnStore: SQLite + FTS5 over agent/CLI/chat turns. ~20ms per
query at zero LLM cost. Microjoule-class recall as a first-class
primitive between L0 cache and L2 embedding+retrieval.
- FrozenSnapshot + StagedSnapshot: bounded byte-budget memory +
user blocks. Mutations don't surface mid-session — they persist
immediately but only the next session loads them. Rationale:
keep the LLM prefix-cache warm. The byte block at the top of
every prompt in a session is byte-identical, so providers can
amortize attention over it.
- 12 tests, all green. Ingested from Hermes Agent's documented
memory pattern.
2. jouleclaw-oracle-fuzz (new crate) — adversarial Oracle backend.
- FuzzOracle<P>: implements jouleclaw-oracle::Oracle over a
caller-supplied deterministic FuzzProperty. Seeds ChaCha20 with
(seed, round) to produce reproducible inputs; short-circuits on
first counterexample with the structured FuzzFailure carried in
FailReason::Custom.
- Composes via CompositeOracle alongside type-checkers / linters /
a future Lean Oracle.
- 6 tests including determinism (same seed → byte-equal verdict)
and composition. Ingested from the OSS-maintainer crash-harness
pattern (Valkey CVE hunt).
3. jouleclaw-cone — cone-gated context injection.
- cone_gated_inject helper + InjectDecision { Full | Skip } enum.
Catalog (skills / tools / memory) is injected ONLY when the
request's novelty crosses a configured threshold; below it, the
agent uses cheap on-demand lookup tools instead of paying the
unconditional prompt-token cost.
- 4 new tests on top of the existing 23. Ingested from Hermes's
own issue #4379 documenting catalog-injection token bloat.
4. jouleclaw-jcr1 — verified-code/1 receipt schema.
- VerifiedCodeReceipt + ProgramRef + SpecRef + ProofRef
{ Lean | Fuzz | TestSuite } + VerifierRef + VerifiedCodeVerdict
{ Pass | Fail }. Canonical JSON with sorted keys; content-
addressed via BLAKE3; ready for COSE_Sign1 over the canonical
bytes via the existing v1 signing path.
- 2 conformance vectors (Lean Pass + Fuzz Fail) with embedded
content_hash that the Rust verifier asserts byte-equal at test
time. Other-language verifiers MUST round-trip under canonical
encoding and match the hash.
- 5 verified_code tests. Ingested from the Axiom Math /
"code-with-proof" pattern (Verina benchmark).
5. Demo binary — examples/wave46_recall_fuzz_verified.rs in
jouleclaw-stack. Runs all five primitives end-to-end in one
cargo run: seed FTS5 store, search, build + freeze snapshot, gate
catalog injection by cone novelty, run fuzz Oracle over a property
in two directions (pass + fail), mint a verified-code/1 receipt
over the pass. Output is reproducible and self-checking.
The triangle is the type system; these five are concrete backends +
schemas + helpers that fill load-bearing slots the triangle types up
but leaves to consumers. None of them invalidate prior waves; each
sits beneath inference per doctrine.
Workspace check clean.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
214 lines
8.8 KiB
Rust
214 lines
8.8 KiB
Rust
//! `wave46_recall_fuzz_verified` — the wave-46 ingest demo.
|
|
//!
|
|
//! Wires the five new primitives shipped this wave into one runnable
|
|
//! pipeline:
|
|
//!
|
|
//! 1. **Context store** ([`jouleclaw_context_store`]) — seed an FTS5
|
|
//! turn store with a few previous sessions; show that recall over
|
|
//! them is microjoule-class with no LLM call.
|
|
//! 2. **Frozen snapshot** — build a bounded memory + user block; show
|
|
//! that staged mutations don't surface in the current session
|
|
//! (the prefix-cache stays warm).
|
|
//! 3. **Cone-gated injection** ([`jouleclaw_cone::cone_gated_inject`])
|
|
//! — for a low-novelty request, the skills catalog is SKIPPED
|
|
//! (the agent uses on-demand lookup instead of paying the prompt-
|
|
//! token cost); for a high-novelty request, it's INJECTED.
|
|
//! 4. **Fuzz Oracle** ([`jouleclaw_oracle_fuzz::FuzzOracle`]) — run a
|
|
//! deterministic property over 256 seeded inputs; on pass, mint a
|
|
//! `verified-code/1` JCR-1 receipt; on fail, mint the same with a
|
|
//! counterexample.
|
|
//! 5. **JCR-1 receipt** ([`jouleclaw_jcr1::VerifiedCodeReceipt`]) —
|
|
//! canonical JSON, content-addressed, ready for the steward to
|
|
//! sign.
|
|
//!
|
|
//! Run:
|
|
//! cargo run -p jouleclaw-stack --example wave46_recall_fuzz_verified
|
|
|
|
use jouleclaw_context_store::{
|
|
DEFAULT_MEMORY_BUDGET_BYTES, DEFAULT_USER_BUDGET_BYTES, FrozenSnapshot, StagedSnapshot,
|
|
TurnRecord, TurnStore,
|
|
};
|
|
use jouleclaw_cone::{BandDispatch, ConeCoord, NoveltyBand, cone_gated_inject};
|
|
use jouleclaw_oracle::{Candidate, Oracle};
|
|
use jouleclaw_oracle_fuzz::{FuzzOracle, FuzzProperty};
|
|
use jouleclaw_jcr1::{
|
|
ProgramRef, ProofRef, SpecRef, VerifiedCodeReceipt, VerifierRef,
|
|
};
|
|
|
|
const CLOSED_AT: &str = "2026-06-05T00:00:00Z";
|
|
const STEWARD: &str = "did:keri:EJ9testStewardAID000000000000000";
|
|
|
|
/// A property: the candidate's content (interpreted as Rust source)
|
|
/// never contains the substring `"unsafe"`. The fuzz inputs are
|
|
/// ignored — this is a property of the candidate, not of inputs.
|
|
/// (Real callers parameterize on inputs; we keep this tight for the
|
|
/// demo.)
|
|
struct NoUnsafe;
|
|
impl FuzzProperty for NoUnsafe {
|
|
fn id(&self) -> &str {
|
|
"no-unsafe"
|
|
}
|
|
fn check(&self, candidate: &Candidate, _input: &[u8]) -> Result<(), String> {
|
|
if candidate.content.contains("unsafe") {
|
|
Err("candidate contains `unsafe`".into())
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::main(flavor = "current_thread")]
|
|
async fn main() {
|
|
// ── 1. Context store: FTS5 over prior session turns ────────────
|
|
println!("== 1. Context store (FTS5 turn search) ==");
|
|
let store = TurnStore::in_memory().expect("open store");
|
|
for (role, text, ts) in [
|
|
("user", "yesterday we discussed prefix-cache preservation", 100),
|
|
("agent", "the frozen-snapshot pattern keeps the prompt block byte-stable", 101),
|
|
("user", "and the FTS5 search over sessions is microjoules", 102),
|
|
("user", "what was the magic word from last week?", 103),
|
|
("agent", "the magic word, as previously discussed, is `please`", 104),
|
|
] {
|
|
store
|
|
.record(&TurnRecord {
|
|
session_id: "session-1".into(),
|
|
role: role.into(),
|
|
content: text.into(),
|
|
ts_unix_secs: ts,
|
|
})
|
|
.expect("record");
|
|
}
|
|
let hits = store.search("magic word", 3).expect("search");
|
|
println!(" query=\"magic word\" hits={}", hits.len());
|
|
for h in &hits {
|
|
println!(" [{:.3}] {} > {}", h.score, h.turn.role, h.turn.content);
|
|
}
|
|
println!();
|
|
|
|
// ── 2. Frozen snapshot: bounded, prefix-cache-stable ───────────
|
|
println!("== 2. Frozen snapshot (bounded; mutations deferred) ==");
|
|
let base = FrozenSnapshot::build(
|
|
"Working on JouleClaw wave-46 ingest from Hermes / Axiom / Valkey research.",
|
|
"David — Founder of openIE / Transaction Science. Prefers terse honest engineering.",
|
|
DEFAULT_MEMORY_BUDGET_BYTES,
|
|
DEFAULT_USER_BUDGET_BYTES,
|
|
)
|
|
.expect("build snapshot");
|
|
println!(" base hash: {}", &base.hash[..16]);
|
|
println!(" base block bytes: {}", base.frozen_block().len());
|
|
|
|
let mut staged = StagedSnapshot::from_base(base.clone());
|
|
staged
|
|
.stage_memory("(updated) wave-46 shipped: context-store, oracle-fuzz, cone-gated.")
|
|
.stage_user(
|
|
"David — Founder of openIE / Transaction Science. Prefers terse honest engineering.",
|
|
);
|
|
// Current session STILL sees the base block — staged mutations
|
|
// don't surface, by design. The LLM's prefix cache hash stays
|
|
// identical across the whole session.
|
|
assert_eq!(staged.current_block(), base.frozen_block());
|
|
println!(" current-session block UNCHANGED — prefix cache preserved.");
|
|
|
|
let next = staged
|
|
.freeze(DEFAULT_MEMORY_BUDGET_BYTES, DEFAULT_USER_BUDGET_BYTES)
|
|
.expect("freeze");
|
|
println!(" next-session hash: {}", &next.hash[..16]);
|
|
println!(" (mutations surface only when the next session loads it)\n");
|
|
|
|
// ── 3. Cone-gated catalog injection ────────────────────────────
|
|
println!("== 3. Cone-gated catalog injection ==");
|
|
let dispatch = BandDispatch::new(NoveltyBand::datum_default()).expect("valid band");
|
|
// Low-novelty: catalog SKIPPED, agent uses on-demand lookup.
|
|
let low = ConeCoord::new(0.1, 0.1);
|
|
let dec_low = cone_gated_inject(&dispatch, low, 0.5, "skills");
|
|
println!(
|
|
" low-novelty (n=0.10) → {} (tier={})",
|
|
if dec_low.should_inject() { "INJECT" } else { "SKIP" },
|
|
dec_low.tier_id()
|
|
);
|
|
// High-novelty: catalog INJECTED.
|
|
let high = ConeCoord::new(0.5, 0.9);
|
|
let dec_high = cone_gated_inject(&dispatch, high, 0.5, "skills");
|
|
println!(
|
|
" high-novelty (n=0.90) → {} (tier={})",
|
|
if dec_high.should_inject() { "INJECT" } else { "SKIP" },
|
|
dec_high.tier_id()
|
|
);
|
|
println!();
|
|
|
|
// ── 4. Fuzz Oracle over a deterministic property ──────────────
|
|
println!("== 4. Adversarial fuzz Oracle ==");
|
|
let safe_candidate = Candidate {
|
|
id: "safe-1".into(),
|
|
content: "fn add(a: i32, b: i32) -> i32 { a + b }".into(),
|
|
language: "rust".into(),
|
|
source_tier: "lut".into(),
|
|
provenance: "demo".into(),
|
|
};
|
|
let oracle = FuzzOracle::smoke("fuzz/no-unsafe", NoUnsafe);
|
|
let v_pass = oracle.verify(&safe_candidate).await.expect("oracle");
|
|
println!(" safe candidate verdict: {}", verdict_tag(&v_pass));
|
|
|
|
let unsafe_candidate = Candidate {
|
|
id: "unsafe-1".into(),
|
|
content: "fn raw() { unsafe { *(0 as *mut u8) = 0 } }".into(),
|
|
language: "rust".into(),
|
|
source_tier: "lut".into(),
|
|
provenance: "demo".into(),
|
|
};
|
|
let v_fail = oracle.verify(&unsafe_candidate).await.expect("oracle");
|
|
println!(" unsafe candidate verdict: {}", verdict_tag(&v_fail));
|
|
println!();
|
|
|
|
// ── 5. Mint a verified-code/1 JCR-1 receipt over the pass ─────
|
|
println!("== 5. verified-code/1 JCR-1 receipt ==");
|
|
let program = ProgramRef {
|
|
language: "rust".into(),
|
|
content_hash: hex_blake3(safe_candidate.content.as_bytes()),
|
|
byte_length: safe_candidate.content.len() as u64,
|
|
};
|
|
let spec = SpecRef {
|
|
content_hash: hex_blake3(b"no `unsafe` in candidate"),
|
|
summary: "no `unsafe` in candidate".into(),
|
|
};
|
|
let proof = ProofRef::Fuzz {
|
|
property_id: "no-unsafe".into(),
|
|
seed: 0,
|
|
rounds: 256,
|
|
};
|
|
let verifier = VerifierRef {
|
|
id: "jouleclaw-oracle-fuzz".into(),
|
|
version: env!("CARGO_PKG_VERSION").into(),
|
|
};
|
|
let receipt = VerifiedCodeReceipt::pass(
|
|
"vcr-wave46-0001",
|
|
CLOSED_AT,
|
|
STEWARD,
|
|
program,
|
|
spec,
|
|
proof,
|
|
verifier,
|
|
vec!["fuzz/no-unsafe".into(), "no-unsafe".into()],
|
|
);
|
|
let canonical = receipt.canonical_bytes().expect("canonical");
|
|
let hash = receipt.content_hash().expect("hash");
|
|
println!(" schema: verified-code/1");
|
|
println!(" receipt id: {}", receipt.id);
|
|
println!(" canonical: {} bytes", canonical.len());
|
|
println!(" content hash: {hash}");
|
|
println!(" (this is the payload the steward signs; verifiers re-canonicalize and check)");
|
|
println!();
|
|
println!("✓ Wave-46 substrate works end-to-end:");
|
|
println!(" FTS5 turn recall → frozen snapshot → cone-gated → fuzz Oracle → JCR-1 receipt");
|
|
}
|
|
|
|
fn verdict_tag(v: &jouleclaw_oracle::Verdict) -> &'static str {
|
|
match v {
|
|
jouleclaw_oracle::Verdict::Pass { .. } => "PASS",
|
|
jouleclaw_oracle::Verdict::Fail { .. } => "FAIL",
|
|
}
|
|
}
|
|
|
|
fn hex_blake3(bytes: &[u8]) -> String {
|
|
blake3::hash(bytes).to_hex().to_string()
|
|
}
|