// Scripted model responses only. Production tools, authority and evidence writers do the work. import { readFileSync, writeFileSync, mkdirSync, existsSync, appendFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; import { DatabaseSync } from 'node:sqlite'; import { startBroker } from '../../../bus/src/runtime.mjs'; import { createRequestStore } from '../../../bus/src/request-store.mjs'; import { bootConfig, loadSystem } from '../../src/config.mjs'; import { loadBusiness, resolveInstance, systemVars } from '../../../organization/src/index.mjs'; import { limitHit } from '../../../organization/src/launch.mjs'; import { tasksAdapter } from '../../../tasks/src/adapter.mjs'; import { createGitSocket } from '../../src/git-socket.mjs'; import { pushWorking, fetchReview } from '../../../harness/src/git-tools.mjs'; import { callTool } from '../../../harness/src/tools.mjs'; import { toolServer } from '../../../harness/src/runner.mjs'; import { buildBundle } from '../../../harness/src/bundle.mjs'; import { HARNESS } from '../../../harness/tests/helpers.mjs'; import { ensureCheckouts } from '../../../seat/src/checkout.mjs'; import { newRun, Registry, readSessions, writeSessionFile, workspaceDir } from '../../../seat/src/session.mjs'; import { startTimeOf } from '../../src/host.mjs'; import { git } from '../../../project/tests/prd-fixture.mjs'; export const REQUIREMENT = 'REQ-POMO-1'; export const PROPOSAL = 'Agent proposal: 25-minute work, 5-minute break, start/pause/reset, a phase-end visual and audible cue after a user gesture. One offline HTML file, no network or external assets.'; export const HTML = ` Pomodoro

Pomodoro

Work

25:00

