From e4ff8bdcbe6355235cff3b22e203be41df26ca60 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Jul 2026 10:58:36 +0000 Subject: [PATCH 1/2] Reduce merge-queue wait to 1 minute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Queued entries now merge after at most 1 minute instead of 5 — a solo repo gains nothing from batching entries longer. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Vi2ifWUY3MXfbcbNFnsS8V --- setup/Protect-MainBranch.Tests.ps1 | 5 +++++ setup/Protect-MainBranch.ps1 | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/setup/Protect-MainBranch.Tests.ps1 b/setup/Protect-MainBranch.Tests.ps1 index a280e3d..a47a303 100644 --- a/setup/Protect-MainBranch.Tests.ps1 +++ b/setup/Protect-MainBranch.Tests.ps1 @@ -33,6 +33,11 @@ Describe 'Get-ProtectionRuleset' -Tag 'Fast' { $script:R.rules.type | Should -Contain 'merge_queue' } + It 'waits at most 1 minute before merging queued entries' { + ($script:R.rules | Where-Object type -EQ 'merge_queue').parameters.min_entries_to_merge_wait_minutes | + Should -Be 1 + } + It 'requires review threads to be resolved (holds auto-merge on open comments)' { ($script:R.rules | Where-Object type -EQ 'pull_request').parameters.required_review_thread_resolution | Should -BeTrue diff --git a/setup/Protect-MainBranch.ps1 b/setup/Protect-MainBranch.ps1 index 55926e3..374454d 100644 --- a/setup/Protect-MainBranch.ps1 +++ b/setup/Protect-MainBranch.ps1 @@ -78,7 +78,7 @@ function Get-ProtectionRuleset { max_entries_to_build = 5 min_entries_to_merge = 1 max_entries_to_merge = 5 - min_entries_to_merge_wait_minutes = 5 + min_entries_to_merge_wait_minutes = 1 check_response_timeout_minutes = 60 } } From 9150c0def324de98874330f7b8d6bb34599ffb41 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Jul 2026 10:58:36 +0000 Subject: [PATCH 2/2] Add MIGRATION.md entry doc and missing .vscode README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIGRATION.md is the entry document for adopting the template's concepts in a repo not created from it: a concept-to-doc map plus the migration steps in dependency order. AGENTS.md's retrofit section now points there instead of duplicating the steps (one source, no drift). .vscode/README.md fills the one gap in per-folder docs — AGENTS.md's mechanism map already linked it, but the file did not exist; .gitignore now tracks it alongside the shipped settings. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Vi2ifWUY3MXfbcbNFnsS8V --- .gitignore | 1 + .vscode/README.md | 35 ++++++++++++++ AGENTS.md | 25 ++-------- MIGRATION.md | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 21 deletions(-) create mode 100644 .vscode/README.md create mode 100644 MIGRATION.md diff --git a/.gitignore b/.gitignore index 470d9fa..d4f60d5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ desktop.ini .vscode/* !.vscode/settings.json !.vscode/extensions.json +!.vscode/README.md # --- transient work (kept out of tracking for now) ---------------------------- .temp/ diff --git a/.vscode/README.md b/.vscode/README.md new file mode 100644 index 0000000..f2a3e23 --- /dev/null +++ b/.vscode/README.md @@ -0,0 +1,35 @@ +# Editor integration + +VS Code workspace wiring so the linters that gate commits also surface live in +the editor. See [`/AGENTS.md`](../AGENTS.md) for the overall architecture. + +| File | Purpose | +| ----------------- | ------------------------------------------------------- | +| `settings.json` | tooling-only workspace settings, wired to `.config/` | +| `extensions.json` | recommended extensions matching the commit-time linters | + +## `settings.json` — same rules, live + +Live markdown linting `extends` the same [`.config/markdownlint.jsonc`](../.config/markdownlint.jsonc) +the commit hook enforces — editor and commit never disagree. File endings and +final newlines honour `.editorconfig` intent for files VS Code creates. + +`editor.formatOnSave` stays **off** by design: formatting is a commit concern +here (markdownlint `--fix`, shfmt), and an editor formatter would fight the +linters. + +## `extensions.json` — surface the gate early + +Recommends one extension per commit-time linter (EditorConfig, markdownlint, +YAML, PowerShell/PSScriptAnalyzer, AsciiDoc, shellcheck, shfmt) so problems +appear while typing, not first at commit. VS Code prompts contributors to +install them on open. + +## Conventions + +- Keep `settings.json` strictly about wiring linters to `.config/` — no + personal preferences (theme, fonts). Extend it freely in a project, but keep + the split. +- `.gitignore` tracks only the shipped files (`settings.json`, + `extensions.json`, this README) and ignores everything else in `.vscode/`, + so personal editor state never lands in the repo. diff --git a/AGENTS.md b/AGENTS.md index 9bf28c6..cbe47a6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,27 +58,10 @@ drifted). Git tracks symlinks natively. ## Retrofit an existing repo -To bring another repo (e.g. one using split per-language workflows and a -hand-rolled `.githooks/` hook) up to this architecture: - -1. **Adopt the orchestrator.** Copy `.pre-commit-config.yaml` and adapt the hook - list to the repo's languages. Remove any `core.hooksPath`/`.githooks/` setup — - pre-commit replaces it. Don't set `core.hooksPath`; the two conflict. -2. **Relocate configs** into `.config/`, referenced explicitly via hook `args` - (keep root-forced files at root). Factor markdown rules into - `markdownlint.jsonc` so the editor and CLI share them. -3. **Move custom checks into shared scripts.** Any bespoke lint/test logic that - lived in CI *and* a local hook becomes one `.config/scripts/*.ps1` invoked as - a `repo: local` hook — run identically local and in CI. Delete the duplicate. -4. **Collapse CI to one workflow** that runs `pre-commit run` (scoped on - `pull_request`, full on `merge_group`). Replace N split per-language workflows; - path-filtering is no longer needed because pre-commit scopes by file. -5. **Wire the editor** (`.vscode/settings.json`) and add recommendations. -6. **Copy the docs** (this file + the per-folder READMEs), trimming to the - retrofitted repo's actual tools. -7. **Purge phantoms.** Verify every tool exists (e.g. there is **no** - `asciidoctor-lint` gem — use `asciidoctor --failure-level` for syntax + Vale - for prose). +The step-by-step guide for bringing a repo **not** created from this template +up to this architecture lives in [`MIGRATION.md`](MIGRATION.md) — the entry +document that lists every concept, orders the migration (orchestrator first, +server-side protection last), and links each concept's reference doc. Anti-pattern this replaces: local hook logic and CI workflows re-implementing "the same" checks separately, which drift apart. One orchestrator, one source. diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..3dbc387 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,116 @@ +# MIGRATION.md — adopting this template in an existing repo + +How to migrate this repo's concepts into a repo that was **not** created from +this template. This is the entry document: it names each concept, gives the +order to adopt them in, and links the reference doc that explains each one in +depth — read those as you reach each step. + +For the architecture itself (what you are adopting and why), read +[`AGENTS.md`](AGENTS.md) first. + +## The concepts and where they are explained + +| Concept | Lives in | Reference doc | +| ------------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------------------------- | +| Orchestration (the local workflow) | `.pre-commit-config.yaml` | [`AGENTS.md`](AGENTS.md) + inline comments | +| Tool configs | `.config/` | [`.config/README.md`](.config/README.md) | +| Shared lint/test scripts | `.config/scripts/` | [`.config/scripts/README.md`](.config/scripts/README.md) | +| Policy rules (custom analyzer rules) | `.config/PSScriptAnalyzerRules/` | [`.config/scripts/README.md`](.config/scripts/README.md) | +| Opt-in overlays | `.config/overlays/` | [`.config/overlays/vale/README.md`](.config/overlays/vale/README.md) | +| CI (GH Actions workflow) | `.github/workflows/lint.yml` | [`.github/README.md`](.github/README.md) | +| GitHub automation beyond CI | `.github/` (Dependabot, CODEOWNERS, PR/issue templates) | [`.github/README.md`](.github/README.md) | +| Editor integration | `.vscode/` | [`.vscode/README.md`](.vscode/README.md) | +| Root convention files | `.editorconfig`, `.gitattributes`, `.gitignore`, `.claudeignore` | self-documenting (declarative) | +| One-time server-side setup | `setup/` | [`setup/README.md`](setup/README.md) | +| Agent entry docs | `CLAUDE.md`, `AGENTS.md`, per-folder READMEs | themselves | + +## Migration, in order + +The order matters: the orchestrator comes first because every later step hangs +hooks off it, and server-side protection comes last because it requires a CI +run to have happened. + +### 1. Adopt the orchestrator + +Copy `.pre-commit-config.yaml` to the target repo's root and adapt the hook +list to its languages — drop hooks for languages the repo doesn't have, keep +the structure (managed hooks for off-the-shelf linters, `repo: local` hooks +for bespoke checks, stages as cadence). Remove any existing +`core.hooksPath`/`.githooks/` mechanism — pre-commit replaces it, and the two +conflict. + +### 2. Relocate configs into `.config/` + +Move tool configs out of root into `.config/`, referenced explicitly via hook +`args` (see [`.config/README.md`](.config/README.md) for which file feeds +which tool). Only files a tool *forces* to root stay there. Factor markdown +rules into `markdownlint.jsonc` so editor and CLI share one rule set. + +### 3. Move custom checks into shared scripts + +Any bespoke lint/test logic that lived in CI *and* a local hook becomes one +`.config/scripts/*.ps1` invoked as a `repo: local` hook — run identically in +both places; delete the duplicate. Follow the script contract in +[`.config/scripts/README.md`](.config/scripts/README.md): fail fast, never +self-install, no-op cleanly on nothing to check. Copy +`Initialize-DevEnvironment.ps1` (bootstrap) and `Invoke-TestLane.ps1` (test +lanes) as-is; tag the repo's Pester tests `Fast`/`Standard`/`Thorough` by +measured cost. + +### 4. Collapse CI to one workflow + +Replace split per-language workflows with one `lint.yml` that runs +`pre-commit run` — scoped to the diff on `pull_request`, full on `merge_group` +(see [`.github/README.md`](.github/README.md)). Path-filtering becomes +unnecessary: pre-commit scopes by file. Keep the full-history gitleaks scan as +the one CI-only step, pin third-party actions by commit SHA, and bring over +`dependabot.yml`, `CODEOWNERS`, and the PR/issue templates, adapting owners +and paths. + +### 5. Wire the editor + +Copy `.vscode/settings.json` and `extensions.json` +(see [`.vscode/README.md`](.vscode/README.md)) so the same rules surface live +while typing. Keep the `.gitignore` pattern that tracks only the shipped +files. + +### 6. Copy the docs and root conventions + +Copy `AGENTS.md`, `CLAUDE.md`, and the per-folder READMEs, trimming each to +the tools the target repo actually uses. Copy the root convention files +(`.editorconfig`, `.gitattributes`, `.gitignore`, `.claudeignore`) and merge +with what exists. Where the same file must exist twice, prefer a symlink over +a copy (rationale and the Windows caveat: [`AGENTS.md`](AGENTS.md)). + +### 7. Purge phantoms + +Verify every referenced tool actually exists and every hook actually runs — +e.g. there is no `asciidoctor-lint` gem; AsciiDoc is checked via +`asciidoctor --failure-level` plus Vale for prose. A hook that silently checks +nothing is worse than no hook. + +### 8. Apply server-side protection, then delete `setup/` + +After the first push and one green CI run (the `lint` check must exist), +run the one-time scripts from [`setup/README.md`](setup/README.md) with +admin + `gh`: + +```pwsh +pwsh -NoProfile -File setup/Protect-MainBranch.ps1 +pwsh -NoProfile -File setup/Enable-RepoSecurity.ps1 +``` + +They create the merge-queue ruleset on the default branch and enable the +server-side security settings. Then delete the `setup/` folder — it has +served its purpose. + +## Verify the migration + +- `pre-commit run --all-files` passes locally. +- A test PR shows the `lint` check running scoped to the diff, and merging + routes through the merge queue (full run at the gate). +- The editor surfaces the same findings the commit hook enforces. + +Anti-pattern this migration removes: local hook logic and CI workflows +re-implementing "the same" checks separately, which drift apart. One +orchestrator, one source.