Commit graph

844 commits

Author SHA1 Message Date
Bryan Helmkamp
3eabc013d1 test(migration): land final Stage 4 fixes — 100% workspace tests green
Close out consumer migration with targeted behavior fixes and the
remaining integration-test fixture rewrites. The full workspace
nextest run now reports 3,760 passed / 0 failed / 182 skipped.

Runtime fixes:
- effective_settings::apply_server_defaults now propagates the full
  server-side Settings shape (llm, sandbox, setup, checkpoint,
  pull_request, artifacts, hooks, mcp_servers, github, slack, fabro)
  into the resolved CLI settings, matching the pre-Stage-3 'merge
  everything server' behavior for RemoteServer/LocalDaemon modes
- fabro-cli commands/run/overrides: route --verbose through
  cli.output.verbosity = verbose instead of a run.metadata stash,
  so it resolves to settings.verbose via the bridge
- fabro-server run_manifest manifest_args_layer: same — emit a
  CliLayer with cli.output.verbosity rather than stuffing the flag
  into run.metadata
- fabro-test settings_storage_dir: detect the managed marker and
  return None instead of parsing the injected server.storage.root,
  so isolated_server correctly spins up a new storage dir
- fabro-server run_manifest_local_daemon test now passes with full
  server-side settings snapshot propagation

Test fixture + assertion updates:
- cmd::config::settings_local_explicit_workflow_path_uses_workflow_project_layers:
  assertion updated for v2 R30 whole-list replacement of
  run.prepare.steps across layers (only workflow-setup survives)
- cmd::config::create_explicit_workflow_path_uses_project_config_relative_to_workflow:
  same correction for the persisted run.settings.setup.commands
- cmd::attach::attach_json_errors_without_prompting_for_human_input
  and cmd::run::json_run_implies_auto_approve_for_human_gates: strip
  the bridge-emitted settings.server and settings.version fields from
  the JSON snapshot so the randomised unix-socket path does not flap
  the insta snapshot
- cmd::server_start::concurrent_autostart_converges_on_one_shared_daemon_and_cleans_up:
  rewrite the injected settings.toml to v2 shape with
  [server.storage] root and [cli.target] type = unix path
- scenario::smoke::attach_smoke_covers_arg_validation_and_remote_server_behaviors:
  two [server] target fixtures rewritten to [cli.target]
  type = http url

Accepted insta snapshots for attach and run JSON outputs. Workspace
build + clippy both clean under -D warnings.
2026-04-09 11:07:18 -04:00
Bryan Helmkamp
16204acf0d fix(effective_settings): keep cli/server stanzas from user settings.toml
LocalDaemon and RemoteServer modes were stripping owner-specific
domains (cli, server) from the user layer as well as from fabro.toml
and workflow.toml. Per the plan's trust boundary rule, owner-specific
domains should only be consumed from ~/.fabro/settings.toml, so the
user layer is the one place they MUST survive. Strip only the
workflow and project layers.
2026-04-09 10:19:18 -04:00
Bryan Helmkamp
d951d0bf82 fix(lint): clippy cleanup for Stage 3/4 consumer migration
- effective_settings server_defaults_layer: drop Result wrapper since
  the body never fails after the v2 switch
- merge.rs: allow needless_pass_by_value module-wide since every
  merge helper consumes both sides by design
- fabro-cli overrides.rs: replace &Option<String> sigs with
  Option<&str>, collapse Default-plus-assignment into struct literal
  (avoid clippy::field_reassign_with_default), and box the metadata
  HashMap inline
- fabro-cli manifest_builder.rs: pull DaytonaDockerfileLayer into
  scope so the pattern match stays absolute-path-clean
- fabro-cli main.rs + commands/config/mod.rs: Box::pin the settings
  subcommand future so clippy::large_futures stays happy
