Skip to content

VatsaShivam/ai-bc-code-reviewer

Repository files navigation

BC Code Reviewer — Multi-Model MCP Server

Production-grade Business Central AL code review engine powered by multi-model LLM consensus and 37 static analysis rules based on Microsoft CodeCop, AppSourceCop, and PerTenantExtensionCop analyzers.

All rules and standards reference the official Microsoft documentation: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/


Table of Contents

  1. Overview
  2. Architecture
  3. Quick Start
  4. Configuration
  5. MCP Tools Reference
  6. Static Analysis Rules
  7. Review Modes
  8. Microsoft BC Development Standards
  9. Security Features
  10. Observability & Logging
  11. SARIF Output for CI/CD
  12. Module Reference
  13. Environment Variables

Overview

The BC Code Reviewer is a Model Context Protocol (MCP) server that reviews Business Central AL source code using two complementary analysis layers:

Layer Speed Token Cost Accuracy
Static rules (regex-based) <100ms Zero High for known patterns
LLM consensus (multi-model) 10-60s Per-model tokens High with voting

The server runs over stdio transport and integrates with VS Code Copilot Chat, Claude Desktop, or any MCP-compatible client.

Key Capabilities

  • 37 static rules aligned with official Microsoft AL analyzers (CodeCop AA, AppSourceCop AS, PTECop PTE)
  • 4 LLM providers — OpenAI, Azure OpenAI, Anthropic, Ollama (local)
  • 8-category LLM system prompt covering Security, Performance, Best Practices, Localizability, Upgrade, Error Handling, Events, and PTE compliance
  • Multi-model consensus — findings are only reported when multiple models agree
  • Per-severity thresholds — critical findings need fewer votes, info findings need more
  • SARIF v2.1.0 export — for CI/CD pipeline integration (GitHub Code Scanning, Azure DevOps)
  • Path traversal protection — workspace root restriction prevents file access attacks
  • API key sanitization — secrets are never leaked in error messages or logs
  • Rate limiting — sliding-window limiter prevents runaway LLM costs
  • Retry with backoff — automatic retries on 429/502/503/504 errors
  • Structured JSON logging — observability-ready log output
  • Disabled rules — suppress specific rule IDs via environment variable

Architecture

┌──────────────────────────────────────────────────────────────┐
│                    MCP Client (VS Code / Claude)             │
│                         stdio transport                      │
└───────────────────────────┬──────────────────────────────────┘
                            │
┌───────────────────────────▼──────────────────────────────────┐
│                     server.py (FastMCP)                       │
│  7 MCP tools: review_al_code, review_al_file,               │
│  review_al_folder, review_static_only,                       │
│  review_al_code_with_model, list_review_rules,               │
│  list_configured_models                                      │
│                                                              │
│  Features: input validation, path traversal protection,      │
│  SARIF output, min_severity filter, structured logging       │
└──────────┬────────────────────────────────────┬──────────────┘
           │                                    │
┌──────────▼──────────┐           ┌─────────────▼─────────────┐
│   reviewer.py       │           │   rules.py                │
│                     │           │                           │
│ CodeReviewAgent     │◄──────────┤ 37 static rule functions  │
│ - review_code()     │           │ _preprocess() strips      │
│ - review_file()     │           │   block comments          │
│ - _apply_consensus()│           │ _strip_string_literals()  │
│ - _compute_score()  │           │ run_static_checks()       │
│ - rate limiter      │           │ disabled_rules filtering  │
│ - SARIF export      │           └───────────────────────────┘
│ - _finding_fingerprint()
└──────────┬──────────┘
           │
┌──────────▼──────────────────────────────────────────────────┐
│                     models.py                                │
│                                                              │
│ MultiModelClient — shared httpx.AsyncClient                  │
│ ├── _call_openai()        (OpenAI / OpenAI-compat)          │
│ ├── _call_azure_openai()  (Azure OpenAI)                    │
│ ├── _call_anthropic()     (Claude)                          │
│ └── _call_ollama()        (Local Ollama)                    │
│                                                              │
│ REVIEW_SYSTEM_PROMPT (~160 lines, 8 categories)             │
│ Features: connection pooling, retry w/ exponential backoff,  │
│ secret sanitization                                          │
└──────────────────────────────────────────────────────────────┘
           │
