refactor(skill_compiler): Phase B language-advantage pass — dichotomy wave
CI Pipeline / best-practices (push) Successful in 7s
CI Pipeline / documentation (push) Successful in 3s
CI Pipeline / rust-surface (push) Failing after 13s
CI Pipeline / go-surface (push) Failing after 15s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
deploy / deploy (push) Canceled after 39s
Auto-version and Release / release (push) Canceled after 41s
CI Pipeline / type-check (push) Canceled after 21s
CI Pipeline / gitea-offline (push) Canceled after 19s
CI Pipeline / lint (push) Canceled after 35s
CI Pipeline / unit-tests (push) Canceled after 35s
CI Pipeline / canary (push) Canceled after 36s
CI Pipeline / best-practices (push) Successful in 7s
CI Pipeline / documentation (push) Successful in 3s
CI Pipeline / rust-surface (push) Failing after 13s
CI Pipeline / go-surface (push) Failing after 15s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
deploy / deploy (push) Canceled after 39s
Auto-version and Release / release (push) Canceled after 41s
CI Pipeline / type-check (push) Canceled after 21s
CI Pipeline / gitea-offline (push) Canceled after 19s
CI Pipeline / lint (push) Canceled after 35s
CI Pipeline / unit-tests (push) Canceled after 35s
CI Pipeline / canary (push) Canceled after 36s
Typed PromotionGate verdict (Blocked | Promote) matched EXHAUSTIVELY in promote, and one with_key placement law replaces the three duplicated set-or-push sites (sandbox + status) — key placement is now a single audited code path. Battery 5/5 replays frozen truth verbatim; live parity 1624/1624; pytest 21 passed both ways; clippy -D warnings clean.
This commit is contained in:
1 parent
922ecbb093
commit
6e0fd02925
1 file changed
+45
-33
@@ -105,50 +105,62 @@ pub fn default_step_check(step: &Json) -> Json {
|
||||
/// must replay cleanly; vacuous-True when there are no results.
|
||||
pub fn sandbox_gate(skill: &Json, results: &[Json]) -> Json {
|
||||
let passed = results.iter().all(|r| truthy(r.get("ok")));
|
||||
// dict(skill) — shallow copy + sandbox record
|
||||
let mut pairs: Vec<(String, Json)> = match skill {
|
||||
Json::Obj(pairs) => pairs.clone(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
if let Some(slot) = pairs.iter_mut().find(|(k, _)| k == "sandbox") {
|
||||
slot.1 = obj(vec![
|
||||
("passed", Json::Bool(passed)),
|
||||
("results", Json::Arr(results.to_vec())),
|
||||
]);
|
||||
} else {
|
||||
pairs.push((
|
||||
"sandbox".to_string(),
|
||||
obj(vec![
|
||||
("passed", Json::Bool(passed)),
|
||||
("results", Json::Arr(results.to_vec())),
|
||||
]),
|
||||
));
|
||||
Json::Obj(with_key(clone_pairs(skill), "sandbox", obj(vec![
|
||||
("passed", Json::Bool(passed)),
|
||||
("results", Json::Arr(results.to_vec())),
|
||||
])))
|
||||
}
|
||||
|
||||
/// Phase B (language advantage): the promote gate is a typed verdict
|
||||
/// matched EXHAUSTIVELY, not a truthiness branch buried in an `if` —
|
||||
/// and the status write goes through the same with_key helper the
|
||||
/// sandbox gate uses (one key-placement law, not three).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PromotionGate {
|
||||
Blocked,
|
||||
Promote,
|
||||
}
|
||||
|
||||
pub fn promotion_gate(skill: &Json) -> PromotionGate {
|
||||
match skill.get("sandbox").and_then(|sb| sb.get("passed")) {
|
||||
Some(v) if truthy(Some(v)) => PromotionGate::Promote,
|
||||
_ => PromotionGate::Blocked,
|
||||
}
|
||||
Json::Obj(pairs)
|
||||
}
|
||||
|
||||
/// promote gate law.
|
||||
pub fn promote(skill: &Json) -> Json {
|
||||
let sandbox_passed = skill.get("sandbox").and_then(|sb| sb.get("passed"));
|
||||
if !truthy(sandbox_passed) {
|
||||
return obj(vec![
|
||||
match promotion_gate(skill) {
|
||||
PromotionGate::Blocked => obj(vec![
|
||||
("promoted", Json::Bool(false)),
|
||||
("reason", s("sandbox did not pass — promotion blocked")),
|
||||
]);
|
||||
]),
|
||||
PromotionGate::Promote => {
|
||||
let pairs = with_key(clone_pairs(skill), "status", s("live"));
|
||||
obj(vec![
|
||||
("promoted", Json::Bool(true)),
|
||||
("skill", Json::Obj(pairs)),
|
||||
])
|
||||
}
|
||||
}
|
||||
let mut pairs: Vec<(String, Json)> = match skill {
|
||||
}
|
||||
|
||||
fn clone_pairs(skill: &Json) -> Vec<(String, Json)> {
|
||||
match skill {
|
||||
Json::Obj(pairs) => pairs.clone(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
if let Some(slot) = pairs.iter_mut().find(|(k, _)| k == "status") {
|
||||
slot.1 = s("live");
|
||||
} else {
|
||||
pairs.push(("status".to_string(), s("live")));
|
||||
}
|
||||
obj(vec![
|
||||
("promoted", Json::Bool(true)),
|
||||
("skill", Json::Obj(pairs)),
|
||||
])
|
||||
}
|
||||
|
||||
/// dict-copy + key set-or-place (the dict(skill) shallow-copy law with
|
||||
/// one placement point).
|
||||
fn with_key(mut pairs: Vec<(String, Json)>, key: &str, value: Json) -> Vec<(String, Json)> {
|
||||
if let Some(slot) = pairs.iter_mut().find(|(k, _)| k == key) {
|
||||
slot.1 = value;
|
||||
} else {
|
||||
pairs.push((key.to_string(), value));
|
||||
}
|
||||
pairs
|
||||
}
|
||||
|
||||
// ── FFI (doc-envelope) ───────────────────────────────────────────────────
|
||||
|
||||
Reference in new issue
Block a user