Commit graph

68 commits

Author SHA1 Message Date
Bryan Helmkamp
a102557d32
Rename config show command to settings 2026-03-30 11:41:18 -04:00
Bryan Helmkamp
bec44709f5
Sort cmd/mod.rs module declarations alphabetically
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:41:18 -04:00
Bryan Helmkamp
8da8298ea5
Extract workflow E2E tests into workflow/ directory
Move the 6 parametrized workflow scenarios from scenario/workflows.rs
into a new workflow/ directory with one file per test. Move fixture
.fabro files from test/scenario/ to workflow/fixtures/ co-located with
the tests.

Rename the scenario_tests! macro to sandbox_tests! in the new module
for clarity. Slim scenario/ down to just lifecycle and exec tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:41:18 -04:00
Bryan Helmkamp
ef46c174b8
Add fabro-cli help snapshots for subcommands 2026-03-30 11:41:18 -04:00
Bryan Helmkamp
90fc680609
Split scenario.rs into scenario/ directory
Break the monolithic scenario.rs into three focused files:
- scenario/workflows.rs — 6 parametrized E2E workflow scenarios
- scenario/lifecycle.rs — run lifecycle (ps, inspect, logs, assets, rm)
- scenario/exec.rs — exec creates file scenario
- scenario/mod.rs — shared helpers, macro, and timeout_for

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:41:15 -04:00
Bryan Helmkamp
f01d74c692
Fix cli-table ignoring NO_COLOR environment variable
cli-table defaults to ColorChoice::Always, emitting ANSI escape codes
regardless of NO_COLOR. Fix all 5 call sites to:

1. Pass use_color to title cell .bold() instead of hardcoding true
2. Set .color_choice(Never) when colors are disabled
3. Use .display() instead of the free print_stdout/print_stderr
   functions (which re-wrap with Always defaults)

Affected commands: model list, model test, ps list, system df, rewind.
The model test snapshots are now clean plaintext.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
e2a8463c2e
Populate serve help snapshot
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
7a777ebf01
Convert serve help test to fabro_snapshot and delete orphaned snap file
Replace ad-hoc insta::assert_snapshot! with TestContext + fabro_snapshot!
for consistency. Delete the orphaned snapshot file from the deleted
cli.rs module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
3dee953cd2
Add git_init() helper to TestContext
Initializes a git repo in temp_dir. Replaces the local init_git_repo()
helper in repo.rs tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
2e913428d5
Convert 6 more predicate assertions to fabro_snapshot
Replace predicates::str::contains checks with full snapshots in
single-command tests: repo deinit failure, repo init help, secret
get/rm missing key, exec missing API key, config show missing workflow.

The remaining predicate usages are in multi-step CRUD tests and legacy
config tests where programmatic assertions are still the better fit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
b638b8d84f
Convert workflow list test to use fabro_snapshot
Replace predicates::str::contains assertion with a full snapshot,
making the test more precise and consistent with other cmd/ tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
cb072aed75
Adopt write_temp/write_home helpers across cmd/ tests
Replace manual std::fs::create_dir_all + std::fs::write boilerplate
with context.write_temp() and context.write_home() in repo, workflow,
exec, and run tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
fa43f8f780
Add write_temp/write_home helpers to TestContext
Add convenience methods that write a file under temp_dir or home_dir,
auto-creating parent directories. Returns &Self for chaining.

Apply write_home in config.rs fixture helpers and standalone tests,
replacing manual create_dir_all + write boilerplate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:31 -04:00
Bryan Helmkamp
9a762746a2
Remove arc() and fabro() helpers in favor of TestContext
Replace all ad-hoc arc()/fabro() command helpers with TestContext methods
(command(), run_cmd(), validate(), exec_cmd(), etc.) across all cmd/
test files. This eliminates 9 duplicate helper definitions and gives
every test consistent isolation (HOME, NO_COLOR, FABRO_STORAGE_DIR,
FABRO_NO_UPGRADE_CHECK).

Also removes init_cli_home() helper — TestContext's env-var-based
FABRO_STORAGE_DIR makes it unnecessary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:40:28 -04:00
Bryan Helmkamp
d365e713b5
Refactor scenario.rs to use TestContext for isolation
Replace manual fabro()/tempdir/--storage-dir boilerplate with TestContext
from fabro-test crate. This gives each scenario proper HOME isolation,
automatic NO_COLOR and upgrade-check suppression, and removes the need
for explicit --storage-dir CLI args.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:37:31 -04:00
Bryan Helmkamp
d1a969510e
Move cli.rs and scenario.rs tests into per-subcommand cmd/ files
Redistribute all tests from the monolithic cli.rs (2190 lines) and the
standalone tests from scenario.rs into their respective cmd/ files,
completing the migration to the one-file-per-subcommand structure.

- Delete cli.rs entirely; move tests to cmd/{run,config,llm,exec,doctor,serve}.rs
- Move scenario.rs standalone tests to cmd/{repo,secret,workflow,doctor}.rs
- Slim scenario.rs to only 6 parametrized E2E workflow scenarios + run lifecycle
- Create new cmd/serve.rs and cmd/workflow.rs modules
- Remove duplicate tests already covered by snapshot tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:37:24 -04:00
Bryan Helmkamp
d4a91eb29d
Replace trycmd tests with fabro-test crate and insta snapshots
Adopt uv's testing pattern: a shared `fabro-test` crate with TestContext
and fabro_snapshot! macro, plus one test file per subcommand under
tests/it/cmd/. This replaces the trycmd-based tests which were hard to
read and didn't compose well with programmatic assertions.