┌──────────▼──────────┐
│     config.py       │
│                     │
│ ReviewerConfig      │
│ ModelConfig          │
│ from_env() loads    │
│ all settings from   │
│ .env / environment  │
└─────────────────────┘

Quick Start

1. Install the Package

# Clone the repository
git clone https://github.com/VatsaShivam/bc_code_reviewer.git
cd bc_code_reviewer

# Install in development mode
pip install -e .

Or install from PyPI (once published):

pip install bc-code-reviewer

2. Configure Environment

Create a .env file in the project root:

# At least one LLM provider is required for non-static reviews
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o

# Optional: Azure OpenAI
# AZURE_OPENAI_API_KEY=...
# AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
# AZURE_OPENAI_DEPLOYMENT=gpt-4o

# Optional: Anthropic
# ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_MODEL=claude-sonnet-4-20250514

# Optional: Ollama (local, no API key needed)
# OLLAMA_MODEL=codellama:13b
# OLLAMA_BASE_URL=http://localhost:11434

3. Run the MCP Server

bc-code-reviewer

4. VS Code Integration

The server can be configured in .vscode/mcp.json:

{
  "servers": {
    "bcCodeReviewer": {
      "type": "stdio",
      "command": "bc-code-reviewer",
      "envFile": "${workspaceFolder}/.env"
    }
  }
}

Once configured, invoke review tools directly from VS Code Copilot Chat.

5. Docker Deployment

Build and run with Docker:

# Build the image
docker build -t bc-code-reviewer .

# Run the container
docker run --env-file .env -it bc-code-reviewer

Configuration

All configuration is via environment variables (loaded from .env).

ReviewerConfig Fields

Field Type Default Env Var Description
consensus_threshold float 0.6 REVIEWER_CONSENSUS_THRESHOLD Fraction of models that must agree (warnings)
consensus_threshold_critical float 0.4 REVIEWER_CONSENSUS_THRESHOLD_CRITICAL Lower threshold for critical findings
consensus_threshold_info float 0.8 REVIEWER_CONSENSUS_THRESHOLD_INFO Higher threshold for info findings
max_file_size_kb int 500 REVIEWER_MAX_FILE_SIZE_KB Max file size for review
max_input_bytes int 512000 REVIEWER_MAX_INPUT_BYTES Hard limit on input code size
review_timeout float 120.0 REVIEWER_TIMEOUT LLM request timeout (seconds)
disabled_rules frozenset empty REVIEWER_DISABLED_RULES Comma-separated rule IDs to suppress
workspace_root str None REVIEWER_WORKSPACE_ROOT Restrict file access to this directory
rate_limit_per_minute int 30 REVIEWER_RATE_LIMIT Max reviews per minute
retry_max_attempts int 3 REVIEWER_RETRY_ATTEMPTS Max LLM retry attempts
retry_backoff_base float 1.0 REVIEWER_RETRY_BACKOFF Base seconds for exponential backoff

MCP Tools Reference

review_al_code

Review AL source code using multi-model consensus.

Parameter Type Default Description
code str required AL source code to review
filename str "untitled.al" File name for context
mode str "consensus" "static", "single", or "consensus"
min_severity str None Filter: "critical", "warning", or "info"
output_format str "json" "json" or "sarif"

review_al_file

Review an AL file from disk.

Parameter Type Default Description
file_path str required Path to .al file
mode str "consensus" Review mode
min_severity str None Severity filter
output_format str "json" Output format

review_al_folder

Review all .al files in a directory recursively.

Parameter Type Default Description
folder_path str required Path to folder
mode str "static" Review mode
max_files int 50 Safety limit (max 200)
min_severity str None Severity filter

review_static_only

Fast static-analysis-only check (zero LLM cost).

Parameter Type Default Description
code str required AL source code
min_severity str None Severity filter

review_al_code_with_model

Review using a specific LLM provider (bypass consensus).

Parameter Type Default Description
code str required AL source code
provider str required "openai", "azure_openai", "anthropic", "ollama"
filename str "untitled.al" File name for context
min_severity str None Severity filter

list_review_rules

List all 37 static rules with IDs, descriptions, and disabled status. Auto-generated from the rule engine.