2026-04-09 10:16:47 -04:00
Bryan Helmkamp
783e544308 test(cli): migrate remaining config/exec/create fixtures to v2
Update remaining legacy-shape TOML fixtures in fabro-cli integration
tests to the v2 schema and adjust assertions for v2 merge semantics:

- settings_legacy_cli_config_warns_and_ignores_it: verbose → cli.output.verbosity
- settings_user_config_wins_over_legacy_cli_config: [llm]/[vars] → [run.model]/[run.inputs]
- settings_uses_fabro_home_for_home_config_resolution: same
- settings_fetches_server_settings_and_merges_with_local_config: [server] target → [cli.target]
- settings_cli_server_target_overrides_configured_server_target: same
- exec fixtures across exec.rs: [exec] → [cli.exec.*] + [cli.output], [server] → [cli.target]
- server target fixtures across model/ps/create/rm/run: [server] target → [cli.target]
- settings_local_workflow_name_applies_run_overlay_and_deep_merges:
  assertions updated for v2 R22 (run.inputs replaces), hooks replaced
  by id, checkpoint.exclude_globs replaces, sandbox.env and
  daytona.labels stay sticky merge-by-key per R71
2026-04-09 10:11:28 -04:00
Bryan Helmkamp
5dab0f4c0b fix(bridge): use hook command shorthand to avoid duplicate serde key
The old HookDefinition struct has HookType flattened via
#[serde(flatten)], so emitting hook_type = Some(HookType::Command {...})
produces an inner 'command' key at the same level as the outer
HookDefinition.command shorthand field. Round-tripping through YAML
then fails with 'duplicate field command'.

Bridge script/command hooks via the HookDefinition.command shorthand
instead, leaving hook_type = None. Also: sandbox FABRO_CONFIG in the
manifest_builder unit test so it doesn't pick up the developer's real
~/.fabro/settings.toml, and update settings_local_merges_cli_and_project_defaults
to reflect v2 R22 semantics: run.inputs replaces wholesale across
layers rather than merging by key, while daytona.labels stays a sticky
merge-by-key map per R71.
2026-04-09 10:06:16 -04:00
Bryan Helmkamp
4a48305fd2 feat(tests): migrate fabro-cli fixtures and repo fabro.toml to v2
Stage 4 consumer migration: rewrite test fixtures across fabro-cli
integration tests and the repo's own fabro.toml + workflow.toml files
to use the v2 namespaced schema.

Fixtures migrated:
- repo fabro.toml: [fabro] root → [project] directory, [pull_request]
  → [run.pull_request], [sandbox] → [run.sandbox], daytona labels
  and snapshot moved under [run.sandbox.daytona], [[hooks]] →
  [[run.hooks]] with id, integer memory/disk → '8GB'/'20GB' Size
  values
- fabro/workflows/{implement-issue,implement-plan,gh-triage,smoke}/
  workflow.toml: version → _version, [github] →
  [server.integrations.github]
- fabro-cli integration tests: config.rs (settings/external fixtures),
  repo.rs, repo_init.rs, runner.rs, run.rs, store_dump.rs,
  workflow.rs, workflow_create.rs, support.rs
- fabro-server run_manifest.rs: prepare_manifest test constructs v2
  manifest configs (run.prepare.steps + server.integrations.github)
  and updated assertion to reflect v2 whole-list replacement of
  run.prepare.steps across layers

Validate command tests all green; ~10 tests remain that need targeted
fixes for specific behaviors that shifted between schemas.
2026-04-09 09:57:30 -04:00
Bryan Helmkamp
eb077ed3a2 feat(config): switch parser and layering to v2 schema
Stage 3 of the settings TOML redesign. Switches the core parse/merge/
resolve path to the v2 namespaced schema while keeping the legacy flat
Settings shape accessible via the bridge for not-yet-migrated consumers.

Parser and layering:
- ConfigLayer is now a newtype around v2 SettingsFile. Loading via
  ConfigLayer::parse/load/settings/for_workflow/project now hard-fails
  on legacy top-level keys (version, llm, vars, sandbox, etc.) with
  targeted rename hints emitted by fabro_types::settings::v2::tree
