Commit graph

15 commits

Author SHA1 Message Date
Jesper Schulz-Wedde
186d8a1314
Complete AL review knowledge readiness (#108)
Some checks failed
Validate knowledge index / validate-index (push) Has been cancelled
Validate AL review fixtures / validate-review-fixtures (push) Has been cancelled
Validate frontmatter and structure / validate (push) Has been cancelled
* Complete AL review knowledge readiness

Fill telemetry and Query coverage, strengthen thin review domains, correct audited content defects, and add deterministic cheap-model evaluation and reference-integrity safeguards.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Generalize review fixture discovery

Derive smoke cases from the leaf, domain, and paired-sample conventions so new leaves require no scoring-contract changes. Keep only exceptional selection/context overrides and fail when retrieval metadata cannot rank the selected article.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Preserve published field IDs in sample

Keep the existing Email and Contact Email field IDs unchanged, clarify that the sample represents an independent baseline, and use a local breaking-change rule for the generic smoke evaluation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Clarify published field identity rules

State explicitly that a published field keeps its ID, name, and type while a replacement is added as a separate field under an unused ID.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

* Align field obsoletion sample baselines

Use Email field ID 3 as the shared baseline so the bad example demonstrates a same-ID rename while the good example retains the original field and adds a separate replacement.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 9825b012-e653-496a-9310-c1f4b6f8ac27

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
2026-07-15 10:55:25 +02:00
Jesper Schulz-Wedde
078b869e33
Add per-row AL performance guidance (#97)
* Add per-row performance guidance

Document SetAutoCalcFields for per-row FlowFields and direct writes on iterated records, with focused reviewer retrieval cues.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

* Bound commit checkpoints by key range

Use a capped ordered query to discover each checkpoint watermark before locking and processing only that key range.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

* Address performance retrieval review

Retrieve Commit-in-loop guidance precisely, process exact checkpoint key lists, and narrow clone-before-write discovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-14 12:51:39 +02:00
Jesper Schulz-Wedde
0e06485027
Correct performance knowledge guidance (#94)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 667c64a8-eb36-4440-bc41-6a97d8fb5542

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
2026-07-14 11:26:29 +02:00
Jesper Schulz-Wedde
292bdabe27
Promote performance knowledge from community to Microsoft layer (#50)
Pure git-mv relocation of all 7 performance articles from community/knowledge/performance/ to microsoft/knowledge/performance/. No content changes.

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-01 10:41:01 +02:00
Jesper Schulz-Wedde
a9f3c50863 Regenerate microsoft/knowledge from upstream BCApps instructions
The previous LLM-generated knowledge files contained factual
hallucinations. The most visible was the claim that `FindFirst` /
`FindLast` "forces a full-table scan" on an unfiltered record - it does
not; those APIs return a single row via the current key.

Other inaccuracies the audit found and fixed:

* `FindSet(true)` was described as "taking a LockTable". The correct
  upstream phrasing is that `FindSet(true)` sets
  `ReadIsolation::UpdLock` on the read. UpdLock and LockTable are
  related but distinct mechanisms.
* The list of production-scale tables had been invented beyond the
  upstream source (e.g. "Detailed Cust. Ledg. Entry") without a
  citation. The regenerated list matches the ten tables upstream lists
  with their P95 row counts.
* `SetLoadFields` guidance had been augmented with an extra mechanism
  claim ("the database resolves the filter using the index without
  hydrating the value") not present in upstream.

Approach: full regeneration of `microsoft/knowledge/` from the six
upstream BCApps Code Review instruction files, with Microsoft Learn /
the AL language reference as a secondary source. Every claim in every
regenerated file is anchored to a verbatim upstream quote (or a Learn
URL); the audit trail lives in artifacts/trace-<domain>.json on the
session workspace.

The PR #11 transaction/error-handling cluster is preserved verbatim:

* performance/understand-implicit-transaction-boundary.md
* performance/codeunit-run-as-atomic-sub-operation.{md,good.al,bad.al}
* performance/codeunit-run-requires-prior-commit-inside-transaction.{md,good.al,bad.al}
* performance/use-tryfunction-for-error-catching-not-rollback.{md,good.al,bad.al}
* performance/avoid-commit-inside-loops.{md,good.al,bad.al}
* security/commitbehavior-attribute-scopes-explicit-commits.{md,good.al,bad.al}
* testing/transactionmodel-attribute-governs-test-transactions.{md,good.al,bad.al}

These articles already cite Microsoft Learn and were carefully
cross-referenced; the regeneration skips their topics rather than
duplicating them.

File counts after regeneration:

  performance   35 .md  (5 preserved + 30 new)
  privacy       17 .md
  security      18 .md  (1 preserved + 17 new)
  style         33 .md
  testing        1 .md  (preserved)
  ui            19 .md
  upgrade       18 .md

Total 141 atomic knowledge files, each strictly one rule. All pass
.github/scripts/validate_frontmatter.py with 0 errors and 0 warnings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-21 09:53:09 +02:00
Jesper Schulz-Wedde
5bcdc55df9 Sync knowledge articles with review agent instructions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-05 14:08:32 +02:00
Jesper Schulz-Wedde
800e266bfe Add seven performance knowledge articles from BC developer guidance
Cover non-obvious platform behaviors a capable LLM reliably gets wrong:
hidden FlowFields still calculate, LockTable scopes to the whole table,
query objects bypass the primary-key cache, table-event subscribers
disable bulk ModifyAll/DeleteAll, Blob fields are uncached, OnCompanyOpen
subscribers block every session creation, and the test framework
disables bulk insert mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:38:28 +02:00
Jesper Schulz-Wedde
dc14e7bb2a Update 6 knowledge articles to align with revised instructions
- performance/use-setloadfields-for-partial-records: Clarify that
  filter-only fields (SetRange/SetFilter) do not need to be listed in
  SetLoadFields — the DB resolves them via the index without hydrating
  the value into AL memory.

- performance/avoid-calcfields-in-loops: Add explicit exception for
  OnAfterGetRecord and OnValidate triggers, which are platform-managed
  and not developer-authored loops.

- performance/split-read-only-and-write-paths-to-avoid-locktable: Add
  ReadIsolation as the primary recommendation for read-only paths;
  LockTable reserved for confirmed write paths only.

- performance/prefer-direct-record-over-recordref: Scope the finding to
  hot unbounded loops (10k+ rows) over ledger-entry-scale tables;
  RecordRef in bounded/admin/setup contexts is not a concern.

- upgrade/enum-changes-must-be-additive-at-the-end: Replace direct
  ObsoleteState = Removed guidance with the two-stage workflow (Pending
  first, Removed later); reference use-obsolete-pending-before-removed.

- upgrade/use-datatransfer-for-large-dataset-initialization: Add the
  >300,000 records threshold as the concrete trigger for requiring
  DataTransfer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-24 10:36:08 +02:00
Volodymyr Dvernytskyi
4ce7d816cc Transaction and error handling in BC AL - new knowledge articles 2026-04-23 20:58:02 +03:00
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
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
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