list_configured_models

List all active LLM providers and consensus thresholds.


Static Analysis Rules

37 rules aligned with official Microsoft analyzers. All run locally at zero token cost.

Reference: CodeCop Analyzer Rules | AppSourceCop Rules | PerTenantExtensionCop Rules

Readability Rules

Rule ID Severity Description MS Doc
AA0005 info Only use BEGIN..END to enclose compound statements AA0005
AA0008 warning Function calls should have parentheses even with no parameters AA0008
AA0013 warning When BEGIN follows THEN/ELSE/DO, it should be on the same line AA0013
AA0074 warning TextConst/Label variable names should have approved suffix (Lbl, Tok, Msg, Err, Qst) AA0074
AA0100 info Do not have identifiers with quotes in the name AA0100

Best Practices Rules

Rule ID Severity Description MS Doc
AA0003 warning Explicit COMMIT() breaking transactional integrity AA0003
AA0040 warning Avoid nested WITH statements AA0040
AA0073 warning Temporary variable must be prefixed with Temp AA0073
AA0137 warning Unused variable declarations AA0137
AA0161 warning Only use AssertError in Test Codeunits AA0161
AA0189 warning Missing ApplicationArea on page field/action AA0189
AA0207 warning EventSubscriber method must be local AA0207
AA0213 warning Obsolete/deprecated AL patterns AA0213
AA0237 warning Non-temporary variable with Temp prefix AA0237
AA0247 info Object missing namespace declaration AA0247
AA0101 warning Use camelCase property values in pages of type API AA0101

Performance Rules

Rule ID Severity Description MS Doc
AA0181 warning FindSet/Find must be used with Next() AA0181
AA0211 warning CalcFields should only be on FlowField or Blob fields AA0211
AA0222 warning SIFT index should not be on primary or unique key AA0222
AA0233 warning Get/FindFirst/FindLast should not be used with Next() AA0233
AA0242 warning FindSet/FindFirst without SetLoadFields — use partial records AA0242

Error Handling Rules

Rule ID Severity Description MS Doc
AA0175 info Get() called with no parameters AA0175
AA0214 warning Insert/Modify/Delete without return check AA0214
AA0231 warning StrSubstNo/concatenation in Error() call AA0231

Localizability Rules

Rule ID Severity Description MS Doc
AA0216 warning Hardcoded strings in Message/Error/Confirm AA0216
AA0217 warning StrSubstNo with inline string instead of Label AA0217
AA0218 warning Page field/action missing ToolTip property AA0218
AA0219 info ToolTip should start with "Specifies" AA0219
AA0225 warning Page field missing Caption property AA0225
AA0234 info Table field missing ToolTip property AA0234
AA0448 warning Use FieldCaption/TableCaption instead of FieldName/TableName AA0448
AA0462 warning CalcDate should use DateFormula variables or <> syntax AA0462
AA0470 warning Label placeholders should have explaining Comment AA0470

Security Rules

Rule ID Severity Description MS Doc
AA0087 warning InherentPermissions (lowering permissions) should only be in tests AA0087
AA0240 warning Email/phone in source code AA0240
AS0016 critical Table field missing DataClassification (table + tableextension) AS0016
PTE0006 critical Encryption key functions must not be invoked PTE0006

PTE Compliance Rules

Rule ID Severity Description MS Doc
PTE0003 critical Subscribing to CompanyOpen events is not allowed PTE0003

Preprocessing

Before rules execute, the engine:

  1. Strips /* */ block comments — preserves line numbers for accurate reporting
  2. Strips string literals (for email/phone rule) — avoids false positives on URLs in Labels
  3. Preserves raw lines for code snippets in findings

Disabling Rules

# Suppress specific rules (comma-separated, case-insensitive)
REVIEWER_DISABLED_RULES=AA0219,AA0100,AA0247

Review Modes

static — Rules Only

  • Speed: <100ms
  • Cost: Zero tokens
  • Use case: Fast CI gate, pre-commit hook
  • Runs all 37 regex-based rules against preprocessed code

single — Rules + One LLM

  • Speed: 5-30s
  • Cost: One model's tokens
  • Use case: Quick feedback from preferred model
  • Static rules + single LLM provider analysis

