diff --git a/.altestrunner/config.json b/.altestrunner/config.json new file mode 100644 index 0000000..034f2f5 --- /dev/null +++ b/.altestrunner/config.json @@ -0,0 +1,16 @@ +{ + "containerResultPath": "", + "launchConfigName": "", + "securePassword": "", + "userName": "", + "companyName": "", + "testSuiteName": "", + "vmUserName": "", + "vmSecurePassword": "", + "remoteContainerName": "", + "dockerHost": "", + "newPSSessionOptions": "", + "testRunnerServiceUrl": "", + "codeCoveragePath": ".altestrunner\\codecoverage.json", + "culture": "en-US" +} \ No newline at end of file diff --git a/custom/knowledge/architecture/al-identifiers-must-be-english.md b/custom/knowledge/architecture/al-identifiers-must-be-english.md new file mode 100644 index 0000000..34191db --- /dev/null +++ b/custom/knowledge/architecture/al-identifiers-must-be-english.md @@ -0,0 +1,81 @@ +--- +bc-version: [all] +domain: architecture +keywords: [naming, english, enu, variable, procedure, field, caption, translation, xliff] +technologies: [al] +countries: [w1] +application-area: [all] +--- + +## Description + +All AL identifiers must be written in English (ENU) regardless of the language +used in conversation with the developer. Translations are handled separately +via XLIFF files — never by writing Danish, German or other language identifiers +in AL source code. + +This applies to: +- Variable names +- Procedure names +- Parameter names +- Field names +- Object names (tables, codeunits, pages, enums, reports) +- Enum value names +- Local and global labels (Label data type) — both the identifier and the default text + +**Captions and ToolTips** may be in the target language in the source file, +but must also be covered by XLIFF translations for all supported locales. + +## Anti Pattern + +```al +// WRONG: Danish identifiers +var + Kreditor: Record Vendor; + Beløb: Decimal; + AntalKilo: Decimal; + +procedure BeregnTotalbeløb(Antal: Decimal; Pris: Decimal): Decimal +begin + exit(Antal * Pris); +end; + +field(50101; "Indgående Mængde"; Decimal) { Caption = 'Indgående Mængde'; } +``` + +## Best Practice + +```al +// CORRECT: English identifiers, Danish captions handled via XLIFF +var + Vendor: Record Vendor; + Amount: Decimal; + QuantityKg: Decimal; + +procedure CalculateTotalAmount(Quantity: Decimal; UnitPrice: Decimal): Decimal +begin + exit(Quantity * UnitPrice); +end; + +field(50101; "Inbound Quantity"; Decimal) { Caption = 'Inbound Quantity'; } +// Caption translation → da-DK XLIFF: 'Indgående Mængde' + +// WRONG: Danish label identifier and text +var + BeløbFejlTxt: Label 'Beløbet må ikke være negativt'; + +// CORRECT: English label identifier and default text — translated via XLIFF +var + AmountMustNotBeNegativeErr: Label 'Amount must not be negative.', Comment = '%1 = Amount'; +``` + +## Conversation vs. code + +The developer may describe requirements in Danish. The agent must translate +the intent into English identifiers when writing AL code: + +- "opret en variabel til beløbet" → `var Amount: Decimal;` +- "procedure der beregner lagerværdien" → `procedure CalculateInventoryValue(...)` +- "felt til indgående mængde" → `field(... ; "Inbound Quantity"; Decimal)` + +Never echo Danish words from the conversation directly into AL identifiers. diff --git a/custom/knowledge/architecture/namespace-must-be-verified-from-source.md b/custom/knowledge/architecture/namespace-must-be-verified-from-source.md new file mode 100644 index 0000000..3948242 --- /dev/null +++ b/custom/knowledge/architecture/namespace-must-be-verified-from-source.md @@ -0,0 +1,86 @@ +--- +bc-version: [all] +domain: architecture +keywords: [namespace, using, compile, al-language, tablerelation, variable, codeunit] +technologies: [al] +countries: [w1] +application-area: [all] +--- + +## Description + +When an agent adds a variable referencing a BC or custom object, it must verify +the correct namespace by reading the source file of that object — not by guessing +or relying on its training data. + +An AL file that "compiles" in the agent's own build may still show as red in +VS Code because the AL Language Server resolves namespaces differently. +The authoritative source for a namespace is always the object's own source file. + +This rule applies to: +- `using` declarations at the top of a codeunit, table, page or enum +- Variable declarations that reference tables, codeunits, pages or enums +- `TableRelation` and `CalcFormula` references + +## How to verify a namespace + +Before adding a `using` statement or a variable referencing an object, the agent +must locate and read the source file for that object: + +``` +// Step 1: Find the source file +Glob: "**/[ObjectName].*.al" or al_symbolsearch query: "[ObjectName]" + +// Step 2: Read the first line — the namespace declaration +namespace SettlementVoucher.SettlementVoucher; ← this is what to use + +// Step 3: Add the using statement in the consuming file +using SettlementVoucher.SettlementVoucher; +``` + +If the object is a Microsoft base application object, use `al_symbolsearch` to +look up the correct namespace — do not assume it from the object name alone. +Microsoft namespaces changed significantly from BC24 onwards. + +## Anti Pattern + +```al +// WRONG: Guessing the namespace from the object name +using Microsoft.Purchases.Vendor; // guessed — may be wrong +using SettlementVoucher; // incomplete — missing sub-namespace + +var + Vendor: Record Vendor; // missing using → red in AL Language Server + SVPost: Codeunit "SV Post"; // wrong namespace → unresolved reference +``` + +## Best Practice + +```al +// CORRECT: Read SVPost.Codeunit.al first → find: namespace SettlementVoucher.SettlementVoucher +// CORRECT: Use al_symbolsearch to find Vendor → namespace Microsoft.Purchases.Vendor + +using Microsoft.Purchases.Vendor; +using Microsoft.Finance.GeneralLedger.Ledger; +using SettlementVoucher.SettlementVoucher; + +codeunit 50204 "SV Incoming Item Flow Tests" +{ + var + Vendor: Record Vendor; + GLEntry: Record "G/L Entry"; + SVPost: Codeunit "SV Post"; +``` + +## Verification step before delivering code + +After writing any AL file, the agent must: + +1. List every `using` statement in the file +2. For each one: confirm the namespace was read from the actual source file + or looked up via `al_symbolsearch` — not assumed +3. If any namespace was assumed rather than verified, re-read the source and correct it + +Never report "compiled successfully" based on a build that did not go through +the AL Language Server in VS Code. The definitive compilation result is what +VS Code shows — not the agent's internal build. diff --git a/custom/knowledge/testing/tests-must-adapt-to-existing-code.md b/custom/knowledge/testing/tests-must-adapt-to-existing-code.md new file mode 100644 index 0000000..906f02c --- /dev/null +++ b/custom/knowledge/testing/tests-must-adapt-to-existing-code.md @@ -0,0 +1,75 @@ +--- +bc-version: [all] +domain: testing +keywords: [test, refactor, adapt, existing-code, green, failing, tdd] +technologies: [al] +countries: [w1] +application-area: [all] +--- + +## Description + +When a CURABIS developer asks for a test that "must work" or "must pass", +the agent's job is to write a test that passes against the **existing production code** +— not to write an idealized test and then report that the code needs changing. + +This rule applies in two distinct scenarios: + +**Scenario A — New test for existing behaviour** +The production code is correct and stable. Write the test to match what the code +actually does. Read the relevant codeunits before writing assertions. If the +expected value in the story differs from what the code produces, surface the +discrepancy and ask before assuming either is wrong. + +**Scenario B — Refactoring an existing test** +The test exists but fails because the production code was changed. Adapt the +test to match the new behaviour. Do not rewrite the production code to make +the old test pass unless explicitly asked to refactor production code. + +## The distinction that matters + +Writing a test that adapts to existing code is **not** the same as writing a +test that accepts wrong behaviour silently. If the production code contains a +bug that contradicts the business specification, flag it explicitly: + +``` +// ⚠️ NOTE: This assertion reflects current code behaviour. +// Business spec says 1792,00 but code currently produces 1800,00. +// Flagged for review — do not merge until resolved. +``` + +Never silently adjust an assertion to make a test green when the discrepancy +is a real business logic error. + +## Anti Pattern + +```al +// WRONG: Writing the "ideal" test without reading the production code, +// then leaving it failing and saying "the code needs to be fixed" +[THEN] +Assert.AreEqual(1792, ActualAmount, 'Total should be 1792'); +// Test fails. Agent says: "You need to fix SVPost to produce 1792." +// This is not what was asked for. +``` + +## Best Practice + +```al +// CORRECT: Read SVPost, understand what it produces, write the test to match. +// If the number is 1792 in both spec and code → assert 1792. +// If the number differs → flag it, don't silently change it. + +// [GIVEN] Read SVPost.Codeunit.al and SV Test Library before writing assertions. +// [THEN] Assert what the code actually produces, verified by reading the source. +Assert.AreEqual(ExpectedAmount, ActualAmount, 'Net payout to vendor must match'); +``` + +## Workflow when asked to write a passing test + +1. Read the relevant production codeunits (SVPost, SVApplyMgt, etc.) +2. Trace the calculation path for the specific scenario +3. Derive the expected values from the code — not only from the story +4. If code and story agree → write the test with those values +5. If code and story disagree → write the test with the code's values AND add + a clearly visible `// ⚠️ NOTE` comment explaining the discrepancy +6. Never leave a test failing when the task was to write a passing test