diff --git a/.claude/skills/changelog/watermark b/.claude/skills/changelog/watermark
index 6d7216bae..a443028b4 100644
--- a/.claude/skills/changelog/watermark
+++ b/.claude/skills/changelog/watermark
@@ -1 +1 @@
-45ff3da4e05c7c67c909d7b860c7764b34e6a342
+ed651dcd571699e92162cf657b8eca42d7a6d6b1
diff --git a/docs/changelog/2026-03-19.mdx b/docs/changelog/2026-03-19.mdx
index b8075bb45..6567f1ab8 100644
--- a/docs/changelog/2026-03-19.mdx
+++ b/docs/changelog/2026-03-19.mdx
@@ -1,5 +1,5 @@
---
-title: "Provider login and auto-detect default provider"
+title: "Provider login, auto-detect provider, and fabro wait"
date: "2026-03-19"
---
@@ -17,12 +17,26 @@ For OpenAI, this launches the browser-based OAuth PKCE flow with an automatic fa
The CLI now checks which providers have API keys configured and automatically selects the best available one, using precedence order Anthropic > OpenAI > Gemini. Previously, running commands without an explicit `--provider` flag always defaulted to Anthropic, which caused errors for users who only had OpenAI or Gemini keys configured.
+## `fabro wait`
+
+A new `fabro wait` subcommand blocks until a workflow run reaches a terminal state and exits with a code reflecting the outcome — analogous to `docker wait`. Accepts a run ID prefix or workflow name, with an optional `--timeout` flag and `--json` output mode for scripting.
+
+```bash
+fabro wait abc123 --timeout 300
+```
+
## More
- Default Anthropic model changed from `claude-opus-4-6` to `claude-sonnet-4-6`
-- Removed OpenSSL runtime dependency — the CLI binary no longer dynamically links against `libssl` or `libcrypto`, so it runs on machines without OpenSSL v3 installed
+- Removed OpenSSL runtime dependency — the CLI binary no longer dynamically links against `libssl` or `libcrypto`
- Added `--web-url` flag to `fabro install` for specifying the web UI base URL for OAuth callbacks
+- `fabro ps` now strips markdown headings and "Plan:" prefix from the GOAL column for cleaner output
+
+
+
+- Node-level `model` attributes are now validated against the model catalog at parse time, with missing aliases surfaced as warnings
+- `reasoning_effort` is now mapped to Anthropic's `output_config.effort` parameter
@@ -32,6 +46,8 @@ The CLI now checks which providers have API keys configured and automatically se
-- Fixed OAuth callback URLs missing from CLI-generated GitHub App manifests, which caused OAuth login failures in the web UI
-- Fixed OpenAI multi-turn conversations failing because `store: false` was incorrectly set for all Responses API requests instead of only the Codex endpoint
+- Fixed agent sessions ignoring node-level `model` and `provider` attributes set in stylesheets
+- Fixed `fabro upgrade` failing with "No such file or directory"
+- Fixed OAuth callback URLs missing from CLI-generated GitHub App manifests
+- Fixed OpenAI multi-turn conversations failing because `store: false` was incorrectly set for all Responses API requests
diff --git a/docs/changelog/2026-03-20.mdx b/docs/changelog/2026-03-20.mdx
new file mode 100644
index 000000000..9ff6053d7
--- /dev/null
+++ b/docs/changelog/2026-03-20.mdx
@@ -0,0 +1,35 @@
+---
+title: "Composable run lifecycle: create, start, attach"
+date: "2026-03-20"
+---
+
+## `fabro create` / `start` / `attach`
+
+`fabro run` has been decomposed into three composable primitives following the Docker-style lifecycle model. `fabro create` allocates the run directory, `fabro start` spawns the detached engine process, and `fabro attach` tails progress with live rendering and handles human-in-the-loop interactions. `fabro run` remains the all-in-one command — it now composes these three steps internally, and `--detach` simply skips the attach step.
+
+This enables new automation patterns: create a run, start it in the background, and attach later — or script CI pipelines that create and start without ever attaching.
+
+```bash
+fabro create my-workflow --goal "Implement feature X"
+fabro start
+fabro attach
+```
+
+## More
+
+
+- Added Linux ARM64 (`aarch64-unknown-linux-gnu`) release target
+- `fabro logs` and `fabro attach` now show tool details for `spawn_agent`, `use_skill`, `list_dir`, and all remaining agent tools
+- Subagent IDs now use short hex strings instead of UUIDs for readability
+
+
+
+- `StageStarted` events are now emitted on retry attempts for better observability
+- Added bundled `implement-issue` workflow for implementing GitHub issues via `fabro run implement-issue`
+- Added bundled `gh-triage` workflow for checking open PRs and issues via `gh` CLI
+- Model aliases in graph nodes are now resolved to canonical IDs at parse time
+
+
+
+- Updated `tar` crate to 0.4.45 (security fix)
+
diff --git a/docs/changelog/2026-03-21.mdx b/docs/changelog/2026-03-21.mdx
new file mode 100644
index 000000000..fdf2c64e9
--- /dev/null
+++ b/docs/changelog/2026-03-21.mdx
@@ -0,0 +1,33 @@
+---
+title: "Anthropic fast mode and deep model testing"
+date: "2026-03-21"
+---
+
+## Anthropic fast mode
+
+You can now enable Anthropic's fast mode for up to 2.5x faster output from Claude Opus 4.6 by setting `speed: fast` in your workflow stylesheet. This is useful for latency-sensitive stages where throughput matters more than cost.
+
+```dot
+graph {
+ graph [stylesheet="speed=fast"]
+}
+```
+
+## `fabro model test --deep`
+
+Model validation now supports a `--deep` flag that runs multi-turn tool-use conversations to verify that a provider handles the full agent loop correctly — not just single-turn completions. Tests run concurrently with a progress bar.
+
+```bash
+fabro model test --deep
+```
+
+## More
+
+
+- Fixed workflow TOML config being lost when running in detach mode
+- Fixed edge `thread_id` precedence to match documented fidelity behavior
+- Fixed Sonnet 4.5 `reasoning_effort` parameter error by converting to the thinking API format
+- Fixed OpenAI reasoning round-trip losing encrypted content by setting `store: false`
+- Fixed OpenAI provider incorrectly omitting `store: true` from requests
+- Suppressed stderr output noise in detach and create modes
+
diff --git a/docs/changelog/2026-03-22.mdx b/docs/changelog/2026-03-22.mdx
new file mode 100644
index 000000000..272eb8a9b
--- /dev/null
+++ b/docs/changelog/2026-03-22.mdx
@@ -0,0 +1,15 @@
+---
+title: "fabro resume subcommand"
+date: "2026-03-22"
+---
+
+## `fabro resume`
+
+Resuming workflows previously required constructing a `fabro run --run-branch fabro/run/` invocation manually. The new `fabro resume` subcommand accepts a run ID or prefix directly, matching the ergonomics of `fabro rewind` and `fabro fork`. Checkpoint-file-based resumption is also supported.
+
+```bash
+fabro resume abc123
+fabro resume --checkpoint path/to/checkpoint.json --workflow workflow.fabro
+```
+
+The unified foreground run path now uses the `create` → `start` → `attach` lifecycle internally, ensuring consistent behavior whether you run, resume, or rewind a workflow.
diff --git a/docs/changelog/2026-03-23.mdx b/docs/changelog/2026-03-23.mdx
new file mode 100644
index 000000000..e3d47ecda
--- /dev/null
+++ b/docs/changelog/2026-03-23.mdx
@@ -0,0 +1,30 @@
+---
+title: "Unlimited tool rounds and workflow syntax improvements"
+date: "2026-03-23"
+---
+
+## Unlimited agent tool rounds
+
+Agent stages no longer have an artificial cap on tool rounds per input or subagent turns. Previously, the default limits could cause agents to stop mid-task on complex operations. Both `max_tool_rounds_per_input` and subagent `max_turns` now default to unlimited, so agents run until they complete their work or hit the context window.
+
+## More
+
+
+- Condition expressions now support quoted strings: `edge [label="status == \"ready\""]`
+- `"end"` and `"End"` are now recognized as exit node identifiers alongside `"END"`
+- Edge selection now falls back to the default edge when no condition matches, instead of erroring
+- `default_max_retries` attribute renamed to `max_retries` on graph-level stylesheets
+- Removed `error_policy` and `k_of_n`/`quorum` attributes from parallel nodes — parallel stages now always wait for all branches
+
+
+
+- Subagents are now automatically cleaned up when a session closes, preventing orphaned background processes
+- All 5xx HTTP status codes from LLM providers are now classified as retryable server errors
+- Request timeouts from LLM providers are now treated as non-retryable by default to avoid redundant retries on slow requests
+
+
+
+- Fixed workflow slug lookup failing for split and resumed runs
+- Fixed split run metadata being lost across engine restarts
+- Fixed split run lifecycle lookup returning stale state
+
diff --git a/docs/changelog/2026-03-26.mdx b/docs/changelog/2026-03-26.mdx
new file mode 100644
index 000000000..170451a22
--- /dev/null
+++ b/docs/changelog/2026-03-26.mdx
@@ -0,0 +1,23 @@
+---
+title: "Pull request pipeline stage and resume reliability"
+date: "2026-03-26"
+---
+
+## Pull request pipeline stage
+
+Workflows can now automatically create pull requests as part of the run pipeline. When a workflow finishes with code changes, the new `pull_request` pipeline stage creates a PR on the target repository with the run's diff, title, and description — no manual `gh pr create` step needed. This integrates with the existing GitHub App authentication and respects the workflow's git configuration.
+
+## More
+
+
+- `fabro resume` now rejects already-succeeded runs with a clear error instead of silently restarting them
+- Resume now validates the checkpoint file before cleaning up state, preventing partial cleanup on corrupt checkpoints
+- `fabro attach` now detects early init failures and rolls back partial worktree state automatically
+- Added restore operation that rebuilds runtime state from the checkpoint when resuming interrupted runs
+
+
+
+- Fixed resume creating unnecessary worktrees and failing to keep the sleep inhibitor alive
+- Fixed git checkpoint options not being threaded through to the resume path
+- Fixed verification regressions introduced by the runtime initialization refactor
+
diff --git a/docs/changelog/2026-03-27.mdx b/docs/changelog/2026-03-27.mdx
new file mode 100644
index 000000000..e833e63dd
--- /dev/null
+++ b/docs/changelog/2026-03-27.mdx
@@ -0,0 +1,30 @@
+---
+title: "fabro config show, preflight subcommand, and storage-dir"
+date: "2026-03-27"
+---
+
+## `fabro config show`
+
+A new `fabro config show` command displays the fully resolved configuration for a workflow, showing how CLI flags, environment variables, project config, and workflow defaults are layered together. This makes it easy to debug configuration issues without guessing which layer is winning.
+
+```bash
+fabro config show my-workflow
+```
+
+## `fabro preflight`
+
+Preflight validation has been extracted from `fabro run --preflight` into its own top-level command. This makes it easier to validate a workflow before running it, especially in CI pipelines where you want a separate validation step.
+
+```bash
+fabro preflight my-workflow
+```
+
+
+**`--run-dir` renamed to `--storage-dir`.** The `--run-dir` CLI flag has been renamed to `--storage-dir` to better reflect its purpose as the base storage directory. Runs are now created under `/runs/` automatically. The `data_dir` config key is also renamed to `storage_dir` (a serde alias preserves backward compatibility for config files).
+
+
+## More
+
+
+- Added `goal_file` and `labels` fields to workflow configuration for specifying goals from files and tagging runs with metadata
+
diff --git a/docs/changelog/2026-03-28.mdx b/docs/changelog/2026-03-28.mdx
new file mode 100644
index 000000000..8eb54037e
--- /dev/null
+++ b/docs/changelog/2026-03-28.mdx
@@ -0,0 +1,24 @@
+---
+title: "File-based workflow imports"
+date: "2026-03-28"
+---
+
+## Workflow imports
+
+Workflows can now import subgraphs from other `.fabro` or `.dot` files, enabling reuse of common patterns across workflows. Imported graphs are merged into the parent workflow at parse time, with node name prefixing to avoid collisions. This replaces the previous `graph_merge` approach with a more flexible file-based import system.
+
+```dot
+graph {
+ graph [import="shared/review-loop.fabro"]
+}
+```
+
+## More
+
+
+- Detached engine processes now have descriptive OS-level process titles (visible in `ps` and activity monitors)
+
+
+
+- Fixed a panic when checking if a process is alive on systems where PID values exceed `i32::MAX`
+
diff --git a/docs/changelog/2026-03-29.mdx b/docs/changelog/2026-03-29.mdx
new file mode 100644
index 000000000..e6e82bdcf
--- /dev/null
+++ b/docs/changelog/2026-03-29.mdx
@@ -0,0 +1,18 @@
+---
+title: "Store dump export command"
+date: "2026-03-29"
+---
+
+## `fabro store dump`
+
+A new `fabro store dump` command exports the contents of the run store to a human-readable format for debugging and inspection. This is useful for diagnosing issues with run state, verifying data integrity after migrations, or extracting run data for external analysis.
+
+```bash
+fabro store dump
+```
+
+## More
+
+
+- Fixed store migration gaps affecting retro agent data, finalize commits, engine failure records, and hydration tolerance
+
diff --git a/docs/docs.json b/docs/docs.json
index 3db7ea916..039397008 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -273,6 +273,14 @@
"group": "March 2026",
"icon": "clock-rotate-left",
"pages": [
+ "changelog/2026-03-29",
+ "changelog/2026-03-28",
+ "changelog/2026-03-27",
+ "changelog/2026-03-26",
+ "changelog/2026-03-23",
+ "changelog/2026-03-22",
+ "changelog/2026-03-21",
+ "changelog/2026-03-20",
"changelog/2026-03-19",
"changelog/2026-03-18",
"changelog/2026-03-17",