consensus — Rules + Multi-Model Voting

  • Speed: 10-60s (parallel LLM calls)
  • Cost: All configured models' tokens
  • Use case: High-confidence production reviews
  • LLM findings are deduplicated and voted on:
Finding Severity Consensus Threshold Min Votes (3 models)
critical 0.4 (40%) 2
warning 0.6 (60%) 2
info 0.8 (80%) 3

Microsoft BC Development Standards

The following standards are enforced through both static rules and the LLM system prompt, based entirely on the official Microsoft documentation.

Source: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/

1. Naming Conventions

Per AL Coding Guidelines:

Rule Standard Example
AA0072 Variable/parameter names suffixed with type/object name CustomerRec: Record Customer;
AA0073 Temporary variables prefixed with Temp TempSalesLine: Record "Sales Line" temporary;
AA0237 Non-temporary variables must NOT have Temp prefix SalesLine: Record "Sales Line";
AA0074 Label/TextConst variables have approved suffixes ConfirmQst, ErrorErr, DescriptionLbl, SeparatorTok
AA0215 PascalCase for objects, methods, properties procedure CalculateTotal()
AA0100 No quoted identifiers unless spaces/reserved words required CustomerName not "CustomerName"
AA0101-104 camelCase for API page/query entity names and columns entityName = 'salesOrder'
AS0011 Mandatory affixes for AppSource extensions FSO_ prefix or _FSO suffix
AA0247 Use namespaces with at least two levels namespace MyCompany.MyApp;
AS0127 Namespaces should have at least two levels namespace Company.Module;

2. Performance Best Practices

Per Performance Articles for Developers:

Standard Description Rule
Partial Records Always use SetLoadFields() before FindSet/FindFirst to avoid JIT loading of table extension fields AA0242
FindSet vs FindFirst Use FindFirst() when only one record needed. FindSet() requires Next() for looping AA0181, AA0233
Set-based operations Prefer CalcFields, CalcSums, SetAutoCalcFields over manual loops LLM
Built-in data structures Use TextBuilder (5+ concatenations), Dictionary (key-value lookups), List (dynamic arrays) LLM
Background tasks Use Page Background Task for calculated values in cues/FactBoxes LLM
Defer LockTable Call Record.LockTable as late as possible to minimize lock duration LLM
Tri-state locking Enable tri-state locking to avoid reads-after-writes taking locks LLM
Read Scale-Out Set DataAccessIntent = ReadOnly on reports, API pages, and queries LLM
Indexing Design proper keys/indexes. Avoid filtering on non-indexed fields (AA0210) LLM
SIFT Use SumIndexField Technology for FlowFields. Don't put SIFT on primary key (AA0222) AA0222
OnAfterGetRecord Avoid CalcFields, CurrPage.Update(), filter changes, and DB writes in this trigger LLM
Media vs Blob Use Media/MediaSet data types instead of Blob for images (client caching + thumbnails) LLM

3. Localizability Standards

Per CodeCop Localizability Rules:

Standard Description Rules
No hardcoded strings All user-facing strings must use Label or TextConst variables AA0216, AA0217
ToolTip required Every page field/action must have a non-empty ToolTip property AA0218, AA0220
ToolTip format Field ToolTips should start with "Specifies" AA0219
Table field ToolTip Table fields should also have ToolTip properties AA0234
Caption required Page fields must have a non-empty Caption property AA0225, AA0226
OptionCaption Required for non-table-field source expressions AA0221, AA0223, AA0224
FieldCaption over FieldName Use FieldCaption() and TableCaption() for localization AA0448
Label placeholders Placeholders in Labels must have explanatory Comment property AA0470
Placeholder matching String parameters must match the number of placeholders AA0131
CalcDate format Use DateFormula variables or <> enclosed strings with CalcDate AA0462
TranslationFile TranslationFile must be enabled (AS0015) AS0015

4. Security & Data Classification

Per AppSourceCop Security Rules:

