Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/agents/squad-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ hooks:
orchestrator, which holds the Git and GitHub tools.

Read first: `.squad/stack.md` (*Layout*, *Writing code*, *Skeleton*, *Known pitfalls*), the *Code style*
and *Architecture* sections of `CLAUDE.md`, the approved plan (for a feature: the tasks assigned to you),
and *Architecture* sections of `AGENTS.md`, the approved plan (for a feature: the tasks assigned to you),
the Tester's tests, and only the parts of `docs/` the plan names. The plan already carries the guarantees
and integration points that apply; `.squad/project.md` is the Lead's and the Reviewer's reading.

Expand Down
4 changes: 2 additions & 2 deletions .claude/agents/squad-lead.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ hooks:
`docs/decisions/`, the area documents the change touches, every decision inside the squad, and the PR
approval.

Read first: `.squad/routing.md`, `.squad/project.md`, `.squad/stack.md`, `CLAUDE.md`, `docs/ARCHITECTURE.md`,
Read first: `.squad/routing.md`, `.squad/project.md`, `.squad/stack.md`, `AGENTS.md`, `docs/ARCHITECTURE.md`,
`docs/decisions/README.md` and the existing records there, `docs/areas/README.md` and the area documents your
change touches (do not contradict an accepted record silently β€” change it if unreleased, supersede it if
released), and the work folder you are given.
Expand Down Expand Up @@ -161,7 +161,7 @@ decision (user-visible behavior change, weakening a guarantee from `docs/ARCHITE
where no option is clearly right.

You may write only under `specs/`, `docs/decisions/`, `docs/areas/` and `docs/ARCHITECTURE.md` β€” never
`.squad/`, `.claude/`, `CLAUDE.md` or `.github/copilot-instructions.md` in a product change. Bash is for read-only commands (`git diff`,
`.squad/`, `.claude/`, `AGENTS.md`, `CLAUDE.md` or `.github/copilot-instructions.md` in a product change. Bash is for read-only commands (`git diff`,
`git log`, `git status`, `grep`, *Test* from `.squad/stack.md` to inspect behavior). Never edit production or
test code, never run Git write operations, never post to GitHub, never call session-management tools
(`create_session`, `send_message`, `archive_session`) β€” follow-up issues you decide on are created by the
Expand Down
8 changes: 4 additions & 4 deletions .claude/agents/squad-reviewer.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ reviewer, not an implementer.

Read first: `.squad/stack.md` (commands, analyzer gate, code and test
conventions), `.squad/project.md` (security areas, guarantees, integration
surface, test doubles), `CLAUDE.md` and `docs/UNIT_TESTS.md`.
surface, test doubles), `AGENTS.md` and `docs/UNIT_TESTS.md`.

## Hard constraints

Expand Down Expand Up @@ -109,7 +109,7 @@ After step 10 the plan comes from the "Squad working record" comment the
calling session points you to.

Outside the squad (e.g. via `create-pr` for a squad-maintenance change), run
`python3 .squad/tools/config-check.py` whenever the diff touches `.claude/`, `CLAUDE.md` or
`python3 .squad/tools/config-check.py` whenever the diff touches `.claude/`, `AGENTS.md`, `CLAUDE.md` or
`.github/copilot-instructions.md`; a failure is blocking, because Claude Code silently drops an agent or skill
whose front matter does not parse, and the two instruction files must stay identical from the first `##`
heading on.
Expand Down Expand Up @@ -149,7 +149,7 @@ hold in every repository:
section has nothing to check here.
- **A new dependency** follows *Dependencies* in `.squad/stack.md` (e.g. a
central version file); a version outside that mechanism is blocking.
- **A change to project conventions** touches `CLAUDE.md`,
- **A change to project conventions** touches `AGENTS.md`,
`.github/copilot-instructions.md`, `.squad/stack.md`, the skill files under
`.claude/skills/` and `docs/`, which are meant to stay in sync with each other. Updating only one of them is a finding.

Expand All @@ -161,7 +161,7 @@ repository names this thing, and is that statement still true?**
- **Analyzer cleanliness**: would the *Analyzer gate* in `.squad/stack.md`
pass? Check the rules listed there as easy to get wrong by hand.
- **Code style**: the conventions in *Writing code* (`stack.md`) and the
code style section of `CLAUDE.md`.
code style section of `AGENTS.md`.
- **Error handling**: are failures from external systems (network, file
system, parsers, child processes) handled rather than allowed to kill a
long-running loop or, worse, silently produce wrong data? A fabricated or
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/create-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ in.
- *Test with coverage* and *Coverage gate* β€” it must pass (the thresholds
are in `.squad/tools/squad_settings.py`)
- `python3 .squad/tools/config-check.py` when the diff touches `.claude/`,
`CLAUDE.md` or `.github/copilot-instructions.md` β€” Claude Code silently
`AGENTS.md`, `CLAUDE.md` or `.github/copilot-instructions.md` β€” Claude Code silently
drops an agent or skill whose front matter does not parse, and the two
instruction files must stay identical from the first `##` heading on
Fix any failures before proceeding β€” do not open a PR with failing checks,
Expand Down
4 changes: 2 additions & 2 deletions .claude/skills/squad-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ action yourself β€” including follow-up issues the Lead decides on.
continuations of one agent or once its reported tokens pass 300,000, launch the member fresh with a short
hand-over (*Continuing a member*). A continued member keeps its role's limits (`.squad/team.md`).
- **The squad does not change itself in a product PR.** An issue or feature PR never touches `.squad/`
(`team.md`, `routing.md`, tools), `.claude/`, `CLAUDE.md` or `.github/copilot-instructions.md`. Lessons about the squad are filed in step 12 as `.squad/routing.md`,
(`team.md`, `routing.md`, tools), `.claude/`, `AGENTS.md`, `CLAUDE.md` or `.github/copilot-instructions.md`. Lessons about the squad are filed in step 12 as `.squad/routing.md`,
*Squad lessons*, says β€” template-managed files in the template repository, project knowledge here. If the
change itself genuinely needs one of those files (e.g. a new build command every contributor must know),
the Lead escalates instead and the Product Manager decides: `.squad/stack.md` and `.squad/project.md` may
Expand All @@ -54,7 +54,7 @@ action yourself β€” including follow-up issues the Lead decides on.
break each other (`.squad/routing.md`). Launch them one after another; only `squad-devils-advocate` and
`squad-security` may run together in steps 2–3, and `squad-reviewer` and `squad-security` in step 8,
because they are read-only and the reviewer's own build happens in a scratch copy.
- **Commits and pushes** to the work branch are always allowed (`CLAUDE.md`, golden rules): commit and
- **Commits and pushes** to the work branch are always allowed (`AGENTS.md`, golden rules): commit and
push `specs/<folder>/log.md` right after intake (step 1), so a stop hook or a crashed session finds no
untracked files, and after every further completed step. PRs are merged with *Squash and merge*, so only
the PR title and description reach `main`; intermediate commit messages may name the step, but never
Expand Down
6 changes: 3 additions & 3 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copilot instructions

Project guidance for GitHub Copilot when working in this repository. These rules mirror
[`CLAUDE.md`](/CLAUDE.md): everything from the first `##` heading on is generated from it by the template's
[`AGENTS.md`](/AGENTS.md): everything from the first `##` heading on is generated from it by the template's
`adopt-template` skill (Claude Code's `@` import lines aside β€” Copilot reads
`.github/instructions/*.instructions.md` through their `applyTo` front matter), and
`.squad/tools/config-check.py` fails when the two differ. Change both files together. This file is a
Expand Down Expand Up @@ -194,8 +194,8 @@ the project's guarantees, security areas and integration surface in
[`.squad/project.md`](/.squad/project.md). Their working records (`plan.md`, `log.md`, for features also
`spec.md` and `tasks.md`) live under `specs/` on the work branch only; before the PR they are posted as a
comment on the issue and removed, so `main` keeps no working records. An issue or feature PR never changes
the squad or these instructions (`.squad/` except `stack.md` and `project.md`, `.claude/`, `CLAUDE.md`,
`.github/copilot-instructions.md`): squad
the squad or these instructions (`.squad/` except `stack.md` and `project.md`, `.claude/`, `AGENTS.md`,
`CLAUDE.md`, `.github/copilot-instructions.md`): squad
lessons are filed as GitHub issues labelled `squad` and never fixed in a product PR. The squad and these
rules come from the template repository named in `.squad/template.json`: a lesson about a template-managed
file becomes an issue there and is rolled out with its `adopt-template` skill; a lesson about project
Expand Down
2 changes: 1 addition & 1 deletion .squad/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ change with it.
- the client table in `docs/ARCHITECTURE.md`, *Integration clients*

**A change to the entity model** touches:
- `DockerUpdateGuardDbContext`, a migration named per the convention in `CLAUDE.md` (*Project configuration*)
- `DockerUpdateGuardDbContext`, a migration named per the convention in `AGENTS.md` (*Project configuration*)
- `src/Tests/DockerUpdateGuard.Data.Tests`
- `docs/ARCHITECTURE.md`, *Data layer*

Expand Down
17 changes: 9 additions & 8 deletions .squad/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ launch) β€” (after step 10, in the "Squad working record" comment that replaces
## Scope of a product PR

An issue or feature PR changes the product and its documentation only. It never touches the squad or the
agent instructions: `.squad/` (`team.md`, `routing.md`, tools), `.claude/`, `CLAUDE.md` and
`.github/copilot-instructions.md`.
agent instructions: `.squad/` (`team.md`, `routing.md`, tools), `.claude/`, `AGENTS.md`, `CLAUDE.md`
and `.github/copilot-instructions.md`.
Lessons about the squad are collected in step 12 and filed where they can be fixed (*Squad lessons*
below), never fixed in the product PR. `python3 .squad/tools/scope-check.py` reports any such file in the
diff; the orchestrator runs it in step 7 and the Reviewer in step 8, and a finding is blocking.
Expand All @@ -49,11 +49,12 @@ repository, its commit and the stack profile). Three kinds:
`.github/ISSUE_TEMPLATE/feature_request.md`, `docs/decisions/_template.md`, `docs/areas/_template.md`,
`specs/README.md` and `specs/_template/`.
- **Marked** β€” rebuilt on every refresh, keeping the repository's content inside
`<!-- project:… -->` blocks: `CLAUDE.md`, `docs/CONTRIBUTING.md`, `docs/ARCHITECTURE.md`, `.github/ISSUE_TEMPLATE/bug_report.md`,
`<!-- project:… -->` blocks: `AGENTS.md`, `docs/CONTRIBUTING.md`, `docs/ARCHITECTURE.md`, `.github/ISSUE_TEMPLATE/bug_report.md`,
`.github/pull_request_template.md`, `docs/decisions/README.md` and `docs/areas/README.md`. Text outside the
project blocks is the template's. `.github/copilot-instructions.md` is generated from `CLAUDE.md`: its own
title and introduction, then the body of `CLAUDE.md` from the first `##` heading on, which `config-check.py`
keeps identical β€” a change to that body (a project block, too) is made in both files.
project blocks is the template's. `.github/copilot-instructions.md` is generated from `AGENTS.md`: its own
title and introduction, then the body of `AGENTS.md` from the first `##` heading on, which `config-check.py`
keeps identical β€” a change to that body (a project block, too) is made in both files. `CLAUDE.md` is managed:
it only imports `AGENTS.md` (`@AGENTS.md`), so Claude Code reads the same rules as every other agent.
- **Seeded** β€” created once and owned by the repository from then on: `.squad/stack.md`,
`.squad/project.md`, `.squad/tools/squad_settings.py`,
`.claude/settings.json`, `SECURITY.md`, `docs/UNIT_TESTS.md` and the stack profile's CI, CodeQL, Dependabot and tool
Expand All @@ -65,7 +66,7 @@ Every lesson from step 12 is filed once, where it can actually be fixed:

