Skip to content

feat: add AL (.al) language support - #2996

Open
PlaySkyHD wants to merge 17 commits into
Graphify-Labs:v8from
PlaySkyHD:feat/al-language
Open

feat: add AL (.al) language support#2996
PlaySkyHD wants to merge 17 commits into
Graphify-Labs:v8from
PlaySkyHD:feat/al-language

Conversation

@PlaySkyHD

@PlaySkyHD PlaySkyHD commented Aug 24, 2026

Copy link
Copy Markdown

feat: add AL (.al) language support

What

Adds extraction support for Microsoft Dynamics 365 Business Central AL (.al) source files, including production applications and dedicated AL test applications.

On Python 3.12+, the optional tree-sitter-al parser provides full structural and semantic extraction. On other supported Python versions, or when the parser is absent, graphify falls back to a built-in structural scanner for files, application objects, procedures, and triggers.

Why

Business Central extensions are currently invisible to graphify because .al is not treated as source code. This PR makes AL a first-class language while preserving graphify's Python 3.10+ compatibility and offline extraction behavior.

What it extracts

  • Business Central application objects, extensions, and permission sets
  • Procedures, overloads, triggers, parameters, fields, and enum values
  • Distinct field/action triggers even when names such as OnValidate repeat
  • Namespaces, using declarations, attributes, and visibility
  • Extension and interface implementation relationships
  • Typed cross-file calls and object references
  • Event subscriber and enum implementation relationships
  • In-corpus app.json application dependencies
  • TestPage targets and HandlerFunctions bindings in AL test apps

Test application semantics

  • TestPage "X" declarations resolve to visible production page objects through references edges with test_target context.
  • [HandlerFunctions('X')] entries resolve to unique procedures in the same test codeunit through references edges with test_handler context.
  • TestPage runtime APIs such as OpenView, SetValue, Invoke, and AssertEquals are not fabricated as calls to undeclared production procedures.
  • Test source remains ordinary code in the graph, preserving [Test], handler, and event attributes.

Details

  • Preserves AL declaration spelling while resolving identifiers case-insensitively with casefold().
  • Uses application, namespace, object kind, and containment context to avoid ambiguous cross-file matches.
  • Resolves overloaded procedures conservatively by signature identity and call arity; same-arity ambiguity remains unresolved.
  • Reads optional app.json metadata for application and dependency boundaries without requiring a valid manifest.
  • Distinguishes missing parser dependencies from parser load failures in diagnostics.
  • Keeps fallback extraction deliberately structural and does not fabricate semantic edges.

Validation corpora

AcmeComments

Tested against the 11-file Business Central extension:

  • 60 nodes
  • 89 edges
  • No failed sources or syntax errors

InterestMgt and InterestMgtTest

Tested against both applications together:

  • 31 detected code/manifest files
  • 211 nodes and 250 edges
  • 25/25 AL application objects represented, including the permission set
  • 48/48 production procedures and 34/34 triggers represented
  • Both OpenInterestCalculator overloads preserved; the one-argument call resolves correctly
  • 13 resolved TestPage target edges
  • 1 resolved test handler binding
  • 1 resolved test-app-to-production-app dependency
  • No fabricated TestPage runtime calls

Changes

  • graphify/extractors/al.py - dedicated Tree-sitter and fallback AL extractor, permission sets, scoped members, overload identities, and test facts
  • graphify/al_resolution.py - ambiguity-safe cross-file, test target, handler, overload, and application dependency resolution
  • graphify/detect.py / graphify/extract.py - .al detection, dispatch, diagnostics, and resolver registration
  • pyproject.toml / uv.lock - optional [al] extra using tree-sitter-al on Python 3.12+
  • tests/test_al.py / AL fixtures - focused extraction, fallback, diagnostics, resolution, test-app, and overload coverage
  • README.md / CHANGELOG.md - language support and installation documentation

Tests

  • uv run pytest tests/test_al.py -q - 17 passed
  • uv run pytest tests/test_detect.py -q - 243 passed, 11 skipped
  • Affected extraction/language regression modules - 629 passed, 21 skipped
  • Windows long-path regression rerun with a short temp root - 1 passed
  • uv run ruff check graphify/extractors/al.py graphify/al_resolution.py tests/test_al.py

