Commit graph

4803 commits

Author SHA1 Message Date
Scott Werner
ce640b6ad3 Unify pinned tag and exact-commit clone paths
Introduce a PinnedRevision enum in clone_source so the Docker and Daytona
providers run one fetch/checkout/verify sequence for both an exact commit
and a tag instead of two near-identical arms. Fold the tag-specific
command builders into the generic ones, share the bare-ref grammar check
between branch and tag validation, and derive the workflow clone source
from the validated Git target in a single match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 12:18:58 -04:00
Scott Werner
fbba98defd Add tag support to Git run targets 2026-08-26 11:16:37 -04:00
Scott Werner
34014e6dce
Merge pull request #790 from fabro-sh/codex/run-intent-folder-target
Add local folder run target
2026-08-26 10:34:59 -04:00
fabro-releases[bot]
ff29795dd8 Bump version to 0.337.0-nightly.1 2026-08-26 13:41:21 +00:00
Bryan Helmkamp
6ac769c4cd
Merge pull request #810 from fabro-sh/mcp-config-name
Add --name to fabro mcp config and fabro mcp init
2026-08-26 09:22:49 -04:00
Bryan Helmkamp
2134f550a4
Merge pull request #811 from fabro-sh/on-failure-succeed
Add on_failure="succeed" as an explicit failure policy
2026-08-26 09:22:10 -04:00
Bryan Helmkamp
d8b28dfafd
Refresh generated CLI reference 2026-08-26 09:15:20 -04:00
Bryan Helmkamp
b3d112b206
Harden succeed failure policy routing 2026-08-26 09:13:04 -04:00
Bryan Helmkamp
e5046d8b1b
Refactor MCP config argument handling 2026-08-26 09:01:37 -04:00
Bryan Helmkamp
a049f94042
Add on_failure="succeed" as an explicit failure policy
A failed node with an effective `succeed` policy and no explicit recovery
route now finishes as `succeeded` and follows normal success routing. The
original failure stays on the outcome so the stage.completed event and the
checkpoint keep the diagnostic, and the outcome notes record which scope
promoted it.

- OnFailure gains a Succeed variant; Node::on_failure resolves the
  deprecated auto_status=true attribute as an alias, with an explicit
  on_failure winning
- The core executor applies the policy before the lifecycle observes the
  result, so the recorded outcome, context keys, goal gates, events, and
  routing all see the effective outcome; this replaces AutoStatusLifecycle
- Explicit routes take priority: a matching condition, preferred label,
  suggested next node, or handler jump keeps the outcome failed. A failed
  outcome takes an unconditional edge only under route, so under succeed
  any edge selection is an explicit route
- succeed applies only to failed, matching exit; the auto_status alias no
  longer promotes partially_succeeded
- Parallel branches promote after their retry loop, so a failed succeed
  branch counts as succeeded in the parent aggregate
- Validation accepts succeed and adds an auto_status_deprecated warning
  that suggests on_failure="succeed"
- Document the policy table, semantics, and deprecation; add a changelog
  entry

Closes #807

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 07:34:24 -04:00
Bryan Helmkamp
24165b10f5
Add --name to fabro mcp config and fabro mcp init
Both commands always registered the MCP client entry under the fixed
`mcpServers` key `fabro`, so users could not register separate Fabro
servers (for example production and testing) without editing the client
JSON by hand.

`--name <NAME>` now selects the `mcpServers` key. It defaults to `fabro`
for backward compatibility and rejects empty values. `fabro mcp init`
upserts only the named entry and preserves entries with other names, so
reusing a name updates that entry in place.

Closes #808

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-26 07:34:06 -04:00
Bryan Helmkamp
c90d195c2f
Merge pull request #806 from fabro-sh/node-on-failure
Add node-level on_failure override
2026-08-26 07:01:49 -04:00
fabro-releases[bot]
1289144f03 Bump version to 0.337.0-nightly.0 2026-08-26 09:31:24 +00:00
Bryan Helmkamp
105f180d3d
Simplify node failure policy resolution 2026-08-25 20:10:05 -04:00
Bryan Helmkamp
69f9d40499
Merge pull request #805 from fabro-sh/model-stylesheet-templates
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
Add model stylesheet templates
2026-08-25 19:02:08 -04:00
Bryan Helmkamp
491babe5da
Add node-level on_failure override
A node can now set its own on_failure attribute to override the
graph-level failed-node routing policy in either direction: a
best-effort node can keep route inside an exit graph, and a critical
node can exit while the rest of the graph keeps the default. An absent
node attribute inherits the graph policy.

