refactor(task_gate): Phase B language-advantage pass — dichotomy wave
CI Pipeline / best-practices (push) Successful in 7s
CI Pipeline / documentation (push) Successful in 7s
CI Pipeline / rust-surface (push) Failing after 14s
CI Pipeline / required-checks (push) Canceled after 0s
CI Pipeline / CI Pipeline / notify-event-bridge (push) Canceled after 0s
CI Pipeline / go-surface (push) Canceled after 17s
CI Pipeline / canary (push) Canceled after 20s
CI Pipeline / type-check (push) Canceled after 11s
CI Pipeline / gitea-offline (push) Canceled after 10s
Auto-version and Release / release (push) Canceled after 27s
deploy / deploy (push) Canceled after 6s
CI Pipeline / unit-tests (push) Canceled after 25s
CI Pipeline / lint (push) Canceled after 26s

This commit is contained in:
Nick committed 2026-10-12 01:41:07 +01:00
1 parent b20a74badb
commit fa72a60d95
1 file changed
+137 -42
+137 -42
View File
@@ -156,12 +156,83 @@ fn py_regex_matches(pattern: &str, text: &str) -> bool {
.unwrap_or(false)
}
fn row_str<'a>(row: &'a Value, key: &str) -> &'a str {
row.get(key).and_then(Value::as_str).unwrap_or("")
// ── typed row boundary (Phase B) ─────────────────────────────────────────────
/// The oracle's status lattice. Rows carry free-text statuses (sqlite TEXT),
/// so the lattice is open at the tail — but every comparison the oracle
/// makes (`!= 'retired'` in record, `== 'active'` in check) is exhaustive
/// here, and `Other` keeps unknown values pass-through exactly like the
/// oracle's string comparisons do.
enum GateStatus<'a> {
Observing,
Active,
Retired,
/// Any non-lattice TEXT value: consulted by record (the oracle only
/// excludes 'retired') and ignored by check (only 'active' projects).
Other(#[allow(dead_code)] &'a str),
}
fn row_i64(row: &Value, key: &str) -> i64 {
row.get(key).and_then(Value::as_i64).unwrap_or(0)
impl GateStatus<'_> {
fn parse(s: &str) -> GateStatus<'_> {
match s {
"observing" => GateStatus::Observing,
"active" => GateStatus::Active,
"retired" => GateStatus::Retired,
other => GateStatus::Other(other),
}
}
/// record_instruction consults non-retired rows only.
fn is_matchable(&self) -> bool {
!matches!(self, GateStatus::Retired)
}
/// check_context projects active rows only.
fn is_active(&self) -> bool {
matches!(self, GateStatus::Active)
}
}
/// Borrowed, typed view of one instruction row — zero-copy &str accessors
/// over the facade's row doc (Phase B: no per-row String churn).
struct GateRow<'a> {
id: i64,
pattern: &'a str,
instruction: &'a str,
count: i64,
threshold: i64,
status: GateStatus<'a>,
}
impl GateRow<'_> {
fn from_doc(row: &Value) -> GateRow<'_> {
let s = |k: &str| row.get(k).and_then(Value::as_str).unwrap_or("");
GateRow {
id: row.get("id").and_then(Value::as_i64).unwrap_or(0),
pattern: s("pattern"),
instruction: s("instruction"),
count: row.get("count").and_then(Value::as_i64).unwrap_or(0),
threshold: row.get("threshold").and_then(Value::as_i64).unwrap_or(0),
status: GateStatus::parse(s("status")),
}
}
}
/// The record verdict before JSON rendering (Phase B: the decision lattice
/// is an enum, the boundary match is exhaustive).
enum RecordVerdict<'a> {
Matched {
id: i64,
new_count: i64,
promoted: bool,
new_status: &'static str,
now: &'a str,
},
NewRow {
instruction: &'a str,
pattern: String,
now: &'a str,
},
}
// ── public functions (name-preserving ports of the oracle) ──────────────────
@@ -175,41 +246,64 @@ pub fn record_instruction(rows: &[Value], text: &str, now: &str) -> Value {
let lowered = text.to_lowercase();
let lowered = lowered.trim();
for row in rows {
if row_str(row, "status") == "retired" {
continue;
}
if py_regex_matches(row_str(row, "pattern"), lowered) {
let new_count = row_i64(row, "count") + 1;
let status = row_str(row, "status");
let new_status = if new_count >= row_i64(row, "threshold") {
"active"
} else {
"observing"
};
return json!({
"matched": true,
"id": row_i64(row, "id"),
"count": new_count,
"status": new_status,
"promoted": new_status == "active" && status != "active",
"last_seen": now,
});
}
}
let verdict = rows
.iter()
.map(GateRow::from_doc)
.find(|row| row.status.is_matchable() && py_regex_matches(row.pattern, lowered))
.map(|row| match row.count + 1 >= row.threshold {
true => RecordVerdict::Matched {
id: row.id,
new_count: row.count + 1,
promoted: !matches!(row.status, GateStatus::Active),
new_status: "active",
now,
},
false => RecordVerdict::Matched {
id: row.id,
new_count: row.count + 1,
promoted: false,
new_status: "observing",
now,
},
})
.unwrap_or_else(|| RecordVerdict::NewRow {
instruction: text,
pattern: extract_pattern(lowered),
now,
});
json!({
"matched": false,
"new_row": {
"instruction": text,
"pattern": extract_pattern(lowered),
"count": 1,
"threshold": 3,
"status": "observing",
"created_at": now,
match verdict {
RecordVerdict::Matched {
id,
new_count,
promoted,
new_status,
now,
} => json!({
"matched": true,
"id": id,
"count": new_count,
"status": new_status,
"promoted": promoted,
"last_seen": now,
},
})
}),
RecordVerdict::NewRow {
instruction,
pattern,
now,
} => json!({
"matched": false,
"new_row": {
"instruction": instruction,
"pattern": pattern,
"count": 1,
"threshold": 3,
"status": "observing",
"created_at": now,
"last_seen": now,
},
}),
}
}
/// task_gate.check_context — project the ACTIVE gates whose pattern matches
@@ -220,13 +314,14 @@ pub fn check_context(rows: &[Value], context: &str) -> Value {
let lowered = context.to_lowercase();
let matches: Vec<Value> = rows
.iter()
.filter(|row| row_str(row, "status") == "active")
.filter(|row| py_regex_matches(row_str(row, "pattern"), &lowered))
.map(GateRow::from_doc)
.filter(|row| row.status.is_active())
.filter(|row| py_regex_matches(row.pattern, &lowered))
.map(|row| {
json!({
"id": row_i64(row, "id"),
"instruction": row_str(row, "instruction"),
"count": row_i64(row, "count"),
"id": row.id,
"instruction": row.instruction,
"count": row.count,
})
})
.collect();