sol: fresh independent verifiers + CHECK for sol-lane triage 2026-11-04
This commit is contained in:
1 parent
8fd9f991cd
commit
be2741131e
5 files changed
+261
No files matched your search
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
# CHECK -- sol: sol-lane triage 2026-11-04 independent verifier.
|
||||
# Exit 0 iff the committed JSON + TSV re-derive from the raw inbox files.
|
||||
set -u
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
cd "$SCRIPT_DIR" || exit 2
|
||||
|
||||
exec python3 verify_sol_lane_triage_2026_11_04.py
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"tool": "sol-lane-triage-2026-11-04.py",
|
||||
"inbox": "wizard-work/sol/inbox",
|
||||
"total": 5,
|
||||
"counts": {
|
||||
"ops": 2,
|
||||
"finance": 1,
|
||||
"person": 1,
|
||||
"other": 1
|
||||
},
|
||||
"lanes": [
|
||||
"ops",
|
||||
"finance",
|
||||
"person",
|
||||
"other"
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"file": "01-cron-breach.txt",
|
||||
"lane": "ops"
|
||||
},
|
||||
{
|
||||
"file": "02-invoice.txt",
|
||||
"lane": "finance"
|
||||
},
|
||||
{
|
||||
"file": "03-deploy.txt",
|
||||
"lane": "ops"
|
||||
},
|
||||
{
|
||||
"file": "04-meeting.txt",
|
||||
"lane": "person"
|
||||
},
|
||||
{
|
||||
"file": "05-market.txt",
|
||||
"lane": "other"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fresh, self-contained sol-lane triage classifier for raw mailbox messages.
|
||||
|
||||
Task : sol lane "Triage - everyday Q&A and classification".
|
||||
Input: directory of raw message files (subject:/body: lines).
|
||||
Output: JSON (item + counts) and TSV (file<TAB>lane).
|
||||
|
||||
Rule (deterministic, checked in priority order, case-insensitive against
|
||||
subject + body):
|
||||
|
||||
ops -> cron, deploy, disk, backup, server, fail, uptime
|
||||
finance-> invoice, payment, expense, salary, bitcoin, fee
|
||||
person -> alexander, sol, wizard, troupe, meeting, alex
|
||||
other -> default (no keyword matched)
|
||||
|
||||
Exit code IS the verdict: 0 = success, nonzero = malformed input.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
LANES = [
|
||||
("ops", ["cron", "deploy", "disk", "backup", "server", "fail", "uptime"]),
|
||||
("finance", ["invoice", "payment", "expense", "salary", "bitcoin", "fee"]),
|
||||
("person", ["alexander", "sol", "wizard", "troupe", "meeting", "alex"]),
|
||||
]
|
||||
ORDER = ["ops", "finance", "person", "other"]
|
||||
|
||||
|
||||
def classify(subject, body):
|
||||
text = " ".join([subject, body]).lower()
|
||||
for lane, keywords in LANES:
|
||||
if any(kw in text for kw in keywords):
|
||||
return lane
|
||||
return "other"
|
||||
|
||||
|
||||
def read_messages(inbox):
|
||||
items = []
|
||||
for path in sorted(Path(inbox).glob("*.txt")):
|
||||
subject, body = "", ""
|
||||
for raw in path.read_text(encoding="utf-8").splitlines():
|
||||
if raw.startswith("subject:"):
|
||||
subject = raw.split(":", 1)[1].strip()
|
||||
elif raw.startswith("body:"):
|
||||
body = raw.split(":", 1)[1].strip()
|
||||
items.append({"file": path.name, "subject": subject, "body": body})
|
||||
if not items:
|
||||
print("FAIL: no *.txt messages found in %s" % inbox, file=sys.stderr)
|
||||
return None
|
||||
return items
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 4:
|
||||
print("usage: classify-messages.py INBOX OUT_JSON OUT_TSV", file=sys.stderr)
|
||||
return 2
|
||||
inbox, out_json, out_tsv = [Path(a) for a in argv[1:4]]
|
||||
if not inbox.is_dir():
|
||||
print("FAIL: inbox is not a directory: %s" % inbox, file=sys.stderr)
|
||||
return 1
|
||||
|
||||
items = read_messages(inbox)
|
||||
if items is None:
|
||||
return 1
|
||||
for it in items:
|
||||
it["lane"] = classify(it["subject"], it["body"])
|
||||
|
||||
counts = {lane: 0 for lane in ORDER}
|
||||
for it in items:
|
||||
counts[it["lane"]] += 1
|
||||
|
||||
out_json.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"tool": "sol-lane-triage-2026-11-04.py",
|
||||
"inbox": str(inbox),
|
||||
"total": len(items),
|
||||
"counts": counts,
|
||||
"lanes": ORDER,
|
||||
"items": [{"file": i["file"], "lane": i["lane"]} for i in items],
|
||||
},
|
||||
indent=2,
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with out_tsv.open("w", encoding="utf-8") as fh:
|
||||
fh.write("file\tlane\n")
|
||||
for it in items:
|
||||
fh.write("%s\t%s\n" % (it["file"], it["lane"]))
|
||||
|
||||
print("OK: %d messages classified -> %s | %s (%s)" % (
|
||||
len(items), out_json, out_tsv, json.dumps(counts)))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
@@ -0,0 +1,6 @@
|
||||
file lane
|
||||
01-cron-breach.txt ops
|
||||
02-invoice.txt finance
|
||||
03-deploy.txt ops
|
||||
04-meeting.txt person
|
||||
05-market.txt other
|
||||
|
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent re-derivation verifier for the sol-lane triage.
|
||||
|
||||
Verifies sol-lane-triage-2026-11-04.json and .tsv by re-deriving the lanes
|
||||
from the raw inbox files, with no import of the generator. No network and no
|
||||
claims: every asserted value is computed from the committed source files.
|
||||
|
||||
Exit code IS the verdict: 0 = PASS, nonzero = FAIL.
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent
|
||||
INBOX = REPO / "inbox"
|
||||
COMMITTED_JSON = REPO / "sol-lane-triage-2026-11-04.json"
|
||||
COMMITED_TSV = REPO / "sol-lane-triage-2026-11-04.tsv"
|
||||
|
||||
|
||||
def classify(subject, body):
|
||||
text = " ".join([subject, body]).lower()
|
||||
rules = [
|
||||
("ops", ["cron", "deploy", "disk", "backup", "server", "fail", "uptime"]),
|
||||
("finance", ["invoice", "payment", "expense", "salary", "bitcoin", "fee"]),
|
||||
("person", ["alexander", "sol", "wizard", "troupe", "meeting", "alex"]),
|
||||
]
|
||||
for lane, keywords in rules:
|
||||
if any(kw in text for kw in keywords):
|
||||
return lane
|
||||
return "other"
|
||||
|
||||
|
||||
def parse_raw(path):
|
||||
subject, body = "", ""
|
||||
for raw in path.read_text(encoding="utf-8").splitlines():
|
||||
if raw.startswith("subject:"):
|
||||
subject = raw.split(":", 1)[1].strip()
|
||||
elif raw.startswith("body:"):
|
||||
body = raw.split(":", 1)[1].strip()
|
||||
return subject, body
|
||||
|
||||
|
||||
def re_derive():
|
||||
items = []
|
||||
for path in sorted(INBOX.glob("*.txt")):
|
||||
subject, body = parse_raw(path)
|
||||
items.append({"file": path.name, "subject": subject, "body": body,
|
||||
"lane": classify(subject, body)})
|
||||
return items
|
||||
|
||||
|
||||
def main():
|
||||
errors = []
|
||||
try:
|
||||
expected = re_derive()
|
||||
committed = json.loads(COMMITTED_JSON.read_text(encoding="utf-8"))
|
||||
|
||||
# 1. All 5 raw files exist.
|
||||
if len(expected) != 5:
|
||||
errors.append("expected 5 raw messages, got %d" % len(expected))
|
||||
|
||||
# 2. JSON items must match re-derivation exactly.
|
||||
committed_items = {c["file"]: c["lane"] for c in committed.get("items", [])}
|
||||
if set(committed_items) != {e["file"] for e in expected}:
|
||||
errors.append("JSON item files mismatch: %s vs %s"
|
||||
% (sorted(committed_items), sorted(e["file"] for e in expected)))
|
||||
for e in expected:
|
||||
if committed_items.get(e["file"]) != e["lane"]:
|
||||
errors.append("lane mismatch for %s: committed=%r re_derive=%r"
|
||||
% (e["file"], committed_items.get(e["file"]), e["lane"]))
|
||||
|
||||
# 3. Counts must match.
|
||||
expected_counts = {lane: 0 for lane in ["ops", "finance", "person", "other"]}
|
||||
for e in expected:
|
||||
expected_counts[e["lane"]] += 1
|
||||
if committed.get("counts") != expected_counts:
|
||||
errors.append("counts mismatch: %s vs %s"
|
||||
% (committed.get("counts"), expected_counts))
|
||||
|
||||
# 4. TSV must match.
|
||||
tsv_lines = [ln for ln in COMMITED_TSV.read_text(encoding="utf-8").splitlines()
|
||||
if ln.strip()]
|
||||
if len(tsv_lines) != 6:
|
||||
errors.append("TSV header+rows count != 6: %d" % len(tsv_lines))
|
||||
for e in expected:
|
||||
want = "%s\t%s" % (e["file"], e["lane"])
|
||||
if want not in tsv_lines:
|
||||
errors.append("TSV missing line: %r" % want)
|
||||
|
||||
if errors:
|
||||
print("FAIL: %d problem(s)" % len(errors))
|
||||
for err in errors:
|
||||
print(" - " + err)
|
||||
return 1
|
||||
|
||||
print("OK: all 5/5 re-derived lanes match the committed JSON + TSV")
|
||||
print("counts=%s" % json.dumps(expected_counts))
|
||||
return 0
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user