Commit graph

545 commits

Author SHA1 Message Date
fabro-releases[bot]
14fc5d446c Bump version to 0.311.0-nightly.0 2026-07-31 10:12:11 +00:00
fabro-releases[bot]
e072ddafb9 Bump version to 0.310.0-nightly.3 2026-07-30 20:13:18 +00:00
fabro-releases[bot]
4ab090cae3 Bump version to 0.310.0-nightly.2 2026-07-30 11:14:09 +00:00
fabro-releases[bot]
69d4482da5 Bump version to 0.310.0-nightly.1 2026-07-30 10:56:04 +00:00
fabro-releases[bot]
381f603bfb Bump version to 0.310.0-nightly.0 2026-07-30 10:05:24 +00:00
fabro-releases[bot]
854f71f2c5 Bump version to 0.309.0-nightly.2 2026-07-29 17:41:07 +00:00
fabro-releases[bot]
1855362354 Bump version to 0.309.0-nightly.1 2026-07-29 15:55:44 +00:00
fabro-releases[bot]
d8434e7672 Bump version to 0.309.0-nightly.0 2026-07-29 10:11:28 +00:00
fabro-releases[bot]
5396565cd4 Bump version to 0.308.0-nightly.1 2026-07-28 22:42:08 +00:00
Bryan Helmkamp
b19dda6aa3
Merge pull request #661 from fabro-sh/fix/small-default-skips-providers-without-small-model
Fix run title generation picking a flagship model, and sharpen the prompt
2026-07-28 17:38:27 -04:00
Bryan Helmkamp
df0bd58819
Merge remote-tracking branch 'origin/main' into fix/small-default-skips-providers-without-small-model
# Conflicts:
#	lib/apps/fabro-server/src/test_support.rs
2026-07-28 17:06:20 -04:00
Bryan Helmkamp
1aa7a153b0
Merge pull request #652 from fabro-sh/fix/publish-failures
Make publish failures terminal
2026-07-28 17:03:18 -04:00
Bryan Helmkamp
73f48eeddb
refactor: simplify publish pipeline and collapse duplicated stage errors
Follow-up cleanup on the publish-failures change.

Error model:
- Collapse `Error::{Engine, Publish, Handler}` into one `Error::Stage` with an
  `ErrorStage` discriminator. The three shared a field shape and had to be
  edited together in four match groups; nine near-identical constructors
  become two private helpers.
- Add `Error::failure_reason()`, replacing the same error -> FailureReason
  mapping written out in four places.
- Publish errors are now terminal. Publish runs once, after execution, so no
  caller could ever act on the retryable classification.

Publish phase:
- Fix: a branch that was pushed is now still reported when pull request
  creation fails afterwards. `PublishOutcome` records what happened and
  carries the error separately, instead of hiding both behind a `Result`.
- Drop `PublishOutcome::NoChanges`, which no consumer distinguished from
  `Published { pr_url: None }`.
- Move publish onto `Concluded` as methods and replace three near-identical
  precondition guards with one `publish_target()`.

Pull requests:
- `maybe_open_pull_request` -> `open_pull_request` returning the record
  directly. Both callers already reject empty diffs, so the `Ok(None)` path
  was unreachable.
- Drop `CreatedPullRequest.head_sha`, which echoed back its own input.

GitHub client:
- Delete `branch_exists`, which had no callers and duplicated
  `branch_head_sha`. Give `branch_head_sha` the `_with_client` split every
  sibling has and port the tests to `MockHttpClient`.
- Collapse the copy-pasted credential match in `resolve_clone_credentials`.

Events:
- `PullRequestCreated.head_sha` is `Option<String>` instead of using an empty
  string to mean absent.
- Centralize the run-branch refspec in `lifecycle::git::push_run_branch`, so
  `git.push` reports a branch name from both emitters as documented.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 15:09:10 -04:00
