Compare commits
3
Commits
5bded8094b
...
8dbbb26f55
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dbbb26f55 | ||
|
|
4bdd23e70e | ||
|
|
9f97f411c9 |
No files matched your search
@@ -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.
|
||||
@@ -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())
|
||||
@@ -0,0 +1 @@
|
||||
This test file contains exactly ten words total here now
|
||||
@@ -23,7 +23,7 @@ def main():
|
||||
text = sys.stdin.read()
|
||||
|
||||
count = count_words(text)
|
||||
print(f"Word count: {count}")
|
||||
print(count)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user