Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cursor/agents/flatbread-architecture-planner.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Keep recommendations aligned with `flatbread-flow-pmf-audit.md` and `flatbread-f

## Output Schema For DAG Handoff

When invoked inside a DAG task (the `dag-task-runner` skill), keep the response under ~1800 chars and lead with these exact `##` headings so downstream tasks can find them after the 2000-char upstream stitch cap:
When invoked inside a DAG task (the `proof` skill / `@flatbread/proof` package), keep the response under ~1800 chars and lead with these exact `##` headings so downstream tasks can find them after the 2000-char upstream stitch cap:

```
## Current contract
Expand Down
269 changes: 20 additions & 249 deletions .cursor/skills/dag-task-runner/SKILL.md

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions .cursor/skills/dag-task-runner/scripts/.gitignore

This file was deleted.

35 changes: 0 additions & 35 deletions .cursor/skills/dag-task-runner/scripts/package.json

This file was deleted.

4 changes: 2 additions & 2 deletions .cursor/skills/flatbread-major-migration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Treat breaking work as a coordinated monorepo release across `flatbread`, `@flat

## Default DAG Shape

When this skill is run under `dag-task-runner`, use the topology in `flatbread-flow-agentic-workflows.md` ("DAG Topology" section). The canonical schema-migration shape — express the DAG via `depends_on` only; the runner computes ranks via Kahn topo-sort. The shape below is what `tsx run_dag.ts --init-only` produces for the starter template (21 tasks across 7 ranks):
When this skill is run under `proof` (the `@flatbread/proof` package; legacy alias `dag-task-runner`), use the topology in `flatbread-flow-agentic-workflows.md` ("DAG Topology" section). The canonical schema-migration shape — express the DAG via `depends_on` only; the runner computes ranks via Kahn topo-sort. The shape below is what `pnpm exec proof --init-only` produces for the starter template (21 tasks across 7 ranks):

```
rank 1 diag-schema, diag-resolvers, diag-types, diag-codegen, diag-cli,
Expand All @@ -79,7 +79,7 @@ rank 6 verify-cli (reviewer; b
rank 7 browser-verify (browser-verifier; binds port 5057, depends_on impl-examples + verify-cli)
```

Two ranks bind port `5057` (`verify-cli`, `browser-verify`); they must remain on distinct ranks. A starter JSON lives at `.cursor/skills/dag-task-runner/examples/flatbread/dag-schema-migration.json`. Edit task contents and `depends_on`, then re-run `--init-only` to confirm the rank shape didn't regress.
Two ranks bind port `5057` (`verify-cli`, `browser-verify`); they must remain on distinct ranks. A starter JSON lives at `.cursor/skills/proof/examples/flatbread/dag-schema-migration.json`. Edit task contents and `depends_on`, then re-run `--init-only` to confirm the rank shape didn't regress.

### Safe parallel cuts

Expand Down
238 changes: 238 additions & 0 deletions .cursor/skills/proof/SKILL.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"id": "recommend-roadmap",
"depends_on": ["synthesize-pmf-gaps"],
"complexity": "HIGH",
"subtask_prompt": "You are acting as `flatbread-architecture-planner` producing a roadmap recommendation. Follow its output schema. Output must lead with these `##` headings verbatim: `## Current contract`, `## Proposed contract`, `## Migration impact`, `## Validation plan`, `## Human checkpoints`.\n\nBased on the synthesized PMF gaps, recommend a concise product direction and roadmap. Output a sharper positioning statement, 3-5 product primitives to add or clarify (each with file/package anchor), near-term experiments, and what not to build yet. `## Migration impact` should map each recommendation to the affected packages so a follow-up `flatbread-major-migration` DAG (template at `.cursor/skills/dag-task-runner/examples/flatbread/dag-schema-migration.json`) can be authored from this output without re-deriving scope."
"subtask_prompt": "You are acting as `flatbread-architecture-planner` producing a roadmap recommendation. Follow its output schema. Output must lead with these `##` headings verbatim: `## Current contract`, `## Proposed contract`, `## Migration impact`, `## Validation plan`, `## Human checkpoints`.\n\nBased on the synthesized PMF gaps, recommend a concise product direction and roadmap. Output a sharper positioning statement, 3-5 product primitives to add or clarify (each with file/package anchor), near-term experiments, and what not to build yet. `## Migration impact` should map each recommendation to the affected packages so a follow-up `flatbread-major-migration` DAG (template at `.cursor/skills/proof/examples/flatbread/dag-schema-migration.json`) can be authored from this output without re-deriving scope."
}
]
}
6 changes: 5 additions & 1 deletion examples/nextjs/lib/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,21 @@ export async function graphqlFetch<T = unknown>(
variables?: Record<string, unknown>,
endpoint: string = 'http://localhost:5057/graphql'
): Promise<T> {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 15000);

const response = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
signal: controller.signal,
body: JSON.stringify({
query,
variables,
}),
});
}).finally(() => clearTimeout(timeout));

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
Expand Down
12 changes: 6 additions & 6 deletions flatbread-flow-agentic-workflows.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,22 @@ For schema-breaking work, use the `flatbread-major-migration` project skill and

