sol: add demands class triage 2026-10-31
This commit is contained in:
1 parent
46ed920871
commit
794e21ba43
3 files changed
+206
No files matched your search
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# CHECK -- sol: demands class triage 2026-10-31 (forge: verify lane).
|
||||
# Exit 0 iff the committed Demands-ClassTriage-2026-10-31.json re-derives from
|
||||
# the frozen demands.json evidence via the independent verifier above.
|
||||
set -u
|
||||
|
||||
cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1
|
||||
# The script sits in wizard-work/sol/, two levels below the repo root.
|
||||
REPO_ROOT="$(cd ../.. && pwd)"
|
||||
cd "$REPO_ROOT" || exit 1
|
||||
|
||||
exec python3 wizard-work/sol/verify_demands_class_triage_2026_10_31.py
|
||||
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"generated_utc": "2026-10-31T06:10:42Z",
|
||||
"source": "/root/troupe-standup/wizard-work/sol/demands.json",
|
||||
"seed_sha256": "209a13c57183217e23e36e9c958213848063e94961fe638a723efe9f0e1b5ff0",
|
||||
"count": 8,
|
||||
"categories": {
|
||||
"ops": 4,
|
||||
"admin": 2,
|
||||
"archive": 1,
|
||||
"support": 1
|
||||
},
|
||||
"rubric": {
|
||||
"support": [
|
||||
"how does",
|
||||
"how can",
|
||||
"explain",
|
||||
"what is"
|
||||
],
|
||||
"archive": [
|
||||
"closed",
|
||||
"turned off",
|
||||
"went stale",
|
||||
"removed",
|
||||
"done"
|
||||
],
|
||||
"admin": [
|
||||
"summarize",
|
||||
"cost",
|
||||
"choose",
|
||||
"provider",
|
||||
"quarter"
|
||||
],
|
||||
"ops": [
|
||||
"migrate",
|
||||
"fix",
|
||||
"deploy",
|
||||
"send",
|
||||
"run",
|
||||
"watch",
|
||||
"approve",
|
||||
"smoke"
|
||||
]
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"id": "D1",
|
||||
"category": "ops"
|
||||
},
|
||||
{
|
||||
"id": "D2",
|
||||
"category": "ops"
|
||||
},
|
||||
{
|
||||
"id": "D3",
|
||||
"category": "admin"
|
||||
},
|
||||
{
|
||||
"id": "D4",
|
||||
"category": "ops"
|
||||
},
|
||||
{
|
||||
"id": "D5",
|
||||
"category": "archive"
|
||||
},
|
||||
{
|
||||
"id": "D6",
|
||||
"category": "support"
|
||||
},
|
||||
{
|
||||
"id": "D7",
|
||||
"category": "admin"
|
||||
},
|
||||
{
|
||||
"id": "D8",
|
||||
"category": "ops"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent verifier for wizard-work/sol/Demands-ClassTriage-2026-10-31.json.
|
||||
|
||||
Exit 0 iff the committed artifact re-derives every category for the 8 demands
|
||||
straight off the frozen seed evidence (demands.json), using an embedded
|
||||
keyword rubric that is a deliberately different expression shape from the
|
||||
builder. Also checks the self-derived counts, the seed sha256 and the count
|
||||
field match the self-derived values. Exit code IS the verdict: 0 = correct,
|
||||
nonzero = wrong.
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
REPO = HERE.parent.parent
|
||||
DEMANDS = REPO / "wizard-work" / "sol" / "demands.json"
|
||||
ART = HERE / "Demands-ClassTriage-2026-10-31.json"
|
||||
|
||||
|
||||
def re_derive(t: str) -> str:
|
||||
"""Independent re-derivation: a flat list of (category, keyword) pairs,
|
||||
scanned in order. Deliberately a different expression shape than the
|
||||
builder (which nests the same lists in a dict + if/elif chain)."""
|
||||
low = (t or "").strip().lower()
|
||||
for cat in ("support", "archive", "admin", "ops"):
|
||||
for kw in RUBRIC[cat]:
|
||||
if kw in low:
|
||||
return cat
|
||||
return "other"
|
||||
|
||||
|
||||
RUBRIC = {
|
||||
"support": ("how does", "how can", "explain", "what is"),
|
||||
"archive": ("closed", "turned off", "went stale", "removed", "done"),
|
||||
"admin": ("summarize", "cost", "choose", "provider", "quarter"),
|
||||
"ops": ("migrate", "fix", "deploy", "send", "run", "watch", "approve", "smoke"),
|
||||
}
|
||||
|
||||
|
||||
def expected(seed) -> dict[str, str]:
|
||||
out = {}
|
||||
for it in seed.get("demands", []):
|
||||
out[it["id"]] = re_derive(it.get("text", ""))
|
||||
return out
|
||||
|
||||
|
||||
def main() -> int:
|
||||
problems = []
|
||||
seed = None
|
||||
art = None
|
||||
|
||||
if not DEMANDS.exists():
|
||||
problems.append("frozen demands seed missing: %s" % DEMANDS)
|
||||
if not ART.exists():
|
||||
problems.append("artifact missing: %s" % ART)
|
||||
|
||||
if not problems:
|
||||
seed = json.loads(DEMANDS.read_text(encoding="utf-8"))
|
||||
art = json.loads(ART.read_text(encoding="utf-8"))
|
||||
|
||||
if len(seed.get("demands", [])) != 8:
|
||||
problems.append("seed demands != 8")
|
||||
|
||||
exp = expected(seed)
|
||||
got = {i["id"]: i.get("category") for i in art.get("items", [])}
|
||||
|
||||
if set(exp) != set(got):
|
||||
problems.append("id sets differ: %s vs %s"
|
||||
% (sorted(exp), sorted(got)))
|
||||
|
||||
for iid, want in sorted(exp.items()):
|
||||
if got.get(iid) != want:
|
||||
problems.append(
|
||||
"id %s: got %r, expected %r" % (iid, got.get(iid), want))
|
||||
|
||||
from collections import Counter
|
||||
|
||||
exp_items = dict(exp)
|
||||
exp_counts = dict(Counter(exp.values()))
|
||||
if art.get("categories") != exp_counts:
|
||||
problems.append(
|
||||
"categories %r != re-derived counts %r"
|
||||
% (art.get("categories"), exp_counts))
|
||||
|
||||
want_counts = {}
|
||||
for v in exp.values():
|
||||
want_counts[v] = want_counts.get(v, 0) + 1
|
||||
if art.get("categories") != want_counts:
|
||||
problems.append(
|
||||
"category counts %r != %r" % (art.get("categories"), want_counts))
|
||||
|
||||
want_sha = hashlib.sha256(DEMANDS.read_bytes()).hexdigest()
|
||||
if art.get("seed_sha256") != want_sha:
|
||||
problems.append(
|
||||
"seed_sha256 %r != %r" % (art.get("seed_sha256"), want_sha))
|
||||
|
||||
if art.get("count") != len(seed.get("demands", [])):
|
||||
problems.append("count field %r != %r"
|
||||
% (art.get("count"), len(seed.get("demands", []))))
|
||||
|
||||
if problems:
|
||||
print("FAIL")
|
||||
for p in problems:
|
||||
print(" -", p)
|
||||
return 1
|
||||
|
||||
print("PASS: Demands-ClassTriage-2026-10-31.json re-derives 8/8 demands "
|
||||
"from evidence; categories=%s" % (art.get("categories")))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user