Commit graph

1670 commits

Author SHA1 Message Date
Bryan Helmkamp
b6cc56c17b Add resolve_run() that accepts run ID prefix or workflow name
Subcommands like cp, diff, preview, ssh, and pr previously only
accepted run ID prefixes. The new resolve_run() tries run ID prefix
first, then falls back to workflow name (most recent run), making
these commands more ergonomic.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 15:42:03 -04:00
Bryan Helmkamp
8188b47f1f Fix detect_binary test to work on Ubuntu (dash) sandboxes
`sh --version` exits non-zero on dash (Ubuntu default), so the test
only passed on macOS where sh is bash. Use `git` instead which
reliably supports --version on all platforms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 15:31:27 -04:00
Bryan Helmkamp
738d42a7b0 Fix empty run_id on sandbox events in progress.jsonl
The JSONL listener's run_id was initialized to "" and only populated
when WorkflowRunStarted fired, but sandbox events emit before that.
Seed it with the already-generated ULID so all events carry the run_id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 15:00:40 -04:00
Bryan Helmkamp
5fe1925944 Add fabro workflow create <name> subcommand to scaffold new workflows
Writes a starter workflow.fabro (DOT graph) and workflow.toml into the
project's workflows directory. Supports --goal flag and derives the
digraph name from the workflow name using PascalCase conversion. Also
defaults the `graph` field in workflow.toml to "workflow.fabro" so it
can be omitted from generated configs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:32:00 -04:00
Bryan Helmkamp
79ef0672d9 Extract RunDefaults::merge_overlay to replace inline field-by-field merge
The inline merge in run_command() duplicated the structure of
apply_defaults() with shallower (inconsistent) semantics. This extracts
a proper merge_overlay method that deep-merges compound fields (vars,
hooks, mcp_servers, sandbox sub-fields) consistently with apply_defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:23:23 -04:00
Bryan Helmkamp
c0b4a2dc83 Extend fabro.toml with project-level run defaults
Add project-level run defaults to fabro.toml so sandbox, LLM, hooks,
MCP servers, and other settings can be shared across workflows instead
of duplicated in each workflow.toml. Precedence: workflow.toml >
fabro.toml > cli.toml/server.toml.

