From e750a6b5d9215f14f4cd4ed933cd2ac0ae6f84bf Mon Sep 17 00:00:00 2001 From: Krzysztof Ploch Date: Sat, 12 Sep 2026 13:23:32 +0200 Subject: [PATCH 1/5] build(solution): Consume ploch-common as released packages Switch the cross-repo dependency on ploch-common from relative ProjectReference to PackageReference against the stable 4.0.47 release, so the packed libraries declare stable dependency ranges. A cross-repo ProjectReference becomes a NuGet dependency at pack time, carrying whatever version the sibling checkout happens to be on. The release therefore would have shipped a stable Ploch.CommandLine.Spectre depending on a prerelease Ploch.Common - fatal under NU5104 with TreatWarningsAsErrors. The packed nuspecs now list Ploch.Common, Ploch.Common.Apps.Shared and Ploch.Common.DependencyInjection at 4.0.47. Three defects had to be fixed for this to work at all: - nuget.config mapped Ploch.* only to GitHub Packages. Source mapping is longest-prefix-wins and exclusive, so nuget.org was never consulted for a Ploch package and the stable release was unreachable (NU1103). The pattern is now listed under both feeds. - The test projects declared no xunit packages, inheriting the harness through the sibling ProjectReference closure. A PackageReference only propagates what the nuspec declares, and Ploch.TestingSupport.XUnit3.Dependencies declares Microsoft.NET.Test.Sdk with exclude="Build,Analyzers" and omits xunit.runner.visualstudio entirely, so the suite built clean and discovered no tests. The harness is now declared in Directory.Build.props for every test project. - The solution included eight ploch-common source and test projects, so this repository compiled and tested another repository's code. Removed. UsePlochProjectReferences=true restores ProjectReference resolution for cross-repo development; both modes build clean and pass all 265 tests. release.yml no longer checks out ploch-common - it built only the main solution, so the sources were unused and the moving master ref was the last path by which a prerelease could reach a release. The sample now pins the stable 4.0.47 instead of 4.0.21-prerelease. It previously failed to build standalone with NU1109 then CS7069; it now builds with zero warnings, passes 41 tests and runs end to end. Ploch.Common.Apps.Shared is pinned locally because it is published but missing from the shared Ploch.Packages.props (mrploch/mrploch-development#21). Remaining CI cleanup: #51. Refs: #46 Refs: #47 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01MroAgPwA8tGuEPi2rz4qJU --- .github/workflows/release.yml | 13 +++--- Directory.Build.props | 43 +++++++++++++++++++ Directory.Packages.props | 20 ++++++++- Ploch.CommandLine.Spectre.slnx | 12 ------ nuget.config | 17 +++++++- samples/SampleApp/Directory.Packages.props | 19 +++++--- ...ommandLine.Spectre.FluentValidation.csproj | 12 +++++- .../Ploch.CommandLine.Spectre.Serilog.csproj | 7 ++- .../Ploch.CommandLine.Spectre.csproj | 11 ++++- ...Line.Spectre.FluentValidation.Tests.csproj | 9 +++- ...h.CommandLine.Spectre.Serilog.Tests.csproj | 9 +++- .../Ploch.CommandLine.Spectre.Tests.csproj | 11 ++++- .../Ploch.CommandLine.UseCases.Tests.csproj | 9 +++- 13 files changed, 155 insertions(+), 37 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cad917f..bde997b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -77,13 +77,12 @@ jobs: path: ploch-commandline fetch-depth: 0 - - name: Checkout ploch-common (sibling project references) - uses: actions/checkout@v4 - with: - repository: mrploch/ploch-common - ref: master - path: ploch-common - fetch-depth: 0 + # No ploch-common checkout. The release build consumes ploch-common as released NuGet + # packages (UsePlochProjectReferences defaults to false), so the sibling sources are not + # needed - and checking them out at the moving `master` branch is what made this workflow + # able to pack a stable package with prerelease Ploch.Common dependencies (issue #47). + # mrploch-development is still required: Directory.Packages.props imports the shared + # version files from it. - name: Checkout mrploch-development (shared build config) uses: actions/checkout@v4 diff --git a/Directory.Build.props b/Directory.Build.props index 8feb96e..33d0759 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -78,6 +78,27 @@ default + + + false + + @@ -102,4 +123,26 @@ + + + + + + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 1c8019e..e1d6aed 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,4 +1,4 @@ - + true @@ -10,7 +10,23 @@ - + + + + + + diff --git a/Ploch.CommandLine.Spectre.slnx b/Ploch.CommandLine.Spectre.slnx index eb14a9b..87a019b 100644 --- a/Ploch.CommandLine.Spectre.slnx +++ b/Ploch.CommandLine.Spectre.slnx @@ -1,16 +1,4 @@ - - - - - - - - - - - - diff --git a/nuget.config b/nuget.config index e3624d3..796a000 100644 --- a/nuget.config +++ b/nuget.config @@ -7,11 +7,24 @@ - + + diff --git a/samples/SampleApp/Directory.Packages.props b/samples/SampleApp/Directory.Packages.props index facd497..b5bbc00 100644 --- a/samples/SampleApp/Directory.Packages.props +++ b/samples/SampleApp/Directory.Packages.props @@ -1,4 +1,4 @@ - + @@ -30,11 +30,18 @@ - - - + + + diff --git a/src/Spectre/CommandLine.Spectre.FluentValidation/Ploch.CommandLine.Spectre.FluentValidation.csproj b/src/Spectre/CommandLine.Spectre.FluentValidation/Ploch.CommandLine.Spectre.FluentValidation.csproj index bd4627a..c3c3bcb 100644 --- a/src/Spectre/CommandLine.Spectre.FluentValidation/Ploch.CommandLine.Spectre.FluentValidation.csproj +++ b/src/Spectre/CommandLine.Spectre.FluentValidation/Ploch.CommandLine.Spectre.FluentValidation.csproj @@ -8,13 +8,21 @@ + + + + + + + + + - - + diff --git a/src/Spectre/CommandLine.Spectre.Serilog/Ploch.CommandLine.Spectre.Serilog.csproj b/src/Spectre/CommandLine.Spectre.Serilog/Ploch.CommandLine.Spectre.Serilog.csproj index 34c961c..b2f9615 100644 --- a/src/Spectre/CommandLine.Spectre.Serilog/Ploch.CommandLine.Spectre.Serilog.csproj +++ b/src/Spectre/CommandLine.Spectre.Serilog/Ploch.CommandLine.Spectre.Serilog.csproj @@ -21,7 +21,12 @@ - + + + + + + diff --git a/src/Spectre/CommandLine.Spectre/Ploch.CommandLine.Spectre.csproj b/src/Spectre/CommandLine.Spectre/Ploch.CommandLine.Spectre.csproj index 871af3b..411351a 100644 --- a/src/Spectre/CommandLine.Spectre/Ploch.CommandLine.Spectre.csproj +++ b/src/Spectre/CommandLine.Spectre/Ploch.CommandLine.Spectre.csproj @@ -37,10 +37,19 @@ - + + + + + + + + + + diff --git a/tests/Spectre/CommandLine.Spectre.FluentValidation.Tests/Ploch.CommandLine.Spectre.FluentValidation.Tests.csproj b/tests/Spectre/CommandLine.Spectre.FluentValidation.Tests/Ploch.CommandLine.Spectre.FluentValidation.Tests.csproj index 04dedfa..bdad956 100644 --- a/tests/Spectre/CommandLine.Spectre.FluentValidation.Tests/Ploch.CommandLine.Spectre.FluentValidation.Tests.csproj +++ b/tests/Spectre/CommandLine.Spectre.FluentValidation.Tests/Ploch.CommandLine.Spectre.FluentValidation.Tests.csproj @@ -13,8 +13,15 @@ - + + + + + + + + diff --git a/tests/Spectre/CommandLine.Spectre.Serilog.Tests/Ploch.CommandLine.Spectre.Serilog.Tests.csproj b/tests/Spectre/CommandLine.Spectre.Serilog.Tests/Ploch.CommandLine.Spectre.Serilog.Tests.csproj index dffdff3..3a06987 100644 --- a/tests/Spectre/CommandLine.Spectre.Serilog.Tests/Ploch.CommandLine.Spectre.Serilog.Tests.csproj +++ b/tests/Spectre/CommandLine.Spectre.Serilog.Tests/Ploch.CommandLine.Spectre.Serilog.Tests.csproj @@ -13,8 +13,15 @@ - + + + + + + + + diff --git a/tests/Spectre/CommandLine.Spectre.Tests/Ploch.CommandLine.Spectre.Tests.csproj b/tests/Spectre/CommandLine.Spectre.Tests/Ploch.CommandLine.Spectre.Tests.csproj index 3d3a060..64bdb6b 100644 --- a/tests/Spectre/CommandLine.Spectre.Tests/Ploch.CommandLine.Spectre.Tests.csproj +++ b/tests/Spectre/CommandLine.Spectre.Tests/Ploch.CommandLine.Spectre.Tests.csproj @@ -13,8 +13,17 @@ - + + + + + + + + + + diff --git a/tests/Spectre/CommandLine.UseCases.Tests/Ploch.CommandLine.UseCases.Tests.csproj b/tests/Spectre/CommandLine.UseCases.Tests/Ploch.CommandLine.UseCases.Tests.csproj index 6dbbad2..0cd1da4 100644 --- a/tests/Spectre/CommandLine.UseCases.Tests/Ploch.CommandLine.UseCases.Tests.csproj +++ b/tests/Spectre/CommandLine.UseCases.Tests/Ploch.CommandLine.UseCases.Tests.csproj @@ -13,8 +13,15 @@ - + + + + + + + + From 9232f0087d095eaaf5e00daaab8e56d77c4eff82 Mon Sep 17 00:00:00 2001 From: Krzysztof Ploch Date: Sat, 12 Sep 2026 13:28:30 +0200 Subject: [PATCH 2/5] ci(github-actions): Follow the ploch-common default branch rename ploch-common renamed its default branch from master to main, so every workflow that checked the sibling out at `master` failed before doing any work: build Clone ploch-common fatal: Remote branch master not found qodana actions/checkout A branch or tag with the name 'master' could not be found Confirmed against the remote: `git ls-remote --heads` lists `main` and no `master`. Pre-existing breakage rather than a consequence of the package switch - the last green build on main was 2026-08-28, before the rename. build-dotnet.yml keeps the clone: its `Build sample application` step deliberately runs -p:UsePlochProjectReferences=true so a library change cannot break the sample silently, and that needs the sources. Whether publish-docs and qodana still need the checkout at all now that the solution restores from packages is the open question in #51. Refs: #51 Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01MroAgPwA8tGuEPi2rz4qJU --- .agents/dotnet-dev-finishing-touches/SKILL.md | 242 +++++++++++--- .agents/implement-issue/SKILL.md | 302 +++++++++++++----- .claude/rules/naming.md | 65 +++- .claude/rules/pr-checks-completion-gate.md | 4 +- .claude/skills/dev-finishing-touches/SKILL.md | 30 +- .../dotnet-dev-finishing-touches/SKILL.md | 28 +- .claude/skills/implement-issue/SKILL.md | 268 +++++++++++----- .github/workflows/build-dotnet.yml | 2 +- .github/workflows/publish-docs.yml | 2 +- .github/workflows/qodana_code_quality.yml | 2 +- 10 files changed, 694 insertions(+), 251 deletions(-) diff --git a/.agents/dotnet-dev-finishing-touches/SKILL.md b/.agents/dotnet-dev-finishing-touches/SKILL.md index c991b51..ad8adf0 100644 --- a/.agents/dotnet-dev-finishing-touches/SKILL.md +++ b/.agents/dotnet-dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dotnet-dev-finishing-touches -description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — .NET Branch Quality Pass @@ -12,20 +12,32 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c **Core principles:** - **Fix, don't suppress** — suppressions are a last resort, never a shortcut. When suppression is genuinely needed, use `/dotnet-dev-practical` for the correct technique. + - **Verify every fix** — rebuild after every change. Never assume a fix worked. + - **Zero warnings before push** — every warning pushed costs a full CI round-trip (5-15 minutes). Fix locally in seconds. + - **Evidence before claims** — never report completion without build output, test counts, and CI status. + - **Backup before modify** — before editing any file, save a `.bak` copy so the user can review exactly what changed. See [Backup Before Modify](#backup-before-modify). + - **One unified TODO list drives the pass** — local warnings, failing CI checks, and PR comments/conversations all live in a single tracked list. The skill is not complete until every item on that list is resolved. See [Master TODO List](#phase-25-build-master-todo-list). + - **CI state is known up front, not after push** — a sub-agent inspects existing CI run status before any local work begins so failing checks are visible and planned from the start. See [Phase 1.5](#phase-15-ci-status-pre-check-sub-agent). + - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is reviewed by the Codex MCP (`mcp__codex-cli__codex`) **before the commit**, not after. Applies equally to warning fixes, CI-failure fixes, and PR-comment-driven fixes. See [Codex Validation Gate](#codex-validation-gate). + +- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). + - **Zero unaddressed PR comments** — every unresolved review thread must be triaged and closed out before the skill reports complete. Valid issues are fixed in code; false positives get a reply that cites specific evidence (what the code actually does, which test/spec proves it, why the analyser or reviewer was wrong). A thread is never left silent, and a bot-flagged thread is never closed without a reply. See [Phase 11](#phase-11-address-pr-comments-skip-if---no-push). + - **All-green completion gate — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: + 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. Bot-authored threads (CodeRabbit, Codacy comments, Bito) follow the same rules as human-authored. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the dotnet-dev-finishing-touches skill to perform a quality pass on the current branch." @@ -41,15 +53,17 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c Before running any phase, check these prerequisites. If one is missing, **stop and tell the user** — do not silently work around the gap. -| Requirement | Required for | Fallback if missing | -|-------------|-------------|---------------------| -| `dotnet` CLI (.NET 9+ SDK) | Phases 4, 5, 7 | Stop — the skill cannot run without it. | -| `gh` CLI, authenticated (`gh auth status`) | Phases 1, 1.5, 10, 11 | Stop if Phase 10/11 is in scope. For Phase 1/1.5 the skill can continue without PR context but must flag the gap in the report. | -| `git` CLI, working tree clean of unrelated changes | All phases | Stop and ask the user to commit/stash unrelated work. | -| `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | -| `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | -| `mcp__codex-cli__codex` | Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | -| `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | +| Requirement | Required for | Fallback if missing | +| -------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `dotnet` CLI (.NET 9+ SDK) | Phases 4, 5, 7 | Stop — the skill cannot run without it. | +| `gh` CLI, authenticated (`gh auth status`) | Phases 1, 1.5, 10, 11 | Stop if Phase 10/11 is in scope. For Phase 1/1.5 the skill can continue without PR context but must flag the gap in the report. | +| `git` CLI, working tree clean of unrelated changes | All phases | Stop and ask the user to commit/stash unrelated work. | +| `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | +| `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | +| `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | +| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | +| `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | +| `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | ## The Process @@ -84,6 +98,7 @@ digraph finishing_touches { more_warnings [shape=diamond, label="More warnings\nremaining?"]; grand_review [label="8. Grand Review\n(all changes, suggestions)"]; review_ok [shape=diamond, label="Changes\nready?"]; + ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot\n(parallel, full context, high effort)"]; apply [label="8b. Apply Suggestions"]; commit [label="9. Commit\n(/commit skill)"]; push_check [shape=diamond, label="--no-push?"]; @@ -129,7 +144,9 @@ digraph finishing_touches { more_warnings -> classify [label="yes"]; more_warnings -> grand_review [label="no"]; grand_review -> review_ok; - review_ok -> commit [label="yes"]; + review_ok -> ai_review [label="yes"]; + ai_review -> commit [label="no must-fix outstanding"]; + ai_review -> apply [label="must-fix findings"]; review_ok -> apply [label="no"]; apply -> build; commit -> push_check; @@ -172,25 +189,30 @@ cp "path/to/MyClass.cs" "path/to/MyClass.cs.bak" ### Phase 0: Detect Repository & Solution 1. **Find the repo root:** + ```bash REPO_ROOT=$(git rev-parse --show-toplevel) REPO_NAME=$(basename "$REPO_ROOT") ``` 2. **Locate the solution file.** Prefer `.slnx` over `.sln`. Prefer the file matching the repo name pattern (e.g. `Ploch.Common.slnx` in `ploch-common`): + ```bash find "$REPO_ROOT" -maxdepth 2 -name "*.slnx" -not -path "*/.history/*" -not -path "*/samples/*" | sort find "$REPO_ROOT" -maxdepth 2 -name "*.sln" -not -path "*/.history/*" -not -path "*/samples/*" | sort ``` + If multiple solution files exist and the correct one is ambiguous, present the list and ask the user. 3. **Detect the base branch:** + ```bash BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') if [ -z "$BASE_BRANCH" ]; then BASE_BRANCH=$(git branch -r | grep -oP 'origin/(main|master)' | head -1 | sed 's@origin/@@') fi ``` + Convention: `ploch-common` uses `master`; newer repos use `main`. 4. Store `REPO_ROOT`, `REPO_NAME`, `SOLUTION_FILE`, and `BASE_BRANCH` for all subsequent phases. @@ -202,6 +224,7 @@ cp "path/to/MyClass.cs" "path/to/MyClass.cs.bak" Gather full context about the branch's purpose. 1. **Check for an associated PR:** + ```bash gh pr view --json number,url,title,body,labels,state 2>/dev/null || echo "NO_PR" ``` @@ -209,9 +232,11 @@ Gather full context about the branch's purpose. 2. **If a PR exists**, extract linked issue numbers from the PR body (look for `Closes #N`, `Refs #N`, `Fixes #N`, `Resolves #N`). 3. **If a linked issue is found:** + ```bash gh issue view --json number,title,body,labels,comments ``` + Understand the issue requirements, acceptance criteria, and any discussion context. 4. **Understand the branch purpose** from all gathered context — PR description, issue body, branch name, commit messages. This context drives decisions in later phases (e.g. whether a warning fix would change the branch's intended behaviour). @@ -229,21 +254,27 @@ Gather full context about the branch's purpose. **Invocation:** Use the `Agent` tool with `subagent_type="general-purpose"` and brief it to: 1. Detect whether a PR exists for the current branch and whether any CI runs have started: + ```bash gh pr view --json number,url,statusCheckRollup 2>/dev/null gh run list --branch "$(git branch --show-current)" --limit 20 --json databaseId,name,status,conclusion,workflowName,headBranch,event,createdAt ``` + 2. For every check with `conclusion` other than `success`/`skipped`/`neutral` (i.e. `failure`, `cancelled`, `timed_out`, `action_required`, or still `in_progress`), fetch the failure logs: + ```bash gh pr checks --json name,state,link,description gh run view --log-failed ``` + 3. For each non-green check, extract and return a structured entry: + - Check name (e.g. `build-test-sonar / build`, `SonarCloud Code Analysis`) - Status / conclusion - Run ID and link - Root-cause excerpt (3–15 lines of the actual failing output — not the whole log) - Suggested TODO title (e.g. `Fix SonarCloud quality gate failure: duplicated blocks in Foo.cs`) + 4. Report back as a bullet list grouped by workflow. Under 300 words. **No fixes. No file edits.** **Brief template to pass to the sub-agent:** @@ -259,17 +290,20 @@ Gather full context about the branch's purpose. Build the complete picture of all changes on the branch. 1. **All committed changes vs base branch:** + ```bash git diff "$BASE_BRANCH"...HEAD --name-only ``` 2. **Uncommitted changes (staged + unstaged):** + ```bash git diff --name-only # unstaged git diff --staged --name-only # staged ``` 3. **Untracked files:** + ```bash git ls-files --others --exclude-standard ``` @@ -277,6 +311,7 @@ Build the complete picture of all changes on the branch. 4. **Merge** all lists into a deduplicated set of modified files. Filter to `.cs` files for code analysis phases. 5. **Read the full diffs** for context: + ```bash git diff "$BASE_BRANCH"...HEAD # committed changes git diff # unstaged @@ -296,8 +331,11 @@ Build the complete picture of all changes on the branch. **Required TODO sources — all three must be harvested, not just local issues:** 1. **Local build warnings** — from Phase 5. Initially seeded as a single placeholder TODO ("Run initial build and enumerate warnings on modified files"); once the build runs, the placeholder is expanded into one TODO per warning-on-modified-file. + 2. **Failing CI checks** — from the Phase 1.5 sub-agent's `CI_ISSUES` list. One TODO per non-green check, with the check name, run link, and root-cause excerpt referenced in the TODO body. + 3. **PR review threads, conversations, and reviews** — fetched here (not just in Phase 11). REST endpoints do not expose thread resolution state, so the primary source is the GraphQL `reviewThreads` connection: + ```bash # Thread IDs + resolution state (primary source for TODO creation) gh api graphql -f query=' @@ -315,12 +353,13 @@ Build the complete picture of all changes on the branch. } } }' -F owner= -F repo= -F pr= - + # Issue-level conversation comments (PR discussion, not inline review) gh api repos///issues//comments --paginate # Full review objects (for body-only reviews without inline comments) gh api repos///pulls//reviews --paginate ``` + **One TODO per unresolved, non-outdated review thread + one TODO per issue-comment that raises an actionable concern.** Resolved or outdated threads are excluded. Automated-bot threads (SonarCloud, Codacy, Dependabot, codeant-ai) are included — they must be triaged and replied-to the same as human reviewer threads. Record each thread's GraphQL `id` (e.g. `PRRT_...`) and the root comment's `databaseId` in the TODO body so Phase 11 can reply + resolve without re-fetching. **Additional sources folded in as the pass progresses:** @@ -329,16 +368,17 @@ Build the complete picture of all changes on the branch. - Coverage gaps identified in Phase 4 — one TODO per file under 80%. - Grand-review findings from Phase 8 — one TODO per actionable suggestion. - New items surfaced by Codex validation in the [Codex Validation Gate](#codex-validation-gate) — one TODO per Codex finding rated "must fix" or "should fix". +- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) — one TODO per Codex, Antigravity and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. **TODO item format:** -| Field | Content | -|-------|---------| -| Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | -| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex` | -| Reference | File + line / check name + run link / comment URL | -| Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | -| Status | `pending` → `in_progress` → `completed` | +| Field | Content | +| --------- | -------------------------------------------------------------------------------------------------- | +| Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | +| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `antigravity`, `copilot` | +| Reference | File + line / check name + run link / comment URL | +| Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | +| Status | `pending` → `in_progress` → `completed` | **Rules:** @@ -362,6 +402,7 @@ For each modified `.cs` file in a NuGet-producing project: 1. **Read the file** and identify all `public` members — classes, interfaces, structs, enums, records, methods, properties, constructors. 2. **For each public member without XML docs**, add documentation following `rules/documentation.md`: + - `` on all public types, methods, properties, constructors. - `` for each parameter. - `` for non-void methods. @@ -371,12 +412,14 @@ For each modified `.cs` file in a NuGet-producing project: - Follow Microsoft's style (reference `System.Text.Json`, `Microsoft.Extensions.DependencyInjection` for examples). 3. **For each public member with existing XML docs**, review for correctness: + - All parameters documented and named correctly (no stale `` tags for renamed/removed parameters). - Return value described accurately. - Summary matches current behaviour (not stale from a refactor). - Exception documentation matches actual throws. 4. Optionally use the Roslyn MCP tool for public API surface discovery: + ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_public_api ``` @@ -388,6 +431,7 @@ For each modified `.cs` file in a NuGet-producing project: ### Phase 4: Test Coverage Analysis 1. **Run tests with coverage:** + ```bash dotnet test "$SOLUTION_FILE" /p:CollectCoverage=true /p:CoverletOutput=./CoverageResults/ "/p:CoverletOutputFormat=cobertura%2copencover" ``` @@ -395,11 +439,13 @@ For each modified `.cs` file in a NuGet-producing project: 2. **Analyse coverage** on the modified files. The target is **>= 80%** on changed/new code. 3. Optionally use the Roslyn MCP tool for coverage mapping: + ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_test_coverage_map ``` 4. **If coverage is below 80%:** + - **Assess scope:** Can the missing tests be added without significant new test infrastructure (new test harnesses, database fixtures, complex mock setups)? - **If yes:** Add the missing tests following `rules/writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture. Test both positive and negative cases. Name tests: `_should_`. - **If no (significant new infra needed):** **STOP and ask the user** whether to proceed with test infrastructure creation or defer. @@ -411,6 +457,7 @@ For each modified `.cs` file in a NuGet-producing project: ### Phase 5: Build Solution 1. **Build with normal verbosity** to capture all warnings: + ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 ``` @@ -436,14 +483,15 @@ For each warning on a modified file, follow this decision tree: **YES — the code should be fixed:** 1. Plan the fix carefully. Before applying, check two safety gates: - **Safety Gate 1 — Public API impact:** Does the fix rename, remove, or change the signature of a public member? Does it add `sealed`, change a return type, or alter an interface? + - If **yes**: **STOP and ask the user.** Public API changes are a permanent commitment in a NuGet library. - If **no**: proceed to Safety Gate 2. - + **Safety Gate 2 — Semantic behaviour change:** Does the fix change the runtime behaviour of the code on this branch? (e.g. altering exception handling, changing data transformation logic, modifying control flow) + - If **yes**: **STOP and ask the user.** The finishing-touches pass should not alter the branch's intended behaviour without explicit approval. - If **no**: apply the fix. @@ -452,17 +500,21 @@ For each warning on a modified file, follow this decision tree: **NO — the warning is a false positive:** 1. Check: does the **same warning appear in 3 or more other files** across the solution? + ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 | grep "" | wc -l ``` 2. **If common (3+ files):** Disable globally in `.editorconfig` rather than suppressing inline: + ```ini dotnet_diagnostic..severity = none # ``` + For test-specific suppressions, use the nested `.editorconfig` in `tests/`. 3. **If isolated (< 3 files):** Suppress inline using the narrowest scope technique from `/dotnet-dev-practical`: + - **Single line:** `#pragma warning disable ` with `#pragma warning restore ` and a comment explaining why. - **Single member:** `[SuppressMessage("Category", "ID", Justification = "...")]` — the `Justification` is **mandatory**. - The suppression **must** include a documented reason. Never suppress without explaining why. @@ -472,6 +524,7 @@ For each warning on a modified file, follow this decision tree: #### Rules that must NEVER be suppressed Consult `/dotnet-dev-practical` → `analyzer-reference.md` → "Rules That Should Never Be Suppressed": + - VSTHRD002, VSTHRD100, VSTHRD110 (threading bugs) - CS8600-CS8777 (nullable violations — elevated to ERROR in workspace) - CA2100 (SQL injection), CA2153 (corrupted state exceptions) @@ -488,6 +541,7 @@ If one of these fires on a modified file, it indicates a real bug. Fix the code. After each fix or suppression in Phase 6: 1. **Rebuild the solution:** + ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 ``` @@ -507,6 +561,7 @@ After each fix or suppression in Phase 6: Review all changes made during the finishing-touches pass holistically. 1. **Read the full diff:** + ```bash git diff # unstaged finishing-touches changes git diff --staged # if anything was staged @@ -514,6 +569,7 @@ Review all changes made during the finishing-touches pass holistically. ``` 2. **Check for:** + - Consistency with the branch's original purpose — do all changes still make sense together? - Naming consistency (British English, camelCase, verb-first methods per `rules/naming.md`). - Unused imports or dead code introduced by fixes. @@ -521,10 +577,9 @@ Review all changes made during the finishing-touches pass holistically. - No leftover debugging code, TODO comments, or temporary workarounds. 3. **Project documentation review — keep markdown docs in sync with code changes.** - The branch's changes may have introduced new features, changed behaviour, added configuration options, or modified APIs that are described in the project's manually-authored markdown documentation. These docs **must** be updated to reflect the current state. - **Discovery — find all project documentation:** + ```bash # Primary location find "$REPO_ROOT/docs" -name "*.md" 2>/dev/null @@ -533,14 +588,16 @@ Review all changes made during the finishing-touches pass holistically. # Other common locations find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` - + **For each documentation file found**, check whether the branch's changes affect what it describes: + - **README.md** — Does it describe features, APIs, or usage patterns that have changed? Are installation instructions, quick-start examples, or configuration options still accurate? - **docs/*.md** — Do design documents, architecture guides, or spec files reference behaviour or APIs that the branch modified? Are code examples still valid? - **RELEASE_NOTES.md / CHANGELOG.md** — Should a new entry be added for user-visible changes (new features, breaking changes, significant bug fixes)? - **Any other `.md` files** in the project — plans, migration guides, API references. - + **What to do:** + - If a doc page describes something the branch changed → **update the doc** to match the new reality. - If a doc page contains code examples that reference modified APIs → **update or verify the examples**. - If a doc page describes a feature that was removed → **remove or update the section**. @@ -548,19 +605,77 @@ Review all changes made during the finishing-touches pass holistically. - **Do not create new documentation files** unless explicitly asked — this skill focuses on keeping existing docs accurate. 4. Optionally use Roslyn MCP tools for deeper analysis: + ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code ``` -4. **If suggestions are actionable and non-controversial**, apply them and loop back to Phase 5 (Build). +5. **If suggestions are actionable and non-controversial**, apply them and loop back to Phase 5 (Build). -5. **If suggestions require user input** or are outside the finishing-touches scope, record them for the completion report. +6. **If suggestions require user input** or are outside the finishing-touches scope, record them for the completion report. **Cross-reference:** `dotnet-claude-kit:80-20-review`, `dotnet-claude-kit:code-review-workflow`. --- +### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) + +**Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates one staged fix at a time): here every reviewer sees the **entire branch** and hunts for what the pass missed — correctness bugs, API-contract breaks, async and thread-safety hazards, suppressions that hide real defects, test gaps, better approaches. + +**Panel definition, invocation flags, preflight and fallbacks live in [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** Read it before running this phase; this section covers only what is specific to .NET library work. + +**When:** After the Grand Review (Phase 8), when the branch is in its intended final local state — zero build warnings, tests passing, coverage met. If findings force changes, apply them, loop back to Phase 5 (Build), and re-run the affected reviewer on the updated diff before proceeding. + +**All three reviewers run. In parallel. None is optional.** If one is unavailable, follow the fallback ladder in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Fallback Ladder — never silently downgrade the panel. A reviewer that was skipped or substituted is always named in the Phase 12 report with the reason. + +**Run the Copilot preflight first**, before assembling the context — a stale Copilot session surfaces as `421 Misdirected Request` on every call, and it is cheaper to discover that with a one-token probe than after building a full context package. + +#### Step 1 — Assemble the full context package (once, shared by all three) + +Reviewers receive the **entire context first**, then the review request. Build a single context document containing, in this order: + +1. **Repo primer:** what the library does, its public surface, its consumers, and the conventions that constrain changes — `Directory.Build.props` settings, central package management, the analyser set (StyleCop, Roslynator, SonarAnalyzer, NetAnalyzers), the zero-warning bar, xUnit v3 + FluentAssertions + AutoFixture testing standards, and the repo's versioning scheme (NBGV or `VersionPrefix`). +2. **Branch intent:** PR title + full body (or intended PR description if not yet opened), linked issue title + body, branch name. +3. **The complete diff:** `git diff "$BASE_BRANCH"...HEAD` plus any staged/unstaged finishing-touches changes. +4. **Full current contents of every modified file** — not just hunks; reviewers need surrounding types and members to judge contracts. +5. **Verification already performed:** build output (zero warnings), test counts and results, coverage figures on modified code, and every analyser suppression added in Phase 6 **with its justification**. +6. **The review brief** (last, after all context). + +**Review brief (same for all three reviewers):** + +> Review this branch as a senior .NET reviewer for a published NuGet library. Work at **maximum depth/effort** — this is a pre-merge gate, not a skim. Hunt specifically for: (1) correctness bugs in the C# changes; (2) **public API contract problems** — breaking changes to signatures, nullability annotations, or behavioural contracts that consumers depend on, and whether they are declared as breaking; (3) async/await correctness — missing `ConfigureAwait`, sync-over-async, unobserved tasks, `CancellationToken` not honoured; (4) thread-safety and disposal hazards; (5) **analyser suppressions that hide a real defect** rather than a false positive — challenge every suppression in the diff against its stated justification; (6) test gaps — untested edge cases, negative paths, and boundary conditions, judged against the xUnit v3 / FluentAssertions / AutoFixture conventions; (7) XML documentation that is missing, inaccurate, or contradicts the implementation; (8) allocation and performance regressions on hot paths; (9) simpler or more idiomatic approaches worth taking now. For each finding return: severity (`must-fix` / `should-fix` / `nit`), file + line, what is wrong, evidence, and a concrete suggested fix. If you find nothing in a category, say so explicitly. End with an overall verdict: `APPROVE`, `APPROVE_WITH_NOTES`, or `REQUEST_CHANGES`. + +#### Step 2 — Dispatch all three reviews in parallel + +- **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package at the highest reasoning effort the tool exposes. +- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. +- **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool, so there is no `mcp__copilot__*` to load. Use the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a scratch file and pass it via shell substitution rather than inlining it in the command line. + +Send all three requests in the same tool-call block so they run concurrently. If the package exceeds a transport's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the brief only after the final part — the requirement is *entire context first, then the review*. + +#### Step 3 — Triage the findings + +1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. +2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. +3. Triage each finding like a PR comment, using the seven-category model in [`pr-checks-completion-gate.md`](../../rules/pr-checks-completion-gate.md): valid → fix (backups, ask-gates for API/semantic changes, **Codex Validation Gate for non-trivial fixes**, then loop to Phase 5); disagree → record the finding **and** the evidence-based reason for declining in the report. A declined external finding is never silently dropped. +4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). +5. **A finding that would change the public API or semantic behaviour still hits the existing ask-gates** — an external reviewer's recommendation does not bypass the user's sign-off on breaking changes. + +#### Step 4 — Verify the reviewers changed nothing, then record + +Copilot runs with shell access, and `--deny-tool 'write'` does not cover shell redirections. Confirm the working tree is untouched: + +```bash +git status --porcelain +``` + +The output must match its pre-review state. Any difference is an unintended write — revert it and record the incident. + +Store for the Phase 12 report: each reviewer's verdict, finding counts by severity, which findings were fixed vs declined (with reasons), re-review outcomes, and the model each reviewer actually ran (Copilot's in particular, since a fallback to Kimi K3 must be visible). + +--- + ### Phase 9: Commit **Delegate to the `/commit` skill** for the actual commit creation. @@ -568,13 +683,18 @@ Review all changes made during the finishing-touches pass holistically. Before invoking `/commit`, ensure: 1. **All files are ready.** Stage specific files — **never** `git add -A` or `git add .`. **Exclude all `.bak` files** — they must never be staged or committed. Verify the **staged** index contains no `.bak` paths: + ```bash # Lists only files staged for commit — must be empty git diff --cached --name-only | grep -E '\.bak(/|$)' && echo "FAIL: .bak staged" || echo "OK" ``` + `git status` alone is **insufficient** because it also lists untracked `.bak` files, which are expected and allowed — the check must scope to the staged index. + 2. **The issue number** is known from Phase 1. If none was found, follow the lookup order in `rules/commits.md`: check PR → search issues → ask the user. + 3. **Breaking changes** are detected: check for removed/renamed public APIs, changed method signatures, changed defaults, changed serialisation formats. + 4. **The commit type** matches the nature of changes (typically `chore` or `refactor` for finishing-touches, but `fix` if a real bug was found and fixed, `docs` if only documentation was added). **Commit-message ownership.** The `/commit` skill handles generic mechanics (conventional format, HEREDOC, `Co-Authored-By` trailer) but **does not** enforce this workspace's `Refs: #` footer or `BREAKING CHANGE:` footer — those are per-repo rules from `rules/commits.md`. This skill is therefore responsible for: @@ -609,27 +729,34 @@ If the finishing-touches pass made changes across multiple logical areas (e.g. d **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. 1. **Pre-push build verification:** + ```bash dotnet build "$SOLUTION_FILE" ``` + If any warnings appear, **stop and fix before pushing**. 2. **Push:** + ```bash git push -u origin HEAD ``` 3. **Monitor ALL CI checks** (including non-required): + ```bash gh pr checks --watch ``` + If no PR exists, monitor via: + ```bash gh run list --branch "$(git branch --show-current)" --limit 5 gh run view --log-failed ``` 4. **On failure:** + - Retrieve failure logs: `gh run view --log-failed` - Diagnose the root cause from the actual error output. Do not guess. - Fix the issue. @@ -637,6 +764,7 @@ If the finishing-touches pass made changes across multiple logical areas (e.g. d - After pushing the fix, monitor checks again. Repeat until all green. 5. **Do not:** + - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence. - Push speculative fixes without reading the failure logs. @@ -685,15 +813,15 @@ gh api repos///pulls//reviews --paginate Classify each thread into **exactly one** category. Record the category on the thread's TODO: -| Category | Meaning | Required resolution path | -|----------|---------|--------------------------| -| `VALID_ISSUE` | The reviewer/analyser is correct and the code needs to change | Fix code → Codex (if non-trivial) → commit → push → CI green → reply citing commit + evidence → resolve thread | -| `FALSE_POSITIVE` | The flag is wrong — code is correct, analyser misread, reviewer misread the context | Reply with specific evidence (what the code actually does, which test/spec/invariant proves it, why the flag is wrong) → resolve thread | -| `ALREADY_FIXED` | The concern is valid but was resolved in a subsequent commit on this branch | Reply pointing at the specific commit hash + diff line → resolve thread | -| `SUGGESTION_ACCEPTED` | Non-blocking suggestion worth taking | Same flow as `VALID_ISSUE` | -| `SUGGESTION_DECLINED` | Non-blocking suggestion we decline on merit | Reply explaining why (principle, trade-off, out-of-scope + follow-up issue link) → resolve thread | -| `QUESTION` | Reviewer asked for clarification, no code change implied | Reply with the answer → resolve thread | -| `OUT_OF_SCOPE` | Valid concern but outside this PR's scope | Open a follow-up GitHub issue, reply linking the issue → resolve thread. Per `feedback_create_followup_issues` memory — always file the issue, never defer verbally. | +| Category | Meaning | Required resolution path | +| --------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `VALID_ISSUE` | The reviewer/analyser is correct and the code needs to change | Fix code → Codex (if non-trivial) → commit → push → CI green → reply citing commit + evidence → resolve thread | +| `FALSE_POSITIVE` | The flag is wrong — code is correct, analyser misread, reviewer misread the context | Reply with specific evidence (what the code actually does, which test/spec/invariant proves it, why the flag is wrong) → resolve thread | +| `ALREADY_FIXED` | The concern is valid but was resolved in a subsequent commit on this branch | Reply pointing at the specific commit hash + diff line → resolve thread | +| `SUGGESTION_ACCEPTED` | Non-blocking suggestion worth taking | Same flow as `VALID_ISSUE` | +| `SUGGESTION_DECLINED` | Non-blocking suggestion we decline on merit | Reply explaining why (principle, trade-off, out-of-scope + follow-up issue link) → resolve thread | +| `QUESTION` | Reviewer asked for clarification, no code change implied | Reply with the answer → resolve thread | +| `OUT_OF_SCOPE` | Valid concern but outside this PR's scope | Open a follow-up GitHub issue, reply linking the issue → resolve thread. Per `feedback_create_followup_issues` memory — always file the issue, never defer verbally. | **A thread must never be closed without a reply.** "Resolve with no response" is only acceptable when the thread was authored by us and had no other participants. @@ -714,23 +842,34 @@ For bot-flagged false positives (SonarCloud, Codacy, codeant-ai): the same bar a For each thread in these categories: 1. Mark the TODO `in_progress`. + 2. Create `.bak` copies of all files the fix will touch (per [Backup Before Modify](#backup-before-modify)). + 3. Plan the fix. Apply the [Safety Gate 1 — Public API impact](#phase-6-classify--address-each-warning) and [Safety Gate 2 — Semantic behaviour change](#phase-6-classify--address-each-warning) checks from Phase 6. + 4. **Codex validation (mandatory before commit for non-trivial fixes)** — invoke the [Codex Validation Gate](#codex-validation-gate) with the thread URL, original code, proposed diff, and reasoning. Do **not** commit until the verdict is `APPROVED` or `APPROVED_WITH_NOTES`. + 5. Apply the fix. Rebuild (loop back to Phase 5 → Phase 7 if warnings regress). Run the affected tests. + 6. Commit (via the `/commit` skill — one commit per logical thread group; batching threads that touch the same file or concern is fine, but the commit message body must list every thread addressed). **Never amend.** + 7. Push. Monitor CI via Phase 10 until all checks are green. + 8. Reply on the thread (using the root `databaseId` as `in_reply_to`): + ```bash gh api repos///pulls//comments \ -f body=' and the specific change>' \ -F in_reply_to= ``` + 9. Resolve the thread: + ```bash gh api graphql -f query='mutation($id:ID!){resolveReviewThread(input:{threadId:$id}){thread{id isResolved}}}' \ -F id= ``` + 10. Mark the TODO `completed` and record the reply URL + commit hash on the TODO for the Phase 12 report. #### Step 5 — Reply-only workflow for FALSE_POSITIVE / SUGGESTION_DECLINED / ALREADY_FIXED / QUESTION / OUT_OF_SCOPE @@ -799,10 +938,12 @@ Pass forward for the completion report: **Additionally required when Phase 11 ran (`--no-push` OFF AND a PR exists):** 6. **Zero unaddressed PR review threads.** Re-run the Phase 11 Step 1 GraphQL enumeration one final time. Every thread in the result must satisfy one of: + - `isResolved=true`, **or** - `isResolved=false` AND the latest comment on the thread is authored by us AND the thread is listed under "Awaiting reviewer" in the final report. - + Any thread that is `isResolved=false` with the latest comment authored by someone other than us is **unaddressed** — loop back to Phase 11 Step 2. + 7. **No new PR activity has arrived since the last poll.** Re-fetch issue comments and reviews one final time. If anything new has appeared (new inline comments, new review, new issue comment), extend the TODO list and loop back to Phase 11. If any applicable condition is not satisfied, **do not report completion.** State which gate failed and continue the loop. @@ -822,6 +963,14 @@ Provide a summary with evidence: - **Test Coverage:** ~% on modified code ( tests added) - **Warnings Resolved:** fixed, suppressed (with justification), disabled globally - **Code Review Fixes:** improvements applied +- **External-review fixes:** from Codex, from Antigravity, from Copilot, declined with reasons + +### External AI Review +| Reviewer | Model | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | +|----------|-------|---------|----------|------------|-----|-------|--------------------------| +| Codex | ... | ... | n | n | n | n | n | +| Antigravity | ... | ... | n | n | n | n | n | +| Copilot | `grok-4.6` | ... | n | n | n | n | n | ### Warning Resolution Summary | Warning ID | File | Resolution | Justification | @@ -876,19 +1025,22 @@ done ``` **Cleanup command:** + ```bash find . -name "*.bak" -not -path "*/bin/*" -not -path "*/obj/*" -delete ``` ### Commit + `` — `` + ``` --- ## Codex Validation Gate -**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. +**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. **Timing rule:** Codex runs on the *uncommitted* diff. The correct sequence is: stage files → invoke Codex on the staged diff → act on the verdict → commit. If you are already mid-commit when you realise the gate was skipped, reset the staging, run Codex, then re-stage and commit as a single commit. Do **not** commit first and retroactively "validate" — that defeats the gate. @@ -967,6 +1119,7 @@ Use the `codex` action of `mcp__codex-cli__codex` with a self-contained brief. T When CI fails or PR comments require code changes: ``` + Fix code → Phase 5 (Build — zero warnings locally) → Phase 7 (Rebuild & Verify) → Phase 8 (Grand Review) @@ -975,6 +1128,7 @@ Fix code → Phase 5 (Build — zero warnings locally) → Phase 10 (Monitor CI) → Phase 11 (Address Comments) → Phase 12 (Report) + ``` Each iteration creates a **new commit**. After all fixes are done, update the PR description to reflect the **final** state. @@ -1032,6 +1186,10 @@ If you catch yourself about to do any of these, stop and reconsider: - About to **apply a non-trivial fix without a Codex MCP review** — non-trivial fixes must pass the Codex Validation Gate **before the commit**, not after. - About to **commit a PR-comment-driven code change without running Codex first** — PR-comment fixes are never exempt from the gate; stage, validate, then commit. - About to **silently skip the Codex gate because the MCP is unavailable** — retry or explicitly ask the user; never pretend the gate passed. +- About to **skip Phase 8.5** or run fewer than **all three** external reviewers without the user's explicit sign-off. +- About to let Copilot's `--model` fall back to `auto`, or to omit `--effort high` — both silently downgrade the review. +- About to **run Copilot without the read-only `--deny-tool` set**, or to skip the post-review `git status --porcelain` check. +- About to **silently drop an external reviewer's `must-fix`** — every one is fixed or declined with recorded evidence. - About to **reply to a PR comment with a generic "false positive" message** — every false-positive reply must cite specific evidence (file/line, test, spec, invariant) per [Step 3 — Reply quality rules](#step-3--reply-quality-rules-especially-for-false_positive). - About to **resolve a PR review thread without posting a reply first** — a resolved thread without an explicit response does not count as addressed; the only exception is a thread we authored ourselves with no other participants. - About to **leave a thread unresolved after replying to a bot** (SonarCloud, Codacy, codeant-ai, Dependabot) — bot threads always get both a reply and a resolve. @@ -1055,6 +1213,7 @@ If you catch yourself about to do any of these, stop and reconsider: | 6. Warnings | Each warning classified and addressed | Resolution documented per warning | | 7. Verify | Warning resolved after each fix | Rebuild output confirms | | 8. Grand Review | All changes reviewed holistically | No outstanding concerns | +| 8.5 External AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer | Commit message | | 10. CI | All checks green (including non-required) | `gh pr checks` output | | 11. PR Comments | Every thread triaged, fixed-or-replied, and (for bots + clear-cut cases) resolved | Zero `isResolved=false` threads whose latest comment is not ours; category breakdown recorded | @@ -1095,10 +1254,13 @@ If you catch yourself about to do any of these, stop and reconsider: - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_test_coverage_map` — Coverage analysis - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns` — Anti-pattern detection - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code` — Unused code detection -- **`mcp__codex-cli__codex`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)). Use `ToolSearch` to load the schema if not already available. +- **`mcp__codex-cli__codex` / `mcp__codex-cli__review`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)) and one third of the Phase 8.5 panel. Use `ToolSearch` to load the schema if not already available. +- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check +- **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - GitHub CLI (`gh`) — PR management, CI monitoring, comment handling **Uses these tools for sub-agent / TODO orchestration:** - `Agent` (with `subagent_type="general-purpose"`) — the Phase 1.5 CI pre-check sub-agent. - `TaskCreate` / `TaskUpdate` / `TaskList` — master TODO list in Phase 2.5 and ongoing throughout the pass. - `mcp__contextstream__memory(action="create_todo")` — optional alternative to `TaskCreate` when ContextStream is active. +``` diff --git a/.agents/implement-issue/SKILL.md b/.agents/implement-issue/SKILL.md index 4c1a655..f16c8a4 100644 --- a/.agents/implement-issue/SKILL.md +++ b/.agents/implement-issue/SKILL.md @@ -12,15 +12,20 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet **Core principles:** - **Maximum autonomy** — research before asking. Only ask the user when genuinely blocked after exhausting all research options. + - **Maximum thoroughness** — every phase has explicit quality gates. No shortcuts. No skipped steps. + - **Evidence before claims** — never report completion without evidence (build output, test counts, CI status, PR URL). + - **All comments addressed** — every single PR comment and conversation must be addressed. No exceptions. Bot-authored threads (CodeRabbit, Codacy, Bito, SonarCloud) follow the same triage rules as human reviewers. SonarCloud / SonarQube Cloud additionally reports issues that exist **only in the SonarCloud platform** (not as GitHub comments) — these are fetched via the `sonarqube-cloud` MCP server and resolved with the same seven-category triage. + - **All checks pass — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: + 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the implement-issue skill to implement GitHub issue #\." @@ -28,15 +33,24 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet ## Invocation ``` -/implement-issue # Full end-to-end -/implement-issue --no-push # Implement + commit locally, skip push/PR/CI +/implement-issue | # Full end-to-end +/implement-issue | --no-push # Implement + commit locally, skip push/PR/CI ``` -Supported URL formats: +### Supported URL formats + +**For GitHub issues:** + - `https://github.com///issues/` - `/#` - `#` (current repo) +**For Linear issues:** + +- `https://linear.app//issue//` +- `<team>/<linear-issue-id>` +- `<linear-issue-id>` (Linear workspace/team from repository `## Project Scope` in `CLAUDE.md`, or the mirrored section in `AGENTS.md` / `GEMINI.md` / `.github/copilot-instructions.md`) + **`--no-push` flag:** When set, skip all push, PR creation, CI monitoring, and PR comment resolution steps. Commit locally only. ## The Process @@ -49,7 +63,7 @@ digraph implement_issue { fetch [label="0. Fetch & Parse Issue"]; repo [label="1. Identify Target Repository"]; research [label="2. Research & Gather Context"]; - plan [label="3. Plan Implementation\n(Codex reviews plan)"]; + plan [label="3. Plan Implementation\n(Codex + Copilot + Antigravity review plan)"]; blocked [shape=diamond, label="Genuinely\nblocked?"]; ask [label="Ask user"]; branch [label="4. Create Branch"]; @@ -57,7 +71,7 @@ digraph implement_issue { build [label="6. Build & Static Analysis\n(Zero new warnings)"]; test [label="7. Test\n(All pass, coverage gates)"]; review [label="8. Self-Review\n(git diff, patterns, docs)"]; - codex [label="9. Codex Review"]; + codex [label="9. External AI Review\nCodex + Antigravity + Copilot"]; issues [shape=diamond, label="Issues\nfound?"]; commit [label="10. Commit\n(Conventional, Refs: #issue)"]; push_check [shape=diamond, label="--no-push?"]; @@ -65,7 +79,7 @@ digraph implement_issue { monitor [label="12. Monitor CI Checks\n(ALL checks incl. non-required)"]; ci_ok [shape=diamond, label="All checks\npass?"]; fix_ci [label="Read logs, diagnose, fix"]; - comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud issues)"]; + comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud, Codacy issues + any other issue)"]; comments_ok [shape=diamond, label="All addressed?\nNo new comments?"]; gate [label="14. Completion Gate\n(All criteria met?)"]; gate_ok [shape=diamond, label="Pass?"]; @@ -102,36 +116,49 @@ digraph implement_issue { ### Phase 0: Fetch & Parse Issue 1. **Parse the URL** to extract `owner`, `repo`, and `issue-number`. + 2. **Fetch the full issue:** + ```bash gh issue view <number> --repo <owner>/<repo> --json number,title,body,labels,assignees,milestone,state,comments,projectItems ``` + 3. **Extract and understand:** + - **Title** and **description** — what needs to be done. - **Acceptance criteria** — look for a section in the body (e.g. "## Acceptance Criteria", "### AC", checkboxes). If none, derive from the description. - **Labels** — determine change type (`bug` → fix, `enhancement`/`feature` → feature, `documentation` → docs, etc.). - **Linked issues/PRs** — referenced in the body or comments (`#123`, `Depends on ...`). - **Comments** — additional context, clarifications, decisions from the discussion. + 4. **If the issue is closed** or already has a linked merged PR that fully addresses it, stop and inform the user. ### Phase 1: Identify Target Repository 1. Determine the target repository from the issue URL. + 2. Map to the local workspace directory: `C:\DevNet\my\mrploch\<repo-name>\`. + 3. Verify the repo is cloned: + ```bash ls "C:/DevNet/my/mrploch/<repo-name>" ``` + 4. Navigate to the repo and ensure it is up to date: + ```bash cd "C:/DevNet/my/mrploch/<repo-name>" git fetch origin git status ``` + 5. Identify the base branch (`main` or `master`): + ```bash git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' ``` + If that fails, check `git branch -r` for `origin/main` or `origin/master`. `ploch-common` uses `master`; newer repos use `main`. ### Phase 2: Research & Gather Context @@ -139,38 +166,49 @@ digraph implement_issue { Before writing any code, build comprehensive understanding. This phase is critical — thorough research prevents wasted implementation time. 1. **Read the target repo:** + - README.md, CLAUDE.md, `.claude/rules/` files. - Relevant source files in the area of change. - Existing tests for the affected modules. - Project structure (`src/`, `tests/`, solution files). - `Directory.Build.props`, `Directory.Packages.props` for build configuration. + 2. **Check related issues and PRs:** + ```bash # Related issues (open and closed) gh issue list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 # Related PRs (open and recently closed/merged) gh pr list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 ``` + 3. **Read linked or related PRs** for context on prior decisions and approaches: + ```bash gh pr view <pr-number> --repo <owner>/<repo> --json title,body,files,commits gh pr diff <pr-number> --repo <owner>/<repo> ``` + 4. **Check sibling repos** for patterns — browse `C:\DevNet\my\mrploch\` siblings: + - `ploch-common` — extension methods, serialisation, DI bundles, CRUD endpoints. - `ploch-data` — repository pattern, Unit of Work, entity configurations, Specification. - `ploch-lists`, `ploch-groupmatters` — application-level patterns (API, data layer, model). - `mrploch-development` — shared build config, dependency versions. + 5. **Research externally** if needed: + - Microsoft Learn docs: `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` - Library documentation via Context7: `mcp__plugin_context7_context7__resolve-library-id` then `query-docs` - External repo understanding via DeepWiki: `mcp__plugin_10x-swe_deepwiki__ask_question` - Web search for non-obvious problems or unfamiliar APIs. + 6. **Understand the area of change** — read the specific files, classes, and methods that will be affected. Trace call chains. Understand the data flow. Identify what tests exist and what patterns they follow. ### Phase 3: Plan Implementation 1. **Create a detailed plan** using **TodoWrite** with sub-tasks covering: + - Implementation tasks (code changes, new files, modified files). - Test creation (unit tests, integration tests if needed, bug-reproducing test if it's a bug fix). - Documentation tasks (XML docs on new public APIs, README/doc page updates). @@ -180,28 +218,35 @@ Before writing any code, build comprehensive understanding. This phase is critic - Commit. - Push/PR (unless `--no-push`). -2. **Consult Codex for plan review:** +2. **Consult two external models for plan review** — send both requests in the same tool-call block so they run concurrently: + ``` - mcp__codex-cli__codex + mcp__codex-cli__codex # OpenAI lens + copilot -p "<plan brief>" --model grok-4.6 … # xAI lens, via Bash — see rules/external-ai-review.md ``` - Send the plan along with: + + Send the plan to each along with: + - The issue description and acceptance criteria. - Key files and patterns discovered during research. - Any design decisions you've made and their rationale. - Ask Codex to review the plan for completeness, correctness, and adherence to project patterns. + Ask each to review the plan for completeness, correctness, and adherence to project patterns. A plan is cheap to fix and expensive to get wrong, so it earns two independent opinions before any code is written. Full Copilot flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md). -3. **Address Codex feedback** — adjust the plan if Codex identifies gaps, risks, or improvements. +3. **Address the feedback** — adjust the plan if either reviewer identifies gaps, risks, or improvements. Where they disagree, judge on the evidence; if the disagreement is both genuine and load-bearing, surface it to the user rather than picking silently. 4. **Auto-proceed** unless there are genuinely blocking questions that cannot be resolved by research or best judgment. Resolve uncertainties yourself in most cases. ### Phase 4: Create Branch 1. Ensure you are on the base branch and it is up to date: + ```bash git checkout <base-branch> && git pull origin <base-branch> ``` + 2. Determine the change type from the issue analysis (Phase 0). Mapping: + - `bug` label or bug-related title → `fix` - `enhancement`/`feature` label or new capability → `feature` - Documentation-only → `docs` @@ -209,10 +254,13 @@ Before writing any code, build comprehensive understanding. This phase is critic - Code restructuring without behaviour change → `refactor` - Performance improvement → `perf` - Tests only → `test` + 3. Create the branch following the naming convention (see `rules/branch-naming.md`): + ```bash git checkout -b <change-type>/<issue-number>-<brief-description> ``` + Example: `feature/72-dbcontext-creation-lifecycle-plugins`, `fix/187-duplicate-entity-concurrent-upsert` ### Phase 5: Implement @@ -248,7 +296,9 @@ When the issue is a bug fix: #### Documentation - **XML documentation** on all new/modified public types, methods, properties (for public/open-source packages). Follow Microsoft's style. Include `<example>` blocks where usage is not obvious. See `rules/documentation.md`. + - **Update project markdown documentation** — manually-authored `.md` files must stay in sync with the code. Discover all project docs: + ```bash REPO_ROOT=$(git rev-parse --show-toplevel) # Primary: docs/ folder, root-level docs, and any other .md files in the project @@ -256,7 +306,9 @@ When the issue is a bug fix: ls "$REPO_ROOT"/README.md "$REPO_ROOT"/RELEASE_NOTES.md "$REPO_ROOT"/CHANGELOG.md 2>/dev/null find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` + For each documentation file found, check whether your changes affect what it describes: + - **README.md** — features, APIs, usage patterns, installation instructions, quick-start examples, configuration options. - **docs/*.md** — design documents, architecture guides, spec files, migration guides, API references. - **RELEASE_NOTES.md / CHANGELOG.md** — add entries for user-visible changes (new features, breaking changes, significant bug fixes). @@ -266,6 +318,7 @@ When the issue is a bug fix: #### SampleApp (ploch-data only) If working on the `ploch-data` repository and the change adds or modifies library features: + - Update the SampleApp to demonstrate the new/changed features. - The SampleApp must use NuGet package references, not ProjectReference. - See `rules/sample-apps.md`. @@ -285,6 +338,7 @@ Read the **entire** build output. Do not skim. #### Step 2: Catalogue every warning Go through every warning in the build output. These come from: + - **StyleCop.Analyzers** — naming, documentation, layout, ordering. - **Roslynator.Analyzers** — code simplification, redundancy, best practices. - **SonarAnalyzer.CSharp** — bugs, code smells, security hotspots. @@ -311,12 +365,12 @@ The build output must show **zero warnings**. If any remain, go back to Step 3. #### Summary -| Gate | Requirement | -|------|-------------| -| Compilation | Zero errors | -| Static analysis warnings | Zero (all fixed) | -| Code style (.editorconfig) | Zero violations | -| Suppressions added | Zero (unless justified and documented) | +| Gate | Requirement | +| -------------------------- | -------------------------------------- | +| Compilation | Zero errors | +| Static analysis warnings | Zero (all fixed) | +| Code style (.editorconfig) | Zero violations | +| Suppressions added | Zero (unless justified and documented) | ### Phase 7: Test @@ -347,91 +401,147 @@ Before committing, review your own changes thoroughly: 3. Re-validate against the original issue requirements and acceptance criteria from Phase 0. Did you implement everything that was asked? Did you miss any AC? 4. If anything needs improvement: fix it, then loop back to **Phase 6** (Build). -### Phase 9: Codex Review +### Phase 9: External AI Review — Codex + Antigravity + Copilot + +**Panel definition, invocation flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** + +All three reviews are **mandatory** for every non-trivial change — three providers, three sets of blind spots. Run them in parallel (one tool-call block) and pass **full context** to each: the issue number + title + requirements, the design decisions taken and why, the diff (`git diff <base-branch>...HEAD`), verification evidence (build/test results), and a request for a structured verdict (`APPROVED` / `APPROVED_WITH_NOTES` / `CHANGES_REQUESTED` / `REJECTED` with concrete findings). + +1. **Codex review:** + + ``` + mcp__codex-cli__review (or mcp__codex-cli__codex with a review brief) + ``` + + Provide the diff and full context as above. **Fallback:** if the Codex MCP is unavailable (e.g. account/model restriction — try at least one alternative model before concluding), substitute an independent local review agent (e.g. `feature-dev:code-reviewer`) with the same brief, and record the substitution in the PR description and completion report. Never silently skip the second opinion. + +2. **Antigravity review:** -1. **Submit changes for Codex review:** ``` - mcp__codex-cli__review + mcp__antigravity__ask_antigravity (model="gemini-3.1-pro-high", paths=[...]) ``` - Provide the diff (`git diff <base-branch>...HEAD`) and context about what was changed and why. -2. **Review Codex feedback** — evaluate each suggestion on merit. -3. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build). -4. **Document disagreements** — if you disagree with a Codex suggestion, note your reasoning. This is acceptable — not every suggestion must be implemented. + + Provide the same full-context brief and the diff. Ask specifically for: correctness issues, missed edge cases, API-contract concerns, and test-coverage gaps. + +3. **Copilot review:** + + ```bash + copilot -p "$BRIEF" --model grok-4.6 --effort high --allow-all-tools \ + --deny-tool 'write' --disable-builtin-mcps --no-ask-user -s --log-level none -C "$REPO_ROOT" + ``` + + Shell-out through `Bash` — Copilot is **not** an MCP server, so there is no `mcp__copilot__*` tool to load. Use the full canonical flag set from [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (the abbreviated form above omits the `shell(git …)` / `shell(gh …)` denials). Run the preflight first; on failure follow the fallback ladder (retry with `GITHUB_TOKEN`/`GH_TOKEN`/`COPILOT_GITHUB_TOKEN` stripped → Kimi K3 → ask the user). Afterwards verify `git status --porcelain` is unchanged. + +4. **Review all feedback** — evaluate each suggestion from all three reviewers on merit. Deduplicate overlapping findings, crediting each reviewer that raised them; a finding raised independently by two model families is higher-confidence. + +5. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build), then re-run the affected reviewer on the revised diff. + +6. **Document disagreements** — if you disagree with a suggestion, note your reasoning (in the PR description's Design Decisions section if user-visible). This is acceptable — not every suggestion must be implemented, but a declined finding is recorded with its evidence, never silently dropped. + +7. **Record which model each reviewer ran** — Copilot's in particular, so a fallback to Kimi K3 is visible in the completion report. **Skip this phase** only for truly trivial changes (single-line typo fix, config-only change). ### Phase 10: Commit - **One commit per logical change** — typically one commit for the entire issue. For large issues with naturally separable parts, use multiple focused commits. + - **Conventional Commits** format (see `rules/commits.md`): + ``` <type>(<scope>): <subject> - + <body — what changed and why> - + [BREAKING CHANGE: <description>] Refs: #<issue-number> ``` + - The `Refs: #<issue-number>` footer is **mandatory**. The issue number comes from Phase 0. + - Detect and document breaking changes — check for removed/renamed public APIs, changed signatures, changed defaults. Add `BREAKING CHANGE:` footer if any. + - Stage specific files — **never** `git add -A` or `git add .`. + - **Never amend** existing commits unless the user explicitly asks. + - Update the change log if the commit contains user-visible changes (new features, breaking changes, significant fixes). ### Phase 11: Push & Create PR (skip if `--no-push`) 0. **Pre-push build verification** — before any push, run a final clean build of the full solution and confirm **zero warnings**: + ```bash dotnet build <solution-file> ``` + If any warnings appear, **stop and fix them before pushing**. This is critical — every warning you let through will come back as a CI failure or PR comment, costing a full pipeline round-trip. Fix locally first. 1. **Push the branch:** + ```bash git push -u origin HEAD ``` 2. **Check for existing PR:** + ```bash gh pr view --json number,url 2>/dev/null || echo "NO_PR" ``` 3. **Read PR template** (if it exists): + ```bash cat .github/pull_request_template.md 2>/dev/null || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null ``` 4. **Create PR** with a detailed description following `rules/pr-descriptions.md`: + ```bash gh pr create --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF' ## Summary - + <What this PR does and why. Reference the issue.> - + ## Changes - + - <Specific change 1> - <Specific change 2> - ... - + ## Design Decisions - + <Non-obvious choices and their rationale> - + ## Testing - + - Unit tests: <count> added/modified - Manual verification: <what was tested> - Coverage: ~<percentage>% on new code - + ## Related - + Closes #<issue-number> EOF )" && gh pr edit --add-assignee @me ``` -5. **If updating an existing PR** (e.g. after fix loop): +4b. **Request a GitHub Copilot review (mandatory):** immediately after creating the PR, request Copilot as a reviewer via the GitHub MCP tool: + +``` +mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) +``` + + Fallback if the MCP tool is unavailable: + +```bash +gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" +``` + + Copilot's review comments are then addressed in Phase 13 like any other reviewer's. + +1. **If updating an existing PR** (e.g. after fix loop): + ```bash gh pr edit <pr-number> --body "$(cat <<'EOF' [updated body reflecting final state] @@ -446,18 +556,21 @@ Before committing, review your own changes thoroughly: **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. A bot that says `fail` because it hasn't yet rescanned the latest commit is **still failing** by the gate's definition — wait for the rescan or push a no-op-ish commit to retrigger; do not declare completion with a "stale check" caveat. 1. **Wait for ALL checks** to complete — **including non-required checks:** + ```bash gh pr checks <pr-number> --watch ``` 2. **If any check fails:** a. Retrieve the failure logs: - ```bash - # Find the failed run - gh run list --branch <branch-name> --limit 5 - # Get failure details - gh run view <run-id> --log-failed - ``` + + ```bash + # Find the failed run + gh run list --branch <branch-name> --limit 5 + # Get failure details + gh run view <run-id> --log-failed + ``` + b. **Diagnose the root cause** — read the actual error output. Do not guess. c. If the failure is not obvious, research the error (web search, docs, sibling repos for how they handle it). d. Fix the issue in code. @@ -465,6 +578,7 @@ Before committing, review your own changes thoroughly: f. After pushing the fix, monitor checks again. Repeat until **all green**. 3. **Do not:** + - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence (check if the same test fails consistently). - Push speculative fixes without reading the failure logs. @@ -506,6 +620,7 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary #### GitHub PR comments, review threads & conversations 1. **Fetch all PR feedback:** + ```bash # Review comments (inline on code) gh api repos/<owner>/<repo>/pulls/<pr-number>/comments --paginate @@ -516,12 +631,14 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 2. **For each comment or conversation:** + - If it identifies a **valid issue** → fix the code. - If it is a **false positive or irrelevant** → reply with a clear, specific explanation of why you believe so. Do not just say "false positive" — explain the reasoning. - If it is a **suggestion worth considering** → evaluate on merit. Implement if it improves the code; explain why not if you disagree. - **Every single conversation must have a response.** No comment left unaddressed. It does not matter whether it is blocking the merge or not. 3. **Reply to comments:** + ```bash # Reply to a review comment gh api repos/<owner>/<repo>/pulls/<pr-number>/comments/<comment-id>/replies -f body="<your reply>" @@ -530,12 +647,14 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 4. **If code changes were made:** + - Commit the fixes (new commit, never amend). - Push. - **Loop back to Phase 12** (monitor CI checks again). - After checks pass, re-fetch comments — new automated comments may have been added by the new push. 5. **Only proceed when:** + - Zero unaddressed conversations remain. - No new comments have appeared since your last round of responses. - All CI checks are still green after the latest push. @@ -555,21 +674,21 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary Before reporting completion, **every single one** of these criteria must be met: -| # | Criterion | How to Verify | -|---|-----------|---------------| -| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | -| 2 | All tests pass | Test output with counts | -| 3 | Test coverage ≥80% on new code | Coverage report or estimate | -| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | -| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | -| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | -| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | -| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | -| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | -| 10 | SampleApp works (if ploch-data) | Manual test | -| 11 | Conventional commit with `Refs: #issue` | Commit log | -| 12 | PR description documents all changes and decisions | PR body | -| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | +| # | Criterion | How to Verify | +| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | +| 2 | All tests pass | Test output with counts | +| 3 | Test coverage ≥80% on new code | Coverage report or estimate | +| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | +| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | +| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | +| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | +| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | +| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | +| 10 | SampleApp works (if ploch-data) | Manual test | +| 11 | Conventional commit with `Refs: #issue` | Commit log | +| 12 | PR description documents all changes and decisions | PR body | +| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | **If any criterion is not met:** go back and fix it. Do not report completion. @@ -656,19 +775,20 @@ When an issue requires changes in multiple repositories: **Research before asking.** The user expects maximum autonomy. -| Situation | Action | -|-----------|--------| -| Unsure about a pattern | Check sibling repos for examples | -| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | -| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | -| Unsure about test approach | Check existing test projects for patterns | -| Build warning you don't understand | Research the analyser rule ID, then fix or document | -| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | -| PR comment you disagree with | Reply with clear reasoning, citing evidence | -| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) for opinion | -| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | +| Situation | Action | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| Unsure about a pattern | Check sibling repos for examples | +| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | +| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | +| Unsure about test approach | Check existing test projects for patterns | +| Build warning you don't understand | Research the analyser rule ID, then fix or document | +| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | +| PR comment you disagree with | Reply with clear reasoning, citing evidence | +| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | +| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | **Only ask the user when:** + - A decision has significant business or architectural impact that cannot be inferred from the issue, codebase, or documentation. - Multiple valid approaches exist AND the choice materially affects the user AND research hasn't provided a clear winner. - You are truly blocked with no way to research the answer. @@ -680,6 +800,7 @@ When an issue requires changes in multiple repositories: ## Non-Blocking Issues When you encounter something worth tracking that is outside the current issue's scope, **open a GitHub issue** for it — do not accumulate items in a `TODO-important.md` file. Create an issue when you encounter: + - Questions that can be answered later. - Suggestions for improvements outside the current issue scope. - Technical debt noticed but outside scope. @@ -687,6 +808,7 @@ When you encounter something worth tracking that is outside the current issue's - Pre-existing issues discovered during implementation. Guidance: + - Give it a clear conventional-style title (e.g. `chore: ...`, `test: ...`, `refactor: ...`) and a body capturing the context, why it is out of scope, and a suggested resolution. - Label genuinely high-priority follow-ups (release blockers, correctness or consumer risk) with the `important` label so they stand out. Create the label first if the repo does not have it. - Cross-reference the originating issue/PR in the new issue body. @@ -721,31 +843,32 @@ If you catch yourself about to do any of these, stop and reconsider: ## Quick Reference -| Phase | Gate | Evidence Required | -|-------|------|-------------------| -| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | -| 1. Repo | Repo identified and up to date | `git status` clean | -| 2. Research | Context gathered | Key files and patterns identified | -| 3. Plan | Reviewed by Codex | Plan approved or adjusted | -| 4. Branch | Created from latest base | Branch name follows convention | -| 5. Implement | Code + tests + docs written | Files created/modified | -| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | -| 7. Test | All pass, ≥80% new coverage | Test output with counts | -| 8. Self-Review | No issues found | `git diff` reviewed | -| 9. Codex | Feedback addressed | Review notes | -| 10. Commit | Conventional format, `Refs` footer | Commit message | -| 11. PR | Detailed description, linked issue | PR URL | -| 12. CI | ALL green (including non-required) | `gh pr checks` output | -| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | -| 14. Gate | All 13 criteria met | Checklist verified | -| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | -| 15. Report | Evidence provided | Summary with links | +| Phase | Gate | Evidence Required | +| ---------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | +| 1. Repo | Repo identified and up to date | `git status` clean | +| 2. Research | Context gathered | Key files and patterns identified | +| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | +| 4. Branch | Created from latest base | Branch name follows convention | +| 5. Implement | Code + tests + docs written | Files created/modified | +| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | +| 7. Test | All pass, ≥80% new coverage | Test output with counts | +| 8. Self-Review | No issues found | `git diff` reviewed | +| 9. External AI Review | Codex, Antigravity AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | +| 10. Commit | Conventional format, `Refs` footer | Commit message | +| 11. PR | Detailed description, linked issue | PR URL | +| 12. CI | ALL green (including non-required) | `gh pr checks` output | +| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | +| 14. Gate | All 13 criteria met | Checklist verified | +| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | +| 15. Report | Evidence provided | Summary with links | --- ## Integration **References these rules (auto-loaded from `.claude/rules/`):** + - `branch-naming.md` — Branch naming convention - `commits.md` — Conventional Commit format and issue linking - `writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture standards @@ -760,6 +883,7 @@ If you catch yourself about to do any of these, stop and reconsider: - `agent.md` — Agent behaviour specification and CI check gate **Uses these skills when appropriate:** + - **dotnet-dev-finishing-touches** — REQUIRED final quality pass after the completion gate (Phase 14.5) - **superpowers:verification-before-completion** — REQUIRED before any completion claim - **superpowers:dispatching-parallel-agents** — When multiple independent sub-tasks exist @@ -769,8 +893,10 @@ If you catch yourself about to do any of these, stop and reconsider: - **review-pr-comments** — For structured PR comment review (Phase 13) **Uses these MCP tools:** + - `mcp__codex-cli__codex` — Plan review and ad-hoc consultation for non-obvious decisions - `mcp__codex-cli__review` — Code change review +- `copilot` CLI on Grok 4.6 — Phase 3 plan review and Phase 9 code review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` / `microsoft_docs_fetch` — .NET documentation - `mcp__plugin_context7_context7__resolve-library-id` / `query-docs` — Library documentation - `mcp__plugin_10x-swe_deepwiki__ask_question` — Understanding external repositories diff --git a/.claude/rules/naming.md b/.claude/rules/naming.md index 98dc10a..3ee11ab 100644 --- a/.claude/rules/naming.md +++ b/.claude/rules/naming.md @@ -1,5 +1,62 @@ -# Naming Standards +# Identifier Naming Standards -- Use **camelCase** for methods and properties. -- Boolean names should begin with: `is`, `are`, `should`, `could`, `would` (e.g., `shouldLogUserOutAfterTransfer`). -- Methods must start with a verb (e.g., `removeUserFromList`). +Naming rules for **identifiers inside code** — types, members, parameters, locals. For **project, assembly, namespace, and package** names, see [`project-naming.md`](./project-naming.md); the two rules do not overlap. + +The workspace is primarily C#, so C# rules come first and are the default. Language-specific sections at the end cover the exceptions. + +--- + +## C# — Casing + +C# casing is **not a matter of taste**; it is fixed by the [.NET Framework Design Guidelines](https://learn.microsoft.com/dotnet/standard/design-guidelines/naming-guidelines) and enforced by the analysers already enabled in every repo (StyleCop, Roslynator, `Microsoft.CodeAnalysis.NetAnalyzers`). Deviating produces build warnings, and `TreatWarningsAsErrors` turns those into build failures in test projects. + +| Identifier | Casing | Example | +|---|---|---| +| Class, struct, record, enum, delegate | PascalCase | `ProfileRepository` | +| Interface | PascalCase, `I` prefix | `IUnitOfWork` | +| Method | PascalCase | `RemoveUserFromList` | +| Property, event | PascalCase | `CreatedTime` | +| Public / protected field (rare — prefer a property) | PascalCase | `Empty` | +| Private field | `_camelCase` | `_profileRepository` | +| `const` / `static readonly` | PascalCase — **never** `SCREAMING_CASE` | `DefaultTimeout` | +| Parameter, local variable | camelCase | `cancellationToken` | +| Generic type parameter | PascalCase, `T` prefix | `TEntity`, `TId` | +| Enum member | PascalCase | `DeleteBehavior.Cascade` | +| Local function | PascalCase | `static bool IsMatch(...)` | + +**Never use camelCase for a method or property in C#.** `shouldLogUserOutAfterTransfer` is a JavaScript identifier; the C# form is `ShouldLogUserOutAfterTransfer`. + +**Async methods end with `Async`** when they return `Task`/`Task<T>`/`ValueTask<T>` — `GetByIdAsync`, `CommitAsync` — matching the repository interfaces in `Ploch.Data.GenericRepository`. The suffix is dropped only for methods whose name already reads as an operation returning a task and which have no synchronous counterpart (e.g. an `ExecuteAsync` override where the base defines the name). + +--- + +## C# — Word Choice + +These rules apply regardless of casing, and they are where most real naming defects live. + +- **Methods start with a verb.** `RemoveUserFromList`, `CalculateTotal`, `ParseConnectionString` — not `UserRemoval` or `TotalCalculation`. A method *does* something; a name without a verb hides what. +- **Booleans read as an assertion.** Prefix with `Is`, `Are`, `Has`, `Can`, `Should`, or `Was`: `IsActive`, `HasChildren`, `CanExecute`, `ShouldLogUserOutAfterTransfer`. A boolean named `Status` or `Flag` forces the reader to open the definition. +- **No abbreviations or contractions.** The guidelines are explicit — `GetWindow`, not `GetWin`. Use `configuration` not `cfg`, `repository` not `repo`, `authentication` not `auth`, `count` not `cnt`. Widely accepted acronyms (`Id`, `Api`, `Db`, `Http`, `Xml`, `Json`, `Ui`) are the exception. +- **Acronym casing follows the assembly rule:** two-letter acronyms are fully capitalised (`IO`, `DB`, `UI`), three-or-more are PascalCased (`Xml`, `Html`, `Json`, `Http`). So `HttpClient` and `XmlReader`, but `IOException` and `UIElement`. In camelCase positions the first acronym is lowercased whole: `ioStream`, `htmlParser`. +- **Say the domain, not the mechanism.** `profileRepository` beats `repo2`; `retryDelay` beats `ts`. +- **Avoid `Manager`, `Helper`, `Util`, `Processor`, `Handler`, `Info`, and `Data` as type-name suffixes.** They describe nothing — a `ProfileManager` could do anything. Name the responsibility: `ProfileValidator`, `ProfileImporter`, `ProfileCache`. +- **Do not encode the type in the name.** `strName`, `intCount`, and `lstProfiles` are Hungarian notation; C# has a type system. +- **Match the codebase's existing vocabulary.** If the domain already says "Entry", a new type is not an "Item". + +### Names that collide + +The same shadowing trap that governs namespace segments applies to type names: do not name a type after a BCL type it will sit alongside — `Task`, `File`, `Path`, `Type`, `Timer`, `Action`, `Event`, `Stream`, `Version`, `Index`, `Range`. Qualify with the domain instead (`WorkItem`, `TrackedFile`, `AuditEvent`). See [`project-naming.md`](./project-naming.md#names-that-collide) for the full list and the entity-naming table. + +--- + +## Test Naming + +Test class and method naming is governed by [`writing-dotnet-tests.md`](./writing-dotnet-tests.md) and deliberately **breaks** the PascalCase method rule above: test methods use `<Member>_should_<expected behaviour>` with lowercase words, because the method name is a sentence read in a test report, not an API surface. That exception is confined to test projects. + +--- + +## Other Languages + +- **PowerShell** (`scripts/`, setup and provisioning scripts): `Verb-Noun` for functions, using an [approved verb](https://learn.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands) (`Install-SessionEndHook`, `Get-ProjectConfig`); PascalCase for parameters (`-WhatIf`, `-ConfigPath`); camelCase for local variables. +- **JavaScript / TypeScript** (`ploch-ai-site` and any web tooling): camelCase for functions, methods, properties and variables; PascalCase for classes, types and components; `SCREAMING_SNAKE_CASE` for module-level constants. The verb-first and boolean-prefix rules above still apply — they are about word choice, not casing. +- **SQL / EF Core column names:** follow whatever the entity configuration establishes for the repo; do not introduce a second convention. diff --git a/.claude/rules/pr-checks-completion-gate.md b/.claude/rules/pr-checks-completion-gate.md index 4183845..4aba9c9 100644 --- a/.claude/rules/pr-checks-completion-gate.md +++ b/.claude/rules/pr-checks-completion-gate.md @@ -35,7 +35,7 @@ The following are the bots routinely seen in this workspace's PRs. The list is i **SonarCloud findings are not all on GitHub.** Unlike Codacy or CodeRabbit, SonarCloud usually posts only a single summary PR comment — not one thread per finding. The individual bugs, code smells, vulnerabilities, and security hotspots live in the SonarCloud platform and **must** be fetched via the `sonarqube-cloud` MCP server (configured at workspace scope — see `mrploch/CLAUDE.md` § "SonarQube MCP Servers"): - **Project key:** `.sonarlint/connectedMode.json` → `projectKey`; else `sonar.projectKey` in `sonar-project.properties` or `.github/workflows/*.yml`; else `mcp__sonarqube-cloud__search_my_sonarqube_projects(q="<repo>")`. -- **Issues:** `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projects=["<key>"], pullRequestId="<PR#>", issueStatuses=["OPEN","CONFIRMED"])`. +- **Issues:** `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projectKeys=["<key>"], pullRequest="<PR#>", issueStatuses=["OPEN","CONFIRMED"])`. - **Security hotspots:** `mcp__sonarqube-cloud__search_security_hotspots(projectKey="<key>", pullRequest="<PR#>", status=["TO_REVIEW"])`. - **Quality gate:** `mcp__sonarqube-cloud__get_project_quality_gate_status(projectKey="<key>", pullRequest="<PR#>")`. @@ -119,7 +119,7 @@ done **Step 7 — SonarCloud platform is clean (MCP, not shell).** The bash steps above only see GitHub-surfaced data. Separately confirm via the `sonarqube-cloud` MCP server that the PR has zero open findings: -- `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projects=["<key>"], pullRequestId="<PR#>", issueStatuses=["OPEN","CONFIRMED"])` → expected: empty. +- `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projectKeys=["<key>"], pullRequest="<PR#>", issueStatuses=["OPEN","CONFIRMED"])` → expected: empty. - `mcp__sonarqube-cloud__search_security_hotspots(projectKey="<key>", pullRequest="<PR#>", status=["TO_REVIEW"])` → expected: empty. - `mcp__sonarqube-cloud__get_project_quality_gate_status(projectKey="<key>", pullRequest="<PR#>")` → expected: `OK`. diff --git a/.claude/skills/dev-finishing-touches/SKILL.md b/.claude/skills/dev-finishing-touches/SKILL.md index d9c3233..4785e04 100644 --- a/.claude/skills/dev-finishing-touches/SKILL.md +++ b/.claude/skills/dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dev-finishing-touches -description: Last-mile quality pass for ploch-ai-site branches (Astro static site, bilingual PL/EN) — reviews all changes (committed + uncommitted), verifies content parity and SEO surfaces (hreflang, JSON-LD, meta, sitemaps), builds with zero astro-check errors/warnings/hints, runs a mandatory triple external AI review of the whole PR (Codex, Gemini AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local check output + failing CI checks + every unresolved PR review thread + every external-AI-review finding, triages each item into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, and only completes when every CI check is green, every TODO is resolved, zero PR review threads remain unaddressed, and manual browser verification of both language versions has passed. Use when the user says "/dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for ploch-ai-site branches (Astro static site, bilingual PL/EN) — reviews all changes (committed + uncommitted), verifies content parity and SEO surfaces (hreflang, JSON-LD, meta, sitemaps), builds with zero astro-check errors/warnings/hints, runs a mandatory triple external AI review of the whole PR (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local check output + failing CI checks + every unresolved PR review thread + every external-AI-review finding, triages each item into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, and only completes when every CI check is green, every TODO is resolved, zero PR review threads remain unaddressed, and manual browser verification of both language versions has passed. Use when the user says "/dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — Branch Quality Pass (ploch-ai-site) @@ -29,7 +29,7 @@ This is the web-site adaptation of the workspace's `.NET` finishing-touches skil - **CI state is known up front, not after push** — a sub-agent inspects existing CI run status before any local work begins. See [Phase 1.5](#phase-15-ci-status-pre-check-sub-agent). -- **Triple external AI review is mandatory** — before commit/push, the **entire PR context** (description, linked issue, full diff, full contents of modified files, repo conventions) is handed to **Codex, Gemini and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort review of the branch. Three different model families means three different blind spots. Every finding they raise is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). +- **Triple external AI review is mandatory** — before commit/push, the **entire PR context** (description, linked issue, full diff, full contents of modified files, repo conventions) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort review of the branch. Three different model families means three different blind spots. Every finding they raise is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is additionally reviewed by the Codex MCP **before the commit**, not after. Applies equally to check fixes, CI-failure fixes, PR-comment-driven fixes, and external-review-driven fixes. See [Codex Validation Gate](#codex-validation-gate). @@ -65,7 +65,7 @@ Before running any phase, check these prerequisites. If one is missing, **stop a | `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | | `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | | `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Load via `ToolSearch` ("select:mcp__codex-cli__codex,mcp__codex-cli__review"); retry once; if still missing, **pause and ask the user** whether to proceed without Codex (record the decision). Never silently skip. | -| `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | +| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | | `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | | Browser tooling (`claude-in-chrome` MCP, Playwright MCP, or `curl` fallback) | Phase 9.5 manual verification | Prefer a real browser MCP. If none is available, use `astro preview` + `curl` + dist HTML inspection and state in the report that visual verification was curl-level only. | | `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build + check, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | @@ -93,7 +93,7 @@ digraph finishing_touches { verify [label="6. Rebuild & Verify"]; more [shape=diamond, label="More findings?"]; grand [label="7. Grand Review\n(diff + docs sync)"]; - ai_review [label="8.5 External AI Review\nCodex + Gemini + Copilot (parallel,\nfull context, high effort)"]; + ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot (parallel,\nfull context, high effort)"]; ai_findings [shape=diamond, label="Findings\nraised?"]; triage_ai [label="Triage findings into TODO;\nfix valid ones"]; commit [label="9. Commit\n(/commit + Refs footer)"]; @@ -272,7 +272,7 @@ cp "src/layouts/Base.astro" "src/layouts/Base.astro.bak" One TODO per unresolved, non-outdated thread + one per actionable issue-level comment. Bot threads (Copilot, Codex connector, Sourcery, CodeRabbit) are included and triaged exactly like human threads. Record each thread's GraphQL `id` and root `databaseId` in the TODO body. -4. **External AI review findings** — from Phase 8.5. One TODO per Codex, Gemini and Copilot finding rated must-fix or should-fix (deduplicate findings more than one reviewer raises; note every attribution on the merged TODO — agreement across independent model families raises confidence and should be recorded). +4. **External AI review findings** — from Phase 8.5. One TODO per Codex, Antigravity and Copilot finding rated must-fix or should-fix (deduplicate findings more than one reviewer raises; note every attribution on the merged TODO — agreement across independent model families raises confidence and should be recorded). **Additional sources folded in as the pass progresses:** content-parity gaps from Phase 3 (one TODO per page pair), grand-review findings from Phase 7, Codex Validation Gate findings. @@ -281,7 +281,7 @@ cp "src/layouts/Base.astro" "src/layouts/Base.astro.bak" | Field | Content | | --------- | ---------------------------------------------------------------------------------------------------- | | Title | Short imperative (e.g. "Fix missing EN mirror of new PL services section") | -| Source | One of: `local-check`, `ci-check`, `pr-comment`, `content-parity`, `grand-review`, `codex`, `gemini`, `copilot` | +| Source | One of: `local-check`, `ci-check`, `pr-comment`, `content-parity`, `grand-review`, `codex`, `antigravity`, `copilot` | | Reference | File + line / check name + run link / comment URL / reviewer finding ID | | Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | | Status | `pending` → `in_progress` → `completed` | @@ -423,7 +423,7 @@ Review all changes holistically. --- -### Phase 8.5: External AI Review — Codex + Gemini + Copilot (MANDATORY) +### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) **Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates individual fixes): here every reviewer sees the **entire PR** and hunts for anything the pass missed — bugs, SEO regressions, bilingual drift, security issues, better approaches. @@ -453,7 +453,7 @@ The reviewers must receive the **entire context first**, then the review request #### Step 2 — Dispatch all three reviews in parallel - **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package. Request the highest reasoning effort the tool exposes (e.g. `model`/`effort` config set to high) — the brief's "maximum depth" instruction applies regardless. -- **Gemini:** `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code` if the gemini-cli server is absent), passing the same package. Use the highest-capability model/thinking configuration the tool exposes. +- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, passing the same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. - **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool. Write the context package plus brief to a scratch file and pass it as the prompt, using the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a file and pass it via shell substitution rather than inlining it in the command line. Send all three requests in the same tool-call block so they run concurrently. If the context package exceeds a tool's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the review brief only after the final part — the requirement is *entire context first, then the review*. @@ -461,7 +461,7 @@ Send all three requests in the same tool-call block so they run concurrently. If #### Step 3 — Triage the findings 1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. -2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `gemini` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. +2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. 3. Triage each finding like a PR comment: valid → fix (backups, safety gate, Codex Validation Gate for non-trivial fixes, then loop to Phase 4); disagree → record the finding **and** the evidence-based reason for declining in the report — a declined external finding is never silently dropped. 4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). @@ -609,7 +609,7 @@ Re-run the enumeration + comment fetches. Any new thread/comment (including revi ### Changes Applied - **Content/SEO integrity:** <PL/EN parity fixes, hreflang/meta/JSON-LD corrections> - **Check findings resolved:** <count> fixed, <count> suppressed (each with documented justification) -- **External-review fixes:** <count> from Codex, <count> from Gemini, <count> from Copilot, <count> declined with reasons +- **External-review fixes:** <count> from Codex, <count> from Antigravity, <count> from Copilot, <count> declined with reasons - **Docs updated:** <files> ### Build & Check Status @@ -619,7 +619,7 @@ Re-run the enumeration + comment fetches. Any new thread/comment (including revi | Reviewer | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | |----------|---------|----------|------------|-----|-------|--------------------------| | Codex | ... | n | n | n | n | n | -| Gemini | ... | n | n | n | n | n | +| Antigravity | ... | n | n | n | n | n | | Copilot (`grok-4.6`) | ... | n | n | n | n | n | ### Manual Verification @@ -693,7 +693,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t 2. **PL/EN parity requires a content decision** — e.g. new PL copy with no obvious EN rendering, or a translation judgement call. 3. **A change touches deploy-sensitive files** (`.htaccess`, `_headers`, workflows, `wrangler.jsonc`) beyond the branch's scope. 4. **No GitHub issue can be found** for the `Refs` footer — follow `rules/commits.md` lookup order and ask if none found. -5. **Codex or Gemini MCP is unavailable** after a retry — ask whether to proceed with a reduced review. +5. **Codex or Antigravity MCP is unavailable** after a retry — ask whether to proceed with a reduced review. 6. **An external reviewer's `REQUEST_CHANGES` must-fix** conflicts with the user's explicit prior direction — surface the conflict, don't pick silently. --- @@ -707,7 +707,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t | PL/EN wording mismatch | Polish wins; mirror the meaning into EN | | CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | | PR comment you disagree with | Reply with evidence-based reasoning | -| Codex and Gemini disagree with each other | Judge on the evidence; if genuinely ambiguous and impactful, surface both positions to the user | +| Codex and Antigravity disagree with each other | Judge on the evidence; if genuinely ambiguous and impactful, surface both positions to the user | | Link-check failure on an external URL | Internal links must be fixed; external ones verified manually (CI is offline-only, so external failures are local-run-only signals) | --- @@ -749,7 +749,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t | 4. Build/Check | 0 errors / 0 warnings / 0 hints; links + JSON-LD valid | Command output | | 5–6. Findings | Each finding classified, addressed, verified | Resolution documented per finding | | 7. Grand Review | Holistic review + docs sync done | No outstanding concerns | -| 8.5 AI Review | Codex, Gemini AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | +| 8.5 AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer, no `.bak` staged | Commit message + staged-index check | | 9.5 Manual Verify | Both languages browser-verified | Pages + method recorded | | 10. CI | All checks green (incl. non-required) | `gh pr checks` output | @@ -776,7 +776,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t **Uses these MCP tools:** - **`mcp__codex-cli__review` / `mcp__codex-cli__codex`** — Phase 8.5 whole-branch review + the per-fix Codex Validation Gate (load via `ToolSearch`) -- **`mcp__gemini-cli__gemini`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`) +- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check - **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - `claude-in-chrome` / Playwright MCP — Phase 9.5 browser verification - Context7 MCP — Astro documentation lookups diff --git a/.claude/skills/dotnet-dev-finishing-touches/SKILL.md b/.claude/skills/dotnet-dev-finishing-touches/SKILL.md index 1f5b036..ad8adf0 100644 --- a/.claude/skills/dotnet-dev-finishing-touches/SKILL.md +++ b/.claude/skills/dotnet-dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dotnet-dev-finishing-touches -description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Gemini AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — .NET Branch Quality Pass @@ -27,7 +27,7 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is reviewed by the Codex MCP (`mcp__codex-cli__codex`) **before the commit**, not after. Applies equally to warning fixes, CI-failure fixes, and PR-comment-driven fixes. See [Codex Validation Gate](#codex-validation-gate). -- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Gemini and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). +- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). - **Zero unaddressed PR comments** — every unresolved review thread must be triaged and closed out before the skill reports complete. Valid issues are fixed in code; false positives get a reply that cites specific evidence (what the code actually does, which test/spec proves it, why the analyser or reviewer was wrong). A thread is never left silent, and a bot-flagged thread is never closed without a reply. See [Phase 11](#phase-11-address-pr-comments-skip-if---no-push). @@ -61,7 +61,7 @@ Before running any phase, check these prerequisites. If one is missing, **stop a | `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | | `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | | `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | -| `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | +| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | | `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | | `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | @@ -98,7 +98,7 @@ digraph finishing_touches { more_warnings [shape=diamond, label="More warnings\nremaining?"]; grand_review [label="8. Grand Review\n(all changes, suggestions)"]; review_ok [shape=diamond, label="Changes\nready?"]; - ai_review [label="8.5 External AI Review\nCodex + Gemini + Copilot\n(parallel, full context, high effort)"]; + ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot\n(parallel, full context, high effort)"]; apply [label="8b. Apply Suggestions"]; commit [label="9. Commit\n(/commit skill)"]; push_check [shape=diamond, label="--no-push?"]; @@ -368,14 +368,14 @@ Build the complete picture of all changes on the branch. - Coverage gaps identified in Phase 4 — one TODO per file under 80%. - Grand-review findings from Phase 8 — one TODO per actionable suggestion. - New items surfaced by Codex validation in the [Codex Validation Gate](#codex-validation-gate) — one TODO per Codex finding rated "must fix" or "should fix". -- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) — one TODO per Codex, Gemini and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. +- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) — one TODO per Codex, Antigravity and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. **TODO item format:** | Field | Content | | --------- | -------------------------------------------------------------------------------------------------- | | Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | -| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `gemini`, `copilot` | +| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `antigravity`, `copilot` | | Reference | File + line / check name + run link / comment URL | | Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | | Status | `pending` → `in_progress` → `completed` | @@ -619,7 +619,7 @@ Review all changes made during the finishing-touches pass holistically. --- -### Phase 8.5: External AI Review — Codex + Gemini + Copilot (MANDATORY) +### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) **Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates one staged fix at a time): here every reviewer sees the **entire branch** and hunts for what the pass missed — correctness bugs, API-contract breaks, async and thread-safety hazards, suppressions that hide real defects, test gaps, better approaches. @@ -649,7 +649,7 @@ Reviewers receive the **entire context first**, then the review request. Build a #### Step 2 — Dispatch all three reviews in parallel - **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package at the highest reasoning effort the tool exposes. -- **Gemini:** `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code` if the gemini-cli server is absent), same package, highest-capability model/thinking configuration. +- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. - **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool, so there is no `mcp__copilot__*` to load. Use the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a scratch file and pass it via shell substitution rather than inlining it in the command line. Send all three requests in the same tool-call block so they run concurrently. If the package exceeds a transport's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the brief only after the final part — the requirement is *entire context first, then the review*. @@ -657,7 +657,7 @@ Send all three requests in the same tool-call block so they run concurrently. If #### Step 3 — Triage the findings 1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. -2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `gemini` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. +2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. 3. Triage each finding like a PR comment, using the seven-category model in [`pr-checks-completion-gate.md`](../../rules/pr-checks-completion-gate.md): valid → fix (backups, ask-gates for API/semantic changes, **Codex Validation Gate for non-trivial fixes**, then loop to Phase 5); disagree → record the finding **and** the evidence-based reason for declining in the report. A declined external finding is never silently dropped. 4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). 5. **A finding that would change the public API or semantic behaviour still hits the existing ask-gates** — an external reviewer's recommendation does not bypass the user's sign-off on breaking changes. @@ -963,13 +963,13 @@ Provide a summary with evidence: - **Test Coverage:** ~<percentage>% on modified code (<count> tests added) - **Warnings Resolved:** <count> fixed, <count> suppressed (with justification), <count> disabled globally - **Code Review Fixes:** <count> improvements applied -- **External-review fixes:** <count> from Codex, <count> from Gemini, <count> from Copilot, <count> declined with reasons +- **External-review fixes:** <count> from Codex, <count> from Antigravity, <count> from Copilot, <count> declined with reasons ### External AI Review | Reviewer | Model | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | |----------|-------|---------|----------|------------|-----|-------|--------------------------| | Codex | ... | ... | n | n | n | n | n | -| Gemini | ... | ... | n | n | n | n | n | +| Antigravity | ... | ... | n | n | n | n | n | | Copilot | `grok-4.6` | ... | n | n | n | n | n | ### Warning Resolution Summary @@ -1040,7 +1040,7 @@ find . -name "*.bak" -not -path "*/bin/*" -not -path "*/obj/*" -delete ## Codex Validation Gate -**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. +**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. **Timing rule:** Codex runs on the *uncommitted* diff. The correct sequence is: stage files → invoke Codex on the staged diff → act on the verdict → commit. If you are already mid-commit when you realise the gate was skipped, reset the staging, run Codex, then re-stage and commit as a single commit. Do **not** commit first and retroactively "validate" — that defeats the gate. @@ -1213,7 +1213,7 @@ If you catch yourself about to do any of these, stop and reconsider: | 6. Warnings | Each warning classified and addressed | Resolution documented per warning | | 7. Verify | Warning resolved after each fix | Rebuild output confirms | | 8. Grand Review | All changes reviewed holistically | No outstanding concerns | -| 8.5 External AI Review | Codex, Gemini AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | +| 8.5 External AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer | Commit message | | 10. CI | All checks green (including non-required) | `gh pr checks` output | | 11. PR Comments | Every thread triaged, fixed-or-replied, and (for bots + clear-cut cases) resolved | Zero `isResolved=false` threads whose latest comment is not ours; category breakdown recorded | @@ -1255,7 +1255,7 @@ If you catch yourself about to do any of these, stop and reconsider: - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns` — Anti-pattern detection - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code` — Unused code detection - **`mcp__codex-cli__codex` / `mcp__codex-cli__review`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)) and one third of the Phase 8.5 panel. Use `ToolSearch` to load the schema if not already available. -- **`mcp__gemini-cli__gemini`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`) +- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check - **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - GitHub CLI (`gh`) — PR management, CI monitoring, comment handling diff --git a/.claude/skills/implement-issue/SKILL.md b/.claude/skills/implement-issue/SKILL.md index 28a7276..f16c8a4 100644 --- a/.claude/skills/implement-issue/SKILL.md +++ b/.claude/skills/implement-issue/SKILL.md @@ -12,15 +12,20 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet **Core principles:** - **Maximum autonomy** — research before asking. Only ask the user when genuinely blocked after exhausting all research options. + - **Maximum thoroughness** — every phase has explicit quality gates. No shortcuts. No skipped steps. + - **Evidence before claims** — never report completion without evidence (build output, test counts, CI status, PR URL). + - **All comments addressed** — every single PR comment and conversation must be addressed. No exceptions. Bot-authored threads (CodeRabbit, Codacy, Bito, SonarCloud) follow the same triage rules as human reviewers. SonarCloud / SonarQube Cloud additionally reports issues that exist **only in the SonarCloud platform** (not as GitHub comments) — these are fetched via the `sonarqube-cloud` MCP server and resolved with the same seven-category triage. + - **All checks pass — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: + 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the implement-issue skill to implement GitHub issue #\<number\>." @@ -28,15 +33,24 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet ## Invocation ``` -/implement-issue <github-issue-url> # Full end-to-end -/implement-issue <github-issue-url> --no-push # Implement + commit locally, skip push/PR/CI +/implement-issue <github-issue-url>|<linear-issue-url> # Full end-to-end +/implement-issue <github-issue-url>|<linear-issue-url> --no-push # Implement + commit locally, skip push/PR/CI ``` -Supported URL formats: +### Supported URL formats + +**For GitHub issues:** + - `https://github.com/<owner>/<repo>/issues/<number>` - `<owner>/<repo>#<number>` - `#<number>` (current repo) +**For Linear issues:** + +- `https://linear.app/<team>/issue/<linear-issue-id>/<title>` +- `<team>/<linear-issue-id>` +- `<linear-issue-id>` (Linear workspace/team from repository `## Project Scope` in `CLAUDE.md`, or the mirrored section in `AGENTS.md` / `GEMINI.md` / `.github/copilot-instructions.md`) + **`--no-push` flag:** When set, skip all push, PR creation, CI monitoring, and PR comment resolution steps. Commit locally only. ## The Process @@ -49,7 +63,7 @@ digraph implement_issue { fetch [label="0. Fetch & Parse Issue"]; repo [label="1. Identify Target Repository"]; research [label="2. Research & Gather Context"]; - plan [label="3. Plan Implementation\n(Codex + Copilot review plan)"]; + plan [label="3. Plan Implementation\n(Codex + Copilot + Antigravity review plan)"]; blocked [shape=diamond, label="Genuinely\nblocked?"]; ask [label="Ask user"]; branch [label="4. Create Branch"]; @@ -57,7 +71,7 @@ digraph implement_issue { build [label="6. Build & Static Analysis\n(Zero new warnings)"]; test [label="7. Test\n(All pass, coverage gates)"]; review [label="8. Self-Review\n(git diff, patterns, docs)"]; - codex [label="9. External AI Review\nCodex + Gemini + Copilot"]; + codex [label="9. External AI Review\nCodex + Antigravity + Copilot"]; issues [shape=diamond, label="Issues\nfound?"]; commit [label="10. Commit\n(Conventional, Refs: #issue)"]; push_check [shape=diamond, label="--no-push?"]; @@ -65,7 +79,7 @@ digraph implement_issue { monitor [label="12. Monitor CI Checks\n(ALL checks incl. non-required)"]; ci_ok [shape=diamond, label="All checks\npass?"]; fix_ci [label="Read logs, diagnose, fix"]; - comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud issues)"]; + comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud, Codacy issues + any other issue)"]; comments_ok [shape=diamond, label="All addressed?\nNo new comments?"]; gate [label="14. Completion Gate\n(All criteria met?)"]; gate_ok [shape=diamond, label="Pass?"]; @@ -102,36 +116,49 @@ digraph implement_issue { ### Phase 0: Fetch & Parse Issue 1. **Parse the URL** to extract `owner`, `repo`, and `issue-number`. + 2. **Fetch the full issue:** + ```bash gh issue view <number> --repo <owner>/<repo> --json number,title,body,labels,assignees,milestone,state,comments,projectItems ``` + 3. **Extract and understand:** + - **Title** and **description** — what needs to be done. - **Acceptance criteria** — look for a section in the body (e.g. "## Acceptance Criteria", "### AC", checkboxes). If none, derive from the description. - **Labels** — determine change type (`bug` → fix, `enhancement`/`feature` → feature, `documentation` → docs, etc.). - **Linked issues/PRs** — referenced in the body or comments (`#123`, `Depends on ...`). - **Comments** — additional context, clarifications, decisions from the discussion. + 4. **If the issue is closed** or already has a linked merged PR that fully addresses it, stop and inform the user. ### Phase 1: Identify Target Repository 1. Determine the target repository from the issue URL. + 2. Map to the local workspace directory: `C:\DevNet\my\mrploch\<repo-name>\`. + 3. Verify the repo is cloned: + ```bash ls "C:/DevNet/my/mrploch/<repo-name>" ``` + 4. Navigate to the repo and ensure it is up to date: + ```bash cd "C:/DevNet/my/mrploch/<repo-name>" git fetch origin git status ``` + 5. Identify the base branch (`main` or `master`): + ```bash git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' ``` + If that fails, check `git branch -r` for `origin/main` or `origin/master`. `ploch-common` uses `master`; newer repos use `main`. ### Phase 2: Research & Gather Context @@ -139,38 +166,49 @@ digraph implement_issue { Before writing any code, build comprehensive understanding. This phase is critical — thorough research prevents wasted implementation time. 1. **Read the target repo:** + - README.md, CLAUDE.md, `.claude/rules/` files. - Relevant source files in the area of change. - Existing tests for the affected modules. - Project structure (`src/`, `tests/`, solution files). - `Directory.Build.props`, `Directory.Packages.props` for build configuration. + 2. **Check related issues and PRs:** + ```bash # Related issues (open and closed) gh issue list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 # Related PRs (open and recently closed/merged) gh pr list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 ``` + 3. **Read linked or related PRs** for context on prior decisions and approaches: + ```bash gh pr view <pr-number> --repo <owner>/<repo> --json title,body,files,commits gh pr diff <pr-number> --repo <owner>/<repo> ``` + 4. **Check sibling repos** for patterns — browse `C:\DevNet\my\mrploch\` siblings: + - `ploch-common` — extension methods, serialisation, DI bundles, CRUD endpoints. - `ploch-data` — repository pattern, Unit of Work, entity configurations, Specification. - `ploch-lists`, `ploch-groupmatters` — application-level patterns (API, data layer, model). - `mrploch-development` — shared build config, dependency versions. + 5. **Research externally** if needed: + - Microsoft Learn docs: `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` - Library documentation via Context7: `mcp__plugin_context7_context7__resolve-library-id` then `query-docs` - External repo understanding via DeepWiki: `mcp__plugin_10x-swe_deepwiki__ask_question` - Web search for non-obvious problems or unfamiliar APIs. + 6. **Understand the area of change** — read the specific files, classes, and methods that will be affected. Trace call chains. Understand the data flow. Identify what tests exist and what patterns they follow. ### Phase 3: Plan Implementation 1. **Create a detailed plan** using **TodoWrite** with sub-tasks covering: + - Implementation tasks (code changes, new files, modified files). - Test creation (unit tests, integration tests if needed, bug-reproducing test if it's a bug fix). - Documentation tasks (XML docs on new public APIs, README/doc page updates). @@ -181,11 +219,14 @@ Before writing any code, build comprehensive understanding. This phase is critic - Push/PR (unless `--no-push`). 2. **Consult two external models for plan review** — send both requests in the same tool-call block so they run concurrently: + ``` mcp__codex-cli__codex # OpenAI lens copilot -p "<plan brief>" --model grok-4.6 … # xAI lens, via Bash — see rules/external-ai-review.md ``` + Send the plan to each along with: + - The issue description and acceptance criteria. - Key files and patterns discovered during research. - Any design decisions you've made and their rationale. @@ -199,10 +240,13 @@ Before writing any code, build comprehensive understanding. This phase is critic ### Phase 4: Create Branch 1. Ensure you are on the base branch and it is up to date: + ```bash git checkout <base-branch> && git pull origin <base-branch> ``` + 2. Determine the change type from the issue analysis (Phase 0). Mapping: + - `bug` label or bug-related title → `fix` - `enhancement`/`feature` label or new capability → `feature` - Documentation-only → `docs` @@ -210,10 +254,13 @@ Before writing any code, build comprehensive understanding. This phase is critic - Code restructuring without behaviour change → `refactor` - Performance improvement → `perf` - Tests only → `test` + 3. Create the branch following the naming convention (see `rules/branch-naming.md`): + ```bash git checkout -b <change-type>/<issue-number>-<brief-description> ``` + Example: `feature/72-dbcontext-creation-lifecycle-plugins`, `fix/187-duplicate-entity-concurrent-upsert` ### Phase 5: Implement @@ -249,7 +296,9 @@ When the issue is a bug fix: #### Documentation - **XML documentation** on all new/modified public types, methods, properties (for public/open-source packages). Follow Microsoft's style. Include `<example>` blocks where usage is not obvious. See `rules/documentation.md`. + - **Update project markdown documentation** — manually-authored `.md` files must stay in sync with the code. Discover all project docs: + ```bash REPO_ROOT=$(git rev-parse --show-toplevel) # Primary: docs/ folder, root-level docs, and any other .md files in the project @@ -257,7 +306,9 @@ When the issue is a bug fix: ls "$REPO_ROOT"/README.md "$REPO_ROOT"/RELEASE_NOTES.md "$REPO_ROOT"/CHANGELOG.md 2>/dev/null find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` + For each documentation file found, check whether your changes affect what it describes: + - **README.md** — features, APIs, usage patterns, installation instructions, quick-start examples, configuration options. - **docs/*.md** — design documents, architecture guides, spec files, migration guides, API references. - **RELEASE_NOTES.md / CHANGELOG.md** — add entries for user-visible changes (new features, breaking changes, significant bug fixes). @@ -267,6 +318,7 @@ When the issue is a bug fix: #### SampleApp (ploch-data only) If working on the `ploch-data` repository and the change adds or modifies library features: + - Update the SampleApp to demonstrate the new/changed features. - The SampleApp must use NuGet package references, not ProjectReference. - See `rules/sample-apps.md`. @@ -286,6 +338,7 @@ Read the **entire** build output. Do not skim. #### Step 2: Catalogue every warning Go through every warning in the build output. These come from: + - **StyleCop.Analyzers** — naming, documentation, layout, ordering. - **Roslynator.Analyzers** — code simplification, redundancy, best practices. - **SonarAnalyzer.CSharp** — bugs, code smells, security hotspots. @@ -312,12 +365,12 @@ The build output must show **zero warnings**. If any remain, go back to Step 3. #### Summary -| Gate | Requirement | -|------|-------------| -| Compilation | Zero errors | -| Static analysis warnings | Zero (all fixed) | -| Code style (.editorconfig) | Zero violations | -| Suppressions added | Zero (unless justified and documented) | +| Gate | Requirement | +| -------------------------- | -------------------------------------- | +| Compilation | Zero errors | +| Static analysis warnings | Zero (all fixed) | +| Code style (.editorconfig) | Zero violations | +| Suppressions added | Zero (unless justified and documented) | ### Phase 7: Test @@ -348,31 +401,43 @@ Before committing, review your own changes thoroughly: 3. Re-validate against the original issue requirements and acceptance criteria from Phase 0. Did you implement everything that was asked? Did you miss any AC? 4. If anything needs improvement: fix it, then loop back to **Phase 6** (Build). -### Phase 9: External AI Review — Codex + Gemini + Copilot +### Phase 9: External AI Review — Codex + Antigravity + Copilot **Panel definition, invocation flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** All three reviews are **mandatory** for every non-trivial change — three providers, three sets of blind spots. Run them in parallel (one tool-call block) and pass **full context** to each: the issue number + title + requirements, the design decisions taken and why, the diff (`git diff <base-branch>...HEAD`), verification evidence (build/test results), and a request for a structured verdict (`APPROVED` / `APPROVED_WITH_NOTES` / `CHANGES_REQUESTED` / `REJECTED` with concrete findings). 1. **Codex review:** + ``` mcp__codex-cli__review (or mcp__codex-cli__codex with a review brief) ``` + Provide the diff and full context as above. **Fallback:** if the Codex MCP is unavailable (e.g. account/model restriction — try at least one alternative model before concluding), substitute an independent local review agent (e.g. `feature-dev:code-reviewer`) with the same brief, and record the substitution in the PR description and completion report. Never silently skip the second opinion. -2. **Gemini review:** + +2. **Antigravity review:** + ``` - mcp__gemini__gemini-analyze-code (or mcp__gemini__gemini-query with the diff inline) + mcp__antigravity__ask_antigravity (model="gemini-3.1-pro-high", paths=[...]) ``` + Provide the same full-context brief and the diff. Ask specifically for: correctness issues, missed edge cases, API-contract concerns, and test-coverage gaps. + 3. **Copilot review:** + ```bash copilot -p "$BRIEF" --model grok-4.6 --effort high --allow-all-tools \ --deny-tool 'write' --disable-builtin-mcps --no-ask-user -s --log-level none -C "$REPO_ROOT" ``` + Shell-out through `Bash` — Copilot is **not** an MCP server, so there is no `mcp__copilot__*` tool to load. Use the full canonical flag set from [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (the abbreviated form above omits the `shell(git …)` / `shell(gh …)` denials). Run the preflight first; on failure follow the fallback ladder (retry with `GITHUB_TOKEN`/`GH_TOKEN`/`COPILOT_GITHUB_TOKEN` stripped → Kimi K3 → ask the user). Afterwards verify `git status --porcelain` is unchanged. + 4. **Review all feedback** — evaluate each suggestion from all three reviewers on merit. Deduplicate overlapping findings, crediting each reviewer that raised them; a finding raised independently by two model families is higher-confidence. + 5. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build), then re-run the affected reviewer on the revised diff. + 6. **Document disagreements** — if you disagree with a suggestion, note your reasoning (in the PR description's Design Decisions section if user-visible). This is acceptable — not every suggestion must be implemented, but a declined finding is recorded with its evidence, never silently dropped. + 7. **Record which model each reviewer ran** — Copilot's in particular, so a fallback to Kimi K3 is visible in the completion report. **Skip this phase** only for truly trivial changes (single-line typo fix, config-only change). @@ -380,85 +445,103 @@ All three reviews are **mandatory** for every non-trivial change — three provi ### Phase 10: Commit - **One commit per logical change** — typically one commit for the entire issue. For large issues with naturally separable parts, use multiple focused commits. + - **Conventional Commits** format (see `rules/commits.md`): + ``` <type>(<scope>): <subject> - + <body — what changed and why> - + [BREAKING CHANGE: <description>] Refs: #<issue-number> ``` + - The `Refs: #<issue-number>` footer is **mandatory**. The issue number comes from Phase 0. + - Detect and document breaking changes — check for removed/renamed public APIs, changed signatures, changed defaults. Add `BREAKING CHANGE:` footer if any. + - Stage specific files — **never** `git add -A` or `git add .`. + - **Never amend** existing commits unless the user explicitly asks. + - Update the change log if the commit contains user-visible changes (new features, breaking changes, significant fixes). ### Phase 11: Push & Create PR (skip if `--no-push`) 0. **Pre-push build verification** — before any push, run a final clean build of the full solution and confirm **zero warnings**: + ```bash dotnet build <solution-file> ``` + If any warnings appear, **stop and fix them before pushing**. This is critical — every warning you let through will come back as a CI failure or PR comment, costing a full pipeline round-trip. Fix locally first. 1. **Push the branch:** + ```bash git push -u origin HEAD ``` 2. **Check for existing PR:** + ```bash gh pr view --json number,url 2>/dev/null || echo "NO_PR" ``` 3. **Read PR template** (if it exists): + ```bash cat .github/pull_request_template.md 2>/dev/null || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null ``` 4. **Create PR** with a detailed description following `rules/pr-descriptions.md`: + ```bash gh pr create --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF' ## Summary - + <What this PR does and why. Reference the issue.> - + ## Changes - + - <Specific change 1> - <Specific change 2> - ... - + ## Design Decisions - + <Non-obvious choices and their rationale> - + ## Testing - + - Unit tests: <count> added/modified - Manual verification: <what was tested> - Coverage: ~<percentage>% on new code - + ## Related - + Closes #<issue-number> EOF )" && gh pr edit --add-assignee @me ``` 4b. **Request a GitHub Copilot review (mandatory):** immediately after creating the PR, request Copilot as a reviewer via the GitHub MCP tool: - ``` - mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) - ``` + +``` +mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) +``` + Fallback if the MCP tool is unavailable: - ```bash - gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" - ``` + +```bash +gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" +``` + Copilot's review comments are then addressed in Phase 13 like any other reviewer's. -5. **If updating an existing PR** (e.g. after fix loop): +1. **If updating an existing PR** (e.g. after fix loop): + ```bash gh pr edit <pr-number> --body "$(cat <<'EOF' [updated body reflecting final state] @@ -473,18 +556,21 @@ All three reviews are **mandatory** for every non-trivial change — three provi **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. A bot that says `fail` because it hasn't yet rescanned the latest commit is **still failing** by the gate's definition — wait for the rescan or push a no-op-ish commit to retrigger; do not declare completion with a "stale check" caveat. 1. **Wait for ALL checks** to complete — **including non-required checks:** + ```bash gh pr checks <pr-number> --watch ``` 2. **If any check fails:** a. Retrieve the failure logs: - ```bash - # Find the failed run - gh run list --branch <branch-name> --limit 5 - # Get failure details - gh run view <run-id> --log-failed - ``` + + ```bash + # Find the failed run + gh run list --branch <branch-name> --limit 5 + # Get failure details + gh run view <run-id> --log-failed + ``` + b. **Diagnose the root cause** — read the actual error output. Do not guess. c. If the failure is not obvious, research the error (web search, docs, sibling repos for how they handle it). d. Fix the issue in code. @@ -492,6 +578,7 @@ All three reviews are **mandatory** for every non-trivial change — three provi f. After pushing the fix, monitor checks again. Repeat until **all green**. 3. **Do not:** + - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence (check if the same test fails consistently). - Push speculative fixes without reading the failure logs. @@ -533,6 +620,7 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary #### GitHub PR comments, review threads & conversations 1. **Fetch all PR feedback:** + ```bash # Review comments (inline on code) gh api repos/<owner>/<repo>/pulls/<pr-number>/comments --paginate @@ -543,12 +631,14 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 2. **For each comment or conversation:** + - If it identifies a **valid issue** → fix the code. - If it is a **false positive or irrelevant** → reply with a clear, specific explanation of why you believe so. Do not just say "false positive" — explain the reasoning. - If it is a **suggestion worth considering** → evaluate on merit. Implement if it improves the code; explain why not if you disagree. - **Every single conversation must have a response.** No comment left unaddressed. It does not matter whether it is blocking the merge or not. 3. **Reply to comments:** + ```bash # Reply to a review comment gh api repos/<owner>/<repo>/pulls/<pr-number>/comments/<comment-id>/replies -f body="<your reply>" @@ -557,12 +647,14 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 4. **If code changes were made:** + - Commit the fixes (new commit, never amend). - Push. - **Loop back to Phase 12** (monitor CI checks again). - After checks pass, re-fetch comments — new automated comments may have been added by the new push. 5. **Only proceed when:** + - Zero unaddressed conversations remain. - No new comments have appeared since your last round of responses. - All CI checks are still green after the latest push. @@ -582,21 +674,21 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary Before reporting completion, **every single one** of these criteria must be met: -| # | Criterion | How to Verify | -|---|-----------|---------------| -| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | -| 2 | All tests pass | Test output with counts | -| 3 | Test coverage ≥80% on new code | Coverage report or estimate | -| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | -| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | -| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | -| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | -| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | -| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | -| 10 | SampleApp works (if ploch-data) | Manual test | -| 11 | Conventional commit with `Refs: #issue` | Commit log | -| 12 | PR description documents all changes and decisions | PR body | -| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | +| # | Criterion | How to Verify | +| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | +| 2 | All tests pass | Test output with counts | +| 3 | Test coverage ≥80% on new code | Coverage report or estimate | +| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | +| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | +| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | +| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | +| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | +| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | +| 10 | SampleApp works (if ploch-data) | Manual test | +| 11 | Conventional commit with `Refs: #issue` | Commit log | +| 12 | PR description documents all changes and decisions | PR body | +| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | **If any criterion is not met:** go back and fix it. Do not report completion. @@ -683,19 +775,20 @@ When an issue requires changes in multiple repositories: **Research before asking.** The user expects maximum autonomy. -| Situation | Action | -|-----------|--------| -| Unsure about a pattern | Check sibling repos for examples | -| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | -| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | -| Unsure about test approach | Check existing test projects for patterns | -| Build warning you don't understand | Research the analyser rule ID, then fix or document | -| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | -| PR comment you disagree with | Reply with clear reasoning, citing evidence | -| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | -| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | +| Situation | Action | +| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| Unsure about a pattern | Check sibling repos for examples | +| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | +| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | +| Unsure about test approach | Check existing test projects for patterns | +| Build warning you don't understand | Research the analyser rule ID, then fix or document | +| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | +| PR comment you disagree with | Reply with clear reasoning, citing evidence | +| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | +| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | **Only ask the user when:** + - A decision has significant business or architectural impact that cannot be inferred from the issue, codebase, or documentation. - Multiple valid approaches exist AND the choice materially affects the user AND research hasn't provided a clear winner. - You are truly blocked with no way to research the answer. @@ -707,6 +800,7 @@ When an issue requires changes in multiple repositories: ## Non-Blocking Issues When you encounter something worth tracking that is outside the current issue's scope, **open a GitHub issue** for it — do not accumulate items in a `TODO-important.md` file. Create an issue when you encounter: + - Questions that can be answered later. - Suggestions for improvements outside the current issue scope. - Technical debt noticed but outside scope. @@ -714,6 +808,7 @@ When you encounter something worth tracking that is outside the current issue's - Pre-existing issues discovered during implementation. Guidance: + - Give it a clear conventional-style title (e.g. `chore: ...`, `test: ...`, `refactor: ...`) and a body capturing the context, why it is out of scope, and a suggested resolution. - Label genuinely high-priority follow-ups (release blockers, correctness or consumer risk) with the `important` label so they stand out. Create the label first if the repo does not have it. - Cross-reference the originating issue/PR in the new issue body. @@ -748,31 +843,32 @@ If you catch yourself about to do any of these, stop and reconsider: ## Quick Reference -| Phase | Gate | Evidence Required | -|-------|------|-------------------| -| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | -| 1. Repo | Repo identified and up to date | `git status` clean | -| 2. Research | Context gathered | Key files and patterns identified | -| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | -| 4. Branch | Created from latest base | Branch name follows convention | -| 5. Implement | Code + tests + docs written | Files created/modified | -| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | -| 7. Test | All pass, ≥80% new coverage | Test output with counts | -| 8. Self-Review | No issues found | `git diff` reviewed | -| 9. External AI Review | Codex, Gemini AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | -| 10. Commit | Conventional format, `Refs` footer | Commit message | -| 11. PR | Detailed description, linked issue | PR URL | -| 12. CI | ALL green (including non-required) | `gh pr checks` output | -| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | -| 14. Gate | All 13 criteria met | Checklist verified | -| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | -| 15. Report | Evidence provided | Summary with links | +| Phase | Gate | Evidence Required | +| ---------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | +| 1. Repo | Repo identified and up to date | `git status` clean | +| 2. Research | Context gathered | Key files and patterns identified | +| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | +| 4. Branch | Created from latest base | Branch name follows convention | +| 5. Implement | Code + tests + docs written | Files created/modified | +| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | +| 7. Test | All pass, ≥80% new coverage | Test output with counts | +| 8. Self-Review | No issues found | `git diff` reviewed | +| 9. External AI Review | Codex, Antigravity AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | +| 10. Commit | Conventional format, `Refs` footer | Commit message | +| 11. PR | Detailed description, linked issue | PR URL | +| 12. CI | ALL green (including non-required) | `gh pr checks` output | +| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | +| 14. Gate | All 13 criteria met | Checklist verified | +| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | +| 15. Report | Evidence provided | Summary with links | --- ## Integration **References these rules (auto-loaded from `.claude/rules/`):** + - `branch-naming.md` — Branch naming convention - `commits.md` — Conventional Commit format and issue linking - `writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture standards @@ -787,6 +883,7 @@ If you catch yourself about to do any of these, stop and reconsider: - `agent.md` — Agent behaviour specification and CI check gate **Uses these skills when appropriate:** + - **dotnet-dev-finishing-touches** — REQUIRED final quality pass after the completion gate (Phase 14.5) - **superpowers:verification-before-completion** — REQUIRED before any completion claim - **superpowers:dispatching-parallel-agents** — When multiple independent sub-tasks exist @@ -796,6 +893,7 @@ If you catch yourself about to do any of these, stop and reconsider: - **review-pr-comments** — For structured PR comment review (Phase 13) **Uses these MCP tools:** + - `mcp__codex-cli__codex` — Plan review and ad-hoc consultation for non-obvious decisions - `mcp__codex-cli__review` — Code change review - `copilot` CLI on Grok 4.6 — Phase 3 plan review and Phase 9 code review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 226e9fb..0d23a57 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -50,7 +50,7 @@ jobs: # ploch-common is cloned in full because it uses Nerdbank.GitVersioning too, and NBGV # cannot compute a version height from a shallow clone. - name: Clone ploch-common (referenced projects) - run: git clone https://github.com/mrploch/ploch-common.git --branch master ../ploch-common + run: git clone https://github.com/mrploch/ploch-common.git --branch main ../ploch-common - name: Clone mrploch-development (shared build config) run: git clone --depth 1 https://github.com/mrploch/mrploch-development.git ../mrploch-development diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 390bc13..1c984a2 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -39,7 +39,7 @@ jobs: uses: actions/checkout@v4 with: repository: mrploch/ploch-common - ref: master + ref: main path: ploch-common fetch-depth: 0 diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index 3c2fce5..a90d536 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -26,7 +26,7 @@ jobs: - uses: actions/checkout@v4 with: repository: mrploch/ploch-common - ref: master + ref: main path: ploch-common fetch-depth: 0 - uses: actions/checkout@v4 From 1cbd612637d9ced2656f4c2b77a352399b9336a5 Mon Sep 17 00:00:00 2001 From: Krzysztof Ploch <kris@ploch.dev> Date: Sat, 12 Sep 2026 13:29:28 +0200 Subject: [PATCH 3/5] revert(solution): Drop unrelated agent tooling from this branch Seven agent-configuration files were swept into 9232f00 by accident: the index still held them staged from a `git stash pop`, and a plain `git commit` commits the index rather than only the paths named in the preceding `git add`. None of them belong to this branch, which is about consuming ploch-common as released packages. Restored to their state on main so the pull request diff contains only the build and workflow changes. The content is not lost - it remains in 9232f00, and the working-tree copies are handed back uncommitted. One of them, .claude/rules/naming.md, is a real fix for #50 (the rule tells agents to use camelCase for C# methods) and wants its own branch and commit message rather than a silent ride on this one. Refs: #47 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MroAgPwA8tGuEPi2rz4qJU --- .agents/dotnet-dev-finishing-touches/SKILL.md | 242 +++----------- .agents/implement-issue/SKILL.md | 302 +++++------------- .claude/rules/naming.md | 65 +--- .claude/rules/pr-checks-completion-gate.md | 4 +- .claude/skills/dev-finishing-touches/SKILL.md | 30 +- .../dotnet-dev-finishing-touches/SKILL.md | 28 +- .claude/skills/implement-issue/SKILL.md | 268 +++++----------- 7 files changed, 248 insertions(+), 691 deletions(-) diff --git a/.agents/dotnet-dev-finishing-touches/SKILL.md b/.agents/dotnet-dev-finishing-touches/SKILL.md index ad8adf0..c991b51 100644 --- a/.agents/dotnet-dev-finishing-touches/SKILL.md +++ b/.agents/dotnet-dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dotnet-dev-finishing-touches -description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — .NET Branch Quality Pass @@ -12,32 +12,20 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c **Core principles:** - **Fix, don't suppress** — suppressions are a last resort, never a shortcut. When suppression is genuinely needed, use `/dotnet-dev-practical` for the correct technique. - - **Verify every fix** — rebuild after every change. Never assume a fix worked. - - **Zero warnings before push** — every warning pushed costs a full CI round-trip (5-15 minutes). Fix locally in seconds. - - **Evidence before claims** — never report completion without build output, test counts, and CI status. - - **Backup before modify** — before editing any file, save a `.bak` copy so the user can review exactly what changed. See [Backup Before Modify](#backup-before-modify). - - **One unified TODO list drives the pass** — local warnings, failing CI checks, and PR comments/conversations all live in a single tracked list. The skill is not complete until every item on that list is resolved. See [Master TODO List](#phase-25-build-master-todo-list). - - **CI state is known up front, not after push** — a sub-agent inspects existing CI run status before any local work begins so failing checks are visible and planned from the start. See [Phase 1.5](#phase-15-ci-status-pre-check-sub-agent). - - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is reviewed by the Codex MCP (`mcp__codex-cli__codex`) **before the commit**, not after. Applies equally to warning fixes, CI-failure fixes, and PR-comment-driven fixes. See [Codex Validation Gate](#codex-validation-gate). - -- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). - - **Zero unaddressed PR comments** — every unresolved review thread must be triaged and closed out before the skill reports complete. Valid issues are fixed in code; false positives get a reply that cites specific evidence (what the code actually does, which test/spec proves it, why the analyser or reviewer was wrong). A thread is never left silent, and a bot-flagged thread is never closed without a reply. See [Phase 11](#phase-11-address-pr-comments-skip-if---no-push). - - **All-green completion gate — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: - 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. Bot-authored threads (CodeRabbit, Codacy comments, Bito) follow the same rules as human-authored. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the dotnet-dev-finishing-touches skill to perform a quality pass on the current branch." @@ -53,17 +41,15 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c Before running any phase, check these prerequisites. If one is missing, **stop and tell the user** — do not silently work around the gap. -| Requirement | Required for | Fallback if missing | -| -------------------------------------------------- | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `dotnet` CLI (.NET 9+ SDK) | Phases 4, 5, 7 | Stop — the skill cannot run without it. | -| `gh` CLI, authenticated (`gh auth status`) | Phases 1, 1.5, 10, 11 | Stop if Phase 10/11 is in scope. For Phase 1/1.5 the skill can continue without PR context but must flag the gap in the report. | -| `git` CLI, working tree clean of unrelated changes | All phases | Stop and ask the user to commit/stash unrelated work. | -| `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | -| `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | -| `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | -| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | -| `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | -| `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | +| Requirement | Required for | Fallback if missing | +|-------------|-------------|---------------------| +| `dotnet` CLI (.NET 9+ SDK) | Phases 4, 5, 7 | Stop — the skill cannot run without it. | +| `gh` CLI, authenticated (`gh auth status`) | Phases 1, 1.5, 10, 11 | Stop if Phase 10/11 is in scope. For Phase 1/1.5 the skill can continue without PR context but must flag the gap in the report. | +| `git` CLI, working tree clean of unrelated changes | All phases | Stop and ask the user to commit/stash unrelated work. | +| `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | +| `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | +| `mcp__codex-cli__codex` | Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | +| `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | ## The Process @@ -98,7 +84,6 @@ digraph finishing_touches { more_warnings [shape=diamond, label="More warnings\nremaining?"]; grand_review [label="8. Grand Review\n(all changes, suggestions)"]; review_ok [shape=diamond, label="Changes\nready?"]; - ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot\n(parallel, full context, high effort)"]; apply [label="8b. Apply Suggestions"]; commit [label="9. Commit\n(/commit skill)"]; push_check [shape=diamond, label="--no-push?"]; @@ -144,9 +129,7 @@ digraph finishing_touches { more_warnings -> classify [label="yes"]; more_warnings -> grand_review [label="no"]; grand_review -> review_ok; - review_ok -> ai_review [label="yes"]; - ai_review -> commit [label="no must-fix outstanding"]; - ai_review -> apply [label="must-fix findings"]; + review_ok -> commit [label="yes"]; review_ok -> apply [label="no"]; apply -> build; commit -> push_check; @@ -189,30 +172,25 @@ cp "path/to/MyClass.cs" "path/to/MyClass.cs.bak" ### Phase 0: Detect Repository & Solution 1. **Find the repo root:** - ```bash REPO_ROOT=$(git rev-parse --show-toplevel) REPO_NAME=$(basename "$REPO_ROOT") ``` 2. **Locate the solution file.** Prefer `.slnx` over `.sln`. Prefer the file matching the repo name pattern (e.g. `Ploch.Common.slnx` in `ploch-common`): - ```bash find "$REPO_ROOT" -maxdepth 2 -name "*.slnx" -not -path "*/.history/*" -not -path "*/samples/*" | sort find "$REPO_ROOT" -maxdepth 2 -name "*.sln" -not -path "*/.history/*" -not -path "*/samples/*" | sort ``` - If multiple solution files exist and the correct one is ambiguous, present the list and ask the user. 3. **Detect the base branch:** - ```bash BASE_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@') if [ -z "$BASE_BRANCH" ]; then BASE_BRANCH=$(git branch -r | grep -oP 'origin/(main|master)' | head -1 | sed 's@origin/@@') fi ``` - Convention: `ploch-common` uses `master`; newer repos use `main`. 4. Store `REPO_ROOT`, `REPO_NAME`, `SOLUTION_FILE`, and `BASE_BRANCH` for all subsequent phases. @@ -224,7 +202,6 @@ cp "path/to/MyClass.cs" "path/to/MyClass.cs.bak" Gather full context about the branch's purpose. 1. **Check for an associated PR:** - ```bash gh pr view --json number,url,title,body,labels,state 2>/dev/null || echo "NO_PR" ``` @@ -232,11 +209,9 @@ Gather full context about the branch's purpose. 2. **If a PR exists**, extract linked issue numbers from the PR body (look for `Closes #N`, `Refs #N`, `Fixes #N`, `Resolves #N`). 3. **If a linked issue is found:** - ```bash gh issue view <number> --json number,title,body,labels,comments ``` - Understand the issue requirements, acceptance criteria, and any discussion context. 4. **Understand the branch purpose** from all gathered context — PR description, issue body, branch name, commit messages. This context drives decisions in later phases (e.g. whether a warning fix would change the branch's intended behaviour). @@ -254,27 +229,21 @@ Gather full context about the branch's purpose. **Invocation:** Use the `Agent` tool with `subagent_type="general-purpose"` and brief it to: 1. Detect whether a PR exists for the current branch and whether any CI runs have started: - ```bash gh pr view --json number,url,statusCheckRollup 2>/dev/null gh run list --branch "$(git branch --show-current)" --limit 20 --json databaseId,name,status,conclusion,workflowName,headBranch,event,createdAt ``` - 2. For every check with `conclusion` other than `success`/`skipped`/`neutral` (i.e. `failure`, `cancelled`, `timed_out`, `action_required`, or still `in_progress`), fetch the failure logs: - ```bash gh pr checks <pr-number> --json name,state,link,description gh run view <run-id> --log-failed ``` - 3. For each non-green check, extract and return a structured entry: - - Check name (e.g. `build-test-sonar / build`, `SonarCloud Code Analysis`) - Status / conclusion - Run ID and link - Root-cause excerpt (3–15 lines of the actual failing output — not the whole log) - Suggested TODO title (e.g. `Fix SonarCloud quality gate failure: duplicated blocks in Foo.cs`) - 4. Report back as a bullet list grouped by workflow. Under 300 words. **No fixes. No file edits.** **Brief template to pass to the sub-agent:** @@ -290,20 +259,17 @@ Gather full context about the branch's purpose. Build the complete picture of all changes on the branch. 1. **All committed changes vs base branch:** - ```bash git diff "$BASE_BRANCH"...HEAD --name-only ``` 2. **Uncommitted changes (staged + unstaged):** - ```bash git diff --name-only # unstaged git diff --staged --name-only # staged ``` 3. **Untracked files:** - ```bash git ls-files --others --exclude-standard ``` @@ -311,7 +277,6 @@ Build the complete picture of all changes on the branch. 4. **Merge** all lists into a deduplicated set of modified files. Filter to `.cs` files for code analysis phases. 5. **Read the full diffs** for context: - ```bash git diff "$BASE_BRANCH"...HEAD # committed changes git diff # unstaged @@ -331,11 +296,8 @@ Build the complete picture of all changes on the branch. **Required TODO sources — all three must be harvested, not just local issues:** 1. **Local build warnings** — from Phase 5. Initially seeded as a single placeholder TODO ("Run initial build and enumerate warnings on modified files"); once the build runs, the placeholder is expanded into one TODO per warning-on-modified-file. - 2. **Failing CI checks** — from the Phase 1.5 sub-agent's `CI_ISSUES` list. One TODO per non-green check, with the check name, run link, and root-cause excerpt referenced in the TODO body. - 3. **PR review threads, conversations, and reviews** — fetched here (not just in Phase 11). REST endpoints do not expose thread resolution state, so the primary source is the GraphQL `reviewThreads` connection: - ```bash # Thread IDs + resolution state (primary source for TODO creation) gh api graphql -f query=' @@ -353,13 +315,12 @@ Build the complete picture of all changes on the branch. } } }' -F owner=<owner> -F repo=<repo> -F pr=<pr-number> - + # Issue-level conversation comments (PR discussion, not inline review) gh api repos/<owner>/<repo>/issues/<pr-number>/comments --paginate # Full review objects (for body-only reviews without inline comments) gh api repos/<owner>/<repo>/pulls/<pr-number>/reviews --paginate ``` - **One TODO per unresolved, non-outdated review thread + one TODO per issue-comment that raises an actionable concern.** Resolved or outdated threads are excluded. Automated-bot threads (SonarCloud, Codacy, Dependabot, codeant-ai) are included — they must be triaged and replied-to the same as human reviewer threads. Record each thread's GraphQL `id` (e.g. `PRRT_...`) and the root comment's `databaseId` in the TODO body so Phase 11 can reply + resolve without re-fetching. **Additional sources folded in as the pass progresses:** @@ -368,17 +329,16 @@ Build the complete picture of all changes on the branch. - Coverage gaps identified in Phase 4 — one TODO per file under 80%. - Grand-review findings from Phase 8 — one TODO per actionable suggestion. - New items surfaced by Codex validation in the [Codex Validation Gate](#codex-validation-gate) — one TODO per Codex finding rated "must fix" or "should fix". -- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) — one TODO per Codex, Antigravity and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. **TODO item format:** -| Field | Content | -| --------- | -------------------------------------------------------------------------------------------------- | -| Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | -| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `antigravity`, `copilot` | -| Reference | File + line / check name + run link / comment URL | -| Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | -| Status | `pending` → `in_progress` → `completed` | +| Field | Content | +|-------|---------| +| Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | +| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex` | +| Reference | File + line / check name + run link / comment URL | +| Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | +| Status | `pending` → `in_progress` → `completed` | **Rules:** @@ -402,7 +362,6 @@ For each modified `.cs` file in a NuGet-producing project: 1. **Read the file** and identify all `public` members — classes, interfaces, structs, enums, records, methods, properties, constructors. 2. **For each public member without XML docs**, add documentation following `rules/documentation.md`: - - `<summary>` on all public types, methods, properties, constructors. - `<param>` for each parameter. - `<returns>` for non-void methods. @@ -412,14 +371,12 @@ For each modified `.cs` file in a NuGet-producing project: - Follow Microsoft's style (reference `System.Text.Json`, `Microsoft.Extensions.DependencyInjection` for examples). 3. **For each public member with existing XML docs**, review for correctness: - - All parameters documented and named correctly (no stale `<param>` tags for renamed/removed parameters). - Return value described accurately. - Summary matches current behaviour (not stale from a refactor). - Exception documentation matches actual throws. 4. Optionally use the Roslyn MCP tool for public API surface discovery: - ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_public_api ``` @@ -431,7 +388,6 @@ For each modified `.cs` file in a NuGet-producing project: ### Phase 4: Test Coverage Analysis 1. **Run tests with coverage:** - ```bash dotnet test "$SOLUTION_FILE" /p:CollectCoverage=true /p:CoverletOutput=./CoverageResults/ "/p:CoverletOutputFormat=cobertura%2copencover" ``` @@ -439,13 +395,11 @@ For each modified `.cs` file in a NuGet-producing project: 2. **Analyse coverage** on the modified files. The target is **>= 80%** on changed/new code. 3. Optionally use the Roslyn MCP tool for coverage mapping: - ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_test_coverage_map ``` 4. **If coverage is below 80%:** - - **Assess scope:** Can the missing tests be added without significant new test infrastructure (new test harnesses, database fixtures, complex mock setups)? - **If yes:** Add the missing tests following `rules/writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture. Test both positive and negative cases. Name tests: `<TestedMethodName>_should_<what_it_should_do>`. - **If no (significant new infra needed):** **STOP and ask the user** whether to proceed with test infrastructure creation or defer. @@ -457,7 +411,6 @@ For each modified `.cs` file in a NuGet-producing project: ### Phase 5: Build Solution 1. **Build with normal verbosity** to capture all warnings: - ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 ``` @@ -483,15 +436,14 @@ For each warning on a modified file, follow this decision tree: **YES — the code should be fixed:** 1. Plan the fix carefully. Before applying, check two safety gates: + **Safety Gate 1 — Public API impact:** Does the fix rename, remove, or change the signature of a public member? Does it add `sealed`, change a return type, or alter an interface? - - If **yes**: **STOP and ask the user.** Public API changes are a permanent commitment in a NuGet library. - If **no**: proceed to Safety Gate 2. - + **Safety Gate 2 — Semantic behaviour change:** Does the fix change the runtime behaviour of the code on this branch? (e.g. altering exception handling, changing data transformation logic, modifying control flow) - - If **yes**: **STOP and ask the user.** The finishing-touches pass should not alter the branch's intended behaviour without explicit approval. - If **no**: apply the fix. @@ -500,21 +452,17 @@ For each warning on a modified file, follow this decision tree: **NO — the warning is a false positive:** 1. Check: does the **same warning appear in 3 or more other files** across the solution? - ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 | grep "<WARNING_ID>" | wc -l ``` 2. **If common (3+ files):** Disable globally in `.editorconfig` rather than suppressing inline: - ```ini dotnet_diagnostic.<ID>.severity = none # <reason> ``` - For test-specific suppressions, use the nested `.editorconfig` in `tests/`. 3. **If isolated (< 3 files):** Suppress inline using the narrowest scope technique from `/dotnet-dev-practical`: - - **Single line:** `#pragma warning disable <ID>` with `#pragma warning restore <ID>` and a comment explaining why. - **Single member:** `[SuppressMessage("Category", "ID", Justification = "...")]` — the `Justification` is **mandatory**. - The suppression **must** include a documented reason. Never suppress without explaining why. @@ -524,7 +472,6 @@ For each warning on a modified file, follow this decision tree: #### Rules that must NEVER be suppressed Consult `/dotnet-dev-practical` → `analyzer-reference.md` → "Rules That Should Never Be Suppressed": - - VSTHRD002, VSTHRD100, VSTHRD110 (threading bugs) - CS8600-CS8777 (nullable violations — elevated to ERROR in workspace) - CA2100 (SQL injection), CA2153 (corrupted state exceptions) @@ -541,7 +488,6 @@ If one of these fires on a modified file, it indicates a real bug. Fix the code. After each fix or suppression in Phase 6: 1. **Rebuild the solution:** - ```bash dotnet build "$SOLUTION_FILE" -v normal 2>&1 ``` @@ -561,7 +507,6 @@ After each fix or suppression in Phase 6: Review all changes made during the finishing-touches pass holistically. 1. **Read the full diff:** - ```bash git diff # unstaged finishing-touches changes git diff --staged # if anything was staged @@ -569,7 +514,6 @@ Review all changes made during the finishing-touches pass holistically. ``` 2. **Check for:** - - Consistency with the branch's original purpose — do all changes still make sense together? - Naming consistency (British English, camelCase, verb-first methods per `rules/naming.md`). - Unused imports or dead code introduced by fixes. @@ -577,9 +521,10 @@ Review all changes made during the finishing-touches pass holistically. - No leftover debugging code, TODO comments, or temporary workarounds. 3. **Project documentation review — keep markdown docs in sync with code changes.** + The branch's changes may have introduced new features, changed behaviour, added configuration options, or modified APIs that are described in the project's manually-authored markdown documentation. These docs **must** be updated to reflect the current state. + **Discovery — find all project documentation:** - ```bash # Primary location find "$REPO_ROOT/docs" -name "*.md" 2>/dev/null @@ -588,16 +533,14 @@ Review all changes made during the finishing-touches pass holistically. # Other common locations find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` - + **For each documentation file found**, check whether the branch's changes affect what it describes: - - **README.md** — Does it describe features, APIs, or usage patterns that have changed? Are installation instructions, quick-start examples, or configuration options still accurate? - **docs/*.md** — Do design documents, architecture guides, or spec files reference behaviour or APIs that the branch modified? Are code examples still valid? - **RELEASE_NOTES.md / CHANGELOG.md** — Should a new entry be added for user-visible changes (new features, breaking changes, significant bug fixes)? - **Any other `.md` files** in the project — plans, migration guides, API references. - + **What to do:** - - If a doc page describes something the branch changed → **update the doc** to match the new reality. - If a doc page contains code examples that reference modified APIs → **update or verify the examples**. - If a doc page describes a feature that was removed → **remove or update the section**. @@ -605,77 +548,19 @@ Review all changes made during the finishing-touches pass holistically. - **Do not create new documentation files** unless explicitly asked — this skill focuses on keeping existing docs accurate. 4. Optionally use Roslyn MCP tools for deeper analysis: - ``` mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code ``` -5. **If suggestions are actionable and non-controversial**, apply them and loop back to Phase 5 (Build). +4. **If suggestions are actionable and non-controversial**, apply them and loop back to Phase 5 (Build). -6. **If suggestions require user input** or are outside the finishing-touches scope, record them for the completion report. +5. **If suggestions require user input** or are outside the finishing-touches scope, record them for the completion report. **Cross-reference:** `dotnet-claude-kit:80-20-review`, `dotnet-claude-kit:code-review-workflow`. --- -### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) - -**Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates one staged fix at a time): here every reviewer sees the **entire branch** and hunts for what the pass missed — correctness bugs, API-contract breaks, async and thread-safety hazards, suppressions that hide real defects, test gaps, better approaches. - -**Panel definition, invocation flags, preflight and fallbacks live in [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** Read it before running this phase; this section covers only what is specific to .NET library work. - -**When:** After the Grand Review (Phase 8), when the branch is in its intended final local state — zero build warnings, tests passing, coverage met. If findings force changes, apply them, loop back to Phase 5 (Build), and re-run the affected reviewer on the updated diff before proceeding. - -**All three reviewers run. In parallel. None is optional.** If one is unavailable, follow the fallback ladder in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Fallback Ladder — never silently downgrade the panel. A reviewer that was skipped or substituted is always named in the Phase 12 report with the reason. - -**Run the Copilot preflight first**, before assembling the context — a stale Copilot session surfaces as `421 Misdirected Request` on every call, and it is cheaper to discover that with a one-token probe than after building a full context package. - -#### Step 1 — Assemble the full context package (once, shared by all three) - -Reviewers receive the **entire context first**, then the review request. Build a single context document containing, in this order: - -1. **Repo primer:** what the library does, its public surface, its consumers, and the conventions that constrain changes — `Directory.Build.props` settings, central package management, the analyser set (StyleCop, Roslynator, SonarAnalyzer, NetAnalyzers), the zero-warning bar, xUnit v3 + FluentAssertions + AutoFixture testing standards, and the repo's versioning scheme (NBGV or `VersionPrefix`). -2. **Branch intent:** PR title + full body (or intended PR description if not yet opened), linked issue title + body, branch name. -3. **The complete diff:** `git diff "$BASE_BRANCH"...HEAD` plus any staged/unstaged finishing-touches changes. -4. **Full current contents of every modified file** — not just hunks; reviewers need surrounding types and members to judge contracts. -5. **Verification already performed:** build output (zero warnings), test counts and results, coverage figures on modified code, and every analyser suppression added in Phase 6 **with its justification**. -6. **The review brief** (last, after all context). - -**Review brief (same for all three reviewers):** - -> Review this branch as a senior .NET reviewer for a published NuGet library. Work at **maximum depth/effort** — this is a pre-merge gate, not a skim. Hunt specifically for: (1) correctness bugs in the C# changes; (2) **public API contract problems** — breaking changes to signatures, nullability annotations, or behavioural contracts that consumers depend on, and whether they are declared as breaking; (3) async/await correctness — missing `ConfigureAwait`, sync-over-async, unobserved tasks, `CancellationToken` not honoured; (4) thread-safety and disposal hazards; (5) **analyser suppressions that hide a real defect** rather than a false positive — challenge every suppression in the diff against its stated justification; (6) test gaps — untested edge cases, negative paths, and boundary conditions, judged against the xUnit v3 / FluentAssertions / AutoFixture conventions; (7) XML documentation that is missing, inaccurate, or contradicts the implementation; (8) allocation and performance regressions on hot paths; (9) simpler or more idiomatic approaches worth taking now. For each finding return: severity (`must-fix` / `should-fix` / `nit`), file + line, what is wrong, evidence, and a concrete suggested fix. If you find nothing in a category, say so explicitly. End with an overall verdict: `APPROVE`, `APPROVE_WITH_NOTES`, or `REQUEST_CHANGES`. - -#### Step 2 — Dispatch all three reviews in parallel - -- **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package at the highest reasoning effort the tool exposes. -- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. -- **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool, so there is no `mcp__copilot__*` to load. Use the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a scratch file and pass it via shell substitution rather than inlining it in the command line. - -Send all three requests in the same tool-call block so they run concurrently. If the package exceeds a transport's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the brief only after the final part — the requirement is *entire context first, then the review*. - -#### Step 3 — Triage the findings - -1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. -2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. -3. Triage each finding like a PR comment, using the seven-category model in [`pr-checks-completion-gate.md`](../../rules/pr-checks-completion-gate.md): valid → fix (backups, ask-gates for API/semantic changes, **Codex Validation Gate for non-trivial fixes**, then loop to Phase 5); disagree → record the finding **and** the evidence-based reason for declining in the report. A declined external finding is never silently dropped. -4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). -5. **A finding that would change the public API or semantic behaviour still hits the existing ask-gates** — an external reviewer's recommendation does not bypass the user's sign-off on breaking changes. - -#### Step 4 — Verify the reviewers changed nothing, then record - -Copilot runs with shell access, and `--deny-tool 'write'` does not cover shell redirections. Confirm the working tree is untouched: - -```bash -git status --porcelain -``` - -The output must match its pre-review state. Any difference is an unintended write — revert it and record the incident. - -Store for the Phase 12 report: each reviewer's verdict, finding counts by severity, which findings were fixed vs declined (with reasons), re-review outcomes, and the model each reviewer actually ran (Copilot's in particular, since a fallback to Kimi K3 must be visible). - ---- - ### Phase 9: Commit **Delegate to the `/commit` skill** for the actual commit creation. @@ -683,18 +568,13 @@ Store for the Phase 12 report: each reviewer's verdict, finding counts by severi Before invoking `/commit`, ensure: 1. **All files are ready.** Stage specific files — **never** `git add -A` or `git add .`. **Exclude all `.bak` files** — they must never be staged or committed. Verify the **staged** index contains no `.bak` paths: - ```bash # Lists only files staged for commit — must be empty git diff --cached --name-only | grep -E '\.bak(/|$)' && echo "FAIL: .bak staged" || echo "OK" ``` - `git status` alone is **insufficient** because it also lists untracked `.bak` files, which are expected and allowed — the check must scope to the staged index. - 2. **The issue number** is known from Phase 1. If none was found, follow the lookup order in `rules/commits.md`: check PR → search issues → ask the user. - 3. **Breaking changes** are detected: check for removed/renamed public APIs, changed method signatures, changed defaults, changed serialisation formats. - 4. **The commit type** matches the nature of changes (typically `chore` or `refactor` for finishing-touches, but `fix` if a real bug was found and fixed, `docs` if only documentation was added). **Commit-message ownership.** The `/commit` skill handles generic mechanics (conventional format, HEREDOC, `Co-Authored-By` trailer) but **does not** enforce this workspace's `Refs: #<issue-number>` footer or `BREAKING CHANGE:` footer — those are per-repo rules from `rules/commits.md`. This skill is therefore responsible for: @@ -729,34 +609,27 @@ If the finishing-touches pass made changes across multiple logical areas (e.g. d **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. 1. **Pre-push build verification:** - ```bash dotnet build "$SOLUTION_FILE" ``` - If any warnings appear, **stop and fix before pushing**. 2. **Push:** - ```bash git push -u origin HEAD ``` 3. **Monitor ALL CI checks** (including non-required): - ```bash gh pr checks --watch ``` - If no PR exists, monitor via: - ```bash gh run list --branch "$(git branch --show-current)" --limit 5 gh run view <run-id> --log-failed ``` 4. **On failure:** - - Retrieve failure logs: `gh run view <run-id> --log-failed` - Diagnose the root cause from the actual error output. Do not guess. - Fix the issue. @@ -764,7 +637,6 @@ If the finishing-touches pass made changes across multiple logical areas (e.g. d - After pushing the fix, monitor checks again. Repeat until all green. 5. **Do not:** - - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence. - Push speculative fixes without reading the failure logs. @@ -813,15 +685,15 @@ gh api repos/<owner>/<repo>/pulls/<pr-number>/reviews --paginate Classify each thread into **exactly one** category. Record the category on the thread's TODO: -| Category | Meaning | Required resolution path | -| --------------------- | ----------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `VALID_ISSUE` | The reviewer/analyser is correct and the code needs to change | Fix code → Codex (if non-trivial) → commit → push → CI green → reply citing commit + evidence → resolve thread | -| `FALSE_POSITIVE` | The flag is wrong — code is correct, analyser misread, reviewer misread the context | Reply with specific evidence (what the code actually does, which test/spec/invariant proves it, why the flag is wrong) → resolve thread | -| `ALREADY_FIXED` | The concern is valid but was resolved in a subsequent commit on this branch | Reply pointing at the specific commit hash + diff line → resolve thread | -| `SUGGESTION_ACCEPTED` | Non-blocking suggestion worth taking | Same flow as `VALID_ISSUE` | -| `SUGGESTION_DECLINED` | Non-blocking suggestion we decline on merit | Reply explaining why (principle, trade-off, out-of-scope + follow-up issue link) → resolve thread | -| `QUESTION` | Reviewer asked for clarification, no code change implied | Reply with the answer → resolve thread | -| `OUT_OF_SCOPE` | Valid concern but outside this PR's scope | Open a follow-up GitHub issue, reply linking the issue → resolve thread. Per `feedback_create_followup_issues` memory — always file the issue, never defer verbally. | +| Category | Meaning | Required resolution path | +|----------|---------|--------------------------| +| `VALID_ISSUE` | The reviewer/analyser is correct and the code needs to change | Fix code → Codex (if non-trivial) → commit → push → CI green → reply citing commit + evidence → resolve thread | +| `FALSE_POSITIVE` | The flag is wrong — code is correct, analyser misread, reviewer misread the context | Reply with specific evidence (what the code actually does, which test/spec/invariant proves it, why the flag is wrong) → resolve thread | +| `ALREADY_FIXED` | The concern is valid but was resolved in a subsequent commit on this branch | Reply pointing at the specific commit hash + diff line → resolve thread | +| `SUGGESTION_ACCEPTED` | Non-blocking suggestion worth taking | Same flow as `VALID_ISSUE` | +| `SUGGESTION_DECLINED` | Non-blocking suggestion we decline on merit | Reply explaining why (principle, trade-off, out-of-scope + follow-up issue link) → resolve thread | +| `QUESTION` | Reviewer asked for clarification, no code change implied | Reply with the answer → resolve thread | +| `OUT_OF_SCOPE` | Valid concern but outside this PR's scope | Open a follow-up GitHub issue, reply linking the issue → resolve thread. Per `feedback_create_followup_issues` memory — always file the issue, never defer verbally. | **A thread must never be closed without a reply.** "Resolve with no response" is only acceptable when the thread was authored by us and had no other participants. @@ -842,34 +714,23 @@ For bot-flagged false positives (SonarCloud, Codacy, codeant-ai): the same bar a For each thread in these categories: 1. Mark the TODO `in_progress`. - 2. Create `.bak` copies of all files the fix will touch (per [Backup Before Modify](#backup-before-modify)). - 3. Plan the fix. Apply the [Safety Gate 1 — Public API impact](#phase-6-classify--address-each-warning) and [Safety Gate 2 — Semantic behaviour change](#phase-6-classify--address-each-warning) checks from Phase 6. - 4. **Codex validation (mandatory before commit for non-trivial fixes)** — invoke the [Codex Validation Gate](#codex-validation-gate) with the thread URL, original code, proposed diff, and reasoning. Do **not** commit until the verdict is `APPROVED` or `APPROVED_WITH_NOTES`. - 5. Apply the fix. Rebuild (loop back to Phase 5 → Phase 7 if warnings regress). Run the affected tests. - 6. Commit (via the `/commit` skill — one commit per logical thread group; batching threads that touch the same file or concern is fine, but the commit message body must list every thread addressed). **Never amend.** - 7. Push. Monitor CI via Phase 10 until all checks are green. - 8. Reply on the thread (using the root `databaseId` as `in_reply_to`): - ```bash gh api repos/<owner>/<repo>/pulls/<pr-number>/comments \ -f body='<evidence-based response referencing commit <hash> and the specific change>' \ -F in_reply_to=<root-comment-databaseId> ``` - 9. Resolve the thread: - ```bash gh api graphql -f query='mutation($id:ID!){resolveReviewThread(input:{threadId:$id}){thread{id isResolved}}}' \ -F id=<thread-id> ``` - 10. Mark the TODO `completed` and record the reply URL + commit hash on the TODO for the Phase 12 report. #### Step 5 — Reply-only workflow for FALSE_POSITIVE / SUGGESTION_DECLINED / ALREADY_FIXED / QUESTION / OUT_OF_SCOPE @@ -938,12 +799,10 @@ Pass forward for the completion report: **Additionally required when Phase 11 ran (`--no-push` OFF AND a PR exists):** 6. **Zero unaddressed PR review threads.** Re-run the Phase 11 Step 1 GraphQL enumeration one final time. Every thread in the result must satisfy one of: - - `isResolved=true`, **or** - `isResolved=false` AND the latest comment on the thread is authored by us AND the thread is listed under "Awaiting reviewer" in the final report. - - Any thread that is `isResolved=false` with the latest comment authored by someone other than us is **unaddressed** — loop back to Phase 11 Step 2. + Any thread that is `isResolved=false` with the latest comment authored by someone other than us is **unaddressed** — loop back to Phase 11 Step 2. 7. **No new PR activity has arrived since the last poll.** Re-fetch issue comments and reviews one final time. If anything new has appeared (new inline comments, new review, new issue comment), extend the TODO list and loop back to Phase 11. If any applicable condition is not satisfied, **do not report completion.** State which gate failed and continue the loop. @@ -963,14 +822,6 @@ Provide a summary with evidence: - **Test Coverage:** ~<percentage>% on modified code (<count> tests added) - **Warnings Resolved:** <count> fixed, <count> suppressed (with justification), <count> disabled globally - **Code Review Fixes:** <count> improvements applied -- **External-review fixes:** <count> from Codex, <count> from Antigravity, <count> from Copilot, <count> declined with reasons - -### External AI Review -| Reviewer | Model | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | -|----------|-------|---------|----------|------------|-----|-------|--------------------------| -| Codex | ... | ... | n | n | n | n | n | -| Antigravity | ... | ... | n | n | n | n | n | -| Copilot | `grok-4.6` | ... | n | n | n | n | n | ### Warning Resolution Summary | Warning ID | File | Resolution | Justification | @@ -1025,22 +876,19 @@ done ``` **Cleanup command:** - ```bash find . -name "*.bak" -not -path "*/bin/*" -not -path "*/obj/*" -delete ``` ### Commit - `<commit-hash>` — `<commit-message-subject>` - ``` --- ## Codex Validation Gate -**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. +**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. **Timing rule:** Codex runs on the *uncommitted* diff. The correct sequence is: stage files → invoke Codex on the staged diff → act on the verdict → commit. If you are already mid-commit when you realise the gate was skipped, reset the staging, run Codex, then re-stage and commit as a single commit. Do **not** commit first and retroactively "validate" — that defeats the gate. @@ -1119,7 +967,6 @@ Use the `codex` action of `mcp__codex-cli__codex` with a self-contained brief. T When CI fails or PR comments require code changes: ``` - Fix code → Phase 5 (Build — zero warnings locally) → Phase 7 (Rebuild & Verify) → Phase 8 (Grand Review) @@ -1128,7 +975,6 @@ Fix code → Phase 5 (Build — zero warnings locally) → Phase 10 (Monitor CI) → Phase 11 (Address Comments) → Phase 12 (Report) - ``` Each iteration creates a **new commit**. After all fixes are done, update the PR description to reflect the **final** state. @@ -1186,10 +1032,6 @@ If you catch yourself about to do any of these, stop and reconsider: - About to **apply a non-trivial fix without a Codex MCP review** — non-trivial fixes must pass the Codex Validation Gate **before the commit**, not after. - About to **commit a PR-comment-driven code change without running Codex first** — PR-comment fixes are never exempt from the gate; stage, validate, then commit. - About to **silently skip the Codex gate because the MCP is unavailable** — retry or explicitly ask the user; never pretend the gate passed. -- About to **skip Phase 8.5** or run fewer than **all three** external reviewers without the user's explicit sign-off. -- About to let Copilot's `--model` fall back to `auto`, or to omit `--effort high` — both silently downgrade the review. -- About to **run Copilot without the read-only `--deny-tool` set**, or to skip the post-review `git status --porcelain` check. -- About to **silently drop an external reviewer's `must-fix`** — every one is fixed or declined with recorded evidence. - About to **reply to a PR comment with a generic "false positive" message** — every false-positive reply must cite specific evidence (file/line, test, spec, invariant) per [Step 3 — Reply quality rules](#step-3--reply-quality-rules-especially-for-false_positive). - About to **resolve a PR review thread without posting a reply first** — a resolved thread without an explicit response does not count as addressed; the only exception is a thread we authored ourselves with no other participants. - About to **leave a thread unresolved after replying to a bot** (SonarCloud, Codacy, codeant-ai, Dependabot) — bot threads always get both a reply and a resolve. @@ -1213,7 +1055,6 @@ If you catch yourself about to do any of these, stop and reconsider: | 6. Warnings | Each warning classified and addressed | Resolution documented per warning | | 7. Verify | Warning resolved after each fix | Rebuild output confirms | | 8. Grand Review | All changes reviewed holistically | No outstanding concerns | -| 8.5 External AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer | Commit message | | 10. CI | All checks green (including non-required) | `gh pr checks` output | | 11. PR Comments | Every thread triaged, fixed-or-replied, and (for bots + clear-cut cases) resolved | Zero `isResolved=false` threads whose latest comment is not ours; category breakdown recorded | @@ -1254,13 +1095,10 @@ If you catch yourself about to do any of these, stop and reconsider: - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__get_test_coverage_map` — Coverage analysis - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns` — Anti-pattern detection - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code` — Unused code detection -- **`mcp__codex-cli__codex` / `mcp__codex-cli__review`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)) and one third of the Phase 8.5 panel. Use `ToolSearch` to load the schema if not already available. -- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check -- **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) +- **`mcp__codex-cli__codex`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)). Use `ToolSearch` to load the schema if not already available. - GitHub CLI (`gh`) — PR management, CI monitoring, comment handling **Uses these tools for sub-agent / TODO orchestration:** - `Agent` (with `subagent_type="general-purpose"`) — the Phase 1.5 CI pre-check sub-agent. - `TaskCreate` / `TaskUpdate` / `TaskList` — master TODO list in Phase 2.5 and ongoing throughout the pass. - `mcp__contextstream__memory(action="create_todo")` — optional alternative to `TaskCreate` when ContextStream is active. -``` diff --git a/.agents/implement-issue/SKILL.md b/.agents/implement-issue/SKILL.md index f16c8a4..4c1a655 100644 --- a/.agents/implement-issue/SKILL.md +++ b/.agents/implement-issue/SKILL.md @@ -12,20 +12,15 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet **Core principles:** - **Maximum autonomy** — research before asking. Only ask the user when genuinely blocked after exhausting all research options. - - **Maximum thoroughness** — every phase has explicit quality gates. No shortcuts. No skipped steps. - - **Evidence before claims** — never report completion without evidence (build output, test counts, CI status, PR URL). - - **All comments addressed** — every single PR comment and conversation must be addressed. No exceptions. Bot-authored threads (CodeRabbit, Codacy, Bito, SonarCloud) follow the same triage rules as human reviewers. SonarCloud / SonarQube Cloud additionally reports issues that exist **only in the SonarCloud platform** (not as GitHub comments) — these are fetched via the `sonarqube-cloud` MCP server and resolved with the same seven-category triage. - - **All checks pass — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: - 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the implement-issue skill to implement GitHub issue #\<number\>." @@ -33,24 +28,15 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet ## Invocation ``` -/implement-issue <github-issue-url>|<linear-issue-url> # Full end-to-end -/implement-issue <github-issue-url>|<linear-issue-url> --no-push # Implement + commit locally, skip push/PR/CI +/implement-issue <github-issue-url> # Full end-to-end +/implement-issue <github-issue-url> --no-push # Implement + commit locally, skip push/PR/CI ``` -### Supported URL formats - -**For GitHub issues:** - +Supported URL formats: - `https://github.com/<owner>/<repo>/issues/<number>` - `<owner>/<repo>#<number>` - `#<number>` (current repo) -**For Linear issues:** - -- `https://linear.app/<team>/issue/<linear-issue-id>/<title>` -- `<team>/<linear-issue-id>` -- `<linear-issue-id>` (Linear workspace/team from repository `## Project Scope` in `CLAUDE.md`, or the mirrored section in `AGENTS.md` / `GEMINI.md` / `.github/copilot-instructions.md`) - **`--no-push` flag:** When set, skip all push, PR creation, CI monitoring, and PR comment resolution steps. Commit locally only. ## The Process @@ -63,7 +49,7 @@ digraph implement_issue { fetch [label="0. Fetch & Parse Issue"]; repo [label="1. Identify Target Repository"]; research [label="2. Research & Gather Context"]; - plan [label="3. Plan Implementation\n(Codex + Copilot + Antigravity review plan)"]; + plan [label="3. Plan Implementation\n(Codex reviews plan)"]; blocked [shape=diamond, label="Genuinely\nblocked?"]; ask [label="Ask user"]; branch [label="4. Create Branch"]; @@ -71,7 +57,7 @@ digraph implement_issue { build [label="6. Build & Static Analysis\n(Zero new warnings)"]; test [label="7. Test\n(All pass, coverage gates)"]; review [label="8. Self-Review\n(git diff, patterns, docs)"]; - codex [label="9. External AI Review\nCodex + Antigravity + Copilot"]; + codex [label="9. Codex Review"]; issues [shape=diamond, label="Issues\nfound?"]; commit [label="10. Commit\n(Conventional, Refs: #issue)"]; push_check [shape=diamond, label="--no-push?"]; @@ -79,7 +65,7 @@ digraph implement_issue { monitor [label="12. Monitor CI Checks\n(ALL checks incl. non-required)"]; ci_ok [shape=diamond, label="All checks\npass?"]; fix_ci [label="Read logs, diagnose, fix"]; - comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud, Codacy issues + any other issue)"]; + comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud issues)"]; comments_ok [shape=diamond, label="All addressed?\nNo new comments?"]; gate [label="14. Completion Gate\n(All criteria met?)"]; gate_ok [shape=diamond, label="Pass?"]; @@ -116,49 +102,36 @@ digraph implement_issue { ### Phase 0: Fetch & Parse Issue 1. **Parse the URL** to extract `owner`, `repo`, and `issue-number`. - 2. **Fetch the full issue:** - ```bash gh issue view <number> --repo <owner>/<repo> --json number,title,body,labels,assignees,milestone,state,comments,projectItems ``` - 3. **Extract and understand:** - - **Title** and **description** — what needs to be done. - **Acceptance criteria** — look for a section in the body (e.g. "## Acceptance Criteria", "### AC", checkboxes). If none, derive from the description. - **Labels** — determine change type (`bug` → fix, `enhancement`/`feature` → feature, `documentation` → docs, etc.). - **Linked issues/PRs** — referenced in the body or comments (`#123`, `Depends on ...`). - **Comments** — additional context, clarifications, decisions from the discussion. - 4. **If the issue is closed** or already has a linked merged PR that fully addresses it, stop and inform the user. ### Phase 1: Identify Target Repository 1. Determine the target repository from the issue URL. - 2. Map to the local workspace directory: `C:\DevNet\my\mrploch\<repo-name>\`. - 3. Verify the repo is cloned: - ```bash ls "C:/DevNet/my/mrploch/<repo-name>" ``` - 4. Navigate to the repo and ensure it is up to date: - ```bash cd "C:/DevNet/my/mrploch/<repo-name>" git fetch origin git status ``` - 5. Identify the base branch (`main` or `master`): - ```bash git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' ``` - If that fails, check `git branch -r` for `origin/main` or `origin/master`. `ploch-common` uses `master`; newer repos use `main`. ### Phase 2: Research & Gather Context @@ -166,49 +139,38 @@ digraph implement_issue { Before writing any code, build comprehensive understanding. This phase is critical — thorough research prevents wasted implementation time. 1. **Read the target repo:** - - README.md, CLAUDE.md, `.claude/rules/` files. - Relevant source files in the area of change. - Existing tests for the affected modules. - Project structure (`src/`, `tests/`, solution files). - `Directory.Build.props`, `Directory.Packages.props` for build configuration. - 2. **Check related issues and PRs:** - ```bash # Related issues (open and closed) gh issue list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 # Related PRs (open and recently closed/merged) gh pr list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 ``` - 3. **Read linked or related PRs** for context on prior decisions and approaches: - ```bash gh pr view <pr-number> --repo <owner>/<repo> --json title,body,files,commits gh pr diff <pr-number> --repo <owner>/<repo> ``` - 4. **Check sibling repos** for patterns — browse `C:\DevNet\my\mrploch\` siblings: - - `ploch-common` — extension methods, serialisation, DI bundles, CRUD endpoints. - `ploch-data` — repository pattern, Unit of Work, entity configurations, Specification. - `ploch-lists`, `ploch-groupmatters` — application-level patterns (API, data layer, model). - `mrploch-development` — shared build config, dependency versions. - 5. **Research externally** if needed: - - Microsoft Learn docs: `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` - Library documentation via Context7: `mcp__plugin_context7_context7__resolve-library-id` then `query-docs` - External repo understanding via DeepWiki: `mcp__plugin_10x-swe_deepwiki__ask_question` - Web search for non-obvious problems or unfamiliar APIs. - 6. **Understand the area of change** — read the specific files, classes, and methods that will be affected. Trace call chains. Understand the data flow. Identify what tests exist and what patterns they follow. ### Phase 3: Plan Implementation 1. **Create a detailed plan** using **TodoWrite** with sub-tasks covering: - - Implementation tasks (code changes, new files, modified files). - Test creation (unit tests, integration tests if needed, bug-reproducing test if it's a bug fix). - Documentation tasks (XML docs on new public APIs, README/doc page updates). @@ -218,35 +180,28 @@ Before writing any code, build comprehensive understanding. This phase is critic - Commit. - Push/PR (unless `--no-push`). -2. **Consult two external models for plan review** — send both requests in the same tool-call block so they run concurrently: - +2. **Consult Codex for plan review:** ``` - mcp__codex-cli__codex # OpenAI lens - copilot -p "<plan brief>" --model grok-4.6 … # xAI lens, via Bash — see rules/external-ai-review.md + mcp__codex-cli__codex ``` - - Send the plan to each along with: - + Send the plan along with: - The issue description and acceptance criteria. - Key files and patterns discovered during research. - Any design decisions you've made and their rationale. - Ask each to review the plan for completeness, correctness, and adherence to project patterns. A plan is cheap to fix and expensive to get wrong, so it earns two independent opinions before any code is written. Full Copilot flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md). + Ask Codex to review the plan for completeness, correctness, and adherence to project patterns. -3. **Address the feedback** — adjust the plan if either reviewer identifies gaps, risks, or improvements. Where they disagree, judge on the evidence; if the disagreement is both genuine and load-bearing, surface it to the user rather than picking silently. +3. **Address Codex feedback** — adjust the plan if Codex identifies gaps, risks, or improvements. 4. **Auto-proceed** unless there are genuinely blocking questions that cannot be resolved by research or best judgment. Resolve uncertainties yourself in most cases. ### Phase 4: Create Branch 1. Ensure you are on the base branch and it is up to date: - ```bash git checkout <base-branch> && git pull origin <base-branch> ``` - 2. Determine the change type from the issue analysis (Phase 0). Mapping: - - `bug` label or bug-related title → `fix` - `enhancement`/`feature` label or new capability → `feature` - Documentation-only → `docs` @@ -254,13 +209,10 @@ Before writing any code, build comprehensive understanding. This phase is critic - Code restructuring without behaviour change → `refactor` - Performance improvement → `perf` - Tests only → `test` - 3. Create the branch following the naming convention (see `rules/branch-naming.md`): - ```bash git checkout -b <change-type>/<issue-number>-<brief-description> ``` - Example: `feature/72-dbcontext-creation-lifecycle-plugins`, `fix/187-duplicate-entity-concurrent-upsert` ### Phase 5: Implement @@ -296,9 +248,7 @@ When the issue is a bug fix: #### Documentation - **XML documentation** on all new/modified public types, methods, properties (for public/open-source packages). Follow Microsoft's style. Include `<example>` blocks where usage is not obvious. See `rules/documentation.md`. - - **Update project markdown documentation** — manually-authored `.md` files must stay in sync with the code. Discover all project docs: - ```bash REPO_ROOT=$(git rev-parse --show-toplevel) # Primary: docs/ folder, root-level docs, and any other .md files in the project @@ -306,9 +256,7 @@ When the issue is a bug fix: ls "$REPO_ROOT"/README.md "$REPO_ROOT"/RELEASE_NOTES.md "$REPO_ROOT"/CHANGELOG.md 2>/dev/null find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` - For each documentation file found, check whether your changes affect what it describes: - - **README.md** — features, APIs, usage patterns, installation instructions, quick-start examples, configuration options. - **docs/*.md** — design documents, architecture guides, spec files, migration guides, API references. - **RELEASE_NOTES.md / CHANGELOG.md** — add entries for user-visible changes (new features, breaking changes, significant bug fixes). @@ -318,7 +266,6 @@ When the issue is a bug fix: #### SampleApp (ploch-data only) If working on the `ploch-data` repository and the change adds or modifies library features: - - Update the SampleApp to demonstrate the new/changed features. - The SampleApp must use NuGet package references, not ProjectReference. - See `rules/sample-apps.md`. @@ -338,7 +285,6 @@ Read the **entire** build output. Do not skim. #### Step 2: Catalogue every warning Go through every warning in the build output. These come from: - - **StyleCop.Analyzers** — naming, documentation, layout, ordering. - **Roslynator.Analyzers** — code simplification, redundancy, best practices. - **SonarAnalyzer.CSharp** — bugs, code smells, security hotspots. @@ -365,12 +311,12 @@ The build output must show **zero warnings**. If any remain, go back to Step 3. #### Summary -| Gate | Requirement | -| -------------------------- | -------------------------------------- | -| Compilation | Zero errors | -| Static analysis warnings | Zero (all fixed) | -| Code style (.editorconfig) | Zero violations | -| Suppressions added | Zero (unless justified and documented) | +| Gate | Requirement | +|------|-------------| +| Compilation | Zero errors | +| Static analysis warnings | Zero (all fixed) | +| Code style (.editorconfig) | Zero violations | +| Suppressions added | Zero (unless justified and documented) | ### Phase 7: Test @@ -401,147 +347,91 @@ Before committing, review your own changes thoroughly: 3. Re-validate against the original issue requirements and acceptance criteria from Phase 0. Did you implement everything that was asked? Did you miss any AC? 4. If anything needs improvement: fix it, then loop back to **Phase 6** (Build). -### Phase 9: External AI Review — Codex + Antigravity + Copilot - -**Panel definition, invocation flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** - -All three reviews are **mandatory** for every non-trivial change — three providers, three sets of blind spots. Run them in parallel (one tool-call block) and pass **full context** to each: the issue number + title + requirements, the design decisions taken and why, the diff (`git diff <base-branch>...HEAD`), verification evidence (build/test results), and a request for a structured verdict (`APPROVED` / `APPROVED_WITH_NOTES` / `CHANGES_REQUESTED` / `REJECTED` with concrete findings). - -1. **Codex review:** - - ``` - mcp__codex-cli__review (or mcp__codex-cli__codex with a review brief) - ``` - - Provide the diff and full context as above. **Fallback:** if the Codex MCP is unavailable (e.g. account/model restriction — try at least one alternative model before concluding), substitute an independent local review agent (e.g. `feature-dev:code-reviewer`) with the same brief, and record the substitution in the PR description and completion report. Never silently skip the second opinion. - -2. **Antigravity review:** +### Phase 9: Codex Review +1. **Submit changes for Codex review:** ``` - mcp__antigravity__ask_antigravity (model="gemini-3.1-pro-high", paths=[...]) + mcp__codex-cli__review ``` - - Provide the same full-context brief and the diff. Ask specifically for: correctness issues, missed edge cases, API-contract concerns, and test-coverage gaps. - -3. **Copilot review:** - - ```bash - copilot -p "$BRIEF" --model grok-4.6 --effort high --allow-all-tools \ - --deny-tool 'write' --disable-builtin-mcps --no-ask-user -s --log-level none -C "$REPO_ROOT" - ``` - - Shell-out through `Bash` — Copilot is **not** an MCP server, so there is no `mcp__copilot__*` tool to load. Use the full canonical flag set from [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (the abbreviated form above omits the `shell(git …)` / `shell(gh …)` denials). Run the preflight first; on failure follow the fallback ladder (retry with `GITHUB_TOKEN`/`GH_TOKEN`/`COPILOT_GITHUB_TOKEN` stripped → Kimi K3 → ask the user). Afterwards verify `git status --porcelain` is unchanged. - -4. **Review all feedback** — evaluate each suggestion from all three reviewers on merit. Deduplicate overlapping findings, crediting each reviewer that raised them; a finding raised independently by two model families is higher-confidence. - -5. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build), then re-run the affected reviewer on the revised diff. - -6. **Document disagreements** — if you disagree with a suggestion, note your reasoning (in the PR description's Design Decisions section if user-visible). This is acceptable — not every suggestion must be implemented, but a declined finding is recorded with its evidence, never silently dropped. - -7. **Record which model each reviewer ran** — Copilot's in particular, so a fallback to Kimi K3 is visible in the completion report. + Provide the diff (`git diff <base-branch>...HEAD`) and context about what was changed and why. +2. **Review Codex feedback** — evaluate each suggestion on merit. +3. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build). +4. **Document disagreements** — if you disagree with a Codex suggestion, note your reasoning. This is acceptable — not every suggestion must be implemented. **Skip this phase** only for truly trivial changes (single-line typo fix, config-only change). ### Phase 10: Commit - **One commit per logical change** — typically one commit for the entire issue. For large issues with naturally separable parts, use multiple focused commits. - - **Conventional Commits** format (see `rules/commits.md`): - ``` <type>(<scope>): <subject> - + <body — what changed and why> - + [BREAKING CHANGE: <description>] Refs: #<issue-number> ``` - - The `Refs: #<issue-number>` footer is **mandatory**. The issue number comes from Phase 0. - - Detect and document breaking changes — check for removed/renamed public APIs, changed signatures, changed defaults. Add `BREAKING CHANGE:` footer if any. - - Stage specific files — **never** `git add -A` or `git add .`. - - **Never amend** existing commits unless the user explicitly asks. - - Update the change log if the commit contains user-visible changes (new features, breaking changes, significant fixes). ### Phase 11: Push & Create PR (skip if `--no-push`) 0. **Pre-push build verification** — before any push, run a final clean build of the full solution and confirm **zero warnings**: - ```bash dotnet build <solution-file> ``` - If any warnings appear, **stop and fix them before pushing**. This is critical — every warning you let through will come back as a CI failure or PR comment, costing a full pipeline round-trip. Fix locally first. 1. **Push the branch:** - ```bash git push -u origin HEAD ``` 2. **Check for existing PR:** - ```bash gh pr view --json number,url 2>/dev/null || echo "NO_PR" ``` 3. **Read PR template** (if it exists): - ```bash cat .github/pull_request_template.md 2>/dev/null || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null ``` 4. **Create PR** with a detailed description following `rules/pr-descriptions.md`: - ```bash gh pr create --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF' ## Summary - + <What this PR does and why. Reference the issue.> - + ## Changes - + - <Specific change 1> - <Specific change 2> - ... - + ## Design Decisions - + <Non-obvious choices and their rationale> - + ## Testing - + - Unit tests: <count> added/modified - Manual verification: <what was tested> - Coverage: ~<percentage>% on new code - + ## Related - + Closes #<issue-number> EOF )" && gh pr edit --add-assignee @me ``` -4b. **Request a GitHub Copilot review (mandatory):** immediately after creating the PR, request Copilot as a reviewer via the GitHub MCP tool: - -``` -mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) -``` - - Fallback if the MCP tool is unavailable: - -```bash -gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" -``` - - Copilot's review comments are then addressed in Phase 13 like any other reviewer's. - -1. **If updating an existing PR** (e.g. after fix loop): - +5. **If updating an existing PR** (e.g. after fix loop): ```bash gh pr edit <pr-number> --body "$(cat <<'EOF' [updated body reflecting final state] @@ -556,21 +446,18 @@ gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[ **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. A bot that says `fail` because it hasn't yet rescanned the latest commit is **still failing** by the gate's definition — wait for the rescan or push a no-op-ish commit to retrigger; do not declare completion with a "stale check" caveat. 1. **Wait for ALL checks** to complete — **including non-required checks:** - ```bash gh pr checks <pr-number> --watch ``` 2. **If any check fails:** a. Retrieve the failure logs: - - ```bash - # Find the failed run - gh run list --branch <branch-name> --limit 5 - # Get failure details - gh run view <run-id> --log-failed - ``` - + ```bash + # Find the failed run + gh run list --branch <branch-name> --limit 5 + # Get failure details + gh run view <run-id> --log-failed + ``` b. **Diagnose the root cause** — read the actual error output. Do not guess. c. If the failure is not obvious, research the error (web search, docs, sibling repos for how they handle it). d. Fix the issue in code. @@ -578,7 +465,6 @@ gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[ f. After pushing the fix, monitor checks again. Repeat until **all green**. 3. **Do not:** - - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence (check if the same test fails consistently). - Push speculative fixes without reading the failure logs. @@ -620,7 +506,6 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary #### GitHub PR comments, review threads & conversations 1. **Fetch all PR feedback:** - ```bash # Review comments (inline on code) gh api repos/<owner>/<repo>/pulls/<pr-number>/comments --paginate @@ -631,14 +516,12 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 2. **For each comment or conversation:** - - If it identifies a **valid issue** → fix the code. - If it is a **false positive or irrelevant** → reply with a clear, specific explanation of why you believe so. Do not just say "false positive" — explain the reasoning. - If it is a **suggestion worth considering** → evaluate on merit. Implement if it improves the code; explain why not if you disagree. - **Every single conversation must have a response.** No comment left unaddressed. It does not matter whether it is blocking the merge or not. 3. **Reply to comments:** - ```bash # Reply to a review comment gh api repos/<owner>/<repo>/pulls/<pr-number>/comments/<comment-id>/replies -f body="<your reply>" @@ -647,14 +530,12 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 4. **If code changes were made:** - - Commit the fixes (new commit, never amend). - Push. - **Loop back to Phase 12** (monitor CI checks again). - After checks pass, re-fetch comments — new automated comments may have been added by the new push. 5. **Only proceed when:** - - Zero unaddressed conversations remain. - No new comments have appeared since your last round of responses. - All CI checks are still green after the latest push. @@ -674,21 +555,21 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary Before reporting completion, **every single one** of these criteria must be met: -| # | Criterion | How to Verify | -| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | -| 2 | All tests pass | Test output with counts | -| 3 | Test coverage ≥80% on new code | Coverage report or estimate | -| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | -| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | -| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | -| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | -| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | -| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | -| 10 | SampleApp works (if ploch-data) | Manual test | -| 11 | Conventional commit with `Refs: #issue` | Commit log | -| 12 | PR description documents all changes and decisions | PR body | -| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | +| # | Criterion | How to Verify | +|---|-----------|---------------| +| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | +| 2 | All tests pass | Test output with counts | +| 3 | Test coverage ≥80% on new code | Coverage report or estimate | +| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | +| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | +| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | +| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | +| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | +| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | +| 10 | SampleApp works (if ploch-data) | Manual test | +| 11 | Conventional commit with `Refs: #issue` | Commit log | +| 12 | PR description documents all changes and decisions | PR body | +| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | **If any criterion is not met:** go back and fix it. Do not report completion. @@ -775,20 +656,19 @@ When an issue requires changes in multiple repositories: **Research before asking.** The user expects maximum autonomy. -| Situation | Action | -| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| Unsure about a pattern | Check sibling repos for examples | -| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | -| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | -| Unsure about test approach | Check existing test projects for patterns | -| Build warning you don't understand | Research the analyser rule ID, then fix or document | -| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | -| PR comment you disagree with | Reply with clear reasoning, citing evidence | -| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | -| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | +| Situation | Action | +|-----------|--------| +| Unsure about a pattern | Check sibling repos for examples | +| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | +| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | +| Unsure about test approach | Check existing test projects for patterns | +| Build warning you don't understand | Research the analyser rule ID, then fix or document | +| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | +| PR comment you disagree with | Reply with clear reasoning, citing evidence | +| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) for opinion | +| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | **Only ask the user when:** - - A decision has significant business or architectural impact that cannot be inferred from the issue, codebase, or documentation. - Multiple valid approaches exist AND the choice materially affects the user AND research hasn't provided a clear winner. - You are truly blocked with no way to research the answer. @@ -800,7 +680,6 @@ When an issue requires changes in multiple repositories: ## Non-Blocking Issues When you encounter something worth tracking that is outside the current issue's scope, **open a GitHub issue** for it — do not accumulate items in a `TODO-important.md` file. Create an issue when you encounter: - - Questions that can be answered later. - Suggestions for improvements outside the current issue scope. - Technical debt noticed but outside scope. @@ -808,7 +687,6 @@ When you encounter something worth tracking that is outside the current issue's - Pre-existing issues discovered during implementation. Guidance: - - Give it a clear conventional-style title (e.g. `chore: ...`, `test: ...`, `refactor: ...`) and a body capturing the context, why it is out of scope, and a suggested resolution. - Label genuinely high-priority follow-ups (release blockers, correctness or consumer risk) with the `important` label so they stand out. Create the label first if the repo does not have it. - Cross-reference the originating issue/PR in the new issue body. @@ -843,32 +721,31 @@ If you catch yourself about to do any of these, stop and reconsider: ## Quick Reference -| Phase | Gate | Evidence Required | -| ---------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | -| 1. Repo | Repo identified and up to date | `git status` clean | -| 2. Research | Context gathered | Key files and patterns identified | -| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | -| 4. Branch | Created from latest base | Branch name follows convention | -| 5. Implement | Code + tests + docs written | Files created/modified | -| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | -| 7. Test | All pass, ≥80% new coverage | Test output with counts | -| 8. Self-Review | No issues found | `git diff` reviewed | -| 9. External AI Review | Codex, Antigravity AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | -| 10. Commit | Conventional format, `Refs` footer | Commit message | -| 11. PR | Detailed description, linked issue | PR URL | -| 12. CI | ALL green (including non-required) | `gh pr checks` output | -| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | -| 14. Gate | All 13 criteria met | Checklist verified | -| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | -| 15. Report | Evidence provided | Summary with links | +| Phase | Gate | Evidence Required | +|-------|------|-------------------| +| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | +| 1. Repo | Repo identified and up to date | `git status` clean | +| 2. Research | Context gathered | Key files and patterns identified | +| 3. Plan | Reviewed by Codex | Plan approved or adjusted | +| 4. Branch | Created from latest base | Branch name follows convention | +| 5. Implement | Code + tests + docs written | Files created/modified | +| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | +| 7. Test | All pass, ≥80% new coverage | Test output with counts | +| 8. Self-Review | No issues found | `git diff` reviewed | +| 9. Codex | Feedback addressed | Review notes | +| 10. Commit | Conventional format, `Refs` footer | Commit message | +| 11. PR | Detailed description, linked issue | PR URL | +| 12. CI | ALL green (including non-required) | `gh pr checks` output | +| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | +| 14. Gate | All 13 criteria met | Checklist verified | +| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | +| 15. Report | Evidence provided | Summary with links | --- ## Integration **References these rules (auto-loaded from `.claude/rules/`):** - - `branch-naming.md` — Branch naming convention - `commits.md` — Conventional Commit format and issue linking - `writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture standards @@ -883,7 +760,6 @@ If you catch yourself about to do any of these, stop and reconsider: - `agent.md` — Agent behaviour specification and CI check gate **Uses these skills when appropriate:** - - **dotnet-dev-finishing-touches** — REQUIRED final quality pass after the completion gate (Phase 14.5) - **superpowers:verification-before-completion** — REQUIRED before any completion claim - **superpowers:dispatching-parallel-agents** — When multiple independent sub-tasks exist @@ -893,10 +769,8 @@ If you catch yourself about to do any of these, stop and reconsider: - **review-pr-comments** — For structured PR comment review (Phase 13) **Uses these MCP tools:** - - `mcp__codex-cli__codex` — Plan review and ad-hoc consultation for non-obvious decisions - `mcp__codex-cli__review` — Code change review -- `copilot` CLI on Grok 4.6 — Phase 3 plan review and Phase 9 code review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` / `microsoft_docs_fetch` — .NET documentation - `mcp__plugin_context7_context7__resolve-library-id` / `query-docs` — Library documentation - `mcp__plugin_10x-swe_deepwiki__ask_question` — Understanding external repositories diff --git a/.claude/rules/naming.md b/.claude/rules/naming.md index 3ee11ab..98dc10a 100644 --- a/.claude/rules/naming.md +++ b/.claude/rules/naming.md @@ -1,62 +1,5 @@ -# Identifier Naming Standards +# Naming Standards -Naming rules for **identifiers inside code** — types, members, parameters, locals. For **project, assembly, namespace, and package** names, see [`project-naming.md`](./project-naming.md); the two rules do not overlap. - -The workspace is primarily C#, so C# rules come first and are the default. Language-specific sections at the end cover the exceptions. - ---- - -## C# — Casing - -C# casing is **not a matter of taste**; it is fixed by the [.NET Framework Design Guidelines](https://learn.microsoft.com/dotnet/standard/design-guidelines/naming-guidelines) and enforced by the analysers already enabled in every repo (StyleCop, Roslynator, `Microsoft.CodeAnalysis.NetAnalyzers`). Deviating produces build warnings, and `TreatWarningsAsErrors` turns those into build failures in test projects. - -| Identifier | Casing | Example | -|---|---|---| -| Class, struct, record, enum, delegate | PascalCase | `ProfileRepository` | -| Interface | PascalCase, `I` prefix | `IUnitOfWork` | -| Method | PascalCase | `RemoveUserFromList` | -| Property, event | PascalCase | `CreatedTime` | -| Public / protected field (rare — prefer a property) | PascalCase | `Empty` | -| Private field | `_camelCase` | `_profileRepository` | -| `const` / `static readonly` | PascalCase — **never** `SCREAMING_CASE` | `DefaultTimeout` | -| Parameter, local variable | camelCase | `cancellationToken` | -| Generic type parameter | PascalCase, `T` prefix | `TEntity`, `TId` | -| Enum member | PascalCase | `DeleteBehavior.Cascade` | -| Local function | PascalCase | `static bool IsMatch(...)` | - -**Never use camelCase for a method or property in C#.** `shouldLogUserOutAfterTransfer` is a JavaScript identifier; the C# form is `ShouldLogUserOutAfterTransfer`. - -**Async methods end with `Async`** when they return `Task`/`Task<T>`/`ValueTask<T>` — `GetByIdAsync`, `CommitAsync` — matching the repository interfaces in `Ploch.Data.GenericRepository`. The suffix is dropped only for methods whose name already reads as an operation returning a task and which have no synchronous counterpart (e.g. an `ExecuteAsync` override where the base defines the name). - ---- - -## C# — Word Choice - -These rules apply regardless of casing, and they are where most real naming defects live. - -- **Methods start with a verb.** `RemoveUserFromList`, `CalculateTotal`, `ParseConnectionString` — not `UserRemoval` or `TotalCalculation`. A method *does* something; a name without a verb hides what. -- **Booleans read as an assertion.** Prefix with `Is`, `Are`, `Has`, `Can`, `Should`, or `Was`: `IsActive`, `HasChildren`, `CanExecute`, `ShouldLogUserOutAfterTransfer`. A boolean named `Status` or `Flag` forces the reader to open the definition. -- **No abbreviations or contractions.** The guidelines are explicit — `GetWindow`, not `GetWin`. Use `configuration` not `cfg`, `repository` not `repo`, `authentication` not `auth`, `count` not `cnt`. Widely accepted acronyms (`Id`, `Api`, `Db`, `Http`, `Xml`, `Json`, `Ui`) are the exception. -- **Acronym casing follows the assembly rule:** two-letter acronyms are fully capitalised (`IO`, `DB`, `UI`), three-or-more are PascalCased (`Xml`, `Html`, `Json`, `Http`). So `HttpClient` and `XmlReader`, but `IOException` and `UIElement`. In camelCase positions the first acronym is lowercased whole: `ioStream`, `htmlParser`. -- **Say the domain, not the mechanism.** `profileRepository` beats `repo2`; `retryDelay` beats `ts`. -- **Avoid `Manager`, `Helper`, `Util`, `Processor`, `Handler`, `Info`, and `Data` as type-name suffixes.** They describe nothing — a `ProfileManager` could do anything. Name the responsibility: `ProfileValidator`, `ProfileImporter`, `ProfileCache`. -- **Do not encode the type in the name.** `strName`, `intCount`, and `lstProfiles` are Hungarian notation; C# has a type system. -- **Match the codebase's existing vocabulary.** If the domain already says "Entry", a new type is not an "Item". - -### Names that collide - -The same shadowing trap that governs namespace segments applies to type names: do not name a type after a BCL type it will sit alongside — `Task`, `File`, `Path`, `Type`, `Timer`, `Action`, `Event`, `Stream`, `Version`, `Index`, `Range`. Qualify with the domain instead (`WorkItem`, `TrackedFile`, `AuditEvent`). See [`project-naming.md`](./project-naming.md#names-that-collide) for the full list and the entity-naming table. - ---- - -## Test Naming - -Test class and method naming is governed by [`writing-dotnet-tests.md`](./writing-dotnet-tests.md) and deliberately **breaks** the PascalCase method rule above: test methods use `<Member>_should_<expected behaviour>` with lowercase words, because the method name is a sentence read in a test report, not an API surface. That exception is confined to test projects. - ---- - -## Other Languages - -- **PowerShell** (`scripts/`, setup and provisioning scripts): `Verb-Noun` for functions, using an [approved verb](https://learn.microsoft.com/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands) (`Install-SessionEndHook`, `Get-ProjectConfig`); PascalCase for parameters (`-WhatIf`, `-ConfigPath`); camelCase for local variables. -- **JavaScript / TypeScript** (`ploch-ai-site` and any web tooling): camelCase for functions, methods, properties and variables; PascalCase for classes, types and components; `SCREAMING_SNAKE_CASE` for module-level constants. The verb-first and boolean-prefix rules above still apply — they are about word choice, not casing. -- **SQL / EF Core column names:** follow whatever the entity configuration establishes for the repo; do not introduce a second convention. +- Use **camelCase** for methods and properties. +- Boolean names should begin with: `is`, `are`, `should`, `could`, `would` (e.g., `shouldLogUserOutAfterTransfer`). +- Methods must start with a verb (e.g., `removeUserFromList`). diff --git a/.claude/rules/pr-checks-completion-gate.md b/.claude/rules/pr-checks-completion-gate.md index 4aba9c9..4183845 100644 --- a/.claude/rules/pr-checks-completion-gate.md +++ b/.claude/rules/pr-checks-completion-gate.md @@ -35,7 +35,7 @@ The following are the bots routinely seen in this workspace's PRs. The list is i **SonarCloud findings are not all on GitHub.** Unlike Codacy or CodeRabbit, SonarCloud usually posts only a single summary PR comment — not one thread per finding. The individual bugs, code smells, vulnerabilities, and security hotspots live in the SonarCloud platform and **must** be fetched via the `sonarqube-cloud` MCP server (configured at workspace scope — see `mrploch/CLAUDE.md` § "SonarQube MCP Servers"): - **Project key:** `.sonarlint/connectedMode.json` → `projectKey`; else `sonar.projectKey` in `sonar-project.properties` or `.github/workflows/*.yml`; else `mcp__sonarqube-cloud__search_my_sonarqube_projects(q="<repo>")`. -- **Issues:** `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projectKeys=["<key>"], pullRequest="<PR#>", issueStatuses=["OPEN","CONFIRMED"])`. +- **Issues:** `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projects=["<key>"], pullRequestId="<PR#>", issueStatuses=["OPEN","CONFIRMED"])`. - **Security hotspots:** `mcp__sonarqube-cloud__search_security_hotspots(projectKey="<key>", pullRequest="<PR#>", status=["TO_REVIEW"])`. - **Quality gate:** `mcp__sonarqube-cloud__get_project_quality_gate_status(projectKey="<key>", pullRequest="<PR#>")`. @@ -119,7 +119,7 @@ done **Step 7 — SonarCloud platform is clean (MCP, not shell).** The bash steps above only see GitHub-surfaced data. Separately confirm via the `sonarqube-cloud` MCP server that the PR has zero open findings: -- `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projectKeys=["<key>"], pullRequest="<PR#>", issueStatuses=["OPEN","CONFIRMED"])` → expected: empty. +- `mcp__sonarqube-cloud__search_sonar_issues_in_projects(projects=["<key>"], pullRequestId="<PR#>", issueStatuses=["OPEN","CONFIRMED"])` → expected: empty. - `mcp__sonarqube-cloud__search_security_hotspots(projectKey="<key>", pullRequest="<PR#>", status=["TO_REVIEW"])` → expected: empty. - `mcp__sonarqube-cloud__get_project_quality_gate_status(projectKey="<key>", pullRequest="<PR#>")` → expected: `OK`. diff --git a/.claude/skills/dev-finishing-touches/SKILL.md b/.claude/skills/dev-finishing-touches/SKILL.md index 4785e04..d9c3233 100644 --- a/.claude/skills/dev-finishing-touches/SKILL.md +++ b/.claude/skills/dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dev-finishing-touches -description: Last-mile quality pass for ploch-ai-site branches (Astro static site, bilingual PL/EN) — reviews all changes (committed + uncommitted), verifies content parity and SEO surfaces (hreflang, JSON-LD, meta, sitemaps), builds with zero astro-check errors/warnings/hints, runs a mandatory triple external AI review of the whole PR (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local check output + failing CI checks + every unresolved PR review thread + every external-AI-review finding, triages each item into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, and only completes when every CI check is green, every TODO is resolved, zero PR review threads remain unaddressed, and manual browser verification of both language versions has passed. Use when the user says "/dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for ploch-ai-site branches (Astro static site, bilingual PL/EN) — reviews all changes (committed + uncommitted), verifies content parity and SEO surfaces (hreflang, JSON-LD, meta, sitemaps), builds with zero astro-check errors/warnings/hints, runs a mandatory triple external AI review of the whole PR (Codex, Gemini AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local check output + failing CI checks + every unresolved PR review thread + every external-AI-review finding, triages each item into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, and only completes when every CI check is green, every TODO is resolved, zero PR review threads remain unaddressed, and manual browser verification of both language versions has passed. Use when the user says "/dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — Branch Quality Pass (ploch-ai-site) @@ -29,7 +29,7 @@ This is the web-site adaptation of the workspace's `.NET` finishing-touches skil - **CI state is known up front, not after push** — a sub-agent inspects existing CI run status before any local work begins. See [Phase 1.5](#phase-15-ci-status-pre-check-sub-agent). -- **Triple external AI review is mandatory** — before commit/push, the **entire PR context** (description, linked issue, full diff, full contents of modified files, repo conventions) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort review of the branch. Three different model families means three different blind spots. Every finding they raise is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). +- **Triple external AI review is mandatory** — before commit/push, the **entire PR context** (description, linked issue, full diff, full contents of modified files, repo conventions) is handed to **Codex, Gemini and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort review of the branch. Three different model families means three different blind spots. Every finding they raise is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is additionally reviewed by the Codex MCP **before the commit**, not after. Applies equally to check fixes, CI-failure fixes, PR-comment-driven fixes, and external-review-driven fixes. See [Codex Validation Gate](#codex-validation-gate). @@ -65,7 +65,7 @@ Before running any phase, check these prerequisites. If one is missing, **stop a | `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | | `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | | `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Load via `ToolSearch` ("select:mcp__codex-cli__codex,mcp__codex-cli__review"); retry once; if still missing, **pause and ask the user** whether to proceed without Codex (record the decision). Never silently skip. | -| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | +| `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | | `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | | Browser tooling (`claude-in-chrome` MCP, Playwright MCP, or `curl` fallback) | Phase 9.5 manual verification | Prefer a real browser MCP. If none is available, use `astro preview` + `curl` + dist HTML inspection and state in the report that visual verification was curl-level only. | | `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build + check, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | @@ -93,7 +93,7 @@ digraph finishing_touches { verify [label="6. Rebuild & Verify"]; more [shape=diamond, label="More findings?"]; grand [label="7. Grand Review\n(diff + docs sync)"]; - ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot (parallel,\nfull context, high effort)"]; + ai_review [label="8.5 External AI Review\nCodex + Gemini + Copilot (parallel,\nfull context, high effort)"]; ai_findings [shape=diamond, label="Findings\nraised?"]; triage_ai [label="Triage findings into TODO;\nfix valid ones"]; commit [label="9. Commit\n(/commit + Refs footer)"]; @@ -272,7 +272,7 @@ cp "src/layouts/Base.astro" "src/layouts/Base.astro.bak" One TODO per unresolved, non-outdated thread + one per actionable issue-level comment. Bot threads (Copilot, Codex connector, Sourcery, CodeRabbit) are included and triaged exactly like human threads. Record each thread's GraphQL `id` and root `databaseId` in the TODO body. -4. **External AI review findings** — from Phase 8.5. One TODO per Codex, Antigravity and Copilot finding rated must-fix or should-fix (deduplicate findings more than one reviewer raises; note every attribution on the merged TODO — agreement across independent model families raises confidence and should be recorded). +4. **External AI review findings** — from Phase 8.5. One TODO per Codex, Gemini and Copilot finding rated must-fix or should-fix (deduplicate findings more than one reviewer raises; note every attribution on the merged TODO — agreement across independent model families raises confidence and should be recorded). **Additional sources folded in as the pass progresses:** content-parity gaps from Phase 3 (one TODO per page pair), grand-review findings from Phase 7, Codex Validation Gate findings. @@ -281,7 +281,7 @@ cp "src/layouts/Base.astro" "src/layouts/Base.astro.bak" | Field | Content | | --------- | ---------------------------------------------------------------------------------------------------- | | Title | Short imperative (e.g. "Fix missing EN mirror of new PL services section") | -| Source | One of: `local-check`, `ci-check`, `pr-comment`, `content-parity`, `grand-review`, `codex`, `antigravity`, `copilot` | +| Source | One of: `local-check`, `ci-check`, `pr-comment`, `content-parity`, `grand-review`, `codex`, `gemini`, `copilot` | | Reference | File + line / check name + run link / comment URL / reviewer finding ID | | Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | | Status | `pending` → `in_progress` → `completed` | @@ -423,7 +423,7 @@ Review all changes holistically. --- -### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) +### Phase 8.5: External AI Review — Codex + Gemini + Copilot (MANDATORY) **Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates individual fixes): here every reviewer sees the **entire PR** and hunts for anything the pass missed — bugs, SEO regressions, bilingual drift, security issues, better approaches. @@ -453,7 +453,7 @@ The reviewers must receive the **entire context first**, then the review request #### Step 2 — Dispatch all three reviews in parallel - **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package. Request the highest reasoning effort the tool exposes (e.g. `model`/`effort` config set to high) — the brief's "maximum depth" instruction applies regardless. -- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, passing the same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. +- **Gemini:** `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code` if the gemini-cli server is absent), passing the same package. Use the highest-capability model/thinking configuration the tool exposes. - **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool. Write the context package plus brief to a scratch file and pass it as the prompt, using the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a file and pass it via shell substitution rather than inlining it in the command line. Send all three requests in the same tool-call block so they run concurrently. If the context package exceeds a tool's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the review brief only after the final part — the requirement is *entire context first, then the review*. @@ -461,7 +461,7 @@ Send all three requests in the same tool-call block so they run concurrently. If #### Step 3 — Triage the findings 1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. -2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. +2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `gemini` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. 3. Triage each finding like a PR comment: valid → fix (backups, safety gate, Codex Validation Gate for non-trivial fixes, then loop to Phase 4); disagree → record the finding **and** the evidence-based reason for declining in the report — a declined external finding is never silently dropped. 4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). @@ -609,7 +609,7 @@ Re-run the enumeration + comment fetches. Any new thread/comment (including revi ### Changes Applied - **Content/SEO integrity:** <PL/EN parity fixes, hreflang/meta/JSON-LD corrections> - **Check findings resolved:** <count> fixed, <count> suppressed (each with documented justification) -- **External-review fixes:** <count> from Codex, <count> from Antigravity, <count> from Copilot, <count> declined with reasons +- **External-review fixes:** <count> from Codex, <count> from Gemini, <count> from Copilot, <count> declined with reasons - **Docs updated:** <files> ### Build & Check Status @@ -619,7 +619,7 @@ Re-run the enumeration + comment fetches. Any new thread/comment (including revi | Reviewer | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | |----------|---------|----------|------------|-----|-------|--------------------------| | Codex | ... | n | n | n | n | n | -| Antigravity | ... | n | n | n | n | n | +| Gemini | ... | n | n | n | n | n | | Copilot (`grok-4.6`) | ... | n | n | n | n | n | ### Manual Verification @@ -693,7 +693,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t 2. **PL/EN parity requires a content decision** — e.g. new PL copy with no obvious EN rendering, or a translation judgement call. 3. **A change touches deploy-sensitive files** (`.htaccess`, `_headers`, workflows, `wrangler.jsonc`) beyond the branch's scope. 4. **No GitHub issue can be found** for the `Refs` footer — follow `rules/commits.md` lookup order and ask if none found. -5. **Codex or Antigravity MCP is unavailable** after a retry — ask whether to proceed with a reduced review. +5. **Codex or Gemini MCP is unavailable** after a retry — ask whether to proceed with a reduced review. 6. **An external reviewer's `REQUEST_CHANGES` must-fix** conflicts with the user's explicit prior direction — surface the conflict, don't pick silently. --- @@ -707,7 +707,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t | PL/EN wording mismatch | Polish wins; mirror the meaning into EN | | CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | | PR comment you disagree with | Reply with evidence-based reasoning | -| Codex and Antigravity disagree with each other | Judge on the evidence; if genuinely ambiguous and impactful, surface both positions to the user | +| Codex and Gemini disagree with each other | Judge on the evidence; if genuinely ambiguous and impactful, surface both positions to the user | | Link-check failure on an external URL | Internal links must be fixed; external ones verified manually (CI is offline-only, so external failures are local-run-only signals) | --- @@ -749,7 +749,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t | 4. Build/Check | 0 errors / 0 warnings / 0 hints; links + JSON-LD valid | Command output | | 5–6. Findings | Each finding classified, addressed, verified | Resolution documented per finding | | 7. Grand Review | Holistic review + docs sync done | No outstanding concerns | -| 8.5 AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | +| 8.5 AI Review | Codex, Gemini AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer, no `.bak` staged | Commit message + staged-index check | | 9.5 Manual Verify | Both languages browser-verified | Pages + method recorded | | 10. CI | All checks green (incl. non-required) | `gh pr checks` output | @@ -776,7 +776,7 @@ Each iteration is a **new commit**. After all fixes, update the PR description t **Uses these MCP tools:** - **`mcp__codex-cli__review` / `mcp__codex-cli__codex`** — Phase 8.5 whole-branch review + the per-fix Codex Validation Gate (load via `ToolSearch`) -- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check +- **`mcp__gemini-cli__gemini`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`) - **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - `claude-in-chrome` / Playwright MCP — Phase 9.5 browser verification - Context7 MCP — Astro documentation lookups diff --git a/.claude/skills/dotnet-dev-finishing-touches/SKILL.md b/.claude/skills/dotnet-dev-finishing-touches/SKILL.md index ad8adf0..1f5b036 100644 --- a/.claude/skills/dotnet-dev-finishing-touches/SKILL.md +++ b/.claude/skills/dotnet-dev-finishing-touches/SKILL.md @@ -1,6 +1,6 @@ --- name: dotnet-dev-finishing-touches -description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Antigravity AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. +description: Last-mile quality pass for .NET library branches — reviews all changes (committed + uncommitted), adds missing XML docs, ensures 80%+ test coverage, builds with zero warnings, resolves static analyzer diagnostics using /dotnet-dev-practical suppression techniques, runs a mandatory triple external AI review of the whole branch (Codex, Gemini AND GitHub Copilot CLI on Grok 4.6, each given the entire context first, then reviewing at high effort), creates a conventional commit, and monitors CI until green. Starts with a CI pre-check sub-agent, builds a unified TODO list covering local warnings + failing CI checks + every unresolved PR review thread, triages each thread into valid / false-positive / already-fixed / suggestion / question, fixes valid issues in code (Codex-validated before commit) and replies to false positives with specific evidence-based reasoning, validates non-trivial fixes via Codex MCP, and only completes when every CI check is green, every TODO is resolved, and zero PR review threads remain unaddressed. Use when the user says "/dotnet-dev-finishing-touches" or asks to polish, finish, or clean up a branch before pushing. --- # Finishing Touches — .NET Branch Quality Pass @@ -27,7 +27,7 @@ Perform a thorough review-and-fix cycle on the current branch's changes before c - **Non-trivial fixes require Codex validation** — any change beyond mechanical edits is reviewed by the Codex MCP (`mcp__codex-cli__codex`) **before the commit**, not after. Applies equally to warning fixes, CI-failure fixes, and PR-comment-driven fixes. See [Codex Validation Gate](#codex-validation-gate). -- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Antigravity and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). +- **Triple external AI review is mandatory** — before commit/push, the **entire branch context** (PR description, linked issue, full diff, full contents of modified files, repo conventions, verification already performed) is handed to **Codex, Gemini and GitHub Copilot CLI (Grok 4.6)**, which each perform an independent high-effort whole-branch review. Three model families means three sets of blind spots. This is distinct from the per-fix Codex gate: the gate validates one staged diff, this reviews the whole branch. Every finding is triaged into the master TODO. See [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) and [`rules/external-ai-review.md`](../../rules/external-ai-review.md). - **Zero unaddressed PR comments** — every unresolved review thread must be triaged and closed out before the skill reports complete. Valid issues are fixed in code; false positives get a reply that cites specific evidence (what the code actually does, which test/spec proves it, why the analyser or reviewer was wrong). A thread is never left silent, and a bot-flagged thread is never closed without a reply. See [Phase 11](#phase-11-address-pr-comments-skip-if---no-push). @@ -61,7 +61,7 @@ Before running any phase, check these prerequisites. If one is missing, **stop a | `Agent` tool (for Phase 1.5 sub-agent) | Phase 1.5 only | Skip Phase 1.5 and run the CI pre-check inline from the main context; record the skip in the report. | | `TaskCreate` / `TaskUpdate` / `TaskList` tools | Phase 2.5 master TODO list | Fall back to `mcp__contextstream__memory(action="create_todo")` if ContextStream is active, otherwise an in-memory list tracked in the main transcript. Never proceed without *some* tracked list. | | `mcp__codex-cli__codex` / `mcp__codex-cli__review` | Phase 8.5 + Codex Validation Gate | Retry once via `ToolSearch`; if still missing, **pause and ask the user** whether to proceed without the gate (and record the decision in the final report). Never silently skip. | -| `mcp__antigravity__ask_antigravity` (fallback `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | +| `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code`) | Phase 8.5 | Load via `ToolSearch`; retry once; if still missing, **pause and ask the user** whether to proceed with a reduced panel (record the decision). Never silently skip. | | `copilot` CLI on `PATH`, authenticated (GitHub Copilot CLI) | Phase 8.5 | Shell-out reviewer — **not** an MCP tool. Run the preflight in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Preflight; on failure follow its fallback ladder (retry with token env stripped → Kimi K3 → ask the user). Never silently skip. | | `superpowers:verification-before-completion` skill | Phase 12 | If unavailable, invoke the verification checklist inline (re-run build, re-run tests, re-check CI, re-enumerate PR threads) — do not skip the verification itself. | @@ -98,7 +98,7 @@ digraph finishing_touches { more_warnings [shape=diamond, label="More warnings\nremaining?"]; grand_review [label="8. Grand Review\n(all changes, suggestions)"]; review_ok [shape=diamond, label="Changes\nready?"]; - ai_review [label="8.5 External AI Review\nCodex + Antigravity + Copilot\n(parallel, full context, high effort)"]; + ai_review [label="8.5 External AI Review\nCodex + Gemini + Copilot\n(parallel, full context, high effort)"]; apply [label="8b. Apply Suggestions"]; commit [label="9. Commit\n(/commit skill)"]; push_check [shape=diamond, label="--no-push?"]; @@ -368,14 +368,14 @@ Build the complete picture of all changes on the branch. - Coverage gaps identified in Phase 4 — one TODO per file under 80%. - Grand-review findings from Phase 8 — one TODO per actionable suggestion. - New items surfaced by Codex validation in the [Codex Validation Gate](#codex-validation-gate) — one TODO per Codex finding rated "must fix" or "should fix". -- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory) — one TODO per Codex, Antigravity and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. +- External AI review findings from [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory) — one TODO per Codex, Gemini and Copilot finding rated `must-fix` or `should-fix`. Deduplicate findings more than one reviewer raises and credit every attribution; agreement across independent model families is higher-confidence and should be noted. **TODO item format:** | Field | Content | | --------- | -------------------------------------------------------------------------------------------------- | | Title | Short imperative (e.g. "Fix SA1600 missing XML docs in `Foo.cs`") | -| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `antigravity`, `copilot` | +| Source | One of: `local-warning`, `ci-check`, `pr-comment`, `xml-docs`, `coverage`, `grand-review`, `codex`, `gemini`, `copilot` | | Reference | File + line / check name + run link / comment URL | | Trivial? | `yes` or `no` — drives the Codex Validation Gate decision | | Status | `pending` → `in_progress` → `completed` | @@ -619,7 +619,7 @@ Review all changes made during the finishing-touches pass holistically. --- -### Phase 8.5: External AI Review — Codex + Antigravity + Copilot (MANDATORY) +### Phase 8.5: External AI Review — Codex + Gemini + Copilot (MANDATORY) **Purpose:** An independent, whole-branch review by three external models from three different providers **before** commit/push. This is distinct from the [Codex Validation Gate](#codex-validation-gate) (which validates one staged fix at a time): here every reviewer sees the **entire branch** and hunts for what the pass missed — correctness bugs, API-contract breaks, async and thread-safety hazards, suppressions that hide real defects, test gaps, better approaches. @@ -649,7 +649,7 @@ Reviewers receive the **entire context first**, then the review request. Build a #### Step 2 — Dispatch all three reviews in parallel - **Codex:** `mcp__codex-cli__review` (purpose-built review action) or `mcp__codex-cli__codex`, passing the full context package at the highest reasoning effort the tool exposes. -- **Antigravity:** `mcp__antigravity__ask_antigravity` with `model="gemini-3.1-pro-high"` and `paths` set to every file in scope, same package. **Capture `git status --porcelain` before the call and diff it after** — the bridge runs with `--dangerously-skip-permissions` (ploch-ai-configuration#47), so this check is the only thing keeping the reviewer read-only. +- **Gemini:** `mcp__gemini-cli__gemini` (or `mcp__gemini__gemini-analyze-code` if the gemini-cli server is absent), same package, highest-capability model/thinking configuration. - **Copilot:** the `copilot` CLI via `Bash` — **not** an MCP tool, so there is no `mcp__copilot__*` to load. Use the canonical command in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (`--model grok-4.6 --effort high`, the read-only `--deny-tool` set, `--disable-builtin-mcps`, `--no-ask-user`, `-s`). Because the package is large, write it to a scratch file and pass it via shell substitution rather than inlining it in the command line. Send all three requests in the same tool-call block so they run concurrently. If the package exceeds a transport's input limit, split it into a numbered multi-part upload ("context part 1/3…") and send the brief only after the final part — the requirement is *entire context first, then the review*. @@ -657,7 +657,7 @@ Send all three requests in the same tool-call block so they run concurrently. If #### Step 3 — Triage the findings 1. Merge the three findings lists; deduplicate (same file/line/concern → one TODO crediting every reviewer that raised it). A finding raised independently by two or more model families is higher-confidence — note the agreement on the TODO. -2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `antigravity` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. +2. One master-TODO per `must-fix` and `should-fix` finding (`Source: codex` / `gemini` / `copilot`). `nit`s are batched into a single TODO and applied where cheap, or explicitly declined in the report. 3. Triage each finding like a PR comment, using the seven-category model in [`pr-checks-completion-gate.md`](../../rules/pr-checks-completion-gate.md): valid → fix (backups, ask-gates for API/semantic changes, **Codex Validation Gate for non-trivial fixes**, then loop to Phase 5); disagree → record the finding **and** the evidence-based reason for declining in the report. A declined external finding is never silently dropped. 4. **Verdict handling:** if any reviewer returns `REQUEST_CHANGES`, the skill cannot proceed to Phase 9 until every `must-fix` from that reviewer is fixed or explicitly declined with evidence the user can audit. Re-run that reviewer on the updated diff and obtain `APPROVE`/`APPROVE_WITH_NOTES` (or user override). 5. **A finding that would change the public API or semantic behaviour still hits the existing ask-gates** — an external reviewer's recommendation does not bypass the user's sign-off on breaking changes. @@ -963,13 +963,13 @@ Provide a summary with evidence: - **Test Coverage:** ~<percentage>% on modified code (<count> tests added) - **Warnings Resolved:** <count> fixed, <count> suppressed (with justification), <count> disabled globally - **Code Review Fixes:** <count> improvements applied -- **External-review fixes:** <count> from Codex, <count> from Antigravity, <count> from Copilot, <count> declined with reasons +- **External-review fixes:** <count> from Codex, <count> from Gemini, <count> from Copilot, <count> declined with reasons ### External AI Review | Reviewer | Model | Verdict | must-fix | should-fix | nit | Fixed | Declined (with evidence) | |----------|-------|---------|----------|------------|-----|-------|--------------------------| | Codex | ... | ... | n | n | n | n | n | -| Antigravity | ... | ... | n | n | n | n | n | +| Gemini | ... | ... | n | n | n | n | n | | Copilot | `grok-4.6` | ... | n | n | n | n | n | ### Warning Resolution Summary @@ -1040,7 +1040,7 @@ find . -name "*.bak" -not -path "*/bin/*" -not -path "*/obj/*" -delete ## Codex Validation Gate -**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--antigravity--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. +**Purpose:** Non-trivial fixes (anything beyond a mechanical edit) must pass a second-opinion review by the Codex MCP (`mcp__codex-cli__codex`) **before the change is committed**, not after. This gate is **distinct from [Phase 8.5](#phase-85-external-ai-review--codex--gemini--copilot-mandatory)**: the gate validates one specific staged diff, Phase 8.5 reviews the entire branch. A fix that came *out of* Phase 8.5 still goes through this gate if it is non-trivial. This is a cross-cutting gate that applies to Phases 6 (warning fixes), 10 (CI-failure fixes), and 11 (PR-comment fixes), as well as any test additions in Phase 4b. **Timing rule:** Codex runs on the *uncommitted* diff. The correct sequence is: stage files → invoke Codex on the staged diff → act on the verdict → commit. If you are already mid-commit when you realise the gate was skipped, reset the staging, run Codex, then re-stage and commit as a single commit. Do **not** commit first and retroactively "validate" — that defeats the gate. @@ -1213,7 +1213,7 @@ If you catch yourself about to do any of these, stop and reconsider: | 6. Warnings | Each warning classified and addressed | Resolution documented per warning | | 7. Verify | Warning resolved after each fix | Rebuild output confirms | | 8. Grand Review | All changes reviewed holistically | No outstanding concerns | -| 8.5 External AI Review | Codex, Antigravity AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | +| 8.5 External AI Review | Codex, Gemini AND Copilot reviewed with full context at high effort; verdicts recorded; `git status --porcelain` unchanged after the Copilot run | Verdicts + findings table | | 9. Commit | Conventional format with `Refs` footer | Commit message | | 10. CI | All checks green (including non-required) | `gh pr checks` output | | 11. PR Comments | Every thread triaged, fixed-or-replied, and (for bots + clear-cut cases) resolved | Zero `isResolved=false` threads whose latest comment is not ours; category breakdown recorded | @@ -1255,7 +1255,7 @@ If you catch yourself about to do any of these, stop and reconsider: - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__detect_antipatterns` — Anti-pattern detection - `mcp__plugin_dotnet-claude-kit_cwm-roslyn-navigator__find_dead_code` — Unused code detection - **`mcp__codex-cli__codex` / `mcp__codex-cli__review`** — **Required** second-opinion review for every non-trivial fix (see [Codex Validation Gate](#codex-validation-gate)) and one third of the Phase 8.5 panel. Use `ToolSearch` to load the schema if not already available. -- **`mcp__antigravity__ask_antigravity`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`); pin `model="gemini-3.1-pro-high"` and run the pre/post `git status --porcelain` write check +- **`mcp__gemini-cli__gemini`** (fallback `mcp__gemini__gemini-analyze-code`) — Phase 8.5 whole-branch review (load via `ToolSearch`) - **`copilot` CLI (Grok 4.6)** — Phase 8.5 whole-branch review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) - GitHub CLI (`gh`) — PR management, CI monitoring, comment handling diff --git a/.claude/skills/implement-issue/SKILL.md b/.claude/skills/implement-issue/SKILL.md index f16c8a4..28a7276 100644 --- a/.claude/skills/implement-issue/SKILL.md +++ b/.claude/skills/implement-issue/SKILL.md @@ -12,20 +12,15 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet **Core principles:** - **Maximum autonomy** — research before asking. Only ask the user when genuinely blocked after exhausting all research options. - - **Maximum thoroughness** — every phase has explicit quality gates. No shortcuts. No skipped steps. - - **Evidence before claims** — never report completion without evidence (build output, test counts, CI status, PR URL). - - **All comments addressed** — every single PR comment and conversation must be addressed. No exceptions. Bot-authored threads (CodeRabbit, Codacy, Bito, SonarCloud) follow the same triage rules as human reviewers. SonarCloud / SonarQube Cloud additionally reports issues that exist **only in the SonarCloud platform** (not as GitHub comments) — these are fetched via the `sonarqube-cloud` MCP server and resolved with the same seven-category triage. - - **All checks pass — non-negotiable.** The hard gate for this skill is defined in **`../../../.claude/rules/pr-checks-completion-gate.md`** (workspace-level). The skill reports complete only when **all four** gate conditions are simultaneously true on the latest pushed commit: - 1. Every CI check (build, tests, Analyze, Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, repository-specific checks) shows `pass` — no `fail`, `pending`, `queued`, `in_progress`, `action_required`, or `skipped`. Required vs not-required is irrelevant. 2. Every static-analysis bot has rendered a verdict and that verdict is "no new issues". A bot that has not yet posted its check is **not** the same as a passing bot — wait for it (use `ScheduleWakeup` ~270s). 3. Every PR review thread is either resolved or has us as the latest contributor with an active reply. 4. Re-polling produces no new threads, comments, or check runs. - + **Stale checks are still failures.** "Codacy is stale, expected to go green" is **not** an acceptable completion claim. Wait for the rescan or push a follow-up to retrigger. **Announce at start:** "I'm using the implement-issue skill to implement GitHub issue #\<number\>." @@ -33,24 +28,15 @@ Orchestrate autonomous, end-to-end implementation of a GitHub issue — from fet ## Invocation ``` -/implement-issue <github-issue-url>|<linear-issue-url> # Full end-to-end -/implement-issue <github-issue-url>|<linear-issue-url> --no-push # Implement + commit locally, skip push/PR/CI +/implement-issue <github-issue-url> # Full end-to-end +/implement-issue <github-issue-url> --no-push # Implement + commit locally, skip push/PR/CI ``` -### Supported URL formats - -**For GitHub issues:** - +Supported URL formats: - `https://github.com/<owner>/<repo>/issues/<number>` - `<owner>/<repo>#<number>` - `#<number>` (current repo) -**For Linear issues:** - -- `https://linear.app/<team>/issue/<linear-issue-id>/<title>` -- `<team>/<linear-issue-id>` -- `<linear-issue-id>` (Linear workspace/team from repository `## Project Scope` in `CLAUDE.md`, or the mirrored section in `AGENTS.md` / `GEMINI.md` / `.github/copilot-instructions.md`) - **`--no-push` flag:** When set, skip all push, PR creation, CI monitoring, and PR comment resolution steps. Commit locally only. ## The Process @@ -63,7 +49,7 @@ digraph implement_issue { fetch [label="0. Fetch & Parse Issue"]; repo [label="1. Identify Target Repository"]; research [label="2. Research & Gather Context"]; - plan [label="3. Plan Implementation\n(Codex + Copilot + Antigravity review plan)"]; + plan [label="3. Plan Implementation\n(Codex + Copilot review plan)"]; blocked [shape=diamond, label="Genuinely\nblocked?"]; ask [label="Ask user"]; branch [label="4. Create Branch"]; @@ -71,7 +57,7 @@ digraph implement_issue { build [label="6. Build & Static Analysis\n(Zero new warnings)"]; test [label="7. Test\n(All pass, coverage gates)"]; review [label="8. Self-Review\n(git diff, patterns, docs)"]; - codex [label="9. External AI Review\nCodex + Antigravity + Copilot"]; + codex [label="9. External AI Review\nCodex + Gemini + Copilot"]; issues [shape=diamond, label="Issues\nfound?"]; commit [label="10. Commit\n(Conventional, Refs: #issue)"]; push_check [shape=diamond, label="--no-push?"]; @@ -79,7 +65,7 @@ digraph implement_issue { monitor [label="12. Monitor CI Checks\n(ALL checks incl. non-required)"]; ci_ok [shape=diamond, label="All checks\npass?"]; fix_ci [label="Read logs, diagnose, fix"]; - comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud, Codacy issues + any other issue)"]; + comments [label="13. Address PR Comments\n(ALL conversations + SonarCloud issues)"]; comments_ok [shape=diamond, label="All addressed?\nNo new comments?"]; gate [label="14. Completion Gate\n(All criteria met?)"]; gate_ok [shape=diamond, label="Pass?"]; @@ -116,49 +102,36 @@ digraph implement_issue { ### Phase 0: Fetch & Parse Issue 1. **Parse the URL** to extract `owner`, `repo`, and `issue-number`. - 2. **Fetch the full issue:** - ```bash gh issue view <number> --repo <owner>/<repo> --json number,title,body,labels,assignees,milestone,state,comments,projectItems ``` - 3. **Extract and understand:** - - **Title** and **description** — what needs to be done. - **Acceptance criteria** — look for a section in the body (e.g. "## Acceptance Criteria", "### AC", checkboxes). If none, derive from the description. - **Labels** — determine change type (`bug` → fix, `enhancement`/`feature` → feature, `documentation` → docs, etc.). - **Linked issues/PRs** — referenced in the body or comments (`#123`, `Depends on ...`). - **Comments** — additional context, clarifications, decisions from the discussion. - 4. **If the issue is closed** or already has a linked merged PR that fully addresses it, stop and inform the user. ### Phase 1: Identify Target Repository 1. Determine the target repository from the issue URL. - 2. Map to the local workspace directory: `C:\DevNet\my\mrploch\<repo-name>\`. - 3. Verify the repo is cloned: - ```bash ls "C:/DevNet/my/mrploch/<repo-name>" ``` - 4. Navigate to the repo and ensure it is up to date: - ```bash cd "C:/DevNet/my/mrploch/<repo-name>" git fetch origin git status ``` - 5. Identify the base branch (`main` or `master`): - ```bash git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' ``` - If that fails, check `git branch -r` for `origin/main` or `origin/master`. `ploch-common` uses `master`; newer repos use `main`. ### Phase 2: Research & Gather Context @@ -166,49 +139,38 @@ digraph implement_issue { Before writing any code, build comprehensive understanding. This phase is critical — thorough research prevents wasted implementation time. 1. **Read the target repo:** - - README.md, CLAUDE.md, `.claude/rules/` files. - Relevant source files in the area of change. - Existing tests for the affected modules. - Project structure (`src/`, `tests/`, solution files). - `Directory.Build.props`, `Directory.Packages.props` for build configuration. - 2. **Check related issues and PRs:** - ```bash # Related issues (open and closed) gh issue list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 # Related PRs (open and recently closed/merged) gh pr list --repo <owner>/<repo> --search "<keywords>" --state all --limit 10 ``` - 3. **Read linked or related PRs** for context on prior decisions and approaches: - ```bash gh pr view <pr-number> --repo <owner>/<repo> --json title,body,files,commits gh pr diff <pr-number> --repo <owner>/<repo> ``` - 4. **Check sibling repos** for patterns — browse `C:\DevNet\my\mrploch\` siblings: - - `ploch-common` — extension methods, serialisation, DI bundles, CRUD endpoints. - `ploch-data` — repository pattern, Unit of Work, entity configurations, Specification. - `ploch-lists`, `ploch-groupmatters` — application-level patterns (API, data layer, model). - `mrploch-development` — shared build config, dependency versions. - 5. **Research externally** if needed: - - Microsoft Learn docs: `mcp__claude_ai_Microsoft_Learn__microsoft_docs_search` - Library documentation via Context7: `mcp__plugin_context7_context7__resolve-library-id` then `query-docs` - External repo understanding via DeepWiki: `mcp__plugin_10x-swe_deepwiki__ask_question` - Web search for non-obvious problems or unfamiliar APIs. - 6. **Understand the area of change** — read the specific files, classes, and methods that will be affected. Trace call chains. Understand the data flow. Identify what tests exist and what patterns they follow. ### Phase 3: Plan Implementation 1. **Create a detailed plan** using **TodoWrite** with sub-tasks covering: - - Implementation tasks (code changes, new files, modified files). - Test creation (unit tests, integration tests if needed, bug-reproducing test if it's a bug fix). - Documentation tasks (XML docs on new public APIs, README/doc page updates). @@ -219,14 +181,11 @@ Before writing any code, build comprehensive understanding. This phase is critic - Push/PR (unless `--no-push`). 2. **Consult two external models for plan review** — send both requests in the same tool-call block so they run concurrently: - ``` mcp__codex-cli__codex # OpenAI lens copilot -p "<plan brief>" --model grok-4.6 … # xAI lens, via Bash — see rules/external-ai-review.md ``` - Send the plan to each along with: - - The issue description and acceptance criteria. - Key files and patterns discovered during research. - Any design decisions you've made and their rationale. @@ -240,13 +199,10 @@ Before writing any code, build comprehensive understanding. This phase is critic ### Phase 4: Create Branch 1. Ensure you are on the base branch and it is up to date: - ```bash git checkout <base-branch> && git pull origin <base-branch> ``` - 2. Determine the change type from the issue analysis (Phase 0). Mapping: - - `bug` label or bug-related title → `fix` - `enhancement`/`feature` label or new capability → `feature` - Documentation-only → `docs` @@ -254,13 +210,10 @@ Before writing any code, build comprehensive understanding. This phase is critic - Code restructuring without behaviour change → `refactor` - Performance improvement → `perf` - Tests only → `test` - 3. Create the branch following the naming convention (see `rules/branch-naming.md`): - ```bash git checkout -b <change-type>/<issue-number>-<brief-description> ``` - Example: `feature/72-dbcontext-creation-lifecycle-plugins`, `fix/187-duplicate-entity-concurrent-upsert` ### Phase 5: Implement @@ -296,9 +249,7 @@ When the issue is a bug fix: #### Documentation - **XML documentation** on all new/modified public types, methods, properties (for public/open-source packages). Follow Microsoft's style. Include `<example>` blocks where usage is not obvious. See `rules/documentation.md`. - - **Update project markdown documentation** — manually-authored `.md` files must stay in sync with the code. Discover all project docs: - ```bash REPO_ROOT=$(git rev-parse --show-toplevel) # Primary: docs/ folder, root-level docs, and any other .md files in the project @@ -306,9 +257,7 @@ When the issue is a bug fix: ls "$REPO_ROOT"/README.md "$REPO_ROOT"/RELEASE_NOTES.md "$REPO_ROOT"/CHANGELOG.md 2>/dev/null find "$REPO_ROOT" -maxdepth 2 -name "*.md" -not -path "*/.git/*" -not -path "*/node_modules/*" -not -path "*/bin/*" -not -path "*/obj/*" -not -path "*/.claude/*" -not -path "*/change-log/*" 2>/dev/null ``` - For each documentation file found, check whether your changes affect what it describes: - - **README.md** — features, APIs, usage patterns, installation instructions, quick-start examples, configuration options. - **docs/*.md** — design documents, architecture guides, spec files, migration guides, API references. - **RELEASE_NOTES.md / CHANGELOG.md** — add entries for user-visible changes (new features, breaking changes, significant bug fixes). @@ -318,7 +267,6 @@ When the issue is a bug fix: #### SampleApp (ploch-data only) If working on the `ploch-data` repository and the change adds or modifies library features: - - Update the SampleApp to demonstrate the new/changed features. - The SampleApp must use NuGet package references, not ProjectReference. - See `rules/sample-apps.md`. @@ -338,7 +286,6 @@ Read the **entire** build output. Do not skim. #### Step 2: Catalogue every warning Go through every warning in the build output. These come from: - - **StyleCop.Analyzers** — naming, documentation, layout, ordering. - **Roslynator.Analyzers** — code simplification, redundancy, best practices. - **SonarAnalyzer.CSharp** — bugs, code smells, security hotspots. @@ -365,12 +312,12 @@ The build output must show **zero warnings**. If any remain, go back to Step 3. #### Summary -| Gate | Requirement | -| -------------------------- | -------------------------------------- | -| Compilation | Zero errors | -| Static analysis warnings | Zero (all fixed) | -| Code style (.editorconfig) | Zero violations | -| Suppressions added | Zero (unless justified and documented) | +| Gate | Requirement | +|------|-------------| +| Compilation | Zero errors | +| Static analysis warnings | Zero (all fixed) | +| Code style (.editorconfig) | Zero violations | +| Suppressions added | Zero (unless justified and documented) | ### Phase 7: Test @@ -401,43 +348,31 @@ Before committing, review your own changes thoroughly: 3. Re-validate against the original issue requirements and acceptance criteria from Phase 0. Did you implement everything that was asked? Did you miss any AC? 4. If anything needs improvement: fix it, then loop back to **Phase 6** (Build). -### Phase 9: External AI Review — Codex + Antigravity + Copilot +### Phase 9: External AI Review — Codex + Gemini + Copilot **Panel definition, invocation flags, preflight and fallbacks: [`rules/external-ai-review.md`](../../rules/external-ai-review.md).** All three reviews are **mandatory** for every non-trivial change — three providers, three sets of blind spots. Run them in parallel (one tool-call block) and pass **full context** to each: the issue number + title + requirements, the design decisions taken and why, the diff (`git diff <base-branch>...HEAD`), verification evidence (build/test results), and a request for a structured verdict (`APPROVED` / `APPROVED_WITH_NOTES` / `CHANGES_REQUESTED` / `REJECTED` with concrete findings). 1. **Codex review:** - ``` mcp__codex-cli__review (or mcp__codex-cli__codex with a review brief) ``` - Provide the diff and full context as above. **Fallback:** if the Codex MCP is unavailable (e.g. account/model restriction — try at least one alternative model before concluding), substitute an independent local review agent (e.g. `feature-dev:code-reviewer`) with the same brief, and record the substitution in the PR description and completion report. Never silently skip the second opinion. - -2. **Antigravity review:** - +2. **Gemini review:** ``` - mcp__antigravity__ask_antigravity (model="gemini-3.1-pro-high", paths=[...]) + mcp__gemini__gemini-analyze-code (or mcp__gemini__gemini-query with the diff inline) ``` - Provide the same full-context brief and the diff. Ask specifically for: correctness issues, missed edge cases, API-contract concerns, and test-coverage gaps. - 3. **Copilot review:** - ```bash copilot -p "$BRIEF" --model grok-4.6 --effort high --allow-all-tools \ --deny-tool 'write' --disable-builtin-mcps --no-ask-user -s --log-level none -C "$REPO_ROOT" ``` - Shell-out through `Bash` — Copilot is **not** an MCP server, so there is no `mcp__copilot__*` tool to load. Use the full canonical flag set from [`rules/external-ai-review.md`](../../rules/external-ai-review.md) § Copilot CLI Invocation Contract (the abbreviated form above omits the `shell(git …)` / `shell(gh …)` denials). Run the preflight first; on failure follow the fallback ladder (retry with `GITHUB_TOKEN`/`GH_TOKEN`/`COPILOT_GITHUB_TOKEN` stripped → Kimi K3 → ask the user). Afterwards verify `git status --porcelain` is unchanged. - 4. **Review all feedback** — evaluate each suggestion from all three reviewers on merit. Deduplicate overlapping findings, crediting each reviewer that raised them; a finding raised independently by two model families is higher-confidence. - 5. **Address valid feedback** — if code changes are needed, make them and loop back to **Phase 6** (Build), then re-run the affected reviewer on the revised diff. - 6. **Document disagreements** — if you disagree with a suggestion, note your reasoning (in the PR description's Design Decisions section if user-visible). This is acceptable — not every suggestion must be implemented, but a declined finding is recorded with its evidence, never silently dropped. - 7. **Record which model each reviewer ran** — Copilot's in particular, so a fallback to Kimi K3 is visible in the completion report. **Skip this phase** only for truly trivial changes (single-line typo fix, config-only change). @@ -445,103 +380,85 @@ All three reviews are **mandatory** for every non-trivial change — three provi ### Phase 10: Commit - **One commit per logical change** — typically one commit for the entire issue. For large issues with naturally separable parts, use multiple focused commits. - - **Conventional Commits** format (see `rules/commits.md`): - ``` <type>(<scope>): <subject> - + <body — what changed and why> - + [BREAKING CHANGE: <description>] Refs: #<issue-number> ``` - - The `Refs: #<issue-number>` footer is **mandatory**. The issue number comes from Phase 0. - - Detect and document breaking changes — check for removed/renamed public APIs, changed signatures, changed defaults. Add `BREAKING CHANGE:` footer if any. - - Stage specific files — **never** `git add -A` or `git add .`. - - **Never amend** existing commits unless the user explicitly asks. - - Update the change log if the commit contains user-visible changes (new features, breaking changes, significant fixes). ### Phase 11: Push & Create PR (skip if `--no-push`) 0. **Pre-push build verification** — before any push, run a final clean build of the full solution and confirm **zero warnings**: - ```bash dotnet build <solution-file> ``` - If any warnings appear, **stop and fix them before pushing**. This is critical — every warning you let through will come back as a CI failure or PR comment, costing a full pipeline round-trip. Fix locally first. 1. **Push the branch:** - ```bash git push -u origin HEAD ``` 2. **Check for existing PR:** - ```bash gh pr view --json number,url 2>/dev/null || echo "NO_PR" ``` 3. **Read PR template** (if it exists): - ```bash cat .github/pull_request_template.md 2>/dev/null || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null ``` 4. **Create PR** with a detailed description following `rules/pr-descriptions.md`: - ```bash gh pr create --title "<type>(<scope>): <subject>" --body "$(cat <<'EOF' ## Summary - + <What this PR does and why. Reference the issue.> - + ## Changes - + - <Specific change 1> - <Specific change 2> - ... - + ## Design Decisions - + <Non-obvious choices and their rationale> - + ## Testing - + - Unit tests: <count> added/modified - Manual verification: <what was tested> - Coverage: ~<percentage>% on new code - + ## Related - + Closes #<issue-number> EOF )" && gh pr edit --add-assignee @me ``` 4b. **Request a GitHub Copilot review (mandatory):** immediately after creating the PR, request Copilot as a reviewer via the GitHub MCP tool: - -``` -mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) -``` - + ``` + mcp__github__request_copilot_review(owner="<owner>", repo="<repo>", pullNumber=<pr-number>) + ``` Fallback if the MCP tool is unavailable: - -```bash -gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" -``` - + ```bash + gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[]=copilot-pull-request-reviewer[bot]" + ``` Copilot's review comments are then addressed in Phase 13 like any other reviewer's. -1. **If updating an existing PR** (e.g. after fix loop): - +5. **If updating an existing PR** (e.g. after fix loop): ```bash gh pr edit <pr-number> --body "$(cat <<'EOF' [updated body reflecting final state] @@ -556,21 +473,18 @@ gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[ **Bots that must reach a `success` verdict before this phase exits** (when present on the PR): `build`, `Test Results`, `Analyze (csharp)` (CodeQL), `Codacy Static Code Analysis`, `SonarCloud Code Analysis` / `SonarQube Cloud`, `CodeRabbit`, `Bito AI Code Review Agent`, any coverage bot (Codecov / Coveralls / Codacy Coverage), and any repository-specific custom check. A bot that has not yet appeared in `gh pr checks` is **not** absent — it is **pending its first run**, and you wait for it. A bot that says `fail` because it hasn't yet rescanned the latest commit is **still failing** by the gate's definition — wait for the rescan or push a no-op-ish commit to retrigger; do not declare completion with a "stale check" caveat. 1. **Wait for ALL checks** to complete — **including non-required checks:** - ```bash gh pr checks <pr-number> --watch ``` 2. **If any check fails:** a. Retrieve the failure logs: - - ```bash - # Find the failed run - gh run list --branch <branch-name> --limit 5 - # Get failure details - gh run view <run-id> --log-failed - ``` - + ```bash + # Find the failed run + gh run list --branch <branch-name> --limit 5 + # Get failure details + gh run view <run-id> --log-failed + ``` b. **Diagnose the root cause** — read the actual error output. Do not guess. c. If the failure is not obvious, research the error (web search, docs, sibling repos for how they handle it). d. Fix the issue in code. @@ -578,7 +492,6 @@ gh api repos/<owner>/<repo>/pulls/<pr-number>/requested_reviewers -f "reviewers[ f. After pushing the fix, monitor checks again. Repeat until **all green**. 3. **Do not:** - - Ignore or dismiss failing checks — even non-required ones. - Assume a failure is flaky without evidence (check if the same test fails consistently). - Push speculative fixes without reading the failure logs. @@ -620,7 +533,6 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary #### GitHub PR comments, review threads & conversations 1. **Fetch all PR feedback:** - ```bash # Review comments (inline on code) gh api repos/<owner>/<repo>/pulls/<pr-number>/comments --paginate @@ -631,14 +543,12 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 2. **For each comment or conversation:** - - If it identifies a **valid issue** → fix the code. - If it is a **false positive or irrelevant** → reply with a clear, specific explanation of why you believe so. Do not just say "false positive" — explain the reasoning. - If it is a **suggestion worth considering** → evaluate on merit. Implement if it improves the code; explain why not if you disagree. - **Every single conversation must have a response.** No comment left unaddressed. It does not matter whether it is blocking the merge or not. 3. **Reply to comments:** - ```bash # Reply to a review comment gh api repos/<owner>/<repo>/pulls/<pr-number>/comments/<comment-id>/replies -f body="<your reply>" @@ -647,14 +557,12 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary ``` 4. **If code changes were made:** - - Commit the fixes (new commit, never amend). - Push. - **Loop back to Phase 12** (monitor CI checks again). - After checks pass, re-fetch comments — new automated comments may have been added by the new push. 5. **Only proceed when:** - - Zero unaddressed conversations remain. - No new comments have appeared since your last round of responses. - All CI checks are still green after the latest push. @@ -674,21 +582,21 @@ SonarCloud rarely posts one PR thread per finding — it posts a single summary Before reporting completion, **every single one** of these criteria must be met: -| # | Criterion | How to Verify | -| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | -| 2 | All tests pass | Test output with counts | -| 3 | Test coverage ≥80% on new code | Coverage report or estimate | -| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | -| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | -| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | -| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | -| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | -| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | -| 10 | SampleApp works (if ploch-data) | Manual test | -| 11 | Conventional commit with `Refs: #issue` | Commit log | -| 12 | PR description documents all changes and decisions | PR body | -| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | +| # | Criterion | How to Verify | +|---|-----------|---------------| +| 1 | **Zero build warnings (entire solution)** | `dotnet build` output — zero warnings from all static analysers | +| 2 | All tests pass | Test output with counts | +| 3 | Test coverage ≥80% on new code | Coverage report or estimate | +| 4 | Code formatted per .editorconfig | `EnforceCodeStyleInBuild` — no style errors | +| 5 | **All CI checks green** (including non-required) — every check listed by `gh pr checks <pr-number>` shows `pass`. Codacy, SonarCloud / SonarQube, CodeQL, CodeRabbit, Bito, coverage bots, and any repository-specific custom check **all** count, regardless of "required" status. Stale or pending checks fail this criterion. | `gh pr checks <pr-number>` — every line ends with `pass`; cross-check with `gh api repos/<owner>/<repo>/commits/<sha>/check-runs` | +| 6 | **All PR comments and conversations addressed** — including bot-authored ones (CodeRabbit, Codacy, Bito, SonarCloud). Every thread is either resolved or has us as the latest contributor with an active reply. | GraphQL `reviewThreads` query: zero `isResolved=false AND isOutdated=false` threads where the latest commenter is not us | +| 7 | No new comments since last check | Re-fetch after waiting; re-poll until two consecutive polls return identical state | +| 8 | All acceptance criteria from the issue met | Re-read issue body, verify each AC | +| 9 | Documentation up to date | XML docs on public APIs; project markdown docs (README.md, docs/*.md, RELEASE_NOTES.md) reviewed and updated to match code changes | +| 10 | SampleApp works (if ploch-data) | Manual test | +| 11 | Conventional commit with `Refs: #issue` | Commit log | +| 12 | PR description documents all changes and decisions | PR body | +| 13 | **SonarCloud platform clean** — zero `OPEN`/`CONFIRMED` issues and zero `TO_REVIEW` hotspots for the PR. A passing `SonarQube Cloud` GitHub check is **not** sufficient — a quality gate can pass with issues below threshold. | `sonarqube-cloud` MCP: `search_sonar_issues_in_projects` + `search_security_hotspots` for the PR both return empty; `get_project_quality_gate_status` is `OK` | **If any criterion is not met:** go back and fix it. Do not report completion. @@ -775,20 +683,19 @@ When an issue requires changes in multiple repositories: **Research before asking.** The user expects maximum autonomy. -| Situation | Action | -| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -| Unsure about a pattern | Check sibling repos for examples | -| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | -| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | -| Unsure about test approach | Check existing test projects for patterns | -| Build warning you don't understand | Research the analyser rule ID, then fix or document | -| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | -| PR comment you disagree with | Reply with clear reasoning, citing evidence | -| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | -| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | +| Situation | Action | +|-----------|--------| +| Unsure about a pattern | Check sibling repos for examples | +| Unsure about a library API | Context7, Microsoft Learn, DeepWiki, web search | +| Unsure about project convention | Read `.claude/rules/`, `.editorconfig`, existing code | +| Unsure about test approach | Check existing test projects for patterns | +| Build warning you don't understand | Research the analyser rule ID, then fix or document | +| CI check failure | Read logs (`gh run view --log-failed`), identify root cause, fix | +| PR comment you disagree with | Reply with clear reasoning, citing evidence | +| Non-obvious implementation choice | Consult Codex (`mcp__codex-cli__codex`) and/or Copilot (`copilot --model grok-4.6`) for a second opinion | +| Multiple valid approaches | Evaluate trade-offs, pick the one most consistent with existing patterns, document the decision in PR description | **Only ask the user when:** - - A decision has significant business or architectural impact that cannot be inferred from the issue, codebase, or documentation. - Multiple valid approaches exist AND the choice materially affects the user AND research hasn't provided a clear winner. - You are truly blocked with no way to research the answer. @@ -800,7 +707,6 @@ When an issue requires changes in multiple repositories: ## Non-Blocking Issues When you encounter something worth tracking that is outside the current issue's scope, **open a GitHub issue** for it — do not accumulate items in a `TODO-important.md` file. Create an issue when you encounter: - - Questions that can be answered later. - Suggestions for improvements outside the current issue scope. - Technical debt noticed but outside scope. @@ -808,7 +714,6 @@ When you encounter something worth tracking that is outside the current issue's - Pre-existing issues discovered during implementation. Guidance: - - Give it a clear conventional-style title (e.g. `chore: ...`, `test: ...`, `refactor: ...`) and a body capturing the context, why it is out of scope, and a suggested resolution. - Label genuinely high-priority follow-ups (release blockers, correctness or consumer risk) with the `important` label so they stand out. Create the label first if the repo does not have it. - Cross-reference the originating issue/PR in the new issue body. @@ -843,32 +748,31 @@ If you catch yourself about to do any of these, stop and reconsider: ## Quick Reference -| Phase | Gate | Evidence Required | -| ---------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | -| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | -| 1. Repo | Repo identified and up to date | `git status` clean | -| 2. Research | Context gathered | Key files and patterns identified | -| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | -| 4. Branch | Created from latest base | Branch name follows convention | -| 5. Implement | Code + tests + docs written | Files created/modified | -| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | -| 7. Test | All pass, ≥80% new coverage | Test output with counts | -| 8. Self-Review | No issues found | `git diff` reviewed | -| 9. External AI Review | Codex, Antigravity AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | -| 10. Commit | Conventional format, `Refs` footer | Commit message | -| 11. PR | Detailed description, linked issue | PR URL | -| 12. CI | ALL green (including non-required) | `gh pr checks` output | -| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | -| 14. Gate | All 13 criteria met | Checklist verified | -| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | -| 15. Report | Evidence provided | Summary with links | +| Phase | Gate | Evidence Required | +|-------|------|-------------------| +| 0. Fetch | Issue parsed | Title, body, labels, ACs extracted | +| 1. Repo | Repo identified and up to date | `git status` clean | +| 2. Research | Context gathered | Key files and patterns identified | +| 3. Plan | Reviewed by Codex + Copilot | Plan approved or adjusted | +| 4. Branch | Created from latest base | Branch name follows convention | +| 5. Implement | Code + tests + docs written | Files created/modified | +| 6. Build | **Zero warnings (entire solution)** | Build output — zero analyser warnings | +| 7. Test | All pass, ≥80% new coverage | Test output with counts | +| 8. Self-Review | No issues found | `git diff` reviewed | +| 9. External AI Review | Codex, Gemini AND Copilot ran; all feedback addressed; working tree unchanged by reviewers | Verdicts + review notes | +| 10. Commit | Conventional format, `Refs` footer | Commit message | +| 11. PR | Detailed description, linked issue | PR URL | +| 12. CI | ALL green (including non-required) | `gh pr checks` output | +| 13. Comments | ALL addressed (GitHub + SonarCloud platform), no new ones | Zero unresolved threads; zero open SonarCloud issues/hotspots | +| 14. Gate | All 13 criteria met | Checklist verified | +| 14.5 Finishing Touches | `/dotnet-dev-finishing-touches` completed its own gate | Finishing-touches report | +| 15. Report | Evidence provided | Summary with links | --- ## Integration **References these rules (auto-loaded from `.claude/rules/`):** - - `branch-naming.md` — Branch naming convention - `commits.md` — Conventional Commit format and issue linking - `writing-dotnet-tests.md` — xUnit v3, FluentAssertions, AutoFixture standards @@ -883,7 +787,6 @@ If you catch yourself about to do any of these, stop and reconsider: - `agent.md` — Agent behaviour specification and CI check gate **Uses these skills when appropriate:** - - **dotnet-dev-finishing-touches** — REQUIRED final quality pass after the completion gate (Phase 14.5) - **superpowers:verification-before-completion** — REQUIRED before any completion claim - **superpowers:dispatching-parallel-agents** — When multiple independent sub-tasks exist @@ -893,7 +796,6 @@ If you catch yourself about to do any of these, stop and reconsider: - **review-pr-comments** — For structured PR comment review (Phase 13) **Uses these MCP tools:** - - `mcp__codex-cli__codex` — Plan review and ad-hoc consultation for non-obvious decisions - `mcp__codex-cli__review` — Code change review - `copilot` CLI on Grok 4.6 — Phase 3 plan review and Phase 9 code review, invoked through `Bash`; flags, preflight and fallbacks in [`rules/external-ai-review.md`](../../rules/external-ai-review.md) From c96e43e301fc3a4d0caa6303e58f6716e7b55afd Mon Sep 17 00:00:00 2001 From: Krzysztof Ploch <kris@ploch.dev> Date: Sat, 12 Sep 2026 14:20:38 +0200 Subject: [PATCH 4/5] fix(solution): Close out the external review of the package switch Addresses the findings from the three-reviewer external panel (Codex, Antigravity/Gemini 3.1 Pro, Copilot/Grok 4.6) and the four GitHub PR bots. All three external reviewers returned APPROVE_WITH_NOTES. Directory.Packages.props - the local Ploch.Common.Apps.Shared pin is now Remove-then-Include, versioned from $(PlochCommonPackagesVersion). A second PackageVersion for an id the imported shared file also defines is a hard error, verified: "error NU1506: Warning As Error: Duplicate 'PackageVersion' items found". Because CI checks out mrploch-development at the moving main branch, merging the upstream fix this pin anticipates (mrploch-development#21) would have broken restore here with no commit in this repository. Verified by simulating that merge: restore succeeds and resolves a single entry. Found by Codex. release.yml - GH_PACKAGES_TOKEN is now validated fail-fast alongside GH_TOKEN, since assigning an unset secret still sends an empty password and 401s. Its rationale is rewritten: an unauthenticated eligible feed neither reliably fails nor is merely cosmetic. NuGet queries sources concurrently and rethrows a terminal protocol failure, so whether the nuget.org match arrives before the GitHub feed exhausts its retries is a race - one green run is a sample of it, not a proof. It is also load-bearing, because prerelease Ploch builds exist only on that feed. build-dotnet.yml - the sample build now passes -p:GeneratePackageOnBuild=false. Copilot reported that this step repacks the libraries over the package-mode nupkgs the workflow publishes, with ploch-common as a prerelease ProjectReference dependency - the #47 defect returning. Codex investigated the same hypothesis and refuted it; measurement on a clean tree confirms the refutation, because the step packs into bin/Debug while the publish script globs bin/Release. The suppression is kept as defence in depth: the only thing preventing the bug is that the libraries are not members of the sample solution, so adding them would silently arm it. Also corrected several comments that had become false: the claim that both reference modes are exercised in CI (they are not - only the sample is built in project-reference mode, tracked in #51), the MSB3202 rationale for the ploch-common clones in build-dotnet and publish-docs, release.yml's reference to sibling repositories plural, and "four major versions" where 2.0.1 to 4.0.47 is two. Documented the residual dependency-confusion consideration of mapping a wildcard to a public feed, and added PrivateAssets to the test host and VSTest adapter to match the SDK template. Follow-ups filed rather than fixed here: #53 (release builds read Ploch versions from a moving sibling checkout) and #54 (fork PRs cannot authenticate the GitHub feed, so they will fail during any prerelease cycle). Refs: #46 Refs: #47 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MroAgPwA8tGuEPi2rz4qJU --- .github/workflows/build-dotnet.yml | 38 ++++++++++++++---- .github/workflows/publish-docs.yml | 16 ++++++-- .github/workflows/qodana_code_quality.yml | 5 +++ .github/workflows/release.yml | 47 ++++++++++++++++++++++- Directory.Build.props | 20 ++++++++-- Directory.Packages.props | 37 +++++++++++++----- nuget.config | 9 +++++ 7 files changed, 147 insertions(+), 25 deletions(-) diff --git a/.github/workflows/build-dotnet.yml b/.github/workflows/build-dotnet.yml index 0d23a57..16cc1df 100644 --- a/.github/workflows/build-dotnet.yml +++ b/.github/workflows/build-dotnet.yml @@ -40,12 +40,19 @@ jobs: with: fetch-depth: 0 - # The solution references sibling repositories by relative path (../ploch-common and - # ../mrploch-development) - the workspace layout where every mrploch repo is cloned next - # to the others. Reproduce that layout beside the workspace, otherwise restore fails with - # MSB3202 for every ../ploch-common project. Cloning the siblings (rather than checking - # this repository out into a named sub-directory) keeps this repository at the workspace - # root, which is what the Codacy reporter and SonarScanner both expect. + # Reproduce the workspace layout beside the checkout: every mrploch repo cloned next to + # the others. Cloning the siblings (rather than checking this repository out into a named + # sub-directory) keeps this repository at the workspace root, which is what the Codacy + # reporter and SonarScanner both expect. + # + # mrploch-development is required unconditionally: Directory.Packages.props imports the + # shared version files from it. + # + # ploch-common is required by exactly ONE step - "Build sample application", which runs + # -p:UsePlochProjectReferences=true so a library change cannot break the sample silently. + # The main solution restore no longer needs it: in the default package mode the Ploch + # dependencies come from nuget.org, so the old MSB3202-on-every-ploch-common-project + # rationale no longer applies. Whether this clone should go away entirely is #51. # # ploch-common is cloned in full because it uses Nerdbank.GitVersioning too, and NBGV # cannot compute a version height from a shallow clone. @@ -179,8 +186,25 @@ jobs: # between begin and end, and the sample is deliberately excluded from analysis (it also # already sits in sonar.coverage.exclusions). Not continue-on-error - a broken sample is a # broken build. + # + # -p:GeneratePackageOnBuild=false is defence in depth, not a fix for a live bug. In + # UsePlochProjectReferences mode this step pulls the four library projects in as + # ProjectReferences, and they set GeneratePackageOnBuild=true, so in principle they could + # pack a second time - over the package-mode nupkgs this workflow later publishes - with + # ploch-common resolved as a ProjectReference and therefore a PRERELEASE dependency + # version. That is exactly the #47 defect this branch exists to remove. + # + # It does not currently happen: measured on a fully clean tree, this step packs the + # libraries into bin/Debug, while publish-nuget-packages.sh globs */bin/Release/*.nupkg, + # so the published artefacts are untouched. But the only thing preventing it is an + # incidental configuration-mapping quirk - the library projects are not members of the + # sample solution, so they do not inherit its Release mapping. Adding them to that + # solution would silently arm the bug. Suppressing the pack removes the class outright. + # + # Raised by the Copilot (Grok 4.6) reviewer on PR #52 as a live defect; investigated and + # refuted independently by the Codex reviewer; refutation confirmed by measurement. - name: Build sample application - run: dotnet build ./samples/SampleApp/Ploch.CommandLine.Spectre.SampleApp.slnx -c Release -p:UsePlochProjectReferences=true + run: dotnet build ./samples/SampleApp/Ploch.CommandLine.Spectre.SampleApp.slnx -c Release -p:UsePlochProjectReferences=true -p:GeneratePackageOnBuild=false # The main ruleset has a code_coverage rule, which reads coverage GitHub itself holds - # SonarCloud's and Codacy's copies are invisible to it. actions/upload-code-coverage takes a diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index 1c984a2..c5378bc 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -21,14 +21,24 @@ concurrency: jobs: publish-docs: + # Restoring the solution resolves Ploch.* from nuget.org and the authenticated GitHub + # Packages feed. Without the token that feed 401s on every Ploch package; restore usually + # still falls back to nuget.org, but the fallback is a race and a prerelease version would + # not be on nuget.org at all. See the longer note in release.yml. Raised by the Codex + # reviewer on PR #52. + env: + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest steps: - # The solution references sibling repositories by relative path - the workspace layout where - # every mrploch repo is cloned next to the others. Reproduce that layout here, otherwise the - # docfx metadata pass fails with MSB3202 for every ../ploch-common project. + # Reproduce the workspace layout here - every mrploch repo cloned next to the others. + # mrploch-development is required: Directory.Packages.props imports the shared version + # files from it. The ploch-common clone below is now belt-and-braces: in the default + # package mode the docfx metadata pass resolves Ploch dependencies from nuget.org, so the + # old MSB3202-on-every-ploch-common-project rationale no longer applies. Whether it can + # be dropped is #51. - name: Checkout uses: actions/checkout@v4 with: diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index a90d536..0d210d0 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -9,6 +9,11 @@ on: jobs: qodana: + # Same reason as publish-docs.yml: the scan restores the solution, which resolves Ploch.* + # from the authenticated GitHub Packages feed. See the note in release.yml. Raised by the + # Codex reviewer on PR #52. + env: + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} runs-on: ubuntu-latest permissions: contents: write diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bde997b..d30a38f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,8 +27,34 @@ jobs: env: RELEASE_VERSION: ${{ inputs.release_version }} NEXT_VERSION_INPUT: ${{ inputs.next_version }} - # Every `run` step operates inside the checked-out repository. Sibling repositories are - # checked out next to it, reproducing the workspace layout the solution expects. + # nuget.config maps Ploch.* to both nuget.org and the GitHub Packages feed, and the + # GitHub feed authenticates with %GH_PACKAGES_TOKEN%. Without it, every Ploch restore + # queries that feed unauthenticated and takes a 401. + # + # This is a reliability fix, and the mechanism is worth stating precisely because the + # obvious reading of it is wrong in both directions. An unauthenticated eligible feed + # does not reliably fail - a local test with an isolated packages folder and no token + # warned, retried, fell back to nuget.org and exited 0 - but neither is it merely + # cosmetic. NuGet queries sources concurrently and a restore succeeds as soon as one + # supplies the requested version, while a terminal protocol failure from another source + # is rethrown rather than ignored. Which of those happens first is a race: if the + # GitHub feed exhausts its retries before nuget.org returns the match, restore can fail + # with NU1301 even though the package exists on nuget.org. One green run is a sample of + # that race, not proof it cannot go the other way. + # + # It is also load-bearing, not just defensive: prerelease Ploch builds exist ONLY on the + # GitHub feed, so the moment the shared Ploch.Packages.props names a prerelease the + # nuget.org fallback finds nothing and restore fails hard with NU1103. + # + # It does NOT fix that for pull requests from forks - GitHub does not expose repository + # secrets to fork PRs at all, so no workflow can authenticate for them. Tracked in #54. + # + # Raised by four PR reviewers (codeant-ai, qodo, copilot, chatgpt-codex) and sharpened + # by the Codex and Antigravity reviewers on PR #52. + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} + # Every `run` step operates inside the checked-out repository. mrploch-development - the + # only sibling this workflow still needs - is checked out next to it, reproducing the + # workspace layout Directory.Packages.props expects. defaults: run: working-directory: ploch-commandline @@ -68,6 +94,23 @@ jobs: fi echo "GH_TOKEN is valid" + # Validate GH_PACKAGES_TOKEN too. Assigning it is not the same as having it: an unset or + # expired secret still leaves nuget.config sending an empty password to the GitHub + # Packages feed, which 401s and puts the restore back in the NU1301 race described on the + # job env above - the exact failure the token was added to remove. Fail here, with a + # readable message, rather than in the middle of a restore. + # Raised by the Copilot (Grok 4.6) reviewer on PR #52. + - name: Validate GH_PACKAGES_TOKEN secret + working-directory: . + env: + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} + run: | + if [ -z "$GH_PACKAGES_TOKEN" ]; then + echo "::error::GH_PACKAGES_TOKEN secret is not set. A token with 'read:packages' scope is required so the GitHub Packages feed mapped for Ploch.* in nuget.config can be authenticated." + exit 1 + fi + echo "GH_PACKAGES_TOKEN is set" + # Use the default GITHUB_TOKEN for checkout - it always works and has read access. # GH_TOKEN (PAT) is configured separately before push steps, because it is the # only token that can trigger subsequent workflows when pushing commits. diff --git a/Directory.Build.props b/Directory.Build.props index 33d0759..0d0d7b2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -92,8 +92,13 @@ Opt in with -p:UsePlochProjectReferences=true to build against a local ploch-common checkout instead - for cross-repo development, where a change in ploch-common needs to be seen here before it is published. Note the local checkout may be ahead of the released - packages (ploch-common main is on 4.1-prerelease), so the two modes are not interchangeable - and both are exercised in CI. + packages (ploch-common main is on 4.1-prerelease), so the two modes are not interchangeable. + + CI only exercises the DEFAULT (package) mode for the main solution. The one + -p:UsePlochProjectReferences=true invocation in build-dotnet.yml builds the *sample* + solution and does not run the main test projects against the sibling dependency graph, so + project-reference mode is verified locally but not guarded by CI. Raised by the Codex + reviewer on PR #52; adding a second CI job for it is tracked in #51. --> <PropertyGroup> <UsePlochProjectReferences Condition="'$(UsePlochProjectReferences)' == ''">false</UsePlochProjectReferences> @@ -141,8 +146,15 @@ so this is the correct home for it rather than a transitive accident. --> <ItemGroup Condition="$(IsTestProject)"> - <PackageReference Include="Microsoft.NET.Test.Sdk" /> + <!-- + PrivateAssets on the runner infrastructure but not on xunit.v3, matching the dotnet SDK + test template: the host and the VSTest adapter are build-time infrastructure, whereas + xunit.v3 is a real reference the test code compiles against. Currently cosmetic - test + projects are IsPackable=false so nothing flows anywhere - but the template shape is the + one a reader expects. Raised by the Copilot (Grok 4.6) reviewer on PR #52. + --> + <PackageReference Include="Microsoft.NET.Test.Sdk" PrivateAssets="all" /> <PackageReference Include="xunit.v3" /> - <PackageReference Include="xunit.runner.visualstudio" /> + <PackageReference Include="xunit.runner.visualstudio" PrivateAssets="all" /> </ItemGroup> </Project> diff --git a/Directory.Packages.props b/Directory.Packages.props index e1d6aed..efcaf64 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,19 +14,38 @@ <!-- Ploch package versions (ploch-common, ploch-data) come from the shared file so every repository in the workspace resolves the same builds. This replaces a local - `Ploch.Common 2.0.1` pin that was four major versions behind the packages this + `Ploch.Common 2.0.1` pin that was two major versions behind the packages this repository's own published package depends on (issues #46, #47). --> <Import Project="../mrploch-development/dependencies/Ploch.Packages.props" /> + <!-- + Ploch.Common.Apps.Shared is published (4.0.47) but is not listed in the shared + Ploch.Packages.props, so it cannot be centrally versioned from there yet. + Tracked by: mrploch/mrploch-development#21 + + Written as Remove-then-Include rather than a plain Include, and versioned from the shared + family property rather than a literal, so that it survives the upstream fix landing: + + * A second PackageVersion for an id that the imported file also defines is a hard error, + not a warning - verified: "error NU1506: Warning As Error: Duplicate 'PackageVersion' + items found". Since CI checks out mrploch-development at the moving `main` branch, a + merge in *that* repository would otherwise break restore here with no commit in this + one. The Remove makes the collision impossible. + * Taking the version from $(PlochCommonPackagesVersion) means that once the id is listed + upstream this block resolves to the identical version the rest of the family gets, so + it degrades into a harmless no-op that can be deleted at leisure instead of urgently. + The literal is only a fallback for the case where that property does not exist - + mrploch/mrploch-development#5 proposes renaming it to per-repo variables. + + Raised by the Codex reviewer on PR #52. + --> + <PropertyGroup> + <PlochAppsSharedVersion>$(PlochCommonPackagesVersion)</PlochAppsSharedVersion> + <PlochAppsSharedVersion Condition="'$(PlochAppsSharedVersion)' == ''">4.0.47</PlochAppsSharedVersion> + </PropertyGroup> <ItemGroup> - <!-- - Ploch.Common.Apps.Shared is published (4.0.47) but is not listed in the shared - Ploch.Packages.props, so it cannot be centrally versioned from there yet. Pinned here - to the same version the rest of the ploch-common family resolves to; remove this entry - once mrploch/mrploch-development adds it upstream. - Tracked by: mrploch/mrploch-development#21 - --> - <PackageVersion Include="Ploch.Common.Apps.Shared" Version="4.0.47" /> + <PackageVersion Remove="Ploch.Common.Apps.Shared" /> + <PackageVersion Include="Ploch.Common.Apps.Shared" Version="$(PlochAppsSharedVersion)" /> </ItemGroup> <Import Project="../mrploch-development/dependencies/Common.Packages.props" /> <Import Project="../mrploch-development/dependencies/Serilog.Logging.Packages.props" /> diff --git a/nuget.config b/nuget.config index 796a000..a64d2dd 100644 --- a/nuget.config +++ b/nuget.config @@ -20,6 +20,15 @@ Listing the pattern under both makes both feeds eligible and NuGet resolves the best match across them: stable releases from nuget.org, prerelease CI builds from GitHub Packages when a version range asks for one. + + One consequence worth stating, raised by the Antigravity reviewer on PR #52: a + wildcard pattern pointed at a public feed is the shape of a dependency-confusion + risk. If a Ploch.* package ever existed ONLY on GitHub Packages, someone could + publish that id on nuget.org and this mapping would happily consider it. That is + not the case today - every Ploch.* package this repository consumes is published on + nuget.org, and the family is open source - so the wildcard is accurate rather than + permissive. If a genuinely private Ploch.* package is ever introduced, narrow the + nuget.org side to explicit package ids instead of the prefix. --> <packageSourceMapping> <packageSource key="nuget.org"> From 4a7abe812d9a0feba993ac04242b22b34717a667 Mon Sep 17 00:00:00 2001 From: Krzysztof Ploch <kris@ploch.dev> Date: Sat, 12 Sep 2026 14:27:15 +0200 Subject: [PATCH 5/5] fix(github-actions): Scope the package token and make its check real Two findings from the PR reviewers on the previous commit. CodeRabbit: GH_PACKAGES_TOKEN was declared at job level, so the package credential was readable by every step in the job - checkout, artefact upload, the GitHub Release action, and the Qodana container action, none of which need it. Moved to the steps that actually restore: "Restore dependencies" in release.yml, "Build documentation site" in publish-docs.yml, and the Qodana Scan action, which restores inside its own container. The job-level declaration in build-dotnet.yml is pre-existing and left alone; several of its steps consume the feed. Copilot: the Validate GH_PACKAGES_TOKEN step only tested that the secret was non-empty, while its own message promised to catch an expired token or a missing read:packages scope. A non-empty but invalid token would have passed the gate and then 401'd during restore - the exact failure the step exists to pre-empt. It now authenticates against the GitHub Packages NuGet index and requires HTTP 200, mirroring how the existing GH_TOKEN validation curls the API. Refs: #47 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MroAgPwA8tGuEPi2rz4qJU --- .github/workflows/publish-docs.yml | 14 ++--- .github/workflows/qodana_code_quality.yml | 9 ++-- .github/workflows/release.yml | 66 ++++++++++++++--------- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index c5378bc..6a048b9 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -21,13 +21,6 @@ concurrency: jobs: publish-docs: - # Restoring the solution resolves Ploch.* from nuget.org and the authenticated GitHub - # Packages feed. Without the token that feed 401s on every Ploch package; restore usually - # still falls back to nuget.org, but the fallback is a race and a prerelease version would - # not be on nuget.org at all. See the longer note in release.yml. Raised by the Codex - # reviewer on PR #52. - env: - GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} @@ -75,6 +68,13 @@ jobs: - name: Build documentation site working-directory: ploch-commandline + # Scoped to this step, not the job, so the package credential is not exposed to + # checkout, upload or deployment actions (least privilege, raised by the CodeRabbit + # reviewer on PR #52). nuget.config maps Ploch.* to both nuget.org and the + # authenticated GitHub Packages feed; without the token that feed 401s on every Ploch + # package and the nuget.org fallback is a race. Full reasoning in release.yml. + env: + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} run: dotnet docfx DocumentationSite/docfx.json - name: Upload artifact diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml index 0d210d0..3153fea 100644 --- a/.github/workflows/qodana_code_quality.yml +++ b/.github/workflows/qodana_code_quality.yml @@ -9,11 +9,6 @@ on: jobs: qodana: - # Same reason as publish-docs.yml: the scan restores the solution, which resolves Ploch.* - # from the authenticated GitHub Packages feed. See the note in release.yml. Raised by the - # Codex reviewer on PR #52. - env: - GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} runs-on: ubuntu-latest permissions: contents: write @@ -68,5 +63,9 @@ jobs: with: pr-mode: false env: + # Scoped to this step, not the job (least privilege, raised by the CodeRabbit reviewer + # on PR #52). The scan restores the solution inside its container, which resolves + # Ploch.* from the authenticated GitHub Packages feed. Full reasoning in release.yml. + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} QODANA_TOKEN: ${{ secrets.QODANA_TOKEN_657107159 }} QODANA_ENDPOINT: 'https://qodana.cloud' \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d30a38f..f69112d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,31 +27,6 @@ jobs: env: RELEASE_VERSION: ${{ inputs.release_version }} NEXT_VERSION_INPUT: ${{ inputs.next_version }} - # nuget.config maps Ploch.* to both nuget.org and the GitHub Packages feed, and the - # GitHub feed authenticates with %GH_PACKAGES_TOKEN%. Without it, every Ploch restore - # queries that feed unauthenticated and takes a 401. - # - # This is a reliability fix, and the mechanism is worth stating precisely because the - # obvious reading of it is wrong in both directions. An unauthenticated eligible feed - # does not reliably fail - a local test with an isolated packages folder and no token - # warned, retried, fell back to nuget.org and exited 0 - but neither is it merely - # cosmetic. NuGet queries sources concurrently and a restore succeeds as soon as one - # supplies the requested version, while a terminal protocol failure from another source - # is rethrown rather than ignored. Which of those happens first is a race: if the - # GitHub feed exhausts its retries before nuget.org returns the match, restore can fail - # with NU1301 even though the package exists on nuget.org. One green run is a sample of - # that race, not proof it cannot go the other way. - # - # It is also load-bearing, not just defensive: prerelease Ploch builds exist ONLY on the - # GitHub feed, so the moment the shared Ploch.Packages.props names a prerelease the - # nuget.org fallback finds nothing and restore fails hard with NU1103. - # - # It does NOT fix that for pull requests from forks - GitHub does not expose repository - # secrets to fork PRs at all, so no workflow can authenticate for them. Tracked in #54. - # - # Raised by four PR reviewers (codeant-ai, qodo, copilot, chatgpt-codex) and sharpened - # by the Codex and Antigravity reviewers on PR #52. - GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} # Every `run` step operates inside the checked-out repository. mrploch-development - the # only sibling this workflow still needs - is checked out next to it, reproducing the # workspace layout Directory.Packages.props expects. @@ -109,7 +84,16 @@ jobs: echo "::error::GH_PACKAGES_TOKEN secret is not set. A token with 'read:packages' scope is required so the GitHub Packages feed mapped for Ploch.* in nuget.config can be authenticated." exit 1 fi - echo "GH_PACKAGES_TOKEN is set" + # A presence check is not enough: an expired token, or one without read:packages, + # is non-empty and still 401s during restore - which is the failure this step + # exists to pre-empt. So actually authenticate against the feed nuget.config uses. + # Basic auth with the token as the password is how NuGet presents it. + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -u "x-access-token:$GH_PACKAGES_TOKEN" https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json) + if [ "$HTTP_STATUS" != "200" ]; then + echo "::error::GH_PACKAGES_TOKEN is invalid, expired, or lacks 'read:packages' (HTTP $HTTP_STATUS from the GitHub Packages NuGet index). Regenerate the token and update the repository secret." + exit 1 + fi + echo "GH_PACKAGES_TOKEN authenticates against GitHub Packages" # Use the default GITHUB_TOKEN for checkout - it always works and has read access. # GH_TOKEN (PAT) is configured separately before push steps, because it is the @@ -176,6 +160,36 @@ jobs: echo "NuGet package version: $NUGET_VERSION" - name: Restore dependencies + # Scoped to this step rather than the job, so the package credential is not exposed + # to checkout, upload, release or other third-party actions (least privilege, raised + # by the CodeRabbit reviewer on PR #52). + # + # nuget.config maps Ploch.* to both nuget.org and the GitHub Packages feed, and the + # GitHub feed authenticates with %GH_PACKAGES_TOKEN%. Without it, every Ploch restore + # queries that feed unauthenticated and takes a 401. + # + # This is a reliability fix, and the mechanism is worth stating precisely because the + # obvious reading of it is wrong in both directions. An unauthenticated eligible feed + # does not reliably fail - a local test with an isolated packages folder and no token + # warned, retried, fell back to nuget.org and exited 0 - but neither is it merely + # cosmetic. NuGet queries sources concurrently and a restore succeeds as soon as one + # supplies the requested version, while a terminal protocol failure from another source + # is rethrown rather than ignored. Which of those happens first is a race: if the + # GitHub feed exhausts its retries before nuget.org returns the match, restore can fail + # with NU1301 even though the package exists on nuget.org. One green run is a sample of + # that race, not proof it cannot go the other way. + # + # It is also load-bearing, not just defensive: prerelease Ploch builds exist ONLY on the + # GitHub feed, so the moment the shared Ploch.Packages.props names a prerelease the + # nuget.org fallback finds nothing and restore fails hard with NU1103. + # + # It does NOT fix that for pull requests from forks - GitHub does not expose repository + # secrets to fork PRs at all, so no workflow can authenticate for them. Tracked in #54. + # + # Raised by four PR reviewers (codeant-ai, qodo, copilot, chatgpt-codex) and sharpened + # by the Codex and Antigravity reviewers on PR #52. + env: + GH_PACKAGES_TOKEN: ${{ secrets.GH_PACKAGES_TOKEN }} run: dotnet restore ./Ploch.CommandLine.Spectre.slnx - name: Build (Release)