After the single-DB refactor, closing one SlateRunStore could close the
shared SlateDB for every run in the process. Under shared-daemon test
load that surfaced as 500 responses with \"db is closed\" on later state,
event, and delete requests.
Make run-handle close a no-op so the shared DB lifetime stays owned by
the store/process rather than individual run handles.
Move durable run access and execution control onto the server-backed client,
canonicalize run APIs under /api/v1/runs, and switch CLI integration tests
to a shared test daemon/storage model with shared-state-safe assertions.
The test captures Debug output from RunEvent, which renders the event body variant name rather than the canonical envelope string. Assert on StallWatchdogTimeout so the check matches the collected output.
Disable proxy discovery for the hot test HTTP clients so nextest no longer
pays macOS system proxy lookup on repeated reqwest client creation.
Also keep the approved OAuth loopback cleanup and replace GitHub test key
generation with a checked-in PEM fixture.
Define the new run-store contract in the OpenAPI spec, regenerate the
Rust and TypeScript clients, and implement the matching store and
server support for run state, event access, blobs, and stage artifacts.
Align the HTTP API with the CLI's existing `fabro create` / `fabro start`
separation. POST /api/v1/runs now creates a run in `submitted` status
without queuing it. A new POST /api/v1/runs/{id}/start transitions to
`queued` and notifies the scheduler. Also removes the unused
/api/v1/runs/{id}/context endpoint.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove unused RunEventHeader and AssistantUsageProps structs, simplify
identity RunNoticeLevel conversion, and return references from
event_name()/properties() instead of cloning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a shared StoredEvent schema in fabro-types and switch workflow,
store, CLI, and server event handling to use it directly.
This removes the writer/reader mismatch around flattened failure data,
updates affected projections and progress rendering, and refreshes the
fixture/snapshot coverage around the canonical event shape.
Rename durable artifact values to raw byte blobs keyed by RunBlobId,
add the blob type in fabro-types, switch SlateRunStore to write/read/list
blob APIs, and export blobs from store dumps by UUID.
Merged origin/main incorporating:
- db_prefix threading in SlateRunStore for run isolation
- matches_run validation in active run cache
- NodeVisitRef type in fabro-store types
- ListRunsQuery parameter for list_runs API
- HashSet dedup in catalog listing
- Updated snapshot tests for new run directory format
Preserved from feature branch:
- NodeAsset struct and exports
- StageId-based node references in run state
- make_run_dir as pub for cross-crate access
- Thread-spawn approach in handler test_default for tokio safety
- parse_run_id handles YYYYMMDD-ULID directory format
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move run.running emission onto the event emitter path so it cannot race
past sandbox.initialized or run.started via a direct store append. This
keeps event ordering deterministic for CLI consumers and snapshot tests.
Move durable run metadata and path derivation onto RunId, simplify the
Slate catalog/index format, and carry the storage-specific run directory
through workflow creation so detached and lookup flows stay aligned.
Also update affected CLI snapshots and test helpers to match the new
run discovery behavior.
File paths in node asset keys contain / (e.g. src/main.rs), which
conflicted with the / segment separator. Using # eliminates the
ambiguity — the filename is always the trailing segment after the
last #, so embedded slashes parse correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clarifies that this type is an event-sourced projection of run history,
distinct from fabro_core::ExecutionState which tracks live execution.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolves the name collision with fabro_store::RunState. The core type
represents live in-memory execution state (current node, visits, context),
while the store type is an event-sourced projection of a full run record.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
NodeOutcomeRecord was a duplicate alias for Outcome<Option<StageUsage>>
which fabro-workflow already calls Outcome. Inline the type instead.
RunSummary duplicated CatalogRecord's four fields. Use #[serde(flatten)]
to embed CatalogRecord directly, eliminating the duplication.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- run_dump: take &Path instead of PathBuf by value in path helpers
- test_support: remove empty no-op persist_run_artifacts_for_tests
- agent.rs: use u32::try_from instead of as u32 cast
- retro.rs: remove unnecessary let binding
- pull_request.rs: use NodeState::default() instead of Default::default()
- execute/tests.rs: replace bool::then in filter_map with filter+map
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>