refactor(self_improve): Phase B language-advantage pass — dichotomy wave
Typed Seam (Ok/Failed/Missing) and Severity (Warning/Info/Error) enums: analyze_system and _warn_stderr match exhaustively on Seam::from_probe, suggest_improvements classifies via Severity::classify — the oracle's elif-chain fall-through semantics preserved (battery-proven: 8/8 cargo tests incl. 61-row frozen-truth replay, 61/61 live parity both pins, clippy -D warnings + fmt clean, freeze regen byte-identical modulo the wall-clock stamp).
This commit is contained in:
1 parent
bd5c46f9d9
commit
eef472cdca
11 files changed
+353
-170
No files matched your search
@@ -2,16 +2,16 @@
|
||||
|
||||
_Regenerate with `python3 scripts/dichotomy_audit.py --write`. A module is FULL only when 80%+ of its Python functions have name-preserving counterparts in the Go/Rust implementation — directories without the functions are facades and count as NOT TOUCHED._
|
||||
|
||||
**FULL completion: 57%** (110/192 runtime modules at FULL)
|
||||
**FULL completion: 58%** (111/192 runtime modules at FULL)
|
||||
|
||||
Function-level detail: 72% (1638/2284 runtime functions matched) — secondary; includes in-flight work
|
||||
Function-level detail: 72% (1644/2287 runtime functions matched) — secondary; includes in-flight work
|
||||
|
||||
| Status | Modules | Lines | Meaning |
|
||||
|---|---|---|---|
|
||||
| FULL | 110 | 46125 | 80%+ of functions ported |
|
||||
| PARTIAL | 43 | 17482 | 20–80% — real logic exists, gaps named below |
|
||||
| FULL | 111 | 46509 | 80%+ of functions ported |
|
||||
| PARTIAL | 42 | 17236 | 20–80% — real logic exists, gaps named below |
|
||||
| NOT TOUCHED | 39 | 11471 | no name-preserving implementation |
|
||||
| Total runtime | 192 | 75078 | |
|
||||
| Total runtime | 192 | 75216 | |
|
||||
|
||||
## NOT TOUCHED — the port queue, in priority order (largest first)
|
||||
|
||||
@@ -78,7 +78,6 @@ Function-level detail: 72% (1638/2284 runtime functions matched) — secondary;
|
||||
| drift_observability | 399 | 5/9 | _do_core, main, _load_alerts, _save_alerts |
|
||||
| pins | 282 | 7/11 | _store_path, _detail_blob, unpin, list_pins |
|
||||
| prompt_sync | 487 | 11/15 | _now, _rust_available, get_store, main |
|
||||
| self_improve | 246 | 1/5 | _now, suggest_improvements, handle_hook, main |
|
||||
| task_gate | 301 | 5/9 | _tg_core, _now, list_gates, main |
|
||||
| tier_manager | 262 | 6/10 | demotion_sweep, get_tier_config, should_search, should_compress |
|
||||
| connection_pool | 226 | 7/10 | get_pool, _kernel_state, _get_connection_core |
|
||||
@@ -163,6 +162,7 @@ Function-level detail: 72% (1638/2284 runtime functions matched) — secondary;
|
||||
| voice_sync | 426 | 12/12 | RUST |
|
||||
| night_mode | 421 | 19/19 | GO |
|
||||
| construction_mode | 412 | 5/5 | RUST |
|
||||
| self_improve | 384 | 7/8 | RUST |
|
||||
| build_basis | 375 | 11/13 | RUST |
|
||||
| attention_capsule | 365 | 6/7 | RUST |
|
||||
| testing_mode | 362 | 11/13 | RUST |
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
//! itself as the kernel input; failing fixtures fail with PATH-FREE
|
||||
//! sqlite messages so no truth row embeds machine paths).
|
||||
|
||||
use crate::{analyze_system, handle_hook, main, suggest_improvements, _now, _warn_stderr};
|
||||
use crate::{_now, _warn_stderr, analyze_system, handle_hook, main, suggest_improvements};
|
||||
use evidence_provenance::pyjson::{self, Json};
|
||||
|
||||
const TRUTH: &str = include_str!("frozen_si_truth.json");
|
||||
@@ -27,10 +27,7 @@ fn at<'a>(v: &'a Json, path: &[&str]) -> Option<&'a Json> {
|
||||
let mut cur = v;
|
||||
for k in path {
|
||||
cur = match cur {
|
||||
Json::Obj(pairs) => pairs
|
||||
.iter()
|
||||
.find(|(k2, _)| k2 == k)
|
||||
.map(|(_, x)| x)?,
|
||||
Json::Obj(pairs) => pairs.iter().find(|(k2, _)| k2 == k).map(|(_, x)| x)?,
|
||||
_ => return None,
|
||||
};
|
||||
}
|
||||
@@ -164,13 +161,23 @@ fn replay_cli_rows() {
|
||||
Some(i) => argv.get(i + 1).cloned().unwrap_or_default(),
|
||||
None => "unknown".to_string(),
|
||||
};
|
||||
let out = main(&argv[0], &event, argv.iter().any(|a| a == "--json"),
|
||||
at(&c, &["probe"]).expect("probe"))
|
||||
.expect("cli kernel must render");
|
||||
let out = main(
|
||||
&argv[0],
|
||||
&event,
|
||||
argv.iter().any(|a| a == "--json"),
|
||||
at(&c, &["probe"]).expect("probe"),
|
||||
)
|
||||
.expect("cli kernel must render");
|
||||
let want = Json::Obj(vec![
|
||||
("stdout".into(), c.get("stdout").cloned().unwrap_or(Json::Str(String::new()))),
|
||||
("stderr".into(), c.get("stderr").cloned().unwrap_or(Json::Str(String::new()))),
|
||||
(
|
||||
"stdout".into(),
|
||||
c.get("stdout").cloned().unwrap_or(Json::Str(String::new())),
|
||||
),
|
||||
(
|
||||
"stderr".into(),
|
||||
c.get("stderr").cloned().unwrap_or(Json::Str(String::new())),
|
||||
),
|
||||
]);
|
||||
must_eq(&format!("cli/{name}"), &want, &out);
|
||||
}
|
||||
}
|
||||
}
|
||||
+236
-153
@@ -70,10 +70,71 @@ fn opt_err(v: &Json) -> Option<String> {
|
||||
}
|
||||
}
|
||||
|
||||
fn finding(area: &str, severity: &str, text: String, suggestion: Option<&str>) -> Json {
|
||||
/// The typed probe-seam view (Phase B): each of the five seams is either
|
||||
/// present-and-green, present-and-failed-with-a-message, or absent from
|
||||
/// the probe doc. `analyze_system` and `_warn_stderr` match exhaustively
|
||||
/// on this instead of re-walking stringly Json — a seam shape arriving
|
||||
/// wrong side compiles, not silently passes.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Seam {
|
||||
Ok(Json),
|
||||
Failed { error: String },
|
||||
Missing,
|
||||
}
|
||||
|
||||
impl Seam {
|
||||
pub fn from_probe(probe: &Json, key: &str) -> Seam {
|
||||
match probe.get(key) {
|
||||
None => Seam::Missing,
|
||||
Some(part) => match opt_err(part) {
|
||||
None => Seam::Ok(part.clone()),
|
||||
Some(error) => Seam::Failed { error },
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The oracle's elif chain as an exhaustive enum (Phase B): a known
|
||||
/// severity maps to a suggestion marker class; anything else — bools,
|
||||
/// numbers, unknown strings — renders nothing, exactly the oracle's
|
||||
/// fall-through.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Severity {
|
||||
Warning,
|
||||
Info,
|
||||
Error,
|
||||
}
|
||||
|
||||
impl Severity {
|
||||
/// Oracle order: `== "warning"`, elif `== "info"`, elif `== "error"`.
|
||||
/// A NON-STR severity never matches any branch (Python: `True ==
|
||||
/// "warning"` is False, no truthy fallthrough); a missing key raises
|
||||
/// — handled by the caller's KeyError envelope, not here.
|
||||
pub fn classify(severity: &Json) -> Option<Severity> {
|
||||
match severity {
|
||||
Json::Str(x) => match x.as_str() {
|
||||
"warning" => Some(Severity::Warning),
|
||||
"info" => Some(Severity::Info),
|
||||
"error" => Some(Severity::Error),
|
||||
_ => None, // the oracle's elif fall-through
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Severity::Warning => "warning",
|
||||
Severity::Info => "info",
|
||||
Severity::Error => "error",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn finding(area: &str, severity: Severity, text: String, suggestion: Option<&str>) -> Json {
|
||||
let mut pairs = vec![
|
||||
("area", Json::Str(area.to_string())),
|
||||
("severity", Json::Str(severity.to_string())),
|
||||
("severity", Json::Str(severity.as_str().to_string())),
|
||||
("finding", Json::Str(text)),
|
||||
];
|
||||
if let Some(su) = suggestion {
|
||||
@@ -85,113 +146,114 @@ fn finding(area: &str, severity: &str, text: String, suggestion: Option<&str>) -
|
||||
// ── pure kernels ────────────────────────────────────────────────────────────
|
||||
|
||||
/// Analyze system state and return findings (the oracle's five-seam
|
||||
/// threshold ladder, byte-exact).
|
||||
/// threshold ladder, byte-exact). Phase B: each block matches on the
|
||||
/// typed `Seam` view — a probe shape arriving wrong is a compile-time
|
||||
/// concern here, not a silent stringly pass-through.
|
||||
pub fn analyze_system(probe: &Json) -> Json {
|
||||
let mut findings: Vec<Json> = Vec::new();
|
||||
|
||||
// 1. Memory store health — an error here becomes the error FINDING
|
||||
// (the only block whose failure is a finding, not a warning).
|
||||
let store = probe.get("store").cloned().unwrap_or(Json::Null);
|
||||
if let Some(err) = opt_err(&store) {
|
||||
findings.push(finding("memory_store", "error", err, None));
|
||||
} else {
|
||||
let entries = num(&store, "entries");
|
||||
let associations = num(&store, "associations");
|
||||
if entries > 1000 {
|
||||
findings.push(finding(
|
||||
"memory_store",
|
||||
"warning",
|
||||
format!(
|
||||
"Memory store has {entries} entries — approaching scale where retrieval quality may degrade"
|
||||
),
|
||||
Some("Consider implementing abstraction pipeline to compress entries into concepts"),
|
||||
));
|
||||
// Missing == the oracle's block never running: no findings.
|
||||
match Seam::from_probe(probe, "store") {
|
||||
Seam::Failed { error } => {
|
||||
findings.push(finding("memory_store", Severity::Error, error, None));
|
||||
}
|
||||
// entries * 0.5 in exact integer math (associations < entries/2.0).
|
||||
if associations * 2 < entries {
|
||||
findings.push(finding(
|
||||
"memory_store",
|
||||
"info",
|
||||
format!(
|
||||
"Only {associations} associations for {entries} entries — sparse connectivity"
|
||||
),
|
||||
Some("Run _auto_associate more aggressively or lower the cosine threshold"),
|
||||
));
|
||||
Seam::Ok(store) => {
|
||||
let entries = num(&store, "entries");
|
||||
let associations = num(&store, "associations");
|
||||
if entries > 1000 {
|
||||
findings.push(finding(
|
||||
"memory_store",
|
||||
Severity::Warning,
|
||||
format!(
|
||||
"Memory store has {entries} entries — approaching scale where retrieval quality may degrade"
|
||||
),
|
||||
Some("Consider implementing abstraction pipeline to compress entries into concepts"),
|
||||
));
|
||||
}
|
||||
// entries * 0.5 in exact integer math (associations < entries/2.0).
|
||||
if associations * 2 < entries {
|
||||
findings.push(finding(
|
||||
"memory_store",
|
||||
Severity::Info,
|
||||
format!(
|
||||
"Only {associations} associations for {entries} entries — sparse connectivity"
|
||||
),
|
||||
Some("Run _auto_associate more aggressively or lower the cosine threshold"),
|
||||
));
|
||||
}
|
||||
}
|
||||
Seam::Missing => {}
|
||||
}
|
||||
|
||||
// 2. Plugin usage (only a finding above 80 registered plugins).
|
||||
if let Some(plugins) = probe.get("plugins") {
|
||||
if opt_err(plugins).is_none() && num(plugins, "count") > 80 {
|
||||
if let Seam::Ok(plugins) = Seam::from_probe(probe, "plugins") {
|
||||
let count = num(&plugins, "count");
|
||||
if count > 80 {
|
||||
findings.push(finding(
|
||||
"plugins",
|
||||
"info",
|
||||
format!(
|
||||
"{} plugins registered — capability broker should help discovery",
|
||||
num(plugins, "count")
|
||||
),
|
||||
Severity::Info,
|
||||
format!("{count} plugins registered — capability broker should help discovery"),
|
||||
Some("Verify capability broker is matching intents to plugins correctly"),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Abstraction pipeline.
|
||||
if let Some(ab) = probe.get("abstraction") {
|
||||
if opt_err(ab).is_none() {
|
||||
let facts = num(ab, "facts");
|
||||
let observations = num(ab, "observations");
|
||||
if facts > 0 && observations == 0 {
|
||||
findings.push(finding(
|
||||
"abstraction",
|
||||
"warning",
|
||||
format!("{facts} facts extracted but 0 observations synthesized"),
|
||||
Some("Run observation synthesis on entities with 3+ facts"),
|
||||
));
|
||||
}
|
||||
if facts < 50 {
|
||||
findings.push(finding(
|
||||
"abstraction",
|
||||
"info",
|
||||
format!("Only {facts} facts extracted — abstraction pipeline needs more data"),
|
||||
Some("Run abstraction on more transcripts"),
|
||||
));
|
||||
}
|
||||
if let Seam::Ok(ab) = Seam::from_probe(probe, "abstraction") {
|
||||
let facts = num(&ab, "facts");
|
||||
let observations = num(&ab, "observations");
|
||||
if facts > 0 && observations == 0 {
|
||||
findings.push(finding(
|
||||
"abstraction",
|
||||
Severity::Warning,
|
||||
format!("{facts} facts extracted but 0 observations synthesized"),
|
||||
Some("Run observation synthesis on entities with 3+ facts"),
|
||||
));
|
||||
}
|
||||
if facts < 50 {
|
||||
findings.push(finding(
|
||||
"abstraction",
|
||||
Severity::Info,
|
||||
format!("Only {facts} facts extracted — abstraction pipeline needs more data"),
|
||||
Some("Run abstraction on more transcripts"),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Cache effectiveness — `{hit_rate:.0%}` is python's
|
||||
// half-to-even percent formatting (12.5% → "13%"… no: 12% — the
|
||||
// battery's 1/8 and 3/8 rows pin the banker's-rounding law).
|
||||
if let Some(cache) = probe.get("cache") {
|
||||
if opt_err(cache).is_none() {
|
||||
let total = num(cache, "total");
|
||||
if total > 0 {
|
||||
let hits = num(cache, "hits");
|
||||
let misses = num(cache, "misses");
|
||||
let denom = (hits + misses).max(1) as f64;
|
||||
let hit_rate = hits as f64 / denom;
|
||||
if hit_rate < 0.3 {
|
||||
findings.push(finding(
|
||||
"cache",
|
||||
"warning",
|
||||
format!("Cache hit rate is {:.0}% — low effectiveness", hit_rate * 100.0),
|
||||
Some("Check if cache keys match actual query patterns"),
|
||||
));
|
||||
}
|
||||
if let Seam::Ok(cache) = Seam::from_probe(probe, "cache") {
|
||||
let total = num(&cache, "total");
|
||||
if total > 0 {
|
||||
let hits = num(&cache, "hits");
|
||||
let misses = num(&cache, "misses");
|
||||
let denom = (hits + misses).max(1) as f64;
|
||||
let hit_rate = hits as f64 / denom;
|
||||
if hit_rate < 0.3 {
|
||||
findings.push(finding(
|
||||
"cache",
|
||||
Severity::Warning,
|
||||
format!(
|
||||
"Cache hit rate is {:.0}% — low effectiveness",
|
||||
hit_rate * 100.0
|
||||
),
|
||||
Some("Check if cache keys match actual query patterns"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. use_history for learning data.
|
||||
if let Some(history) = probe.get("history") {
|
||||
if opt_err(history).is_none() && num(history, "count") < 100 {
|
||||
if let Seam::Ok(history) = Seam::from_probe(probe, "history") {
|
||||
let count = num(&history, "count");
|
||||
if count < 100 {
|
||||
findings.push(finding(
|
||||
"learning",
|
||||
"info",
|
||||
format!(
|
||||
"Only {} use_history entries — not enough for Thompson Sampling",
|
||||
num(history, "count")
|
||||
),
|
||||
Severity::Info,
|
||||
format!("Only {count} use_history entries — not enough for Thompson Sampling"),
|
||||
Some("Continue using the system to accumulate learning data"),
|
||||
));
|
||||
}
|
||||
@@ -213,38 +275,42 @@ fn py_field(f: &Json, key: &str) -> Result<String, (String, String)> {
|
||||
|
||||
/// Generate improvement suggestions based on analysis. Lookup order is
|
||||
/// the oracle's: severity (all branches), then area → finding per branch,
|
||||
/// then suggestion for warning/info.
|
||||
/// then suggestion for warning/info. Phase B: the elif chain is the
|
||||
/// exhaustive `Severity::classify` match — unknown or non-str severities
|
||||
/// render nothing, exactly the oracle's fall-through.
|
||||
pub fn suggest_improvements(findings: &Json) -> Result<Json, (String, String)> {
|
||||
let items = match findings {
|
||||
Json::Arr(items) => items,
|
||||
_ => return Err(("'findings' is not a list".to_string(), "ValueError".to_string())),
|
||||
_ => {
|
||||
return Err((
|
||||
"'findings' is not a list".to_string(),
|
||||
"ValueError".to_string(),
|
||||
))
|
||||
}
|
||||
};
|
||||
let mut suggestions = Vec::new();
|
||||
for f in items {
|
||||
let severity = match f.get("severity") {
|
||||
Some(Json::Str(x)) => x.clone(),
|
||||
None => return Err(("'severity'".to_string(), "KeyError".to_string())),
|
||||
Some(_) => String::new(), // non-str values match no branch
|
||||
};
|
||||
match severity.as_str() {
|
||||
"warning" | "info" => {
|
||||
let raw = f
|
||||
.get("severity")
|
||||
.ok_or_else(|| ("'severity'".to_string(), "KeyError".to_string()))?;
|
||||
match Severity::classify(raw) {
|
||||
Some(sev @ (Severity::Warning | Severity::Info)) => {
|
||||
let area = py_field(f, "area")?;
|
||||
let text = py_field(f, "finding")?;
|
||||
let sug = py_field(f, "suggestion")?;
|
||||
let mark = if severity == "warning" {
|
||||
let mark = if sev == Severity::Warning {
|
||||
"⚠\u{fe0f}"
|
||||
} else {
|
||||
"ℹ\u{fe0f}"
|
||||
};
|
||||
suggestions
|
||||
.push(Json::Str(format!("{mark} [{area}] {text} → {sug}")));
|
||||
suggestions.push(Json::Str(format!("{mark} [{area}] {text} → {sug}")));
|
||||
}
|
||||
"error" => {
|
||||
Some(Severity::Error) => {
|
||||
let area = py_field(f, "area")?;
|
||||
let text = py_field(f, "finding")?;
|
||||
suggestions.push(Json::Str(format!("❌ [{area}] {text}")));
|
||||
}
|
||||
_ => {} // the oracle's elif chain: unknown severity renders nothing
|
||||
None => {} // the oracle's elif chain: unknown severity renders nothing
|
||||
}
|
||||
}
|
||||
Ok(Json::Arr(suggestions))
|
||||
@@ -330,9 +396,7 @@ pub fn main(
|
||||
let sev = s(f, "severity");
|
||||
let area = s(f, "area");
|
||||
let text = s(f, "finding");
|
||||
stdout.push(format!(
|
||||
" [{sev:<7}] [{area:<15}] {text}"
|
||||
));
|
||||
stdout.push(format!(" [{sev:<7}] [{area:<15}] {text}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,8 +406,7 @@ pub fn main(
|
||||
let findings = analyze_system(probe);
|
||||
match suggest_improvements(&findings) {
|
||||
Ok(Json::Arr(sugs)) if sugs.is_empty() => {
|
||||
stdout
|
||||
.push(" No improvement suggestions — system looks healthy".to_string());
|
||||
stdout.push(" No improvement suggestions — system looks healthy".to_string());
|
||||
}
|
||||
Ok(Json::Arr(sugs)) => {
|
||||
for sug in sugs {
|
||||
@@ -360,12 +423,7 @@ pub fn main(
|
||||
let res = handle_hook(event, None);
|
||||
stdout.push(pyjson::dumps(&res));
|
||||
}
|
||||
_ => {
|
||||
return Err((
|
||||
format!("unknown cmd: {cmd}"),
|
||||
"ValueError".to_string(),
|
||||
))
|
||||
}
|
||||
_ => return Err((format!("unknown cmd: {cmd}"), "ValueError".to_string())),
|
||||
}
|
||||
let join = |lines: Vec<String>| {
|
||||
if lines.is_empty() {
|
||||
@@ -384,22 +442,24 @@ pub fn main(
|
||||
/// preserving): the four best-effort warning lines (oracle blocks 2–5)
|
||||
/// when a seam failed. The memory_store seam is NOT here — its failure
|
||||
/// is an error finding, not a warning line. Public so the battery can
|
||||
/// replay the frozen stderr rows byte-exactly.
|
||||
/// replay the frozen stderr rows byte-exactly. Phase B: the loop walks
|
||||
/// the typed `Seam` view — only `Failed` warns; a missing seam never ran
|
||||
/// and stays silent.
|
||||
pub fn _warn_stderr(probe: &Json) -> String {
|
||||
let mut out = String::new();
|
||||
let warn = |label: &str, part: Option<&Json>, out: &mut String| {
|
||||
if let Some(p) = part {
|
||||
if let Some(err) = opt_err(p) {
|
||||
out.push_str(&format!(
|
||||
"[self_improve] WARNING: {label} failed: {err}\n"
|
||||
));
|
||||
}
|
||||
let seams = [
|
||||
("plugins", "plugin check"),
|
||||
("abstraction", "abstraction check"),
|
||||
("cache", "cache check"),
|
||||
("history", "learning check"),
|
||||
];
|
||||
for (key, label) in seams {
|
||||
if let Seam::Failed { error } = Seam::from_probe(probe, key) {
|
||||
out.push_str(&format!(
|
||||
"[self_improve] WARNING: {label} failed: {error}\n"
|
||||
));
|
||||
}
|
||||
};
|
||||
warn("plugin check", probe.get("plugins"), &mut out);
|
||||
warn("abstraction check", probe.get("abstraction"), &mut out);
|
||||
warn("cache check", probe.get("cache"), &mut out);
|
||||
warn("learning check", probe.get("history"), &mut out);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
@@ -417,11 +477,9 @@ fn envelope(result: Result<Json, (String, String)>) -> *mut c_char {
|
||||
let out = pyjson::dumps(&body);
|
||||
match CString::new(out) {
|
||||
Ok(c) => c.into_raw(),
|
||||
Err(_) => CString::new(
|
||||
r#"{"ok":false,"err":"nul in output","type":"RuntimeError"}"#,
|
||||
)
|
||||
.unwrap()
|
||||
.into_raw(),
|
||||
Err(_) => CString::new(r#"{"ok":false,"err":"nul in output","type":"RuntimeError"}"#)
|
||||
.unwrap()
|
||||
.into_raw(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,8 +501,7 @@ macro_rules! ffi {
|
||||
($name:ident, $body:expr) => {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn $name(arg: *const c_char) -> *mut c_char {
|
||||
let out: Result<Json, (String, String)> =
|
||||
read_arg(arg).and_then(|raw| $body(&raw));
|
||||
let out: Result<Json, (String, String)> = read_arg(arg).and_then(|raw| $body(&raw));
|
||||
envelope(out)
|
||||
}
|
||||
};
|
||||
@@ -458,15 +515,21 @@ ffi!(si_analyze, |raw: &str| -> Result<Json, (String, String)> {
|
||||
|
||||
ffi!(si_suggest, |raw: &str| -> Result<Json, (String, String)> {
|
||||
let doc = parse_doc(raw)?;
|
||||
let findings = doc.get("findings").cloned().unwrap_or(Json::Arr(Vec::new()));
|
||||
let findings = doc
|
||||
.get("findings")
|
||||
.cloned()
|
||||
.unwrap_or(Json::Arr(Vec::new()));
|
||||
suggest_improvements(&findings)
|
||||
});
|
||||
|
||||
ffi!(si_handle_hook, |raw: &str| -> Result<Json, (String, String)> {
|
||||
let doc = parse_doc(raw)?;
|
||||
let event = s(&doc, "event");
|
||||
Ok(handle_hook(&event, doc.get("data")))
|
||||
});
|
||||
ffi!(
|
||||
si_handle_hook,
|
||||
|raw: &str| -> Result<Json, (String, String)> {
|
||||
let doc = parse_doc(raw)?;
|
||||
let event = s(&doc, "event");
|
||||
Ok(handle_hook(&event, doc.get("data")))
|
||||
}
|
||||
);
|
||||
|
||||
ffi!(si_now, |raw: &str| -> Result<Json, (String, String)> {
|
||||
let doc = parse_doc(raw)?;
|
||||
@@ -499,26 +562,41 @@ mod tests {
|
||||
#[test]
|
||||
fn healthy_probe_yields_no_findings() {
|
||||
let probe = obj(vec![
|
||||
("store", obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("entries", Json::Num(100.0)),
|
||||
("chunks", Json::Num(200.0)),
|
||||
("associations", Json::Num(60.0)),
|
||||
])),
|
||||
("plugins", obj(vec![("ok", Json::Bool(true)), ("count", Json::Num(10.0))])),
|
||||
("abstraction", obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("facts", Json::Num(51.0)),
|
||||
("observations", Json::Num(10.0)),
|
||||
])),
|
||||
("cache", obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("total", Json::Num(10.0)),
|
||||
("active", Json::Num(10.0)),
|
||||
("hits", Json::Num(7.0)),
|
||||
("misses", Json::Num(3.0)),
|
||||
])),
|
||||
("history", obj(vec![("ok", Json::Bool(true)), ("count", Json::Num(150.0))])),
|
||||
(
|
||||
"store",
|
||||
obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("entries", Json::Num(100.0)),
|
||||
("chunks", Json::Num(200.0)),
|
||||
("associations", Json::Num(60.0)),
|
||||
]),
|
||||
),
|
||||
(
|
||||
"plugins",
|
||||
obj(vec![("ok", Json::Bool(true)), ("count", Json::Num(10.0))]),
|
||||
),
|
||||
(
|
||||
"abstraction",
|
||||
obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("facts", Json::Num(51.0)),
|
||||
("observations", Json::Num(10.0)),
|
||||
]),
|
||||
),
|
||||
(
|
||||
"cache",
|
||||
obj(vec![
|
||||
("ok", Json::Bool(true)),
|
||||
("total", Json::Num(10.0)),
|
||||
("active", Json::Num(10.0)),
|
||||
("hits", Json::Num(7.0)),
|
||||
("misses", Json::Num(3.0)),
|
||||
]),
|
||||
),
|
||||
(
|
||||
"history",
|
||||
obj(vec![("ok", Json::Bool(true)), ("count", Json::Num(150.0))]),
|
||||
),
|
||||
]);
|
||||
let findings = analyze_system(&probe);
|
||||
match &findings {
|
||||
@@ -531,7 +609,10 @@ mod tests {
|
||||
fn store_error_becomes_error_finding_without_suggestion() {
|
||||
let probe = obj(vec![(
|
||||
"store",
|
||||
obj(vec![("ok", Json::Bool(false)), ("error", Json::Str("no such table: entries".into()))]),
|
||||
obj(vec![
|
||||
("ok", Json::Bool(false)),
|
||||
("error", Json::Str("no such table: entries".into())),
|
||||
]),
|
||||
)]);
|
||||
match analyze_system(&probe) {
|
||||
Json::Arr(items) => {
|
||||
@@ -548,9 +629,11 @@ mod tests {
|
||||
fn isoformat_shape_holds_for_pinned_instants() {
|
||||
assert_eq!(_now(0).unwrap(), "1970-01-01T00:00:00+00:00");
|
||||
// 2026-10-11T12:00:00+00:00 (epoch seconds 1,791,720,000)
|
||||
assert_eq!(_now(1_791_720_000_000_000).unwrap(),
|
||||
"2026-10-11T12:00:00+00:00");
|
||||
assert_eq!(
|
||||
_now(1_791_720_000_000_000).unwrap(),
|
||||
"2026-10-11T12:00:00+00:00"
|
||||
);
|
||||
// half second past any second renders six digits
|
||||
assert_eq!(_now(500_000).unwrap(), "1970-01-01T00:00:00.500000+00:00");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
Compiling self_improve v0.1.0 (/mnt/workdrive/rune-wave-dc/src/rust/self_improve)
|
||||
Finished `release` profile [optimized] target(s) in 0.39s
|
||||
Running unittests src/lib.rs (src/rust/self_improve/target/release/deps/self_improve-d3b64b1f4ff14666)
|
||||
|
||||
running 8 tests
|
||||
test tests::healthy_probe_yields_no_findings ... ok
|
||||
test tests::isoformat_shape_holds_for_pinned_instants ... ok
|
||||
test tests::store_error_becomes_error_finding_without_suggestion ... ok
|
||||
test branch_battery::replay_handle_hook_rows ... ok
|
||||
test branch_battery::replay_now_rows ... ok
|
||||
test branch_battery::replay_suggest_rows ... ok
|
||||
test branch_battery::replay_cli_rows ... ok
|
||||
test branch_battery::replay_analyze_rows ... ok
|
||||
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests self_improve
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
EXIT=0
|
||||
@@ -0,0 +1,2 @@
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.03s
|
||||
EXIT=0
|
||||
@@ -0,0 +1,3 @@
|
||||
......sssssssssss..s........................ [100%]
|
||||
32 passed, 12 skipped in 1.26s
|
||||
EXIT=0
|
||||
@@ -0,0 +1 @@
|
||||
EXIT=0
|
||||
@@ -0,0 +1,8 @@
|
||||
frozen 61 cases → src/rust/self_improve/src/frozen_si_truth.json
|
||||
src/rust/self_improve/src/frozen_si_truth.json | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
M src/rust/self_improve/src/frozen_si_truth.json
|
||||
FREEZE_BYTE_IDENTICAL_IF_EMPTY_ABOVE
|
||||
EXIT=0
|
||||
|
||||
[cross-check] the 1-line diff is the "frozen" wall-clock STAMP only; all 61 case rows byte-identical (proved: replay 61/61 + git diff shows only line 4221). Committed truth restored after regen.
|
||||
@@ -0,0 +1,3 @@
|
||||
........ [100%]
|
||||
8 passed in 0.60s
|
||||
EXIT=0
|
||||
@@ -0,0 +1,2 @@
|
||||
replay: 61/61 rows byte-identical (facade both-pins + kernel direct)
|
||||
EXIT=0
|
||||
@@ -0,0 +1,51 @@
|
||||
# verification/si-phaseb-summary.md — self_improve Phase B evidence
|
||||
|
||||
Module: self_improve (parity commit dc1d17b3 + this Phase B pass)
|
||||
Worktree: /mnt/workdrive/rune-wave-dc (detached, gitea/master + 1)
|
||||
|
||||
## Phase B change (language-advantage pass, battery-guarded)
|
||||
|
||||
src/rust/self_improve/src/lib.rs only:
|
||||
- `Seam` enum (Ok/Failed/Missing) — the probe-seam view; `analyze_system`
|
||||
and `_warn_stderr` now match on `Seam::from_probe` exhaustively instead
|
||||
of re-walking stringly `opt_err`/`get` chains. Missing == the oracle's
|
||||
block never running (silent); Failed carries the verbatim error string.
|
||||
- `Severity` enum — the oracle's elif chain (`== "warning"` / `"info"` /
|
||||
`"error"`); `suggest_improvements` classifies via `Severity::classify`
|
||||
(non-str severities match no branch, missing key raises KeyError —
|
||||
unchanged semantics).
|
||||
- `finding()` takes `Severity`; all five blocks construct typed findings.
|
||||
- cargo fmt applied (import order in branch_battery.rs was the only
|
||||
pre-existing fmt drift).
|
||||
|
||||
## Evidence files (Read-tool cross-checked)
|
||||
|
||||
- verification/si-phaseb-cargo-test.log — EXIT=0, 8 passed
|
||||
(3 kernel unit + 5 branch_battery frozen-truth replays — Phase B is
|
||||
behavior-identical by battery proof, not by inspection)
|
||||
- verification/si-phaseb-clippy.log — EXIT=0 (`cargo clippy --all-targets
|
||||
-- -D warnings`)
|
||||
- verification/si-phaseb-fmt.log — EXIT=0 (`cargo fmt -- --check`)
|
||||
- verification/si-phaseb-freeze.log — freeze regen against the LIVE
|
||||
oracle (RUNE_SI_CORE=python pinned in-script): 61 cases; the only
|
||||
diff vs the committed truth is the wall-clock `"frozen"` STAMP
|
||||
(line 4221) — all 61 case rows byte-identical; committed truth
|
||||
restored afterwards
|
||||
- verification/si-phaseb-replay.log — EXIT=0: `replay: 61/61 rows
|
||||
byte-identical (facade both-pins + kernel direct)` — live parity 100%
|
||||
through the NEW typed code paths
|
||||
- verification/si-phaseb-pytest.log — EXIT=0: 8 passed
|
||||
(tests/test_self_improve_port.py, both pins in-process)
|
||||
- verification/si-phaseb-collateral.log — EXIT=0: 32 passed, 12 skipped
|
||||
(pre-existing skips) across tui_post_response_consolidation,
|
||||
capability_broker_delegation, cache, sleep_time_gap_delegation,
|
||||
self_improve_port
|
||||
|
||||
## Audit
|
||||
|
||||
docs/dichotomy-rebase-honest-audit.md regenerated (--write) at this tree:
|
||||
self_improve 7/8 FULL, side=RUST (unmatched: `_si_core` — the
|
||||
kernel-resolution loader probe, facade-only glue by law, same category as
|
||||
self_modify's landed `_smod_core`; documented in si-summary.md).
|
||||
Programme: FULL 55% (105/192) | fn 71% at THIS tree (pre-push snapshot;
|
||||
close-time rebase regenerates again).
|
||||
Reference in new issue
Block a user