--- name: dotnet-cop description: > Pre-merge code review for .NET 10 pull requests. Ground truth: Minimal API + IModule (reflection-based isolation) + hexagonal per module (Domain/Application/Infrastructure). Persistence is chosen per bounded context โ€” EF Core CRUD and event-sourced Marten stores are both first-class, with no global default. Optional additive: DDD / CQRS per module. Diffs current branch against a target branch, applies .NET-specific checklists (Minimal API endpoints, modular isolation, ports & adapters, schema-per-module + RLS, C# strictness, xUnit v3 only), runs dotnet build + dotnet format --verify-no-changes, and emits a tiered report (verbose for juniors, terse for seniors). Auto-loads project AGENTS.md rules. Use when user runs /cop-review, says "pre-merge review", or invokes dotnet-cop. --- # dotnet-cop Pre-merge review. Compares HEAD vs `origin/`. Minimal-API-first, SoT-aware. Project-aware (reads `AGENTS.md`). Tooling-aware (runs dotnet build + dotnet format --verify-no-changes). ## When to Activate - Selected by `code-reviewer` for .NET guidance during `/cop-review` - User runs `/cop-review ` on a .NET repo - dotnet-cop specialist is explicitly invoked ## Inputs | Arg | Required | Default | Meaning | |---|---|---|---| | `` | yes | โ€” | Target branch (e.g. `main`, `develop`, `release/x`) | | `--level` | no | auto | `junior` (verbose teaching) or `senior` (terse). Auto = senior. | | `--scope` | no | all | Comma list: `minimal-api,isolation,ports-adapters,ef-core,csharp,result,ddd` + optional `cqrs,event-sourcing`. `ddd` auto-enables when the diff touches domain files; pass `ddd` to force it on. | | `--no-tools` | no | false | Skip dotnet build + format check (static review only) | ## Hard Rules 1. **Read-only.** Never patch code. Output report only. 2. **Diff window:** `git merge-base HEAD origin/`..`HEAD`. Never review changes already on target. 3. **Confidence โ‰ฅ 80%.** Skip uncertain findings. Use `โ“ q:` instead of speculative `๐Ÿ”ด bug:`. 4. **Project rules win.** `AGENTS.md` overrides this skill. Re-read on every run; do not cache between sessions. 5. **dotnet-clean-architecture ground truth:** load [[dotnet-clean-architecture]] SKILL.md before flagging architecture code. Do not invent APIs or patterns. 6. **No fluff.** No "great work", no restating what the diff already shows. ## Pipeline ``` 1. Parse args -> target, level, scope 2. git fetch (silent; --quiet) 3. base = git merge-base HEAD / 4. changed = git diff --name-status base..HEAD 5. Load /AGENTS.md (if exists) -> project rules 6. For each changed file: - Skim full file (not just hunk) for context - Apply relevant sub-checklists by path/role: *Module.cs / *Extensions.cs -> modular-isolation.md Infrastructure/Events/*.cs / *DbContext.cs -> cross-module-communication.md *Endpoint.cs (Minimal API) -> minimal-api.md **/Ports/Incoming/*.cs -> ports-adapters.md **/Ports/Outgoing/*.cs -> ports-adapters.md Infrastructure/Adapter/*.cs -> ports-adapters.md *DbContext.cs / Migrations/** -> ef-core.md *.cs (any) -> csharp-strict.md - Apply skill `comment-judge` (REVIEW mode) to every added/changed comment - If ddd is in scope OR the diff touches domain files (paths under **/*.Domain/** or **/Domain/**): load [[dotnet-ddd]] (review-checklist.md); defer deep CQRS/ES to optional-cqrs.md / optional-event-sourcing.md. ddd is auto-enabled for domain diffs; --scope=ddd forces it on when no domain file is detected. - If --scope includes cqrs && module signals use: optional-cqrs.md - If --scope includes event-sourcing && module signals use: optional-event-sourcing.md 7. If !--no-tools: - dotnet build --nologo -clp:ErrorsOnly (the solution if one exists, else the relevant project(s) โ€” fail fast) - dotnet format --verify-no-changes (capture exit code) 8. Aggregate findings -> render via output-format.md ``` ## Severity | Tag | Meaning | Action | |---|---|---| | ๐Ÿ”ด bug | broken behavior, runtime crash, data loss | BLOCK merge | | ๐ŸŸ  sec | security risk (unvalidated input, leaked secret, tenant-data leak) | BLOCK merge | | ๐ŸŸก risk | works today, fragile tomorrow (N+1, missing filter, scope violation) | Fix before merge | | ๐ŸŸข arch | violates mandatory architecture rule (SoT) or AGENTS.md-escalated opt-in rule | Fix before merge | | ๐Ÿ”ต nit | style, naming, micro-optim | Optional | | โ“ q | genuine question | Author decides | Promote to BLOCK if AGENTS.md flags the category as mandatory. ## Sub-pages (read on demand) - [[dotnet-cop-minimal-api]] โ€” endpoint mapping, route groups, ProblemDetails, FluentValidation at boundary, no business logic in handlers. - [[dotnet-cop-modular-isolation]] โ€” module boundaries, no direct cross-module type references (hard blocker), communication via ports/events, reflection-based module discovery, per-module language autonomy. - [[dotnet-cop-cross-module-communication]] โ€” Cross-module communication (modular monolith): Wolverine-only inter-module reads, per-module projection DbContexts, forbidden cross-domain read ports in SharedKernel, `Model/` convention. Illustrated with the Sales module. - [[dotnet-cop-ports-adapters]] โ€” hexagonal: Domain/Application define ports, Infrastructure implements adapters; dependency direction; no EF entities leaking into Domain/Application. - [[dotnet-cop-ef-core]] โ€” DbContext per context/projection (hard blocker on shared DbContext), schema-per-module isolation, FORCE RLS mandatory on all context-schema tables, query splitting, N+1 prevention. - [[dotnet-cop-result]] โ€” business errors returned as `Result`/`Result`, never thrown; `Error` defined in Domain; no HTTP coupling in Domain/Application. - [[dotnet-ddd]] (ddd scope โ€” auto-enabled when the diff touches domain files) โ€” DDD tactical patterns (entities, value objects, aggregates, repositories) and strategic design for domain-layer code. Deep CQRS/ES enforcement defers to [[dotnet-cop-optional-cqrs]] and [[dotnet-cop-optional-event-sourcing]]. - [[dotnet-cop-optional-cqrs]] (opt-in) โ€” commands/queries, handlers, CQRS pattern. Only when module signals use. - [[dotnet-cop-optional-event-sourcing]] (opt-in) โ€” event-sourced aggregates, immutable events, append-only event store. Only when module signals use. - [[dotnet-cop-output-format]] โ€” junior vs senior render templates. - [[dotnet-cop-enforcement]] โ€” BLOCK vs WARN severity checklist (load always). SoT rules listed first; opt-in rules clearly marked. ## AGENTS.md Loading Always: ```bash test -f AGENTS.md && cat AGENTS.md test -f .agent/AGENTS.md && cat .agent/AGENTS.md ``` Parse rule blocks. Where this skill and AGENTS.md disagree, AGENTS.md wins. Cite the AGENTS.md line in the finding: `(AGENTS.md ยง
)`. ## Output Contract Single markdown document, sections in fixed order: 1. **Summary** โ€” target, base SHA, head SHA, files changed, finding counts by severity. 2. **Blockers** (๐Ÿ”ด / ๐ŸŸ  / ๐ŸŸข-when-AGENTS-mandates) โ€” sorted by severity, then file path. 3. **Should-fix** (๐ŸŸก) โ€” same sort. 4. **Optional** (๐Ÿ”ต / โ“) โ€” collapsible. 5. **Tooling** โ€” dotnet build summary, dotnet format summary. 6. **Verdict** โ€” `APPROVE` / `APPROVE-WITH-CHANGES` / `BLOCK`. See [[dotnet-cop-output-format]] for full templates. ## Boundaries - Does not write code fixes. Suggestions only. - Does not run integration or unit tests by default (delegate to the `tdd` workflow / `tdd-guide`). - Does not approve PRs in GitHub/Azure. Author posts the report manually. - Does not auto-fix formatting. Reports format violations only. - If no diff (HEAD == base), exit early with "no changes to review".