Bryan Helmkamp
010c8d50c1
Add structured review targets to human gates 2026-07-28 13:24:12 -04:00
fabro-releases[bot]
8cc711463b Bump version to 0.308.0-nightly.0 2026-07-28 10:11:13 +00:00
Bryan Helmkamp
24b0576ffe
Record fabro-template as a fabro-server dependency in Cargo.lock
Missed in the previous commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-27 17:23:26 -04:00
fabro-releases[bot]
2bcf94fed8 Bump version to 0.305.0-nightly.3
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
TypeScript / Typecheck (push) Has been cancelled
TypeScript / Test (push) Has been cancelled
TypeScript / Build (push) Has been cancelled
2026-07-25 19:35:43 +00:00
fabro-releases[bot]
e510dac98d Bump version to 0.305.0-nightly.2 2026-07-25 16:18:41 +00:00
Bryan Helmkamp
5980627bc8
refactor(glob): unify workspace path matching 2026-07-25 10:30:19 -04:00
fabro-releases[bot]
db0b6c9b7c Bump version to 0.305.0-nightly.1 2026-07-25 11:18:11 +00:00
fabro-releases[bot]
c2b95a7a75 Bump version to 0.305.0-nightly.0 2026-07-25 03:21:30 +00:00
Bryan Helmkamp
1ca9fe977d
fix(sandbox): simplify Bash contract implementation 2026-07-24 21:55:36 -04:00
Bryan Helmkamp
3606ba6a0f
feat(sandbox): standardize command execution on non-login Bash
Fabro advertised Bash while its three backends implemented three
different contracts: Daytona evaluated commands through `sh`, and
Docker's streaming, stdio, and setup paths used a login shell. Bash-only
syntax silently misbehaved depending on provider and code path, and
login profiles could change PATH and command behavior per image.

Make `bash -c` the enforced interpreter for every command string the
Unix sandbox API accepts, on every production backend and through both
buffered and streaming execution. This selects the interpreter only —
no `errexit`, no `pipefail`, no login mode — so `false | true` still
succeeds and a workflow that wants other semantics writes them into its
own command.

Local resolves `bash` through the worker's PATH (NixOS has no
/bin/bash) and reuses that one executable across all three command
paths. Docker and Daytona require /bin/bash with no `sh` fallback.

Fresh initialization and resume/start now verify Bash through a shared
marker-validating probe before reporting the sandbox usable, so a
missing or non-Bash interpreter fails at the lifecycle boundary with
provider-specific remediation instead of on the first command. The
probe also rejects Bash in POSIX mode, which an image whose `bash` is
really `sh` would otherwise pass.

Sandbox MCP scripts and the detached launch wrapper move under the same
contract; host-side stdio MCP scripts, hooks, and interactive terminals
are separate executors and keep their existing `sh` behavior.

The `shell` tool's name and JSON schema are unchanged across providers;
only its prose now identifies `command` as Bash source.