Standard Description Rules
DataClassification Every table field of class 'Normal' must have DataClassification set. ToBeClassified is NOT acceptable for submission AS0016
Valid classifications CustomerContent, EndUserIdentifiableInformation, AccountData, OrganizationIdentifiableInformation, SystemMetadata AS0016
No PII in code Email addresses and phone numbers must not appear in source code AA0240
Encryption keys Encryption key functions (CreateEncryptionKey, DeleteEncryptionKey, etc.) must not be invoked PTE0006
Permissions InherentPermissions (lowering permissions) should only be used in test codeunits AA0087
InternalsVisibleTo Must not be used as a security feature AS0081, PTE0012
Permission sets Table definitions must have a matching permission set PTE0004, AS0103
Permission set XML Permission Sets should not be defined in XML files AS0094, PTE0014
Unsafe methods Unsafe methods cannot be invoked in AppSource applications AS0060
Reserved tables Reserved database tables are read-only in multi-tenant environments AS0059

5. Error Handling Standards

Standard Description Rules
Check return values Use Insert(true) to raise error on failure, or check with if Rec.Insert() then AA0214
Error with Label Never use string concatenation or StrSubstNo directly in Error() calls AA0231
TESTFIELD Validate key fields before record operations AA0175
COMMIT Avoid explicit COMMIT() — let the platform manage transactions AA0003
AssertError Only use in Test Codeunits AA0161, AS0058, PTE0007

6. Upgrade & Compatibility Standards

Per AppSourceCop Upgrade Rules:

Standard Description Rules
Don't delete published tables Tables and table extensions that have been published must not be deleted AS0001
Don't delete published fields Fields must not be deleted from published extensions AS0002
Don't change field types Published fields must not change type AS0004
Don't rename tables Published tables must not change name AS0006
Don't change keys Key fields must not be changed or deleted AS0009, AS0010
Obsolete lifecycle Use Pending -> Removed transition with justification and ObsoleteTag AA0213, AS0073, AS0075, AS0115
Public API stability Published procedures, events, and return types cannot be removed/changed AS0018-AS0028
Extension name stability Extension name and publisher cannot be changed AS0096, AS0097

7. Events & Extensibility Standards

Standard Description Rules
Local subscribers EventSubscriber methods must be local AA0207
No CompanyOpen Must not subscribe to CompanyOpen events (blocks session creation) PTE0003, AS0061
Affix on procedures Procedures in extension objects require mandatory affixes AS0079
Integration events Use Business/Integration events for extensibility, avoid tight coupling LLM
Subscriber codeunit size Keep subscriber codeunits small. Use single-instance when possible LLM
External business events Should have obsolete marker before removal AA0250, AA0251, AS0135
Limit OnCompanyOpen work Minimize logic in sign-in event subscribers to avoid blocking sessions LLM

8. PTE (Per-Tenant Extension) Compliance

Per PerTenantExtensionCop Rules:

Standard Description Rules
Object ID range Object IDs must be in the free range (50000-99999 for PTE) PTE0001
Field ID range Field IDs must be in the free range PTE0002
ApplicationArea All page controls and actions must set ApplicationArea PTE0008
No encryption keys Encryption key functions are forbidden PTE0006
No test assertions Test assertion functions not allowed in non-test context PTE0007
Permission sets Table definitions must have matching permission sets PTE0004
Compilation target Must be allowed in multi-tenant SaaS environment PTE0005
No entitlements Entitlements cannot be defined in PTE extensions PTE0013

9. Web Service Standards

Per Writing Efficient Web Services:

Standard Description
API pages over SOAP Use API pages/queries instead of SOAP endpoints (up to 10x faster)
No UI pages as endpoints Avoid exposing standard UI pages as web service endpoints
Conditional triggers Make AL code conditional on ClientType when page is exposed as endpoint
OData $batch Use $batch for sequential child record inserts to avoid parent record locks
Throttling handling Handle HTTP 429 (Too Many Requests), 503 (Service Unavailable), 504 (Gateway Timeout)
Retry strategies Implement exponential backoff with randomization for throttled requests
API versioning Use the highest API version available. Don't use beta API pages
ReadOnly intent Set DataAccessIntent = ReadOnly on API queries consumed by Power BI
Avoid temp tables Don't use temp tables as API source if >100 records (no caching, no efficient paging)

10. Page Design Standards

Per Writing Efficient Pages:

