diff --git a/.github/prompts/audit-instructions.prompt.md b/.github/prompts/audit-instructions.prompt.md new file mode 100644 index 0000000..19cfefb --- /dev/null +++ b/.github/prompts/audit-instructions.prompt.md @@ -0,0 +1,51 @@ +--- +description: "Audit .github/instructions/ and .github/skills/ for duplication, stale references, and unscoped or misscoped files." +agent: "agent" +--- + +# Audit Instructions & Skills + +Walk every file under `.github/instructions/` and `.github/skills/` and produce a prioritised report of issues. Make no edits unless the user approves them after reading the report. + +## Steps + +### 1. Inventory + +List every `*.instructions.md` and every `**/SKILL.md`, plus `copilot-instructions.md` and any `*.prompt.md`. + +### 2. Per-File Checks + +For each instructions file: + +- `applyTo` glob exists and matches actual files in the repo (no dead globs). +- `description` accurately reflects the content (no stale TOCs, no over-promises). +- Content is project-specific — flag anything restating universal Markdown / C# / formatter rules, or duplicating the agent runtime (e.g., "work in parallel", "save to memory"). +- File defers to enforcement layers (`.editorconfig`, analyzers, `Directory.Build.props`) instead of restating their rules. +- Cross-references point at files that exist. + +For each skill: + +- Frontmatter `name` matches the directory name. +- `description` starts with the action and includes "Use when:". +- Procedure steps are actionable, not narration. +- Commands actually work against this repo's tool versions and config files. +- Cross-skill references use relative paths. + +### 3. Cross-File Checks + +- Same rule defined in multiple files with different wording or severity → flag. +- Topics not covered by any file but enforced via PR comments / convention → flag as candidate new file. +- `applyTo` overlap that could cause conflicting guidance on a single file → flag. + +### 4. Report + +Produce a table sorted by priority (high / medium / low): + +| Priority | File | Issue | Suggested fix | + +End with two summary counts: total files inspected, total issues found. + +## Guardrails + +- Read-only by default. Apply fixes only if the user explicitly approves them. +- When suggesting a fix, quote the exact lines to change so the user can decide without re-reading the file. diff --git a/.github/prompts/convert-controller-to-minimal.prompt.md b/.github/prompts/convert-controller-to-minimal.prompt.md new file mode 100644 index 0000000..a7300ee --- /dev/null +++ b/.github/prompts/convert-controller-to-minimal.prompt.md @@ -0,0 +1,65 @@ +--- +description: "Convert an MVC controller to Minimal API endpoints following the project's ASP.NET conventions." +agent: "agent" +--- + +# Convert Controller to Minimal API + +Refactor an MVC controller into Minimal API endpoints aligned with [aspnet-api.instructions.md](../instructions/aspnet-api.instructions.md). + +## Input + +Path to the controller file (e.g., `src/MyApi/Controllers/OrdersController.cs`). Ask if not provided. + +## Steps + +### 1. Analyse the Controller + +For each action method, capture: + +- HTTP verb and route template. +- Parameter binding sources (`[FromRoute]`, `[FromQuery]`, `[FromBody]`, `[FromServices]`). +- Return type and possible status codes. +- Filters / attributes (`[Authorize]`, `[ProducesResponseType]`, etc.). +- Async signature and `CancellationToken` usage. + +### 2. Produce a Migration Plan + +Present a table to the user before writing any code: + +| Action | New endpoint | Notes (auth, filters, response types) | + +Ask for confirmation or adjustments. + +### 3. Generate the Endpoint File + +Create `Endpoints.cs` next to the controller, following the conventions: + +- Static class with a `MapXEndpoints(this IEndpointRouteBuilder)` extension. +- `MapGroup("/api/v{apiVersion}/{resource}")` with shared `.WithTags(...)`. +- Use **`TypedResults`** for every return path. +- Use **`[AsParameters]`** for complex parameter sets. +- Use **`CancellationToken`** on every async lambda. +- Errors return **`ProblemDetails`** via `TypedResults.Problem(...)`. +- Endpoint lambdas stay thin; delegate to injected services. + +### 4. Wire Up Registration + +In `Program.cs`, replace `MapControllers()` (or supplement it) with the new `MapXEndpoints()` call. If the controller was the last one, also remove `AddControllers()`. + +### 5. Migrate Tests + +For each test targeting the controller, port it to use `WebApplicationFactory` against the new endpoint. Keep the file name and test names; update the arrange/act sections only. + +### 6. Delete the Controller + +Only after the new endpoints + tests pass. Run `dotnet build` and `dotnet test` before deletion. + +### 7. Update README + +If the project's `README.md` documented the old controller routes, update it in the same commit (per [copilot-instructions.md](../copilot-instructions.md)). + +## Guardrails + +- Do not change behaviour while converting — refactor first, behaviour changes go in a separate commit. +- If a controller uses filters or model binders without a Minimal API equivalent, surface the gap and ask before inventing one. diff --git a/.github/prompts/refactor-to-loggermessage.prompt.md b/.github/prompts/refactor-to-loggermessage.prompt.md new file mode 100644 index 0000000..d9c0f9e --- /dev/null +++ b/.github/prompts/refactor-to-loggermessage.prompt.md @@ -0,0 +1,66 @@ +--- +description: "Convert inline logger calls to LoggerMessage-generated partial methods, per the C# conventions." +agent: "agent" +--- + +# Refactor to LoggerMessage + +Replace inline `logger.LogX(...)` calls with `LoggerMessage`-generated `partial` methods, as required by [csharp.instructions.md](../instructions/csharp.instructions.md). + +## Input + +A file or project path. If unspecified, default to the active editor file. + +## Steps + +### 1. Inventory + +Find every `ILogger.Log*(...)` call site (`LogTrace`, `LogDebug`, `LogInformation`, `LogWarning`, `LogError`, `LogCritical`). Group by containing class. + +### 2. Plan + +For each class with hits, present a table before editing: + +| Method | Level | EventId | Message template | Args | + +Pick stable, sequential `EventId` values per class (start at 1 within the class). Confirm with the user when message templates need to be reworded for clarity. + +### 3. Convert the Class + +- Mark the class `partial`. +- Add a nested `static partial class Log` (or top-level partial methods, per existing project style — match what's already in the codebase). +- For each call site, generate: + ```csharp + [LoggerMessage(EventId = N, Level = LogLevel.X, Message = "...")] + static partial void (ILogger logger, ); + ``` +- Replace each call site with the new method invocation. +- Method names: `PascalCase`, verb-led, third-person (`OrderProcessed`, not `LogOrderProcessed` or `OrderWasProcessed`). + +### 4. Handle Edge Cases + +- **Exceptions**: `Exception` parameter goes first; do not include it in the message template. +- **Scopes** (`logger.BeginScope`): leave alone — `LoggerMessage` does not replace scopes. +- **Conditional logging** (`if (logger.IsEnabled(...))`): drop the guard; the generated method already checks. + +### 5. Verify + +```bash +dotnet build +``` + +Source generators must produce zero warnings. If a `[LoggerMessage]` definition is rejected, surface the analyzer message and the offending method. + +### 6. Run Tests + +```bash +dotnet test +``` + +Logger-based assertions in tests usually keep working, but message-template changes can break string-matching tests — flag any test failures explicitly. + +## Guardrails + +- Do not change log levels while refactoring — that's a separate decision. +- Do not invent new log statements; only convert what already exists. +- If a class is `sealed` and has external partial declarations, surface the conflict before adding `partial` to the type. diff --git a/.github/prompts/summarize-for-pr.prompt.md b/.github/prompts/summarize-for-pr.prompt.md new file mode 100644 index 0000000..60dd1e2 --- /dev/null +++ b/.github/prompts/summarize-for-pr.prompt.md @@ -0,0 +1,62 @@ +--- +description: "Create a temporary markdown file summarising all branch changes vs. main/master for PR review" +agent: "agent" +--- + +# Summarize Branch Changes for PR + +Create a temporary markdown file in the repository root called `BRANCH_CHANGES.md` that summarises all changes on the current branch compared to the master/main/default branch. This file is intended to aid PR review and should be deleted before merging. + +## Input + +No explicit input required — the summary is derived from git history and the current Copilot session context. + +## Steps + +### 1. Gather Git Context + +- Determine the current branch name (`git branch --show-current`). +- Find the merge base with `origin/master`. +- Collect the commit log between the merge base and HEAD (`git log --oneline`). +- Collect the diff stat (`git diff --stat`), file change list (`--diff-filter`), and numstat. + +### 2. Distil Session Requests (if applicable) + +If Copilot session context is available, extract the key user requests that drove the changes and present them as a bullet-point list at the top of the file under a **Copilot Session Requests** heading. + +### 3. Produce the Markdown File + +Create `BRANCH_CHANGES.md` in the repository root with the following sections: + +#### Header + +- Branch name, base branch, and current date. + +#### Copilot Session Requests + +- Bullet list of the user prompts/requests from the current session that led to changes (omit if no session context). + +#### Commits + +- Table with columns: Hash, Message, Author, Date. + +#### Files Changed + +- Table with columns: File, Change type (Added/Modified/Deleted), Insertions, Deletions. +- Summary line: _N files changed, X insertions, Y deletions._ + +#### Change Details + +- One sub-heading per changed file (or logical group of related files). +- Numbered list of the distinct changes made, written for a reviewer who is unfamiliar with the recent context. + +#### Pending Session Work (if applicable) + +- Any in-progress or uncommitted work from the current Copilot session that has not yet been committed. + +## Guidelines + +- Keep descriptions concise but specific — a reviewer should understand _what_ changed and _why_ without reading the diff. +- Use git data as the source of truth; supplement with session context only for intent and motivation. +- Do not include the full diff content — summarise it. +- Mark the file clearly as temporary (mention it should be deleted before merge). diff --git a/.github/prompts/sync-from-template.prompt.md b/.github/prompts/sync-from-template.prompt.md new file mode 100644 index 0000000..be7ebb6 --- /dev/null +++ b/.github/prompts/sync-from-template.prompt.md @@ -0,0 +1,72 @@ +--- +description: "Sync the current repository with upstream changes from kritikos-io/templates-dotnet, with conflict-resolution guidance." +agent: "agent" +--- + +# Sync From Template + +Pull updates from the upstream `kritikos-io/templates-dotnet` repository, following the workflow documented in the root `README.md`. + +## Steps + +### 1. Verify the `template` Remote + +```bash +git remote -v | grep template +``` + +If absent, add it and warn the user that the first sync requires `--allow-unrelated-histories`: + +```bash +git remote add template https://github.com/kritikos-io/templates-dotnet +git fetch --all +``` + +### 2. Check Working Tree + +`git status` must be clean. If it isn't, stop and ask the user to commit or stash before continuing. + +### 3. Pull + +- **First-time sync** (template remote was just added): + ```bash + git merge template/main --allow-unrelated-histories + ``` +- **Subsequent syncs**: + ```bash + git pull template main + ``` + +### 4. Resolve Conflicts + +Common conflict zones, with resolution guidance: + +| File / area | Strategy | +| --- | --- | +| `Solution.slnx`, `Solution.code-workspace` | Keep local — these are project-specific. Re-apply any new entries from upstream manually. | +| `Directory.Build.props`, `Directory.Build.targets`, `Directory.Packages.props` | Take upstream as the base, re-apply project-specific overrides on top. | +| `.github/instructions/`, `.github/skills/`, `.github/prompts/` | Take upstream; project-specific guidance should live in a *separate* file, never as edits to template-shipped files. | +| `README.md`, `LICENSE.md`, `icon.png` | Keep local — these are project-specific. | +| `docker/Dockerfile` | Take upstream; project-specific compose lives in `docker/compose.*.yaml`. | + +When a conflict needs human judgement, list it with file path + decision options rather than guessing. + +### 5. Verify + +```bash +dotnet restore --force-evaluate +dotnet build +dotnet test +``` + +If lock files moved, commit `packages.lock.json` updates. + +### 6. Commit + +Use a single merge commit; do not squash. Subject: + +``` +🔀 Syncs with kritikos-io/templates-dotnet +``` + +(Per [copilot-commit-message-instructions.md](../copilot-commit-message-instructions.md): gitmoji, third-person imperative.)