From d0aa38344d9c621dcc78be2f28be9d407d2d0672 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Wed, 26 Aug 2026 13:09:04 -0400 Subject: [PATCH 1/2] fix(typescript): allow catch/return/throw as legitimate method names func_start's reserved-keyword shield unconditionally excluded catch, return, and throw to stop `} catch (e) {` control-flow blocks from being misidentified as method definitions -- but that also permanently hid a real method/property legitimately named one of those words (a Promise-like thenable's catch(), an AsyncIterator protocol's return()). Moved to a conditional exclusion: only excluded when immediately followed by whitespace then `(`/`<`, the shape idiomatic control-flow and statement syntax always has (`catch (e)`, `return (...)`, `return: () => {...}`). Verified via the full 23-file typescript corpus diff against tree-sitter: the targeted catch case is fixed, zero new regressions introduced anywhere else in the corpus (131 -> 130 missing). A second `return`-named occurrence in the same file remains a separate, pre-existing same-name dedup gap in detector.py, unrelated to this regex change (unaffected either way). Fixes #2276. Co-Authored-By: Claude Sonnet 5 --- gitgalaxy/standards/language_standards.py | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/gitgalaxy/standards/language_standards.py b/gitgalaxy/standards/language_standards.py index 34ee40d60..1cd2af4ee 100644 --- a/gitgalaxy/standards/language_standards.py +++ b/gitgalaxy/standards/language_standards.py @@ -1286,7 +1286,23 @@ class PrismConfigSchema(TypedDict): # isn't immediately adjacent to the name, so `\??` matches # zero-width here and the mandatory `\(` lookahead then fails # against the literal `?` still sitting in the way). - r"(?!(?:class|interface|enum|if|for|while|switch|catch|return|throw|new|typeof|jQuery|function|yield|await|void)\b|type\b(?![ \t\n]*\()|\$)(\[[^\]]+\]|[#]?[a-zA-Z_$][\w$]*)(?=\??[ \t\n]{0,50}(?:<(?:[^<>]|<[^<>]*>)*>)?[ \t\n]{0,50}\()" + # BUG FIX (issue #2276): `catch`/`return`/`throw` used to be + # unconditionally excluded here to stop `} catch (e) {` + # control-flow blocks (and ordinary `return`/`throw` + # statements) from being misidentified as method + # definitions -- but that also permanently hid a REAL method + # or property legitimately named `catch`/`return`/`throw` + # (a Promise-like thenable's `catch()`, an AsyncIterator + # protocol's `return()`). Moved to a CONDITIONAL exclusion: + # only excluded when immediately followed by whitespace then + # `(`/`<` -- idiomatic control-flow/statement syntax always + # has that shape (`catch (e)`, `return (...)`, + # `catch(...)`, `return: () => {...}`). Confirmed via direct + # testing that `} catch (e) {` still correctly does NOT + # match, while `catch(...)` and + # `return: () => {...}` now do. + r"(?!(?:class|interface|enum|if|for|while|switch|new|typeof|jQuery|function|yield|await|void)\b|type\b(?![ \t\n]*\()|\$|(?:catch|return|throw)\b[ \t\n]+(?:\(|<))(\[[^\]]+\]|[#]?[a-zA-Z_$][\w$]*)(?=\??[ \t\n]{0,50}(?:<(?:[^<>]|<[^<>]*>)*>)?[ \t\n]{0,50}\()" r"|" # BUG FIX (R3): The arrow-value (Branch 5 / standalone value) branch # is known to fail on mid-statement function values (e.g. `const a = b || () => {}`) @@ -1336,7 +1352,11 @@ class PrismConfigSchema(TypedDict): # public/private/etc. modifier to route them through Branch A # instead. Same zero-whitespace-before-`?` placement, same # ternary-collision reasoning. - r"^[ \t]*(?!(?:class|interface|enum|if|for|while|switch|catch|return|throw|new|typeof|jQuery|function|yield|await|void)\b|type\b(?![ \t\n]*\()|\$)(\[[^\]]+\]|[#]?[a-zA-Z_$][\w$]*)(?=\??[ \t\n]{0,50}(?:<(?:[^<>]|<[^<>]*>)*>)?[ \t\n]{0,50}\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)[ \t\n]{0,50}(?:(?::[^{;]{0,200})?[ \t\n]{0,50}(?:=>[ \t\n]{0,50})?\{|:[^{;]{0,200}[ \t\n]{0,50};))" + # BUG FIX (issue #2276): same conditional-exclusion fix as + # Branch A above, mirrored here since this branch carries + # its own copy of the same reserved-keyword shield -- see + # that branch's comment for the full rationale. + r"^[ \t]*(?!(?:class|interface|enum|if|for|while|switch|new|typeof|jQuery|function|yield|await|void)\b|type\b(?![ \t\n]*\()|\$|(?:catch|return|throw)\b[ \t\n]+(?:\(|<))(\[[^\]]+\]|[#]?[a-zA-Z_$][\w$]*)(?=\??[ \t\n]{0,50}(?:<(?:[^<>]|<[^<>]*>)*>)?[ \t\n]{0,50}\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\)[ \t\n]{0,50}(?:(?::[^{;]{0,200})?[ \t\n]{0,50}(?:=>[ \t\n]{0,50})?\{|:[^{;]{0,200}[ \t\n]{0,50};))" r")", re.M, ), From 7f0560ae9de743be907fae0be90bf0c1227ea039 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Wed, 26 Aug 2026 15:24:53 -0400 Subject: [PATCH 2/2] chore: bless golden masters + tree-sitter baseline for #2276's fix Structural drift is fully attributable to the fix: async.ts now correctly extracts `catch` as a real method (253 -> 254 function/ method declarations), with the expected downstream ripple into topological coordinates and structural-magnitude aggregates for the same file/directory group -- CLAUDE.md's documented, expected class of drift when a function count changes. The tree-sitter-accuracy-audit baseline needed a reviewed (not blind) regeneration: `catch` is now correctly reported as a real function (verified directly against source, see #2276), but this tool's own tree-sitter walker filters reserved-control-flow-keyword-shaped names defensively (the same class of tooling blind spot already documented in this tool's own module docstring for cpp/c's macro-shield precedent) -- so it counted GitGalaxy's new, correct find as "extra_functions: 12 -> 13" against a ground truth that's itself wrong here. Regenerated per that same documented precedent ("reviewed rather than treated as a real regression"), not force-overridden blind. python tests/tools/audit_check.py --ci: all clear. Co-Authored-By: Claude Sonnet 5 --- gitgalaxy/standards/language_standards.py | 2 +- tests/golden_master_audit.json | 28 +++++++++++++------ tests/golden_master_zero_dep_audit.json | 28 +++++++++++++------ ...e_sitter_accuracy_baseline_typescript.json | 2 +- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/gitgalaxy/standards/language_standards.py b/gitgalaxy/standards/language_standards.py index 1cd2af4ee..bf28b5de9 100644 --- a/gitgalaxy/standards/language_standards.py +++ b/gitgalaxy/standards/language_standards.py @@ -63,7 +63,7 @@ | Solidity | 100.0% | 94.3% | 100.0% | 100.0% | | Swift | 100.0% | 99.2% | 100.0% | 100.0% | | Tcl | 98.6% | 99.3% | N/A | N/A | -| Typescript | 99.5% | 99.6% | 100.0% | 100.0% | +| Typescript | 99.5% | 99.5% | 100.0% | 100.0% | | Zig | 100.0% | 100.0% | 100.0% | 100.0% | """ diff --git a/tests/golden_master_audit.json b/tests/golden_master_audit.json index b997745b5..614acc337 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-26T15:27:06.920235+00:00", - "Total Scan Duration": "33.55 seconds" + "Analysis ISO Timestamp": "2026-08-26T19:15:10.569129+00:00", + "Total Scan Duration": "34.9 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", @@ -360,7 +360,7 @@ "typescript": { "files": 24, "loc": 36020, - "impact": 4277.700000000002 + "impact": 4278.140000000001 }, "kotlin": { "files": 5, @@ -1781,7 +1781,7 @@ }, "typescript/vscode": { "file_count": 11, - "total_mass": 1429.32, + "total_mass": 1429.76, "avg_exposures": { "cognitive_load": 35.35, "safety_score": 59.85, @@ -358546,7 +358546,7 @@ } }, "typescript/vscode": { - "Directory Group Magnitude": 1429.32, + "Directory Group Magnitude": 1429.76, "File Count": 11, "Ecosystem Fingerprint (Archetypes)": { "Unclassified": "81.8%", @@ -359062,9 +359062,9 @@ "Identity Proof": "Single Indicator (Ext: .ts)" }, "2. Topological Coordinates": { - "X": 3477.88, + "X": 3477.86, "Y": 154.07, - "Z": 3300.26 + "Z": 3300.27 }, "3. Architectural Profile": { "Repository Archetype": "Unclassified", @@ -359076,7 +359076,7 @@ "Total LOC": 2646, "Coding LOC": 1803, "Documentation LOC": 419, - "Structural Magnitude": 319.07, + "Structural Magnitude": 319.51, "Control Flow Ratio": "33.0%", "Popularity Rank": 0, "Raw Churn Frequency": 0.0, @@ -359720,6 +359720,16 @@ "Start Line": 2592, "End Line": 2600 }, + { + "Function Name": "catch", + "Structural Impact": 4.4, + "Lines of Code (LOC)": 3, + "Control Flow Branches": 2, + "Input Parameters": 1, + "Control Flow Ratio": "50.0%", + "Start Line": 74, + "End Line": 76 + }, { "Function Name": "loop", "Structural Impact": 4.2, @@ -361626,7 +361636,7 @@ "Control Flow Branches": 288, "Sequential Logic Declarations": 586, "Function Parameters": 412, - "Function/Method Declarations": 253, + "Function/Method Declarations": 254, "Class/Entity Declarations": 47, "Defensive Programming Constructs": 258, "Type/Safety Bypasses": 36, diff --git a/tests/golden_master_zero_dep_audit.json b/tests/golden_master_zero_dep_audit.json index 7d4bb7e93..007d523d0 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-26T15:27:45.955779+00:00", - "Total Scan Duration": "31.79 seconds" + "Analysis ISO Timestamp": "2026-08-26T19:15:50.161013+00:00", + "Total Scan Duration": "32.4 seconds" }, "Source Control Footprint (Immutable Anchor)": { "Active Branch": "HEAD", @@ -360,7 +360,7 @@ "typescript": { "files": 24, "loc": 36020, - "impact": 4277.700000000002 + "impact": 4278.140000000001 }, "kotlin": { "files": 5, @@ -1781,7 +1781,7 @@ }, "typescript/vscode": { "file_count": 11, - "total_mass": 1429.32, + "total_mass": 1429.76, "avg_exposures": { "cognitive_load": 35.35, "safety_score": 59.85, @@ -358546,7 +358546,7 @@ } }, "typescript/vscode": { - "Directory Group Magnitude": 1429.32, + "Directory Group Magnitude": 1429.76, "File Count": 11, "Ecosystem Fingerprint (Archetypes)": { "Unclassified": "81.8%", @@ -359062,9 +359062,9 @@ "Identity Proof": "Single Indicator (Ext: .ts)" }, "2. Topological Coordinates": { - "X": 3477.88, + "X": 3477.86, "Y": 154.07, - "Z": 3300.26 + "Z": 3300.27 }, "3. Architectural Profile": { "Repository Archetype": "Unclassified", @@ -359076,7 +359076,7 @@ "Total LOC": 2646, "Coding LOC": 1803, "Documentation LOC": 419, - "Structural Magnitude": 319.07, + "Structural Magnitude": 319.51, "Control Flow Ratio": "33.0%", "Popularity Rank": 0, "Raw Churn Frequency": 0.0, @@ -359720,6 +359720,16 @@ "Start Line": 2592, "End Line": 2600 }, + { + "Function Name": "catch", + "Structural Impact": 4.4, + "Lines of Code (LOC)": 3, + "Control Flow Branches": 2, + "Input Parameters": 1, + "Control Flow Ratio": "50.0%", + "Start Line": 74, + "End Line": 76 + }, { "Function Name": "loop", "Structural Impact": 4.2, @@ -361626,7 +361636,7 @@ "Control Flow Branches": 288, "Sequential Logic Declarations": 586, "Function Parameters": 412, - "Function/Method Declarations": 253, + "Function/Method Declarations": 254, "Class/Entity Declarations": 47, "Defensive Programming Constructs": 258, "Type/Safety Bypasses": 36, diff --git a/tests/tree_sitter_accuracy_baseline_typescript.json b/tests/tree_sitter_accuracy_baseline_typescript.json index de1aa4252..e62eb2c51 100644 --- a/tests/tree_sitter_accuracy_baseline_typescript.json +++ b/tests/tree_sitter_accuracy_baseline_typescript.json @@ -3,7 +3,7 @@ "args_exact_match": 2741, "corpus_path": "language-crucible/data/typescript", "extra_classes": 0, - "extra_functions": 12, + "extra_functions": 13, "files_scanned": 23, "found_classes": 842, "found_functions": 2773,