مسیر C#/.NET و آداپتورهای پشته · فصل ۱ — Modern C#، ASP.NET Core، EF Core و Testing · 325
Modern C#/.NET Refresh
Build a modern .NET baseline contract that pins SDK, runtime, target framework and C# language version; distinguishes LTS/STS support from local installation; reviews relevant breaking changes before migration; verifies nullable/async/configuration assumptions with a bounded compile-and-test fixture; and records exactly what changed so a refresh is proven by evidence rather than by using newer syntax. میتواند «Modern C#/.NET Refresh» را در یک سرویس .NET محدود اجرا و با تست/diagnostics مناسب verify کند.
Lesson summary
Build a modern .NET baseline contract that pins SDK, runtime, target framework and C# language version; distinguishes LTS/STS support from local installation; reviews relevant breaking changes before migration; verifies nullable/async/configuration assumptions with a bounded compile-and-test fixture; and records exactly what changed so a refresh is proven by evidence rather than by using newer syntax.
میتواند «Modern C#/.NET Refresh» را در یک سرویس .NET محدود اجرا و با تست/diagnostics مناسب verify کند.
This lesson produces
میتواند «Modern C#/.NET Refresh» را در یک سرویس .NET محدود اجرا و با تست/diagnostics مناسب verify کند.
Who it is for
Foundation
Use a field map, one worked scenario and explicit state vocabulary before independent construction.
Repair
Identify the failed evidence dimension, use the smallest mutated fixture and rerun only the affected gate.
Experienced
Compress definitions; require trade-off defense, counterexample analysis and changed-context transfer.
Prerequisites
Why installing an SDK does not finish a refresh
Nima installs a new SDK. His editor detects it and a small example using newer C# works. The order service, however, still targets net8.0, and its global.json selects an older toolchain. A colleague changes only the target framework. The build now passes, but a Name: null configuration breaks the display-name path. Both developers changed something real; neither has yet established a sufficient reason to accept the service change.
You will follow one bounded service from its previous state to a proposed candidate. Your deliverable is the Modern .NET Baseline Matrix and Upgrade Verification Ledger v1: a matrix separating SDK, runtime, target framework, language and dependencies, with a ledger connecting the decision to tests, diagnostics and a rollback point. You must explain what changed, why it was needed, what remains unknown and what evidence would change your decision.
The core lab runs with Python 3.10+ and synthetic JSON inputs. SDK selection and data comparisons actually execute in Python; the supplied .NET build and test receipts are SYNTHETIC. A complete disposable C# project is also included, but its publisher execution remains UNVERIFIED. VERIFIED_SYNTHETIC means only acceptance within SYNTHETIC_ONLY; it is neither deployment permission nor verification of real service data.
Allow 60 active minutes. Open the learner lab, preserve the input and then make your comparisons. This lesson does not take ownership of API construction, database migration or service hosting. Its useful result is a defensible refresh decision, not a collection of newer syntax examples.
For readers who can already read C# and async calls, or who enter from the course's general path and first complete this lesson's short C#/.NET reading bridge, and want an evidence-based return to .NET.
This is not a complete C# language course from zero, a database change or a live service deployment; the entry bridge closes only the minimum reading threshold needed for this lesson and NET-002.
Choose a route and establish entry evidence
The conceptual prerequisite is FND-003, the controlled AI coding loop. Before entering, separate request, context, candidate, evidence and decision in five lines. “Repair the order service's display name” is a request; configuration and versions are context; a changed function is a candidate; observed test output is evidence; accepting or rejecting that change is your decision. A confident assistant response does not fill the evidence line. If this distinction is fragile, rewrite the example around a familiar small change before continuing. This bridge does not replace a C# fundamentals course.
C#/.NET translation bridge for learners entering from the general path
If you entered through the course's general path and have not previously read C#, this section closes only the code-reading threshold used by NET-001 and NET-002; it is not a replacement for a full language course. If you can answer the five readiness prompts below without guessing, skip directly to “Four numbers answer four different questions.”
static async Task<string> LoadDisplayNameAsync(User? user)
{
if (user is null) return "guest";
var name = user.Name ?? "anonymous";
await Task.Delay(1);
return name;
}
This snippet expresses ideas you have already met in the general path using C# notation. User? user is a parameter named user whose User reference may be null. Task<string> means the async method eventually produces a string. if (...) return ... is a conditional branch with an early return. var name is a local binding; var does not mean an untyped runtime value—the compiler infers the static type from the right-hand expression. ?? selects the right-hand fallback when the left-hand value is null. await observes an asynchronous operation to completion before the method continues. Braces delimit the method body, and a call such as Task.Delay(1) invokes a member through its type/name.
If you completed WEB-001, one analogy can help: TypeScript string | null and C# string? both force you to account for a possibly absent value, but their syntax and rules are not interchangeable. This is only a reading analogy; WEB-001 does not become a new prerequisite for NET-001.
Five-point probe: identify (1) the input and its type, (2) where nullability is handled, (3) every path that returns, (4) the local binding and fallback, and (5) what async/await ultimately return to the caller. If four or five are clear, continue.
If three or fewer are clear, paraphrase the snippet once: “a user may be null; if absent return guest; otherwise take the name or its fallback; await one async operation; return the name.” Then change the local variable name and fallback and answer the five prompts again. The exit criterion is following data/control flow, not memorizing syntax.
Bridge recap: to continue, you only need to follow a parameter, nullable type, condition, local binding, fallback, return, and await in one small C# method. Deeper language instruction remains out of scope.
For the foundation route, read the mental model and state vocabulary, then complete both worked examples and the guided diagnosis. A suggested time split is eight minutes for boundaries and terms, twelve for mechanisms, ten for examples, twelve for guided practice, twelve for transfer and six for assessment. These are activity estimates, not a promise about installing a toolchain.
If experienced, start with the disagreement in sdk_pin_old.json. Compress definitions that you can already explain with a counterexample. Still submit the complete matrix, rejection of the tempting shortcut, change-cost rationale and transfer artifact. The faster route carries the same evidence requirements.
For repair, identify the failed dimension and its pointer, return to the relevant explanation, propose the smallest relevant change and recheck the evidence that depends on it. All routes converge on the same deliverable. The educational predecessor is MKN-031, and the next lesson is NET-002. The present package does not assume that every neighboring lesson is locally available. Completing this refresh contributes one bounded piece of evidence; it does not close the chapter's testing and hosting outcome.
Entry evidence: separate request, context, candidate, observed evidence and decision for one small change.
If you confused an assistant proposal with evidence, rebuild the display-name example as five controlled-loop lines and answer again.
Four numbers answer four different questions
The SDK selects build tooling; the runtime executes built code; TargetFramework identifies the API surface and compilation target contract; the C# version constrains the language accepted by the compiler. They are related facts, not interchangeable labels. Installing SDK 10 does not automatically rewrite a net8.0 project as net10.0. Nor does net10.0 pin a runtime patch such as 10.0.12. Version selection in .NET
Keep two mental columns: declared and observed. A global.json file requests tool selection; an observation of the selected tool needs its own context. The runtime value in a fixture is likewise a claim made by that input, not proof of installation on your machine. Framework-dependent deployments can select a runtime patch under host rules; self-contained deployments carry their own runtime and require separate servicing. Success in one column cannot silently fill another.
The flow's text equivalent: capture the previous state and context; separate SDK, runtime, TFM and language; check support and dependencies; connect relevant breaking changes to behavior and tests; construct a bounded candidate; examine context-bound build, test and diagnostic evidence. Missing or stale evidence leads to HOLD; contradiction requires repair and rerun; complete synthetic inputs permit only VERIFIED_SYNTHETIC. Preserve the versioned ledger afterward.
The arrows represent dependencies, not an instruction to edit every field. A service may need new observations while retaining its version declarations. Conversely, an apparently small project edit may invalidate several observations because they describe the former candidate. A digest helps identify that dependency; it does not perform a build.
NET-001-F1 — Retrieve the boundary: Why is “SDK 10 is installed” insufficient to accept the service? Answer the four questions above with an appropriate evidence item for each, and name one out-of-scope activity. Listing four version numbers alone does not demonstrate the distinction between declaration and observation.
From a version pin to an evidence state
The order scenario starts at 8.0.100 / 8.0.0 / net8.0 / 12.0. These are historical baseline values, not today's installation recommendation. Its exercise candidate is 10.0.401 / 10.0.12 / net10.0 / 14.0. At the 2026-09-12 check, the support page records .NET 10 as LTS through 2028-11-14, and .NET 8 through 2026-11-10; the listed patches are 10.0.12 and 8.0.31, respectively. An LTS label alone does not establish that an old patch satisfies current servicing requirements. Support policy
The candidate's tooling pin in the dotnet folder is:
{"sdk":{"version":"10.0.401","rollForward":"disable","allowPrerelease":false}}
With disable, that exact SDK must exist. Having only 10.0.112 does not satisfy a request for 10.0.401. The Python model implements only disable and latestPatch. The latter selects the highest eligible installed version in the same feature band, never below the request. For example, 10.0.100 with latestPatch can select 10.0.112; 10.0.401 belongs to another band. Other policies remain UNSUPPORTED in this model. global.json
The real CLI's starting directory matters when it searches for global.json; MSBuild resolution can start from solution or project context. This lab receives an explicit, already-resolved JSON object. It does not simulate directory traversal, an IDE or all of MSBuild. Record that limit beside its result.
Use states precisely. UNKNOWN means the input cannot establish a fact; UNSUPPORTED means a combination or policy is outside the supported contract; UNVERIFIED means evidence is insufficient; STALE means evidence does not apply to the current time or candidate; REVIEW_REQUIRED preserves unfinished review; FAILED records a contradiction with an expectation. HOLD is the aggregate decision when a blocker remains. A weighted score or an unrelated green PASS cannot erase these causes. One missing diagnostic capture and one failed regression can coexist, and both belong in the ledger.
Connect a change to observable behavior
The sample project declares TargetFramework=net10.0, LangVersion=14.0 and Nullable=enable. The explicit language version is a reproducible choice for this exercise. In real projects the language default follows the TFM, and explicitly retaining an earlier version can be valid. Do not substitute latest for a versioned decision. Using a language newer than the TFM's supported default is not a supported combination. Configure the language version
At the review date, C# 14 is the stable release associated with .NET 10. Selecting it does not require rewriting every function. For example, changes to Span-related overload resolution can affect some calls. The exercise's synthetic source inventory declares zero such calls, so this entry is NOT_APPLICABLE with a concrete reason. Absence in that supplied inventory is not an automated audit of a real repository. C# 14, overload-resolution change
Our applicable change concerns JSON configuration. Before .NET 10 the JSON provider converted null into an empty string, alongside the binder's earlier null handling. In .NET 10 null is preserved and the binder can assign it. Consequently, do not claim that an old JSON null always left a property's initializer untouched. For this string-property example, a missing key and an explicit null are different inputs. Preserved configuration nulls
The local display contract requires missing, null and empty values to produce “Guest”, while " Neda " becomes "Neda". Code that starts by calling name.Trim() can fail when it receives a real null. A small repair is:
static string DisplayName(string? name) =>
string.IsNullOrWhiteSpace(name) ? "Guest" : name.Trim();
That guard implements a product decision about empty values. Nullable analysis supplies compiler diagnostics; it does not insert runtime guards. The sample's TreatWarningsAsErrors=true is a strict local contract, not a claim that every team should apply an identical setting without review. External library boundaries and uncertain annotations still need examination. Nullable references
The async boundary likewise involves more than adding async. This service contract returns Task; its caller awaits completion, observes dependency failure in that path and checks cancellation before an effect. async void does not fit this service contract; event handlers are its usual special case. A scoped dependency must remain alive through the awaited work. Returning unfinished work from a closed scope can leave it using a disposed object. The included project checks failure and cancellation as well as disposal after completion. A small test does not establish the scheduling behavior of every async program. Async return types, DI lifetimes
NET-001-F2 — Diagnose negative evidence: In regression_failed.json, how can a successful build coexist with a failed config_null case? Locate the test-result pointer, distinguish a nullable warning from a runtime guard, and propose a repair that does not change the public expectation merely to make the result green.
Worked examples: a coherent candidate and the wrong SDK
baseline.json is a synthetic record for orders-refresh. Read before first and then candidate; the fixture's name does not mean it contains only the previous state. It includes both states and candidate receipts in one context. These commands actually calculate tool selection and field differences:
python inspect_baseline.py fixtures/baseline.json
python inspect_project.py
The model selects 10.0.401 for the candidate. Changes include the four versions, global.json, the synthetic dependency version, the null policy and the source revision. Nullable settings, the Task contract and the lifetime boundary remain unchanged. Retaining them does not remove the need to test them. Read this compact view alongside resources/tables/NET-001-T1.csv; the full matrix has 23 columns and two rows, with every field mapped in field_map.json.
| Dimension | Previous state | Order candidate | Reason to inspect |
|---|---|---|---|
| SDK / Runtime | 8.0.100 / 8.0.0 | 10.0.401 / 10.0.12 | Separate tooling and execution target |
| TFM / C# | net8.0 / 12.0 | net10.0 / 14.0 | Separate API and language contracts |
| global.json | Exact 8.0.100 pin | Exact 10.0.401 pin | Installation alone is insufficient |
| Synthetic package | DisplayAdapter 1.0 | DisplayAdapter 2.0 | Target verification matrix |
| Null behavior | Trim then fallback | Guard then trim | CFG_NULL_10 applies |
| Build / tests / diagnostics | Not reassessed | Synthetic PASS / 7 cases / synthetic PASS | Receipts share the context |
| Review / rollback | Human approval not supplied | Synthetic review and rollback | No real-service claim |
In contracts.json, version 1.0 of the imaginary package is verified only for net8.0 in the exercise matrix; version 2.0 covers both targets. This file is not NuGet authority. In a real project, a package's lower TFM does not by itself prove incompatibility: compatible asset selection, restore and application behavior need review. The exercise uses only its explicitly verified set.
Compare all seven observations with their public expectations, not just their PASS labels. Cases cover missing, null and empty names, a padded name, awaited failure, cancellation before an effect and scope lifetime. Build, tests, diagnostics and review must bind to service, context and the four relevant digests. Rollback must identify the same previous-state digest. For this input and historical exercise date, no contract blocker remains: VERIFIED_SYNTHETIC within SYNTHETIC_ONLY. That verdict does not claim actual execution of the seven C# tests.
In sdk_pin_old.json, both SDKs are declared installed, but the candidate's global.json still requests exact 8.0.100. The model selects 8 despite the candidate's SDK 10 and net10.0 claims. Preserve three causes: SDK_SELECTION_MISMATCH/FAILED, BASELINE_CONTRACT_FAILURE/FAILED and CONTEXT_STALE/STALE. The pin change changed the candidate digest, leaving earlier receipts disconnected. The decision is HOLD. The proposed repair is to align the pin and then regenerate dependent receipts in the new context. Editing the hash on an old receipt cannot substitute for a fresh execution.
Isolate failures without erasing their causes
Each negative fixture exposes a shortcut. tfm_without_review empties the breaking-change review; repairing it requires connecting an applicable change to source and test evidence, not writing “everything reviewed.” language_package_conflict returns a dependency to an unverified target matrix; if receipt bindings become stale as well, both causes remain. nullable_disabled weakens the warning contract, while async_void breaks the completion-observation contract. Green copied receipts do not neutralize those differences.
In missing_diagnostic, the capture reference is blank. Plausible output fields do not rescue the missing diagnostic evidence: it remains UNVERIFIED. In stale_review, the review's candidate hash differs from the current candidate. A reviewer name and a REVIEWED label cannot conceal STALE. Check the six bindings—service, context, baseline, candidate, source and tools—individually.
Three ledger mistakes are particularly tempting. First, changing a FAILED label while retaining the failed observation does not repair the test. Second, missing evidence is not negative evidence: an absent capture means the behavior was not established, not that the expected behavior was observed. Third, finding the first failure does not justify dropping independent causes. If diagnostics expose synthetic private data and a regression fails, preserve both the privacy problem and the failed test.
Use synthetic data throughout this exercise. Do not add tokens, connection strings or customer records to make the ledger look more complete. Named cases, versions, context identifiers and sanitized outcomes provide the necessary explanation. A small repair begins at the causal field, but every observation bound to a changed digest must be renewed. A small code change is not permission to retain an unrelated receipt. Likewise, a “no code change” decision still needs applicable evidence when the service identity or review context has changed.
Experienced route: defend a smaller change
A colleague proposes requiring SDK feature band 400 and C# 14 across every service for consistency. Standardization can reduce support cost, but it is not evidence of this service's need. The checked download page lists both SDK 10.0.401 and 10.0.112 with runtime 10.0.12 and C# 14. An earlier feature-band number alone does not mean an obsolete patch. That download listing also does not certify every IDE or operating system in your environment. .NET 10 downloads
To compress the route, supply three short defenses. What source requirement makes a language change necessary? Which tool-selection rule actually applies in the team's environment? What evidence establishes dependency compatibility and retained behavior on the candidate? If the first answer is “no current requirement,” say so. That answer does not remove the other two questions.
Provide a counterexample as well: a service with the same TFM and a lower explicit language pin can compile unchanged code without adopting a new language feature. Conversely, an actual requirement for a newer feature can justify changing the language and its related tests. The word “modern” does not decide between those cases.
Repair your reasoning by returning to the nearest causal evidence. Wrong tool selection belongs with global.json and resolver output; display-name failure belongs with the null contract and test case; lost async work belongs with Task, cancellation and lifetime. If your only defense is a larger version number, return to the mental model and separate declared state from observed behavior. This route omits repeated definitions, not the changed-context evidence required for the final decision.
Upgrade, retain or temporarily hold?
In a real project, temporarily retaining a supported family on its current patch can buy time to collect evidence. Its costs include approaching end of support and potentially repeating work later. Moving to .NET 10 offers a longer support horizon, but it does not automatically solve source, tooling or dependency compatibility. Syntax modernization without a behavioral need also increases review and diff cost; its benefit should be explicit.
For the order service, net10.0 is part of the exercise's target contract. “Stay on net8 for now” therefore is not a successful answer to this contract. You may describe it as a proposed scope change while retaining HOLD. Outside the exercise, the service owner must set goals, timing, cost and risk. Microsoft documentation establishes platform mechanisms; it does not authorize a production change or set the team's policy.
The breaking-change catalog is a search map. This lesson defines two entries for its small synthetic inventory, not an exhaustive audit of every 8-to-10 migration. A real service review must also examine intervening releases, consumed libraries, relevant APIs and tooling. “I read two links” does not mean “no other applicable change exists.” .NET 10 compatibility catalog
Write stop conditions before judging the result. A dependency without compatibility evidence, a contradictory test, an unreferenced diagnostic capture or a missing rollback point blocks acceptance. This lab's rollback models restoring a disposable file snapshot only. It does not establish database reversal, reversal of external effects or deployment rollback. Do not average a cost score with a test score to conceal a decisive failure. Discuss cost as a trade-off while preserving technical blockers in their own states.
Guided diagnosis and independent transfer
Inside the learner folder, inspect the input inventory and create a fresh response for regression_failed:
python run_checks.py --inventory
python run_checks.py --template fixtures/regression_failed.json submission.guided.json --as-of 2026-09-12
Before checking it, fill readiness_state, the complete issues list, evidence_refs, rationale, minimal_repair and review_trigger yourself. Start the guided case at test ID config_null. Read its index from this file's array and use a pointer such as /tests/1/observed to reference the observation. Here is the scaffold: what does the build's PASS establish, and which behavioral claim does this test observation contradict? Then explain the difference between repairing code and editing an expectation.
python run_checks.py --check fixtures/regression_failed.json submission.guided.json
STRUCTURE_PASS_SEMANTICS_UNREVIEWED means the response shape, bindings and references passed. It does not establish correct reasoning or a complete cause set; semantic review is still needed. The checker deliberately does not supply the final transfer answer. Choose a fresh output name when repeating the exercise; it will not overwrite an existing file.
Now examine transfer_existing.json independently. The second service already targets net10.0, uses an earlier SDK feature band and explicitly pins an earlier language version. Public definitions and expectations are in contracts.json; an aggregate verdict and completed response are not supplied. Extract this service's own previous and candidate states, recompute model selection, and compare its source inventory, compatibility and receipts with its own identity. Decide what, if anything, needs changing. Connect each recommendation to a reason and a cost.
NET-001-F3 — Transfer: Without consulting the worked example's decision label, create submission.transfer.json containing all causes, evidence and the repair plan. Preserve the original input. If you create a proposed variant, use a separate filename and label newly constructed synthetic receipts as synthetic. Changing a service identifier or hash on an old receipt is not a fresh observation. Explain the version-installation decision separately from the evidence-sufficiency decision.
What actually ran, and what must you submit?
SDK selection and digest calculation in inspect_baseline.py are actual Python execution. inspect_project.py reads four explicit XML declarations only; it does not evaluate imports, Directory.Build.props, conditions or MSBuild execution. The resolver is likewise not a complete .NET host implementation. JSON build, test and diagnostic receipts are synthetic data for decision practice. Preserve that boundary even when every Python check is green.
The included dotnet/RefreshProbe.csproj is accompanied by a complete Program.cs, global.json and NuGet.Config. This console probe uses a framework reference and does not install the imaginary DisplayAdapter package. It therefore probes guard, async and scope behavior, rather than actually building the fictional service with that package. In a separate environment containing the exact SDK and required targeting packs, run from the dotnet folder:
dotnet --version
dotnet restore --configfile NuGet.Config
dotnet build --no-restore
dotnet run --no-build --no-restore
The last command executes assertions in the console program. This is not an xUnit project, and dotnet test is not a substitute. In the publisher environment, CoreCLR startup failed and no build ran. Successful output from those commands is not claimed for this package. If you execute them, retain the commands, observed versions, exit codes, context, exact source hashes and sanitized output in a separate ledger. Their scope is DISPOSABLE_CONSOLE_ONLY. Do not disguise actual output as a synthetic receipt or change the scope marker without defining a new evidence contract.
For the core exercise, submit the complete two-state matrix, evidence ledger, JSON response and causal explanation. baseline_digest and candidate_digest hash canonical sorted JSON; source_digest binds the declared synthetic inventory only, and tools_sha256 binds the Python model file. These are neither independent execution attestations nor hashes of all C# source files. The fixture's synthetic reviewer is also not a person who approved your real service. No human service owner is supplied by this package.
Keep historical reproduction separate from current claims. Use 2026-09-12 to reproduce the example, and the actual date for a current decision. After 2026-10-18, or an earlier material version, policy or context change, retain REVIEW_REQUIRED until sources and evidence are refreshed. A valid answer must be reproducible from visible inputs. “The assistant said so” is not sufficient provenance.
Assessment: from a matrix to a defensible decision
NET-001-S1 — Boundary: Explain in one paragraph what this refresh establishes and what it does not. Separate SDK, runtime, TFM and language; use one appropriate non-success state with its cause; explain why the work does not replace the API lesson or the testing and hosting outcome.
NET-001-S2 — Application: Build the complete matrix and evidence ledger for baseline.json. Include all 17 critical dimensions: sdk_version, runtime_version, target_framework, csharp_language_version, support_channel, support_end, global_json_ref, package_target_compatibility, nullable_context, breaking_change_ref, compile_state, test_state, diagnostic_state, baseline_digest, candidate_digest, review_state and audit_event_id. Retain async, configuration, DI and review_owner fields in the full matrix as well. Reference every claim and state the decision's scope.
NET-001-S3 — Diagnosis: Explain sdk_pin_old.json without removing the newly installed SDK from its inventory. Compute the selected version, identify the invalidated field and consequence, and give a minimal repair. Explain which receipts must be regenerated after changing the pin because their context or digest binding changed. “It works on my machine” is insufficient evidence.
NET-001-S4 — Transfer: Build an independent matrix and response for the service already on net10.0. Compare its language pin and SDK band with source requirements and the support snapshot; distinguish required from optional changes; reassess every receipt. Your reasoning must come from the second service, not the first service's versions or verdict. Include a repair plan, stop condition and future review trigger.
A sufficient answer meets five dimensions together: correct boundary, exact binding, preserved negative evidence, a bounded decision and independent transfer. Correct codes accompanied by incorrect reasoning or unrelated pointers are insufficient. Repair an insufficient dimension with its relevant fixture; a high average cannot erase it. For discussion, identify the shortcut most likely to create false confidence in your team and the smallest observation that would expose it. Use a synthetic or sanitized example only. The goal is a decision another reader can reconstruct, including the reason you declined to claim more.
Sources, dates and claim boundaries
Official sources for this edition were checked on 2026-09-12, with review due 2026-10-18. .NET releases and support, the .NET 10 overview, C# 14 and the breaking-change catalog are the four primary anchors. Ten additional official references for mechanisms explained in the lesson are linked in the text and recorded in resources/references/sources.json. Patch numbers and “current stable” wording are bound to that date.
Read three kinds of statement separately. Source fact: the platform source establishes global.json behavior, null handling and support dates. Case inference: the supplied synthetic inventory and public expectations determine which changes apply to this scenario. Exercise design: ledger fields, strict warning settings, the Guest expectation, decision vocabulary and conjunctive evidence requirements are educational choices. An official link does not turn those choices into a Microsoft mandate.
Revisit dependent evidence when target versions, packages, configuration behavior, model source, environment or time changes. Do not silently overwrite an earlier snapshot; retain a new version and the reason for its differences. The lesson supplies bilingual text and practice, but invents neither an owner's experience nor human approval. After completing the assessment, the educational route continues to NET-002. The present lesson's result remains the bounded refresh ledger you can explain and reproduce.
Assessment
There is no answer key in this lesson pack; answer it yourself and mark honestly. "Needs review" sends the lesson to your review queue.
Assessment rubric
هر پنج بُعد لازماند؛ میانگین، شکست را حذف نمیکند. All five dimensions must be sufficient; averaging cannot erase a failure.
| بُعد / Dimension | کافی / Sufficient | ناکافی / Insufficient |
|---|---|---|
| مرز / Boundary | SDK، Runtime، TFM، زبان و دامنه جدا / Separates four version facts and execution scope | نصب را تأیید نوسازی میداند / Treats installation as verification |
| اتصال / Binding | ورودی، سیاست، قرارداد، زمینه و هشها دقیق / Exact input, policy, contracts, context and hashes | رسید کپیشده با هش ویرایششده / Relabels copied receipts |
| منفی / Negative | همهٔ علتهای نوعدار و مشاهدهٔ تست / All typed causes and observed test outcomes | PASS را جای مشاهده میگذارد / Substitutes PASS for observations |
| تصمیم / Decision | حکم محدود، ترمیم و محرک بازبینی / Bounded state, minimal repair and review trigger | ادعای build یا تولید بیشاهد / Unsupported build or production claim |
| انتقال / Transfer | از نیاز سرویس دوم دوباره نتیجه میگیرد / Recomputes from the second service's needs | طرح ارتقای اول را کپی میکند / Copies the first migration plan |
کد درست بدون استدلال کافی نیست. Correct issue codes without causal reasoning are insufficient. A Python resolver pass does not establish C# compilation or live runtime behavior. Human service-owner approval is not supplied.
References & freshness
Case studies
Lab files
Requires Python 3.10+, standard library only. Run in this folder:
python inspect_baseline.py fixtures/baseline.json
python inspect_project.py
python run_checks.py --inventory
python run_checks.py --template fixtures/regression_failed.json submission.json --as-of 2026-09-12
python run_checks.py --check fixtures/regression_failed.json submission.json
Between the last two commands, supply the decision, all typed causes, pointers, rationale, minimal repair and review trigger. STRUCTURE_PASS_SEMANTICS_UNREVIEWED checks shape and binding only. Existing output files are not overwritten.
baseline and sdk_pin_old are worked cases; regression_failed is guided; transfer_existing is independent. policy.json supplies all rules; contracts.json supplies expectations and snapshot sources; resources contains full tables, mappings, references and assessments. Produce your own transfer decision. Preserve proposed candidates and newly constructed synthetic receipts in separately named files.
Python actually executes only the bounded resolver and comparisons. The global.json input is already resolved; only disable and latestPatch for stable versions are implemented. inspect_project reads four explicit declarations, not evaluated MSBuild. Build, test and diagnostic fixture data are synthetic, not C# execution.
The dotnet folder contains a complete console project with assertions. With exact SDK 10.0.401 and required targeting packs, run there: dotnet restore --configfile NuGet.Config, then dotnet build --no-restore and dotnet run --no-build --no-restore. dotnet test does not replace this console harness. The project uses a framework reference and does not install the imaginary exercise package. Publisher execution is UNVERIFIED: CoreCLR startup failed and no build ran. Record your actual output with C# source hashes and context in a separate ledger; do not disguise it as a synthetic receipt. Rollback covers a disposable snapshot, not database effects.
The example date is 2026-09-12; review is due 2026-10-18. For current claims preserve the actual date and expired states. No human owner or real-service approval is supplied.