Commit graph

343 commits

Author SHA1 Message Date
Bryan Helmkamp
3233ef529b refactor(server): make secrets and operational checks server-canonical
Move secret storage, diagnostics, and repo/provider validation behind the
server API so credentials live under the server storage dir and take effect
immediately without process env mutation.

This also removes the old .env runtime path, rewires doctor/install/secret/
provider login/repo init around the server contract, and regenerates the
TypeScript client for the new endpoints.
2026-04-05 17:34:01 -04:00
Bryan Helmkamp
cdddcdeadf refactor(cli): remove global execution mode 2026-04-05 15:20:00 -04:00
Bryan Helmkamp
d34a22a725 docs(cli): remove stale fabro llm references 2026-04-05 14:43:49 -04:00
Bryan Helmkamp
d4b9331d2e refactor(cli): make model commands server-canonical 2026-04-05 14:09:24 -04:00
Bryan Helmkamp
2e2197b722 plan 2026-04-05 11:03:02 -04:00
Bryan Helmkamp
bf2b6ba701 refactor(cli): route run state through the shared server daemon
Move durable run access and execution control onto the server-backed client,
canonicalize run APIs under /api/v1/runs, and switch CLI integration tests
to a shared test daemon/storage model with shared-state-safe assertions.
2026-04-05 00:15:33 -04:00
Bryan Helmkamp
582c78096b refactor: add run store HTTP endpoints
Define the new run-store contract in the OpenAPI spec, regenerate the
Rust and TypeScript clients, and implement the matching store and
server support for run state, event access, blobs, and stage artifacts.
2026-04-04 15:37:43 -04:00
Bryan Helmkamp
aa5047c509 Merge remote-tracking branch 'origin/main' 2026-04-04 13:33:32 -04:00
Bryan Helmkamp
3c99e98903 refactor: split POST /runs into create + start, remove context endpoint
Align the HTTP API with the CLI's existing `fabro create` / `fabro start`
separation. POST /api/v1/runs now creates a run in `submitted` status
without queuing it. A new POST /api/v1/runs/{id}/start transitions to
`queued` and notifies the scheduler. Also removes the unused
/api/v1/runs/{id}/context endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:02:08 -04:00
Bryan Helmkamp
1189cddd25 refactor: simplify run event representation 2026-04-04 12:59:42 -04:00
Bryan Helmkamp
a632813a20 cleanup 2026-04-04 12:08:57 -04:00
Bryan Helmkamp
cba8de4d94 Refactor assets into blob-backed artifacts 2026-04-04 12:08:15 -04:00
Bryan Helmkamp
14516f3e9c docs: clarify file-backed artifact docs
Update the run directory, context, and output docs to describe
large offloaded values as file-backed artifacts while preserving the
existing cache path examples.
2026-04-04 00:00:25 -07:00
Bryan Helmkamp
9752bfc37c Rename fabro-api-types to fabro-api with progenitor client generation
Replace typify-only type generation with progenitor, which generates both
Rust types (in a `types` module) and a reqwest-based HTTP client from the
OpenAPI spec. Also upgrades reqwest 0.12→0.13 and rmcp 0.15→1.3 to align
dependency versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 11:17:27 -07:00
Bryan Helmkamp
0c7bb831b3 docs 2026-04-03 06:45:25 -07:00
Bryan Helmkamp
af2a1e4f6d Add server daemon management with Unix socket support
Transform `fabro server` from foreground-only TCP into a proper daemon:
- `server start` launches background daemon with flock-based locking
- `server start --foreground` retains current blocking behavior
- `server stop` sends SIGTERM, waits, escalates to SIGKILL
- `server status` reports running/stopped with PID, bind, uptime (--json)
- `--bind` replaces `--host`/`--port`, supporting Unix sockets and TCP
- Default bind is `{storage_dir}/fabro.sock` (Unix socket)
- Hidden `__serve` subcommand for daemon child process lifecycle
- Graceful shutdown via SIGTERM/SIGINT signal handlers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:40:19 -07:00
Bryan Helmkamp
7235414e6a Rename FabroSettings to Settings, eliminate FabroSettingsExt
Move storage_dir() from FabroSettingsExt trait in fabro-config into an
inherent method on Settings in fabro-types. Remove the re-export from
fabro-config so callers import directly from fabro_types. Drop the
redundant Fabro prefix since the type already lives in the fabro_types
crate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 07:36:44 -07:00
Bryan Helmkamp
b56b82d34b Cut over Fabro web app to a server-backed SPA
Replace the old React Router SSR setup with a static SPA build served by
fabro-server, move setup and GitHub auth handling into Rust, and update the
default local web URL and stale Arc-era references to match the Fabro name.
2026-04-01 21:36:01 -07:00
Bryan Helmkamp
108e0cd632 Split agent processing into thinking and executing 2026-03-30 19:56:38 -04:00
Bryan Helmkamp
77bcf76581 Refactor run event envelopes and subagent linking 2026-03-30 17:09:07 -04:00
Bryan Helmkamp
d50b3187e5 Remove deprecated fabro init command
Users should use `fabro repo init` instead. The deprecation shim has
been in place long enough; remove it and update all docs references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:17:38 -04:00
Bryan Helmkamp
93aa239056 Add fabro completion subcommand for shell completions
Uses clap_complete to generate tab-completion scripts for zsh, fish,
elvish, and PowerShell. Bash generation is caught gracefully since
clap_complete panics with #[command(flatten)] subcommands.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:17:38 -04:00
Bryan Helmkamp
41f7b0cda6 Rename fabro serve to fabro server start
Restructure the flat `serve` command into a nested `server start`
subcommand, following the existing namespace pattern (system prune,
repo init, etc.).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:17:38 -04:00
Bryan Helmkamp
55df05fe43 Prefix API routes with /api/v1 2026-03-30 16:17:06 -04:00
Bryan Helmkamp
73cbcabf77 Remove Sprites sandbox provider
Drop the Sprites (Fly.io microVM) sandbox provider entirely. Three
providers remain: Local, Docker, and Daytona.

