From 266a7659f200e8ea7670c43da719b342009744e0 Mon Sep 17 00:00:00 2001 From: "Steven T. Cramer" Date: Thu, 2 Jul 2026 16:47:08 +0700 Subject: [PATCH 1/2] =?UTF-8?q?docs(kanban):=20add=20task=20084=20?= =?UTF-8?q?=E2=80=94=20universal=20#region=20Purpose=20analyzer=20(TWPA000?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer design decision: universal rule, not a non-trivial heuristic — trivial files get a one-line Purpose instead of an exemption, so the analyzer is exact (no threshold, no misclassification, no suppression management). Includes assembly rename to convention-analyzers + single Directory.Build.props wiring, which absorbs 082 and flows enforcement into generated apps. Co-Authored-By: Claude Fable 5 --- ...wire-via-directorybuildprops-absorb-082.md | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md diff --git a/kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md b/kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md new file mode 100644 index 00000000..afd3f530 --- /dev/null +++ b/kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md @@ -0,0 +1,69 @@ +# Convention analyzer: require `#region Purpose` in every source file (rename assembly, wire via Directory.Build.props, absorb 082) + +## Description + +Enforcement backstop for the agent-context-regions convention (follow-up to +[[050-010-add-region-purpose-and-region-design-to-all-migrated-source-files]]), built on the +080 lesson: a convention nobody enforces decays (regions sat at 4/304 for a year). + +**Key design decision (maintainer, 2026-07-02): the rule is UNIVERSAL, not threshold-based.** +Every compiled `.cs` file requires `#region Purpose` — trivial files get a one-line region +("Assembly marker enabling typed assembly references.") instead of an exemption. Rationale: + +- A "non-trivial file" heuristic (member counts, line thresholds) misclassifies in both + directions and pushes complexity into the analyzer + suppressions. A universal rule is + **exact**: no threshold to tune, no judgment to encode, no escape hatches to manage. +- Even trivial files benefit — "why does this AssemblyMarker exist" is a real question a + one-line Purpose answers; a dead-code reference file gets "kept as reference for X". +- Cost is one 3-line insertion per trivial file (~140 files), paid once, mechanical. +- Generated code is excluded structurally (`GeneratedCodeAnalysisFlags.None`), not by judgment. + +`#region Design` is **not** analyzer-enforced: "has design decisions worth recording" cannot be +judged mechanically. Design stays governed by the AGENTS.md maintenance rule and review. + +## Diagnostics + +- **TWPA0004** — compiled, non-generated `.cs` file lacks a `#region Purpose` block. + Severity Warning (build-breaking under the repo's warnings-as-errors). + +## Architecture / wiring (this is the other half of the task) + +1. **Rename** `timewarp-architecture-contract-analyzers` → `timewarp-architecture-convention-analyzers` + (the assembly now hosts contract rules TWPA0002/0003 *and* repo-wide convention rules; the + "contract" name stops fitting). Update: csproj + folder, `.slnx`, test project reference, + `web-contracts.csproj` reference (superseded by step 2), AnalyzerReleases files. +2. **Wire once in `source/Directory.Build.props`** — `` with a condition excluding the analyzer/attributes projects + themselves (self-reference guard). Remove the now-redundant per-csproj reference in + web-contracts. Scope = `source/` only (tests deliberately excluded — a test's why is its name). +3. **This absorbs [[082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts]]**: + TWPA0002/0003 reach api/grpc/foundation contracts through the same wiring (inert in projects + without `AbstractValidator` usage). Close 082 into this task. +4. **Template effect:** generated `dotnet new timewarp-architecture` apps inherit both region and + nullability enforcement out of the box. + +## Recipe (080-proven: wire + reconcile in the same PR, tree never red) + +- [ ] Write `PurposeRegionAnalyzer` (TWPA0004): syntax-tree check for a `#region` directive whose + text is `Purpose`; skip generated code; register in AnalyzerReleases. +- [ ] Fixie tests: file with region = clean; without = flagged; generated file = clean; + `#region Purpose` nested/after-namespace = decide (recommend: anywhere in file counts — + placement is skill guidance, not analyzer scope). +- [ ] Rename assembly + rewire per Architecture above; full build to enumerate violations. +- [ ] Backfill one-line `#region Purpose` into every reported file (~140 trivial: assembly + markers, global-usings, the 8 deliberate 050-010 skips incl. dead-code reference files). + Mechanical fan-out or script; content must still be true, not filler. +- [ ] TWPA0002/0003 fallout in api/grpc/foundation contracts: fix same-axis (type + initializer + only), per 077/080 precedent. +- [ ] `dev build` green (0/0); all analyzer + sourcegen tests green. +- [ ] Close 082 as absorbed; update the `agent-context-regions` skill (timewarp-flow): replace + "skip trivial files" with "Purpose is universal — one line even for markers; Design only + where there are decisions"; sync skills. + +## Notes + +- Freshness remains out of scope — no tool can verify a region is *true*; that stays with the + AGENTS.md reconcile rule and PR review. This analyzer guarantees presence only. +- Consumers who want the softer stance can downgrade via + `dotnet_diagnostic.TWPA0004.severity = suggestion` in `.editorconfig` — document, don't build, + the escape hatch. From c3d3474f8af7679f7c7e77e1ec534b8124a0fa7a Mon Sep 17 00:00:00 2001 From: "Steven T. Cramer" Date: Thu, 2 Jul 2026 17:26:00 +0700 Subject: [PATCH 2/2] feat(084): universal #region Purpose analyzer (TWPA0004); convention-analyzers wired repo-wide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rule is universal by design (maintainer): every compiled, non-generated .cs file requires #region Purpose — trivial files get a one-line region instead of an exemption, so the analyzer needs no triviality heuristic. #region Design is deliberately not enforced (judgment, governed by AGENTS.md). - Assembly renamed timewarp-architecture-contract-analyzers -> timewarp-architecture-convention-analyzers; wired ONCE in source/Directory.Build.props (self-excluded, IsAspireProjectResource=false), replacing the per-csproj web-contracts reference. Absorbs task 082: TWPA0002/0003 now reach every source project — and generated apps inherit all three rules from the template. - Backfill to 304/304 coverage: 51 formulaic files scripted (markers, global-usings), 88 small files via 8-agent fan-out (one-line Purpose; Design only where genuine). - Broadened TWPA0003 caught a real one: sample-options.cs SampleOption = string.Empty with a NotEmpty() options validator -> = null!. - Analyzer defect found by the test framework's suppression pass: reporting at TextSpan(0,0) made the diagnostic unsuppressable by a leading #pragma. Fixed: anchor on the file's first token; trivia-only files exempt. Verified: dev build 0/0; analyzer tests 21/21; sourcegen 14/14; web-server integration 11 passed. Skill updated (universal Purpose) in timewarp-flow 25e288b and synced. Tasks 084 done, 082 closed as absorbed. Co-Authored-By: Claude Fable 5 --- AGENTS.md | 9 +- ...alyzer-to-api-grpc-foundation-contracts.md | 9 ++ ...wire-via-directorybuildprops-absorb-082.md | 39 ++++-- source/Directory.Build.props | 12 +- .../assembly-marker.cs | 4 + .../global-usings.cs | 4 + .../api-endpoint-attribute.cs | 10 ++ .../assembly-marker.cs | 4 + .../AnalyzerReleases.Shipped.md | 0 .../AnalyzerReleases.Unshipped.md | 1 + ...contract-nullability-validator-analyzer.cs | 0 .../global-usings.cs | 6 + .../purpose-region-analyzer.cs | 72 ++++++++++ ...-architecture-convention-analyzers.csproj} | 3 +- .../api-application/api-application-module.cs | 10 ++ .../api/api-application/assembly-marker.cs | 4 + .../api/api-application/global-usings.cs | 4 + .../api/api-contracts/assembly-marker.cs | 4 + .../weather-forecast/feature-annotations.cs | 4 + .../api/api-contracts/global-usings.cs | 4 + .../api/api-domain/assembly-marker.cs | 4 + .../api/api-domain/global-usings.cs | 4 + .../api/api-infrastructure/assembly-marker.cs | 4 + .../api/api-infrastructure/global-usings.cs | 4 + .../api/api-server/assembly-marker.cs | 4 + .../api-server/features/base/base-error.cs | 4 + .../features/base/base-exception.cs | 4 + .../api/api-server/global-usings.cs | 4 + .../aspire/aspire-app-host/constants.cs | 4 + .../aspire/aspire-app-host/global-usings.cs | 4 + .../aspire-service-defaults/global-usings.cs | 4 + .../grpc/grpc-application/assembly-marker.cs | 4 + .../grpc/grpc-application/global-usings.cs | 4 + .../grpc/grpc-contracts/assembly-marker.cs | 4 + .../features/hello/hello-request.cs | 4 + .../features/hello/hello-response.cs | 4 + .../features/hello/i-hello-service.cs | 4 + .../features/superhero/superhero-request.cs | 4 + .../features/superhero/superhero-response.cs | 4 + .../grpc/grpc-contracts/global-usings.cs | 4 + .../grpc/grpc-domain/assembly-marker.cs | 4 + .../grpc/grpc-domain/global-usings.cs | 4 + .../grpc-infrastructure/assembly-marker.cs | 4 + .../grpc/grpc-infrastructure/global-usings.cs | 4 + .../grpc/grpc-server/assembly-marker.cs | 4 + .../features/hello/hello-service.cs | 4 + .../grpc/grpc-server/global-usings.cs | 4 + .../grpc-server/services/greeter-service.cs | 4 + .../web/web-application/assembly-marker.cs | 4 + .../web/web-application/global-usings.cs | 4 + .../web/web-contracts/assembly-marker.cs | 4 + .../extensions/assembly-extensions.cs | 4 + .../features/admin/users/user-ids.cs | 4 + .../internals-visible-to-client-and-server.cs | 4 + .../todo-items/queries/get-todo-item-by-id.cs | 9 ++ .../todo-items/queries/search-todo-items.cs | 9 ++ .../web/web-contracts/global-usings.cs | 4 + .../web-contracts/types/signal-r-result.cs | 4 + .../web/web-contracts/web-contracts.csproj | 7 - .../web-domain/abstractions/i-invariants.cs | 4 + .../web-domain/aggregates/catalog/category.cs | 9 ++ .../web-domain/aggregates/catalog/product.cs | 4 + .../web/web-domain/assembly-marker.cs | 4 + .../web/web-domain/global-usings.cs | 4 + .../web/web-infrastructure/assembly-marker.cs | 4 + .../configuration/postgres-db-options.cs | 4 + .../web/web-infrastructure/global-usings.cs | 4 + .../persistence/postgres-db-context.cs | 11 ++ .../persistence/sql-db-context.cs | 9 ++ .../web-infrastructure-module.cs | 10 ++ .../web/web-server/assembly-marker.cs | 4 + .../configuration/sample-options.cs | 6 +- .../features/analytics/feature-annotations.cs | 4 + .../features/auth/feature-annotations.cs | 4 + .../auth/get-sign-in-token-endpoint.cs | 4 + .../features/hello/feature-annotations.cs | 4 + .../features/profile/feature-annotations.cs | 4 + .../features/profile/get-profile-endpoint.cs | 4 + .../web/web-server/global-usings.cs | 4 + .../web/web-spa/assembly-marker.cs | 4 + .../web/web-spa/components/base/edit-mode.cs | 4 + .../components/elements/HyperLink.razor.cs | 3 + .../interfaces/i-navigable-component.cs | 4 + .../components/interfaces/i-static-route.cs | 4 + .../components/pages/SideNavigation.razor.cs | 4 + .../pages/SideNavigationLink.razor.cs | 4 + .../container-apps/web/web-spa/constants.cs | 4 + .../account/pages/ChangePasswordPage.razor.cs | 4 + .../account/pages/LogoutPage.razor.cs | 4 + .../pages/login-page/LoginPage.razor.cs | 4 + .../admin/roles/pages/RolePage.razor.cs | 4 + .../admin/roles/role-state/role-state.cs | 4 + .../application/pages/HomePage.razor.cs | 4 + .../custom-requirements/module-requirement.cs | 4 + .../web-spa/features/base/i-base-action.cs | 4 + .../counter/pages/CounterPage.razor.cs | 4 + .../features/debugger/pages/TestPage.razor.cs | 4 + .../developer/components/user-claims-base.cs | 4 + .../developer/pages/AlertExamplePage.razor.cs | 4 + .../developer/pages/UserClaimsPage.razor.cs | 4 + .../event-stream-state/event-stream-state.cs | 4 + .../pages/EventStreamPage.razor.cs | 4 + .../superhero/pages/SuperheroPage.razor.cs | 4 + .../features/superhero/superhero-module.cs | 4 + .../superhero-state/superhero-state.cs | 4 + .../to-do/pages/TodoItemPage.razor.cs | 4 + .../to-do/pages/TodoItemsPage.razor.cs | 4 + .../web/web-spa/features/to-do/todo-state.cs | 10 ++ .../pages/WeatherForecastsPage.razor.cs | 4 + .../weather-forecast-module.cs | 4 + .../web/web-spa/global-suppressions.cs | 4 + .../web/web-spa/global-usings.cs | 4 + .../web-spa/java-script-interop-constants.cs | 4 + .../web/web-spa/pages/ProfilePage.razor.cs | 4 + .../web/web-spa/pages/SettingsPage.razor.cs | 4 + .../post-pipeline-notification.cs | 4 + .../pre-pipeline-notification.cs | 4 + source/container-apps/yarp/assembly-marker.cs | 4 + source/container-apps/yarp/global-usings.cs | 4 + .../abstractions/i-current-user-service.cs | 4 + .../abstractions/i-date-time-service.cs | 9 ++ .../foundation-application/assembly-marker.cs | 4 + .../foundation-application/global-usings.cs | 4 + .../foundation-contracts/assembly-marker.cs | 4 + .../foundation-contracts/base/base-message.cs | 4 + .../base/base-paged-request.cs | 4 + .../foundation-contracts/base/base-request.cs | 4 + .../base/base-response.cs | 4 + .../foundation-contracts/base/http-verb.cs | 4 + .../base/i-api-request.cs | 4 + .../base/i-base-message.cs | 4 + .../base/i-base-request.cs | 4 + .../base/i-query-string-route-provider.cs | 4 + .../configuration/service-names.cs | 9 ++ .../foundation-contracts/global-usings.cs | 4 + .../types/mock-response-factory.cs | 4 + .../foundation-domain/assembly-marker.cs | 4 + .../entities/base/base-entity.cs | 4 + .../entities/base/base-event.cs | 4 + .../foundation-domain/global-usings.cs | 4 + .../assembly-marker.cs | 4 + .../common-infrastructure-module.cs | 4 + .../global-usings.cs | 4 + .../foundation-server/assembly-marker.cs | 4 + .../foundation-server/global-usings.cs | 4 + .../foundation-server/i-aspnet-module.cs | 4 + .../foundation-server/i-aspnet-program.cs | 4 + .../timewarp-modules/assembly-marker.cs | 4 + .../timewarp-modules/global-usings.cs | 4 + source/libraries/timewarp-modules/i-module.cs | 4 + .../purpose-region-analyzer-tests.cs | 129 ++++++++++++++++++ ...mewarp-architecture-analyzers-tests.csproj | 2 +- timewarp-architecture.slnx | 2 +- 153 files changed, 878 insertions(+), 31 deletions(-) rename kanban/{to-do => done}/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md (80%) rename kanban/{to-do => done}/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md (62%) rename source/analyzers/{timewarp-architecture-contract-analyzers => timewarp-architecture-convention-analyzers}/AnalyzerReleases.Shipped.md (100%) rename source/analyzers/{timewarp-architecture-contract-analyzers => timewarp-architecture-convention-analyzers}/AnalyzerReleases.Unshipped.md (83%) rename source/analyzers/{timewarp-architecture-contract-analyzers => timewarp-architecture-convention-analyzers}/contract-nullability-validator-analyzer.cs (100%) rename source/analyzers/{timewarp-architecture-contract-analyzers => timewarp-architecture-convention-analyzers}/global-usings.cs (62%) create mode 100644 source/analyzers/timewarp-architecture-convention-analyzers/purpose-region-analyzer.cs rename source/analyzers/{timewarp-architecture-contract-analyzers/timewarp-architecture-contract-analyzers.csproj => timewarp-architecture-convention-analyzers/timewarp-architecture-convention-analyzers.csproj} (81%) create mode 100644 tests/analyzers/timewarp-architecture-analyzers-tests/purpose-region-analyzer-tests.cs diff --git a/AGENTS.md b/AGENTS.md index 672750ee..ecb48a3b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,13 +4,14 @@ Guidance for all coding agents working in this repository (included by CLAUDE.md ## Agent Context Regions — maintenance rule -Non-trivial source files carry embedded context regions (`#region Purpose`, `#region Design`, -optionally `#region Open Questions`). These are part of the code, not decoration: +Every source file carries a `#region Purpose` block (enforced at build time by **TWPA0004**); +files with design decisions also carry `#region Design`, and optionally `#region Open Questions`. +These are part of the code, not decoration: - **When you edit a file that has regions, reconcile them with your change before finishing.** A Design region describing the old approach is a bug you just introduced. -- **When you create a non-trivial source file, add `Purpose` and `Design` regions** at the top, - before the namespace. +- **When you create a source file, add `#region Purpose`** (one honest line minimum) at the top, + before the namespace — plus `Design` where there are genuine decisions to record. - **When you read an unanswered question in `#region Open Questions` that you can answer,** answer it (or implement the answer and remove the pair). diff --git a/kanban/to-do/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md b/kanban/done/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md similarity index 80% rename from kanban/to-do/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md rename to kanban/done/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md index 75f8d6b1..b16a0f8e 100644 --- a/kanban/to-do/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md +++ b/kanban/done/082-broaden-contract-nullability-analyzer-to-api-grpc-foundation-contracts.md @@ -1,5 +1,14 @@ # Broaden contract nullability analyzer to api / grpc / foundation contracts +> **CLOSED — ABSORBED BY +> [[084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082]] +> (2026-07-02).** The assembly (renamed `timewarp-architecture-convention-analyzers`) is now wired +> once via `source/Directory.Build.props`, reaching **every** project under `source/` — a superset +> of this task's scope. The broadened sweep found one real violation +> (`web-server/configuration/sample-options.cs` — `= string.Empty` + validated `NotEmpty()`), +> fixed same-axis; api/grpc/foundation contracts were clean. Stretch items (SetValidator +> composition-following, code-fix provider) remain unpicked — revive as their own tasks if wanted. + ## Description Task 080 shipped `ContractNullabilityValidatorAnalyzer` (TWPA0002: `string?` + `NotEmpty()`/ diff --git a/kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md b/kanban/done/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md similarity index 62% rename from kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md rename to kanban/done/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md index afd3f530..9b22a1ee 100644 --- a/kanban/to-do/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md +++ b/kanban/done/084-convention-analyzer-require-region-purpose-in-every-source-file-rename-assembly-wire-via-directorybuildprops-absorb-082.md @@ -44,21 +44,30 @@ judged mechanically. Design stays governed by the AGENTS.md maintenance rule and ## Recipe (080-proven: wire + reconcile in the same PR, tree never red) -- [ ] Write `PurposeRegionAnalyzer` (TWPA0004): syntax-tree check for a `#region` directive whose - text is `Purpose`; skip generated code; register in AnalyzerReleases. -- [ ] Fixie tests: file with region = clean; without = flagged; generated file = clean; - `#region Purpose` nested/after-namespace = decide (recommend: anywhere in file counts — - placement is skill guidance, not analyzer scope). -- [ ] Rename assembly + rewire per Architecture above; full build to enumerate violations. -- [ ] Backfill one-line `#region Purpose` into every reported file (~140 trivial: assembly - markers, global-usings, the 8 deliberate 050-010 skips incl. dead-code reference files). - Mechanical fan-out or script; content must still be true, not filler. -- [ ] TWPA0002/0003 fallout in api/grpc/foundation contracts: fix same-axis (type + initializer - only), per 077/080 precedent. -- [ ] `dev build` green (0/0); all analyzer + sourcegen tests green. -- [ ] Close 082 as absorbed; update the `agent-context-regions` skill (timewarp-flow): replace - "skip trivial files" with "Purpose is universal — one line even for markers; Design only - where there are decisions"; sync skills. +- [x] `PurposeRegionAnalyzer` (TWPA0004): syntax-tree action; region-name match; generated code + excluded via `GeneratedCodeAnalysisFlags.None`; registered in AnalyzerReleases. +- [x] Fixie tests (5): without = flagged; with = clean; **anywhere-in-file counts** (placement is + skill guidance); Design-only still flagged; generated clean. All 21 analyzer tests green. +- [x] Assembly renamed `timewarp-architecture-convention-analyzers`; wired once in + `source/Directory.Build.props` (self-excluded; `IsAspireProjectResource="false"` to keep the + Aspire AppHost from treating the analyzer ref as an app resource — ASPIRE004). +- [x] Backfill: 51 formulaic files scripted (assembly markers, global-usings, identical one-liners); + 88 small files via 8-agent fan-out (one-line Purpose, Design only where genuine — includes + the 050-010 skips: dead-code files now say *why they're kept*). **304/304 coverage.** +- [x] TWPA0002/0003 broadening caught **one real violation outside web-contracts**: + `web-server/configuration/sample-options.cs` `SampleOption = string.Empty` (+ `NotEmpty()` + via the options validator) → `= null!`. api/grpc/foundation contracts were clean. +- [x] `dev build` green (0/0); analyzer 21/21, sourcegen 14/14, web-server integration 11 passed. +- [x] 082 closed as absorbed; `agent-context-regions` skill updated (universal Purpose, no + triviality exemption, TWPA0004 noted) — flow commit `25e288b`, synced. + +## Result — analyzer defect found & fixed via the test framework's hidden suppression pass + +The testing framework prepends `#pragma warning disable TWPA0004` and verifies the diagnostic +disappears. The first implementation reported at `TextSpan(0,0)` — a position *before* any leading +pragma takes effect — making the diagnostic **unsuppressable** (a real defect, not a test +artifact). Fix: anchor on the file's **first token**; trivia-only files (fully commented out / +`#if false`) have no active code and are structurally exempt. ## Notes diff --git a/source/Directory.Build.props b/source/Directory.Build.props index 6b87517f..9685dcf3 100644 --- a/source/Directory.Build.props +++ b/source/Directory.Build.props @@ -35,5 +35,15 @@ - + + + + + + diff --git a/source/analyzers/timewarp-architecture-analyzers/assembly-marker.cs b/source/analyzers/timewarp-architecture-analyzers/assembly-marker.cs index f5b05dca..837743b2 100644 --- a/source/analyzers/timewarp-architecture-analyzers/assembly-marker.cs +++ b/source/analyzers/timewarp-architecture-analyzers/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Analyzers; /// diff --git a/source/analyzers/timewarp-architecture-analyzers/global-usings.cs b/source/analyzers/timewarp-architecture-analyzers/global-usings.cs index 408d23dd..864cd527 100644 --- a/source/analyzers/timewarp-architecture-analyzers/global-usings.cs +++ b/source/analyzers/timewarp-architecture-analyzers/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.CodeAnalysis; global using Microsoft.CodeAnalysis.CSharp; global using Microsoft.CodeAnalysis.CSharp.Syntax; diff --git a/source/analyzers/timewarp-architecture-attributes/api-endpoint-attribute.cs b/source/analyzers/timewarp-architecture-attributes/api-endpoint-attribute.cs index 47e66527..8d5d183e 100644 --- a/source/analyzers/timewarp-architecture-attributes/api-endpoint-attribute.cs +++ b/source/analyzers/timewarp-architecture-attributes/api-endpoint-attribute.cs @@ -1,3 +1,13 @@ +#region Purpose +// Marks a contract class for FastEndpoint source generation — the generator emits the endpoint class, so none is hand-written. +#endregion + +#region Design +// Lives in a small runtime-attributes assembly, separate from the analyzer, so contract projects +// reference plain attributes without taking a Roslyn dependency. +// EndpointType optionally overrides the generated endpoint's base class (default BaseFastEndpoint). +#endregion + namespace TimeWarp.Architecture.Attributes; [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] diff --git a/source/analyzers/timewarp-architecture-attributes/assembly-marker.cs b/source/analyzers/timewarp-architecture-attributes/assembly-marker.cs index 9361b9ad..6be8e1cb 100644 --- a/source/analyzers/timewarp-architecture-attributes/assembly-marker.cs +++ b/source/analyzers/timewarp-architecture-attributes/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Attributes; /// diff --git a/source/analyzers/timewarp-architecture-contract-analyzers/AnalyzerReleases.Shipped.md b/source/analyzers/timewarp-architecture-convention-analyzers/AnalyzerReleases.Shipped.md similarity index 100% rename from source/analyzers/timewarp-architecture-contract-analyzers/AnalyzerReleases.Shipped.md rename to source/analyzers/timewarp-architecture-convention-analyzers/AnalyzerReleases.Shipped.md diff --git a/source/analyzers/timewarp-architecture-contract-analyzers/AnalyzerReleases.Unshipped.md b/source/analyzers/timewarp-architecture-convention-analyzers/AnalyzerReleases.Unshipped.md similarity index 83% rename from source/analyzers/timewarp-architecture-contract-analyzers/AnalyzerReleases.Unshipped.md rename to source/analyzers/timewarp-architecture-convention-analyzers/AnalyzerReleases.Unshipped.md index 3b4c69eb..8e92cb94 100644 --- a/source/analyzers/timewarp-architecture-contract-analyzers/AnalyzerReleases.Unshipped.md +++ b/source/analyzers/timewarp-architecture-convention-analyzers/AnalyzerReleases.Unshipped.md @@ -7,3 +7,4 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- TWPA0002 | Design | Warning | ContractNullabilityValidatorAnalyzer: nullable property has a NotEmpty()/NotNull() presence rule TWPA0003 | Design | Warning | ContractNullabilityValidatorAnalyzer: required property has a fabricated empty-string default +TWPA0004 | Documentation | Warning | PurposeRegionAnalyzer: source file lacks a #region Purpose block diff --git a/source/analyzers/timewarp-architecture-contract-analyzers/contract-nullability-validator-analyzer.cs b/source/analyzers/timewarp-architecture-convention-analyzers/contract-nullability-validator-analyzer.cs similarity index 100% rename from source/analyzers/timewarp-architecture-contract-analyzers/contract-nullability-validator-analyzer.cs rename to source/analyzers/timewarp-architecture-convention-analyzers/contract-nullability-validator-analyzer.cs diff --git a/source/analyzers/timewarp-architecture-contract-analyzers/global-usings.cs b/source/analyzers/timewarp-architecture-convention-analyzers/global-usings.cs similarity index 62% rename from source/analyzers/timewarp-architecture-contract-analyzers/global-usings.cs rename to source/analyzers/timewarp-architecture-convention-analyzers/global-usings.cs index e686c673..e4db5171 100644 --- a/source/analyzers/timewarp-architecture-contract-analyzers/global-usings.cs +++ b/source/analyzers/timewarp-architecture-convention-analyzers/global-usings.cs @@ -1,6 +1,12 @@ +#region Purpose +// Global usings for the convention-analyzers assembly. +#endregion + global using Microsoft.CodeAnalysis; global using Microsoft.CodeAnalysis.CSharp; global using Microsoft.CodeAnalysis.CSharp.Syntax; global using Microsoft.CodeAnalysis.Diagnostics; +global using Microsoft.CodeAnalysis.Text; global using System.Collections.Immutable; +global using System.IO; global using System.Linq; diff --git a/source/analyzers/timewarp-architecture-convention-analyzers/purpose-region-analyzer.cs b/source/analyzers/timewarp-architecture-convention-analyzers/purpose-region-analyzer.cs new file mode 100644 index 00000000..f901a170 --- /dev/null +++ b/source/analyzers/timewarp-architecture-convention-analyzers/purpose-region-analyzer.cs @@ -0,0 +1,72 @@ +#region Purpose +// Enforces the agent-context-regions convention: every source file carries a #region Purpose block. +#endregion + +#region Design +// The rule is deliberately UNIVERSAL rather than "non-trivial files only": any triviality +// heuristic (member counts, line thresholds) misclassifies in both directions and pushes +// complexity into suppressions. Trivial files satisfy the rule with a one-line Purpose instead +// of an exemption, so the check needs no judgment. Generated code is excluded structurally via +// GeneratedCodeAnalysisFlags.None (auto-generated headers, *.g.cs), not by heuristic. +// A #region Design block is intentionally NOT enforced — "has decisions worth recording" cannot +// be judged mechanically; that half of the convention is governed by AGENTS.md and review. +// Placement anywhere in the file counts: position is skill guidance, not analyzer scope. +#endregion + +namespace TimeWarp.Architecture.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public class PurposeRegionAnalyzer : DiagnosticAnalyzer +{ + public const string DiagnosticId = "TWPA0004"; + + private static readonly DiagnosticDescriptor Rule = + new + ( + DiagnosticId, + title: "Source file lacks a #region Purpose block", + messageFormat: "File '{0}' has no '#region Purpose' block; add one (a single // line suffices) stating what the file is for", + category: "Documentation", + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: "Every source file embeds agent/human context in a '#region Purpose' block. Trivial files use a one-line Purpose rather than being exempt. See the agent-context-regions skill." + ); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterSyntaxTreeAction(AnalyzeTree); + } + + private static void AnalyzeTree(SyntaxTreeAnalysisContext context) + { + SyntaxNode root = context.Tree.GetRoot(context.CancellationToken); + + bool hasPurposeRegion = root + .DescendantNodes(descendIntoTrivia: true) + .OfType() + .Any(static region => RegionName(region) == "Purpose"); + + if (hasPurposeRegion) return; + + // Anchor on the first token (not position 0): a diagnostic located before a leading + // `#pragma warning disable` could never be suppressed by it. Trivia-only files (fully + // commented out / #if false) have no active code and are not flagged. + SyntaxToken firstToken = root.GetFirstToken(); + if (firstToken.RawKind == 0) return; + + string fileName = Path.GetFileName(context.Tree.FilePath); + context.ReportDiagnostic(Diagnostic.Create(Rule, firstToken.GetLocation(), fileName)); + } + + // "#region Purpose" -> "Purpose" (the name rides in the directive's trailing preprocessing message). + private static string RegionName(RegionDirectiveTriviaSyntax region) + { + string text = region.ToString(); + int keywordEnd = text.IndexOf("#region", System.StringComparison.Ordinal); + return keywordEnd < 0 ? string.Empty : text.Substring(keywordEnd + "#region".Length).Trim(); + } +} diff --git a/source/analyzers/timewarp-architecture-contract-analyzers/timewarp-architecture-contract-analyzers.csproj b/source/analyzers/timewarp-architecture-convention-analyzers/timewarp-architecture-convention-analyzers.csproj similarity index 81% rename from source/analyzers/timewarp-architecture-contract-analyzers/timewarp-architecture-contract-analyzers.csproj rename to source/analyzers/timewarp-architecture-convention-analyzers/timewarp-architecture-convention-analyzers.csproj index 90fc1e33..ba12a038 100644 --- a/source/analyzers/timewarp-architecture-contract-analyzers/timewarp-architecture-contract-analyzers.csproj +++ b/source/analyzers/timewarp-architecture-convention-analyzers/timewarp-architecture-convention-analyzers.csproj @@ -3,7 +3,8 @@ true true + safe to reference from every project — including contracts — without triggering the + FastEndpoint generator. Wired repo-wide via source/Directory.Build.props. --> diff --git a/source/container-apps/api/api-application/api-application-module.cs b/source/container-apps/api/api-application/api-application-module.cs index a98b9f93..cb064087 100644 --- a/source/container-apps/api/api-application/api-application-module.cs +++ b/source/container-apps/api/api-application/api-application-module.cs @@ -1,3 +1,13 @@ +#region Purpose +// IModule registration hook for the Api application layer's services. +#endregion + +#region Design +// ConfigureServices deliberately throws: the layer has no services to register, and the throw +// makes accidental composition loud instead of silently succeeding. Replace the throw with real +// registrations when the layer gains services. +#endregion + namespace TimeWarp.Architecture.Api.Application; public class ApiApplicationModule : IModule diff --git a/source/container-apps/api/api-application/assembly-marker.cs b/source/container-apps/api/api-application/assembly-marker.cs index c04adb60..e325a64e 100644 --- a/source/container-apps/api/api-application/assembly-marker.cs +++ b/source/container-apps/api/api-application/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Api.Application; /// diff --git a/source/container-apps/api/api-application/global-usings.cs b/source/container-apps/api/api-application/global-usings.cs index 6b9611f8..a433cbe4 100644 --- a/source/container-apps/api/api-application/global-usings.cs +++ b/source/container-apps/api/api-application/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using OneOf; diff --git a/source/container-apps/api/api-contracts/assembly-marker.cs b/source/container-apps/api/api-contracts/assembly-marker.cs index 5baa15b4..282afa81 100644 --- a/source/container-apps/api/api-contracts/assembly-marker.cs +++ b/source/container-apps/api/api-contracts/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Api.Contracts; /// diff --git a/source/container-apps/api/api-contracts/features/weather-forecast/feature-annotations.cs b/source/container-apps/api/api-contracts/features/weather-forecast/feature-annotations.cs index 12e3ac82..b51927a9 100644 --- a/source/container-apps/api/api-contracts/features/weather-forecast/feature-annotations.cs +++ b/source/container-apps/api/api-contracts/features/weather-forecast/feature-annotations.cs @@ -1,3 +1,7 @@ +#region Purpose +// Per-feature constants slot: FeatureGroup names the WeatherForecast group used to categorize its endpoints in API metadata. +#endregion + namespace TimeWarp.Architecture.Features.WeatherForecasts; public static class FeatureAnnotations diff --git a/source/container-apps/api/api-contracts/global-usings.cs b/source/container-apps/api/api-contracts/global-usings.cs index d8497e24..edce0155 100644 --- a/source/container-apps/api/api-contracts/global-usings.cs +++ b/source/container-apps/api/api-contracts/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Ardalis.GuardClauses; global using FluentValidation; global using OneOf; diff --git a/source/container-apps/api/api-domain/assembly-marker.cs b/source/container-apps/api/api-domain/assembly-marker.cs index 7636084e..97303dae 100644 --- a/source/container-apps/api/api-domain/assembly-marker.cs +++ b/source/container-apps/api/api-domain/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Api.Domain; /// diff --git a/source/container-apps/api/api-domain/global-usings.cs b/source/container-apps/api/api-domain/global-usings.cs index d2434d2b..9ae16c42 100644 --- a/source/container-apps/api/api-domain/global-usings.cs +++ b/source/container-apps/api/api-domain/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + // global using xyz; diff --git a/source/container-apps/api/api-infrastructure/assembly-marker.cs b/source/container-apps/api/api-infrastructure/assembly-marker.cs index d3e55111..e59d1b6f 100644 --- a/source/container-apps/api/api-infrastructure/assembly-marker.cs +++ b/source/container-apps/api/api-infrastructure/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Api.Infrastructure; /// diff --git a/source/container-apps/api/api-infrastructure/global-usings.cs b/source/container-apps/api/api-infrastructure/global-usings.cs index d2434d2b..9ae16c42 100644 --- a/source/container-apps/api/api-infrastructure/global-usings.cs +++ b/source/container-apps/api/api-infrastructure/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + // global using xyz; diff --git a/source/container-apps/api/api-server/assembly-marker.cs b/source/container-apps/api/api-server/assembly-marker.cs index 409aef6f..db941d68 100644 --- a/source/container-apps/api/api-server/assembly-marker.cs +++ b/source/container-apps/api/api-server/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Api.Server; /// diff --git a/source/container-apps/api/api-server/features/base/base-error.cs b/source/container-apps/api/api-server/features/base/base-error.cs index d71a1411..2c405a61 100644 --- a/source/container-apps/api/api-server/features/base/base-error.cs +++ b/source/container-apps/api/api-server/features/base/base-error.cs @@ -1,3 +1,7 @@ +#region Purpose +// Base message-bearing error type for Api server features; a convention anchor with no derived types in the template. +#endregion + namespace TimeWarp.Architecture.Features; public class BaseError diff --git a/source/container-apps/api/api-server/features/base/base-exception.cs b/source/container-apps/api/api-server/features/base/base-exception.cs index 1444612c..05b026e8 100644 --- a/source/container-apps/api/api-server/features/base/base-exception.cs +++ b/source/container-apps/api/api-server/features/base/base-exception.cs @@ -1,3 +1,7 @@ +#region Purpose +// Base exception type for Api server feature failures; a convention anchor with no derived types in the template. +#endregion + namespace TimeWarp.Architecture.Features; public class BaseException : Exception diff --git a/source/container-apps/api/api-server/global-usings.cs b/source/container-apps/api/api-server/global-usings.cs index 6e7fbf71..9b7b3f97 100644 --- a/source/container-apps/api/api-server/global-usings.cs +++ b/source/container-apps/api/api-server/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using FastEndpoints; global using FluentValidation; global using Microsoft.AspNetCore.Mvc; diff --git a/source/container-apps/aspire/aspire-app-host/constants.cs b/source/container-apps/aspire/aspire-app-host/constants.cs index 47462339..78f44300 100644 --- a/source/container-apps/aspire/aspire-app-host/constants.cs +++ b/source/container-apps/aspire/aspire-app-host/constants.cs @@ -1,3 +1,7 @@ +#region Purpose +// Aspire AppHost resource names, pinned to the ServiceNames the apps use for service discovery. +#endregion + namespace TimeWarp.Architecture.Aspire; internal class Constants diff --git a/source/container-apps/aspire/aspire-app-host/global-usings.cs b/source/container-apps/aspire/aspire-app-host/global-usings.cs index 79067e23..6a46cf79 100644 --- a/source/container-apps/aspire/aspire-app-host/global-usings.cs +++ b/source/container-apps/aspire/aspire-app-host/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Aspire.Customization.AppHost; global using Aspire.Hosting.Yarp; global using Aspire.Hosting.Yarp.Transforms; diff --git a/source/container-apps/aspire/aspire-service-defaults/global-usings.cs b/source/container-apps/aspire/aspire-service-defaults/global-usings.cs index 2de17d97..d7cda22c 100644 --- a/source/container-apps/aspire/aspire-service-defaults/global-usings.cs +++ b/source/container-apps/aspire/aspire-service-defaults/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.AspNetCore.Builder; global using Microsoft.AspNetCore.Diagnostics.HealthChecks; global using Microsoft.Extensions.DependencyInjection; diff --git a/source/container-apps/grpc/grpc-application/assembly-marker.cs b/source/container-apps/grpc/grpc-application/assembly-marker.cs index 05400051..41d70dcf 100644 --- a/source/container-apps/grpc/grpc-application/assembly-marker.cs +++ b/source/container-apps/grpc/grpc-application/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Grpc.Application; /// diff --git a/source/container-apps/grpc/grpc-application/global-usings.cs b/source/container-apps/grpc/grpc-application/global-usings.cs index e7cf3247..d5896074 100644 --- a/source/container-apps/grpc/grpc-application/global-usings.cs +++ b/source/container-apps/grpc/grpc-application/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using TimeWarp.Mediator; diff --git a/source/container-apps/grpc/grpc-contracts/assembly-marker.cs b/source/container-apps/grpc/grpc-contracts/assembly-marker.cs index 3b30cede..2bccb8cf 100644 --- a/source/container-apps/grpc/grpc-contracts/assembly-marker.cs +++ b/source/container-apps/grpc/grpc-contracts/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Grpc.Contracts; /// diff --git a/source/container-apps/grpc/grpc-contracts/features/hello/hello-request.cs b/source/container-apps/grpc/grpc-contracts/features/hello/hello-request.cs index c8b46bbe..6d2d0b8e 100644 --- a/source/container-apps/grpc/grpc-contracts/features/hello/hello-request.cs +++ b/source/container-apps/grpc/grpc-contracts/features/hello/hello-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-first gRPC request for the Hello sample; DataContract member ordering defines the wire shape in place of a .proto file. +#endregion + namespace TimeWarp.Architecture.Features.Hellos; [DataContract] diff --git a/source/container-apps/grpc/grpc-contracts/features/hello/hello-response.cs b/source/container-apps/grpc/grpc-contracts/features/hello/hello-response.cs index 669987a4..bd497c96 100644 --- a/source/container-apps/grpc/grpc-contracts/features/hello/hello-response.cs +++ b/source/container-apps/grpc/grpc-contracts/features/hello/hello-response.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-first gRPC response carrying the Hello sample's greeting back to the caller. +#endregion + namespace TimeWarp.Architecture.Features.Hellos; [DataContract] diff --git a/source/container-apps/grpc/grpc-contracts/features/hello/i-hello-service.cs b/source/container-apps/grpc/grpc-contracts/features/hello/i-hello-service.cs index 2ece8f13..4779da19 100644 --- a/source/container-apps/grpc/grpc-contracts/features/hello/i-hello-service.cs +++ b/source/container-apps/grpc/grpc-contracts/features/hello/i-hello-service.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-first gRPC service contract for the Hello sample; server and clients bind to this shared interface, so no .proto file exists. +#endregion + namespace TimeWarp.Architecture.Features.Hellos; [ServiceContract] diff --git a/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-request.cs b/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-request.cs index d7490c7a..4f542e0b 100644 --- a/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-request.cs +++ b/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-first gRPC request asking the demo superhero service for a batch of fabricated heroes. +#endregion + namespace TimeWarp.Architecture.Features.Superheros; [ProtoContract] diff --git a/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-response.cs b/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-response.cs index 2f5c51ea..732f1184 100644 --- a/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-response.cs +++ b/source/container-apps/grpc/grpc-contracts/features/superhero/superhero-response.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-first gRPC response carrying the fabricated superhero batch back to the client. +#endregion + namespace TimeWarp.Architecture.Features.Superheros; [ProtoContract] diff --git a/source/container-apps/grpc/grpc-contracts/global-usings.cs b/source/container-apps/grpc/grpc-contracts/global-usings.cs index 28085f93..4fef0e0b 100644 --- a/source/container-apps/grpc/grpc-contracts/global-usings.cs +++ b/source/container-apps/grpc/grpc-contracts/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Grpc.Core; global using ProtoBuf; global using ProtoBuf.Grpc; diff --git a/source/container-apps/grpc/grpc-domain/assembly-marker.cs b/source/container-apps/grpc/grpc-domain/assembly-marker.cs index 342721c2..596f8f75 100644 --- a/source/container-apps/grpc/grpc-domain/assembly-marker.cs +++ b/source/container-apps/grpc/grpc-domain/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Grpc.Domain; /// diff --git a/source/container-apps/grpc/grpc-domain/global-usings.cs b/source/container-apps/grpc/grpc-domain/global-usings.cs index d2434d2b..9ae16c42 100644 --- a/source/container-apps/grpc/grpc-domain/global-usings.cs +++ b/source/container-apps/grpc/grpc-domain/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + // global using xyz; diff --git a/source/container-apps/grpc/grpc-infrastructure/assembly-marker.cs b/source/container-apps/grpc/grpc-infrastructure/assembly-marker.cs index 11a5a1a5..b92ba066 100644 --- a/source/container-apps/grpc/grpc-infrastructure/assembly-marker.cs +++ b/source/container-apps/grpc/grpc-infrastructure/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Grpc.Infrastructure; /// diff --git a/source/container-apps/grpc/grpc-infrastructure/global-usings.cs b/source/container-apps/grpc/grpc-infrastructure/global-usings.cs index d2434d2b..9ae16c42 100644 --- a/source/container-apps/grpc/grpc-infrastructure/global-usings.cs +++ b/source/container-apps/grpc/grpc-infrastructure/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + // global using xyz; diff --git a/source/container-apps/grpc/grpc-server/assembly-marker.cs b/source/container-apps/grpc/grpc-server/assembly-marker.cs index 8899a877..80562ee5 100644 --- a/source/container-apps/grpc/grpc-server/assembly-marker.cs +++ b/source/container-apps/grpc/grpc-server/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Grpc.Server; /// diff --git a/source/container-apps/grpc/grpc-server/features/hello/hello-service.cs b/source/container-apps/grpc/grpc-server/features/hello/hello-service.cs index 8212c15c..714ec381 100644 --- a/source/container-apps/grpc/grpc-server/features/hello/hello-service.cs +++ b/source/container-apps/grpc/grpc-server/features/hello/hello-service.cs @@ -1,3 +1,7 @@ +#region Purpose +// Server implementation of the code-first IHelloService gRPC contract — the sample showing how Grpc.Server fulfills contracts defined in Grpc.Contracts. +#endregion + namespace TimeWarp.Architecture.Features.Hellos; public class HelloService : IHelloService diff --git a/source/container-apps/grpc/grpc-server/global-usings.cs b/source/container-apps/grpc/grpc-server/global-usings.cs index 620079c6..dbc86311 100644 --- a/source/container-apps/grpc/grpc-server/global-usings.cs +++ b/source/container-apps/grpc/grpc-server/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Grpc.Core; global using ProtoBuf.Grpc; global using ProtoBuf.Grpc.Server; diff --git a/source/container-apps/grpc/grpc-server/services/greeter-service.cs b/source/container-apps/grpc/grpc-server/services/greeter-service.cs index 34d3ff2e..e6b3b23d 100644 --- a/source/container-apps/grpc/grpc-server/services/greeter-service.cs +++ b/source/container-apps/grpc/grpc-server/services/greeter-service.cs @@ -1,3 +1,7 @@ +#region Purpose +// Proto-first gRPC sample: implements the .proto-generated Greeter service, contrasting with the code-first HelloService. +#endregion + namespace TimeWarp.Architecture.GrpcServer.Services; public class GreeterService : Greeter.GreeterBase diff --git a/source/container-apps/web/web-application/assembly-marker.cs b/source/container-apps/web/web-application/assembly-marker.cs index 8c858621..ea7ecf0a 100644 --- a/source/container-apps/web/web-application/assembly-marker.cs +++ b/source/container-apps/web/web-application/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Application; /// diff --git a/source/container-apps/web/web-application/global-usings.cs b/source/container-apps/web/web-application/global-usings.cs index d4530ea8..2baad417 100644 --- a/source/container-apps/web/web-application/global-usings.cs +++ b/source/container-apps/web/web-application/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.Extensions.Logging; global using OneOf; global using OneOf.Types; diff --git a/source/container-apps/web/web-contracts/assembly-marker.cs b/source/container-apps/web/web-contracts/assembly-marker.cs index 6c08c37a..162efa7c 100644 --- a/source/container-apps/web/web-contracts/assembly-marker.cs +++ b/source/container-apps/web/web-contracts/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Contracts; /// diff --git a/source/container-apps/web/web-contracts/extensions/assembly-extensions.cs b/source/container-apps/web/web-contracts/extensions/assembly-extensions.cs index e8342dad..eb27d36e 100644 --- a/source/container-apps/web/web-contracts/extensions/assembly-extensions.cs +++ b/source/container-apps/web/web-contracts/extensions/assembly-extensions.cs @@ -1,3 +1,7 @@ +#region Purpose +// Reflection helper for discovering types in an assembly by attribute, used to register contracts without hand-maintained lists. +#endregion + namespace TimeWarp.Architecture.Extensions; public static class AssemblyExtensions diff --git a/source/container-apps/web/web-contracts/features/admin/users/user-ids.cs b/source/container-apps/web/web-contracts/features/admin/users/user-ids.cs index c611677b..18fe0b72 100644 --- a/source/container-apps/web/web-contracts/features/admin/users/user-ids.cs +++ b/source/container-apps/web/web-contracts/features/admin/users/user-ids.cs @@ -1,3 +1,7 @@ +#region Purpose +// Well-known user ids so seed data, mocks, and contract handlers all reference the same sample identities. +#endregion + namespace TimeWarp.Architecture.Services; public static class UserIds diff --git a/source/container-apps/web/web-contracts/features/infrastructure/internals-visible-to-client-and-server.cs b/source/container-apps/web/web-contracts/features/infrastructure/internals-visible-to-client-and-server.cs index 540bd4c7..baffcccc 100644 --- a/source/container-apps/web/web-contracts/features/infrastructure/internals-visible-to-client-and-server.cs +++ b/source/container-apps/web/web-contracts/features/infrastructure/internals-visible-to-client-and-server.cs @@ -1,3 +1,7 @@ +#region Purpose +// Grants Web.Contracts internal visibility to the SPA, the server, and their integration tests so contract internals stay inside the web boundary. +#endregion + [assembly: InternalsVisibleTo("Web.Spa")] [assembly: InternalsVisibleTo("Web.Spa.Integration.Tests")] [assembly: InternalsVisibleTo("Web.Server")] diff --git a/source/container-apps/web/web-contracts/features/todo-items/queries/get-todo-item-by-id.cs b/source/container-apps/web/web-contracts/features/todo-items/queries/get-todo-item-by-id.cs index 99e1a6ed..0def05e1 100644 --- a/source/container-apps/web/web-contracts/features/todo-items/queries/get-todo-item-by-id.cs +++ b/source/container-apps/web/web-contracts/features/todo-items/queries/get-todo-item-by-id.cs @@ -1,3 +1,12 @@ +#region Purpose +// Endpoint-centric wrapper for the get-todo-item-by-id query contract. +#endregion + +#region Design +// Deliberately empty stub: it reserves the wrapper name so the nested Query, Response, and Validator +// can be added when the endpoint is built. See CreateTodoItem for the completed shape. +#endregion + namespace TimeWarp.Architecture.Features.TodoItems; public sealed partial class GetTodoItemById diff --git a/source/container-apps/web/web-contracts/features/todo-items/queries/search-todo-items.cs b/source/container-apps/web/web-contracts/features/todo-items/queries/search-todo-items.cs index 125c566e..c85ebbcc 100644 --- a/source/container-apps/web/web-contracts/features/todo-items/queries/search-todo-items.cs +++ b/source/container-apps/web/web-contracts/features/todo-items/queries/search-todo-items.cs @@ -1,3 +1,12 @@ +#region Purpose +// Endpoint-centric wrapper for the search-todo-items query contract. +#endregion + +#region Design +// Deliberately empty stub: it reserves the wrapper name so the nested Query, Response, and Validator +// can be added when the endpoint is built. See CreateTodoItem for the completed shape. +#endregion + namespace TimeWarp.Architecture.Features.TodoItems; public sealed partial class SearchTodoItems diff --git a/source/container-apps/web/web-contracts/global-usings.cs b/source/container-apps/web/web-contracts/global-usings.cs index b89726ff..8b5e580c 100644 --- a/source/container-apps/web/web-contracts/global-usings.cs +++ b/source/container-apps/web/web-contracts/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Ardalis.GuardClauses; global using FluentValidation; global using OneOf; diff --git a/source/container-apps/web/web-contracts/types/signal-r-result.cs b/source/container-apps/web/web-contracts/types/signal-r-result.cs index 50bcf685..40af45eb 100644 --- a/source/container-apps/web/web-contracts/types/signal-r-result.cs +++ b/source/container-apps/web/web-contracts/types/signal-r-result.cs @@ -1,3 +1,7 @@ +#region Purpose +// Serializable success/failure envelope for SignalR hub method returns, because OneOf discriminated unions do not survive SignalR serialization. +#endregion + namespace TimeWarp.Architecture.Types; public sealed class SignalrResult diff --git a/source/container-apps/web/web-contracts/web-contracts.csproj b/source/container-apps/web/web-contracts/web-contracts.csproj index 470a59f0..52dfa978 100644 --- a/source/container-apps/web/web-contracts/web-contracts.csproj +++ b/source/container-apps/web/web-contracts/web-contracts.csproj @@ -32,13 +32,6 @@ Condition="'$(UseFoundationPackages)' != 'true'" /> - - - - - diff --git a/source/container-apps/web/web-domain/abstractions/i-invariants.cs b/source/container-apps/web/web-domain/abstractions/i-invariants.cs index aa41b145..87102686 100644 --- a/source/container-apps/web/web-domain/abstractions/i-invariants.cs +++ b/source/container-apps/web/web-domain/abstractions/i-invariants.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker interface tagging domain invariant rule sets (the nested AbstractValidator classes on entities) so they are identifiable as invariants rather than request validators. +#endregion + namespace TimeWarp.Architecture.Abstractions; /// diff --git a/source/container-apps/web/web-domain/aggregates/catalog/category.cs b/source/container-apps/web/web-domain/aggregates/catalog/category.cs index 2689f156..42c7ecf1 100644 --- a/source/container-apps/web/web-domain/aggregates/catalog/category.cs +++ b/source/container-apps/web/web-domain/aggregates/catalog/category.cs @@ -1,3 +1,12 @@ +#region Purpose +// Commented-out Category entity sketch (nopCommerce-derived) kept as reference for a future catalog aggregate. +#endregion + +#region Design +// Beyond the property list, the sketch records the intended pattern for entity invariants: +// a nested Invariants : AbstractValidator class tagged with IInvariants. +#endregion + //namespace TimeWarp.Architecture.Entities.Catalog; //using FluentValidation; diff --git a/source/container-apps/web/web-domain/aggregates/catalog/product.cs b/source/container-apps/web/web-domain/aggregates/catalog/product.cs index 56cdbe0b..ff4e848a 100644 --- a/source/container-apps/web/web-domain/aggregates/catalog/product.cs +++ b/source/container-apps/web/web-domain/aggregates/catalog/product.cs @@ -1,3 +1,7 @@ +#region Purpose +// Commented-out Product entity sketch (nopCommerce-derived) kept as reference for a future catalog aggregate. +#endregion + //namespace TimeWarp.Architecture.Entities.Catalog; //using System; diff --git a/source/container-apps/web/web-domain/assembly-marker.cs b/source/container-apps/web/web-domain/assembly-marker.cs index 717e1390..c6c6d596 100644 --- a/source/container-apps/web/web-domain/assembly-marker.cs +++ b/source/container-apps/web/web-domain/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Domain; /// diff --git a/source/container-apps/web/web-domain/global-usings.cs b/source/container-apps/web/web-domain/global-usings.cs index 7bc18aca..e91d3dba 100644 --- a/source/container-apps/web/web-domain/global-usings.cs +++ b/source/container-apps/web/web-domain/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using TimeWarp.Foundation.Entities; diff --git a/source/container-apps/web/web-infrastructure/assembly-marker.cs b/source/container-apps/web/web-infrastructure/assembly-marker.cs index 4ee22a47..acb47ff1 100644 --- a/source/container-apps/web/web-infrastructure/assembly-marker.cs +++ b/source/container-apps/web/web-infrastructure/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Infrastructure; /// diff --git a/source/container-apps/web/web-infrastructure/configuration/postgres-db-options.cs b/source/container-apps/web/web-infrastructure/configuration/postgres-db-options.cs index 96a9f0ff..1844ae47 100644 --- a/source/container-apps/web/web-infrastructure/configuration/postgres-db-options.cs +++ b/source/container-apps/web/web-infrastructure/configuration/postgres-db-options.cs @@ -1,3 +1,7 @@ +#region Purpose +// Binds the PostgreSQL connection string from configuration for PostgresDbModule and the Postgres environment check. +#endregion + namespace TimeWarp.Architecture.Configuration; public sealed partial class PostgresDbOptions diff --git a/source/container-apps/web/web-infrastructure/global-usings.cs b/source/container-apps/web/web-infrastructure/global-usings.cs index 2077128a..33697c5f 100644 --- a/source/container-apps/web/web-infrastructure/global-usings.cs +++ b/source/container-apps/web/web-infrastructure/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using FluentValidation; global using Microsoft.EntityFrameworkCore; global using Microsoft.EntityFrameworkCore.Metadata.Builders; diff --git a/source/container-apps/web/web-infrastructure/persistence/postgres-db-context.cs b/source/container-apps/web/web-infrastructure/persistence/postgres-db-context.cs index bf574c63..767a0f94 100644 --- a/source/container-apps/web/web-infrastructure/persistence/postgres-db-context.cs +++ b/source/container-apps/web/web-infrastructure/persistence/postgres-db-context.cs @@ -1,3 +1,14 @@ +#region Purpose +// EF Core context for the PostgreSQL store; the seam where template consumers add their entity sets. +#endregion + +#region Design +// Deliberately entity-free: the template ships the Postgres plumbing (module, health and +// environment checks, schema-creation hosted service) and leaves the model to the consumer. +// Connection setup lives in PostgresDbModule.ConfigurePostgresDb, not OnConfiguring, so the +// context stays configuration-agnostic. +#endregion + namespace TimeWarp.Architecture.Persistence; public sealed partial class PostgresDbContext : DbContext { } diff --git a/source/container-apps/web/web-infrastructure/persistence/sql-db-context.cs b/source/container-apps/web/web-infrastructure/persistence/sql-db-context.cs index b8f796b7..cc04a79e 100644 --- a/source/container-apps/web/web-infrastructure/persistence/sql-db-context.cs +++ b/source/container-apps/web/web-infrastructure/persistence/sql-db-context.cs @@ -1,3 +1,12 @@ +#region Purpose +// Placeholder EF Core context marking the seam for a SQL Server storage option alongside Postgres. +#endregion + +#region Design +// Unregistered dead code kept as reference: its only mention is a commented-out +// AddDbContextCheck line in Web.Server's Program, showing where SQL Server wiring would go. +#endregion + namespace TimeWarp.Architecture.Data; public class SqlDbContext : DbContext { } diff --git a/source/container-apps/web/web-infrastructure/web-infrastructure-module.cs b/source/container-apps/web/web-infrastructure/web-infrastructure-module.cs index 258c0e9e..71b3ef9c 100644 --- a/source/container-apps/web/web-infrastructure/web-infrastructure-module.cs +++ b/source/container-apps/web/web-infrastructure/web-infrastructure-module.cs @@ -1,3 +1,13 @@ +#region Purpose +// DI registration hook for the Web.Infrastructure assembly, called unconditionally from Web.Server's Program. +#endregion + +#region Design +// Empty by design: Postgres wiring lives in Web.Server's PostgresDbModule behind the +// `postgres` feature flag, so this module is the seam for flag-independent infrastructure +// services only. +#endregion + namespace TimeWarp.Architecture.Web.Infrastructure; public class WebInfrastructureModule : IModule diff --git a/source/container-apps/web/web-server/assembly-marker.cs b/source/container-apps/web/web-server/assembly-marker.cs index 4a93bc36..2560eeda 100644 --- a/source/container-apps/web/web-server/assembly-marker.cs +++ b/source/container-apps/web/web-server/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Server; /// diff --git a/source/container-apps/web/web-server/configuration/sample-options.cs b/source/container-apps/web/web-server/configuration/sample-options.cs index 65a455ec..879f00e7 100644 --- a/source/container-apps/web/web-server/configuration/sample-options.cs +++ b/source/container-apps/web/web-server/configuration/sample-options.cs @@ -1,6 +1,10 @@ +#region Purpose +// Example options class demonstrating the AddFluentValidatedOptions binding-plus-validation pattern. +#endregion + namespace TimeWarp.Architecture.Configuration; public class SampleOptions { - public string SampleOption { get; set; } = string.Empty; + public string SampleOption { get; set; } = null!; } diff --git a/source/container-apps/web/web-server/features/analytics/feature-annotations.cs b/source/container-apps/web/web-server/features/analytics/feature-annotations.cs index 16616410..2a401150 100644 --- a/source/container-apps/web/web-server/features/analytics/feature-annotations.cs +++ b/source/container-apps/web/web-server/features/analytics/feature-annotations.cs @@ -1,3 +1,7 @@ +#region Purpose +// Names the Analytics feature group as a constant for tagging its endpoints in API metadata; no code consumes it. +#endregion + namespace TimeWarp.Architecture.Features.Analytics; public static class FeatureAnnotations diff --git a/source/container-apps/web/web-server/features/auth/feature-annotations.cs b/source/container-apps/web/web-server/features/auth/feature-annotations.cs index 43f6465c..803c5446 100644 --- a/source/container-apps/web/web-server/features/auth/feature-annotations.cs +++ b/source/container-apps/web/web-server/features/auth/feature-annotations.cs @@ -1,3 +1,7 @@ +#region Purpose +// Names the Auth feature group as a constant for tagging its endpoints in API metadata; no code consumes it. +#endregion + namespace TimeWarp.Architecture.Features.Auth; public static class FeatureAnnotations diff --git a/source/container-apps/web/web-server/features/auth/get-sign-in-token-endpoint.cs b/source/container-apps/web/web-server/features/auth/get-sign-in-token-endpoint.cs index 3e0bfeae..abba423b 100644 --- a/source/container-apps/web/web-server/features/auth/get-sign-in-token-endpoint.cs +++ b/source/container-apps/web/web-server/features/auth/get-sign-in-token-endpoint.cs @@ -1,3 +1,7 @@ +#region Purpose +// HTTP GET adapter that exchanges a user id for a Passwordless.dev sign-in token via the mediator pipeline. +#endregion + namespace TimeWarp.Architecture.Features.Auth; using static GetSignInToken; diff --git a/source/container-apps/web/web-server/features/hello/feature-annotations.cs b/source/container-apps/web/web-server/features/hello/feature-annotations.cs index b9d64085..7ee979b7 100644 --- a/source/container-apps/web/web-server/features/hello/feature-annotations.cs +++ b/source/container-apps/web/web-server/features/hello/feature-annotations.cs @@ -1,3 +1,7 @@ +#region Purpose +// Names the Hello feature group as a constant for tagging its endpoints in API metadata; no code consumes it. +#endregion + namespace TimeWarp.Architecture.Features.Hellos; public static class FeatureAnnotations diff --git a/source/container-apps/web/web-server/features/profile/feature-annotations.cs b/source/container-apps/web/web-server/features/profile/feature-annotations.cs index e8bc533b..2599bda8 100644 --- a/source/container-apps/web/web-server/features/profile/feature-annotations.cs +++ b/source/container-apps/web/web-server/features/profile/feature-annotations.cs @@ -1,3 +1,7 @@ +#region Purpose +// Names the Profiles feature group as a constant for tagging its endpoints in API metadata; no code consumes it. +#endregion + namespace TimeWarp.Architecture.Features.Profiles; public static class FeatureAnnotations diff --git a/source/container-apps/web/web-server/features/profile/get-profile-endpoint.cs b/source/container-apps/web/web-server/features/profile/get-profile-endpoint.cs index 836d5200..1b868c00 100644 --- a/source/container-apps/web/web-server/features/profile/get-profile-endpoint.cs +++ b/source/container-apps/web/web-server/features/profile/get-profile-endpoint.cs @@ -1,3 +1,7 @@ +#region Purpose +// HTTP GET adapter serving the signed-in user's display profile via the mediator pipeline. +#endregion + namespace TimeWarp.Architecture.Features.Profiles; using static GetProfile; diff --git a/source/container-apps/web/web-server/global-usings.cs b/source/container-apps/web/web-server/global-usings.cs index b1ac6631..e1b6adbf 100644 --- a/source/container-apps/web/web-server/global-usings.cs +++ b/source/container-apps/web/web-server/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using TimeWarp.Mediator; global using TimeWarp.Mediator.Pipeline; global using FluentValidation; diff --git a/source/container-apps/web/web-spa/assembly-marker.cs b/source/container-apps/web/web-spa/assembly-marker.cs index 8d8bc2f9..553edb49 100644 --- a/source/container-apps/web/web-spa/assembly-marker.cs +++ b/source/container-apps/web/web-spa/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Web.Spa; /// diff --git a/source/container-apps/web/web-spa/components/base/edit-mode.cs b/source/container-apps/web/web-spa/components/base/edit-mode.cs index 345fedca..4d1f47e0 100644 --- a/source/container-apps/web/web-spa/components/base/edit-mode.cs +++ b/source/container-apps/web/web-spa/components/base/edit-mode.cs @@ -1,3 +1,7 @@ +#region Purpose +// Shared enum so form components can switch read-only, edit, and create behavior from one state value. +#endregion + namespace TimeWarp.Architecture.Components; public enum EditMode { View, Edit, New }; diff --git a/source/container-apps/web/web-spa/components/elements/HyperLink.razor.cs b/source/container-apps/web/web-spa/components/elements/HyperLink.razor.cs index e69de29b..7fa759f6 100644 --- a/source/container-apps/web/web-spa/components/elements/HyperLink.razor.cs +++ b/source/container-apps/web/web-spa/components/elements/HyperLink.razor.cs @@ -0,0 +1,3 @@ +#region Purpose +// Empty code-behind for the HyperLink element — its logic lives in HyperLink.razor's @code block; this file marks where code-behind goes if it grows. +#endregion diff --git a/source/container-apps/web/web-spa/components/interfaces/i-navigable-component.cs b/source/container-apps/web/web-spa/components/interfaces/i-navigable-component.cs index 5f0dbf3b..65c46375 100644 --- a/source/container-apps/web/web-spa/components/interfaces/i-navigable-component.cs +++ b/source/container-apps/web/web-spa/components/interfaces/i-navigable-component.cs @@ -1,3 +1,7 @@ +#region Purpose +// Lets navigation menus read a page's title, icon, and auth policy statically, without instantiating the page. +#endregion + namespace TimeWarp.Architecture.Common.Interfaces; using TimeWarp.Architecture; diff --git a/source/container-apps/web/web-spa/components/interfaces/i-static-route.cs b/source/container-apps/web/web-spa/components/interfaces/i-static-route.cs index 4df90697..c36bd2c8 100644 --- a/source/container-apps/web/web-spa/components/interfaces/i-static-route.cs +++ b/source/container-apps/web/web-spa/components/interfaces/i-static-route.cs @@ -1,3 +1,7 @@ +#region Purpose +// Lets links build a page's href via static GetPageUrl() instead of hard-coded route strings; implemented on pages by the [Page] source generator. +#endregion + namespace TimeWarp.Architecture.Common.Interfaces; public interface IStaticRoute { diff --git a/source/container-apps/web/web-spa/components/pages/SideNavigation.razor.cs b/source/container-apps/web/web-spa/components/pages/SideNavigation.razor.cs index 694465a9..7a3f34de 100644 --- a/source/container-apps/web/web-spa/components/pages/SideNavigation.razor.cs +++ b/source/container-apps/web/web-spa/components/pages/SideNavigation.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the side navigation container: exposes the RenderFragment slot the shell fills with nav links. +#endregion + namespace TimeWarp.Architecture.Components; partial class SideNavigation diff --git a/source/container-apps/web/web-spa/components/pages/SideNavigationLink.razor.cs b/source/container-apps/web/web-spa/components/pages/SideNavigationLink.razor.cs index 13f55a56..24a20f48 100644 --- a/source/container-apps/web/web-spa/components/pages/SideNavigationLink.razor.cs +++ b/source/container-apps/web/web-spa/components/pages/SideNavigationLink.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for a single side-nav link: merges caller-supplied CSS classes into the link via CssBuilder. +#endregion + namespace TimeWarp.Architecture.Components; using CssBuilder = BlazorComponentUtilities.CssBuilder; diff --git a/source/container-apps/web/web-spa/constants.cs b/source/container-apps/web/web-spa/constants.cs index 2e15c5db..8793b42d 100644 --- a/source/container-apps/web/web-spa/constants.cs +++ b/source/container-apps/web/web-spa/constants.cs @@ -1,3 +1,7 @@ +#region Purpose +// SPA-local constants that have no home elsewhere, such as the non-standard HTTP status representing a client-cancelled operation. +#endregion + namespace TimeWarp.Architecture; internal static class Constants diff --git a/source/container-apps/web/web-spa/features/account/pages/ChangePasswordPage.razor.cs b/source/container-apps/web/web-spa/features/account/pages/ChangePasswordPage.razor.cs index 2d6ee6c3..8a897d59 100644 --- a/source/container-apps/web/web-spa/features/account/pages/ChangePasswordPage.razor.cs +++ b/source/container-apps/web/web-spa/features/account/pages/ChangePasswordPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the change-password placeholder page: [Page] drives source-generated routing and navigation plumbing. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/changePassword")] diff --git a/source/container-apps/web/web-spa/features/account/pages/LogoutPage.razor.cs b/source/container-apps/web/web-spa/features/account/pages/LogoutPage.razor.cs index 1de6b27d..220a563f 100644 --- a/source/container-apps/web/web-spa/features/account/pages/LogoutPage.razor.cs +++ b/source/container-apps/web/web-spa/features/account/pages/LogoutPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the signed-out confirmation page: [Page] drives source-generated routing and navigation plumbing. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Logout")] diff --git a/source/container-apps/web/web-spa/features/account/pages/login-page/LoginPage.razor.cs b/source/container-apps/web/web-spa/features/account/pages/login-page/LoginPage.razor.cs index 38e90959..c89c12bc 100644 --- a/source/container-apps/web/web-spa/features/account/pages/login-page/LoginPage.razor.cs +++ b/source/container-apps/web/web-spa/features/account/pages/login-page/LoginPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the login page (passkey sign-in demo lives in the .razor @code block): [Page] drives source-generated routing and navigation plumbing. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Login")] diff --git a/source/container-apps/web/web-spa/features/admin/roles/pages/RolePage.razor.cs b/source/container-apps/web/web-spa/features/admin/roles/pages/RolePage.razor.cs index d7988482..9a11f8f4 100644 --- a/source/container-apps/web/web-spa/features/admin/roles/pages/RolePage.razor.cs +++ b/source/container-apps/web/web-spa/features/admin/roles/pages/RolePage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the admin New Role page, which demos contract-interface form binding (IRoleDetails): [Page] drives source-generated routing. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Admin/Roles/New")] diff --git a/source/container-apps/web/web-spa/features/admin/roles/role-state/role-state.cs b/source/container-apps/web/web-spa/features/admin/roles/role-state/role-state.cs index 8cd17778..5de1f476 100644 --- a/source/container-apps/web/web-spa/features/admin/roles/role-state/role-state.cs +++ b/source/container-apps/web/web-spa/features/admin/roles/role-state/role-state.cs @@ -1,3 +1,7 @@ +#region Purpose +// Tracks the id of the most recently created role so the roles demo page can confirm the create round-trip. +#endregion + namespace TimeWarp.Architecture.Features.Admin.Roles; [StateAccess] diff --git a/source/container-apps/web/web-spa/features/application/pages/HomePage.razor.cs b/source/container-apps/web/web-spa/features/application/pages/HomePage.razor.cs index b68b3f68..40b6a8da 100644 --- a/source/container-apps/web/web-spa/features/application/pages/HomePage.razor.cs +++ b/source/container-apps/web/web-spa/features/application/pages/HomePage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers the root route for the app's landing page; markup and button handlers live in HomePage.razor. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/")] diff --git a/source/container-apps/web/web-spa/features/authorization/custom-requirements/module-requirement.cs b/source/container-apps/web/web-spa/features/authorization/custom-requirements/module-requirement.cs index 1659b91e..43205f47 100644 --- a/source/container-apps/web/web-spa/features/authorization/custom-requirements/module-requirement.cs +++ b/source/container-apps/web/web-spa/features/authorization/custom-requirements/module-requirement.cs @@ -1,3 +1,7 @@ +#region Purpose +// Carries the module Guid an authorization policy demands; ModuleRequirementHandler satisfies it from fetched module grants. +#endregion + namespace TimeWarp.Architecture.CustomRequirements; public sealed class ModuleRequirement diff --git a/source/container-apps/web/web-spa/features/base/i-base-action.cs b/source/container-apps/web/web-spa/features/base/i-base-action.cs index 1e1c052a..3e8ab807 100644 --- a/source/container-apps/web/web-spa/features/base/i-base-action.cs +++ b/source/container-apps/web/web-spa/features/base/i-base-action.cs @@ -1,3 +1,7 @@ +#region Purpose +// Unifies MediatR's IBaseRequest with TimeWarp.State's IAction so state actions can travel through the MediatR pipeline. +#endregion + namespace TimeWarp.Architecture.Features; public interface IBaseAction : IBaseRequest, IAction; diff --git a/source/container-apps/web/web-spa/features/counter/pages/CounterPage.razor.cs b/source/container-apps/web/web-spa/features/counter/pages/CounterPage.razor.cs index ab3b73a9..ed280246 100644 --- a/source/container-apps/web/web-spa/features/counter/pages/CounterPage.razor.cs +++ b/source/container-apps/web/web-spa/features/counter/pages/CounterPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the counter demo page; wires handlers for route navigation home and a full store reset. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Counter")] diff --git a/source/container-apps/web/web-spa/features/debugger/pages/TestPage.razor.cs b/source/container-apps/web/web-spa/features/debugger/pages/TestPage.razor.cs index c310fe29..e9355469 100644 --- a/source/container-apps/web/web-spa/features/debugger/pages/TestPage.razor.cs +++ b/source/container-apps/web/web-spa/features/debugger/pages/TestPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers the route for a scratch page used for ad-hoc debugging experiments. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Debugger/Test")] diff --git a/source/container-apps/web/web-spa/features/developer/components/user-claims-base.cs b/source/container-apps/web/web-spa/features/developer/components/user-claims-base.cs index 93562105..a2c61866 100644 --- a/source/container-apps/web/web-spa/features/developer/components/user-claims-base.cs +++ b/source/container-apps/web/web-spa/features/developer/components/user-claims-base.cs @@ -1,3 +1,7 @@ +#region Purpose +// Disabled (#if false) claims-display base-class sketch kept as reference; the TODO below records the pending delete-or-integrate decision. +#endregion + // TODO [2026-06]: Reassess UserClaimsBase after web-spa builds cleanly under AnalysisMode=All. // // Context: diff --git a/source/container-apps/web/web-spa/features/developer/pages/AlertExamplePage.razor.cs b/source/container-apps/web/web-spa/features/developer/pages/AlertExamplePage.razor.cs index f001038f..3d1b42eb 100644 --- a/source/container-apps/web/web-spa/features/developer/pages/AlertExamplePage.razor.cs +++ b/source/container-apps/web/web-spa/features/developer/pages/AlertExamplePage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers the route for a developer gallery page showcasing SimpleAlert variants. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/developer/alert-example")] diff --git a/source/container-apps/web/web-spa/features/developer/pages/UserClaimsPage.razor.cs b/source/container-apps/web/web-spa/features/developer/pages/UserClaimsPage.razor.cs index c62b6959..75f911c8 100644 --- a/source/container-apps/web/web-spa/features/developer/pages/UserClaimsPage.razor.cs +++ b/source/container-apps/web/web-spa/features/developer/pages/UserClaimsPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers the route for a developer diagnostic page that displays the signed-in user's claims. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Developer/UserClaims")] diff --git a/source/container-apps/web/web-spa/features/event-stream/event-stream-state/event-stream-state.cs b/source/container-apps/web/web-spa/features/event-stream/event-stream-state/event-stream-state.cs index 8ec98575..76cd425b 100644 --- a/source/container-apps/web/web-spa/features/event-stream/event-stream-state/event-stream-state.cs +++ b/source/container-apps/web/web-spa/features/event-stream/event-stream-state/event-stream-state.cs @@ -1,3 +1,7 @@ +#region Purpose +// Accumulates the action names captured by the event-stream middleware demo for display on the EventStream page. +#endregion + namespace TimeWarp.Architecture.Features.EventStreams; [StateAccess] diff --git a/source/container-apps/web/web-spa/features/event-stream/pages/EventStreamPage.razor.cs b/source/container-apps/web/web-spa/features/event-stream/pages/EventStreamPage.razor.cs index 420be277..5fefbd6f 100644 --- a/source/container-apps/web/web-spa/features/event-stream/pages/EventStreamPage.razor.cs +++ b/source/container-apps/web/web-spa/features/event-stream/pages/EventStreamPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers the route for the page demonstrating the EventStream middleware's captured action log. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/EventStream")] diff --git a/source/container-apps/web/web-spa/features/superhero/pages/SuperheroPage.razor.cs b/source/container-apps/web/web-spa/features/superhero/pages/SuperheroPage.razor.cs index 5015d5ab..96b17e86 100644 --- a/source/container-apps/web/web-spa/features/superhero/pages/SuperheroPage.razor.cs +++ b/source/container-apps/web/web-spa/features/superhero/pages/SuperheroPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the Superheros page: wires the route and kicks off the gRPC superhero fetch on initialization. +#endregion + namespace TimeWarp.Architecture.Pages; using static TimeWarp.Architecture.Features.Superheros.SuperheroState; diff --git a/source/container-apps/web/web-spa/features/superhero/superhero-module.cs b/source/container-apps/web/web-spa/features/superhero/superhero-module.cs index a93e63a6..8d143955 100644 --- a/source/container-apps/web/web-spa/features/superhero/superhero-module.cs +++ b/source/container-apps/web/web-spa/features/superhero/superhero-module.cs @@ -1,3 +1,7 @@ +#region Purpose +// DI registration for the superhero feature: the service-URI resolver and the gRPC client provider its state actions depend on. +#endregion + namespace TimeWarp.Architecture.Features.Superheros; public class SuperheroModule diff --git a/source/container-apps/web/web-spa/features/superhero/superhero-state/superhero-state.cs b/source/container-apps/web/web-spa/features/superhero/superhero-state/superhero-state.cs index 20d2f047..1a947b47 100644 --- a/source/container-apps/web/web-spa/features/superhero/superhero-state/superhero-state.cs +++ b/source/container-apps/web/web-spa/features/superhero/superhero-state/superhero-state.cs @@ -1,3 +1,7 @@ +#region Purpose +// Root partial of the superhero TimeWarp State store: holds the superhero list; actions live in sibling superhero-state.*.cs partials. +#endregion + namespace TimeWarp.Architecture.Features.Superheros; [StateAccess] diff --git a/source/container-apps/web/web-spa/features/to-do/pages/TodoItemPage.razor.cs b/source/container-apps/web/web-spa/features/to-do/pages/TodoItemPage.razor.cs index 1a72e155..ae78de83 100644 --- a/source/container-apps/web/web-spa/features/to-do/pages/TodoItemPage.razor.cs +++ b/source/container-apps/web/web-spa/features/to-do/pages/TodoItemPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the single todo item page: binds the TodoItemId route parameter consumed by the edit form. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/todoitems/{TodoItemId:Guid}")] diff --git a/source/container-apps/web/web-spa/features/to-do/pages/TodoItemsPage.razor.cs b/source/container-apps/web/web-spa/features/to-do/pages/TodoItemsPage.razor.cs index 9169d987..e3547ff6 100644 --- a/source/container-apps/web/web-spa/features/to-do/pages/TodoItemsPage.razor.cs +++ b/source/container-apps/web/web-spa/features/to-do/pages/TodoItemsPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the todo items list page: declares the route; the markup delegates rendering to TodoItemList. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/todoitems")] diff --git a/source/container-apps/web/web-spa/features/to-do/todo-state.cs b/source/container-apps/web/web-spa/features/to-do/todo-state.cs index ed7f10c7..6f239002 100644 --- a/source/container-apps/web/web-spa/features/to-do/todo-state.cs +++ b/source/container-apps/web/web-spa/features/to-do/todo-state.cs @@ -1,3 +1,13 @@ +#region Purpose +// Placeholder marking where the to-do feature's client-side state store belongs. +#endregion + +#region Design +// Deliberately empty: it neither extends State nor gets registered, because the +// to-do pages and components talk to the API directly rather than through a store. +// Convert it to a TimeWarp State store when the feature needs shared client state. +#endregion + namespace TimeWarp.Architecture.Features.ToDo; public class TodoState diff --git a/source/container-apps/web/web-spa/features/weather-forecast/pages/WeatherForecastsPage.razor.cs b/source/container-apps/web/web-spa/features/weather-forecast/pages/WeatherForecastsPage.razor.cs index a1b3a9e4..bdf608d5 100644 --- a/source/container-apps/web/web-spa/features/weather-forecast/pages/WeatherForecastsPage.razor.cs +++ b/source/container-apps/web/web-spa/features/weather-forecast/pages/WeatherForecastsPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the weather forecasts page: declares the route; the fetch-on-init logic lives in the .razor @code block. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/WeatherForecasts")] diff --git a/source/container-apps/web/web-spa/features/weather-forecast/weather-forecast-module.cs b/source/container-apps/web/web-spa/features/weather-forecast/weather-forecast-module.cs index 4ce60c22..473e2e28 100644 --- a/source/container-apps/web/web-spa/features/weather-forecast/weather-forecast-module.cs +++ b/source/container-apps/web/web-spa/features/weather-forecast/weather-forecast-module.cs @@ -1,3 +1,7 @@ +#region Purpose +// DI registration hook for the weather forecast feature; the body is empty because the feature needs nothing beyond shared services. +#endregion + namespace TimeWarp.Architecture.Features.WeatherForecasts; public class WeatherForecastModule diff --git a/source/container-apps/web/web-spa/global-suppressions.cs b/source/container-apps/web/web-spa/global-suppressions.cs index 15edfda9..189ab2fd 100644 --- a/source/container-apps/web/web-spa/global-suppressions.cs +++ b/source/container-apps/web/web-spa/global-suppressions.cs @@ -1,3 +1,7 @@ +#region Purpose +// Assembly-level analyzer suppressions for Web.Spa, gathering warnings judged acceptable instead of scattering pragmas through code. +#endregion + // This file is used by Code Analysis to maintain SuppressMessage // attributes that are applied to this project. // Project-level suppressions either have no target or are given diff --git a/source/container-apps/web/web-spa/global-usings.cs b/source/container-apps/web/web-spa/global-usings.cs index b60d4d1e..8d3500aa 100644 --- a/source/container-apps/web/web-spa/global-usings.cs +++ b/source/container-apps/web/web-spa/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Ardalis.GuardClauses; global using Icons = Microsoft.FluentUI.AspNetCore.Components.Icons; global using TimeWarp.State; diff --git a/source/container-apps/web/web-spa/java-script-interop-constants.cs b/source/container-apps/web/web-spa/java-script-interop-constants.cs index 022586d8..6dd9fef8 100644 --- a/source/container-apps/web/web-spa/java-script-interop-constants.cs +++ b/source/container-apps/web/web-spa/java-script-interop-constants.cs @@ -1,3 +1,7 @@ +#region Purpose +// Names of JS interop functions as constants, so C# callers and the wwwroot/js implementations agree on a single string. +#endregion + namespace TimeWarp.Architecture; /// diff --git a/source/container-apps/web/web-spa/pages/ProfilePage.razor.cs b/source/container-apps/web/web-spa/pages/ProfilePage.razor.cs index 9a0d72cc..ed1d9385 100644 --- a/source/container-apps/web/web-spa/pages/ProfilePage.razor.cs +++ b/source/container-apps/web/web-spa/pages/ProfilePage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind for the Profile page: declares the route and gates it behind an authenticated user. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Profile")] diff --git a/source/container-apps/web/web-spa/pages/SettingsPage.razor.cs b/source/container-apps/web/web-spa/pages/SettingsPage.razor.cs index a547dc00..2fb71258 100644 --- a/source/container-apps/web/web-spa/pages/SettingsPage.razor.cs +++ b/source/container-apps/web/web-spa/pages/SettingsPage.razor.cs @@ -1,3 +1,7 @@ +#region Purpose +// Code-behind that binds the /Settings route to the Settings placeholder page. +#endregion + namespace TimeWarp.Architecture.Pages; [Page("/Settings")] diff --git a/source/container-apps/web/web-spa/pipeline/notification-post-processor/post-pipeline-notification.cs b/source/container-apps/web/web-spa/pipeline/notification-post-processor/post-pipeline-notification.cs index 77d73ed2..884f8d5c 100644 --- a/source/container-apps/web/web-spa/pipeline/notification-post-processor/post-pipeline-notification.cs +++ b/source/container-apps/web/web-spa/pipeline/notification-post-processor/post-pipeline-notification.cs @@ -1,3 +1,7 @@ +#region Purpose +// Notification carrying a completed request/response pair so features can react to other features' actions without coupling to their handlers. +#endregion + namespace TimeWarp.Architecture.Pipeline.NotificationPostProcessor; public class PostPipelineNotification : INotification diff --git a/source/container-apps/web/web-spa/pipeline/notification-pre-processor/pre-pipeline-notification.cs b/source/container-apps/web/web-spa/pipeline/notification-pre-processor/pre-pipeline-notification.cs index 287d4ab2..2d0a2319 100644 --- a/source/container-apps/web/web-spa/pipeline/notification-pre-processor/pre-pipeline-notification.cs +++ b/source/container-apps/web/web-spa/pipeline/notification-pre-processor/pre-pipeline-notification.cs @@ -1,3 +1,7 @@ +#region Purpose +// Notification carrying a request about to be handled so features can observe or react before the handler runs, without coupling to it. +#endregion + namespace TimeWarp.Architecture.Pipeline.NotificationPreProcessor; public class PrePipelineNotification : INotification diff --git a/source/container-apps/yarp/assembly-marker.cs b/source/container-apps/yarp/assembly-marker.cs index 2b52b177..928066bb 100644 --- a/source/container-apps/yarp/assembly-marker.cs +++ b/source/container-apps/yarp/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Architecture.Yarp.Server; /// diff --git a/source/container-apps/yarp/global-usings.cs b/source/container-apps/yarp/global-usings.cs index 2f7f34ad..a94f6f72 100644 --- a/source/container-apps/yarp/global-usings.cs +++ b/source/container-apps/yarp/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.AspNetCore.Builder; global using Microsoft.AspNetCore.Routing; global using Microsoft.Extensions.Configuration; diff --git a/source/foundation/foundation-application/abstractions/i-current-user-service.cs b/source/foundation/foundation-application/abstractions/i-current-user-service.cs index 7b250ca7..8956c990 100644 --- a/source/foundation/foundation-application/abstractions/i-current-user-service.cs +++ b/source/foundation/foundation-application/abstractions/i-current-user-service.cs @@ -1,3 +1,7 @@ +#region Purpose +// Abstraction exposing the authenticated user's id so application code never reaches into HttpContext or auth plumbing. +#endregion + namespace TimeWarp.Foundation.Abstractions; public interface ICurrentUserService diff --git a/source/foundation/foundation-application/abstractions/i-date-time-service.cs b/source/foundation/foundation-application/abstractions/i-date-time-service.cs index a6663797..539c3e23 100644 --- a/source/foundation/foundation-application/abstractions/i-date-time-service.cs +++ b/source/foundation/foundation-application/abstractions/i-date-time-service.cs @@ -1,3 +1,12 @@ +#region Purpose +// Injectable clock abstraction so consumers can be tested with frozen or scripted time. +#endregion + +#region Design +// NextUtcNow contracts to hand out strictly increasing timestamps for consumers that use +// time as an ordering key; see DateTimeService in foundation-infrastructure for the mechanics. +#endregion + namespace TimeWarp.Foundation.Abstractions; public interface IDateTimeService diff --git a/source/foundation/foundation-application/assembly-marker.cs b/source/foundation/foundation-application/assembly-marker.cs index 560330e9..d14b1312 100644 --- a/source/foundation/foundation-application/assembly-marker.cs +++ b/source/foundation/foundation-application/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Foundation.Common.Application; /// diff --git a/source/foundation/foundation-application/global-usings.cs b/source/foundation/foundation-application/global-usings.cs index d2434d2b..9ae16c42 100644 --- a/source/foundation/foundation-application/global-usings.cs +++ b/source/foundation/foundation-application/global-usings.cs @@ -1 +1,5 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + // global using xyz; diff --git a/source/foundation/foundation-contracts/assembly-marker.cs b/source/foundation/foundation-contracts/assembly-marker.cs index f800281d..edcf93a0 100644 --- a/source/foundation/foundation-contracts/assembly-marker.cs +++ b/source/foundation/foundation-contracts/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Foundation.Common.Contracts; /// diff --git a/source/foundation/foundation-contracts/base/base-message.cs b/source/foundation/foundation-contracts/base/base-message.cs index e74e5458..d530e2ec 100644 --- a/source/foundation/foundation-contracts/base/base-message.cs +++ b/source/foundation/foundation-contracts/base/base-message.cs @@ -1,3 +1,7 @@ +#region Purpose +// Root of the contract message hierarchy, giving requests and responses a single common ancestor. +#endregion + namespace TimeWarp.Foundation.Features; /// diff --git a/source/foundation/foundation-contracts/base/base-paged-request.cs b/source/foundation/foundation-contracts/base/base-paged-request.cs index 347f936c..1fea1733 100644 --- a/source/foundation/foundation-contracts/base/base-paged-request.cs +++ b/source/foundation/foundation-contracts/base/base-paged-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Base for list-style requests, supplying Page/PageSize so paging is uniform across endpoints. +#endregion + namespace TimeWarp.Foundation.Features; public abstract class BasePagedRequest : BaseRequest diff --git a/source/foundation/foundation-contracts/base/base-request.cs b/source/foundation/foundation-contracts/base/base-request.cs index e6e6158c..f3d2fb88 100644 --- a/source/foundation/foundation-contracts/base/base-request.cs +++ b/source/foundation/foundation-contracts/base/base-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Common ancestor for all request contracts, marking the request side of the message hierarchy. +#endregion + namespace TimeWarp.Foundation.Features; /// diff --git a/source/foundation/foundation-contracts/base/base-response.cs b/source/foundation/foundation-contracts/base/base-response.cs index fbcd1eb1..dbea84a2 100644 --- a/source/foundation/foundation-contracts/base/base-response.cs +++ b/source/foundation/foundation-contracts/base/base-response.cs @@ -1,3 +1,7 @@ +#region Purpose +// Common ancestor for all response contracts, marking the response side of the message hierarchy. +#endregion + namespace TimeWarp.Foundation.Features; /// diff --git a/source/foundation/foundation-contracts/base/http-verb.cs b/source/foundation/foundation-contracts/base/http-verb.cs index 7defea96..704a365b 100644 --- a/source/foundation/foundation-contracts/base/http-verb.cs +++ b/source/foundation/foundation-contracts/base/http-verb.cs @@ -1,3 +1,7 @@ +#region Purpose +// Enum of HTTP methods so contracts can declare their verb without depending on System.Net.Http's HttpMethod class. +#endregion + namespace TimeWarp.Foundation.Features; public enum HttpVerb { diff --git a/source/foundation/foundation-contracts/base/i-api-request.cs b/source/foundation/foundation-contracts/base/i-api-request.cs index 040f6d54..e84afe30 100644 --- a/source/foundation/foundation-contracts/base/i-api-request.cs +++ b/source/foundation/foundation-contracts/base/i-api-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Makes a request contract self-describing (route + verb) so a generic API client can dispatch it without per-endpoint plumbing. +#endregion + namespace TimeWarp.Foundation.Features; public interface IApiRequest : IBaseRequest diff --git a/source/foundation/foundation-contracts/base/i-base-message.cs b/source/foundation/foundation-contracts/base/i-base-message.cs index dba49c6d..5d9085ad 100644 --- a/source/foundation/foundation-contracts/base/i-base-message.cs +++ b/source/foundation/foundation-contracts/base/i-base-message.cs @@ -1,3 +1,7 @@ +#region Purpose +// Root marker of the contract message hierarchy so generic plumbing can constrain to "any request or response". +#endregion + namespace TimeWarp.Foundation.Features; /// diff --git a/source/foundation/foundation-contracts/base/i-base-request.cs b/source/foundation/foundation-contracts/base/i-base-request.cs index 73971d8e..603b22f4 100644 --- a/source/foundation/foundation-contracts/base/i-base-request.cs +++ b/source/foundation/foundation-contracts/base/i-base-request.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker that distinguishes requests from responses within the contract message hierarchy. +#endregion + namespace TimeWarp.Foundation.Features; /// diff --git a/source/foundation/foundation-contracts/base/i-query-string-route-provider.cs b/source/foundation/foundation-contracts/base/i-query-string-route-provider.cs index 861a5d43..d41781f2 100644 --- a/source/foundation/foundation-contracts/base/i-query-string-route-provider.cs +++ b/source/foundation/foundation-contracts/base/i-query-string-route-provider.cs @@ -1,3 +1,7 @@ +#region Purpose +// Lets GET-style query contracts build their own route with parameters encoded in the query string, since GETs carry no body. +#endregion + namespace TimeWarp.Foundation.Features; public interface IQueryStringRouteProvider:IApiRequest diff --git a/source/foundation/foundation-contracts/configuration/service-names.cs b/source/foundation/foundation-contracts/configuration/service-names.cs index 92441abc..7eb4c967 100644 --- a/source/foundation/foundation-contracts/configuration/service-names.cs +++ b/source/foundation/foundation-contracts/configuration/service-names.cs @@ -1,3 +1,12 @@ +#region Purpose +// Single source of truth for service-discovery names shared by the Aspire AppHost and every client that resolves a service BaseAddress. +#endregion + +#region Design +// Aspire AppHost resource names must equal these constants: service discovery resolves +// addresses by name, and a mismatch yields a null BaseAddress during server-side rendering. +#endregion + namespace TimeWarp.Foundation.Configuration; public static class ServiceNames { diff --git a/source/foundation/foundation-contracts/global-usings.cs b/source/foundation/foundation-contracts/global-usings.cs index e086ae7a..ef563885 100644 --- a/source/foundation/foundation-contracts/global-usings.cs +++ b/source/foundation/foundation-contracts/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Ardalis.GuardClauses; global using FluentValidation; global using FluentValidation.Results; diff --git a/source/foundation/foundation-contracts/types/mock-response-factory.cs b/source/foundation/foundation-contracts/types/mock-response-factory.cs index 9ce00cf0..2892fa23 100644 --- a/source/foundation/foundation-contracts/types/mock-response-factory.cs +++ b/source/foundation/foundation-contracts/types/mock-response-factory.cs @@ -1,3 +1,7 @@ +#region Purpose +// Delegate shape that lets each contract supply its own canned response, so mock API services can run the SPA without a backend. +#endregion + namespace TimeWarp.Foundation.Types; public delegate TResponse MockResponseFactory(IApiRequest request) where TResponse : class; diff --git a/source/foundation/foundation-domain/assembly-marker.cs b/source/foundation/foundation-domain/assembly-marker.cs index 30cbca44..c3262caa 100644 --- a/source/foundation/foundation-domain/assembly-marker.cs +++ b/source/foundation/foundation-domain/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Foundation.Common.Domain; /// diff --git a/source/foundation/foundation-domain/entities/base/base-entity.cs b/source/foundation/foundation-domain/entities/base/base-entity.cs index f2881864..7128dc23 100644 --- a/source/foundation/foundation-domain/entities/base/base-entity.cs +++ b/source/foundation/foundation-domain/entities/base/base-entity.cs @@ -1,3 +1,7 @@ +#region Purpose +// Common base for domain entities so every entity carries a Guid identity regardless of database provider. +#endregion + namespace TimeWarp.Foundation.Entities; public abstract class BaseEntity { diff --git a/source/foundation/foundation-domain/entities/base/base-event.cs b/source/foundation/foundation-domain/entities/base/base-event.cs index 4dcd7770..cec58744 100644 --- a/source/foundation/foundation-domain/entities/base/base-event.cs +++ b/source/foundation/foundation-domain/entities/base/base-event.cs @@ -1,3 +1,7 @@ +#region Purpose +// Common base for domain events so they publish through the MediatR notification pipeline. +#endregion + namespace TimeWarp.Foundation.Entities.Base; public abstract class BaseEvent : INotification { } diff --git a/source/foundation/foundation-domain/global-usings.cs b/source/foundation/foundation-domain/global-usings.cs index 1ac25d00..27f7ccc4 100644 --- a/source/foundation/foundation-domain/global-usings.cs +++ b/source/foundation/foundation-domain/global-usings.cs @@ -1,2 +1,6 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using System.Reflection; global using TimeWarp.Mediator; diff --git a/source/foundation/foundation-infrastructure/assembly-marker.cs b/source/foundation/foundation-infrastructure/assembly-marker.cs index a23e90dd..a161a73c 100644 --- a/source/foundation/foundation-infrastructure/assembly-marker.cs +++ b/source/foundation/foundation-infrastructure/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Foundation.Common.Infrastructure; /// diff --git a/source/foundation/foundation-infrastructure/common-infrastructure-module.cs b/source/foundation/foundation-infrastructure/common-infrastructure-module.cs index 7622bd17..c1f1b340 100644 --- a/source/foundation/foundation-infrastructure/common-infrastructure-module.cs +++ b/source/foundation/foundation-infrastructure/common-infrastructure-module.cs @@ -1,3 +1,7 @@ +#region Purpose +// Registers infrastructure services every server needs (current-user resolution) so each host wires them through one module instead of repeating the registrations. +#endregion + namespace TimeWarp.Foundation.Common.Infrastructure; public class CommonInfrastructureModule : IModule diff --git a/source/foundation/foundation-infrastructure/global-usings.cs b/source/foundation/foundation-infrastructure/global-usings.cs index 4c806c2a..de3982cd 100644 --- a/source/foundation/foundation-infrastructure/global-usings.cs +++ b/source/foundation/foundation-infrastructure/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.AspNetCore.Http; global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; diff --git a/source/foundation/foundation-server/assembly-marker.cs b/source/foundation/foundation-server/assembly-marker.cs index c4118143..91c17af5 100644 --- a/source/foundation/foundation-server/assembly-marker.cs +++ b/source/foundation/foundation-server/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Foundation.Common.Server; /// diff --git a/source/foundation/foundation-server/global-usings.cs b/source/foundation/foundation-server/global-usings.cs index 43e0a704..5a22ab9c 100644 --- a/source/foundation/foundation-server/global-usings.cs +++ b/source/foundation/foundation-server/global-usings.cs @@ -1,3 +1,7 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Ardalis.GuardClauses; global using Azure.Identity; global using FastEndpoints; diff --git a/source/foundation/foundation-server/i-aspnet-module.cs b/source/foundation/foundation-server/i-aspnet-module.cs index 41179ed8..f7e4c6ec 100644 --- a/source/foundation/foundation-server/i-aspnet-module.cs +++ b/source/foundation/foundation-server/i-aspnet-module.cs @@ -1,3 +1,7 @@ +#region Purpose +// Extends IModule with configuration, middleware, and endpoint hooks so a module can wire the full ASP.NET pipeline, not just DI services. +#endregion + namespace TimeWarp.Foundation; public interface IAspNetModule : IModule diff --git a/source/foundation/foundation-server/i-aspnet-program.cs b/source/foundation/foundation-server/i-aspnet-program.cs index a899befe..2b250f85 100644 --- a/source/foundation/foundation-server/i-aspnet-program.cs +++ b/source/foundation/foundation-server/i-aspnet-program.cs @@ -1,2 +1,6 @@ +#region Purpose +// Marks the composition-root module of an ASP.NET host, distinguishing the program itself from the feature modules it composes. +#endregion + namespace TimeWarp.Foundation; public interface IAspNetProgram : IAspNetModule { } diff --git a/source/libraries/timewarp-modules/assembly-marker.cs b/source/libraries/timewarp-modules/assembly-marker.cs index fbcd7ea8..b8eb1c17 100644 --- a/source/libraries/timewarp-modules/assembly-marker.cs +++ b/source/libraries/timewarp-modules/assembly-marker.cs @@ -1,3 +1,7 @@ +#region Purpose +// Marker type providing a typed reference to this assembly (registration, scanning, InternalsVisibleTo). +#endregion + namespace TimeWarp.Modules; /// diff --git a/source/libraries/timewarp-modules/global-usings.cs b/source/libraries/timewarp-modules/global-usings.cs index 034c2451..ba05b357 100644 --- a/source/libraries/timewarp-modules/global-usings.cs +++ b/source/libraries/timewarp-modules/global-usings.cs @@ -1,2 +1,6 @@ +#region Purpose +// Project-wide using directives so individual files omit repeated imports. +#endregion + global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; diff --git a/source/libraries/timewarp-modules/i-module.cs b/source/libraries/timewarp-modules/i-module.cs index d74a1c8f..f31fdb78 100644 --- a/source/libraries/timewarp-modules/i-module.cs +++ b/source/libraries/timewarp-modules/i-module.cs @@ -1,3 +1,7 @@ +#region Purpose +// Contract for self-registering modules; the static abstract hook lets each assembly wire its own DI services without a central composition root. +#endregion + namespace TimeWarp.Modules; public interface IModule diff --git a/tests/analyzers/timewarp-architecture-analyzers-tests/purpose-region-analyzer-tests.cs b/tests/analyzers/timewarp-architecture-analyzers-tests/purpose-region-analyzer-tests.cs new file mode 100644 index 00000000..dba11bf6 --- /dev/null +++ b/tests/analyzers/timewarp-architecture-analyzers-tests/purpose-region-analyzer-tests.cs @@ -0,0 +1,129 @@ +// ReSharper disable InconsistentNaming +namespace PurposeRegionAnalyzer_; + +using Microsoft.CodeAnalysis.CSharp.Testing; +using TimeWarp.Architecture.Analyzers; +using TimeWarp.Architecture.Analyzers.Tests; + +public class Should_Enforce_Purpose_Region +{ + private static CSharpAnalyzerTest Test(string fileName, string source) => + new() { TestState = { Sources = { (fileName, source) } } }; + + public static async Task Given_File_Without_Purpose_Region() + { + const string Source = + """ + namespace Contracts; + + public class Widget + { + public string Name { get; set; } = null!; + } + """; + + DiagnosticResult expectedDiagnostic = new DiagnosticResult(id: "TWPA0004", DiagnosticSeverity.Warning) + .WithSpan("Widget.cs", 1, 1, 1, 10) + .WithArguments("Widget.cs"); + + CSharpAnalyzerTest analyzerTest = new() + { + TestState = + { + Sources = + { + ("Widget.cs", Source) + } + } + }; + + analyzerTest.ExpectedDiagnostics.Add(expectedDiagnostic); + + await analyzerTest.RunAsync(); + } + + public static async Task Given_File_With_Purpose_Region_IsClean() + { + const string Source = + """ + #region Purpose + // A widget shape used to verify the analyzer accepts a top-of-file region. + #endregion + + namespace Contracts; + + public class Widget + { + public string Name { get; set; } = null!; + } + """; + + await Test("Widget.cs", Source).RunAsync(); + } + + public static async Task Given_Purpose_Region_Anywhere_In_File_IsClean() + { + // Placement is skill guidance, not analyzer scope — a nested region still satisfies the rule. + const string Source = + """ + namespace Contracts; + + public class Widget + { + #region Purpose + // Region nested inside the type still counts. + #endregion + public string Name { get; set; } = null!; + } + """; + + await Test("Widget.cs", Source).RunAsync(); + } + + public static async Task Given_Other_Region_Names_Still_Flagged() + { + const string Source = + """ + #region Design + // Design alone is not enough; Purpose is the universal requirement. + #endregion + + namespace Contracts; + + public class Widget; + """; + + DiagnosticResult expectedDiagnostic = new DiagnosticResult(id: "TWPA0004", DiagnosticSeverity.Warning) + .WithSpan("Widget.cs", 5, 1, 5, 10) + .WithArguments("Widget.cs"); + + CSharpAnalyzerTest analyzerTest = new() + { + TestState = + { + Sources = + { + ("Widget.cs", Source) + } + } + }; + + analyzerTest.ExpectedDiagnostics.Add(expectedDiagnostic); + + await analyzerTest.RunAsync(); + } + + public static async Task Given_Generated_File_IsClean() + { + // header marks the tree generated; GeneratedCodeAnalysisFlags.None skips it. + const string Source = + """ + // + namespace Contracts; + + public class Widget; + """; + + await Test("Widget.g.cs", Source).RunAsync(); + } +} diff --git a/tests/analyzers/timewarp-architecture-analyzers-tests/timewarp-architecture-analyzers-tests.csproj b/tests/analyzers/timewarp-architecture-analyzers-tests/timewarp-architecture-analyzers-tests.csproj index cd2782c5..8f991d58 100644 --- a/tests/analyzers/timewarp-architecture-analyzers-tests/timewarp-architecture-analyzers-tests.csproj +++ b/tests/analyzers/timewarp-architecture-analyzers-tests/timewarp-architecture-analyzers-tests.csproj @@ -12,6 +12,6 @@ - + \ No newline at end of file diff --git a/timewarp-architecture.slnx b/timewarp-architecture.slnx index b51a7989..a6bace5d 100644 --- a/timewarp-architecture.slnx +++ b/timewarp-architecture.slnx @@ -16,7 +16,7 @@ - +