Remove validation that ran twice on the same inputs: clap already
enforces the flag co-occurrence rules, and the native Git layer no
longer re-checks selectors, branch names, refs, and commit SHAs that
selection parsing already validated. Remote selector shape rules now
delegate to the shared WorkflowPath validator.
Reuse fabro_proc for the process-group kill and liveness probe instead
of calling nix directly, dropping the extra nix features. Fold the
duplicated branch/tag candidate derivation into one RefCandidates type,
label each Git command explicitly instead of inferring it from argv,
hoist the duplicated workflow resolver call in create_run, and merge the
two directory target arms now that the default is just the caller path.
Share the run-argument parser and workflow/commit fixtures across the
unit tests through a test_support module, drop an integration test that
duplicated one cell of the cross-product test, and make the malformed
slug vectors assert the clap rejection they exercise.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
When `fabro run` or `fabro create` omits `--environment` and the server
has no environment named `default`, the CLI previously failed with only
"could not retrieve environment `default`". It now lists the server's
environment catalog in the error so the user can pass an explicit
`--environment <id>` or create the missing `default` entry. Explicit
`--environment` lookups keep their existing not-found message.
Adds `Client::list_environments` to fabro-client for the catalog read.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move the "which failures can happen before Starting" classification onto
FailureReason as an exhaustive predicate and use it for every
Runnable -> Failed transition, replacing the hand-maintained allowlist.
Give the pending-cancel precedence rule a single owner shared by the
worker launch and worker exit paths.
Test cleanups: share the Notify wait loop, server record fixture, and
post-failure assertions; simplify the pre-start test runtime's hold
flag; and parameterize the slate run.failed payload helper.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Use the shared clone-based provider predicate and rely on the settings
resolver dropping disabled pull-request settings instead of re-checking
the enabled flag. List the new intent-lane error code in the OpenAPI
description, trim the acceptance tests to what they actually prove, and
fold the docs note into the existing requirements sentence.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move ProjectedRun next to EventProjectionCache in run_state, since the
summary store both produces and consumes it, and give it a replay
constructor that owns the events-to-head derivation. load_projection now
returns RunNotFound directly instead of erasing it to None and having
callers rebuild it; load_run_projection is the single Option translation
point. install_in_memory_state reuses the existing From impl, and the
commit path passes its Arc through instead of unwrapping and
reallocating it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The supervisor's periodic recovery scan asked SQLite for every run that
had ever recorded an explicit pull request creation request and then
replayed each inactive candidate's full history to learn whether the
request was still pending. With projections now loaded on demand that
set grows without bound and was replayed every scan.
The candidate query now mirrors the projection reducer: a run is a
candidate only when its latest creation request has no later request,
created, linked, or unlinked event, and no later failure naming the same
creation id. Callers still replay each candidate to confirm, so the query
only has to avoid omitting a pending run, and the replayed set is bounded
by in-flight requests.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Drop the unreachable active-run mismatch guard that was copied into
load_run_projection: the active-runs map is only ever inserted under the
handle's own run ID, so the check could never fire. Remove it from the two
pre-existing sites too and delete matches_run.
Trim install_in_memory_state to take only the committed projection, since
the event envelope duplicated last_seq and the inner scope only existed to
release the lock before the now-removed shared cache update. Add a From
impl so RunDatabase::build no longer hand-builds EventProjectionCache, and
rename projected_state_locked to match its projection_snapshot sibling.
In fabro-server, have reject_if_archived and ensure_run_exists read the
run summary row instead of replaying the full event history for inactive
runs; the summary is written in the same transaction as the event.
Fold the repeated store-reopen fixtures in fabro-store and fabro-server
tests into helpers, and fix a stale comment about the deleted shared
projection cache.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Quality pass over the intent-producer changes, no behavior changes
intended:
- Move the TOML->JSON scalar conversion into fabro-types as
toml_scalar_to_json_value, next to its inverse, with typed errors and
round-trip tests; the CLI now calls the shared helper.
- Reuse goal_layer_from_args for --goal/--goal-file resolution instead
of a second copy of the exclusivity check and cwd anchoring.
- Delete the dead run_manifest_args helper and the test that kept it
compiling; preflight_manifest_args is the remaining real builder.
- Make run_target_for_environment a pure (provider, cwd) -> target
mapping using is_clone_based(), warning at the call site, and default
the environment id from DEFAULT_ENVIRONMENT_ID instead of a literal.
- Resolve the parent run and retrieve the environment concurrently.
- Drop the ResolvedCommandSettings pass-through struct and the
duplicated parse-error mapping in the project settings presence read.
- Share the environment/workflow-version/git test mocks from the cmd
test support module instead of three per-file copies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Load recovery candidates from the warm projection cache instead of
replaying each run's full event history, and check dispatch
eligibility before any I/O
- Extract the shared can_dispatch predicate used by both the recovery
scan and the worker dispatch loop
- Drop load_durable_run_status, now identical to durable_run_status
- Share parse_stored_run_id across the three stored-id decode sites
- Reuse push_order for the canonical run ordering in list_all and
list_by_statuses
- Replace the test-only queue clear accessor with the existing drain
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Drop the post-decode run_id/session_id/event-body checks in
find_session_owner: decode_event_row already verifies every stored
column against the decoded envelope, and the WHERE clause pins
session_id and event_name to the requested values.
- Build the lookup query from SELECT_EVENT_COLUMNS like the sibling
event queries instead of duplicating the column list.
- Carry the stored run_id text in the unparseable-id error instead of
an "<invalid>" placeholder.
- Fetch applied migration versions once per migrate() and share the
set between the session-owner preflight and the pre-migration
snapshot; check the applied version first so steady-state startups
skip the sqlite_master probe. Mark the preflight as removable with
the run-history compatibility window.
- Restore session_by_id_key as a #[cfg(test)] helper so tests stop
hand-rolling the legacy reverse-index key shape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Share canonicalize_location and resolve_existing_workflow_location
between the local package resolver and the version collector, drop the
redundant package-root pre-check and the PackageFileReadError enum in
favor of anyhow context, and read HEAD's SHA from git2 instead of a
separate rev-parse subprocess.
Make GitRunTargetObservation a plain struct, replace the repo-info
tuple with a named struct, tighten the closure view trait, avoid
deep-cloning the root workflow during collected validation, remove the
unused into_closure accessor, and dedupe test helpers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move the content-derived id check into create_workflow_version so every
caller gets it, drop the redundant expected_id parameter from
register_workflow_versions, and collapse the duplicated httpmock setups
and ordering machinery in the client tests. Use in-scope imports and the
neighbouring reader idiom in the server intent tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>