sol: sol-lane triage manifest for 2026-11-01 re-derived from live wizard-work/sol tree
This commit is contained in:
1 parent
fd1adb600c
commit
0e4b391680
5 files changed
+4006
No files matched your search
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
# CHECK -- sol: sol-lane triage manifest for 2026-11-01 (forge: sol lane).
|
||||
# Exit 0 iff the committed manifest re-derives from the frozen seed by the
|
||||
# rubric and every frozen path exists as a real, non-ignored file in the repo.
|
||||
set -u
|
||||
|
||||
# Resolves the repo root from THIS script's own location, so the gate works
|
||||
# no matter what the caller's working directory is (the previous version did
|
||||
# `cd "$(dirname ...)"` which silently ran python3 from the wrong cwd).
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR" && pwd)"
|
||||
cd "$REPO_ROOT" || exit 2
|
||||
|
||||
exec python3 wizard-work/sol/verify_sol_lane_triage_2026_11_01.py
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generator for the sol-lane triage artifact for 2026-11-01.
|
||||
|
||||
Classifies every file under wizard-work/sol/ by a fixed rubric (extension +
|
||||
content sniff). Emits a frozen seed (per-file evidence) and a manifest.
|
||||
|
||||
Writes both a repo copy (wizard-work/sol/) and the Hermes copy
|
||||
/root/.hermes/wizard-outputs/sol/.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent.parent
|
||||
SRC = REPO / "wizard-work" / "sol"
|
||||
HERMES_OUT = Path("/root/.hermes/wizard-outputs/sol")
|
||||
DATE = "2026-11-01"
|
||||
|
||||
# Rubric: extension -> category. Pure function of the lowercased extension.
|
||||
RULER = {
|
||||
"md": "text", "txt": "text", "rst": "text", "adoc": "text", "org": "text", "log": "text",
|
||||
"json": "data", "csv": "data", "tsv": "data", "yaml": "data", "yml": "data", "toml": "data",
|
||||
"sqlite": "data", "db": "data", "ipynb": "data",
|
||||
"mp3": "media", "wav": "media", "mp4": "media", "webm": "media", "png": "media",
|
||||
"jpg": "media", "jpeg": "media", "gif": "media", "webp": "media", "svg": "media",
|
||||
"py": "script", "sh": "script", "bash": "script", "zsh": "script", "ps1": "script", "bat": "script",
|
||||
"pdf": "doc", "doc": "doc", "docx": "doc", "ppt": "doc", "pptx": "doc", "xls": "doc", "xlsx": "doc",
|
||||
}
|
||||
|
||||
KNOWN_MAGICS = {
|
||||
"png": b"\x89PNG", "gif": b"GIF8", "jpg": b"\xff\xf0", "webp": b"WEBP", "svg": b"<?xml",
|
||||
"zip/pptx": b"PK\x03\x04", "db": b"SQLite", "sqlite": b"SQLite",
|
||||
}
|
||||
|
||||
|
||||
def classify(rel: str) -> str:
|
||||
"""Return the category for a file given its path relative to SRC."""
|
||||
base = rel.rsplit("/", 1)[-1]
|
||||
ext = base.rsplit(".", 1)[1].lower() if "." in base else ""
|
||||
if ext in RULER:
|
||||
return RULER[ext]
|
||||
# Content-sniff fallback for extensions the ruler has no entry for.
|
||||
p = REPO / rel
|
||||
try:
|
||||
with p.open("rb") as fh:
|
||||
head = fh.read(1024)
|
||||
except OSError:
|
||||
return "other"
|
||||
for key, magic in KNOWN_MAGICS.items():
|
||||
if head.startswith(magic):
|
||||
return {"png": "media", "gif": "media", "jpg": "media", "webp": "media",
|
||||
"svg": "text", "zip/pptx": "doc", "db": "data", "sqlite": "data"}[key]
|
||||
try:
|
||||
head.decode("utf-8")
|
||||
return "text"
|
||||
except UnicodeDecodeError:
|
||||
return "data"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
out = subprocess.run(
|
||||
["git", "-C", str(REPO), "ls-files", "wizard-work/sol/"],
|
||||
capture_output=True, text=True, check=True,
|
||||
).stdout
|
||||
files = [ln for ln in out.splitlines() if ln.strip()]
|
||||
if not files:
|
||||
print("ERROR: no tracked files under wizard-work/sol/", file=subprocess.stderr)
|
||||
return 1
|
||||
|
||||
records = []
|
||||
for rel in files:
|
||||
# rel is git-ls-files relative to the repo root; store the
|
||||
# wizard-work/sol/-relative path like the existing convention.
|
||||
src_rel = rel.split("wizard-work/sol/", 1)[1]
|
||||
records.append({"rel": src_rel,
|
||||
"ext": src_rel.rsplit(".", 1)[1].lower() if "." in src_rel.rsplit("/", 1)[-1] else "",
|
||||
"category": classify(rel)})
|
||||
|
||||
by_category = {}
|
||||
by_dir = {}
|
||||
for r in records:
|
||||
by_category[r["category"]] = by_category.get(r["category"], 0) + 1
|
||||
by_dir[r["rel"]] = by_dir.get(r["rel"], 0) + 1
|
||||
|
||||
seed = {"date": DATE, "source": "git ls-files wizard-work/sol/", "files": records}
|
||||
manifest = {
|
||||
"date": DATE,
|
||||
"source": "git ls-files wizard-work/sol/",
|
||||
"total_files": len(records),
|
||||
"by_category": by_category,
|
||||
"by_dir": by_dir,
|
||||
"files": records,
|
||||
}
|
||||
|
||||
repo_files = {
|
||||
"seed": SRC / f"sol-lane-triage-seed-{DATE}.json",
|
||||
"manifest": SRC / f"sol-lane-triage-{DATE}.json",
|
||||
"hermes": HERMES_OUT / f"sol-lane-triage-{DATE}.json",
|
||||
"hermes_seed": HERMES_OUT / f"sol-lane-triage-seed-{DATE}.json",
|
||||
}
|
||||
for p in (repo_files["seed"], repo_files["manifest"], repo_files["hermes"], repo_files["hermes_seed"]):
|
||||
p.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
repo_files["seed"].write_text(json.dumps(seed, indent=2) + "\n", encoding="utf-8")
|
||||
repo_files["manifest"].write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
||||
repo_files["hermes_seed"].write_text(json.dumps(seed, indent=2) + "\n", encoding="utf-8")
|
||||
repo_files["hermes"].write_text(json.dumps(manifest, indent=2) + "\n", encoding="utf-8")
|
||||
|
||||
print(f"WROTE {repo_files['manifest']}")
|
||||
print(f"WROTE {repo_files['seed']}")
|
||||
print(f"HERMES: {repo_files['hermes']}")
|
||||
print(f"HERMES seed: {repo_files['hermes_seed']}")
|
||||
print("categories:", by_category)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent verifier for the sol-lane triage artifact (2026-11-01).
|
||||
|
||||
Exit 0 iff the committed manifest re-derives from the frozen seed by the
|
||||
rubric, and every frozen path still exists as a real, non-ignored file in
|
||||
the repo.
|
||||
|
||||
Design (independent of the generator): this verifier re-reads only the seed
|
||||
and the committed manifest, applies the rubric table below to each recorded
|
||||
extension, and compares. It also confirms that every frozen path resolves
|
||||
to a real file under the repo and is not ignored by .gitignore.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent.parent
|
||||
SRC = REPO / "wizard-work" / "sol"
|
||||
SEED = REPO / "wizard-work" / "sol" / "sol-lane-triage-seed-2026-11-01.json"
|
||||
MANIFEST = REPO / "wizard-work" / "sol" / "sol-lane-triage-2026-11-01.json"
|
||||
|
||||
# Rubric re-embedded here so the verifier does not import the generator.
|
||||
RULER = {
|
||||
"md": "text", "txt": "text", "rst": "text", "adoc": "text", "org": "text", "log": "text",
|
||||
"json": "data", "csv": "data", "tsv": "data", "yaml": "data", "yml": "data", "toml": "data",
|
||||
"sqlite": "data", "db": "data", "ipynb": "data",
|
||||
"mp3": "media", "wav": "media", "mp4": "media", "webm": "media", "png": "media",
|
||||
"jpg": "media", "jpeg": "media", "gif": "media", "webp": "media", "svg": "media",
|
||||
"py": "script", "sh": "script", "bash": "script", "zsh": "script", "ps1": "script", "bat": "script",
|
||||
"pdf": "doc", "doc": "doc", "docx": "doc", "ppt": "doc", "pptx": "doc", "xls": "doc", "xlsx": "doc",
|
||||
}
|
||||
# Content sniff for extensions the ruler has no entry for.
|
||||
KNOWN_MAGICS = {
|
||||
"png": b"\x89PNG", "gif": b"GIF8", "jpg": b"\xff\xf0", "webp": b"WEBP", "svg": b"<?xml",
|
||||
"zip/pptx": b"PK\x03\x04", "db": b"SQLite", "sqlite": b"SQLite",
|
||||
}
|
||||
|
||||
|
||||
def expected_category(rel: str, ext: str) -> str:
|
||||
if ext in RULER:
|
||||
return RULER[ext]
|
||||
p = SRC / rel
|
||||
try:
|
||||
with p.open("rb") as fh:
|
||||
head = fh.read(1024)
|
||||
except OSError:
|
||||
return "other"
|
||||
for key, magic in KNOWN_MAGICS.items():
|
||||
if head.startswith(magic):
|
||||
return {"png": "media", "gif": "media", "jpg": "media", "webp": "media",
|
||||
"svg": "text", "zip/pptx": "doc", "db": "data", "sqlite": "data"}[key]
|
||||
try:
|
||||
head.decode("utf-8")
|
||||
return "text"
|
||||
except UnicodeDecodeError:
|
||||
return "data"
|
||||
|
||||
|
||||
def is_ignored(rel: str) -> bool:
|
||||
res = subprocess.run(
|
||||
["git", "-C", str(REPO), "check-ignore", "-q", "--", rel],
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
||||
)
|
||||
return res.returncode == 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
problems = []
|
||||
if not SEED.exists():
|
||||
print(f"PROBLEM: seed missing: {SEED}")
|
||||
return 1
|
||||
if not MANIFEST.exists():
|
||||
print(f"PROBLEM: manifest missing: {MANIFEST}")
|
||||
return 1
|
||||
|
||||
seed = json.loads(SEED.read_text(encoding="utf-8"))
|
||||
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
|
||||
files = seed.get("files", [])
|
||||
mfiles = manifest.get("files", [])
|
||||
|
||||
# 1. Manifest file set must match the frozen seed exactly.
|
||||
seed_paths = {f["rel"] for f in files}
|
||||
m_paths = {f["rel"] for f in mfiles}
|
||||
if seed_paths != m_paths:
|
||||
problems.append(f"manifest path set != seed: seed={len(seed_paths)} manifest={len(m_paths)}")
|
||||
|
||||
# 2. Every category must re-derive by the rule from the recorded extension.
|
||||
for f in files:
|
||||
rel, ext, recorded = f["rel"], f["ext"], f["category"]
|
||||
exp = expected_category(rel, ext)
|
||||
if exp != recorded:
|
||||
problems.append(f"category mismatch {rel}: ruler says {exp}, manifest says {recorded}")
|
||||
|
||||
# 3. Every frozen path must still exist as a real file and not be ignored.
|
||||
for f in files:
|
||||
p = SRC / f["rel"]
|
||||
if not p.is_file():
|
||||
problems.append(f"missing on disk: {f['rel']}")
|
||||
elif is_ignored(f["rel"]):
|
||||
problems.append(f"ignored by .gitignore: {f['rel']}")
|
||||
|
||||
# 4. Aggregate counts must be self-consistent.
|
||||
counts = {}
|
||||
for f in files:
|
||||
counts[f["category"]] = counts.get(f["category"], 0) + 1
|
||||
if manifest.get("total_files") != len(files):
|
||||
problems.append(f"total_files {manifest.get('total_files')} != seed {len(files)}")
|
||||
if counts != manifest.get("by_category"):
|
||||
problems.append(f"by_category mismatch: seed={counts} manifest={manifest.get('by_category')}")
|
||||
|
||||
if problems:
|
||||
print(f"VERIFY FAIL ({len(problems)} problems)")
|
||||
for pb in problems:
|
||||
print(f" - {pb}")
|
||||
return 1
|
||||
print(f"VERIFY OK ({len(files)} files, categories re-derived, all paths present)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user