@loops-adk/core 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { renderPlan, jobMeta, run, exitCodeFor, loop, agentJob, agentCheck, bodyPassed, gateJob } from './chunk-3BPU34DE.js';
2
+ import { renderPlan, jobMeta, listRuns, runsHome, readRunStatus, runEventsPath, formatEvent, run, exitCodeFor, loop, agentJob, agentCheck, bodyPassed, gateJob } from './chunk-6BDWTFOS.js';
3
3
  import './chunk-JFTXJ7I2.js';
4
4
  import './chunk-XC46B4FD.js';
5
5
  import './chunk-Y2SD7GBL.js';
@@ -474,6 +474,7 @@ async function execute(file, flags) {
474
474
  recordTo: flags.record,
475
475
  checkpoint: flags.checkpoint,
476
476
  resumeFrom: flags.resume,
477
+ supervise: flags.supervise,
477
478
  onLimit,
478
479
  maxWaitMs,
479
480
  resumeCommand
@@ -540,6 +541,15 @@ Paused at a limit. Resume with:
540
541
  );
541
542
  }
542
543
  }
544
+ function relAge(ms2) {
545
+ const s = Math.max(0, Math.round(ms2 / 1e3));
546
+ if (s < 60) return `${s}s`;
547
+ const m = Math.round(s / 60);
548
+ if (m < 60) return `${m}m`;
549
+ const h = Math.round(m / 60);
550
+ if (h < 48) return `${h}h`;
551
+ return `${Math.round(h / 24)}d`;
552
+ }
543
553
  async function main(argv = process.argv) {
544
554
  const program = new Command();
545
555
  program.name("loops").description(
@@ -587,7 +597,10 @@ async function main(argv = process.argv) {
587
597
  ).option(
588
598
  "--max-wait <dur>",
589
599
  "cap an auto/wait limit-wait (e.g. 5m, 30s); default 5m"
590
- ).option("--json", "emit NDJSON events to stdout (no TUI)").option("--no-tui", "plain line output instead of the Ink TUI").action(
600
+ ).option("--json", "emit NDJSON events to stdout (no TUI)").option("--no-tui", "plain line output instead of the Ink TUI").option(
601
+ "--supervise",
602
+ "register this run in ~/.loops/runs so `loops list`/`status`/`tail` can observe it from another process"
603
+ ).action(
591
604
  (file, flags) => execute(file, flags)
592
605
  );
593
606
  program.command("validate").argument("<file>", "a loop-definition file to check").description(
@@ -608,6 +621,102 @@ ${plan.map((l) => ` ${l}`).join("\n")}
608
621
  process.stdout.write(`${renderPlan(jobMeta(job)).join("\n")}
609
622
  `);
610
623
  });
624
+ program.command("list").alias("ls").description("list supervised runs (start one with `loops run --supervise`)").action(() => {
625
+ const runs = listRuns();
626
+ if (!runs.length) {
627
+ process.stdout.write(
628
+ `no supervised runs in ${runsHome()}
629
+ (start one with: loops run --supervise <file>)
630
+ `
631
+ );
632
+ return;
633
+ }
634
+ for (const r of runs) {
635
+ const state = r.status === "running" ? r.alive ? "running" : "dead" : r.status;
636
+ const age = relAge(Date.now() - (r.endedAt ?? r.updatedAt));
637
+ process.stdout.write(
638
+ `${r.runId.padEnd(26)} ${state.padEnd(9)} iter ${String(r.live.iteration).padStart(3)} ${age.padStart(4)} ${r.title}
639
+ `
640
+ );
641
+ }
642
+ });
643
+ program.command("status").argument("<runId>", "a run id from `loops list`").description("show a supervised run's live state and shape").action((runId) => {
644
+ const r = readRunStatus(runId);
645
+ if (!r) {
646
+ process.stderr.write(`no run "${runId}" in ${runsHome()}
647
+ `);
648
+ process.exitCode = 1;
649
+ return;
650
+ }
651
+ const state = r.status === "running" ? r.alive ? "running" : "dead (process gone)" : r.status;
652
+ const g = r.live.lastGate;
653
+ const o = r.live.lastOutcome;
654
+ const lines = [
655
+ `${r.runId} [${state}]`,
656
+ ` title: ${r.title}`,
657
+ ` cwd: ${r.cwd}`,
658
+ ` pid: ${r.pid}`,
659
+ r.live.iteration ? ` at: ${r.live.path.join(" \u203A ")} (iteration ${r.live.iteration})` : "",
660
+ g ? ` gate: ${g.which} ${g.met ? "met" : "not met"}${g.confidence != null ? ` @ ${g.confidence.toFixed(2)}` : ""}: ${g.reason}` : "",
661
+ o ? ` last: ${o.status}${o.summary ? `: ${o.summary}` : ""}` : "",
662
+ ` tokens: ${r.live.usage.inputTokens} in / ${r.live.usage.outputTokens} out (${r.live.usage.calls} calls)`
663
+ ].filter(Boolean);
664
+ process.stdout.write(`${lines.join("\n")}
665
+ `);
666
+ if (r.shape)
667
+ process.stdout.write(
668
+ `
669
+ shape:
670
+ ${renderPlan(r.shape).map((l) => ` ${l}`).join("\n")}
671
+ `
672
+ );
673
+ });
674
+ program.command("tail").argument("<runId>", "a run id from `loops list`").description("stream a supervised run's events live (Ctrl-C to stop)").action(async (runId) => {
675
+ const path2 = runEventsPath(runId);
676
+ if (!fs.existsSync(path2)) {
677
+ process.stderr.write(`no run "${runId}" in ${runsHome()}
678
+ `);
679
+ process.exitCode = 1;
680
+ return;
681
+ }
682
+ let offset = 0;
683
+ let stop = false;
684
+ const onSig = () => {
685
+ stop = true;
686
+ };
687
+ process.once("SIGINT", onSig);
688
+ for (; ; ) {
689
+ const buf = fs.readFileSync(path2, "utf8");
690
+ if (buf.length > offset) {
691
+ const chunk = buf.slice(offset);
692
+ const lastNl = chunk.lastIndexOf("\n");
693
+ if (lastNl >= 0) {
694
+ offset += lastNl + 1;
695
+ for (const line of chunk.slice(0, lastNl).split("\n")) {
696
+ if (!line.trim()) continue;
697
+ try {
698
+ process.stdout.write(`${formatEvent(JSON.parse(line))}
699
+ `);
700
+ } catch {
701
+ }
702
+ }
703
+ }
704
+ }
705
+ if (stop) break;
706
+ const st = readRunStatus(runId);
707
+ if (st && st.status !== "running") {
708
+ process.stdout.write(`\u25C2 ${st.status}
709
+ `);
710
+ break;
711
+ }
712
+ if (st && !st.alive) {
713
+ process.stdout.write("\u25C2 process gone (no terminal status)\n");
714
+ break;
715
+ }
716
+ await new Promise((res) => setTimeout(res, 200));
717
+ }
718
+ process.removeListener("SIGINT", onSig);
719
+ });
611
720
  await program.parseAsync(argv);
612
721
  }
