refactor(grading): Phase B language-advantage pass — dichotomy wave
Auto-version and Release / release (push) Failing after 57s
CI Pipeline / rust-surface (push) Failing after 57s
CI Pipeline / best-practices (push) Failing after 58s
CI Pipeline / lint (push) Failing after 58s
CI Pipeline / unit-tests (push) Failing after 1m0s
CI Pipeline / documentation (push) Failing after 1m0s
CI Pipeline / canary (push) Failing after 1m1s
CI Pipeline / go-surface (push) Failing after 1m4s
CI Pipeline / gitea-offline (push) Successful in 14s
CI Pipeline / type-check (push) Failing after 34s
CI Pipeline / required-checks (push) Failing after 0s
deploy / deploy (push) Failing after 40s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Failing after 4s

This commit is contained in:
Nick committed 2026-10-12 03:42:52 +01:00
1 parent 1494c1a5db
commit 04583cd26a
2 files changed
+187 -56

No files matched your search

+44 -2
View File
@@ -29,12 +29,12 @@ fn battery_replays_frozen_truth_verbatim() {
let expected = s(row, "expected");
let args = row.get("args").and_then(|a| a.as_array()).expect("args array");
let outcome = match fname {
"affirm_rule" => affirm_rule(args[0].as_str().expect("fact arg")),
"affirm_rule" => affirm_rule(args[0].as_str().expect("fact arg")).into_owned(),
"grade_fact" => {
let fact = args[0].as_str().expect("fact arg");
let target = args.get(1).and_then(|t| t.as_str());
let user_name = s(row, "user_name");
grade_fact(fact, target, user_name).to_string()
grade_fact(fact, target, user_name).as_str().to_string()
}
"tier_of" => tier_of(args[0].as_str().expect("grade arg")).to_string(),
other => panic!("unknown fn in truth row {}: {}", i, other),
@@ -91,3 +91,45 @@ fn tier_of_unknown_defaults_g3() {
assert_eq!(tier_of("nonsense-grade"), "G3");
assert_eq!(tier_of("archive"), "G3");
}
#[test]
fn grade_enum_matches_exhaustively() {
// The kernel's tier vocabulary is the Grade enum; every variant must
// carry its oracle tier name AND journal label.
let pairs = [
(super::Grade::Constitution, "constitution", "G0"),
(super::Grade::Operating, "operating", "G1"),
(super::Grade::Persona, "persona", "G2p"),
(super::Grade::Human, "human", "G2"),
(super::Grade::Project, "project", "G2"),
(super::Grade::Skill, "skill", "P"),
(super::Grade::Mempalace, "mempalace", "G4"),
(super::Grade::Hindsight, "hindsight", "G3"),
];
for (g, name, label) in pairs {
assert_eq!(g.as_str(), name);
assert_eq!(g.label(), label);
}
}
#[test]
fn name_containment_is_substring_bounded_not_token() {
// Mirrors the oracle's padded-haystack containment: "nickname nick"
// DOES contain " nick " (substring semantics), "nickel" does not.
assert!(super::contains_space_bounded("nickname nick", "nick"));
assert!(!super::contains_space_bounded("nickel settings", "nick"));
assert!(super::contains_space_bounded("nick", "nick"));
assert!(!super::contains_space_bounded("anything", ""));
}
#[test]
fn affirm_pass_through_is_zero_copy() {
// The pass-through path must BORROW the (trimmed) input, not allocate.
let owned = String::from("an ordinary fact");
match affirm_rule(&owned) {
std::borrow::Cow::Borrowed(s) => assert_eq!(s, "an ordinary fact"),
std::borrow::Cow::Owned(s) => panic!("pass-through allocated: {s}"),
}
// A known prohibition rewrites -> owned.
assert!(matches!(affirm_rule("never hedge"), std::borrow::Cow::Owned(_)));
}
+143 -54
View File
@@ -5,7 +5,14 @@
//! operating / G2 human+project / G3 hindsight / G4 mempalace via keyword
//! scoring, plus the curated prohibition→affirmation table.
//!
//! Parity port (commit 1): name-preserving functions, pythonic data flow.
//! Phase B (language-advantage pass): the tier vocabulary is a `Grade` enum
//! matched exhaustively (no stringly-typed fallthrough inside the kernel);
//! `affirm_rule` returns `Cow<'_, str>` — the pass-through path is
//! zero-copy; the affirmation needle needs ONE normalized alt-form per call
//! instead of the oracle's two allocations per dict entry; the user-name
//! containment check runs byte-boundary matching without building the
//! padded haystack; FFI errors are a typed `FfiError` enum carried in
//! `Result`.
//!
//! FFI contract (doc-envelope law — every call returns {"ok", "value"|"err"}):
//! * gr_affirm_rule({fact}) -> the (possibly rewritten) rule string
@@ -148,29 +155,96 @@ pub const AFFIRM_DICT: &[(&str, &str)] = &[
// ── the ported surface (name-preserving) ─────────────────────────────────
/// The tier vocabulary, matched exhaustively everywhere inside the kernel.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Grade {
Constitution,
Operating,
Persona,
Human,
Project,
Skill,
Mempalace,
Hindsight,
}
impl Grade {
/// The oracle's tier name (grade_fact's return vocabulary).
pub fn as_str(self) -> &'static str {
match self {
Grade::Constitution => "constitution",
Grade::Operating => "operating",
Grade::Persona => "persona",
Grade::Human => "human",
Grade::Project => "project",
Grade::Skill => "skill",
Grade::Mempalace => "mempalace",
Grade::Hindsight => "hindsight",
}
}
/// The oracle's journal label (tier_of's return vocabulary).
pub fn label(self) -> &'static str {
match self {
Grade::Constitution => "G0",
Grade::Operating => "G1",
Grade::Persona => "G2p",
Grade::Human | Grade::Project => "G2",
Grade::Skill => "P",
Grade::Mempalace => "G4",
Grade::Hindsight => "G3",
}
}
}
/// True iff `name` occurs in `low` with a space (or string edge) on BOTH
/// sides — the zero-copy form of the oracle's `format!(" {} ", name)
/// .contains(...)` check on the padded haystack. Substring semantics, not
/// token semantics: "nickname nick" DOES contain " nick ".
fn contains_space_bounded(low: &str, name: &str) -> bool {
if name.is_empty() {
return false;
}
let bytes = low.as_bytes();
let mut from = 0;
while let Some(pos) = low[from..].find(name) {
let i = from + pos;
let after = i + name.len();
let bounded = (i == 0 || bytes[i - 1] == b' ') && (after == low.len() || bytes[after] == b' ');
if bounded {
return true;
}
from = i + 1;
}
false
}
/// Rewrite a perceived demand/rule as a positive affirmation. Only known
/// prohibitions (AFFIRM_DICT) rewrite; everything else passes through
/// unchanged with the bullet/marker prefix stripped and whitespace
/// normalized — a blind substitution could invert meaning.
pub fn affirm_rule(fact: &str) -> String {
/// normalized — a blind substitution could invert meaning. Zero-copy on
/// the pass-through path (Cow borrows `fact` after trim).
pub fn affirm_rule(fact: &str) -> std::borrow::Cow<'_, str> {
let f = fact.trim().trim_start_matches(['-', '*', ' ']).trim();
let low = f.to_lowercase().split_whitespace().collect::<Vec<&str>>().join(" ");
// The oracle's second needle (low.strip(".").replace(" ", " ")) is
// key-independent and can only differ from `low` when edge dots or
// double spaces exist — normalize ONCE under that guard, lazily,
// instead of the oracle's two allocations per dict entry. Per-key
// `or` order is preserved (primary needle wins per entry).
let alt = (low.starts_with('.') || low.ends_with('.') || low.contains(" "))
.then(|| low.trim_matches('.').replace(" ", " "));
for (key, pos) in AFFIRM_DICT {
if low.contains(key) || low.trim_matches('.').replace(" ", " ").contains(key) {
return pos.to_string();
if low.contains(key) || alt.as_deref().is_some_and(|a| a.contains(key)) {
return pos.to_string().into();
}
}
f.to_string()
f.into()
}
/// Keyword-signal count as a single iterator fold.
fn count_signals(low: &str, signals: &[&str]) -> usize {
let mut n = 0;
for s in signals {
if low.contains(s) {
n += 1;
}
}
n
signals.iter().filter(|s| low.contains(**s)).count()
}
/// Return the tier (G0..G4) for a fact/rule based on type + language.
@@ -179,16 +253,16 @@ fn count_signals(low: &str, signals: &[&str]) -> usize {
/// import-time MEMORY_USER_NAME read — the oracle normalizes it with
/// strip().lower() at import, so the kernel repeats that (idempotent)
/// normalization at entry to stay faithful for any caller.
pub fn grade_fact(fact: &str, target: Option<&str>, user_name: &str) -> &'static str {
pub fn grade_fact(fact: &str, target: Option<&str>, user_name: &str) -> Grade {
let low = fact.to_lowercase();
let user_name = user_name.trim().to_lowercase();
// Constitution grows only via explicit directive language.
if CONSTITUTION_SIGNALS.iter().any(|s| low.contains(s)) {
return "constitution";
return Grade::Constitution;
}
// Documents / verbatim archival material -> cold.
if DOC_SIGNALS.iter().any(|s| low.contains(s)) {
return "mempalace";
return Grade::Mempalace;
}
// Behavioural rules -> operating (hot, auto). Imperative + agent-first.
let rule_score = count_signals(&low, RULE_STRONG) * 2 + count_signals(&low, RULE_WEAK);
@@ -196,76 +270,91 @@ pub fn grade_fact(fact: &str, target: Option<&str>, user_name: &str) -> &'static
let user_score = count_signals(&low, USER_FACT_SIGNALS);
let proj_score = count_signals(&low, PROJECT_SIGNALS);
if target == Some("operating") {
return "operating";
return Grade::Operating;
}
if target == Some("persona") {
// persona is identity growth — a tier of its own, slow-gated.
return "persona";
return Grade::Persona;
}
// A user fact states a stable attribute/preference about the user; a rule
// states what the agent does. "User prefers X" -> human. "When the user
// says X, do Y" -> operating. Strong imperative on the agent's behaviour
// -> operating. A decisive personal attribute routes to human even alone;
// otherwise the general user-signal count decides.
let name_token: String = if user_name.is_empty() {
"__none__".to_string()
} else {
format!(" {} ", user_name)
};
let decisive_attr = USER_ATTR_DECISIVE.iter().any(|s| low.contains(s));
let agent_markers = ["i ", "do not", "always", "never "];
let is_personal_attr = (decisive_attr || user_score >= 2)
&& !agent_markers.iter().any(|s| low.contains(s))
&& !format!(" {} ", low).contains(&name_token);
if is_personal_attr {
return "human";
let agent_free = ["i ", "do not", "always", "never "]
.iter()
.all(|s| !low.contains(s));
let name_blocked = !user_name.is_empty() && contains_space_bounded(&low, &user_name);
if (decisive_attr || user_score >= 2) && agent_free && !name_blocked {
return Grade::Human;
}
if rule_score >= 2 || affirm_score >= 1 {
return "operating";
return Grade::Operating;
}
if target == Some("project") || proj_score >= 2 {
return "project";
return Grade::Project;
}
if user_score >= 2 || target == Some("human") {
return "human";
return Grade::Human;
}
if target == Some("skill") || low.contains("procedure") || low.contains("steps") {
return "skill";
if target == Some("skill") || ["procedure", "steps"].iter().any(|s| low.contains(s)) {
return Grade::Skill;
}
"hindsight"
Grade::Hindsight
}
/// Human label for a grade, for journaling / canary output.
/// Human label for a grade, for journaling / canary output. Unknown grades
/// default to G3 (the oracle's .get(grade, "G3")).
pub fn tier_of(grade: &str) -> &'static str {
match grade {
"constitution" => "G0",
"operating" => "G1",
"persona" => "G2p",
"human" => "G2",
"project" => "G2",
"skill" => "P",
"mempalace" => "G4",
"hindsight" => "G3",
_ => "G3",
"constitution" => Grade::Constitution.label(),
"operating" => Grade::Operating.label(),
"persona" => Grade::Persona.label(),
"human" => Grade::Human.label(),
"project" => Grade::Project.label(),
"skill" => Grade::Skill.label(),
"mempalace" => Grade::Mempalace.label(),
"hindsight" => Grade::Hindsight.label(),
_ => Grade::Hindsight.label(),
}
}
// ── FFI (doc-envelope law) ───────────────────────────────────────────────
// ── FFI (doc-envelope law, typed errors) ─────────────────────────────────
fn read_arg(ptr: *const std::os::raw::c_char) -> Result<serde_json::Value, String> {
/// Typed FFI error (Phase B): the doc-envelope `err` string is produced
/// from this enum instead of ad-hoc strings.
#[derive(Debug)]
enum FfiError {
NullPtr,
Utf8(std::str::Utf8Error),
Json(serde_json::Error),
}
impl FfiError {
fn message(&self) -> String {
match self {
FfiError::NullPtr => "null argument pointer".to_string(),
FfiError::Utf8(e) => e.to_string(),
FfiError::Json(e) => e.to_string(),
}
}
}
fn read_arg(ptr: *const std::os::raw::c_char) -> Result<serde_json::Value, FfiError> {
if ptr.is_null() {
return Err("null argument pointer".into());
return Err(FfiError::NullPtr);
}
let x = unsafe { std::ffi::CStr::from_ptr(ptr) }
.to_str()
.map_err(|e| e.to_string())?;
serde_json::from_str(x).map_err(|e| e.to_string())
.map_err(FfiError::Utf8)?;
serde_json::from_str(x).map_err(FfiError::Json)
}
fn envelope(r: Result<serde_json::Value, String>) -> *mut std::os::raw::c_char {
fn envelope(r: Result<serde_json::Value, FfiError>) -> *mut std::os::raw::c_char {
let v = match r {
Ok(x) => serde_json::json!({"ok": true, "value": x}),
Err(e) => serde_json::json!({"ok": false, "err": e}),
Err(e) => serde_json::json!({"ok": false, "err": e.message()}),
};
std::ffi::CString::new(serde_json::to_string(&v).unwrap_or_default())
.map(|c| c.into_raw())
@@ -282,7 +371,7 @@ fn str_field(v: &serde_json::Value, key: &str) -> String {
/// gr_affirm_rule({fact}) -> the (possibly rewritten) rule string.
#[no_mangle]
pub extern "C" fn gr_affirm_rule(arg: *const std::os::raw::c_char) -> *mut std::os::raw::c_char {
envelope(read_arg(arg).map(|a| serde_json::Value::String(affirm_rule(&str_field(&a, "fact")))))
envelope(read_arg(arg).map(|a| serde_json::Value::String(affirm_rule(&str_field(&a, "fact")).into_owned())))
}
/// gr_grade_fact({fact, target, user_name}) -> the tier name.
@@ -294,7 +383,7 @@ pub extern "C" fn gr_grade_fact(arg: *const std::os::raw::c_char) -> *mut std::o
_ => None,
};
let user_name = str_field(&a, "user_name");
serde_json::Value::String(grade_fact(&str_field(&a, "fact"), target, &user_name).to_string())
serde_json::Value::String(grade_fact(&str_field(&a, "fact"), target, &user_name).as_str().to_string())
}))
}