diff --git a/.squad/agents/gimli/charter.md b/.squad/agents/gimli/charter.md index 3d4000c2..d994c631 100644 --- a/.squad/agents/gimli/charter.md +++ b/.squad/agents/gimli/charter.md @@ -22,7 +22,7 @@ You are Gimli, the Tester on the {ProjectName} project. You own unit tests, inte - Does NOT write production code (flag gaps, don't fix them — tell Aragorn or the relevant agent) ## Critical Rules -1. **Before any push: run the FULL local test suite** — `dotnet test tests/Api.Tests.Unit tests/Shared.Tests.Unit tests/Web.Tests.Unit tests/Web.Tests.Bunit tests/Architecture.Tests`. Zero failures required. Pre-push hook gates on these test suites. CI must never be the first place test failures are discovered. +1. **Before any push: run the FULL local test suite** — `dotnet test tests/Unit.Tests tests/Architecture.Tests -c Release`. Zero failures required, and the coverage gate (89% line threshold) must pass. Pre-push hook gates on these suites. CI must never be the first place test failures or coverage gaps are discovered. 2. **Domain-specific collections REQUIRED** — Use `[Collection("{Entity}Integration")]` (one per domain entity) on all integration test classes. Each collection is backed by `ICollectionFixture`. Do NOT use the old single `[Collection("Integration")]`. Use `$"T{Guid.NewGuid():N}"` as the DB name in the constructor for per-test-method isolation. 3. **NEVER compare two `{Entity}Dto.Empty` calls** — `Empty` calls `DateTime.UtcNow` each time; assert individual fields instead 4. **`GenerateSlug` trailing underscore is correct** — `"C# Is Great!"` → `"c_is_great_"` (trailing underscore expected) @@ -38,9 +38,10 @@ You are Gimli, the Tester on the {ProjectName} project. You own unit tests, inte // Project Name : {ProjectName} // ============================================= ``` - Project Name: `Api.Tests.Unit`, `Shared.Tests.Unit`, `Web.Tests.Unit`, `Api.Tests.Integration`, `Web.Tests.Bunit`, or `Aspire` based on test project directory. + Project Name: `Unit.Tests`, `Architecture.Tests`, or `Integration.Tests` based on test project directory. 7. AAA pattern (Arrange / Act / Assert) with comments 8. File-scoped namespaces, tab indentation +9. **Gimli is spawned in parallel with Sam/Legolas** for every feature/fix. Tests ship with the code — not after the PR is opened. ## Model Preferred: auto (test authoring resolves to claude-sonnet-4.6) diff --git a/.squad/ceremonies.md b/.squad/ceremonies.md index 45b4a581..e312963f 100644 --- a/.squad/ceremonies.md +++ b/.squad/ceremonies.md @@ -2,6 +2,29 @@ > Team meetings that happen before or after work. Each squad configures their own. +## Feature Work Kickoff + +| Field | Value | +|-------|-------| +| **Trigger** | auto | +| **When** | before | +| **Condition** | any agent picks up a feature or fix issue that touches production code | +| **Facilitator** | coordinator | +| **Participants** | feature author + Gimli + Frodo | +| **Time budget** | focused | +| **Enabled** | ✅ yes | + +**Agenda:** +1. Feature author reads the issue and identifies files to be changed +2. Gimli is spawned in parallel to write tests from the issue's acceptance criteria +3. Frodo is spawned in parallel to note doc/README impact +4. If new architectural patterns are involved → rubber duck BEFORE coding starts +5. All agents confirm scope before the first file is opened + +**Hard Rule:** No feature code is written without Gimli already working on tests. Tests are a parallel deliverable, not a post-merge cleanup. + +--- + ## Design Review | Field | Value | @@ -28,14 +51,16 @@ |-------|-------| | **Trigger** | auto | | **When** | after | -| **Condition** | build failure, test failure, or reviewer rejection | +| **Condition** | build failure, test failure, coverage gate failure, CI failure, or reviewer rejection | | **Facilitator** | lead | | **Participants** | all-involved | | **Time budget** | focused | | **Enabled** | ✅ yes | **Agenda:** -1. What happened? (facts only) -2. Root cause analysis -3. What should change? -4. Action items for next iteration +1. What happened? (facts only — no blame) +2. Root cause analysis (was it a guardrail gap? a bypass? missing agent activation?) +3. What should change? (update routing.md, ceremonies.md, or playbooks) +4. Action items with owner assigned + +**Hard Rule:** Every CI failure triggers a retrospective. Ralph documents action items in `.squad/decisions/inbox/` within the same session. The squad does not move to the next sprint without closing all retrospective action items. diff --git a/.squad/playbooks/pr-merge-process.md b/.squad/playbooks/pr-merge-process.md index 78f322ed..063d0a21 100644 --- a/.squad/playbooks/pr-merge-process.md +++ b/.squad/playbooks/pr-merge-process.md @@ -56,13 +56,17 @@ Ralph MUST verify ALL of the following before spawning reviewers. Any failing ga | Gate | Command | Expected | | ------------------------- | ---------------------------------------------------------------- | ------------------------------- | | GitHub issue exists | `gh pr view --json body -q .body \| grep -E "Closes #[0-9]+"` | Contains `Closes #N` | -| CI green | `gh pr checks --watch --interval 5` | All passing | +| CI fully green | `gh pr checks --watch --interval 5` | All checks passing (including coverage gate) | +| Coverage gate passing | Check CI run logs for `The total line coverage is below` | No coverage error in logs | | No conflicts | `gh pr view --json mergeable -q .mergeable` | `MERGEABLE` | | PR template filled | `gh pr view --json body` | Contains filled checkboxes | | Branch is `squad/*` | `gh pr view --json headRefName -q .headRefName` | Starts with `squad/` | +| Tests authored | PR diff includes test file additions/modifications | Gimli coverage present | > **If `Closes #N` is missing**, the PR was opened without a GitHub issue. Ralph must STOP, create the issue, link it in the PR body, assign it to the correct milestone and Project #4, then re-run this gate. +> **If coverage gate is failing** (CI red on coverage, not test logic), DO NOT spawn reviewers. Route to Gimli (issue #68 pattern) to add Domain tests. The PR is not review-ready until CI is fully green including coverage. + ## Step 4 — Spawn Reviewers Aragorn is ALWAYS required. Additional reviewers depend on files changed: diff --git a/.squad/playbooks/pre-push-process.md b/.squad/playbooks/pre-push-process.md index 8b5bc7b6..48520962 100644 --- a/.squad/playbooks/pre-push-process.md +++ b/.squad/playbooks/pre-push-process.md @@ -2,10 +2,21 @@ **Owner:** Boromir (DevOps) + Aragorn (Lead) **Ref:** `.github/hooks/pre-push`, `CONTRIBUTING.md` -**Last Updated:** 2026-04-13 +**Last Updated:** 2026-04-19 --- +> ⛔ **HARD BLOCK — `git push --no-verify` is prohibited.** +> Bypassing the pre-push hook defeats all local quality gates (build, tests, +> coverage). CI becomes the first place failures are discovered — wasting +> everyone's time. **Fix the root cause instead:** +> - SDK mismatch → install the SDK version pinned in `global.json` from https://dot.net +> - Hook not installed → run `scripts/install-hooks.sh` +> - Docker not running → start Docker Desktop / `sudo systemctl start docker` +> +> Any `--no-verify` push requires **prior written approval from Ralph + Aragorn** +> documented in a GitHub issue comment. Undocumented bypasses are a retro action item. + ## Overview The pre-push hook (`.github/hooks/pre-push`) enforces 5 gates that mirror CI. This playbook documents what agents must do before pushing and how to troubleshoot failures. diff --git a/.squad/playbooks/sprint-planning.md b/.squad/playbooks/sprint-planning.md index 09f08a95..41942bb7 100644 --- a/.squad/playbooks/sprint-planning.md +++ b/.squad/playbooks/sprint-planning.md @@ -93,6 +93,16 @@ Todo ID: {todo-id}" **Issue title convention:** `[Sprint N] {Verb} {Noun}` (e.g., `[Sprint 1] Add BlogPost entity and repository`) +**Mandatory format — every issue must satisfy both:** + +| Field | Requirement | +|-------|-------------| +| Title | Must start with `[Sprint N]` prefix | +| Milestone | Must be set to `Sprint N: {Theme}` before any branch is created | + +> **Hard rule:** An issue without a milestone or without the `[Sprint N]` prefix in its +> title is incomplete. No branch or code may reference it until both fields are set. + After creating each issue, **Aragorn immediately triages** it: - Replace `squad` label with `squad:{member}` (e.g., `squad:sam`) - This triggers normal issue routing for that member @@ -292,22 +302,31 @@ Before any agent writes, modifies, or commits code, a GitHub issue **must** exis ``` 1. Does a GitHub issue exist for this work? - YES → confirm it is assigned to the correct milestone + Project #4, then proceed to Step 1 + YES → does the issue have: + a) a milestone set to "Sprint N: {Theme}"? + b) a title starting with "[Sprint N]"? + If either is missing → fix it now before touching any file. + Then proceed to Step 1. NO → CREATE the issue now before touching any file - → Assign to milestone, add to Project #4 + → Title MUST start with "[Sprint N]" + → Milestone MUST be set to "Sprint N: {Theme}" + → Add to Project #4 → Create squad/{issue}-{slug} branch → THEN and only then begin writing code ``` -If you skip this gate and write code without an issue, you have violated the squad's process. -The work must be stashed, the issue created retroactively, a proper branch checked out, and -the stash re-applied before committing. This costs time — follow the gate. +If you skip this gate and write code without an issue, or create an issue without the +sprint prefix and milestone, you have violated the squad's process. The work must be +stashed, the issue corrected, a proper branch checked out, and the stash re-applied +before committing. This costs time — follow the gate. --- ## Anti-Patterns - ❌ **Writing any code before a GitHub issue exists** — always create the issue first +- ❌ **Creating an issue without setting its milestone** — every issue must be assigned to `Sprint N: {Theme}` before any branch is created +- ❌ **Creating an issue whose title does not start with `[Sprint N]`** — the sprint prefix is mandatory; bare titles like "Fix login bug" are invalid - ❌ **Implementing a `[[PLAN]]` request without first running the sprint planning ceremony** — plan → issue → branch → code - ❌ **Opening `squad/{issue}` PRs directly to `dev`** during an active sprint - ❌ **Skipping worktree** — always work in `../MyBlog-sprint-{N}/` for isolation diff --git a/.squad/routing.md b/.squad/routing.md index f3639ecd..f6dc6b66 100644 --- a/.squad/routing.md +++ b/.squad/routing.md @@ -63,10 +63,12 @@ spawn prompt: After Sprint 1.1, these process assets are part of normal squad flow: 1. **Before writing any code**, a GitHub issue MUST exist for the work. This is an - absolute gate with no exceptions. If no issue exists, create it first — assign - to the correct milestone, add to Project #4 — then create the `squad/{issue}-{slug}` - branch, and only then write code. See the Hard Gate section in - `.squad/playbooks/sprint-planning.md`. + absolute gate with no exceptions. The issue must also have a milestone set to + `Sprint N: {Theme}` and a title that starts with `[Sprint N]`. If no issue + exists — or the issue lacks a milestone or sprint prefix — create/fix it first, + assign to the correct milestone, add to Project #4 — then create the + `squad/{issue}-{slug}` branch, and only then write code. See the Hard Gate section + in `.squad/playbooks/sprint-planning.md`. 2. **Before any push-ready handoff**, route through the pre-push gate skill and pre-push playbook so agents respect the live MyBlog hook: `squad/{issue}-{slug}` branch naming, Release build, `Architecture.Tests`, `Unit.Tests`, and @@ -85,7 +87,24 @@ After Sprint 1.1, these process assets are part of normal squad flow: `.squad/playbooks/sprint-planning.md`. 8. **When a user makes any coding request** (direct instruction, `[[PLAN]]`, or follow-on work), the very first agent action is to check whether a GitHub issue - exists. If not, create it before any file is opened or modified. + exists with a `[Sprint N]` title prefix and a sprint milestone set. If the issue + is missing, create it. If it exists but lacks the prefix or milestone, fix those + fields before any file is opened or modified. +9. **When any production code is written or modified** (Domain, Web, Persistence, + AppHost), Gimli MUST be spawned in parallel to write or update unit tests. + No feature branch closes without corresponding test authoring. The coverage gate + (currently 89% line threshold in `Unit.Tests.csproj`) must pass locally before + push. This is not optional — test coverage is a first-class deliverable. +10. **`git push --no-verify` is PROHIBITED.** It bypasses all pre-push quality gates + (build, tests, coverage) and wastes CI time when failures are discovered + remotely. If the hook fails due to a local SDK mismatch, fix the root cause: + install the SDK version pinned in `global.json` (e.g., `dotnet-install.sh` + or download from https://dot.net). SDK mismatch is never a valid bypass reason. + Any `--no-verify` push requires prior documented approval from Ralph + Aragorn. +11. **When new architectural patterns are introduced** (new CQRS handler type, new + service abstraction, new Blazor rendering pattern, new repository strategy), a + rubber duck review MUST be run before the branch is pushed. Document the + pattern decision in `.squad/decisions/inbox/` and route to Aragorn for ADR. ## Rules @@ -94,5 +113,5 @@ After Sprint 1.1, these process assets are part of normal squad flow: 3. **Quick facts → coordinator answers directly.** Don't spawn an agent for "what port does the server run on?" 4. **When two agents could handle it**, pick the one whose domain is the primary concern. 5. **"Team, ..." → fan-out.** Spawn all relevant agents in parallel as `mode: "background"`. -6. **Anticipate downstream work.** If a feature is being built, spawn the tester to write test cases from requirements simultaneously. +6. **Anticipate downstream work.** If a feature is being built, spawn Gimli (tests), Frodo (doc impact), and Pippin (changelog note) in parallel with the feature author. Tests are not an afterthought — they ship with the code. 7. **Issue-labeled work** — when a `squad:{member}` label is applied to an issue, route to that member. The Lead handles all `squad` (base label) triage. diff --git a/.squad/templates/issue-lifecycle.md b/.squad/templates/issue-lifecycle.md index 988c06c0..15c11396 100644 --- a/.squad/templates/issue-lifecycle.md +++ b/.squad/templates/issue-lifecycle.md @@ -54,6 +54,19 @@ squad/{issue-number}-{kebab-case-slug} ``` Example: `squad/42-fix-login-validation` +**Mandatory issue format:** + +Every GitHub issue created by Squad MUST satisfy both of the following before any +branch or code references it: + +| Field | Requirement | Example | +|-------|-------------|---------| +| Title | Starts with `[Sprint N]` prefix | `[Sprint 3] Add BlogPost list page` | +| Milestone | Set to `Sprint N: {Theme}` | `Sprint 3: MongoDB Persistence` | + +If either field is missing, set it before creating the branch. An issue without a +sprint assignment is considered incomplete and must not be used as a branch target. + ### Azure DevOps | ADO State | Squad Board State |