Commit graph

91 commits

Author SHA1 Message Date
Bryan Helmkamp
e50df2b58b
feat(command): distinguish cancelled commands from timeouts
Represent command termination explicitly across sandbox results, events,
run projections, API types, and the run stage UI. This removes the fake
-1 exit code path for timeout/cancel and lets consumers tell cancelled
commands apart from timed-out commands.
2026-04-30 22:45:37 -04:00
Bryan Helmkamp
8ac400df1c
feat(command): stream command logs from CAS-backed storage
Persist command stdout/stderr through scratch logs and finalized CAS refs, expose byte-offset tailing through the API, and render separate streaming panels in the web run view.

Resolve command output blob refs for execution-time consumers such as edge routing and retros, and make Docker streaming timeout/cancel drain output before returning.
2026-04-30 22:45:37 -04:00
Bryan Helmkamp
1862024b61
refactor(api): tighten shared type schemas 2026-04-30 06:20:05 -04:00
Bryan Helmkamp
78a2f8638b
refactor(api): reuse billing and model domain types 2026-04-30 06:15:18 -04:00
Bryan Helmkamp
13281ed3af
refactor(api): reuse canonical run events 2026-04-29 20:36:59 -04:00
Bryan Helmkamp
6a8329b376
refactor(api): align run projection types 2026-04-29 20:32:50 -04:00
Bryan Helmkamp
3e97cae0ae
refactor(api): unify secret metadata types 2026-04-29 20:26:13 -04:00
Bryan Helmkamp
25cd80c072
refactor(api): unify leaf API types 2026-04-29 20:21:23 -04:00
Bryan Helmkamp
642e312cca
refactor: unify duplicate API types via with_replacement
Eliminate four parallel-type duplications between fabro-api generated
DTOs and fabro-types canonical types. The wire shape is owned by
OpenAPI; canonical types are reused via fabro-api/build.rs
with_replacement so the adapter functions and silent unwrap_or_default
defaults disappear.

- SecretType moves to fabro-types (was fabro-vault); deletes
  secret_type_from_api adapter.
- DiffLineStats renamed to DiffStats, moved to fabro-types, switched
  u64 -> i64 to match the OpenAPI integer; deletes line_stats_to_api.
- ManifestPreRunPushOutcome rewritten as a oneOf+discriminator
  PreRunPushOutcome over five variant schemas, deleting both
  pre_run_push_outcome_from_manifest and build_manifest_push_outcome.
- ManifestGit and PreRunGitContext unify as GitContext: dirty:
  DirtyStatus replaces clean: bool (preserving the Unknown state
  previously truncated on the wire), sha becomes Option<String>, and
  origin_url/branch fold into the unified context. RunSpec and
  RunCreatedProps flatten three fields (repo_origin_url, base_branch,
  pre_run_git) into a single git: Option<GitContext>.

Each replacement gets a fabro-api parity test (TypeId equality plus
JSON roundtrip) modeled on run_summary_round_trip.rs. TS client
regenerated.

