From 57c582321bd88c99518299a6f4644e337f5a1376 Mon Sep 17 00:00:00 2001 From: PBNZ <93853627+PBNZ@users.noreply.github.com> Date: Thu, 13 Aug 2026 19:31:35 +1200 Subject: [PATCH] fix(check): planned START-HERE paths no longer fail the self-check (refs #31) A backticked map token suffixed "(planned)" declares layout the repo has not grown into yet; repokit-check.ps1 now skips its existence assertion, per the standard's own rule against pre-creating empty directories. The marker covers only the token it follows, so an unmarked broken path in the same row still fails. Documented in the-standard.md (Variance declarations, "Planned paths"), decided in ADR-0010, covered by two new smoke cases. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_013g4xpqBjwwzfqtKyEHuWUr --- CHANGELOG.md | 8 +++++ docs/CHECKPOINT.md | 10 +++--- docs/adr/0010-planned-start-here-paths.md | 32 +++++++++++++++++++ .../templates/core/scripts/repokit-check.ps1 | 25 +++++++++------ .../repo-standard/standard/the-standard.md | 6 ++++ scripts/smoke_test_repokit_check.ps1 | 18 ++++++++++- 6 files changed, 85 insertions(+), 14 deletions(-) create mode 100644 docs/adr/0010-planned-start-here-paths.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 68221f8..ef03e46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- `repokit-check.ps1` no longer fails START-HERE rows that declare planned-but-not-yet-created + paths (#31, ADR-0010): a backticked token suffixed `(planned)` skips the existence assertion + — the standard prescribes not pre-creating empty directories — while the marker covers only + the token it follows, so an unmarked broken path in the same row still fails. Documented in + the standard's *Variance declarations* (*Planned paths*) and covered by two smoke cases. + ## [0.6.0] - 2026-08-13 ### Added diff --git a/docs/CHECKPOINT.md b/docs/CHECKPOINT.md index b34f4e5..83eea62 100644 --- a/docs/CHECKPOINT.md +++ b/docs/CHECKPOINT.md @@ -4,9 +4,11 @@ Resume state: what a fresh session needs to pick this repo up. Keep every line c pre-commit checklist has the tripwire, and stale entries are worse than none. - Last updated: 2026-08-13 -- Status: DONE -- In progress: nothing — author-identity + branch-hygiene batch (#25/#26/#28, PRs #29/#30, - ADR-0009) merged and closed; release 0.6.0 cut; `delete-branch-on-merge` enabled on the repo -- Next step: paused — nothing pending +- Status: IN PROGRESS +- In progress: scaffolding field-report batch #31/#32/#33/#34 — four local branches ready for + review (`fix/31-planned-start-here-paths`, `docs/33-adopt-existing-dir-and-branding`, + `feat/32-early-licence-optin`, `feat/34-privacy-guard`; ADR-0010/0011/0012) +- Next step: review the four branches locally, push, open one PR each (`Refs #NN`), merge in + numeric order resolving trivial `CHANGELOG.md` [Unreleased] overlaps, verify each issue, close One line per fact, current state only — history lives in `CHANGELOG.md` and git. diff --git a/docs/adr/0010-planned-start-here-paths.md b/docs/adr/0010-planned-start-here-paths.md new file mode 100644 index 0000000..20b3eae --- /dev/null +++ b/docs/adr/0010-planned-start-here-paths.md @@ -0,0 +1,32 @@ +# ADR-0010: "(planned)" START-HERE paths — declare layout before it exists + +- **Status:** accepted +- **Date:** 2026-08-13 + +## Context + +Field report #31: `the-standard.md` prescribes not pre-creating empty directories ("directories +are created when first populated"), but `repokit-check.ps1` asserts that every path-like token +in the START-HERE map resolves. A row declaring a monorepo's planned component layout +(`firmware/`, `app/`) therefore failed the self-check — following one rule broke the other. The +observed workaround (rewording the row to avoid path-like tokens) hid useful, greppable path +names from the map. + +## Decision + +A per-token marker, not a per-row or label-allowlist rule: a backticked token immediately +followed by `(planned)` is skipped by the self-check's existence assertion. Chosen over the +issue's alternative (only asserting rows whose label is in the known required set) because that +would silently stop checking *every* documentation row — the existence check on declared paths +is most of the self-check's value, and the marker keeps it on by default with an explicit, +visible opt-out per token. The marker covers only the token it follows, so one planned entry +cannot mask an unrelated broken path in the same row. Documented in the standard's *Variance +declarations* (as *Planned paths*), covered by two smoke cases (pass without the directory; +unmarked broken path beside a planned one still fails). + +## Consequences + +Planned layout is declarable in the map with real path tokens, and the check stays honest: an +existing-path claim is still verified everywhere the marker is absent. The marker is trust-based +— nothing forces its removal when the path becomes real; a stale `(planned)` on an existing path +merely skips a check that would pass, so the failure mode is benign. diff --git a/plugins/repokit/skills/new-repo/templates/core/scripts/repokit-check.ps1 b/plugins/repokit/skills/new-repo/templates/core/scripts/repokit-check.ps1 index d94b30e..192eb48 100644 --- a/plugins/repokit/skills/new-repo/templates/core/scripts/repokit-check.ps1 +++ b/plugins/repokit/skills/new-repo/templates/core/scripts/repokit-check.ps1 @@ -5,7 +5,9 @@ # Verifies the repo's *declared* structure actually exists (see the RepoKit standard, # "Variance declarations"): # 1. AGENTS.md (canonical agent file) exists; CLAUDE.md (loader shim) exists and imports it. -# 2. Every path named in the START-HERE map resolves to an existing file or directory. +# 2. Every path named in the START-HERE map resolves to an existing file or directory. A +# token suffixed "(planned)" declares a path the repo has not grown into yet and is +# skipped — the standard says not to pre-create empty directories. # 3. A changelog exists at the default location or a declared one. # 4. An ADR directory (or declared substitute) exists. # 5. A resume-state row exists in the START-HERE map (docs/CHECKPOINT.md or a declared @@ -71,14 +73,19 @@ if ($dataRows.Count -eq 0) { } else { Pass "START-HERE map found ($($dataRows.Count) rows)" foreach ($row in $dataRows) { - $tokens = [regex]::Matches($row, '`([^`]+)`') | ForEach-Object { $_.Groups[1].Value } - foreach ($tok in $tokens) { - if ($tok.Contains('/') -and $tok -match '^[A-Za-z0-9_.-]+(/[A-Za-z0-9_.-]+)*/?$') { - if (Test-Path -LiteralPath (Join-Path $RepoRoot $tok.TrimEnd('/'))) { - Pass "START-HERE path resolves: $tok" - } else { - Fail "START-HERE path does not resolve: $tok" - } + foreach ($m in [regex]::Matches($row, '`([^`]+)`')) { + $tok = $m.Groups[1].Value + if (-not ($tok.Contains('/') -and $tok -match '^[A-Za-z0-9_.-]+(/[A-Za-z0-9_.-]+)*/?$')) { continue } + # "(planned)" right after the closing backtick marks a declared-but-not-yet-created + # path; it covers only the token it follows. + if ($row.Substring($m.Index + $m.Length) -match '^\s*\(planned\)') { + Pass "START-HERE path declared planned - not required to exist yet: $tok" + continue + } + if (Test-Path -LiteralPath (Join-Path $RepoRoot $tok.TrimEnd('/'))) { + Pass "START-HERE path resolves: $tok" + } else { + Fail "START-HERE path does not resolve: $tok" } } } diff --git a/plugins/repokit/skills/repo-standard/standard/the-standard.md b/plugins/repokit/skills/repo-standard/standard/the-standard.md index c2fa315..f66c7e4 100644 --- a/plugins/repokit/skills/repo-standard/standard/the-standard.md +++ b/plugins/repokit/skills/repo-standard/standard/the-standard.md @@ -209,6 +209,12 @@ it locally before a release, or add one CI line: run: ./scripts/repokit-check.ps1 ``` +**Planned paths.** A map row may name layout the repo has not grown into yet (say, a monorepo's +`firmware/` and `app/` components) — declaring intent is useful, and the standard says *not* to +pre-create empty directories. Suffix the backticked token with `(planned)` — +`` `firmware/` (planned) `` — and the self-check skips that token's existence assertion. The +marker covers only the token it follows; remove it when the path becomes real. + **Adoption marker — retro-adopted repos.** A repo that adopts the standard mid-life snaps to the conventions at the adoption commit; nothing before it should ever be re-flagged by an audit. Declare the compliance horizon with one line in `AGENTS.md`, right under the START-HERE map: diff --git a/scripts/smoke_test_repokit_check.ps1 b/scripts/smoke_test_repokit_check.ps1 index 0eab61f..ac3ec5b 100644 --- a/scripts/smoke_test_repokit_check.ps1 +++ b/scripts/smoke_test_repokit_check.ps1 @@ -6,7 +6,9 @@ # FAILS on each drift case from the retrospective (refs #16): missing shim, non-importing shim, # broken START-HERE path, missing changelog, missing ADR dir, missing resume-state row — plus # the author-identity cases (refs #25/#26): handle + noreply passes, a real name or personal -# email fails, and a declared variance row switches the check off. +# email fails, and a declared variance row switches the check off — plus the "(planned)" +# marker cases (refs #31): a planned path needn't exist, and the marker covers only the token +# it follows. $ErrorActionPreference = 'Stop' @@ -113,6 +115,20 @@ Assert-Check 'declared author-identity variance passes' $d 0 Assert-Check 'web-flow identity passes' (New-GitFixture 'GitHub' 'noreply@github.com') 0 Assert-Check 'real name on the web-flow email fails' (New-GitFixture 'Octo Cat' 'noreply@github.com') 1 +# --- "(planned)" marker cases (refs #31) ----------------------------------------------------- + +# 14. A row may declare planned-but-not-yet-created paths — the standard says not to pre-create +# empty directories, so the marker skips the existence assertion. +$d = New-Fixture +Add-Content (Join-Path $d 'AGENTS.md') '| Planned component layout | `firmware/` (planned), `app/` (planned) |' +Assert-Check 'planned paths pass without existing' $d 0 + +# 15. The marker covers only the token it follows — an unmarked broken path in the same row +# still fails. +$d = New-Fixture +Add-Content (Join-Path $d 'AGENTS.md') '| Mixed row | `missing/dir` and `future/dir` (planned) |' +Assert-Check 'unmarked broken path beside a planned one still fails' $d 1 + if ($script:failed -gt 0) { Write-Host "smoke_test_repokit_check: $script:failed failure(s)"; exit 1 } Write-Host 'smoke_test_repokit_check: all cases passed' # Explicit success exit: the last negative case leaves $LASTEXITCODE = 1, and GitHub's pwsh