| The lesson concerns | Filed as | Fixed by |
| ------------------- | -------- | -------- |
| a **managed** file, or the template part of a **marked** file (squad rules, agents, skills, tools, the template sections of `CLAUDE.md`) | an issue labelled `squad` in the template repository named in `.squad/template.json` (`repository`), titled `[Squad] <lesson> (from <this repository>#<issue>)` and linking the run | a PR in the template repository, then a refresh of every repository that uses the template (`adopt-template`) β€” never a local edit, which the next refresh would overwrite |
| a **managed** file, or the template part of a **marked** file (squad rules, agents, skills, tools, the template sections of `AGENTS.md`) | an issue labelled `squad` in the template repository named in `.squad/template.json` (`repository`), titled `[Squad] <lesson> (from <this repository>#<issue>)` and linking the run | a PR in the template repository, then a refresh of every repository that uses the template (`adopt-template`) β€” never a local edit, which the next refresh would overwrite |
| **project knowledge**: `.squad/stack.md`, `.squad/project.md`, `.squad/tools/squad_settings.py`, a `<!-- project:… -->` block, another seeded file | an issue labelled `squad` in this repository | a small squad-maintenance PR in this repository, checked with `.squad/tools/config-check.py` |

One run's lessons go into at most one issue per destination. A lesson that is general β€” one that would change
Expand Down Expand Up @@ -181,7 +182,7 @@ coverage. Step 7 still runs *Format check*, the *Analyzer gate* and `scope-check
**Continuing a member.** A fix round or a delta round of the same member within the same run continues
that member's last launch (the harness keeps a launched subagent's context: `SendMessage` to its agent id,
or the Agent tool's resume) with the findings and the new head SHA, instead of a fresh launch that reloads
`CLAUDE.md`, `stack.md`, `project.md`, the plan and the code. A fresh launch stays the rule for the first
`AGENTS.md`, `stack.md`, `project.md`, the plan and the code. A fresh launch stays the rule for the first
launch of a mode, after a session restart (the agent id is gone) and when the previous launch ended on an
API error. The log records a continuation as a launch of that member (`squad-log.py … --continued`): the
notification reports the agent's tokens since its first launch but its tool uses and duration for the round
Expand Down
4 changes: 2 additions & 2 deletions .squad/team.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Lead cannot resolve.

## Shared rules (apply to every member)

`CLAUDE.md`, `docs/ARCHITECTURE.md`, `docs/CONTRIBUTING.md`, `docs/UNIT_TESTS.md`, `.squad/stack.md` and
`AGENTS.md`, `docs/ARCHITECTURE.md`, `docs/CONTRIBUTING.md`, `docs/UNIT_TESTS.md`, `.squad/stack.md` and
`.squad/project.md` are binding: unit tests for all new code until the *Coverage gate* passes, the code
conventions from `stack.md` while writing, English for everything
that ends up in the repository or on GitHub. Inside the squad, the member that changed files β€” Dev,
Expand All @@ -58,7 +58,7 @@ labels it "Code Officer only" is superseded by this rule. The Code Officer owns
launched only for analyzer diagnostics or style findings that need reading. Subagents never run Git write operations or post
to GitHub β€” the `PreToolUse` hook `.claude/hooks/git-guard.py`, declared in every `squad-*.md`, denies them
(`git add` and a scratch `git worktree` for experiments stay allowed, `.squad/routing.md`, *Concurrency*);
the orchestrator commits and pushes to the work branch at any time (see `CLAUDE.md`, golden rules) and
the orchestrator commits and pushes to the work branch at any time (see `AGENTS.md`, golden rules) and
opens the pull request only after the Lead's approval. Because the orchestrator may commit an interim state
while a member works (a stop hook demands it), a clean `git status` at hand-back is no sign of lost work: a
member reports its changes against the head SHA it was given (`git diff <sha>`).
Expand Down
2 changes: 1 addition & 1 deletion .squad/template.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"repository": "LarsLaskowski/Squad-Spec-Repository-Template",
"commit": "133edf2a6697efb356bce8dd82c498a347b62a8a",
"commit": "daa6b39c0c0c44a9f20154a7eff746673d26cc79",
"profile": "dotnet",
"profiles": [
"dotnet"
Expand Down
17 changes: 13 additions & 4 deletions .squad/tools/config-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
- every squad agent (`squad-*.md`) declares the `PreToolUse` hook `.claude/hooks/git-guard.py` for `Bash`, and
that hook exists: it keeps Git and GitHub write operations out of the members' hands; it also names its
`model` as an alias (`haiku`, `sonnet`, `opus`) and an explicit `effort`;
- `CLAUDE.md` and its GitHub Copilot mirror `.github/copilot-instructions.md` exist and are identical from their
first `## ` heading on (only the title and introduction differ; Claude Code `@path` import lines on a line of
their own are left out of the comparison, Copilot reads `.github/instructions/*.instructions.md` itself);
- `AGENTS.md` (the rules every agent reads) and its GitHub Copilot mirror `.github/copilot-instructions.md` exist
and are identical from their first `## ` heading on (only the title and introduction differ; Claude Code `@path`
import lines on a line of their own are left out of the comparison, Copilot reads
`.github/instructions/*.instructions.md` itself), and `CLAUDE.md` imports `AGENTS.md` (`@AGENTS.md` on a line of
its own), so Claude Code loads the same rules;
- `.squad/template.json` names the template repository (where lessons about template-managed files are
filed) and, for a repository with several stack profiles, lists them in `profiles` (the first one is
`profile`); then every profile has its `analyzer-check-<profile>.py` and `session-start-<profile>.sh`
Expand Down Expand Up @@ -44,7 +46,9 @@
MODELS = ("haiku", "sonnet", "opus")
EFFORTS = ("low", "medium", "high", "xhigh", "max")
SKILLS_DIR = os.path.join(CLAUDE_DIR, "skills")
INSTRUCTION_FILES = ["CLAUDE.md", os.path.join(GITHUB_DIR, "copilot-instructions.md")]
INSTRUCTION_FILES = ["AGENTS.md", os.path.join(GITHUB_DIR, "copilot-instructions.md")]
CLAUDE_FILE = "CLAUDE.md"
RULES_IMPORT = re.compile(r"^@AGENTS\.md[ \t]*$", re.M)
REQUIRED_FILES = [os.path.join(SQUAD_DIR, "stack.md"), os.path.join(SQUAD_DIR, "project.md"),
os.path.join(SQUAD_DIR, "tools", "squad_settings.py")]
# No quantifier overlaps another one, so matching stays linear (no backtracking).
Expand Down Expand Up @@ -143,6 +147,11 @@ def check_instructions(errors):
reference, mirror = INSTRUCTION_FILES
if instruction_body(mirror) != instruction_body(reference):
errors.append(f"{mirror} differs from {reference} after the first '## ' heading - make the same change in both")
if not os.path.isfile(CLAUDE_FILE):
errors.append(f"{CLAUDE_FILE} is missing (written by adopt-template)")
elif not RULES_IMPORT.search(read_text(CLAUDE_FILE)):
errors.append(f"{CLAUDE_FILE} does not import {reference} ('@{reference}' on a line of its own) - "
"refresh the squad with adopt-template")


def check_template_record(errors):
Expand Down
5 changes: 3 additions & 2 deletions .squad/tools/scope-check.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
included; BASE_REF from `.squad/tools/squad_settings.py`, default origin/main):

- no squad or instruction file is changed: `.squad/` except `stack.md` and `project.md`, `.claude/`,
`CLAUDE.md`, `.github/copilot-instructions.md` (`.squad/routing.md`, *Scope of a product PR*; squad lessons become issues);
`AGENTS.md`, `CLAUDE.md`, `.github/copilot-instructions.md` (`.squad/routing.md`, *Scope of a product PR*; squad
lessons become issues);
- a marked file (`docs/CONTRIBUTING.md`, `docs/ARCHITECTURE.md`, the bug report and pull request templates,
the decision and area index) is changed only inside its `<!-- project:… -->` blocks;
- no changed Markdown file contains a control character (Unicode categories Cc, Cf, Zl, Zp other than tab
Expand Down Expand Up @@ -41,7 +42,7 @@
from analyzer_common import BASE_REF, git, merge_base, settings # noqa: E402 (shared helpers next to this script)

SQUAD_FILES_ALLOWED = {".squad/stack.md", ".squad/project.md"}
INSTRUCTION_FILES = {"CLAUDE.md", ".github/copilot-instructions.md"}
INSTRUCTION_FILES = {"AGENTS.md", "CLAUDE.md", ".github/copilot-instructions.md"}
MARKED = ["docs/CONTRIBUTING.md", "docs/ARCHITECTURE.md", ".github/ISSUE_TEMPLATE/bug_report.md",
".github/pull_request_template.md", "docs/decisions/README.md", "docs/areas/README.md"]
DOCS_TIER = ["README.md", "SECURITY.md", ".squad/stack.md", ".squad/project.md",
Expand Down
Loading
Loading