- new fabro_config::merge module encodes the merge matrix directly:
  replace-by-default maps, sticky merge for run.sandbox.env and
  provider-native labels, splice-aware string arrays for
  run.model.fallbacks and notification route events, whole-list
  replacement for run.prepare.steps, field-merge keyed objects for
  notifications/MCPs/web-auth providers, and ordered hook id-aware
  replacement
- ConfigLayer::resolve delegates to fabro_types::settings::v2::bridge
  so consumers keep reading through the legacy Settings shape until
  Stage 4 migrates them off it
- effective_settings::resolve_settings now treats project/workflow/
  run/features as shared layered domains and strips cli/server from
  non-local layers before merging, fulfilling the owner-first trust
  boundary rule

Consumer migration (Stage 4 preview, kept to the files that block
the workspace build):
- fabro-server run_manifest builds v2 RunLayer from ManifestArgs and
  resolves manifest dockerfile references through the v2 sandbox
  daytona snapshot tree
- fabro-cli manifest_builder consults run.goal via v2; user_config
  writes the v2 server.storage.root field under the CLI storage-dir
  override; run/overrides constructs a v2 RunLayer from RunArgs
- fabro-cli scaffolds (repo init, workflow create) emit _version = 1
  with project.directory/workflow.graph/run.sandbox etc.

fabro-config / fabro-types legacy parse-time types (ProjectConfig,
LlmConfig, SandboxConfig, PullRequestConfig, ExecConfig, SettingsFile
try_into, etc.) are deleted from the parse path; the resolved type
re-exports (LlmSettings, SandboxSettings, etc.) remain as shims so
unmigrated consumers keep compiling.

fabro-test helper: settings.toml fixtures now use _version = 1 plus
[server.storage] root and [cli.target] type = "unix" path. Legacy
flat storage_dir/server.target handling removed from the sync path.

Known Stage 4/5 follow-ups:
- fabro-cli integration test fixtures still use legacy-shape TOML
  (version = 1, [llm], [sandbox], [vars], [exec], [fabro], etc.);
  tests currently fail to parse against the v2 schema as intended.
  Migrating them is the bulk of Stage 4 and lands in subsequent
  commits.
- OpenAPI ServerSettings schema, generated clients, apps/fabro-web
  workflowData fallback, and docs/reference examples are unchanged
  and land in Stage 5.
2026-04-09 09:49:23 -04:00
Bryan Helmkamp
91b36e7006 feat(types): flesh out v2 subtrees and add legacy bridge
Stage 2 of the settings TOML redesign. Completes the v2 resolved
settings tree and adds a temporary internal bridge so callers can
migrate incrementally during stages 3 and 4.

- run subtree: model (with splice-aware fallbacks), git author,
  prepare steps (script xor command), execution (mode, approval,
  retros as positive-form), checkpoint, sandbox (with local/daytona
  provider leaves and sticky env), notifications (keyed routes with
  slack/discord/teams subtables), interviews (provider + subtables),
  agent (permissions + mcps map), hooks (id-aware ordered list), scm
  (with github leaf), pull_request, artifacts
- cli subtree: target (http/unix), auth (strategy), exec (model,
  agent, prevent_idle_sleep), output (format, verbosity), updates,
  logging
- server subtree: listen (tcp/unix with tls), api, web, auth (api
  jwt/mtls, web providers), storage, artifacts (local/s3 provider
  leaves), slatedb (local/s3 provider leaves), scheduler, logging,
  integrations (github/slack/discord/teams)
- closed ObjectStoreProvider enum so unknown providers hard-fail
  schema validation
- provider-specific subtables use enumerated known providers rather
  than flatten+HashMap so strict deny_unknown_fields still holds
