diff --git a/msdmd/SKILL.md b/msdmd/SKILL.md index 1a6f0be..a891cc1 100644 --- a/msdmd/SKILL.md +++ b/msdmd/SKILL.md @@ -146,6 +146,13 @@ A reference implementation in pure stdlib Python lives at Both commit to zero non-stdlib dependencies so you can copy them into any project. +The Python reference helper owns its `MODULE_BUILD` and field-preservation +`CONTRACTS` beside the implementation. A consumer that executes this vendored +helper in its contract audit should reconcile those exact dependency declarations +and provide a local resolving `CHECKS` witness. The dependency's canonical owner +and exact source identity remain explicit; local execution does not transfer +parser ownership to the consumer. + Extension detection refuses ambiguous suffixes rather than sniffing content. For example, `.m` can mean Objective-C or MATLAB/Octave and therefore has no automatic marker. A caller that already knows the language may still call diff --git a/msdmd/parsers/universal.py b/msdmd/parsers/universal.py index e6cb88a..e25feee 100644 --- a/msdmd/parsers/universal.py +++ b/msdmd/parsers/universal.py @@ -1,4 +1,27 @@ -# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10 +# ratios: loc_comments=161:80 imports_exports=4:7 calls_definitions=55:10 +# === MODULE_BUILD === +# id: msdmd_python_reference_parser +# module_name: universal +# module_kind: instrument +# summary: parses canonical line-comment metadata without executing inspected source +# owner: The Interdependency skill-lib +# public_surface: COMMENT_MARKERS, RATIO_IDS, marker_for, parse_text, parse_file, walk_tree, parse_ratios, parse_ratios_file, ratios_placement +# internal_surface: marker and block matching helpers +# auth_boundary: none +# storage_boundary: read +# network_boundary: none +# user_data_boundary: read +# admin_only: false +# tests: tests/test_universal_parser.py +# rollout: exact-pinned reference parser propagation +# rollback: restore a previously accepted exact parser identity +# === END MODULE_BUILD === +# === CONTRACTS === +# id: msdmd_python_parser_preserves_field_names +# given: a valid metadata entry uses lowercase snake-case field names containing digits +# then: parsed entries retain those field names and string values without executing the inspected source +# class: evidence +# === END CONTRACTS === """Universal msdmd parser — pure stdlib. Implements the parser contract from ``msdmd/SKILL.md``: extracts every @@ -253,4 +276,4 @@ def ratios_placement(text: str, marker: str = "#") -> tuple[bool, bool]: last_ok = bool(line_re.match(raw.rstrip())) break return (opening_ok, last_ok) -# ratios: loc_comments=161:57 imports_exports=4:7 calls_definitions=55:10 \ No newline at end of file +# ratios: loc_comments=161:80 imports_exports=4:7 calls_definitions=55:10 diff --git a/tests/test_universal_parser.py b/tests/test_universal_parser.py index 9cf62bd..33b8860 100644 --- a/tests/test_universal_parser.py +++ b/tests/test_universal_parser.py @@ -1,3 +1,12 @@ +# === CHECKS === +# id: check_msdmd_python_numeric_field_contract +# proves: msdmd_python_parser_preserves_field_names +# call: self::test_parser_field_contract +# requires: python3 +# timeout: 10 +# mutates: filesystem +# cleanup: tempdir_teardown +# === END CHECKS === from __future__ import annotations import re @@ -18,6 +27,27 @@ ROOT = Path(__file__).resolve().parents[1] +def test_parser_field_contract() -> None: + """No-argument CHECKS witness, also executed by the unittest suite.""" + checks = unittest.TestCase() + helper = ROOT / "msdmd/parsers/universal.py" + module = parse_file(helper, "MODULE_BUILD")[0] + checks.assertEqual("msdmd_python_reference_parser", module["id"]) + checks.assertIn("COMMENT_MARKERS", module["public_surface"].split(", ")) + checks.assertEqual("read", module["storage_boundary"]) + checks.assertEqual("read", module["user_data_boundary"]) + checks.assertEqual("msdmd_python_parser_preserves_field_names", parse_file(helper, "CONTRACTS")[0]["id"]) + with tempfile.TemporaryDirectory() as directory: + marker = Path(directory) / "executed" + source = Path(directory) / "inspected.py" + text = "# === NARRATIVE ===\n# id: source_bound_narrative\n# evidence_sha256: abc123\n# === END NARRATIVE ===\n" + source.write_text(text + "from pathlib import Path\n" + f"Path({str(marker)!r}).write_text('executed')\n") + expected = [{"id": "source_bound_narrative", "evidence_sha256": "abc123"}] + checks.assertEqual(expected, parse_text(text, "NARRATIVE")) + checks.assertEqual(expected, parse_file(source, "NARRATIVE")) + checks.assertFalse(marker.exists(), "parsing executed inspected source") + + class UniversalParserTest(unittest.TestCase): def test_parse_single_block_with_multiple_entries(self) -> None: text = """# === CONTRACTS === @@ -58,15 +88,7 @@ def test_parse_all_matching_blocks_not_just_first(self) -> None: ) def test_parse_numeric_snake_case_field(self) -> None: - text = """# === NARRATIVE === -# id: source_bound_narrative -# evidence_sha256: abc123 -# === END NARRATIVE === -""" - self.assertEqual( - [{"id": "source_bound_narrative", "evidence_sha256": "abc123"}], - parse_text(text, "NARRATIVE"), - ) + test_parser_field_contract() def test_parse_typescript_comment_marker(self) -> None: text = """// === CAPABILITIES ===