Files
ThothII/scripts/test_workspace_descriptor_doc_contract.py

603 lines
30 KiB
Python
Executable File

#!/usr/bin/env python3
"""Unit and policy-matrix coverage for workspace descriptor documentation regions."""
import unittest
from dataclasses import dataclass
try:
from workspace_descriptor_doc_contract import (
ContractError,
_render_active_markdown,
check_document_text,
check_project_state_text,
scan_active_markdown,
)
except ModuleNotFoundError: # Support `python -m unittest scripts.test_...` from repo root.
from scripts.workspace_descriptor_doc_contract import (
ContractError,
_render_active_markdown,
check_document_text,
check_project_state_text,
scan_active_markdown,
)
WORKSPACE_START = "<!-- workspace-descriptor-contract:start -->"
WORKSPACE_END = "<!-- workspace-descriptor-contract:end -->"
NON_WORKSPACE_START = "<!-- non-workspace-migration:start -->"
NON_WORKSPACE_END = "<!-- non-workspace-migration:end -->"
@dataclass(frozen=True)
class PolicyCase:
name: str
expected: str
content: str
CASES = [
PolicyCase('m_schema_v1', 'R', 'Schema v1 descriptors return `migration_required`.'),
PolicyCase('m_schema_dash_v2', 'R', 'Schema-v2 descriptors report `migration_required`.'),
PolicyCase('m_schema_num1', 'R', 'Schema 1 descriptors remain `migration_required`.'),
PolicyCase('m_schema_word1', 'R', 'Schema version 1 descriptors remain `migration_required`.'),
PolicyCase('m_schema_under_colon', 'R', 'A descriptor with schema_version: 1 returns `migration_required`.'),
PolicyCase('m_schema_under_eq', 'R', 'A descriptor with schema_version=2 returns `migration_required`.'),
PolicyCase('m_schema_v1_and_v2', 'R', 'Schema v1 and v2 descriptors remain `migration_required`.'),
PolicyCase('m_bare_and', 'R', 'v1 and v2 descriptors remain `migration_required`.'),
PolicyCase('m_bare_or', 'R', 'v1 or v2 descriptors remain `migration_required`.'),
PolicyCase('m_bare_slash', 'R', 'v1/v2 descriptors remain `migration_required`.'),
PolicyCase('a_they', 'R', 'Schema v1 descriptors are rejected. They return `migration_required`.'),
PolicyCase('a_these_desc', 'R', 'Schema v1 descriptors are rejected. These descriptors return `migration_required`.'),
PolicyCase('a_those_desc', 'R', 'Schema v1 descriptors are rejected. Those descriptors return `migration_required`.'),
PolicyCase('a_such_desc', 'R', 'Schema v1 descriptors are rejected. Such descriptors return `migration_required`.'),
PolicyCase('a_their', 'R', 'Schema v1 descriptors are rejected. Their validation returns `migration_required`.'),
PolicyCase('a_the_desc', 'R', 'Schema v1 descriptors are rejected. The descriptors return `migration_required`.'),
PolicyCase('a_the_candidate', 'R', 'Schema v1 candidates are rejected. The candidate returns `migration_required`.'),
PolicyCase('a_still', 'R', 'Schema v1 descriptors are rejected, but still return `migration_required`.'),
PolicyCase('a_it', 'R', 'Schema v1 descriptor is rejected. It still returns `migration_required`.'),
PolicyCase('a_this_desc', 'R', 'Schema v1 descriptor is rejected. This descriptor still returns `migration_required`.'),
PolicyCase('a_that_desc', 'R', 'Schema v1 descriptor is rejected. That descriptor still returns `migration_required`.'),
PolicyCase('a_such_candidate', 'R', 'Schema v1 candidate is rejected. Such a candidate still returns `migration_required`.'),
PolicyCase('d_workspace', 'R', 'Workspace descriptors remain `migration_required`.'),
PolicyCase('d_possessive', 'R', "Workspace descriptors' status is `migration_required`."),
PolicyCase('d_validation', 'R', 'Workspace descriptor validation returns `migration_required`.'),
PolicyCase('d_legacy', 'R', 'Legacy descriptors remain `migration_required`.'),
PolicyCase('d_bare_descriptor', 'R', 'The descriptor remains `migration_required`.'),
PolicyCase('r_workspace', 'R', '`migration_required` is returned by workspace descriptors.'),
PolicyCase('r_workspace_status', 'R', '`migration_required` is the status for workspace descriptors.'),
PolicyCase('r_legacy', 'R', '`migration_required` applies to legacy descriptors.'),
PolicyCase('r_bare_descriptor', 'R', '`migration_required` is the status for the descriptor.'),
PolicyCase('u_standalone', 'A', 'The unrelated session database may report `migration_required`.'),
PolicyCase('u_after_period', 'A', 'Schema v1 descriptors are rejected. The unrelated session database may report `migration_required`.'),
PolicyCase('u_while', 'A', 'Schema v1 descriptors are rejected while the unrelated session database may report `migration_required`.'),
PolicyCase('u_and_the', 'A', 'Schema v1 descriptors are rejected and the unrelated session database may report `migration_required`.'),
PolicyCase('u_and_a', 'A', 'Schema v1 descriptors are rejected and a session database upgrade may report `migration_required`.'),
PolicyCase('u_and_this', 'A', 'Schema v1 descriptors are rejected and this unrelated session database may report `migration_required`.'),
PolicyCase('u_and_these', 'A', 'Schema v1 descriptors are rejected and these unrelated session database upgrades may report `migration_required`.'),
PolicyCase('u_and_our', 'A', 'Schema v1 descriptors are rejected and our unrelated session database may report `migration_required`.'),
PolicyCase('u_and_bare_subject', 'A', 'Schema v1 descriptors are rejected and session database upgrades may report `migration_required`.'),
PolicyCase('u_prev_then_these', 'A', 'Schema v1 descriptors are rejected. These unrelated session database upgrades report `migration_required`.'),
PolicyCase('u_api_versions', 'A', 'The unrelated session API v1 and v2 may report `migration_required`.'),
PolicyCase('u_db_schema_version', 'A', 'The unrelated session database schema version 1 may report `migration_required`.'),
PolicyCase('u_reverse_negative', 'A', '`migration_required` is not returned by workspace descriptors; it belongs to the session database.'),
PolicyCase('s_accept_although', 'A', 'Although schema v1 descriptors are rejected, the unrelated session database may report `migration_required`.'),
PolicyCase('s_accept_because', 'A', 'Schema v1 descriptors are rejected because the unrelated session database may report `migration_required`.'),
PolicyCase('s_accept_mentions_that', 'A', 'Schema v1 descriptor documentation mentions that the unrelated session database may report `migration_required`.'),
PolicyCase('s_accept_unrelated_descriptor', 'A', 'The unrelated session database descriptor reports `migration_required`.'),
PolicyCase('s_accept_unrelated_candidate', 'A', 'An unrelated candidate remains `migration_required`.'),
PolicyCase('s_reject_workspace_anaphor_they', 'R', 'Workspace descriptors are rejected. They return `migration_required`.'),
PolicyCase('s_reject_workspace_anaphor_it', 'R', 'A workspace descriptor is rejected. It returns `migration_required`.'),
PolicyCase('s_reject_descriptor_anaphor', 'R', 'The descriptor is rejected. It returns `migration_required`.'),
]
def workspace_region(extra=""):
body = (
"Schema v4 is the only accepted workspace descriptor. "
"Schema v1, v2, and v3 workspace descriptors are rejected before activation."
)
if extra:
body += "\n" + extra
return f"{WORKSPACE_START}\n{body}\n{WORKSPACE_END}"
def non_workspace_region(content):
return f"{NON_WORKSPACE_START}\n{content}\n{NON_WORKSPACE_END}"
def generic_fixture(*, workspace_extra="", current_extra=""):
return f"# Fixture\n\n{workspace_region(workspace_extra)}\n\n{current_extra}\n"
def project_fixture(*, workspace_extra="", current_extra="", historical_extra=""):
return (
"# Project state\n\n"
+ workspace_region(workspace_extra)
+ "\n\n"
+ current_extra
+ "\n\n# Historical archive\n"
+ "## Historical snapshots and archived reference notes\n\n"
+ historical_extra
+ "\n"
)
class PolicyMatrixTests(unittest.TestCase):
def test_52_case_matrix_across_both_entry_points(self):
self.assertEqual(len(CASES), 52)
for case in CASES:
if case.expected == "R":
generic = generic_fixture(workspace_extra=case.content)
project = project_fixture(workspace_extra=case.content)
else:
allowed = non_workspace_region(case.content)
generic = generic_fixture(current_extra=allowed)
project = project_fixture(current_extra=allowed)
for path, checker, text in (
("generic", check_document_text, generic),
("project", check_project_state_text, project),
):
with self.subTest(case=case.name, path=path, expected=case.expected):
if case.expected == "R":
with self.assertRaises(ContractError):
checker(text, f"{path}-{case.name}")
else:
checker(text, f"{path}-{case.name}")
class RegionStructureTests(unittest.TestCase):
def assert_invalid_both(self, generic, project=None):
with self.assertRaises(ContractError):
check_document_text(generic, "generic-invalid")
with self.assertRaises(ContractError):
check_project_state_text(project or project_fixture(current_extra=generic), "project-invalid")
def test_unmarked_unrelated_migration_required_is_rejected(self):
text = "The unrelated session database may report `migration_required`."
self.assert_invalid_both(generic_fixture(current_extra=text), project_fixture(current_extra=text))
def test_marked_unrelated_migration_required_is_accepted(self):
text = non_workspace_region("The session database may report `migration_required`.")
check_document_text(generic_fixture(current_extra=text), "generic-allowed")
check_project_state_text(project_fixture(current_extra=text), "project-allowed")
def test_missing_reversed_duplicate_and_nested_markers_are_rejected(self):
malformed = (
WORKSPACE_START,
WORKSPACE_END + "\n" + WORKSPACE_START,
workspace_region() + "\n" + workspace_region(),
WORKSPACE_START + "\n" + NON_WORKSPACE_START + "\n" + WORKSPACE_END + "\n" + NON_WORKSPACE_END,
NON_WORKSPACE_START + "\n" + NON_WORKSPACE_START + "\n" + NON_WORKSPACE_END + "\n" + NON_WORKSPACE_END,
NON_WORKSPACE_START + "\n" + workspace_region() + "\n" + NON_WORKSPACE_END,
workspace_region() + "\n" + NON_WORKSPACE_END,
)
for index, text in enumerate(malformed):
with self.subTest(index=index):
self.assert_invalid_both(text)
def test_migration_required_inside_workspace_block_is_rejected(self):
text = generic_fixture(workspace_extra="Descriptors return `migration_required`.")
self.assert_invalid_both(text, project_fixture(workspace_extra="Descriptors return `migration_required`."))
def test_legacy_support_inside_workspace_block_is_rejected(self):
text = generic_fixture(workspace_extra="Schema v1 descriptors are operational and readable.")
self.assert_invalid_both(
text,
project_fixture(workspace_extra="Schema v1 descriptors are operational and readable."),
)
def test_migrate_legacy_is_forbidden_even_in_non_workspace_region(self):
allowed = non_workspace_region("Run `migrate-legacy` for the session database.")
self.assert_invalid_both(generic_fixture(current_extra=allowed), project_fixture(current_extra=allowed))
def test_project_requires_terminal_historical_h1(self):
valid = project_fixture(historical_extra="Schema v2 returned `migration_required` historically.")
check_project_state_text(valid, "project-valid-history")
for name, text in (
("missing", valid.replace("# Historical archive\n", "")),
(
"blank-physical-line",
valid.replace(
"# Historical archive\n## Historical",
"# Historical archive\n\n## Historical",
),
),
(
"prose-physical-line",
valid.replace(
"# Historical archive\n## Historical",
"# Historical archive\nArchived notes follow.\n## Historical",
),
),
(
"comment-physical-line",
valid.replace(
"# Historical archive\n## Historical",
"# Historical archive\n<!-- archived -->\n## Historical",
),
),
(
"intervening-h2",
valid.replace(
"# Historical archive\n## Historical",
"# Historical archive\n## Other archive\n## Historical",
),
),
(
"intervening-setext-h2",
valid.replace(
"# Historical archive\n## Historical",
"# Historical archive\nOther archive\n-------------\n## Historical",
),
),
(
"setext-replacement-h2",
valid.replace(
"## Historical snapshots",
"Historical snapshots\n--------------------",
),
),
("later-h1", valid + "\n# Returned live section\n"),
("duplicate-h1", valid + "\n# Historical archive\n"),
):
with self.subTest(name=name), self.assertRaises(ContractError):
check_project_state_text(text, f"project-{name}")
def test_markers_inside_fences_comments_or_code_do_not_count(self):
fake = workspace_region()
for name, wrapped in (
("backtick-fence", f"```markdown\n{fake}\n```"),
("tilde-fence", f"~~~~\n{fake}\n~~~~"),
("outer-comment", f"<!--\n{fake}\n-->"),
("indented-code", "\n".join(" " + line for line in fake.splitlines())),
):
generic = f"# Fixture\n\n{wrapped}\n"
project = (
f"# Project\n\n{wrapped}\n\n# Historical archive\n"
"## Historical snapshots\n"
)
with self.subTest(name=name):
self.assert_invalid_both(generic, project)
def test_extra_inactive_marker_literals_do_not_duplicate_active_region(self):
fake_region = f"{WORKSPACE_START}\ninactive example\n{WORKSPACE_END}"
extras = (
f"```\n{fake_region}\n```",
f" ~~~\n{fake_region}\n ~~~~",
"\n".join(" " + line for line in fake_region.splitlines()),
)
for index, extra in enumerate(extras):
with self.subTest(index=index):
check_document_text(generic_fixture(current_extra=extra), f"generic-extra-{index}")
check_project_state_text(
project_fixture(current_extra=extra), f"project-extra-{index}"
)
nested_comment = f"<!--\n{fake_region}\n-->"
self.assert_invalid_both(
generic_fixture(current_extra=nested_comment),
project_fixture(current_extra=nested_comment),
)
def test_inline_and_partially_indented_markers_are_misplaced(self):
for name, marker in (
("inline", "text <!-- workspace-descriptor-contract:start -->"),
("one-space", " <!-- workspace-descriptor-contract:start -->"),
("inline-allow", "text <!-- non-workspace-migration:start -->"),
("one-space-allow", " <!-- non-workspace-migration:start -->"),
):
generic = generic_fixture(current_extra=marker)
project = project_fixture(current_extra=marker)
with self.subTest(name=name):
self.assert_invalid_both(generic, project)
def test_inactive_allow_markers_do_not_authorize_but_extra_literals_are_ignored(self):
allow = non_workspace_region("migration_required")
fake_token_region = non_workspace_region("migration_required")
fake_empty_region = non_workspace_region("inactive example")
wrappers = (
(f"```\n{fake_token_region}\n```", f"```\n{fake_empty_region}\n```", True),
(f"<!--\n{fake_token_region}\n-->", f"<!--\n{fake_empty_region}\n-->", False),
(
"\n".join(" " + line for line in fake_token_region.splitlines()),
"\n".join(" " + line for line in fake_empty_region.splitlines()),
True,
),
)
for index, (fake_with_token, fake_without_token, extra_allowed) in enumerate(wrappers):
with self.subTest(index=index, mode="sole"):
self.assert_invalid_both(
generic_fixture(current_extra=fake_with_token + "\nmigration_required"),
project_fixture(current_extra=fake_with_token + "\nmigration_required"),
)
extra_generic = generic_fixture(current_extra=fake_without_token + "\n" + allow)
extra_project = project_fixture(current_extra=fake_without_token + "\n" + allow)
with self.subTest(index=index, mode="extra"):
if extra_allowed:
check_document_text(extra_generic, f"generic-extra-allow-{index}")
check_project_state_text(extra_project, f"project-extra-allow-{index}")
else:
self.assert_invalid_both(extra_generic, extra_project)
def test_fence_closer_must_match_character_and_minimum_length(self):
fake = workspace_region()
for name, fenced in (
("short-backtick-close", f"````\n```\n{fake}"),
("wrong-character-close", f"~~~~\n```\n{fake}\n~~~~"),
):
project = (
f"# Project\n\n{fenced}\n\n# Historical archive\n"
"## Historical snapshots\n"
)
with self.subTest(name=name):
self.assert_invalid_both(f"# Fixture\n\n{fenced}\n", project)
safe_fake = f"{WORKSPACE_START}\ninactive example\n{WORKSPACE_END}"
valid_extra = f"````\n{safe_fake}\n`````"
check_document_text(generic_fixture(current_extra=valid_extra), "valid-long-close")
def test_noncanonical_contract_sentences_are_rejected(self):
variants = (
workspace_region().replace(
"Schema v4 is the only accepted workspace descriptor.",
"Only schema v4 workspace descriptors are accepted.",
),
workspace_region().replace(
"Schema v4 is the only accepted workspace descriptor.",
"Not Schema v4 is the only accepted workspace descriptor.",
),
workspace_region().replace(
"Schema v1, v2, and v3 workspace descriptors are rejected before activation.",
"Not Schema v1, v2, and v3 workspace descriptors are rejected before activation.",
),
)
for index, noncanonical in enumerate(variants):
with self.subTest(index=index):
self.assert_invalid_both(
generic_fixture().replace(workspace_region(), noncanonical),
project_fixture().replace(workspace_region(), noncanonical),
)
def test_remaining_legacy_claim_and_deleted_transformer_are_rejected(self):
for claim in (
"The system supports schema v1 descriptors.",
"A v2 descriptor remains readable.",
"Legacy-descriptor activation is operational.",
):
with self.subTest(claim=claim):
self.assert_invalid_both(
generic_fixture(workspace_extra=claim),
project_fixture(workspace_extra=claim),
)
for deleted in (
"Run the deleted legacy descriptor transformer.",
"Invoke the descriptor legacy migrator.",
"Use the legacy transformer.",
):
with self.subTest(deleted=deleted):
self.assert_invalid_both(
generic_fixture(current_extra=deleted),
project_fixture(current_extra=deleted),
)
def test_deleted_tools_are_rejected_after_active_markdown_rendering(self):
examples = (
"migrate-`**legacy**`",
"migrate-[legacy](https://example.invalid/tool)",
"migrate-[legacy][tool]\n\n[tool]: https://example.invalid/tool",
"legacy descriptor **transformer**",
"migrate&#45;legacy",
"migrate-<span>legacy</span>",
r"migrate\-legacy",
"legacy descriptor trans<!-- hidden -->former",
"Run migrate-[legacy\n](https://example.invalid/tool)",
"Run migrate-[legacy\n][tool]\n\n[tool]: https://example.invalid/tool",
"migrate-``\nlegacy\n``",
"<!-- hidden --> migrate-legacy",
"<!-- hidden --> legacy descriptor transformer",
"migrate-`\nlegacy\n`",
"<!-- hidden\ncomment --> migrate-legacy",
"migrate-legacy <!-- hidden\ncomment --> safe suffix",
)
for index, example in enumerate(examples):
with self.subTest(index=index, example=example):
self.assert_invalid_both(
generic_fixture(current_extra=example),
project_fixture(current_extra=example),
)
def test_deleted_tool_examples_in_inactive_markdown_are_allowed(self):
inactive_examples = (
"<!--\nmigrate-legacy\nlegacy descriptor transformer\n-->",
"<!-- migrate-legacy and legacy descriptor transformer -->",
"[safe label](https://example.invalid/migrate-legacy)",
"[safe label][tool]\n\n[tool]: https://example.invalid/migrate-legacy",
'<span data-example="migrate-legacy">safe text</span>',
"safe prefix <!-- migrate-legacy --> safe suffix",
"safe prefix <!--\nmigrate-legacy\nlegacy descriptor transformer\n--> safe suffix",
)
for index, example in enumerate(inactive_examples):
with self.subTest(index=index):
check_document_text(
generic_fixture(current_extra=example), f"generic-inactive-tool-{index}"
)
check_project_state_text(
project_fixture(current_extra=example), f"project-inactive-tool-{index}"
)
def test_deleted_tools_in_operator_visible_code_blocks_are_rejected(self):
examples = (
"```text\nmigrate-legacy\n```",
"~~~~\nlegacy descriptor transformer\n~~~~",
" migrate-legacy",
"\tlegacy descriptor transformer",
"```text\n[safe](https://example.invalid/migrate-legacy)\n```",
" <!-- migrate-legacy -->",
"```html\n<!-- migrate-legacy -->\n```",
"```html\n<!-- outer <!-- migrate-legacy --> -->\n```",
)
for index, example in enumerate(examples):
with self.subTest(index=index):
self.assert_invalid_both(
generic_fixture(current_extra=example),
project_fixture(current_extra=example),
)
def test_hidden_canonical_sentences_cannot_satisfy_workspace_contract(self):
canonical = workspace_region()[len(WORKSPACE_START) + 1 : -len(WORKSPACE_END) - 1]
hidden_bodies = (
f"<!--\n{canonical}\n-->",
f"```text\n{canonical}\n```",
"\n".join(" " + line for line in canonical.splitlines()),
f"`{canonical}`",
)
for index, hidden in enumerate(hidden_bodies):
hidden_region = f"{WORKSPACE_START}\n{hidden}\n{WORKSPACE_END}"
with self.subTest(index=index):
self.assert_invalid_both(
generic_fixture().replace(workspace_region(), hidden_region),
project_fixture().replace(workspace_region(), hidden_region),
)
def test_current_legacy_schema_references_require_non_workspace_region(self):
claim = "Schema v1 workspace descriptors remain operational and readable."
visible_claims = (
claim,
f"```text\n{claim}\n```",
" " + claim,
)
for index, visible_claim in enumerate(visible_claims):
with self.subTest(index=index):
self.assert_invalid_both(
generic_fixture(current_extra=visible_claim),
project_fixture(current_extra=visible_claim),
)
hidden_claim = f"<!-- {claim} -->"
check_document_text(
generic_fixture(current_extra=hidden_claim), "generic-hidden-legacy"
)
check_project_state_text(
project_fixture(current_extra=hidden_claim), "project-hidden-legacy"
)
allowed = non_workspace_region(claim)
check_document_text(generic_fixture(current_extra=allowed), "generic-allowed-legacy")
check_project_state_text(
project_fixture(current_extra=allowed), "project-allowed-legacy"
)
def test_html_comments_fail_closed_when_unclosed_or_nested(self):
malformed = (
"<!-- unclosed comment",
"safe prefix <!-- unclosed comment",
"<!-- outer\n<!-- inner -->\n-->\nmigrate-legacy",
(
"<!-- outer\n<!-- inner -->\n-->\n"
"Schema v1 workspace descriptors remain operational and readable."
),
"<!-- outer\n<!-- inner -->\n-->\nsafe trailing text",
)
for index, text in enumerate(malformed):
with self.subTest(index=index):
self.assert_invalid_both(
generic_fixture(current_extra=text),
project_fixture(current_extra=text),
)
visible_suffixes = (
"<!-- hidden --> migrate-legacy",
"<!-- hidden\n--> legacy descriptor transformer",
)
for index, text in enumerate(visible_suffixes):
with self.subTest(index=index, kind="visible-suffix"):
self.assert_invalid_both(
generic_fixture(current_extra=text),
project_fixture(current_extra=text),
)
pure_comments = (
"<!-- migrate-legacy -->",
"<!--\nlegacy descriptor transformer\n-->",
)
for index, text in enumerate(pure_comments):
with self.subTest(index=index, kind="pure-comment"):
check_document_text(
generic_fixture(current_extra=text), f"generic-pure-comment-{index}"
)
check_project_state_text(
project_fixture(current_extra=text), f"project-pure-comment-{index}"
)
def test_alternate_html_comment_closer_fails_closed_outside_code(self):
malformed = (
"<!-- hidden --!> migrate-legacy",
(
"<!-- hidden --!> "
"Schema v1 workspace descriptors remain operational and readable."
),
"<!-- hidden\n--!> migrate-legacy",
)
for index, text in enumerate(malformed):
generic = generic_fixture(current_extra=text)
project = project_fixture(current_extra=text)
with (
self.subTest(index=index, entry_point="generic"),
self.assertRaisesRegex(ContractError, "alternate HTML comment closer"),
):
check_document_text(generic, f"generic-alternate-closer-{index}")
with (
self.subTest(index=index, entry_point="project"),
self.assertRaisesRegex(ContractError, "alternate HTML comment closer"),
):
check_project_state_text(project, f"project-alternate-closer-{index}")
safe_code = (
"```html\n<!-- hidden --!> safe fenced example\n```\n"
" <!-- hidden --!> safe indented example"
)
check_document_text(generic_fixture(current_extra=safe_code), "generic-safe-code-closer")
check_project_state_text(
project_fixture(current_extra=safe_code), "project-safe-code-closer"
)
visible_code = (
"```html\n<!-- hidden --!> migrate-legacy\n```\n"
" <!-- hidden --!> Schema v1 workspace descriptors remain operational."
)
self.assert_invalid_both(
generic_fixture(current_extra=visible_code),
project_fixture(current_extra=visible_code),
)
def test_visible_comment_prefix_and_suffix_are_preserved_without_structural_reparse(self):
text = (
"safe prefix <!-- hidden --> safe suffix\n"
"before <!--\nhidden\n--> after\n"
"<!-- hidden --> # Reconstructed heading must not count\n"
)
scan = scan_active_markdown(text, "visible-comment-test")
self.assertEqual(
_render_active_markdown(scan),
"safe prefix safe suffix before after # Reconstructed heading must not count",
)
self.assertFalse(any(heading.text.startswith("Reconstructed") for heading in scan.headings))
def test_setext_h1_after_archive_is_rejected(self):
project = project_fixture(historical_extra="Returned live section\n=====================")
with self.assertRaises(ContractError):
check_project_state_text(project, "project-setext-live-tail")
def test_heading_literals_in_adversarial_fences_and_comments_are_inactive(self):
historical = (
"````\nFake live H1\n============\n```\n`````\n"
"<!--\nComment live H1\n===============\n-->"
)
check_project_state_text(
project_fixture(historical_extra=historical), "project-inactive-headings"
)
def test_historical_markers_cannot_satisfy_current_contract(self):
current_without = "# Project state\n\nNo current workspace contract.\n"
historical = "# Historical archive\n## Historical snapshots\n\n" + workspace_region()
with self.assertRaises(ContractError):
check_project_state_text(current_without + historical, "project-historical-marker")
if __name__ == "__main__":
unittest.main(verbosity=2)