From bcb5f173ea90eba6b1ebd2cf3fa96a48496a43e5 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Sun, 2 Aug 2026 17:40:27 -0400 Subject: [PATCH 1/4] Reapply "Extraction hardening: scheme (#992)" This reverts commit 6ac709d16699d48020547b8883d2938d1305dea3. --- gitgalaxy/standards/language_standards.py | 2 +- tests/extraction/languages/test_scheme.py | 123 ++++++++++++++++++ .../extraction/test_args_extraction_strict.py | 11 -- .../test_function_extraction_strict.py | 13 +- 4 files changed, 125 insertions(+), 24 deletions(-) create mode 100644 tests/extraction/languages/test_scheme.py diff --git a/gitgalaxy/standards/language_standards.py b/gitgalaxy/standards/language_standards.py index 3a8f828ff..e52c12ec4 100644 --- a/gitgalaxy/standards/language_standards.py +++ b/gitgalaxy/standards/language_standards.py @@ -11612,7 +11612,7 @@ class PrismConfigSchema(TypedDict): # missed the extremely common `` angle-bracket naming # convention for record types (SRFI-9/R6RS idiom, e.g. ``). "class_start": re.compile( - r"^[ \t]*\([ \t]*define-record-type\s+([a-zA-Z0-9_!?*+/<>=.~$%^&:-]+)(?=[ \t)\]\n\r])", + r"^[ \t\n]*\([ \t\n]*define-record-type[ \t\n]+(?:\([ \t\n]*)?([a-zA-Z0-9_!?*+/<>=.~$%^&:-]+)(?=[ \t\n)\]\r])", re.M, ), # --- PHASE 2: RISK & STRUCTURAL INTEGRITY --- diff --git a/tests/extraction/languages/test_scheme.py b/tests/extraction/languages/test_scheme.py new file mode 100644 index 000000000..abc3c0668 --- /dev/null +++ b/tests/extraction/languages/test_scheme.py @@ -0,0 +1,123 @@ + +import sys +from pathlib import Path +import pytest + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +from _extraction_harness import ( + assert_invalid_no_match, + assert_pathological_match, + assert_valid_match, +) +from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS + +scheme_rules = LANGUAGE_DEFINITIONS["scheme"]["rules"] +FUNC_START = scheme_rules.get("func_start") +ARGS = scheme_rules.get("args") +CLASS_START = scheme_rules.get("class_start") + +FUNCTION_CASES = { + "valid": [ + ("(define (TargetFunc x y)", "TargetFunc"), + ("(define (TargetFunc)", "TargetFunc"), + ("(define (string->number str)", "string->number"), + ("(define (foo* x)", "foo*"), + ("(define (1+ x)", "1+"), + ], + "invalid": [ + "(define-record-type TargetFunc", + "(if TargetFunc", + "(let ((TargetFunc 1))", + "(define TargetFunc 42)", + '"(define (TargetFunc x y)"', + '; (define (TargetFunc x y)', + ], + "pathological": [ + ("( \n define \n ( \n TargetFunc \n x \n )", "TargetFunc"), + ("(define \t (TargetFunc\n x\n y)", "TargetFunc"), + ], +} + +ARGS_CASES = { + "valid": [ + ("(define (TargetFunc a b)", "TargetFunc"), + ("(define (TargetFunc)", "TargetFunc"), + ("(define (TargetFunc a b . rest)", "TargetFunc"), + ("(define (TargetFunc a [b 1])", "TargetFunc"), + ], + "invalid": [ + "(TargetFunc a b)", + "(if (> a b)", + "(define TargetFunc 42)", + '"(define (TargetFunc a b)"', + '; (define (TargetFunc a b)', + ], + "pathological": [ + ("( \n define \n ( \n TargetFunc \n a \n b \n )", "TargetFunc"), + ("(define\n\t(TargetFunc\n\ta\n\tb)", "TargetFunc"), + ], +} + +CLASS_CASES = { + "valid": [ + ("(define-record-type TargetFunc (make-Target) Target?)", "TargetFunc"), + ("(define-record-type (make-target))", ""), + ("(define-record-type (TargetFunc x y)", "TargetFunc"), + ], + "invalid": [ + "(define (TargetFunc x y)", + "(let ((TargetFunc 1))", + '"(define-record-type TargetFunc"', + '; (define-record-type TargetFunc', + ], + "pathological": [ + ("( \n define-record-type \n TargetFunc \n (", "TargetFunc"), + ("(define-record-type \n \n (", ""), + ], +} + +class TestSchemeExtraction: + @pytest.mark.parametrize("payload, expected_name", FUNCTION_CASES.get("valid", [])) + def test_positive_function_extraction(self, payload, expected_name): + if not FUNC_START: pytest.skip("No pattern") + assert_valid_match(FUNC_START, payload, expected_name, "scheme") + + @pytest.mark.parametrize("payload", FUNCTION_CASES.get("invalid", [])) + def test_negative_function_extraction(self, payload): + if not FUNC_START: pytest.skip("No pattern") + assert_invalid_no_match(FUNC_START, payload, "scheme") + + @pytest.mark.parametrize("payload, expected_name", FUNCTION_CASES.get("pathological", [])) + def test_pathological_function_extraction(self, payload, expected_name): + if not FUNC_START: pytest.skip("No pattern") + assert_pathological_match(FUNC_START, payload, expected_name, "scheme") + + @pytest.mark.parametrize("payload, expected_name", ARGS_CASES.get("valid", [])) + def test_positive_args_extraction(self, payload, expected_name): + if not ARGS: pytest.skip("No pattern") + assert_valid_match(ARGS, payload, expected_name, "scheme") + + @pytest.mark.parametrize("payload", ARGS_CASES.get("invalid", [])) + def test_negative_args_extraction(self, payload): + if not ARGS: pytest.skip("No pattern") + assert_invalid_no_match(ARGS, payload, "scheme") + + @pytest.mark.parametrize("payload, expected_name", ARGS_CASES.get("pathological", [])) + def test_pathological_args_extraction(self, payload, expected_name): + if not ARGS: pytest.skip("No pattern") + assert_pathological_match(ARGS, payload, expected_name, "scheme") + + @pytest.mark.parametrize("payload, expected_name", CLASS_CASES.get("valid", [])) + def test_positive_class_extraction(self, payload, expected_name): + if not CLASS_START: pytest.skip("No pattern") + assert_valid_match(CLASS_START, payload, expected_name, "scheme") + + @pytest.mark.parametrize("payload", CLASS_CASES.get("invalid", [])) + def test_negative_class_extraction(self, payload): + if not CLASS_START: pytest.skip("No pattern") + assert_invalid_no_match(CLASS_START, payload, "scheme") + + @pytest.mark.parametrize("payload, expected_name", CLASS_CASES.get("pathological", [])) + def test_pathological_class_extraction(self, payload, expected_name): + if not CLASS_START: pytest.skip("No pattern") + assert_pathological_match(CLASS_START, payload, expected_name, "scheme") diff --git a/tests/extraction/test_args_extraction_strict.py b/tests/extraction/test_args_extraction_strict.py index a98d92ccc..3bd46c10e 100644 --- a/tests/extraction/test_args_extraction_strict.py +++ b/tests/extraction/test_args_extraction_strict.py @@ -81,17 +81,6 @@ ("proc \n ::namespace::TargetFunc \n { \n a \n b \n } \n {", "TargetFunc") ], }, - "scheme": { - "valid": [ - ("(define (TargetFunc a b)", "TargetFunc"), - ("(define (TargetFunc)", "TargetFunc"), - ], - "invalid": ["(TargetFunc a b)", "(if (> a b)"], - "pathological": [ - # Deep vertical S-expressions - ("( \n define \n ( \n TargetFunc \n a \n b \n )", "TargetFunc") - ], - }, } diff --git a/tests/extraction/test_function_extraction_strict.py b/tests/extraction/test_function_extraction_strict.py index cbcb4ec78..9cadb9592 100644 --- a/tests/extraction/test_function_extraction_strict.py +++ b/tests/extraction/test_function_extraction_strict.py @@ -128,18 +128,7 @@ "pathological": [("METHOD \n TargetFunc \n .", "TargetFunc")], }, - "scheme": { - "valid": [ - ("(define (TargetFunc x y)", "TargetFunc"), - ("(define (TargetFunc)", "TargetFunc"), - ], - "invalid": [ - "(define-record-type TargetFunc", - "(if TargetFunc", - "(let ((TargetFunc 1))", - ], - "pathological": [("( \n define \n ( \n TargetFunc \n x \n )", "TargetFunc")], - }, + "dockerfile": { "valid": [ ("RUN apt-get update", "RUN"), From 2db92412facb2ab1ad9922cff7f6767464871697 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Sun, 2 Aug 2026 17:51:21 -0400 Subject: [PATCH 2/4] fix: resolve ruff formatting and unused imports --- tests/extraction/languages/test_scheme.py | 37 +++++++++++++++-------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/tests/extraction/languages/test_scheme.py b/tests/extraction/languages/test_scheme.py index abc3c0668..3fd5ea4f2 100644 --- a/tests/extraction/languages/test_scheme.py +++ b/tests/extraction/languages/test_scheme.py @@ -1,6 +1,6 @@ - import sys from pathlib import Path + import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) @@ -9,6 +9,7 @@ assert_pathological_match, assert_valid_match, ) + from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS scheme_rules = LANGUAGE_DEFINITIONS["scheme"]["rules"] @@ -30,7 +31,7 @@ "(let ((TargetFunc 1))", "(define TargetFunc 42)", '"(define (TargetFunc x y)"', - '; (define (TargetFunc x y)', + "; (define (TargetFunc x y)", ], "pathological": [ ("( \n define \n ( \n TargetFunc \n x \n )", "TargetFunc"), @@ -50,7 +51,7 @@ "(if (> a b)", "(define TargetFunc 42)", '"(define (TargetFunc a b)"', - '; (define (TargetFunc a b)', + "; (define (TargetFunc a b)", ], "pathological": [ ("( \n define \n ( \n TargetFunc \n a \n b \n )", "TargetFunc"), @@ -68,7 +69,7 @@ "(define (TargetFunc x y)", "(let ((TargetFunc 1))", '"(define-record-type TargetFunc"', - '; (define-record-type TargetFunc', + "; (define-record-type TargetFunc", ], "pathological": [ ("( \n define-record-type \n TargetFunc \n (", "TargetFunc"), @@ -76,48 +77,58 @@ ], } + class TestSchemeExtraction: @pytest.mark.parametrize("payload, expected_name", FUNCTION_CASES.get("valid", [])) def test_positive_function_extraction(self, payload, expected_name): - if not FUNC_START: pytest.skip("No pattern") + if not FUNC_START: + pytest.skip("No pattern") assert_valid_match(FUNC_START, payload, expected_name, "scheme") @pytest.mark.parametrize("payload", FUNCTION_CASES.get("invalid", [])) def test_negative_function_extraction(self, payload): - if not FUNC_START: pytest.skip("No pattern") + if not FUNC_START: + pytest.skip("No pattern") assert_invalid_no_match(FUNC_START, payload, "scheme") @pytest.mark.parametrize("payload, expected_name", FUNCTION_CASES.get("pathological", [])) def test_pathological_function_extraction(self, payload, expected_name): - if not FUNC_START: pytest.skip("No pattern") + if not FUNC_START: + pytest.skip("No pattern") assert_pathological_match(FUNC_START, payload, expected_name, "scheme") @pytest.mark.parametrize("payload, expected_name", ARGS_CASES.get("valid", [])) def test_positive_args_extraction(self, payload, expected_name): - if not ARGS: pytest.skip("No pattern") + if not ARGS: + pytest.skip("No pattern") assert_valid_match(ARGS, payload, expected_name, "scheme") @pytest.mark.parametrize("payload", ARGS_CASES.get("invalid", [])) def test_negative_args_extraction(self, payload): - if not ARGS: pytest.skip("No pattern") + if not ARGS: + pytest.skip("No pattern") assert_invalid_no_match(ARGS, payload, "scheme") @pytest.mark.parametrize("payload, expected_name", ARGS_CASES.get("pathological", [])) def test_pathological_args_extraction(self, payload, expected_name): - if not ARGS: pytest.skip("No pattern") + if not ARGS: + pytest.skip("No pattern") assert_pathological_match(ARGS, payload, expected_name, "scheme") @pytest.mark.parametrize("payload, expected_name", CLASS_CASES.get("valid", [])) def test_positive_class_extraction(self, payload, expected_name): - if not CLASS_START: pytest.skip("No pattern") + if not CLASS_START: + pytest.skip("No pattern") assert_valid_match(CLASS_START, payload, expected_name, "scheme") @pytest.mark.parametrize("payload", CLASS_CASES.get("invalid", [])) def test_negative_class_extraction(self, payload): - if not CLASS_START: pytest.skip("No pattern") + if not CLASS_START: + pytest.skip("No pattern") assert_invalid_no_match(CLASS_START, payload, "scheme") @pytest.mark.parametrize("payload, expected_name", CLASS_CASES.get("pathological", [])) def test_pathological_class_extraction(self, payload, expected_name): - if not CLASS_START: pytest.skip("No pattern") + if not CLASS_START: + pytest.skip("No pattern") assert_pathological_match(CLASS_START, payload, expected_name, "scheme") From fba3a1f0c0cab0ccc53ec993c2851eca91962739 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Sun, 2 Aug 2026 18:33:49 -0400 Subject: [PATCH 3/4] fix: correct syntax error in test_args_extraction_strict.py --- tests/extraction/test_args_extraction_strict.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/extraction/test_args_extraction_strict.py b/tests/extraction/test_args_extraction_strict.py index a4c19c04f..b822ac964 100644 --- a/tests/extraction/test_args_extraction_strict.py +++ b/tests/extraction/test_args_extraction_strict.py @@ -70,8 +70,6 @@ ) ], }, - ], - }, } From 3580c783d9a6285720ccbbee42779480f59e87da Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Sun, 2 Aug 2026 18:36:15 -0400 Subject: [PATCH 4/4] chore: update golden master for tcl, yacc, and scheme --- tests/golden_master_audit.json | 57 +++++++++++++------------ tests/golden_master_zero_dep_audit.json | 57 +++++++++++++------------ 2 files changed, 60 insertions(+), 54 deletions(-) diff --git a/tests/golden_master_audit.json b/tests/golden_master_audit.json index a1d72587f..ea5067984 100644 --- a/tests/golden_master_audit.json +++ b/tests/golden_master_audit.json @@ -12,8 +12,8 @@ }, "Target Root Name": "data", "Absolute Project Path": "/home/joe/nyx_projects/language-crucible/data", - "Analysis ISO Timestamp": "2026-08-02T21:00:34.380214+00:00", - "Total Scan Duration": "27.12 seconds" + "Analysis ISO Timestamp": "2026-08-02T22:35:36.465352+00:00", + "Total Scan Duration": "28.45 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "main", @@ -4129,7 +4129,7 @@ }, "firewall": { "imports_whitelisted": 0, - "imports_unknown": 8398, + "imports_unknown": 8400, "imports_blacklisted": 0, "threats_found": 139, "threats_allowed": 0 @@ -9238,11 +9238,11 @@ "file_cluster_4": 11.947, "file_cluster_5": 12.007, "file_cluster_6": 11.805, - "file_cluster_7": 11.126, + "file_cluster_7": 11.127, "file_cluster_8": 10.51, "file_cluster_9": 11.766, "file_cluster_10": 12.467, - "file_cluster_11": 11.466, + "file_cluster_11": 11.467, "file_cluster_12": 11.576, "file_cluster_13": 11.512, "file_cluster_14": 15.505, @@ -9292,7 +9292,7 @@ "Sequential Logic Declarations": 488, "Function Parameters": 65, "Function/Method Declarations": 65, - "Class/Entity Declarations": 6, + "Class/Entity Declarations": 7, "Defensive Programming Constructs": 14, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -246917,26 +246917,26 @@ }, "3. Architectural Profile": { "Repository Archetype": "file_cluster_17", - "Repository Drift (Z-Score)": 14.511, + "Repository Drift (Z-Score)": 14.547, "Repository Fingerprint": { - "file_cluster_0": 14.576, - "file_cluster_1": 15.253, - "file_cluster_2": 15.098, - "file_cluster_3": 15.905, - "file_cluster_4": 14.675, - "file_cluster_5": 15.692, - "file_cluster_6": 14.863, - "file_cluster_7": 14.988, - "file_cluster_8": 14.527, - "file_cluster_9": 14.736, - "file_cluster_10": 15.479, - "file_cluster_11": 14.527, - "file_cluster_12": 15.254, - "file_cluster_13": 14.7, - "file_cluster_14": 17.825, - "file_cluster_15": 15.28, - "file_cluster_16": 15.243, - "file_cluster_17": 14.511 + "file_cluster_0": 14.602, + "file_cluster_1": 15.29, + "file_cluster_2": 15.133, + "file_cluster_3": 15.94, + "file_cluster_4": 14.713, + "file_cluster_5": 15.726, + "file_cluster_6": 14.898, + "file_cluster_7": 15.023, + "file_cluster_8": 14.566, + "file_cluster_9": 14.768, + "file_cluster_10": 15.515, + "file_cluster_11": 14.559, + "file_cluster_12": 15.291, + "file_cluster_13": 14.735, + "file_cluster_14": 17.832, + "file_cluster_15": 15.316, + "file_cluster_16": 15.279, + "file_cluster_17": 14.547 }, "File Archetype": null, "File Drift (Z-Score)": 0.0, @@ -247903,12 +247903,15 @@ "Agentic Rce": 0 }, "8. Dependency Network": { - "Direct Upstream (Fragility)": 0, + "Direct Upstream (Fragility)": 2, "Direct Downstream (Dependency Blast Radius)": 0, "Total Upstream (Absolute Fragility)": 0, "Total Downstream (Absolute Dependency Blast Radius)": 0 }, - "9. Extracted Dependencies": [] + "9. Extracted Dependencies": [ + "$testdir/malloc_common.tcl", + "$testdir/thread_common.tcl" + ] } } }, diff --git a/tests/golden_master_zero_dep_audit.json b/tests/golden_master_zero_dep_audit.json index 04495f47f..3e7254dc0 100644 --- a/tests/golden_master_zero_dep_audit.json +++ b/tests/golden_master_zero_dep_audit.json @@ -12,8 +12,8 @@ }, "Target Root Name": "data", "Absolute Project Path": "/home/joe/nyx_projects/language-crucible/data", - "Analysis ISO Timestamp": "2026-08-02T21:01:06.203842+00:00", - "Total Scan Duration": "24.31 seconds" + "Analysis ISO Timestamp": "2026-08-02T22:36:12.130018+00:00", + "Total Scan Duration": "26.02 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "main", @@ -4129,7 +4129,7 @@ }, "firewall": { "imports_whitelisted": 0, - "imports_unknown": 8398, + "imports_unknown": 8400, "imports_blacklisted": 0, "threats_found": 139, "threats_allowed": 0 @@ -9238,11 +9238,11 @@ "file_cluster_4": 11.947, "file_cluster_5": 12.007, "file_cluster_6": 11.805, - "file_cluster_7": 11.126, + "file_cluster_7": 11.127, "file_cluster_8": 10.51, "file_cluster_9": 11.766, "file_cluster_10": 12.467, - "file_cluster_11": 11.466, + "file_cluster_11": 11.467, "file_cluster_12": 11.576, "file_cluster_13": 11.512, "file_cluster_14": 15.505, @@ -9292,7 +9292,7 @@ "Sequential Logic Declarations": 488, "Function Parameters": 65, "Function/Method Declarations": 65, - "Class/Entity Declarations": 6, + "Class/Entity Declarations": 7, "Defensive Programming Constructs": 14, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -246917,26 +246917,26 @@ }, "3. Architectural Profile": { "Repository Archetype": "file_cluster_17", - "Repository Drift (Z-Score)": 14.511, + "Repository Drift (Z-Score)": 14.547, "Repository Fingerprint": { - "file_cluster_0": 14.576, - "file_cluster_1": 15.253, - "file_cluster_2": 15.098, - "file_cluster_3": 15.905, - "file_cluster_4": 14.675, - "file_cluster_5": 15.692, - "file_cluster_6": 14.863, - "file_cluster_7": 14.988, - "file_cluster_8": 14.527, - "file_cluster_9": 14.736, - "file_cluster_10": 15.479, - "file_cluster_11": 14.527, - "file_cluster_12": 15.254, - "file_cluster_13": 14.7, - "file_cluster_14": 17.825, - "file_cluster_15": 15.28, - "file_cluster_16": 15.243, - "file_cluster_17": 14.511 + "file_cluster_0": 14.602, + "file_cluster_1": 15.29, + "file_cluster_2": 15.133, + "file_cluster_3": 15.94, + "file_cluster_4": 14.713, + "file_cluster_5": 15.726, + "file_cluster_6": 14.898, + "file_cluster_7": 15.023, + "file_cluster_8": 14.566, + "file_cluster_9": 14.768, + "file_cluster_10": 15.515, + "file_cluster_11": 14.559, + "file_cluster_12": 15.291, + "file_cluster_13": 14.735, + "file_cluster_14": 17.832, + "file_cluster_15": 15.316, + "file_cluster_16": 15.279, + "file_cluster_17": 14.547 }, "File Archetype": null, "File Drift (Z-Score)": 0.0, @@ -247903,12 +247903,15 @@ "Agentic Rce": 0 }, "8. Dependency Network": { - "Direct Upstream (Fragility)": 0, + "Direct Upstream (Fragility)": 2, "Direct Downstream (Dependency Blast Radius)": 0, "Total Upstream (Absolute Fragility)": 0, "Total Downstream (Absolute Dependency Blast Radius)": 0 }, - "9. Extracted Dependencies": [] + "9. Extracted Dependencies": [ + "$testdir/malloc_common.tcl", + "$testdir/thread_common.tcl" + ] } } },