BREAKING CHANGE: sandbox commands no longer load login-shell profiles,
so environment set in /etc/profile.d/*.sh, ~/.bash_profile, or
nvm/rbenv/sdkman initializers is gone. Move those exports into the
Dockerfile's ENV or the Daytona snapshot image.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 21:26:05 -04:00
Bryan Helmkamp
fd6f14f107
refactor(agent): simplify prompt template rendering 2026-07-24 19:10:48 -04:00
Bryan Helmkamp
1d685cbea4
refactor(agent): render profile prompts with minijinja via fabro-template
The previous commit introduced render_prompt and splice_optional_section, a
second templating mechanism in a workspace that already standardizes on
MiniJinja behind fabro-template. Drop both and render the profile prompts the
same way fabro-workflow and fabro-manifest render theirs.

Expressing the conditionals as {% if %} lets every profile collapse to a single
template, since the optional blocks no longer need to be separate files spliced
in from Rust:

  before: 6 files + 2 splice helpers, prompt prose split across .md and .rs
  after:  3 files, one per profile, all prose in the template

Rust now passes only facts -- provider name, which file-edit tool is active,
and whether web search and subagents are available. Values land under `vars`,
so templates read {{ vars.env_block }}. Booleans are passed as "true"/"false"
and compared explicitly via the bool_var helper, because the shared
TemplateContext types vars as strings and a bare {% if %} on the string
"false" would be truthy.

Also converts fabro-server's Ask Fabro prompt, which is assembled at runtime.
Its tool guidance now arrives as a template variable instead of being
interpolated into the template text. That guidance carries tool names and
descriptions that can originate from MCP servers, and MiniJinja does not
re-render substituted values, so a tool description containing {{ ... }} stays
inert rather than being evaluated.

Output is unchanged. Verified by diffing all ten prompt variants against the
same unmodified origin/main worktree used for the previous commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 18:23:47 -04:00
fabro-releases[bot]
ffee6ed29e Bump version to 0.304.0-nightly.1 2026-07-24 14:47:39 +00:00
fabro-releases[bot]
df3c834581 Bump version to 0.304.0-nightly.0 2026-07-24 01:48:13 +00:00
Fabro
b3e085dc45 Merge remote-tracking branch 'origin/main' into fabro/run/01KY7Y01REECZ24XXTMBZ3PPV9 2026-07-23 20:29:21 +00:00
fabro-releases[bot]
8c37f5fae5 Bump version to 0.303.0-nightly.4 2026-07-23 20:10:14 +00:00
Fabro
56119990be fabro(01KY7Y01REECZ24XXTMBZ3PPV9): simplify_fable (succeeded)
Fabro-Run: 01KY7Y01REECZ24XXTMBZ3PPV9
Fabro-Completed: 6
Fabro-Checkpoint: 497f92f4d9

⚒️ Generated with [Fabro](https://fabro.sh)
2026-07-23 19:10:39 +00:00
fabro-releases[bot]
5d7ecd7348 Bump version to 0.303.0-nightly.3 2026-07-23 18:35:29 +00:00
Bryan Helmkamp
0432c019ee
chore: address review feedback on error mapping and test-support gating
- Return 400 (not 500) for WorkflowError::ModelReference from run
  creation, matching ModelSelection: an ambiguous model/provider token
  is user input, not a server fault.
- Gate fabro-workflow's test_support module behind
  cfg(any(test, feature = "test-support")) so the feature actually
  controls exposure, per the repo's test-support boundary guidance.
  Add the self dev-dependency so tests/it keeps compiling, and gate
  the pipeline helpers that only test_support consumed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 13:38:55 -04:00
fabro-releases[bot]
e9a571da2e Bump version to 0.303.0-nightly.2 2026-07-23 10:06:14 +00:00
fabro-releases[bot]
d9282e66f9 Bump version to 0.303.0-nightly.1 2026-07-23 01:49:45 +00:00
fabro-releases[bot]
3c4ed41d57 Bump version to 0.303.0-nightly.0 2026-07-23 00:17:24 +00:00
Bryan Helmkamp
2843b33d92 Simplify runs read model: single-source mappings, leaner queries
Consolidate duplicated logic from the SQLite runs read model review:

- Derive the status sort CASE and board-column filter from a new
  RunStatusKind::board_rank(), replacing three hand-maintained copies
  of the status/column mapping; add a test upserting every status
  variant so the migration CHECK can't silently drift
- Share RunSize bucket thresholds between from_total_usd_micros and
  the generated size-sort CASE via RunSize::BUCKET_MAX_USD_MICROS
- Resolve run selectors from a lean identity query instead of
  decoding every stored summary per request
- Delete the RunsSortKey/RunsSortDirection adapter enums; the store
  sort enums now carry the wire serde names
- Consolidate the workflow display-name fallback chain into
  WorkflowRef::display_name() (store, CLI, run lookup)
- Share pagination clamping and the paginated list envelope across
  handlers
- Reconcile now skips rows whose source seq is unchanged and
  batch-deletes stale rows; drop the two indexes no query can use
- Hold the summary store OnceLock cell in RunDatabaseInner instead of
  a snapshot so late attachment reaches already-open writers
- Misc: expect() on COUNT(*) sign, %err logging, shared wall-time
  helper, shared SQLite test fixture, dead billing fallback removed

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 13:55:22 -04:00
Bryan Helmkamp
22844300af Add SQLite runs read model 2026-07-22 13:55:22 -04:00
Bryan Helmkamp
c12264c16d Migrate automations to SQLite 2026-07-22 13:32:35 -04:00
Bryan Helmkamp
431399826d Simplify SQLite stores after review
- Delete the dead test-only Vault-based env-secrets migration and point
  the startup migration tests at the production migrate_to_store path
  over a real SQLite-backed SecretStore
- Extract shared legacy-import helpers (timestamped backup rename,
  is_toml_file) into fabro_db::legacy and parse_rfc3339_utc into
  fabro-db, replacing four per-crate copies
- Take one secrets snapshot in migrate_to_store instead of per-name
  queries
- Share one bind order between the MCP store INSERT and UPDATE
  statements
- Return SecretEntry directly from entry_from_row
- Unify the environment/MCP store blocking loaders into a generic
  load_store_blocking helper

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 13:11:10 -04:00
Bryan Helmkamp
ec3933d5de Move MCP servers to SQLite storage 2026-07-22 13:10:01 -04:00
Bryan Helmkamp
f2cbc016ee Clean up SQLite secrets migration and fix CLI env credential regression
Review pass over the secrets-to-SQLite migration:

- Add SecretStore::open() consolidating the connect/migrate/import-legacy
  sequence repeated at five call sites; fabro-agent and fabro-cli drop
  their fabro-db dependency
- Restore process-env LLM credential lookup in the standalone CLI/agent
  sources via SqlVaultCredentialSource::new (regression: vault_only
  dropped the env fallback that VaultCredentialSource::new provided)
- Fix five install tests that still asserted against the legacy
  secrets.json, which the importer renames to .bak
- Make AppStateConfig.preloaded_vault required, deleting the fallback
  that re-read the already-renamed legacy file; drop the now-unused
  vault_path field and demote load_startup_vault to test-only
- Skip the snapshot clones and CAS retry in resolve() when the vault
  holds no OAuth secrets (per-request hot path)
- Remove dead persist_with_secret_store, the VaultSecretWrite alias,
  the secret_type_string one-liner (now SecretType::as_str), the
  impossible RowCountOverflow error, and duplicated row parsing
- Run check_crypto concurrently with the other diagnostics checks

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 12:45:38 -04:00
Bryan Helmkamp
d325a2c1e6 Migrate secrets storage to SQLite 2026-07-22 12:44:20 -04:00
Scott Werner
70370fdaba
Merge pull request #585 from fabro-sh/db-premigration-snapshot
Snapshot fabro.sqlite3 before applying new migrations
2026-07-22 12:38:30 -04:00
Bryan Helmkamp
ec6292827e
Bump version to 0.302.0-nightly.1 2026-07-22 12:29:40 -04:00
Scott Werner
f91c71b8e0 Snapshot fabro.sqlite3 before applying new migrations
A binary downgrade after new SQLite migrations have been applied fails
sqlx's startup validation ("migration was previously applied but is
missing in the resolved migrations") and previously left the operator
with no rollback artifact: the shared database had no backup, so
recovering meant hand-editing _sqlx_migrations and dropping tables.

Database::migrate now writes a consistent single-file snapshot to
<db>.pre-migration.bak (via VACUUM INTO, mode 0600) before applying any
migration the database has not seen. Rollback is: stop the server,
replace the database file with the snapshot, delete -wal/-shm siblings,
start the previous binary. Fresh databases and no-op migrates skip the
snapshot, so the file always preserves the state from immediately before
the most recent schema change. A snapshot failure fails the migration:
no rollback artifact, no schema change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 08:58:33 -04:00
fabro-releases[bot]
d967b33e92 Bump version to 0.302.0-nightly.0 2026-07-22 10:06:43 +00:00
fabro-releases[bot]
ed78df733d Bump version to 0.293.0-nightly.0
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
2026-07-13 10:25:55 +00:00
fabro-releases[bot]
52d8c01c2a Bump version to 0.292.0-nightly.0 2026-07-12 09:51:04 +00:00
fabro-releases[bot]
dfcdda2ab7 Bump version to 0.291.0-nightly.0 2026-07-11 09:48:48 +00:00
fabro-releases[bot]
aadaa3f370 Bump version to 0.290.0-nightly.0 2026-07-10 10:25:04 +00:00