- Node::on_failure returns Option<OnFailure> so absence means inherit
- Graph::resolve_on_failure(node_id) is the single resolution point,
  returning ResolvedOnFailure { policy, scope } so the executor's
  end-of-run message names the scope that stopped routing
- The core Graph trait method becomes resolve_on_failure(node_id); the
  graph-scope failure message is unchanged
- The failed-human-gate fallthrough block stays independent of a
  node-level route override
- Validation now accepts and value-checks node-level on_failure (it
  previously warned that node placement had no effect) and keeps the
  edge-placement warning with updated wording
- Document precedence in transitions, failures, and the DOT reference,
  and extend today's changelog entry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Chraa21RK7i2KqHdZSJLb8
2026-08-25 18:55:39 -04:00
Bryan Helmkamp
74e2c3597c
Simplify model stylesheet template plumbing
Apply cleanup review findings on the model stylesheet template branch:

- Move the root-only stylesheet rule into visit_graph_references via a
  GraphPosition parameter, so the bundler and workflow-version stop
  re-implementing the entrypoint guard with duplicated match arms
- Let ModelStylesheetTemplateTransform build its own template store and
  skip the pass entirely when the graph has no stylesheet; drop its dead
  Transform impl and the template_render_store re-export
- Parse fix-message namespaces with the typed Namespace enum, share the
  vars/goal fix strings with script_interpolation_fix, and replace the
  attribute_name magic-string check with a restricted-namespace fix the
  stylesheet transform sets on its own render target
- Drop template_render_store's content parameter; the store's render
  always overwrites it before rendering
- Trim redundant tests and add a transform_options() helper in
  pipeline/validate.rs tests

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019FBHEs42qNHDeKmsqTSDSQ
2026-08-25 18:54:06 -04:00
Bryan Helmkamp
a522414bdc
Add model stylesheet templates 2026-08-25 18:14:25 -04:00
Scott Werner
ca9fb1d262 Align folder target warn logs with tracing style
Capture the error with Debug so the source chain stays visible, and use
lowercase fixed message strings per the logging guidelines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 15:40:29 -04:00
Bryan Helmkamp
9223349101
Merge pull request #803 from fabro-sh/model-test-tools-reasoning-effort
feat(model): add tool and reasoning test controls
2026-08-25 15:39:18 -04:00
Bryan Helmkamp
fb1ecfe23f
Merge pull request #804 from fabro-sh/codex/graph-on-failure
Add graph on_failure exit policy
2026-08-25 15:39:10 -04:00
Scott Werner
9dc39ce9fa Simplify folder target admission and startup checks
Collapse the triple Folder dispatch in run-intent admission into a single
prepare_intent_target call that canonicalizes and observes Git under one
provider gate, and stop feeding target/git into the compiler input only to
overwrite them afterwards. In run start, hoist the duplicated Folder
rejection out of the Docker and Daytona arms, restore kind_name() for the
Git/None arm, and drop the unreachable absolute/symlink checks that follow
canonicalize. Dedupe the folder-target test fixtures in both crates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 14:53:31 -04:00
Bryan Helmkamp
32d6be7ea5
refactor(model): simplify model test plumbing
Review cleanups for the tools/reasoning-effort model test change:

- Extract a shared parse_query_enum helper in the models handler in
  place of two copy-pasted parse-or-400 match blocks.
- Collapse the duplicated basic-probe pipeline in fabro-llm behind a
  single basic_probe core; name the shared EXPANDED_MAX_TOKENS budget.
- Pass &ModelTestArgs to test_models_via_server instead of threading
  five of its fields positionally.
- Dedupe the two forwarding CLI integration tests behind a helper.
- Derive clap::ValueEnum for ReasoningEffort behind a feature-gated
  clap dep (same pattern as MergeStrategy in fabro-types) so --help,
  cli.mdx, and error output list effort values from the enum instead
  of a hand-written list that drifts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TDdjG18d2AHh7mFWXFkBLn
