Commit graph

10 commits

Author SHA1 Message Date
Jesper Schulz-Wedde
0540c7bf6e Reframe seed-article banners as community contribution invitations
The 35 articles still in their seed form previously carried a banner
reading "Seed article. ... Domain stewards should expand, restructure,
and refine as needed." For a community preview, that phrasing reads as
"TODO left in production" to first-time visitors.

Replace all three banner variants (performance-seeded, security-seeded,
community-ported) with a single positive invitation:

> Contributions welcome — open a PR to refine or extend this article.

Content and structure of the articles are unchanged; only the leading
quote block differs. Articles that had their banner fully stripped in
the earlier triage pass (the showcase-grade ten) are unaffected.
2026-04-23 17:31:36 +02:00
Jesper Schulz-Wedde
e570d6113f Extract 55 knowledge articles from BC review-agent prompt
Adds 55 articles (plus 76 code samples) spanning four new domains and
two existing domains, extracted from the internal Business Central
review-agent prompt. Content was filtered against BCQuality's
remedial-knowledge premise: each article encodes BC-specific behaviour,
a CodeCop rule, a platform API semantic, or an anti-false-positive
guideline that a capable LLM would otherwise get wrong.

New domains:
- privacy (11 articles): DataClassification inheritance semantics, the
  StrSubstNo-defeats-Error-telemetry-classification pitfall, Privacy
  Notice consent for outgoing requests, anti-false-positives for pages
  and in-memory data.
- upgrade (11 articles): upgrade-codeunit structure, upgrade-tag
  lifecycle and registration, protected DB reads, DataTransfer for
  large datasets, InitValue semantics, enum-ordinal preservation,
  obsolete-workflow, first-install detection.
- ui (9 articles): caption capitalization by phrase type, tooltip voice,
  teaching-tip vs tooltip, tour-tip conventions, character limits,
  banned terms, ampersand handling, title punctuation.
- style (11 articles): label-suffix convention, API page naming,
  temporary-variable prefix, label properties (Comment/Locked), named
  invocations, FieldCaption in user messages, OptionCaption pairing,
  Error-parameter passing, `this` keyword, required parentheses, file
  naming.

Gaps in existing domains:
- performance (11 articles): production-scale table catalog (no row
  counts, per internal-data concern), anti-false-positive for bounded
  tables, guard-before-Get ordering, redundant-Get-in-OnAfterGetRecord,
  LockTable in read-only helpers, combined ModifyAll passes, writes in
  OnAfterGetRecord, SetLoadFields heuristics, temporary-table
  regressions, FlowField source-table widening, MaintainSQLIndex
  disabling SIFT.
- security (2 articles): environment-specific hardcoded GUIDs,
  ValidateTableRelation=false on user input.

Intentionally excluded: specific production P95 row-count numbers
(aggregated internal telemetry); rewritten as categorical guidance on
which tables to treat as production-scale without publishing sizes.

All articles use `bc-version: [all]` (applies to every BC version, per
the new schema sentinel). Validator passes with 0 errors / 0 warnings.
2026-04-23 16:43:42 +02:00
Jesper Schulz-Wedde
9a4198eb28 Add [all] sentinel to bc-version; apply to version-agnostic knowledge
Most of the corpus — FindSet/SetLoadFields/CalcFields patterns, permission
sets, SingleInstance codeunits, DataClassification, IsolatedStorage,
transaction scope, SecretText — describes BC platform behaviour that is
identical across supported versions. The seed [26..28] range on every
file implied a version-specificity the content does not actually have,
and there was no way to express "applies to every version" in the
schema the way [w1] and [all] already do for countries and
application-area.

Extend the v1 schema with a universal sentinel for bc-version, parallel
to the sentinels already defined for the other dimensions:

  bc-version: [all]         # applies to every BC version

[all] is mutually exclusive with explicit versions. Range shorthand
([26..28]) and explicit lists ([26, 27, 28]) continue to work for files
genuinely tied to a version-gated API or deprecation.