- Create lib/crates/fabro-test with TestContext, run_and_format,
  apply_filters, INSTA_FILTERS, and test_context!/fabro_snapshot! macros
- Add 42 snapshot tests across 16 subcommand files
- Delete trycmd.rs and all tests/cmd/ trycmd files
- Remove trycmd dependency, add fabro-test dev-dependency

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 11:28:41 -04:00
Bryan Helmkamp
e2d1ad2144
Clean up workspace clippy warnings 2026-03-30 11:27:25 -04:00
Bryan Helmkamp
e304dcca37
Use typed RunId across workflows 2026-03-30 09:20:11 -04:00
Bryan Helmkamp
c6ff6c95a2
Fix snapshot execution cleanup and GitHub PEM loading 2026-03-29 23:00:43 -04:00
Bryan Helmkamp
31ef250e2c
Fix asset capture robustness and retry filtering 2026-03-29 22:23:33 -04:00
Bryan Helmkamp
4268d04052
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
57abdcaeba
Rename cli.toml to user.toml 2026-03-29 21:24:10 -04:00
Bryan Helmkamp
d7e32f1380
Centralize global CLI override application 2026-03-29 21:08:16 -04:00
Bryan Helmkamp
79a366022f
Infer CLI mode from storage and server flags 2026-03-29 20:58:46 -04:00
Bryan Helmkamp
f5e4b4bb4e
Make metadata rebuild recovery robust 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
48ea1cc4de
Consolidate integration tests under tests/it 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
e1e433ea17
Remove legacy runtime IPC fallbacks 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
5c215033c1
Apply rustfmt 2024 style edition across workspace
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
88cab7b8f9
Clean up runtime path docs and test comment 2026-03-29 13:47:08 -04:00
Bryan Helmkamp
9e7814d062
Create RuntimeState for run runtime and cache paths 2026-03-29 13:47:08 -04:00
Bryan Helmkamp
6a0f571571
Refactor workflow operations and config resolution 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
25df708760
Thin CLI run commands and move execution into workflows operations 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
33f4da33c1
Clean up resolved settings interfaces 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
68ca9e892a
Fix workflow-relative config resolution 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
8a256bb68e
Refactor config layering into combine plus settings 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
126ece3d71
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
960ae3b3ac
Add fabro config show command 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
c871ecb274
Refactor fabro-cli run command layout 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
241f0192f2
refactor(fabro-cli): slim down main 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
b748c7e6ea
Guard resume against completed runs 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
d45b4516ab
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
e7a36a1feb
Remove RunSpec + Manifest types and all remaining references
Delete run_spec.rs and manifest.rs modules. Remove write_manifest()
from the engine, update DiskLifecycle and GitLifecycle to only write
StartRecord. Remove read_manifest() from MetadataStore. Update
run_fork to only handle run.json/start.json. Convert resume.rs to
use RunRecord/StartRecord from the metadata branch. Update all tests
and integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:06 -04:00
Bryan Helmkamp
08dbcee01e
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
0466f94239
Fix CLI integration test timeout by skipping upgrade check
The dry_run_writes_jsonl_and_live_json test was timing out at 4s because
the arc() helper didn't pass --no-upgrade-check, causing every test run
to await a background GitHub API call before process exit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:06 -04:00
Bryan Helmkamp
50b1776607
Remove dead selected_options field from Answer struct
The field was populated in constructors but never read by any code.
Selected keys are already carried by AnswerValue::MultiSelected(Vec<String>),
making this field redundant. Also removes the unused options parameter from
Answer::multi_selected().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 16:07:26 -04:00
Bryan Helmkamp
f5d363237a
Fix workflow slug lookup for split and resumed runs 2026-03-23 10:23:11 -04:00
Bryan Helmkamp
b5c014443e
Preserve split run metadata across restarts 2026-03-23 10:04:49 -04:00
Bryan Helmkamp
6f0023698b
Fix split run lifecycle lookup 2026-03-23 08:44:46 -04:00
Bryan Helmkamp
3db2c237e2
Unify fabro run foreground to use create + start + attach (#141)
## Summary

- **Unify foreground and detach code paths**: Both `fabro run` modes now
go through the same `create_run() + start_run()` pipeline, with
foreground adding `attach_run()`. Only `--preflight` remains as a
special case.
- **Fix three bugs in create→start→attach path**: (1) `_run_engine`
crashed for `.fabro` workflows by hardcoding `run.toml` — now falls back
to `graph.fabro`; (2) `attach_run` couldn't detect crashed engines due
to zombie processes — `start_run` now returns the `Child` handle; (3)
`create_run` ignored `--run-id`.
- **Configure nextest slow-timeout profiles**: Tighten unit test timeout
to 2s slow / 4s kill, add `e2e` profile with 10s/30s. Switch CI and docs
to `cargo nextest run`.

## Test plan

- [ ] `cargo nextest run --workspace` passes with new timeout profiles
- [ ] `fabro run <workflow>` works in foreground mode (create + start +
attach)
- [ ] `fabro run --detach <workflow>` prints run ID and exits
- [ ] `fabro attach <run>` works standalone (without child handle)
- [ ] `fabro resume <run>` works for both `.toml` and `.fabro` workflows

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 22:48:09 -04:00