2026-08-25 14:49:34 -04:00
Bryan Helmkamp
15d1ef5b2c
Simplify on_failure validation rule and tests
- Dedup Diagnostic construction in the on_failure_valid rule
- Use the shared node_with_attrs test helper
- Drop an executor test that duplicated existing retry-target coverage
- Build on_failure integration test graphs from DOT and share a run
  harness, exercising the parser path for valid on_failure values

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J6MnJri6oSEMZaYeADY5dP
2026-08-25 14:49:05 -04:00
Scott Werner
b5d517e4b5 Gate folder path access behind Local admission 2026-08-25 14:10:24 -04:00
Bryan Helmkamp
b4092af89f
Add graph on_failure exit policy 2026-08-25 13:45:51 -04:00
Bryan Helmkamp
5ead0145b9
feat(model): separate tool and reasoning tests 2026-08-25 13:36:51 -04:00
Scott Werner
c396a6cf6f Add local folder run target 2026-08-25 11:59:37 -04:00
Scott Werner
679d20cb52
Merge pull request #792 from fabro-sh/codex/sqlite-authorization-codes
Move pending CLI authorizations to SQLite
2026-08-25 11:46:10 -04:00
Scott Werner
0001cfba02
Merge pull request #789 from fabro-sh/codex/run-intent-none-target
Add empty workspace run target
2026-08-25 11:25:41 -04:00
fabro-releases[bot]
e74f3c6c4b Bump version to 0.336.0-nightly.1 2026-08-25 13:26:02 +00:00
Bryan Helmkamp
1465082447
Merge pull request #797 from fabro-sh/github-app-install-error-wording
fix(github): name both causes of an installation lookup 404
2026-08-25 09:09:28 -04:00
Bryan Helmkamp
4015754f15
Merge pull request #801 from fabro-sh/fix-798-sandbox-runtime-blobs
fix(sandbox): materialize prompt blobs in runtime storage, not the checkout
2026-08-25 09:09:16 -04:00
Bryan Helmkamp
f322025b3d
refactor(sandbox): home the runtime directory under the system tmp dir
Use /tmp/fabro/runtime for both Docker and Daytona instead of
provider-specific roots. A writable /tmp inside the sandbox is already
a dependency (commit-message files, exec stop-files), it needs no
root-level mkdir for non-root container users, and it makes the two
providers uniform.

The trailing runtime path component stays load-bearing: materialized
blobs at runtime/blobs/{hash}.json are recognized as managed blob
references and normalized back to blob:// in durable context.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Kmn5jyrdpyCdvcfvmEDvA
2026-08-25 07:21:24 -04:00
Bryan Helmkamp
b4fd7ae00b
fix(sandbox): materialize prompt blobs in runtime storage, not the checkout
Remote prompt-value materialization wrote demoted values to
{working_directory}/.fabro/blobs inside the repository checkout, so a
later checkpoint could commit them and leak them into the run pull
request.

Give each sandbox a run-scoped runtime directory outside the source
checkout as part of the Sandbox contract:

- Sandbox::runtime_directory() names the directory; host-local
  sandboxes return None because the engine owns a host-side runtime
  directory (RunScratch) for those runs.
- Docker creates /fabro/runtime at initialize with umask 077 and
  uploads runtime files with mode 0600.
- Daytona creates /home/daytona/fabro/runtime with mode 0700.
- Both remote materialization paths in fabro-workflow share one
  materialization-path helper built on the new contract. The paths keep
  the runtime/blobs suffix, so durable context still normalizes to
  blob://sha256/... references.
- Local materialization now writes owner-private directories and files
  on Unix.

Regression coverage: an integration test runs remote-style prompt
demotion against a real git checkout, then a real checkpoint commit,
and asserts the checkout stays clean, the agent-facing file is
readable, and a deleted materialized file is recreated from the
durable blob store. A real-Docker test verifies the runtime directory
and blob file permissions inside a container.

