diff --git a/.agents/skills/dotnet-codestyle/SKILL.md b/.agents/skills/dotnet-codestyle/SKILL.md
index 69efa64..ee8d9a9 100644
--- a/.agents/skills/dotnet-codestyle/SKILL.md
+++ b/.agents/skills/dotnet-codestyle/SKILL.md
@@ -101,130 +101,13 @@ updates, dependency upgrades, benchmarks) on top:
## Coding standards and conventions
-Code snippets below are illustrative examples only, replace namespaces and types to match your
-project.
+Key rules: no `var` (always explicit types), file-scoped namespaces, Allman braces, Nullable
+enabled, modern C# features (primary constructors, pattern matching, collection expressions). Every
+public surface has XML documentation. Private fields use `_camelCase`, static fields `s_camelCase`,
+constants PascalCase. Member ordering follows StyleCop SA1201.
-### C# language features
-
-1. **File-scoped namespaces**:
-
- ```csharp
- namespace Example.Project.Library;
- ```
-
-2. **Nullable reference types**: enabled (`enable`), use nullable annotations
- appropriately, use `required` for mandatory properties.
-3. **Modern C# features**: prefer modern language constructs, primary constructors when
- appropriate, top-level statements for console apps, pattern matching over traditional checks,
- collection expressions when types loosely match, extension methods (the classic
- `this`-parameter form or an `extension() { ... }` block on C# 14+), implicit object
- creation when the type is apparent, range and index operators.
-4. **Expression-bodied members**: use for applicable methods, properties, accessors, operators,
- lambdas, local functions.
-5. **`var` keyword**: do NOT use `var`, always use explicit types:
-
- ```csharp
- // Correct
- int count = 42;
- string name = "test";
-
- // Incorrect
- var count = 42;
- var name = "test";
- ```
-
-### Naming conventions
-
-1. **Private fields**: underscore prefix with camelCase:
-
- ```csharp
- private readonly HttpClient _httpClient;
- private int _counter;
- ```
-
-2. **Static fields**: `s_` prefix with camelCase:
-
- ```csharp
- private static int s_instanceCount;
- ```
-
-3. **Constants**: PascalCase:
-
- ```csharp
- private const int MaxRetries = 3;
- ```
-
-### Code structure
-
-1. **Global usings**: use `GlobalUsings.cs` for common namespaces:
-
- ```csharp
- global using System;
- global using System.Net.Http;
- global using System.Threading.Tasks;
- global using Microsoft.Extensions.Logging;
- ```
-
-2. **Usings placement**: outside the namespace, sorted with `System` directives first:
-
- ```csharp
- using System.CommandLine;
- using System.Runtime.CompilerServices;
- using Example.Project.Library;
-
- namespace Example.Project.Console;
- ```
-
-3. **Braces**: Allman style:
-
- ```csharp
- public void Method()
- {
- if (condition)
- {
- // code
- }
- }
- ```
-
-4. **Indentation**: C# files 4 spaces, XML/csproj files 2 spaces, YAML files 2 spaces, JSON files
- 4 spaces.
-5. **Line endings**: not specified here, governed per repo by `.editorconfig` / `.gitattributes`
- per GOVERNANCE.md's "Line Endings" section.
-6. **`#region`**: do not use regions, prefer logical file/folder/namespace organization.
-7. **Member ordering (StyleCop SA1201)**: const -> static readonly -> static fields -> instance
- readonly fields -> instance fields -> constructors -> public (events -> properties -> indexers
- -> methods -> operators) -> non-public in same order -> nested types.
-
-### Comments and documentation
-
-XML documentation is on: `true`, and
-missing XML comments for public APIs are suppressed in `.editorconfig`. Every public surface must
-still be documented: a single-line summary, additional details in remarks, documented input
-parameters, return values, exceptions, and crefs.
-
-```csharp
-///
-/// Example of a single line summary.
-///
-///
-/// Additional important details about usage.
-/// Multiple lines if needed.
-///
-///
-/// The quote category to request
-///
-///
-/// A that can be used to cancel the request.
-///
-///
-/// A containing the quote text.
-///
-///
-/// Thrown when is not a supported value.
-///
-public async Task GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken) {}
-```
+For language features, naming, code structure, and XML documentation examples, see
+`references/conventions.md`.
## Analyzer suppressions (.NET)
@@ -312,47 +195,15 @@ The .NET mechanics, narrowest first:
## Testing conventions
-1. **Framework**: xUnit v3 or later (the `xunit.v3` package, never the legacy v2 `xunit` package)
- with AwesomeAssertions for every assertion. Native xUnit asserts (`Assert.Equal`,
- `Assert.True`, ...) are not allowed, use the fluent `.Should()` API. Dynamic test skipping
- (`Assert.Skip`, `Assert.SkipWhen`) is control flow, not an assertion, and stays native:
-
- ```csharp
- [Fact]
- public void MethodName_Scenario_ExpectedBehavior()
- {
- // Arrange
- int expected = 42;
-
- // Act
- int actual = GetValue();
-
- // Assert
- actual.Should().Be(expected);
- }
- ```
-
-2. **Organization**: Arrange-Act-Assert pattern.
-3. **Naming**: descriptive names with underscores.
-4. **Theory tests**: use `[Theory]` with `[InlineData]`.
+xUnit v3 (`xunit.v3`, not the legacy `xunit`) + AwesomeAssertions (`.Should()` API, never native
+asserts). Arrange-Act-Assert pattern, descriptive underscore names, `[Theory]`/`[InlineData]` for
+parameterized tests. See `references/testing.md` for the framework setup template.
## Project configuration
-1. **Target framework**: .NET 10.0 (`net10.0`).
-2. **AOT compatibility**: `true`,
- `true`.
-3. **Assembly information**: use semantic versioning, include SourceLink
- (`true`), embed untracked sources
- (`true`).
-4. **Internal visibility**: use `InternalsVisibleTo` for test and benchmark access (adapt the
- project names to your repo's test/benchmark projects):
-
- ```xml
-
-
-
-
- ```
+.NET 10.0 target, AOT-compatible (`IsAotCompatible=true`, `VerifyReferenceAotCompatibility=true`),
+SourceLink, embedded untracked sources, `InternalsVisibleTo` for test/benchmark access. See
+`references/project-config.md` for the full property list.
## Best practices
diff --git a/.agents/skills/dotnet-codestyle/references/conventions.md b/.agents/skills/dotnet-codestyle/references/conventions.md
new file mode 100644
index 0000000..5eb4854
--- /dev/null
+++ b/.agents/skills/dotnet-codestyle/references/conventions.md
@@ -0,0 +1,126 @@
+# .NET Coding Standards and Conventions
+
+Code snippets below are illustrative examples only, replace namespaces and types to match your
+project.
+
+## C# language features
+
+1. **File-scoped namespaces**:
+
+ ```csharp
+ namespace Example.Project.Library;
+ ```
+
+2. **Nullable reference types**: enabled (`enable`), use nullable annotations
+ appropriately, use `required` for mandatory properties.
+3. **Modern C# features**: prefer modern language constructs, primary constructors when
+ appropriate, top-level statements for console apps, pattern matching over traditional checks,
+ collection expressions when types loosely match, extension methods (the classic
+ `this`-parameter form or an `extension() { ... }` block on C# 14+), implicit object
+ creation when the type is apparent, range and index operators.
+4. **Expression-bodied members**: use for applicable methods, properties, accessors, operators,
+ lambdas, local functions.
+5. **`var` keyword**: do NOT use `var`, always use explicit types:
+
+ ```csharp
+ // Correct
+ int count = 42;
+ string name = "test";
+
+ // Incorrect
+ var count = 42;
+ var name = "test";
+ ```
+
+## Naming conventions
+
+1. **Private fields**: underscore prefix with camelCase:
+
+ ```csharp
+ private readonly HttpClient _httpClient;
+ private int _counter;
+ ```
+
+2. **Static fields**: `s_` prefix with camelCase:
+
+ ```csharp
+ private static int s_instanceCount;
+ ```
+
+3. **Constants**: PascalCase:
+
+ ```csharp
+ private const int MaxRetries = 3;
+ ```
+
+## Code structure
+
+1. **Global usings**: use `GlobalUsings.cs` for common namespaces:
+
+ ```csharp
+ global using System;
+ global using System.Net.Http;
+ global using System.Threading.Tasks;
+ global using Microsoft.Extensions.Logging;
+ ```
+
+2. **Usings placement**: outside the namespace, sorted with `System` directives first:
+
+ ```csharp
+ using System.CommandLine;
+ using System.Runtime.CompilerServices;
+ using Example.Project.Library;
+
+ namespace Example.Project.Console;
+ ```
+
+3. **Braces**: Allman style:
+
+ ```csharp
+ public void Method()
+ {
+ if (condition)
+ {
+ // code
+ }
+ }
+ ```
+
+4. **Indentation**: C# files 4 spaces, XML/csproj files 2 spaces, YAML files 2 spaces, JSON files
+ 4 spaces.
+5. **Line endings**: not specified here, governed per repo by `.editorconfig` / `.gitattributes`
+ per GOVERNANCE.md's "Line Endings" section.
+6. **`#region`**: do not use regions, prefer logical file/folder/namespace organization.
+7. **Member ordering (StyleCop SA1201)**: const -> static readonly -> static fields -> instance
+ readonly fields -> instance fields -> constructors -> public (events -> properties -> indexers
+ -> methods -> operators) -> non-public in same order -> nested types.
+
+## Comments and documentation
+
+XML documentation is on: `true`, and
+missing XML comments for public APIs are suppressed in `.editorconfig`. Every public surface must
+still be documented: a single-line summary, additional details in remarks, documented input
+parameters, return values, exceptions, and crefs.
+
+```csharp
+///
+/// Example of a single line summary.
+///
+///
+/// Additional important details about usage.
+/// Multiple lines if needed.
+///
+///
+/// The quote category to request
+///
+///
+/// A that can be used to cancel the request.
+///
+///
+/// A containing the quote text.
+///
+///
+/// Thrown when is not a supported value.
+///
+public async Task GetQuoteOfTheDayAsync(string category, CancellationToken cancellationToken) {}
+```
diff --git a/.agents/skills/dotnet-codestyle/references/project-config.md b/.agents/skills/dotnet-codestyle/references/project-config.md
new file mode 100644
index 0000000..8f6e838
--- /dev/null
+++ b/.agents/skills/dotnet-codestyle/references/project-config.md
@@ -0,0 +1,17 @@
+# .NET Project Configuration
+
+1. **Target framework**: .NET 10.0 (`net10.0`).
+2. **AOT compatibility**: `true`,
+ `true`.
+3. **Assembly information**: use semantic versioning, include SourceLink
+ (`true`), embed untracked sources
+ (`true`).
+4. **Internal visibility**: use `InternalsVisibleTo` for test and benchmark access (adapt the
+ project names to your repo's test/benchmark projects):
+
+ ```xml
+
+
+
+
+ ```
diff --git a/.agents/skills/dotnet-codestyle/references/testing.md b/.agents/skills/dotnet-codestyle/references/testing.md
new file mode 100644
index 0000000..5a84a17
--- /dev/null
+++ b/.agents/skills/dotnet-codestyle/references/testing.md
@@ -0,0 +1,25 @@
+# .NET Testing Conventions
+
+1. **Framework**: xUnit v3 or later (the `xunit.v3` package, never the legacy v2 `xunit` package)
+ with AwesomeAssertions for every assertion. Native xUnit asserts (`Assert.Equal`,
+ `Assert.True`, ...) are not allowed, use the fluent `.Should()` API. Dynamic test skipping
+ (`Assert.Skip`, `Assert.SkipWhen`) is control flow, not an assertion, and stays native:
+
+ ```csharp
+ [Fact]
+ public void MethodName_Scenario_ExpectedBehavior()
+ {
+ // Arrange
+ int expected = 42;
+
+ // Act
+ int actual = GetValue();
+
+ // Assert
+ actual.Should().Be(expected);
+ }
+ ```
+
+2. **Organization**: Arrange-Act-Assert pattern.
+3. **Naming**: descriptive names with underscores.
+4. **Theory tests**: use `[Theory]` with `[InlineData]`.
diff --git a/.agents/skills/git-commit-conventions/SKILL.md b/.agents/skills/git-commit-conventions/SKILL.md
index 3709d31..85e46eb 100644
--- a/.agents/skills/git-commit-conventions/SKILL.md
+++ b/.agents/skills/git-commit-conventions/SKILL.md
@@ -154,28 +154,13 @@ the rewrite looks, a rejected push is recoverable, a force-pushed one is not.
## History rewrites re-identify only what changed
-**A history rewrite includes only the commits that must change, and re-identifies any commit it
-rewrites that is not the agent's own.** Filtering history (`git filter-repo` or an equivalent, for
-example to strip PII) re-signs every commit it touches with the rewriter's own key, while the
-tooling preserves each commit's original `author`/`committer` unless told otherwise. GitHub
-verifies a signature against the commit's `committer` identity, so a signature from the rewriter's
-key over a commit still committed by a bot (`dependabot[bot]`, `github-actions[bot]`) or GitHub's
-own web-flow does not match its committer and lands `unknown_key`/unverified, which a
-require-signed-commits rule then rejects.
-
-Two gates keep committer and signature aligned:
-
-1. **Scope the rewrite to only the commits that must be modified.** By default those are the
- rewriter's own, whose committer already matches, so a commit that needs no change stays out of
- the rewrite entirely and its identity and signature are never touched.
-2. **If a commit that must change is not the rewriter's own, set its `committer` to the rewriter's
- own signing identity before re-signing** (and its `author` too, since a rewrite that alters
- content should not keep attributing it to the bot). The original bot attribution is deliberately
- given up as the cost of having to rewrite it.
-
-Never leave a signature over a commit committed by another identity. Verify after any rewrite that
-every rewritten commit is signed and committed under the correct identity
-(`git log --show-signature`).
+**Do not rewrite a commit that does not need to change.** A history rewrite (e.g. `git filter-repo`
+to strip PII) re-signs every touched commit with the rewriter's key. If that commit is still
+committed by a bot (`dependabot[bot]`, `github-actions[bot]`) or GitHub's own web-flow, the
+signature will not match the committer and the require-signed-commits rule rejects it. Scope the
+rewrite to only the commits that must change. Set `committer` (and `author`) to the rewriter's
+identity on any non-own commit that must be modified. Verify with `git log --show-signature` after
+any rewrite. See `references/history-rewrite.md` for the full two-gate rule.
## Never run destructive git commands without being asked
diff --git a/.agents/skills/git-commit-conventions/references/history-rewrite.md b/.agents/skills/git-commit-conventions/references/history-rewrite.md
new file mode 100644
index 0000000..b331a55
--- /dev/null
+++ b/.agents/skills/git-commit-conventions/references/history-rewrite.md
@@ -0,0 +1,24 @@
+# History Rewrites: Re-identification Rules
+
+**A history rewrite includes only the commits that must change, and re-identifies any commit it
+rewrites that is not the agent's own.** Filtering history (`git filter-repo` or an equivalent, for
+example to strip PII) re-signs every commit it touches with the rewriter's own key, while the
+tooling preserves each commit's original `author`/`committer` unless told otherwise. GitHub
+verifies a signature against the commit's `committer` identity, so a signature from the rewriter's
+key over a commit still committed by a bot (`dependabot[bot]`, `github-actions[bot]`) or GitHub's
+own web-flow does not match its committer and lands `unknown_key`/unverified, which a
+require-signed-commits rule then rejects.
+
+Two gates keep committer and signature aligned:
+
+1. **Scope the rewrite to only the commits that must be modified.** By default those are the
+ rewriter's own, whose committer already matches, so a commit that needs no change stays out of
+ the rewrite entirely and its identity and signature are never touched.
+2. **If a commit that must change is not the rewriter's own, set its `committer` to the rewriter's
+ own signing identity before re-signing** (and its `author` too, since a rewrite that alters
+ content should not keep attributing it to the bot). The original bot attribution is deliberately
+ given up as the cost of having to rewrite it.
+
+Never leave a signature over a commit committed by another identity. Verify after any rewrite that
+every rewritten commit is signed and committed under the correct identity
+(`git log --show-signature`).
diff --git a/.agents/skills/python-codestyle/SKILL.md b/.agents/skills/python-codestyle/SKILL.md
index a5a262d..911ae30 100644
--- a/.agents/skills/python-codestyle/SKILL.md
+++ b/.agents/skills/python-codestyle/SKILL.md
@@ -24,66 +24,16 @@ language shares (clean-compile verification as a concept, the suppression-scope
casing in prose), this Skill is everything specific to a Python project on top of that: the two
profiles, the toolchain, layout, and the language-level conventions.
-## Adapt before propagating
-
-The rules below describe the default Python profile: a package that publishes to PyPI,
-type-checked by pyright in strict mode, dependencies in `[dependency-groups]`. A derived repo
-often differs, and when it does, adapt these fields to match the repo's actual toolchain rather
-than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate and gets rejected
-in review). The axes that commonly vary per repo:
-
-- **Type checker in CI**: pyright strict, mypy in CI with pyright editor-only (Pylance), or both.
- Whichever runs in CI is the one the clean-compile and the CI gate invoke.
-- **Dependency declaration**: `[dependency-groups]`, or PEP 621 `[project.optional-dependencies]`
- (dev tools installed with `uv sync --extra `).
-- **Versioning / publishing**: a published package (`_version.py` plus a version source,
- `uv build`, and a PyPI publish step), or a source-only repo with a static `version` and no
- publish step (see Versioning below).
-- **Disabled markdownlint rules**: repo-specific, `.markdownlint-cli2.jsonc` at the repo root is
- the source of truth, not any example rule named here.
-- **VS Code config home**: editor settings/extensions may live in `.vscode/*.json` or the
- `.code-workspace`, while tasks/launch/debug configs can only be external `.vscode/*.json`
- (they cannot live in the workspace file). The repo's own `tasks.json` sits wherever it keeps it,
- and the canonical task definitions it is written against are the hub `vscode-tasks-python.json`
- snippet, which resolves the same way from every repo.
-
## Two profiles
-A repo's Python is one of two shapes, declared as the `build` or `lint-only` profile and validated
-against the `pyproject.toml` shape. Most of this Skill (uv project, `uv.lock`, `uv run`, src
-layout, pytest coverage) describes the Project shape (the `build` profile). The two differ by
-whether the Python has third-party runtime dependencies, which shows up structurally in
-`pyproject.toml`, so the fleet's audit reads the shape there:
+Read the repo's `pyproject.toml` shape and pick the profile before applying any other rule:
-- **Project** (the `build` profile): the Python has third-party runtime dependencies, or is the
- repo's deliverable. It is a PEP 621 uv project: `[project]` with `dependencies` (dev tools in
- `[project.optional-dependencies]` or `[dependency-groups]`), a `[build-system]`, and a committed
- `uv.lock` (pinned LF, per GOVERNANCE.md's "Line Endings" section). CI runs `uv sync --frozen` +
- `uv run `, so the lockfile pins tool versions.
-- **Scripts** (the `lint-only` profile): stdlib-only utility scripts embedded in a non-Python repo
- (e.g. a Python tooling subtree of a `csharp` app). Run the tools with `uvx` (no project install,
- no lockfile): the `pyproject.toml` carries only tool config (`[tool.ruff]`, `[tool.mypy]`, and
- an optional `[tool.pyright]` editor block), with no `[project]`, no `[build-system]`, and no
- `uv.lock` (that metadata would misrepresent it as a shippable package). mypy is the type-check
- gate (there is no first-party package for pyright strict to anchor on), and a `[tool.pyright]`
- block in standard mode keeps Pylance quiet in the editor, the same mypy-gate/pyright-editor
- split the build profile uses. There is no lockfile, and a `uvx @` pin in a `run:`
- step is not something Dependabot tracks, so CI runs `uvx ruff@latest` / `uvx mypy@latest` rather
- than a manual pin that would silently go stale. The fleet rule is to pin only what Dependabot
- auto-updates (SHA-pinned actions, package deps) and otherwise run latest, so the VS Code tasks,
- README, and CI all run the unpinned latest here. `.py` files follow the repo's LF line-ending
- default (per GOVERNANCE.md's "Line Endings" section). There is no pytest suite, and `unittest` is the runner
- instead. A script that carries a gate still earns tests, written with the standard library's
- `unittest` so they run under bare `python3` with nothing installed, as `test_