Conversation
…target framework Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
${analyzerFolder}ALCops.*.dllspecs resolve from the provisioned folder first, falling through to the tools directory and project-local pathsalmcpreceives the provisioned analyzer paths via--codeanalyzers, soal_compileandget_fixesagree on which rules runWhat changed
New services:
TargetFrameworkMoniker— detect DevTools TFM from the loaded assembly, find the bestlib/<tfm>folder in a NuGet packageNuGetVersions— parse NuGet flat-containerindex.jsonfor latest stable / highest overall versionAlcopsAnalyzerProvisioner— downloadALCops.Analyzersnupkg, extract matching TFM folder, cache under~/.alcops/analyzers/<tfm>/<version>/, with offline fallback to newest cached versionAlcopsAnalyzerProvisionerStartup—IHostedServicethat runs provisioning on a background task (never blocksinitialize)Modified services:
ProxyOptions— new--alcops-analyzers <latest|prerelease|x.y.z|off>CLI option (consumed, not forwarded toalmcp)ExternalAnalyzerLoader— provisioned folder is probed first forAnalyzerFolderRelativespecs;WellKnownBcCopspecs (Microsoft cops) are unchangedProjectAnalyzerResolver— awaits provisionerReadybefore resolving analyzersWorkspaceStartupResolver— split into sync project-discovery (Config) and async full-config (GetConfigAsync/BuildAlMcpArgsAsync) that awaits the provisionerAlMcpProxy—StartCoreAsyncawaitsBuildAlMcpArgsAsyncbefore launching the childMcpHost— registers provisioner, wires it into loader/resolver/workspace, active under--no-proxytooBreaking changes
None. The
--alcops-analyzersoption defaults tolatest, which is new behaviour (automatic download from NuGet on every startup). Pass--alcops-analyzers offto restore the previous behaviour where no analyzers are downloaded.Test plan
dotnet build --configuration Release— 0 warnings, 0 errorsdotnet test --configuration Release— 102 tests pass, 0 skippedTargetFrameworkMonikerTests— ShortName conversions, FindBestLibFolder exact/fallback/netstandard/none casesNuGetVersionsTests— latest stable vs prerelease, malformed entries, edge casesAlcopsAnalyzerProvisionerTests— extracts correct TFM, writes manifest, cache hit on second run, network failure with warm/cold cache, off mode, pinned mode (all with fake HttpMessageHandler, no real network)ExternalAnalyzerLoaderTests— provisioned folder wins for${analyzerFolder}specs, falls through when absent, not used for${CodeCop}ProxyOptionsTests—--alcops-analyzersparsed and consumedManual verification (3 runs with
--no-proxy, from the ApplyFixProject fixture)Run 1 — default (
latest): fresh download from NuGetRun 2 — cache hit: same command, no download
Run 3 —
--alcops-analyzers off: provisioning disabled, no downloadDesign notes
The provisioner detects the DevTools target framework from the
TargetFrameworkAttributeon the loadedMicrosoft.Dynamics.Nav.CodeAnalysisassembly (the same assemblyBcToolsLocatoralready resolved). It fetches the latest stableALCops.Analyzersversion from the NuGet flat-container index, downloads the nupkg, and extracts the best matchinglib/<tfm>/folder into~/.alcops/analyzers/<tfm>/<version>/. A.alcops-manifest.jsontracks the extracted files so cache validity can be checked without re-downloading. When the network is unreachable, the provisioner falls back to the newest cached version for the same TFM. The version can be pinned (--alcops-analyzers 1.2.0), set toprerelease, or disabled (off). The cache path can be overridden viaALCOPS_ANALYZERS_CACHE.The provisioner runs on a background task via
AlcopsAnalyzerProvisionerStartup(anIHostedService), so it never blocks the MCPinitializehandshake. Downstream consumers (ExternalAnalyzerLoader,ProjectAnalyzerResolver,WorkspaceStartupResolver) awaitAlcopsAnalyzerProvisioner.Readywhich completes with the provisioned folder path (ornullon failure/off). When the provisioned folder is available,ExternalAnalyzerLoader.ResolveDllPathprobes it first for${analyzerFolder}ALCops.*.dllspecs; Microsoft cops and non-ALCops third-party analyzers are unaffected.This PR is the prerequisite for a follow-up PR that drops the AL VS Code extension
bin/probe fromBcToolsLocator, since users who relied on the extension solely for its analyzer DLLs now get them provisioned automatically.🤖 Generated with Claude Code