Standard Description
Minimize parts Reduce the number of page parts on role centers
Remove unneeded CalcFields Remove calculated fields from lists if not needed (setting Visible=false is NOT enough)
Dedicated lookups Create dedicated lookup pages instead of using full list pages for dropdowns
Page Background Tasks Use for calculated values in cues to keep UI responsive
Edit-in-Excel Make AL code conditional on ClientType — avoid FactBox updates and defaulting logic
Rendering property Use DefaultRenderingLayout with rendering syntax instead of deprecated ExcelLayout/RDLCLayout/WordLayout

11. Data Access Standards

Per Efficient Data Access:

Standard Description
Proper indexing Design appropriate keys for the way code accesses data. Avoid too many indexes
SystemModifiedAt Use SystemModifiedAt field for delta reads / change tracking
NCCI Use Non-clustered Columnstore Indexes for real-time analytics (runtime 19.0+)
LockTable defer Call Record.LockTable as late as possible in AL code
Record isolation Set record instance isolation level for concurrent transaction safety
Bulk inserts Leverage bulk insert mode; avoid test framework during insert/update performance tests
Number sequences Use NumberSequence data type for fast, non-blocking number sequences (accepts holes)

Security Features

Path Traversal Protection

When REVIEWER_WORKSPACE_ROOT is set, all file access is restricted:

REVIEWER_WORKSPACE_ROOT=c:\MyProject
  • review_al_file("c:\MyProject\src\MyPage.al") -> Allowed
  • review_al_file("c:\etc\passwd") -> Access denied
  • Symlinks are rejected

API Key Sanitization

Error messages are sanitized before being returned to clients or logged. Patterns caught: api_key, authorization, bearer, x-api-key, password, secret, token, URL query parameters.

Input Validation

  • Max input size enforced (max_input_bytes, default 512KB)
  • Null bytes stripped from input
  • Empty/whitespace-only input rejected
  • File extensions validated (.al only)
  • File size checked before reading (max_file_size_kb)

Rate Limiting

Sliding-window rate limiter prevents runaway costs:

REVIEWER_RATE_LIMIT=30  # max reviews per minute

Observability & Logging

Text Logging (default)

Standard Python logging to stderr with structured JSON events:

INFO:bc_code_reviewer.reviewer:{"event": "review_start", "review_id": "review-a1b2c3d4e5f6", ...}
INFO:bc_code_reviewer.reviewer:{"event": "review_complete", "score": 7.5, "duration_ms": 234.5}

Structured JSON Logging

Enable JSON-formatted logs for log aggregation (ELK, Datadog, etc.):

REVIEWER_LOG_FORMAT=json

Log Events

Event Fields Description
server_start models, disabled_rules, workspace_root Server initialization
review_start review_id, filename, mode, code_size Review initiated
static_complete review_id, finding_count Static analysis done
llm_complete review_id, models, total_findings LLM analysis done
review_complete review_id, filename, score, finding_count, duration_ms Review finished

SARIF Output for CI/CD

Export findings in SARIF v2.1.0 format for integration with GitHub Code Scanning, Azure DevOps, or any SARIF-compatible tool.

review_al_code(code="...", output_format="sarif")
review_al_file(file_path="MyPage.al", output_format="sarif")

Module Reference

bc_code_reviewer/
├── __init__.py          # Package entry point, exports main()
├── config.py            # ReviewerConfig + ModelConfig dataclasses
├── models.py            # Multi-provider LLM client (OpenAI/Azure/Anthropic/Ollama)
├── reviewer.py          # CodeReviewAgent — orchestrates static + LLM analysis
├── rules.py             # 37 static regex-based rule functions
└── server.py            # FastMCP server exposing 7 tools
Module Key Classes/Functions
config.py ModelConfig, ReviewerConfig, from_env()
models.py MultiModelClient, ModelResponse, _sanitize_error(), REVIEW_SYSTEM_PROMPT
reviewer.py CodeReviewAgent, ReviewResult, _RateLimiter, _finding_fingerprint(), to_sarif()
rules.py RuleFinding, 37 _check_*() functions, ALL_RULES, run_static_checks()
server.py 7 @mcp.tool() functions, _JsonFormatter, main()

LLM System Prompt Categories

