import test from 'node:test'; import assert from 'node:assert/strict'; import { mkdtempSync, rmSync, writeFileSync, readFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { execFileSync } from 'node:child_process'; import { fixture, git } from './spec-fixtures.mjs'; test('current citation is recorded; docs commits do not stale it and a new spec never reopens settlement', async t => { const f = await fixture(t); const d = await f.raise({ project: 'stack', spec_path: 'spec/north-star.md', spec_commit: f.commit }); const stored = f.store.get('SELECT spec_path,spec_commit FROM decisions WHERE id=?', d.id); assert.equal(stored.spec_path, 'spec/north-star.md'); assert.equal(stored.spec_commit, f.commit); f.call(f.human, 'decision.resolve', { id: d.id, choice: 'yes' }); await f.call(f.coder, 'record.write', { project: 'stack', path: 'docs/design.md', record: '# Design\n' }); await f.raise({ project: 'stack', spec_path: 'spec/north-star.md', spec_commit: f.commit }); f.save('# Updated\n'); assert.equal(f.store.get('SELECT op FROM decision_events WHERE decision=? ORDER BY seq DESC', d.id).op, 'resolved'); assert.equal(f.store.get('SELECT spec_commit FROM decisions WHERE id=?', d.id).spec_commit, f.commit); assert.throws(() => f.call(f.human, 'decision.resolve', { id: d.id, choice: 'no' }), /decision-closed/); }); test('stale, unconfirmed, missing and partial spec citations refuse without inserting a decision', async t => { const f = await fixture(t), citation = { project: 'stack', spec_path: 'spec/north-star.md', spec_commit: f.commit }; const current = f.save('# Current\n'); await assert.rejects(f.raise(citation), { code: 'stale-spec' }); f.save('# Agent\n', 'coder.coder'); await assert.rejects(f.raise({ ...citation, spec_commit: git(f.repo, 'rev-parse', 'HEAD') }), { code: 'spec-unconfirmed' }); for (const args of [{ project: 'stack', spec_path: citation.spec_path }, { project: 'stack', spec_commit: current }, { spec_path: citation.spec_path, spec_commit: current }, { ...citation, spec_path: 'docs/design.md' }]) await assert.rejects(f.raise(args), { code: 'invalid-spec-citation' }); git(f.repo, 'rm', '--', 'spec/north-star.md'); git(f.repo, '-c', 'user.name=jason', '-c', 'user.email=jason@mosaic.invalid', 'commit', '-m', 'Missing'); await assert.rejects(f.raise(citation), { code: 'project-read-missing' }); assert.equal(f.store.get('SELECT count(*) n FROM decisions').n, 0); }); test('uncited raises retain their synchronous path and spec read is available to any held role in its business', async t => { const f = await fixture(t); const d = f.raise({}); assert.equal(typeof d.then, 'undefined'); assert.equal(f.store.get('SELECT spec_commit FROM decisions WHERE id=?', d.id).spec_commit, null); const spec = await f.call(f.reviewer, 'spec.read', { project: 'stack', commit: f.commit }); assert.equal(spec.commit, f.commit); assert.equal(spec.confirmed, true); assert.equal(spec.content, readFileSync(join(f.repo, 'spec/north-star.md'), 'utf8')); await assert.rejects(f.call(f.reviewer, 'spec.read', { project: 'other' }), { code: 'project-not-declared' }); await assert.rejects(f.call(f.reviewer, 'spec.read', { project: 'stack', business: 'other' }), { code: 'invalid-request' }); await assert.rejects(f.call(f.human, 'spec.read', { project: 'stack' }), { code: 'agent-required' }); }); test('record writes bind the session author, require authority and refuse spec and impersonation paths', async t => { const f = await fixture(t); const written = await f.call(f.coder, 'record.write', { project: 'stack', path: 'docs/result.md', record: '# Result\n' }); assert.equal(git(f.repo, 'show', '-s', '--format=%an', written.commit), 'coder.coder'); assert.equal(git(f.repo, 'show', '--format=', '--name-only', written.commit), 'docs/result.md'); await assert.rejects(f.call(f.coder, 'record.write', { project: 'stack', path: 'spec/north-star.md', record: '# Bad' }), { code: 'project-spec-human-only' }); await assert.rejects(f.call(f.coder, 'record.write', { project: 'stack', path: 'docs/x.md', record: '# Bad', author: { definition: 'human', instance: 'jason' } }), { code: 'invalid-request' }); await assert.rejects(f.call(f.reviewer, 'record.write', { project: 'stack', path: 'docs/x.md', record: '# Bad' }), { code: 'decision-required' }); const event = f.store.all("SELECT body FROM events WHERE kind='action.allowed'").map(r => JSON.parse(r.body)).find(r => r.action === 'record.write'); assert.equal(event.commit, written.commit); assert.equal(event.path, 'docs/result.md'); });