Update read.md (field definition, matching semantics, partial-context
rule), write.md (default to [all], use ranges only with a concrete
reason), README.md (frontmatter example), and the CI validator. All
forty existing knowledge files and the three action skills convert to
[all]; none of the current content is version-gated. Validator passes.
2026-04-23 16:00:03 +02:00
Jesper Schulz-Wedde
23184480d0 Triage seed knowledge and document admission test for preview
Remove seven knowledge files whose content is generic software-engineering
guidance that a capable LLM already applies without BCQuality present
(HTTPS-only, secret-leakage-in-errors, no-credentials-in-URLs, silent
security-error swallowing, short transaction scope, HTTP timeouts,
StrSubstNo-vs-concatenation). These fail the remedial-knowledge premise
and dilute the signal of the preview corpus.

Strip the "Seed article — domain stewards should expand" banner from ten
files that are ready to showcase (AA0232/AA0233 rules, FindSet read-only
semantics, SetLoadFields ordering and usage, CalcFields-in-loops,
SecretText end-to-end, DataClassification). The banner remains on files
that still need domain-steward refinement.

Add a "What belongs here" section to the README stating the admission
test: a file exists only if a modern LLM would get something wrong or
miss something without it. Gives contributors a concrete yes/no filter
before they open a PR.
2026-04-23 15:47:01 +02:00
Jesper Schulz-Wedde
9dad34f48a Revert "Add unit tests and knowledge files for BC domain context"
This reverts commit 7fbb121c24.
2026-04-22 14:03:09 +02:00
Jesper Schulz-Wedde
7fbb121c24 Add unit tests and knowledge files for BC domain context
- Introduced unit tests for the bc-domain-context implementation, covering various scenarios including filtering by application area, technology mismatches, layer precedence, and conditional applicability.
- Added knowledge files related to finance, including topics such as Chart of Accounts, Codeunit 12, Dimension Management, and VAT on prepayment chains, among others.
- Each knowledge file includes structured metadata and best practices to enhance the domain knowledge available for Business Central tasks.
2026-04-22 11:33:47 +02:00
Jesper Schulz-Wedde
62dabf9a11 Co-locate AL samples next to their knowledge articles
The /samples/ top-level tree is replaced with sibling files in each
knowledge-layer folder. An article and its demonstrations now live
side-by-side:

  microsoft/knowledge/<domain>/<slug>.md
  microsoft/knowledge/<domain>/<slug>.good.al
  microsoft/knowledge/<domain>/<slug>.bad.al

Rationale:
- Proximity. An article and its paired samples are one unit; the
  filesystem now reflects that.
- Layer ownership. Samples inherit layer precedence for free -- a
  /custom/ fork can override an article and its samples atomically,
  which the shared /samples/ tree previously made awkward.
- Trivial migration path. Action-skill source globs
  (*/knowledge/<domain>/**/*.md) are unchanged; sample discovery is a
  sibling-filename lookup.

Changes:
- git mv of all 65 sample files from samples/<domain>/<slug>/{bad,good}.al
  to microsoft/knowledge/<domain>/<slug>.{bad,good}.al (history preserved).
- Update See-sample references in all 37 articles that ship samples.
- skills/read.md: replace the no-code-blocks bullet with a pointer to a
  new Sample files section that fully specifies the sibling convention,
  the kinds (good/bad + forward-compatible), multi-technology rules,
  demonstration-only status, and layer-precedence behaviour.
- skills/write.md: update the samples pointer to match.
- README.md: annotate the knowledge tree with the sample sibling shape.
- samples/README.md deleted; content lifted into skills/read.md.
- Both generators (C:\temp\gen_performance_knowledge.py,
  C:\temp\gen_security_knowledge.py) updated to emit at the new paths
  and to stop writing samples/README.md. Re-running them is idempotent
  against the committed layout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 13:45:33 +02:00
Jesper Schulz-Wedde
0980397d27 Seed security knowledge corpus (16 articles + 30 AL samples)
Converts Jesper's existing AL security-review prompt into BCQuality seed
knowledge articles so the al-security-review leaf has a real corpus to
match against. Mirrors the performance seed phase.

Articles under microsoft/knowledge/security/ (16):
- Permission model: follow-least-privilege-in-permission-sets,
  use-indirect-permissions-for-elevated-access,
  use-inherent-permissions-to-grant-minimal-access
- Secrets: never-hardcode-secrets-in-al,
  use-isolated-storage-for-module-and-company-secrets,
  prefer-azure-key-vault-for-production-secrets,
  use-secrettext-for-credentials, use-secrettext-with-httpclient,
  compose-secrets-with-secretstrsubstno,
  use-nondebuggable-when-parsing-secrets