Notes / possible follow-ups

  • Full Tree-sitter extraction requires Python 3.12+ because that is the minimum supported version of the parser package; structural fallback remains available on graphify's older supported Python versions.
  • External Microsoft test-library objects remain unresolved unless their source applications are included in the corpus.
  • .app package binary parsing remains intentionally out of scope.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) as a supported language: introduces graphify/al_resolution.py for application-level, case-insensitive cross-file symbol resolution (objects, procedures, triggers, fields, enum values, extensions, interfaces, typed calls, event subscriptions) plus AL extractor/detector wiring and a new [al] extra with a Tree-sitter path on Python 3.12+ and a structural fallback elsewhere. Documents the new grammar and extra in the README (now 38 grammars) and CHANGELOG, and adds a test covering AL corpus extraction continuing past a failing file.

Worth a look

  • Source-file comparison only handles one absolute/relative directiongraphify/al_resolution.py:19 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Uppercase AL files are not classified as codegraphify/detect.py:45 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • AL fallback omits al_facts from extract_al return schemagraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • AL fallback returns callable parameters as string instead of metadata listgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fallback callable metadata uses string parameters vs list in tree-sitter pathgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2267 functions depend on the 596 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 481 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 40 more — each is listed as a finding

Verification — 2267 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2072 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 3 grounded finding(s) anchored inline below; 45 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/al_resolution.py Outdated
Comment thread graphify/extractors/al.py Outdated
Comment thread graphify/extractors/al.py Outdated

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) extraction as the 38th tree-sitter grammar, with a new graphify/al_resolution.py module that does application-level, case-insensitive cross-file symbol resolution (objects, permission sets, procedures/overloads, triggers, fields, enums, extensions, interfaces, typed calls, event subscriptions, app dependencies, and TestPage/test-handler bindings). Wires up the optional [al] extra for full Tree-sitter extraction on Python 3.12+ and a structural object/procedure/trigger fallback elsewhere, plus tests covering the resolver, invalid/missing manifests, and the optional-extra parser path. Updates README (supported types table, prerequisites) and CHANGELOG accordingly.

Worth a look

  • _same_source suffix match can produce false positives across distinct filesgraphify/al_resolution.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • AL fact ids collide across filesgraphify/al_resolution.py:106 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fallback AL callable IDs collide for repeated triggersgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • masked.find with limited end may miss object opening bracegraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fallback AL object regex omits permissionset objectsgraphify/extractors/al.py:10 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2270 functions depend on the 599 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 483 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 40 more — each is listed as a finding

Verification — 2270 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2075 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 3 grounded finding(s) anchored inline below; 45 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/al_resolution.py Outdated
Comment thread graphify/extractors/al.py Outdated
Comment thread graphify/extractors/al.py Outdated

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) extraction: a new graphify/al_resolution.py performs application-level cross-file symbol resolution (objects, permission sets, procedures/overloads, triggers, fields, enums, extensions, interfaces, typed calls, event subscriptions, app dependencies, and TestPage/handler bindings) with case-insensitive matching and app.json manifest awareness, backed by new detectors and extractors (graphify_detect_*, graphify_extractors_al_*). Registers .al as the 38th grammar with an optional [al] extra and a structural fallback for non-3.12 Python, updating README supported-types and the CHANGELOG.

Worth a look

  • Fallback AL extractor collapses duplicate trigger membersgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2326 functions depend on the 655 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 483 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2326 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2131 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 5 advisory finding(s) below merit a look before merge.


Graphify review — findings

Adds Business Central AL (.al) extraction as the 38th grammar, spanning a new graphify/al_resolution.py application-level resolver (_ALSymbolResolver with manifest/dependency, object, member, and event-subscriber mapping) and AL extractor helpers (Tree-sitter parsing plus a structural fallback for non-3.12 Pythons). Registers the [al] optional extra and documents it in the README supported-types table and CHANGELOG. Includes AL tree-sitter tests asserting callable/field metadata preservation.

Worth a look

  • target selected as candidates[0] after set() dedup on unhashable dictsgraphify/al_resolution.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • opening brace search fails when '{' is outside match spangraphify/extractors/al.py · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Whitespace not stripped from split handler namesgraphify/al_resolution.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • _same_source suffix match can produce false positives across filesgraphify/al_resolution.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Aggregate extractors package now requires optional AL extractorgraphify/extractors/__init__.py:13 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2327 functions depend on the 656 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 483 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2327 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2132 function(s) in the blast radius were not formally verified this run

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.


Graphify review — findings

Adds Business Central AL (.al) extraction with a new al_resolution.py application-level resolver and extractors/al.py, wiring the extractor into extractors/__init__.py and the language-family/detection paths. Models objects, permission sets, procedures/overloads, triggers, fields, enums, extensions, interfaces, typed calls, event subscriptions, and test-app relationships with case-insensitive cross-file resolution and app.json-driven dependency edges; full Tree-sitter parsing requires the optional [al] extra on Python 3.12+ with a structural fallback otherwise. Documents the new grammar in the README and CHANGELOG and adds AL parser fallback/read-error tests.

