mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-26 18:35:05 +00:00
fix: bound snapshot allocation to safe version numbers
This commit is contained in:
2 files changed
+44
-4
No files matched your search
@@ -83,7 +83,8 @@ function parseVersionNumber(fileName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Number(match[1]);
|
||||
const version = Number(match[1]);
|
||||
return Number.isSafeInteger(version) && version >= 1 ? version : null;
|
||||
}
|
||||
|
||||
function listVersions(skillPath) {
|
||||
@@ -170,16 +171,19 @@ function getEvolutionLog(skillPath, logType) {
|
||||
|
||||
function createVersion(skillPath, options = {}) {
|
||||
const skillFilePath = ensureSkillExists(skillPath);
|
||||
ensureSkillVersioning(skillPath);
|
||||
|
||||
const versions = listVersions(skillPath);
|
||||
const versionsDir = getVersionsDir(skillPath);
|
||||
const occupiedPaths = new Set(fs.readdirSync(versionsDir));
|
||||
const occupiedPaths = new Set(fs.existsSync(versionsDir) ? fs.readdirSync(versionsDir) : []);
|
||||
let nextVersion = versions.length === 0 ? 1 : versions[versions.length - 1].version + 1;
|
||||
// Listing excludes non-files, but their paths remain user-owned and occupied.
|
||||
while (occupiedPaths.has(`v${nextVersion}.md`)) {
|
||||
while (Number.isSafeInteger(nextVersion) && occupiedPaths.has(`v${nextVersion}.md`)) {
|
||||
nextVersion += 1;
|
||||
}
|
||||
if (!Number.isSafeInteger(nextVersion)) {
|
||||
throw new Error('Skill snapshot version range is exhausted; existing snapshots were preserved');
|
||||
}
|
||||
ensureSkillVersioning(skillPath);
|
||||
const snapshotPath = path.join(versionsDir, `v${nextVersion}.md`);
|
||||
const skillContent = fs.readFileSync(skillFilePath, 'utf8');
|
||||
const createdAt = options.timestamp || new Date().toISOString();
|
||||
|
||||
@@ -66,5 +66,41 @@ test('health skips malformed amendment rows while retaining a valid pending prop
|
||||
assert.equal(report.skills.find(skill => skill.skill_id === 'demo').pending_amendments, 1);
|
||||
});
|
||||
|
||||
test('snapshot allocation ignores invalid numeric names and preserves their contents', fixture => {
|
||||
const { skillDir, versionsDir } = fixture;
|
||||
fs.mkdirSync(versionsDir);
|
||||
const names = ['v0.md', 'v9007199254740992.md', `v${'9'.repeat(80)}.md`];
|
||||
for (const name of names) fs.writeFileSync(path.join(versionsDir, name), 'preserve');
|
||||
assert.deepEqual(versioning.listVersions(skillDir), []);
|
||||
const snapshot = versioning.createVersion(skillDir);
|
||||
assert.equal(snapshot.version, 1);
|
||||
assert.equal(fs.readFileSync(snapshot.path, 'utf8'), '# Original\n');
|
||||
for (const name of names) assert.equal(fs.readFileSync(path.join(versionsDir, name), 'utf8'), 'preserve');
|
||||
});
|
||||
|
||||
test('exhausted snapshot numbering refuses creation before initializing evolution logs', fixture => {
|
||||
const { skillDir, versionsDir } = fixture;
|
||||
fs.mkdirSync(versionsDir);
|
||||
const last = path.join(versionsDir, `v${Number.MAX_SAFE_INTEGER}.md`);
|
||||
fs.writeFileSync(last, 'preserve');
|
||||
assert.throws(() => versioning.createVersion(skillDir), /snapshot version range is exhausted/);
|
||||
assert.deepEqual(fs.readdirSync(versionsDir), [`v${Number.MAX_SAFE_INTEGER}.md`]);
|
||||
assert.equal(fs.readFileSync(last, 'utf8'), 'preserve');
|
||||
assert.equal(fs.existsSync(versioning.getEvolutionDir(skillDir)), false);
|
||||
});
|
||||
|
||||
test('an occupied final safe snapshot path refuses creation while preserving the directory', fixture => {
|
||||
const { skillDir, versionsDir } = fixture;
|
||||
fs.mkdirSync(versionsDir);
|
||||
fs.writeFileSync(path.join(versionsDir, `v${Number.MAX_SAFE_INTEGER - 1}.md`), 'preserve');
|
||||
const occupied = path.join(versionsDir, `v${Number.MAX_SAFE_INTEGER}.md`);
|
||||
fs.mkdirSync(occupied);
|
||||
fs.writeFileSync(path.join(occupied, 'keep.txt'), 'preserve');
|
||||
assert.throws(() => versioning.createVersion(skillDir), /snapshot version range is exhausted/);
|
||||
assert.equal(fs.readdirSync(versionsDir).length, 2);
|
||||
assert.equal(fs.readFileSync(path.join(occupied, 'keep.txt'), 'utf8'), 'preserve');
|
||||
assert.equal(fs.existsSync(versioning.getEvolutionDir(skillDir)), false);
|
||||
});
|
||||
|
||||
console.log(`Results: Passed: ${passed}, Failed: ${failed}`);
|
||||
process.exitCode = failed > 0 ? 1 : 0;
|
||||
Reference in new issue
Block a user