Commit graph

2582 commits

Author SHA1 Message Date
Bryan Helmkamp
acc92e5358 refactor(interview): simplify pending question handling
Collapse the live answer rendezvous into ControlInterviewer, move pending
question storage onto a shared typed record, and route HTTP and Slack answer
submission through one server-side flow.
2026-04-07 19:44:32 -04:00
Bryan Helmkamp
87bc42be70 refactor(interview): move run answers onto control channels
Persist pending interviews in run state, deliver accepted answers to workers
through the server-owned control path, and remove the old scratch-file and
WebInterviewer transports.

This also moves Slack onto the canonical server answer flow, adds richer
question metadata to the API and run events, and covers the subprocess
question lifecycle with end-to-end tests.
2026-04-07 19:23:36 -04:00
Bryan Helmkamp
a4cb75be31 refactor(store): unify run dump export sources
Share one store-dump export pipeline across the server-backed CLI path
and the local test helper, and add mixed blob-ref plus artifact coverage
for the exported output.
2026-04-07 18:28:28 -04:00
Bryan Helmkamp
225ae6d906 fix(store): make run export use server-backed blob reads
Route `fabro store dump` through the server client for run state, events,
blob hydration, and artifact downloads instead of reopening storage directly
from the CLI process. This fixes blob-backed checkpoint exports and restores
store-dump coverage under the in-memory test server.
2026-04-07 18:16:29 -04:00
Bryan Helmkamp
87279d830c fix(clippy): restore workspace lint cleanups after main merge
Reapply the lint-safe changes that were partially displaced while merging
origin/main, including the billing serialization assertion and the attach
replay/server annotation cleanups. This keeps the merged main branch back to a
clean full-workspace clippy pass before the store-dump debugging continues.
2026-04-07 18:01:53 -04:00
Bryan Helmkamp
58860e5ded Merge remote-tracking branch 'origin/main'
Resolve the artifact lifecycle merge by keeping object-backed upload and sandbox sync behavior alongside durable blob-ref normalization.
2026-04-07 17:52:07 -04:00
Bryan Helmkamp
41c4760cf2 fix(artifacts): harden object-backed upload rollout
Tighten the worker upload path so object-backed runs only fail when an
artifact upload is actually attempted without a token, and update CLI
snapshots for the new artifact storage metadata.

Fold in the workspace test and clippy fixes needed to verify the final
artifact upload implementation cleanly across Rust and web targets.
2026-04-07 17:45:49 -04:00
Bryan Helmkamp
4f88a11daf feat(workflow): persist offloaded context as global blob refs
Store large context payloads in the global CAS and keep durable
checkpoint state as blob://sha256 refs instead of execution-local file
paths. Resolve and materialize blob refs at execution, output, and export
time so resumed and remote runs can read legacy and new artifacts
consistently.
2026-04-07 17:18:28 -04:00
Bryan Helmkamp
494a7fe1cc feat(artifacts): finish object-backed artifact uploads
Add scoped worker upload tokens and HTTP artifact upload clients.

Support manifest-first multipart stage artifact uploads with validation and checksums.

