From 6ced5a2a69da9f4991bb67adf4a8ca9c0adb79b8 Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Fri, 21 Aug 2026 21:40:16 +0300 Subject: [PATCH 1/4] S2.4: add regression test for the spec-set gate's exit-code semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit design/30-slices.md § S2 requires a workflow-parsing test asserting the "Check the spec set" step swallows neither exit 1 nor exit 2 (no continue-on-error, no || true). The step itself already satisfies this; no test asserted it. --- tools/Test-CIWorkflow.Tests.ps1 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/Test-CIWorkflow.Tests.ps1 b/tools/Test-CIWorkflow.Tests.ps1 index ccd7c1c..d2bd93c 100644 --- a/tools/Test-CIWorkflow.Tests.ps1 +++ b/tools/Test-CIWorkflow.Tests.ps1 @@ -33,6 +33,28 @@ Describe 'CI workflow: the Run Pester tests step is authenticated (#79)' { } } +Describe 'CI workflow: the Check the spec set step does not swallow a failing exit code (S2.4)' { + + BeforeAll { + $script:WorkflowPath = Join-Path (Split-Path $PSScriptRoot -Parent) '.github/workflows/verify.yml' + $script:Lines = Get-Content -LiteralPath $script:WorkflowPath + } + + It 'the "Check the spec set" step carries neither continue-on-error nor a swallowed exit code' { + $stepIndex = ($script:Lines | Select-String -Pattern '- name: Check the spec set').LineNumber + $stepIndex | Should -Not -BeNullOrEmpty + + $nextStepIndex = ($script:Lines | Select-String -Pattern '^\s*- name:' | + Where-Object { $_.LineNumber -gt $stepIndex } | + Select-Object -First 1).LineNumber + $endIndex = if ($nextStepIndex) { $nextStepIndex - 1 } else { $script:Lines.Count } + $stepBody = $script:Lines[($stepIndex - 1)..($endIndex - 1)] -join "`n" + + $stepBody | Should -Not -Match 'continue-on-error' + $stepBody | Should -Not -Match '\|\|\s*true' + } +} + Describe 'CI workflow: design-state pin ancestry is evaluable' { BeforeAll { From bcd8fec59d282dc2907704d2d223ce78d4c44c53 Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Fri, 21 Aug 2026 21:47:28 +0300 Subject: [PATCH 2/4] Record verification gate results for PR #27 /verify against slice/S2: parse-check and companion-split pass; Pester suite and design-state check fail on pre-existing design/state-index.md staleness unrelated to this PR; spec-set gate did not run (no provisional-register region yet, S5's territory). --- .claude/verify-report.json | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/.claude/verify-report.json b/.claude/verify-report.json index a4f742e..d8b23ac 100644 --- a/.claude/verify-report.json +++ b/.claude/verify-report.json @@ -1,29 +1,29 @@ { "gates": [ - { - "name": "Parse-check PowerShell scripts", - "status": "Passed", - "detail": "Parsed every *.ps1 under the repository with [System.Management.Automation.Language.Parser]::ParseFile. No parse errors." - }, - { - "name": "Run Pester tests", - "status": "Passed", - "detail": "Invoke-Pester -Path tools -Output Detailed -PassThru\nTests completed in 110.75s\nTests Passed: 280, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0" - }, - { - "name": "Validate the core/companion split", - "status": "Passed", - "detail": "./tools/Test-Companion.ps1\nCompanion split OK - 21 core(s) checked, 0 companion file(s) present, 21 core(s) with no companion.\nState: Valid, Findings: {}, CoreCount: 21, CompanionCount: 0, AbsentCount: 21. Exit 0." - }, - { - "name": "Check the design state against the tree", - "status": "Passed", - "detail": "./tools/Test-DesignState.ps1\nFindings (0):\nReported (8, all non-blocking): [MirrorStale] work/8..work/14 - MirroredAt '394505aae8cdd82a2375a4956fc7ba93090db469' is not the current commit '66fb48a7f411a4bdbecbb6b3a846da80a95586f2'; [WorkStateDivergence] work/8: mirrored State 'OPEN' disagrees with tracker's 'CLOSED'.\nCould not evaluate (0):\nLargest closure: unit/script/test-designstate, 6122 bytes (ceiling 16384), largest contributor contract/test-designstate.\nExit code: 0." - }, - { - "name": "Check the spec set", - "status": "DidNotRun", - "reason": "./tools/Test-SpecSet.ps1 exited 2, State=NotEvaluated, Reason=RegisterAbsent, Detail='No provisional-register region exists, so provisional-number checks could not run.' Documents=8, Declarations=936, Unchecked=1." - } + { + "name": "Parse-check PowerShell scripts", + "status": "Passed", + "detail": "Every *.ps1 under the repository parsed with [System.Management.Automation.Language.Parser]::ParseFile with zero parse errors returned." + }, + { + "name": "Run Pester tests", + "status": "Failed", + "detail": "Invoke-Pester -Path tools -Output Detailed -PassThru: Tests Passed: 276, Failed: 5, Skipped: 0, Inconclusive: 0, NotRun: 0.\n\nAll 5 failures trace to one pre-existing cause unrelated to this PR: design/state-index.md's `outstanding` region is stale against the live tracker state (rank numbers shifted and issues #19/#26 are missing from the committed table), which Test-DesignState.ps1 reports as a blocking ProjectionStale finding when run against this repository's real tree. Failing tests:\n\n- S11.4/S11.5 (Test-DesignState.Tests.ps1:1418): Expected $null or empty, but got @{Class=ProjectionStale; Subject=design/state-index.md#outstanding; Detail=the tree's copy of this region differs from its regeneration; Blocking=True}.\n- S12.5 (Test-DesignState.Tests.ps1:1479): Expected 0, because findings: [ProjectionStale] design/state-index.md#outstanding: the tree's copy of this region differs from its regeneration; could not evaluate:, but got 1.\n- S7.9 (Test-DesignState.Tests.ps1:1486): Expected 0, but got 1 (ProjectionStale finding count).\n- S18.6 (Test-DesignState.Tests.ps1:1553): Expected 0, but got 1 (same ProjectionStale cause surfacing through the EnforcementUnevidenced restore path).\n- S7.3 (Update-DesignProjection.Tests.ps1:397): Expected '?? .claude/session-costs.tsv', but got @(' M design/state-index.md', '?? .claude/session-costs.tsv') — running the real (non-DryRun) projector against this repository rewrites design/state-index.md's outstanding region, which is the same staleness the other four failures detect.\n\nThe rewrite this last test performs was reverted from the working tree both times it was reproduced (git checkout -- design/state-index.md); it is not part of this PR's diff." + }, + { + "name": "Validate the core/companion split", + "status": "Passed", + "detail": "./tools/Test-Companion.ps1: Companion split OK - 21 core(s) checked, 0 companion file(s) present, 21 core(s) with no companion. State: Valid. Exit code 0." + }, + { + "name": "Check the design state against the tree", + "status": "Failed", + "detail": "./tools/Test-DesignState.ps1 exit code 1.\n\nFindings (1):\n [ProjectionStale] design/state-index.md#outstanding: the tree's copy of this region differs from its regeneration\n\nThis is the same pre-existing tracker/projection drift as the Pester failures above — design/state-index.md's outstanding table has not been regenerated since GitHub project ranks moved and issues #19/#26 were opened. It also reports 10 non-blocking MirrorStale/WorkStateDivergence findings (work/8 through work/26) for the same reason: WorkRef mirrors were last stamped at an earlier commit. None of this touches .github/workflows/verify.yml, the file this PR (S2) changes." + }, + { + "name": "Check the spec set", + "status": "DidNotRun", + "reason": "./tools/Test-SpecSet.ps1 returned State: NotEvaluated, Reason: RegisterAbsent, Detail: 'No provisional-register region exists, so provisional-number checks could not run.' Exit code 2. Pre-existing — the provisional-register region is later slices' (S5's) territory, not S2's." + } ] } From 9ba4f5099c5131bf26ecacefafbeebc2bd102384 Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Fri, 21 Aug 2026 21:57:27 +0300 Subject: [PATCH 3/4] Regenerate design/state-index.md's outstanding projection afb4cf0 updated 8 WorkRef records (rank changes, issues #19/#26 added) but never re-ran Update-DesignProjection.ps1, leaving the outstanding region stale against them since that commit. This is a pure projection regenerate - no hand-authored content changed. Clears the ProjectionStale finding that was failing Test-DesignState.ps1 and 5 Pester tests on main. --- design/state-index.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/design/state-index.md b/design/state-index.md index f6c78b5..97b80c2 100644 --- a/design/state-index.md +++ b/design/state-index.md @@ -152,10 +152,12 @@ This document is a navigation view generated from `design/state/`. Edit the reco | Rank | Issue | Title | Criteria | Mirrored at | |---|---|---|---|---| | 1 | #8 | S1 — The spec set is read end to end, or the run stops and points at the line | S1.1, S1.2, S1.3, S1.4, S1.5, S1.6, S1.7, S1.8, S1.9, S1.10 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 2 | #9 | S2 — Every push runs the checks | S2.1, S2.2, S2.3, S2.4, S2.5 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 3 | #10 | S3 — The two documents stop being able to disagree about the types they both describe | S3.1, S3.2, S3.3, S3.4, S3.5, S3.6, S3.7, S3.8, S3.9, S3.10 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 4 | #11 | S4 — Every reference resolves, and every claim about the engine repository pins a commit | S4.1, S4.2, S4.3, S4.4, S4.5, S4.6 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 5 | #12 | S5 — Every provisional number says why it is deferred and what would settle it | S5.1, S5.2, S5.3, S5.4, S5.5, S5.6 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 6 | #13 | S6 — Everything the game keeps in state is counted, and told what it must say | S6.1, S6.2, S6.3, S6.4, S6.5 | `394505aae8cdd82a2375a4956fc7ba93090db469` | -| 7 | #14 | S7 — The missing lifecycles are written | S7.1, S7.2, S7.3 | `394505aae8cdd82a2375a4956fc7ba93090db469` | +| 9 | #9 | S2 — Every push runs the checks | S2.1, S2.2, S2.3, S2.4, S2.5 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 10 | #10 | S3 — The two documents stop being able to disagree about the types they both describe | S3.1, S3.2, S3.3, S3.4, S3.5, S3.6, S3.7, S3.8, S3.9, S3.10 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 11 | #11 | S4 — Every reference resolves, and every claim about the engine repository pins a commit | S4.1, S4.2, S4.3, S4.4, S4.5, S4.6 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 12 | #12 | S5 — Every provisional number says why it is deferred and what would settle it | S5.1, S5.2, S5.3, S5.4, S5.5, S5.6 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 13 | #13 | S6 — Everything the game keeps in state is counted, and told what it must say | S6.1, S6.2, S6.3, S6.4, S6.5 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 14 | #14 | S7 — The missing lifecycles are written | S7.1, S7.2, S7.3 | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 19 | #19 | Restore missing design-state closure records | — | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | +| 26 | #26 | Read-SpecSetIndex fails closed incorrectly for a shallow fixture path | — | `14a48c1a615cf682dc7e532eba983c49e6abc65d` | From b7853d9c5ae4d226d0e3626697c47bf68f5ab161 Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Fri, 21 Aug 2026 21:59:23 +0300 Subject: [PATCH 4/4] Record verification gate results for PR #27 (post state-index fix) Parse-check, Pester (281/281), companion split, and design-state now all pass at 9ba4f50. Check the spec set still exits 2 (RegisterAbsent) by contract design (SS5) - not a defect, and not this PR's to resolve. --- .claude/verify-report.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.claude/verify-report.json b/.claude/verify-report.json index d8b23ac..3622986 100644 --- a/.claude/verify-report.json +++ b/.claude/verify-report.json @@ -7,8 +7,8 @@ }, { "name": "Run Pester tests", - "status": "Failed", - "detail": "Invoke-Pester -Path tools -Output Detailed -PassThru: Tests Passed: 276, Failed: 5, Skipped: 0, Inconclusive: 0, NotRun: 0.\n\nAll 5 failures trace to one pre-existing cause unrelated to this PR: design/state-index.md's `outstanding` region is stale against the live tracker state (rank numbers shifted and issues #19/#26 are missing from the committed table), which Test-DesignState.ps1 reports as a blocking ProjectionStale finding when run against this repository's real tree. Failing tests:\n\n- S11.4/S11.5 (Test-DesignState.Tests.ps1:1418): Expected $null or empty, but got @{Class=ProjectionStale; Subject=design/state-index.md#outstanding; Detail=the tree's copy of this region differs from its regeneration; Blocking=True}.\n- S12.5 (Test-DesignState.Tests.ps1:1479): Expected 0, because findings: [ProjectionStale] design/state-index.md#outstanding: the tree's copy of this region differs from its regeneration; could not evaluate:, but got 1.\n- S7.9 (Test-DesignState.Tests.ps1:1486): Expected 0, but got 1 (ProjectionStale finding count).\n- S18.6 (Test-DesignState.Tests.ps1:1553): Expected 0, but got 1 (same ProjectionStale cause surfacing through the EnforcementUnevidenced restore path).\n- S7.3 (Update-DesignProjection.Tests.ps1:397): Expected '?? .claude/session-costs.tsv', but got @(' M design/state-index.md', '?? .claude/session-costs.tsv') — running the real (non-DryRun) projector against this repository rewrites design/state-index.md's outstanding region, which is the same staleness the other four failures detect.\n\nThe rewrite this last test performs was reverted from the working tree both times it was reproduced (git checkout -- design/state-index.md); it is not part of this PR's diff." + "status": "Passed", + "detail": "Invoke-Pester -Path tools -Output Detailed -PassThru: Tests Passed: 281, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0. The 5 failures present at 6ced5a2/bcd8fec were a single pre-existing cause (design/state-index.md's outstanding region stale against the live tracker after afb4cf0 updated WorkRef records without re-running the projector) and were cleared by 9ba4f50, which regenerates that projection. That commit changes only the projected `outstanding` table, no hand-authored content." }, { "name": "Validate the core/companion split", @@ -17,13 +17,13 @@ }, { "name": "Check the design state against the tree", - "status": "Failed", - "detail": "./tools/Test-DesignState.ps1 exit code 1.\n\nFindings (1):\n [ProjectionStale] design/state-index.md#outstanding: the tree's copy of this region differs from its regeneration\n\nThis is the same pre-existing tracker/projection drift as the Pester failures above — design/state-index.md's outstanding table has not been regenerated since GitHub project ranks moved and issues #19/#26 were opened. It also reports 10 non-blocking MirrorStale/WorkStateDivergence findings (work/8 through work/26) for the same reason: WorkRef mirrors were last stamped at an earlier commit. None of this touches .github/workflows/verify.yml, the file this PR (S2) changes." + "status": "Passed", + "detail": "./tools/Test-DesignState.ps1: Findings (0), CouldNotEvaluate (0), ExitCode 0. Largest closure: unit/script/test-designstate, 6122 bytes (ceiling 16384), largest contributor contract/test-designstate. The blocking ProjectionStale finding present before 9ba4f50 is gone." }, { "name": "Check the spec set", "status": "DidNotRun", - "reason": "./tools/Test-SpecSet.ps1 returned State: NotEvaluated, Reason: RegisterAbsent, Detail: 'No provisional-register region exists, so provisional-number checks could not run.' Exit code 2. Pre-existing — the provisional-register region is later slices' (S5's) territory, not S2's." + "reason": "./tools/Test-SpecSet.ps1 returned State: NotEvaluated, Reason: RegisterAbsent, Detail: 'No provisional-register region exists, so provisional-number checks could not run.' Exit code 2. Not a defect: design/20-contract.md's Error semantics table names RegisterAbsent as an unchecked reason that forces exit 2 by design (SS5, 'If any check is unchecked, the run exits 2 regardless of findings'). The provisional-register region is S5's territory, not S2's, and main itself has been red for this same reason since S1 added this workflow step. design/30-slices.md's own Contract question 1 already flags SS5's all-unchecked-forces-2 semantics as possibly wrong for the permanent CrossRepositoryUnresolvable case; this run surfaces a second, narrower instance (RegisterAbsent, temporary, clears when S5 lands) that the recorded question's 'S1-S3 and S5-S7 are unaffected' line did not anticipate. That is a contract question for /contract, not a code fix here." } ] }