Worth a look

  • ImportError from tree_sitter (not tree_sitter_al) misreported as fallback path or wrong errorgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Comment masker treats // inside quoted AL identifiers as a real commentgraphify/extractors/al.py:57 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Only the first implemented interface is recordedgraphify/extractors/al.py:268 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2330 functions depend on the 659 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 483 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2330 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2135 function(s) in the blast radius were not formally verified this run

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 4 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) extraction as the 38th tree-sitter grammar, introducing graphify/al_resolution.py for application-level cross-file symbol resolution (objects, procedures, fields, enums, extensions, events, app dependencies, and test-app bindings) plus new AL extractors. Documents the optional [al] extra in the README support table and language list, with a structural fallback for non-3.12 Python. Records the feature in the 0.9.48 changelog.

Worth a look

  • _matching_brace ignores braces inside masked/unmasked strings and commentsgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fallback skipped when tree_sitter core import failsgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Regex fallback omits permissionset objectsgraphify/extractors/al.py:10 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • AL optional-extra guidance is codified with misspelled package nametests/test_al.py:50 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2332 functions depend on the 661 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 484 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2332 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2137 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) extraction as the 38th tree-sitter grammar, introducing graphify/al_resolution.py with an _ALSymbolResolver that maps object/member facts and resolves cross-file references (calls, events, extensions, app dependencies, TestPage/handler bindings) case-insensitively. Registers the optional [al] extra with a structural object/procedure/trigger fallback for Python versions without the Tree-sitter grammar, including UTF-8 BOM handling. Updates README extension tables and adds the 0.9.48 changelog entry.

Worth a look

  • Malformed non-object app.json crashes AL resolutiongraphify/al_resolution.py:52 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Fallback AL object regex omits permissionset objectsgraphify/extractors/al.py:11 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • _matching_brace ignores masking and counts braces inside strings/commentsgraphify/extractors/al.py:128 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2333 functions depend on the 662 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 484 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2333 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2138 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) extraction as a new tree-sitter grammar with an optional [al] extra, wiring it into graphify.detect (filetype detection, office/import paths) and the extractor registry, with a structural object/procedure/trigger fallback on Python versions lacking the Tree-sitter parser. Introduces graphify/al_resolution.py (_ALSymbolResolver) for application-level, case-insensitive cross-file symbol resolution — objects, members, extensions, typed calls, event subscriptions, TestPage/handler bindings, and app.json dependency edges. Documents the new grammar and extra in README/CHANGELOG and adds AL extraction tests.

Worth a look

  • extract_al returns an error instead of falling back when the installed AL parser failsgraphify/extractors/al.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Valid AL permission set extensions are not recognizedgraphify/extractors/al.py:10 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2339 functions depend on the 668 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 485 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2339 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2144 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL (.al) as a supported language, with full Tree-sitter extraction via the optional [al] extra and a structural fallback extractor for other Python versions. Introduces graphify/al_resolution.py for application-level, case-insensitive cross-file symbol resolution (objects, members/overloads, extensions, app-manifest dependencies) and adds AL extractor/resolver tests. Updates README (grammar count 37→38, extras table, extension list) and the CHANGELOG.

Worth a look

  • Fallback flag overwritten across files of same extensiongraphify/extract.py:5704 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Drops all but the first interface in implements clausesgraphify/extractors/al.py:323 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2342 functions depend on the 671 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 485 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2342 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2147 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 2 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Microsoft Dynamics 365 Business Central AL (.al) extraction with a new al_resolution.py application-level resolver and al extractor covering objects, permission sets, extensions, procedures/overloads, triggers, fields, enums, interfaces, typed calls, event subscriptions, app dependencies, and TestPage/handler bindings. Registers the optional [al] extra (full Tree-sitter on Python 3.12+, structural fallback otherwise) and wires app.json manifest resolution with case-insensitive cross-file matching. Updates the README grammar count to 38, adds the extension/extra rows, and adds a 0.9.48 CHANGELOG entry.

Worth a look

  • Comment masking starts inside quoted AL identifiersgraphify/extractors/al.py:65 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Optional tree_sitter dependency is required by fallback testtests/test_al.py:127 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2564 functions depend on the 1033 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 487 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2564 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2369 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds first-class Business Central AL (.al) extraction: a new graphify/al_resolution.py with _ALSymbolResolver for application-level, case-insensitive cross-file symbol resolution (objects, members, app.json manifest dependencies), plus AL extractor internals (altreecontext, al_extract_member, mask_al_code) and the [al] optional extra with a Tree-sitter path on Python 3.12+ and a structural fallback elsewhere. Registers .al in the supported-language surface (README extension table now 38 grammars, environment-variable/extras docs) and adds the 0.9.48 changelog entry. Includes extensive AL parser and extraction tests covering fallback specs, optional-extra reporting, case-insensitive detection, and calls/handler edges.

