Share ACTIVE_STAGE_STATES/SUCCEEDED_STAGE_STATES across stage-sidebar and
run-overview, collapse the nested match in active_stage_state_from_events,
and drop a few WHAT-comments that narrated the recent rename.
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.
Extract Panel, Row, ViewToggle, and value renderers into a shared module
so the run settings page can adopt the same paneled layout and Settings/
JSON toggle as the server settings page. The run page groups its frozen
snapshot into Workflow, Sandbox, Git, and Artifacts panels and falls
back to raw JSON for everything else.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
- classify_section now returns FileDiffChangeKind directly (unnecessary_wraps)
- collapse nested Some(...) or-pattern into single arm (unnested_or_patterns)
- replace .unwrap() with .expect() in append_completed_run_with_final_patch test helper (unwrap_used)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Return degraded run files with the same FileDiff[] shape as live responses, using nullable contents and per-file unified patches so the web sidebar and deep links work consistently.
Inline static credential-refresh failure tags instead of round-tripping
through a classifier whose substring matches always returned the
sentinel its callers prepended. Drop the dead `Error::Exec` accessors
in favor of pattern matching, and replace the redundant
`MetadataSnapshot::pushed` field with `push_error.is_none()`. Also fix
a regression in Docker `refresh_push_credentials` that was discarding
stderr and exit code on `set_url_nonzero` failures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add structured exec errors whose Display output keeps raw command output out of logs and notices while preserving stdout/stderr through explicit accessors. Stop Daytona from logging raw command strings and propagate git_push_ref errors so metadata push warnings include safe failure detail.
- Add `parent_or_dot()` helper to replace the repeated
`.parent().unwrap_or_else(|| Path::new("."))` idiom at three call sites.
- Add `From<ManifestPath> for PathBuf` and use it in
`BundleFileResolver::resolve` to drop a per-resolve `PathBuf` clone.
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.
Generate a fresh UUIDv4 per request, attach it to response headers,
JSON error bodies, and HTTP response logs so client-visible failures can be
matched to server logs without trusting inbound request id headers.
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>
When GitHub redirects back to /setup after installing the app, render a
distinct view that confirms the install and points users to retry the
run, instead of the first-time terminal setup instructions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Place a Settings | JSON toggle on the right of the description row. The
JSON view renders the full server settings object as syntax-highlighted
server-settings.json via the existing CollapsibleFile component.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reuse the existing @pierre/diffs Shiki highlighter and registered DOT
grammar (already used on the workflow definition page) so the Source
view renders workflow.fabro with proper highlighting instead of plain
monospace text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Toggling to Source unmounted the graph container, so switching back
mounted a fresh inner div without re-running the render effect — leaving
"Loading diagram..." stuck. Hide the graph via the hidden attribute
instead so the cached SVG and pan/zoom state survive view switches.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After a successful clone, both providers run "git remote set-url origin"
to embed an authenticated URL so the engine can push back. When that
command failed, the warning logged only exit_code, leaving subsequent
push failures with no usable trace.
- docker: log redacted stderr alongside exit_code (URL contains the
installation token, so reuse redact_auth_url).
- daytona: same, plus surface the previously-swallowed Err from
execute_command, and include the origin URL on embed_token_in_url
failures.
In all three branches, point the message at the consequence ("subsequent
git push will fail") so the warning isn't read as cosmetic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>