From a934172d31bbbb5cc0fc18f9f3036e6062892625 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 9 Jul 2026 14:39:57 -0700 Subject: [PATCH 1/3] AGENTS.md: add Communicating with the User conventions (#268) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a short **Communicating with the User** section to AGENTS.md with two agent<->user interaction rules: 1. **Reference every pull request as a clickable link** β€” a markdown link to the PR (`[#123](.../pull/123)`), never a bare `#123`; same for issues and commits. 2. **Ask for input as a numbered list** β€” so the user can reply per number; two or more questions are always numbered. Additive only; no existing wording changed. Placed as a new H2 after `PR Review Etiquette`, before `Workflow YAML Conventions`. CRLF preserved. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) --- AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 24ae4423..770d9f73 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -199,6 +199,11 @@ Bring the user in when: Anti-pattern: don't keep flipping the code on the same style point. Flip the rule once and stick to the rule. +## Communicating with the User + +- **Reference every pull request as a clickable link.** When you mention a PR - in chat, a summary, or a report - render it as a markdown link to the PR (`[#123](https://github.com///pull/123)`), never a bare `#123`. The same applies to issues and commits. +- **Ask for input as a numbered list.** When you need the user to decide or answer, present the questions - and any options - as a numbered list so they can reply per number. A single inline question is fine; two or more are always numbered. + ## Workflow YAML Conventions These conventions describe the target state. New and modified workflows must respect them; the rest of the repo is expected to be brought up to the same standard. Sweep PRs that apply a rule everywhere are welcome when a rule changes. From e9aa3bc708519069d742042d7e4ff45cfa32270a Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 9 Jul 2026 15:54:54 -0700 Subject: [PATCH 2/3] =?UTF-8?q?AGENTS.md:=20add=20Supported=20Development?= =?UTF-8?q?=20Platforms=20rule=20(#228=20=C2=A70)=20(#269)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Encodes the last unincorporated piece of the #228 retrospective β€” **Β§0, the cross-platform decision framework** β€” as a new `## Supported Development Platforms` section in AGENTS.md (before `## Devcontainer`): - **Cross-platform by default** β€” Windows + macOS + Linux, via WSL2/devcontainer for a consistent Linux toolchain; editing is cross-platform through the GUI regardless. - **Narrow only for a hard runtime ceiling** set by dependencies (decided per repo, before writing dev tooling) β€” e.g. a Home Assistant integration is Linux-only because HA Core is POSIX-only. The narrowing axis is where code *executes* for dev/testing, not where editing happens. - **Record a narrowed platform + reason in the repo** so it reads as deliberate. Additive only; CRLF preserved. Completes #228's incorporation; the sectionβ†’PR mapping will be posted on #228 at close. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- AGENTS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 770d9f73..a1ffc6ed 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -245,6 +245,12 @@ The CI lint job runs these tools (workflow YAML and Markdown), but run them loca When pulling a public image fails on a Docker-Desktop/WSL credential-helper error (`docker-credential-desktop.exe: exec format error`), retry with an empty Docker config: `DOCKER_CONFIG=$(mktemp -d) docker run ...` after writing `{}` to `$DOCKER_CONFIG/config.json`. +## Supported Development Platforms + +- **Cross-platform by default - Windows + macOS + Linux.** Linux runs natively (a Linux desktop, or SSH/remote into a Linux host), through a devcontainer on Windows or macOS, or through WSL2 on Windows - the devcontainer and WSL routes carry their own nuances (mounts, path translation, SSH-agent forwarding) but deliver the same toolchain. Editing is cross-platform through the GUI regardless of where code runs. Assume this default. +- **A repo's platform ceiling is set by its dependencies, not tooling effort; decide it per repo before writing dev tooling.** Narrow below the default only for a hard runtime ceiling - the code can only execute or test on one platform (e.g. a Home Assistant integration is Linux-only: HA Core has POSIX-only dependencies and will not run natively on Windows, so even maximal tooling yields only lint-only there). The narrowing axis is where code *executes* for dev and testing - native, SSH-remote, container, or CI - never where editing happens. +- **Record a narrowed platform and its reason in the repo** (README/AGENTS) so the restriction reads as a deliberate dependency ceiling, not an omission. + ## Devcontainer Contributors commit to this repo with signed commits; the SSH-signing setup lives in [docs/ssh-signing.md](./docs/ssh-signing.md), host prerequisites in [docs/host-setup.md](./docs/host-setup.md), and devcontainer SSH-agent forwarding in [docs/devcontainer.md](./docs/devcontainer.md). This repo ships no application toolchain; the per-language devcontainer definitions it once used are kept as reference under [`catalog/snippets/devcontainer/`](./catalog/snippets/devcontainer/). From 86ed881da3f2679538c6db7e08dd537bce30775e Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Thu, 9 Jul 2026 16:12:43 -0700 Subject: [PATCH 3/3] CODESTYLE: xUnit v3 + AwesomeAssertions, and ILoggerFactory-not-Serilog for libraries (#270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two C# rule sharpenings in CODESTYLE.md, both from maintainer directives. **Testing Conventions** β€” was "xUnit with AwesomeAssertions"; now explicit: - **xUnit v3 or later** (the `xunit.v3` package, never the legacy v2 `xunit`). - **AwesomeAssertions** for every assertion; native xUnit asserts (`Assert.Equal`, `Assert.True`, ...) are not allowed. **Error Handling and Logging** β€” clarified that Serilog is the **application's** concrete backend, and strengthened the library rule: - A NuGet **library** depends only on `Microsoft.Extensions.Logging.Abstractions` and exposes an `ILoggerFactory` seam (settable factory defaulting to `NullLoggerFactory`, `SetFactory`/`TrySetFactory`); it **never** references Serilog or a sink. - The **application** owns the concrete logger and bridges it (`SerilogLoggerFactory`), injecting it. Reference: `LanguageTags` (`LogOptions` + `LanguageTagsCreate/LoggerFactory`). Additive/sharpening only; markdownlint clean; CRLF preserved. **Fleet audit (backlog to follow):** violators are **Utilities** (xUnit v2 + native asserts; library ships Serilog) and **AudioCleaner** (xUnit v2 + native asserts). LanguageTags, PlexCleaner, NxWitness, PhotoCleaner, MediaTools already comply. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- CODESTYLE.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/CODESTYLE.md b/CODESTYLE.md index f3633687..2a374d50 100644 --- a/CODESTYLE.md +++ b/CODESTYLE.md @@ -156,7 +156,7 @@ Note: Code snippets are illustrative examples only. Replace namespaces/types to global using System; global using System.Net.Http; global using System.Threading.Tasks; - global using Serilog; + global using Microsoft.Extensions.Logging; ``` 2. **Usings placement**: Outside namespace, sorted with `System` directives first @@ -245,15 +245,13 @@ Follow the scope hierarchy in [Analyzer Diagnostics and Suppressions][analyzer-d #### Error Handling and Logging -1. **Serilog logging**: Use structured logging +1. **Structured logging**: Use structured message templates - Serilog is the **application's** concrete backend; a library never references it (see item 2) ```csharp - logger.Error(exception, "{Function}", function); + logger.LogError(exception, "{Function}", function); ``` -2. **Library log configuration**: Libraries must expose logging configuration - - Provide options or settings to supply an `ILoggerFactory` and/or `ILogger` - - Offer a global fallback logger for static usage when needed +2. **Libraries log through abstractions, never a concrete backend.** A NuGet **library** depends only on `Microsoft.Extensions.Logging.Abstractions` and exposes an `ILoggerFactory` seam - a settable global factory defaulting to `NullLoggerFactory` (fallback `NullLogger.Instance`) with `SetFactory`/`TrySetFactory`, and/or an `ILoggerFactory`/`ILogger` parameter in its API. It must **not** reference Serilog or any sink - that forces a logging framework on every consumer and drags in AOT-incompatible dependencies. The consuming **application** owns the concrete logger (Serilog is fine there), bridges it to `ILoggerFactory` (e.g. `SerilogLoggerFactory` from `Serilog.Extensions.Logging`), and injects it. Reference: `LanguageTags` - `LogOptions` in the library; the CLI's `LoggerFactory` builds the Serilog-backed factory and injects it via `LogOptions.SetFactory`. 3. **CallerMemberName**: Use for automatic function name tracking @@ -294,7 +292,7 @@ Follow the scope hierarchy in [Analyzer Diagnostics and Suppressions][analyzer-d #### Testing Conventions -1. **Framework**: xUnit with AwesomeAssertions +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 ```csharp [Fact]