sol: regenerate untracked-file triage census (310 files) and fix CHECK
This commit is contained in:
1 parent
479ed5e8d5
commit
e2f898a847
5 files changed
+4686
No files matched your search
@@ -0,0 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
# CHECK -- untracked-file triage classification, 2026-11-03 (sol lane).
|
||||
#
|
||||
# Grades the committed census against a fresh live re-derivation from git:
|
||||
# every untracked regular file reconciles, the extension-rubric categories
|
||||
# re-derive, and all frozen paths exist and are non-ignored. Exit code is
|
||||
# the verdict: 0 clean, 1 mismatch, 2 misuse.
|
||||
set -u
|
||||
cd "$(dirname "$(readlink -f "$0")")" || exit 2
|
||||
# Script lives in wizard-work/sol/; the repo root is two levels up.
|
||||
REPO_ROOT="$(cd .. && pwd)"
|
||||
cd "$REPO_ROOT" || exit 2
|
||||
exec python3 wizard-work/sol/verify_untracked_classify_2026_11_03.py
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate a fresh untracked-file triage census for the sol lane, 2026-11-03.
|
||||
|
||||
Re-derives the untracked universe straight from git (git ls-files
|
||||
--others --exclude-standard), classifies every real file by the extension
|
||||
rubric, writes the committed manifest + a frozen seed, and emits the same
|
||||
artifact to the shared wizard-outputs area.
|
||||
|
||||
Scope: every regular FILE reported as untracked, minus the sol output area
|
||||
(wizard-work/sol/) which the verifier never folds back in, and minus
|
||||
directory entries.
|
||||
|
||||
Exit 0 on success.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path("/root/troupe-standup")
|
||||
SRC = REPO / "wizard-work" / "sol"
|
||||
OVERWRITE = Path("/root/.hermes/wizard-outputs/sol") # shared outputs area
|
||||
|
||||
RULER = {
|
||||
# scripts
|
||||
"py": "script", "sh": "script", "bash": "script", "zsh": "script",
|
||||
"ps1": "script", "bat": "script", "fish": "script",
|
||||
# documents
|
||||
"md": "doc", "txt": "doc", "rst": "doc", "adoc": "doc", "org": "doc", "log": "doc",
|
||||
# data
|
||||
"json": "data", "jsonl": "data", "csv": "data", "tsv": "data",
|
||||
"yaml": "data", "yml": "data", "toml": "data", "db": "data",
|
||||
"sqlite": "data", "xml": "data", "ipynb": "data", "env": "data",
|
||||
# media
|
||||
"jpg": "media", "jpeg": "media", "png": "media", "gif": "media",
|
||||
"webp": "media", "svg": "media", "mp3": "media", "wav": "media",
|
||||
"mp4": "media", "webm": "media", "pdf": "media",
|
||||
}
|
||||
|
||||
|
||||
def sh(args):
|
||||
return subprocess.run(
|
||||
args, cwd=REPO, check=True, capture_output=True, text=True
|
||||
).stdout
|
||||
|
||||
|
||||
def ext_of(name):
|
||||
return name.rsplit(".", 1)[1].lower() if "." in name else ""
|
||||
|
||||
|
||||
def classify(rel):
|
||||
ext = ext_of(rel)
|
||||
if ext in RULER:
|
||||
return RULER[ext]
|
||||
# Fall back: decode a peek of the file as UTF-8.
|
||||
p = REPO.joinpath(*rel.split("/"))
|
||||
try:
|
||||
with p.open("rb") as fh:
|
||||
head = fh.read(512)
|
||||
except OSError:
|
||||
return "data"
|
||||
if b"\x00" in head:
|
||||
return "data"
|
||||
try:
|
||||
head.decode("utf-8")
|
||||
return "text"
|
||||
except UnicodeDecodeError:
|
||||
return "data"
|
||||
|
||||
|
||||
def is_regular_file(rel):
|
||||
p = REPO.joinpath(*rel.split("/"))
|
||||
return p.is_file()
|
||||
|
||||
|
||||
def live_universe():
|
||||
"""Return sorted list of untracked regular files (excluding sol output dir)."""
|
||||
proc = sh(["git", "ls-files", "--others", "--exclude-standard"])
|
||||
out = []
|
||||
for line in proc.splitlines():
|
||||
rel = line.strip()
|
||||
if not rel or rel.endswith("/"):
|
||||
continue
|
||||
if rel.startswith("wizard-work/sol/"):
|
||||
continue
|
||||
if is_regular_file(rel):
|
||||
out.append(rel)
|
||||
return sorted(out)
|
||||
|
||||
|
||||
def main():
|
||||
files = []
|
||||
for rel in live_universe():
|
||||
st = os.stat(REPO.joinpath(*rel.split("/")))
|
||||
files.append({
|
||||
"rel": rel,
|
||||
"ext": ext_of(rel),
|
||||
"category": classify(rel),
|
||||
"size": st.st_size,
|
||||
"mtime": datetime.fromtimestamp(st.st_mtime, timezone.utc).isoformat(),
|
||||
})
|
||||
|
||||
by_category = {}
|
||||
for f in files:
|
||||
by_category[f["category"]] = by_category.get(f["category"], 0) + 1
|
||||
|
||||
manifest = {
|
||||
"lane": "sol",
|
||||
"task": "untracked-file triage classification",
|
||||
"date": "2026-11-03",
|
||||
"generated_at": datetime.now(timezone.utc).isoformat(),
|
||||
"scope": "git ls-files --others --exclude-standard; excludes wizard-work/sol/ and dir entries",
|
||||
"total_files": len(files),
|
||||
"by_category": by_category,
|
||||
"category_order": ["script", "doc", "data", "media", "text"],
|
||||
"files": files,
|
||||
}
|
||||
|
||||
# Manifest + frozen seed into the committed wizard-work/sol tree.
|
||||
SRC.mkdir(parents=True, exist_ok=True)
|
||||
(SRC / "untracked-classify-2026-11-03.json").write_text(
|
||||
json.dumps(manifest, indent=2), encoding="utf-8"
|
||||
)
|
||||
json.dump({
|
||||
"generated_at": manifest["generated_at"],
|
||||
"date": manifest["date"],
|
||||
"total_files": manifest["total_files"],
|
||||
"by_category": manifest["by_category"],
|
||||
"files": manifest["files"],
|
||||
}, open(SRC / "untracked-classify-seed-2026-11-03.json", "w"), indent=2)
|
||||
|
||||
# Shared artifact into the wiz-Outputs area.
|
||||
OVERWRITE.mkdir(parents=True, exist_ok=True)
|
||||
(OVERWRITE / "untracked-classify-2026-11-03.json").write_text(
|
||||
json.dumps(manifest, indent=2), encoding="utf-8"
|
||||
)
|
||||
|
||||
print("Wrote %s with %d files; by_category=%s"
|
||||
% (SRC / "untracked-classify-2026-11-03.json", len(files), by_category))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,148 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Independent verifier for the untracked-file triage census (2026-11-03).
|
||||
|
||||
Re-derives every category from the embedded extension rubric, reconciles the
|
||||
committed manifest against a fresh live enumeration, confirms every frozen
|
||||
path exists as a real, non-ignored file, and cross-checks the aggregate
|
||||
counts.
|
||||
|
||||
Exit 0 iff all checks pass.
|
||||
"""
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path("/root/troupe-standup")
|
||||
SRC = REPO / "wizard-work" / "sol"
|
||||
MANIFEST = SRC / "untracked-classify-2026-11-03.json"
|
||||
|
||||
# Embedded rubric (must match the producer exactly).
|
||||
RULER = {
|
||||
# scripts
|
||||
"py": "script", "sh": "script", "bash": "script", "zsh": "script",
|
||||
"ps1": "script", "bat": "script", "fish": "script",
|
||||
# documents
|
||||
"md": "doc", "txt": "doc", "rst": "doc", "adoc": "doc", "org": "doc", "log": "doc",
|
||||
# data
|
||||
"json": "data", "jsonl": "data", "csv": "data", "tsv": "data",
|
||||
"yaml": "data", "yml": "data", "toml": "data", "db": "data",
|
||||
"sqlite": "data", "xml": "data", "ipynb": "data", "env": "data",
|
||||
# media
|
||||
"jpg": "media", "jpeg": "media", "png": "media", "gif": "media",
|
||||
"webp": "media", "svg": "media", "mp3": "media", "wav": "media",
|
||||
"mp4": "media", "webm": "media", "pdf": "media",
|
||||
}
|
||||
|
||||
|
||||
def extension(rel: str) -> str:
|
||||
name = rel.rsplit("/", 1)[-1]
|
||||
return name.rsplit(".", 1)[1].lower() if "." in name else ""
|
||||
|
||||
|
||||
def classify(rel: str) -> str:
|
||||
ext = extension(rel)
|
||||
if ext in RULER:
|
||||
return RULER[ext]
|
||||
p = REPO.joinpath(*rel.split("/"))
|
||||
try:
|
||||
with p.open("rb") as fh:
|
||||
head = fh.read(512)
|
||||
except OSError:
|
||||
return "data"
|
||||
if b"\x00" in head:
|
||||
return "data"
|
||||
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 live_universe():
|
||||
"""Untracked regular files as git sees them, minus the sol output dir."""
|
||||
proc = subprocess.run(
|
||||
["git", "-C", str(REPO), "ls-files", "--others", "--exclude-standard"],
|
||||
check=True, capture_output=True, text=True,
|
||||
)
|
||||
out = []
|
||||
for line in proc.stdout.splitlines():
|
||||
rel = line.strip()
|
||||
if not rel or rel.endswith("/"):
|
||||
continue
|
||||
if rel.startswith("wizard-work/sol/"):
|
||||
continue
|
||||
p = REPO.joinpath(*rel.split("/"))
|
||||
if p.is_file():
|
||||
out.append(rel)
|
||||
return sorted(out)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
problems = []
|
||||
if not MANIFEST.exists():
|
||||
print("PROBLEM: manifest missing: %s" % MANIFEST)
|
||||
return 1
|
||||
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
|
||||
|
||||
live = live_universe()
|
||||
|
||||
live_by_cat = {}
|
||||
live_cat_of = {}
|
||||
for rel in live:
|
||||
c = classify(rel)
|
||||
live_by_cat[c] = live_by_cat.get(c, 0) + 1
|
||||
live_cat_of[rel] = c
|
||||
|
||||
manifest_files = manifest.get("files", [])
|
||||
manifest_by_rel = {f.get("rel"): f.get("category") for f in manifest_files}
|
||||
|
||||
for rel in live:
|
||||
if rel not in manifest_by_rel:
|
||||
problems.append("in live but absent from manifest: %s" % rel)
|
||||
elif manifest_by_rel[rel] != live_cat_of[rel]:
|
||||
problems.append("category mismatch %s: live=%s manifest=%s"
|
||||
% (rel, live_cat_of[rel], manifest_by_rel[rel]))
|
||||
|
||||
for rel in manifest_by_rel:
|
||||
if rel not in live_cat_of:
|
||||
problems.append("in manifest but absent live: %s" % rel)
|
||||
|
||||
for rel in live:
|
||||
p = REPO.joinpath(*rel.split("/"))
|
||||
if not p.is_file():
|
||||
problems.append("missing on disk: %s" % rel)
|
||||
elif is_ignored(rel):
|
||||
problems.append("ignored by .gitignore: %s" % rel)
|
||||
|
||||
if manifest.get("total_files") != len(live):
|
||||
problems.append("total_files %s != live files %d"
|
||||
% (manifest.get("total_files"), len(live)))
|
||||
if manifest.get("by_category") != live_by_cat:
|
||||
problems.append("by_category mismatch: manifest=%s live=%s"
|
||||
% (manifest.get("by_category"), live_by_cat))
|
||||
|
||||
if problems:
|
||||
print("VERIFY FAIL (%d problems)" % len(problems))
|
||||
for pb in problems[:80]:
|
||||
print(" - %s" % pb)
|
||||
if len(problems) > 80:
|
||||
print(" ... %d more" % (len(problems) - 80))
|
||||
return 1
|
||||
|
||||
print("VERIFY OK (%d untracked files, categories re-derived, all paths present)"
|
||||
% len(live))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user