`; // Executed independently by coder and reviewer against the actual HTML bytes. export function verifyHTML(bytes) { if (!bytes.includes('25:00') || /https?:\/\/|]+src=|]+href=/i.test(bytes)) throw new Error('offline acceptance failed'); return 'Passed offline single-file checks, 25/5 proposal, start/pause/reset and phase-end cue; browser acceptance is recorded separately by the integration gate.'; } const TIMER_TEST = `import test from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; import vm from 'node:vm'; test('approved offline timer starts, pauses, resumes, changes phase and resets',()=>{ const bytes=readFileSync(new URL('./pomodoro.html',import.meta.url),'utf8'); assert.doesNotMatch(bytes,/https?:\\/\\//); const elements=Object.fromEntries(['clock','phase','cue','start','pause','reset'].map(id=>[id,{textContent:'',addEventListener(_,fn){this.click=fn;}}])); let now=0,tick;const context={document:{querySelector:s=>elements[s.slice(1)],addEventListener(){}},window:{},Date:{now:()=>now},setInterval:fn=>{tick=fn;}}; vm.runInNewContext(bytes.match(/', "document.addEventListener('keydown',e=>{if(e.key.toLowerCase()==='r')document.querySelector('#reset').click();});") : boundHTML; if (!existsSync(join(clone, path)) || readFileSync(join(clone, path), 'utf8') !== expected) { git(clone, 'checkout', '-qb', 'pomodoro-' + s.request.slice(0, 8)); mkdirSync(dirname(join(clone, path)), { recursive: true }); writeFileSync(join(clone, path), expected); writeFileSync(join(clone, dirname(path), 'pomodoro.test.mjs'), TIMER_TEST); verifyHTML(readFileSync(join(clone, path), 'utf8')); const tested = await run(process.execPath, ['--test', join(dirname(path), 'pomodoro.test.mjs')], { cwd: clone, env: { PATH: process.env.PATH, TMPDIR: process.env.TMPDIR } }); appendFileSync(join(root, 'coder-tests.log'), tested.stdout); git(clone, 'add', '--', dirname(path)); git(clone, 'commit', '--author', 'coder ', '-qm', 'Build the approved offline Pomodoro'); } const commit = git(clone, 'rev-parse', 'HEAD'), branch = git(clone, 'branch', '--show-current'); const pushed = rows('action.allowed', task).find(e => e.body.action === 'git.push.working' && e.body.commit === commit); if (!pushed) await tool('coder', 'push_working', { task_ref: task, project: s.project, branch }); if (!rows('review.requested', task).some(e => e.body.commit === commit)) await tool('coder', 'request_review', { task_ref: task, commit, to: 'reviewer' }); await tool('pm', 'advance_request', { request: s.request, revision: s.revision, op: 'review' }); continue; } if (s.phase === 'review') { await refreshGit(); await launch('reviewer'); const task = s.tasks[0], review = rows('review.requested', task).at(-1); if (!rows('review.verdict', task).some(e => e.body.request === review.id)) { const fetched = await tool('reviewer', 'fetch_review', { task_ref: task, request: review.id }); const path = `products/${s.project}/pomodoro.html`; const bytes = git(fetched.clone, 'show', `${fetched.commit}:${path}`); const results = verifyHTML(bytes); git(fetched.clone, 'checkout', '--detach', fetched.commit); const tested = await run(process.execPath, ['--test', join(dirname(path), 'pomodoro.test.mjs')], { cwd: fetched.clone, env: { PATH: process.env.PATH, TMPDIR: process.env.TMPDIR } }); appendFileSync(join(root, 'reviewer-tests.log'), tested.stdout); const verification = await tool('reviewer', 'write_record', { project: s.project, path: 'docs/verification-' + s.request.slice(0, 8) + '.md', record: JSON.stringify({ version: 1, task_ref: task, review_request: review.id, commit: fetched.commit, results }) }); await tool('reviewer', 'review_verdict', { task_ref: task, request: review.id, verdict: 'approve', body: JSON.stringify({ verification_record: { path: verification.path, commit: verification.commit }, results }) }); } await tool('pm', 'advance_request', { request: s.request, revision: s.revision, op: 'deliver' }); continue; } if (s.phase === 'delivery') { const task = s.tasks[0], verdict = rows('review.verdict', task).at(-1), record = JSON.parse(store.get('SELECT body FROM messages WHERE id=?', verdict.body.message).body.split('\n\n').slice(1).join('\n\n')).verification_record; if (!rows('task.closed', task).length) await tool('pm', 'task_close', { task_ref: task, verdict: verdict.id }); await tool('pm', 'deliver_request', { request: s.request, revision: s.revision, op: 'delivery', task_ref: task, verdict: verdict.id, path: `products/${s.project}/pomodoro.html`, verification_record: record }); continue; } if (s.phase === 'complete') { const messages = store.all('SELECT * FROM messages WHERE business=? ORDER BY seq', 'demo'); if (!messages.some(m => m.from_role === 'chief' && m.to_role === 'assistant' && m.in_reply_to === s.source_message)) { await tool('chief', 'send_message', { to: 'assistant', in_reply_to: s.source_message, body: 'Reviewed local HTML is ready: ' + JSON.stringify(s.delivery_evidence) }); } if (!messages.some(m => m.from_role === 'assistant' && m.to_role === 'human' && m.in_reply_to === s.source_message)) { await tool('assistant', 'send_message', { to: 'human', in_reply_to: s.source_message, body: 'Download the reviewed Pomodoro HTML. ' + s.delivery }); } await bus.requestLifecycle.recover(); return state(); } throw new Error('unexpected phase ' + s.phase); } throw new Error('fixture made no bounded progress'); } const handlers = { start: ({ text, attach }) => startRequest(text, attach), drive, arm: ({ point }) => { armed = point; return true; }, console: async ({ verb, args, subject }) => { const cap = bus.broker.bindConsole({ business: 'demo', human: 'jason', subject }); try { const result = await bus.broker.request(cap, { verb, args }); if (verb === 'decision.resolve.console') await checkpoint('selection-resolution'); return result; } finally { bus.broker.disconnect(cap); } }, human: ({ verb, args }) => call('human', verb, args), close: async () => { for (const server of servers) await new Promise(resolve => server.close(resolve)); await socket?.close(); db.close(); await bus.close(); return true; }, }; process.on('message', async m => { try { const value = await handlers[m.op](m.args ?? {}); process.send({ id: m.id, value }); if (m.op === 'close') process.disconnect(); } catch (e) { process.send({ id: m.id, error: e.code ?? e.message, detail: e.stack }); } }); process.send({ ready: true }); }