Greenfield app, no production deployments — wire contract changed
directly without backwards-compat shims.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 12:29:37 -07:00
Bryan Helmkamp
44d1d7f5e2
refactor(api): reuse run summary domain type 2026-04-26 23:28:04 -04:00
Bryan Helmkamp
d07596ca80
feat(server): support stdout log destination
Add configurable server log destinations with an environment override so containers can stream foreground server logs to stdout while local installs keep file logging by default. Validate configured log filters at load time and reject stdout logging for daemon mode.
2026-04-26 14:52:15 -04:00
Bryan Helmkamp
9220af6e80
migrate remaining run settings consumers to dense snapshots 2026-04-23 11:55:12 -04:00
Bryan Helmkamp
b2bcf0d5a8
refactor settings builders and dense run snapshots 2026-04-23 11:35:21 -04:00
Bryan Helmkamp
fa62da5d9d
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-api/build.rs
#	lib/crates/fabro-server/src/install.rs
#	lib/crates/fabro-server/src/serve.rs
#	lib/packages/fabro-api-client/src/.openapi-generator/FILES
#	lib/packages/fabro-api-client/src/models/index.ts
2026-04-22 21:18:50 -04:00
Bryan Helmkamp
ebb8bf7add
refactor settings API entrypoints 2026-04-22 18:58:47 -04:00
Bryan Helmkamp
6c3211e3ce
refactor(run-status): unify tagged lifecycle states 2026-04-22 17:15:13 -04:00
Bryan Helmkamp
eb7e65b6b4
refactor(api): reuse domain status types in fabro-api
Replace the generated status family with fabro-types replacements and add
parity tests that lock type identity and JSON shape to the OpenAPI spec.
2026-04-21 09:10:53 -04:00
Bryan Helmkamp
aa8cdd6986
refactor(cli): rename ServerStoreClient -> Client, fabro_api::Client -> ApiClient
The CLI façade is the primary type callers reach for, so it deserves
the bare `Client` name (per `reqwest::Client`, `hyper::Client`
convention). The raw generated HTTP binding is secondary and is more
accurately named `ApiClient`. "Store" in `ServerStoreClient` was
leftover from the SlateDB-ownership refactor and no longer describes
the type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 08:56:09 -04:00
Bryan Helmkamp
83743de293
chore(clippy): add unwrap-used baseline
Enable clippy's unwrap_used lint at warn level, document the long-term
policy carveouts for tests and LockResult, and localize the generated
OpenAPI client exemption so the remaining warning surface is real repo
code.
2026-04-19 20:43:23 -04:00
Bryan Helmkamp
ad0d532691
chore(clippy): require reasons on allow attributes
Enable clippy::allow_attributes_without_reason at the workspace level.
Add concise, callsite-specific reasons to existing allow attributes, including generated code paths.
2026-04-19 20:24:24 -04:00
Bryan Helmkamp
3b2cffceaf 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
5eeacd7864 fmt 2026-04-11 11:27:46 -04: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
0abf7c1b4d Rename fabro-api crate to fabro-server
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:09 -04:00
Bryan Helmkamp
f7392767ee Configure SlateDB flush_interval to 5ms for local storage
SlateDB defaults to 100ms flush_interval (tuned for S3 cost). For
local/in-memory object stores this adds unnecessary write latency.
Pass flush_interval through SlateStore::new() so callers control
the setting, and switch open_db() to use Db::builder().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:09 -04:00
Bryan Helmkamp
96641f4acc Wire workflows and CLI to fabro-store 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
4ceee0c921 Centralize sandbox variant handling 2026-03-29 13:47:09 -04:00
Bryan Helmkamp
2dbf656e42 Rename *config* variables/params that hold *Settings types
Local variables and function parameters named with "config" but holding
*Settings types (FabroSettings, TlsSettings, ApiSettings, LlmSettings)
are renamed to use "settings" for consistency with the type system.
Module paths (cli_config::) and struct fields are unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:09 -04:00
Bryan Helmkamp
7de491ce8a Enable 7 additional pedantic clippy lints
Enables char_lit_as_u8, collapsible_else_if, collapsible_if,
map_unwrap_or, match_same_arms, used_underscore_binding, and
if_not_else. Fixes all violations: combines duplicate match arms,
renames underscore-prefixed bindings that are actually used, rewrites
if-not-else patterns, and applies map_or where appropriate.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
8f288214eb Enable cast_possible_wrap clippy lint and fix violations
Replaces 14 unsigned-to-signed `as` casts with try_from().unwrap()
to panic on overflow instead of silently wrapping.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
752d04cbcb Enable additional pedantic clippy lints and fix violations
Enables cast_possible_truncation, cast_sign_loss, items_after_statements,
needless_pass_by_value, return_self_not_must_use, uninlined_format_args,
unreadable_literal, and unnested_or_patterns. Keeps doc_markdown disabled.

