From bb016996a94b468b3271fc635857b3ceb6a43d50 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 13 Jul 2026 10:39:21 -0700 Subject: [PATCH 1/2] Rename HomeAutomation -> HomeAutomation-Config; prefer split over mixed-EOL - registry: rename the entry (name + url) for fleet naming consistency (config repos are *-Config); driftNotes note the rename and that the Vantage config is split out to its own Windows/CRLF Vantage-Config repo (strip the legacy Vantage/ subtree during onboarding). - AGENTS.md "Line Endings": rewrite the mixed-consumer guidance to lead with the preferred answer - split by platform into single-platform repos (Vantage-Config out of the lf HomeAutomation-Config), with the per-path .editorconfig override kept only as a fallback for a subtree that genuinely cannot be split. Supersedes the earlier "HomeAutomation is a mixed repo" example, which the split makes obsolete. Co-Authored-By: Claude Opus 4.8 (1M context) --- AGENTS.md | 2 +- registry/repos.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8726ec24..31462b3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -130,7 +130,7 @@ Applies to code and workflow (`#`) comments alike. - **[`.editorconfig`](./.editorconfig) sets the line ending:** `[*] end_of_line = crlf` is the **default** - every file type is CRLF unless pinned otherwise - with **LF** pinned for the execution-sensitive exceptions - `*.sh`, Dockerfiles, and any individual `.py` executed directly via its shebang (pinned **by path**, e.g. `spec/validate.py`; vanilla `.py` stays CRLF, since Python's universal newlines accept it and it is commonly edited on Windows). Only the LF exceptions are declared; the redundant per-type CRLF rules are intentionally omitted. `.gitattributes` mirrors it: `* -text` (git stores the exact bytes you commit and will **not** normalize) plus the matching LF pins. - **Choosing an ending for a new file type:** CRLF is the **default** - cross-platform editors on Windows produce it, and it is harmless on Linux for everything except shell. Use LF only when the type **requires** it or CRLF **breaks how it is consumed**: executable scripts/shebangs (`*.sh`, s6, husky), Dockerfiles (CRLF breaks `RUN` heredocs/continuations), and tool-owned formats with a native LF ending (KiCad). **Non-workflow YAML stays CRLF** - GitHub Actions' parser tolerates it (a repo that also runs yamllint sets `new-lines: disable` to defer to `.editorconfig`). **Workflow YAML (`.github/workflows/*.{yml,yaml}`) is pinned LF** in `.editorconfig` - Dependabot and Actions rewrite it with LF, so declaring LF keeps it consistent instead of mixed on every bump. This (and the catalog snippet workflows in `catalog/snippets/workflows/*`, pinned LF the same way) is an LF class **not** backed by a `.gitattributes` pin: git keeps `* -text` (no normalization), and CI's `editorconfig-checker` (EOL-only) catches a mismatch instead. Distinguish where a file is *consumed* from where it is *edited*: consumption on Linux alone does not force LF. A config or pattern file consumed by a Linux tool stays CRLF when the tool tolerates a trailing CR: `.dockerignore` and `.gitignore` are CRLF (their parsers strip the CR), and only a *Dockerfile* - interpreted, where a CR breaks `RUN` heredocs and line continuations - is LF. - **Operational (config) repos: the global default follows the consuming application's native platform, not the fleet CRLF default.** A config repo (registry `workflowModel: operational`) is a *view into an application's configuration directory* - often the exact tree mounted into that app's container - so its files must use the ending the app itself reads and writes, and forcing the fleet CRLF default would fight the app. Set the `[*] end_of_line` default to the app's native ending and record it in the registry [`lineEndings`](./registry/repos.json) field (`lf` | `crlf`): **LF** for a Linux-native app whose config lives in a Linux container - ESPHome, Home Assistant, a devcontainer-only or HACS config - and **CRLF** for a Windows-native editor - e.g. Vantage InFusion config edited by Design Center on Windows. The execution-sensitive LF pins (`*.sh`, Dockerfiles, workflow YAML) still apply on top, and `.gitattributes` still mirrors the chosen default. This override is for operational repos only; `release` repos keep the `[*] end_of_line = crlf` fleet default above. Do **not** re-normalize such a repo to the fleet default - that is exactly the over-normalization these per-repo endings prevent. - - **Mixed-consumer repos: global default = the primary consumer, with a per-path override for a differently-consumed subtree.** When one repo is consumed on two platforms, the registry `lineEndings` records the **primary** default and a subtree carries an `.editorconfig` path override (CRLF/LF) matching *its* consumer, treated like any tool-owned format (pin it; it is not fleet drift). Example: `HomeAutomation` is `lineEndings: lf` (Linux docker-compose, shell, and dnsmasq/unbound daemon configs on the Proxmox host), with its Windows-edited `Vantage/**` subtree - UTF-8 CRLF Design Center project files (`.dc`, which are really XML) - pinned `[Vantage/**] end_of_line = crlf`; the global `* -text` in `.gitattributes` already preserves those bytes, so no extra git pin is needed. + - **Mixed-consumer config: prefer to split by platform into single-platform repos, not one mixed repo.** When a config repo would be consumed on two platforms (a Linux app plus a Windows-edited subtree), the clean answer is a repo per consumer, each single-platform with its own `lineEndings` - e.g. the Vantage InFusion / Design Center config (Windows/CRLF) lives in its own `Vantage-Config` repo, **not** as a `Vantage/**` subtree inside the Linux-`lf` `HomeAutomation-Config`. That keeps each repo's default, CI, and checkout matched to one platform and avoids per-path EOL machinery entirely. **Fallback only if a subtree genuinely cannot be split out:** keep the global default at the primary consumer and pin the odd subtree with an `.editorconfig` path override (e.g. `[/**] end_of_line = crlf`) matching its consumer, treated like any tool-owned format; the global `* -text` in `.gitattributes` already preserves those bytes, so no extra git pin is needed. - **Scripts and extensionless executables must be LF - and pinned in `.gitattributes`, not just configured.** A CRLF shebang (`#!/usr/bin/env bash\r`) breaks execution. `.editorconfig` sets `[*.sh] = lf`, but that extension-based rule does not match **extensionless** executables (s6 service scripts `run`/`up`/`finish`, husky/git hook scripts like `.husky/pre-commit`), and `* -text` enforces nothing - so a broad normalization pass or an editor can silently flip them to CRLF (it has). `.gitattributes` is the enforcement layer: it carries `*.sh text eol=lf`, and any repo whose tooling ships extensionless scripts **adds the matching path pin** - e.g. `Docker/s6-overlay/** text eol=lf` for s6 init, `.husky/pre-commit text eol=lf` for husky hooks - so git holds them at LF on checkout and `--renormalize`. This pin is mandatory for any repo that overrides s6 init, uses husky/git hooks, or otherwise ships executable scripts. The same explicit-pin rule extends to **tool-owned file formats the base config doesn't key on**: pin them to whatever ending the tool reads and writes so a normalization sweep can't churn them - e.g. KiCad project/footprint/3D files (`*.kicad_mod`, `*.kicad_sym`, `*.step`), which KiCad writes LF (`*.kicad_mod text eol=lf`, ...). The principle is general: a file class the `.editorconfig` extension rules and `* -text` don't cover needs an explicit `.gitattributes` pin matching its tool's native ending. - **Pair each such pin with a matching `.editorconfig` override - the git pin alone is not enough.** `.gitattributes` governs **git** (checkout, commit, `--renormalize`); the **editor** follows `.editorconfig`, where the `[*] end_of_line = crlf` default still applies to any file no extension rule covers. So even with the git pin, the editor writes a CRLF shebang into an extensionless hook (breaking it when run from the working tree) or re-ends/trims a byte-sensitive data file. Give every extensionless **executable** an editorconfig LF override beside its `.gitattributes` pin (`[.husky/pre-commit] end_of_line = lf`); and for a **byte-preserve data directory** (downloaded or opaque source whose exact bytes the consumer may depend on) disable *all* editor normalization, not just EOL - `[/*]` 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, so the editor enforces neither the global `charset` nor `end_of_line` on that path). Keep these overrides with the line-ending governance (above any `.NET-only` divider), not in the language-style section. - **New files:** create them with the `.editorconfig`-mandated ending. diff --git a/registry/repos.json b/registry/repos.json index d3b4283f..7c131b70 100644 --- a/registry/repos.json +++ b/registry/repos.json @@ -157,8 +157,8 @@ "driftNotes": ["Docker image wrapping upstream Nx products; C# (CreateMatrix) is the codegen generator, not a shipped package (IsPackable=false, no nuget push).", "Release is the two-phase model (weekly schedule + workflow_dispatch publish; ordinary merges do not) plus an extra Make/Matrix.json path-scoped push that republishes when the codegen version pin bumps.", "Docker Hub README published per-image via a Matrix.json-derived matrix.", "Branch hygiene: 3 stale Dependabot nuget branches (PRs closed/superseded) linger, safe to delete; main+develop otherwise clean after the 2026-07 sweep."] }, { - "name": "HomeAutomation", - "url": "https://github.com/ptr727/HomeAutomation", + "name": "HomeAutomation-Config", + "url": "https://github.com/ptr727/HomeAutomation-Config", "status": "cataloged", "types": ["source-only"], "groundTruthBranch": "develop", @@ -169,7 +169,7 @@ "requiredSecrets": [], "consumerModel": "pull", "releaseTrigger": "dispatch-only", - "driftNotes": ["Maintainer config/ops repo (docker-compose stacks, lifecycle scripts, Firewalla configs).", "Dual-platform EOL: lf global (Linux Proxmox host - docker/shell/dnsmasq/unbound) with the Windows-edited Vantage/** Design Center subtree (UTF-8 CRLF .dc XML) pinned crlf. Consolidates the former standalone Vantage-Config repo (removed from the registry; Design Center is now freely available, so its installer archives were discarded).", "Private; README self-flags previously-committed secrets - secrets-hygiene concern.", "Operational rollout pending: lint CI feeding the required check, dispatch-only source-release scaffolding (version.json + NBGV get-version + publish-release.yml, tag + source zip), and develop-as-ground-truth adoption."] + "driftNotes": ["Maintainer config/ops repo (docker-compose stacks, lifecycle scripts, Firewalla configs); Linux-consumed on the Proxmox host, so lineEndings lf.", "Renamed from HomeAutomation for fleet naming consistency (config repos are *-Config). The Vantage controller config is split out to its own Windows/CRLF Vantage-Config repo, not carried here - strip the legacy Vantage/ subtree during onboarding.", "Private; README self-flags previously-committed secrets - secrets-hygiene concern.", "Operational rollout pending: lint CI feeding the required check, dispatch-only source-release scaffolding (version.json + NBGV get-version + publish-release.yml, tag + source zip), and develop-as-ground-truth adoption."] }, { "name": "KiCadLibrary", From da9014e6d1ece17d453305792ec46bb4d409e1d7 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Mon, 13 Jul 2026 10:58:36 -0700 Subject: [PATCH 2/2] Re-add Vantage-Config to the registry (recreated single-platform repo) Copilot review caught that AGENTS.md and the HomeAutomation-Config driftNotes reference Vantage-Config while the registry (post-#289) had no such entry. It is being recreated as a lean Windows/CRLF operational repo, so catalog it: operational, lineEndings crlf, dispatch-only github-release, with a driftNote that onboarding is pending until content is repopulated from Windows. Co-Authored-By: Claude Opus 4.8 (1M context) --- registry/repos.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/registry/repos.json b/registry/repos.json index 7c131b70..2637f519 100644 --- a/registry/repos.json +++ b/registry/repos.json @@ -279,6 +279,21 @@ "releaseTrigger": "none", "driftNotes": ["Work-in-progress: pre-CI (no .github/workflows, no version.json, no repo-config). main+develop both exist."] }, + { + "name": "Vantage-Config", + "url": "https://github.com/ptr727/Vantage-Config", + "status": "cataloged", + "types": ["source-only"], + "groundTruthBranch": "develop", + "workflowModel": "operational", + "lineEndings": "crlf", + "hasDevelop": true, + "publish": [{ "target": "github-release", "mechanism": "none" }], + "requiredSecrets": [], + "consumerModel": "pull", + "releaseTrigger": "dispatch-only", + "driftNotes": ["Vantage InFusion / Design Center controller config edited on Windows (UTF-8 CRLF .dc XML, really special XML), so lineEndings crlf.", "Recreated lean and single-platform: Design Center is freely available, so no installer archives are kept; split out of HomeAutomation-Config. Being repopulated from the Windows editing host - operational onboarding (baseline, lint CI, dispatch-only publisher, rulesets, develop/main) pending once content lands."] + }, { "name": "HolidayLights", "url": "https://github.com/ptr727/HolidayLights",