fix(6): retire validate.ts/verify.cjs cooperating-sibling, fix W007/phaseVariants/W006 drift via generator (#156)
* test(6): reproduce W007 + phaseVariants + W006 drift between CJS verify and SDK validate Adds tests/6-validate-cjs-drift-regression.test.cjs with 5 RED tests covering the three drift items from issue #6 between verify.cjs (Check 8) and validate.ts (Check 8): 1. W007 activeDiskPhases — verify.cjs uses diskPhases (includes archived) for W007; archived phase "1" absent from current ROADMAP fires false W007. validate.ts: activeDiskPhases (active phasesDir only) correctly excludes archives. 2. phaseVariants() normalization — ROADMAP says "01A", disk has "1A-foo". verify.cjs parseInt("01A")=1 → padded "01" (drops letter suffix) → miss. validate.ts phaseVariants("01A") = {"01A","1A","01A"} → "1A" matched. Both W006 and W007 fire as false positives in verify.cjs. 3. W006 letter-suffix padding mismatch — ROADMAP says "3B", disk has "03B-foo". verify.cjs parseInt("3B")=3 → padded "03" (drops "B") → diskPhases.has("03B") missed. W006 and W007 fire as false positives. All 5 tests RED on origin/main. Will turn GREEN after generator + verify.cjs migration. References: - Issue #6 (open-gsd/get-shit-done-redux) — maintainer acceptance criteria: "Port all three items to verify.cjs; add parity tests confirming identical output for all three cases on both paths" - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) — precedent for the generator pattern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(6): add sdk/scripts/gen-validate.mjs generator Extracts phaseVariants() from sdk/dist/query/validate.js via brace-balanced source-text parsing (phaseVariants is a closure inside validateHealth, not a module export, so Function.prototype.toString() is unavailable). Emits get-shit-done/bin/lib/validate.generated.cjs with three pure helpers: - phaseVariants(phase): normalized Set of padded/unpadded/letter-suffix variants - buildRoadmapPhaseVariants(content): {roadmapPhases, roadmapPhaseVariants} - buildNotStartedPhaseVariants(content): Set of unchecked-phase variants These three helpers directly address the three drift items in issue #6. Follows the gen-phase-lifecycle-policy.mjs extraction pattern from PR #154. References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) — generator pattern precedent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(6): add sdk/scripts/check-validate-fresh.mjs freshness check Mirrors check-phase-lifecycle-policy-fresh.mjs from PR #154: imports buildValidateCjs() directly, regenerates in-memory, and diffs against the committed validate.generated.cjs. Exits 1 if stale (CI gate). References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) — precedent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(6): emit validate.generated.cjs from validate.ts Generated by: node sdk/scripts/gen-validate.mjs Exports three pure helpers extracted from sdk/src/query/validate.ts Check 8: - phaseVariants(phase): Set of normalized variants {"01A","1A"} etc. - buildRoadmapPhaseVariants(content): {roadmapPhases, roadmapPhaseVariants} - buildNotStartedPhaseVariants(content): Set of unchecked-phase variants Freshness check: node sdk/scripts/check-validate-fresh.mjs → FRESH References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(6): migrate verify.cjs to consume validate.generated.cjs helpers (GREEN) Check 8 in verify.cjs now uses three generated helpers from validate.generated.cjs: 1. buildRoadmapPhaseVariants(roadmapContent) — replaces hand-rolled roadmapPhases Set. Produces both roadmapPhases (raw, for W006 message) and roadmapPhaseVariants (all variants, for W007 membership check). Fixes false W007 for letter-suffix phases with padding mismatch. 2. activeDiskPhases — now uses collectDiskPhases() WITHOUT forEachArchivedPhaseToken. W007 iterates activeDiskPhases, not diskPhases, so archived phases absent from current ROADMAP no longer trigger false W007. 3. buildNotStartedPhaseVariants(roadmapContent) — replaces raw+parseInt-padded notStartedPhases population. Uses phaseVariants() expansion so zero-padded letter-suffix unchecked entries (e.g. "03B") correctly suppress W006 for their un-padded counterpart ("3B") and vice versa. 4. phaseVariants() in W006 loop — replaces parseInt-padded disk-existence check. "3B" now matches disk dir "03B-foo" via variant expansion. Also updates test fixture for drift item 1 to use two milestone archives (v1.0 + v1.1), accurately reproducing the scenario where forEachArchivedPhaseToken walks ALL archives while getActiveMilestoneArchiveDir returns only the most recent one. All 5 tests GREEN. Confirmed RED on pre-fix code (git stash test). References: - Issue #6 (open-gsd/get-shit-done-redux) — maintainer acceptance criteria: "Port all three items to verify.cjs; add parity tests confirming identical output" - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) — generator pattern precedent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * ci(6): wire validate freshness check into test workflow Adds 'SDK generated validate artifact drift check' step to .github/workflows/test.yml, mirroring the pattern used by all PR #154 generator freshness checks. Runs on ubuntu-latest/node-24 only (same as other artifact drift checks). Placement: after workstream-name-policy check, before Shared Module hand-sync drift check. References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) — precedent Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(6): wire gen:validate into sdk/package.json, root package.json, and allowlist sdk/package.json: adds gen:validate and check:validate-fresh npm scripts. package.json: adds check:validate-fresh script (mirrors other check:*-fresh entries). scripts/shared-module-handsync-allowlist.json: updates verify.cjs justification to note that Check 8 W006/W007 helpers are now generated from validate.ts via gen-validate.mjs (issue #6), with freshness check at check-validate-fresh.mjs. References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs(6): amend ADR-3524 — validate.ts now uses generator pattern Adds 2026-05-23 amendment section to docs/adr/3524-cjs-sdk-hard-seam.md documenting: - Generator/artifact/freshness-check/CI paths - Three drift items resolved (W007 activeDiskPhases, phaseVariants normalization, W006 unchecked-phase variant skip) - phaseVariants extraction technique (brace-balanced source-text parsing) - Parity test coverage (5 tests, RED→GREEN) - Allowlist classification preserved (cooperating-sibling) References: - Issue #6 (open-gsd/get-shit-done-redux) - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md) - PR #154 (issue #4) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(6): add changeset fragment for validate.ts/verify.cjs generator migration Touches get-shit-done/bin/lib/validate.generated.cjs and verify.cjs which match USER_FACING_PREFIXES. Required by the fix-template checklist + the changeset-lint CI workflow. Refs #6 #156 * docs(6): register validate.generated.cjs in INVENTORY + manifest INVENTORY parity test demanded a row for the new generated CJS surface and a matching entry in INVENTORY-MANIFEST.json. Headline count bumped from 74 → 75. Refs #6 --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-05-21",
|
||||
"generated": "2026-05-23",
|
||||
"families": {
|
||||
"agents": [
|
||||
"gsd-advisor-researcher",
|
||||
@@ -325,6 +325,7 @@
|
||||
"template.cjs",
|
||||
"uat.cjs",
|
||||
"validate-command-router.cjs",
|
||||
"validate.generated.cjs",
|
||||
"verify-command-router.cjs",
|
||||
"verify.cjs",
|
||||
"workstream-inventory-builder.generated.cjs",
|
||||
|
||||
@@ -361,7 +361,7 @@ The `gsd-planner` agent is decomposed into a core agent plus reference modules t
|
||||
|
||||
---
|
||||
|
||||
## CLI Modules (74 shipped)
|
||||
## CLI Modules (75 shipped)
|
||||
|
||||
Full listing: `get-shit-done/bin/lib/*.cjs`.
|
||||
|
||||
@@ -433,6 +433,7 @@ Full listing: `get-shit-done/bin/lib/*.cjs`.
|
||||
| `template.cjs` | Template selection and filling with variable substitution |
|
||||
| `uat.cjs` | UAT file parsing, verification debt tracking, audit-uat support |
|
||||
| `validate-command-router.cjs` | Thin CJS subcommand router adapter for `gsd-tools validate` |
|
||||
| `validate.generated.cjs` | GENERATED — CJS artifact emitted from `sdk/src/query/validate.ts` via `sdk/scripts/gen-validate.mjs`; pure phase variant normalization helpers (`phaseVariants`, `buildRoadmapPhaseVariants`, `buildNotStartedPhaseVariants`) used by `verify.cjs` for W006/W007 checks; no I/O, no async; do not edit directly |
|
||||
| `verify-command-router.cjs` | Thin CJS subcommand router adapter for `gsd-tools verify` |
|
||||
| `verify.cjs` | Plan structure, phase completeness, reference, commit validation |
|
||||
| `workstream-inventory-builder.generated.cjs` | GENERATED — pure workstream inventory projection builder; CJS artifact emitted from `sdk/src/workstream-inventory/builder.ts` via `sdk/scripts/gen-workstream-inventory-builder.mjs`; do not edit directly |
|
||||
|
||||
@@ -101,3 +101,48 @@ A top-of-file banner is auto-inserted by each generator into the emitted `.gener
|
||||
## Amendments
|
||||
|
||||
_(Append-only. Use a dated header when the decision evolves.)_
|
||||
|
||||
### 2026-05-23 — validate.ts → verify.cjs generator pattern (issue #6)
|
||||
|
||||
Three pure helpers from `sdk/src/query/validate.ts` Check 8 are now generated into
|
||||
`get-shit-done/bin/lib/validate.generated.cjs` via `sdk/scripts/gen-validate.mjs`,
|
||||
following the same I/O adapter pattern established by PR #154 (issue #4):
|
||||
|
||||
**Generator:** `sdk/scripts/gen-validate.mjs`
|
||||
**Artifact:** `get-shit-done/bin/lib/validate.generated.cjs`
|
||||
**Freshness check:** `sdk/scripts/check-validate-fresh.mjs`
|
||||
**CI:** `.github/workflows/test.yml` — "SDK generated validate artifact drift check"
|
||||
|
||||
**Three drift items resolved (issue #6):**
|
||||
|
||||
1. **W007 `activeDiskPhases`** — `verify.cjs` Check 8 previously iterated `diskPhases`
|
||||
(which includes archived milestone phases via `forEachArchivedPhaseToken`) for the W007
|
||||
check. Archived phases absent from the current ROADMAP produced false W007 warnings.
|
||||
Fix: W007 now iterates `activeDiskPhases` (from `collectDiskPhases()` only, without
|
||||
`forEachArchivedPhaseToken`), matching `validate.ts` Check 8 behavior.
|
||||
|
||||
2. **`phaseVariants()` normalization** — `verify.cjs` Check 8 used `parseInt(p).padStart(2,'0')`
|
||||
for disk-existence and roadmap-membership checks, which drops letter suffixes (e.g. "3B" →
|
||||
"03" instead of "03B"). Phase dirs with letter-suffix padding mismatches (ROADMAP "3B",
|
||||
disk "03B-foo") produced false W006 and W007. Fix: both checks now use `phaseVariants(p)`
|
||||
from the generated module, which returns the full normalized Set including letter-suffix forms.
|
||||
|
||||
3. **W006 unchecked-phase variant skip** — `verify.cjs` Check 8 built `notStartedPhases` with
|
||||
raw + `parseInt`-padded forms (drops letter suffix). `phaseVariants()` is now used instead,
|
||||
so unchecked entries like "3B" correctly suppress W006 for "03B" (and vice versa).
|
||||
|
||||
**`phaseVariants` extraction note:** `phaseVariants` is defined as a closure inside `validateHealth`
|
||||
in the compiled output (not a module-level export). It is extracted via brace-balanced source-text
|
||||
parsing from `sdk/dist/query/validate.js`, the same technique used for `escapeRegex` extraction in
|
||||
`gen-phase-lifecycle-policy.mjs`. The function is deterministic and pure: no closures over external
|
||||
state, no side effects.
|
||||
|
||||
**Parity tests:** `tests/6-validate-cjs-drift-regression.test.cjs` — 5 tests (all GREEN after fix,
|
||||
all RED on pre-fix `origin/main`). Covers each drift item with concrete fixtures:
|
||||
- Drift 1: two milestone archives (v1.0 old, v1.1 active); v1.0 phase absent from ROADMAP.
|
||||
- Drift 2: ROADMAP "01A", disk "1A-foo" — padding mismatch.
|
||||
- Drift 3: ROADMAP "3B", disk "03B-foo" — zero-padded letter-suffix mismatch.
|
||||
|
||||
**Allowlist:** `scripts/shared-module-handsync-allowlist.json` — `verify.cjs` entry updated to
|
||||
reference the generator and freshness check. Classification remains `cooperating-sibling` (verify.cjs
|
||||
is still a full implementation; only Check 8 helpers are generated).
|
||||
|
||||
Reference in New Issue
Block a user