Repository Public
1/** Run logic of the chaos suite: 6 steps mixing every effect class. Effects are files under ctx.workspaceAbs. */2import fs from 'node:fs';3import path from 'node:path';4import type { RunLogic } from '../../src/index.js';56export const STEP_NAMES = ['s0', 's1', 's2', 's3', 's4', 's5'];78export function makeChaosLogic(opts: { assumed: boolean }): RunLogic {9 return async (ctx) => {10 const dir = ctx.workspaceAbs;11 const count = (i: number): void => fs.appendFileSync(path.join(dir, 'exec.log'), `s${i}\n`);1213 const a = await ctx.step({ kind: 'calc', name: 's0', effect: 'pure', request: { x: 20 } }, async () => {14 count(0);15 return { result: { v: 42 } };16 });17 await ctx.emit('system.notice', { mark: 'after-s0' });18 const b = await ctx.step({ kind: 'tool_call', name: 's1', effect: 'read', request: { file: 'input.txt' } }, async () => {19 count(1);20 return { result: { content: fs.readFileSync(path.join(dir, 'input.txt'), 'utf8') } };21 });22 const c = await ctx.step({ kind: 'tool_call', name: 's2', effect: 'idempotent_write', request: { content: 'hello' } }, async (idem) => {23 count(2);24 fs.mkdirSync(path.join(dir, 'idem'), { recursive: true });25 fs.writeFileSync(path.join(dir, 'idem', idem), 'hello'); // keyed by idem_key: a re-execution overwrites26 return { result: { written: true } };27 });28 const ledger = path.join(dir, 'ledger.txt');29 const d = await ctx.step(30 {31 kind: 'tool_call', name: 's3', effect: 'non_idempotent', request: { to: 'ledger' },32 reconcile: async (_req, idem) => {33 const lines = fs.existsSync(ledger) ? fs.readFileSync(ledger, 'utf8').split('\n') : [];34 return lines.includes(idem) ? { done: true, result: { ledgered: true } } : { done: false };35 },36 },37 async (idem) => {38 count(3);39 fs.appendFileSync(ledger, `${idem}\n`);40 return { result: { ledgered: true } };41 },42 );43 await ctx.emit('system.notice', { mark: 'after-s3' });44 const e = await ctx.step(45 {46 kind: 'tool_call', name: 's4', effect: 'non_idempotent', request: { send: 'mail' },47 ...(opts.assumed ? { assumedResult: () => ({ sent: true }) as Record<string, unknown> } : {}),48 },49 async (idem): Promise<{ result: Record<string, unknown> }> => {50 count(4);51 fs.appendFileSync(path.join(dir, 'unprobed.txt'), `${idem}\n`);52 return { result: { sent: true } };53 },54 );55 const f = await ctx.step({ kind: 'model_call', name: 's5', effect: 'model_call', request: { prompt: [a, b, c, d, e] } }, async () => {56 count(5);57 return { result: { text: 'ok' }, usage: { usd: 0.01, inputTokens: 10, outputTokens: 5 } };58 });59 await ctx.emit('system.notice', { mark: 'end' });60 return { status: 'done', summary: 'chaos run complete', payload: { a, b, c, d, e, f }, artifacts: [], evidence: [], openQuestions: [] };61 };62}63