Commit graph

624 commits

Author SHA1 Message Date
Bryan Helmkamp
cfb4ea91a3
feat(llm): register providers from resolved catalog
Resolve LLM credentials and adapter registration through the runtime catalog so settings-defined providers can be used for requests. This keeps built-in behavior default-equivalent while supporting provider IDs, aliases, extra headers, header-only auth, base URLs, and provider API model IDs at the adapter boundary.
2026-05-12 19:58:14 -04:00
Bryan Helmkamp
264cac3c64
feat(server): inject settings-backed model catalog (#247)
Some checks are pending
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
## Summary

This PR moves the server-facing model catalog paths onto a resolved
catalog stored in `AppState`, using configured `[llm]` provider/model
overrides layered on top of the built-in catalog.

The server now uses the injected catalog for:

- `/models` listing and model test lookup
- `/completions` default model and provider inference
- manifest preflight materialization and LLM model alias resolution
- diagnostics LLM probes
- pull request default model selection
- runtime settings refresh via `replace_settings`

It also adds catalog overlay helpers in `fabro-model` and converts
resolved server runtime `[llm]` settings into the catalog shape in
`fabro-config`.

This branch also includes the earlier `chore: update dockerfile` commit,
which updates the Daytona snapshot to `fabro-v10` and installs Chromium
through the xtradeb PPA with an XFCE/browser wrapper.

Related: #210

## Tests

- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo nextest run -p fabro-config -p fabro-model -p fabro-server`
(844 tests passed)
- `cargo +nightly-2026-04-14 clippy -p fabro-config -p fabro-model -p
fabro-server --all-targets -- -D warnings`
2026-05-12 17:55:28 -04:00
Bryan Helmkamp
34d83db801
feat(model): support open provider catalog data (#245)
## Summary

This PR moves Fabro’s provider/model catalog toward settings-driven
provider identity by replacing the closed provider schema at the
API/auth/model boundary with `ProviderId`, then loading built-in
provider and model metadata from embedded per-provider TOML files.

The immediate result is that built-ins now use the same settings-shaped
catalog data that custom providers will use later, while request-serving
paths still keep the existing bootstrap/default catalog behavior until
the resolved-catalog plumbing lands.

## Changes

- Replaces API-facing provider enum usage with string-backed
`ProviderId`, including OpenAPI/progenitor replacements and regenerated
TypeScript client models.
- Routes model, auth, billing, CLI, server, and workflow call sites
through provider IDs where they cross product identity boundaries.
- Builds `Catalog` from settings-shaped provider/model data with
validation for adapter keys, OpenAI-compatible `base_url`, duplicate
aliases, provider defaults, disabled entries, model controls, and
per-speed cost rows.
- Replaces `catalog.json` with embedded provider TOML files under
`lib/crates/fabro-model/src/catalog/providers/`.
- Adds an explicit `fabro_model::bootstrap_catalog` hatch for
setup/install paths and extends the dev policy test to keep bootstrap
access contained.
- Preserves public training and knowledge-cutoff labels in LLM model
settings while still accepting bare TOML dates.

## Verification

- `cargo nextest run -p fabro-model -p fabro-config -p fabro-api` — 416
passed
- `cargo nextest run -p fabro-dev --features dev
bootstrap_catalog_references_stay_in_allowlist` — 1 passed
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`
- `cargo build --workspace`
- `git diff --check`

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 via [Codex](https://openai.com/codex)
2026-05-12 15:42:49 -04:00
Bryan Helmkamp
087c9233f3
fix(validate): pick up sibling workflow.toml inputs for bare .fabro path (#242)
## Summary

- `fabro validate path/to/workflow.fabro` now auto-discovers a sibling
`workflow.toml` and loads its `[run.inputs]`, so templated graphs
validate the same way they do when invoked by name or by toml path.
- The discovery is opt-in to the user's specific graph: we only pick up
the sibling toml if its `[workflow].graph` resolves back to the `.fabro`
the user passed. Unrelated tomls in the same directory are ignored.

## Why

`fabro validate` is the natural fast-feedback tool for CI/pre-commit
hooks that iterate on changed `.fabro` files. Previously, a graph using
`{{ inputs.* }}` would fail with a generic MiniJinja "undefined value"
error when validated by path, even when a sibling `workflow.toml`
defined those inputs. The other two invocation forms (by name, by toml)
worked, which made the path form a usability cliff.

Fixes #195.

## Test plan

- [x] New integration test:
`bare_fabro_picks_up_sibling_workflow_toml_inputs` validates
`test/templated_inputs/workflow.fabro` (uses `{{ inputs.app_dir }}`) and
expects `Validation: OK`.
- [x] New unit tests in `fabro-config::project`:
  - `resolve_workflow_path_picks_up_sibling_workflow_toml` — happy path.
- `resolve_workflow_path_ignores_sibling_toml_pointing_elsewhere` —
guard: don't apply an unrelated sibling toml.
- [x] `cargo nextest run --workspace` — 5585 tests pass.
- [x] `cargo +nightly-2026-04-14 fmt --check --all`, `clippy --workspace
--all-targets -- -D warnings` clean.
- [x] Manual: `fabro validate /tmp/fabro-issue-195/workflow.fabro`
(templated graph + sibling toml with `[run.inputs]`) prints `Validation:
OK`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Nate Aune <118984+natea@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:05:21 -04:00
Bryan Helmkamp
a33d17c88d
feat(run): add managed branch controls (#243)
## Summary

Adds run-level controls for clone behavior, managed run branch
setup/pushes, and metadata branch writes/pushes so workflows can opt out
of Fabro-managed Git behavior without relying on provider-specific
`skip_clone` settings. This closes fabro-sh/fabro#240.

## What Changed

- Introduced `[run.clone]`, `[run.run_branch]`, and `[run.meta_branch]`
settings with defaults that preserve current behavior.
- Removed user-facing `skip_clone` from Docker/Daytona config while
mapping the new run-level clone setting into the internal sandbox
runtime options.
- Gated run branch setup/push, metadata branch writer creation/push, and
PR branch output on the new settings.
- Enforced invalid combinations: pull requests require an enabled pushed
run branch, and disabling the run branch also disables metadata branch
behavior.
- Updated OpenAPI, the generated TypeScript API client, frontend fixture
data, and docs for the new configuration shape.

## Testing

- `cargo nextest run -p fabro-config -p fabro-types -p fabro-workflow -p
fabro-server`
- `cargo build -p fabro-api`
- `cd lib/packages/fabro-api-client && bun run generate`
- `cd lib/packages/fabro-api-client && bun run typecheck`
- `cd apps/fabro-web && bun run typecheck`
- `cd apps/fabro-web && bun test`
- `cargo build --workspace`
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`
- `cargo insta pending-snapshots`
- `git diff --check`

## Post-Deploy Monitoring & Validation

- Validation window: first 24 hours after release; owner: release
owner/on-call engineer.
- Log queries/search terms: `run_branch`, `meta_branch`,
`clone.enabled`, `skip_clone`, `pull request requires an enabled pushed
run branch`, `metadata branch`.
- Healthy signals: runs without custom branch config continue creating
and pushing run/meta branches; runs with `[run.clone] enabled = false`
start provider sandboxes without cloning; runs with branch pushes
disabled complete without Git push errors.
- Failure signals: increased run startup failures for Docker/Daytona,
unexpected PR creation conflicts, missing metadata for default-config
runs, or validation errors for configurations that previously used
default settings.
- Mitigation trigger: if default-config runs stop producing expected
branch/metadata artifacts or sandbox startup failures increase, roll
back the release or temporarily restore previous defaults while
investigating the run-level setting resolution path.

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 via [Codex](https://openai.com/codex)

Co-authored-by: Haroldo Olivieri <6575718+haroldolivieri@users.noreply.github.com>
2026-05-12 12:00:30 -04:00
Bryan Helmkamp
234bd5663e
Add ACP backend support (#237)
## Summary
Implemented ACP support as a first-class Fabro backend alongside `api`
and `cli`. This adds a new `fabro-acp` crate using the official ACP Rust
crates, routes `backend=\"acp\"` for agent and prompt nodes, adds
sandbox stdio support for local/Docker/test-support paths, emits ACP
workflow events/projections, updates server steerability handling,
validation, documentation, and black-box CLI coverage.

## Test Plan
Passed strict non-live verification:
- `ulimit -n 4096 && cargo nextest run -p fabro-workflow --run-ignored
all --no-fail-fast` — 1162 passed, 0 skipped.
- `ulimit -n 4096 && cargo nextest run -p fabro-acp -p fabro-sandbox -p
fabro-workflow -p fabro-validate -p fabro-store -p fabro-server -p
fabro-cli --run-ignored all --no-fail-fast -E 'not
test(daytona_streaming_live_smoke)'` — 3125 passed.
- `cargo build --workspace` — passed.
- `ulimit -n 4096 && cargo nextest run --workspace --run-ignored all
--no-fail-fast -E 'not test(daytona_streaming_live_smoke)'` — 5666
passed.
- `cargo +nightly-2026-04-14 fmt --check --all` — passed.
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings` — passed.

Live-environment tests skipped/excluded under explicit user override:
- `daytona_streaming_live_smoke` was excluded from final nextest runs
because it requires live Daytona infrastructure and `DAYTONA_API_KEY`.
- Confirmed with `env -u DAYTONA_API_KEY cargo test -p fabro-sandbox
--features daytona --test daytona_streaming_live
daytona_streaming_live::daytona_streaming_live_smoke -- --ignored
--exact --nocapture`: failed fast with `DAYTONA_API_KEY must be set to
run this live smoke test`.
2026-05-11 23:39:43 -04:00
Bryan Helmkamp
a19f6dd03a
feat(cli): add Fabro MCP server (#236)
## Summary

Adds a stdio-based Fabro MCP server so MCP clients can manage Fabro
workflow runs through the authenticated `fabro` CLI, without a separate
MCP auth flow.

## What Changed

- Adds `fabro mcp start`, `fabro mcp config`, and `fabro mcp init
<agent>` for launching and configuring the MCP server.
- Introduces a new `fabro-mcp-server` crate with run-management tools:
  - `fabro_run_create`
  - `fabro_run_search`
  - `fabro_run_interact`
  - `fabro_run_gather`
  - `fabro_run_events`
- Reuses the CLI's authenticated server connection behavior, including
OAuth refresh, dev-token/local-server handling, explicit server targets,
proxy behavior, and stdio env/cwd isolation.
- Moves shared run-manifest construction into `fabro-manifest` so CLI
runs and MCP-created runs use the same override semantics.
- Extends MCP client stdio support with configured cwd and exact
environment handling for reliable spawned-server tests.

---------

Co-authored-by: fabro-sh-0530[bot] <281434857+fabro-sh-0530[bot]@users.noreply.github.com>
Co-authored-by: Fabro <noreply@fabro.sh>
2026-05-11 18:20:50 -04:00
Bryan Helmkamp
9ea00185dc
fix(server): avoid cancelling terminal runs during delete
Skip cancellation signaling when the durable run projection is already terminal so deletion cannot append cancelled failure events after a successful run.
2026-05-11 08:34:27 -04:00
Bryan Helmkamp
b5101bbde3
refactor(types): remove legacy run summary shape
Use the canonical nested Run DTO directly and reject the old flat run summary JSON shape. Update store, server, CLI, and fixtures to read and produce canonical fields.
2026-05-10 23:29:41 -04:00
Bryan Helmkamp
4fa4716015
refactor(core): simplify reviewed run cleanup
Reuse shared frontend formatting and SSE dedupe helpers, tighten typed sandbox handling, remove obsolete run DTOs, and collapse auth-session revoke into a single store operation.
2026-05-10 22:53:20 -04:00
Bryan Helmkamp
cccb557281
feat(api): unify public run shape
Return canonical Run payloads across run list, board, create, and lifecycle endpoints. Move archive state out of RunStatus and into lifecycle metadata, split sandbox runtime from planned sandbox data, and separate static pull request records from live pull request details.

Regenerate the TypeScript API client and migrate web, CLI, server, store, workflow, and API tests to the new contract.
2026-05-10 20:48:55 -04:00
Bryan Helmkamp
b6d4d240ae
feat(auth): add unified session API
Expose browser and CLI auth sessions through a normalized API, and allow revoking active CLI refresh-token chains while keeping browser sessions non-revocable for v1.
2026-05-10 14:16:23 -04:00
Bryan Helmkamp
5209d05623
refactor(sandbox): unify run sandbox identity
Replace the separate sandbox record shape with a typed RunSandbox model shared by projections, API responses, and generated clients. The public contract now uses SandboxProvider plus a non-null id and working_directory, and removes sandbox identifier/name leakage.
2026-05-10 13:16:57 -04:00
Bryan Helmkamp
47f581cc1d
fix(server): improve sandbox service discovery
Fall back to procfs when ss is unavailable, report the discovery source in API metadata, and surface the sandbox install tip in the services UI. Previewable services are ordered first for clearer service selection.
2026-05-10 12:40:38 -04:00
Bryan Helmkamp
9c08653228
feat(server): list sandbox services 2026-05-10 11:24:39 -04:00
Bryan Helmkamp
e86b11f395
fix(server): point sandbox VNC preview at noVNC viewer page
Daytona's signed preview URL targets the noVNC service root, which
serves a directory listing of the noVNC distribution rather than the
actual viewer. The result was that selecting VNC mode in the run
sandbox tab loaded an iframe of `vnc.html`, `vnc_auto.html`, … as
links instead of the desktop.

Fix it server-side by parsing the signed URL, replacing the path with
`/vnc.html`, and appending `autoconnect=true&resize=scale` so the
iframe immediately connects and scales to fit. Existing query params
on the signed URL (e.g. proxy tokens) are preserved. The intentional
url::Url use is wrapped with #[expect(disallowed_types)] since this is
internal URL manipulation, not a logging/error boundary; the
parse-failure error message omits the URL to avoid leaking creds in
client-facing API responses.

Verified live against a Daytona run on the daytona-medium snapshot:
the response now ends with /vnc.html?autoconnect=true&resize=scale
and the iframe loads the actual noVNC viewer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 10:13:26 -04:00
Bryan Helmkamp
ac90bb199c
feat(server): add Daytona VNC preview endpoint
Adds the sandbox VNC API contract, Daytona Computer Use startup flow, signed noVNC preview response, and generated TypeScript client support.
2026-05-10 00:06:43 -04:00
Bryan Helmkamp
36c5a86005
refactor(runs): simplify run projection shape
Make run.created the projection anchor and require canonical run spec/status fields in API and clients.

Collapse diff/checkpoint/conclusion payloads around RunDiff and update server, CLI, workflow, store, and generated clients.
2026-05-09 23:31:43 -04:00
Bryan Helmkamp
85ca7d5310
feat(server): wire GET /api/v1/runs/{id}/sandbox handler
Returns sandbox_details for the run-owned sandbox. Maps internal errors
into the HTTP shape required by the OpenAPI contract: 404 when the run
or sandbox record is missing, 501 when the provider has no details
implementation, 409 when an existing provider's inspection fails.
2026-05-09 21:44:07 -04:00
Bryan Helmkamp
02d494c268
feat(sandbox,server,web): add sandbox_details inspection and unify SandboxResources
Adds fabro_sandbox::sandbox_details, a control-plane inspection function
that maps Local, Docker, and Daytona providers into a shared
SandboxDetails record (state, image, resources, labels, timestamps).

To avoid type sprawl, the demo board's SandboxResources is unified with
the new control-plane shape (cpu_cores: f64, memory_bytes: u64,
disk_bytes: u64). The runs board chip in apps/fabro-web converts
memory_bytes back to GB for display.
2026-05-09 21:40:19 -04:00
Bryan Helmkamp
8cdc4a6f28
fix(runs): repair deletion of unreadable runs
Allow forced run deletion to purge durable metadata even when projection replay fails, and add a repair command path for deleting unreadable runs in batch.
2026-05-09 17:45:55 -04:00
Bryan Helmkamp
61ab94195e
feat(sandbox): copy Docker exec access command 2026-05-09 17:05:46 -04:00
Bryan Helmkamp
4ef239de79
fix(run-files): remove needless borrow 2026-05-09 16:06:31 -04:00
Bryan Helmkamp
db3f348fab
feat(runs): add sandbox terminal
Expose a run-scoped websocket terminal for Docker and Daytona sandboxes, and add the web terminal route so sandbox-backed runs can be inspected interactively from the run detail page.
2026-05-09 16:06:04 -04:00
Bryan Helmkamp
237318f13f
Merge remote-tracking branch 'origin/main' 2026-05-09 15:40:18 -04:00
Bryan Helmkamp
65c8a12cce
Merge remote-tracking branch 'origin/main' 2026-05-09 15:39:44 -04:00
Bryan Helmkamp
929ece9f6d
test(run-files): cover commits route envelope 2026-05-09 15:34:36 -04:00
Bryan Helmkamp
ac07df6a66
refactor(billing): call token aggregation directly 2026-05-09 15:32:55 -04:00
Bryan Helmkamp
67decad7b5
feat(billing): project live stage token usage
Store live per-stage token counts on StageProjection, carry typed billing model identity through agent.message events, and derive billing rollups from the projection so in-flight stages can report usage before terminal events arrive.
2026-05-09 15:25:51 -04:00
Bryan Helmkamp
010828ae7a
Add run commit diff picker 2026-05-09 14:49:15 -04:00
Bryan Helmkamp
685cc18156
fix(build): refresh embedded git sha on branch commits
Track the active loose HEAD ref from CLI and server build scripts so local builds refresh FABRO_GIT_SHA after normal branch commits without watching packed-refs.
2026-05-09 14:10:04 -04:00
Bryan Helmkamp
8b7d5bd16c
fix(run-files): simplify scoped diffs to tracked files
Use one git diff command for working-tree scopes and exclude untracked files from all scoped run-file views. Update the API description to document the tracked-file scope semantics.
2026-05-09 13:38:44 -04:00
Bryan Helmkamp
447b94da6d
feat(run-files): add sandbox diff scopes
Add committed, uncommitted, and all scope handling for run files with source reporting for sandbox and final patch responses.

Wire the run files page to persist scope in the URL and cache each scope independently.
2026-05-09 13:00:14 -04:00
Bryan Helmkamp
48545f4a7d
Merge remote-tracking branch 'origin/main' 2026-05-09 11:43:59 -04:00
Bryan Helmkamp
ba790ea1e8
refactor(runs): resolve titles from run projection
Centralize legacy title fallback behind RunProjection::title() so summaries and lifecycle responses use the same resolved title behavior.
2026-05-09 11:42:50 -04:00
Bryan Helmkamp
697dc1294f
feat(runs): support explicit run titles
Persist resolved run titles on creation, expose title update events, and add the run title PATCH API. Regenerate API clients and refresh web/server invalidation so title changes are reflected across run detail and board views.
2026-05-09 11:18:12 -04:00
Bryan Helmkamp
1ff30ea03c
Merge remote-tracking branch 'origin/main' 2026-05-09 11:05:15 -04:00
Bryan Helmkamp
2a8884883a
refactor(workflow): remove local worktree mode
Make local sandbox execution direct by removing the public worktree mode and in-place controls from CLI, config, run state, API surfaces, docs, and UI. Keep worktree support only for internal parallel-node isolation.
2026-05-09 11:04:23 -04:00
Bryan Helmkamp
42fa31244a
test(server): expect project settings without directory 2026-05-09 10:55:56 -04:00
Bryan Helmkamp
5b0b1efdc2
fix(workflow): ignore deprecated project directory
Project workflows now resolve from the discovered .fabro directory instead of honoring project.directory. Keep the legacy field parse-only while removing it from resolved settings and API/client shapes.
2026-05-09 10:55:56 -04:00
Bryan Helmkamp
5fc9157017
refactor(workflow): remove retro stage (#230)
## Summary

Removes Fabro's automatic retro generation stage so workflow runs go
directly from execution to finalization and optional PR creation. This
drops the retro-specific crate, events, projection fields, config/API
knobs, and user-facing docs in favor of the existing durable run
observability surfaces.

## What Changed

- Deleted the `fabro-retro` crate and the workflow `retro` pipeline
phase, with finalization now consuming `Executed` state directly.
- Removed retro configuration and API surface area, including
`--no-retro`, `[run.execution].retros`, manifest `no_retro`,
`features.retros`, and run projection `retro*` fields.
- Retired typed `retro.*` events while keeping historical event logs
readable by deserializing retired retro event names as `Unknown`.
- Stopped appending retro sections to generated PR bodies and updated
docs, marketing copy, screenshots, and navigation to point users toward
observability/event-stream inspection.

## Testing

Not run during PR creation; this branch already contained the
implementation commit.

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 (unknown context, reasoning unspecified) via
[Codex](https://openai.com/codex)
2026-05-09 10:18:20 -04:00
Bryan Helmkamp
f07bb4aaba
feat(cli): support sparse input overrides (#222)
## Summary
- Add repeatable `-I` / `--input KEY=VALUE` CLI overrides for workflow
run inputs on `fabro run`, `fabro create`, and `fabro preflight`. CLI
inputs are sparse per-key overrides that merge over the resolved config
inputs (preserving unrelated inherited values), unlike TOML
`[run.inputs]` which still replaces wholesale.
- Manifest bundling and graph-level goal resolution render workflow
source with the effective inputs before structural scanning, so
input-driven `@prompt`, `import`, and `stack.child_workflow` paths get
bundled correctly.
- Persist raw `KEY=VALUE` strings on `ManifestArgs.input` so server-side
replay applies the same sparse overrides on top of merged config.
- Review-driven cleanups: shared `TemplateContext::for_input_scan`
helper for the recurring "render inputs but defer goal" idiom (replaces
4 sites), `#[derive(Default)]` on `ManifestBuildInput` to drop
boilerplate, inline trivial `apply_input_overrides` wrapper, drop a
redundant clone, and tighten the parser/test helpers.

## Test plan
- [ ] `cargo nextest run -p fabro-cli -p fabro-config -p fabro-server -p
fabro-template -p fabro-workflow`
- [ ] `cargo +nightly-2026-04-14 fmt --check --all`
- [ ] `cargo +nightly-2026-04-14 clippy -p fabro-cli -p fabro-config -p
fabro-server -p fabro-template -p fabro-workflow --all-targets -- -D
warnings`
- [ ] Smoke: `fabro run <workflow> -I key=value --input other=42`
overrides those keys while preserving unrelated inherited inputs
- [ ] Smoke: `-I` accepts strings, integers, floats, booleans, empty
values; rejects arrays, inline tables, datetimes; rejects missing `=`
and empty key
- [ ] Smoke: input-driven `@prompts/{{ inputs.foo }}` and
`stack.child_workflow="{{ inputs.bar }}/workflow.fabro"` paths bundle
correctly when overridden via `-I`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 10:00:35 -04:00
Bryan Helmkamp
6719a3cdac
refactor: simplify reviewed run cleanup
Reuse shared PR chip rendering, persist runtime stage handlers from events, and remove duplicated lifecycle/delete helpers found during review.
2026-05-08 23:29:08 -04:00
Bryan Helmkamp
79a095d7c6
fix(runs): restore terminal sandbox regressions
Emit local sandbox stop events so CLI follow and event-history tests can observe terminal cleanup under run-owned sandbox lifecycle. Fall back to stored file diffs when completed runs no longer have an active sandbox.
2026-05-08 22:41:42 -04:00
Bryan Helmkamp
d3e33ce32c
feat(runs): own sandbox lifecycle
Create run-owned sandbox lifecycle operations so terminal runs stop by default, resumes attach and start persisted sandboxes, and run deletion deletes or hands off provider resources according to preserve settings.
2026-05-08 18:38:08 -07:00
Bryan Helmkamp
9a3ab8bbba
fix(cli): re-prompt invalid attach interview input
Keep invalid terminal answers local to attach prompts instead of treating them as interrupted interviews, and accept No for confirmation answers to match documented yes/no behavior.
2026-05-08 13:46:12 -07:00
Bryan Helmkamp
1a43cf5abc
feat(api): expose stage handlers on run stages
Populate RunStage.handler from workflow graph metadata and use it for the run stages renderer instead of inferring from activity events.
2026-05-08 13:36:02 -07:00
Bryan Helmkamp
0b29dbe6d8
feat(runs): link stored pull requests 2026-05-08 13:17:08 -07:00
Bryan Helmkamp
81af03edcd
fix(api): keep archive mutation test on typed answers 2026-05-08 10:28:09 -07:00
Bryan Helmkamp
b0dfd6b3b4
fix(api): type interview answer submissions
Replace the loose interview answer request payload with a discriminated OpenAPI union so generated clients enforce the wire contract. Surface structured HTTP error details in the web client and update browser, CLI, and server answer submission paths to use the typed variants.
2026-05-08 09:18:35 -07:00