Skip to content
12 changes: 6 additions & 6 deletions .agents/skills/comment-and-doc-style/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ hub-hosted tool the reader runs, are in `references/carried-doc-references.md`.

## PR titles and commit messages

- **Format**: an imperative subject, 72 characters or fewer, no trailing period ("Add 24-hour
PM2.5 average sensor", not "Added X" or "Adds X"). An optional body, blank-line separated,
- **Format**: an imperative subject, 72 characters or fewer, no trailing period ("Add 24-Hour
PM2.5 Average Sensor", not "Added X" or "Adds X"). An optional body, blank-line separated,
explains *why* the change is being made when that is non-obvious, the diff already shows *what*.
- **Rules**: no vague titles (`update stuff`, `wip`). Dependabot's default `Bump X from Y to Z`
titles are fine as-is. No `Co-Authored-By:` lines unless the developer explicitly asks. No
Expand All @@ -237,11 +237,11 @@ hub-hosted tool the reader runs, are in `references/carried-doc-references.md`.
*EPA-Corrected*, *24-Hour*).

```text
Add structured logging extensions to library
Pin softprops/action-gh-release to commit SHA
Drop net8.0 multi-targeting from console project
Add Structured Logging Extensions to Library
Pin softprops/action-gh-release to Commit SHA
Drop net8.0 Multi-Targeting from Console Project
Bump xunit.v3 from 3.2.2 to 3.3.0
Clarify devcontainer setup steps in README
Clarify devcontainer Setup Steps in README
```

## Quantitative claims
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ tool-owned format outside `.bat`/`.cmd`, or a byte-preserve data directory whose
consumer may depend on), still pair a `.gitattributes` pin with a matching `.editorconfig`
override, since the git pin alone is not enough there, `.gitattributes` governs git while the
editor follows `.editorconfig`. For a byte-preserve directory, disable all editor normalization,
not just EOL: `[<dir>/*]` with `charset = unset`, `end_of_line = unset`, `insert_final_newline =
not just EOL: `[<dir>/**]` with `charset = unset`, `end_of_line = unset`, `insert_final_newline =
false`, `trim_trailing_whitespace = false` (`unset` is EditorConfig's spec-defined special value
that removes an inherited property).
that removes an inherited property, and `**` is needed rather than `*` so a nested file under the
directory is covered too, since `*` excludes `/` and only matches one path component).

## Editing discipline

Expand Down
12 changes: 11 additions & 1 deletion .agents/skills/dotnet-codestyle/references/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,15 @@ parameters, return values, exceptions, and crefs.
/// <exception cref="System.ArgumentException">
/// Thrown when <paramref name="category"/> is not a supported value.
/// </exception>
public async Task<string> GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken) {}
public async Task<string> GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken)
{
if (category is not ("motivational" or "humor"))
{
throw new ArgumentException($"Unsupported category: {category}", nameof(category));
}

cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(1, cancellationToken);
return $"Quote for {category}";
}
```
4 changes: 4 additions & 0 deletions .agents/skills/dotnet-codestyle/references/project-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@
<InternalsVisibleTo Include="YourTestProject" />
</ItemGroup>
```

5. **Nullable and XML documentation**: `<Nullable>enable</Nullable>`,
`<GenerateDocumentationFile>true</GenerateDocumentationFile>` (see `references/conventions.md`
for the XML documentation format every public surface needs).
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Two traps, both learned the hard way:
`git checkout -b promote/develop-to-main origin/main && git merge origin/develop`, take
`develop`'s side for the EOL-conflicted files (`git checkout --theirs <file>`) **after
confirming each is content-identical modulo EOL, or that `develop` is a strict superset**
(`diff <(git show :2:f | tr -d '\r') <(git show :3:f | tr -d '\r')`), then open that branch into
(`diff <(git show ":2:<file>" | tr -d '\r') <(git show ":3:<file>" | tr -d '\r')`), then open that branch into
`main`. Verify no genuine `main`-only content is dropped (build/test where the repo supports it).

## Why both rulesets omit "Require branches to be up to date before merging"
Expand Down
45 changes: 27 additions & 18 deletions .agents/skills/python-codestyle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ declaration, versioning, VS Code config), see `references/profiles.md`.
| [ruff][ruff-link] | lint + format + import sort | `pyproject.toml` `[tool.ruff]` |
| [pyright][pyright-link] | type checker (the default, a strict baseline) | `pyproject.toml` `[tool.pyright]` |
| [mypy][mypy-link] | additional/alternate type checker (optional, the CI checker in a mypy-in-CI repo, required for Home Assistant) | `pyproject.toml` `[tool.mypy]` (or per home-assistant/core) |
| [pytest][docs-link] | test runner | `pyproject.toml` `[tool.pytest.ini_options]` |
| [pytest][docs-link] | test runner (build profile only, lint-only uses `unittest`) | `pyproject.toml` `[tool.pytest.ini_options]` |

**Type checking targets strongly typed, deterministic code.** pyright in strict mode is the
default baseline on first-party code (a repo may instead run mypy in CI and keep pyright
Expand All @@ -72,7 +72,9 @@ inherently consistent.

## Local development loop

From inside the Python project directory:
From inside a **build**-profile Python project directory. A **lint-only** Scripts profile has no
`uv.lock` to sync and no pytest to run, substitute `uvx` per tool and `unittest` per the Two
Profiles section above:

```sh
uv sync # creates .venv, installs deps + dev group
Expand All @@ -85,15 +87,18 @@ uv run pytest # run tests
uv build # produce wheel + sdist in ./dist (published packages only)
```

The Python clean-compile is `uv run ruff format` + `uv run ruff check` + the repo's type checker:
`uv run pyright`, or `uv run mypy src` where mypy is the CI checker, or both where the repo runs
both (see Type checking above). Run it, plus `uv run pytest`, before committing. These are
documented commands, and an optional VS Code tasks mirror (all `type: process`, no `&&` shell
chaining, so it runs the same on any task shell) is in the hub `vscode-tasks-python.json` snippet.
CI runs the same clean-compile commands as the authoritative backstop. A working local hook is
strongly suggested, not opt-in: wire the Python `pre-commit` framework from the canonical
`catalog/snippets/pre-commit/.pre-commit-config.yaml`. See GOVERNANCE.md "Running the Linters
Locally" for what the hook must cover and what its absence means.
The **build**-profile Python clean-compile is `uv run ruff format` + `uv run ruff check` + the
repo's type checker: `uv run pyright`, or `uv run mypy src` where mypy is the CI checker, or both
where the repo runs both (see Type checking above). Run it, plus `uv run pytest`, before
committing. A **lint-only** profile's clean-compile substitutes its `uvx` and `unittest`
equivalents, per Two Profiles above, and has no such command to run before committing beyond
those. These are documented commands, and an optional VS Code tasks mirror (all `type: process`,
no `&&` shell chaining, so it runs the same on any task shell) is in the hub
`vscode-tasks-python.json` snippet. CI runs the same clean-compile commands as the authoritative
backstop. A working local hook is strongly suggested, not opt-in: wire the Python `pre-commit`
framework from the canonical `catalog/snippets/pre-commit/.pre-commit-config.yaml`. See
GOVERNANCE.md "Running the Linters Locally" for what the hook must cover and what its absence
means.

A restricted executor gives each task a cache directory under a writable temporary root. Point
`UV_CACHE_DIR`, `RUFF_CACHE_DIR`, `MYPY_CACHE_DIR`, and `COVERAGE_FILE` into that directory before
Expand Down Expand Up @@ -142,9 +147,12 @@ For comments, docstrings, full type-hint rules, naming, imports, and all pattern

## Tests

`uv run pytest`. One test file per module (`test_<module>.py`), fixtures over setup/teardown,
fakes over mocks. Test the docstring's contract, not implementation details. See
`references/testing.md` for the full conventions.
`uv run pytest` for a build profile, `unittest` for a lint-only Scripts profile (see Two Profiles
above). One test file per module (`test_<module>.py`). A build profile prefers fixtures over
`unittest`'s `setUp`/`tearDown` lifecycle hooks. A lint-only profile uses those hooks directly,
since `unittest` has no fixture-injection mechanism of its own. Fakes over mocks either way. Test
the docstring's contract, not implementation details. See `references/testing.md` for the full
build-profile conventions, and `references/profiles.md` for the lint-only `unittest` conventions.

## Versioning

Expand All @@ -159,10 +167,11 @@ Before pushing or opening a PR:
- VS Code's Problems pane should be quiet for the files you touched. The relevant linters are ruff
(via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's
bundled Pylance).
- The CI gate is `uv run ruff check`, `uv run ruff format --check`, the repo's type checker
(`uv run pyright` or `uv run mypy src`), and `uv run pytest`, the same commands as the local
loop above, run from the Python project directory (invoked as separate steps, not `&&`-chained,
so the runner shell is irrelevant).
- The **build**-profile CI gate is `uv run ruff check`, `uv run ruff format --check`, the repo's
type checker (`uv run pyright` or `uv run mypy src`), and `uv run pytest`, the same commands as
the local loop above, run from the Python project directory (invoked as separate steps, not
`&&`-chained, so the runner shell is irrelevant). A **lint-only** profile's CI gate is its `uvx`
equivalents plus its `unittest` suite, per `references/profiles.md`.
- Markdown in this directory follows CODESTYLE.md's repo-wide Markdown and Spelling rules,
packaged as the `comment-and-doc-style` Skill.

Expand Down
4 changes: 4 additions & 0 deletions .agents/skills/python-codestyle/references/testing.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Python Testing Conventions

This covers the **build** profile. A **lint-only** Scripts profile has no `uv.lock` and does not
use pytest, its testing conventions (`unittest`, `uvx coverage@latest run -m unittest discover`)
are in `references/profiles.md`.

Use `pytest` with configuration in `[tool.pytest.ini_options]`. Default invocation:
`uv run pytest`.

Expand Down
8 changes: 5 additions & 3 deletions .agents/skills/resync-a-repo/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ Preserve the evidence RESYNC.md section 2 requires, and do not leave the finding
4. **Interface workflows.** Honor the named contract, required jobs, the ruleset-bound check name,
the artifact-name handoff, rather than copying bytes.
5. **Settings, rulesets, and secrets.** Run
`repo-config/configure.sh check <owner>/<repo> release|operational` from the hub at `main`,
then `apply` for what it reports, never from a carried copy.
`repo-config/configure.sh check "<owner>/<repo>" release` (substitute `operational` for an
operational repo) from the hub at `main`, then `apply` for what it reports, never from a
carried copy.
6. **Intent files last, and by hand,** since nothing mechanical judges these.

Reconcile the registry entry (`status`, `types`, `releaseTrigger`, `workflowModel`,
Expand All @@ -81,4 +82,5 @@ One focused pull request per drift class, branched from the target's `develop`,
push to a protected branch and never a hand edit outside a pull request. Close the review loop,
per the `pr-review-conduct` skill, before asking the maintainer for merge permission. The
maintainer merges, the agent drives to green and stops. Re-run the audit after the merge and
commit the report, done means measured, not applied.
commit the report once authorized, per `git-commit-conventions`, done means measured, not
applied.
2 changes: 1 addition & 1 deletion .agents/skills/skill-lifecycle/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ A skill surfaces at a trigger moment. A rule that binds every action all the tim
3. **Author the body per the `comment-and-doc-style` skill**: LF (the repo default), present tense, ASCII tiers, no semicolon in prose. Name hub paths as plain code spans rather than repo-relative links, because an installed copy resolves no repo path, and say "from a hub checkout" for anything the reader must run.
4. **Split bulk into `references/`** when the source doc is large: the SKILL.md carries the summary and the binding rules, and each `references/*.md` carries one topic read on demand, the shape `comment-and-doc-style` uses.
5. **Apply the doc-packaging pattern below in the same change** when the skill packages a law doc or one of its sections.
6. **Regenerate and commit all trees together**: `python3 scripts/build_dist.py`, then commit the source and both generated trees in one commit. CI runs `--check` on every pull request and fails a desynced distribution. `python3 scripts/tests/test_build_dist.py` covers the generator itself.
6. **Regenerate and commit all trees together**: `python3 scripts/build_dist.py`, then, once authorized, commit the source and both generated trees in one commit, per `git-commit-conventions`. CI runs `--check` on every pull request and fails a desynced distribution. `python3 scripts/tests/test_build_dist.py` covers the generator itself.
7. **Record the surfacing**: annotate the `AGENTS.md` "Where the Rules Live" row when the skill packages a GOVERNANCE section, or its closing paragraph when the skill is new content, so the map stays the one place coverage is read from.
8. **Refresh the machines after merge**: re-run `python3 scripts/skills_install.py` per machine, the cadence `docs/host-setup.md` "Fleet Skills Install" states. Until then every machine serves the previous skill set, which `--report` says.

Expand Down
9 changes: 6 additions & 3 deletions .agents/skills/standup-a-repo/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@ maintainer can supply what section 0A lists.
inventing a shape.

8. **Settings, rulesets, and secrets.** STANDUP.md section 4: confirm the remote and the GitHub
repository agree before running anything else here, then apply with
`repo-config/configure.sh apply owner/repo release|operational` from the hub at `main` and check with the same
command's `check` subcommand, never from a hand-built or carried copy.
repository agree before running anything else here, then run
`repo-config/configure.sh check owner/repo release` (substitute `operational` for an
operational repo) from the hub at `main`. A non-zero exit there means drift was found, not a
command failure. Review what it reports. Then run the same command's `apply` subcommand, which
idempotently reconciles the repo to the full committed configuration regardless of what `check`
reported, never from a hand-built or carried copy.

9. **Verify with the audit.** STANDUP.md section 5: run `AUDIT.md` end to end. The repo is stood
up only when it passes for its type, or its residual deltas are tracked in
Expand Down
2 changes: 1 addition & 1 deletion .claude-plugin/fleet-skills/.source-digest
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b945e66c274cb82a
5ab0e6a26d537def
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,8 @@ hub-hosted tool the reader runs, are in `references/carried-doc-references.md`.

## PR titles and commit messages

- **Format**: an imperative subject, 72 characters or fewer, no trailing period ("Add 24-hour
PM2.5 average sensor", not "Added X" or "Adds X"). An optional body, blank-line separated,
- **Format**: an imperative subject, 72 characters or fewer, no trailing period ("Add 24-Hour
PM2.5 Average Sensor", not "Added X" or "Adds X"). An optional body, blank-line separated,
explains *why* the change is being made when that is non-obvious, the diff already shows *what*.
- **Rules**: no vague titles (`update stuff`, `wip`). Dependabot's default `Bump X from Y to Z`
titles are fine as-is. No `Co-Authored-By:` lines unless the developer explicitly asks. No
Expand All @@ -237,11 +237,11 @@ hub-hosted tool the reader runs, are in `references/carried-doc-references.md`.
*EPA-Corrected*, *24-Hour*).

```text
Add structured logging extensions to library
Pin softprops/action-gh-release to commit SHA
Drop net8.0 multi-targeting from console project
Add Structured Logging Extensions to Library
Pin softprops/action-gh-release to Commit SHA
Drop net8.0 Multi-Targeting from Console Project
Bump xunit.v3 from 3.2.2 to 3.3.0
Clarify devcontainer setup steps in README
Clarify devcontainer Setup Steps in README
```

## Quantitative claims
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ tool-owned format outside `.bat`/`.cmd`, or a byte-preserve data directory whose
consumer may depend on), still pair a `.gitattributes` pin with a matching `.editorconfig`
override, since the git pin alone is not enough there, `.gitattributes` governs git while the
editor follows `.editorconfig`. For a byte-preserve directory, disable all editor normalization,
not just EOL: `[<dir>/*]` with `charset = unset`, `end_of_line = unset`, `insert_final_newline =
not just EOL: `[<dir>/**]` with `charset = unset`, `end_of_line = unset`, `insert_final_newline =
false`, `trim_trailing_whitespace = false` (`unset` is EditorConfig's spec-defined special value
that removes an inherited property).
that removes an inherited property, and `**` is needed rather than `*` so a nested file under the
directory is covered too, since `*` excludes `/` and only matches one path component).

## Editing discipline

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,15 @@ parameters, return values, exceptions, and crefs.
/// <exception cref="System.ArgumentException">
/// Thrown when <paramref name="category"/> is not a supported value.
/// </exception>
public async Task<string> GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken) {}
public async Task<string> GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken)
{
if (category is not ("motivational" or "humor"))
{
throw new ArgumentException($"Unsupported category: {category}", nameof(category));
}

cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(1, cancellationToken);
return $"Quote for {category}";
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@
<InternalsVisibleTo Include="YourTestProject" />
</ItemGroup>
```

5. **Nullable and XML documentation**: `<Nullable>enable</Nullable>`,
`<GenerateDocumentationFile>true</GenerateDocumentationFile>` (see `references/conventions.md`
for the XML documentation format every public surface needs).
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Two traps, both learned the hard way:
`git checkout -b promote/develop-to-main origin/main && git merge origin/develop`, take
`develop`'s side for the EOL-conflicted files (`git checkout --theirs <file>`) **after
confirming each is content-identical modulo EOL, or that `develop` is a strict superset**
(`diff <(git show :2:f | tr -d '\r') <(git show :3:f | tr -d '\r')`), then open that branch into
(`diff <(git show ":2:<file>" | tr -d '\r') <(git show ":3:<file>" | tr -d '\r')`), then open that branch into
`main`. Verify no genuine `main`-only content is dropped (build/test where the repo supports it).

## Why both rulesets omit "Require branches to be up to date before merging"
Expand Down
Loading