- bridge module (settings::v2::bridge) with bridge_to_old() mapping
  the v2 resolved tree back to the legacy flat Settings shape for
  fields that current consumers read. Env interpolation emits raw
  source form; resolution is a Stage 3 concern
- representative_full_tree_parses integration test exercises the
  canonical example from the brainstorm document end-to-end
- 140 tests passing; workspace clippy-clean under -D warnings
2026-04-09 09:17:37 -04:00
Bryan Helmkamp
ab9a2d9418 feat(types): add settings v2 parse tree scaffolding
Stage 1 of the settings TOML redesign. Introduces the namespaced v2
schema module alongside the existing flat Settings shape so the
workspace still builds while the new parser architecture comes online.

- value-language helpers with full unit-test coverage:
  - Duration: single-unit suffixes (ms, s, m, h, d); rejects composed
    values like '1h30m'; canonical renderer picks the largest unit
  - Size: decimal (KB, MB, GB, TB) and binary (KiB, MiB, GiB, TiB)
    units; bare integers default to GB; canonical renderer picks the
    largest decimal unit
  - ModelRef: bare vs qualified forms with a ModelRegistry trait for
    later ambiguity resolution
  - InterpString: ${env.NAME} tokens with whole-value, substring, and
    multi-token support; provenance tagging for outward-facing redaction
  - SpliceArray: '...' marker with append, prepend, and single-marker
    enforcement
- SchemaVersion pre-validation: missing defaults to 1, legacy 'version'
  key hard-fails with a rename hint, unsupported higher versions
  hard-fail with an upgrade hint
- SettingsFile top-level sparse parse tree with strict unknown-key
  rejection and targeted rename hints for every legacy top-level
  section (llm, vars, exec, fabro, setup, sandbox, etc.)
- Skeleton ProjectLayer/WorkflowLayer/RunLayer/CliLayer/ServerLayer/
  FeaturesLayer with deny_unknown_fields; full subtree fleshed out in
  Stage 2

65 new unit tests all passing. fabro-types is clippy-clean under
-D warnings.
2026-04-09 09:02:45 -04:00
Bryan Helmkamp
fa3507d8c7 feat(artifacts): remove scratch artifact cache staging
Stage captured artifacts in per-attempt tempdirs and persist them through an
explicit artifact sink instead of writing into run scratch cache.

Server-managed and test-owned runs now write directly to ArtifactStore, while
CLI worker runs keep the staged upload path. The local run summary now prints
durable artifact identifiers and copy hints rather than scratch-cache paths,
and the run-directory docs and integration coverage were updated to match.
2026-04-08 17:42:55 -04:00
Bryan Helmkamp
2fd5411f8f fix(test): remove dist/ dependency from source_maps_are_not_served test
Use a synthetic .map path instead of scanning apps/fabro-web/dist at
runtime, which requires a prior bun build and breaks on fresh checkouts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:51:23 -04:00
Bryan Helmkamp
56228ea07e test(cli): add integration tests for fabro uninstall
7 IT tests in cmd/uninstall.rs covering:
- help snapshot
- not-installed detection (plain + JSON)
- dry-run preview without deleting
- --yes removes ~/.fabro/
- --json inventory output (dry-run + execute)

Also fixes the "not installed" check to use marker files
(settings.toml, certs/, storage/) instead of directory existence,
since the CLI's logging startup may auto-create the directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:47:48 -04:00
Bryan Helmkamp
ed70aa6dda fix(test): remove workspace test build warnings
Drop the unused test-only import in fabro-server and the unused test
binding in fabro-workflow so workspace test builds stay warning-free.
2026-04-08 16:47:23 -04:00
Bryan Helmkamp
ad4c5f0c98 fix(cli): restore fabro-cli verification after merge
Resolve new clippy failures introduced by the merge and update the root
help snapshot to include the uninstall command so fabro-cli lint and
test verification return to green.
2026-04-08 16:41:13 -04:00
Bryan Helmkamp
f0d57dacc9 Merge remote-tracking branch 'origin/main' 2026-04-08 16:32:44 -04:00
Bryan Helmkamp
166b60e3b1 feat(cli): add fabro uninstall command
Adds a top-level `fabro uninstall` command that reverses `fabro install`
and `install.sh`. Defaults to dry-run (preview) mode, requiring `--yes`
to execute.

