#!/usr/bin/env python3
"""Fail closed when assembled narration contains internal remediation markers.

Usage: audit_story_semantic_markers.py STORY.json [RECEIPT.json]
The story must use parts[].paragraphs[]. This is a lexical pre-gate; a human or
independent full-read semantic audit is still required for every changed paragraph.
"""
from pathlib import Path
import hashlib
import json
import re
import sys

PATTERNS = {
    "synthetic_uniqueness_marker": r"\bP\d+D\d+L\d+\b",
    "todo_fixme": r"\b(?:TODO|FIXME|TBD)\b",
    "revision_scaffolding": r"\b(?:PLACEHOLDER|REWRITE_ME|DRAFT_ONLY)\b",
}


def main() -> int:
    if len(sys.argv) not in (2, 3):
        raise SystemExit("usage: audit_story_semantic_markers.py STORY.json [RECEIPT.json]")
    source = Path(sys.argv[1])
    data = json.loads(source.read_text())
    findings = []
    paragraphs = 0
    for part in data.get("parts", []):
        part_no = part.get("part")
        for index, text in enumerate(part.get("paragraphs", []), 1):
            paragraphs += 1
            for code, pattern in PATTERNS.items():
                matches = re.findall(pattern, text, flags=re.IGNORECASE)
                if matches:
                    findings.append({
                        "code": code,
                        "part": part_no,
                        "paragraph": index,
                        "matches": matches,
                    })
    receipt = {
        "status": "passed" if not findings else "failed",
        "story_path": str(source),
        "story_sha256": hashlib.sha256(source.read_bytes()).hexdigest(),
        "paragraphs_scanned": paragraphs,
        "findings": findings,
        "semantic_full_read_required": True,
        "note": "Zero lexical findings do not prove natural, scene-specific, audio-ready prose.",
    }
    rendered = json.dumps(receipt, ensure_ascii=False, indent=2) + "\n"
    if len(sys.argv) == 3:
        Path(sys.argv[2]).write_text(rendered)
    print(rendered, end="")
    return 0 if receipt["status"] == "passed" else 1


if __name__ == "__main__":
    raise SystemExit(main())
