From 03019e2566f31a5252f4c11be47e0429113a369d Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 04:28:05 +0000 Subject: [PATCH 1/2] Declare and execute the TypeScript parser numeric-field contract --- .github/workflows/ci.yml | 3 +++ msdmd/parsers/universal.ts | 23 ++++++++++++++++++++++ tests/test_universal_parser.py | 35 ++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de4d41b..684beef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,9 @@ jobs: - uses: actions/setup-python@v7.0.0 with: python-version: "3.x" + - uses: actions/setup-node@v6 + with: + node-version: "24.15.0" - name: Unit tests run: python -m unittest discover -s tests - name: Exact EDCM cross-source construction witness diff --git a/msdmd/parsers/universal.ts b/msdmd/parsers/universal.ts index 67b7b21..6b4dc72 100644 --- a/msdmd/parsers/universal.ts +++ b/msdmd/parsers/universal.ts @@ -1,4 +1,27 @@ // ratios: loc_comments=hmmm imports_exports=hmmm calls_definitions=hmmm +// === MODULE_BUILD === +// id: msdmd_typescript_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: Entry, WalkOptions, COMMENT_MARKERS, RATIO_IDS, markerFor, parseText, parseFile, walkTree, parseRatios, parseRatiosFile, ratiosPlacement +// 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::test_typescript_parser_field_contract +// rollout: exact-pinned reference parser propagation +// rollback: restore a previously accepted exact parser identity +// === END MODULE_BUILD === +// === CONTRACTS === +// id: msdmd_typescript_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 Node stdlib (fs, path). * diff --git a/tests/test_universal_parser.py b/tests/test_universal_parser.py index 33b8860..dd6d197 100644 --- a/tests/test_universal_parser.py +++ b/tests/test_universal_parser.py @@ -10,6 +10,8 @@ from __future__ import annotations import re +import json +import subprocess import tempfile import unittest from pathlib import Path @@ -48,7 +50,40 @@ def test_parser_field_contract() -> None: checks.assertFalse(marker.exists(), "parsing executed inspected source") +# === CHECKS === +# id: check_msdmd_typescript_numeric_field_contract +# proves: msdmd_typescript_parser_preserves_field_names +# call: self::test_typescript_parser_field_contract +# requires: python3, node24 +# timeout: 10 +# mutates: filesystem +# cleanup: tempdir_teardown +# === END CHECKS === + + +def test_typescript_parser_field_contract() -> None: + """Execute the actual TypeScript parser using Node's native type stripping.""" + checks = unittest.TestCase() + helper = ROOT / "msdmd/parsers/universal.ts" + module = parse_file(helper, "MODULE_BUILD")[0] + checks.assertEqual("msdmd_typescript_reference_parser", module["id"]) + checks.assertEqual("msdmd_typescript_parser_preserves_field_names", parse_file(helper, "CONTRACTS")[0]["id"]) + with tempfile.TemporaryDirectory() as directory: + marker = Path(directory) / "executed" + source = Path(directory) / "inspected.ts" + text = "// === NARRATIVE ===\n// id: source_bound_narrative\n// evidence_sha256: abc123\n// === END NARRATIVE ===\n" + source.write_text(text + 'import {writeFileSync} from "node:fs";\n' + f'writeFileSync({json.dumps(str(marker))}, "executed");\n') + script = f"import {{parseText, parseFile}} from {json.dumps(helper.as_uri())};" + f"process.stdout.write(JSON.stringify([parseText({json.dumps(text)}, 'NARRATIVE', '//'),parseFile({json.dumps(str(source))}, 'NARRATIVE')]));" + result = subprocess.run(["node", "--input-type=module", "--eval", script], check=True, capture_output=True, text=True) + expected = [{"id": "source_bound_narrative", "evidence_sha256": "abc123"}] + checks.assertEqual([expected, expected], json.loads(result.stdout)) + checks.assertFalse(marker.exists(), "TypeScript parsing executed inspected source") + + class UniversalParserTest(unittest.TestCase): + def test_typescript_numeric_field_contract(self) -> None: + test_typescript_parser_field_contract() + def test_parse_single_block_with_multiple_entries(self) -> None: text = """# === CONTRACTS === # id: first_contract From 5e7239b52dc5403d8d01fbc63341fe397719ec3f Mon Sep 17 00:00:00 2001 From: Erin Spencer Date: Sat, 12 Sep 2026 04:29:35 +0000 Subject: [PATCH 2/2] Keep both reference parser ownership boundaries explicit --- msdmd/SKILL.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/msdmd/SKILL.md b/msdmd/SKILL.md index a891cc1..9a6a036 100644 --- a/msdmd/SKILL.md +++ b/msdmd/SKILL.md @@ -146,10 +146,10 @@ 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 +The Python and TypeScript reference helpers each own `MODULE_BUILD` and +field-preservation `CONTRACTS` beside their implementations. A consumer that +executes or updates a vendored helper should reconcile its 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.