From 0587fae2e50d1cef705234452ec0b217bcedd25e Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Mon, 16 Mar 2026 19:06:15 -0400 Subject: [PATCH] Docs: add auto-merge config, auto-merge to GitHub features, turn-level retries Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/skills/docs/watermark | 2 +- docs/execution/failures.mdx | 13 +++++++++---- docs/execution/run-configuration.mdx | 4 ++++ docs/integrations/github.mdx | 1 + 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.claude/skills/docs/watermark b/.claude/skills/docs/watermark index 08130de4b..c29af3c95 100644 --- a/.claude/skills/docs/watermark +++ b/.claude/skills/docs/watermark @@ -1 +1 @@ -49379f08d0f26d38c25f036738c4a85cddd7a323 +610aff744609268ae879a58acfe6c9a6bb0572e0 diff --git a/docs/execution/failures.mdx b/docs/execution/failures.mdx index b48cd59fb..2daca6724 100644 --- a/docs/execution/failures.mdx +++ b/docs/execution/failures.mdx @@ -27,7 +27,7 @@ implement -> escalate [condition="failure_class=deterministic"] ## Retry layers -Fabro retries failures at two levels: **LLM retries** handle transient API errors inside a single model call, and **node retries** re-execute the entire node handler when the first level isn't enough. These layers are independent — a node retry re-runs the full handler, which gets its own fresh set of LLM retries. +Fabro retries failures at three levels: **LLM retries** handle transient API errors inside a single model call, **turn-level retries** recover from dropped streams mid-response, and **node retries** re-execute the entire node handler when the first two levels aren't enough. These layers are independent — a node retry re-runs the full handler, which gets its own fresh set of LLM and turn-level retries. ### LLM retries @@ -45,9 +45,13 @@ Only transient errors are retried: rate limits, server errors (5xx), timeouts, n If the provider returns a `Retry-After` header, Fabro respects it — unless the delay exceeds 60 seconds, in which case the call fails rather than blocking the run. +### Turn-level retries + +When an LLM stream drops mid-response (common under high concurrency), Fabro retries the same agent turn up to 3 times instead of failing the entire session. Conversation history is preserved across retries, and any partial assistant output from the interrupted stream is replayed so the model can continue where it left off. This avoids restarting the full stage from scratch for transient stream failures. + ### Node retries -When a node handler fails (after LLM retries are exhausted), the engine can retry the entire node. This is controlled by **retry policies**. +When a node handler fails (after LLM and turn-level retries are exhausted), the engine can retry the entire node. This is controlled by **retry policies**. #### Retry policies @@ -266,8 +270,9 @@ digraph Example { A node failure does **not** automatically terminate the run. Fabro follows this escalation path: 1. **LLM retries** — transient API errors are retried inside the model call (up to 3 retries) -2. **Provider failover** — if configured, switch to a fallback provider -3. **Node retries** — re-execute the entire handler (per the retry policy) +2. **Turn-level retries** — dropped streams retry the same agent turn (up to 3 retries), preserving conversation history +3. **Provider failover** — if configured, switch to a fallback provider +4. **Node retries** — re-execute the entire handler (per the retry policy) 4. **Edge routing** — if the node ultimately fails, look for an outgoing edge that matches (e.g., `condition="outcome=fail"`) 5. **Retry target** — if no matching edge exists, check `retry_target` / `fallback_retry_target` on the node and graph 6. **Run failure** — if none of the above produces a path forward, the run terminates diff --git a/docs/execution/run-configuration.mdx b/docs/execution/run-configuration.mdx index 27c330da9..4b8d25305 100644 --- a/docs/execution/run-configuration.mdx +++ b/docs/execution/run-configuration.mdx @@ -345,12 +345,16 @@ Automatically open a GitHub pull request when the workflow run completes success [pull_request] enabled = true draft = true +auto_merge = false +merge_strategy = "squash" ``` | Field | Description | |---|---| | `enabled` | When `true`, Fabro creates a PR from the agent's working branch after a successful run. Default: `false`. | | `draft` | When `true`, the PR is created as a draft pull request. Default: `true`. | +| `auto_merge` | When `true`, enables GitHub auto-merge on the created PR. Implies `draft = false` since GitHub doesn't allow auto-merge on draft PRs. The repository must have auto-merge enabled in GitHub settings. Default: `false`. | +| `merge_strategy` | Merge method when `auto_merge` is enabled: `squash` (default), `merge`, or `rebase`. | ### `[github]` diff --git a/docs/integrations/github.mdx b/docs/integrations/github.mdx index 8b2e26478..9b82eb58f 100644 --- a/docs/integrations/github.mdx +++ b/docs/integrations/github.mdx @@ -13,6 +13,7 @@ Fabro uses a [GitHub App](https://docs.github.com/en/apps/overview) to authentic | **Private repo cloning** | Daytona and Docker sandboxes clone private repositories using short-lived Installation Access Tokens | | **Checkpoint pushing** | After each workflow stage, Fabro pushes the run branch and metadata branch back to origin from inside the sandbox | | **Auto-PR** | When `[pull_request] enabled = true` in the [run config](/execution/run-configuration#pull_request), Fabro opens a PR from the agent's working branch after a successful run | +| **Auto-merge** | When `[pull_request] auto_merge = true`, Fabro enables GitHub's auto-merge on created PRs so they merge automatically once required checks pass | | **Sandbox GITHUB_TOKEN** | When `[github] permissions` are declared in the run config, Fabro mints a scoped Installation Access Token and injects it as `GITHUB_TOKEN` in the sandbox | ## Setup