- Rename `directory` → `work_dir` with backwards-compat serde alias
- Add `hooks` and `mcp_servers` to `RunDefaults` with merge logic
- Extend `ProjectConfig` with all run-defaults fields + `into_run_defaults()`
- Remove duplicate `McpServerEntry` from fabro-config (use run_config's)
- Move `hook_config` from ServerConfig into `run_defaults.hooks`
- Wire project config merge and hooks/mcp fallbacks in run_command()
- Update OpenAPI spec and regenerate TypeScript client

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:11:16 -04:00
Bryan Helmkamp
81a60028c6 Add ~/.fabro/ fallback for @ file references
When an @file reference can't be resolved against the workflow's
directory, fall back to ~/.fabro/ so users can share prompt files
across workflows without duplication. The workflow directory keeps
higher precedence so project-specific overrides still win.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 13:44:16 -04:00
Bryan Helmkamp
bba11a9eb9 Rename arc/ to fabro/ in git branch prefixes and workflow paths
Complete the rebrand by replacing hardcoded "arc/run/" branch prefixes
with a RUN_BRANCH_PREFIX constant ("fabro/run/") and updating
fabro init to create workflows under fabro/workflows/ instead of
arc/workflows/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:20:07 -04:00
Bryan Helmkamp
dd439ba185 Use daytona-medium snapshot as default Daytona sandbox
The bare ubuntu:22.04 image lacks git and other tooling, causing git
checkpoints to fail. Switch to the daytona-medium snapshot which has
standard dev tools pre-installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:10:50 -04:00
Bryan Helmkamp
6596e14e04 Backfill missing git_commit_sha from run branch commit messages
The engine writes git_commit_sha to on-disk checkpoint.json but not to the
metadata branch. When the metadata checkpoint lacks this field, walk the
run branch and match commits by message pattern to fill in the SHAs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 11:52:33 -04:00
Bryan Helmkamp
7ae2163163 Add fabro rewind command to rewind workflow runs to earlier checkpoints
Enables rewinding both the metadata branch and run branch refs to a
target checkpoint, allowing resume from an earlier point with
`fabro run --run-branch`. Supports targeting by node name, node@visit,
or @ordinal, with parallel interior snap-back and optional remote push.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 11:38:17 -04:00
Bryan Helmkamp
bfda77c4a3 Improve workflow list output with grouped sections, descriptions, and tests
Show workflows grouped by User/Project with directory paths in headings,
aligned NAME/DESCRIPTION columns, truncated goal snippets, and (none)
for empty sections. Add tests for list_workflows_detailed, read_workflow_goal,
and truncate_str.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 11:19:08 -04:00
Bryan Helmkamp
c2ec23b147 Add fabro workflow list command
Adds a new `workflow` subcommand group with a `list` command that
discovers available workflows via `fabro.toml` and prints their names.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 09:58:03 -04:00
Bryan Helmkamp
8ef1fbd6f8 Add user-level workflow lookup in ~/.fabro/workflows/
`fabro run NAME` now checks ~/.fabro/workflows/ as a fallback when the
workflow isn't found in the project directory, letting users have
personal workflows available across all projects. Project workflows
take precedence over user workflows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 23:16:18 -04:00
Bryan Helmkamp
fdcebd850b Fix remaining .dot test references in integration.rs
Update two test TOML graph references from test.dot to test.fabro.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 22:39:58 -04:00
Bryan Helmkamp
21aff5431c Update docs, frontend, marketing, and skills for .fabro extension
Update 47 MDX doc pages, OpenAPI spec, SVG diagram, language
grammar, frontend demo data, marketing page, skills, and README
to use .fabro extension. Add "fabro" to fileTypes in language
grammars. Document stack.child_workflow alongside stack.child_dotfile.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 22:38:25 -04:00
Bryan Helmkamp
85db69fdc1 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) <noreply@anthropic.com>
2026-03-13 22:27:19 -04:00
Bryan Helmkamp
f12f261ddd Add graph.fabro as primary filename with graph.dot fallback
Write graph.fabro in run dirs and metadata branches. Read with
graph.dot fallback for backward compatibility with existing runs.
Add stack.child_workflow attribute with stack.child_dotfile fallback.
No files renamed yet — fallback paths handle everything.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 22:16:10 -04:00
Bryan Helmkamp
e5d1790551 Add thread_id_requires_fidelity_full lint rule
Warn when thread_id is set without fidelity=full, since session reuse
only works with full fidelity. Checks node-level, edge-level, and
graph-level default_thread attributes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 20:58:08 -04:00
Bryan Helmkamp
6bbc6eb1cd Rename Arc to Fabro in user-facing strings, comments, and tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 20:43:21 -04:00
Bryan Helmkamp
858bdc3788 Split trycmd into per-subcommand tests and remove live-probe doctor fixtures
Split the single cli_tests trycmd function into 14 per-subcommand test
functions so nextest can parallelize them. Delete header.toml and
verbose.toml doctor fixtures that ran live network probes — the existing
dry-run-flag.toml and help.trycmd already cover the same output assertion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 18:03:23 -04:00
Bryan Helmkamp
cb21dc8096 Fix slow unit tests (>5s) by removing unnecessary production delays
- doctor_no_color test: add --dry-run flag to skip live network probes (11s -> <1s)
- retry tests: set retry_policy=linear for 500ms delay instead of 5s default backoff
- cli_backend tests: make poll_interval configurable on AgentCliBackend, use 10ms in tests
- doctor TOML fixtures: remove status.code=1 now that dry-run doctor exits 0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 17:59:43 -04:00
Bryan Helmkamp
1b3d3d900b Move git SHA/build date from fabro-util to fabro-cli build.rs
fabro-util is a low-level crate depended on by almost everything, so its
build.rs reruns cascaded through the whole workspace. fabro-cli is the
leaf binary — nothing depends on it, so rebuilds are limited to just
that one crate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 15:03:12 -04:00
Bryan Helmkamp
cdbfc72719 Fix fabro-util build.rs rerun-if-changed path to prevent constant recompilation
The relative path to .git/HEAD was wrong (../../ instead of ../../../),
pointing to a nonexistent file. Cargo reruns build scripts when a
rerun-if-changed target doesn't exist, causing a full workspace rebuild
on every invocation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-13 14:53:11 -04:00
Bryan Helmkamp
4920f6e959 Fix assemble_narrative_only test to expect branding footer
The assemble_pr_body function unconditionally appends the "Generated
with Fabro" footer, but this test was asserting the bare narrative.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:05:59 -04:00
Bryan Helmkamp
3f04e978c8 use Freeform question type for human gates with no fixed choices
When a human gate has only a freeform edge and no fixed choices, use
QuestionType::Freeform instead of MultipleChoice. This sends the user
directly to a text input prompt, skipping the unnecessary select menu.
Also removes the Quit choice from the REPL workflow so it uses the new
freeform-only path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:25:37 -04:00
Bryan Helmkamp
c5bee7bf43 show prior node output before human gate prompts
Thread the previous stage's response through `Question.context_display`
so `ConsoleInterviewer` renders it before the interactive prompt. This
lets users see the agent's response before deciding what to do next in
looping workflows like REPL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:57:35 -04:00
Bryan Helmkamp
1ddcb92ab7 add Fabro branding to generated commits and PRs
Update default git author to Fabro <noreply@fabro.sh>. Append
"Generated with Fabro" footer to all checkpoint and metadata commits,
and to PR bodies. When the commit author is overridden, add a
Co-Authored-By trailer for attribution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:28:06 -04:00
Bryan Helmkamp
463ff8acd2 rename project_docs module to memory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:02:11 -04:00
Bryan Helmkamp
e968ece42c rename git trailers from Arc-* to Fabro-* to match product rename
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:56:59 -04:00
Bryan Helmkamp
d37fb9a9b4 simplify model stylesheet: rename llm_model/llm_provider, add provider inference
Rename `llm_model` → `model` and `llm_provider` → `provider` in stylesheet
properties, accessor methods, and all DOT/doc references. Add
ProviderInferenceTransform that automatically infers provider from the model
catalog, eliminating redundant provider declarations in stylesheets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:27:18 -04:00
Bryan Helmkamp
48eb867ce2 fix clippy large_enum_variant and rename ARC_ env vars in .env.example
Box the Usage field in Turn::Assistant to satisfy clippy::large_enum_variant.
Rename ARC_ prefixed env vars to FABRO_ in .env.example.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 14:37:22 -04:00
Bryan Helmkamp
28884ae093 rename Arc to Fabro in all Rust crates, symbols, env vars, and supporting files
- Rename 20 crate directories lib/crates/arc-* → fabro-*
- Update all Cargo.toml: crate names, dep paths, feature flags, bin name
- Rename arc_server module → fabro_server in fabro-llm
- ArcError → FabroError across 30+ files
- ARC_VERSION/ARC_GIT_SHA/ARC_BUILD_DATE → FABRO_* constants
- All use/qualified paths: arc_agent:: → fabro_agent::, etc. (~1500 occurrences)
- Env vars ARC_* → FABRO_* in string literals and shell scripts
- String literals: X-Arc-Demo, arc-bot, arc@local, arc-web, arc-mcp, etc.
- Path strings: .arc/ → .fabro/, arc.toml → fabro.toml, refs/arc/ → refs/fabro/
- arc-api.yaml → fabro-api.yaml (OpenAPI spec)
- skills/arc-create-workflow → fabro-create-workflow
- trycmd fixtures: $ arc → $ fabro
- Inline snapshots (insta) updated
- CI, Docker, install.sh, scripts, CLAUDE.md, AGENTS.md
- TypeScript app: env vars, headers, JWT issuer
- Docs: page slugs, git refs, config paths, sandbox names, repo URLs
- Repo references: brynary/arc → fabro-sh/fabro

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:25:58 -04:00
Bryan Helmkamp
3ce976a006 docs: update license references from AGPL to MIT
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:14:37 -04:00
Bryan Helmkamp
d657025de0 feat(arc-ssh): add preview_url_base to SshConfig for port preview URLs
Allows users to specify a reachable base URL for SSH hosts so that
get_preview_url(port) returns the correct external URL instead of
falling back to localhost.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 08:10:32 -04:00
Bryan Helmkamp
c3f2ccd68a Update docs screenshots and fix demo workflow serialization
Replace docs/images screenshots (runs-board, run-detail, workflow-example)
with fresh captures from the current FABRO-branded UI in demo mode.

