refactor(construction_pattern): Phase B language-advantage pass — dichotomy wave

SignalTally struct + free _check fn (evaluate closure accumulators as one
struct); _surface_text zero-copy BTreeSet<&str> borrowing input JSON (per-
token allocations eliminated, sorted projection byte-identical);
_need_dict Map::with_capacity(3). Battery 14/14, clippy 0, harness 18/18
byte-identical, live parity 192/192 both pins, pytest 30/30+66/66.
This commit is contained in:
Nick committed 2026-10-14 12:33:14 +01:00
1 parent ee77255c65
commit 45a7dd6a8c
8 files changed
+94 -36

No files matched your search

+61 -36
View File
@@ -246,7 +246,7 @@ pub fn _entity_matches(signal: &str, entity_id: &str) -> bool {
/// canonical fields — objective, affected_surface, constraints. Everything
/// else a caller attached is dropped at the kernel boundary.
pub fn _need_dict(need: &Map<String, Value>) -> Map<String, Value> {
let mut out = Map::new();
let mut out = Map::with_capacity(3);
out.insert("objective".into(), need.get("objective").cloned().unwrap_or(Value::Null));
out.insert(
"affected_surface".into(),
@@ -262,9 +262,11 @@ pub fn _need_dict(need: &Map<String, Value>) -> Map<String, Value> {
/// Everything the affected surface offers as evidence: paths, entities,
/// ui surfaces, regions, workflow configs, the objective text tokens
/// (deterministic split — not semantics). Set semantics; sorted projection
/// because the frozen truth stores `sorted(set)`.
/// because the frozen truth stores `sorted(set)`. Phase B: tokens borrow
/// the input JSON and the one lowered objective — the only allocations are
/// the lowered objective and the final output array.
pub fn _surface_text(need: &Map<String, Value>, surface: &Map<String, Value>) -> Value {
let mut tokens: std::collections::BTreeSet<String> = std::collections::BTreeSet::new();
let mut tokens: std::collections::BTreeSet<&str> = std::collections::BTreeSet::new();
for k in [
"affected_paths",
"affected_existing_entities",
@@ -272,19 +274,17 @@ pub fn _surface_text(need: &Map<String, Value>, surface: &Map<String, Value>) ->
"affected_regions",
"workflow_config_surfaces",
] {
for t in surface.get(k).map(str_list).unwrap_or_default() {
tokens.insert(t.to_string());
}
tokens.extend(surface.get(k).map(str_list).unwrap_or_default());
}
for t in need.get("affected_surface").map(str_list).unwrap_or_default() {
tokens.insert(t.to_string());
}
let objective = need.get("objective").and_then(|v| v.as_str()).unwrap_or("");
let lowered = objective.replace(['/', '-'], " ").to_lowercase();
for w in lowered.split_whitespace() {
tokens.insert(w.to_string());
}
Value::Array(tokens.into_iter().map(Value::String).collect())
tokens.extend(need.get("affected_surface").map(str_list).unwrap_or_default());
let lowered = need
.get("objective")
.and_then(|v| v.as_str())
.unwrap_or("")
.replace(['/', '-'], " ")
.to_lowercase();
tokens.extend(lowered.split_whitespace());
Value::Array(tokens.into_iter().map(|t| Value::String(t.to_string())).collect())
}
// ── small JSON accessors (borrowed; owned only where the output needs it) ──
@@ -456,6 +456,40 @@ fn surface_kind_present(kind: &str, surface: &Map<String, Value>) -> bool {
.unwrap_or(false)
}
/// The evaluate_applicability signal tally — Python's `_check` closure with
/// its three nonlocal accumulators as ONE struct; the free `_check` mutates
/// it and the contracts_match pass records hits directly.
struct SignalTally {
groups_declared: usize,
groups_hit: Vec<&'static str>,
evidence: Map<String, Value>,
}
impl SignalTally {
fn record_hits(&mut self, group: &'static str, hits: Vec<&str>) {
self.groups_hit.push(group);
self.evidence.insert(group.to_string(), json!(hits));
}
}
/// Python's nested `_check`: count a DECLARED signal group and record its
/// evidence when any candidate produces a hit (first 5 kept).
fn _check(
tally: &mut SignalTally,
group: &'static str,
candidates: &[&str],
present: &dyn Fn(&str) -> bool,
) {
if candidates.is_empty() {
return;
}
tally.groups_declared += 1;
let hits: Vec<&str> = candidates.iter().filter(|c| present(c)).copied().collect();
if !hits.is_empty() {
tally.record_hits(group, hits.iter().take(5).copied().collect());
}
}
/// Deterministic applicability verdict from the pattern's declared signals.
pub fn evaluate_applicability(
pattern: &Map<String, Value>,
@@ -497,9 +531,9 @@ pub fn evaluate_applicability(
}
};
let mut groups_hit: Vec<&'static str> = Vec::new();
let mut groups_declared: usize = 0;
let mut evidence = Map::new();
let groups_hit: Vec<&'static str> = Vec::new();
let groups_declared: usize = 0;
let evidence = Map::new();
let paths: Vec<&str> = surface
.get("affected_paths")
@@ -510,34 +544,24 @@ pub fn evaluate_applicability(
.collect();
let entities: Vec<&str> = surface.get("affected_existing_entities").map(str_list).unwrap_or_default();
let mut _check = |group: &'static str, candidates: &[&str], present: &dyn Fn(&str) -> bool| {
if candidates.is_empty() {
return;
}
groups_declared += 1;
let hits: Vec<&str> = candidates.iter().filter(|c| present(c)).copied().collect();
if !hits.is_empty() {
groups_hit.push(group);
evidence.insert(group.to_string(), json!(hits.iter().take(5).collect::<Vec<_>>()));
}
};
let mut tally = SignalTally { groups_declared, groups_hit, evidence };
let surface_kinds = signals.get("surface_kinds").map(str_list).unwrap_or_default();
_check("surface_kinds", &surface_kinds, &|c| surface_kind_present(c, surface));
_check(&mut tally, "surface_kinds", &surface_kinds, &|c| surface_kind_present(c, surface));
let path_signals = signals.get("path_contains").map(str_list).unwrap_or_default();
_check("path_contains", &path_signals, &|c| paths.iter().any(|p| _path_matches(c, p)));
_check(&mut tally, "path_contains", &path_signals, &|c| paths.iter().any(|p| _path_matches(c, p)));
let entity_signals = signals.get("entities_match").map(str_list).unwrap_or_default();
_check("entities_match", &entity_signals, &|c| entities.iter().any(|e| _entity_matches(c, e)));
_check(&mut tally, "entities_match", &entity_signals, &|c| entities.iter().any(|e| _entity_matches(c, e)));
let objective_words: Vec<String> =
objective.replace('/', " ").split_whitespace().map(|w| w.to_lowercase()).collect();
let objective_signals_owned: Vec<String> =
signals.get("objective_any").map(str_list).unwrap_or_default().into_iter().map(str::to_lowercase).collect();
let objective_signals: Vec<&str> = objective_signals_owned.iter().map(String::as_str).collect();
_check("objective_any", &objective_signals, &|c| objective_words.iter().any(|w| w == c));
_check(&mut tally, "objective_any", &objective_signals, &|c| objective_words.iter().any(|w| w == c));
if let Some(contracts) = signals.get("contracts_match").and_then(|v| v.as_array()) {
if !contracts.is_empty() {
groups_declared += 1;
tally.groups_declared += 1;
let wanted: Vec<&str> = contracts.iter().filter_map(|c| c.as_str()).collect();
let hits: Vec<String> = authorities
.values()
@@ -549,12 +573,13 @@ pub fn evaluate_applicability(
.map(|(e, to)| format!("{e}->{to}"))
.collect();
if !hits.is_empty() {
groups_hit.push("contracts_match");
evidence.insert("contracts_match".into(), json!(hits.iter().take(5).collect::<Vec<_>>()));
tally.record_hits("contracts_match", hits.iter().take(5).map(|s| s.as_str()).collect());
}
}
}
let SignalTally { groups_declared, groups_hit, evidence } = tally;
if groups_declared == 0 {
return json!({
"pattern": pattern_id,
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
+1
View File
@@ -0,0 +1 @@
0
@@ -0,0 +1 @@
0
+27
View File
@@ -0,0 +1,27 @@
# construction_pattern Phase B (gap-close language-advantage pass) — verification summary
Follows feat 1ad658cf (gap-close to FULL 13/13) on the same contract
BUILDER-2026-10-13T13:18:48Z-5b5364-factory-gap-cp (closed; evidence
refreshed separately to cite this SHA). Behavior-preserving by battery:
- `SignalTally` struct + free `fn _check` — the evaluate_applicability
closure's three nonlocal accumulators as one struct (house tally style;
contracts_match records through `record_hits` too).
- `_surface_text` zero-copy tokens — `BTreeSet<&str>` borrowing the input
JSON + one lowered objective; per-token String allocations eliminated
(UTF-8 byte order == code-point order, so the sorted projection is
byte-identical to `sorted(set)`).
- `_need_dict` — `Map::with_capacity(3)` envelope preallocation.
## Commands and exit codes (all in this worktree, post-edit)
| Check | Command | Exit |
|---|---|---|
| cargo battery | `cargo test --release` | 0 — 14/14 (`verification/cp-phaseb-cargo-test.{log,exit}`) |
| clippy | `cargo clippy --all-targets -- -D warnings` | 0 (`verification/cp-phaseb-clippy.*`) |
| harness truth | `PYTHONPATH=src python3 scripts/freeze_truth.py --verify src/rust/construction_pattern/frozen_truth.json --module rune.construction_pattern` | 0 — 18 cases byte-identical |
| live parity | `PYTHONPATH=src python3 scripts/check_construction_pattern_parity.py` | 0 — 192/192 both pins |
| pytest (python pin) | `RUNE_CP_CORE=python pytest tests/test_construction_pattern.py` | 0 — 30/30 |
| pytest (auto/kernel) | module + consumers (contextual_construction, project_build_lifecycle) | 0 — 66/66 |
Audit row: construction_pattern 13/13 FULL (missing: none).