From 85db69fdc16c35330d82761df867cc07f83b2bcf Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Fri, 13 Mar 2026 22:27:19 -0400 Subject: [PATCH] Rename .dot files to .fabro and update all references Rename 79 workflow files from .dot to .fabro extension across fabro/workflows/, test/, test/docs/, and files-internal/demo/. Update TOML configs, Rust production code, test code, and shell scripts. Backward compat tests in test/attractor/ are unchanged. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../daytona-check/{check.dot => check.fabro} | 0 fabro/workflows/daytona-check/run.toml | 2 +- .../{architect.dot => architect.fabro} | 0 .../factory/{expand.dot => expand.fabro} | 0 .../{implement.dot => implement.fabro} | 0 .../factory/{seed.dot => seed.fabro} | 0 .../factory/{specify.dot => specify.fabro} | 0 .../factory/{sync.dot => sync.fabro} | 0 .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/golden-gate/workflow.toml | 2 +- .../hello/{workflow.dot => workflow.fabro} | 0 fabro/workflows/hello/workflow.toml | 2 +- .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/imagegen-openai/workflow.toml | 2 +- .../imagegen/{workflow.dot => workflow.fabro} | 0 fabro/workflows/imagegen/workflow.toml | 2 +- .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/implement/workflow.toml | 2 +- .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/playwright-demo/workflow.toml | 2 +- .../repl/{workflow.dot => workflow.fabro} | 0 fabro/workflows/repl/workflow.toml | 2 +- .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/solitaire/workflow.toml | 2 +- ...ltimodel.dot => spec-dod-multimodel.fabro} | 0 .../spec/{spec-dod.dot => spec-dod.fabro} | 0 .../vnc-demo/{workflow.dot => workflow.fabro} | 0 fabro/workflows/vnc-demo/workflow.toml | 2 +- .../{workflow.dot => workflow.fabro} | 0 fabro/workflows/web-game-demo/workflow.toml | 2 +- .../demo/{01-hello.dot => 01-hello.fabro} | 0 .../{02-tool-use.dot => 02-tool-use.fabro} | 0 .../{03-subagent.dot => 03-subagent.fabro} | 0 .../{04-pipeline.dot => 04-pipeline.fabro} | 0 ...5-branch-loop.dot => 05-branch-loop.fabro} | 0 .../{06-parallel.dot => 06-parallel.fabro} | 0 ...{07-human-gate.dot => 07-human-gate.fabro} | 0 ...8-multi-model.dot => 08-multi-model.fabro} | 0 .../{09-simplify.dot => 09-simplify.fabro} | 0 ...-implement.dot => 10-plan-implement.fabro} | 0 .../{11-ensemble.dot => 11-ensemble.fabro} | 0 .../{12-web-fetch.dot => 12-web-fetch.fabro} | 0 ...{13-web-search.dot => 13-web-search.fabro} | 0 ...-imagegen.dot => 14-search-imagegen.fabro} | 0 files-internal/demo/14-search-imagegen.toml | 2 +- lib/crates/fabro-api/src/demo/mod.rs | 26 ++-- lib/crates/fabro-cli/src/init.rs | 8 +- lib/crates/fabro-cli/tests/cli.rs | 2 +- .../tests/cmd/run/dry-run-branching.toml | 2 +- .../tests/cmd/run/dry-run-conditions.toml | 2 +- .../tests/cmd/run/dry-run-legacy-tool.toml | 2 +- .../tests/cmd/run/dry-run-parallel.toml | 2 +- .../tests/cmd/run/dry-run-simple.toml | 2 +- .../tests/cmd/run/dry-run-styled.toml | 2 +- .../tests/cmd/validate/branching.toml | 2 +- .../tests/cmd/validate/conditions.toml | 2 +- .../fabro-cli/tests/cmd/validate/invalid.toml | 2 +- .../tests/cmd/validate/legacy-tool.toml | 2 +- .../tests/cmd/validate/parallel.toml | 2 +- .../fabro-cli/tests/cmd/validate/simple.toml | 2 +- .../fabro-cli/tests/cmd/validate/styled.toml | 2 +- lib/crates/fabro-workflows/src/cli/graph.rs | 32 +++-- lib/crates/fabro-workflows/src/cli/mod.rs | 14 +- lib/crates/fabro-workflows/src/cli/parse.rs | 20 ++- .../fabro-workflows/src/cli/project_config.rs | 28 ++-- lib/crates/fabro-workflows/src/cli/run.rs | 18 +-- .../fabro-workflows/src/cli/run_config.rs | 134 +++++++++--------- .../fabro-workflows/src/cli/validate.rs | 20 ++- .../src/handler/manager_loop.rs | 2 +- .../fabro-workflows/src/pull_request.rs | 6 +- .../fabro-workflows/src/validation/rules.rs | 4 +- test/{branching.dot => branching.fabro} | 0 test/{conditions.dot => conditions.fabro} | 0 ...put-patterns.dot => output-patterns.fabro} | 0 .../prompts/{pipeline.dot => pipeline.fabro} | 0 .../{new-features.dot => new-features.fabro} | 0 .../models/{example.dot => example.fabro} | 0 .../{my-workflow.dot => my-workflow.fabro} | 0 ...lone-substack.dot => clone-substack.fabro} | 0 ...ltimodel.dot => spec-dod-multimodel.fabro} | 0 .../{spec-dod.dot => spec-dod.fabro} | 0 ...ormance.dot => n-l-spec-conformance.fabro} | 0 ...{semantic-port.dot => semantic-port.fabro} | 0 .../context/{example.dot => example.fabro} | 0 .../{example-02.dot => example-02.fabro} | 0 .../{example-03.dot => example-03.fabro} | 0 .../{example-04.dot => example-04.fabro} | 0 .../failures/{example.dot => example.fabro} | 0 ...efault-choice.dot => default-choice.fabro} | 0 .../run-configuration/{c-i.dot => c-i.fabro} | 0 .../execution/run-configuration/run-c-i.toml | 2 +- ...lan-implement.dot => plan-implement.fabro} | 0 ...nd-preview.dot => build-and-preview.fabro} | 0 .../{research.dot => research.fabro} | 0 .../daytona/{example.dot => example.fabro} | 0 ...nt-feature.dot => implement-feature.fabro} | 0 .../{my-workflow.dot => my-workflow.fabro} | 0 test/docs/run_tests.sh | 4 +- .../{branch-loop.dot => branch-loop.fabro} | 0 .../{fixed-loop.dot => fixed-loop.fabro} | 0 .../ensemble/{ensemble.dot => ensemble.fabro} | 0 .../hello-world/{hello.dot => hello.fabro} | 0 .../{sub-agent.dot => sub-agent.fabro} | 0 .../{tool-use.dot => tool-use.fabro} | 0 .../{multi-model.dot => multi-model.fabro} | 0 .../{parallel.dot => parallel.fabro} | 0 ...lan-implement.dot => plan-implement.fabro} | 0 ...-and-test.dot => implement-and-test.fabro} | 0 .../{sub-workflow.dot => sub-workflow.fabro} | 2 +- ...{hitl-patterns.dot => hitl-patterns.fabro} | 0 ...ll-node-types.dot => all-node-types.fabro} | 0 .../{example.dot => example.fabro} | 0 ...patterns.dot => transition-patterns.fabro} | 0 .../variables/{check.dot => check.fabro} | 0 .../variables/{example.dot => example.fabro} | 0 test/docs/workflows/variables/run-check.toml | 2 +- test/{invalid.dot => invalid.fabro} | 0 test/{legacy_tool.dot => legacy_tool.fabro} | 0 test/{parallel.dot => parallel.fabro} | 0 test/{retro-e2e.dot => retro-e2e.fabro} | 0 test/{simple.dot => simple.fabro} | 0 test/{styled.dot => styled.fabro} | 0 122 files changed, 199 insertions(+), 175 deletions(-) rename fabro/workflows/daytona-check/{check.dot => check.fabro} (100%) rename fabro/workflows/factory/{architect.dot => architect.fabro} (100%) rename fabro/workflows/factory/{expand.dot => expand.fabro} (100%) rename fabro/workflows/factory/{implement.dot => implement.fabro} (100%) rename fabro/workflows/factory/{seed.dot => seed.fabro} (100%) rename fabro/workflows/factory/{specify.dot => specify.fabro} (100%) rename fabro/workflows/factory/{sync.dot => sync.fabro} (100%) rename fabro/workflows/golden-gate/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/hello/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/imagegen-openai/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/imagegen/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/implement/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/playwright-demo/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/repl/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/solitaire/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/spec/{spec-dod-multimodel.dot => spec-dod-multimodel.fabro} (100%) rename fabro/workflows/spec/{spec-dod.dot => spec-dod.fabro} (100%) rename fabro/workflows/vnc-demo/{workflow.dot => workflow.fabro} (100%) rename fabro/workflows/web-game-demo/{workflow.dot => workflow.fabro} (100%) rename files-internal/demo/{01-hello.dot => 01-hello.fabro} (100%) rename files-internal/demo/{02-tool-use.dot => 02-tool-use.fabro} (100%) rename files-internal/demo/{03-subagent.dot => 03-subagent.fabro} (100%) rename files-internal/demo/{04-pipeline.dot => 04-pipeline.fabro} (100%) rename files-internal/demo/{05-branch-loop.dot => 05-branch-loop.fabro} (100%) rename files-internal/demo/{06-parallel.dot => 06-parallel.fabro} (100%) rename files-internal/demo/{07-human-gate.dot => 07-human-gate.fabro} (100%) rename files-internal/demo/{08-multi-model.dot => 08-multi-model.fabro} (100%) rename files-internal/demo/{09-simplify.dot => 09-simplify.fabro} (100%) rename files-internal/demo/{10-plan-implement.dot => 10-plan-implement.fabro} (100%) rename files-internal/demo/{11-ensemble.dot => 11-ensemble.fabro} (100%) rename files-internal/demo/{12-web-fetch.dot => 12-web-fetch.fabro} (100%) rename files-internal/demo/{13-web-search.dot => 13-web-search.fabro} (100%) rename files-internal/demo/{14-search-imagegen.dot => 14-search-imagegen.fabro} (100%) rename test/{branching.dot => branching.fabro} (100%) rename test/{conditions.dot => conditions.fabro} (100%) rename test/docs/agents/outputs/{output-patterns.dot => output-patterns.fabro} (100%) rename test/docs/agents/prompts/{pipeline.dot => pipeline.fabro} (100%) rename test/docs/changelog/2026-03-05/{new-features.dot => new-features.fabro} (100%) rename test/docs/core-concepts/models/{example.dot => example.fabro} (100%) rename test/docs/core-concepts/workflows/{my-workflow.dot => my-workflow.fabro} (100%) rename test/docs/examples/clone-substack/{clone-substack.dot => clone-substack.fabro} (100%) rename test/docs/examples/definition-of-done/{spec-dod-multimodel.dot => spec-dod-multimodel.fabro} (100%) rename test/docs/examples/definition-of-done/{spec-dod.dot => spec-dod.fabro} (100%) rename test/docs/examples/nlspec-conformance/{n-l-spec-conformance.dot => n-l-spec-conformance.fabro} (100%) rename test/docs/examples/semantic-port/{semantic-port.dot => semantic-port.fabro} (100%) rename test/docs/execution/context/{example.dot => example.fabro} (100%) rename test/docs/execution/failures/{example-02.dot => example-02.fabro} (100%) rename test/docs/execution/failures/{example-03.dot => example-03.fabro} (100%) rename test/docs/execution/failures/{example-04.dot => example-04.fabro} (100%) rename test/docs/execution/failures/{example.dot => example.fabro} (100%) rename test/docs/execution/interviews/{default-choice.dot => default-choice.fabro} (100%) rename test/docs/execution/run-configuration/{c-i.dot => c-i.fabro} (100%) rename test/docs/getting-started/why-fabro/{plan-implement.dot => plan-implement.fabro} (100%) rename test/docs/human-tools/preview/{build-and-preview.dot => build-and-preview.fabro} (100%) rename test/docs/integrations/brave-search/{research.dot => research.fabro} (100%) rename test/docs/integrations/daytona/{example.dot => example.fabro} (100%) rename test/docs/reference/dot-language/{implement-feature.dot => implement-feature.fabro} (100%) rename test/docs/reference/dot-language/{my-workflow.dot => my-workflow.fabro} (100%) rename test/docs/tutorials/branch-loop/{branch-loop.dot => branch-loop.fabro} (100%) rename test/docs/tutorials/branch-loop/{fixed-loop.dot => fixed-loop.fabro} (100%) rename test/docs/tutorials/ensemble/{ensemble.dot => ensemble.fabro} (100%) rename test/docs/tutorials/hello-world/{hello.dot => hello.fabro} (100%) rename test/docs/tutorials/hello-world/{sub-agent.dot => sub-agent.fabro} (100%) rename test/docs/tutorials/hello-world/{tool-use.dot => tool-use.fabro} (100%) rename test/docs/tutorials/multi-model/{multi-model.dot => multi-model.fabro} (100%) rename test/docs/tutorials/parallel-review/{parallel.dot => parallel.fabro} (100%) rename test/docs/tutorials/plan-implement/{plan-implement.dot => plan-implement.fabro} (100%) rename test/docs/tutorials/sub-workflow/{implement-and-test.dot => implement-and-test.fabro} (100%) rename test/docs/tutorials/sub-workflow/{sub-workflow.dot => sub-workflow.fabro} (84%) rename test/docs/workflows/human-in-the-loop/{hitl-patterns.dot => hitl-patterns.fabro} (100%) rename test/docs/workflows/stages-and-nodes/{all-node-types.dot => all-node-types.fabro} (100%) rename test/docs/workflows/stylesheets/{example.dot => example.fabro} (100%) rename test/docs/workflows/transitions/{transition-patterns.dot => transition-patterns.fabro} (100%) rename test/docs/workflows/variables/{check.dot => check.fabro} (100%) rename test/docs/workflows/variables/{example.dot => example.fabro} (100%) rename test/{invalid.dot => invalid.fabro} (100%) rename test/{legacy_tool.dot => legacy_tool.fabro} (100%) rename test/{parallel.dot => parallel.fabro} (100%) rename test/{retro-e2e.dot => retro-e2e.fabro} (100%) rename test/{simple.dot => simple.fabro} (100%) rename test/{styled.dot => styled.fabro} (100%) diff --git a/fabro/workflows/daytona-check/check.dot b/fabro/workflows/daytona-check/check.fabro similarity index 100% rename from fabro/workflows/daytona-check/check.dot rename to fabro/workflows/daytona-check/check.fabro diff --git a/fabro/workflows/daytona-check/run.toml b/fabro/workflows/daytona-check/run.toml index 8a71f726c..c6ca50922 100644 --- a/fabro/workflows/daytona-check/run.toml +++ b/fabro/workflows/daytona-check/run.toml @@ -1,6 +1,6 @@ version = 1 goal = "Run cargo check in a Daytona cloud sandbox" -graph = "check.dot" +graph = "check.fabro" [llm] model = "claude-sonnet" diff --git a/fabro/workflows/factory/architect.dot b/fabro/workflows/factory/architect.fabro similarity index 100% rename from fabro/workflows/factory/architect.dot rename to fabro/workflows/factory/architect.fabro diff --git a/fabro/workflows/factory/expand.dot b/fabro/workflows/factory/expand.fabro similarity index 100% rename from fabro/workflows/factory/expand.dot rename to fabro/workflows/factory/expand.fabro diff --git a/fabro/workflows/factory/implement.dot b/fabro/workflows/factory/implement.fabro similarity index 100% rename from fabro/workflows/factory/implement.dot rename to fabro/workflows/factory/implement.fabro diff --git a/fabro/workflows/factory/seed.dot b/fabro/workflows/factory/seed.fabro similarity index 100% rename from fabro/workflows/factory/seed.dot rename to fabro/workflows/factory/seed.fabro diff --git a/fabro/workflows/factory/specify.dot b/fabro/workflows/factory/specify.fabro similarity index 100% rename from fabro/workflows/factory/specify.dot rename to fabro/workflows/factory/specify.fabro diff --git a/fabro/workflows/factory/sync.dot b/fabro/workflows/factory/sync.fabro similarity index 100% rename from fabro/workflows/factory/sync.dot rename to fabro/workflows/factory/sync.fabro diff --git a/fabro/workflows/golden-gate/workflow.dot b/fabro/workflows/golden-gate/workflow.fabro similarity index 100% rename from fabro/workflows/golden-gate/workflow.dot rename to fabro/workflows/golden-gate/workflow.fabro diff --git a/fabro/workflows/golden-gate/workflow.toml b/fabro/workflows/golden-gate/workflow.toml index 1d05663cd..152cce8be 100644 --- a/fabro/workflows/golden-gate/workflow.toml +++ b/fabro/workflows/golden-gate/workflow.toml @@ -1,6 +1,6 @@ version = 1 goal = "Create a hyperrealistic interactive 3D Golden Gate Bridge flight experience" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "gpt-5.4" diff --git a/fabro/workflows/hello/workflow.dot b/fabro/workflows/hello/workflow.fabro similarity index 100% rename from fabro/workflows/hello/workflow.dot rename to fabro/workflows/hello/workflow.fabro diff --git a/fabro/workflows/hello/workflow.toml b/fabro/workflows/hello/workflow.toml index 9bf0f1c3e..7cae89273 100644 --- a/fabro/workflows/hello/workflow.toml +++ b/fabro/workflows/hello/workflow.toml @@ -1,5 +1,5 @@ version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "local" diff --git a/fabro/workflows/imagegen-openai/workflow.dot b/fabro/workflows/imagegen-openai/workflow.fabro similarity index 100% rename from fabro/workflows/imagegen-openai/workflow.dot rename to fabro/workflows/imagegen-openai/workflow.fabro diff --git a/fabro/workflows/imagegen-openai/workflow.toml b/fabro/workflows/imagegen-openai/workflow.toml index f7dd64814..f4bec7465 100644 --- a/fabro/workflows/imagegen-openai/workflow.toml +++ b/fabro/workflows/imagegen-openai/workflow.toml @@ -1,5 +1,5 @@ version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" diff --git a/fabro/workflows/imagegen/workflow.dot b/fabro/workflows/imagegen/workflow.fabro similarity index 100% rename from fabro/workflows/imagegen/workflow.dot rename to fabro/workflows/imagegen/workflow.fabro diff --git a/fabro/workflows/imagegen/workflow.toml b/fabro/workflows/imagegen/workflow.toml index 5e9ff0e16..b2505c847 100644 --- a/fabro/workflows/imagegen/workflow.toml +++ b/fabro/workflows/imagegen/workflow.toml @@ -1,5 +1,5 @@ version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" diff --git a/fabro/workflows/implement/workflow.dot b/fabro/workflows/implement/workflow.fabro similarity index 100% rename from fabro/workflows/implement/workflow.dot rename to fabro/workflows/implement/workflow.fabro diff --git a/fabro/workflows/implement/workflow.toml b/fabro/workflows/implement/workflow.toml index ed04a100e..19bb24bed 100644 --- a/fabro/workflows/implement/workflow.toml +++ b/fabro/workflows/implement/workflow.toml @@ -1,5 +1,5 @@ version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "local" diff --git a/fabro/workflows/playwright-demo/workflow.dot b/fabro/workflows/playwright-demo/workflow.fabro similarity index 100% rename from fabro/workflows/playwright-demo/workflow.dot rename to fabro/workflows/playwright-demo/workflow.fabro diff --git a/fabro/workflows/playwright-demo/workflow.toml b/fabro/workflows/playwright-demo/workflow.toml index e78ff8309..ea32034cc 100644 --- a/fabro/workflows/playwright-demo/workflow.toml +++ b/fabro/workflows/playwright-demo/workflow.toml @@ -1,6 +1,6 @@ version = 1 goal = "Browse Hacker News with Playwright MCP and capture screenshots" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "claude-sonnet-4-6" diff --git a/fabro/workflows/repl/workflow.dot b/fabro/workflows/repl/workflow.fabro similarity index 100% rename from fabro/workflows/repl/workflow.dot rename to fabro/workflows/repl/workflow.fabro diff --git a/fabro/workflows/repl/workflow.toml b/fabro/workflows/repl/workflow.toml index e2f3cfc22..717c72b75 100644 --- a/fabro/workflows/repl/workflow.toml +++ b/fabro/workflows/repl/workflow.toml @@ -1,5 +1,5 @@ version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "local" diff --git a/fabro/workflows/solitaire/workflow.dot b/fabro/workflows/solitaire/workflow.fabro similarity index 100% rename from fabro/workflows/solitaire/workflow.dot rename to fabro/workflows/solitaire/workflow.fabro diff --git a/fabro/workflows/solitaire/workflow.toml b/fabro/workflows/solitaire/workflow.toml index 7955ccc14..a66507eb1 100644 --- a/fabro/workflows/solitaire/workflow.toml +++ b/fabro/workflows/solitaire/workflow.toml @@ -1,2 +1,2 @@ version = 1 -graph = "workflow.dot" \ No newline at end of file +graph = "workflow.fabro" \ No newline at end of file diff --git a/fabro/workflows/spec/spec-dod-multimodel.dot b/fabro/workflows/spec/spec-dod-multimodel.fabro similarity index 100% rename from fabro/workflows/spec/spec-dod-multimodel.dot rename to fabro/workflows/spec/spec-dod-multimodel.fabro diff --git a/fabro/workflows/spec/spec-dod.dot b/fabro/workflows/spec/spec-dod.fabro similarity index 100% rename from fabro/workflows/spec/spec-dod.dot rename to fabro/workflows/spec/spec-dod.fabro diff --git a/fabro/workflows/vnc-demo/workflow.dot b/fabro/workflows/vnc-demo/workflow.fabro similarity index 100% rename from fabro/workflows/vnc-demo/workflow.dot rename to fabro/workflows/vnc-demo/workflow.fabro diff --git a/fabro/workflows/vnc-demo/workflow.toml b/fabro/workflows/vnc-demo/workflow.toml index b927ab847..917290bf7 100644 --- a/fabro/workflows/vnc-demo/workflow.toml +++ b/fabro/workflows/vnc-demo/workflow.toml @@ -1,6 +1,6 @@ version = 1 goal = "Browse the web with Playwright while user watches via VNC" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "claude-sonnet-4-6" diff --git a/fabro/workflows/web-game-demo/workflow.dot b/fabro/workflows/web-game-demo/workflow.fabro similarity index 100% rename from fabro/workflows/web-game-demo/workflow.dot rename to fabro/workflows/web-game-demo/workflow.fabro diff --git a/fabro/workflows/web-game-demo/workflow.toml b/fabro/workflows/web-game-demo/workflow.toml index 92fc16627..e09936cbc 100644 --- a/fabro/workflows/web-game-demo/workflow.toml +++ b/fabro/workflows/web-game-demo/workflow.toml @@ -1,6 +1,6 @@ version = 1 goal = "Verify the develop-web-game skill is properly set up with its asset files" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "claude-sonnet-4-6" diff --git a/files-internal/demo/01-hello.dot b/files-internal/demo/01-hello.fabro similarity index 100% rename from files-internal/demo/01-hello.dot rename to files-internal/demo/01-hello.fabro diff --git a/files-internal/demo/02-tool-use.dot b/files-internal/demo/02-tool-use.fabro similarity index 100% rename from files-internal/demo/02-tool-use.dot rename to files-internal/demo/02-tool-use.fabro diff --git a/files-internal/demo/03-subagent.dot b/files-internal/demo/03-subagent.fabro similarity index 100% rename from files-internal/demo/03-subagent.dot rename to files-internal/demo/03-subagent.fabro diff --git a/files-internal/demo/04-pipeline.dot b/files-internal/demo/04-pipeline.fabro similarity index 100% rename from files-internal/demo/04-pipeline.dot rename to files-internal/demo/04-pipeline.fabro diff --git a/files-internal/demo/05-branch-loop.dot b/files-internal/demo/05-branch-loop.fabro similarity index 100% rename from files-internal/demo/05-branch-loop.dot rename to files-internal/demo/05-branch-loop.fabro diff --git a/files-internal/demo/06-parallel.dot b/files-internal/demo/06-parallel.fabro similarity index 100% rename from files-internal/demo/06-parallel.dot rename to files-internal/demo/06-parallel.fabro diff --git a/files-internal/demo/07-human-gate.dot b/files-internal/demo/07-human-gate.fabro similarity index 100% rename from files-internal/demo/07-human-gate.dot rename to files-internal/demo/07-human-gate.fabro diff --git a/files-internal/demo/08-multi-model.dot b/files-internal/demo/08-multi-model.fabro similarity index 100% rename from files-internal/demo/08-multi-model.dot rename to files-internal/demo/08-multi-model.fabro diff --git a/files-internal/demo/09-simplify.dot b/files-internal/demo/09-simplify.fabro similarity index 100% rename from files-internal/demo/09-simplify.dot rename to files-internal/demo/09-simplify.fabro diff --git a/files-internal/demo/10-plan-implement.dot b/files-internal/demo/10-plan-implement.fabro similarity index 100% rename from files-internal/demo/10-plan-implement.dot rename to files-internal/demo/10-plan-implement.fabro diff --git a/files-internal/demo/11-ensemble.dot b/files-internal/demo/11-ensemble.fabro similarity index 100% rename from files-internal/demo/11-ensemble.dot rename to files-internal/demo/11-ensemble.fabro diff --git a/files-internal/demo/12-web-fetch.dot b/files-internal/demo/12-web-fetch.fabro similarity index 100% rename from files-internal/demo/12-web-fetch.dot rename to files-internal/demo/12-web-fetch.fabro diff --git a/files-internal/demo/13-web-search.dot b/files-internal/demo/13-web-search.fabro similarity index 100% rename from files-internal/demo/13-web-search.dot rename to files-internal/demo/13-web-search.fabro diff --git a/files-internal/demo/14-search-imagegen.dot b/files-internal/demo/14-search-imagegen.fabro similarity index 100% rename from files-internal/demo/14-search-imagegen.dot rename to files-internal/demo/14-search-imagegen.fabro diff --git a/files-internal/demo/14-search-imagegen.toml b/files-internal/demo/14-search-imagegen.toml index 9ed6a11d2..e4ab2c1d9 100644 --- a/files-internal/demo/14-search-imagegen.toml +++ b/files-internal/demo/14-search-imagegen.toml @@ -1,6 +1,6 @@ version = 1 goal = "Search the web for a famous landmark, then generate an image of it" -graph = "14-search-imagegen.dot" +graph = "14-search-imagegen.fabro" [sandbox] provider = "daytona" diff --git a/lib/crates/fabro-api/src/demo/mod.rs b/lib/crates/fabro-api/src/demo/mod.rs index ebe606317..0bffb0475 100644 --- a/lib/crates/fabro-api/src/demo/mod.rs +++ b/lib/crates/fabro-api/src/demo/mod.rs @@ -1303,7 +1303,7 @@ mod runs { serde_json::to_value(fabro_workflows::cli::run_config::WorkflowRunConfig { version: 1, goal: Some("Add rate limiting to auth endpoints".into()), - graph: "implement.dot".into(), + graph: "implement.fabro".into(), directory: Some("/workspace/api-server".into()), llm: Some(fabro_workflows::cli::run_config::LlmConfig { model: Some("claude-opus-4-6".into()), @@ -1415,7 +1415,7 @@ mod workflows { WorkflowListItem { name: "Fix Build".into(), slug: "fix_build".into(), - filename: "fix_build.dot".into(), + filename: "fix_build.fabro".into(), last_run: Some(WorkflowLastRun { ran_at: ts("2025-09-15T12:00:00Z"), }), @@ -1424,7 +1424,7 @@ mod workflows { WorkflowListItem { name: "Implement Feature".into(), slug: "implement".into(), - filename: "implement.dot".into(), + filename: "implement.fabro".into(), last_run: Some(WorkflowLastRun { ran_at: ts("2025-09-11T10:00:00Z"), }), @@ -1433,7 +1433,7 @@ mod workflows { WorkflowListItem { name: "Sync Drift".into(), slug: "sync_drift".into(), - filename: "sync_drift.dot".into(), + filename: "sync_drift.fabro".into(), last_run: Some(WorkflowLastRun { ran_at: ts("2025-09-14T14:00:00Z"), }), @@ -1442,7 +1442,7 @@ mod workflows { WorkflowListItem { name: "Expand Product".into(), slug: "expand".into(), - filename: "expand.dot".into(), + filename: "expand.fabro".into(), last_run: Some(WorkflowLastRun { ran_at: ts("2025-09-01T08:00:00Z"), }), @@ -1475,12 +1475,12 @@ mod workflows { pub fn detail(name: &str) -> Option { let items = [ WorkflowDetail { - name: "Fix Build".into(), slug: "fix_build".into(), filename: "fix_build.dot".into(), + name: "Fix Build".into(), slug: "fix_build".into(), filename: "fix_build.fabro".into(), description: "Automatically diagnoses and fixes CI build failures by analyzing error logs, identifying root causes, and applying targeted code changes.".into(), config: run_config_to_api(fabro_workflows::cli::run_config::WorkflowRunConfig { version: 1, goal: Some("Diagnose and fix CI build failures".into()), - graph: "fix_build.dot".into(), + graph: "fix_build.fabro".into(), directory: None, llm: Some(fabro_workflows::cli::run_config::LlmConfig { model: Some("claude-sonnet".into()), @@ -1543,12 +1543,12 @@ mod workflows { "#.into(), }, WorkflowDetail { - name: "Implement Feature".into(), slug: "implement".into(), filename: "implement.dot".into(), + name: "Implement Feature".into(), slug: "implement".into(), filename: "implement.fabro".into(), description: "Generates production-ready code from a technical blueprint, including tests, documentation, and a pull request ready for review.".into(), config: run_config_to_api(fabro_workflows::cli::run_config::WorkflowRunConfig { version: 1, goal: Some("Implement feature from technical blueprint".into()), - graph: "implement.dot".into(), + graph: "implement.fabro".into(), directory: None, llm: Some(fabro_workflows::cli::run_config::LlmConfig { model: Some("claude-sonnet".into()), @@ -1629,12 +1629,12 @@ mod workflows { "#.into(), }, WorkflowDetail { - name: "Sync Drift".into(), slug: "sync_drift".into(), filename: "sync_drift.dot".into(), + name: "Sync Drift".into(), slug: "sync_drift".into(), filename: "sync_drift.fabro".into(), description: "Detects configuration and code drift between environments, then generates reconciliation patches to bring everything back in sync.".into(), config: run_config_to_api(fabro_workflows::cli::run_config::WorkflowRunConfig { version: 1, goal: Some("Detect and reconcile configuration drift across environments".into()), - graph: "sync_drift.dot".into(), + graph: "sync_drift.fabro".into(), directory: None, llm: Some(fabro_workflows::cli::run_config::LlmConfig { model: Some("claude-sonnet".into()), @@ -1703,12 +1703,12 @@ mod workflows { "#.into(), }, WorkflowDetail { - name: "Expand Product".into(), slug: "expand".into(), filename: "expand.dot".into(), + name: "Expand Product".into(), slug: "expand".into(), filename: "expand.fabro".into(), description: "Evolves the product by analyzing usage patterns and specifications to propose and implement incremental improvements.".into(), config: run_config_to_api(fabro_workflows::cli::run_config::WorkflowRunConfig { version: 1, goal: Some("Propose and implement incremental product improvements".into()), - graph: "expand.dot".into(), + graph: "expand.fabro".into(), directory: None, llm: Some(fabro_workflows::cli::run_config::LlmConfig { model: Some("claude-sonnet".into()), diff --git a/lib/crates/fabro-cli/src/init.rs b/lib/crates/fabro-cli/src/init.rs index 3bb1825eb..0894e0e5e 100644 --- a/lib/crates/fabro-cli/src/init.rs +++ b/lib/crates/fabro-cli/src/init.rs @@ -58,8 +58,8 @@ root = \"fabro/\" std::fs::create_dir_all(&workflow_dir) .with_context(|| format!("failed to create {}", workflow_dir.display()))?; - // Create workflow.dot - let dot_path = workflow_dir.join("workflow.dot"); + // Create workflow.fabro + let dot_path = workflow_dir.join("workflow.fabro"); std::fs::write( &dot_path, r#"digraph Hello { @@ -79,14 +79,14 @@ root = \"fabro/\" eprintln!( " {} {}", green.apply_to("✔"), - dim.apply_to("arc/workflows/hello/workflow.dot") + dim.apply_to("arc/workflows/hello/workflow.fabro") ); // Create workflow.toml let toml_path = workflow_dir.join("workflow.toml"); std::fs::write( &toml_path, - "version = 1\ngraph = \"workflow.dot\"\n\n[sandbox]\nprovider = \"local\"\n", + "version = 1\ngraph = \"workflow.fabro\"\n\n[sandbox]\nprovider = \"local\"\n", ) .with_context(|| format!("failed to write {}", toml_path.display()))?; eprintln!( diff --git a/lib/crates/fabro-cli/tests/cli.rs b/lib/crates/fabro-cli/tests/cli.rs index 17a38df55..4c54b26be 100644 --- a/lib/crates/fabro-cli/tests/cli.rs +++ b/lib/crates/fabro-cli/tests/cli.rs @@ -373,7 +373,7 @@ fn dry_run_writes_jsonl_and_live_json() { "--auto-approve", "--run-dir", run_dir.to_str().unwrap(), - "../../../test/simple.dot", + "../../../test/simple.fabro", ]) .assert() .success(); diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-branching.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-branching.toml index abe612d96..d251a1daa 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-branching.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-branching.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/branching.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/branching.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-conditions.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-conditions.toml index 53e52c729..2a7994e25 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-conditions.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-conditions.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/conditions.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/conditions.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-legacy-tool.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-legacy-tool.toml index c624796ff..9712fe83d 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-legacy-tool.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-legacy-tool.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/legacy_tool.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/legacy_tool.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-parallel.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-parallel.toml index b9b381dc2..a2a78502a 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-parallel.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-parallel.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/parallel.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/parallel.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-simple.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-simple.toml index 92e070c51..25601de4c 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-simple.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-simple.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/simple.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/simple.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/run/dry-run-styled.toml b/lib/crates/fabro-cli/tests/cmd/run/dry-run-styled.toml index b8b494e66..0e2e9c37f 100644 --- a/lib/crates/fabro-cli/tests/cmd/run/dry-run-styled.toml +++ b/lib/crates/fabro-cli/tests/cmd/run/dry-run-styled.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["run", "--dry-run", "--auto-approve", "../../../test/styled.dot"] +args = ["run", "--dry-run", "--auto-approve", "../../../test/styled.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/branching.toml b/lib/crates/fabro-cli/tests/cmd/validate/branching.toml index e3bf5f06a..4595e9da3 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/branching.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/branching.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/branching.dot"] +args = ["validate", "../../../test/branching.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/conditions.toml b/lib/crates/fabro-cli/tests/cmd/validate/conditions.toml index 629cbfbbf..61a1a7305 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/conditions.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/conditions.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/conditions.dot"] +args = ["validate", "../../../test/conditions.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/invalid.toml b/lib/crates/fabro-cli/tests/cmd/validate/invalid.toml index 8fa3e95e1..5d7789906 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/invalid.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/invalid.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/invalid.dot"] +args = ["validate", "../../../test/invalid.fabro"] status = "failed" [fs] diff --git a/lib/crates/fabro-cli/tests/cmd/validate/legacy-tool.toml b/lib/crates/fabro-cli/tests/cmd/validate/legacy-tool.toml index de32fb90b..2b3373f09 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/legacy-tool.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/legacy-tool.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/legacy_tool.dot"] +args = ["validate", "../../../test/legacy_tool.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/parallel.toml b/lib/crates/fabro-cli/tests/cmd/validate/parallel.toml index d26522dbd..371ce7f86 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/parallel.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/parallel.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/parallel.dot"] +args = ["validate", "../../../test/parallel.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/simple.toml b/lib/crates/fabro-cli/tests/cmd/validate/simple.toml index a7f032ff6..310fe6d0a 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/simple.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/simple.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/simple.dot"] +args = ["validate", "../../../test/simple.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-cli/tests/cmd/validate/styled.toml b/lib/crates/fabro-cli/tests/cmd/validate/styled.toml index 787bedc3e..36ef4f1f9 100644 --- a/lib/crates/fabro-cli/tests/cmd/validate/styled.toml +++ b/lib/crates/fabro-cli/tests/cmd/validate/styled.toml @@ -1,5 +1,5 @@ bin.name = "fabro" -args = ["validate", "../../../test/styled.dot"] +args = ["validate", "../../../test/styled.fabro"] [fs] sandbox = false diff --git a/lib/crates/fabro-workflows/src/cli/graph.rs b/lib/crates/fabro-workflows/src/cli/graph.rs index ef1da13dc..daab1c69c 100644 --- a/lib/crates/fabro-workflows/src/cli/graph.rs +++ b/lib/crates/fabro-workflows/src/cli/graph.rs @@ -11,7 +11,7 @@ use tracing::debug; use crate::validation::Severity; use crate::workflow::prepare_from_file; -use super::{print_diagnostics, read_dot_file, relative_path}; +use super::{print_diagnostics, read_workflow_file, relative_path}; /// Output format for graph rendering. #[derive(Debug, Clone, Copy, Default, ValueEnum)] @@ -34,7 +34,7 @@ impl fmt::Display for GraphFormat { #[derive(Args)] pub struct GraphArgs { - /// Path to the .dot workflow file, .toml task config, or project workflow name + /// Path to the .fabro workflow file, .toml task config, or project workflow name pub workflow: PathBuf, /// Output format @@ -58,7 +58,7 @@ pub fn graph_command(args: &GraphArgs, styles: &Styles) -> anyhow::Result<()> { bail!("Validation failed"); } - let source = read_dot_file(&dot_path)?; + let source = read_workflow_file(&dot_path)?; let rendered = render_dot(&source, args.format)?; if let Some(ref output_path) = args.output { @@ -140,7 +140,7 @@ mod tests { #[test] fn graph_missing_file() { let args = GraphArgs { - workflow: PathBuf::from("/tmp/nonexistent_workflow_99999.dot"), + workflow: PathBuf::from("/tmp/nonexistent_workflow_99999.fabro"), format: GraphFormat::Svg, output: None, }; @@ -151,7 +151,10 @@ mod tests { #[test] fn graph_invalid_syntax() { - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "not a valid dot file").unwrap(); let args = GraphArgs { @@ -171,7 +174,10 @@ mod tests { return; } - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "{VALID_DOT}").unwrap(); let output_dir = tempfile::tempdir().unwrap(); @@ -197,7 +203,10 @@ mod tests { return; } - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "{VALID_DOT}").unwrap(); let output_dir = tempfile::tempdir().unwrap(); @@ -227,7 +236,10 @@ mod tests { return; } - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "{VALID_DOT}").unwrap(); let output_dir = tempfile::tempdir().unwrap(); @@ -258,10 +270,10 @@ mod tests { std::fs::create_dir_all(&wf_dir).unwrap(); std::fs::write( wf_dir.join("workflow.toml"), - "version = 1\ngraph = \"workflow.dot\"\n", + "version = 1\ngraph = \"workflow.fabro\"\n", ) .unwrap(); - std::fs::write(wf_dir.join("workflow.dot"), VALID_DOT).unwrap(); + std::fs::write(wf_dir.join("workflow.fabro"), VALID_DOT).unwrap(); let output_dir = tempfile::tempdir().unwrap(); let output_path = output_dir.path().join("out.svg"); diff --git a/lib/crates/fabro-workflows/src/cli/mod.rs b/lib/crates/fabro-workflows/src/cli/mod.rs index ee2a0b515..1625dd30f 100644 --- a/lib/crates/fabro-workflows/src/cli/mod.rs +++ b/lib/crates/fabro-workflows/src/cli/mod.rs @@ -87,7 +87,7 @@ impl FromStr for SandboxProvider { #[command( name = "fabro-workflows", version, - about = "DOT-based workflow runner for AI workflows" + about = "Workflow runner for AI workflows" )] pub struct Cli { #[command(subcommand)] @@ -96,7 +96,7 @@ pub struct Cli { #[derive(Subcommand)] pub enum Command { - /// Launch a workflow from a .dot or .toml task file + /// Launch a workflow from a .fabro or .toml task file Run(RunArgs), /// Parse and validate a workflow without executing Validate(ValidateArgs), @@ -104,7 +104,7 @@ pub enum Command { #[derive(Args)] pub struct RunArgs { - /// Path to a .dot workflow file or .toml task config (not required with --run-branch) + /// Path to a .fabro workflow file or .toml task config (not required with --run-branch) #[arg(required_unless_present = "run_branch")] pub workflow: Option, @@ -175,22 +175,22 @@ pub struct RunArgs { #[derive(Args)] pub struct ValidateArgs { - /// Path to the .dot workflow file + /// Path to the .fabro workflow file pub workflow: PathBuf, } #[derive(Args)] pub struct ParseArgs { - /// Path to the .dot workflow file + /// Path to the .fabro workflow file pub workflow: PathBuf, } -/// Read a .dot file from disk. +/// Read a workflow file from disk. /// /// # Errors /// /// Returns an error if the file cannot be read. -pub fn read_dot_file(path: &Path) -> anyhow::Result { +pub fn read_workflow_file(path: &Path) -> anyhow::Result { std::fs::read_to_string(path) .map_err(|e| anyhow::anyhow!("Failed to read {}: {e}", path.display())) } diff --git a/lib/crates/fabro-workflows/src/cli/parse.rs b/lib/crates/fabro-workflows/src/cli/parse.rs index 9b135f720..9e5ba3777 100644 --- a/lib/crates/fabro-workflows/src/cli/parse.rs +++ b/lib/crates/fabro-workflows/src/cli/parse.rs @@ -1,6 +1,6 @@ use std::io::Write; -use super::{read_dot_file, ParseArgs}; +use super::{read_workflow_file, ParseArgs}; /// Parse a DOT file and print its raw AST as JSON. /// @@ -14,7 +14,7 @@ pub fn parse_command(args: &ParseArgs) -> anyhow::Result<()> { fn parse_command_to(args: &ParseArgs, mut out: impl Write) -> anyhow::Result<()> { let (dot_path, _cfg) = super::project_config::resolve_workflow(&args.workflow)?; - let source = read_dot_file(&dot_path)?; + let source = read_workflow_file(&dot_path)?; let ast = crate::parser::parse_ast(&source)?; serde_json::to_writer_pretty(&mut out, &ast)?; writeln!(out)?; @@ -30,7 +30,10 @@ mod tests { #[test] fn parse_command_outputs_json_ast() { - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!( tmp, r#"digraph Hello {{ @@ -54,7 +57,10 @@ mod tests { #[test] fn parse_command_rejects_invalid_dot() { - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "not a valid dot file").unwrap(); let args = ParseArgs { @@ -71,11 +77,11 @@ mod tests { std::fs::create_dir_all(&wf_dir).unwrap(); std::fs::write( wf_dir.join("workflow.toml"), - "version = 1\ngraph = \"workflow.dot\"\n", + "version = 1\ngraph = \"workflow.fabro\"\n", ) .unwrap(); std::fs::write( - wf_dir.join("workflow.dot"), + wf_dir.join("workflow.fabro"), r#"digraph Hello { start [shape=Mdiamond] exit [shape=Msquare] @@ -97,7 +103,7 @@ mod tests { #[test] fn parse_command_rejects_missing_file() { let args = ParseArgs { - workflow: PathBuf::from("/tmp/nonexistent_parse_test_12345.dot"), + workflow: PathBuf::from("/tmp/nonexistent_parse_test_12345.fabro"), }; let result = parse_command_to(&args, Vec::new()); assert!(result.is_err(), "expected Err for missing file"); diff --git a/lib/crates/fabro-workflows/src/cli/project_config.rs b/lib/crates/fabro-workflows/src/cli/project_config.rs index e552658f4..3fec1dabf 100644 --- a/lib/crates/fabro-workflows/src/cli/project_config.rs +++ b/lib/crates/fabro-workflows/src/cli/project_config.rs @@ -80,7 +80,7 @@ pub fn discover_project_config(start: &Path) -> anyhow::Result (TempDir, PathBuf) { let tmp = TempDir::new().unwrap(); @@ -450,15 +450,15 @@ mod tests { fs::create_dir_all(&wf_dir).unwrap(); fs::write( wf_dir.join("workflow.toml"), - "version = 1\ngraph = \"workflow.dot\"\n", + "version = 1\ngraph = \"workflow.fabro\"\n", ) .unwrap(); fs::write( - wf_dir.join("workflow.dot"), + wf_dir.join("workflow.fabro"), "digraph G { start [shape=Mdiamond]; exit [shape=Msquare]; start -> exit }", ) .unwrap(); - let dot_path = wf_dir.join("workflow.dot"); + let dot_path = wf_dir.join("workflow.fabro"); (tmp, dot_path) } @@ -483,10 +483,10 @@ mod tests { } #[test] - fn resolve_workflow_dot_path() { + fn resolve_workflow_fabro_path() { let (tmp, expected_dot) = setup_workflow_project("hello"); let (dot_path, cfg) = resolve_workflow_from(&expected_dot, tmp.path()).unwrap(); assert_eq!(dot_path, expected_dot); - assert!(cfg.is_none(), "expected None for .dot path"); + assert!(cfg.is_none(), "expected None for .fabro path"); } } diff --git a/lib/crates/fabro-workflows/src/cli/run.rs b/lib/crates/fabro-workflows/src/cli/run.rs index 76005250e..aa64981cd 100644 --- a/lib/crates/fabro-workflows/src/cli/run.rs +++ b/lib/crates/fabro-workflows/src/cli/run.rs @@ -34,7 +34,7 @@ use indicatif::HumanDuration; use std::time::Duration; use super::{ - compute_stage_cost, format_cost, format_tokens_human, print_diagnostics, read_dot_file, + compute_stage_cost, format_cost, format_tokens_human, print_diagnostics, read_workflow_file, RunArgs, SandboxProvider, }; @@ -349,7 +349,7 @@ pub async fn run_command( .unwrap_or_default(); // 1. Parse and validate workflow - let source = read_dot_file(&dot_path)?; + let source = read_workflow_file(&dot_path)?; let vars = run_cfg .as_ref() .and_then(|c| c.vars.as_ref()) @@ -2524,7 +2524,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".to_string()), - graph: "test.dot".to_string(), + graph: "test.fabro".to_string(), directory: None, llm: Some(run_config::LlmConfig { model: Some("toml-model".to_string()), @@ -2568,7 +2568,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".to_string()), - graph: "test.dot".to_string(), + graph: "test.fabro".to_string(), directory: None, llm: Some(run_config::LlmConfig { model: Some("toml-model".to_string()), @@ -2647,7 +2647,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".to_string()), - graph: "test.dot".to_string(), + graph: "test.fabro".to_string(), directory: None, llm: Some(run_config::LlmConfig { model: Some("toml-model".to_string()), @@ -2673,7 +2673,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".to_string()), - graph: "w.dot".into(), + graph: "w.fabro".into(), directory: None, llm: None, setup: None, @@ -2704,7 +2704,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".to_string()), - graph: "w.dot".into(), + graph: "w.fabro".into(), directory: None, llm: None, setup: None, @@ -2782,7 +2782,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".into()), - graph: "w.dot".into(), + graph: "w.fabro".into(), directory: None, llm: None, setup: None, @@ -2842,7 +2842,7 @@ mod tests { let cfg = run_config::WorkflowRunConfig { version: 1, goal: Some("test".into()), - graph: "w.dot".into(), + graph: "w.fabro".into(), directory: None, llm: None, setup: None, diff --git a/lib/crates/fabro-workflows/src/cli/run_config.rs b/lib/crates/fabro-workflows/src/cli/run_config.rs index 05d2d7eac..7bd64316f 100644 --- a/lib/crates/fabro-workflows/src/cli/run_config.rs +++ b/lib/crates/fabro-workflows/src/cli/run_config.rs @@ -441,7 +441,7 @@ mod tests { let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [vars] repo_url = "https://github.com/org/repo" @@ -522,7 +522,7 @@ language = "python" let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" @@ -538,7 +538,7 @@ devcontainer = true let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" @@ -553,7 +553,7 @@ provider = "daytona" let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" @@ -569,7 +569,7 @@ provider = "daytona" let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" @@ -614,7 +614,7 @@ dockerfile = "FROM rust:1.85-slim-bookworm\nRUN apt-get update" let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "daytona" @@ -633,12 +633,12 @@ auto_stop_interval = 30 let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" "#; let config = parse_run_config(toml).unwrap(); assert_eq!(config.version, 1); assert_eq!(config.goal.as_deref(), Some("Run tests")); - assert_eq!(config.graph, "workflow.dot"); + assert_eq!(config.graph, "workflow.fabro"); assert!(config.directory.is_none()); assert!(config.llm.is_none()); assert!(config.setup.is_none()); @@ -648,7 +648,7 @@ graph = "workflow.dot" fn parse_toml_without_goal() { let toml = r#" version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" "#; let config = parse_run_config(toml).unwrap(); assert!(config.goal.is_none()); @@ -659,7 +659,7 @@ graph = "workflow.dot" let toml = r#" version = 1 goal = "Full workflow" -graph = "workflow.dot" +graph = "workflow.fabro" directory = "/tmp/repo" [llm] @@ -688,7 +688,7 @@ timeout_ms = 60000 let toml = r#" version = 2 goal = "x" -graph = "p.dot" +graph = "p.fabro" "#; let err = parse_run_config(toml).unwrap_err(); assert!( @@ -700,22 +700,22 @@ graph = "p.dot" #[test] fn graph_path_resolved_relative_to_toml() { let toml_path = Path::new("/tmp/sub/task.toml"); - let resolved = resolve_graph_path(toml_path, "p.dot"); - assert_eq!(resolved, PathBuf::from("/tmp/sub/p.dot")); + let resolved = resolve_graph_path(toml_path, "p.fabro"); + assert_eq!(resolved, PathBuf::from("/tmp/sub/p.fabro")); } #[test] fn graph_path_absolute_unchanged() { let toml_path = Path::new("/tmp/sub/task.toml"); - let resolved = resolve_graph_path(toml_path, "/other/workflow.dot"); - assert_eq!(resolved, PathBuf::from("/other/workflow.dot")); + let resolved = resolve_graph_path(toml_path, "/other/workflow.fabro"); + assert_eq!(resolved, PathBuf::from("/other/workflow.fabro")); } #[test] fn goal_is_optional() { let no_goal = r#" version = 1 -graph = "p.dot" +graph = "p.fabro" "#; let config = parse_run_config(no_goal).unwrap(); assert!(config.goal.is_none()); @@ -735,7 +735,7 @@ goal = "x" let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox.daytona.snapshot] name = "my-snapshot" @@ -767,7 +767,7 @@ dockerfile = { path = "./Dockerfile" } r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox.daytona.snapshot] name = "my-snapshot" @@ -795,7 +795,7 @@ dockerfile = { path = "Dockerfile" } r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox.daytona.snapshot] name = "my-snapshot" @@ -867,7 +867,7 @@ key = "value" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#, ) .unwrap(); @@ -890,7 +890,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [llm] model = "task-model" @@ -916,7 +916,7 @@ model = "task-model" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [vars] task_key = "task_val" @@ -945,7 +945,7 @@ shared = "from_task" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#, ) .unwrap(); @@ -964,7 +964,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [llm] model = "haiku" @@ -991,7 +991,7 @@ model = "haiku" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [setup] commands = ["make test"] @@ -1016,7 +1016,7 @@ commands = ["make test"] let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "docker" @@ -1032,7 +1032,7 @@ preserve = true let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [sandbox] provider = "docker" @@ -1047,7 +1047,7 @@ provider = "docker" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.local] worktree_mode = "always" @@ -1062,7 +1062,7 @@ worktree_mode = "always" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "local" @@ -1077,7 +1077,7 @@ provider = "local" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.local] "#; @@ -1092,7 +1092,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] preserve = true @@ -1123,7 +1123,7 @@ preserve = true r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "docker" @@ -1154,7 +1154,7 @@ provider = "docker" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "daytona" @@ -1191,7 +1191,7 @@ provider = "daytona" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "daytona" @@ -1231,7 +1231,7 @@ auto_stop_interval = 60 r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona.labels] project = "fabro" @@ -1272,7 +1272,7 @@ env = "from_task" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona.snapshot] name = "task-snap" @@ -1316,7 +1316,7 @@ cpu = 2 r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona] auto_stop_interval = 60 @@ -1358,7 +1358,7 @@ auto_stop_interval = 60 let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "claude-opus-4-6" @@ -1380,7 +1380,7 @@ gemini = ["anthropic", "openai"] let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [llm] model = "claude-opus-4-6" @@ -1397,7 +1397,7 @@ provider = "anthropic" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [llm] model = "opus" @@ -1426,7 +1426,7 @@ anthropic = ["gemini"] r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [llm] model = "opus" @@ -1489,7 +1489,7 @@ model = "opus" let toml = r#" version = 1 goal = "Test hooks" -graph = "test.dot" +graph = "test.fabro" [[hooks]] event = "stage_start" @@ -1518,7 +1518,7 @@ command = "echo done" let toml = r#" version = 1 goal = "No hooks" -graph = "test.dot" +graph = "test.fabro" "#; let cfg: WorkflowRunConfig = toml::from_str(toml).unwrap(); assert!(cfg.hooks.is_empty()); @@ -1529,7 +1529,7 @@ graph = "test.dot" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona] network = "block" @@ -1548,7 +1548,7 @@ network = "block" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona] network = "block" @@ -1585,7 +1585,7 @@ network = "block" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.daytona] auto_stop_interval = 60 @@ -1625,7 +1625,7 @@ auto_stop_interval = 60 let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [checkpoint] exclude_globs = ["**/node_modules/**", "**/.cache/**"] @@ -1642,7 +1642,7 @@ exclude_globs = ["**/node_modules/**", "**/.cache/**"] let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#; let config = parse_run_config(toml).unwrap(); assert!(config.checkpoint.exclude_globs.is_empty()); @@ -1654,7 +1654,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [checkpoint] exclude_globs = ["**/dist/**", "**/.cache/**"] @@ -1680,7 +1680,7 @@ exclude_globs = ["**/dist/**", "**/.cache/**"] r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#, ) .unwrap(); @@ -1700,7 +1700,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [checkpoint] exclude_globs = ["**/dist/**"] @@ -1730,7 +1730,7 @@ exclude_globs = ["**/node_modules/**"] let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.env] FOO = "bar" @@ -1748,7 +1748,7 @@ BAZ = "${env.HOME}" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "daytona" @@ -1800,7 +1800,7 @@ provider = "daytona" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.env] TASK_KEY = "task_val" @@ -1838,7 +1838,7 @@ SHARED = "from_task" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox] provider = "daytona" @@ -1874,7 +1874,7 @@ provider = "daytona" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.env] LITERAL = "hello" @@ -1899,7 +1899,7 @@ FROM_HOST = "${env.FABRO_TEST_LOAD_ENV}" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [sandbox.env] MISSING = "${env.FABRO_TEST_DEFINITELY_NOT_SET_67890}" @@ -1920,7 +1920,7 @@ MISSING = "${env.FABRO_TEST_DEFINITELY_NOT_SET_67890}" let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [pull_request] enabled = true @@ -1935,7 +1935,7 @@ enabled = true let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#; let config = parse_run_config(toml).unwrap(); assert!(config.pull_request.is_none()); @@ -1947,7 +1947,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [pull_request] enabled = true @@ -1971,7 +1971,7 @@ enabled = true r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#, ) .unwrap(); @@ -2001,7 +2001,7 @@ enabled = true let toml = r#" version = 1 goal = "Run tests" -graph = "workflow.dot" +graph = "workflow.fabro" [assets] include = ["test-results/**", "playwright-report/**", "*.trace.zip"] @@ -2018,7 +2018,7 @@ include = ["test-results/**", "playwright-report/**", "*.trace.zip"] fn parse_toml_without_assets() { let toml = r#" version = 1 -graph = "workflow.dot" +graph = "workflow.fabro" "#; let config = parse_run_config(toml).unwrap(); assert!(config.assets.is_none()); @@ -2030,7 +2030,7 @@ graph = "workflow.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" "#, ) .unwrap(); @@ -2051,7 +2051,7 @@ graph = "w.dot" r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [assets] include = ["playwright-report/**"] @@ -2074,7 +2074,7 @@ include = ["playwright-report/**"] let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [pull_request] enabled = true @@ -2091,7 +2091,7 @@ draft = true let toml = r#" version = 1 goal = "test" -graph = "w.dot" +graph = "w.fabro" [pull_request] enabled = true diff --git a/lib/crates/fabro-workflows/src/cli/validate.rs b/lib/crates/fabro-workflows/src/cli/validate.rs index 1fac435fc..7490ae344 100644 --- a/lib/crates/fabro-workflows/src/cli/validate.rs +++ b/lib/crates/fabro-workflows/src/cli/validate.rs @@ -46,7 +46,10 @@ mod tests { #[test] fn validate_valid_workflow() { - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!( tmp, r#"digraph Simple {{ @@ -74,7 +77,10 @@ mod tests { #[test] fn validate_invalid_syntax() { - let mut tmp = tempfile::Builder::new().suffix(".dot").tempfile().unwrap(); + let mut tmp = tempfile::Builder::new() + .suffix(".fabro") + .tempfile() + .unwrap(); write!(tmp, "not a valid dot file").unwrap(); let args = ValidateArgs { @@ -101,8 +107,8 @@ mod tests { std::fs::create_dir_all(&prompts_dir).unwrap(); std::fs::write(prompts_dir.join("plan.md"), "Plan the work carefully.").unwrap(); - // Write a .dot file that uses @prompts/plan.md - let dot_path = dir.path().join("workflow.dot"); + // Write a .fabro file that uses @prompts/plan.md + let dot_path = dir.path().join("workflow.fabro"); std::fs::write( &dot_path, r#"digraph FileRef { @@ -128,11 +134,11 @@ mod tests { std::fs::create_dir_all(&wf_dir).unwrap(); std::fs::write( wf_dir.join("workflow.toml"), - "version = 1\ngraph = \"workflow.dot\"\n", + "version = 1\ngraph = \"workflow.fabro\"\n", ) .unwrap(); std::fs::write( - wf_dir.join("workflow.dot"), + wf_dir.join("workflow.fabro"), r#"digraph Hello { graph [goal="Test"] start [shape=Mdiamond] @@ -154,7 +160,7 @@ mod tests { #[test] fn validate_missing_file() { let args = ValidateArgs { - workflow: PathBuf::from("/tmp/nonexistent_workflow_12345.dot"), + workflow: PathBuf::from("/tmp/nonexistent_workflow_12345.fabro"), }; let styles = Styles::new(false); let result = validate_command(&args, &styles); diff --git a/lib/crates/fabro-workflows/src/handler/manager_loop.rs b/lib/crates/fabro-workflows/src/handler/manager_loop.rs index 8038f93f0..3c3b41155 100644 --- a/lib/crates/fabro-workflows/src/handler/manager_loop.rs +++ b/lib/crates/fabro-workflows/src/handler/manager_loop.rs @@ -334,7 +334,7 @@ mod tests { assert!(outcome .failure_reason() .unwrap() - .contains("No child DOT source")); + .contains("No child workflow source")); } #[tokio::test] diff --git a/lib/crates/fabro-workflows/src/pull_request.rs b/lib/crates/fabro-workflows/src/pull_request.rs index d08c164b1..62fe4e57f 100644 --- a/lib/crates/fabro-workflows/src/pull_request.rs +++ b/lib/crates/fabro-workflows/src/pull_request.rs @@ -602,7 +602,7 @@ mod tests { let dot = "digraph implement {\n plan [type=\"agent\"]\n code [type=\"agent\"]\n plan -> code\n}\n"; let section = format_arc_details_section(&conclusion, Some(dot)); - assert!(section.contains("implement.dot")); + assert!(section.contains("implement.fabro")); assert!(section.contains("2 nodes and 1 edge")); assert!(section.contains("```dot")); assert!(section.contains("digraph implement")); @@ -737,7 +737,7 @@ mod tests { plan -> code }"#; let (name, nodes, edges) = parse_dot_summary(dot); - assert_eq!(name, "my_workflow.dot"); + assert_eq!(name, "my_workflow.fabro"); assert_eq!(nodes, 2); assert_eq!(edges, 1); } @@ -745,7 +745,7 @@ mod tests { #[test] fn parse_dot_summary_empty() { let (name, nodes, edges) = parse_dot_summary(""); - assert_eq!(name, "workflow.dot"); + assert_eq!(name, "workflow.fabro"); assert_eq!(nodes, 0); assert_eq!(edges, 0); } diff --git a/lib/crates/fabro-workflows/src/validation/rules.rs b/lib/crates/fabro-workflows/src/validation/rules.rs index e041e830b..dbdc76539 100644 --- a/lib/crates/fabro-workflows/src/validation/rules.rs +++ b/lib/crates/fabro-workflows/src/validation/rules.rs @@ -997,7 +997,7 @@ impl LintRule for UnresolvedFileRefRule { ), node_id: Some(node.id.clone()), edge: None, - fix: Some("Check that the path is relative to the .dot file's directory and the file exists".to_string()), + fix: Some("Check that the path is relative to the workflow file's directory and the file exists".to_string()), }); } } @@ -1011,7 +1011,7 @@ impl LintRule for UnresolvedFileRefRule { message: format!("Graph goal has unresolved file reference: {goal}"), node_id: None, edge: None, - fix: Some("Check that the path is relative to the .dot file's directory and the file exists".to_string()), + fix: Some("Check that the path is relative to the workflow file's directory and the file exists".to_string()), }); } } diff --git a/test/branching.dot b/test/branching.fabro similarity index 100% rename from test/branching.dot rename to test/branching.fabro diff --git a/test/conditions.dot b/test/conditions.fabro similarity index 100% rename from test/conditions.dot rename to test/conditions.fabro diff --git a/test/docs/agents/outputs/output-patterns.dot b/test/docs/agents/outputs/output-patterns.fabro similarity index 100% rename from test/docs/agents/outputs/output-patterns.dot rename to test/docs/agents/outputs/output-patterns.fabro diff --git a/test/docs/agents/prompts/pipeline.dot b/test/docs/agents/prompts/pipeline.fabro similarity index 100% rename from test/docs/agents/prompts/pipeline.dot rename to test/docs/agents/prompts/pipeline.fabro diff --git a/test/docs/changelog/2026-03-05/new-features.dot b/test/docs/changelog/2026-03-05/new-features.fabro similarity index 100% rename from test/docs/changelog/2026-03-05/new-features.dot rename to test/docs/changelog/2026-03-05/new-features.fabro diff --git a/test/docs/core-concepts/models/example.dot b/test/docs/core-concepts/models/example.fabro similarity index 100% rename from test/docs/core-concepts/models/example.dot rename to test/docs/core-concepts/models/example.fabro diff --git a/test/docs/core-concepts/workflows/my-workflow.dot b/test/docs/core-concepts/workflows/my-workflow.fabro similarity index 100% rename from test/docs/core-concepts/workflows/my-workflow.dot rename to test/docs/core-concepts/workflows/my-workflow.fabro diff --git a/test/docs/examples/clone-substack/clone-substack.dot b/test/docs/examples/clone-substack/clone-substack.fabro similarity index 100% rename from test/docs/examples/clone-substack/clone-substack.dot rename to test/docs/examples/clone-substack/clone-substack.fabro diff --git a/test/docs/examples/definition-of-done/spec-dod-multimodel.dot b/test/docs/examples/definition-of-done/spec-dod-multimodel.fabro similarity index 100% rename from test/docs/examples/definition-of-done/spec-dod-multimodel.dot rename to test/docs/examples/definition-of-done/spec-dod-multimodel.fabro diff --git a/test/docs/examples/definition-of-done/spec-dod.dot b/test/docs/examples/definition-of-done/spec-dod.fabro similarity index 100% rename from test/docs/examples/definition-of-done/spec-dod.dot rename to test/docs/examples/definition-of-done/spec-dod.fabro diff --git a/test/docs/examples/nlspec-conformance/n-l-spec-conformance.dot b/test/docs/examples/nlspec-conformance/n-l-spec-conformance.fabro similarity index 100% rename from test/docs/examples/nlspec-conformance/n-l-spec-conformance.dot rename to test/docs/examples/nlspec-conformance/n-l-spec-conformance.fabro diff --git a/test/docs/examples/semantic-port/semantic-port.dot b/test/docs/examples/semantic-port/semantic-port.fabro similarity index 100% rename from test/docs/examples/semantic-port/semantic-port.dot rename to test/docs/examples/semantic-port/semantic-port.fabro diff --git a/test/docs/execution/context/example.dot b/test/docs/execution/context/example.fabro similarity index 100% rename from test/docs/execution/context/example.dot rename to test/docs/execution/context/example.fabro diff --git a/test/docs/execution/failures/example-02.dot b/test/docs/execution/failures/example-02.fabro similarity index 100% rename from test/docs/execution/failures/example-02.dot rename to test/docs/execution/failures/example-02.fabro diff --git a/test/docs/execution/failures/example-03.dot b/test/docs/execution/failures/example-03.fabro similarity index 100% rename from test/docs/execution/failures/example-03.dot rename to test/docs/execution/failures/example-03.fabro diff --git a/test/docs/execution/failures/example-04.dot b/test/docs/execution/failures/example-04.fabro similarity index 100% rename from test/docs/execution/failures/example-04.dot rename to test/docs/execution/failures/example-04.fabro diff --git a/test/docs/execution/failures/example.dot b/test/docs/execution/failures/example.fabro similarity index 100% rename from test/docs/execution/failures/example.dot rename to test/docs/execution/failures/example.fabro diff --git a/test/docs/execution/interviews/default-choice.dot b/test/docs/execution/interviews/default-choice.fabro similarity index 100% rename from test/docs/execution/interviews/default-choice.dot rename to test/docs/execution/interviews/default-choice.fabro diff --git a/test/docs/execution/run-configuration/c-i.dot b/test/docs/execution/run-configuration/c-i.fabro similarity index 100% rename from test/docs/execution/run-configuration/c-i.dot rename to test/docs/execution/run-configuration/c-i.fabro diff --git a/test/docs/execution/run-configuration/run-c-i.toml b/test/docs/execution/run-configuration/run-c-i.toml index 8aac9e239..ffe6b3458 100644 --- a/test/docs/execution/run-configuration/run-c-i.toml +++ b/test/docs/execution/run-configuration/run-c-i.toml @@ -1,6 +1,6 @@ version = 1 goal = "Run tests for $repo_name" -graph = "c-i.dot" +graph = "c-i.fabro" [vars] language = "test-language" diff --git a/test/docs/getting-started/why-fabro/plan-implement.dot b/test/docs/getting-started/why-fabro/plan-implement.fabro similarity index 100% rename from test/docs/getting-started/why-fabro/plan-implement.dot rename to test/docs/getting-started/why-fabro/plan-implement.fabro diff --git a/test/docs/human-tools/preview/build-and-preview.dot b/test/docs/human-tools/preview/build-and-preview.fabro similarity index 100% rename from test/docs/human-tools/preview/build-and-preview.dot rename to test/docs/human-tools/preview/build-and-preview.fabro diff --git a/test/docs/integrations/brave-search/research.dot b/test/docs/integrations/brave-search/research.fabro similarity index 100% rename from test/docs/integrations/brave-search/research.dot rename to test/docs/integrations/brave-search/research.fabro diff --git a/test/docs/integrations/daytona/example.dot b/test/docs/integrations/daytona/example.fabro similarity index 100% rename from test/docs/integrations/daytona/example.dot rename to test/docs/integrations/daytona/example.fabro diff --git a/test/docs/reference/dot-language/implement-feature.dot b/test/docs/reference/dot-language/implement-feature.fabro similarity index 100% rename from test/docs/reference/dot-language/implement-feature.dot rename to test/docs/reference/dot-language/implement-feature.fabro diff --git a/test/docs/reference/dot-language/my-workflow.dot b/test/docs/reference/dot-language/my-workflow.fabro similarity index 100% rename from test/docs/reference/dot-language/my-workflow.dot rename to test/docs/reference/dot-language/my-workflow.fabro diff --git a/test/docs/run_tests.sh b/test/docs/run_tests.sh index 93e2de846..406b3f98d 100755 --- a/test/docs/run_tests.sh +++ b/test/docs/run_tests.sh @@ -35,7 +35,7 @@ run_one() { # Check for companion run.toml (run-.toml in same dir) local stem - stem="$(basename "${dot%.dot}")" + stem="$(basename "${dot%.fabro}")" local toml toml="${dot_dir}/run-${stem}.toml" @@ -101,7 +101,7 @@ echo "" dots=() while IFS= read -r dot; do dots+=("$dot") -done < <(find "$SCRIPT_DIR" -name '*.dot' | sort) +done < <(find "$SCRIPT_DIR" -name '*.fabro' | sort) # Run with parallelism active=0 diff --git a/test/docs/tutorials/branch-loop/branch-loop.dot b/test/docs/tutorials/branch-loop/branch-loop.fabro similarity index 100% rename from test/docs/tutorials/branch-loop/branch-loop.dot rename to test/docs/tutorials/branch-loop/branch-loop.fabro diff --git a/test/docs/tutorials/branch-loop/fixed-loop.dot b/test/docs/tutorials/branch-loop/fixed-loop.fabro similarity index 100% rename from test/docs/tutorials/branch-loop/fixed-loop.dot rename to test/docs/tutorials/branch-loop/fixed-loop.fabro diff --git a/test/docs/tutorials/ensemble/ensemble.dot b/test/docs/tutorials/ensemble/ensemble.fabro similarity index 100% rename from test/docs/tutorials/ensemble/ensemble.dot rename to test/docs/tutorials/ensemble/ensemble.fabro diff --git a/test/docs/tutorials/hello-world/hello.dot b/test/docs/tutorials/hello-world/hello.fabro similarity index 100% rename from test/docs/tutorials/hello-world/hello.dot rename to test/docs/tutorials/hello-world/hello.fabro diff --git a/test/docs/tutorials/hello-world/sub-agent.dot b/test/docs/tutorials/hello-world/sub-agent.fabro similarity index 100% rename from test/docs/tutorials/hello-world/sub-agent.dot rename to test/docs/tutorials/hello-world/sub-agent.fabro diff --git a/test/docs/tutorials/hello-world/tool-use.dot b/test/docs/tutorials/hello-world/tool-use.fabro similarity index 100% rename from test/docs/tutorials/hello-world/tool-use.dot rename to test/docs/tutorials/hello-world/tool-use.fabro diff --git a/test/docs/tutorials/multi-model/multi-model.dot b/test/docs/tutorials/multi-model/multi-model.fabro similarity index 100% rename from test/docs/tutorials/multi-model/multi-model.dot rename to test/docs/tutorials/multi-model/multi-model.fabro diff --git a/test/docs/tutorials/parallel-review/parallel.dot b/test/docs/tutorials/parallel-review/parallel.fabro similarity index 100% rename from test/docs/tutorials/parallel-review/parallel.dot rename to test/docs/tutorials/parallel-review/parallel.fabro diff --git a/test/docs/tutorials/plan-implement/plan-implement.dot b/test/docs/tutorials/plan-implement/plan-implement.fabro similarity index 100% rename from test/docs/tutorials/plan-implement/plan-implement.dot rename to test/docs/tutorials/plan-implement/plan-implement.fabro diff --git a/test/docs/tutorials/sub-workflow/implement-and-test.dot b/test/docs/tutorials/sub-workflow/implement-and-test.fabro similarity index 100% rename from test/docs/tutorials/sub-workflow/implement-and-test.dot rename to test/docs/tutorials/sub-workflow/implement-and-test.fabro diff --git a/test/docs/tutorials/sub-workflow/sub-workflow.dot b/test/docs/tutorials/sub-workflow/sub-workflow.fabro similarity index 84% rename from test/docs/tutorials/sub-workflow/sub-workflow.dot rename to test/docs/tutorials/sub-workflow/sub-workflow.fabro index 1ae7b24fb..46d92422b 100644 --- a/test/docs/tutorials/sub-workflow/sub-workflow.dot +++ b/test/docs/tutorials/sub-workflow/sub-workflow.fabro @@ -6,7 +6,7 @@ digraph SubWorkflow { exit [shape=Msquare, label="Exit"] plan [label="Plan", prompt="Analyze the goal. List the functions needed, their signatures, and edge cases. Write the plan to plan.md."] - impl [label="Implement & Test", shape=house, stack.child_dotfile="implement-and-test.dot", manager.max_cycles=50] + impl [label="Implement & Test", shape=house, stack.child_workflow="implement-and-test.fabro", manager.max_cycles=50] review [label="Review", prompt="Read every file the child workflow created. Run the tests yourself with 'python3 -m pytest -v'. Verify the implementation matches plan.md and all tests pass. Write a short verdict to review.md."] start -> plan -> impl -> review -> exit diff --git a/test/docs/workflows/human-in-the-loop/hitl-patterns.dot b/test/docs/workflows/human-in-the-loop/hitl-patterns.fabro similarity index 100% rename from test/docs/workflows/human-in-the-loop/hitl-patterns.dot rename to test/docs/workflows/human-in-the-loop/hitl-patterns.fabro diff --git a/test/docs/workflows/stages-and-nodes/all-node-types.dot b/test/docs/workflows/stages-and-nodes/all-node-types.fabro similarity index 100% rename from test/docs/workflows/stages-and-nodes/all-node-types.dot rename to test/docs/workflows/stages-and-nodes/all-node-types.fabro diff --git a/test/docs/workflows/stylesheets/example.dot b/test/docs/workflows/stylesheets/example.fabro similarity index 100% rename from test/docs/workflows/stylesheets/example.dot rename to test/docs/workflows/stylesheets/example.fabro diff --git a/test/docs/workflows/transitions/transition-patterns.dot b/test/docs/workflows/transitions/transition-patterns.fabro similarity index 100% rename from test/docs/workflows/transitions/transition-patterns.dot rename to test/docs/workflows/transitions/transition-patterns.fabro diff --git a/test/docs/workflows/variables/check.dot b/test/docs/workflows/variables/check.fabro similarity index 100% rename from test/docs/workflows/variables/check.dot rename to test/docs/workflows/variables/check.fabro diff --git a/test/docs/workflows/variables/example.dot b/test/docs/workflows/variables/example.fabro similarity index 100% rename from test/docs/workflows/variables/example.dot rename to test/docs/workflows/variables/example.fabro diff --git a/test/docs/workflows/variables/run-check.toml b/test/docs/workflows/variables/run-check.toml index f400c4450..c2fc7c72c 100644 --- a/test/docs/workflows/variables/run-check.toml +++ b/test/docs/workflows/variables/run-check.toml @@ -1,6 +1,6 @@ version = 1 goal = "Run tests for $repo_name" -graph = "check.dot" +graph = "check.fabro" [vars] language = "test-language" diff --git a/test/invalid.dot b/test/invalid.fabro similarity index 100% rename from test/invalid.dot rename to test/invalid.fabro diff --git a/test/legacy_tool.dot b/test/legacy_tool.fabro similarity index 100% rename from test/legacy_tool.dot rename to test/legacy_tool.fabro diff --git a/test/parallel.dot b/test/parallel.fabro similarity index 100% rename from test/parallel.dot rename to test/parallel.fabro diff --git a/test/retro-e2e.dot b/test/retro-e2e.fabro similarity index 100% rename from test/retro-e2e.dot rename to test/retro-e2e.fabro diff --git a/test/simple.dot b/test/simple.fabro similarity index 100% rename from test/simple.dot rename to test/simple.fabro diff --git a/test/styled.dot b/test/styled.fabro similarity index 100% rename from test/styled.dot rename to test/styled.fabro