/* semver — semver parse and comparison helpers shared across the site-kernel packages. Do not support pre-release / build metadata / ranges beyond simple bounds — ecosystem versions are plain x.y.z. Semver parsing is a small local implementation — no external semver dependency. RFC-1097: step 6 — compass.migrate codemod run Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order. RFC-1097: sweep — werkstatt-engine clean Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics. */ const SEMVER_RE = /^(\d+)\.(\d+)\.(\d+)$/; export function parseSemver(value: string): [number, number, number] { const m = SEMVER_RE.exec(value.trim()); if (!m) throw new Error(`not a valid x.y.z version: "${value}"`); return [Number(m[1]), Number(m[2]), Number(m[3])]; } /** -1 if a < b, 0 if equal, 1 if a > b. */ export function compareSemver(a: string, b: string): -1 | 0 | 1 { const pa = parseSemver(a); const pb = parseSemver(b); for (let i = 0; i < 3; i++) { if (pa[i] < pb[i]) return -1; if (pa[i] > pb[i]) return 1; } return 0; } export const ltSemver = (a: string, b: string): boolean => compareSemver(a, b) < 0; export const gtSemver = (a: string, b: string): boolean => compareSemver(a, b) > 0; export const eqSemver = (a: string, b: string): boolean => compareSemver(a, b) === 0; /** True when `from < v <= to` — the half-open interval migrators are selected over. */ export function inOpenClosedRange(v: string, from: string, to: string): boolean { return gtSemver(v, from) && compareSemver(v, to) <= 0; }