## DAG Topology

When running this workflow under the `dag-task-runner` skill, map phases to ranks. The runner executes a rank concurrently, then proceeds to the next.
When running this workflow under the `proof` skill (the `@flatbread/proof` package; legacy alias `dag-task-runner`), map phases to ranks. The runner executes a rank concurrently, then proceeds to the next.

### Constraints (read before authoring a Flatbread DAG)

- **No sub-sub-agents in DAG runs.** Each DAG node is a Cursor SDK local agent. It cannot reliably delegate to `.cursor/agents/*` via `Task(subagent_type=…)`. Inline the relevant agent identity into the `subtask_prompt` instead — start the prompt with `You are acting as <agent-name>. Follow its responsibilities and output schema.` and **paste the full output-schema heading list verbatim into every prompt**, not just the first per identity. The runner only forwards `apiKey`/`model`/`cwd` to `Agent.create` (proof: `.cursor/skills/dag-task-runner/scripts/run_dag.ts:482-486`), so `.cursor/agents/*` system prompts do not propagate.
- **No sub-sub-agents in DAG runs.** Each DAG node is a Cursor SDK local agent. It cannot reliably delegate to `.cursor/agents/*` via `Task(subagent_type=…)`. Inline the relevant agent identity into the `subtask_prompt` instead — start the prompt with `You are acting as <agent-name>. Follow its responsibilities and output schema.` and **paste the full output-schema heading list verbatim into every prompt**, not just the first per identity. The runner only forwards `apiKey`/`model`/`cwd` to `Agent.create` (proof: `packages/proof/src/run_dag.ts`), so `.cursor/agents/*` system prompts do not propagate.
- **`readonly: true` and `tools:` frontmatter are advisory in DAG mode.** A subagent acting as `flatbread-architecture-planner` can still write files because the runner does not pass agent frontmatter to `Agent.create`. `Do not edit files.` is purely a prompt-level instruction; reinforce it in the prompt body for read-only tasks.
- **Project skills do auto-attach.** `dag-task-runner` and `flatbread-major-migration` are visible to subagents via description, so subtask prompts can reference them by name without re-explaining their contents.
- **Project skills do auto-attach.** `proof` and `flatbread-major-migration` are visible to subagents via description, so subtask prompts can reference them by name without re-explaining their contents.
- **Same-rank file-write safety for Flatbread.** The coupled chain `packages/core` → `packages/codegen` → `examples/nextjs` is the most common contention. Treat the safe parallel cuts list below as the source of truth.
- **Same-rank port-5057 safety.** `flatbread start` always binds port `5057` (and `5058` for HTTPS, per `packages/flatbread/src/cli/index.ts:128-135`). Never put two tasks that invoke `flatbread start`, `pnpm dev`, `pnpm build`, or `agent-browser` against `examples/nextjs` in the same rank.
- **2000-char upstream stitch cap on a 4000-char `STREAM_CAP`.** Each child sees at most 2000 chars of each parent's `resultText`, and the parent's output is itself capped at 4000 chars. Subagent output must lead with the structured headings the downstream task needs and group related entries (e.g. `packages/core/src/{generators,resolvers,types}.ts`) to fit in the window.

### Default DAG shape per phase

"Rank" is computed by the runner via Kahn topo-sort over `depends_on`. Author the DAG by `depends_on` only and let the runner derive ranks. Run `tsx run_dag.ts --init-only --dag <path>` after editing to confirm the rank count didn't regress.
"Rank" is computed by the runner via Kahn topo-sort over `depends_on`. Author the DAG by `depends_on` only and let the runner derive ranks. Run `pnpm exec proof --init-only --dag <path>` after editing to confirm the rank count didn't regress.

The schema-migration starter (`.cursor/skills/dag-task-runner/examples/flatbread/dag-schema-migration.json`, 21 tasks) collapses to 7 ranks:
The schema-migration starter (`.cursor/skills/proof/examples/flatbread/dag-schema-migration.json`, 21 tasks) collapses to 7 ranks:

| Phase | Rank | Tasks | Identity |
| --------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------- | -------------------------------- |
Expand Down Expand Up @@ -142,7 +142,7 @@ Every DAG subtask whose work touches positioning, docs, README, examples, or roa

### Templates

Reusable DAG JSONs live at `.cursor/skills/dag-task-runner/examples/flatbread/`. Start from the closest template and edit task-level details rather than re-deriving the rank structure each time.
Reusable DAG JSONs live at `.cursor/skills/proof/examples/flatbread/`. Start from the closest template and edit task-level details rather than re-deriving the rank structure each time.

## Failure Recovery

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@flatbread/codegen": "workspace:*",
"@flatbread/config": "workspace:*",
"@flatbread/core": "workspace:*",
"@flatbread/proof": "workspace:*",
"@flatbread/resolver-svimg": "workspace:*",
"@flatbread/source-filesystem": "workspace:*",
"@flatbread/transformer-markdown": "workspace:*",
Expand Down
129 changes: 129 additions & 0 deletions packages/proof/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Proof

