* test(26): reproduce W005/W006-archived/I001 false positives in CJS validate path Issue #26 (open-gsd/get-shit-done-redux): three validation drift items from PR #3479 were hand-ported to verify.cjs via PR #3806 but never routed through the generator pattern. This means they can drift again whenever validate.ts changes. RED tests assert that validate.generated.cjs exports four new items: - phaseDirNameRe (W005 regex — /^\d{2,}(?:\.\d+)*-[\w-]+$/) - MILESTONE_ARCHIVE_DIR_RE (W006-archived — /^v\d+.*-phases$/i) - PHASE_TOKEN_FROM_DIR_RE (W006-archived — phase dir token extractor) - canonicalPlanStem (I001 — plan/summary stem canonicalization) Three of four new export tests are RED (exports missing from generated artifact). Behavioral tests (W005 no-false-positive, W006-archived no-false-positive, I001 no-false-positive) are GREEN because #3806's hand-ported fixes are present. References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6), PR #3479 (original fix), PR #3806 (hand-port). * chore(26): extend gen-validate.mjs to export W005/W006-archived/I001 helpers Issue #26 (open-gsd/get-shit-done-redux): extend gen-validate.mjs (introduced in PR #156 / issue #6) to also extract the three drift items that PR #3806 hand-ported to verify.cjs but were never routed through the generator. New helpers added to gen-validate.mjs: phaseDirNameRe (PHASE_DIR_NAME_RE) — W005 phase directory naming regex. /^\d{2,}(?:\.\d+)*-[\w-]+$/ accepts multi-digit prefixes (999.1-foo valid). Requires adding PHASE_DIR_NAME_RE as a named constant to validate.ts so it appears as an extractable identifier in the compiled output. PHASE_TOKEN_FROM_DIR_RE — W006-archived regex; extracts phase token from directory names like "64-auth-service" → "64". Used by forEachArchivedPhaseToken() and collectDiskPhases() in verify.cjs. MILESTONE_ARCHIVE_DIR_RE — W006-archived regex; matches milestone archive directory names like "v1.0-phases". Used by listMilestoneArchiveDirs(). canonicalPlanStem() — I001 PLAN/SUMMARY stem canonicalization. '68-01-scaffolding' → '68-01'. Top-level named function in compiled output. Extraction approach: PHASE_TOKEN_FROM_DIR_RE and MILESTONE_ARCHIVE_DIR_RE are module-level const assignments, extracted via extractConstRegExp() (handles both `const` and `export const` prefixes). PHASE_DIR_NAME_RE is the new named export added to validate.ts in this commit. canonicalPlanStem is a top-level function, extracted via extractTopLevelFunction() (brace-balanced). validate.ts change: inline regex in Check 6 extracted to named constant PHASE_DIR_NAME_RE (exported) and Check 6 updated to reference it. References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6). * chore(26): regenerate validate.generated.cjs with W005/W006-archived/I001 helpers Re-run of sdk/scripts/gen-validate.mjs after extending it in the preceding commit. The artifact now exports seven items (was three): New (issue #26): phaseDirNameRe — /^\d{2,}(?:\.\d+)*-[\w-]+$/ (W005 check) PHASE_TOKEN_FROM_DIR_RE — phase token extractor regex (W006-archived) MILESTONE_ARCHIVE_DIR_RE — archive dir name matcher (W006-archived) canonicalPlanStem() — PLAN/SUMMARY stem canonicalization (I001) Existing (issue #6): phaseVariants() buildRoadmapPhaseVariants() buildNotStartedPhaseVariants() Freshness check: node sdk/scripts/check-validate-fresh.mjs → "fresh". References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6). * fix(26): migrate verify.cjs W005/W006-archived/I001 call sites to generated helpers Issue #26 (open-gsd/get-shit-done-redux): three hand-maintained items in verify.cjs now consumed from validate.generated.cjs (ADR-3524 §4 adapter pattern). Changes: - Top-of-file require(): extend to also destructure phaseDirNameRe, PHASE_TOKEN_FROM_DIR_RE, MILESTONE_ARCHIVE_DIR_RE, canonicalPlanStem from validate.generated.cjs (issue #26 exports). - Remove inline PHASE_TOKEN_FROM_DIR_RE and MILESTONE_ARCHIVE_DIR_RE constants (lines ~403-404). Now sourced from generated artifact. listMilestoneArchiveDirs and forEachArchivedPhaseToken pick them up via the require() at top of file. - Check 6 (W005): replace inline regex /^\d{2,}(?:\.\d+)*-[\w-]+$/ with phaseDirNameRe from validate.generated.cjs. No behavior change. - Remove inline canonicalPlanStem() function (~8 lines). Now sourced from validate.generated.cjs. Check 7 (I001) continues to call it as before. Public API of verify.cjs unchanged. Same migration shape as PR #156's Check 8. References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6), PR #3479 (original fix), PR #3806 (hand-port that #26 supersedes). * docs(26): extend ADR-3524 2026-05-23 amendment with #26 scope Extends the existing 2026-05-23 amendment (not a new dated section) to document the W005/W006-archived/I001 generator migration introduced by issue #26. Key points documented: - Four new exports added to validate.generated.cjs (phaseDirNameRe, PHASE_TOKEN_FROM_DIR_RE, MILESTONE_ARCHIVE_DIR_RE, canonicalPlanStem) - W006-archived coverage note: both fixes were already in verify.cjs from #3806; the gap was generator coverage of the regex constants - Extraction methods: extractConstRegExp() and extractTopLevelFunction() - Parity tests: tests/26-w005-w006-i001-cjs-drift-regression.test.cjs (7 tests) - Cross-reference: issue #26 completes the validate.ts ↔ verify.cjs migration scope started by issue #6 References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6), PR #3479 (original fix), PR #3806 (hand-port). * chore(26): add changeset fragment for W005/W006-archived/I001 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. References: issue #26, ADR-3524, PR #154 (issue #4), PR #156 (issue #6).
98 lines
4.1 KiB
JavaScript
98 lines
4.1 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* GENERATED FILE — DO NOT EDIT.
|
|
*
|
|
* Source: sdk/src/query/validate.ts
|
|
* Regenerate: cd sdk && npm run gen:validate
|
|
*
|
|
* Validate Helpers — pure computation helpers and regex constants extracted from
|
|
* sdk/src/query/validate.ts. No I/O. No async. No filesystem operations.
|
|
*
|
|
* Issue #6 drift items (three helpers):
|
|
* 1. phaseVariants() — replaces parseInt-based padded/unpadded check in verify.cjs
|
|
* Check 8 (W006 disk-existence and W007 roadmap-membership checks).
|
|
* 2. buildRoadmapPhaseVariants() — replaces raw roadmapPhases set in W007 loop.
|
|
* 3. buildNotStartedPhaseVariants() — replaces raw+zero-padded notStartedPhases
|
|
* in W006 skip logic.
|
|
*
|
|
* Issue #26 drift items (four constants/helpers):
|
|
* 4. phaseDirNameRe — W005 phase directory naming regex (was inline in verify.cjs Check 6).
|
|
* 5. PHASE_TOKEN_FROM_DIR_RE — extracts phase token from dir name (was inline in
|
|
* verify.cjs forEachArchivedPhaseToken / collectDiskPhases).
|
|
* 6. MILESTONE_ARCHIVE_DIR_RE — identifies milestone archive directories (was inline).
|
|
* 7. canonicalPlanStem() — I001 PLAN/SUMMARY stem canonicalization (was inline in Check 7).
|
|
*
|
|
* I/O adapter pattern (ADR-3524 §4): pure transforms extracted from the SDK.
|
|
*
|
|
* References:
|
|
* - ADR-3524 (docs/adr/3524-cjs-sdk-hard-seam.md)
|
|
* - Issue #6 (open-gsd/get-shit-done-redux)
|
|
* - Issue #26 (open-gsd/get-shit-done-redux)
|
|
* - PR #154 (issue #4) — generator pattern precedent
|
|
* - PR #156 (issue #6) — validate.ts generator that #26 extends
|
|
*/
|
|
|
|
// ── Issue #26: regex constants (W005, W006-archived) ────────────────────────
|
|
const phaseDirNameRe = /^\d{2,}(?:\.\d+)*-[\w-]+$/;
|
|
const PHASE_TOKEN_FROM_DIR_RE = /^(?:[A-Z]{1,6}-)?(\d+[A-Z]?(?:\.\d+)*)(?:-|$)/i;
|
|
const MILESTONE_ARCHIVE_DIR_RE = /^v\d+.*-phases$/i;
|
|
|
|
// ── Issue #26: I001 canonicalization ────────────────────────────────────────
|
|
function canonicalPlanStem(stem) {
|
|
const m = stem.match(/^(\d+[A-Z]?(?:\.\d+)*-\d+)/i);
|
|
return m ? m[1] : stem;
|
|
}
|
|
|
|
// ── Issue #6: phase variant helpers (W006/W007) ──────────────────────────────
|
|
function phaseVariants(phase) {
|
|
|
|
const variants = new Set([phase]);
|
|
const dotIdx = phase.indexOf('.');
|
|
const head = dotIdx === -1 ? phase : phase.slice(0, dotIdx);
|
|
const tail = dotIdx === -1 ? '' : phase.slice(dotIdx);
|
|
const headMatch = head.match(/^(\d+)([A-Z]?)$/i);
|
|
if (!headMatch)
|
|
return variants;
|
|
const numericHead = headMatch[1];
|
|
const letterSuffix = headMatch[2] || '';
|
|
variants.add(`${String(parseInt(numericHead, 10))}${letterSuffix}${tail}`);
|
|
variants.add(`${numericHead.padStart(2, '0')}${letterSuffix}${tail}`);
|
|
return variants;
|
|
|
|
}
|
|
|
|
function buildRoadmapPhaseVariants(roadmapContent) {
|
|
const roadmapPhases = new Set();
|
|
const roadmapPhaseVariants = new Set();
|
|
const phasePattern = /#{2,4}\s*Phase\s+(\d+[A-Z]?(?:\.\d+)*)\s*:/gi;
|
|
let m;
|
|
while ((m = phasePattern.exec(roadmapContent)) !== null) {
|
|
roadmapPhases.add(m[1]);
|
|
for (const variant of phaseVariants(m[1])) roadmapPhaseVariants.add(variant);
|
|
}
|
|
return { roadmapPhases, roadmapPhaseVariants };
|
|
}
|
|
|
|
function buildNotStartedPhaseVariants(roadmapContent) {
|
|
const notStartedPhases = new Set();
|
|
const uncheckedPattern = /-\s*\[\s\]\s*\*{0,2}Phase\s+(\d+[A-Z]?(?:\.\d+)*)[:\s*]/gi;
|
|
let um;
|
|
while ((um = uncheckedPattern.exec(roadmapContent)) !== null) {
|
|
for (const variant of phaseVariants(um[1])) notStartedPhases.add(variant);
|
|
}
|
|
return notStartedPhases;
|
|
}
|
|
|
|
module.exports = {
|
|
// Issue #26 exports (W005 regex, W006-archived regex constants, I001 helper)
|
|
phaseDirNameRe,
|
|
PHASE_TOKEN_FROM_DIR_RE,
|
|
MILESTONE_ARCHIVE_DIR_RE,
|
|
canonicalPlanStem,
|
|
// Issue #6 exports (W006/W007 phase variant helpers)
|
|
phaseVariants,
|
|
buildRoadmapPhaseVariants,
|
|
buildNotStartedPhaseVariants,
|
|
};
|