fix: carry verified storage capability and deterministic Canvas checks

This commit is contained in:
haelyra
2026-10-11 12:49:24 -04:00
6 changed files with 113 additions and 15 deletions
+28
View File
@@ -350,6 +350,34 @@ test(`unverified staging directory identity preserves ${foreign ? 'foreign conte
}
for (const rollback of [false, true]) {
test(`${rollback ? 'rollback' : 'snapshot'} rejects unsupported hardlink storage before initializing history`, fixture => {
const { skillDir, versionsDir } = fixture;
if (rollback) {
fs.mkdirSync(versionsDir);
fs.writeFileSync(path.join(versionsDir, 'v1.md'), '# Saved target\n');
}
const linkSync = fs.linkSync;
const primary = Object.assign(new Error('Injected unsupported hard links'), { code: 'EOPNOTSUPP' });
fs.linkSync = () => { throw primary; };
try {
assert.throws(() => rollback ? versioning.rollbackTo(skillDir, 1) : versioning.createVersion(skillDir), error =>
/requires hardlink-capable storage/.test(error.message) && error.primaryError === primary);
} finally {
fs.linkSync = linkSync;
}
assert.equal(fs.readFileSync(path.join(skillDir, 'SKILL.md'), 'utf8'), '# Original\n');
assert.equal(fs.existsSync(versioning.getEvolutionDir(skillDir)), false);
if (rollback) {
assert.deepEqual(fs.readdirSync(versionsDir), ['v1.md']);
assert.equal(fs.readFileSync(path.join(versionsDir, 'v1.md'), 'utf8'), '# Saved target\n');
} else assert.equal(fs.existsSync(versionsDir), false);
assert.equal(fs.readdirSync(skillDir).filter(name => name.startsWith('.snapshot-')).length, 0);
const snapshot = versioning.createVersion(skillDir);
assert.equal(snapshot.version, rollback ? 2 : 1);
});
}
test('successful rollback snapshots restored content and retains earlier targets for another rollback', fixture => {
const { skillDir } = fixture;
versioning.createVersion(skillDir);
+26 -13
View File
@@ -1267,20 +1267,33 @@ async function main(suite = createTestRunner()) {
const bound = await staleCanvas.listen(0);
const opened = jsonBody(await request(bound.port, 'POST', '/api/sessions', { body: { file: staleArtifact } }));
await request(bound.port, 'POST', `/api/session/${opened.key}/typing`, { body: { state: 'typing' } });
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'typing');
await new Promise(resolve => setTimeout(resolve, 60));
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'waiting');
// Keep real HTTP transitions, but advance their activity clock explicitly:
// loaded runners can exceed the expiry between two HTTP round trips.
const originalNow = Date.now;
let now = originalNow();
Date.now = () => now;
try {
await request(bound.port, 'POST', `/api/session/${opened.key}/typing`, { body: { state: 'typing' } });
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'typing');
now += 19;
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'typing');
now += 1;
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'waiting');
// An abandoned agent decays to queued so the human is never told a
// stalled session is still being worked on.
await request(bound.port, 'POST', `/api/session/${opened.key}/typing`, { body: { state: 'thinking' } });
await request(bound.port, 'POST', `/api/session/${opened.key}/feedback`, {
body: { items: [{ kind: 'chat', text: 'still there?' }] }
});
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'thinking');
await new Promise(resolve => setTimeout(resolve, 60));
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'queued');
// An abandoned agent decays to queued so the human is never told a
// stalled session is still being worked on.
await request(bound.port, 'POST', `/api/session/${opened.key}/typing`, { body: { state: 'thinking' } });
await request(bound.port, 'POST', `/api/session/${opened.key}/feedback`, {
body: { items: [{ kind: 'chat', text: 'still there?' }] }
});
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'thinking');
now += 39;
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'thinking');
now += 1;
assert.strictEqual(staleCanvas.presenceFor(opened.key), 'queued');
} finally {
Date.now = originalNow;
}
await closeStaleCanvas();
});