Commit graph

3024 commits

Author SHA1 Message Date
Fabro
54a7f635b5 fabro(01KQD54J8NA8NZ0KPTCE79389Y): greet (success)
Fabro-Run: 01KQD54J8NA8NZ0KPTCE79389Y
Fabro-Completed: 2
Fabro-Checkpoint: 5b4e1d8f86

⚒️ Generated with [Fabro](https://fabro.sh)
2026-04-29 17:39:16 +00:00
Bryan Helmkamp
a6a11cdd82
chore(run-files): fix pre-existing clippy lints
- 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>
2026-04-29 13:16:40 -04:00
Bryan Helmkamp
7feef1c6b2
Merge remote-tracking branch 'origin/main' 2026-04-29 13:01:43 -04:00
Bryan Helmkamp
6156f65799
fix(run-files): normalize degraded file diffs
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.
2026-04-29 13:00:55 -04:00
Bryan Helmkamp
ece80c750d
Merge pull request #176 from justinabrahms/fix/at-path-resolves-relative-to-workflow-file
fix: resolve @path references relative to workflow file, not CWD
2026-04-29 09:57:33 -07:00
Bryan Helmkamp
32166e4cdf
refactor(sandbox): simplify exec error helpers and metadata snapshot
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>
2026-04-29 12:52:30 -04:00
Bryan Helmkamp
cebdf8dee5
Merge remote-tracking branch 'origin/main' into pr-176
# Conflicts:
#	lib/crates/fabro-cli/src/manifest_builder.rs
#	lib/crates/fabro-server/src/run_manifest.rs
2026-04-29 12:45:33 -04:00
Bryan Helmkamp
067fa3ee82
fix(sandbox): make git push failures log-safe
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.
2026-04-29 12:40:50 -04:00
Bryan Helmkamp
91a0bdc3f4
refactor(manifest): tighten ManifestPath API
- 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>
2026-04-29 12:37:46 -04:00
Bryan Helmkamp
786e01c7a7
refactor(manifest): type bundle paths end-to-end
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.
2026-04-29 12:26:39 -04:00
Bryan Helmkamp
890fbb8fa4
feat(server): correlate API errors with request ids
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.
2026-04-29 12:20:56 -04:00
Bryan Helmkamp
dede93dceb
Merge remote-tracking branch 'origin/main' 2026-04-29 11:51:47 -04:00
Bryan Helmkamp
0719e321b1
chore(lint): satisfy workspace clippy 2026-04-29 11:48:22 -04:00
Bryan Helmkamp
eb4c1a9089
fix(server): persist terminal state for startup cancellation 2026-04-29 10:54:44 -04:00
Bryan Helmkamp
6cb185b858
feat(github): point install errors at the configured app and require creds for docker
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>
2026-04-29 10:43:00 -04:00
Bryan Helmkamp
7d7931e56a
feat(web): show GitHub App install return state on /setup
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>
2026-04-29 10:41:28 -04:00
Bryan Helmkamp
708f2999bd
chore(docker): set FABRO_LOG=debug in local compose
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:19:24 -04:00
Bryan Helmkamp
beff3985f0
ui(web): add Settings/JSON view toggle on settings page
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>
2026-04-29 09:12:40 -04:00
Bryan Helmkamp
81f73e8246
ui(web): syntax-highlight DOT source on run graph page
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>
2026-04-29 09:09:45 -04:00
Bryan Helmkamp
b36be97675
fix(web): keep graph mounted when toggling to source view
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>
2026-04-29 09:01:38 -04:00
Bryan Helmkamp
066cd9fa15
ui(web): right-align Graph/Source toggle on run graph page
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 09:00:42 -04:00
Bryan Helmkamp
d58c45fe80
fix(auth): clarify dev-token login recovery
Format the dev-token-only login failure as an action block and include the resolved --server value in the recovery command.
2026-04-29 08:20:21 -04:00
Bryan Helmkamp
843ef3c6a9
fix(sandbox): include stderr on origin-credential setup failures
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>
2026-04-29 08:14:56 -04:00
Bryan Helmkamp
fb17fe9ff1
fix(sandbox): include redacted git stderr in push-failure log
The previous "Failed to push git ref" warning logged only the exit code,
forcing manual reproduction in the sandbox to learn what GitHub said.
Include redacted stderr/stdout (entropy + gitleaks scrubbed via
fabro_redact::redact_string), the timed_out flag, and a short hint
keyed off well-known git/GitHub error phrases (missing credentials,
permission denied, ruleset rejection, repo-not-found, DNS failure).

Output is tail-trimmed to 2 KiB so a chatty git progress dump can't
flood the log line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 08:12:26 -04:00
Bryan Helmkamp
f40bcd1215
fix(server): forward GITHUB_APP_PRIVATE_KEY via worker_command
The previous commit added GITHUB_APP_PRIVATE_KEY to the worker env
allowlist, but the secret is in server.env / ServerSecrets, not in the
server's process env, so the allowlist couldn't see it.

Forward the value explicitly from ServerSecrets at spawn time, mirroring
how FABRO_WORKER_TOKEN is already passed. Keeps the allowlist narrow as
a fail-closed barrier against ambient env leakage and keeps ServerSecrets
as the single read site for server.env secrets.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 08:09:02 -04:00
Bryan Helmkamp
85c763d511
fix(cli): persist auth login target
When auth login succeeds and no CLI target is configured, write the resolved server target to settings.toml so later CLI commands can reuse it.
2026-04-29 08:02:50 -04:00
Bryan Helmkamp
90c4bd84c9
fix(server): forward GITHUB_APP_PRIVATE_KEY to worker subprocess
Add GITHUB_APP_PRIVATE_KEY to the worker env allowlist so the
__run-worker subprocess can mint installation tokens for git push.
Without it the worker resolves github_app=None and clone-based sandboxes
push without auth, which fails as exit-128 against any repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 07:56:43 -04:00
Bryan Helmkamp
9ad47990f4
fix(web): include server URL in auth quick start
Expose the configured server.web.url in system info so the empty runs quick start can show a runnable fabro auth login command instead of a placeholder.
2026-04-29 07:45:17 -04:00
fabro-releases[bot]
46bbac92eb Bump version to 0.218.0-nightly.0 2026-04-29 09:55:40 +00:00
Justin Abrahms
c93c52e131
style: fix rustfmt nightly formatting in test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-29 08:14:01 +02:00
Bryan Helmkamp
24b8f1ec04
fix(docs): use MDX comment syntax for generated fences
Mintlify parses pages as MDX and rejects HTML-style `<!-- ... -->`
comments, which broke the docs deployment on cli.mdx with a parse
error. Switch the generator fences (and the matching markers in the
two reference pages and the dev test fixtures) to `{/* ... */}` so
Mintlify can parse them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 01:27:43 -04:00
Bryan Helmkamp
f676fa779b
fix(ci): clean up clippy warnings and refresh CLI docs
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>
2026-04-29 01:03:16 -04:00
Bryan Helmkamp
788b389e4c
test(cli): prune slow integration outliers
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (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
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.
2026-04-28 19:26:27 -07:00
Bryan Helmkamp
4ce07aac17
test(cli): trim slow integration fixture 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.
2026-04-28 19:14:56 -07:00
Bryan Helmkamp
e3c7dbb88d
perf(workflow): batch metadata snapshots with fast-import
Replace per-file sandbox metadata git writes with one fast-import stream per metadata commit while preserving the push-after-each-commit contract. Cover binary files, quoted paths, parent linkage, and per-snapshot push behavior in the metadata writer regression test.
2026-04-28 15:41:06 -07:00
Bryan Helmkamp
4ca8962a02
fix(cli): keep validate off runtime preflight
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.
2026-04-28 14:50:04 -07:00
Bryan Helmkamp
2cbd3768b8
fix(cli): prevent manifest git push prompts
Disable terminal prompts for manifest pre-run push attempts and cover the behavior with an offline remote-helper regression test.
2026-04-28 14:36:27 -07:00
Bryan Helmkamp
8c3d3c340a
Merge remote-tracking branch 'origin/main' 2026-04-28 12:31:09 -07:00
Bryan Helmkamp
97cf146670
Merge remote-tracking branch 'origin/main' 2026-04-28 12:29:40 -07: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
7045a2d7a4
docs: commit plan 2026-04-28 09:46:52 -07:00
Bryan Helmkamp
a4d9979701
chore(build): reduce dev/test debug info to cut target churn
Set debug = "line-tables-only" and split-debuginfo = "off" for the dev
and test profiles. Keeps backtraces with file/line info but trims local
variable metadata and split-debug artifacts that drive APFS metadata
churn during cargo clean and incremental rebuilds on macOS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:42:28 -07:00
Bryan Helmkamp
e4152e5deb
docs: archive collapse-in-place-types plan
Following project convention to keep historical plans under docs/plans/.
2026-04-28 09:36:14 -07:00
Bryan Helmkamp
102b2340a3
docs: rename checkpoints_disabled to in_place in events doc
Aligns the run.created event description with the persisted field
rename (RunSpec.in_place / RunCreatedProps.in_place).
2026-04-28 09:34:40 -07:00
Bryan Helmkamp
20e161bc07
refactor: rename checkpoints_disabled -> in_place
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.
2026-04-28 09:33:59 -07:00
Bryan Helmkamp
9e079b6c0a
feat(test): add DuckDB diff query for bench-tests CSVs
Two queries: per-test p50/p90 regression ordered by largest median delta,
plus a per-package roll-up of total wall-time and quantile shifts. Filters
to passed tests so flakes don't skew medians. Run with `duckdb < test/
analysis/bench-tests-diff.sql` against two CSVs produced by `cargo dev
bench-tests`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:27:05 -07:00
Bryan Helmkamp
928b2f585b
refactor: drop WorkdirStrategy and RunOptions.checkpoints_disabled
WorkdirStrategy was structurally redundant with the existing
LocalSandboxLayer.worktree_mode config — Local sandboxes always picked
LocalWorktree, everything else picked Cloud, and the LocalDirectory arm
was only ever reachable via the parallel checkpoints_disabled bool.

resolve_worktree_plan now reads worktree_mode directly: Cloud sandboxes
return None with a pre_run_git base sha; Local + Never returns None
with no base sha; Local + non-Never builds the WorktreePlan as before.

RunOptions.checkpoints_disabled drops out: the lifecycle gate becomes
has_run_branch (git: None alone is the canonical "no git checkpoints"
signal), and tests/fixtures stop carrying the field.
2026-04-28 09:24:41 -07:00
Bryan Helmkamp
be9d9284be
feat(dev): add bench-tests command for capturing per-test timing CSV
Runs the workspace test suite N times via `cargo nextest run --no-fail-fast`
and appends one row per testcase to a CSV (git_sha, run_index, started_at,
binary, package, classname, test_name, status, duration_ms). Group ≈ package
is derived from the JUnit testsuite name.

The lenient `[profile.bench]` (with junit.path) is synthesized at runtime to
target/bench-tests/nextest-tool.toml and passed via `--tool-config-file`, so
nothing needs to be added to .config/nextest.toml.

Intended use: collect samples on the current checkout, switch SHAs, collect
again, then diff/aggregate externally to hunt slowdowns.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 09:18:00 -07:00
Bryan Helmkamp
3f027be220
refactor: route --in-place through worktree_mode override
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.
2026-04-28 08:44:54 -07:00
Bryan Helmkamp
01f5a06a80
Merge remote-tracking branch 'origin/main' 2026-04-28 08:24:05 -07:00