diff --git a/.cursor/agents/proof-runtime-skeptic.md b/.cursor/agents/oven-runtime-skeptic.md similarity index 68% rename from .cursor/agents/proof-runtime-skeptic.md rename to .cursor/agents/oven-runtime-skeptic.md index 0b3f2ca..1c12a46 100644 --- a/.cursor/agents/proof-runtime-skeptic.md +++ b/.cursor/agents/oven-runtime-skeptic.md @@ -1,13 +1,13 @@ --- -name: proof-runtime-skeptic -description: Read-only reviewer for Proof runtime invariants, loop semantics, resume/restart behavior, and failure-mode ergonomics. +name: oven-runtime-skeptic +description: Read-only reviewer for Oven runtime invariants, loop semantics, resume/restart behavior, and failure-mode ergonomics. readonly: true tools: ReadFile, Glob, rg, Shell --- -# Proof Runtime Skeptic +# Oven Runtime Skeptic -You review `@flatbread/proof` like a failure analyst. Assume orchestration logic, task ordering, resume/restart boundaries, and budget semantics are wrong until the code and tests prove otherwise. +You review `@flatbread/oven` like a failure analyst. Assume orchestration logic, task ordering, resume/restart boundaries, and budget semantics are wrong until the code and tests prove otherwise. ## Bias @@ -20,8 +20,8 @@ You review `@flatbread/proof` like a failure analyst. Assume orchestration logic - Runtime correctness for DAG execution, especially dependency ordering, rank behavior, partial reruns, and terminal outcomes. - Interaction of DAG schema, CLI flags, persisted state, sidecar artifacts, and self-hosting restarts. - Whether tests prove the runtime contract contributors will depend on. -- Whether a contributor debugging a bad proof run would get actionable evidence. -- Prefer `pnpm test` when validating proof runtime behavior. +- Whether a contributor debugging a bad oven run would get actionable evidence. +- Prefer `pnpm test` when validating oven runtime behavior. ## Output diff --git a/.cursor/skills/dag-task-runner/SKILL.md b/.cursor/skills/dag-task-runner/SKILL.md index 11447bb..2eca6fd 100644 --- a/.cursor/skills/dag-task-runner/SKILL.md +++ b/.cursor/skills/dag-task-runner/SKILL.md @@ -1,33 +1,33 @@ --- name: dag-task-runner -description: DEPRECATED ALIAS — the DAG task runner has been promoted to @flatbread/proof. Use the `proof` skill (.cursor/skills/proof/SKILL.md) for new work; this entry only exists to redirect agents that still reference the old name. +description: DEPRECATED ALIAS — the DAG task runner has been promoted to @flatbread/oven. Use the `oven` skill (.cursor/skills/oven/SKILL.md) for new work; this entry only exists to redirect agents that still reference the old name. --- -# DAG Task Runner — moved to `proof` +# DAG Task Runner — moved to `oven` This skill has been renamed and promoted from a copy-into-skill bundle to the -standalone `@flatbread/proof` package (GitHub: `FlatbreadLabs/proof`). +standalone `@flatbread/oven` package (GitHub: `FlatbreadLabs/oven`). ## What changed -| Before | After | -| -------------------------------------------------------- | -------------------------------------------- | -| Skill name `dag-task-runner` | Skill name `proof` | -| Runtime in `.cursor/skills/dag-task-runner/scripts/*.ts` | Runtime in `src/*.ts` | -| Run via `tsx .cursor/skills/.../run_dag.ts` | Run via `pnpm exec proof` | -| Supervisor `tsx .../run_dag_supervisor.ts` | Supervisor `pnpm exec proof-supervisor` | -| Default state dir `.dag-runner/` | Default state dir `.proof/` | -| Log prefix `[dag-runner]` / `[dag-runner-supervisor]` | Log prefix `[proof]` / `[proof-supervisor]` | -| Examples at `.cursor/skills/dag-task-runner/examples/` | Examples at `.cursor/skills/proof/examples/` | +| Before | After | +| -------------------------------------------------------- | ------------------------------------------- | +| Skill name `dag-task-runner` | Skill name `oven` | +| Runtime in `.cursor/skills/dag-task-runner/scripts/*.ts` | Runtime in `src/*.ts` | +| Run via `tsx .cursor/skills/.../run_dag.ts` | Run via `pnpm exec oven` | +| Supervisor `tsx .../run_dag_supervisor.ts` | Supervisor `pnpm exec oven-supervisor` | +| Default state dir `.dag-runner/` | Default state dir `.oven/` | +| Log prefix `[dag-runner]` / `[dag-runner-supervisor]` | Log prefix `[oven]` / `[oven-supervisor]` | +| Examples at `.cursor/skills/dag-task-runner/examples/` | Examples at `.cursor/skills/oven/examples/` | -CLI flag names, the DAG JSON schema, the `.canvas.tsx` shape, oracle / pause / convergence semantics, and the public library API are all unchanged. Existing DAG JSON files and persisted run-state files (move them from `.dag-runner/` to `.proof/` if you want to resume) work as-is. +CLI flag names, the DAG JSON schema, the `.canvas.tsx` shape, oracle / pause / convergence semantics, and the public library API are all unchanged. Existing DAG JSON files and persisted run-state files (move them from `.dag-runner/` to `.oven/` if you want to resume) work as-is. ## What to do -1. Open `.cursor/skills/proof/SKILL.md` for the canonical workflow. -2. Replace any hardcoded `.cursor/skills/dag-task-runner/scripts/run_dag.ts` paths in your prompts / playbooks with the `pnpm exec proof` invocation. -3. If you have an in-flight run with `.dag-runner/run-state.json`, either rename the directory to `.proof/` or pass the old path explicitly via `--state-path`. +1. Open `.cursor/skills/oven/SKILL.md` for the canonical workflow. +2. Replace any hardcoded `.cursor/skills/dag-task-runner/scripts/run_dag.ts` paths in your prompts / playbooks with the `pnpm exec oven` invocation. +3. If you have an in-flight run with `.dag-runner/run-state.json`, either rename the directory to `.oven/` or pass the old path explicitly via `--state-path`. ## Why -`dag-task-runner` was always a copy-into-project bundle, which meant every project carried its own bit-rotted snapshot of the runtime. Promoting it to `@flatbread/proof` keeps one maintained runner with tsup builds, lint, and type checks, and gives downstream tooling a stable `import { parseDAG, computeRanks, ... } from '@flatbread/proof'` library surface alongside the CLI. +`dag-task-runner` was always a copy-into-project bundle, which meant every project carried its own bit-rotted snapshot of the runtime. Promoting it to `@flatbread/oven` keeps one maintained runner with tsup builds, lint, and type checks, and gives downstream tooling a stable `import { parseDAG, computeRanks, ... } from '@flatbread/oven'` library surface alongside the CLI. diff --git a/.cursor/skills/proof/SKILL.md b/.cursor/skills/oven/SKILL.md similarity index 82% rename from .cursor/skills/proof/SKILL.md rename to .cursor/skills/oven/SKILL.md index 568bdf1..3bfe4aa 100644 --- a/.cursor/skills/proof/SKILL.md +++ b/.cursor/skills/oven/SKILL.md @@ -1,13 +1,13 @@ --- -name: proof +name: oven description: Decompose a user's task into a DAG of subtasks and execute them with Cursor SDK local subagents in topological order, rendering live streaming status to a canvas. Each task has a complexity (HIGH/MED/LOW) that maps to a model. Use when the user asks to fan out work, decompose a task into a DAG, run subagents in parallel, or break a large task into a dependency graph. --- -# Proof +# Oven Decomposes a user-described task into a JSON DAG, then runs each node as a Cursor SDK local subagent (with parents' outputs stitched into the child's prompt). Live DAG state — including each running subagent's streaming output — is rendered into a `.canvas.tsx` that the runner rewrites on every status transition; the IDE hot-recompiles so the user sees subagents move through `PENDING -> RUNNING -> FINISHED/ERROR` in real time. -The runtime ships as the npm package `@flatbread/proof` (sources under `src/`). It exposes two CLIs — `proof` (runner) and `proof-supervisor` (self-hosting wrapper) — plus a public library API for tooling that wants to author or inspect DAGs programmatically. +The runtime ships as the npm package `@flatbread/oven` (sources under `src/`). It exposes two CLIs — `oven` (runner) and `oven-supervisor` (self-hosting wrapper) — plus a public library API for tooling that wants to author or inspect DAGs programmatically. ## When to use @@ -71,7 +71,7 @@ The runner executes tasks within a rank **concurrently** via `Promise.all`. A li Quality bar: when you sketch the rank structure (rank 1 → rank 2 → …), at least one rank should contain more than one task in any non-trivial problem. If your DAG is a single chain of 1-task ranks, you almost certainly missed parallelism — go back and look again. -The example shipped with the skill (`.cursor/skills/proof/examples/example_dag.json`) demonstrates the pattern: rank 1 fans out to two read-only research tasks, rank 2 merges them into a design, rank 3 implements, and rank 4 fans out again to tests + docs. For `kind: "oracle"`, `kind: "pause"`, and `DAG.loops`, see `.cursor/skills/proof/examples/example_gates_dag.json`. +The example shipped with the skill (`.cursor/skills/oven/examples/example_dag.json`) demonstrates the pattern: rank 1 fans out to two read-only research tasks, rank 2 merges them into a design, rank 3 implements, and rank 4 fans out again to tests + docs. For `kind: "oracle"`, `kind: "pause"`, and `DAG.loops`, see `.cursor/skills/oven/examples/example_gates_dag.json`. Write the JSON to a temp file **and immediately generate the initial canvas** so the user can open it while subagents spin up. Run all of the following in a single shell block: @@ -88,7 +88,7 @@ JSON [ -f "$(git rev-parse --show-toplevel)/dist/run_dag.js" ] || pnpm build # 3. Generate the initial all-PENDING canvas (no CURSOR_API_KEY needed) -pnpm exec proof \ +pnpm exec oven \ --init-only \ --dag /tmp/dag-.json \ --canvas-path "$CANVAS_PATH" @@ -121,7 +121,7 @@ Ensure `CURSOR_API_KEY` is set (the runner fails fast if missing), then launch: ```bash [ -n "$CURSOR_API_KEY" ] || { [ -f .env ] && set -a && source .env && set +a; } -pnpm exec proof \ +pnpm exec oven \ --dag /tmp/dag-.json \ --canvas-path "$CANVAS_PATH" ``` @@ -129,7 +129,7 @@ pnpm exec proof \ If the DAG is expected to edit the runner itself (`src/**`), launch through the supervisor instead so source edits take effect at a process boundary: ```bash -pnpm exec proof-supervisor \ +pnpm exec oven-supervisor \ --dag /tmp/dag-.json \ --canvas-path "$CANVAS_PATH" \ --state-path "$HOME/.cursor/projects//dag-state/.json" @@ -147,7 +147,7 @@ Same `--canvas-path` as Step 1. The runner: 6. Artifact output (default, suppress with `--no-artifacts` or override path with `--full-output-dir`; skipped entirely for `--init-only` and `--dry-check-cmds`): - **At run start:** writes `_dag.json` (the original DAG definition) to the artifacts directory. - **As each task finishes:** writes `${taskId}.md` (full transcript for `kind: task`, `oracle`, and `pause`). - - **At run end:** best-effort `_index.md` (run summary table with timestamps, outcome, and per-task links for transcripts that exist); write failures are logged as `[proof]` warnings rather than crashing the runner. + - **At run end:** best-effort `_index.md` (run summary table with timestamps, outcome, and per-task links for transcripts that exist); write failures are logged as `[oven]` warnings rather than crashing the runner. 7. On SIGINT/SIGTERM/SIGHUP, cancels all in-flight subagents before finalizing the canvas. #### CLI knobs @@ -162,7 +162,7 @@ Same `--canvas-path` as Step 1. The runner: | `--stream-publish-ms ` | `500` | Throttles live canvas streaming writes. | | `--stream-idle-timeout-ms ` | `300000` (5 min) | Marks a task `ERROR` if no stream events arrive. | | `--debounce ` | `200` | Canvas write debounce interval. | -| `--full-output-dir ` | computed default | Per-task transcripts + `_index.md` + `_dag.json`. Default: `/.flatbread/artifacts/dag--/`. Override path or suppress with `--no-artifacts`. | +| `--full-output-dir ` | computed default | Per-task transcripts + `_index.md` + `_dag.json`. Default: `/.oven/artifacts/dag--/`. Override path or suppress with `--no-artifacts`. | | `--no-artifacts` | `false` | Suppresses per-task transcripts, `_index.md`, and `_dag.json`; does **not** suppress `--findings-dir` JSON sidecars (separate code path). Canvas is still written. | ### Step 4 — Summarize @@ -177,7 +177,7 @@ After the runner exits, briefly summarize what completed/failed and re-link the | MED | `composer-2` | | LOW | `gpt-5.4-nano` | -Override any subset inline with top-level DAG `models`, or pass a reusable profile with `--models-file `. Values can be plain SDK model id strings or SDK model selections with `params`. At run time, Proof calls `Cursor.models.list()`, validates ids and param values, and expands partial selections by requiring requested params to match a catalog variant, then choosing the valid variant whose omitted params best match the model's default variant. Precedence is defaults < DAG `models` < `--models-file`. The Cursor model catalog can vary by account. +Override any subset inline with top-level DAG `models`, or pass a reusable profile with `--models-file `. Values can be plain SDK model id strings or SDK model selections with `params`. At run time, Oven calls `Cursor.models.list()`, validates ids and param values, and expands partial selections by requiring requested params to match a catalog variant, then choosing the valid variant whose omitted params best match the model's default variant. Precedence is defaults < DAG `models` < `--models-file`. The Cursor model catalog can vary by account. To use a cheaper high-capability GPT model, use the base SDK id plus params, not a suffix-style id: @@ -225,31 +225,31 @@ set -a && source .env && set +a ## CLI options -| Flag | Default | Notes | -| ---------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `--dag` | required | Path to the DAG JSON file. | -| `--canvas-path` | composed from below | Full path to the canvas file. Preferred as an absolute path for parent-managed flow; relative paths are accepted and resolve from the runner process cwd, not `--cwd`. | -| `--canvas` | — | Canvas filename stem (no `.canvas.tsx`). Used only if `--canvas-path` is omitted. | -| `--canvases-dir` | derived from cwd | Override the canvases output directory. Used only with `--canvas`. | -| `--cwd` | `process.cwd()` | Working dir each subagent operates in. | -| `--models-file` | — | JSON file containing a partial complexity → model override map. | -| `--debounce` | `200` (ms) | Canvas write debounce interval. | -| `--init-only` | `false` | Write the initial all-`PENDING` canvas and exit. No `CURSOR_API_KEY` required. | -| `--full-output-dir` | computed default | Per-task transcripts as `${taskId}.md` plus `_index.md` and `_dag.json`. Defaults to `/.flatbread/artifacts/dag--/`. Override with an explicit path or suppress with `--no-artifacts`. | -| `--no-artifacts` | `false` | Suppresses per-task transcripts, `_index.md`, and `_dag.json`; does **not** suppress `--findings-dir` JSON sidecars (separate code path). Canvas is still written. | -| `--findings-dir` | — | Per-task JSON sidecars as `${taskId}.findings.json` for original runs and `${taskId}.iter.findings.json` for convergence re-runs. Schema: `{ taskId, iteration, status, durationMs, sections }`. | -| `--state-path` | — | Persist resumable runner state. Defaults to `.proof/run-state.json` when `--restart-on-runner-change` is set. | -| `--resume-state` | — | Load a persisted `RunState` and skip already terminal tasks. | -| `--restart-on-runner-change` | `false` | Detect runner runtime file changes after safe boundaries and exit `75` for supervisor restart. | -| `--max-runner-restarts` | `20` | Supervisor-only cap for relaunches from `proof-supervisor`. | -| `--task-timeout-ms` | `1200000` (20 min) | Marks a task `ERROR` if it exceeds this duration. | -| `--stream-publish-ms` | `500` (ms) | Throttles live canvas streaming writes to avoid excessive cloning. | -| `--stream-idle-timeout-ms` | `300000` (5 min) | Marks a task `ERROR` if no stream events arrive within this window. | +| Flag | Default | Notes | +| ---------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `--dag` | required | Path to the DAG JSON file. | +| `--canvas-path` | composed from below | Full path to the canvas file. Preferred as an absolute path for parent-managed flow; relative paths are accepted and resolve from the runner process cwd, not `--cwd`. | +| `--canvas` | — | Canvas filename stem (no `.canvas.tsx`). Used only if `--canvas-path` is omitted. | +| `--canvases-dir` | derived from cwd | Override the canvases output directory. Used only with `--canvas`. | +| `--cwd` | `process.cwd()` | Working dir each subagent operates in. | +| `--models-file` | — | JSON file containing a partial complexity → model override map. | +| `--debounce` | `200` (ms) | Canvas write debounce interval. | +| `--init-only` | `false` | Write the initial all-`PENDING` canvas and exit. No `CURSOR_API_KEY` required. | +| `--full-output-dir` | computed default | Per-task transcripts as `${taskId}.md` plus `_index.md` and `_dag.json`. Defaults to `/.oven/artifacts/dag--/`. Override with an explicit path or suppress with `--no-artifacts`. | +| `--no-artifacts` | `false` | Suppresses per-task transcripts, `_index.md`, and `_dag.json`; does **not** suppress `--findings-dir` JSON sidecars (separate code path). Canvas is still written. | +| `--findings-dir` | — | Per-task JSON sidecars as `${taskId}.findings.json` for original runs and `${taskId}.iter.findings.json` for convergence re-runs. Schema: `{ taskId, iteration, status, durationMs, sections }`. | +| `--state-path` | — | Persist resumable runner state. Defaults to `.oven/run-state.json` when `--restart-on-runner-change` is set. | +| `--resume-state` | — | Load a persisted `RunState` and skip already terminal tasks. | +| `--restart-on-runner-change` | `false` | Detect runner runtime file changes after safe boundaries and exit `75` for supervisor restart. | +| `--max-runner-restarts` | `20` | Supervisor-only cap for relaunches from `oven-supervisor`. | +| `--task-timeout-ms` | `1200000` (20 min) | Marks a task `ERROR` if it exceeds this duration. | +| `--stream-publish-ms` | `500` (ms) | Throttles live canvas streaming writes to avoid excessive cloning. | +| `--stream-idle-timeout-ms` | `300000` (5 min) | Marks a task `ERROR` if no stream events arrive within this window. | ## Caveats -- Per-task markdown transcripts, a run index (`_index.md`), and the DAG definition (`_dag.json`) are written under **`/.flatbread/artifacts/`** by default on **full DAG runs** (not `--init-only` or `--dry-check-cmds`). Pass `--no-artifacts` to suppress transcripts/index/DAG JSON, or `--full-output-dir` to override the path. `_index.md` links only transcripts that exist; if an individual transcript write fails, that row is marked as a missing transcript. **`--no-artifacts` does not disable `--findings-dir`** — for fully clean disk output, omit `--findings-dir` as well. In CI or read-only workspaces you may want `--no-artifacts` or a writable `--full-output-dir`. -- When using `proof-supervisor`, each **child runner process** recomputes the default artifacts path with a new timestamp unless you pin a stable directory. The supervisor forwards the full argv to each child (only `--max-runner-restarts` is stripped), so put **`--full-output-dir ` on the supervisor invocation** if every restart should write into the same artifacts folder. +- Per-task markdown transcripts, a run index (`_index.md`), and the DAG definition (`_dag.json`) are written under **`/.oven/artifacts/`** by default on **full DAG runs** (not `--init-only` or `--dry-check-cmds`). Pass `--no-artifacts` to suppress transcripts/index/DAG JSON, or `--full-output-dir` to override the path. `_index.md` links only transcripts that exist; if an individual transcript write fails, that row is marked as a missing transcript. **`--no-artifacts` does not disable `--findings-dir`** — for fully clean disk output, omit `--findings-dir` as well. In CI or read-only workspaces you may want `--no-artifacts` or a writable `--full-output-dir`. +- When using `oven-supervisor`, each **child runner process** recomputes the default artifacts path with a new timestamp unless you pin a stable directory. The supervisor forwards the full argv to each child (only `--max-runner-restarts` is stripped), so put **`--full-output-dir ` on the supervisor invocation** if every restart should write into the same artifacts folder. - `--resume-state` creates a new artifact directory for the resumed session; tasks completed in prior sessions do not have transcripts in the new directory. - Local runtime only — every subagent runs against `--cwd` (defaults to wherever you invoke the runner). - Sibling tasks in the same rank run in parallel; do not let them write the same files. @@ -262,9 +262,9 @@ set -a && source .env && set +a ## Reference -- Package: `@flatbread/proof` (repo root; sources in `src/`) -- Parallelism example: `.cursor/skills/proof/examples/example_dag.json` -- Gates example (oracle, pause, loops): `.cursor/skills/proof/examples/example_gates_dag.json` -- Library exports: `import { parseDAG, computeRanks, ... } from '@flatbread/proof'` +- Package: `@flatbread/oven` (repo root; sources in `src/`) +- Parallelism example: `.cursor/skills/oven/examples/example_dag.json` +- Gates example (oracle, pause, loops): `.cursor/skills/oven/examples/example_gates_dag.json` +- Library exports: `import { parseDAG, computeRanks, ... } from '@flatbread/oven'` - Cursor SDK docs: https://cursor.com/docs/api/sdk/typescript -- Runtime reviewer agent: `.cursor/agents/proof-runtime-skeptic.md` +- Runtime reviewer agent: `.cursor/agents/oven-runtime-skeptic.md` diff --git a/.cursor/skills/proof/examples/example_dag.json b/.cursor/skills/oven/examples/example_dag.json similarity index 100% rename from .cursor/skills/proof/examples/example_dag.json rename to .cursor/skills/oven/examples/example_dag.json diff --git a/.cursor/skills/proof/examples/example_gates_dag.json b/.cursor/skills/oven/examples/example_gates_dag.json similarity index 100% rename from .cursor/skills/proof/examples/example_gates_dag.json rename to .cursor/skills/oven/examples/example_gates_dag.json diff --git a/.gitignore b/.gitignore index b109d5f..4b17854 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ dist .DS_Store .env .env.* -.flatbread/artifacts/ -.proof/ +.oven/artifacts/ +.oven/ *.log .pnpm-debug.log diff --git a/.prettierignore b/.prettierignore index 498141e..a4faeef 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,4 @@ dist node_modules pnpm-lock.yaml -.flatbread -.proof +.oven diff --git a/AGENTS.md b/AGENTS.md index 124fc2f..0e4d443 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,11 +1,11 @@ # Agents -Proof is a standalone agent-orchestration tool. It takes a DAG of Cursor +Oven is a standalone agent-orchestration tool. It takes a DAG of Cursor subagent tasks, runs them in dependency order with a model chosen by task complexity, and writes live status into a `.canvas.tsx` file. -The npm package name is `@flatbread/proof`. The GitHub repo is -`FlatbreadLabs/proof`. +The npm package name is `@flatbread/oven`. The GitHub repo is +`FlatbreadLabs/oven`. ## Key commands @@ -22,7 +22,7 @@ Useful extras: `pnpm lint:fix`, `pnpm models:list`, and ## Gotchas -1. **Build before test or CLI use.** `pnpm test` and `pnpm exec proof` need +1. **Build before test or CLI use.** `pnpm test` and `pnpm exec oven` need `dist/`. Run `pnpm build` after a clean install or source edit. 2. **`CURSOR_API_KEY` for real runs.** Full DAG runs and `pnpm models:list` need the key. `--init-only` and `--dry-check-cmds` do not. diff --git a/README.md b/README.md index 05ad90d..cc698d3 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# Proof +# Oven -Proof is an agent-orchestration tool for Cursor. You give it a DAG of subagent +Oven is an agent-orchestration tool for Cursor. You give it a DAG of subagent tasks; it runs each node in dependency order, picks a model from the task's complexity (`HIGH` / `MED` / `LOW`), and streams live status into a `.canvas.tsx` file so you can watch work move from `PENDING` to `RUNNING` to `FINISHED` or `ERROR`. -The npm package is `@flatbread/proof`. It ships: +The npm package is `@flatbread/oven`. It ships: -- `proof` — run a DAG, or initialize its canvas without an API key -- `proof-supervisor` — self-hosting wrapper that restarts when the runner's own +- `oven` — run a DAG, or initialize its canvas without an API key +- `oven-supervisor` — self-hosting wrapper that restarts when the runner's own sources change between ranks - Library exports for tooling that authors, validates, or inspects DAGs @@ -61,7 +61,7 @@ Create a DAG JSON file: Write the initial canvas without `CURSOR_API_KEY`: ```bash -pnpm exec proof \ +pnpm exec oven \ --init-only \ --dag /tmp/example-dag.json \ --canvas-path /tmp/example-dag.canvas.tsx @@ -72,7 +72,7 @@ Run the DAG: ```bash export CURSOR_API_KEY=crsr_... -pnpm exec proof \ +pnpm exec oven \ --dag /tmp/example-dag.json \ --canvas-path /tmp/example-dag.canvas.tsx ``` @@ -80,7 +80,7 @@ pnpm exec proof \ Validate shell commands embedded in prompts (no API key, no canvas write): ```bash -pnpm exec proof --dry-check-cmds --dag .cursor/skills/proof/examples/example_dag.json +pnpm exec oven --dry-check-cmds --dag .cursor/skills/oven/examples/example_dag.json ``` ## DAG shape @@ -92,7 +92,7 @@ Every DAG has a `title` and a `tasks` array. Each task needs: - `complexity`: `HIGH`, `MED`, or `LOW`; maps to a Cursor model. - `subtask_prompt`: standalone instructions for the subagent. -Proof computes ranks with Kahn topological sort and runs sibling tasks in the same rank concurrently. Avoid placing two sibling tasks in the same rank if they write the same files. +Oven computes ranks with Kahn topological sort and runs sibling tasks in the same rank concurrently. Avoid placing two sibling tasks in the same rank if they write the same files. Optional top-level `models` can override the default complexity map with plain SDK model id strings or SDK model selections: @@ -116,7 +116,7 @@ SDK model id strings or SDK model selections: Use the object shape when you need `params`; use a string when the model id is enough. For example, use `{ "id": "gpt-5.4", "params": [{ "id": "reasoning", "value": "high" }] }`, not a suffix-style id like `gpt-5.4-high`. -When a DAG runs, Proof calls `Cursor.models.list()`, validates model ids and +When a DAG runs, Oven calls `Cursor.models.list()`, validates model ids and param values, and expands partial selections to the closest valid SDK preset variant using that model's default variant for omitted params. `--init-only` does not call the SDK, so it can still render a canvas without `CURSOR_API_KEY`. @@ -126,7 +126,7 @@ Optional task kinds add control gates: - `kind: "oracle"` runs a shell command and records pass/fail evidence. - `kind: "pause"` waits for a checkpoint sentinel so a human can inspect or approve before downstream work continues. -See `.cursor/skills/proof/examples/example_gates_dag.json` for a small DAG that combines mixed `complexity`, an oracle, a pause, and a `DAG.loops` entry. +See `.cursor/skills/oven/examples/example_gates_dag.json` for a small DAG that combines mixed `complexity`, an oracle, a pause, and a `DAG.loops` entry. ## `DAG.loops` @@ -173,7 +173,7 @@ Notes: By default, every **full DAG run** writes per-task markdown transcripts to a timestamped directory (not `--init-only`, which exits before artifact setup, and not `--dry-check-cmds`, which never enters the runner): ``` -/.flatbread/artifacts/dag--/ +/.oven/artifacts/dag--/ _dag.json # The original DAG definition _index.md # Run summary: outcome, timings, and links to all transcripts .md # Full agent output for each task (kind: task, oracle, or pause) @@ -189,20 +189,20 @@ By default, every **full DAG run** writes per-task markdown transcripts to a tim Paths resolve from `--cwd` (defaults to the process working directory). The live canvas still defaults under `~/.cursor/projects//canvases/` when using `--canvas` without `--canvas-path`. -Previously, transcripts only appeared when you passed `--full-output-dir`; now they land under `.flatbread/` by default. Use `--no-artifacts` for opt-out, or `--full-output-dir` to redirect elsewhere. +Previously, transcripts only appeared when you passed `--full-output-dir`; now they land under `.oven/` by default. Use `--no-artifacts` for opt-out, or `--full-output-dir` to redirect elsewhere. `--no-artifacts` suppresses transcripts, `_index.md`, and `_dag.json` only. **`--findings-dir` JSON sidecars use a separate path** — omit that flag (or point it elsewhere) if you need completely artifact-free output besides the canvas. To suppress artifact writing: ```bash -pnpm exec proof --dag /tmp/my.json --canvas-path /tmp/my.canvas.tsx --no-artifacts +pnpm exec oven --dag /tmp/my.json --canvas-path /tmp/my.canvas.tsx --no-artifacts ``` To write artifacts to a custom path: ```bash -pnpm exec proof --dag /tmp/my.json --canvas-path /tmp/my.canvas.tsx \ +pnpm exec oven --dag /tmp/my.json --canvas-path /tmp/my.canvas.tsx \ --full-output-dir /path/to/my-artifacts/ ``` @@ -211,31 +211,31 @@ pnpm exec proof --dag /tmp/my.json --canvas-path /tmp/my.canvas.tsx \ The canonical Cursor skill entrypoint lives at: ```text -.cursor/skills/proof/SKILL.md +.cursor/skills/oven/SKILL.md ``` -Use that skill when a request asks to decompose work, run subagents in parallel, or execute a task as a dependency graph. The legacy `.cursor/skills/dag-task-runner/SKILL.md` entry remains as a compatibility handoff and points to Proof. +Use that skill when a request asks to decompose work, run subagents in parallel, or execute a task as a dependency graph. The legacy `.cursor/skills/dag-task-runner/SKILL.md` entry remains as a compatibility handoff and points to Oven. For read-only reviews of loop semantics, resume/restart boundaries, budget handling, and failure-mode ergonomics, use: ```text -.cursor/agents/proof-runtime-skeptic.md +.cursor/agents/oven-runtime-skeptic.md ``` ## Self-hosting mode -When the DAG may edit Proof itself, use the supervisor: +When the DAG may edit Oven itself, use the supervisor: ```bash -pnpm exec proof-supervisor \ +pnpm exec oven-supervisor \ --dag /tmp/example-dag.json \ --canvas-path /tmp/example-dag.canvas.tsx \ --state-path /tmp/example-dag-state.json ``` -The supervisor adds `--restart-on-runner-change`. If runtime files change after a rank, Proof persists state, exits with code `75`, and the supervisor resumes from the state file under the rebuilt runtime. +The supervisor adds `--restart-on-runner-change`. If runtime files change after a rank, Oven persists state, exits with code `75`, and the supervisor resumes from the state file under the rebuilt runtime. -Each supervisor-spawned runner picks a **new default** `.flatbread/artifacts/dag--/` directory unless you pin **`--full-output-dir ` on the supervisor command** so every child inherits the same path. +Each supervisor-spawned runner picks a **new default** `.oven/artifacts/dag--/` directory unless you pin **`--full-output-dir ` on the supervisor command** so every child inherits the same path. After editing `src/**`, rebuild before resuming packaged CLI runs: @@ -251,14 +251,14 @@ pnpm build pnpm test pnpm lint pnpm models:list -pnpm exec proof --dry-check-cmds --dag .cursor/skills/proof/examples/example_dag.json +pnpm exec oven --dry-check-cmds --dag .cursor/skills/oven/examples/example_dag.json ``` `pnpm test` runs the AVA suite (parser, bounded loops, output retention, and the cloud-agent fetch script smoke tests). ## Library API -Proof also exposes helpers for tooling: +Oven also exposes helpers for tooling: ```ts import { @@ -269,7 +269,7 @@ import { runDryCheck, type DAG, type TaskState, -} from '@flatbread/proof'; +} from '@flatbread/oven'; ``` The public API includes DAG parsing and rank computation, model resolution, canvas state types, convergence helpers, dry command checks, oracle and pause helpers, and self-hosting state utilities. diff --git a/bin/proof-supervisor.js b/bin/oven-supervisor.js similarity index 82% rename from bin/proof-supervisor.js rename to bin/oven-supervisor.js index 468147a..598c833 100755 --- a/bin/proof-supervisor.js +++ b/bin/oven-supervisor.js @@ -7,7 +7,7 @@ if (process.env.FLATBREAD_CI) { process.cwd(), 'node_modules', '@flatbread', - 'proof', + 'oven', 'dist', 'run_dag_supervisor.js' ); @@ -15,7 +15,7 @@ if (process.env.FLATBREAD_CI) { if (existsSync(cliPath)) { import('../dist/run_dag_supervisor.js'); } else { - console.log('@flatbread/proof supervisor CLI is not available'); + console.log('@flatbread/oven supervisor CLI is not available'); } } else { import('../dist/run_dag_supervisor.js'); diff --git a/bin/proof.js b/bin/oven.js similarity index 83% rename from bin/proof.js rename to bin/oven.js index b350074..66648ba 100755 --- a/bin/proof.js +++ b/bin/oven.js @@ -7,7 +7,7 @@ if (process.env.FLATBREAD_CI) { process.cwd(), 'node_modules', '@flatbread', - 'proof', + 'oven', 'dist', 'run_dag.js' ); @@ -15,7 +15,7 @@ if (process.env.FLATBREAD_CI) { if (existsSync(cliPath)) { import('../dist/run_dag.js'); } else { - console.log('@flatbread/proof CLI is not available'); + console.log('@flatbread/oven CLI is not available'); } } else { import('../dist/run_dag.js'); diff --git a/package.json b/package.json index cc6a9ba..c5b4981 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@flatbread/proof", + "name": "@flatbread/oven", "version": "1.0.0", "description": "Bounded DAG task runner for Cursor agents. Runs subagent tasks in topological order with a live canvas, oracle and pause gates, and bounded re-execution loops.", "type": "module", @@ -16,13 +16,13 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/FlatbreadLabs/proof.git" + "url": "git+https://github.com/FlatbreadLabs/oven.git" }, - "homepage": "https://github.com/FlatbreadLabs/proof#readme", + "homepage": "https://github.com/FlatbreadLabs/oven#readme", "author": "Tony Ketcham ", "license": "MIT", "bugs": { - "url": "https://github.com/FlatbreadLabs/proof/issues" + "url": "https://github.com/FlatbreadLabs/oven/issues" }, "exports": { ".": "./dist/index.js" @@ -31,8 +31,8 @@ "module": "dist/index.js", "types": "dist/index.d.ts", "bin": { - "proof": "bin/proof.js", - "proof-supervisor": "bin/proof-supervisor.js" + "oven": "bin/oven.js", + "oven-supervisor": "bin/oven-supervisor.js" }, "files": [ "bin", diff --git a/src/__tests__/output-retention-phase1.test.ts b/src/__tests__/output-retention-phase1.test.ts index 8c6c789..561b8dc 100644 --- a/src/__tests__/output-retention-phase1.test.ts +++ b/src/__tests__/output-retention-phase1.test.ts @@ -112,7 +112,7 @@ test('convergence extraContext carries late blockers under full upstream excerpt }); test('findings sidecar uses parseSource (full transcript) over bounded resultText', async (t) => { - const dir = mkdtempSync(join(tmpdir(), 'proof-sidecar-')); + const dir = mkdtempSync(join(tmpdir(), 'oven-sidecar-')); try { const ts: TaskState = { id: 'task-a', @@ -167,7 +167,7 @@ test('summarize upstream does not rewrite author-owned trailing ellipsis', (t) = }); test('task transcript mirror serializes overlapping flushes in append order', async (t) => { - const dir = mkdtempSync(join(tmpdir(), 'proof-stream-')); + const dir = mkdtempSync(join(tmpdir(), 'oven-stream-')); const store = new TaskTranscriptStore(); try { await store.beginMirroredAppend('task-a', dir); @@ -188,7 +188,7 @@ test('task transcript mirror serializes overlapping flushes in append order', as }); test('task transcript store reads existing mirror files after resume', (t) => { - const dir = mkdtempSync(join(tmpdir(), 'proof-stream-resume-')); + const dir = mkdtempSync(join(tmpdir(), 'oven-stream-resume-')); const store = new TaskTranscriptStore(); try { const rel = taskStreamArtifactRelPath('task-a'); diff --git a/src/canvas_writer.ts b/src/canvas_writer.ts index ea35ad4..6ea2caf 100644 --- a/src/canvas_writer.ts +++ b/src/canvas_writer.ts @@ -212,7 +212,7 @@ export function renderCanvasSource(state: RunState): string { return `${HEADER}\n\nconst STATE: RunState = ${stateLiteral};\n\n${BODY}\n`; } -const HEADER = `/* AUTO-GENERATED by @flatbread/proof. Do not edit by hand — the runner overwrites this file. */ +const HEADER = `/* AUTO-GENERATED by @flatbread/oven. Do not edit by hand — the runner overwrites this file. */ import { Card, CardBody, @@ -292,7 +292,7 @@ interface RunState { }`; const BODY = String.raw`const NODE_H = 64; -const SCROLL_STORAGE_KEY = '@flatbread/proof:scroll-y'; +const SCROLL_STORAGE_KEY = '@flatbread/oven:scroll-y'; const COMPLETED_DOT_COLOR = '#22c55e'; const AWAITING_DOT_COLOR = '#f59e0b'; const BUDGET_DOT_COLOR = '#ef4444'; diff --git a/src/dag.ts b/src/dag.ts index cea780f..719738a 100644 --- a/src/dag.ts +++ b/src/dag.ts @@ -2,7 +2,7 @@ * DAG schema parsing, validation, and topological ranking for the runner. * * The DAG file shape is intentionally tiny — see - * .cursor/skills/proof/examples/example_dag.json. + * .cursor/skills/oven/examples/example_dag.json. */ export type Complexity = 'HIGH' | 'MED' | 'LOW'; diff --git a/src/index.ts b/src/index.ts index 6311f29..68e28d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ /** - * Public library surface for `@flatbread/proof` — the DAG task runner that + * Public library surface for `@flatbread/oven` — the DAG task runner that * decomposes a task into a graph of Cursor SDK subagents and proves they * delivered via live canvas, oracles, pause gates, and convergence loops. * - * The primary use case is the `proof` CLI (`bin/proof.js`); these exports + * The primary use case is the `oven` CLI (`bin/oven.js`); these exports * are for tooling that wants to author or inspect DAGs programmatically. */ diff --git a/src/oracle_task.ts b/src/oracle_task.ts index 6c7eed9..af05215 100644 --- a/src/oracle_task.ts +++ b/src/oracle_task.ts @@ -98,7 +98,7 @@ export async function runOracleTask( deps.writer.schedule(deps.cloneState(deps.state)); console.log( - `[proof] oracle ${task.id} → exec \`${command}\` (expect /${expectSrc}/)` + `[oven] oracle ${task.id} → exec \`${command}\` (expect /${expectSrc}/)` ); const outcome = await execShell(command, options); @@ -142,7 +142,7 @@ export async function runOracleTask( deps.writer.schedule(deps.cloneState(deps.state)); console.log( - `[proof] oracle ${task.id} → ${pass ? 'PASS' : 'FAIL'} (exit ${ + `[oven] oracle ${task.id} → ${pass ? 'PASS' : 'FAIL'} (exit ${ outcome.exitCode ?? 'null' }, ${ts.durationMs}ms${outcome.timedOut ? ', TIMED OUT' : ''})` ); diff --git a/src/pause_task.ts b/src/pause_task.ts index 66bc53a..88babe6 100644 --- a/src/pause_task.ts +++ b/src/pause_task.ts @@ -60,7 +60,7 @@ export async function runPauseTask( deps.writer.schedule(deps.cloneState(deps.state)); console.log( - `[proof] pause ${task.id} → AWAITING_APPROVAL; delete ${sentinelPath} to release the gate` + `[oven] pause ${task.id} → AWAITING_APPROVAL; delete ${sentinelPath} to release the gate` ); const deadline = Date.now() + options.taskTimeoutMs; @@ -92,7 +92,7 @@ export async function runPauseTask( ts.resultText = renderApprovedResultText(sentinelPath, ts.finishedAt); deps.writer.schedule(deps.cloneState(deps.state)); console.log( - `[proof] pause ${task.id} → FINISHED (sentinel removed, ${ts.durationMs}ms gated)` + `[oven] pause ${task.id} → FINISHED (sentinel removed, ${ts.durationMs}ms gated)` ); return; } diff --git a/src/run_dag.ts b/src/run_dag.ts index e1990ed..f958a74 100644 --- a/src/run_dag.ts +++ b/src/run_dag.ts @@ -34,7 +34,7 @@ * --full-output-dir Per-task transcripts as `${taskId}.md` plus * `_index.md` (run summary table) and `_dag.json` * (the original DAG definition). Defaults to - * `/.flatbread/artifacts/dag--/` + * `/.oven/artifacts/dag--/` * when omitted. Override with an explicit path or * suppress entirely with `--no-artifacts`. * --no-artifacts Skip writing per-task transcripts, _index.md, @@ -58,7 +58,7 @@ * `## Stderr (tail)` headings round-trip * through the same parser as regular tasks. * --checkpoint-dir Directory for `kind: 'pause'` sentinel files - * (default `.proof/` under --cwd). + * (default `.oven/` under --cwd). * --converge-on After the main DAG run, parse the named task's * authoritative transcript for `## Blockers` / * `## High-severity findings` (fallbacks to bounded @@ -71,7 +71,7 @@ * --max-iterations is reached. * --max-iterations Convergence iteration ceiling (default: 3). * --state-path Persist resumable runner state after each rank. - * Defaults to `.proof/run-state.json` when + * Defaults to `.oven/run-state.json` when * --restart-on-runner-change is enabled. * --resume-state Resume from a previously persisted state file. * --restart-on-runner-change @@ -188,7 +188,7 @@ interface CliArgs { streamIdleTimeoutMs: number; initOnly: boolean; dryCheckCmds: boolean; - /** Absolute dir for `kind: 'pause'` sentinel files. Defaults to `/.proof`. */ + /** Absolute dir for `kind: 'pause'` sentinel files. Defaults to `/.oven`. */ checkpointDir: string; /** When set, the runner re-executes ancestors after the named task to converge on a clean review. */ convergeOn?: string; @@ -281,7 +281,7 @@ function parseArgs(argv: string[]): CliArgs { const checkpointRaw = args['checkpoint-dir']; const checkpointDir = isAbsolute(checkpointRaw ?? '') ? (checkpointRaw as string) - : resolve(cwd, checkpointRaw ?? '.proof'); + : resolve(cwd, checkpointRaw ?? '.oven'); const convergeRaw = args['converge-on']; const convergeOn = convergeRaw !== undefined && convergeRaw !== '' && convergeRaw !== 'true' @@ -300,7 +300,7 @@ function parseArgs(argv: string[]): CliArgs { statePathRaw !== undefined && statePathRaw !== '' && statePathRaw !== 'true' ? statePathRaw : restartOnRunnerChange - ? (resumeState ?? '.proof/run-state.json') + ? (resumeState ?? '.oven/run-state.json') : undefined; return { @@ -402,7 +402,7 @@ function ensureCursorRipgrepPathEnv(): void { const bundlePkg = cursorSdkRipgrepBundlePackage(); if (!bundlePkg) { console.warn( - '[proof] No bundled ripgrep target for platform; set CURSOR_RIPGREP_PATH to an absolute `rg` path if local agents fail.' + '[oven] No bundled ripgrep target for platform; set CURSOR_RIPGREP_PATH to an absolute `rg` path if local agents fail.' ); return; } @@ -420,7 +420,7 @@ function ensureCursorRipgrepPathEnv(): void { // Optional dependency missing for this OS/arch — user can set CURSOR_RIPGREP_PATH. } console.warn( - `[proof] Could not resolve bundled ripgrep from ${bundlePkg}. Install optional @cursor deps or export CURSOR_RIPGREP_PATH=/absolute/path/to/rg` + `[oven] Could not resolve bundled ripgrep from ${bundlePkg}. Install optional @cursor deps or export CURSOR_RIPGREP_PATH=/absolute/path/to/rg` ); } @@ -444,18 +444,13 @@ function slugifyTitle(s: string): string { /** * Default artifacts directory under the repo (`--cwd`) tree so transcripts - * live beside the workspace (Flatbread convention: `.flatbread/`). Timestamped + * live beside the workspace (Oven convention: `.oven/`). Timestamped * so repeated runs accumulate rather than overwriting each other. */ function defaultArtifactsDir(cwd: string, dagTitleSlug: string): string { const slug = dagTitleSlug || 'untitled'; const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); - return join( - resolve(cwd), - '.flatbread', - 'artifacts', - `dag-${slug}-${timestamp}` - ); + return join(resolve(cwd), '.oven', 'artifacts', `dag-${slug}-${timestamp}`); } async function loadResumedRunState( @@ -600,7 +595,7 @@ async function main(): Promise { modelForComplexity(complexity); } console.log( - '[proof] validated model selections against Cursor.models.list()' + '[oven] validated model selections against Cursor.models.list()' ); } const ranks = computeRanks(dag); @@ -642,7 +637,7 @@ async function main(): Promise { })(); if (fullOutputAbsoluteDir) { await mkdir(fullOutputAbsoluteDir, { recursive: true }); - console.log(`[proof] artifacts → ${fullOutputAbsoluteDir}`); + console.log(`[oven] artifacts → ${fullOutputAbsoluteDir}`); await writeFile( join(fullOutputAbsoluteDir, '_dag.json'), JSON.stringify(raw, null, 2), @@ -656,7 +651,7 @@ async function main(): Promise { : undefined; if (findingsAbsoluteDir && !args.initOnly) { await mkdir(findingsAbsoluteDir, { recursive: true }); - console.log(`[proof] findings-dir → ${findingsAbsoluteDir}`); + console.log(`[oven] findings-dir → ${findingsAbsoluteDir}`); } const statePathAbsolute = @@ -698,14 +693,14 @@ async function main(): Promise { let indexWritten = false; console.log( - `[proof] DAG "${dag.title}" — ${dag.tasks.length} tasks across ${ranks.length} rank(s)` + `[oven] DAG "${dag.title}" — ${dag.tasks.length} tasks across ${ranks.length} rank(s)` ); - console.log(`[proof] canvas → ${args.canvasPath}`); + console.log(`[oven] canvas → ${args.canvasPath}`); if (resumeStateAbsolute) { - console.log(`[proof] resumed state ← ${resumeStateAbsolute}`); + console.log(`[oven] resumed state ← ${resumeStateAbsolute}`); } if (statePathAbsolute) { - console.log(`[proof] state-path → ${statePathAbsolute}`); + console.log(`[oven] state-path → ${statePathAbsolute}`); } // Always write the initial all-PENDING canvas first. This is what the parent @@ -715,7 +710,7 @@ async function main(): Promise { await persistState('initial state'); if (args.initOnly) { - console.log('[proof] --init-only: initial canvas written, exiting'); + console.log('[oven] --init-only: initial canvas written, exiting'); return; } @@ -726,16 +721,16 @@ async function main(): Promise { // ERROR, finalize the canvas, and exit cleanly. const onUnhandledRejection = (reason: unknown) => { const msg = reason instanceof Error ? reason.message : String(reason); - console.error(`[proof] (suppressed unhandled SDK rejection) ${msg}`); + console.error(`[oven] (suppressed unhandled SDK rejection) ${msg}`); }; const onUncaughtException = (err: Error): void => { const msg = err?.stack ?? err?.message ?? String(err); - console.error(`[proof] uncaught exception: ${msg}`); + console.error(`[oven] uncaught exception: ${msg}`); void failAndExit(1, 'FAILED', `Runner crashed: ${err.message}`); }; const onSignal = (signal: NodeJS.Signals): void => { const exitCode = signal === 'SIGINT' ? 130 : 143; - console.error(`[proof] received ${signal}; finalizing canvas before exit`); + console.error(`[oven] received ${signal}; finalizing canvas before exit`); void failAndExit( exitCode, 'INTERRUPTED', @@ -762,9 +757,9 @@ async function main(): Promise { await writer.flush(); await persistState(`runner source changed after ${boundary}`); console.log( - `[proof] runner source changed after ${boundary}; persisted state and exiting ${EXIT_RUNNER_RESTART}` + `[oven] runner source changed after ${boundary}; persisted state and exiting ${EXIT_RUNNER_RESTART}` ); - console.log(`[proof] changed runner files: ${changed.join(', ')}`); + console.log(`[oven] changed runner files: ${changed.join(', ')}`); process.exit(EXIT_RUNNER_RESTART); } @@ -792,7 +787,7 @@ async function main(): Promise { } ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] _index.md write failed: ${msg}`); + console.warn(`[oven] _index.md write failed: ${msg}`); }); indexWritten = true; } @@ -800,7 +795,7 @@ async function main(): Promise { const flushMsg = flushErr instanceof Error ? flushErr.message : String(flushErr); console.error( - `[proof] failed to flush canvas during shutdown: ${flushMsg}` + `[oven] failed to flush canvas during shutdown: ${flushMsg}` ); } finally { finalized = true; @@ -870,7 +865,7 @@ async function main(): Promise { ts.resultText ?? '' ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] artifact write failed for ${task.id}: ${msg}`); + console.warn(`[oven] artifact write failed for ${task.id}: ${msg}`); }); } return; @@ -898,7 +893,7 @@ async function main(): Promise { ts.resultText ?? '' ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] artifact write failed for ${task.id}: ${msg}`); + console.warn(`[oven] artifact write failed for ${task.id}: ${msg}`); }); } return; @@ -938,7 +933,7 @@ async function main(): Promise { } catch (err) { const msg = err instanceof Error ? err.message : String(err); console.error( - `[proof] findings sidecar write failed for ${task.id}: ${msg}` + `[oven] findings sidecar write failed for ${task.id}: ${msg}` ); } } @@ -954,14 +949,14 @@ async function main(): Promise { }); if (runnableRank.length === 0) { console.log( - `[proof] rank ${rankIdx + 1}/${ranks.length}: ${rank + `[oven] rank ${rankIdx + 1}/${ranks.length}: ${rank .map((t) => t.id) .join(', ')} (already complete; skipping)` ); continue; } console.log( - `[proof] rank ${rankIdx + 1}/${ranks.length}: ${runnableRank + `[oven] rank ${rankIdx + 1}/${ranks.length}: ${runnableRank .map((t) => t.id) .join(', ')}` ); @@ -1055,7 +1050,7 @@ async function main(): Promise { } ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] _index.md write failed: ${msg}`); + console.warn(`[oven] _index.md write failed: ${msg}`); }); // Skip the defensive `finally` rewrite now that this attempt finished // (success or logged failure). @@ -1064,17 +1059,17 @@ async function main(): Promise { const succeeded = state.tasks.length - errors.length - budgetHits.length; console.log( - `[proof] done — ${succeeded}/${ + `[oven] done — ${succeeded}/${ state.tasks.length } succeeded in ${formatMs(state.finishedAt - state.startedAt)}` ); if (errors.length > 0) { - console.log(`[proof] errors: ${errors.map((e) => e.id).join(', ')}`); + console.log(`[oven] errors: ${errors.map((e) => e.id).join(', ')}`); process.exitCode = 1; } if (budgetHits.length > 0) { console.log( - `[proof] budget-exceeded: ${budgetHits.map((b) => b.id).join(', ')}` + `[oven] budget-exceeded: ${budgetHits.map((b) => b.id).join(', ')}` ); // Distinct from the generic ERROR exit (1) so wrapper scripts can // branch on budget. We only upgrade `0`; a prior ERROR-driven `1` @@ -1085,7 +1080,7 @@ async function main(): Promise { } if (fullOutputAbsoluteDir) { console.log( - `[proof] full transcripts + index (_index.md) → ${fullOutputAbsoluteDir}` + `[oven] full transcripts + index (_index.md) → ${fullOutputAbsoluteDir}` ); } } catch (err) { @@ -1114,11 +1109,11 @@ async function main(): Promise { } ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] _index.md write failed: ${msg}`); + console.warn(`[oven] _index.md write failed: ${msg}`); }); indexWritten = true; } - console.error(`[proof] ${err.message}`); + console.error(`[oven] ${err.message}`); process.exit(EXIT_BUDGET_EXCEEDED); } const msg = err instanceof Error ? err.message : String(err); @@ -1160,7 +1155,7 @@ async function main(): Promise { } ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] _index.md write failed: ${msg}`); + console.warn(`[oven] _index.md write failed: ${msg}`); }); } } @@ -1372,7 +1367,7 @@ async function runTask( options.transcriptStore.getJoined(task.id) ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] artifact write failed for ${task.id}: ${msg}`); + console.warn(`[oven] artifact write failed for ${task.id}: ${msg}`); }); } options.transcriptStore.finalizeTaskMirrorsDone(task.id); @@ -1545,7 +1540,7 @@ async function bestEffortCancel( } catch (cancelErr) { const msg = cancelErr instanceof Error ? cancelErr.message : String(cancelErr); - console.error(`[proof] failed to cancel timed-out task ${taskId}: ${msg}`); + console.error(`[oven] failed to cancel timed-out task ${taskId}: ${msg}`); } } @@ -1753,7 +1748,7 @@ async function runConvergenceLoop( if (!convergeTs) { // Defensive — main() already validates this, but the loop must not crash. console.error( - `[proof] ${loopId}: convergence task "${convergeOn}" not found in state; skipping` + `[oven] ${loopId}: convergence task "${convergeOn}" not found in state; skipping` ); return; } @@ -1784,7 +1779,7 @@ async function runConvergenceLoop( const findings = extractConvergenceFindings(reviewerSource); if (!findings.hasIssues) { console.log( - `[proof] ${loopId} (converge-on ${convergeOn}): clean — no Blockers / High-severity findings after ${ + `[oven] ${loopId} (converge-on ${convergeOn}): clean — no Blockers / High-severity findings after ${ iter - 1 } re-iteration(s)` ); @@ -1813,13 +1808,13 @@ async function runConvergenceLoop( convergeTs.errorMessage = `Convergence iteration ${iter} would exceed budget.maxIterations=${budget.maxIterations}`; writer.schedule(structuredCloneState(state)); console.log( - `[proof] ${loopId} (converge-on ${convergeOn}): BUDGET-EXCEEDED — iteration ${iter} would exceed budget.maxIterations=${budget.maxIterations}` + `[oven] ${loopId} (converge-on ${convergeOn}): BUDGET-EXCEEDED — iteration ${iter} would exceed budget.maxIterations=${budget.maxIterations}` ); return; } console.log( - `[proof] ${loopId} iteration ${iter}/${maxIterations}: ${findings.blockerLines.length} blocker(s), ${findings.highSeverityLines.length} high-severity finding(s) — re-running ${reExecIds.size} task(s)` + `[oven] ${loopId} iteration ${iter}/${maxIterations}: ${findings.blockerLines.length} blocker(s), ${findings.highSeverityLines.length} high-severity finding(s) — re-running ${reExecIds.size} task(s)` ); const convergenceContext = buildConvergenceContext( @@ -1909,16 +1904,16 @@ async function runConvergenceLoop( } catch (err) { const msg = err instanceof Error ? err.message : String(err); console.error( - `[proof] findings sidecar re-write failed for ${convergeOn} after BUDGET-EXCEEDED: ${msg}` + `[oven] findings sidecar re-write failed for ${convergeOn} after BUDGET-EXCEEDED: ${msg}` ); } } console.log( - `[proof] ${loopId} (converge-on ${convergeOn}): BUDGET-EXCEEDED — exhausted maxIterations=${maxIterations} with ${finalFindings.blockerLines.length} blocker(s), ${finalFindings.highSeverityLines.length} high-severity finding(s)` + `[oven] ${loopId} (converge-on ${convergeOn}): BUDGET-EXCEEDED — exhausted maxIterations=${maxIterations} with ${finalFindings.blockerLines.length} blocker(s), ${finalFindings.highSeverityLines.length} high-severity finding(s)` ); } else { console.log( - `[proof] ${loopId} (converge-on ${convergeOn}): clean after ${maxIterations} re-iteration(s)` + `[oven] ${loopId} (converge-on ${convergeOn}): clean after ${maxIterations} re-iteration(s)` ); } } @@ -1941,7 +1936,7 @@ async function skipTask( ', ' )} blocked this task (upstream ERROR or BUDGET-EXCEEDED)`; console.log( - `[proof] skipping ${task.id} — upstream ${failedDeps.join( + `[oven] skipping ${task.id} — upstream ${failedDeps.join( ', ' )} in ERROR/BUDGET-EXCEEDED` ); @@ -1954,7 +1949,7 @@ async function skipTask( '' ).catch((e: unknown) => { const msg = e instanceof Error ? e.message : String(e); - console.warn(`[proof] artifact write failed for ${task.id}: ${msg}`); + console.warn(`[oven] artifact write failed for ${task.id}: ${msg}`); }); } @@ -2043,7 +2038,7 @@ function structuredCloneState(state: RunState): RunState { main().catch((err) => { console.error( - `[proof] fatal: ${err instanceof Error ? (err.stack ?? err.message) : err}` + `[oven] fatal: ${err instanceof Error ? (err.stack ?? err.message) : err}` ); process.exit(1); }); diff --git a/src/run_dag_supervisor.ts b/src/run_dag_supervisor.ts index e186611..0e0e3e5 100644 --- a/src/run_dag_supervisor.ts +++ b/src/run_dag_supervisor.ts @@ -46,7 +46,7 @@ function resolveTsxBin(): string { return 'tsx'; } -const DEFAULT_STATE_PATH = '.proof/run-state.json'; +const DEFAULT_STATE_PATH = '.oven/run-state.json'; const DEFAULT_MAX_RESTARTS = 20; interface SupervisorArgs { @@ -139,7 +139,7 @@ async function runOnce(argv: readonly string[]): Promise { }); child.on('error', (err) => { console.error( - `[proof-supervisor] failed to launch runner: ${err.message}` + `[oven-supervisor] failed to launch runner: ${err.message}` ); resolveCode(1); }); @@ -159,7 +159,7 @@ async function main(): Promise { if (restart > 0) { argv = setFlag(argv, '--resume-state', absoluteStatePath); console.log( - `[proof-supervisor] restart ${restart}/${parsed.maxRestarts} from ${absoluteStatePath}` + `[oven-supervisor] restart ${restart}/${parsed.maxRestarts} from ${absoluteStatePath}` ); } @@ -170,14 +170,14 @@ async function main(): Promise { } console.error( - `[proof-supervisor] exceeded --max-runner-restarts=${parsed.maxRestarts}` + `[oven-supervisor] exceeded --max-runner-restarts=${parsed.maxRestarts}` ); process.exit(1); } main().catch((err) => { console.error( - `[proof-supervisor] fatal: ${ + `[oven-supervisor] fatal: ${ err instanceof Error ? (err.stack ?? err.message) : err }` ); diff --git a/src/task_transcript.ts b/src/task_transcript.ts index 265c378..8b3a3f6 100644 --- a/src/task_transcript.ts +++ b/src/task_transcript.ts @@ -57,7 +57,7 @@ export class TaskTranscriptStore { const msg = e instanceof Error ? e.message : String(e); logMirrorError?.( taskId, - `[proof] stream mirror init failed for ${taskId}: ${msg}` + `[oven] stream mirror init failed for ${taskId}: ${msg}` ); } } @@ -102,7 +102,7 @@ export class TaskTranscriptStore { const msg = e instanceof Error ? e.message : String(e); logMirrorError?.( taskId, - `[proof] stream mirror append failed for ${taskId}: ${msg}` + `[oven] stream mirror append failed for ${taskId}: ${msg}` ); } });