Features:
- Inventory and dry-run preview with sizes and `--json` support
- Server shutdown (guarded — only when server is running)
- Safety guardrails (refuses to delete /, $HOME, or dirs without markers)
- Shell config cleanup (exact `# fabro` sentinel match, PATH validation,
  atomic write via temp+rename)
- Binary status reporting with tailored brew/cargo/manual hints
- Exit code: 0 on success, 1 on critical failure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:31:32 -04:00
Bryan Helmkamp
30e63b270f Merge remote-tracking branch 'origin/main' 2026-04-08 16:30:26 -04:00
Bryan Helmkamp
367fd9302b refactor(cli): centralize command settings and server access
Add CommandContext to load machine settings once per invocation, cache
server access, and route migrated commands through the shared
ServerStoreClient path instead of reloading settings and reconnecting ad
hoc.
2026-04-08 16:27:25 -04:00
Bryan Helmkamp
e098d8d4c0 refactor: remove negative scratch assertions and rename child dir to stages/
Remove test assertions that verified legacy files (final.patch,
workflow_bundle.json, manifest.json, cache/artifacts/values/) do not
exist in scratch directories — these are a test smell since the code
that wrote them is long gone.

Also rename child workflow scratch path from nodes/{id}_{visit}/child
to stages/{id}@{visit}/child to align with stage_id convention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:23:02 -04:00
Bryan Helmkamp
45675fc42d feat(server): make web ui optional
Add a server-side web.enabled toggle and CLI overrides so Fabro can run
with API and health only while disabling the embedded SPA, browser auth
routes, and web-only helper endpoints.
2026-04-08 16:22:41 -04:00
Bryan Helmkamp
150443123c Merge remote-tracking branch 'origin/main' into production-web-ui 2026-04-08 16:07:38 -04:00
Bryan Helmkamp
15d1c67be9 fix: resolve clippy warnings across workspace
- fabro-types: remove redundant "freeform" match arm (match_same_arms)
- fabro-server: use let...else and remove needless return
- fabro-cli/runner: use while-let instead of match loop, unwrap Option
  from build_artifact_uploader return type
- fabro-cli/attach: introduce AttachOptions struct to reduce bool
  parameter count (fn_params_excessive_bools)
- fabro-test: fix unused variable and needless continue in session lock

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:56:51 -04:00
Bryan Helmkamp
6b0419bc10 fix(test): eliminate session lock race and openssl /dev/stdin flake
Two flake sources identified across 100+ full-suite runs:

1. Session lock EINVAL race: cleanup_session_root's remove_dir_all
   could delete the session root between with_session_lock's
   create_dir_all and File::create, causing EINVAL. Fix: retry the
   create-dir + create-file sequence as a unit.

2. mTLS cert generation: openssl req -key /dev/stdin failed under fd
   pressure with "Bad file descriptor". Fix: read from the already-
   written server.key file path instead of piping through /dev/stdin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:48:51 -04:00