Proof is Flatbread's DAG task runner for Cursor agents. It decomposes a task into a graph of subagents, runs each node in topological order, and writes a live `.canvas.tsx` so you can watch the work move from `PENDING` to `RUNNING` to `FINISHED` or `ERROR`.

The package ships as `@flatbread/proof` and exposes:

- `proof`: run a DAG or initialize its canvas.
- `proof-supervisor`: run Proof in self-hosting mode so edits to `packages/proof/src/**` can be picked up between ranks.
- Library exports for tooling that wants to author, validate, or inspect DAGs programmatically.

## Quick Start

Build the package once after installing dependencies:

```bash
pnpm -F @flatbread/proof build
```

Create a DAG JSON file:

```json
{
"title": "Build a tiny CLI todo app",
"tasks": [
{
"id": "design",
"depends_on": [],
"complexity": "LOW",
"subtask_prompt": "Design the minimal CLI commands and file layout."
},
{
"id": "implement",
"depends_on": ["design"],
"complexity": "MED",
"subtask_prompt": "Implement the todo CLI based on the design."
}
]
}
```

Initialize a canvas without requiring `CURSOR_API_KEY`:

```bash
pnpm exec proof \
--init-only \
--dag /tmp/example-dag.json \
--canvas-path /tmp/example-dag.canvas.tsx
```

Run the DAG:

```bash
export CURSOR_API_KEY=crsr_...

pnpm exec proof \
--dag /tmp/example-dag.json \
--canvas-path /tmp/example-dag.canvas.tsx
```

## DAG Shape

Every DAG has a `title` and a `tasks` array. Each task needs:

- `id`: unique kebab-case task id.
- `depends_on`: ids of parent tasks that must finish first.
- `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.

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.

## Project Skill

The canonical Cursor skill entrypoint lives at:

```text
.cursor/skills/proof/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.

## Self-Hosting Mode

When the DAG may edit Proof itself, use the supervisor:

```bash
pnpm exec proof-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.

After editing `packages/proof/src/**`, rebuild before resuming packaged CLI runs:

```bash
pnpm -F @flatbread/proof build
```

## Useful Commands

```bash
pnpm -F @flatbread/proof typecheck
pnpm -F @flatbread/proof build
pnpm -F @flatbread/proof models:list
pnpm exec proof --dry-check-cmds --dag .cursor/skills/proof/examples/example_dag.json
```

## Library API

Proof also exposes helpers for tooling:

```ts
import {
computeRanks,
createModelResolver,
parseDAG,
runDryCheck,
type DAG,
type TaskState,
} from '@flatbread/proof';
```

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.
22 changes: 22 additions & 0 deletions packages/proof/bin/proof-supervisor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env node
import { resolve } from 'path';
import { existsSync } from 'fs';

if (process.env.FLATBREAD_CI) {
const cliPath = resolve(
process.cwd(),
'node_modules',
'@flatbread',
'proof',
'dist',
'run_dag_supervisor.js'
);

if (existsSync(cliPath)) {
import('../dist/run_dag_supervisor.js');
} else {
console.log('@flatbread/proof supervisor CLI is not available');
}
} else {
import('../dist/run_dag_supervisor.js');
}
22 changes: 22 additions & 0 deletions packages/proof/bin/proof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env node
import { resolve } from 'path';
import { existsSync } from 'fs';

if (process.env.FLATBREAD_CI) {
const cliPath = resolve(
process.cwd(),
'node_modules',
'@flatbread',
'proof',
'dist',
'run_dag.js'
);

if (existsSync(cliPath)) {
import('../dist/run_dag.js');
} else {
console.log('@flatbread/proof CLI is not available');
}
} else {
import('../dist/run_dag.js');
}
51 changes: 51 additions & 0 deletions packages/proof/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"name": "@flatbread/proof",
"version": "0.1.0-alpha.0",
"description": "Decompose a task into a DAG of subagents and prove they did the work — live canvas, oracles, pause gates, and convergence loops.",
"type": "module",
"scripts": {
"build": "tsup",
"dev": "tsup --watch src",
"typecheck": "tsc -p tsconfig.json --noEmit",
"models:list": "tsx src/list_models.ts"
},
"repository": {
"type": "git",
"url": "git+https://github.com/FlatbreadLabs/flatbread.git",
"directory": "packages/proof"
},
"homepage": "https://github.com/FlatbreadLabs/flatbread/tree/main/packages/proof#readme",
"author": "Tony Ketcham <ketcham.dev@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/FlatbreadLabs/flatbread/issues"
},
"exports": {
".": "./dist/index.js"
},
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"bin": {
"proof": "bin/proof.js",
"proof-supervisor": "bin/proof-supervisor.js"
},
"files": [
"bin",
"dist",
"src",
"*.d.ts"
],
"engines": {
"node": ">=18"
},
"dependencies": {
"@cursor/sdk": "^1.0.9"
},
"devDependencies": {
"@types/node": "^22.10.0",
"tsup": "^8.3.0",
"tsx": "^4.19.0",
"typescript": "^5.7.0"
}
}
Loading
Loading