Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: giancarloerra/SocratiCode
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: giancarloerra/SocratiCode
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: fix/grammar-prevalidate
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 1 commit
  • 5 files changed
  • 2 contributors

Commits on May 4, 2026

  1. fix(graph): pre-validate ast-grep grammar libraryPath to survive miss…

    …ing prebuilds
    
    Resolves #43. On Linux/Node combinations where one ast-grep grammar
    package's prebuilt parser binary is missing for the host architecture
    (reporter: Ubuntu 24.04 + WSL2 + Node 24, missing the cpp prebuild),
    the existing loader silently failed to register every dynamic grammar,
    not just the broken one.
    
    Mechanism: registerDynamicLanguage iterates the modules it receives
    and accesses the lazy libraryPath getter on each. If that getter
    throws (because the prebuild lookup fails), the entire batch call
    aborts atomically — none of the 13 dynamic grammars get registered.
    The empty inner `catch {}` in ensureDynamicLanguages discarded the
    underlying reason, and the failure surfaced only at WARN as a generic
    "Failed to register dynamic ast-grep languages", with no indication
    of which grammar was the culprit.
    
    Empirically verified against @ast-grep/napi@0.40.5 in a clean Node
    environment:
    
    - Sequential register({A}); register({B}) calls REPLACE rather than
      accumulate; only the last call's grammar survives. So the obvious
      alternative of "register one at a time" is actively broken — it
      would silently leave only the last grammar in langPackages
      registered (php, since it's last in our list). On a polyglot
      codebase that's a regression.
    
    - Batch register({A, B, C}) with one entry whose libraryPath getter
      throws aborts atomically — none of A/B/C end up registered.
    
    The fix is to pre-validate each grammar's libraryPath getter inside
    our own per-grammar try/catch, exclude any that throw, then make ONE
    batch registerDynamicLanguage call with only the survivors:
    
    - src/services/code-graph.ts: ensureDynamicLanguages now touches
      mod.libraryPath inside the inner try/catch so a missing-prebuild
      failure is contained to that one grammar. Adds module-level
      loadedDynamicLanguages and failedDynamicLanguages state plus a
      public getDynamicLanguageStatus() introspection API. The empty
      `catch {}` becomes `catch (err) { ... }` capturing the actual
      reason. Per-grammar failures and the (now-rare) catch-all log at
      warn level with the underlying message.
    
    - src/tools/graph-tools.ts: codebase_graph_status now appends an
      "AST grammars: Loaded / Failed" block listing both sets, with the
      failure reason for each unloaded grammar. Users see the loader
      state without needing to enable debug logging.
    
    - src/services/graph-symbols.ts: extractSymbolsAndCalls bumps its
      failure log from DEBUG to WARN with one-shot dedupe per language —
      one warn per language for the lifetime of the process, not one
      warn per file (potentially hundreds).
    
    - src/services/graph-imports.ts: extractImports gets the same
      one-shot dedupe per language treatment for consistency.
    
    - tests/unit/dynamic-language-loader.test.ts: nine new tests covering
      the sync contract, idempotence, loaded/failed sort order, disjoint
      sets, and a sanity check that at least one expected grammar
      registers in the test environment.
    
    The loader stays sync. createRequire stays. No call-site signature
    changes, no test fixture rewrites. Existing 721 tests pass; with the
    new file, 730 tests pass. typecheck and biome clean. CodeRabbit
    review of the diff returned no findings.
    
    Co-authored-by: X-Adam <X-Adam@users.noreply.github.com>
    Giancarlo Erra and x-adam committed May 4, 2026
    Configuration menu
    Copy the full SHA
    e075d6f View commit details
    Browse the repository at this point in the history
Loading