- Delete lib/crates/fabro-sandbox/src/sprites/ module
- Remove sprites feature flag and dep comments from Cargo.toml
- Remove sprites module declaration from lib.rs
- Update resolve_path cfg guard to daytona-only
- Delete docs/integrations/sprites.mdx and remove nav entry
- Remove Sprites rows from provider tables in docs
- Clean up SDK reference and changelog mentions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:23:06 -04:00
Bryan Helmkamp
3936f185cf Remove SSH and Exe sandbox providers
Only three sandbox providers remain: Local, Docker, and Daytona.

- Move detect_clone_params and GitCloneParams from ssh_common into daytona module
- Delete ssh/, exe/, and ssh_common.rs implementation files
- Remove Exe/Ssh variants from SandboxProvider, SandboxSpec, CliSandboxProvider
- Remove data_host from Sandbox trait and SandboxRecord
- Remove ExeSettings, SshSettings, ExeConfig, SshConfig types
- Remove ssh/exe/exedev feature flags from all Cargo.toml files
- Remove openssh workspace dependency
- Remove ExeSettings/SshSettings from OpenAPI spec
- Update docs to remove SSH/Exe references, delete exe-dev.mdx

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:17:20 -04:00
Bryan Helmkamp
a66b65bfc3 Move cp, ssh, preview under fabro sandbox namespace
These commands all operate on a run's sandbox environment. Grouping them
under `fabro sandbox` makes the mental model clear and avoids confusion
with `fabro asset cp`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:00:37 -04:00
Bryan Helmkamp
74b2c5c889 Rename config show command to settings 2026-03-30 11:41:18 -04:00
Bryan Helmkamp
bafab58442 Fix asset capture robustness and retry filtering 2026-03-29 22:23:33 -04:00
Bryan Helmkamp
b6947af7af Add per-asset metadata (mime, md5, sha256) to asset capture
Replace the batch AssetsCaptured event with per-file AssetCaptured events
that include content hashes and MIME type. The asset collection manifest
now stores a captured_assets array with full metadata instead of bare
path strings, enabling downstream integrity verification and content
type awareness.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 22:10:09 -04:00
Bryan Helmkamp
be6e37fa26 Rename cli.toml to user.toml 2026-03-29 21:24:10 -04:00
Bryan Helmkamp
652faf44d8 Infer CLI mode from storage and server flags 2026-03-29 20:58:46 -04:00
Bryan Helmkamp
e9e7c54adf Fix Mintlify API reference docs 2026-03-29 16:03:06 -04:00
Bryan Helmkamp
4d62c784ee Update docs for new CLI commands, fast mode, and subagent defaults
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 15:02:48 -04:00
Bryan Helmkamp
813c5eeaaf Add changelog entries for 2026-03-19 through 2026-03-29
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 14:18:16 -04:00
Bryan Helmkamp
9613d691f2 Refactor config resolution around ConfigLayer 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
38d24336b0 Remove legacy runtime IPC fallbacks 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
4b1caafcc8 Fix leading space in artifact path doc example
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
65b8cb6a31 Clean up runtime path docs and test comment 2026-03-29 13:47:08 -04:00
Bryan Helmkamp
bf9fd2cea2 Create RuntimeState for run runtime and cache paths 2026-03-29 13:47:08 -04:00
Bryan Helmkamp
c192c106f6 Rename fabro-types to fabro-api-types
Better reflects that this crate contains auto-generated types scoped
to the API layer. Pure rename with no behavior change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
defcf9c746 Clean up resolved settings interfaces 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
aec2d5b437 Rename --run-dir to --storage-dir, unify with data_dir
Replace the per-run `--run-dir` CLI flag with `--storage-dir` which sets
the base storage directory (default ~/.fabro). Runs are now created under
`<storage-dir>/runs/` automatically. This unifies the server's `data_dir`
config with the CLI by renaming `FabroConfig.data_dir` to `storage_dir`
and adding a `storage_dir()` convenience method.