613
722
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runtime/hub.ts","../src/runtime/signals.ts","../src/reporters.ts","../src/config.ts","../src/cli.tsx","../src/index.ts"],"names":["path","loop","z"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * A tiny synchronous fan-out so multiple consumers (stats, the TUI, a JSON\n * reporter) can each observe the same event stream. Not worth a dependency —\n * it is six lines and never the gnarly part.\n */\n\nimport type { LoopEvent } from '../core/types.ts';\n\nexport type Listener = (event: LoopEvent) => void;\n\nexport interface Hub {\n emit: Listener;\n subscribe(listener: Listener): () => void;\n}\n\nexport function createHub(): Hub {\n const listeners = new Set<Listener>();\n return {\n emit(event) {\n for (const listener of listeners) listener(event);\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n","/**\n * Early-exit wiring. Maps OS signals (Ctrl-C / SIGTERM) onto an\n * `AbortController` so a run unwinds cleanly: in-flight engine calls abort,\n * loops/dags return `aborted`, and the exit summary still prints. A second\n * Ctrl-C force-exits in case a backend ignores the abort.\n */\n\nexport interface AbortHandle {\n controller: AbortController;\n dispose: () => void;\n}\n\nexport function installSignalHandlers(): AbortHandle {\n const controller = new AbortController();\n let hits = 0;\n\n const onSignal = () => {\n hits += 1;\n if (hits === 1) controller.abort();\n else process.exit(130);\n };\n\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n return {\n controller,\n dispose() {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n },\n };\n}\n","/**\n * Non-TUI output paths: a human-readable line reporter (`--no-tui`, CI logs)\n * and a machine-readable NDJSON reporter (`--json`). Plus the exit summary,\n * shared by every mode.\n */\n\nimport pc from 'picocolors';\n\nimport type { Listener } from './runtime/hub.ts';\nimport type { LoopEvent, Outcome } from './core/types.ts';\nimport type { RunResult } from './runtime/runner.ts';\n\nconst indent = (path: string[]) => ' '.repeat(Math.max(0, path.length - 1));\nconst statusColor = (status: Outcome['status'], text: string): string =>\n status === 'pass'\n ? pc.green(text)\n : status === 'fail'\n ? pc.red(text)\n : status === 'exhausted'\n ? pc.yellow(text)\n : status === 'paused'\n ? pc.cyan(text)\n : pc.gray(text);\n\n/** Format an epoch ms as a local clock time, for \"resuming at <time>\". */\nconst clock = (ts: number): string =>\n new Date(ts).toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n\n/** Emit each event as one NDJSON line on stdout. */\nexport function jsonReporter(): Listener {\n return (event: LoopEvent) =>\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\n/** Per-loop-path accumulator, so we can print one report line per iteration. */\ninterface IterAccum {\n iteration: number;\n bodyStatus?: Outcome['status'];\n until?: { met: boolean; reason: string };\n stopOn?: { met: boolean; reason: string };\n review?: { status: Outcome['status']; summary?: string };\n tokensIn: number;\n tokensOut: number;\n}\n\n/** Compact a token count, e.g. 1234 → \"1.2k\". */\nconst tok = (n: number): string =>\n n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);\n\n/** Human-readable streaming output. Agent text streams inline; events labelled. */\nexport function plainReporter(): Listener {\n let streaming = false;\n const endStream = () => {\n if (streaming) {\n process.stdout.write('\\n');\n streaming = false;\n }\n };\n\n // Per loop path: the in-flight iteration's accumulating facts. A new\n // `loop:iteration` (or `loop:end`) for that path flushes the previous one.\n const accums = new Map<string, IterAccum>();\n const reportIteration = (key: string, indentPath: string[]): void => {\n const a = accums.get(key);\n if (!a) return;\n accums.delete(key);\n const parts: string[] = [];\n if (a.bodyStatus)\n parts.push(`body=${statusColor(a.bodyStatus, a.bodyStatus)}`);\n if (a.until)\n parts.push(`until=${a.until.met ? pc.green('met') : pc.gray('not met')}`);\n if (a.stopOn?.met) parts.push(`stopOn=${pc.red('met')}`);\n if (a.review) {\n const rv = `review=${statusColor(a.review.status, a.review.status)}`;\n parts.push(\n a.review.summary ? `${rv} ${pc.dim(`(${a.review.summary})`)}` : rv,\n );\n }\n parts.push(`${tok(a.tokensIn)}/${tok(a.tokensOut)} tok`);\n console.log(\n `${indent(indentPath)} ${pc.gray(`↳ iter ${a.iteration}:`)} ${parts.join(pc.gray(' · '))}`,\n );\n };\n\n return (event: LoopEvent) => {\n const key = event.path.join(' / ');\n switch (event.kind) {\n case 'engine:text':\n process.stdout.write(event.delta);\n streaming = true;\n return;\n case 'loop:start':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('▸ loop')} ${pc.bold(last(event.path))}${event.max ? pc.gray(` (max ${event.max})`) : ''}`,\n );\n return;\n case 'loop:iteration':\n endStream();\n reportIteration(key, event.path); // flush the previous iteration's report\n accums.set(key, {\n iteration: event.iteration,\n tokensIn: 0,\n tokensOut: 0,\n });\n console.log(\n `${indent(event.path)}${pc.gray(` iteration ${event.iteration}`)}`,\n );\n return;\n case 'loop:condition': {\n endStream();\n const a = accums.get(key);\n if (a) {\n if (event.which === 'until')\n a.until = { met: event.result.met, reason: event.result.reason };\n else if (event.which === 'stopOn')\n a.stopOn = { met: event.result.met, reason: event.result.reason };\n }\n console.log(\n `${indent(event.path)} ${pc.magenta(event.which)}: ${event.result.met ? pc.green('met') : pc.gray('not met')} — ${pc.dim(event.result.reason)}`,\n );\n return;\n }\n case 'loop:review': {\n endStream();\n const a = accums.get(key);\n if (a)\n a.review = {\n status: event.outcome.status,\n summary: event.outcome.summary,\n };\n console.log(\n `${indent(event.path)} ${pc.blue('review')}: ${statusColor(event.outcome.status, event.outcome.status)}${event.outcome.summary ? pc.dim(` — ${event.outcome.summary}`) : ''}`,\n );\n return;\n }\n case 'job:end': {\n // The loop body runs at the loop's own path; record its outcome on the\n // current iteration accumulator for that path.\n const a = accums.get(key);\n if (a) a.bodyStatus = event.outcome.status;\n return;\n }\n case 'engine:usage': {\n const a = accums.get(key);\n if (a) {\n a.tokensIn += event.usage.inputTokens;\n a.tokensOut += event.usage.outputTokens;\n }\n return;\n }\n case 'loop:end':\n endStream();\n reportIteration(key, event.path); // flush the final iteration's report\n console.log(\n `${indent(event.path)}${pc.cyan('◂ loop')} ${pc.bold(last(event.path))} → ${statusColor(event.outcome.status, event.outcome.status)} ${pc.gray(`(${event.iterations} iter)`)}`,\n );\n return;\n case 'dag:start':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('▸ dag')} ${pc.bold(last(event.path))} ${pc.gray(`[${event.nodes.join(', ')}]`)}`,\n );\n return;\n case 'dag:node':\n if (event.phase === 'start') return;\n endStream();\n console.log(\n `${indent(event.path)} ${pc.gray('node')} ${event.node}: ${event.outcome ? statusColor(event.outcome.status, event.phase === 'skip' ? 'skipped' : event.outcome.status) : event.phase}`,\n );\n return;\n case 'dag:end':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('◂ dag')} ${pc.bold(last(event.path))} → ${statusColor(event.outcome.status, event.outcome.status)}`,\n );\n return;\n case 'job:start':\n endStream();\n console.log(`${indent(event.path)} ${pc.gray('•')} ${event.label}`);\n return;\n case 'engine:tool':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.dim(`tool ${event.phase}: ${event.name}`)}`,\n );\n return;\n case 'limit:wait':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.yellow(`⏳ ${event.code.toLowerCase()}`)}: waiting ${Math.round(event.waitMs / 1000)}s, resuming at ${clock(event.resumeAt)}`,\n );\n return;\n case 'limit:pause':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.cyan(`⏸ ${event.code.toLowerCase()}`)}: ${pc.dim(event.reason)}`,\n );\n return;\n case 'log':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.dim(`[${event.level}] ${event.message}`)}`,\n );\n return;\n case 'error':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.red(`✗ ${event.code}: ${event.message}`)}`,\n );\n return;\n default:\n return;\n }\n };\n}\n\n/** The exit summary, printed once at the end in every mode. */\nexport function printSummary(result: RunResult, resumeCommand?: string): void {\n const { outcome, stats } = result;\n const line = pc.dim('─'.repeat(56));\n console.log(`\\n${line}`);\n console.log(\n `${pc.bold('Result')} ${statusColor(outcome.status, outcome.status.toUpperCase())}${outcome.confidence != null ? pc.gray(` confidence ${outcome.confidence.toFixed(2)}`) : ''}`,\n );\n if (outcome.summary) console.log(`${pc.dim('Summary')} ${outcome.summary}`);\n // A paused run is resumable; surface the exact command to continue it.\n if (outcome.status === 'paused') {\n console.log(\n resumeCommand\n ? `${pc.dim('Resume')} ${pc.cyan(resumeCommand)}`\n : `${pc.dim('Resume')} ${pc.yellow('re-run with --checkpoint <path> to make a pause resumable')}`,\n );\n }\n\n console.log(line);\n console.log(`${pc.bold('Loops')}`);\n for (const loop of stats.loops) {\n const reviews = loop.reviewsPassed + loop.reviewsFailed;\n console.log(\n ` ${loop.path || '(root)'} — ${loop.iterations} iter` +\n (reviews\n ? `, reviews ${pc.green(String(loop.reviewsPassed))}/${pc.red(String(loop.reviewsFailed))}`\n : '') +\n (loop.lastStatus\n ? ` → ${statusColor(loop.lastStatus, loop.lastStatus)}`\n : ''),\n );\n }\n if (stats.loops.length === 0) console.log(pc.dim(' (none)'));\n\n console.log(line);\n console.log(\n `${pc.bold('Usage')} ${stats.agentCalls} agent call(s), ` +\n `${pc.cyan(String(stats.totalInputTokens))} in / ${pc.cyan(String(stats.totalOutputTokens))} out tokens, ` +\n `${(stats.elapsedMs / 1000).toFixed(1)}s`,\n );\n for (const m of stats.models) {\n console.log(\n pc.dim(\n ` ${m.model}: ${m.calls} call(s), ${m.inputTokens} in / ${m.outputTokens} out`,\n ),\n );\n }\n\n if (result.budget) {\n const b = result.budget;\n const spent =\n b.remaining === 0 ? pc.red(String(b.spent)) : pc.cyan(String(b.spent));\n console.log(\n `${pc.bold('Budget')} ${spent} / ${b.limit} tokens ${pc.gray(`(${b.remaining} remaining)`)}`,\n );\n }\n\n if (stats.errors.length) {\n console.log(line);\n console.log(`${pc.bold(pc.red('Errors'))} (${stats.errors.length})`);\n for (const e of stats.errors.slice(0, 10)) {\n console.log(pc.red(` ✗ [${e.code}] ${e.path}: ${e.message}`));\n }\n }\n console.log(line);\n}\n\nfunction last(path: string[]): string {\n return path[path.length - 1] ?? '(root)';\n}\n","/**\n * The no-file path: turn CLI flags into a standard loop (worker → until →\n * review). Validated with zod so a bad invocation fails with a clear message\n * rather than odd runtime behaviour. A definition file bypasses all of this and\n * builds the `Job` directly.\n */\n\nimport ms from 'ms';\nimport { z } from 'zod';\n\nimport { loop } from './core/loop.ts';\nimport { agentJob } from './core/job.ts';\nimport { agentCheck, bodyPassed, gateJob } from './core/condition.ts';\nimport type { Job } from './core/types.ts';\nimport type { EngineName } from './engines/engine.ts';\n\nexport const FlagSpec = z.object({\n prompt: z\n .string()\n .min(\n 1,\n 'a --prompt or --prompt-file is required when no definition file is given',\n ),\n engine: z.string().optional(),\n workerModel: z.string().optional(),\n validatorModel: z.string().optional(),\n reviewerModel: z.string().optional(),\n max: z.number().int().positive().optional(),\n untilAgent: z.string().optional(),\n threshold: z.number().min(0).max(1).default(0.8),\n startAgent: z.string().optional(),\n review: z.string().optional(),\n reviewThreshold: z.number().min(0).max(1).default(0.85),\n interval: z.number().int().nonnegative().optional(),\n maxTokens: z.number().int().positive().optional(),\n});\n\nexport type FlagSpec = z.infer<typeof FlagSpec>;\n\n/** Parse a duration like `5m`, `30s`, `1h` (or a bare ms number) to ms. */\nexport function parseDuration(value: string): number {\n if (/^\\d+$/.test(value)) return Number(value);\n const out = ms(value as ms.StringValue);\n if (typeof out !== 'number' || Number.isNaN(out)) {\n throw new Error(`invalid duration: \"${value}\" (try 30s, 5m, 1h)`);\n }\n return out;\n}\n\n/** Build the standard loop from flags. Parses + validates once, here. */\nexport function buildJobFromFlags(input: z.input<typeof FlagSpec>): Job {\n const spec = FlagSpec.parse(input);\n const engine = spec.engine as EngineName | undefined;\n\n const worker = agentJob({\n label: 'worker',\n engine,\n model: spec.workerModel,\n maxTokens: spec.maxTokens,\n // On a review-restart, fold the reviewer's objection into the next prompt\n // so the retry is informed rather than a blind repeat.\n prompt: (ctx) =>\n ctx.lastReview\n ? `${spec.prompt}\\n\\nYour previous attempt was REJECTED in review: ${ctx.lastReview.summary ?? ctx.lastReview.status}. Address that specifically this time.`\n : spec.prompt,\n });\n\n const until = spec.untilAgent\n ? agentCheck({\n question: spec.untilAgent,\n threshold: spec.threshold,\n model: spec.validatorModel,\n engine,\n })\n : bodyPassed();\n\n const start = spec.startAgent\n ? agentCheck({\n question: spec.startAgent,\n threshold: 0.5,\n model: spec.validatorModel,\n engine,\n })\n : undefined;\n\n const review = spec.review\n ? gateJob(\n 'review',\n agentCheck({\n question: spec.review,\n threshold: spec.reviewThreshold,\n model: spec.reviewerModel,\n engine,\n }),\n )\n : undefined;\n\n return loop({\n name: 'main',\n body: worker,\n start,\n until,\n review,\n max: spec.max,\n delayMs: spec.interval,\n });\n}\n","/**\n * The `loops` CLI. Two ways to define a run:\n * 1. a definition file that default-exports a `Job` — full power, nesting;\n * 2. flags (`--prompt`, `--until`, `--review`, …) — the standard loop.\n *\n * Output mode: Ink TUI by default (a TTY), `--no-tui` for line logs, `--json`\n * for an NDJSON event stream. Ctrl-C / `q` aborts cleanly and still summarises.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport React from 'react';\nimport { Command } from 'commander';\nimport { z } from 'zod';\n\nimport { run, exitCodeFor } from './runtime/runner.ts';\nimport { createHub } from './runtime/hub.ts';\nimport { installSignalHandlers } from './runtime/signals.ts';\nimport { jsonReporter, plainReporter, printSummary } from './reporters.ts';\nimport { buildJobFromFlags, parseDuration } from './config.ts';\nimport { loop } from './core/loop.ts';\nimport { jobMeta, renderPlan } from './core/describe.ts';\nimport type { Job, LoopConfig } from './core/types.ts';\nimport type { EngineName, EngineOptions } from './engines/engine.ts';\n\ninterface RunFlags {\n prompt?: string;\n promptFile?: string;\n engine?: string;\n defaultModel?: string;\n workerModel?: string;\n validatorModel?: string;\n reviewerModel?: string;\n max?: string;\n until?: string;\n threshold?: string;\n start?: string;\n review?: string;\n reviewThreshold?: string;\n interval?: string;\n maxTokens?: string;\n apiKey?: string;\n cliBinary?: string;\n permissionMode?: string;\n engineArg?: string[];\n state?: string;\n budget?: string;\n record?: string;\n checkpoint?: string;\n resume?: string;\n onLimit?: string;\n maxWait?: string;\n json?: boolean;\n tui?: boolean; // commander sets false for --no-tui\n}\n\nconst ON_LIMIT_VALUES = ['auto', 'wait', 'exit-resume', 'fail'] as const;\ntype OnLimitValue = (typeof ON_LIMIT_VALUES)[number];\n\n/** The worker prompt comes from --prompt OR --prompt-file (not both). */\nfunction resolvePrompt(flags: RunFlags): string {\n if (flags.promptFile != null && flags.prompt != null) {\n throw new Error('pass either --prompt or --prompt-file, not both');\n }\n if (flags.promptFile != null) {\n const resolved = path.resolve(flags.promptFile);\n if (!fs.existsSync(resolved))\n throw new Error(`prompt file not found: ${flags.promptFile}`);\n return fs.readFileSync(resolved, 'utf8');\n }\n return flags.prompt ?? '';\n}\n\nasync function loadJob(file: string): Promise<{ job: Job; title: string }> {\n const resolved = path.resolve(file);\n if (!fs.existsSync(resolved)) {\n throw new Error(\n `loop file not found: ${file}\\n(omit the file argument to use flags mode, or run \\`loops run --help\\`)`,\n );\n }\n // The bin registers tsx's loader globally, so this plain import transforms a\n // `.loop.ts` wherever it lives — inside this package or in a consumer repo that\n // has `loops` installed. (A scoped `tsImport` only covers this package's tree,\n // which is why an out-of-tree recipe used to die on `Unexpected token 'export'`.)\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pathToFileURL(resolved).href)) as Record<string, unknown>;\n } catch (e) {\n const detail = e instanceof Error ? e.message : String(e);\n const esmHint =\n /ES Module|import statement outside a module|ERR_REQUIRE_ESM/i.test(detail)\n ? `\\n hint: the recipe's folder is not an ES module scope. Add a package.json ` +\n `with {\"type\":\"module\"} next to it (repos that use loops as a submodule already have this).`\n : '';\n throw new Error(\n `failed to load loop file ${file}:\\n ${detail}${esmHint}\\n` +\n `(the file is imported and run like \\`node <file>\\`; fix the error above, or ` +\n `run \\`loops validate ${file}\\` to check it without executing)`,\n );\n }\n const def = mod.default ?? mod.job ?? mod.loop;\n const title = path.basename(file).replace(/\\.(loop\\.)?(t|j)sx?$/, '');\n if (typeof def === 'function') return { job: def as Job, title };\n if (def && typeof def === 'object' && 'body' in def)\n return { job: loop(def as LoopConfig), title };\n throw new Error(\n `${file}: default export must be a Job (from loop()/dag()/agentJob()) or a LoopConfig`,\n );\n}\n\nfunction buildFromFlags(flags: RunFlags): Job {\n const num = (v: string | undefined) => (v == null ? undefined : Number(v));\n const prompt = resolvePrompt(flags); // outside the try so its errors aren't reported as flag-validation\n try {\n // Parsing/validation lives in buildJobFromFlags (single source of truth);\n // we just shape the raw input and translate a Zod failure into a clean error.\n return buildJobFromFlags({\n prompt,\n engine: flags.engine,\n workerModel: flags.workerModel,\n validatorModel: flags.validatorModel,\n reviewerModel: flags.reviewerModel,\n max: num(flags.max),\n untilAgent: flags.until,\n threshold: num(flags.threshold),\n startAgent: flags.start,\n review: flags.review,\n reviewThreshold: num(flags.reviewThreshold),\n interval:\n flags.interval != null ? parseDuration(flags.interval) : undefined,\n maxTokens: num(flags.maxTokens),\n });\n } catch (e) {\n if (e instanceof z.ZodError) {\n throw new Error(\n `invalid flags:\\n - ${e.issues.map((i) => i.message).join('\\n - ')}`,\n );\n }\n throw e;\n }\n}\n\nasync function execute(\n file: string | undefined,\n flags: RunFlags,\n): Promise<void> {\n const { job, title } = file\n ? await loadJob(file)\n : { job: buildFromFlags(flags), title: 'loop' };\n\n const engineOptions: EngineOptions = {};\n if (flags.defaultModel) engineOptions.defaultModel = flags.defaultModel;\n if (flags.apiKey) engineOptions.apiKey = flags.apiKey;\n if (flags.cliBinary) engineOptions.cliBinary = flags.cliBinary;\n if (flags.permissionMode)\n engineOptions.permissionMode =\n flags.permissionMode as EngineOptions['permissionMode'];\n if (flags.engineArg?.length) engineOptions.cliArgs = flags.engineArg;\n\n let state: Record<string, unknown> | undefined;\n if (flags.state) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(flags.state);\n } catch (e) {\n throw new Error(\n `--state must be valid JSON: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(\n `--state must be a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`,\n );\n }\n state = parsed as Record<string, unknown>;\n }\n\n let budget: number | undefined;\n if (flags.budget != null) {\n budget = Number(flags.budget);\n if (!Number.isFinite(budget) || budget <= 0) {\n throw new Error(\n `--budget must be a positive number of tokens, got \"${flags.budget}\"`,\n );\n }\n }\n\n let onLimit: OnLimitValue | undefined;\n if (flags.onLimit != null) {\n if (!ON_LIMIT_VALUES.includes(flags.onLimit as OnLimitValue)) {\n throw new Error(\n `--on-limit must be one of ${ON_LIMIT_VALUES.join(' | ')}, got \"${flags.onLimit}\"`,\n );\n }\n onLimit = flags.onLimit as OnLimitValue;\n }\n\n const maxWaitMs =\n flags.maxWait != null ? parseDuration(flags.maxWait) : undefined;\n\n const mode: 'json' | 'plain' | 'tui' = flags.json\n ? 'json'\n : flags.tui === false || !process.stdout.isTTY\n ? 'plain'\n : 'tui';\n\n const resumeCommand = buildResumeCommand(file, flags);\n\n const hub = createHub();\n const signals = installSignalHandlers();\n const runOptions = {\n engine: flags.engine as EngineName | undefined,\n engineOptions,\n signal: signals.controller.signal,\n onEvent: hub.emit,\n state,\n budget,\n recordTo: flags.record,\n checkpoint: flags.checkpoint,\n resumeFrom: flags.resume,\n onLimit,\n maxWaitMs,\n resumeCommand,\n };\n\n let result;\n if (mode === 'tui') {\n const { render } = await import('ink');\n const { App } = await import('./tui/App.tsx');\n const instance = render(\n <App\n hub={hub}\n title={title}\n onAbort={() => signals.controller.abort()}\n />,\n );\n result = await run(job, runOptions);\n instance.unmount();\n await instance.waitUntilExit().catch(() => {});\n printSummary(result, resumeCommand);\n } else {\n const unsubscribe = hub.subscribe(\n mode === 'json' ? jsonReporter() : plainReporter(),\n );\n result = await run(job, runOptions);\n unsubscribe();\n if (mode !== 'json') printSummary(result, resumeCommand);\n }\n\n if (result.outcome.status === 'paused') printResumeGuidance(file, flags);\n\n signals.dispose();\n process.exitCode = exitCodeFor(result.outcome);\n}\n\n/**\n * Reconstruct a ready-to-paste resume command from the invocation, when there is\n * something to resume from: a checkpoint path. The resumed run reads warm state\n * from the checkpoint, so it picks up where the limit stopped it. Returns\n * `undefined` when no checkpoint is configured — a run with no checkpoint can\n * still pause cleanly, but it has no warm state to resume.\n */\nfunction buildResumeCommand(\n file: string | undefined,\n flags: RunFlags,\n): string | undefined {\n if (!flags.checkpoint) return undefined;\n const parts = ['loops', 'run'];\n if (file) parts.push(quoteArg(file));\n parts.push('--resume', quoteArg(flags.checkpoint));\n // Carry the flags that shape the run so the resume is the same job.\n if (flags.engine) parts.push('--engine', flags.engine);\n if (flags.budget) parts.push('--budget', flags.budget);\n if (flags.onLimit) parts.push('--on-limit', flags.onLimit);\n if (flags.maxWait) parts.push('--max-wait', flags.maxWait);\n if (flags.record) parts.push('--record', quoteArg(flags.record));\n if (flags.checkpoint) parts.push('--checkpoint', quoteArg(flags.checkpoint));\n if (flags.tui === false) parts.push('--no-tui');\n if (flags.json) parts.push('--json');\n return parts.join(' ');\n}\n\n/** Shell-quote an argument only when it contains whitespace or quotes. */\nfunction quoteArg(value: string): string {\n return /[\\s'\"]/.test(value) ? `'${value.replace(/'/g, `'\\\\''`)}'` : value;\n}\n\n/** Print resume guidance to stderr on a paused run (a TUI-safe channel). */\nfunction printResumeGuidance(file: string | undefined, flags: RunFlags): void {\n const cmd = buildResumeCommand(file, flags);\n if (cmd) {\n process.stderr.write(`\\nPaused at a limit. Resume with:\\n ${cmd}\\n`);\n } else {\n process.stderr.write(\n '\\nPaused at a limit. No checkpoint was configured, so there is no warm ' +\n 'state to resume.\\nRe-run with --checkpoint <path> to make a pause ' +\n 'resumable.\\n',\n );\n }\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const program = new Command();\n program\n .name('loops')\n .description(\n 'Run a prompt/agent in a loop with a fresh context every iteration. A nestable job primitive: loops, DAG stages, agent-validated conditions, review-restart.',\n )\n .version('0.1.0');\n\n program\n .command('run', { isDefault: true })\n .argument(\n '[file]',\n 'a loop-definition file (default-exports a Job); omit to use flags',\n )\n .option('-p, --prompt <text>', 'worker prompt (no-file mode)')\n .option(\n '-f, --prompt-file <path>',\n 'read the worker prompt from a file (no-file mode)',\n )\n .option(\n '-e, --engine <name>',\n 'default engine: agent-sdk | claude-cli | anthropic-api',\n )\n .option('--default-model <id>', 'fallback model id for engines')\n .option('--worker-model <id>', 'model for the worker job')\n .option(\n '--validator-model <id>',\n 'small model for agent-validated conditions',\n )\n .option('--reviewer-model <id>', 'model for the review job')\n .option('-n, --max <n>', 'max iterations')\n .option('-u, --until <question>', 'agent-validated stop condition')\n .option('-t, --threshold <0..1>', 'confidence threshold for --until', '0.8')\n .option('--start <question>', 'agent-validated start gate')\n .option(\n '--review <instructions>',\n 'review job; failing it restarts the loop',\n )\n .option(\n '--review-threshold <0..1>',\n 'confidence threshold for --review',\n '0.85',\n )\n .option('-i, --interval <dur>', 'delay between iterations (e.g. 30s, 5m)')\n .option('--max-tokens <n>', 'max output tokens per agent turn')\n .option('--api-key <key>', 'Anthropic API key (anthropic-api engine)')\n .option(\n '--cli-binary <path>',\n 'path to the claude binary (claude-cli engine)',\n )\n .option(\n '--permission-mode <mode>',\n 'tool permission mode for claude-cli/agent-sdk (default | acceptEdits | bypassPermissions | plan | dontAsk | auto)',\n )\n .option(\n '--engine-arg <arg>',\n 'extra arg forwarded to the claude-cli engine (repeatable)',\n (v: string, acc: string[]) => acc.concat(v),\n [] as string[],\n )\n .option('--state <json>', 'seed the shared run state (JSON)')\n .option('--budget <tokens>', 'cap total tokens (input+output) for the run')\n .option('--record <path>', 'append a JSONL run record to this path')\n .option(\n '--checkpoint <path>',\n 'snapshot run state to this path at each loop/dag/job boundary',\n )\n .option(\n '--resume <path>',\n 'restore run state from a prior --checkpoint file',\n )\n .option(\n '--on-limit <policy>',\n 'on a rate/quota/budget limit: auto | wait | exit-resume | fail (default auto)',\n )\n .option(\n '--max-wait <dur>',\n 'cap an auto/wait limit-wait (e.g. 5m, 30s); default 5m',\n )\n .option('--json', 'emit NDJSON events to stdout (no TUI)')\n .option('--no-tui', 'plain line output instead of the Ink TUI')\n .action((file: string | undefined, flags: RunFlags) =>\n execute(file, flags),\n );\n\n program\n .command('validate')\n .argument('<file>', 'a loop-definition file to check')\n .description(\n 'load a .loop.ts and print its shape without running it: the cheap, no-model pre-flight an agent runs before `loops run`',\n )\n .action(async (file: string) => {\n // loadJob imports + constructs the Job (so it catches syntax, import,\n // transform, and bad-export errors) but never calls run(), so no agent\n // turns fire. A failure throws the same agent-grade error `run` would,\n // and the top-level handler reports it with exit code 1.\n const { job } = await loadJob(file);\n const plan = renderPlan(jobMeta(job));\n process.stdout.write(\n `✓ ${file} loads (not executed)\\n${plan.map((l) => ` ${l}`).join('\\n')}\\n`,\n );\n });\n\n program\n .command('describe')\n .argument('<file>', 'a loop-definition file')\n .description(\n \"print a loop's shape (its gate, body, and dag nodes) without running it\",\n )\n .action(async (file: string) => {\n const { job } = await loadJob(file);\n process.stdout.write(`${renderPlan(jobMeta(job)).join('\\n')}\\n`);\n });\n\n await program.parseAsync(argv);\n}\n","#!/usr/bin/env node\nimport { main } from './cli.tsx';\n\nmain().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"]}
1
+ {"version":3,"sources":["../src/runtime/hub.ts","../src/runtime/signals.ts","../src/reporters.ts","../src/config.ts","../src/cli.tsx","../src/index.ts"],"names":["path","loop","z","ms"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * A tiny synchronous fan-out so multiple consumers (stats, the TUI, a JSON\n * reporter) can each observe the same event stream. Not worth a dependency —\n * it is six lines and never the gnarly part.\n */\n\nimport type { LoopEvent } from '../core/types.ts';\n\nexport type Listener = (event: LoopEvent) => void;\n\nexport interface Hub {\n emit: Listener;\n subscribe(listener: Listener): () => void;\n}\n\nexport function createHub(): Hub {\n const listeners = new Set<Listener>();\n return {\n emit(event) {\n for (const listener of listeners) listener(event);\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n };\n}\n","/**\n * Early-exit wiring. Maps OS signals (Ctrl-C / SIGTERM) onto an\n * `AbortController` so a run unwinds cleanly: in-flight engine calls abort,\n * loops/dags return `aborted`, and the exit summary still prints. A second\n * Ctrl-C force-exits in case a backend ignores the abort.\n */\n\nexport interface AbortHandle {\n controller: AbortController;\n dispose: () => void;\n}\n\nexport function installSignalHandlers(): AbortHandle {\n const controller = new AbortController();\n let hits = 0;\n\n const onSignal = () => {\n hits += 1;\n if (hits === 1) controller.abort();\n else process.exit(130);\n };\n\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n return {\n controller,\n dispose() {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n },\n };\n}\n","/**\n * Non-TUI output paths: a human-readable line reporter (`--no-tui`, CI logs)\n * and a machine-readable NDJSON reporter (`--json`). Plus the exit summary,\n * shared by every mode.\n */\n\nimport pc from 'picocolors';\n\nimport type { Listener } from './runtime/hub.ts';\nimport type { LoopEvent, Outcome } from './core/types.ts';\nimport type { RunResult } from './runtime/runner.ts';\n\nconst indent = (path: string[]) => ' '.repeat(Math.max(0, path.length - 1));\nconst statusColor = (status: Outcome['status'], text: string): string =>\n status === 'pass'\n ? pc.green(text)\n : status === 'fail'\n ? pc.red(text)\n : status === 'exhausted'\n ? pc.yellow(text)\n : status === 'paused'\n ? pc.cyan(text)\n : pc.gray(text);\n\n/** Format an epoch ms as a local clock time, for \"resuming at <time>\". */\nconst clock = (ts: number): string =>\n new Date(ts).toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n\n/** Emit each event as one NDJSON line on stdout. */\nexport function jsonReporter(): Listener {\n return (event: LoopEvent) =>\n process.stdout.write(`${JSON.stringify(event)}\\n`);\n}\n\n/** Per-loop-path accumulator, so we can print one report line per iteration. */\ninterface IterAccum {\n iteration: number;\n bodyStatus?: Outcome['status'];\n until?: { met: boolean; reason: string };\n stopOn?: { met: boolean; reason: string };\n review?: { status: Outcome['status']; summary?: string };\n tokensIn: number;\n tokensOut: number;\n}\n\n/** Compact a token count, e.g. 1234 → \"1.2k\". */\nconst tok = (n: number): string =>\n n >= 1000 ? `${(n / 1000).toFixed(1)}k` : String(n);\n\n/** Human-readable streaming output. Agent text streams inline; events labelled. */\nexport function plainReporter(): Listener {\n let streaming = false;\n const endStream = () => {\n if (streaming) {\n process.stdout.write('\\n');\n streaming = false;\n }\n };\n\n // Per loop path: the in-flight iteration's accumulating facts. A new\n // `loop:iteration` (or `loop:end`) for that path flushes the previous one.\n const accums = new Map<string, IterAccum>();\n const reportIteration = (key: string, indentPath: string[]): void => {\n const a = accums.get(key);\n if (!a) return;\n accums.delete(key);\n const parts: string[] = [];\n if (a.bodyStatus)\n parts.push(`body=${statusColor(a.bodyStatus, a.bodyStatus)}`);\n if (a.until)\n parts.push(`until=${a.until.met ? pc.green('met') : pc.gray('not met')}`);\n if (a.stopOn?.met) parts.push(`stopOn=${pc.red('met')}`);\n if (a.review) {\n const rv = `review=${statusColor(a.review.status, a.review.status)}`;\n parts.push(\n a.review.summary ? `${rv} ${pc.dim(`(${a.review.summary})`)}` : rv,\n );\n }\n parts.push(`${tok(a.tokensIn)}/${tok(a.tokensOut)} tok`);\n console.log(\n `${indent(indentPath)} ${pc.gray(`↳ iter ${a.iteration}:`)} ${parts.join(pc.gray(' · '))}`,\n );\n };\n\n return (event: LoopEvent) => {\n const key = event.path.join(' / ');\n switch (event.kind) {\n case 'engine:text':\n process.stdout.write(event.delta);\n streaming = true;\n return;\n case 'loop:start':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('▸ loop')} ${pc.bold(last(event.path))}${event.max ? pc.gray(` (max ${event.max})`) : ''}`,\n );\n return;\n case 'loop:iteration':\n endStream();\n reportIteration(key, event.path); // flush the previous iteration's report\n accums.set(key, {\n iteration: event.iteration,\n tokensIn: 0,\n tokensOut: 0,\n });\n console.log(\n `${indent(event.path)}${pc.gray(` iteration ${event.iteration}`)}`,\n );\n return;\n case 'loop:condition': {\n endStream();\n const a = accums.get(key);\n if (a) {\n if (event.which === 'until')\n a.until = { met: event.result.met, reason: event.result.reason };\n else if (event.which === 'stopOn')\n a.stopOn = { met: event.result.met, reason: event.result.reason };\n }\n console.log(\n `${indent(event.path)} ${pc.magenta(event.which)}: ${event.result.met ? pc.green('met') : pc.gray('not met')} — ${pc.dim(event.result.reason)}`,\n );\n return;\n }\n case 'loop:review': {\n endStream();\n const a = accums.get(key);\n if (a)\n a.review = {\n status: event.outcome.status,\n summary: event.outcome.summary,\n };\n console.log(\n `${indent(event.path)} ${pc.blue('review')}: ${statusColor(event.outcome.status, event.outcome.status)}${event.outcome.summary ? pc.dim(` — ${event.outcome.summary}`) : ''}`,\n );\n return;\n }\n case 'job:end': {\n // The loop body runs at the loop's own path; record its outcome on the\n // current iteration accumulator for that path.\n const a = accums.get(key);\n if (a) a.bodyStatus = event.outcome.status;\n return;\n }\n case 'engine:usage': {\n const a = accums.get(key);\n if (a) {\n a.tokensIn += event.usage.inputTokens;\n a.tokensOut += event.usage.outputTokens;\n }\n return;\n }\n case 'loop:end':\n endStream();\n reportIteration(key, event.path); // flush the final iteration's report\n console.log(\n `${indent(event.path)}${pc.cyan('◂ loop')} ${pc.bold(last(event.path))} → ${statusColor(event.outcome.status, event.outcome.status)} ${pc.gray(`(${event.iterations} iter)`)}`,\n );\n return;\n case 'dag:start':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('▸ dag')} ${pc.bold(last(event.path))} ${pc.gray(`[${event.nodes.join(', ')}]`)}`,\n );\n return;\n case 'dag:node':\n if (event.phase === 'start') return;\n endStream();\n console.log(\n `${indent(event.path)} ${pc.gray('node')} ${event.node}: ${event.outcome ? statusColor(event.outcome.status, event.phase === 'skip' ? 'skipped' : event.outcome.status) : event.phase}`,\n );\n return;\n case 'dag:end':\n endStream();\n console.log(\n `${indent(event.path)}${pc.cyan('◂ dag')} ${pc.bold(last(event.path))} → ${statusColor(event.outcome.status, event.outcome.status)}`,\n );\n return;\n case 'job:start':\n endStream();\n console.log(`${indent(event.path)} ${pc.gray('•')} ${event.label}`);\n return;\n case 'engine:tool':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.dim(`tool ${event.phase}: ${event.name}`)}`,\n );\n return;\n case 'limit:wait':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.yellow(`⏳ ${event.code.toLowerCase()}`)}: waiting ${Math.round(event.waitMs / 1000)}s, resuming at ${clock(event.resumeAt)}`,\n );\n return;\n case 'limit:pause':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.cyan(`⏸ ${event.code.toLowerCase()}`)}: ${pc.dim(event.reason)}`,\n );\n return;\n case 'log':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.dim(`[${event.level}] ${event.message}`)}`,\n );\n return;\n case 'error':\n endStream();\n console.log(\n `${indent(event.path)} ${pc.red(`✗ ${event.code}: ${event.message}`)}`,\n );\n return;\n default:\n return;\n }\n };\n}\n\n/** The exit summary, printed once at the end in every mode. */\nexport function printSummary(result: RunResult, resumeCommand?: string): void {\n const { outcome, stats } = result;\n const line = pc.dim('─'.repeat(56));\n console.log(`\\n${line}`);\n console.log(\n `${pc.bold('Result')} ${statusColor(outcome.status, outcome.status.toUpperCase())}${outcome.confidence != null ? pc.gray(` confidence ${outcome.confidence.toFixed(2)}`) : ''}`,\n );\n if (outcome.summary) console.log(`${pc.dim('Summary')} ${outcome.summary}`);\n // A paused run is resumable; surface the exact command to continue it.\n if (outcome.status === 'paused') {\n console.log(\n resumeCommand\n ? `${pc.dim('Resume')} ${pc.cyan(resumeCommand)}`\n : `${pc.dim('Resume')} ${pc.yellow('re-run with --checkpoint <path> to make a pause resumable')}`,\n );\n }\n\n console.log(line);\n console.log(`${pc.bold('Loops')}`);\n for (const loop of stats.loops) {\n const reviews = loop.reviewsPassed + loop.reviewsFailed;\n console.log(\n ` ${loop.path || '(root)'} — ${loop.iterations} iter` +\n (reviews\n ? `, reviews ${pc.green(String(loop.reviewsPassed))}/${pc.red(String(loop.reviewsFailed))}`\n : '') +\n (loop.lastStatus\n ? ` → ${statusColor(loop.lastStatus, loop.lastStatus)}`\n : ''),\n );\n }\n if (stats.loops.length === 0) console.log(pc.dim(' (none)'));\n\n console.log(line);\n console.log(\n `${pc.bold('Usage')} ${stats.agentCalls} agent call(s), ` +\n `${pc.cyan(String(stats.totalInputTokens))} in / ${pc.cyan(String(stats.totalOutputTokens))} out tokens, ` +\n `${(stats.elapsedMs / 1000).toFixed(1)}s`,\n );\n for (const m of stats.models) {\n console.log(\n pc.dim(\n ` ${m.model}: ${m.calls} call(s), ${m.inputTokens} in / ${m.outputTokens} out`,\n ),\n );\n }\n\n if (result.budget) {\n const b = result.budget;\n const spent =\n b.remaining === 0 ? pc.red(String(b.spent)) : pc.cyan(String(b.spent));\n console.log(\n `${pc.bold('Budget')} ${spent} / ${b.limit} tokens ${pc.gray(`(${b.remaining} remaining)`)}`,\n );\n }\n\n if (stats.errors.length) {\n console.log(line);\n console.log(`${pc.bold(pc.red('Errors'))} (${stats.errors.length})`);\n for (const e of stats.errors.slice(0, 10)) {\n console.log(pc.red(` ✗ [${e.code}] ${e.path}: ${e.message}`));\n }\n }\n console.log(line);\n}\n\nfunction last(path: string[]): string {\n return path[path.length - 1] ?? '(root)';\n}\n","/**\n * The no-file path: turn CLI flags into a standard loop (worker → until →\n * review). Validated with zod so a bad invocation fails with a clear message\n * rather than odd runtime behaviour. A definition file bypasses all of this and\n * builds the `Job` directly.\n */\n\nimport ms from 'ms';\nimport { z } from 'zod';\n\nimport { loop } from './core/loop.ts';\nimport { agentJob } from './core/job.ts';\nimport { agentCheck, bodyPassed, gateJob } from './core/condition.ts';\nimport type { Job } from './core/types.ts';\nimport type { EngineName } from './engines/engine.ts';\n\nexport const FlagSpec = z.object({\n prompt: z\n .string()\n .min(\n 1,\n 'a --prompt or --prompt-file is required when no definition file is given',\n ),\n engine: z.string().optional(),\n workerModel: z.string().optional(),\n validatorModel: z.string().optional(),\n reviewerModel: z.string().optional(),\n max: z.number().int().positive().optional(),\n untilAgent: z.string().optional(),\n threshold: z.number().min(0).max(1).default(0.8),\n startAgent: z.string().optional(),\n review: z.string().optional(),\n reviewThreshold: z.number().min(0).max(1).default(0.85),\n interval: z.number().int().nonnegative().optional(),\n maxTokens: z.number().int().positive().optional(),\n});\n\nexport type FlagSpec = z.infer<typeof FlagSpec>;\n\n/** Parse a duration like `5m`, `30s`, `1h` (or a bare ms number) to ms. */\nexport function parseDuration(value: string): number {\n if (/^\\d+$/.test(value)) return Number(value);\n const out = ms(value as ms.StringValue);\n if (typeof out !== 'number' || Number.isNaN(out)) {\n throw new Error(`invalid duration: \"${value}\" (try 30s, 5m, 1h)`);\n }\n return out;\n}\n\n/** Build the standard loop from flags. Parses + validates once, here. */\nexport function buildJobFromFlags(input: z.input<typeof FlagSpec>): Job {\n const spec = FlagSpec.parse(input);\n const engine = spec.engine as EngineName | undefined;\n\n const worker = agentJob({\n label: 'worker',\n engine,\n model: spec.workerModel,\n maxTokens: spec.maxTokens,\n // On a review-restart, fold the reviewer's objection into the next prompt\n // so the retry is informed rather than a blind repeat.\n prompt: (ctx) =>\n ctx.lastReview\n ? `${spec.prompt}\\n\\nYour previous attempt was REJECTED in review: ${ctx.lastReview.summary ?? ctx.lastReview.status}. Address that specifically this time.`\n : spec.prompt,\n });\n\n const until = spec.untilAgent\n ? agentCheck({\n question: spec.untilAgent,\n threshold: spec.threshold,\n model: spec.validatorModel,\n engine,\n })\n : bodyPassed();\n\n const start = spec.startAgent\n ? agentCheck({\n question: spec.startAgent,\n threshold: 0.5,\n model: spec.validatorModel,\n engine,\n })\n : undefined;\n\n const review = spec.review\n ? gateJob(\n 'review',\n agentCheck({\n question: spec.review,\n threshold: spec.reviewThreshold,\n model: spec.reviewerModel,\n engine,\n }),\n )\n : undefined;\n\n return loop({\n name: 'main',\n body: worker,\n start,\n until,\n review,\n max: spec.max,\n delayMs: spec.interval,\n });\n}\n","/**\n * The `loops` CLI. Two ways to define a run:\n * 1. a definition file that default-exports a `Job` — full power, nesting;\n * 2. flags (`--prompt`, `--until`, `--review`, …) — the standard loop.\n *\n * Output mode: Ink TUI by default (a TTY), `--no-tui` for line logs, `--json`\n * for an NDJSON event stream. Ctrl-C / `q` aborts cleanly and still summarises.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport React from 'react';\nimport { Command } from 'commander';\nimport { z } from 'zod';\n\nimport { run, exitCodeFor } from './runtime/runner.ts';\nimport { createHub } from './runtime/hub.ts';\nimport { installSignalHandlers } from './runtime/signals.ts';\nimport { jsonReporter, plainReporter, printSummary } from './reporters.ts';\nimport { buildJobFromFlags, parseDuration } from './config.ts';\nimport { loop } from './core/loop.ts';\nimport { jobMeta, renderPlan } from './core/describe.ts';\nimport {\n listRuns,\n readRunStatus,\n runEventsPath,\n runsHome,\n formatEvent,\n} from './runtime/supervisor.ts';\nimport type { Job, LoopConfig } from './core/types.ts';\nimport type { EngineName, EngineOptions } from './engines/engine.ts';\n\ninterface RunFlags {\n prompt?: string;\n promptFile?: string;\n engine?: string;\n defaultModel?: string;\n workerModel?: string;\n validatorModel?: string;\n reviewerModel?: string;\n max?: string;\n until?: string;\n threshold?: string;\n start?: string;\n review?: string;\n reviewThreshold?: string;\n interval?: string;\n maxTokens?: string;\n apiKey?: string;\n cliBinary?: string;\n permissionMode?: string;\n engineArg?: string[];\n state?: string;\n budget?: string;\n record?: string;\n checkpoint?: string;\n resume?: string;\n supervise?: boolean;\n onLimit?: string;\n maxWait?: string;\n json?: boolean;\n tui?: boolean; // commander sets false for --no-tui\n}\n\nconst ON_LIMIT_VALUES = ['auto', 'wait', 'exit-resume', 'fail'] as const;\ntype OnLimitValue = (typeof ON_LIMIT_VALUES)[number];\n\n/** The worker prompt comes from --prompt OR --prompt-file (not both). */\nfunction resolvePrompt(flags: RunFlags): string {\n if (flags.promptFile != null && flags.prompt != null) {\n throw new Error('pass either --prompt or --prompt-file, not both');\n }\n if (flags.promptFile != null) {\n const resolved = path.resolve(flags.promptFile);\n if (!fs.existsSync(resolved))\n throw new Error(`prompt file not found: ${flags.promptFile}`);\n return fs.readFileSync(resolved, 'utf8');\n }\n return flags.prompt ?? '';\n}\n\nasync function loadJob(file: string): Promise<{ job: Job; title: string }> {\n const resolved = path.resolve(file);\n if (!fs.existsSync(resolved)) {\n throw new Error(\n `loop file not found: ${file}\\n(omit the file argument to use flags mode, or run \\`loops run --help\\`)`,\n );\n }\n // The bin registers tsx's loader globally, so this plain import transforms a\n // `.loop.ts` wherever it lives — inside this package or in a consumer repo that\n // has `loops` installed. (A scoped `tsImport` only covers this package's tree,\n // which is why an out-of-tree recipe used to die on `Unexpected token 'export'`.)\n let mod: Record<string, unknown>;\n try {\n mod = (await import(pathToFileURL(resolved).href)) as Record<string, unknown>;\n } catch (e) {\n const detail = e instanceof Error ? e.message : String(e);\n const esmHint =\n /ES Module|import statement outside a module|ERR_REQUIRE_ESM/i.test(detail)\n ? `\\n hint: the recipe's folder is not an ES module scope. Add a package.json ` +\n `with {\"type\":\"module\"} next to it (repos that use loops as a submodule already have this).`\n : '';\n throw new Error(\n `failed to load loop file ${file}:\\n ${detail}${esmHint}\\n` +\n `(the file is imported and run like \\`node <file>\\`; fix the error above, or ` +\n `run \\`loops validate ${file}\\` to check it without executing)`,\n );\n }\n const def = mod.default ?? mod.job ?? mod.loop;\n const title = path.basename(file).replace(/\\.(loop\\.)?(t|j)sx?$/, '');\n if (typeof def === 'function') return { job: def as Job, title };\n if (def && typeof def === 'object' && 'body' in def)\n return { job: loop(def as LoopConfig), title };\n throw new Error(\n `${file}: default export must be a Job (from loop()/dag()/agentJob()) or a LoopConfig`,\n );\n}\n\nfunction buildFromFlags(flags: RunFlags): Job {\n const num = (v: string | undefined) => (v == null ? undefined : Number(v));\n const prompt = resolvePrompt(flags); // outside the try so its errors aren't reported as flag-validation\n try {\n // Parsing/validation lives in buildJobFromFlags (single source of truth);\n // we just shape the raw input and translate a Zod failure into a clean error.\n return buildJobFromFlags({\n prompt,\n engine: flags.engine,\n workerModel: flags.workerModel,\n validatorModel: flags.validatorModel,\n reviewerModel: flags.reviewerModel,\n max: num(flags.max),\n untilAgent: flags.until,\n threshold: num(flags.threshold),\n startAgent: flags.start,\n review: flags.review,\n reviewThreshold: num(flags.reviewThreshold),\n interval:\n flags.interval != null ? parseDuration(flags.interval) : undefined,\n maxTokens: num(flags.maxTokens),\n });\n } catch (e) {\n if (e instanceof z.ZodError) {\n throw new Error(\n `invalid flags:\\n - ${e.issues.map((i) => i.message).join('\\n - ')}`,\n );\n }\n throw e;\n }\n}\n\nasync function execute(\n file: string | undefined,\n flags: RunFlags,\n): Promise<void> {\n const { job, title } = file\n ? await loadJob(file)\n : { job: buildFromFlags(flags), title: 'loop' };\n\n const engineOptions: EngineOptions = {};\n if (flags.defaultModel) engineOptions.defaultModel = flags.defaultModel;\n if (flags.apiKey) engineOptions.apiKey = flags.apiKey;\n if (flags.cliBinary) engineOptions.cliBinary = flags.cliBinary;\n if (flags.permissionMode)\n engineOptions.permissionMode =\n flags.permissionMode as EngineOptions['permissionMode'];\n if (flags.engineArg?.length) engineOptions.cliArgs = flags.engineArg;\n\n let state: Record<string, unknown> | undefined;\n if (flags.state) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(flags.state);\n } catch (e) {\n throw new Error(\n `--state must be valid JSON: ${e instanceof Error ? e.message : String(e)}`,\n );\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error(\n `--state must be a JSON object, got ${Array.isArray(parsed) ? 'array' : typeof parsed}`,\n );\n }\n state = parsed as Record<string, unknown>;\n }\n\n let budget: number | undefined;\n if (flags.budget != null) {\n budget = Number(flags.budget);\n if (!Number.isFinite(budget) || budget <= 0) {\n throw new Error(\n `--budget must be a positive number of tokens, got \"${flags.budget}\"`,\n );\n }\n }\n\n let onLimit: OnLimitValue | undefined;\n if (flags.onLimit != null) {\n if (!ON_LIMIT_VALUES.includes(flags.onLimit as OnLimitValue)) {\n throw new Error(\n `--on-limit must be one of ${ON_LIMIT_VALUES.join(' | ')}, got \"${flags.onLimit}\"`,\n );\n }\n onLimit = flags.onLimit as OnLimitValue;\n }\n\n const maxWaitMs =\n flags.maxWait != null ? parseDuration(flags.maxWait) : undefined;\n\n const mode: 'json' | 'plain' | 'tui' = flags.json\n ? 'json'\n : flags.tui === false || !process.stdout.isTTY\n ? 'plain'\n : 'tui';\n\n const resumeCommand = buildResumeCommand(file, flags);\n\n const hub = createHub();\n const signals = installSignalHandlers();\n const runOptions = {\n engine: flags.engine as EngineName | undefined,\n engineOptions,\n signal: signals.controller.signal,\n onEvent: hub.emit,\n state,\n budget,\n recordTo: flags.record,\n checkpoint: flags.checkpoint,\n resumeFrom: flags.resume,\n supervise: flags.supervise,\n onLimit,\n maxWaitMs,\n resumeCommand,\n };\n\n let result;\n if (mode === 'tui') {\n const { render } = await import('ink');\n const { App } = await import('./tui/App.tsx');\n const instance = render(\n <App\n hub={hub}\n title={title}\n onAbort={() => signals.controller.abort()}\n />,\n );\n result = await run(job, runOptions);\n instance.unmount();\n await instance.waitUntilExit().catch(() => {});\n printSummary(result, resumeCommand);\n } else {\n const unsubscribe = hub.subscribe(\n mode === 'json' ? jsonReporter() : plainReporter(),\n );\n result = await run(job, runOptions);\n unsubscribe();\n if (mode !== 'json') printSummary(result, resumeCommand);\n }\n\n if (result.outcome.status === 'paused') printResumeGuidance(file, flags);\n\n signals.dispose();\n process.exitCode = exitCodeFor(result.outcome);\n}\n\n/**\n * Reconstruct a ready-to-paste resume command from the invocation, when there is\n * something to resume from: a checkpoint path. The resumed run reads warm state\n * from the checkpoint, so it picks up where the limit stopped it. Returns\n * `undefined` when no checkpoint is configured — a run with no checkpoint can\n * still pause cleanly, but it has no warm state to resume.\n */\nfunction buildResumeCommand(\n file: string | undefined,\n flags: RunFlags,\n): string | undefined {\n if (!flags.checkpoint) return undefined;\n const parts = ['loops', 'run'];\n if (file) parts.push(quoteArg(file));\n parts.push('--resume', quoteArg(flags.checkpoint));\n // Carry the flags that shape the run so the resume is the same job.\n if (flags.engine) parts.push('--engine', flags.engine);\n if (flags.budget) parts.push('--budget', flags.budget);\n if (flags.onLimit) parts.push('--on-limit', flags.onLimit);\n if (flags.maxWait) parts.push('--max-wait', flags.maxWait);\n if (flags.record) parts.push('--record', quoteArg(flags.record));\n if (flags.checkpoint) parts.push('--checkpoint', quoteArg(flags.checkpoint));\n if (flags.tui === false) parts.push('--no-tui');\n if (flags.json) parts.push('--json');\n return parts.join(' ');\n}\n\n/** Shell-quote an argument only when it contains whitespace or quotes. */\nfunction quoteArg(value: string): string {\n return /[\\s'\"]/.test(value) ? `'${value.replace(/'/g, `'\\\\''`)}'` : value;\n}\n\n/** Print resume guidance to stderr on a paused run (a TUI-safe channel). */\nfunction printResumeGuidance(file: string | undefined, flags: RunFlags): void {\n const cmd = buildResumeCommand(file, flags);\n if (cmd) {\n process.stderr.write(`\\nPaused at a limit. Resume with:\\n ${cmd}\\n`);\n } else {\n process.stderr.write(\n '\\nPaused at a limit. No checkpoint was configured, so there is no warm ' +\n 'state to resume.\\nRe-run with --checkpoint <path> to make a pause ' +\n 'resumable.\\n',\n );\n }\n}\n\n/** Compact relative age, e.g. `8s`, `5m`, `2h`, `3d`. */\nfunction relAge(ms: number): string {\n const s = Math.max(0, Math.round(ms / 1000));\n if (s < 60) return `${s}s`;\n const m = Math.round(s / 60);\n if (m < 60) return `${m}m`;\n const h = Math.round(m / 60);\n if (h < 48) return `${h}h`;\n return `${Math.round(h / 24)}d`;\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const program = new Command();\n program\n .name('loops')\n .description(\n 'Run a prompt/agent in a loop with a fresh context every iteration. A nestable job primitive: loops, DAG stages, agent-validated conditions, review-restart.',\n )\n .version('0.1.0');\n\n program\n .command('run', { isDefault: true })\n .argument(\n '[file]',\n 'a loop-definition file (default-exports a Job); omit to use flags',\n )\n .option('-p, --prompt <text>', 'worker prompt (no-file mode)')\n .option(\n '-f, --prompt-file <path>',\n 'read the worker prompt from a file (no-file mode)',\n )\n .option(\n '-e, --engine <name>',\n 'default engine: agent-sdk | claude-cli | anthropic-api',\n )\n .option('--default-model <id>', 'fallback model id for engines')\n .option('--worker-model <id>', 'model for the worker job')\n .option(\n '--validator-model <id>',\n 'small model for agent-validated conditions',\n )\n .option('--reviewer-model <id>', 'model for the review job')\n .option('-n, --max <n>', 'max iterations')\n .option('-u, --until <question>', 'agent-validated stop condition')\n .option('-t, --threshold <0..1>', 'confidence threshold for --until', '0.8')\n .option('--start <question>', 'agent-validated start gate')\n .option(\n '--review <instructions>',\n 'review job; failing it restarts the loop',\n )\n .option(\n '--review-threshold <0..1>',\n 'confidence threshold for --review',\n '0.85',\n )\n .option('-i, --interval <dur>', 'delay between iterations (e.g. 30s, 5m)')\n .option('--max-tokens <n>', 'max output tokens per agent turn')\n .option('--api-key <key>', 'Anthropic API key (anthropic-api engine)')\n .option(\n '--cli-binary <path>',\n 'path to the claude binary (claude-cli engine)',\n )\n .option(\n '--permission-mode <mode>',\n 'tool permission mode for claude-cli/agent-sdk (default | acceptEdits | bypassPermissions | plan | dontAsk | auto)',\n )\n .option(\n '--engine-arg <arg>',\n 'extra arg forwarded to the claude-cli engine (repeatable)',\n (v: string, acc: string[]) => acc.concat(v),\n [] as string[],\n )\n .option('--state <json>', 'seed the shared run state (JSON)')\n .option('--budget <tokens>', 'cap total tokens (input+output) for the run')\n .option('--record <path>', 'append a JSONL run record to this path')\n .option(\n '--checkpoint <path>',\n 'snapshot run state to this path at each loop/dag/job boundary',\n )\n .option(\n '--resume <path>',\n 'restore run state from a prior --checkpoint file',\n )\n .option(\n '--on-limit <policy>',\n 'on a rate/quota/budget limit: auto | wait | exit-resume | fail (default auto)',\n )\n .option(\n '--max-wait <dur>',\n 'cap an auto/wait limit-wait (e.g. 5m, 30s); default 5m',\n )\n .option('--json', 'emit NDJSON events to stdout (no TUI)')\n .option('--no-tui', 'plain line output instead of the Ink TUI')\n .option(\n '--supervise',\n 'register this run in ~/.loops/runs so `loops list`/`status`/`tail` can observe it from another process',\n )\n .action((file: string | undefined, flags: RunFlags) =>\n execute(file, flags),\n );\n\n program\n .command('validate')\n .argument('<file>', 'a loop-definition file to check')\n .description(\n 'load a .loop.ts and print its shape without running it: the cheap, no-model pre-flight an agent runs before `loops run`',\n )\n .action(async (file: string) => {\n // loadJob imports + constructs the Job (so it catches syntax, import,\n // transform, and bad-export errors) but never calls run(), so no agent\n // turns fire. A failure throws the same agent-grade error `run` would,\n // and the top-level handler reports it with exit code 1.\n const { job } = await loadJob(file);\n const plan = renderPlan(jobMeta(job));\n process.stdout.write(\n `✓ ${file} loads (not executed)\\n${plan.map((l) => ` ${l}`).join('\\n')}\\n`,\n );\n });\n\n program\n .command('describe')\n .argument('<file>', 'a loop-definition file')\n .description(\n \"print a loop's shape (its gate, body, and dag nodes) without running it\",\n )\n .action(async (file: string) => {\n const { job } = await loadJob(file);\n process.stdout.write(`${renderPlan(jobMeta(job)).join('\\n')}\\n`);\n });\n\n // ── Supervision: observe a run from another process (the registry is files) ──\n\n program\n .command('list')\n .alias('ls')\n .description('list supervised runs (start one with `loops run --supervise`)')\n .action(() => {\n const runs = listRuns();\n if (!runs.length) {\n process.stdout.write(\n `no supervised runs in ${runsHome()}\\n(start one with: loops run --supervise <file>)\\n`,\n );\n return;\n }\n for (const r of runs) {\n const state =\n r.status === 'running' ? (r.alive ? 'running' : 'dead') : r.status;\n const age = relAge(Date.now() - (r.endedAt ?? r.updatedAt));\n process.stdout.write(\n `${r.runId.padEnd(26)} ${state.padEnd(9)} iter ${String(r.live.iteration).padStart(3)} ${age.padStart(4)} ${r.title}\\n`,\n );\n }\n });\n\n program\n .command('status')\n .argument('<runId>', 'a run id from `loops list`')\n .description(\"show a supervised run's live state and shape\")\n .action((runId: string) => {\n const r = readRunStatus(runId);\n if (!r) {\n process.stderr.write(`no run \"${runId}\" in ${runsHome()}\\n`);\n process.exitCode = 1;\n return;\n }\n const state =\n r.status === 'running'\n ? r.alive\n ? 'running'\n : 'dead (process gone)'\n : r.status;\n const g = r.live.lastGate;\n const o = r.live.lastOutcome;\n const lines = [\n `${r.runId} [${state}]`,\n ` title: ${r.title}`,\n ` cwd: ${r.cwd}`,\n ` pid: ${r.pid}`,\n r.live.iteration\n ? ` at: ${r.live.path.join(' › ')} (iteration ${r.live.iteration})`\n : '',\n g\n ? ` gate: ${g.which} ${g.met ? 'met' : 'not met'}${g.confidence != null ? ` @ ${g.confidence.toFixed(2)}` : ''}: ${g.reason}`\n : '',\n o ? ` last: ${o.status}${o.summary ? `: ${o.summary}` : ''}` : '',\n ` tokens: ${r.live.usage.inputTokens} in / ${r.live.usage.outputTokens} out (${r.live.usage.calls} calls)`,\n ].filter(Boolean);\n process.stdout.write(`${lines.join('\\n')}\\n`);\n if (r.shape)\n process.stdout.write(\n `\\n shape:\\n${renderPlan(r.shape)\n .map((l) => ` ${l}`)\n .join('\\n')}\\n`,\n );\n });\n\n program\n .command('tail')\n .argument('<runId>', 'a run id from `loops list`')\n .description(\"stream a supervised run's events live (Ctrl-C to stop)\")\n .action(async (runId: string) => {\n const path = runEventsPath(runId);\n if (!fs.existsSync(path)) {\n process.stderr.write(`no run \"${runId}\" in ${runsHome()}\\n`);\n process.exitCode = 1;\n return;\n }\n let offset = 0;\n let stop = false;\n const onSig = () => {\n stop = true;\n };\n process.once('SIGINT', onSig);\n for (;;) {\n const buf = fs.readFileSync(path, 'utf8');\n if (buf.length > offset) {\n // Only consume up to the last newline, so a torn read never drops a line.\n const chunk = buf.slice(offset);\n const lastNl = chunk.lastIndexOf('\\n');\n if (lastNl >= 0) {\n offset += lastNl + 1;\n for (const line of chunk.slice(0, lastNl).split('\\n')) {\n if (!line.trim()) continue;\n try {\n process.stdout.write(`${formatEvent(JSON.parse(line))}\\n`);\n } catch {\n /* skip an unparseable line */\n }\n }\n }\n }\n if (stop) break;\n const st = readRunStatus(runId);\n if (st && st.status !== 'running') {\n process.stdout.write(`◂ ${st.status}\\n`);\n break;\n }\n if (st && !st.alive) {\n process.stdout.write('◂ process gone (no terminal status)\\n');\n break;\n }\n await new Promise((res) => setTimeout(res, 200));\n }\n process.removeListener('SIGINT', onSig);\n });\n\n await program.parseAsync(argv);\n}\n","#!/usr/bin/env node\nimport { main } from './cli.tsx';\n\nmain().catch((err: unknown) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loops-adk/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "license": "MIT",
5
5
  "author": "Jonny Neill",
6
6
  "description": "Run an agent in a convergence loop with an honest done-gate. A small, nestable loop and DAG primitive: deterministic plus agent-judge conditions, git as memory, review-restart, budgets, and a live TUI.",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: author-loop
3
- description: Use when writing, running, or validating a loops `.loop.ts` the mental model, the honest-convergence gate, the git-memory tiers, the loop archetypes, and copy-paste recipes for authoring convergence loops with the `loops` library. Load this before composing a loop.
3
+ description: Use when writing, running, or validating a loops `.loop.ts`: the mental model, the honest-convergence gate, the git-memory tiers, the loop archetypes, and copy-paste recipes for authoring convergence loops with the `loops` library. Load this before composing a loop.
4
4
  ---
5
5
 
6
6
  # Authoring loops
@@ -11,9 +11,9 @@ description: Use when writing, running, or validating a loops `.loop.ts` — the
11
11
 
12
12
  There is one unit of work and two supporting types:
13
13
 
14
- - `Job = (ctx) => Promise<Outcome>` a unit of work of any size.
15
- - `Condition = (ctx, last) => Promise<{ met, reason, confidence? }>` a yes/no gate.
16
- - `Engine` where an agent turn runs (a model backend).
14
+ - `Job = (ctx) => Promise<Outcome>`: a unit of work of any size.
15
+ - `Condition = (ctx, last) => Promise<{ met, reason, confidence? }>`: a yes/no gate.
16
+ - `Engine`: where an agent turn runs (a model backend).
17
17
 
18
18
  `loop()` returns a `Job`. `dag()` returns a `Job`. So loops and DAGs **nest both ways**: a DAG node can be a loop, a loop body can be a DAG. Nesting is the absence of a special case. Author with that freedom; do not reach for a node type that only works in one position.
19
19
 
@@ -45,9 +45,9 @@ export default defineJob(
45
45
 
46
46
  ## The gate is the whole point
47
47
 
48
- The trap this library exists to avoid is "ask the model if it is done" the model grades its own homework and always says yes. Make the gate **honest**:
48
+ The trap this library exists to avoid is "ask the model if it is done": the model grades its own homework and always says yes. Make the gate **honest**:
49
49
 
50
- - Combine a **deterministic** signal (`commandSucceeds('npm', ['test'])` the tests really pass) with a **separate judge** (`agentCheck`). Prefer this mixed form over a lone judge.
50
+ - Combine a **deterministic** signal (`commandSucceeds('npm', ['test'])`: the tests really pass) with a **separate judge** (`agentCheck`). Prefer this mixed form over a lone judge.
51
51
  - `until`/`start`/`stopOn` take one item or many. Arrays are `all` by default; wrap in `any(...)` for or.
52
52
  - Harden the judge: `quorum(2, judgeA, judgeB, judgeC)` is a k-of-n jury. `agentCheck({ dimensions: [...] })` opens on the geometric mean, so one weak dimension drags the verdict down.
53
53
  - A missing confidence scores 0 (fail-closed). Never lean on the model's self-report alone.
@@ -67,16 +67,16 @@ until: [
67
67
  Progress accumulates on disk, so each iteration starts with a clean context but not a blank one.
68
68
 
69
69
  - `ground: true` on an `agentJob` reads the recent commit log + this run's scratch files into the next prompt, so a fresh turn knows what was already tried.
70
- - `commit: { subject }` (or `commit: true`) writes one structured milestone commit on convergence the reasoning welded to the diff. Later turns ground on it.
70
+ - `commit: { subject }` (or `commit: true`) writes one structured milestone commit on convergence: the reasoning welded to the diff. Later turns ground on it.
71
71
  - For long, noisy histories use `ground: { retrieve: true }` (select relevant commits, not recent-N); for indefinite processes add `consolidateJob` to fold history into a bounded, decision-preserving record.
72
72
 
73
73
  ## Three archetypes
74
74
 
75
75
  A loop is not one shape. Pick the one that matches the work:
76
76
 
77
- - **Converge** one hard target, retried until a gate passes: `loop({ until: gate, max })`.
78
- - **Sweep** a known worklist, one fresh task each: a `loop`/`dag` over the list.
79
- - **Tend** an unbounded process picking the next unit: `loop({ until: dynamicCondition, max })`, body dispatches to a sub-loop (wrap in `isolated(...)` for its own worktree).
77
+ - **Converge**: one hard target, retried until a gate passes: `loop({ until: gate, max })`.
78
+ - **Sweep**: a known worklist, one fresh task each: a `loop`/`dag` over the list.
79
+ - **Tend**: an unbounded process picking the next unit: `loop({ until: dynamicCondition, max })`, body dispatches to a sub-loop (wrap in `isolated(...)` for its own worktree).
80
80
 
81
81
  They nest: triage is Tend ∘ Converge; a research sweep is Sweep ∘ Converge.
82
82
 
@@ -111,6 +111,8 @@ Always `loops validate` first. It imports and constructs the loop (catching synt
111
111
 
112
112
  `loops run` works from any repo, including one that uses `loops` as a submodule or dependency. The recipe's folder must be an ES module scope (a `package.json` with `{"type":"module"}`); repos that consume `loops` already have this. If a load fails with an ES-module error, that scope is what is missing.
113
113
 
114
+ Add `--supervise` to make a run observable from another process: it registers under `~/.loops/runs/`, and `loops list` / `loops status <runId>` / `loops tail <runId>` read its live state (shape, iteration, last gate verdict, tokens, events). Use this to watch a long run, or to supervise several at once.
115
+
114
116
  ## Gotchas
115
117
 
116
118
  - **Test offline first.** Use the `mock` engine, or an engine-free `fnJob`/`predicate` body, to prove the loop's shape with zero network. A change to convergence logic deserves a deterministic check, not a live model call.