From ae0e5ac5399ce341b254c3d31c838cf8b56bba95 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 08:02:26 +0000 Subject: [PATCH 1/2] fix: sync docs/llm-guide.md version header, wire it into version-sync The llm-guide.md "Version" header had drifted to 0.6.15 while every other version artifact was at 0.7.16, because version-sync.js and check-version-sync.js never touched it. Bring it in line with package.json and fold it into the sync/check pipeline so it can't drift silently again. --- CLAUDE.md | 1 + docs/llm-guide.md | 2 +- scripts/check-version-sync.js | 16 ++++++++++++++-- scripts/version-sync.js | 12 ++++++++++-- tests/check-version-sync.test.js | 17 +++++++++++++++++ tests/version-sync.test.js | 8 ++++++++ 6 files changed, 51 insertions(+), 5 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 38f57782a..5b8482964 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,7 @@ of these in sync: | `package.json` | `.version` ← **source of truth** | you bump it (`npm version`) | | `package-lock.json` | `.version` + `.packages[""].version` | `npm version`; checked by `check:version` (CI) | | `docs/roadmap.md` | `Current version: **X.Y.Z**` line | `version-sync`; checked by `check:version` (CI) | +| `docs/llm-guide.md` | `Version: **X.Y.Z**` header line | `version-sync`; checked by `check:version` (CI) | | `configurator/package.json` | `.version` | `version-sync`; checked by `check:version` (CI) | | `configurator/package-lock.json` | `.version` + `.packages[""].version` | `version-sync`; checked by `check:version` (CI) | | `dist/*.css` (unminified) | `/*! SLASHED vX.Y.Z */` comment header | **build-derived** — stamped from `package.json`/tag by `bundle.js`; `dist/*.css` is git-ignored, so it cannot drift. `release.yml` re-verifies the stamp before publishing | diff --git a/docs/llm-guide.md b/docs/llm-guide.md index 4759c7593..08d69c235 100644 --- a/docs/llm-guide.md +++ b/docs/llm-guide.md @@ -1,6 +1,6 @@ # Slashed Framework — LLM Reference Guide -> Version: **0.6.15** · Tokens: **686** · Prefix: `--sf-` +> Version: **0.7.16** · Tokens: **686** · Prefix: `--sf-` --- diff --git a/scripts/check-version-sync.js b/scripts/check-version-sync.js index c3910329a..a507ae3bd 100644 --- a/scripts/check-version-sync.js +++ b/scripts/check-version-sync.js @@ -6,6 +6,7 @@ // Checks: // 1. package-lock.json version (root and packages[""]) === package.json // 2. docs/roadmap.md "Current version" === package.json +// 3. docs/llm-guide.md "Version" header === package.json // // Note: configurator/src/data/api-index.generated.json no longer stores a // frameworkVersion field — the version is injected at Vite build time from the @@ -55,7 +56,18 @@ if (!m) { ); } -// 3. configurator/package.json must match package.json. +// 3. docs/llm-guide.md "Version" header must match package.json. +const llmGuide = read('docs/llm-guide.md'); +const guideMatch = llmGuide.match(/Version:\s*\*\*([^*]+)\*\*/); +if (!guideMatch) { + errors.push('docs/llm-guide.md: "Version" header not found'); +} else if (guideMatch[1].trim() !== version) { + errors.push( + `docs/llm-guide.md version "${guideMatch[1].trim()}" != package.json "${version}"`, + ); +} + +// 4. configurator/package.json must match package.json. const configPkg = JSON.parse(read('configurator/package.json')); if (configPkg.version !== version) { errors.push( @@ -63,7 +75,7 @@ if (configPkg.version !== version) { ); } -// 4. configurator/package-lock.json must match package.json. +// 5. configurator/package-lock.json must match package.json. const configLock = JSON.parse(read('configurator/package-lock.json')); if (configLock.version !== version) { errors.push( diff --git a/scripts/version-sync.js b/scripts/version-sync.js index 0b2074a4c..b1c2211b7 100644 --- a/scripts/version-sync.js +++ b/scripts/version-sync.js @@ -1,7 +1,7 @@ #!/usr/bin/env node // Propagates the version from package.json to every other artifact that must -// stay in sync: docs/roadmap.md, configurator/package.json, and both lock files -// under configurator/. +// stay in sync: docs/roadmap.md, docs/llm-guide.md, configurator/package.json, +// and both lock files under configurator/. // // Does NOT touch the root package-lock.json — that is updated by npm itself // when `npm version` runs (called by the release-it after:bump hook before this @@ -70,6 +70,14 @@ changed += sync( `roadmap version = ${version}` ) ? 1 : 0; +// ── docs/llm-guide.md ──────────────────────────────────────────────────────── +changed += sync( + 'docs/llm-guide.md', + new RegExp(`(Version:\\s*\\*\\*)${SEMVER_RE.source}(\\*\\*)`), + `$1${version}$2`, + `llm-guide version = ${version}` +) ? 1 : 0; + // ── configurator/package.json + package-lock.json ─────────────────────────── function syncJsonVersion(rel, label) { const filePath = path.join(ROOT, rel); diff --git a/tests/check-version-sync.test.js b/tests/check-version-sync.test.js index 3c594f89f..28d69dfba 100644 --- a/tests/check-version-sync.test.js +++ b/tests/check-version-sync.test.js @@ -34,6 +34,7 @@ function buildFixture(version = '1.2.3') { fs.mkdirSync(path.join(dir, 'docs')); fs.writeFileSync(path.join(dir, 'docs', 'roadmap.md'), `Current version: **${version}**\n`); + fs.writeFileSync(path.join(dir, 'docs', 'llm-guide.md'), `> Version: **${version}** · Tokens: **1**\n`); fs.mkdirSync(path.join(dir, 'configurator')); fs.writeFileSync(path.join(dir, 'configurator', 'package.json'), JSON.stringify({ version })); @@ -98,6 +99,22 @@ describe('check-version-sync failure cases', () => { assert.ok(r.stderr.includes('"Current version"'), r.stderr); }); + test('fails when docs/llm-guide.md version differs', () => { + const dir = buildFixture(); + fs.writeFileSync(path.join(dir, 'docs', 'llm-guide.md'), '> Version: **9.9.9** · Tokens: **1**\n'); + const r = runChecker(dir); + assert.equal(r.status, 1, 'expected exit 1 for mismatched llm-guide.md'); + assert.ok(r.stderr.includes('llm-guide.md version'), r.stderr); + }); + + test('fails when docs/llm-guide.md has no "Version" header', () => { + const dir = buildFixture(); + fs.writeFileSync(path.join(dir, 'docs', 'llm-guide.md'), '# LLM Guide\n\nNo version here.\n'); + const r = runChecker(dir); + assert.equal(r.status, 1, 'expected exit 1 for missing llm-guide version line'); + assert.ok(r.stderr.includes('"Version"'), r.stderr); + }); + test('fails when configurator/package.json version differs', () => { const dir = buildFixture(); fs.writeFileSync( diff --git a/tests/version-sync.test.js b/tests/version-sync.test.js index 7dde0020c..cea15ebd4 100644 --- a/tests/version-sync.test.js +++ b/tests/version-sync.test.js @@ -36,6 +36,10 @@ function buildFixture(target = '2.0.0', oldVersion = '1.2.3') { path.join(dir, 'docs', 'roadmap.md'), `# Roadmap\n\nCurrent version: **${oldVersion}**\n\nMore text.\n`, ); + fs.writeFileSync( + path.join(dir, 'docs', 'llm-guide.md'), + `# LLM Guide\n\n> Version: **${oldVersion}** · Tokens: **1** · Prefix: \`--sf-\`\n\nMore text.\n`, + ); fs.mkdirSync(path.join(dir, 'configurator')); fs.writeFileSync( @@ -69,6 +73,10 @@ describe('version-sync writer', () => { assert.match(roadmap, /Current version: \*\*2\.0\.0\*\*/, 'roadmap.md not updated'); assert.doesNotMatch(roadmap, /1\.2\.3/, 'roadmap.md still contains the old version'); + const llmGuide = fs.readFileSync(path.join(dir, 'docs', 'llm-guide.md'), 'utf8'); + assert.match(llmGuide, /Version: \*\*2\.0\.0\*\*/, 'llm-guide.md not updated'); + assert.doesNotMatch(llmGuide, /1\.2\.3/, 'llm-guide.md still contains the old version'); + assert.equal(readJson(path.join(dir, 'configurator', 'package.json')).version, '2.0.0'); const lock = readJson(path.join(dir, 'configurator', 'package-lock.json')); From cb344c89ee2cd66d4473216ee440199ba00c4708 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Jul 2026 12:49:25 +0000 Subject: [PATCH 2/2] docs: fix stale row-count in CLAUDE.md version-sync note Greptile review on #614 caught it: adding docs/llm-guide.md made six manually-synced rows, but the prose still said five. --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 5b8482964..c1a7b9111 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ of these in sync: | `dist/*.css` (unminified) | `/*! SLASHED vX.Y.Z */` comment header | **build-derived** — stamped from `package.json`/tag by `bundle.js`; `dist/*.css` is git-ignored, so it cannot drift. `release.yml` re-verifies the stamp before publishing | | Configurator UI version pill | baked in via Vite `__SLASHED_VERSION__` at build time | **build-derived** — injected from root `package.json` at Vite build; cannot drift | -The first five rows are the ones you ever sync; the last two are **build-derived** +The first six rows are the ones you ever sync; the last two are **build-derived** (regenerated from `package.json` at build time and not committed as text you edit), so `version-sync`/`check:version` intentionally don't touch them — never hand-edit them.