Commit graph

2125 commits

Author SHA1 Message Date
Bryan Helmkamp
9f881b2f28
Box::pin run_doctor and run_install to fix clippy large_futures
The storage dir check additions increased the run_doctor future size,
pushing the overall CLI dispatch future past the large_futures threshold.
Box::pin both run_doctor and run_install (which was already marginal).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:39:38 -04:00
Bryan Helmkamp
01f9921051
Merge main into PR branch, resolve conflicts
Resolved conflicts by starting from main's version and re-applying the
storage dir check feature: StorageDirStatus struct, probe_storage_dir(),
check_storage_dir(), and unit tests. Adapted to main's refactored
architecture (settings resolution via user_config::storage_dir, no
--dry-run flag).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 16:30:24 -04:00
Bryan Helmkamp
38a6db8ea6
Add --force option for fabro pr create (#155)
Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:56:01 -04:00
Bryan Helmkamp
3a9f6def9b
Add Homebrew tap auto-update to release workflow
Adds installer/fabro.rb.template and an update-homebrew job that
generates the formula from release artifacts and pushes it to
fabro-sh/homebrew-tap on each tagged release.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 15:38:58 -04:00
Bryan Helmkamp
16f1b991ed
Stop waiting for headless Chrome to exit 2026-04-12 15:12:36 -04:00
Bryan Helmkamp
fb1d3c8928
Disable debug UI auto-refresh for screenshot test 2026-04-12 15:06:04 -04:00
Bryan Helmkamp
b74b9f1365
Increase debug UI Chrome test timeout in CI 2026-04-12 14:59:23 -04:00
Bryan Helmkamp
81547af5c6
Fix headless Chrome debug UI CI test 2026-04-12 14:54:28 -04:00
Bryan Helmkamp
879a830b46
Increase timeout for headless Chrome debug UI test 2026-04-12 14:48:27 -04:00
Bryan Helmkamp
43ba57ecda
Stabilize worker shutdown process group test 2026-04-12 14:36:44 -04:00
Bryan Helmkamp
9361d49fa6
Stabilize TCP host-only bind fallback test 2026-04-12 14:32:10 -04:00
Bryan Helmkamp
9d3b62161d
Fix fabro-server mTLS integration test API 2026-04-12 14:26:28 -04:00
Bryan Helmkamp
15149111b6
Fix Rust CI formatter and clippy warnings 2026-04-12 14:22:40 -04:00
Bryan Helmkamp
c545de08e2
chore: refresh fabro spa assets 2026-04-12 14:15:36 -04:00
Bryan Helmkamp
33933e0676
Split server runtime secrets from vault secrets 2026-04-12 14:03:54 -04:00
Bryan Helmkamp
d48fd7fd1f
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	clippy.toml
2026-04-12 13:43:38 -04:00
Bryan Helmkamp
96cefa84cf
refactor(async): lint std::process::Command across all targets
Move async subprocess paths to Tokio or spawn_blocking, document the
intentional synchronous std::process::Command callsites, and make CI run
Clippy with --all-targets so the guardrail applies to test code too.
2026-04-12 13:35:57 -04:00
Bryan Helmkamp
884c4d4314
feat: add typed secrets metadata and API 2026-04-12 12:47:08 -04:00
Bryan Helmkamp
38c10e6dd6
refactor(async): prefer tokio sleeps and lint std::thread
Add a Clippy disallowed-methods guardrail for std::thread sleep/spawn
and convert the CLI polling paths to tokio::time::sleep so they no
longer block Tokio workers. Keep the intentional OS-thread sites with
narrow #[expect(...)] annotations that explain why std::thread is
required there.
2026-04-12 12:36:19 -04:00
Bryan Helmkamp
af97e6cb8e
fix: simplify fabro-http crate and fix correctness issues
- Replace unwrap_or_default() with expect() in hooks/llm HTTP client
  builders — Default silently discards all config (timeouts, TLS, proxy)
- Route fabro-mcp through fabro_http instead of raw reqwest, respecting
  FABRO_HTTP_PROXY_POLICY for MCP HTTP transport connections
- Deduplicate HttpClientBuilder / BlockingHttpClientBuilder via macro
- Extract helpers for repeated http_client error handling in diagnostics
  and web_auth
- Remove duplicate test_http_client() in fabro-cli and fabro-llm

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 12:20:55 -04:00
Bryan Helmkamp
be42886840
refactor(http): centralize reqwest behind fabro-http
Add the shared fabro-http transport crate and route hand-written HTTP client construction through it.

Use FABRO_HTTP_PROXY_POLICY for test no-proxy defaults, remove direct reqwest deps from ordinary crates, and add clippy bans for raw reqwest entrypoints.
2026-04-12 11:48:54 -04:00
Bryan Helmkamp
f207d6e19a
feat(github): add gh cli integration strategy
Make gh_cli the default GitHub integration path across install, server,
workflow, and CLI surfaces while keeping app-based setup available when
explicitly selected.

Also defer GitHub reqwest client initialization until an HTTP request is
actually needed so missing-token and token-only paths do not trip workspace
test slow timeouts.
2026-04-11 21:35:16 -04:00
Bryan Helmkamp
f08626c045
refactor(cli): clean up remaining Printer migration
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
Shorten fully-qualified Printer paths in attach.rs and convert
two missed eprintln! calls in runs/list.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 15:10:50 -04:00
Bryan Helmkamp
e3dbc4957f
refactor(cli): route command output through Printer
Plumb the CLI printer through command dispatch, replace direct stdout and
stderr writes with printer helpers, preserve important stdout in quiet
mode, and update the Claude Rust formatting hook to use cargo +nightly
fmt.
2026-04-11 14:40:33 -04:00
Bryan Helmkamp
91b96ae6b3
fmt: apply nightly rustfmt after merge
Restore a clean nightly rustfmt baseline on the merged main branch so
cargo +nightly fmt --check --all passes again after bringing in
origin/main.
2026-04-11 13:43:30 -04:00
Bryan Helmkamp
b686203298
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/src/manifest_builder.rs
#	lib/crates/fabro-workflow/src/run_options.rs
2026-04-11 13:28:36 -04:00
Bryan Helmkamp
2f63249e2c
refactor(config): move project state under .fabro
Keep project config and checked-in workflows under .fabro so they stay out of
normal repo listings. Update config discovery, CLI project commands, fixtures,
docs, and checked-in workflow paths to use .fabro/project.toml and
.fabro/workflows/*.
2026-04-11 12:55:46 -04:00
Bryan Helmkamp
c8a7848b6f
refactor: remove backwards-compat error type aliases
No production deployments exist, so there's no need for migration shims.
Remove all six backwards-compat type aliases (AgentError, SdkError,
CoreError, GraphvizError, StoreError, FabroError) and migrate ~880
callsites to use the canonical Error name directly within each crate,
or qualified imports (e.g., `use fabro_llm::Error as LlmError`) for
cross-crate references. Also fix a pre-existing absolute-path clippy
lint in fabro-server error.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:51:42 -04:00
Bryan Helmkamp
952e0831e8
fmt: apply nightly rustfmt and document nightly requirement
The rustfmt.toml uses nightly-only options (struct_field_align_threshold,
imports_granularity, etc.) so stable rustfmt silently skips them,
producing different output. Use cargo +nightly fmt going forward.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:22:51 -04:00
Bryan Helmkamp
dd44220bc3
fix: preserve file path in config parse errors and fix test assertion
The error standardization lost the file path from parse error messages
when anyhow::Context was removed. Add path field to ParseSettings
variant so errors like "Failed to parse settings file at /path: ..."
include the file location. Also fix test that expected capitalized
"Workflow not found" to match the new lowercase error message.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 12:20:17 -04:00
Bryan Helmkamp
1802a61963
Merge branch 'phase-1-error-standardization' 2026-04-11 11:54:00 -04:00
Bryan Helmkamp
e190c098ab
refactor: standardize crate error types 2026-04-11 11:53:53 -04:00
Bryan Helmkamp
3f878cdc85
fmt 2026-04-11 11:27:46 -04:00
Bryan Helmkamp
9fd4388207
chore: clean up template migration fallout 2026-04-11 11:20:16 -04:00
Bryan Helmkamp
04f270b692
refactor: simplify template migration code
- Skip MiniJinja parse+render for plain-text strings (no {{ / {% / {#)
- Remove dead VariableExpansionTransform type alias
- Add From<TemplateError> for FabroError, replace manual map_err with ?
- Extract resolve_prompt_and_model helper in hooks executor

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 11:16:15 -04:00
Bryan Helmkamp
a64f4d0cd8
feat(template): unify workflow and config template syntax
Add a shared MiniJinja-based template crate and migrate workflow prompts,
imports, hooks, and InterpString env references to the new {{ ... }}
syntax. This also threads typed run inputs through workflow rendering and
updates docs and tests to match the new templating model.
2026-04-11 10:58:50 -04:00
Bryan Helmkamp
3db0c84385
test optimizations 2026-04-10 18:08:44 -04:00
Bryan Helmkamp
0221805a73
fix(cli): let detached workers exit after post-run shutdown
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
Move worker control stdin handling off Tokio's blocking shutdown path so
subprocess workers can exit cleanly after success or cooperative
cancellation even when the parent still holds stdin open.

Add regression coverage for retro-enabled success and SIGTERM-driven
cancellation with stdin intentionally left open.
2026-04-10 15:20:41 -04:00
Bryan Helmkamp
9b0eeb3814
Merge remote-tracking branch 'origin/main' 2026-04-10 12:02:05 -04:00
Bryan Helmkamp
4a872633ce
fix(core): prevent infinite loop when goal-gate retry target is terminal
Skip retry when get_retry_target points at a terminal node — retrying
into a terminal re-triggers the same goal-gate failure endlessly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 12:01:46 -04:00
Bryan Helmkamp
7fc133a2b1
chore(simplify): remove unnecessary comment and avoid double-serialization in event API
- Remove narrating comment in run_manifest.rs (code is self-explanatory)
- Optimize api_event_envelope_from_store: reuse payload's existing
  serde_json::Value instead of serialize-then-deserialize round-trip

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 11:47:15 -04:00
Bryan Helmkamp
76089bd8aa
chore(lint): fix all clippy warnings including --tests
Resolve every clippy warning across the workspace when running with
--tests enabled. Previously only library code was lint-clean; test
code had accumulated issues that were invisible without --tests.

Fixes:
- redundant_closure_for_method_calls: |s| s.as_source() -> InterpString::as_source
  (effective_settings, resolve_cli/root/server/features, run_event/record_serde,
  materialize_run) — add InterpString imports where needed
- absolute_paths: inline fabro_types::settings::* paths -> use imports;
  add #![allow(clippy::absolute_paths)] to fabro-cli and fabro-server
  IT test harnesses (matching the existing pattern in integration.rs)
- bool_assert_comparison: assert_eq!(x, true) -> assert!(x)
- needless_raw_string_hashes: r#"..."# -> r"..." where no inner quotes
- field_reassign_with_default: mut + field assign -> struct literal with ..Default
- match_same_arms: merge Timeout | Disconnected arms in attach.rs
- needless_pass_by_value: signal_rx by ref in attach.rs
- unreadable_literal: 9999999999 -> 9_999_999_999
- default_trait_access: Default::default() -> BTreeMap::default()
- items_after_statements: move use to function top
- large_futures: allow in integration.rs test module (test-only, not prod)
- filter_map_bool_then: .filter_map(bool::then) -> .filter().map()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 10:16:24 -04:00
Bryan Helmkamp
3085ad56f8
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/src/commands/install.rs
2026-04-10 10:10:23 -04:00
Bryan Helmkamp
9dea052093
feat(install): let user choose GitHub App owner (personal or org)
Add GhCli wrapper for best-effort gh CLI detection and org discovery.
During `fabro install`, prompt the user to create the GitHub App under
their personal account or an org they admin, with a manual entry fallback
for org app managers. App name defaults to `{owner}-fabro`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 09:32:05 -04:00
Bryan Helmkamp
42f8ec271b
test(fabro-test): scrub FABRO_* env from spawned subprocesses
TestContext::command() was inheriting all parent env vars, so a
developer (or CI) running with FABRO_CONFIG set would pollute child
test subprocesses, causing settings_local_* IT tests to fail with
opaque assertion errors.

Iterate std::env::vars_os() and env_remove every FABRO_* key before
re-adding the controlled set (FABRO_NO_UPGRADE_CHECK, etc.). Safe to
iterate because the prior two commits eliminated all std::env::set_var
callers in fabro-cli and fabro-config tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 08:49:44 -04:00
Bryan Helmkamp
0a57367fee
refactor(config): use lookup injection for active_settings_path env test
The active_settings_path_honors_fabro_config_env test was using an
EnvGuard that called std::env::set_var/remove_var — unsafe shared
mutable state in a parallel test binary.

Extract active_settings_path_with_lookup that takes an env-lookup
closure (same pattern as resolve_auth_mode_with_lookup in jwt_auth.rs).
Rewrite the test to inject the env value via the closure. Delete the
EnvGuard struct — no remaining callers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 08:49:31 -04:00
Bryan Helmkamp
06d9ef6118
refactor(cli): inject user settings layer into build_run_manifest
build_run_manifest was reading FABRO_CONFIG env and ~/.fabro/settings.toml
internally, which forced its 3 unit tests to use unsafe std::env::set_var
to isolate from the developer's real config. This violates the project rule
against mutating shared mutable state in tests.

Add user_layer: SettingsLayer and user_settings_path: Option<PathBuf> to
ManifestBuildInput so callers pass the user layer explicitly.

- Production callers (graph, preflight, validate, run/create) load via
  load_settings_user() + active_settings_path(None) at the command boundary.
- Tests pass SettingsLayer::default() and None, needing no env access.
- Delete all unsafe { set_var/remove_var } blocks and #[allow(unsafe_code)]
  attributes from the 3 manifest_builder tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 08:49:22 -04:00
Bryan Helmkamp
1dfb8fc272
refactor(settings): remove bridge shims and restore contracts
Drop the dead sandbox and hook bridge helpers that no longer have runtime
callers, and move the run settings serde coverage into fabro-types where the
wire types live. Add the missing /api/v1/runs/:id/settings contract test so the
outward sparse settings shape stays covered after the refactor.
2026-04-10 08:35:08 -04:00
Bryan Helmkamp
9a43606759
refactor(settings): rename settings layer and move parsing 2026-04-10 08:10:06 -04:00
Bryan Helmkamp
fab67ad31f
refactor(settings): remove sparse settings compatibility layer 2026-04-10 07:58:46 -04:00