Key changes:
- FabroConfig: `data_dir` → `storage_dir` (serde alias preserves compat)
- CLI: `--run-dir` → `--storage-dir` on `fabro run`
- `__detached`: now takes `--storage-dir` + `--run-id` instead of `--run-dir`
- All ~20 CLI commands derive runs base from config instead of hardcoded default
- Added parameterized `runs_base(storage_dir)` and `make_run_dir()` helpers
- Updated OpenAPI spec, docs, and all tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
03f73bf83c Add fabro config show command 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
8b78d33795 Extract --preflight into fabro preflight subcommand
Preflight validation is conceptually distinct from running a workflow —
it deserves its own top-level command rather than being a flag on `run`.

- Add `PreflightArgs` struct and `Commands::Preflight` variant
- Create `commands/preflight.rs` with dedicated `execute()` function
- Remove `--preflight` flag from `RunArgs`
- Refactor `load_workflow_source_input` to take individual params
  instead of `&RunArgs`
- Refactor `resolve_cli_goal` to take `Option<&str>` / `Option<&Path>`
- Refactor `run_preflight` to take `cli_model`/`cli_provider` instead
  of `&RunArgs`, make `pub(crate)`
- Update docs and skills references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
551d16b74c refactor: clean CREATE/START/RESUME separation
Resume now follows the same subprocess pattern as run: look up run
directory by ID prefix, validate checkpoint exists, clean stale
artifacts, reset status to Submitted, spawn _run_engine --resume, and
attach. This eliminates ~1600 lines of duplicated env/sandbox setup
from resume.rs.

Key changes:
- operations::start() and operations::resume() take run_dir instead
  of Persisted, loading state from disk internally
- run_engine() builds RunOptions from RunRecord on disk, so callers
  no longer extract record fields manually
- StartOptions flattened (no more nested InitOptions)
- FabroError::Precondition variant for start/resume guard checks
- _run_engine accepts --resume flag to dispatch to resume path
- operations::restore removed (no longer needed)
- Resume CLI stripped to just <RUN_ID> + --detach

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
d6aff051a5 Align run persistence with run record plan 2026-03-29 13:47:06 -04:00
Bryan Helmkamp
2fe1682074 Complete remaining RunRecord plan gaps: run_from_record, TOML rename, API RunRecord
Phase 5: Rename debug artifacts from run.toml/graph.fabro to
workflow.toml/workflow.fabro. Change write_run_config_snapshot to
byte-for-byte copy of the original TOML instead of re-serialization.

Phase 6: Add run_from_record() that builds execution state directly
from a RunRecord, bypassing prepare_workflow(). Refactor run_command
into run_command + run_command_impl to share execution logic. Simplify
run_engine_entrypoint to call run_from_record() instead of
reconstructing RunArgs and re-parsing the workflow.

Step 7k: Write RunRecord in the API server's execute_run() for
observability, enabling fabro ps/inspect for API-initiated runs.

Fix stale manifest.json reference in docs/agents/outputs.mdx.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:06 -04:00
Bryan Helmkamp
29bb16a4fa Add RunRecord + StartRecord alongside RunSpec + Manifest
Introduce two new persistence types aligned to the CREATE/START lifecycle:
- RunRecord (run.json): written at CREATE with merged FabroConfig, fully
  transformed Graph, and run metadata
- StartRecord (start.json): written at START with start_time, run_branch,
  and base_sha

All readers (run_lookup, inspect, diff, pr, attach, detached_support,
start, run_fork, pull_request, run_rewind, resume) now read from the
new types first. Legacy manifest.json + spec.json are still written
for backward compatibility (removal in follow-up).

Also adds dry_run, auto_approve, no_retro fields to FabroConfig, derives
Default on LlmConfig and Graph, and updates docs + tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:06 -04:00
Bryan Helmkamp
190bbf4e34 Remove Context logs, replace with RunNotice events + tracing
Context::append_log / logs_snapshot was a write-only audit trail that
was never surfaced — not in events, CLI output, or tracing. Errors like
"checkpoint save failed" were silently swallowed.

Replace all append_log call sites with RunNotice events (which are
automatically traced and visible in progress.jsonl / CLI). Remove the
logs field from both Context types, the Checkpoint struct, the OpenAPI
spec, and the TS client. Old checkpoints containing a logs field are
silently ignored during deserialization.

Also make git_diff return Result<String, String> with structured error
info (exit code + stderr) instead of Option<String>.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:05 -04:00