Bryan Helmkamp
abd87909ae feat(server): support host-only tcp binds
Accept `--bind <ip>` as a TCP bind request while keeping the default
Unix socket behavior unchanged. Resolve host-only TCP binds inside the
serving process so startup output, server metadata, and status always
reflect the concrete host:port, preferring 32276 and falling back to a
random port with a warning when needed.
2026-04-08 15:43:09 -04:00
Bryan Helmkamp
1a1c998dc9 fix(workflow): cancel devcontainer lifecycle commands on shutdown
Pass the run-scoped cancellation flag into devcontainer lifecycle
commands so startup shutdown interrupts those commands promptly and
preserves the cancelled workflow result. Add workflow regression tests
for cancelled setup and devcontainer startup paths.
2026-04-08 15:06:11 -04:00
Bryan Helmkamp
bbd04111ad fix(workflow): cancel setup commands during startup shutdown
Reuse the existing sandbox cancellation bridge for workflow setup
commands so server-side startup cancellation interrupts setup work
promptly and preserves the cancelled terminal state under nextest.
2026-04-08 14:58:32 -04:00
Bryan Helmkamp
f7d86d72e2 Merge remote-tracking branch 'origin/main' into production-web-ui 2026-04-08 14:44:35 -04:00
Bryan Helmkamp
8726065fd1 feat: embed fabro spa and align interruption semantics
Move the built web bundle into an embedded fabro-spa crate so Cargo and
release builds no longer depend on Bun at build time, and preserve the
local dev override path for fast UI iteration.

At the same time, rename interview and agent-level aborted flows to
interrupted, keep cancelled for run-level shutdown, and stop reporting
skipped answers as interruptions in the run event stream.
2026-04-08 14:43:44 -04:00
Bryan Helmkamp
a0e4c648c7 fix(test): reduce test server stop timeout from 8s to 500ms
The test harness waited 8s for the server to shut down gracefully,
accommodating the server's 5s WORKER_CANCEL_GRACE. But in tests,
the CLI returns before workers exit (terminal SSE event → CLI exits →
TestContext drops → SIGTERM while workers still cleaning up), so the
last test in every session paid a ~5s penalty. No real work needs
preserving in tests, so SIGKILL after 500ms instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:29:00 -04:00
Bryan Helmkamp
2138e0cade fix(test): use no_proxy client in detach signal test to prevent macOS timeout flakes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:51:34 -04:00
Bryan Helmkamp
31d80373d4 fix: session cookie decryption and add HTTP endpoint logging
Cookie auth was broken because parse_cookie_header used Cookie::parse
which does not percent-decode values. The cookie crate's private jar
percent-encodes on Set-Cookie but Cookie::parse leaves %2F/%3D intact,
making base64 decryption fail silently. Switch to Cookie::parse_encoded.

Also:
- Add tower-http TraceLayer for request/response logging (DEBUG for
  requests, INFO for responses with status and latency)
- Add structured tracing to all web_auth handlers per logging strategy
- Replace eprintln debug calls with tracing::warn
- Update GitHub App manifest homepage URL to https://fabro.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 11:46:30 -04:00
Bryan Helmkamp
c33deedb34 fix(test): eliminate recovery, cancel, and label flakes
Stabilize the recovery scenario around rebuilt metadata timing and node
ordinals, make in-process run cancellation converge on a cancelled
reason, and keep the label assertion unit test out of the shared
TestContext session lifecycle.
2026-04-08 10:13:17 -04:00
Bryan Helmkamp
5e2d125cd0 fix: GitHub App setup flow — nullable webhook_secret, double POST, stale restart copy, wrong port
- Change webhook_secret to Option<String> in GitHubManifestConversion since
  GitHub's API returns null when no webhook URL is configured
- Use useRef guard to prevent React StrictMode from firing the one-time
  manifest conversion POST twice
- Remove fake "restart required" flow — server reads auth config lazily so
  no restart is needed after setup
- Derive web.url and api.base_url from the request Origin header instead of
  hardcoding port 3000
- Add error logging for manifest conversion parse failures

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:34:39 -04:00
Bryan Helmkamp
2392927e7b test fix 2026-04-08 07:55:32 -04:00
Bryan Helmkamp
da88a47595 feat: wire web UI to real server with demo mode toggle
Server changes:
- Add /boards/runs to demo routes (delegates to list_runs)
- Fix demo get_run_status to return StoreRunSummary shape matching OpenAPI spec
- Enrich real /boards/runs to return RunListItem shape with board column mapping
  (Running->working, Paused->pending, Completed->merge; others excluded)
