Designate retros as experimental, disable by default via [features] flag

Move retro control from [fabro] retro to [features] retros in project
config. Default changes from true to false — retros are now opt-in.
Add retros field to server config Features struct, OpenAPI spec,
TypeScript client, and web app config. Update docs with experimental
warning and new enablement instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-15 20:36:32 -04:00
parent ec9057a4c6
commit b604bc4b60
No known key found for this signature in database
8 changed files with 68 additions and 22 deletions

View file

@ -22,6 +22,7 @@ interface GitConfig {
interface Features {
session_sandboxes: boolean;
retros: boolean;
}
interface WebConfig {
@ -60,6 +61,7 @@ const GIT_DEFAULTS: GitConfig = {
const FEATURES_DEFAULTS: Features = {
session_sandboxes: false,
retros: false,
};
export const FABRO_CONFIG_PATH = join(homedir(), ".fabro", "server.toml");

View file

@ -71,6 +71,9 @@ auto_stop_interval = 60
[sandbox.daytona.labels]
team = "platform"
[features]
retros = true
[checkpoint]
exclude_globs = ["**/node_modules/**", "**/.cache/**"]
@ -138,6 +141,17 @@ Configure checkpoint behavior for all runs.
Exclude globs from `server.toml` and run configs are merged (union, deduplicated). See [Run Configuration — Checkpoint](/execution/run-configuration#checkpoint) for per-run configuration.
### `[features]` section
Toggle experimental or opt-in features. All features default to `false`.
| Key | Description |
|---|---|
| `retros` | Enable automatic [retro](/execution/retros) generation after workflow runs (experimental) |
| `session_sandboxes` | Enable session sandboxes in the web UI |
The same `[features]` section can be set in `fabro.toml` (project-level) to enable features per-project.
## Environment variables
Fabro reads environment variables from a `.env` file in the working directory (if present) and from the shell environment. Provider API keys are required for the models you want to use; everything else is optional.

View file

@ -4505,6 +4505,9 @@ components:
session_sandboxes:
type: boolean
description: Enable session sandboxes.
retros:
type: boolean
description: "Experimental: enable automatic retro generation after workflow runs."
# ── Discovery Schemas ────────────────────────────────────────────────

View file

@ -3,7 +3,11 @@ title: "Retros"
description: "Automatic retrospectives that analyze every workflow run"
---
After every workflow run, Fabro generates a **retro** — a structured retrospective that captures what happened, what went well, and what didn't. Retros combine deterministic metrics extracted from the run's checkpoint with a qualitative narrative produced by an LLM agent that analyzes the full event stream.
<Warning>
**Experimental feature.** Retros are disabled by default. Enable them with `[features] retros = true` in your project config or server config.
</Warning>
After every workflow run, Fabro can generate a **retro** — a structured retrospective that captures what happened, what went well, and what didn't. Retros combine deterministic metrics extracted from the run's checkpoint with a qualitative narrative produced by an LLM agent that analyzes the full event stream.
The goal is continuous improvement. Retros give you a searchable history of how your workflows perform over time, surface friction patterns that would otherwise go unnoticed, and identify follow-up work before it falls through the cracks.
@ -116,19 +120,26 @@ Retro: smooth — Successfully implemented the feature
Retro saved to ~/fabro-logs/01JKXYZ.../retro.json
```
To skip retro generation for a single run, pass `--no-retro`:
To enable retros for your project, set `retros = true` in the `[features]` section of your `fabro.toml`:
```toml title="fabro.toml"
version = 1
[features]
retros = true
```
To skip retro generation for a single run when retros are enabled, pass `--no-retro`:
```bash
fabro run workflow.fabro --no-retro
```
To disable retros project-wide, set `retro = false` in your `fabro.toml`:
Retros can also be enabled server-wide in `server.toml`:
```toml title="fabro.toml"
version = 1
[fabro]
retro = false
```toml title="server.toml"
[features]
retros = true
```
### API

View file

@ -3284,6 +3284,7 @@ mod settings {
},
features: Features {
session_sandboxes: false,
retros: false,
},
log: Default::default(),
run_defaults: fabro_workflows::cli::run_config::RunDefaults {

View file

@ -272,6 +272,7 @@ fn fully_populated_server_config() -> ServerConfig {
},
features: Features {
session_sandboxes: true,
retros: false,
},
log: LogConfig {
level: Some("debug".into()),

View file

@ -19,6 +19,8 @@ pub struct ProjectConfig {
pub version: u32,
#[serde(default)]
pub fabro: ProjectFabroConfig,
#[serde(default)]
pub features: ProjectFeatures,
#[serde(alias = "directory")]
pub work_dir: Option<String>,
pub llm: Option<LlmConfig>,
@ -60,27 +62,29 @@ impl ProjectConfig {
pub struct ProjectFabroConfig {
#[serde(default = "default_root")]
pub root: String,
#[serde(default = "default_retro")]
pub retro: bool,
}
fn default_root() -> String {
".".to_string()
}
fn default_retro() -> bool {
true
}
impl Default for ProjectFabroConfig {
fn default() -> Self {
Self {
root: default_root(),
retro: default_retro(),
}
}
}
/// Feature flags for the project. All features default to `false` (opt-in).
#[derive(Debug, Default, Deserialize, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct ProjectFeatures {
/// Experimental: enable automatic retro generation after workflow runs.
#[serde(default)]
pub retros: bool,
}
/// Parse a project config from a TOML string.
pub fn parse_project_config(content: &str) -> anyhow::Result<ProjectConfig> {
let config: ProjectConfig =
@ -342,12 +346,13 @@ fn resolve_workflow_from(
}
/// Check whether retros are enabled in the project config.
/// Returns `true` (the default) if no config is found or on error.
/// Returns `false` (the default) if no config is found or on error.
/// Retros are an experimental feature gated behind `[features] retros = true`.
pub fn is_retro_enabled() -> bool {
let start = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
match discover_project_config(&start) {
Ok(Some((_path, config))) => config.fabro.retro,
_ => true,
Ok(Some((_path, config))) => config.features.retros,
_ => false,
}
}
@ -375,7 +380,6 @@ mod tests {
version: 1,
fabro: ProjectFabroConfig {
root: ".".to_string(),
retro: true,
},
..Default::default()
}
@ -389,9 +393,15 @@ mod tests {
}
#[test]
fn parse_retro_false() {
let config = parse_project_config("version = 1\n[fabro]\nretro = false\n").unwrap();
assert!(!config.fabro.retro);
fn parse_retros_default_false() {
let config = parse_project_config("version = 1\n").unwrap();
assert!(!config.features.retros);
}
#[test]
fn parse_retros_enabled() {
let config = parse_project_config("version = 1\n[features]\nretros = true\n").unwrap();
assert!(config.features.retros);
}
#[test]

View file

@ -22,5 +22,9 @@ export interface Features {
* Enable session sandboxes.
*/
'session_sandboxes'?: boolean;
/**
* Experimental: enable automatic retro generation after workflow runs.
*/
'retros'?: boolean;
}