Also fix a panic in arc-api demo::run_config_to_api where None-valued
HashMap fields (e.g. sandbox.env) serialized to JSON null, which failed
to deserialize into non-optional HashMap fields in RunConfiguration.
Added strip_nulls helper to clean the intermediate JSON value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 00:38:19 -04:00
Bryan Helmkamp
e7b8b3c938 refactor(arc-github): store client on GitHubTracker, drop redundant graphql_url field
- Add `client: reqwest::Client` field (matches LinearTracker pattern); eliminates 7 per-call client constructions that prevented connection pool reuse
- Remove `graphql_url: String` field — always derivable from base_url, computed via `graphql_url()` method at each call site
- Extract `make_test_issue()` test helper to replace 3 copy-pasted Issue struct literals

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:58:37 -04:00
Bryan Helmkamp
111b730eef feat(tracker): add Tracker trait with Linear and GitHub Projects V2 impls
- New arc-tracker crate defines the Tracker trait and shared Issue/BlockerRef types
- arc-linear: replace Issue/BlockerRef with arc-tracker re-exports, add LinearTracker struct implementing Tracker, remove free functions
- arc-github: add GitHubTracker implementing Tracker via Projects V2 GraphQL API, with lazy project node ID resolution (org → user fallback) and create_installation_access_token_for_projects helper
- 47 tests in arc-github (15 new), 24 tests in arc-linear (updated to use LinearTracker)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 23:32:03 -04:00
Bryan Helmkamp
10f7316f28 Simplify arc-linear: extract helper, fix O(n^2) ordering, add tracing
- Make execute_graphql private (callers use domain functions)
- Extract extract_issues() helper to deduplicate node-parsing blocks
- Replace O(n^2) .find() loop with HashMap for ID-ordered results
- Add tracing::debug on all public functions, warn on HTTP errors
- Extract BLOCKS_RELATION_TYPE constant for magic string

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:39:11 -04:00
Bryan Helmkamp
b509277e15 Add arc-linear crate for Linear issue tracker API integration
GraphQL client with 6 public functions: execute_graphql, fetch_viewer_id,
create_comment, update_issue_state, fetch_candidate_issues, and
fetch_issues_by_ids. Includes Issue/BlockerRef domain types with manual
normalization from GraphQL JSON responses.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:36:33 -04:00
Bryan Helmkamp
199691a949 Remove duplicate origin_url inherent method from SshSandbox
The inherent method shadowed the identical Sandbox trait method,
creating a risk of subtle divergence if one were changed without
the other.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:33:15 -04:00
Bryan Helmkamp
e0b3c4cde4 Add SSH sandbox provider (arc-ssh) for user-provided hosts
Adds a generic SSH sandbox that connects to any user-provided host via
openssh, without VM lifecycle management. Supports git clone with GitHub
App credentials, configurable working directory, and arc cp reconnection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:29:51 -04:00
Bryan Helmkamp
2ce89e5e5e Simplify compaction code: extract helper method, named constant, avoid cloning
Extract duplicated compaction check+trigger blocks in the session loop into
Session::compact_if_needed(). Replace the hardcoded 20_000 token budget with
COMPACTION_USER_MESSAGE_TOKEN_BUDGET constant. Change extract_recent_user_messages
to take ownership of discarded turns instead of borrowing and cloning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:13:29 -04:00
Bryan Helmkamp
f459aa78d7 Improve compaction quality with handoff framing, pre-turn check, and user message preservation
Reframe the summarization prompt as creating a handoff for a different assistant
(rather than self-summarization) to produce more thorough, explicit summaries.
Add a pre-turn compaction check so context is trimmed before building the LLM
request, not just after. Extract recent user messages from discarded turns during
compaction so the model retains the user's actual words alongside tool call/result
pairs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 22:09:23 -04:00
Bryan Helmkamp
e38d3ea3ce Add tracing to DaytonaSandbox::exec_command to diagnose stall watchdog timeouts
A workflow run hung for 33 minutes in a Daytona shell command despite
a 5-minute client-side timeout in tokio::select!. The root cause is
unknown — tests confirm the select pattern works correctly. Adding
info-level tracing at method entry (with command and timeout_ms),
after process service acquisition, and in each select arm so the
next occurrence reveals exactly where execution stalls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 17:04:17 -04:00
Bryan Helmkamp
87435aef11 Preserve ts, run_id, event field order in progress.jsonl
Enable serde_json's preserve_order feature so Map uses insertion-order
IndexMap instead of sorted BTreeMap. Extract build_event_envelope()
from the on_event closure to deduplicate the envelope construction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 13:01:17 -04:00
Bryan Helmkamp
55917f4005 Add arc graph subcommand to render workflow DOT graphs as SVG/PNG
Mirrors `arc validate` workflow resolution. Shells out to `dot` (graphviz)
with friendly error if not installed. Supports --format svg|png and -o output path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 10:34:23 -04:00
Bryan Helmkamp
7dfbd53797 Print resolved graph path in arc run and arc validate
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 10:03:34 -04:00
Bryan Helmkamp
53b27ab188 Group arc doctor checks into Required / Optional / Server sections
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 09:59:54 -04:00
Bryan Helmkamp
ee58694cf0 Add tool call progress display to retro step
Wire ProgressUI and EventEmitter into the retro agent so it shows
stage spinners with nested tool calls, matching the look of agent
nodes in the main workflow.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-11 09:53:40 -04:00