Gate artifact reads by run capability while preserving legacy scratch fallback.
2026-04-07 16:56:37 -04:00
Bryan Helmkamp
2c643e6684 fix(run): terminate active workers on force removal
Active runs deleted through rm --force were removed from server state
without signalling the worker process, which could leave detached
workers orphaned after test cleanup. Terminate the tracked worker
process group before deleting run state and cover it with an
integration regression.
2026-04-07 16:04:26 -04:00
Bryan Helmkamp
e9431657f0 fix(server): update aggregate billing test 2026-04-07 15:35:29 -04:00
Bryan Helmkamp
d65a4c5f1a Merge remote-tracking branch 'origin/main'
# Conflicts:
#	apps/fabro-web/app/routes/run-overview.tsx
#	apps/fabro-web/app/routes/workflow-detail.tsx
#	apps/fabro-web/app/routes/workflows.tsx
#	lib/crates/fabro-workflow/src/lifecycle/artifact.rs
#	lib/crates/fabro-workflow/src/pipeline/finalize.rs
2026-04-07 15:24:07 -04:00
Bryan Helmkamp
537e9d52c7 Merge remote-tracking branch 'origin/main' into codex/fix-attach-terminal-authoritative-stream
# Conflicts:
#	lib/crates/fabro-cli/src/server_client.rs
2026-04-07 15:04:32 -04:00
Bryan Helmkamp
6ca2833e77 refactor(billing): unify the LLM billing domain
Replace the overlapping usage and cost model with canonical billing
primitives centered on ModelRef, ModelHandle, TokenCounts, and
BilledModelUsage. This also renames the public API and web surface from
usage to billing, removes compatibility aliases, and normalizes provider
usage adapters onto the shared billing vocabulary.
2026-04-07 14:33:35 -04:00
Bryan Helmkamp
3b5bb33d73 refactor(run): remove worker-side SlateDB access
Move detached workers onto an HTTP-backed runtime store so the server
remains the only SlateDB owner. This replaces the worker's seeded local
RunDatabase with a canonical server-backed handle for state, events, and
blobs, and updates workflow runtime plumbing to use that abstraction.
2026-04-07 14:33:33 -04:00
Bryan Helmkamp
0eca7d94d6 fix(run): make attach stream terminal-authoritative
Replay persisted run events for attach requests, keep the SSE stream live
only while the run is active, and close on terminal run events instead of
returning 410 for completed runs.

The CLI now treats premature attach EOF as an error, and the affected
integration tests were stabilized around store-backed event ordering and
recovered rewind timelines.
2026-04-07 14:32:23 -04:00
Bryan Helmkamp
0a2fd4b0dc Merge remote-tracking branch 'origin/main' 2026-04-07 13:00:13 -04:00
Bryan Helmkamp
9a5c2406cc feat(run): record run creation provenance
Persist server, client, and subject provenance on run creation so
run state and inspect output can show which Fabro version created a
run, which first-party client submitted it, and how the request was
authenticated.
2026-04-07 12:59:25 -04:00
Bryan Helmkamp
d919fbaadb fmt 2026-04-07 12:59:16 -04:00
Bryan Helmkamp
ca616820ec refactor(cli): stream run attach over SSE
Replace the attach polling loop with the existing run attach SSE endpoint.
Seed from stored history once, fetch interview questions only when needed,
and keep completed-run replay behavior intact.
2026-04-07 12:58:37 -04:00
Bryan Helmkamp
f552646b4f Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/tests/it/cmd/support.rs
2026-04-07 11:44:13 -04:00
Bryan Helmkamp
8a6446addb perf(nextest): keep shared test server state in memory
Default test daemons now opt into an in-memory object store and test
helpers carry explicit run ids instead of rediscovering runs from
shared state.