The REVIEW_SYSTEM_PROMPT in models.py covers 8 categories with ~80 specific rules:

  1. Security — DataClassification, encryption, permissions, PII
  2. Performance — Partial records, FindSet/FindFirst, CalcFields, indexing, SIFT
  3. Best Practices — Naming, readability, unused variables, dead code, namespaces
  4. Localizability — Labels, ToolTips, Captions, OptionCaption, placeholders
  5. Upgrade & Compatibility — Breaking changes, obsolete lifecycle, public API stability
  6. Error Handling — Return checks, TESTFIELD, COMMIT, AssertError
  7. Events & Extensibility — Local subscribers, CompanyOpen, affixes, integration events
  8. PTE Compliance — ID ranges, ApplicationArea, permission sets, compilation target

Environment Variables

LLM Providers

Variable Description
OPENAI_API_KEY OpenAI API key
OPENAI_MODEL Model name (default: gpt-4o)
OPENAI_BASE_URL Custom base URL (for proxies/compat APIs)
OPENAI_TEMPERATURE Sampling temperature (default: 0.2)
OPENAI_MAX_TOKENS Max response tokens (default: 4096)
AZURE_OPENAI_API_KEY Azure OpenAI API key
AZURE_OPENAI_ENDPOINT Azure resource endpoint URL
AZURE_OPENAI_DEPLOYMENT Deployment name (default: gpt-4o)
AZURE_OPENAI_API_VERSION API version (default: 2024-02-01)
ANTHROPIC_API_KEY Anthropic API key
ANTHROPIC_MODEL Model name (default: claude-sonnet-4-20250514)
OLLAMA_MODEL Ollama model name (e.g., codellama:13b)
OLLAMA_BASE_URL Ollama server URL (default: http://localhost:11434)

Reviewer Settings

Variable Description Default
REVIEWER_CONSENSUS_THRESHOLD Warning finding vote threshold 0.6
REVIEWER_CONSENSUS_THRESHOLD_CRITICAL Critical finding vote threshold 0.4
REVIEWER_CONSENSUS_THRESHOLD_INFO Info finding vote threshold 0.8
REVIEWER_MAX_FILE_SIZE_KB Max file size in KB 500
REVIEWER_MAX_INPUT_BYTES Hard input size limit 512000
REVIEWER_TIMEOUT LLM request timeout (seconds) 120
REVIEWER_DISABLED_RULES Comma-separated rule IDs to suppress (none)
REVIEWER_WORKSPACE_ROOT Restrict file access to directory (none)
REVIEWER_RATE_LIMIT Max reviews per minute 30
REVIEWER_RETRY_ATTEMPTS Max LLM retry attempts 3
REVIEWER_RETRY_BACKOFF Exponential backoff base (seconds) 1.0
REVIEWER_LOG_FORMAT "text" or "json" text

Retry & Error Handling

LLM Retry Logic

HTTP Status Retried? Backoff
429 (Rate Limit) Yes 1s, 2s, 4s
500 (Server Error) Yes 1s, 2s, 4s
502 (Bad Gateway) Yes 1s, 2s, 4s
503 (Unavailable) Yes 1s, 2s, 4s
504 (Timeout) Yes 1s, 2s, 4s
401/403 (Auth) No Immediate fail
Network errors Yes 1s, 2s, 4s

Formula: wait = retry_backoff_base * 2^attempt

Connection Pooling

Shared httpx.AsyncClient across all LLM calls:

  • Max 10 concurrent connections, 5 keep-alive
  • 10s connect timeout, configurable request timeout

Finding Schema

{
  "rule_id": "AA0242",
  "category": "Performance",
  "severity": "warning",
  "line": 42,
  "code_snippet": "if Customer.FindSet() then begin",
  "message": "FindSet/FindFirst without SetLoadFields (AA0242)...",
  "suggestion": "Add Rec.SetLoadFields(Field1, Field2) before the Find call.",
  "source": "static",
  "consensus_votes": 3,
  "consensus_total": 3,
  "doc_reference": "https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/analyzers/codecop-aa0242"
}

References


Built for Business Central AL development. All rules and standards based on Microsoft Dynamics 365 Business Central Developer Documentation.

About

AI-powered Business Central AL code review engine with multi-model LLM consensus

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors