From 48d09acc4a3fa0cd3a9d400b8fe6c2c089521808 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Fri, 4 Sep 2026 21:56:55 -0400 Subject: [PATCH 1/2] feat(core-engine): yacc's %union is a real class_start, with the allowlist entry that makes it safe (#2644) `yacc.py` wired `class_start: None` on the reasoning that a grammar file has no object/type concept. True for OOP-style classes, but it misses that Bison's `%union` directive declares a real compound type -- the C union spanning every grammar rule's semantic value (`$$`/`$1`, which `args` already counts). That is the same "non-OOP language's struct/class equivalent" mapping the engine already makes for Fortran's `TYPE ... END TYPE`, COBOL's `PROGRAM-ID` and assembly's `struc` macros, and it is core grammar syntax rather than incidentally-embedded C: `internal_discriminator` already lists `union` among the `%`-directives used to identify a file as yacc in the first place. The rule alone would have made yacc worse. detector.py's named-class extractor consults a language's own `class_start` only for languages in `_CLASS_START_NAMED_EXTRACTION_LANGS`; everyone else falls through to a legacy generic regex (`class|struct|interface|trait|enum`), which reads every `struct foo` declaration in a grammar's embedded C action code as a class -- 17 on config.y, 9 on jailparse.y and 109 across all four real grammar files in the crucible corpus, where the honest answers are 1, 1 and 2. So yacc joins the allowlist in the same change; the two halves only make sense together. Verified by direct source cross-check, the same way abap/cobol/jcl/sqlite were: yacc is tree-sitter-blind, and ctags cannot corroborate classes either (`ctags --list-kinds-full=YACC` exposes exactly one kind, `l`, which is why `CTAGS_CLASS_KINDS["yacc"]` is empty on purpose). `%union` fires exactly once in each grammar that declares one (config.y:1, jailparse.y:45) and zero times in the two that do not (gnucobol's parser.y/scanner.l use `%define api.value.type`) -- 100% precision, and an honest zero where there is no union. Golden masters re-blessed. The diff is exactly two lines in each mode: `Class/Entity Declarations` 0 -> 1 on config.y and jailparse.y. Nothing else moves -- no mass, no risk exposure, no topological re-solve. Tests: the yacc extraction gauntlet's `CLASS_CASES` were empty (the rule was None) and are now populated, including the invalid cases that matter here -- a bare C `union`/`struct` in action code, a mid-line or commented-out occurrence, and `%unionize` against the `\b` guard. Two detector-level tests pin the pair together (one `%union` plus surrounding C structs -> exactly one class; a grammar with no `%union` -> none), plus ReDoS coverage for the new rule. Closes #2644. Part of #2669. Co-Authored-By: Claude Opus 5 (1M context) --- docs/language_status/yacc.md | 54 +++++++++++-- gitgalaxy/core/detector.py | 20 +++++ .../language_standards/languages/yacc.py | 24 +++++- tests/core_engine/test_detector.py | 76 +++++++++++++++++++ tests/extraction/languages/test_yacc.py | 53 ++++++++++++- .../extraction/languages/test_yacc_strict.py | 4 + tests/golden_master_audit.json | 8 +- tests/golden_master_zero_dep_audit.json | 8 +- 8 files changed, 230 insertions(+), 17 deletions(-) diff --git a/docs/language_status/yacc.md b/docs/language_status/yacc.md index ba2881ca9..5825a3cbe 100644 --- a/docs/language_status/yacc.md +++ b/docs/language_status/yacc.md @@ -20,9 +20,9 @@ part of this doc with the most recent, most detailed investigation behind it. | `_meta.blueprint_version` | v5.1 | | `_meta.last_updated` | 2026-03-11 | | `lexical_family` | `standard_block` | -| Structural signature keys wired | 31 / 47 (16 explicit `None`, incl. `class_start` — a grammar file has no object/type concept) | +| Structural signature keys wired | 33 / 48 (15 explicit `None`) — `class_start` joined the wired set in [#2644](https://github.com/squid-protocol/gitgalaxy/issues/2644) | | Function-slicing integration mode | **Mode A (label-greedy)** since 2026-08-27 (was Mode B / brace-based — see §9) | -| Extraction-gauntlet + strict test files | `test_yacc.py`, `test_yacc_strict.py` (68 passing, 1 skipped) | +| Extraction-gauntlet + strict test files | `test_yacc.py`, `test_yacc_strict.py` (98 passing, 1 skipped) | ## 2. Identification surface @@ -40,13 +40,23 @@ whitespace/comments before the `:`) — the closest function-analog the cross-la for a grammar language, the same design decision behind `makefile` targets and `assembly` labels. `args` counts `$1`/`$2`/`$$` positional value references inside a rule's action as a per-rule argument-count proxy (the same spirit as the documented bash/Perl `$1`/`$2` precedent in -`docs/why_gitgalaxy_beats_ast_here.md`). `class_start` is `None`. The remaining 29 wired keys -(branch, io, safety, memory_alloc, macros, pointers, …) run against the embedded C/C++ action and -prologue/epilogue code. +`docs/why_gitgalaxy_beats_ast_here.md`). + +`class_start` targets the **`%union` directive** (#2644) — the C union spanning every rule's +semantic value (`$$`/`$1`, which `args` already counts), and the one real compound type a grammar +declares. That is the same "non-OOP language's struct/class equivalent" mapping the engine already +makes for Fortran's `TYPE … END TYPE`, COBOL's `PROGRAM-ID` and assembly's `struc` macros, and it +is core grammar syntax rather than incidentally-embedded C: `internal_discriminator` already lists +`union` among the `%`-directives used to identify a file as yacc in the first place. Bison's rarer +named-tag form (`%union name {`) captures the tag; the common anonymous form resolves to +`Anonymous_Class`, the same path assembly's own no-name `class_start` takes. + +The remaining wired keys (branch, io, safety, memory_alloc, macros, pointers, …) run against the +embedded C/C++ action and prologue/epilogue code. ## 4. What GitGalaxy explicitly does not track -`class_start` and 15 other keys are wired to `None`: `test`, `concurrency`, `ui_framework`, +15 keys are wired to `None`: `test`, `concurrency`, `ui_framework`, `closures`, `decorators`, `comprehensions`, `scientific`, `ssr_boundaries`, `events`, `dependency_injection`, `inline_asm`, `thread_sleeps`, `sync_locks`, `listeners`, `test_skip` — none have a meaningful analog in a grammar-definition file. @@ -67,7 +77,8 @@ none have a meaningful analog in a grammar-definition file. ## 6. Test depth `tests/extraction/languages/test_yacc.py` (extraction gauntlet) and `test_yacc_strict.py` (ReDoS / -boundary correctness, scaling-ratio methodology). 68 passing, 1 skipped as of this snapshot. +boundary correctness, scaling-ratio methodology). 98 passing, 1 skipped as of this snapshot — the +`class_start` / `%union` cases landed with #2644. ## 7. Relevant closed work @@ -76,6 +87,9 @@ boundary correctness, scaling-ratio methodology). 68 passing, 1 skipped as of th - [#846](https://github.com/squid-protocol/gitgalaxy/issues/846) — extraction hardening for yacc. - [#713](https://github.com/squid-protocol/gitgalaxy/issues/713) — `spec_exposure` unbounded-`[^\]]*` ReDoS fix, applied across 28 languages including yacc. +- [#2644](https://github.com/squid-protocol/gitgalaxy/issues/2644) — `%union` wired as + `class_start`, together with yacc's entry in `detector.py`'s + `_CLASS_START_NAMED_EXTRACTION_LANGS` (see §8). - [#1926](https://github.com/squid-protocol/gitgalaxy/issues/1926) — both real `.y` corpus files were silently excluded from `file_data` by `statistical_auditor.py`; fixing it is what first made yacc visible to the tri-comparison tool at all (the §9 ledger shape was `first_seen` the @@ -87,6 +101,32 @@ The comparison corpus is small (`language-crucible/data/yacc/freebsd/` — FreeB `jailparse.y`), plus `.y`/`.l` files that live inside other language corpora (`cobol/gnucobol_internals/parser.y` + `scanner.l`, an 18k-line real Bison grammar). +**`class_start` / `%union` precision (#2644).** yacc is tree-sitter-blind, so the rule was verified +by direct source cross-check against those four real grammar files rather than by +`tree_sitter_accuracy_audit.py` — the same position abap, cobol, jcl and sqlite are in on +`_CLASS_START_NAMED_EXTRACTION_LANGS`. ctags cannot corroborate it either: `ctags +--list-kinds-full=YACC` exposes exactly one kind, `l` (label), which is why +`CTAGS_CLASS_KINDS["yacc"]` is empty on purpose and §9's comparison covers functions only. So a +direct read of the four grammar files is the only external check there is, and it is the one that +was done: + +| file | `%union` | `class_count` | note | +|---|---|---|---| +| `yacc/freebsd/config.y` | 1 (line 1) | 1 | anonymous union → `Anonymous_Class` | +| `yacc/freebsd/jailparse.y` | 1 (line 45) | 1 | same shape | +| `cobol/gnucobol_internals/parser.y` | 0 | 0 | uses `%define api.value.type`, declares no union | +| `cobol/gnucobol_internals/scanner.l` | 0 | 0 | a lex scanner: no semantic-value union | + +100% precision, no false positives, and an honest zero where a grammar has no union. + +**Why the `_CLASS_START_NAMED_EXTRACTION_LANGS` entry is not optional.** The named-class extractor +only consults a language's own `class_start` for allowlisted languages; everyone else falls through +to a legacy generic regex (`class|struct|interface|trait|enum`). A grammar's embedded C action code +is full of ordinary `struct` declarations, so leaving yacc off the allowlist while wiring the rule +reports **17** classes on `config.y`, **9** on `jailparse.y` and **109** across all four files — +where the honest answers are 1, 1 and 2. Wiring the rule alone would have been worse than the +`None` it replaced; the two changes only make sense together. + ## 9. Tri-comparison: GitGalaxy vs. ctags (no privileged ground truth) **Summary.** The one discrepancy shape the tri-comparison tool ever flagged for yacc diff --git a/gitgalaxy/core/detector.py b/gitgalaxy/core/detector.py index 0ec1c5c7b..210992367 100644 --- a/gitgalaxy/core/detector.py +++ b/gitgalaxy/core/detector.py @@ -532,6 +532,26 @@ def get_mode(cls, lang_id: str) -> Optional[str]: "swift", "tcl", "typescript", + # #2644: yacc gets its own `class_start` (`%union`, a grammar's one real + # compound-type declaration) in the SAME change that adds this entry, and + # the entry is the load-bearing half. A grammar file's embedded C action + # code is full of ordinary `struct foo` declarations, so the legacy + # generic fallback (`class|struct|interface|trait|enum`) reads them all as + # classes: 17 on config.y and 9 on jailparse.y where the honest answer is + # 1 each, and 109 across all four real grammar files in the crucible + # corpus (gnucobol's 18k-line parser.y alone contributes 56, with no + # `%union` and therefore no real class at all). Wiring the rule without + # this entry would make yacc WORSE than the `None` it replaced. + # + # Verified by direct source cross-check rather than + # tree_sitter_accuracy_audit.py: yacc is one of the tree-sitter-blind + # languages (no grammar available to this repo's tooling), the same + # position abap/cobol/jcl/sqlite are in above. Measured: `%union` fires + # exactly once in each grammar that has one (config.y:1, jailparse.y:45), + # zero times in the two that don't (gnucobol's parser.y/scanner.l use + # `%define api.value.type` instead) -- 100% precision, no false positives, + # documented in docs/language_status/yacc.md §8. + "yacc", "zig", } ) diff --git a/gitgalaxy/standards/language_standards/languages/yacc.py b/gitgalaxy/standards/language_standards/languages/yacc.py index c8584d0a3..66cdd3bce 100644 --- a/gitgalaxy/standards/language_standards/languages/yacc.py +++ b/gitgalaxy/standards/language_standards/languages/yacc.py @@ -69,7 +69,29 @@ r"^[ \t]*(?!(?:case|default|public|private|protected)\b)([a-zA-Z_]\w*)(?=(?:[ \t\n]|/\*(?:[^*]|\*[^/])*\*/|//[^\n]*)*:)", re.M, ), - "class_start": None, + # #2644: Bison/Yacc's `%union` directive declares a real compound type -- + # the C union spanning every rule's semantic value (`$$`/`$1`, already + # counted by `args`). Same "non-OOP language's struct/class equivalent" + # mapping the engine already makes for Fortran's `TYPE ... END TYPE`, + # COBOL's `PROGRAM-ID` and assembly's `struc` macros -- and core grammar + # syntax, not embedded C: `internal_discriminator` above already lists + # `union` among the `%`-directives that IDENTIFY a file as yacc. + # + # Optional group 1 captures bison's rarer named-tag form (`%union name {`); + # the common anonymous form leaves it unset and resolves to + # "Anonymous_Class" through `_resolve_class_start_match`, the same path + # assembly's own no-name `class_start` takes. Deliberately no group 2 -- + # a union has no inheritance parent for detector.py's group-2-is-parent + # convention to misread. + # + # NOTE: this rule is only reachable for named extraction because yacc is + # in detector.py's `_CLASS_START_NAMED_EXTRACTION_LANGS`. Removing it + # there does not restore the old behavior -- it drops yacc onto the + # legacy generic fallback (`class|struct|interface|trait|enum`), which + # reads every `struct foo` declaration in a grammar's embedded C actions + # as a class: 17 and 9 on the two real corpus grammars where the honest + # answer is 1 each. The two changes only make sense together. + "class_start": re.compile(r"^[ \t]*%union\b(?:[ \t]+([a-zA-Z_]\w*))?", re.M), # --- PHASE 2: RISK & STRUCTURAL INTEGRITY --- "safety": re.compile(r"\b(assert|YYABORT|YYACCEPT|YYERROR)\b"), "safety_bypasses": re.compile(r"\bgoto\b|\bvoid\s*\*"), diff --git a/tests/core_engine/test_detector.py b/tests/core_engine/test_detector.py index c0b0fb420..dab951f23 100644 --- a/tests/core_engine/test_detector.py +++ b/tests/core_engine/test_detector.py @@ -3909,3 +3909,79 @@ def test_detector_api_declared_orphans_ignores_hits_outside_the_declaration(): "only the non-static declaration is public surface the api rule already counted -- " "the static one's body-local `int counter = 0;` api hit must not suppress it" ) + + +# ============================================================================== +# TEST: YACC NAMED-CLASS EXTRACTION USES %union, NOT THE GENERIC FALLBACK (#2644) +# ============================================================================== +def test_detector_yacc_class_extraction_ignores_embedded_c_structs(): + """ + Regression for #2644. yacc's `class_start` was `None`, so a grammar's one + real compound type -- bison's `%union`, the C union spanning every rule's + semantic value -- was invisible. Wiring that rule is only half the change: + the named-class extractor consults a language's own `class_start` ONLY if + the language is in `_CLASS_START_NAMED_EXTRACTION_LANGS`, otherwise it falls + through to the legacy generic regex (`class|struct|interface|trait|enum`), + which reads every `struct foo` declaration in a grammar's embedded C action + code as a class -- 17 and 9 on the two real corpus grammars where the honest + answer is 1 each. + + So this test pins the pair together: one `%union`, several ordinary C + `struct` declarations around it, exactly one extracted class. + """ + from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS + + yacc_detector = StructuralExtractor("yacc", LANGUAGE_DEFINITIONS) + code = ( + "%union {\n" + "\tchar\t*str;\n" + "\tstruct\tfile_list *file;\n" + "}\n" + "%%\n" + "file_spec:\n" + "\tNAME {\n" + "\t\tstruct file_list *fl;\n" + "\t\tstruct device dev;\n" + "\t\tnewfile($1);\n" + "\t}\n" + "\t;\n" + ) + + result = yacc_detector.splice(code, "") + + names = [c.get("name") for c in result.get("classes", [])] + assert names == ["Anonymous_Class"], ( + f"expected exactly the %union block as the file's one class, got {names} -- " + "yacc dropped off _CLASS_START_NAMED_EXTRACTION_LANGS and the generic " + "fallback is reading embedded C structs as classes again" + ) + assert result["equations"].get("class_start") == 1, "the %union directive must count once as a class_start signal" + + +def test_detector_yacc_grammar_without_a_union_declares_no_class(): + """ + #2644's other half: a grammar that uses `%define api.value.type` instead of + `%union` (gnucobol's 18k-line parser.y does) genuinely has no compound type + to declare. Its embedded C is still full of `struct` declarations -- 56 of + them would surface as classes on the generic fallback -- so an honest zero + here is what proves the language's own rule is the one being consulted. + """ + from gitgalaxy.standards.language_standards import LANGUAGE_DEFINITIONS + + yacc_detector = StructuralExtractor("yacc", LANGUAGE_DEFINITIONS) + code = ( + "%define api.value.type union\n" + "%%\n" + "statement:\n" + "\tWORD {\n" + "\t\tstruct cb_field *f;\n" + "\t\tstruct cb_tree_common *x;\n" + "\t\temit($1);\n" + "\t}\n" + "\t;\n" + ) + + result = yacc_detector.splice(code, "") + + assert result.get("classes") == [], f"a grammar with no %union must declare no class, got {result.get('classes')}" + assert not result["equations"].get("class_start"), "no %union directive means no class_start signal" diff --git a/tests/extraction/languages/test_yacc.py b/tests/extraction/languages/test_yacc.py index c64b5078a..e23f73d9f 100644 --- a/tests/extraction/languages/test_yacc.py +++ b/tests/extraction/languages/test_yacc.py @@ -50,7 +50,40 @@ "pathological": [], } -CLASS_CASES = {"valid": [], "invalid": [], "pathological": []} +# #2644: `%union` is a grammar's one real compound-type declaration -- the C +# union spanning every rule's semantic value. The common anonymous form +# captures no name (expected_name None: the payload must match, and +# _resolve_class_start_match resolves it to "Anonymous_Class", the same path +# assembly's no-name class_start takes); bison's rarer named-tag form +# `%union name {` captures the tag in group 1. +CLASS_CASES = { + "valid": [ + ("%union {", None), + ("%union\t{", None), + (" %union {", None), + ("%union TargetUnion {", "TargetUnion"), + ("%union _target_union", "_target_union"), + ], + "invalid": [ + # Other `%` directives, including the ones `structural_boundaries` owns. + "%token TargetUnion", + "%type expr", + # \b guards the directive name: `%unionize` is not `%union`. + "%unionize {", + # A bare C `union` in embedded action code is not the directive -- this + # is the whole reason yacc needs its own rule instead of the generic + # `class|struct|interface|trait|enum` fallback. + "union TargetUnion {", + "\tstruct file_list *file;", + # Only whitespace may precede the directive: mid-line and commented-out + # occurrences are not declarations. + "yyval = 0; %union {", + "/* %union { */", + ], + "pathological": [ + ("\t \t%union \t TargetUnion {", "TargetUnion"), + ], +} DEPENDENCY_CASES = {"valid": [], "invalid": [], "pathological": []} @@ -89,3 +122,21 @@ def test_invalid_args_extraction(case): def test_pathological_args_extraction(case): pattern = LANGUAGE_DEFINITIONS["yacc"]["rules"]["args"] assert_pathological_match(pattern, case[0], case[1], "yacc.args") + + +@pytest.mark.parametrize("payload,expected_name", CLASS_CASES["valid"]) +def test_valid_class_extraction(payload, expected_name): + pattern = LANGUAGE_DEFINITIONS["yacc"]["rules"]["class_start"] + assert_valid_match(pattern, payload, expected_name, "yacc.class_start") + + +@pytest.mark.parametrize("payload", CLASS_CASES["invalid"]) +def test_invalid_class_extraction(payload): + pattern = LANGUAGE_DEFINITIONS["yacc"]["rules"]["class_start"] + assert_invalid_no_match(pattern, payload, "yacc.class_start") + + +@pytest.mark.parametrize("payload,expected_name", CLASS_CASES["pathological"]) +def test_pathological_class_extraction(payload, expected_name): + pattern = LANGUAGE_DEFINITIONS["yacc"]["rules"]["class_start"] + assert_pathological_match(pattern, payload, expected_name, "yacc.class_start") diff --git a/tests/extraction/languages/test_yacc_strict.py b/tests/extraction/languages/test_yacc_strict.py index 2f11f6957..fad230a55 100644 --- a/tests/extraction/languages/test_yacc_strict.py +++ b/tests/extraction/languages/test_yacc_strict.py @@ -249,8 +249,12 @@ def test_yacc_redos_immunity(): assert_redos_immune(YACC_RULES["dead_code"], "//" + " " * 100000, timeout_sec=2.0) assert_redos_immune(YACC_RULES["structural_boundaries"], "%token " * 20000, timeout_sec=2.0) assert_redos_immune(YACC_RULES["api"], "%define " * 20000, timeout_sec=2.0) + # #2644: the `[ \t]+` before the optional named tag is the only quantifier + # in class_start -- fired against a directive whose tag never arrives. + assert_redos_immune(YACC_RULES["class_start"], "%union" + " \t" * 50000, timeout_sec=2.0) # Realistic-but-large inputs must still match after any bounding. + assert YACC_RULES["class_start"].search("%union {") assert YACC_RULES["ownership"].search("// Author: Jane Doe") assert YACC_RULES["import"].search('#include "parser.h"') assert YACC_RULES["spec_exposure"].search("[SPEC-123] audit trail") diff --git a/tests/golden_master_audit.json b/tests/golden_master_audit.json index 6aa59c6c0..b69cd7ea2 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-09-05T00:45:21.199140+00:00", - "Total Scan Duration": "55.55 seconds" + "Analysis ISO Timestamp": "2026-09-05T01:45:56.042959+00:00", + "Total Scan Duration": "50.35 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", @@ -766527,7 +766527,7 @@ "Sequential Logic Declarations": 39, "Function Parameters": 43, "Function/Method Declarations": 20, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 1, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -766762,7 +766762,7 @@ "Sequential Logic Declarations": 7, "Function Parameters": 71, "Function/Method Declarations": 7, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 0, "Type/Safety Bypasses": 3, "High-Risk Execution Commands": 0, diff --git a/tests/golden_master_zero_dep_audit.json b/tests/golden_master_zero_dep_audit.json index 0c66d170a..99fe59754 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-09-05T00:46:24.417287+00:00", - "Total Scan Duration": "52.22 seconds" + "Analysis ISO Timestamp": "2026-09-05T01:46:51.701925+00:00", + "Total Scan Duration": "45.04 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", @@ -766527,7 +766527,7 @@ "Sequential Logic Declarations": 39, "Function Parameters": 43, "Function/Method Declarations": 20, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 1, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -766762,7 +766762,7 @@ "Sequential Logic Declarations": 7, "Function Parameters": 71, "Function/Method Declarations": 7, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 0, "Type/Safety Bypasses": 3, "High-Risk Execution Commands": 0, From 3938d24bf418b31f08b172401b0edcd4b57fa50c Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Fri, 4 Sep 2026 22:33:19 -0400 Subject: [PATCH 2/2] test: re-bless golden master after merging main (#2644) Regenerated on top of #2736's fixtures rather than text-merging the conflict. The residual diff against main is exactly this branch's own two lines -- `Class/Entity Declarations` 0 -> 1 on yacc/freebsd/config.y and jailparse.y -- confirming the two changes are orthogonal: measured on the merged tree BEFORE regenerating, the only drift against #2736's fixtures was those same two lines. Both modes PASS after the update. The header churn (absolute corpus path, timestamp, scan duration, remote URL suffix) is machine-specific and sanitized away by tests/golden_diff.py's load_and_sanitize. Co-Authored-By: Claude Opus 5 (1M context) --- tests/golden_master_audit.json | 12 ++++++------ tests/golden_master_zero_dep_audit.json | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/golden_master_audit.json b/tests/golden_master_audit.json index f03faca7f..a43e9e0ae 100644 --- a/tests/golden_master_audit.json +++ b/tests/golden_master_audit.json @@ -11,14 +11,14 @@ "pyyaml": false }, "Target Root Name": "data", - "Absolute Project Path": "/srv/storage_16tb/projects/gitgalaxy/language-crucible/data", - "Analysis ISO Timestamp": "2026-09-05T01:34:03.955101+00:00", - "Total Scan Duration": "20.28 seconds" + "Absolute Project Path": "/home/joe/nyx_projects/language-crucible/data", + "Analysis ISO Timestamp": "2026-09-05T02:29:59.884225+00:00", + "Total Scan Duration": "50.71 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", "Commit Hash (SHA-1)": "77bc85ecb8bb2fa8331b83f2bd348ec735df66e3", - "Remote Origin URL": "https://github.com/squid-protocol/language-crucible.git", + "Remote Origin URL": "https://github.com/squid-protocol/language-crucible", "Last Code Integration Date": "2026-08-30T08:52:00-04:00" } }, @@ -766527,7 +766527,7 @@ "Sequential Logic Declarations": 39, "Function Parameters": 43, "Function/Method Declarations": 20, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 1, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -766762,7 +766762,7 @@ "Sequential Logic Declarations": 7, "Function Parameters": 71, "Function/Method Declarations": 7, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 0, "Type/Safety Bypasses": 3, "High-Risk Execution Commands": 0, diff --git a/tests/golden_master_zero_dep_audit.json b/tests/golden_master_zero_dep_audit.json index 637ea5945..b3ef95521 100644 --- a/tests/golden_master_zero_dep_audit.json +++ b/tests/golden_master_zero_dep_audit.json @@ -11,14 +11,14 @@ "pyyaml": false }, "Target Root Name": "data", - "Absolute Project Path": "/srv/storage_16tb/projects/gitgalaxy/language-crucible/data", - "Analysis ISO Timestamp": "2026-09-05T01:34:28.701421+00:00", - "Total Scan Duration": "18.8 seconds" + "Absolute Project Path": "/home/joe/nyx_projects/language-crucible/data", + "Analysis ISO Timestamp": "2026-09-05T02:30:54.498732+00:00", + "Total Scan Duration": "44.43 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", "Commit Hash (SHA-1)": "77bc85ecb8bb2fa8331b83f2bd348ec735df66e3", - "Remote Origin URL": "https://github.com/squid-protocol/language-crucible.git", + "Remote Origin URL": "https://github.com/squid-protocol/language-crucible", "Last Code Integration Date": "2026-08-30T08:52:00-04:00" } }, @@ -766527,7 +766527,7 @@ "Sequential Logic Declarations": 39, "Function Parameters": 43, "Function/Method Declarations": 20, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 1, "Type/Safety Bypasses": 0, "High-Risk Execution Commands": 0, @@ -766762,7 +766762,7 @@ "Sequential Logic Declarations": 7, "Function Parameters": 71, "Function/Method Declarations": 7, - "Class/Entity Declarations": 0, + "Class/Entity Declarations": 1, "Defensive Programming Constructs": 0, "Type/Safety Bypasses": 3, "High-Risk Execution Commands": 0,