From 0c9d7c91cc32f83a53232304f5246dc3636ccdd2 Mon Sep 17 00:00:00 2001 From: Juber Shaikh <40266375+CodeWithJuber@users.noreply.github.com> Date: Sat, 11 Jul 2026 22:36:26 +0400 Subject: [PATCH] fix(release): bump.mjs keeps ROADMAP's "Now" marker in sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every auto-release bumped package.json/CHANGELOG/etc. but left ROADMAP.md's "## Now" version marker untouched, so `forge docs check`'s roadmap-freshness guard went stale after the very release that should have satisfied it — requiring a manual follow-up fix each time (as just happened twice, for v0.12.0 and v0.12.1). applyBump() now rewrites just that one line via the new bumpRoadmapNow(), leaving every other version mention in the doc alone. Also corrects the current drift: ROADMAP said v0.12.1, package.json is already v0.12.2, so `forge docs check` was failing on master. --- ROADMAP.md | 2 +- scripts/bump.mjs | 21 +++++++++++++++++++++ test/bump.test.js | 24 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index e7fdccf..60d873b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7,7 +7,7 @@ every tool. This is where that brain is headed. Direction, not promises — shaped by the two field reports this project is grounded in (the SDLC pain-point map and the ecosystem landscape). Open a Discussion to weigh in. -## Now (`master`, v0.12.1) +## Now (`master`, v0.12.2) The substrate is fully graded — decision math replaces every keyword heuristic: exemplar k-NN routing, entropy secret detection, noisy-OR goal-drift over paths **and** the identifiers a file diff --git a/scripts/bump.mjs b/scripts/bump.mjs index 626e85d..0e5e4e7 100644 --- a/scripts/bump.mjs +++ b/scripts/bump.mjs @@ -21,6 +21,8 @@ * package.json, package-lock.json (root "version" + packages[""].version), * .claude-plugin/plugin.json, .codex-plugin/plugin.json, * CITATION.cff (version + date-released), landing/index.html (display string), + * ROADMAP.md ("## Now" marker version, so `forge docs check`'s roadmap-freshness + * guard never trails a release this same script just cut), * CHANGELOG.md ([Unreleased] rotated under "## [X.Y.Z] - " + compare links). * * Prints ONLY the new version on stdout (diagnostics go to stderr) so callers can @@ -239,6 +241,18 @@ export function rotateChangelog(changelog, newVersion, prevVersion, date) { return out; } +/** + * Rewrites the version in ROADMAP.md's "## Now" marker (e.g. "## Now (`master`, v0.12.0)") + * to `newVersion`. Only that line is touched — other version mentions elsewhere in the + * document (e.g. "Shipped — Substrate v2 ... v0.5.0") are left alone. No-op (returns + * `roadmap` unchanged) if there's no "## Now" heading to update. + */ +export function bumpRoadmapNow(roadmap, newVersion) { + return roadmap.replace(/^(##\s+Now\b[^\n]*)$/m, (line) => + line.replace(/v\d+\.\d+(?:\.\d+)?/, `v${newVersion}`), + ); +} + // --------------------------------------------------------------------------- // File mutation // --------------------------------------------------------------------------- @@ -326,6 +340,13 @@ export function applyBump(root, currentVersion, newVersion, date) { write(landingRel, landing.replace(/forgekit v\d+\.\d+\.\d+/g, `forgekit v${newVersion}`)); } + const roadmapRel = "ROADMAP.md"; + const roadmap = readIfExists(path.join(root, roadmapRel)); + if (roadmap !== null) { + const updated = bumpRoadmapNow(roadmap, newVersion); + if (updated !== roadmap) write(roadmapRel, updated); + } + const clRel = "CHANGELOG.md"; const changelog = readIfExists(path.join(root, clRel)); if (changelog !== null) { diff --git a/test/bump.test.js b/test/bump.test.js index 3333ae8..76e0170 100644 --- a/test/bump.test.js +++ b/test/bump.test.js @@ -5,6 +5,7 @@ import path from "node:path"; import { test } from "node:test"; import { applyBump, + bumpRoadmapNow, changelogBody, collectVersions, computeNext, @@ -192,6 +193,26 @@ test("setUnreleasedBody fills an empty [Unreleased] and rotateChangelog then acc assert.match(rotated, /## \[0\.5\.0\] - 2026-07-11\n\n### Added\n\n- a new thing/); }); +// --------------------------------------------------------------------------- +// ROADMAP "Now" marker +// --------------------------------------------------------------------------- + +test("bumpRoadmapNow updates only the Now marker's version", () => { + const roadmap = + "# Roadmap\n\n## Now (`master`, v0.12.0)\n\nSome text.\n\n" + + "## Shipped — Substrate v2 (v0.5.0)\n\nOlder text mentioning v0.5.0 again.\n"; + const out = bumpRoadmapNow(roadmap, "0.12.1"); + assert.match(out, /## Now \(`master`, v0\.12\.1\)/); + // untouched: version mentions outside the "## Now" line survive verbatim + assert.match(out, /## Shipped — Substrate v2 \(v0\.5\.0\)/); + assert.match(out, /Older text mentioning v0\.5\.0 again\./); +}); + +test("bumpRoadmapNow is a no-op when there's no Now heading", () => { + const roadmap = "# Roadmap\n\nNo heading here.\n"; + assert.equal(bumpRoadmapNow(roadmap, "1.0.0"), roadmap); +}); + // --------------------------------------------------------------------------- // CHANGELOG rotation // --------------------------------------------------------------------------- @@ -280,6 +301,7 @@ function makeFixture() { w(".codex-plugin/plugin.json", '{\n "name": "fixture",\n "version": "0.4.0"\n}\n'); w("CITATION.cff", 'cff-version: 1.2.0\nversion: 0.4.0\ndate-released: "2026-07-06"\n'); w("landing/index.html", '
forgekit v0.4.0 · MIT
\n'); + w("ROADMAP.md", "# Roadmap\n\n## Now (`master`, v0.4.0)\n\nSome text.\n"); w("CHANGELOG.md", CHANGELOG); return dir; } @@ -295,6 +317,7 @@ test("applyBump updates every version field in a fixture tree", () => { ".codex-plugin/plugin.json", "CHANGELOG.md", "CITATION.cff", + "ROADMAP.md", "landing/index.html", "package-lock.json", "package.json", @@ -311,6 +334,7 @@ test("applyBump updates every version field in a fixture tree", () => { assert.match(read("CITATION.cff"), /^version: 0\.5\.0$/m); assert.match(read("CITATION.cff"), /^date-released: "2026-07-07"$/m); assert.match(read("landing/index.html"), /forgekit v0\.5\.0/); + assert.match(read("ROADMAP.md"), /## Now \(`master`, v0\.5\.0\)/); assert.match(read("CHANGELOG.md"), /## \[0\.5\.0\] - 2026-07-07/); } finally { fs.rmSync(dir, { recursive: true, force: true });