- External calls: require-https-for-external-calls,
  set-timeouts-for-external-calls, do-not-put-credentials-in-urls
- Error handling: avoid-sensitive-data-in-error-messages,
  do-not-swallow-security-errors-silently
- Extensibility: do-not-expose-sensitive-data-in-event-publishers

Paired AL samples under samples/security/<slug>/{bad,good}.al, object
IDs 50200-50231 (no overlap with performance 50100-50140).

Rubber-duck findings addressed:
- HttpClient secret-URI: SetSecretRequestUri is on HttpRequestMessage
  (not HttpClient). Rewrote use-secrettext-with-httpclient and its
  good sample to use HttpRequestMessage + HttpClient.Send.
- InherentPermissions only grants access to same-extension objects;
  the sample now defines its own table 50230 "Sec Sample Lookup" and
  grants 'r' on that, not on Database::Customer.
- Reworked compose-secrets-with-secretstrsubstno bad.al away from
  Format(SecretText) (unreliable) to a plain Text+StrSubstNo anti-
  pattern.
- Moved normative guidance out of Description in three articles
  (compose-secrets-..., prefer-azure-key-vault-..., use-inherent-...)
  so it sits in Best Practice / Anti Pattern per READ contract.
- Added a companion helper codeunit (50231) to the indirect-permissions
  good sample so it actually demonstrates the controlled write path.
- Rebuilt the event-publisher good/bad pair on the same ExportCustomer
  scenario so the contrast is the shape of the event signature, not a
  different event.

Also: broaden samples/README.md object-ID range note to 50100-50299.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 13:39:50 +02:00
Jesper Schulz-Wedde
32c40bbf1d Seed performance knowledge corpus (22 articles + AL samples)
Converts an existing performance-review prompt into 22 atomic
knowledge articles under microsoft/knowledge/performance/, each
paired with AL samples under samples/performance/<slug>/ demonstrating
the anti-pattern and/or the best practice. The full set seeds the
corpus the microsoft/skills/al-performance-review leaf skill matches
against and validates the READ knowledge-file format end-to-end.

Every article conforms to the READ contract: six required frontmatter
fields, Description always present, no fenced code blocks, sample
code referenced by repo-relative path. Each article is marked with a
blockquote 'Seed article' note so domain stewards can extend or
restructure them freely.

Articles (ordered by concern area):

Database query efficiency
- use-findset-with-next (AA0181)
- avoid-findfirst-with-next (AA0233)
- only-fetch-records-you-use (AA0175)
- use-findset-readonly-by-default
- use-setloadfields-for-partial-records
- use-addloadfields-in-report-layouts
- use-calcsums-to-aggregate-filtered-sets (file: use-calcsums-for-flowfield-totals.md)
- avoid-calcfields-in-loops
- add-sift-keys-for-flowfields (AA0232)
- use-isempty-for-existence-checks

Filter and key optimization
- filter-before-find
- set-current-key-to-match-filters

Temporary tables and transactions
- use-temporary-tables-for-intermediate-data
- keep-transaction-scope-short
- avoid-user-interaction-in-transactions
- avoid-commit-inside-loops

Record operations
- prefer-get-for-primary-key-lookups
- use-insert-false-when-skipping-triggers
- prefer-direct-record-over-recordref

Strings, codeunits, events
- use-strsubstno-for-message-formatting
- use-single-instance-codeunits-for-caching
- keep-event-subscribers-lightweight

samples/README.md documents the sample-folder convention and makes
clear the samples are demonstration-only, not derived from BC base
application source, with unique object IDs in the 50100-50199 range.

Rubber-duck pass caught: a misleading good.al in avoid-calcfields-in-loops
(fixed by switching to a hoistable CalcFields scenario), an invalid
event subscriber signature in keep-event-subscribers-lightweight
(fixed by adding var xRec), normative guidance leaked into the
Description of use-findset-readonly-by-default (moved to Anti Pattern),
a missing sample pair for keep-transaction-scope-short (added), and
muddy FlowField/CalcSums framing (retitled and clarified).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-17 13:23:34 +02:00
Jesper Schulz-Wedde
758e190c7b Add .gitkeep files to community and microsoft directories; remove .gitkeep from samples 2026-04-17 06:03:14 +02:00