- Update existing tests that asserted old RunStatusResponse fields from /boards/runs

Web UI changes:
- Add DemoModeProvider context and useDemoMode hook
- Hide Workflows/Insights nav items in production mode via getVisibleNavigation
- Change run-detail loader to use /runs/{id} directly instead of searching /boards/runs
- Add mapRunSummaryToRunItem for mapping server response to UI shape
- Add Graph tab, hide Stages tab in production mode, always hide Files tab
- Make run-overview and run-graph loaders resilient to 501 via apiJsonOrNull
- Add isNotImplemented and apiJsonOrNull helpers to api.ts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 04:46:08 -04:00
Bryan Helmkamp
18cb38dac7 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/src/server_client.rs
2026-04-08 03:53:54 -04:00
Bryan Helmkamp
33a5f2adb4 test(cli): replace slow active-run coverage
Replace the slow CLI integration tests that waited on worker shutdown
grace periods with focused coverage that still checks the important
behavior. The attach JSON test now finishes the gated run cleanly,
the rm force test uses a mocked server contract, and the Ctrl-C cancel
path is covered at the attach layer instead of through a full live run.

Add a cooperative subprocess cancel control message so cancel and delete
can abort pending interviews without relying only on the 5 second hard
kill fallback.
2026-04-08 03:47:35 -04:00
Bryan Helmkamp
f0738627c6 test(cli): move timeout-prone run coverage into ITs
Replace bin-scoped localhost HTTP tests with command-facing integration
coverage so they run under the intended IT timeout budget without
changing nextest overrides.
2026-04-08 03:40:48 -04:00
Bryan Helmkamp
8991614290 Merge remote-tracking branch 'origin/main' 2026-04-07 23:44:15 -04:00
Bryan Helmkamp
bcc697c235 fix(cli): follow paginated run events 2026-04-07 23:43:25 -04:00
Bryan Helmkamp
929a0fae81 fix(server): skip delete grace for terminal runs
Completed runs can briefly retain a stale worker PID after their terminal
state is visible. Using the full 5s worker cancellation grace in that window
made rm and prune pay an avoidable delay.

Keep the existing grace for active runs, but use a short delete grace for
already-terminal runs so completed-run cleanup stays fast.
2026-04-07 23:43:06 -04:00
Bryan Helmkamp
0a2d3e3c77 test(cli): narrow system prune coverage for speed 2026-04-07 23:42:15 -04:00
Bryan Helmkamp
b070647f91 test(checkpoint): restore RunRecord helper fields 2026-04-07 23:24:36 -04:00
Bryan Helmkamp
1c6928bfc0 Merge remote-tracking branch 'origin/main' 2026-04-07 23:16:15 -04:00
Bryan Helmkamp
4389049ac0 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-types/src/run_event/run.rs
2026-04-07 23:15:06 -04:00
Bryan Helmkamp
41c4439c5d Merge remote-tracking branch 'origin/main' 2026-04-07 23:13:56 -04:00
Bryan Helmkamp
e7479a4c65 refactor(artifacts): clean up stale artifact wording
Remove leftover object-backed terminology from the worker uploader,
rename the remaining scratch-fallback test to match current behavior,
and update the old artifact upload plan to reflect the current
no-fallback model.
2026-04-07 23:13:22 -04:00
Bryan Helmkamp
ccfae68bc6 test(cli): make server_start cleanup non-graceful 2026-04-07 23:13:11 -04:00
Bryan Helmkamp
75af94dc4f refactor(run): simplify CAS-backed run definitions
Drop compatibility versioning from run-definition blobs, remove the
read-after-write polling added around CAS access, and tighten tests to
assert workflow_bundle.json is never written.
2026-04-07 23:10:00 -04:00
Bryan Helmkamp
b03d04f771 fix(api): resolve build spec path at runtime 2026-04-07 23:05:07 -04:00