"""Tests for ars_anchorize_draft.py (#89 Item 7 Slice A, spec §8.1). Pins the three §8.1 anchorize properties — idempotent (second run byte-identical), content-neutral (output minus marker lines == input), manifest agreement (per-block hashes AND base_draft_hash equal an independent apply-side recomputation) — plus fresh-ID assignment, CRLF handling, schema validity of the emitted manifest, and the CLI rejection path. Run standalone: python -m unittest scripts/test_ars_anchorize_draft.py -v """ from __future__ import annotations import json import tempfile import unittest from pathlib import Path import jsonschema from scripts._block_parser import MARKER_RE, base_draft_hash, parse_document from scripts.ars_anchorize_draft import anchorize_file, anchorize_text, main REPO_ROOT = Path(__file__).resolve().parent.parent MANIFEST_SCHEMA = json.loads( (REPO_ROOT / "shared" / "contracts" / "patch" / "block_manifest.schema.json").read_text() ) FIXTURE = """--- title: fixture --- # Heading First paragraph with a citation. - item one - item two ```python code, untouched ``` > quoted line Final paragraph. """ def _strip_marker_lines(text: str) -> str: kept = [ line for line in text.split("\n") if not MARKER_RE.match(line.rstrip("\r")) ] return "\n".join(kept) class TestAnchorizeText(unittest.TestCase): def test_all_blocks_labeled(self): anchored = anchorize_text(FIXTURE) parsed = parse_document(anchored) self.assertTrue(all(b.block_id is not None for b in parsed.blocks)) self.assertEqual(len(parsed.blocks), 6) def test_ids_zero_padded_sequential_document_order(self): anchored = anchorize_text(FIXTURE) ids = [b.block_id for b in parse_document(anchored).blocks] self.assertEqual(ids, ["B0001", "B0002", "B0003", "B0004", "B0005", "B0006"]) def test_idempotent(self): once = anchorize_text(FIXTURE) self.assertEqual(anchorize_text(once), once) def test_content_neutral(self): anchored = anchorize_text(FIXTURE) self.assertEqual(_strip_marker_lines(anchored), FIXTURE) def test_existing_ids_kept_fresh_is_max_plus_one(self): text = "\nLabeled.\n\nUnlabeled.\n" anchored = anchorize_text(text) ids = [b.block_id for b in parse_document(anchored).blocks] self.assertEqual(ids, ["B0007", "B0008"]) def test_marker_directly_above_block_no_blank_line(self): anchored = anchorize_text("Para.\n") self.assertEqual(anchored, "\nPara.\n") def test_crlf_draft_gets_crlf_marker_lines(self): anchored = anchorize_text("Para one.\r\n\r\nPara two.\r\n") self.assertEqual( anchored, "\r\nPara one.\r\n\r\n\r\nPara two.\r\n", ) def test_frontmatter_never_labeled(self): anchored = anchorize_text(FIXTURE) before_first_block = anchored.split("# Heading")[0] self.assertEqual(before_first_block.count("