Two knowledge false-positive guards addressing bug 642303 (agent FPs on BCApps PR #9607):
- breaking-changes: relocating a field to a tableextension in the same app under the same field ID/name is a relocation, not a deletion/rename; the field still resolves on the table, so it must not be flagged as a deleted shipped field or require ObsoleteState staging. Scoped to the contract axis; silent on data migration.
- events: adding a parameter to an event publisher does not break existing subscribers (subscribers bind by name and match a subset), so the addition itself must not be reported as a breaking signature change.
#122 moved the plugin manifest to the root plugin.json (and moved the
bridge skill to skills/bcquality-al-review/), but the bridge SKILL.md
prose still pointed at the now-deleted .claude-plugin/plugin.json:
- ## Plugin root told the host to resolve PLUGIN_ROOT by anchoring on
.claude-plugin/plugin.json, a marker that no longer exists, so the
location-based fallback could never find it. Anchor on root plugin.json.
- ## Notes described .claude-plugin/plugin.json as the manifest the plugin
uses and root plugin.json as a future form -- the reverse of reality
after #122. Describe root plugin.json as canonical and .claude-plugin/
marketplace.json as the marketplace entry.
Doc-only; no behavior change.
The GitHub Copilot CLI plugin reference requires plugin.json at the root of the plugin directory. BCQuality shipped it only under .claude-plugin/, which is tolerated by --plugin-dir but is non-canonical and can be rejected on the marketplace / 'plugin install owner/repo' path.
Mirror the proven microsoft/BC-ALAgents al-review plugin layout: move plugin.json to the repo (plugin) root and add an explicit skills array plus repository/license/keywords metadata to both plugin.json and marketplace.json. The skills array pins the one real skill (skills/bcquality-al-review/), avoiding ambiguity with the loose meta .md files in skills/.
Verified: 'copilot --plugin-dir <clone>' still loads the bcquality plugin and the bcquality-al-review skill registers at runtime, identical to before.
- upgrade/obsoletereason-need-not-restate-removal-version: ObsoleteTag carries the version; do not flag ObsoleteReason for omitting it (PR 8290)
- error-handling/unchecked-get-throws-when-record-not-found: a bare Rec.Get() errors on missing record; it is not silently ignored (PR 8584)
- performance/onaftergetcurrrecord-is-not-per-row: OnAfterGetCurrRecord fires on selection change, not per row; CalcFields there is not N+1 (PR 8617)
The v1.4 policy deferred every missing-tooltip case to compiler analyzer AA0218. But AA0218 severity is per-app ruleset config and is routinely downgraded to info/None or disabled, so a genuine gap can ship unflagged. PR review is the last line of defence and should raise it independently.
Keeps the false-positive guard intact: a bound field whose source table field supplies a ToolTip still inherits it and is NOT flagged. Adds the genuinely-missing case (bound field whose source is also tooltip-less, or an unbound control) as a medium-severity finding. Updates both the ui inheritance article and the style AA0218 article.
Online eval shows style/variable-declaration-order-by-type firing as false positives (tp/fp 2/1) at minor. The article title itself is 'Order variable declarations by type (CodeCop AA0021)', so it is analyzer-redundant exactly like the this-keyword AA0248, label-suffix AA0074, and ToolTip rules already calibrated to info. Add AA0021 to the analyzer-redundant list so it emits at info and stops competing with substantive style review.
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
* Add precision guards for systematic agent false-positive patterns
Encodes reviewer-confirmed FP guards from the online eval: tooltip-inherited, page-trigger default return, drill-down filter not visible in diff, dual-trigger CalcFields (do.md); and a released-baseline precondition for breaking-change/upgrade findings on never-shipped symbols.
* Scope suggested-code and location to exactly the changed lines
Addresses reviewer-reported misplaced suggestions from the eval: insert-only-property emitting the whole field, single-statement rewrites anchored on the procedure name, and reductive multi-line collapses. The skill now emits a location range that matches precisely the rewritten lines.
* Correct suggested-code scoping guidance to match one-click anchor mechanics
A lone inserted line matches no existing file line and cannot be anchored; bracket the new line with one adjacent unchanged line instead. Reductive collapses omit suggested-code and fall back to a manual snippet.
* Move BC-specific FP guards out of do.md into leaf skills
do.md is the stable action-skill template and must stay domain-agnostic (JesperSchulz review). Relocate the four known false-positive patterns to their domain leaves: ToolTip-inheritance to al-ui-review; drill-down/lookup filtering and CalcFields lifecycle to al-performance-review; page-trigger exit(true) semantics to al-error-handling-review.
* Move suggested-code line-scoping guidance out of do.md into al-code-review
do.md must not carry instructions for how the review skill behaves (JesperSchulz review). Relocate the location/suggested-code precise-span rules to al-code-review's existing Suggested-code guidance section. do.md is now unchanged vs main.
* Move false-positive guards from skills into knowledge files
Keep review skills slim (finders/appliers). The FP guards and released-baseline preconditions previously embedded in leaf skills become negative-clarification knowledge articles in their domains, and the agent-findings policy edits to al-ui/al-privacy are reverted to main. Adds 6 knowledge files: error-handling (page-boolean-triggers-default-to-true), ui (bound-page-field-inherits-source-field-tooltip), performance (calcfields-in-both-getrecord-triggers-is-not-redundant, page-effective-filter-may-live-outside-the-diff), breaking-changes (unreleased-symbol-change-is-not-a-breaking-change), upgrade (unreleased-schema-change-needs-no-upgrade-path).
* Revert branch's suggested-code scoping addition in al-code-review
The three location-span shapes added to al-code-review are output-format mechanics, not domain knowledge: one-click span correctness is the engine's job (Resolve-SuggestionPlacement) and do.md already owns the suggested-code/location contract. The AL concerns the examples illustrate are already covered by existing knowledge (use-isempty-for-existence-check, data-classification-required-on-pii-fields, no-space-before-method-parenthesis). Restores al-code-review to main; the branch now adds only the 6 knowledge files.
* Restore al-ui/al-privacy review skills to base (zero diff in PR)
These two leaf skills carried an accidental net change against the PR merge-base because an earlier revert used the current origin/main (post-#110) instead of the branch base (pre-#110). Restoring them to the merge-base version removes them from the PR diff entirely. Three-way merge still preserves main's #110 suppression.
---------
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
Reviewing #112 surfaced that the authoring docs never state where a new BC
fact (or a false-positive guard) belongs, so an agent iterated do.md -> leaf
skills -> knowledge files across two review rounds before landing knowledge
in a knowledge article. The information to decide existed but was split across
README/do.md/write.md and framed only as positive best practices.
- do.md: add "Skills hold mechanics; knowledge files hold BC facts" — a skill
is a finder/applier; every BC behavioural claim it acts on must be a cited
knowledge file. Names negative knowledge (false-positive guards) as first
class, and forbids both adding a BC fact to a skill and restating an
article's fact inline (the drift/duplication smell).
- write.md: add "Is this a knowledge file?" decision gate at the top, plus a
"Negative knowledge is first-class" section with the Description/Best
Practice/Anti Pattern mapping and a worked example.
- README: note that false-positive-preventing files are first-class knowledge
and add a reviewer heuristic to Contributing.
Prose-only additions; validator passes. Meta-skill contract semantics are
unchanged, so version stays 1 (maintainers may bump if they consider the
explicit boundary rule a contract change).
Copilot-Session: 76eba53e-18cd-4618-a205-3607f260f9f4
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Online eval (182 PRs) shows the reference-less agent-finding channel is where 86% of false positives come from, and it is net-negative in the lowest-yield domains: privacy agent findings score 0 TP / 8 FP and UI/accessibility 1 TP / 11 FP. Restrict these two leaves to knowledge-backed findings only; an uncovered concern is omitted (and, if material and recurring, fixed durably by adding a BCQuality article per the self-improvement loop) instead of emitted with references: [].
* 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>
* Emit human-readable domain label on review findings
Add an optional findings[].domain field to the DO review output contract so
each finding carries its own human-readable review-domain display label. Leaf
review skills set it on every finding they emit; the al-code-review super-skill
copies it verbatim during rollup and sets it to "Agent" for its own
cross-cutting agent findings. This decouples consumers from BCQuality's domain
taxonomy: they render finding.domain verbatim instead of maintaining a
sub-skill-id -> label map.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Define domain display-label constraints
Clarify that review domains may contain internal whitespace, punctuation, case-sensitive text, and non-ASCII characters. Require consumers to preserve and safely encode the complete label instead of relying on lossy slugs, matching the replacement BC-ALAgents consumer.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 77d0a40e-8bf5-40ac-a450-40eb0255db03
---------
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move eight net-new rules into the Microsoft layer, remove six overlapping articles, and update review skill discovery and references.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 0b130227-d418-4bc0-9e7d-ec6a37adf039
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
The al-style-review worked example set findings[0].id to a non-existent
knowledge file (apply-approved-label-suffixes.md) while references[0].path
points to the real file (label-suffix-approved-list.md). The DO output
contract requires id to equal references[0].path for citation-based
findings. Align id to the existing file.
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
Online-eval data shows the style leaf is the largest source of dismissed
findings. Two causes:
- Mechanical, analyzer-enforced conventions (this-keyword AA0248, label
suffixes AA0074, missing ToolTip, label scope) fire at gating severity
and duplicate what CodeCop/AppSourceCop already report. Calibrate them
to info so a severity-gating consumer drops the redundant noise.
- Correctness/logic/data-integrity defects get reframed as style
conventions and emitted here. Sharpen the scope boundary: such defects
belong to the relevant domain leaf, or to al-code-review's cross-cutting
agent channel when no knowledge file covers them, never to this leaf.
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
* Promote security knowledge from community to Microsoft layer
Pure git-mv relocation of the SECURITY domain from the community layer to the Microsoft layer. No content changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review feedback on security knowledge promotion
- do-not-grant-rights-beyond-a-users-entitlement.md: drop the See sample
reference to a .good.al file that does not exist
- Remove the 'Contributions welcome' boilerplate line from
compose-permission-sets, prefer-oauth2, and protect-sensitive-data
- protect-sensitive-data-in-temporary-tables: remove the pointless
DeleteAll on the locally scoped temp buffer in the good sample and
reword Best Practice to note local buffers are cleaned up automatically
- Drop guard-bulk-operations-with-istemporary from the promotion; it
stays in the community layer pending a decision on whether it is security
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Remove Contributions welcome boilerplate from do-not-grant article for consistency
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add monthly manual versioning: VERSION file + release-version workflow
* Version as major.minor (1.0); bump minor monthly, major for breaking
* Clarify BCQuality minor is monotonic and never resets across major bumps
* Align comment with engine X.Y.Z scheme (minor = Z)
* Document BCQuality versioning in README
* Drop PRReviewAgent reference from README versioning section
* Derive release version from git tags, drop VERSION file
---------
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
Author 7 remedial BCQuality knowledge articles plus good/bad AL samples
(21 files) covering AL master-table and data-model design:
- data-modeling: master No. from number series in OnInsert; use codeunit
"No. Series" not obsolete NoSeriesManagement; setup table is a singleton;
set Last Date Modified in OnModify and OnRename; enforce Blocked in
referencing code not in the master.
- style: ApplicationArea required on page controls (AS0062).
- appsource: object affixes prevent collisions (AS0011).
Clean-room authored from own BC knowledge; specifics verified against public
sources only (learn.microsoft.com, microsoft/BCApps). Introduces two new
domains (data-modeling, appsource).
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repair broken knowledge references and align review examples with canonical articles. Correct explicit version gates, restore a missing title, and recognize the plugin directory in the root guard.
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add testing knowledge: UI handlers, table relations, asserterror, fixtures (P1+P2)
Six BC-specific testing-domain knowledge articles in community/knowledge/testing/, each with .good.al/.bad.al samples:
- ui-calls-require-test-handlers
- tablerelation-requires-prerequisite-records
- handlers-enqueue-never-assert
- handlerfunctions-attribute-must-match-ui-path
- asserterror-needs-expectederror-and-code
- use-library-codeunits-for-test-fixtures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Move testing knowledge from community to microsoft layer
Relocates the six P1+P2 testing-domain articles (18 files: .md + .good.al + .bad.al each) from community/knowledge/testing/ to microsoft/knowledge/testing/ per maintainer request. Pure git-mv rename; no content or frontmatter changes.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: merge handler articles, adopt enqueue-driven pattern
Respond to @nikolakukrika's review on #62:
- Merge ui-calls-require-test-handlers, handlerfunctions-attribute-must-match-ui-path
and handlers-enqueue-never-assert into a single ui-handlers-in-tests article.
- Adopt the enqueue-from-test / dequeue-and-assert-in-handler pattern using
Assert.ExpectedConfirm/ExpectedMessage (substring match), with Initialize()
clearing LibraryVariableStorage and AssertEmpty() proving exact call counts.
- asserterror sample now uses Assert.ExpectedTestFieldError + FieldCaption instead
of hardcoded message/code; article text points to the library helpers.
- Drop the tablerelation article and fold its test-relevant ordering point
(relations checked on Validate/Insert(true); build parents first) into
use-library-codeunits-for-test-fixtures.
Article count 198 -> 195.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Package BCQuality as an installable plugin (experiment)
Adds a marketplace + plugin manifest and a bridge review skill that drives the existing Entry protocol from a plugin host. No changes to knowledge or routing logic.
* Bridge skill: make enabled-layers configurable; note layer-pruning limit and manifest choice
Addresses PR #84 review (JesperSchulz): #2 layer policy has no hook in the plugin path -> expose BCQUALITY_ENABLED_LAYERS and document that it narrows discovery only, not a hard deny; #3 document the .claude-plugin manifest choice (verified on Copilot CLI).
---------
Co-authored-by: wenjiefan <wenjiefan@microsoft.com>
* Add 15 community knowledge articles from BC Code Intel ingest
Ingests net-new /community knowledge from BC Code Intelligence, surviving
the admission test, gray-zone salvage, and dedup against the full corpus.
Domains: ui (6), error-handling (3), performance (2), upgrade (1),
appsource (1), security (1), telemetry (1). The two BC24 No. Series
migration drafts are merged into one article.
Adds good/bad AL samples for the clean-fit articles (error-handling,
performance, security, telemetry). UI and appsource remain knowledge-only.
Validator and knowledge-index checks pass (207 articles).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Correct SetLoadFields JIT-load article to match MS docs
The draft claimed accessing an unlisted field "reloads the entire row"
per record. Microsoft's partial-records docs say otherwise: the platform
does an implicit Get that loads the missing field(s), and in a direct var
loop the first JIT updates the enumerator so later iterations do not
re-load. The genuine per-row penalty is the pass-by-value case, where the
copy's enumerator is not updated.
Rewrite the article around JIT loading and the by-value footgun, rename
the slug from ...full-reload to ...jit-load, and fix the good/bad samples
to demonstrate the by-value repetition accurately.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Jeremy Vyska <jeremy@sparebrained.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
The /custom/ layer is a template: in upstream microsoft/BCQuality it stays
empty by default and is meant to be populated only inside a fork or consumer
clone. PR #55 both targeted /custom/ and leaked a new top-level folder.
- skills/write.md: add a fork-precondition guard so authors (human or agent)
confirm they are not in microsoft/BCQuality before scaffolding /custom/ content.
- Guard custom layer workflow: auto-closes upstream PRs that add/modify /custom/
content beyond the template files, with a friendly redirect-to-fork comment.
- Flag new top-level entries workflow: posts an advisory (non-blocking) comment
when a PR introduces an unexpected top-level folder or file for maintainer review.
Both workflows run only on microsoft/BCQuality (never on forks) and read the PR
file list via the API without checking out or executing PR code.
Co-authored-by: Jeremy Vyska <jeremy@sparebrained.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
De-enumerate the AL review leaf list so it lives in exactly one place:
the al-code-review super-skill's frontmatter sub-skills list.
- al-code-review.md: drop the enumerated parenthetical from description
and remove the redundant bullet re-list in the Source section.
- README.md: remove the hardcoded count word and the enumerated domain
list from the leaf-skill sentence.
- validate_frontmatter.py: add cross-file rule R26 asserting a
super-skill's declared sub-skills exactly match the sibling
al-*-review.md leaf files on disk (missing, stale, and unregistered
leaves all fail CI).
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Seed web-services (API v2) knowledge domain
Add eight web-services API page knowledge articles (each with .good.al/.bad.al samples), a new al-web-services-review leaf skill, and wire it into al-code-review and the README.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Trim web-services domain to 6 non-duplicative articles
Drop API entity-naming/camelCase and DelayedInsert articles (owned by the style domain). Reframe the committed-data and API-versioning articles to stay strictly within the endpoint design/behavior lane, and update the leaf skill's worklist tokens and Output example accordingly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Seed a new breaking-changes (AL API stability) knowledge domain with six
articles plus good/bad AL samples, a new al-breaking-changes-review leaf
skill, and minimal wiring into al-code-review and the README.
Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>