No blocking issues surfaced. 21 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2567 functions depend on the 1036 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 487 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2567 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2372 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds a Business Central AL (.al) extractor with full Tree-sitter extraction under the optional [al] extra on Python 3.12+ and a structural object/procedure/trigger fallback otherwise, plus the new graphify/al_resolution.py for case-insensitive application-level symbol resolution (objects, members, extensions, ControlAddIns, event bindings, and app-manifest dependencies). Registers .al as the 38th grammar and documents the extra in the README and CHANGELOG. Includes extensive tests covering fallback paths, namespace/manifest resolution, and test-dispatch handling.

No blocking issues surfaced. 22 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2572 functions depend on the 1041 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 488 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 39 more — each is listed as a finding

Verification — 2572 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit 282976b (diverged from this PR's base — delta is approximate).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2377 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 2 grounded finding(s) anchored inline below; 45 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/extractors/al.py Outdated
Comment thread graphify/extractors/al.py Outdated

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Microsoft Dynamics 365 Business Central AL (.al) extraction as the 38th tree-sitter grammar behind an optional [al] extra, modeling objects, permission sets/extensions, ControlAddIns and UserControls, procedures/overloads, scoped triggers, fields, enums, typed calls, event bindings/subscriptions, app dependencies, and test-app relationships via _ALSymbolResolver with case-insensitive cross-file resolution. Falls back to structural object/procedure/trigger extraction through ALFallbackExtractor when the Tree-sitter grammar is unavailable (non-3.12+ or extra not installed). Wires .al into detection via is_graphable_source and friends and updates the README/CHANGELOG accordingly.

Worth a look

  • Missing-parser diagnostic test expects misspelled package extratests/test_al.py:94 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2576 functions depend on the 1045 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 488 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2576 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit 282976b (diverged from this PR's base — delta is approximate).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2381 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds full Business Central AL (.al) support as the 38th tree-sitter grammar, with a new al optional extra and ALFallbackExtractor that provides structural object/procedure/trigger extraction when Tree-sitter isn't available (Python < 3.12 or extra not installed). Extracts and emits application objects, permission sets/extensions, ControlAddIns, UserControls, procedures/overloads, scoped triggers, fields, enum values, interfaces, typed calls, event bindings/subscriptions, and TestPage/handler relationships, then resolves them across files case-insensitively via _ALSymbolResolver, using app.json manifests for application identity and dependency edges. Member resolution requires a unique candidate (_unique_member_id) matched by parent, signature, and source location, so ambiguous string ids or duplicated members are left unlinked rather than guessed.

Worth a look

  • AL resolution is order-dependent across filesgraphify/al_resolution.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Dependency warning is ignored when an extractor also reports an errorgraphify/extract.py:5696 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Quoted-identifier masking corrupts identifier characters via wrong handler dispatchgraphify/extractors/al.py:60 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2576 functions depend on the 1045 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 488 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2576 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit 282976b (diverged from this PR's base — delta is approximate).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2381 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Business Central AL as a first-class language: .al files now extract application objects, permission sets/extensions, ControlAddIns and hosted UserControls, procedures/overloads, scoped triggers, fields, enums, interfaces, and their typed calls, event bindings/subscriptions, app dependencies, and test-app relationships, with case-insensitive cross-file resolution via _ALSymbolResolver. Wires up manifest-aware application context by walking app.json up the tree to attach app ids/names and emit dependency edges. Full Tree-sitter extraction requires the optional [al] extra on Python 3.12+; other versions fall back to structural object/procedure/trigger extraction.

No blocking issues surfaced. 11 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2579 functions depend on the 1048 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 490 callers, 42 callees
  • new: _rebuild_code() — 98 callers, 50 callees
  • new: detect() — 108 callers, 15 callees
  • new: save_manifest() — 39 callers, 11 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: extract_js() — 80 callers, 3 callees
  • …and 37 more — each is listed as a finding

Verification — 2579 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit 282976b (diverged from this PR's base — delta is approximate).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2384 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify extract.

The verifier did not have enough to check extract, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `cache_root` is annotated `Path | None` — outside the synthesizable primitive/collection set

· 45 more finding(s) on lines outside this diff (see the check run).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant