diff --git a/.claude/agents/squad-dev.md b/.claude/agents/squad-dev.md
index aa8e0c6..42d027a 100644
--- a/.claude/agents/squad-dev.md
+++ b/.claude/agents/squad-dev.md
@@ -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.
diff --git a/.claude/agents/squad-lead.md b/.claude/agents/squad-lead.md
index dea33c2..344a736 100644
--- a/.claude/agents/squad-lead.md
+++ b/.claude/agents/squad-lead.md
@@ -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.
@@ -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
diff --git a/.claude/agents/squad-reviewer.md b/.claude/agents/squad-reviewer.md
index c800bf5..b7cec94 100644
--- a/.claude/agents/squad-reviewer.md
+++ b/.claude/agents/squad-reviewer.md
@@ -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
@@ -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.
@@ -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.
@@ -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
diff --git a/.claude/skills/create-pr/SKILL.md b/.claude/skills/create-pr/SKILL.md
index 1eafcd7..c30a2c8 100644
--- a/.claude/skills/create-pr/SKILL.md
+++ b/.claude/skills/create-pr/SKILL.md
@@ -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,
diff --git a/.claude/skills/squad-issue/SKILL.md b/.claude/skills/squad-issue/SKILL.md
index 0ab29f6..4cdbc42 100644
--- a/.claude/skills/squad-issue/SKILL.md
+++ b/.claude/skills/squad-issue/SKILL.md
@@ -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
@@ -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//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
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 1be12cb..52acc01 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -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
@@ -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
diff --git a/.squad/project.md b/.squad/project.md
index 6bacafe..1048ca5 100644
--- a/.squad/project.md
+++ b/.squad/project.md
@@ -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*
diff --git a/.squad/routing.md b/.squad/routing.md
index 73b0d9a..4ce2ee4 100644
--- a/.squad/routing.md
+++ b/.squad/routing.md
@@ -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.
@@ -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
- `` blocks: `CLAUDE.md`, `docs/CONTRIBUTING.md`, `docs/ARCHITECTURE.md`, `.github/ISSUE_TEMPLATE/bug_report.md`,
+ `` 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
@@ -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] (from #)` 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] (from #)` 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 `` 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
@@ -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
diff --git a/.squad/team.md b/.squad/team.md
index ddf8984..bb34e8a 100644
--- a/.squad/team.md
+++ b/.squad/team.md
@@ -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,
@@ -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 `).
diff --git a/.squad/template.json b/.squad/template.json
index 14c3588..0a5035d 100644
--- a/.squad/template.json
+++ b/.squad/template.json
@@ -1,6 +1,6 @@
{
"repository": "LarsLaskowski/Squad-Spec-Repository-Template",
- "commit": "133edf2a6697efb356bce8dd82c498a347b62a8a",
+ "commit": "daa6b39c0c0c44a9f20154a7eff746673d26cc79",
"profile": "dotnet",
"profiles": [
"dotnet"
diff --git a/.squad/tools/config-check.py b/.squad/tools/config-check.py
index b24b39d..5cbddb8 100644
--- a/.squad/tools/config-check.py
+++ b/.squad/tools/config-check.py
@@ -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-.py` and `session-start-.sh`
@@ -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).
@@ -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):
diff --git a/.squad/tools/scope-check.py b/.squad/tools/scope-check.py
index e2ee0a9..e9844e3 100644
--- a/.squad/tools/scope-check.py
+++ b/.squad/tools/scope-check.py
@@ -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 `` blocks;
- no changed Markdown file contains a control character (Unicode categories Cc, Cf, Zl, Zp other than tab
@@ -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",
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..5bb34de
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,234 @@
+# AGENTS.md
+
+Project guidance for AI coding agents working in this repository. This one file holds the rules for all of
+them: Codex, Kimi Code and GitHub Copilot's coding agent read it directly, Claude Code through the
+`@AGENTS.md` import in [`CLAUDE.md`](/CLAUDE.md), and GitHub Copilot's code review and chat through
+[`.github/copilot-instructions.md`](/.github/copilot-instructions.md), which the template's `adopt-template`
+skill generates from it: everything from the first `##` heading on is identical in both files (Claude Code's
+`@` import lines aside), so a change to it is made in both, and `.squad/tools/config-check.py` fails when they
+differ. This file is a summary; the binding, detailed references are [`ARCHITECTURE.md`](/docs/ARCHITECTURE.md)
+(how the system is put together and why), [`CONTRIBUTING.md`](/docs/CONTRIBUTING.md) (workflow, PR
+conventions, versioning), [`UNIT_TESTS.md`](/docs/UNIT_TESTS.md) (test conventions — **unit tests are
+mandatory for new code**) and [`.squad/stack.md`](/.squad/stack.md) (toolchain and commands). Read them before
+making a non-trivial change; when this file and one of them appear to disagree, treat that as a sync bug to
+fix, not as license to pick either one.
+
+## What this project is
+
+
+DockerUpdateGuard is an ASP.NET Core Razor Components (Blazor Server) web application that tracks what is
+actually running in Docker, compares it with registry metadata, and shows where updates, vulnerabilities and
+shared base-image dependencies need attention. It runs as a Docker container against PostgreSQL.
+
+[`ARCHITECTURE.md`](/docs/ARCHITECTURE.md) is the binding architecture reference: solution layout, composition
+root and startup sequence, configuration model, data layer, integration clients, the background scan engine,
+the UI layer, telemetry, security posture, and the CI/deployment pipeline. Read it before making structural
+changes (new projects, new background jobs, new integration clients, changes to the composition root or entity
+model) and update it in the same change whenever it goes out of date — it must never contain open questions
+or stale claims.
+
+
+## Golden rules
+
+- **Never commit or push to `main`** — no one, not even with approval. Every change goes through a
+ separate branch and a pull request.
+- **Commits and pushes to a feature branch are always allowed** without asking: commit finished work and
+ push it to the current feature branch (creating that branch off `main` if needed), so nothing is lost
+ when a session ends. Force-pushing or otherwise rewriting published history, deleting branches, and
+ creating tags (a `v*` tag may trigger a release) still need explicit user approval.
+- **Pull requests are only opened by the squad or by the user.** The `squad-issue` and `squad-spec`
+ skills open a PR after the Lead's approval (tiers `docs` and `patch`: after a clean review); outside the squad, a PR
+ is opened only when the user explicitly asks for one (e.g. by running the `create-pr` skill). Never open
+ a PR on your own initiative.
+- Run *Format* from [`.squad/stack.md`](/.squad/stack.md) after editing code and before building; CI is
+ not meant to find formatting issues. In the squad skills the member that changed the files runs it on
+ them before handing back (`.squad/team.md`, *Shared rules*).
+- A changed file may not carry **any analyzer diagnostic of any severity**, including info-level ones that
+ never show up as build warnings but that the CI code analysis (e.g. SonarQube Cloud) reports. Check with
+ the *Analyzer gate* from `.squad/stack.md` and fix every finding before considering the work done (in
+ the squad skills, the Code Officer owns this).
+- New or changed production code needs unit tests until the *Coverage gate* in `.squad/stack.md` passes:
+ **at least 80 % line coverage** on new or changed lines and overall (the thresholds live in
+ `.squad/tools/squad_settings.py`, see [`UNIT_TESTS.md`](/docs/UNIT_TESTS.md#code-coverage)).
+
+- Add new packages via **Central Package Management** (`Directory.Packages.props`); do not put version
+ numbers in individual `.csproj` files.
+- Every C# project uses the **Reihitsu.Analyzer** and the **SonarAnalyzer.CSharp** rules, so SonarQube
+ issues surface in the local build, not first in the CI analysis. A build must finish with **zero
+ Reihitsu (`RH####`) warnings and errors**.
+- Wrap every type's members in `#region` blocks **as you write the code** — never leave a type
+ un-regioned and never add the regions only after an analyzer warning.
+
+
+## Commit messages and pull requests
+
+- Commit subject: one summary of **no more than 80 characters**, no trailing period, not in the first
+ person. A body only where the subject does not explain the change; pull requests are squash-merged, so
+ branch commits never reach `main` and may simply name the pipeline step.
+- Pull request title `[area] Description` (areas in `docs/CONTRIBUTING.md`), description of **3–5
+ sentences** on what changed and why: they become the commit on `main`. Title and description are always
+ written in **English**, regardless of the language used in the conversation.
+
+## Commands
+
+
+Run from the repository root, where the solution file lives, in this order: *Restore*, *Format*, *Build*,
+*Test*, *Analyzer gate*, and after *Test with coverage* the *Coverage gate*. Use the commands of those names
+in `.squad/stack.md` as they stand, never a copy from memory: they carry the solution name, the build
+configuration the project tests in, and the formatter's `--force` (`reihitsu-format` asks for confirmation
+for more than 25 files and, without a terminal, formats nothing). The formatter is installed with
+`dotnet tool install -g Reihitsu.Cli`.
+
+
+All commands, with what each one checks, are listed in [`.squad/stack.md`](/.squad/stack.md).
+
+## Architecture
+
+
+- `src/DockerUpdateGuard` — main ASP.NET Core host (`Microsoft.NET.Sdk.Web`); composition root; references the
+ data and telemetry projects. Web startup and dependency wiring stay here.
+- `src/DockerUpdateGuard.Data` — data-access layer; EF Core with PostgreSQL (`Npgsql.EntityFrameworkCore.PostgreSQL`).
+- `src/DockerUpdateGuard.Telemetry` — shared observability layer; OpenTelemetry hosting, OTLP export, ASP.NET
+ Core / HTTP / runtime instrumentation.
+- `src/Tests/DockerUpdateGuard.Tests` — tests for the host/application layer; EF Core InMemory + NSubstitute.
+- `src/Tests/DockerUpdateGuard.Data.Tests` — tests for the data layer; EF Core SQLite.
+
+
+## Project configuration
+
+
+- **Target framework** as set in the project files (see `.squad/stack.md`); **nullable reference types**, **implicit usings**, and
+ **documentation XML** generation are all enabled.
+- **Central Package Management** via `Directory.Packages.props`; never put versions in individual
+ `.csproj` files.
+- **Reihitsu.Analyzer** and **SonarAnalyzer.CSharp** are dev dependencies in every project (via
+ `Directory.Build.props`).
+- **Solution format** is `.slnx` (XML-based) at the repository root.
+
+
+- **Target framework** `net10.0` in the runtime projects; one solution, `DockerUpdateGuard.slnx`, at the
+ repository root.
+- Runtime projects disable generated assembly info and link `SharedAssemblyInfo.cs` from the repository root.
+- Runtime and test projects use per-configuration rulesets from `rules/DockerUpdateGuard.Debug.ruleset` and
+ `rules/DockerUpdateGuard.Release.ruleset`; rules SonarAnalyzer.CSharp disables by default (e.g. `S3776`) are
+ enabled there.
+- SonarCloud rule suppressions are centralized in the shared `src/GlobalSuppressions.cs` (linked into each
+ project), never scattered per file.
+- Tests live under `src/Tests`, not a top-level `tests` folder; keep new test projects there.
+- EF Core migrations follow the SeriesOverwatch pattern: the first migration is `InitialCreate`, later ones
+ `Update1`, `Update2`, …; migration files are renamed to drop the timestamp prefix, while the generated
+ `[Migration("yyyyMMddHHmmss_Name")]` attribute stays unchanged.
+
+
+## Code style
+
+
+File-scoped namespaces; one top-level type per file; `using` outside namespace (System first); Allman
+braces, always required; 4-space indent; `var` preferred; language keywords over BCL types; LINQ method
+syntax only; `== false` instead of `!`; `is null` / `is not null`; no primary constructors; constructor
+injection with `_camelCase` readonly fields; `#region` blocks grouped by member kind (an interface's
+region named after the interface, its description not ending in "implementation"); XML docs on all
+members (English, no ``); `.ConfigureAwait(false)` in library/service code.
+
+
+The detailed C# code-style rules (naming, regions, formatting, XML docs, null handling, suppressed analyzer
+rules) in [`.github/instructions/csharp.instructions.md`](/.github/instructions/csharp.instructions.md) are
+binding; together with *Writing code* in `.squad/stack.md` they describe one set of rules (a conflict between
+them is a sync bug to fix):
+
+@.github/instructions/csharp.instructions.md
+
+- CRLF line endings and no final newline (`.editorconfig`).
+- Tests: MSTest's `Assert` / `CollectionAssert` (no FluentAssertions); **NSubstitute** is the mocking library
+ here, used only where a collaborator crosses an infrastructure boundary; EF Core InMemory / SQLite for data
+ tests (`docs/UNIT_TESTS.md`). Test classes `{TypeUnderTest}Tests`, methods
+ `{TypeUnderTest}{Scenario}{ExpectedResult}`, always with assertion messages.
+
+
+## Testing
+
+
+**Unit tests are mandatory for newly written code.** MSTest with its own `Assert` / `CollectionAssert` (no
+FluentAssertions); test doubles as `.squad/project.md` (*Test doubles*) and `docs/UNIT_TESTS.md` prescribe —
+real objects and hand-written fakes/stubs unless the project names a mocking library. Classes
+`{TypeUnderTest}Tests`, methods `{Class}{Scenario}{ExpectedResult}` in PascalCase **without underscores**;
+always pass an assert message. Timing through an injected `TimeProvider`, never the real clock (the one
+exception, a time bound tested as the ratio of two durations, never an absolute one, is in
+`docs/UNIT_TESTS.md`).
+
+Full conventions, including the project's test doubles and the checklist to run before committing a new
+test, are in [`UNIT_TESTS.md`](/docs/UNIT_TESTS.md).
+
+## Related skills
+
+Project-specific workflow skills live under `.claude/skills/` and run in Claude Code:
+
+- `create-pr` — verify (format, build, tests, analyzer and coverage gates), review the change locally,
+ then open a PR following [`.github/pull_request_template.md`](/.github/pull_request_template.md).
+- `squad-issue` — fix a GitHub issue with the squad: the Lead plans and picks a tier
+ (`docs` / `patch` / `trivial` / `standard` / `security`), the Devil's Advocate challenges `standard`/`security`
+ plans that weigh options once, Security reviews plan and diff of `security` changes, the Tester writes failing tests first,
+ the Dev implements until the *Coverage gate* passes, each member formats the files it changed, the Code
+ Officer clears analyzer diagnostics, the Reviewer reviews the diff, the PR is approved by checklist (the Lead decides what is
+ open), then a PR referencing the issue is opened.
+- `squad-spec` — the same squad pipeline for a new feature, planned as `spec.md`, `plan.md` and
+ `tasks.md` in a working folder under `specs/`.
+- `decision-consolidate` — merge unreleased decision records (Superseded chains, records on one topic) into
+ one record each, delete the obsolete ones, lift behavior that sits in records into the area documents and fix
+ links and index; released records stay untouched.
+- `review-pr` — review an open pull request against this project's stack, analyzer, security and
+ unit-test conventions, and post the findings with an explicit verdict.
+
+Review is defined in `.claude/agents/squad-reviewer.md`, which Claude Code runs as a subagent (read-only,
+pinned to Opus, fresh context). `create-pr` and the squad skills call it *before* pushing, so a change is reviewed while it is
+still local; `review-pr` calls the same agent for a pull request that is already open. The review
+checklist, the integration-surface sweep, the blocking/non-blocking severity model and the "round 1 is a
+full review, later rounds review only the delta" rule live in that one file, so they are identical either
+way.
+
+The squad skills run a multi-role pipeline defined in [`.squad/`](/.squad/team.md) — Lead (plan, decisions,
+PR approval decisions), Devil's Advocate (one plan challenge), Security (plan and diff on the `security` tier), Tester (tests first,
+coverage), Dev, Code Officer (analyzer gate) and Reviewer — as Claude Code subagents under
+`.claude/agents/squad-*.md` (read-only where the role demands it: a hook in each agent denies Git and
+GitHub writes, so only the orchestrating session commits, pushes and posts), with the loop limits and
+escalation rules in [`.squad/routing.md`](/.squad/routing.md). Stack commands live in [`.squad/stack.md`](/.squad/stack.md),
+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/`, `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
+knowledge (`.squad/stack.md`, `.squad/project.md`, a project block) becomes an issue here and is worked in
+a squad-maintenance PR checked with `python3 .squad/tools/config-check.py` (`.squad/routing.md`,
+*Squad lessons*); `python3 .squad/tools/scope-check.py` reports a squad file in a product change. The user
+acts as Product Manager and is only asked when the Lead escalates. Pull requests are merged with *Squash and merge*, so only the
+PR title and description reach `main`.
+
+The reasoning behind code decisions — why something was built the way it was — is recorded by the Lead
+as one decision record per decision in [`docs/decisions/`](/docs/decisions/README.md) (unreleased records are
+edited in place, released ones are append-only and superseded), not in `ARCHITECTURE.md`. What holds today —
+formats, limits, error behavior, guarantees — is written once in the area document of the change in
+[`docs/areas/`](/docs/areas/README.md), which the same pull request updates. Read the relevant records and area
+documents before changing code they cover, and do not contradict an accepted record without changing it
+(unreleased) or superseding it (released).
+
+Two rules these skills enforce that are easy to get wrong:
+
+- **A pull request documents the change, not how it was produced.** The internal review loop — its
+ pass count, its findings, the commits that resolved them — never appears in the PR title, body or
+ commit messages.
+- **A finding posted as a review comment gets worked in that pull request**, blocking or not. It is
+ never deferred to "the next change that touches this code": no such change is scheduled, and the
+ session holding the context to act on it will not exist later. If it really should not be fixed
+ here, reply with the reason or open a linked issue now — then resolve the thread.
+
+## Pull requests, contributing and architecture
+
+Follow [`CONTRIBUTING.md`](/docs/CONTRIBUTING.md) for branch/PR naming (`[area] Description`), the PR
+checklist in [`.github/pull_request_template.md`](/.github/pull_request_template.md), and the
+stability policy. Consult [`ARCHITECTURE.md`](/docs/ARCHITECTURE.md) before changing the behavior it
+describes — the guarantees listed in [`.squad/project.md`](/.squad/project.md) are deliberate, not
+incidental behavior.
diff --git a/CLAUDE.md b/CLAUDE.md
index 0d0c119..3fb3fc8 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,232 +1,7 @@
# CLAUDE.md
-Project guidance for Claude when working in this repository. These rules are mirrored for GitHub Copilot in
-[`.github/copilot-instructions.md`](/.github/copilot-instructions.md): everything from the first `##` heading on
-is identical in both files (Claude Code's `@` import lines aside), so a change to it is made in both, and
-`.squad/tools/config-check.py` fails when they differ. This file is a summary; the
-binding, detailed references are [`ARCHITECTURE.md`](/docs/ARCHITECTURE.md) (how the system is put
-together and why), [`CONTRIBUTING.md`](/docs/CONTRIBUTING.md) (workflow, PR conventions, versioning),
-[`UNIT_TESTS.md`](/docs/UNIT_TESTS.md) (test conventions — **unit tests are mandatory for new code**) and
-[`.squad/stack.md`](/.squad/stack.md) (toolchain and commands). Read them before making a non-trivial
-change; when this file and one of them appear to disagree, treat that as a sync bug to fix, not as
-license to pick either one.
+Claude Code reads this file; the project's rules live in [`AGENTS.md`](/AGENTS.md), the one instruction file
+every AI coding agent of this repository shares, and are imported here in full. Change them there, never here:
+this file is written by the template's `adopt-template` skill and overwritten on every refresh.
-## What this project is
-
-
-DockerUpdateGuard is an ASP.NET Core Razor Components (Blazor Server) web application that tracks what is
-actually running in Docker, compares it with registry metadata, and shows where updates, vulnerabilities and
-shared base-image dependencies need attention. It runs as a Docker container against PostgreSQL.
-
-[`ARCHITECTURE.md`](/docs/ARCHITECTURE.md) is the binding architecture reference: solution layout, composition
-root and startup sequence, configuration model, data layer, integration clients, the background scan engine,
-the UI layer, telemetry, security posture, and the CI/deployment pipeline. Read it before making structural
-changes (new projects, new background jobs, new integration clients, changes to the composition root or entity
-model) and update it in the same change whenever it goes out of date — it must never contain open questions
-or stale claims.
-
-
-## Golden rules
-
-- **Never commit or push to `main`** — no one, not even with approval. Every change goes through a
- separate branch and a pull request.
-- **Commits and pushes to a feature branch are always allowed** without asking: commit finished work and
- push it to the current feature branch (creating that branch off `main` if needed), so nothing is lost
- when a session ends. Force-pushing or otherwise rewriting published history, deleting branches, and
- creating tags (a `v*` tag may trigger a release) still need explicit user approval.
-- **Pull requests are only opened by the squad or by the user.** The `squad-issue` and `squad-spec`
- skills open a PR after the Lead's approval (tiers `docs` and `patch`: after a clean review); outside the squad, a PR
- is opened only when the user explicitly asks for one (e.g. by running the `create-pr` skill). Never open
- a PR on your own initiative.
-- Run *Format* from [`.squad/stack.md`](/.squad/stack.md) after editing code and before building; CI is
- not meant to find formatting issues. In the squad skills the member that changed the files runs it on
- them before handing back (`.squad/team.md`, *Shared rules*).
-- A changed file may not carry **any analyzer diagnostic of any severity**, including info-level ones that
- never show up as build warnings but that the CI code analysis (e.g. SonarQube Cloud) reports. Check with
- the *Analyzer gate* from `.squad/stack.md` and fix every finding before considering the work done (in
- the squad skills, the Code Officer owns this).
-- New or changed production code needs unit tests until the *Coverage gate* in `.squad/stack.md` passes:
- **at least 80 % line coverage** on new or changed lines and overall (the thresholds live in
- `.squad/tools/squad_settings.py`, see [`UNIT_TESTS.md`](/docs/UNIT_TESTS.md#code-coverage)).
-
-- Add new packages via **Central Package Management** (`Directory.Packages.props`); do not put version
- numbers in individual `.csproj` files.
-- Every C# project uses the **Reihitsu.Analyzer** and the **SonarAnalyzer.CSharp** rules, so SonarQube
- issues surface in the local build, not first in the CI analysis. A build must finish with **zero
- Reihitsu (`RH####`) warnings and errors**.
-- Wrap every type's members in `#region` blocks **as you write the code** — never leave a type
- un-regioned and never add the regions only after an analyzer warning.
-
-
-## Commit messages and pull requests
-
-- Commit subject: one summary of **no more than 80 characters**, no trailing period, not in the first
- person. A body only where the subject does not explain the change; pull requests are squash-merged, so
- branch commits never reach `main` and may simply name the pipeline step.
-- Pull request title `[area] Description` (areas in `docs/CONTRIBUTING.md`), description of **3–5
- sentences** on what changed and why: they become the commit on `main`. Title and description are always
- written in **English**, regardless of the language used in the conversation.
-
-## Commands
-
-
-Run from the repository root, where the solution file lives, in this order: *Restore*, *Format*, *Build*,
-*Test*, *Analyzer gate*, and after *Test with coverage* the *Coverage gate*. Use the commands of those names
-in `.squad/stack.md` as they stand, never a copy from memory: they carry the solution name, the build
-configuration the project tests in, and the formatter's `--force` (`reihitsu-format` asks for confirmation
-for more than 25 files and, without a terminal, formats nothing). The formatter is installed with
-`dotnet tool install -g Reihitsu.Cli`.
-
-
-All commands, with what each one checks, are listed in [`.squad/stack.md`](/.squad/stack.md).
-
-## Architecture
-
-
-- `src/DockerUpdateGuard` — main ASP.NET Core host (`Microsoft.NET.Sdk.Web`); composition root; references the
- data and telemetry projects. Web startup and dependency wiring stay here.
-- `src/DockerUpdateGuard.Data` — data-access layer; EF Core with PostgreSQL (`Npgsql.EntityFrameworkCore.PostgreSQL`).
-- `src/DockerUpdateGuard.Telemetry` — shared observability layer; OpenTelemetry hosting, OTLP export, ASP.NET
- Core / HTTP / runtime instrumentation.
-- `src/Tests/DockerUpdateGuard.Tests` — tests for the host/application layer; EF Core InMemory + NSubstitute.
-- `src/Tests/DockerUpdateGuard.Data.Tests` — tests for the data layer; EF Core SQLite.
-
-
-## Project configuration
-
-
-- **Target framework** as set in the project files (see `.squad/stack.md`); **nullable reference types**, **implicit usings**, and
- **documentation XML** generation are all enabled.
-- **Central Package Management** via `Directory.Packages.props`; never put versions in individual
- `.csproj` files.
-- **Reihitsu.Analyzer** and **SonarAnalyzer.CSharp** are dev dependencies in every project (via
- `Directory.Build.props`).
-- **Solution format** is `.slnx` (XML-based) at the repository root.
-
-
-- **Target framework** `net10.0` in the runtime projects; one solution, `DockerUpdateGuard.slnx`, at the
- repository root.
-- Runtime projects disable generated assembly info and link `SharedAssemblyInfo.cs` from the repository root.
-- Runtime and test projects use per-configuration rulesets from `rules/DockerUpdateGuard.Debug.ruleset` and
- `rules/DockerUpdateGuard.Release.ruleset`; rules SonarAnalyzer.CSharp disables by default (e.g. `S3776`) are
- enabled there.
-- SonarCloud rule suppressions are centralized in the shared `src/GlobalSuppressions.cs` (linked into each
- project), never scattered per file.
-- Tests live under `src/Tests`, not a top-level `tests` folder; keep new test projects there.
-- EF Core migrations follow the SeriesOverwatch pattern: the first migration is `InitialCreate`, later ones
- `Update1`, `Update2`, …; migration files are renamed to drop the timestamp prefix, while the generated
- `[Migration("yyyyMMddHHmmss_Name")]` attribute stays unchanged.
-
-
-## Code style
-
-
-File-scoped namespaces; one top-level type per file; `using` outside namespace (System first); Allman
-braces, always required; 4-space indent; `var` preferred; language keywords over BCL types; LINQ method
-syntax only; `== false` instead of `!`; `is null` / `is not null`; no primary constructors; constructor
-injection with `_camelCase` readonly fields; `#region` blocks grouped by member kind (an interface's
-region named after the interface, its description not ending in "implementation"); XML docs on all
-members (English, no ``); `.ConfigureAwait(false)` in library/service code.
-
-
-The detailed C# code-style rules (naming, regions, formatting, XML docs, null handling, suppressed analyzer
-rules) in [`.github/instructions/csharp.instructions.md`](/.github/instructions/csharp.instructions.md) are
-binding; together with *Writing code* in `.squad/stack.md` they describe one set of rules (a conflict between
-them is a sync bug to fix):
-
-@.github/instructions/csharp.instructions.md
-
-- CRLF line endings and no final newline (`.editorconfig`).
-- Tests: MSTest's `Assert` / `CollectionAssert` (no FluentAssertions); **NSubstitute** is the mocking library
- here, used only where a collaborator crosses an infrastructure boundary; EF Core InMemory / SQLite for data
- tests (`docs/UNIT_TESTS.md`). Test classes `{TypeUnderTest}Tests`, methods
- `{TypeUnderTest}{Scenario}{ExpectedResult}`, always with assertion messages.
-
-
-## Testing
-
-
-**Unit tests are mandatory for newly written code.** MSTest with its own `Assert` / `CollectionAssert` (no
-FluentAssertions); test doubles as `.squad/project.md` (*Test doubles*) and `docs/UNIT_TESTS.md` prescribe —
-real objects and hand-written fakes/stubs unless the project names a mocking library. Classes
-`{TypeUnderTest}Tests`, methods `{Class}{Scenario}{ExpectedResult}` in PascalCase **without underscores**;
-always pass an assert message. Timing through an injected `TimeProvider`, never the real clock (the one
-exception, a time bound tested as the ratio of two durations, never an absolute one, is in
-`docs/UNIT_TESTS.md`).
-
-Full conventions, including the project's test doubles and the checklist to run before committing a new
-test, are in [`UNIT_TESTS.md`](/docs/UNIT_TESTS.md).
-
-## Related skills
-
-Project-specific workflow skills live under `.claude/skills/` and run in Claude Code:
-
-- `create-pr` — verify (format, build, tests, analyzer and coverage gates), review the change locally,
- then open a PR following [`.github/pull_request_template.md`](/.github/pull_request_template.md).
-- `squad-issue` — fix a GitHub issue with the squad: the Lead plans and picks a tier
- (`docs` / `patch` / `trivial` / `standard` / `security`), the Devil's Advocate challenges `standard`/`security`
- plans that weigh options once, Security reviews plan and diff of `security` changes, the Tester writes failing tests first,
- the Dev implements until the *Coverage gate* passes, each member formats the files it changed, the Code
- Officer clears analyzer diagnostics, the Reviewer reviews the diff, the PR is approved by checklist (the Lead decides what is
- open), then a PR referencing the issue is opened.
-- `squad-spec` — the same squad pipeline for a new feature, planned as `spec.md`, `plan.md` and
- `tasks.md` in a working folder under `specs/`.
-- `decision-consolidate` — merge unreleased decision records (Superseded chains, records on one topic) into
- one record each, delete the obsolete ones, lift behavior that sits in records into the area documents and fix
- links and index; released records stay untouched.
-- `review-pr` — review an open pull request against this project's stack, analyzer, security and
- unit-test conventions, and post the findings with an explicit verdict.
-
-Review is defined in `.claude/agents/squad-reviewer.md`, which Claude Code runs as a subagent (read-only,
-pinned to Opus, fresh context). `create-pr` and the squad skills call it *before* pushing, so a change is reviewed while it is
-still local; `review-pr` calls the same agent for a pull request that is already open. The review
-checklist, the integration-surface sweep, the blocking/non-blocking severity model and the "round 1 is a
-full review, later rounds review only the delta" rule live in that one file, so they are identical either
-way.
-
-The squad skills run a multi-role pipeline defined in [`.squad/`](/.squad/team.md) — Lead (plan, decisions,
-PR approval decisions), Devil's Advocate (one plan challenge), Security (plan and diff on the `security` tier), Tester (tests first,
-coverage), Dev, Code Officer (analyzer gate) and Reviewer — as Claude Code subagents under
-`.claude/agents/squad-*.md` (read-only where the role demands it: a hook in each agent denies Git and
-GitHub writes, so only the orchestrating session commits, pushes and posts), with the loop limits and
-escalation rules in [`.squad/routing.md`](/.squad/routing.md). Stack commands live in [`.squad/stack.md`](/.squad/stack.md),
-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
-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
-knowledge (`.squad/stack.md`, `.squad/project.md`, a project block) becomes an issue here and is worked in
-a squad-maintenance PR checked with `python3 .squad/tools/config-check.py` (`.squad/routing.md`,
-*Squad lessons*); `python3 .squad/tools/scope-check.py` reports a squad file in a product change. The user
-acts as Product Manager and is only asked when the Lead escalates. Pull requests are merged with *Squash and merge*, so only the
-PR title and description reach `main`.
-
-The reasoning behind code decisions — why something was built the way it was — is recorded by the Lead
-as one decision record per decision in [`docs/decisions/`](/docs/decisions/README.md) (unreleased records are
-edited in place, released ones are append-only and superseded), not in `ARCHITECTURE.md`. What holds today —
-formats, limits, error behavior, guarantees — is written once in the area document of the change in
-[`docs/areas/`](/docs/areas/README.md), which the same pull request updates. Read the relevant records and area
-documents before changing code they cover, and do not contradict an accepted record without changing it
-(unreleased) or superseding it (released).
-
-Two rules these skills enforce that are easy to get wrong:
-
-- **A pull request documents the change, not how it was produced.** The internal review loop — its
- pass count, its findings, the commits that resolved them — never appears in the PR title, body or
- commit messages.
-- **A finding posted as a review comment gets worked in that pull request**, blocking or not. It is
- never deferred to "the next change that touches this code": no such change is scheduled, and the
- session holding the context to act on it will not exist later. If it really should not be fixed
- here, reply with the reason or open a linked issue now — then resolve the thread.
-
-## Pull requests, contributing and architecture
-
-Follow [`CONTRIBUTING.md`](/docs/CONTRIBUTING.md) for branch/PR naming (`[area] Description`), the PR
-checklist in [`.github/pull_request_template.md`](/.github/pull_request_template.md), and the
-stability policy. Consult [`ARCHITECTURE.md`](/docs/ARCHITECTURE.md) before changing the behavior it
-describes — the guarantees listed in [`.squad/project.md`](/.squad/project.md) are deliberate, not
-incidental behavior.
+@AGENTS.md
diff --git a/DockerUpdateGuard.slnx b/DockerUpdateGuard.slnx
index f1fadce..034aedd 100644
--- a/DockerUpdateGuard.slnx
+++ b/DockerUpdateGuard.slnx
@@ -12,6 +12,7 @@
+
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index c75b43d..f33703a 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -6,7 +6,7 @@ implemented. It is a technical reference for contributors and AI coding
agents working in this repository; it complements, and does not repeat,
[README.md](../README.md) (product scope, configuration reference), the
[docs/](.) folder (contribution, testing, deployment tiers), and
-[CLAUDE.md](../CLAUDE.md) /
+[AGENTS.md](../AGENTS.md) /
[.github/copilot-instructions.md](../.github/copilot-instructions.md) and
[.github/instructions/csharp.instructions.md](../.github/instructions/csharp.instructions.md)
(coding conventions).
@@ -67,7 +67,7 @@ observability stays in `.Telemetry`; the host project owns composition.
Solution-wide conventions (`.slnx` format, `net10.0`, nullable/implicit
usings, `SharedAssemblyInfo.cs`, per-configuration rulesets, centralized
`GlobalSuppressions.cs`, `Reihitsu.Analyzer` + `SonarAnalyzer.CSharp`) are
-documented in [CLAUDE.md](../CLAUDE.md) and not repeated here.
+documented in [AGENTS.md](../AGENTS.md) and not repeated here.
## 3. Host composition and startup sequence
@@ -208,7 +208,7 @@ read/write intent, not by entity:
Current migrations, in order: `InitialCreate` → `Update1` → … → `Update7`
(latest). New migrations follow the `Update{N}` naming convention described
-in [CLAUDE.md](../CLAUDE.md#project-configuration); `Design\
+in [AGENTS.md](../AGENTS.md#project-configuration); `Design\
DockerUpdateGuardDbContextFactory` provides the design-time `DbContext` for
`dotnet ef` tooling.
@@ -530,9 +530,9 @@ Summarized here for quick reference; details are in the sections above.
## Development process
-This repository is developed with Claude Code: `CLAUDE.md` holds the rules (mirrored for GitHub Copilot in
-`.github/copilot-instructions.md`), the skills live under `.claude/skills/` and the squad roles under
-`.claude/agents/`. Every pull request is reviewed before it is opened by the read-only reviewer in `.claude/agents/squad-reviewer.md`
+This repository is developed with Claude Code: `AGENTS.md` holds the rules every AI coding agent reads
+(imported by `CLAUDE.md`, mirrored for GitHub Copilot in `.github/copilot-instructions.md`), the skills
+live under `.claude/skills/` and the squad roles under `.claude/agents/`. Every pull request is reviewed before it is opened by the read-only reviewer in `.claude/agents/squad-reviewer.md`
— round 1 is a full review, every later round looks only at the delta, and only blocking findings earn
another round, because a fresh full re-review of unchanged code always finds something new.
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 4e064da..cfc3275 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -86,7 +86,7 @@ Follow the PR template in [`.github/pull_request_template.md`](../.github/pull_r
## Quality gates
-Code-style rules are documented in [`CLAUDE.md`](../CLAUDE.md) and in
+Code-style rules are documented in [`AGENTS.md`](../AGENTS.md) and in
[`.squad/stack.md`](../.squad/stack.md), and are binding for all contributions. Before opening a pull
request, run the commands from `stack.md`: *Format*, *Build*, the *Analyzer gate* (no analyzer diagnostic
of any severity in a changed file) and the *Coverage gate* (line coverage on new or changed production code
diff --git a/docs/UNIT_TESTS.md b/docs/UNIT_TESTS.md
index f97e8c8..49c3560 100644
--- a/docs/UNIT_TESTS.md
+++ b/docs/UNIT_TESTS.md
@@ -94,7 +94,8 @@ public async Task VulnerabilityEnrichmentServiceRefreshAsyncProviderExceptionMar
```
Test class names follow `{TypeUnderTest}Tests` (or `{TypeUnderTest}RenderTests`
-/ `{TypeUnderTest}PersistentStateTests` when split, per `CLAUDE.md`).
+/ `{TypeUnderTest}PersistentStateTests` when split, as described under the
+test project layout above).
## Arranging your tests
@@ -121,7 +122,7 @@ public void ImageReferenceParserParseWrappedMicrosoftRegistryReferenceNormalizes
Every `Assert.*` call must include a message explaining what the assertion
guarantees — not what it checks mechanically, but why it matters. This is a
-binding project rule (see `CLAUDE.md`), not a suggestion:
+binding project rule (see `AGENTS.md`), not a suggestion:
```csharp
Assert.AreEqual(UpdateEvaluationStatus.UpdateAvailable,
@@ -237,7 +238,7 @@ using (var database = new SqliteTestDatabase())
```
- Migration tests (`Update{N}MigrationTests.cs`) follow the migration naming
- rules from `CLAUDE.md` (`InitialCreate`, `Update1`, `Update2`, ...).
+ rules from `AGENTS.md` (`InitialCreate`, `Update1`, `Update2`, ...).
## Testing Blazor components