sol: untracked-file triage classification manifest + verifier
This commit is contained in:
1 parent
27edccc773
commit
376afd33f4
4 files changed
+970
No files matched your search
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# CHECK -- sol: Untracked-file triage classification (forge: verify lane).
|
||||||
|
# Exit 0 iff the committed Untracked-Triad-2026-11-01.json re-derives every
|
||||||
|
# classified path's category/decision from the canonical rule, and each path is
|
||||||
|
# still a real, untracked, non-ignored file on disk.
|
||||||
|
set -u
|
||||||
|
|
||||||
|
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_untracked_triad_2026_11_01.py
|
||||||
@@ -0,0 +1,668 @@
|
|||||||
|
{
|
||||||
|
"artifact": "Untracked-Triad-2026-11-01.json",
|
||||||
|
"corpus_sha256": "321891e6717758c2018fcf7273dd6b37bc61c9325312b54f5a3b82134e1d8826",
|
||||||
|
"files": [
|
||||||
|
"CHECK-sol-untracked-classify",
|
||||||
|
"CHECK-triage-2026-10-29",
|
||||||
|
"checkins/2026-10-27-sentinel.md",
|
||||||
|
"d.jsonl",
|
||||||
|
"docs/clawrouter-plan.md",
|
||||||
|
"docs/flux2-deploy.md",
|
||||||
|
"docs/video-deploy.md",
|
||||||
|
"inbox/dump_seed.py",
|
||||||
|
"kanban.db",
|
||||||
|
"recoveries/apply-queue-status-2026-10-25.md",
|
||||||
|
"repo_exts.tsv",
|
||||||
|
"repo_files.tsv",
|
||||||
|
"repo_tree.tsv",
|
||||||
|
"s.json",
|
||||||
|
"test_sample.txt",
|
||||||
|
"test_validation.txt",
|
||||||
|
"test_verification.txt",
|
||||||
|
"validate_artifact.py",
|
||||||
|
"wizard-work/null/.hermes-tmp.RqZp3z",
|
||||||
|
"wizard-work/null/README-gatehygiene.md",
|
||||||
|
"wizard-work/null/README-q62-scan.md",
|
||||||
|
"wizard-work/null/_probe10.py",
|
||||||
|
"wizard-work/null/_probe11.py",
|
||||||
|
"wizard-work/null/_probe12.py",
|
||||||
|
"wizard-work/null/_probe13.py",
|
||||||
|
"wizard-work/null/_probe14.py",
|
||||||
|
"wizard-work/null/_probe5.py",
|
||||||
|
"wizard-work/null/_probe6.py",
|
||||||
|
"wizard-work/null/_probe7.py",
|
||||||
|
"wizard-work/null/_probe8.py",
|
||||||
|
"wizard-work/null/_probe9.py",
|
||||||
|
"wizard-work/null/_probe_binding_defects.py",
|
||||||
|
"wizard-work/null/_probe_gh1.py",
|
||||||
|
"wizard-work/null/_probe_gh2.py",
|
||||||
|
"wizard-work/null/_probe_gh3.py",
|
||||||
|
"wizard-work/null/_probe_gh4.py",
|
||||||
|
"wizard-work/null/_probe_gh5.py",
|
||||||
|
"wizard-work/null/_probe_gh6.py",
|
||||||
|
"wizard-work/null/_probe_gh7.py",
|
||||||
|
"wizard-work/null/_probe_gh8.py",
|
||||||
|
"wizard-work/null/_probe_gh9.py",
|
||||||
|
"wizard-work/null/_probe_mut2.py",
|
||||||
|
"wizard-work/null/_probe_mut_check.py",
|
||||||
|
"wizard-work/null/_probe_q70_5h.py",
|
||||||
|
"wizard-work/null/_probe_repro1.py",
|
||||||
|
"wizard-work/null/_probe_repro2.py",
|
||||||
|
"wizard-work/null/_probe_repro3.py",
|
||||||
|
"wizard-work/null/_probe_repro4.py",
|
||||||
|
"wizard-work/null/_probe_repro5.py",
|
||||||
|
"wizard-work/null/_probe_repro6.py",
|
||||||
|
"wizard-work/null/_probe_repro7.py",
|
||||||
|
"wizard-work/null/check_gatehygiene.py",
|
||||||
|
"wizard-work/null/check_provenance.py",
|
||||||
|
"wizard-work/null/check_provenance_baseline.tsv",
|
||||||
|
"wizard-work/null/check_provenance_ledger.py",
|
||||||
|
"wizard-work/null/check_q62_scan.py",
|
||||||
|
"wizard-work/null/cli_contract.py",
|
||||||
|
"wizard-work/null/diffkit/__init__.py",
|
||||||
|
"wizard-work/null/diffkit/_flatpkg.py",
|
||||||
|
"wizard-work/null/diffkit/core.py",
|
||||||
|
"wizard-work/null/diffkit/diffkit_cli.py",
|
||||||
|
"wizard-work/null/diffkit/myers.py",
|
||||||
|
"wizard-work/null/diffkit_gate.py",
|
||||||
|
"wizard-work/null/gatehygiene.py",
|
||||||
|
"wizard-work/null/json_salvage.py",
|
||||||
|
"wizard-work/null/membershipkit/.hermes-tmp.sx2gIa",
|
||||||
|
"wizard-work/null/membershipkit/check_membershipkit.sh",
|
||||||
|
"wizard-work/null/membershipkit/mutate_membershipkit.py",
|
||||||
|
"wizard-work/null/membershipkit/test_membershipkit.py",
|
||||||
|
"wizard-work/null/mutate_resolver.py",
|
||||||
|
"wizard-work/null/mutate_salvage.py",
|
||||||
|
"wizard-work/null/q58_warncontrol.py",
|
||||||
|
"wizard-work/null/q62_scan.py",
|
||||||
|
"wizard-work/null/q70_sabotage.py",
|
||||||
|
"wizard-work/null/q76_binding.py",
|
||||||
|
"wizard-work/null/q80_warn.py",
|
||||||
|
"wizard-work/null/revwalk.py",
|
||||||
|
"wizard-work/null/test_gate.py",
|
||||||
|
"wizard-work/null/test_gate_mutants.py",
|
||||||
|
"wizard-work/null/test_json_salvage.py",
|
||||||
|
"wizard-work/null/test_myers_diff.py",
|
||||||
|
"wizard-work/null/test_revwalk.py",
|
||||||
|
"wizard-work/null/verify_check_provenance.py",
|
||||||
|
"wizard-work/null/verify_staged.py",
|
||||||
|
"wizard-work/sol/CHECK-sol-profile-triage-2026-11-02",
|
||||||
|
"wizard-work/sol/Triage-2026-11-02.json",
|
||||||
|
"wizard-work/sol/Triage-2026-11-02.md",
|
||||||
|
"wizard-work/sol/_print_paths.py",
|
||||||
|
"wizard-work/sol/build_untracked_triad_2026_11_01.py",
|
||||||
|
"wizard-work/sol/verify_sol_triage_2026_11_02.py",
|
||||||
|
"wizard-work/sol/verify_untracked_triad_2026_11_01.py",
|
||||||
|
"wizard-work/sphinx/archive-mmlongcite-2026-10-25/probe_paper_facts.json"
|
||||||
|
],
|
||||||
|
"files_count": 92,
|
||||||
|
"generated_at": "2026-11-01T07:23:13Z",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"category": "gate",
|
||||||
|
"decision": "approve",
|
||||||
|
"id": 1,
|
||||||
|
"path": "CHECK-sol-untracked-classify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "gate",
|
||||||
|
"decision": "approve",
|
||||||
|
"id": 2,
|
||||||
|
"path": "CHECK-triage-2026-10-29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 3,
|
||||||
|
"path": "checkins/2026-10-27-sentinel.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 4,
|
||||||
|
"path": "d.jsonl"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 5,
|
||||||
|
"path": "docs/clawrouter-plan.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 6,
|
||||||
|
"path": "docs/flux2-deploy.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 7,
|
||||||
|
"path": "docs/video-deploy.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 8,
|
||||||
|
"path": "inbox/dump_seed.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "persistence",
|
||||||
|
"decision": "archive",
|
||||||
|
"id": 9,
|
||||||
|
"path": "kanban.db"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 10,
|
||||||
|
"path": "recoveries/apply-queue-status-2026-10-25.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 11,
|
||||||
|
"path": "repo_exts.tsv"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 12,
|
||||||
|
"path": "repo_files.tsv"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 13,
|
||||||
|
"path": "repo_tree.tsv"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 14,
|
||||||
|
"path": "s.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 15,
|
||||||
|
"path": "test_sample.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 16,
|
||||||
|
"path": "test_validation.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 17,
|
||||||
|
"path": "test_verification.txt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 18,
|
||||||
|
"path": "validate_artifact.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "other",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 19,
|
||||||
|
"path": "wizard-work/null/.hermes-tmp.RqZp3z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 20,
|
||||||
|
"path": "wizard-work/null/README-gatehygiene.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 21,
|
||||||
|
"path": "wizard-work/null/README-q62-scan.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 22,
|
||||||
|
"path": "wizard-work/null/_probe10.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 23,
|
||||||
|
"path": "wizard-work/null/_probe11.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 24,
|
||||||
|
"path": "wizard-work/null/_probe12.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 25,
|
||||||
|
"path": "wizard-work/null/_probe13.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 26,
|
||||||
|
"path": "wizard-work/null/_probe14.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 27,
|
||||||
|
"path": "wizard-work/null/_probe5.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 28,
|
||||||
|
"path": "wizard-work/null/_probe6.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 29,
|
||||||
|
"path": "wizard-work/null/_probe7.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 30,
|
||||||
|
"path": "wizard-work/null/_probe8.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 31,
|
||||||
|
"path": "wizard-work/null/_probe9.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 32,
|
||||||
|
"path": "wizard-work/null/_probe_binding_defects.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 33,
|
||||||
|
"path": "wizard-work/null/_probe_gh1.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 34,
|
||||||
|
"path": "wizard-work/null/_probe_gh2.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 35,
|
||||||
|
"path": "wizard-work/null/_probe_gh3.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 36,
|
||||||
|
"path": "wizard-work/null/_probe_gh4.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 37,
|
||||||
|
"path": "wizard-work/null/_probe_gh5.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 38,
|
||||||
|
"path": "wizard-work/null/_probe_gh6.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 39,
|
||||||
|
"path": "wizard-work/null/_probe_gh7.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 40,
|
||||||
|
"path": "wizard-work/null/_probe_gh8.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 41,
|
||||||
|
"path": "wizard-work/null/_probe_gh9.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 42,
|
||||||
|
"path": "wizard-work/null/_probe_mut2.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 43,
|
||||||
|
"path": "wizard-work/null/_probe_mut_check.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 44,
|
||||||
|
"path": "wizard-work/null/_probe_q70_5h.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 45,
|
||||||
|
"path": "wizard-work/null/_probe_repro1.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 46,
|
||||||
|
"path": "wizard-work/null/_probe_repro2.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 47,
|
||||||
|
"path": "wizard-work/null/_probe_repro3.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 48,
|
||||||
|
"path": "wizard-work/null/_probe_repro4.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 49,
|
||||||
|
"path": "wizard-work/null/_probe_repro5.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 50,
|
||||||
|
"path": "wizard-work/null/_probe_repro6.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 51,
|
||||||
|
"path": "wizard-work/null/_probe_repro7.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 52,
|
||||||
|
"path": "wizard-work/null/check_gatehygiene.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 53,
|
||||||
|
"path": "wizard-work/null/check_provenance.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 54,
|
||||||
|
"path": "wizard-work/null/check_provenance_baseline.tsv"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 55,
|
||||||
|
"path": "wizard-work/null/check_provenance_ledger.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 56,
|
||||||
|
"path": "wizard-work/null/check_q62_scan.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 57,
|
||||||
|
"path": "wizard-work/null/cli_contract.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 58,
|
||||||
|
"path": "wizard-work/null/diffkit/__init__.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 59,
|
||||||
|
"path": "wizard-work/null/diffkit/_flatpkg.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 60,
|
||||||
|
"path": "wizard-work/null/diffkit/core.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 61,
|
||||||
|
"path": "wizard-work/null/diffkit/diffkit_cli.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 62,
|
||||||
|
"path": "wizard-work/null/diffkit/myers.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 63,
|
||||||
|
"path": "wizard-work/null/diffkit_gate.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 64,
|
||||||
|
"path": "wizard-work/null/gatehygiene.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 65,
|
||||||
|
"path": "wizard-work/null/json_salvage.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "other",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 66,
|
||||||
|
"path": "wizard-work/null/membershipkit/.hermes-tmp.sx2gIa"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 67,
|
||||||
|
"path": "wizard-work/null/membershipkit/check_membershipkit.sh"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 68,
|
||||||
|
"path": "wizard-work/null/membershipkit/mutate_membershipkit.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 69,
|
||||||
|
"path": "wizard-work/null/membershipkit/test_membershipkit.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 70,
|
||||||
|
"path": "wizard-work/null/mutate_resolver.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 71,
|
||||||
|
"path": "wizard-work/null/mutate_salvage.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 72,
|
||||||
|
"path": "wizard-work/null/q58_warncontrol.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 73,
|
||||||
|
"path": "wizard-work/null/q62_scan.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 74,
|
||||||
|
"path": "wizard-work/null/q70_sabotage.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 75,
|
||||||
|
"path": "wizard-work/null/q76_binding.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 76,
|
||||||
|
"path": "wizard-work/null/q80_warn.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 77,
|
||||||
|
"path": "wizard-work/null/revwalk.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 78,
|
||||||
|
"path": "wizard-work/null/test_gate.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 79,
|
||||||
|
"path": "wizard-work/null/test_gate_mutants.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 80,
|
||||||
|
"path": "wizard-work/null/test_json_salvage.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 81,
|
||||||
|
"path": "wizard-work/null/test_myers_diff.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 82,
|
||||||
|
"path": "wizard-work/null/test_revwalk.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 83,
|
||||||
|
"path": "wizard-work/null/verify_check_provenance.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 84,
|
||||||
|
"path": "wizard-work/null/verify_staged.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "other",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 85,
|
||||||
|
"path": "wizard-work/sol/CHECK-sol-profile-triage-2026-11-02"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 86,
|
||||||
|
"path": "wizard-work/sol/Triage-2026-11-02.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "documentation",
|
||||||
|
"decision": "info",
|
||||||
|
"id": 87,
|
||||||
|
"path": "wizard-work/sol/Triage-2026-11-02.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 88,
|
||||||
|
"path": "wizard-work/sol/_print_paths.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 89,
|
||||||
|
"path": "wizard-work/sol/build_untracked_triad_2026_11_01.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 90,
|
||||||
|
"path": "wizard-work/sol/verify_sol_triage_2026_11_02.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "tooling",
|
||||||
|
"decision": "review",
|
||||||
|
"id": 91,
|
||||||
|
"path": "wizard-work/sol/verify_untracked_triad_2026_11_01.py"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"category": "data",
|
||||||
|
"decision": "observe",
|
||||||
|
"id": 92,
|
||||||
|
"path": "wizard-work/sphinx/archive-mmlongcite-2026-10-25/probe_paper_facts.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lane": "Triage - everyday Q&A and classification",
|
||||||
|
"repo": "/root/troupe-standup",
|
||||||
|
"rule": "path-based deterministic classifier (see MODULE_DOCLINE)",
|
||||||
|
"rule_version": "1",
|
||||||
|
"summary": {
|
||||||
|
"data": 11,
|
||||||
|
"documentation": 8,
|
||||||
|
"gate": 2,
|
||||||
|
"other": 3,
|
||||||
|
"persistence": 1,
|
||||||
|
"tooling": 67,
|
||||||
|
"total": 92
|
||||||
|
},
|
||||||
|
"task": "classify untracked repo files into deterministic buckets"
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Build Untracked-Triad-2026-11-01.json.
|
||||||
|
|
||||||
|
Triage: classify the untracked (git ?? ) regular files of the repo into
|
||||||
|
deterministic buckets, then write the machine-readable artifact.
|
||||||
|
|
||||||
|
Rule (deterministic, derived from the relative path only):
|
||||||
|
|
||||||
|
category:
|
||||||
|
gate path starts with "CHECK-"
|
||||||
|
persistence ends with ".db"
|
||||||
|
data ends with ".json", ".jsonl", ".tsv" or ".txt"
|
||||||
|
tooling ends with ".py" or ".sh"
|
||||||
|
documentation ends with ".md"
|
||||||
|
other anything else
|
||||||
|
|
||||||
|
decision:
|
||||||
|
gate -> approve
|
||||||
|
tooling -> review
|
||||||
|
documentation -> info
|
||||||
|
data -> observe
|
||||||
|
persistence -> archive
|
||||||
|
other -> review
|
||||||
|
|
||||||
|
The manifest snapshots the exact file list at generation time (files + a
|
||||||
|
sha256 of the canonical list) so the independent verifier can confirm the
|
||||||
|
artifact is a faithful, reproducible classification, not a hand-edited guess.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
|
def find_repo_root(start):
|
||||||
|
"""Walk up from *start* until a directory that contains a .git marker."""
|
||||||
|
d = os.path.abspath(start)
|
||||||
|
for _ in range(64):
|
||||||
|
if os.path.isdir(os.path.join(d, ".git")):
|
||||||
|
return d
|
||||||
|
parent = os.path.dirname(d)
|
||||||
|
if parent == d:
|
||||||
|
break
|
||||||
|
d = parent
|
||||||
|
raise RuntimeError("could not locate repo root (no .git) above " + start)
|
||||||
|
|
||||||
|
|
||||||
|
REPO_ROOT = find_repo_root(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
OUT_REPO = os.path.join(
|
||||||
|
REPO_ROOT, "wizard-work", "sol", "Untracked-Triad-2026-11-01.json"
|
||||||
|
)
|
||||||
|
OUT_WIZ = os.path.expanduser(
|
||||||
|
os.path.join("~", ".hermes", "wizard-outputs", "sol", "Untracked-Triad-2026-11-01.json")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def git_untracked(repo):
|
||||||
|
"""Return sorted list of untracked regular files (skip untracked dirs)."""
|
||||||
|
proc = subprocess.run(
|
||||||
|
["git", "-C", repo, "status", "--porcelain=v1"],
|
||||||
|
check=True, capture_output=True, text=True,
|
||||||
|
)
|
||||||
|
files = []
|
||||||
|
for line in proc.stdout.splitlines():
|
||||||
|
if line.startswith("??"):
|
||||||
|
path = line[3:].strip()
|
||||||
|
if path and not path.endswith("/"):
|
||||||
|
files.append(path)
|
||||||
|
return sorted(files)
|
||||||
|
|
||||||
|
|
||||||
|
def category_of(rel):
|
||||||
|
low = rel.lower()
|
||||||
|
if low.startswith("check-"):
|
||||||
|
return "gate"
|
||||||
|
if low.endswith(".db"):
|
||||||
|
return "persistence"
|
||||||
|
if low.endswith((".json", ".jsonl", ".tsv", ".txt")):
|
||||||
|
return "data"
|
||||||
|
if low.endswith((".py", ".sh")):
|
||||||
|
return "tooling"
|
||||||
|
if low.endswith(".md"):
|
||||||
|
return "documentation"
|
||||||
|
return "other"
|
||||||
|
|
||||||
|
|
||||||
|
DECISION = {
|
||||||
|
"gate": "approve",
|
||||||
|
"tooling": "review",
|
||||||
|
"documentation": "info",
|
||||||
|
"data": "observe",
|
||||||
|
"persistence": "archive",
|
||||||
|
"other": "review",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build(files):
|
||||||
|
items = []
|
||||||
|
for i, rel in enumerate(files, start=1):
|
||||||
|
cat = category_of(rel)
|
||||||
|
items.append({
|
||||||
|
"id": i,
|
||||||
|
"path": rel,
|
||||||
|
"category": cat,
|
||||||
|
"decision": DECISION[cat],
|
||||||
|
})
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def corpus_sha256(files):
|
||||||
|
canon = json.dumps({"files": files}, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
||||||
|
return hashlib.sha256(canon).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
files = git_untracked(REPO_ROOT)
|
||||||
|
items = build(files)
|
||||||
|
manifest = {
|
||||||
|
"artifact": "Untracked-Triad-2026-11-01.json",
|
||||||
|
"lane": "Triage - everyday Q&A and classification",
|
||||||
|
"task": "classify untracked repo files into deterministic buckets",
|
||||||
|
"generated_at": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||||
|
"repo": REPO_ROOT,
|
||||||
|
"rule": "path-based deterministic classifier (see MODULE_DOCLINE)",
|
||||||
|
"rule_version": "1",
|
||||||
|
"files": files,
|
||||||
|
"files_count": len(files),
|
||||||
|
"corpus_sha256": corpus_sha256(files),
|
||||||
|
"summary": {
|
||||||
|
"total": len(files),
|
||||||
|
"gate": sum(1 for it in items if it["category"] == "gate"),
|
||||||
|
"persistence": sum(1 for it in items if it["category"] == "persistence"),
|
||||||
|
"data": sum(1 for it in items if it["category"] == "data"),
|
||||||
|
"tooling": sum(1 for it in items if it["category"] == "tooling"),
|
||||||
|
"documentation": sum(1 for it in items if it["category"] == "documentation"),
|
||||||
|
"other": sum(1 for it in items if it["category"] == "other"),
|
||||||
|
},
|
||||||
|
"items": items,
|
||||||
|
}
|
||||||
|
|
||||||
|
for out in (OUT_REPO, OUT_WIZ):
|
||||||
|
os.makedirs(os.path.dirname(out), exist_ok=True)
|
||||||
|
with open(out, "w", encoding="utf-8") as fh:
|
||||||
|
json.dump(manifest, fh, indent=2, sort_keys=True)
|
||||||
|
fh.write("\n")
|
||||||
|
|
||||||
|
print("Untracked-Triad-2026-11-01.json written")
|
||||||
|
print(" files:", len(files))
|
||||||
|
print(" corpus_sha256:", manifest["corpus_sha256"])
|
||||||
|
print(" categories:", manifest["summary"])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Independent verifier for Untracked-Triad-2026-11-01.json.
|
||||||
|
|
||||||
|
The classification rule is re-derived from each item's path (the generator's
|
||||||
|
stored category/decision fields are NOT trusted). A wrong classification makes
|
||||||
|
this exit non-zero. Additionally every classified path must still exist on disk
|
||||||
|
as a real, untracked, non-ignored file.
|
||||||
|
|
||||||
|
Exit 0 iff all checks pass.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
MANIFEST = os.path.join(HERE, "Untracked-Triad-2026-11-01.json")
|
||||||
|
|
||||||
|
REPO_ROOT = os.path.dirname(os.path.dirname(HERE))
|
||||||
|
|
||||||
|
|
||||||
|
def cat_of(rel):
|
||||||
|
low = rel.lower()
|
||||||
|
if low.startswith("check-"):
|
||||||
|
return "gate"
|
||||||
|
if low.endswith(".db"):
|
||||||
|
return "persistence"
|
||||||
|
if low.endswith((".json", ".jsonl", ".tsv", ".txt")):
|
||||||
|
return "data"
|
||||||
|
if low.endswith((".py", ".sh")):
|
||||||
|
return "tooling"
|
||||||
|
if low.endswith(".md"):
|
||||||
|
return "documentation"
|
||||||
|
return "other"
|
||||||
|
|
||||||
|
|
||||||
|
DECISION = {
|
||||||
|
"gate": "approve",
|
||||||
|
"tooling": "review",
|
||||||
|
"documentation": "info",
|
||||||
|
"data": "observe",
|
||||||
|
"persistence": "archive",
|
||||||
|
"other": "review",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def git_status_untracked(repo):
|
||||||
|
proc = subprocess_run(["git", "-C", repo, "status", "--porcelain=v1"])
|
||||||
|
return set(line[3:].strip() for line in proc.stdout.splitlines()
|
||||||
|
if line.startswith("??") and not line[3:].strip().endswith("/"))
|
||||||
|
|
||||||
|
|
||||||
|
def git_check_ignored(repo, rel):
|
||||||
|
proc = subprocess_run(["git", "check-ignore", "-q", rel])
|
||||||
|
return proc.returncode == 0
|
||||||
|
|
||||||
|
|
||||||
|
def subprocess_run(cmd):
|
||||||
|
import subprocess
|
||||||
|
return subprocess.run(cmd, capture_output=True, text=True)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
errors = []
|
||||||
|
try:
|
||||||
|
with open(MANIFEST, encoding="utf-8") as fh:
|
||||||
|
man = json.load(fh)
|
||||||
|
except Exception as exc:
|
||||||
|
print("FAIL: cannot load manifest:", exc)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
files = man.get("files", [])
|
||||||
|
items = man.get("items", [])
|
||||||
|
repo = man.get("repo", REPO_ROOT)
|
||||||
|
|
||||||
|
# 1. corpus sha256 must match the recorded file list
|
||||||
|
canon = json.dumps({"files": sorted(files)}, sort_keys=True, separators=(",", ":")).encode("utf-8")
|
||||||
|
computed_sha = hashlib.sha256(canon).hexdigest()
|
||||||
|
if computed_sha != man.get("corpus_sha256"):
|
||||||
|
errors.append("corpus_sha256 mismatch (recorded %s vs computed %s)" %
|
||||||
|
(man.get("corpus_sha256"), computed_sha))
|
||||||
|
|
||||||
|
# 2. ids must be unique and exactly 1..N
|
||||||
|
ids = [it.get("id") for it in items]
|
||||||
|
if sorted(ids) != list(range(1, len(items) + 1)):
|
||||||
|
errors.append("ids are not exactly 1..N")
|
||||||
|
|
||||||
|
# 3. re-derive category/decision from each path; verify file exists, untracked, non-ignored
|
||||||
|
for it in items:
|
||||||
|
rel = it.get("path")
|
||||||
|
exp_cat = it.get("category")
|
||||||
|
exp_dec = it.get("decision")
|
||||||
|
if not rel:
|
||||||
|
errors.append("missing path on item id=%r" % (it.get("id"),))
|
||||||
|
continue
|
||||||
|
act_cat = cat_of(rel)
|
||||||
|
act_dec = DECISION.get(act_cat)
|
||||||
|
if exp_cat != act_cat:
|
||||||
|
errors.append("id=%s path=%s category %s != re-derived %s" % (it.get("id"), rel, exp_cat, act_cat))
|
||||||
|
if exp_dec != act_dec:
|
||||||
|
errors.append("id=%s path=%s decision %s != re-derived %s" % (it.get("id"), rel, exp_dec, act_dec))
|
||||||
|
if not os.path.isfile(os.path.join(repo, rel)):
|
||||||
|
errors.append("id=%s path=%s does not exist as a real file" % (it.get("id"), rel))
|
||||||
|
if rel not in git_status_untracked(repo):
|
||||||
|
errors.append("id=%s path=%s is not currently untracked" % (it.get("id"), rel))
|
||||||
|
if git_check_ignored(repo, rel):
|
||||||
|
errors.append("id=%s path=%s is git-ignored" % (it.get("id"), rel))
|
||||||
|
|
||||||
|
# 4. summary counts must be consistent with items (skip the "total" key,
|
||||||
|
# which is the corpus size, not a category).
|
||||||
|
from collections import Counter
|
||||||
|
CAT_KEYS = {"gate", "persistence", "data", "tooling", "documentation", "other"}
|
||||||
|
cnt = Counter(it.get("category") for it in items)
|
||||||
|
for cat, n in man.get("summary", {}).items():
|
||||||
|
if cat not in CAT_KEYS:
|
||||||
|
continue
|
||||||
|
if cnt.get(cat, 0) != n:
|
||||||
|
errors.append("summary %s=%d but items have %d" % (cat, n, cnt.get(cat, 0)))
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
print("FAIL: %d problem(s)" % len(errors))
|
||||||
|
for e in errors[:40]:
|
||||||
|
print(" -", e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("PASS: %d files classified; %d re-derive to matching category/decision; "
|
||||||
|
"all files real, untracked, non-ignored; corpus sha256 matches."
|
||||||
|
% (len(files), len(items)))
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in new issue
Block a user