sneakoscope 0.7.37 → 0.7.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli/main.mjs +3 -1
- package/src/core/fsx.mjs +1 -1
- package/src/core/version-manager.mjs +35 -9
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sneakoscope",
|
|
3
3
|
"displayName": "ㅅㅋㅅ",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.38",
|
|
5
5
|
"description": "Sneakoscope Codex: database-safe Codex CLI/App harness with Team, Goal, AutoResearch, TriWiki, and Honest Mode.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",
|
package/src/cli/main.mjs
CHANGED
|
@@ -2043,9 +2043,11 @@ async function selftest() {
|
|
|
2043
2043
|
if (!firstVersionBump.ok || firstVersionBump.version !== '0.1.1' || !firstVersionBump.changed) throw new Error('selftest failed: first version bump did not advance patch version');
|
|
2044
2044
|
const bumpedPackage = await readJson(path.join(versionTmp, 'package.json'));
|
|
2045
2045
|
const bumpedLock = await readJson(path.join(versionTmp, 'package-lock.json'));
|
|
2046
|
+
const bumpedChangelog = await safeReadText(path.join(versionTmp, 'CHANGELOG.md'));
|
|
2046
2047
|
if (bumpedPackage.version !== '0.1.1' || bumpedLock.version !== '0.1.1' || bumpedLock.packages[''].version !== '0.1.1') throw new Error('selftest failed: package lock versions not synced');
|
|
2048
|
+
if (!bumpedChangelog.includes('## [0.1.1]') || !bumpedChangelog.includes('automatic SKS version guard')) throw new Error('selftest failed: version bump did not sync changelog section');
|
|
2047
2049
|
const firstCached = await runProcess('git', ['diff', '--cached', '--name-only'], { cwd: versionTmp, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
2048
|
-
if (!firstCached.stdout.includes('package.json') || !firstCached.stdout.includes('package-lock.json')) throw new Error('selftest failed: version files not staged');
|
|
2050
|
+
if (!firstCached.stdout.includes('package.json') || !firstCached.stdout.includes('package-lock.json') || !firstCached.stdout.includes('CHANGELOG.md')) throw new Error('selftest failed: version files not staged');
|
|
2049
2051
|
await runProcess('git', ['commit', '--no-verify', '-m', 'first versioned commit'], { cwd: versionTmp, timeoutMs: 15000, maxOutputBytes: 64 * 1024 });
|
|
2050
2052
|
await writeJsonAtomic(versionStatus.state_path, { schema_version: 1, last_version: '0.1.5', updated_at: nowIso(), pid: process.pid, changed: true });
|
|
2051
2053
|
await writeTextAtomic(path.join(versionTmp, 'CHANGELOG.md'), 'collision selftest\n');
|
package/src/core/fsx.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
|
|
8
|
-
export const PACKAGE_VERSION = '0.7.
|
|
8
|
+
export const PACKAGE_VERSION = '0.7.38';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
|
|
@@ -108,15 +108,17 @@ export async function bumpProjectVersion(root, opts = {}) {
|
|
|
108
108
|
pkg.version = formatSemver(target);
|
|
109
109
|
await writeJsonAtomic(pkgPath, pkg);
|
|
110
110
|
}
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
111
|
+
const targetVersion = formatSemver(target);
|
|
112
|
+
const sourceVersion = await syncSourcePackageVersion(root, targetVersion);
|
|
113
|
+
const changelog = await syncChangelogVersionSection(root, targetVersion);
|
|
114
|
+
const synced = await syncPackageLockVersions(root, targetVersion);
|
|
115
|
+
const staged = await stageVersionFiles(root, [pkgPath, ...synced.files, ...sourceVersion.files, ...changelog.files]);
|
|
114
116
|
if (!staged.ok) return { ok: false, reason: 'git_add_version_files_failed', stderr: staged.stderr };
|
|
115
117
|
if (statePath) {
|
|
116
118
|
await writeJsonAtomic(statePath, {
|
|
117
119
|
schema_version: 1,
|
|
118
|
-
last_version:
|
|
119
|
-
previous_version: pkg.version ===
|
|
120
|
+
last_version: targetVersion,
|
|
121
|
+
previous_version: pkg.version === targetVersion && !changed ? formatSemver(current) : formatSemver(current),
|
|
120
122
|
updated_at: nowIso(),
|
|
121
123
|
pid: process.pid,
|
|
122
124
|
bump: policy.bump || DEFAULT_BUMP,
|
|
@@ -125,19 +127,19 @@ export async function bumpProjectVersion(root, opts = {}) {
|
|
|
125
127
|
}
|
|
126
128
|
await writeJsonAtomic(path.join(root, '.sneakoscope', 'version', 'last.json'), {
|
|
127
129
|
schema_version: 1,
|
|
128
|
-
version:
|
|
130
|
+
version: targetVersion,
|
|
129
131
|
previous_version: formatSemver(current),
|
|
130
132
|
changed,
|
|
131
|
-
synced_files: [...synced.relative_files, ...sourceVersion.relative_files],
|
|
133
|
+
synced_files: [...synced.relative_files, ...sourceVersion.relative_files, ...changelog.relative_files],
|
|
132
134
|
staged_files: staged.relative_files,
|
|
133
135
|
updated_at: nowIso()
|
|
134
136
|
}).catch(() => {});
|
|
135
137
|
return {
|
|
136
138
|
ok: true,
|
|
137
139
|
changed,
|
|
138
|
-
version:
|
|
140
|
+
version: targetVersion,
|
|
139
141
|
previous_version: formatSemver(current),
|
|
140
|
-
synced_files: [...synced.relative_files, ...sourceVersion.relative_files],
|
|
142
|
+
synced_files: [...synced.relative_files, ...sourceVersion.relative_files, ...changelog.relative_files],
|
|
141
143
|
staged_files: staged.relative_files,
|
|
142
144
|
lock_scope: git.common_dir
|
|
143
145
|
};
|
|
@@ -230,6 +232,26 @@ async function syncSourcePackageVersion(root, version) {
|
|
|
230
232
|
return { files: [file], relative_files: [path.relative(root, file)] };
|
|
231
233
|
}
|
|
232
234
|
|
|
235
|
+
async function syncChangelogVersionSection(root, version) {
|
|
236
|
+
const file = path.join(root, 'CHANGELOG.md');
|
|
237
|
+
let text = await readFileMaybe(file);
|
|
238
|
+
const date = nowIso().slice(0, 10);
|
|
239
|
+
const sectionRe = new RegExp(`^##\\s+\\[${escapeRegExp(version)}\\]\\s+-\\s+\\d{4}-\\d{2}-\\d{2}\\s*$`, 'm');
|
|
240
|
+
if (sectionRe.test(text)) return { files: [], relative_files: [] };
|
|
241
|
+
|
|
242
|
+
if (!text.trim()) text = '# Changelog\n\n## [Unreleased]\n\n';
|
|
243
|
+
if (!/^#\s+Changelog\s*$/m.test(text)) text = `# Changelog\n\n${text.replace(/^\s+/, '')}`;
|
|
244
|
+
if (!/^##\s+\[Unreleased\]\s*$/m.test(text)) {
|
|
245
|
+
text = text.replace(/^#\s+Changelog\s*$/m, (title) => `${title}\n\n## [Unreleased]`);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const managedSection = `\n## [${version}] - ${date}\n\n### Fixed\n\n- Keep release metadata aligned after the automatic SKS version guard advances the package version.\n`;
|
|
249
|
+
const next = text.replace(/^##\s+\[Unreleased\]\s*$/m, (heading) => `${heading}\n${managedSection}`);
|
|
250
|
+
if (next === text) return { files: [], relative_files: [] };
|
|
251
|
+
await writeTextAtomic(file, next);
|
|
252
|
+
return { files: [file], relative_files: [path.relative(root, file)] };
|
|
253
|
+
}
|
|
254
|
+
|
|
233
255
|
async function stageVersionFiles(root, files) {
|
|
234
256
|
const existing = [];
|
|
235
257
|
for (const file of files) if (await exists(file)) existing.push(path.relative(root, file));
|
|
@@ -238,6 +260,10 @@ async function stageVersionFiles(root, files) {
|
|
|
238
260
|
return { ok: result.code === 0, relative_files: existing, stderr: result.stderr };
|
|
239
261
|
}
|
|
240
262
|
|
|
263
|
+
function escapeRegExp(value) {
|
|
264
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
265
|
+
}
|
|
266
|
+
|
|
241
267
|
function parseSemver(value) {
|
|
242
268
|
const match = String(value || '').trim().match(/^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/);
|
|
243
269
|
if (!match) return null;
|