diff --git a/lib/repo-doc-sync.js b/lib/repo-doc-sync.js index 76b75dd..45120eb 100644 --- a/lib/repo-doc-sync.js +++ b/lib/repo-doc-sync.js @@ -46,8 +46,11 @@ function counts(projectRoot) { function expectedSurface(projectRoot) { const version = packageVersion(projectRoot); const surfaceCounts = counts(projectRoot); + const published = read(projectRoot, 'USERS.md') + .includes(`latest published release is v${version}`); return { version, + published, counts: surfaceCounts, surface: `${surfaceCounts.skills} skills, ${surfaceCounts.agents} agents`, commandSurface: `${surfaceCounts.skills} slash commands`, @@ -88,6 +91,11 @@ function checkDefinitions(projectRoot) { { safeFix: true, reason: 'user support source version mirrors package version' }), makeCheck('architecture-version', 'ARCHITECTURE.md', `STABLE v${expected.version}`, { safeFix: true, reason: 'architecture release marker mirrors package version' }), + ...(expected.published + ? [makeCheck('architecture-publication-status', 'ARCHITECTURE.md', + `STABLE v${expected.version} published release`, + { safeFix: true, reason: 'published versions must not retain release-candidate status' })] + : []), makeCheck('architecture-surface', 'ARCHITECTURE.md', `Core: ${expected.surface}, ${expected.workflowSurface}`, { safeFix: true, reason: 'architecture surface mirrors repository counts' }), @@ -187,7 +195,13 @@ function safeFixContent(relPath, text, expected) { `The current source version is v${expected.version}`); case 'ARCHITECTURE.md': return replaceOnce( - replaceOnce(text, /STABLE v[0-9]+\.[0-9]+\.[0-9]+/g, `STABLE v${expected.version}`), + replaceOnce( + text, + /STABLE v[0-9]+\.[0-9]+\.[0-9]+(?: (?:release candidate|published release))?/g, + expected.published + ? `STABLE v${expected.version} published release` + : `STABLE v${expected.version}` + ), /Core: [0-9]+ skills, [0-9]+ agents, [0-9]+ workflows/g, `Core: ${expected.surface}, ${expected.workflowSurface}` ); diff --git a/scripts/test-repo-doc-sync.js b/scripts/test-repo-doc-sync.js index 7104ca7..6cd6563 100644 --- a/scripts/test-repo-doc-sync.js +++ b/scripts/test-repo-doc-sync.js @@ -85,6 +85,22 @@ test('run applies only safe mechanical updates and leaves narrative docs stale', assert(result.after.prose.some((check) => check.path === 'RELEASE.md')); }); +test('published versions cannot retain release-candidate architecture status', () => { + const tmp = mkFixture(); + writeRel(tmp, 'USERS.md', + 'The current source version is v9.8.7, and the latest published release is v9.8.7.\n'); + writeRel(tmp, 'ARCHITECTURE.md', + 'STABLE v9.8.7 release candidate\nCore: 4 skills, 2 agents, 1 workflows\n'); + + const before = repoDocSync.detect(tmp); + assert(before.stale.some((check) => check.id === 'architecture-publication-status')); + + repoDocSync.run(tmp, { log: false }); + const architecture = readRel(tmp, 'ARCHITECTURE.md'); + assert(architecture.includes('STABLE v9.8.7 published release')); + assert(!architecture.includes('release candidate')); +}); + test('run writes a Godpowers repo-doc sync log', () => { const tmp = mkFixture(); repoDocSync.run(tmp);