Fixes #798

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Kmn5jyrdpyCdvcfvmEDvA
2026-08-25 07:14:31 -04:00
fabro-releases[bot]
7ae7ca9ead Bump version to 0.336.0-nightly.0 2026-08-25 09:31:30 +00:00
Bryan Helmkamp
bc7635dbd1
fix(github): name both causes of an installation lookup 404
GET /repos/{owner}/{repo}/installation returns 404 both when the App is
not installed for the owner and when the installation's repository
selection excludes the repository. The single-repository mint path
reported only the first cause, which misleads users whose App is
installed but not scoped to the repository. Name both causes and the
repository in the error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:49:49 -04:00
Scott Werner
dc1f235c48 Keep retired Slate helpers test-only 2026-08-24 17:31:15 -04:00
Scott Werner
f3ff7f27a4 Keep auth code store naming consistent 2026-08-24 17:26:17 -04:00
Scott Werner
68ef8c7e89 Leave old SlateDB authorization-code records in place
Drop the startup retirement of the auth/code keyspace instead of
carrying one-shot cleanup code forever. The records it deleted are
inert: at most a handful exist at cutover, every binary (old or new)
rejects them within 60 seconds of issue via the expiry check, and
nothing reads the keyspace after the move to SQLite. The refresh-token
retirement keeps its original inline shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:25:59 -04:00
Scott Werner
a2f0167844 Simplify SQLite authorization-code cutover
Cleanup pass over the pending-CLI-authorization move to SQLite:

- Extract a shared Database::retire_keyspace helper; the refresh-token
  and authorization-code retirements are now one-line wrappers over it.
- Inline the startup retirement call (dropping the single-use wrapper,
  its context-chain test, and the test_close_slate hook it required)
  and run both SlateDB retirement scans concurrently. Error policies
  are unchanged: authorization codes fatal, refresh tokens best-effort.
- Add a shared sqlite_row module with typed identity/timestamp row
  decoding, used by both AuthorizationCodeStore and AuthSessionStore;
  the session store's stringly Error::Other corruption errors become
  the typed InvalidStoredIdentity/InvalidStoredTimestamp variants.
- Delete Repository::gc, which had no production callers left and was
  kept alive by its own test; update the record-layer docs to match.
- Deduplicate the SQLite test-support bootstrap into sqlite_test_pool,
  reuse issue() in the invalid-timestamp test instead of a copied
  INSERT, and fold the new table into the existing existence-check loop
  in the fabro-db schema test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:25:38 -04:00
Scott Werner
05999036aa Move pending CLI authorizations to SQLite 2026-08-24 17:25:19 -04:00
Scott Werner
3e0adde73d Simplify the empty workspace run target plumbing
- Use a derived deserializer for RunTarget by making `None` an empty struct
  variant, which keeps `deny_unknown_fields` strict without a hand-rolled impl
- Make clone_source_for_run the single owner of the empty-workspace decision
  and drop the duplicated target checks in RunSession::new
- Collapse duplicated target/provider compatibility matches in admission and
  start into single matches, using a strum-derived kind name for messages
- Drop the redundant git override in persist_create_run
- Extract a shared helper for the duplicated unavailable-integration test loop

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:21:54 -04:00
Bryan Helmkamp
79168d3a27
Merge pull request #796 from fabro-sh/codex/twin-openai-unknown-fields
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
fix(twin-openai): accept unknown chat fields
2026-08-24 16:46:55 -04:00
Bryan Helmkamp
300aec7f1c
fix(twin-openai): accept unknown chat fields 2026-08-24 16:41:02 -04:00
Scott Werner
2d292c28f8
Merge pull request #783 from fabro-sh/codex/sqlite-blob-startup-activation
Activate verified SQLite blob storage at server startup
2026-08-24 16:32:59 -04:00
Scott Werner
2f3b6477f2 Add empty workspace run target 2026-08-24 14:49:03 -04:00
fabro-releases[bot]
330d0f8984 Bump version to 0.335.0-nightly.1 2026-08-24 18:48:34 +00:00
Scott Werner
fb833294bf Remove stale auth-session test import 2026-08-24 14:40:38 -04:00
Bryan Helmkamp
8a24046b94
Merge pull request #793 from fabro-sh/feature/bounded-agent-tool-output
Bound oversized agent tool output
2026-08-24 14:33:14 -04:00