This also disables the disk-backed store dump integration tests until
store dump is routed through the server's live store handles.
2026-04-07 11:39:40 -04:00
Bryan Helmkamp
0cf80cdcfb refactor(store): share run projection with cli
Make fabro-store::RunProjection the single projection type used by the
server, CLI, and CLI test helpers. This removes the duplicated CLI-side
mirrors and adds serde coverage for the store-owned projection.
2026-04-07 11:36:22 -04:00
Bryan Helmkamp
a2672aef46 refactor(cli): centralize HTTP client builder with User-Agent header
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:31:07 -04:00
Bryan Helmkamp
473fa48f46 Merge remote-tracking branch 'origin/main' 2026-04-07 10:29:36 -04:00
Bryan Helmkamp
d19e724c2c fix(run): propagate worker cancellation into command stages
Pass a real cancel signal from __run-worker through the workflow engine
into sandbox command execution so cancelled runs reap gated shell loops
instead of leaking slow.gate waiters.
2026-04-07 10:09:30 -04:00
Bryan Helmkamp
36cdc92ae5 fix(nextest): let shared test server reap run workers
Give the harness longer to stop the shared test server than the server
itself uses to shut down active run workers. This prevents session cleanup
from SIGKILLing the server before it can terminate worker process groups,
which was leaving orphaned `fabro <run> running` subprocesses behind.
2026-04-07 09:52:12 -04:00
Bryan Helmkamp
330b7ef5e8 test(nextest): share one session server by default
Eagerly start one shared test server per nextest session and point default
TestContext commands at that session socket instead of leaking per-test
daemons keyed by FABRO_STORAGE_DIR. Add isolated_server() for tests that
need an explicit separate daemon, and tighten the ps filtering test so it
still proves the contract without timing out under full-suite load.
2026-04-07 09:44:34 -04:00
Bryan Helmkamp
e2a2696141 chore: remove workflows and steer endpoints
Remove GET /workflows, GET /workflows/{name}, GET /workflows/{name}/runs,
and POST /runs/{id}/steer from the OpenAPI spec, server routes, demo
fixtures, pagination tests, docs navigation, and generated TS client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:25:54 -04:00
Bryan Helmkamp
ba02af2f88 feat(run): harden server-supervised worker lifecycle
Move subprocess workers fully behind the server-owned run store by
switching worker/server coordination to HTTP-backed run events and
control state. Reconcile stale in-flight runs on boot, terminate live
workers during shutdown, and update process titles to reflect server and
worker lifecycle phases.
2026-04-07 07:59:35 -04:00
Bryan Helmkamp
625b05dd78 feat(logging): add daily log rotation and 7-day cleanup
Logs were growing unbounded — cli.log and server.log used
rolling::never() with no rotation. Switch to daily rotation via
tracing-appender builder API (prefix.YYYY-MM-DD.log) and clean up
files older than 7 days on startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 19:08:26 -04:00
Bryan Helmkamp
17e59992d5 chore: remove unused verification, retros, and sessions endpoints
These endpoints had zero CLI callers and served only the web UI demo.
Verification and retros were `not_implemented` stubs in real mode;
sessions had an in-memory implementation but no CLI usage. Removing
them shrinks the API surface and eliminates ~9,000 lines of dead code.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 17:52:51 -04:00
Bryan Helmkamp
c9c9cd01bd chore: remove skill install command and GET /runs/{id}/verification endpoint
Dead feature cleanup: `skill install` was hidden/experimental and never
graduated; the run verification endpoint was only implemented in demo mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 16:38:03 -04:00
Bryan Helmkamp
5abf775cf5 fix(logging): use stable server log paths 2026-04-06 16:18:13 -04:00
Bryan Helmkamp
38a2306e2e feat(system): add server-backed system commands 2026-04-06 16:10:06 -04:00
Bryan Helmkamp
c75349aa12 Merge remote-tracking branch 'origin/main' 2026-04-06 15:25:43 -04:00
Bryan Helmkamp
83eabb5afe fix(storage): use Storage/RunScratch accessors instead of raw path joins
Four callsites were bypassing existing Storage/RunScratch methods:

1. install.rs — .join("secrets.json") → Storage::secrets_path()
2. initialize.rs — .join("worktree") → RunScratch::worktree_dir()
3. git.rs — .join("final.patch") → RunScratch::final_patch()
4. create.rs — duplicated date-format logic → RunScratch::for_run()

Adds RunScratch::for_run(scratch_dir, run_id) to centralize the
date-prefixed directory name, used by both Storage::run_scratch()
and make_run_dir().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 15:12:19 -04:00
Bryan Helmkamp
e9aecf9a17 fix(testing): stabilize artifact fixture under load
Increase the artifact scenario timeout so the retry fixture still forces one timeout without spuriously creating a third retry under full-workspace nextest load. Also import the generated ServerSettings type directly so workspace clippy stays clean.
2026-04-06 14:09:32 -04:00
Bryan Helmkamp
72c5c30c11 refactor(home): remove dead settings path fallbacks
default_settings_path() and active_settings_path() always return a
value (Home::from_env() never fails), so unwrap_or_else fallbacks to
".fabro/settings.toml" were dead code. Change both functions to return
PathBuf instead of Option<PathBuf> and remove the unreachable branches
in server_client, serve, and user config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:59:17 -04:00
Bryan Helmkamp
80561f1e07 chore(api-client): regenerate settings client models 2026-04-06 13:46:57 -04:00
Bryan Helmkamp
fa6a41f995 fix(home): migrate all runtime consumers to use Home
Replaces every dirs::home_dir().join(".fabro") in production code with
Home::from_env() accessors, so FABRO_HOME is respected everywhere:

- fabro-config: project workflows dir, legacy .env path
- fabro-cli: logging dir, install root + cert defaults, upgrade check
  state, workflow list, doctor/install/login legacy_env callers
- fabro-telemetry: tmp dir for spawn, anonymous ID file
- fabro-workflow: file resolver fallback in source resolution
- fabro-agent: skill discovery (session + default_skill_dirs API)

Remaining dirs::home_dir() calls are legitimate: tilde expansion,
display path shortening, non-.fabro paths (e.g. ~/.claude/skills).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:36:43 -04:00
Bryan Helmkamp
e862581fc8 refactor(settings): make settings command server-backed
Default `fabro settings` now resolves effective runtime settings against the
selected server, while `--local` preserves local-only inspection. This also
extracts shared settings resolution logic so CLI output, manifest preparation,
and the `/api/v1/settings` contract stay aligned.
2026-04-06 13:34:28 -04:00
Bryan Helmkamp
5fe4a2e7d3 refactor(home): move Home to fabro-util so all crates can share it
Home lived in fabro-config, which meant fabro-types (a dependency of
fabro-config) could not use it — forcing Settings::storage_dir() to
duplicate the FABRO_HOME / dirs::home_dir() fallback logic. Moving Home
to the leaf crate fabro-util breaks this layering constraint and lets
Settings::storage_dir() delegate to Home::from_env().storage_dir().

Also adds stable accessors: storage_dir, socket_path, workflows_dir,
logs_dir, tmp_dir. fabro-config re-exports Home for API compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-06 13:08:35 -04:00
Bryan Helmkamp
c4b476d660 fix(storage): align workflow scratch defaults with settings
Full workspace verification exposed one real mismatch after the socket and
storage split: workflow default scratch lookup still derived from ~/.fabro
instead of the new storage root. Keep the helper aligned with Settings defaults
and fold in the small clippy-driven cleanups in the related server path code.
2026-04-06 12:21:54 -04:00
Bryan Helmkamp
23231eb1ae refactor(cli): separate local socket and storage defaults
Keep local server targeting based on explicit server targets instead of
implicitly deriving a socket from storage_dir. This makes ~/.fabro/fabro.sock
the default local socket again, keeps storage under ~/.fabro/storage, threads
FABRO_CONFIG through server autostart paths, and updates the CLI test harness
for the new split.
2026-04-06 11:57:14 -04:00
Bryan Helmkamp
fe8fa627a0 fix(storage): satisfy clippy in home and artifact paths 2026-04-06 10:31:08 -04:00
Bryan Helmkamp
bd8f0fe5ee refactor(storage): unify scratch paths and key schema
- centralize FABRO_HOME and storage path resolution in fabro-config
- rename store types, extract ArtifactStore, and simplify run key layout
- switch run scratch to scratch/, remove RuntimeState, and refresh docs/clients
2026-04-06 10:13:37 -04:00
Bryan Helmkamp
9c61608d96 refactor(cli): make run-adjacent commands server-only 2026-04-06 06:12:16 -04:00
Bryan Helmkamp
6d94f93e44 refactor(config): unify machine config as settings.toml
Consolidate CLI and server machine defaults under settings.toml,
including loader renames, writer preservation fixes, same-machine
manifest handling, and docs/test updates for the new config model.
2026-04-05 23:55:28 -04:00
Bryan Helmkamp
f9f7f0baea refactor(cli): make core run lifecycle server-only 2026-04-05 21:57:27 -04:00