Replaces unsafe `as` casts with try_from().unwrap() throughout, using
#[allow] only for f64-to-integer casts which have no try_from equivalent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
1d304b771a Enable clippy pedantic lints and restriction lints workspace-wide
Adopts uv's clippy lint configuration: pedantic group at warn priority,
with noisy lints allowed, plus restriction lints for print/dbg/exit/use_self.
Fixes all violations across the workspace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
97214c7d83 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
0b90305432 Enforce no-inline-qualified-paths via clippy absolute_paths lint
Add clippy.toml with absolute-paths-max-segments = 2 (allowing std/core/alloc)
and enable the absolute_paths = "warn" lint workspace-wide. Fix all ~300
violations across the codebase: replace 3+-segment inline paths with use
statements so call sites read as operations::create() rather than
fabro_workflows::operations::create(). The demo module gets an allow
attribute since it constructs many API types by design.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
41e1809b21 Enforce no-wildcard-imports via clippy workspace lint
Configure clippy `wildcard_imports = "warn"` at the workspace level and
opt all 28 crates in via `[lints] workspace = true`. Fix the three
production glob imports that triggered warnings: fabro-sandbox
read_guard, fabro-cli main, and fabro-api demo module (allowed via
attribute since it constructs many API types by design). Document the
import style convention in CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:08 -04:00
Bryan Helmkamp
48c21ed521 Create fabro-types and rewire shared types 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
58bb577d57 Refactor workflow operations and config resolution 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
590d237844 Tighten workflows request context and launcher cleanup 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
db3231e987 Thin CLI run commands and move execution into workflows operations 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
defcf9c746 Clean up resolved settings interfaces 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
95d8b32919 Refactor config layering into combine plus settings 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
b93e1b0109 Add goal_file and labels to FabroConfig
Allow workflow authors to set default goal files and labels in
workflow.toml/fabro.toml, reducing repetitive CLI flags. CLI flags
override config values; labels are deep-merged with CLI winning on
key collision.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
9cedd9fc0a Fix verification regressions after runtime init refactor 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
6120b38e2d Refactor workflow runtime initialization 2026-03-29 13:47:07 -04:00
Bryan Helmkamp
452624e699 refactor: rename local variables/fields to align with Options suffix
Follow-up to fafc0a3c. Renames local variables, function parameters,
and struct fields that hold renamed types (ExecutorOptions, RunCreateOptions,
RunOptions) from config/settings to options/run_options for consistency.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
2f017a4a64 refactor: rename Settings/Config structs to Options suffix
Standardize naming so all "bag of options" structs use the Options
suffix: ExecutorSettings→ExecutorOptions, RunSettings→RunOptions,
GitCheckpointSettings→GitCheckpointOptions, LifecycleConfig→LifecycleOptions,
RunCreateSettings→RunCreateOptions, StartRetroConfig→StartRetroOptions,
StartFinalizeConfig→StartFinalizeOptions, AutoMergeConfig→AutoMergeOptions.
Also renames the run_settings module to run_options.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
8e1c3bc4e9 refactor(operations): make create own the full create lifecycle
operations::create now handles the full pipeline: var expansion, parse,
goal override, transform, validate, config normalization, and persist.
This eliminates duplicated RunRecord construction and pipeline::persist
calls across CLI and API callers.

Key changes:
- Rename operations::create → validate, CreateOptions → ValidateOptions
- New operations::create returns Persisted, with RunCreateSettings
- Add ValidationFailed error variant with diagnostics
- Move normalize_config, default_run_dir into operations
- Delete prepare_workflow, PreparedWorkflow, CliFlags from CLI
- Make pipeline::persist and types module pub(crate)
- API catches both Parse and ValidationFailed as 400
- CLI prints diagnostics directly from error (no re-validation)
- ExecutionOverrides struct replaces 9-param function

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 13:47:07 -04:00
Bryan Helmkamp
6a70909b00 Add workflow persist stage 2026-03-29 13:47:06 -04:00