Quality skills and knowledge for Business Central development. The shared bar for humans and agents alike.
Find a file
Michael Dieringer 0a8c9a8556
18 AL/BC patterns: style, data-modeling, web-services, appsource, breaking-changes, performance, testing (#156)
* Add 18 community AL/BC patterns across style, data-modeling, web-services, appsource, breaking-changes, performance, and testing

Contributed by CURABIS ApS, generalized from patterns observed across real AppSource/PTE development. Each article follows the knowledge file format (frontmatter, Description/Best Practice/Anti Pattern, sibling .good.al/.bad.al samples).

* Address Jesper Schulz-Wedde's review on PR #156

- Rename 3 articles so their .good.al/.bad.al companion stems match
  (do-not-change-primary-key, testfield-required-setup-field,
  al-identifiers-english), fixing the R14 orphan-sample errors.
- do-not-change-primary-key.good.al: include Flow in the new table's
  own primary key so it actually models the discriminating dimension.
- al-build-output-must-not-pollute-project-root.md: drop the
  unsubstantiated AL0197 causal claim and the non-existent
  al.outputPath setting; reframe as build-artifact hygiene sourced
  from ALTool --outfolder / al_build outputPath.
- prefer-email-module.md: Email Message is Codeunit 8904, not a table;
  distinguish it from the underlying Sent/Outbox/Draft storage.
- file-datatype-saas.md: File.Open/Create/Read/Write fails to compile
  against a Cloud-scoped project, it does not compile and silently
  fail at runtime.
- namespace-must-be-verified-from-source.md: narrow to "resolve from
  the referenced object's source or symbols," since source-file line
  one is not the only authoritative source (symbol packages, comments
  before the namespace line).
- test-data-must-be-random-and-complete.md: drop "assume an empty
  database" and "collision-free" absolutes; reframe around
  independence from unrelated business records and reserving explicit
  values for scenario-defining inputs.
- binary-choice-must-be-boolean.md: scope to genuine true/false
  semantics, not mechanical two-member-enum-to-boolean conversion.
- document-report-word-layout.md: scope down to a sourced Microsoft
  Learn recommendation instead of an unconditional performance
  guarantee; cite the three Learn pages.
- Wire the new articles into their review skills' candidate-selection
  signals (file-datatype-saas, prefer-email-module,
  namespace-must-be-verified-from-source, var-parameters-require-an-
  addressable-variable) so they can actually enter a worklist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix dimension-management-wiring.md: ValidateShortcutDimCode and CreateDim
do not exist on the current DimensionManagement codeunit

Verified against microsoft/BCApps: the real master-table validation
procedure is ValidateDimValueCode (or ValidateShortcutDimValues when a
DimSetID is also needed), and the real document-side inheritance
procedure is GetDefaultDimID, not CreateDim. Caught from Jesper
Schulz-Wedde's review thread, which had been partially hidden by
GitHub's comment folding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Address second round of Jesper Schulz-Wedde's review on PR #156

- dimension-management-wiring.md/.good.al: split into the two distinct
  models the article was conflating - master data (Default Dimension
  records via ValidateDimValueCode/SaveDefaultDim) vs. transactional/
  document data (a single Dimension Set ID assembled via AddDimSource +
  GetDefaultDimID, verified against BCApps' ExchRateAdjmtProcess.Codeunit.al).
  Added a compiling document-table example alongside the existing master
  table one.
- Deleted api-page-flowfields-must-be-calcfields (.md/.good.al/.bad.al):
  Microsoft's own FlowFields documentation states a FlowField used as a
  control's direct source expression is automatically calculated on any
  page - no API-page exception is documented, and none could be
  reproduced.
- prefer-email-module.bad.al/.md: Codeunit Mail has no Send/GetErrorDesc
  members; fixed to the real current 7-argument CreateMessage signature,
  and corrected the claim that the legacy path "still runs" - its base
  implementation no longer sends anything, only raises integration events.
- check-post-line-batch-pattern.md/.good.al: reframed from a universal
  invariant to the standard shape, naming the real Gen./Item/CA/Res./Job/
  Insurance/Mfg. Item/FA Jnl.-Check Line/-Post Line/-Post Batch codeunits
  it's based on. Added the missing Check Line companion codeunit so the
  good fixture is internally complete.
- test-data-must-be-random-and-complete.good.al: removed leftover
  "collision-free" wording contradicting the already-corrected article text.
- fixed-choice-set-must-use-enum-not-integer.md: removed the reintroduced
  state-count heuristic ("the line is the state count"), aligned with
  binary-choice-must-be-boolean.md's semantics-based distinction.
- namespace-must-be-verified-from-source.md: removed the false claim that
  the compiler and AL Language Server use different namespace-resolution
  rules.
- intrinsic-al-functions-must-use-modern-casing.md: removed the unverified
  claim that PascalCase is the VS Code formatter's default output.

Worklist completeness: added cues for the 8 rules in data-modeling,
testing, performance, and web-services that had none (Jesper's explicit
ask), plus the same gap in all 7 style rules from this PR (not explicitly
named this round, but the identical systemic issue) - 15 cues total across
al-data-modeling-review.md, al-testing-review.md, al-performance-review.md,
al-web-services-review.md, and al-style-review.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Fix remaining correctness issues from Jesper's 2026-09-15 re-review

- dimension-management-wiring: SaveDefaultDim's third argument is the
  shortcut dimension number (1-8), not the field's AL field ID; the
  fixture passed FieldNo(...) = 10. GetDefaultDimID's InheritFromDimSetID
  must be 0 when recomputing after the linking record changes, not the
  document's existing Dimension Set ID (which would retain the previous
  customer's leftover dimensions). Verified against
  DimensionManagement.Codeunit.al and BankDepositHeader.Table.al in the
  BCApps reference clone.
- check-post-line-batch-pattern: "Post Line writes exactly one line to
  the ledger" overclaimed - Gen. Jnl.-Post Line alone calls InsertGLEntry
  from a dozen call sites (balancing entry, VAT, currency rounding,
  deferrals) and can write several G/L Entries per journal line.
  Reworded to "posts exactly one journal line" and softened the
  "distinct, non-overlapping responsibilities" absolute.
- namespace-must-be-verified-from-source.bad.al: dropped the "resolves
  in a local build, fails in VS Code" comment (taught an inherent
  compiler/language-server disagreement that isn't real); reframed as
  stale/cached symbols, matching the prose fix already made.
- file-datatype-saas.good.al: replaced the deprecated 5-argument
  UploadIntoStream overload with the current 2-argument one, and
  actually staged through TempBlob as the article's own Best Practice
  instructs (the declared TempBlob variable was previously unused).
- test-data-must-be-random-and-complete: no longer treats a
  short-but-valid value as defective merely for being "underfilled" -
  AL field lengths are maxima, not minimums. Scoped to missing values
  or a scenario with an explicit length/format requirement (e.g. a
  truncation test). Updated the al-testing-review.md routing cue to
  match.
- stored-derived-fields-must-not-be-exposed-directly: stopped mandating
  source-field exposure as part of the core pattern: the good fixture
  exposed only one of the derived value's two inputs (Hours Used, not
  Budgeted Hours), making the claimed "so the consumer can verify it"
  impossible. Reframed as an optional, all-or-nothing addition and
  fixed the fixture to expose both inputs.

Rebased onto upstream/main to resolve conflicts in
al-breaking-changes-review.md, al-data-modeling-review.md,
al-performance-review.md, and al-style-review.md against merged PRs
#148 and #153; all sides' worklist tokens/cues retained.

* Fix remaining READ-convention sample links across this PR's 18 articles

The same plain-backtick "See sample: \`x.good.al\`." form fixed on
al-methods-limited-during-write-transactions (PR #161) turned up
repo-wide on 15 more of this PR's articles - Knowledge-Retrieval.ps1
requires the markdown-link form to associate a sample with its
article. All 16 fixed; the four local validators (frontmatter,
knowledge-index, knowledge-retrieval, review-fixtures, skill-index)
pass.

* Fix two merge-critical correctness issues from Jesper's 2026-09-22 review

- api-page-key-fields-must-be-editable-on-insert.good.al and
  stored-derived-fields-must-not-be-exposed-directly.good.al: both were
  writable API pages missing DelayedInsert = true, contradicting this
  repo's own api-page-delayedinsert-true rule - the canonical "good"
  samples were teaching code BCQuality itself flags.
- dimension-management-wiring.good.al: UpdateDimensionSetID exited
  early when Customer.Get failed, leaving the previous customer's
  shortcut dimension and Dimension Set ID in place - the same staleness
  bug the InheritFromDimSetID = 0 fix (from the prior review round) was
  meant to prevent, just triggered by a failed lookup instead of a
  successful one. Now clears the shortcut field and recomputes with an
  empty source list on a failed lookup too, so GetDefaultDimID
  correctly returns an empty Dimension Set ID instead of never running.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:48:17 +02:00
.claude-plugin Simplify standalone AL code review skill (#150) 2026-09-03 10:25:44 +02:00
.github Add source-verified Finance knowledge and review domain (#57) 2026-09-21 10:20:41 +02:00
community Add AL-focused AppSource validation guidance (#142) 2026-09-14 12:42:45 +02:00
custom Improve partner onboarding and documentation navigation (#174) 2026-09-09 17:31:03 +02:00
docs Add source-verified Finance knowledge and review domain (#57) 2026-09-21 10:20:41 +02:00
evaluation Add source-verified Finance knowledge and review domain (#57) 2026-09-21 10:20:41 +02:00
microsoft 18 AL/BC patterns: style, data-modeling, web-services, appsource, breaking-changes, performance, testing (#156) 2026-09-29 12:48:17 +02:00
schemas Add machine-readable review contracts (#182) 2026-09-15 10:27:40 +02:00
skills Add machine-readable review contracts (#182) 2026-09-15 10:27:40 +02:00
tools Add machine-readable review contracts (#182) 2026-09-15 10:27:40 +02:00
.gitignore Own the knowledge-index generator + index-aware review skills (#25) 2026-06-04 15:02:12 +02:00
CODEOWNERS Fix CODEOWNERS: correct @jeschulz -> @jesperschulz on base rules (#53) 2026-06-25 14:28:48 +02:00
LICENSE Add initial project structure with .gitignore, LICENSE, README, and CODEOWNERS 2026-04-17 05:56:10 +02:00
plugin.json Simplify standalone AL code review skill (#150) 2026-09-03 10:25:44 +02:00
README.md Add SCM functional knowledge domain (#192) 2026-09-21 10:16:44 +02:00
SECURITY.md Microsoft mandatory file 2026-04-17 03:58:13 +00:00

BC Quality - Don’t teach one agent. Teach the ecosystem. 🤝

Quality skills and knowledge that help AI tools make better Business Central development decisions: catch BC-specific defects, avoid misleading advice, and explain findings with references you can read.

BCQuality contains knowledge and reusable skills, not agents or a Business Central extension. Your host supplies the agent. You can install the content as a plugin, use it from another integration, or browse the knowledge directly.

Quick start

The walkthrough below uses GitHub Copilot CLI in a terminal, not the Copilot Chat panel in VS Code. First install Copilot CLI and sign in. Your account and organization policy must allow its use. You do not need to clone BCQuality, build a runner, or deploy an app to Business Central for this source-review example.

Standalone plugin installation

Run these commands in your terminal:

copilot plugin install microsoft/BCQuality
copilot plugin list

The list should include bcquality. The plugin currently exposes the al-code-review skill. Installation and skill discovery are the general pattern; reviewing an app is one example of using it.

Example: Review a complete app folder

Start a new CLI session in your own app folder, replacing the example path:

cd "C:\Repos\MyBusinessCentralApp"
copilot

Approve access only to a project you trust, then ask:

Use the installed al-code-review skill to review the complete Business Central app in this folder without changing my source files. Return the complete BCQuality findings report.

The folder should contain app.json and your AL source; it does not need to be a Git repository. On macOS or Linux, use your app's local path instead.

Expect a report for each selected review, with findings, source locations, severity, confidence, and references to the relevant guidance. Some hosts show the structured JSON directly. completed with no findings means nothing was flagged in that review's scope; partial or failed is not a clean result. See reading your results.

PowerShell 7 (pwsh) is recommended for fast knowledge discovery. If it is unavailable, the review can still discover knowledge by reading the folders.

Documentation

I want to... Start here
Choose direct reading, a supplied skill, or my own agent Ways to use BCQuality
Review a file, changes, a branch, or a particular concern Using BCQuality
Resolve setup problems, incomplete reviews, or incorrect findings Troubleshooting and support
Browse the available guidance Knowledge by domain
Configure the plugin or use my organization's rules Customizing BCQuality
Contribute knowledge or improve a rule Your first contribution
Connect a host, agent, or CI integration Minimal integration example

All documentation and technical references.

Scope

Today's curated content covers technical AL code review and a focused Supply Chain Management (SCM) functional domain. It augments the agent's judgment; it is not an exhaustive BC manual or a substitute for compilation, analyzers, tests, or human review. See coverage and limits for the available domains and the difference between a folder review and a comparison. Mechanical issues already enforced by the AL compiler or standard analyzers are intentionally left to those deterministic tools rather than duplicated here.

The SCM domain covers selected inventory, costing, reservation, tracking, and warehouse/posting workflows, not exhaustive supply chain validation. Broader functional coverage such as Finance, Manufacturing, Jobs, and Service, and technologies such as PowerShell, pipelines, and Power Platform, remain valid future scope, not current coverage claims.

What's in this repo

Knowledge articles cover one concern each. Skills tell an agent how to find and apply the relevant knowledge. Both live in three layers:

Layer Purpose
Microsoft Microsoft-endorsed skills and their knowledge.
Community Community-owned skills and their knowledge.
Custom Organization-specific additions and overrides in your own fork.

All three are enabled by default; Custom is empty upstream. You do not need to configure layers to get started.

Versioning

Update the installed plugin from your terminal, then start a new session:

copilot plugin update bcquality

Plugin versions and content-release tags are different. For reproducible runs and organization forks, see updates and versions.

What belongs here

Knowledge belongs here when it prevents a BC-specific mistake an otherwise capable agent would make, including false-positive findings. BC facts belong in knowledge articles, not skill instructions. See the admission test and examples.

Contributing

Partners are welcome to contribute to the layer that owns the domain, regardless of affiliation. Start with the contribution guide. To report a problem without authoring a rule, see support.

License

MIT