refactor(salience_gate): Phase B language-advantage pass — dichotomy wave

Genuine Rust-side advantages over the Python oracle shape (parity pinned
by the frozen battery — 12/12, replay 119/119, shared verify
byte-identical):
  * lower_for_match: ASCII-anchored Cow — already-lowercase gate texts (the
    common case) match with ZERO allocation; non-ASCII/uppercase takes the
    full Python-parity to_lowercase() path so Unicode case mappings (İ, ẛ)
    are never skipped (borrow predicate is ASCII-only BY CONSTRUCTION).
  * std-only hot-path bench in branch_battery: evaluate_decision over the
    56-envelope frozen corpus + word_boundary_contains micro (evidence:
    verification/salience-gate-phaseb-cargotest.log).
  * #[must_use] on the pure surface (evaluate_decision, evaluate_salience,
    evaluate_salience_dict, to_dict, handle_hook, _sg_core).
  * iterator any() family scans with single-append semantics matching the
    oracle's one-condition-per-family guards (feat fix, made idiomatic).
This commit is contained in:
Nick committed 2026-10-14 02:23:49 +01:00
1 parent 07096f2c59
commit 3d158800c7
2 files changed
+70 -8

No files matched your search

+44 -2
View File
@@ -22,8 +22,8 @@ use serde_json::{json, Value};
use std::collections::BTreeMap;
use super::{
_sg_core, evaluate_salience, evaluate_salience_dict, flag_score, handle_hook, test_salience,
SalienceDecision,
_sg_core, evaluate_decision, evaluate_salience, evaluate_salience_dict, flag_score,
handle_hook, test_salience, word_boundary_contains, SalienceDecision,
};
const ENVELOPE: &str = include_str!("frozen_sg_truth.json");
@@ -212,3 +212,45 @@ fn to_dict_projection_shape() {
assert_eq!(m["minimum_tier"], json!("T0"));
assert_eq!(m["witness_needed"], json!(false));
}
/// Phase B bench (std-only: no criterion dep) — hot-path cost of the full
/// kernel evaluation over the frozen corpus, plus the word-boundary scan
/// micro. Numbers land in the landing evidence log.
#[test]
fn evaluate_hot_path_bench() {
use std::time::Instant;
let cases: Vec<Value> = envelope_cases()
.iter()
.filter(|c| c["fn"] == "evaluate_salience_dict")
.map(|c| c["args"][0].clone())
.collect();
assert!(!cases.is_empty(), "corpus must be non-empty");
let rounds = 1000;
let start = Instant::now();
let mut sink = 0.0f64;
for _ in 0..rounds {
for env in &cases {
sink += evaluate_decision(env).score;
}
}
let per_call = start.elapsed().as_secs_f64() * 1e9 / (rounds * cases.len()) as f64;
let text = "the tests still fail after two attempts but maybe a new plan again";
let start = Instant::now();
let mut hits = 0usize;
for _ in 0..100_000 {
if word_boundary_contains(text, "still") || word_boundary_contains(text, "attempts") {
hits += 1;
}
}
let per_scan = start.elapsed().as_secs_f64() * 1e9 / 100_000.0;
assert!(sink.is_finite() && hits > 0);
println!(
"bench evaluate_decision: {per_call:.1} ns/call over {} frozen envelopes; \
word_boundary_contains: {per_scan:.1} ns/scan",
cases.len()
);
}
+26 -6
View File
@@ -50,6 +50,7 @@ impl Default for SalienceDecision {
impl SalienceDecision {
/// Python SalienceDecision.to_dict parity: verbatim field projection.
#[must_use]
pub fn to_dict(&self) -> BTreeMap<String, Value> {
let mut out = BTreeMap::new();
out.insert("score".to_string(), serde_json::json!(self.score));
@@ -111,9 +112,23 @@ fn add_flag(d: &mut SalienceDecision, flag: &str, code: &str) {
d.rationale_codes.push(code.to_string());
}
/// ASCII-anchored lowercase avoidance: keyword matching only needs the
/// lowercased text; already-ASCII-lowercase strings (the common case) get
/// matched with zero allocation. Non-ASCII (or any uppercase) takes the
/// full Python-parity `to_lowercase()` path — Unicode case mappings (e.g.
/// 'İ') must never be skipped, so the borrow predicate is ASCII-only.
fn lower_for_match(s: &str) -> std::borrow::Cow<'_, str> {
if s.is_ascii() && !s.bytes().any(|b| b.is_ascii_uppercase()) {
std::borrow::Cow::Borrowed(s)
} else {
std::borrow::Cow::Owned(s.to_lowercase())
}
}
/// Typed kernel evaluation — mirrors the Python facade's floor exactly:
/// authority → urgency → failure → retry → contradiction → uncertainty →
/// novel, flags/rationale append in that evaluation order.
#[must_use]
pub fn evaluate_decision(envelope: &Value) -> SalienceDecision {
let mut d = SalienceDecision::default();
@@ -125,12 +140,13 @@ pub fn evaluate_decision(envelope: &Value) -> SalienceDecision {
.get("urgency")
.and_then(|u| u.as_str())
.unwrap_or("normal");
let text = envelope
.get("payload")
.and_then(|p| p.get("text"))
.and_then(|t| t.as_str())
.unwrap_or("")
.to_lowercase();
let text = lower_for_match(
envelope
.get("payload")
.and_then(|p| p.get("text"))
.and_then(|t| t.as_str())
.unwrap_or(""),
);
match authority {
"emergency" => add_flag(&mut d, "HIGH_RISK_IRREVERSIBLE", "emergency_authority"),
@@ -215,6 +231,7 @@ pub fn evaluate_decision(envelope: &Value) -> SalienceDecision {
d
}
#[must_use]
pub fn evaluate_salience(envelope: &Value) -> BTreeMap<String, Value> {
evaluate_decision(envelope).to_dict()
}
@@ -223,6 +240,7 @@ pub fn evaluate_salience(envelope: &Value) -> BTreeMap<String, Value> {
/// wrapper the shared freeze harness freezes: the dataclass-returning
/// evaluate_salience is not JSON-serializable). Pure to_dict composition —
/// zero logic drift from the oracle floor.
#[must_use]
pub fn evaluate_salience_dict(envelope: &Value) -> Value {
serde_json::json!(evaluate_salience(envelope))
}
@@ -231,6 +249,7 @@ pub fn evaluate_salience_dict(envelope: &Value) -> Value {
/// decision only (from the kernel's side the core always exists; the loader
/// module the Python probe returns is unreachable from Rust by design).
/// Some ↔ probe answered the loader; None ↔ python pin honored / fallback.
#[must_use]
pub fn _sg_core(pin: Option<&str>) -> Option<Value> {
if pin == Some("python") {
None
@@ -241,6 +260,7 @@ pub fn _sg_core(pin: Option<&str>) -> Option<Value> {
/// handle_hook — Python handle_hook parity: the plugin hook handler for
/// incoming events. The oracle accepts `data` and ignores it.
#[must_use]
pub fn handle_hook(event: &Value, _data: Option<&Value>) -> Value {
serde_json::json!({"status": "ok", "event": event, "handler": "salience_gate"})
}