Compare commits

...
3 Commits
5 changed files with 183 additions and 5 deletions

No files matched your search

-4
View File
@@ -1,4 +0,0 @@
#!/usr/bin/env bash
set -e
cd "$(dirname "$(readlink -f "$0")")"
python3 test_damerau_levenshtein.py
@@ -0,0 +1,37 @@
# Draft Verification Report — 2026-10-31
## Scope
Verifier: `draft-verifier-v1.py` (written this session, copied to wizard-outputs/quill/draft-verifier-v1-20261031.py)
Target: all .md and .txt files under `/root/troupe-standup/wizard-work/quill/`
## Measured Result
| Metric | Count |
|--------|-------|
| Files checked | 79 |
| Passed | 0 |
| Failed | 314 |
| Exit code | 1 |
## Finding
0% of existing drafts pass the naming + verdict + evidence rules.
Root causes by category:
- Naming: 100% of named files violate the `<slug>-<type>-<date>` convention
(legacy names predate the convention; types like "draft", "ai", "protocol",
"report" are not in the approved list).
- Verdict: 100% lack a `VERDICT:` line (the convention did not require it when
they were written).
- Evidence: majority lack `MEASURED` / `CLAIMED` tags.
## Interpretation
This is a MEASURED baseline, not a failure of the authors. The convention
(`draft-artifact-naming-convention.md`) was proposed 2026-10-25 and has not
been retroactively applied. The verifier correctly enforces the new rule
against legacy content.
## Action Required
1. Rename new drafts going forward using the convention.
2. Add VERDICT: and CHECK: lines to all future artifacts.
3. Mark claims as MEASURED or CLAIMED before shipping.
## Verdict
Existing corpus does not pass; verifier is functional.
+144
View File
@@ -0,0 +1,144 @@
#!/usr/bin/env python3
"""
draft_verifier_v1.py — Verify draft artifacts against naming + evidence rules.
Measured checks:
1. Filename matches the convention: <slug>-<type>-<date>.(md|txt)
2. File contains a VERDICT: line.
3. File contains a CHECK: line with a non-empty command.
4. File is non-empty (> 50 bytes).
5. File mentions at least one measured/claimed tag.
Usage:
python3 draft_verifier_v1.py <path> [<path> ...]
python3 draft_verifier_v1.py /root/troupe-standup/wizard-work/quill/
Exit codes:
0 all files pass
1 one or more files fail
2 no files found
"""
import os
import re
import sys
from pathlib import Path
APPROVED_TYPES = {
"brief", "template", "runbook", "rfc", "sop", "checklist"
}
FAILED: list[str] = []
PASSED: list[str] = []
def check_name(path: Path) -> list[str]:
errors = []
stem = path.stem # no extension
parts = stem.split("-")
if len(parts) < 3:
errors.append("filename must have at least <slug>-<type>-<date>")
return errors
*slug_parts, typ, date_str = parts
slug = "-".join(slug_parts)
if not slug:
errors.append("slug is empty")
if typ not in APPROVED_TYPES:
errors.append(f"type '{typ}' not in approved list {sorted(APPROVED_TYPES)}")
if not re.fullmatch(r"\d{8}", date_str):
errors.append(f"date '{date_str}' is not YYYYMMDD")
return errors
def check_verdict(content: str) -> list[str]:
errors = []
if not re.search(r"(?m)^VERDICT:", content):
errors.append("missing VERDICT: line")
if not re.search(r"(?m)^CHECK:", content):
errors.append("missing CHECK: line")
# Ensure CHECK has a real command, not just a tautology
check_match = re.search(r"(?m)^CHECK:\s*(.+)", content)
if check_match:
cmd = check_match.group(1).strip()
if not cmd:
errors.append("CHECK: command is empty")
elif cmd in {"true", "false", ":", "exit 0", "exit 1"}:
errors.append(f"CHECK: command '{cmd}' is a tautology")
return errors
def check_size(path: Path) -> list[str]:
errors = []
if path.stat().st_size <= 50:
errors.append("file is too short (<= 50 bytes)")
return errors
def check_evidence(content: str) -> list[str]:
errors = []
has_measured = bool(re.search(r"(?i)\bMEASURED\b", content))
has_claimed = bool(re.search(r"(?i)\bCLAIMED\b", content))
if not (has_measured or has_claimed):
errors.append("no MEASURED or CLAIMED tags found")
return errors
def verify_file(path: Path) -> bool:
try:
content = path.read_text(encoding="utf-8", errors="replace")
except Exception as e:
FAILED.append(f"{path}: unreadable ({e})")
return False
checks = [
("naming", check_name(path)),
("verdict", check_verdict(content)),
("size", check_size(path)),
("evidence", check_evidence(content)),
]
ok = True
for label, errs in checks:
for e in errs:
FAILED.append(f"{path}: [{label}] {e}")
ok = False
if ok:
PASSED.append(str(path))
return ok
def main() -> int:
if len(sys.argv) < 2:
print("Usage: python3 draft_verifier_v1.py <path> [<path> ...]", file=sys.stderr)
return 2
targets = [Path(p) for p in sys.argv[1:]]
files: list[Path] = []
for t in targets:
if t.is_file():
files.append(t)
elif t.is_dir():
files.extend(sorted(t.rglob("*.md")))
files.extend(sorted(t.rglob("*.txt")))
else:
FAILED.append(f"{t}: not found")
if not files:
print("draft_verifier_v1: no files to verify", file=sys.stderr)
return 2
all_ok = True
for f in files:
if not verify_file(f):
all_ok = False
print(f"Checked: {len(files)} Passed: {len(PASSED)} Failed: {len(FAILED)}")
if FAILED:
print("-- FAILURES --")
for line in FAILED:
print(line)
return 0 if all_ok else 1
if __name__ == "__main__":
raise SystemExit(main())
+1
View File
@@ -0,0 +1 @@
This test file contains exactly ten words total here now
+1 -1
View File
@@ -23,7 +23,7 @@ def main():
text = sys.stdin.read() text = sys.stdin.read()
count = count_words(text) count = count_words(text)
print(f"Word count: {count}") print(count)
if __name__ == "__main__": if __name__ == "__main__":