Add bounded redacted exec output tails to failure events while keeping tracing log-safe. Centralize tail projection on ExecResult and thread diagnostics through metadata, setup, devcontainer, and CLI install failures.
Move RunDump into fabro-dump so CLI export and retro uploads share the same hydrated run layout. Drop the legacy artifact file-ref parser, add best-effort run.log retrieval for retro, and update retro prompts/docs to use events.jsonl and checkpoints.
Replace 16 inline copies of the `[cli.target] type = "http"` settings TOML across CLI integration tests with a single `set_http_target(&base_url)` method on `TestContext`. Removes a brittle format string that was maintained in ten files but only meaningfully asserted-against in one.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add configured to the model API contract and server responses so clients can see whether provider credential material exists before testing. Use that signal in bulk model tests to skip unconfigured providers before printing progress and treat post-list skips as race failures.
The Metadata init/checkpoint/finalize lines added noise to `fabro run`
output. The underlying events still flow into progress.jsonl; only the
live rendering is removed. Failures continue to render as warnings.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add typed metadata snapshot events around init, checkpoint, and finalize archive writes so run logs expose durable metadata timing and failures. Include snapshot accounting, CLI rendering with compatibility-notice suppression, and event documentation.
The bail!("Validation failed") was nested inside `if !quiet`, so
`fabro run --detach` and `fabro run create` (both pass quiet=true)
silently created runs from invalid workflows. Move the bail outside the
gate; only the workflow summary print remains gated on !quiet.
Also simplifies the surrounding preflight code:
- Extract `cyan_spinner` helper in fabro-cli's shared utilities;
collapse three copy-pasted 13-line spinner setups in preflight.rs,
doctor.rs, and install.rs.
- Add `SandboxProvider::is_clone_based()`; replace the local
`is_clone_based_provider` helper and two inline
`matches!(_, Docker | Daytona)` sites in run_manifest.rs.
- Promote `fabro_sandbox::redact::redact_auth_url` to pub and reuse it;
delete the duplicate `redact_remote_output` in run_manifest.rs.
- Inline the one-liner `preflight_docker_config` /
`preflight_daytona_config` helpers and drop their dedicated tests.
- Type the `prepared_and_resolved_for_sandbox` test helper with
`SandboxProvider` instead of `&str`.
- Drop git ls-remote preflight timeout from 30s to 10s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`fabro preflight` blocks on a single server-side `run_preflight` call.
Without feedback the terminal sits blank until it returns. Mirror the
existing `fabro doctor` spinner (cyan braille, "Running checks...",
80ms tick), gated on `!ctx.json_output()` so JSON and piped callers
stay clean. The network calls run inside an inline async block so the
spinner is `finish_and_clear`ed before any `?`-propagated error
prints.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduce ManifestPath as the canonical in-memory key for run manifests so CLI-produced bundle keys and workflow/server consumers share the same normalization rules. Validate wire keys at the server boundary and add a CLI-to-server round-trip test for user-global @path references.
GitHubAppCredentials now carries the configured app slug, so the "not
installed" error from the installation lookup links to the specific
app's install page (https://github.com/organizations/{owner}/settings/apps/{slug}/installations)
when known, instead of the generic org installations page. Threaded
through the server, workflow pipeline, and CLI runner.
Also treat docker like daytona for GitHub credential gating: both are
clone-based providers that need an installation token to fetch the repo,
so a docker run now requires credentials when daytona would.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop async from validate::run after the preflight refactor removed all
awaits, replace absolute paths and a one-liner helper in
manifest_validation, swap a redundant to_path_buf for clone in a test,
and regenerate cli.mdx so docs check stays green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace remaining expensive CLI lifecycle checks with seeded fixtures or focused unit coverage so the concurrent suite spends less time on duplicate full-process setup.
Seed read-only CLI tests from run-store fixtures, remove duplicate expensive lifecycle coverage, and keep machine-dependent gh tests offline so the suite no longer probes local credentials.
Add a validation-only API response and route while keeping fabro validate local so it does not start or contact the server for structural workflow checks.
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>
The persisted bool described user intent (\"the user opted into the
in-place execution mode\"), not a literal consequence -- SlateDB and
event-sourced checkpoints flow regardless of the flag, only git
checkpoints are skipped. Renaming aligns the name with intent and
decouples it from any future implementation that allows git
checkpoints in-place.
The fork validator still consults this bool to bail out with a clear
error before searching for git checkpoints that won't exist.
Drop --allow-no-checkpoints and the paired ManifestArgs in_place /
allow_no_checkpoints fields. The CLI now translates --in-place into a
single ManifestArgs.worktree_mode = "never" signal that flows through
the existing args→layer pipeline as run.sandbox.local.worktree_mode =
Never. The server computes prepared.in_place from the resolved settings
once, replacing the trio of bail!s and the sandbox-default fixup.
Skip worktree checkpoint setup when a local sandbox is not backed by a git repository, and keep the API contract aligned with RunSpec serialization for omitted labels.
Ensure local runs use the worktree checkpoint path by default, expose source and sandbox paths in API/web surfaces, and remove dead fork/rewind push controls. Update docs for clone-based sandboxes and durable checkpoint timelines.
Add shared sandbox git validation for checkpoint paths, preserve forked run projection state, and record CLI remote mismatches explicitly. Refresh the API/client docs for durable run-store timeline and structured run specs.
The span name "run" already namespaces the field, so `run{id=...}` reads
cleaner than `run{run_id=...}` in log output.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove redundant as_str/from helper methods on provider, reasoning, model-test, safe URL, and interview types. Migrate call sites to Display, IntoStaticStr, and FromStr while keeping wire-format coverage in tests.
- Delete unused `detect_clone_params` and `GitCloneParams` (the clone-based refactor sources clone params from the run spec, not the worker cwd).
- Add `DaytonaSandbox::repo_cloned()` accessor mirroring Docker; replace five inline `OnceCell` reads.
- Inline `sanitize_origin_url` one-liner wrapper in `manifest_builder`.
- Drop unused `pub` on `docker::WORKING_DIRECTORY`.
- Convert `cleanup` early-return to `let-else` and remove a `Some(...).expect(...)` round-trip in `decide_clone`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch Docker sandboxes from host bind mounts to per-run clone-based containers with structured run metadata, reconnect validation, archive-based file transfer, and Docker resource defaults.
Extend run config/API surfaces so Docker image and clone settings flow through manifests, server preflight, workflow startup, and generated clients.
Update docs and tests for the new default Docker provider path.
Move FABRO_LOG_DESTINATION parsing into fabro-config so CLI and server worker startup use the same validation behavior. Worker startup now exports one canonical resolved destination instead of relying on a generic env allowlist path.
The Server prefix is redundant -- the type is used by both Server and
Worker variants of InternalLogSink, and the helper that builds it from a
runtime directory is renamed to log_sink to match.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Workers are an internal implementation detail; operators should not need
to know about them. When the server runs in stdout mode (FABRO_LOG_DESTINATION=stdout,
e.g. inside containers), workers now also stream their tracing to stdout
so all server-level logs land on the same destination.
The parent propagates its resolved destination to each worker via
FABRO_LOG_DESTINATION and inherits the worker's stdout when the parent is
in stdout mode (so worker stdout flows through to docker logs). The
per-run log at <scratch>/runtime/server.log stays a file regardless --
it is read back by the run UI.
A CLI-side ServerLogSink::{File(PathBuf),Stdout} replaces Option<PathBuf>
so the file/stdout intent is explicit at the type level for both the
Server and Worker sinks. LogDestination gains strum::IntoStaticStr so
the parent can stringify it for the worker env without a hand-written map.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>