Non-release builds now append the profile to `fabro --version`
(`x.y (sha date debug)`), `fabro version`, and `fabro system info`,
so users can tell a local build apart from a shipped release. The
API's `SystemInfoResponse` gains a `profile` field so the client
can render the server's build profile too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The spec declared openapi 3.1.0 but used nullable: true (3.0 idiom)
in 78 places, which Mintlify's parser rejected, breaking doc deploys.
Convert to proper 3.1 patterns (type arrays and oneOf with type: null),
switch the server conformance test from openapiv3 (3.0-only) to a
YAML-level walk so it accepts 3.1 input, and regenerate the typescript
client — it now correctly emits `| null` on nullable fields.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clarifies that Submitted/Starting runs are initializing, not just
pending. Also refactors run-detail to display the actual run status
via runStatusDisplay instead of mapping to board columns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Features like session_sandboxes and retros are server-level capability
flags, not user settings. Expose them on GET /system/info where they
belong alongside other server metadata.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a server-targeted `fabro version` command for checking client and
server build identity without reading local storage directly.
This also removes version data from `/health`, moves doctor parity checks
to diagnostics, and updates the API spec, docs, generated client, and
coverage for the new contract.
Remove the server startup path that inferred dry-run from provider
availability and let run.execution.mode inherit normally from
settings.
Model tests now return skip for unconfigured providers at request
time, completions use the real error path, and the CLI/docs/tests are
updated for the removed server --dry-run flag.
Replace the Command::new("dot") shell-out in render_dot() with a direct
FFI call to the vendored Graphviz library. Drop PNG support (SVG only).
Remove GraphFormat enum, dot_is_available() helpers, dot-related
diagnostics/doctor checks, and the graphviz install prompt. Update
OpenAPI spec to remove png format and 502 responses. Update CLI help
text, snapshot tests, and documentation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Conflicts resolved:
- install.rs: kept simplified auth (port 32276, no TLS, no username
in merge_server_settings), adapted to origin's input_source API by
removing username from ServerConfigSelection::Write
- serve.rs: kept ProviderCredentials import from origin, dropped
ClientAuth (removed with mTLS)
- server.rs: kept both imports (ServerAuthMethod + Provider)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the old strategy matrix with server.auth.methods, browser session
cookies, and raw dev-token bearer auth. Remove mTLS auth leftovers, auto-
provision local session secrets, and update tests and docs to the new auth
surface.
Make `fabro settings` render dense resolved settings by default for local
inspection, add a resolved view to the server settings endpoint with an
explicit compatibility marker, and update tests plus generated API clients
to lock the new behavior.
Keep project config and checked-in workflows under .fabro so they stay out of
normal repo listings. Update config discovery, CLI project commands, fixtures,
docs, and checked-in workflow paths to use .fabro/project.toml and
.fabro/workflows/*.
Add a shared MiniJinja-based template crate and migrate workflow prompts,
imports, hooks, and InterpString env references to the new {{ ... }}
syntax. This also threads typed run inputs through workflow rendering and
updates docs and tests to match the new templating model.
Brings in the events schema v2 work (RunEvent envelope fields, ActorRef,
parallel branch ids, flattened EventEnvelope wire JSON) on top of the
local Stage 6 settings TOML redesign.
Conflict resolutions:
- fabro-types/src/lib.rs: keep new ParallelBranchId re-export from
origin; drop the legacy Settings/ArtifactStorage* re-exports (the
flat Settings struct was deleted in Stage 6.3b).
- fabro-server/src/server.rs: keep new ActorRef import from origin;
drop the unused legacy Settings import that came along with it.
- fabro-api-client/src/models/web-settings.ts: keep our deletion. The
remote modification was an incidental TS-client regeneration that
Stage 6.6 already invalidated by collapsing settings DTOs to a
freeform v2 shape.
- fabro-workflow/src/event.rs: rewrite the run_created actor test to
use SettingsFile::default() instead of the deleted Settings type.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces the legacy flat `ServerSettings` / `RunSettings` schemas in
`docs/api-reference/fabro-api.yaml` and 20+ supporting nested type
schemas (LlmSettings, SandboxSettings, HookDefinition, WebSettings,
ApiSettings, GitSettings, McpServerEntry, etc.) with two simple
`type: object, additionalProperties: true` schemas that declare the
wire shape as the v2 `SettingsFile` tree with secret-bearing subtrees
dropped before serialization.
Regenerates the Rust progenitor and TypeScript Axios clients against
the new spec. The progenitor generates `RunSettings` / `ServerSettings`
as `#[serde(transparent)]` newtypes over `serde_json::Map<String,
Value>`; the openapi-generator emits `{ [key: string]: any; }` inlined
into the API method signatures and no longer exports named model
types.
Updates fabro-web to define local `type ServerSettings =
Record<string, unknown>` / `type RunSettings = Record<string,
unknown>` aliases since the generated client no longer exports them.
The UI only `JSON.stringify`s these payloads into a CollapsibleFile,
so the opaque shape is fine.
All 3,756 workspace tests remain green. The OpenAPI conformance test
`server_settings_keys_match_openapi_spec` still passes because
`compare_schema` short-circuits on pure-map schemas (no `properties`);
it becomes a no-op that will be removed entirely when Stage 6.3b
deletes the legacy flat `Settings` struct it still builds.
Unblocks the server handler + CLI migration in the next commits of
Stage 6.6.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The typescript-axios generator was collapsing EventEnvelope's
allOf([inline_object, $ref: RunEvent]) to a bare `type
EventEnvelope = RunEvent` alias, losing the `seq` field at the
type level. TypeScript consumers could write `envelope.seq` and
get `any` (via RunEvent's additionalProperties index signature),
but had no type-level guarantee that seq was present.
Extract `EventSeq` as a named component schema and switch
EventEnvelope's allOf to two $refs. typescript-axios now
generates `export type EventEnvelope = EventSeq & RunEvent`,
which makes `envelope.seq: number` a typed property.
The Rust progenitor client is unchanged: it still flattens the
allOf into a single EventEnvelope struct with `seq: i64` inline,
exactly as before. Wire JSON is byte-identical on both sides.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rewrite every docs/ reference and integration guide example that
previously showed legacy flat TOML (`[llm]`, `[vars]`, `[sandbox]`,
`[setup]`, `[exec]`, `[fabro]`, `[pull_request]`, `[mcp_servers]`,
`[git]`, `[web]`, `[api]`, `[features] retros`, `version = 1`,
top-level `storage_dir`) to use the v2 namespaced schema. Also update
the surrounding prose to describe v2 merge semantics (R22 run.inputs
wholesale replacement, R71 sticky sandbox.env/labels, R30 whole-list
prepare.steps replacement, hook id-based replacement).
Files touched:
- docs/reference/user-configuration.mdx (complete rewrite around
[cli.*] ownership, [run.*] run-scoped defaults, [cli.target] /
[cli.exec] / [cli.output] / [cli.updates] / [cli.logging], and
[run.agent.mcps.<name>] with durations like "10s")
- docs/reference/cli.mdx (settings.toml example uses [cli.exec.*],
[run.model], [cli.target])
- docs/execution/run-configuration.mdx (full run-config example
rewritten to use [workflow].graph, [run].goal/working_dir,
[run.model], [run.prepare.steps], [run.sandbox.daytona.snapshot]
with Size values, [run.inputs], [run.artifacts], [run.agent.mcps],
[run.pull_request], [[run.hooks]] with optional id and duration
timeout; section docs explain the new merge semantics)
- docs/execution/environments.mdx and devcontainers.mdx (sandbox
examples now use [run.sandbox.*])
- docs/execution/retros.mdx (retros moved to [run.execution] retros
= true per R31)
- docs/execution/failures.mdx (fallbacks now a single ordered array
under [run.model].fallbacks)
- docs/workflows/variables.mdx ([vars] → [run.inputs], wholesale
replacement semantics explained)
- docs/administration/server-configuration.mdx (full reference
rewritten around [server.listen]/[server.api]/[server.web]/
[server.auth]/[server.storage]/[server.scheduler]/[server.logging]/
[server.integrations])
- docs/api-reference/overview.mdx (auth strategies now enabled via
[server.auth.api.jwt].enabled and [server.auth.api.mtls].enabled;
listener TLS moved to [server.listen.tls])
- docs/integrations/daytona.mdx, github.mdx (provider config now
nested under [run.sandbox.daytona] / [server.integrations.github])
- docs/human-tools/ssh-access.mdx (sandbox examples to v2)
- docs/agents/mcp.mdx (Playwright sandbox example to [run.agent.mcps])
- docs/core-concepts/models.mdx (model config and fallbacks array to
[run.model])
Canonical fabro-cli overrides and server run_manifest now emit
verbose via [cli.output].verbosity = verbose rather than the prior
run.metadata staging. No code changes beyond those Stage 4 fixes that
were already in flight.
Wire EventEnvelope now inlines the RunEvent payload fields alongside
seq at the top level of the JSON object. The internal Rust
EventEnvelope { seq, payload } stays structurally unchanged; only the
API/SSE serialization layer flattens for clients.
- OpenAPI spec: add stage_id, parallel_group_id, parallel_branch_id,
tool_call_id, actor to RunEvent; model EventEnvelope as allOf(seq,
RunEvent); introduce ActorRef/ActorKind schemas.
- fabro-server: rewrite api_event_envelope_from_store to merge seq
into the payload JSON value before returning the generated flat
type; remove the now-unused nested ApiRunEvent conversion helper.
- fabro-cli server_client: add wire_event_envelope_into_store helper
that turns flat wire JSON back into fabro_store::EventEnvelope
{ seq, payload } for internal consumers.
- Regenerate progenitor Rust types and typescript-axios client.
- Update demo stubs, SSE tests, CLI test helpers, and insta
snapshots to expect the flattened shape and the new stage_id field.
Incidental: the typescript regeneration also picked up prior-merged
spec fields (ApiQuestion stage/timeout/context, upload manifest
batches, web-settings) that were stale in the TS client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
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.
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.
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.
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.
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>
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.
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>
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>
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.
- 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
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.
Move secret storage, diagnostics, and repo/provider validation behind the
server API so credentials live under the server storage dir and take effect
immediately without process env mutation.
This also removes the old .env runtime path, rewires doctor/install/secret/
provider login/repo init around the server contract, and regenerates the
TypeScript client for the new endpoints.
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.
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>
Replace typify-only type generation with progenitor, which generates both
Rust types (in a `types` module) and a reqwest-based HTTP client from the
OpenAPI spec. Also upgrades reqwest 0.12→0.13 and rmcp 0.15→1.3 to align
dependency versions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move storage_dir() from FabroSettingsExt trait in fabro-config into an
inherent method on Settings in fabro-types. Remove the re-export from
fabro-config so callers import directly from fabro_types. Drop the
redundant Fabro prefix since the type already lives in the fabro_types
crate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure the flat `serve` command into a nested `server start`
subcommand, following the existing namespace pattern (system prune,
repo init, etc.).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Better reflects that this crate contains auto-generated types scoped
to the API layer. Pure rename with no behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the per-run `--run-dir` CLI flag with `--storage-dir` which sets
the base storage directory (default ~/.fabro). Runs are now created under
`<storage-dir>/runs/` automatically. This unifies the server's `data_dir`
config with the CLI by renaming `FabroConfig.data_dir` to `storage_dir`
and adding a `storage_dir()` convenience method.
Key changes:
- FabroConfig: `data_dir` → `storage_dir` (serde alias preserves compat)
- CLI: `--run-dir` → `--storage-dir` on `fabro run`
- `__detached`: now takes `--storage-dir` + `--run-id` instead of `--run-dir`
- All ~20 CLI commands derive runs base from config instead of hardcoded default
- Added parameterized `runs_base(storage_dir)` and `make_run_dir()` helpers
- Updated OpenAPI spec, docs, and all tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>