refactor(pane_authority): Phase B language-advantage pass — dichotomy wave
CI Pipeline / best-practices (push) Successful in 9s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 16s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / gitea-offline (push) Successful in 15s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 27s
Auto-version and Release / release (push) Canceled after 45s
CI Pipeline / unit-tests (push) Canceled after 46s
deploy / deploy (push) Canceled after 46s
CI Pipeline / canary (push) Canceled after 45s
CI Pipeline / lint (push) Canceled after 46s
CI Pipeline / best-practices (push) Successful in 9s
CI Pipeline / documentation (push) Successful in 4s
CI Pipeline / rust-surface (push) Failing after 16s
CI Pipeline / go-surface (push) Failing after 20s
CI Pipeline / gitea-offline (push) Successful in 15s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / type-check (push) Canceled after 27s
Auto-version and Release / release (push) Canceled after 45s
CI Pipeline / unit-tests (push) Canceled after 46s
deploy / deploy (push) Canceled after 46s
CI Pipeline / canary (push) Canceled after 45s
CI Pipeline / lint (push) Canceled after 46s
Typed UtteranceKind verdict (Control(&'static str) | Amendment | Discussion) matched EXHAUSTIVELY downstream — the stringly kind chain is gone; adding a class becomes a compiler error instead of a silent fallthrough. Battery 2/2 replays frozen truth verbatim; live parity 826/826; pytest 19 passed both ways; clippy -D warnings clean.
This commit is contained in:
1 parent
acafb72178
commit
6344dfb45d
1 file changed
+88
-72
@@ -46,70 +46,86 @@ const AMENDMENT_KEYS: [&str; 5] = [
|
||||
"actually do",
|
||||
];
|
||||
|
||||
/// classify_utterance law.
|
||||
pub fn classify_utterance(text: Option<&str>) -> Json {
|
||||
/// Phase B (language advantage): the classification result is a typed
|
||||
/// verdict matched EXHAUSTIVELY downstream, not a stringly `kind` —
|
||||
/// adding a class becomes a compiler error instead of a silent fallthrough.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum UtteranceKind {
|
||||
/// control verb: the effective verb (oracle law: phrase matches
|
||||
/// that are not a first-word control verb get "stop")
|
||||
Control(&'static str),
|
||||
Amendment,
|
||||
Discussion,
|
||||
}
|
||||
|
||||
/// classify_utterance law, typed core.
|
||||
pub fn classify_typed(text: Option<&str>) -> UtteranceKind {
|
||||
let low = text.unwrap_or("").to_lowercase();
|
||||
let low = low.trim();
|
||||
let mut words = low.split_whitespace();
|
||||
let first = words.next().unwrap_or("");
|
||||
let control_hit = CONTROL.contains(&first)
|
||||
|| CONTROL.iter().any(|c| {
|
||||
low.contains(&format!("{c} the task")) || low.contains(&format!("{c} everything"))
|
||||
});
|
||||
if control_hit {
|
||||
let verb = if CONTROL.contains(&first) { first } else { "stop" };
|
||||
return obj(vec![
|
||||
let first = low.split_whitespace().next().unwrap_or("");
|
||||
if CONTROL.contains(&first) {
|
||||
return UtteranceKind::Control(CONTROL.iter().find(|c| **c == first).unwrap());
|
||||
}
|
||||
for c in CONTROL {
|
||||
if low.contains(&format!("{c} the task")) || low.contains(&format!("{c} everything")) {
|
||||
return UtteranceKind::Control("stop");
|
||||
}
|
||||
}
|
||||
if AMENDMENT_KEYS.iter().any(|k| low.contains(k)) {
|
||||
return UtteranceKind::Amendment;
|
||||
}
|
||||
UtteranceKind::Discussion
|
||||
}
|
||||
|
||||
/// classify_utterance law.
|
||||
pub fn classify_utterance(text: Option<&str>) -> Json {
|
||||
match classify_typed(text) {
|
||||
UtteranceKind::Control(verb) => obj(vec![
|
||||
("kind", s("control")),
|
||||
("verb", s(verb)),
|
||||
("priority", Json::Num(3.0)),
|
||||
]);
|
||||
]),
|
||||
UtteranceKind::Amendment => {
|
||||
obj(vec![("kind", s("amendment")), ("priority", Json::Num(2.0))])
|
||||
}
|
||||
UtteranceKind::Discussion => {
|
||||
obj(vec![("kind", s("discussion")), ("priority", Json::Num(1.0))])
|
||||
}
|
||||
}
|
||||
if AMENDMENT_KEYS.iter().any(|k| low.contains(k)) {
|
||||
return obj(vec![("kind", s("amendment")), ("priority", Json::Num(2.0))]);
|
||||
}
|
||||
obj(vec![("kind", s("discussion")), ("priority", Json::Num(1.0))])
|
||||
}
|
||||
|
||||
/// apply_to_task law: {task, amendment, applied}.
|
||||
pub fn apply_to_task(pane: &str, task: &Json, utterance: Option<&str>) -> Json {
|
||||
let cls = classify_utterance(utterance);
|
||||
let cls = classify_typed(utterance);
|
||||
// dict(task) — shallow copy
|
||||
let mut pairs: Vec<(String, Json)> = match task {
|
||||
Json::Obj(pairs) => pairs.clone(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
let kind = match cls.get("kind") {
|
||||
Some(Json::Str(k)) => k.as_str(),
|
||||
_ => "",
|
||||
};
|
||||
if kind == "control" {
|
||||
let verb = match cls.get("verb") {
|
||||
Some(Json::Str(v)) => v.as_str(),
|
||||
_ => "",
|
||||
};
|
||||
let status = if verb != "pause" {
|
||||
format!("{verb}ped")
|
||||
} else {
|
||||
"paused".to_string()
|
||||
};
|
||||
set_key(&mut pairs, "status", s(&status));
|
||||
return obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
(
|
||||
"amendment",
|
||||
obj(vec![
|
||||
("kind", s("control")),
|
||||
("verb", s(verb)),
|
||||
("from_pane", s(pane)),
|
||||
]),
|
||||
),
|
||||
("applied", Json::Bool(true)),
|
||||
]);
|
||||
}
|
||||
let text = utterance.unwrap_or("");
|
||||
if pane == "chat" {
|
||||
if kind == "amendment" {
|
||||
return obj(vec![
|
||||
match cls {
|
||||
UtteranceKind::Control(verb) => {
|
||||
let status = if verb != "pause" {
|
||||
format!("{verb}ped")
|
||||
} else {
|
||||
"paused".to_string()
|
||||
};
|
||||
set_key(&mut pairs, "status", s(&status));
|
||||
obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
(
|
||||
"amendment",
|
||||
obj(vec![
|
||||
("kind", s("control")),
|
||||
("verb", s(verb)),
|
||||
("from_pane", s(pane)),
|
||||
]),
|
||||
),
|
||||
("applied", Json::Bool(true)),
|
||||
])
|
||||
}
|
||||
kind if pane == "chat" && kind == UtteranceKind::Amendment => {
|
||||
let text = utterance.unwrap_or("");
|
||||
obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
(
|
||||
"amendment",
|
||||
@@ -121,31 +137,31 @@ pub fn apply_to_task(pane: &str, task: &Json, utterance: Option<&str>) -> Json {
|
||||
]),
|
||||
),
|
||||
("applied", Json::Bool(false)),
|
||||
]);
|
||||
])
|
||||
}
|
||||
return obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
("amendment", Json::Null),
|
||||
("applied", Json::Bool(false)),
|
||||
]);
|
||||
}
|
||||
// WORK pane (and any other pane value): direct application
|
||||
if kind == "amendment" {
|
||||
set_key(&mut pairs, "directive", s(text));
|
||||
return obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
(
|
||||
"amendment",
|
||||
obj(vec![
|
||||
("kind", s("amendment")),
|
||||
("text", s(text)),
|
||||
("from_pane", s("work")),
|
||||
("needs_confirm", Json::Bool(false)),
|
||||
]),
|
||||
),
|
||||
("applied", Json::Bool(true)),
|
||||
]);
|
||||
_ if pane == "chat" => no_amendment(pairs),
|
||||
UtteranceKind::Amendment => {
|
||||
let text = utterance.unwrap_or("");
|
||||
set_key(&mut pairs, "directive", s(text));
|
||||
obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
(
|
||||
"amendment",
|
||||
obj(vec![
|
||||
("kind", s("amendment")),
|
||||
("text", s(text)),
|
||||
("from_pane", s("work")),
|
||||
("needs_confirm", Json::Bool(false)),
|
||||
]),
|
||||
),
|
||||
("applied", Json::Bool(true)),
|
||||
])
|
||||
}
|
||||
_ => no_amendment(pairs),
|
||||
}
|
||||
}
|
||||
|
||||
fn no_amendment(pairs: Vec<(String, Json)>) -> Json {
|
||||
obj(vec![
|
||||
("task", Json::Obj(pairs)),
|
||||
("amendment", Json::Null),
|
||||
|
||||
Reference in new issue
Block a user