refactor(drift_ledger): Phase B language-advantage pass — dichotomy wave
CI Pipeline / best-practices (push) Successful in 10s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 17s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
Auto-version and Release / release (push) Canceled after 36s
CI Pipeline / gitea-offline (push) Canceled after 18s
CI Pipeline / lint (push) Canceled after 36s
CI Pipeline / type-check (push) Canceled after 22s
CI Pipeline / unit-tests (push) Canceled after 35s
CI Pipeline / canary (push) Canceled after 36s
deploy / deploy (push) Canceled after 39s
CI Pipeline / best-practices (push) Successful in 10s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 17s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
Auto-version and Release / release (push) Canceled after 36s
CI Pipeline / gitea-offline (push) Canceled after 18s
CI Pipeline / lint (push) Canceled after 36s
CI Pipeline / type-check (push) Canceled after 22s
CI Pipeline / unit-tests (push) Canceled after 35s
CI Pipeline / canary (push) Canceled after 36s
deploy / deploy (push) Canceled after 39s
Language-advantage pass on the drift_ledger Rust kernel (battery green throughout, live parity re-verified 87/87 byte-identical after rebuild): - Block lattice is a real enum (Constitution..Project) with as_str/of_name/ limit matches — the constitution's stricter limit and its ANY-content- change strict check are exhaustive matches, not string compares; the per-block alert loop and snapshot assembly iterate BlockLabel::ALL. - check_alerts is iterator-composed: BlockLabel::ALL.filter_map over the baseline decision, emitting alerts via then(..) — the python loop's anchor-vs-snapshot branch stays a plain match. - diff_blocks is zero-copy iterator composition (filter_map + take(6)/ take(3) replaces the manual capped pushes); the whitespace-significance filter is one shared fn item over &str slices. - All keyword tables and contents borrow (&str / &Value) end-to-end — no per-block copying or lowering. - Frozen DL truth replay untouched and VERBATIM (branch_battery.rs replays the same 87-case oracle truth).
This commit is contained in:
1 parent
c0ec3135c6
commit
62e47b3812
1 file changed
+112
-65
@@ -14,7 +14,49 @@ use std::os::raw::c_char;
|
||||
|
||||
pub const DRIFT_LIMIT: f64 = 0.30;
|
||||
pub const CONSTITUTION_LIMIT: f64 = 0.05;
|
||||
pub const BLOCKS: &[&str] = &["constitution", "persona", "human", "operating", "project"];
|
||||
|
||||
/// The five guarded blocks — a closed lattice, not stringly-typed routing.
|
||||
/// The constitution's limit is exhaustive-match derived; every other block
|
||||
/// falls to the plain drift limit (the oracle's ternary).
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum BlockLabel {
|
||||
Constitution,
|
||||
Persona,
|
||||
Human,
|
||||
Operating,
|
||||
Project,
|
||||
}
|
||||
|
||||
impl BlockLabel {
|
||||
pub const ALL: [BlockLabel; 5] = [
|
||||
Self::Constitution,
|
||||
Self::Persona,
|
||||
Self::Human,
|
||||
Self::Operating,
|
||||
Self::Project,
|
||||
];
|
||||
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::Constitution => "constitution",
|
||||
Self::Persona => "persona",
|
||||
Self::Human => "human",
|
||||
Self::Operating => "operating",
|
||||
Self::Project => "project",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn of_name(name: &str) -> Option<Self> {
|
||||
Self::ALL.iter().copied().find(|b| b.as_str() == name)
|
||||
}
|
||||
|
||||
pub fn limit(self) -> f64 {
|
||||
match self {
|
||||
Self::Constitution => CONSTITUTION_LIMIT,
|
||||
_ => DRIFT_LIMIT,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// _sha port: hex sha256 of UTF-8 text.
|
||||
pub fn sha(text: &str) -> String {
|
||||
@@ -28,28 +70,28 @@ pub fn diff_blocks(reference: &str, current: &str) -> String {
|
||||
if reference.is_empty() {
|
||||
return "no prior content (first drift from empty baseline)".to_string();
|
||||
}
|
||||
fn sig(l: &str) -> Option<&str> {
|
||||
let s = l.trim();
|
||||
(!s.is_empty()).then_some(s)
|
||||
}
|
||||
let ref_lines: Vec<&str> = reference.lines().collect();
|
||||
let cur_lines: Vec<&str> = current.lines().collect();
|
||||
let ref_set: std::collections::HashSet<&str> =
|
||||
ref_lines.iter().filter_map(|l| { let s = l.trim(); if s.is_empty() { None } else { Some(s) } }).collect();
|
||||
ref_lines.iter().filter_map(|l| sig(l)).collect();
|
||||
let cur_set: std::collections::HashSet<&str> =
|
||||
cur_lines.iter().filter_map(|l| { let s = l.trim(); if s.is_empty() { None } else { Some(s) } }).collect();
|
||||
let mut added: Vec<&str> = vec![];
|
||||
for l in &cur_lines {
|
||||
let s = l.trim();
|
||||
if !s.is_empty() && !ref_set.contains(s) {
|
||||
added.push(s);
|
||||
if added.len() >= 6 { break; }
|
||||
}
|
||||
}
|
||||
let mut removed: Vec<&str> = vec![];
|
||||
for l in &ref_lines {
|
||||
let s = l.trim();
|
||||
if !s.is_empty() && !cur_set.contains(s) {
|
||||
removed.push(s);
|
||||
if removed.len() >= 3 { break; }
|
||||
}
|
||||
}
|
||||
cur_lines.iter().filter_map(|l| sig(l)).collect();
|
||||
let added: Vec<&str> = cur_lines
|
||||
.iter()
|
||||
.filter_map(|l| sig(l))
|
||||
.filter(|s| !ref_set.contains(*s))
|
||||
.take(6)
|
||||
.collect();
|
||||
let removed: Vec<&str> = ref_lines
|
||||
.iter()
|
||||
.filter_map(|l| sig(l))
|
||||
.filter(|s| !cur_set.contains(*s))
|
||||
.take(3)
|
||||
.collect();
|
||||
let mut parts: Vec<String> = vec![];
|
||||
if !added.is_empty() {
|
||||
parts.push(format!(
|
||||
@@ -85,8 +127,9 @@ pub fn check_block(
|
||||
None => (prev_size.max(1), None, cur_size - prev_size),
|
||||
};
|
||||
let pct = (delta.abs() as f64) / (base.max(1) as f64);
|
||||
let limit = if label == "constitution" { CONSTITUTION_LIMIT } else { DRIFT_LIMIT };
|
||||
let content_changed = label == "constitution"
|
||||
let is_constitution = matches!(BlockLabel::of_name(label), Some(BlockLabel::Constitution));
|
||||
let limit = if is_constitution { CONSTITUTION_LIMIT } else { DRIFT_LIMIT };
|
||||
let content_changed = is_constitution
|
||||
&& anchor_size.is_some()
|
||||
&& base_sha.is_some()
|
||||
&& cur_sha.is_some()
|
||||
@@ -100,7 +143,8 @@ pub fn check_block(
|
||||
|
||||
/// auto_fix routing port: (label, anchored, has_last_good) -> {action, reason}.
|
||||
pub fn auto_fix_decision(label: &str, anchored: bool, has_last_good: bool) -> Value {
|
||||
if label == "constitution" {
|
||||
let is_constitution = matches!(BlockLabel::of_name(label), Some(BlockLabel::Constitution));
|
||||
if is_constitution {
|
||||
json!({"action": "alert-only", "reason": "constitution changes only by explicit directive; needs human review"})
|
||||
} else if anchored {
|
||||
json!({"action": "re-anchored", "reason": "anchored block grew (authorised) — re-baselined"})
|
||||
@@ -128,12 +172,13 @@ pub fn ledger_path_for(index_file: &str) -> String {
|
||||
|
||||
/// snapshot() entry-assembly port: {"when", "blocks": {label: {sha, size,
|
||||
/// content}}}. "size" is the oracle's len(raw) — a CHARACTER count, not bytes.
|
||||
/// Unknown labels in the payload are ignored (the oracle iterates BLOCKS).
|
||||
pub fn snapshot_entry(blocks: &Value, when: &str) -> Value {
|
||||
let mut b = serde_json::Map::new();
|
||||
for label in BLOCKS {
|
||||
let raw = blocks.get(*label).and_then(|v| v.as_str()).unwrap_or("");
|
||||
for label in BlockLabel::ALL {
|
||||
let raw = blocks.get(label.as_str()).and_then(|v| v.as_str()).unwrap_or("");
|
||||
b.insert(
|
||||
(*label).to_string(),
|
||||
label.as_str().to_string(),
|
||||
json!({
|
||||
"sha": sha(raw),
|
||||
"size": raw.chars().count(),
|
||||
@@ -170,46 +215,48 @@ pub fn check_alerts(ledger: &Value, blocks: &Value) -> Value {
|
||||
.cloned()
|
||||
.unwrap_or_else(|| json!({}));
|
||||
let anchors = ledger.get("anchors").cloned().unwrap_or_else(|| json!({}));
|
||||
let mut alerts: Vec<Value> = vec![];
|
||||
for label in BLOCKS {
|
||||
let cur = blocks.get(*label).and_then(|v| v.as_str()).unwrap_or("");
|
||||
let cur_size = cur.chars().count() as i64;
|
||||
let anchor_meta = anchors.get(*label);
|
||||
let (base, base_sha, delta, ref_content) = match anchor_meta {
|
||||
Some(a) => {
|
||||
let b = a.get("size").and_then(|v| v.as_i64()).unwrap_or(cur_size);
|
||||
let sh = a.get("sha").and_then(|v| v.as_str());
|
||||
let rc = a.get("content").and_then(|v| v.as_str());
|
||||
(b, sh, cur_size - b, rc)
|
||||
}
|
||||
None => {
|
||||
let pm = prev.get(*label);
|
||||
let ps = pm
|
||||
.and_then(|m| m.get("size"))
|
||||
.and_then(|v| v.as_i64())
|
||||
.unwrap_or(cur_size);
|
||||
let rc = pm.and_then(|m| m.get("content")).and_then(|v| v.as_str());
|
||||
(ps.max(1), None, cur_size - ps, rc)
|
||||
}
|
||||
};
|
||||
let pct = (delta.abs() as f64) / (base.max(1) as f64);
|
||||
let limit = if *label == "constitution" { CONSTITUTION_LIMIT } else { DRIFT_LIMIT };
|
||||
let content_changed = *label == "constitution"
|
||||
&& anchor_meta.is_some()
|
||||
&& base_sha.is_some()
|
||||
&& sha(cur) != base_sha.unwrap();
|
||||
if content_changed || pct > limit {
|
||||
alerts.push(json!({
|
||||
"label": label,
|
||||
"delta": delta,
|
||||
"pct": py_round3(pct),
|
||||
"limit": py_round3(limit),
|
||||
"base": base,
|
||||
"changed": diff_blocks(ref_content.unwrap_or(""), cur),
|
||||
"content_changed": content_changed,
|
||||
}));
|
||||
}
|
||||
}
|
||||
let alerts: Vec<Value> = BlockLabel::ALL
|
||||
.iter()
|
||||
.filter_map(|label| {
|
||||
let cur = blocks.get(label.as_str()).and_then(|v| v.as_str()).unwrap_or("");
|
||||
let cur_size = cur.chars().count() as i64;
|
||||
let anchor_meta = anchors.get(label.as_str());
|
||||
let (base, base_sha, delta, ref_content) = match anchor_meta {
|
||||
Some(a) => {
|
||||
let b = a.get("size").and_then(|v| v.as_i64()).unwrap_or(cur_size);
|
||||
let sh = a.get("sha").and_then(|v| v.as_str());
|
||||
let rc = a.get("content").and_then(|v| v.as_str());
|
||||
(b, sh, cur_size - b, rc)
|
||||
}
|
||||
None => {
|
||||
let pm = prev.get(label.as_str());
|
||||
let ps = pm
|
||||
.and_then(|m| m.get("size"))
|
||||
.and_then(|v| v.as_i64())
|
||||
.unwrap_or(cur_size);
|
||||
let rc = pm.and_then(|m| m.get("content")).and_then(|v| v.as_str());
|
||||
(ps.max(1), None, cur_size - ps, rc)
|
||||
}
|
||||
};
|
||||
let pct = (delta.abs() as f64) / (base.max(1) as f64);
|
||||
let limit = label.limit();
|
||||
let content_changed = matches!(label, BlockLabel::Constitution)
|
||||
&& anchor_meta.is_some()
|
||||
&& base_sha.is_some()
|
||||
&& sha(cur) != base_sha.unwrap();
|
||||
(content_changed || pct > limit).then(|| {
|
||||
json!({
|
||||
"label": label.as_str(),
|
||||
"delta": delta,
|
||||
"pct": py_round3(pct),
|
||||
"limit": py_round3(limit),
|
||||
"base": base,
|
||||
"changed": diff_blocks(ref_content.unwrap_or(""), cur),
|
||||
"content_changed": content_changed,
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
Value::Array(alerts)
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user