Read the framework however the project file spells it - #56
Merged
Conversation
Closes #50. ExtractProjectMetadata read <TargetFramework> and no other spelling. A project from before the SDK format declares <TargetFrameworkVersion>v4.8 and has no <TargetFramework> at all, so it reported an empty framework -- not a wrong one, none. Two of the six real applications came out of `xaflogic wiki` with no framework beside four reporting net7.0 and net9.0. DeclaredTargetFramework reads all three spellings and normalises the pre-SDK one to its moniker: v4.8 becomes net48 and v4.8.1 becomes net481, which are different frameworks and stay distinguishable. A multi-targeting <TargetFrameworks> list, which the old regex could not see either, is reported as the project declared it rather than reduced to one entry -- code has to compile on every framework named there. Null stays distinct from a value, because "no project file was read" and "it targets net48" must never render the same way. Verified on all six real applications: PWPresupuesto net48, pwControlVisita net481, and the four SDK-style ones unchanged. The wiki went from four framework pills to six. AGENTS.md now carries a ground rule for a .NET Framework application rather than only naming the framework in its summary, which is what the issue is actually about: an agent told nothing assumes a modern framework and reaches for APIs that are not there. The rule is deliberately narrow. Most modern C# syntax does compile on net48 once LangVersion is set, and a rule forbidding all of it would be false -- which would cost the true half its credibility. It names only what no compiler switch supplies: the C# 7.3 default, the absent System.Text.Json, IAsyncEnumerable<T>, Index and Range, default interface methods being impossible at all, and the polyfill attributes record and required need. Written from a reading and never from a default, the same discipline the ORM rule keeps, so a modern application is never handed it. Three render sites printed the empty value rather than omitting it: the Markdown overview and detail page emitted a Framework label with nothing after it, and the MCP overview told an agent "Target framework: ." -- which is not a smaller answer than naming one, it is an unreadable one, and that string is what an agent reasons from. New fixture LegacyFrameworkSolution in the pre-SDK project format, with C# written the way that framework compiles: block namespaces and backing-field properties, no auto properties. A fixture that declared a legacy framework while writing modern C# would prove the project file was read and nothing else. It also reaches DevExpress through assembly references rather than PackageReference, so it pins both project-file readings against the same file. 548 tests, up from 525. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W45tzJFX3NoSrk7svtQeKT
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.
Closes #50.
ExtractProjectMetadataread<TargetFramework>and no other spelling. A project from before the SDK format declares<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>and has no<TargetFramework>at all, so it reported an empty framework — not a wrong one, none.Reproduced on the six real applications before anything was changed:
Read it however it is spelled
DeclaredTargetFrameworkhandles all three spellings, in the same shapeDeclaredDevExpressVersionalready uses for the DevExpress version — this is the framework getting the treatment #45 gave the version.<TargetFramework>net9.0net9.0<TargetFrameworks>net8.0;net9.0net8.0;net9.0<TargetFrameworkVersion>v4.8.1net481The multi-targeting spelling was invisible to the old regex too, and it is reported as the project declared it rather than reduced to one entry: picking one would be inventing a fact, and the list is what an agent needs, because code has to compile on every framework named there.
v4.8→net48andv4.8.1→net481are different frameworks, not a typo of each other, and stay distinguishable. Null stays distinct from a value, because "no project file was read" and "it targets net48" must never render the same way.All six real applications after:
The wiki went from four framework pills to six.
The part the issue is actually about
Naming the framework in a summary is not the same as forbidding what it forbids.
AGENTS.mdnow carries a ground rule, in the same numbered list as the ORM rule and gated the same way — written from a reading, never from a default, so a modern application is never handed it.The rule is deliberately narrow, and that was the hard part. Most modern C# syntax does compile on
net48onceLangVersionis set: file-scoped namespaces, raw string literals and top-level statements are fine there. A rule that forbade all of it would be false, and a false half would cost the true half its credibility — which is the same argument this project already makes about reporting "no reports" for an application that has forty.So it names only what no compiler switch can supply:
LangVersionSystem.Text.Json,IAsyncEnumerable<T>,IndexandRangeare absent without a packagerecord, init-only setters andrequiredmembers compile only where a polyfill attribute is suppliedThree render sites printed the empty value instead of omitting it
The Markdown overview emitted a
Framework:label with nothing after it, the detail page did the same, and the MCP overview told an agentTarget framework: .— which is not a smaller answer than naming one, it is an unreadable one, and that string is what an agent reasons from. All three now omit the field.The fixture
New
LegacyFrameworkSolutionin the pre-SDK project format, with C# written the way that framework compiles: block namespaces and backing-field properties, no auto properties. A fixture that declared a legacy framework while writing modern C# would prove the project file was read and nothing else.It also reaches DevExpress through assembly references rather than
PackageReference, so both project-file readings are pinned against the same file — a change that broke the version while fixing the framework would otherwise look green.Verification
AGENTS.md, not the extraction result, because extraction being right is not the same as the agent being told.net10.0has its own test. It is the one moniker where a rule matchingnetfollowed by a low digit gets the answer exactly backwards — and it is the framework this tool is built on, so it would have been wrong about its own repository first.🤖 Generated with Claude Code
https://claude.ai/code/session_01W45tzJFX3NoSrk7svtQeKT