checkpoint

⚒️ Generated with [Fabro](https://fabro.sh)
This commit is contained in:
Fabro 2026-05-22 15:40:48 -04:00
parent ffda695644
commit a22aefee73
6 changed files with 586 additions and 26 deletions

344
run.json

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,107 @@
diff --git a/docs/public/administration/server-configuration.mdx b/docs/public/administration/server-configuration.mdx
index 8552987b6..39cc026a3 100644
--- a/docs/public/administration/server-configuration.mdx
+++ b/docs/public/administration/server-configuration.mdx
@@ -398,4 +398,4 @@ Fabro resolves these from `process env -> server.env`.
| Variable | Default | Description |
|---|---|---|
| `FABRO_LOG` | `info` | Log level: `error`, `warn`, `info`, `debug` |
-| `FABRO_LOG_DESTINATION` | Command-mode default | Server log destination: `file` or `stdout` |
\ No newline at end of file
+| `FABRO_LOG_DESTINATION` | Command-mode default | Server log destination: `file` or `stdout` |
diff --git a/docs/public/execution/run-configuration.mdx b/docs/public/execution/run-configuration.mdx
index 9439ba073..14891af32 100644
--- a/docs/public/execution/run-configuration.mdx
+++ b/docs/public/execution/run-configuration.mdx
@@ -560,4 +560,4 @@ Use `fabro preflight` to validate a run config without executing it:
```bash
fabro preflight run.toml
-```
\ No newline at end of file
+```
diff --git a/lib/crates/fabro-workflow/src/handler/parallel.rs b/lib/crates/fabro-workflow/src/handler/parallel.rs
index 885df80a1..4ec7fbcd8 100644
--- a/lib/crates/fabro-workflow/src/handler/parallel.rs
+++ b/lib/crates/fabro-workflow/src/handler/parallel.rs
@@ -195,7 +195,7 @@ impl Handler for ParallelHandler {
None,
&gs.checkpoint_exclude_globs,
&gs.git_author,
- gs.checkpoint_skip_hooks,
+ gs.checkpoint_skip_git_hooks,
)
.await;
match result {
@@ -321,7 +321,7 @@ impl Handler for ParallelHandler {
.unwrap_or_default();
let skip_git_hooks = git_state
.as_ref()
- .is_some_and(|gs| gs.checkpoint_skip_hooks);
+ .is_some_and(|gs| gs.checkpoint_skip_git_hooks);
let group_id = parallel_group_id.clone();
let branch_scope = StageScope::for_parallel_branch(
setup.target_id.clone(),
@@ -677,9 +677,10 @@ fn parallel_branch_commit_cmd(
skip_git_hooks: bool,
) -> String {
let no_verify = if skip_git_hooks { " --no-verify" } else { "" };
- format!(
- "{git_remote} -c 'user.name={author_name}' -c 'user.email={author_email}' commit --allow-empty{no_verify} -m '{message}'",
- )
+ let name = fabro_sandbox::shell_quote(&format!("user.name={author_name}"));
+ let email = fabro_sandbox::shell_quote(&format!("user.email={author_email}"));
+ let msg = fabro_sandbox::shell_quote(message);
+ format!("{git_remote} -c {name} -c {email} commit --allow-empty{no_verify} -m {msg}")
}
#[cfg(test)]
diff --git a/lib/crates/fabro-workflow/src/pipeline/execute.rs b/lib/crates/fabro-workflow/src/pipeline/execute.rs
index dfd22c655..4a82a509c 100644
--- a/lib/crates/fabro-workflow/src/pipeline/execute.rs
+++ b/lib/crates/fabro-workflow/src/pipeline/execute.rs
@@ -63,7 +63,7 @@ pub async fn execute(init: Initialized) -> Executed {
run_branch: git.run_branch.clone(),
meta_branch: git.meta_branch.clone(),
checkpoint_exclude_globs: run_options.checkpoint_exclude_globs(),
- checkpoint_skip_hooks: run_options.checkpoint_skip_git_hooks(),
+ checkpoint_skip_git_hooks: run_options.checkpoint_skip_git_hooks(),
git_author: run_options.git_author(),
}))
});
diff --git a/lib/crates/fabro-workflow/src/sandbox_git.rs b/lib/crates/fabro-workflow/src/sandbox_git.rs
index eeace9f84..cd7dfe7c4 100644
--- a/lib/crates/fabro-workflow/src/sandbox_git.rs
+++ b/lib/crates/fabro-workflow/src/sandbox_git.rs
@@ -22,13 +22,13 @@ pub struct GitCommandError {
/// Captured git state for a workflow run, shared with handlers.
#[derive(Debug, Clone)]
pub struct GitState {
- pub run_id: RunId,
- pub base_sha: String,
- pub run_branch: Option<String>,
- pub meta_branch: Option<String>,
- pub checkpoint_exclude_globs: Vec<String>,
- pub checkpoint_skip_hooks: bool,
- pub git_author: GitAuthor,
+ pub run_id: RunId,
+ pub base_sha: String,
+ pub run_branch: Option<String>,
+ pub meta_branch: Option<String>,
+ pub checkpoint_exclude_globs: Vec<String>,
+ pub checkpoint_skip_git_hooks: bool,
+ pub git_author: GitAuthor,
}
pub const GIT_REMOTE: &str =
diff --git a/lib/packages/fabro-api-client/src/models/run-checkpoint-settings.ts b/lib/packages/fabro-api-client/src/models/run-checkpoint-settings.ts
index 22f96ffc3..9b36fe41a 100644
--- a/lib/packages/fabro-api-client/src/models/run-checkpoint-settings.ts
+++ b/lib/packages/fabro-api-client/src/models/run-checkpoint-settings.ts
@@ -22,4 +22,4 @@ export interface RunCheckpointSettings {
* @memberof RunCheckpointSettings
*/
'skip_git_hooks': boolean;
-}
\ No newline at end of file
+}

View file

@ -0,0 +1,6 @@
{
"outcome": "succeeded",
"notes": "Stage completed: simplify_opus",
"failure_reason": null,
"timestamp": "2026-05-22T19:35:34.698097Z"
}

View file

@ -0,0 +1,129 @@
Goal: ---
title: Add run.checkpoint.skip_git_hooks
type: feat
status: active
date: 2026-05-22
---
# Add `run.checkpoint.skip_git_hooks`
## Summary
Add an opt-in setting:
```toml
[run.checkpoint]
skip_git_hooks = true
```
When enabled, Fabro-created run-branch checkpoint commits bypass Git commit hooks. Default remains `false`, preserving current behavior. This setting does not affect Fabro workflow hooks or metadata-branch snapshots.
## Key Changes
- Add `skip_git_hooks: bool` to dense checkpoint settings in `fabro-types`, defaulting to `false`.
- Add `skip_git_hooks: Option<bool>` to sparse `fabro-config::RunCheckpointLayer` so layered config can distinguish unset from explicit `false`.
- Update checkpoint layer merging so `exclude_globs` keeps its existing replace/inherit behavior and `skip_git_hooks` uses normal override semantics.
- Update checkpoint resolution so missing config resolves to `skip_git_hooks = false`.
- Thread the resolved setting into run-branch checkpoint commit creation.
- Append the hook-skipping commit option only for Fabro-managed run-branch checkpoint commits, including:
- normal lifecycle checkpoint commits in `sandbox_git.rs`
- parallel base checkpoint commits through the same helper
- parallel branch worktree commits in `handler/parallel.rs`
- Update OpenAPI `RunCheckpointSettings` and regenerate the TypeScript API client so persisted run settings expose the new field.
- Update user docs/options reference to document `skip_git_hooks`, its default, and that it does not disable Fabro `[[run.hooks]]`.
## Test Plan
- `fabro-config` tests:
- `[run.checkpoint] skip_git_hooks = true` resolves to `true`.
- omitted `skip_git_hooks` resolves to `false`.
- higher-layer `skip_git_hooks = false` overrides lower-layer `true`.
- `exclude_globs` merging behavior remains unchanged.
- `fabro-workflow` tests:
- checkpoint commit command includes the hook-skip option when enabled.
- checkpoint commit command omits it when disabled.
- parallel branch commit command respects the setting.
- API/client tests:
- `WorkflowSettings` / `RunCheckpointSettings` round-trip includes `skip_git_hooks`.
- OpenAPI-generated Rust and TypeScript clients reflect the new boolean field.
- Regression:
- existing git checkpoint tests still pass, including metadata branch tests.
## Assumptions
- The setting applies to Git commit hooks for run-branch checkpoint commits; it does not change metadata-branch behavior because metadata snapshots already use `git2` and do not fire local hooks.
- The setting does not disable Fabro lifecycle hooks under `[[run.hooks]]`.
- Default `false` is required for backward compatibility.
## Completed stages
- **toolchain**: succeeded
- Script: `command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1`
- Output:
```
cargo 1.95.0 (f2d3ce0bd 2026-03-21)
```
- **preflight_compile**: succeeded
- Script: `cargo check -q --workspace 2>&1`
- Output: (empty)
- **preflight_lint**: succeeded
- Script: `cargo +nightly-2026-04-14 clippy -q --workspace --all-targets -- -D warnings 2>&1`
- Output: (empty)
- **implement**: succeeded
- Model: claude-opus-4-7, 150.3k tokens in / 39.4k out
- Files: /home/daytona/workspace/fabro/docs/public/administration/server-configuration.mdx, /home/daytona/workspace/fabro/docs/public/api-reference/fabro-api.yaml, /home/daytona/workspace/fabro/docs/public/execution/run-configuration.mdx, /home/daytona/workspace/fabro/lib/crates/fabro-api/tests/workflow_settings_round_trip.rs, /home/daytona/workspace/fabro/lib/crates/fabro-cli/tests/it/cmd/attach.rs, /home/daytona/workspace/fabro/lib/crates/fabro-cli/tests/it/cmd/inspect.rs, /home/daytona/workspace/fabro/lib/crates/fabro-config/src/layers/combine.rs, /home/daytona/workspace/fabro/lib/crates/fabro-config/src/layers/run.rs, /home/daytona/workspace/fabro/lib/crates/fabro-config/src/resolve/run.rs, /home/daytona/workspace/fabro/lib/crates/fabro-config/src/tests/resolve_run.rs, /home/daytona/workspace/fabro/lib/crates/fabro-types/src/settings/run.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/handler/parallel.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/lifecycle/git.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/pipeline/execute.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/run_options.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/sandbox_git.rs, /home/daytona/workspace/fabro/lib/packages/fabro-api-client/src/models/run-checkpoint-settings.ts
- **simplify_opus**: succeeded
- Model: claude-opus-4-7, 46.9k tokens in / 13.0k out
- Files: /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/handler/parallel.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/pipeline/execute.rs, /home/daytona/workspace/fabro/lib/crates/fabro-workflow/src/sandbox_git.rs
# Simplify: Code Review and Cleanup
Review changes vs. origin for reuse, quality, and efficiency. Fix any issues found.
## Phase 1: Identify Changes
Run git diff (or git diff HEAD if there are staged changes) to see what changed. If there are no git changes, review the most recently modified files that the user mentioned or that you edited earlier in this conversation.
## Phase 2: Launch Three Review Agents in Parallel
Use the Agent tool to launch all three agents concurrently in a single message. Pass each agent the full diff so it has the complete context.
### Agent 1: Code Reuse Review
For each change:
1. Search for existing utilities and helpers that could replace newly written code. Use Grep to find similar patterns elsewhere in the codebase — common locations are utility directories, shared modules, and files adjacent to the changed ones.
2. Flag any new function that duplicates existing functionality. Suggest the existing function to use instead.
3. Flag any inline logic that could use an existing utility — hand-rolled string manipulation, manual path handling, custom environment checks, ad-hoc type guards, and similar patterns are common candidates.
Note: This is a greenfield app, so focus on maximizing simplicity and don't worry about changing things to achieve it.
### Agent 2: Code Quality Review
Review the same changes for hacky patterns:
1. Redundant state: state that duplicates existing state, cached values that could be derived, observers/effects that could be direct calls
2. Parameter sprawl: adding new parameters to a function instead of generalizing or restructuring existing ones
3. Copy-paste with slight variation: near-duplicate code blocks that should be unified with a shared abstraction
4. Leaky abstractions: exposing internal details that should be encapsulated, or breaking existing abstraction boundaries
5. Stringly-typed code: using raw strings where constants, enums (string unions), or branded types already exist in the codebase
Note: This is a greenfield app, so be aggressive in optimizing quality.
### Agent 3: Efficiency Review
Review the same changes for efficiency:
1. Unnecessary work: redundant computations, repeated file reads, duplicate network/API calls, N+1 patterns
2. Missed concurrency: independent operations run sequentially when they could run in parallel
3. Hot-path bloat: new blocking work added to startup or per-request/per-render hot paths
4. Unnecessary existence checks: pre-checking file/resource existence before operating (TOCTOU anti-pattern) — operate directly and handle the error
5. Memory: unbounded data structures, missing cleanup, event listener leaks
6. Overly broad operations: reading entire files when only a portion is needed, loading all items when filtering for one
## Phase 3: Fix Issues
Wait for all three agents to complete. Aggregate their findings and fix each issue directly. If a finding is a false positive or not worth addressing, note it and move on — do not argue with the finding, just skip it.
When done, briefly summarize what was fixed (or confirm the code was already clean).

View file

@ -0,0 +1,5 @@
{
"mode": "agent",
"provider": "openai",
"model": "gpt-5.5"
}

View file

@ -0,0 +1,21 @@
Review/cleanup complete. I found and fixed two issues:
- Added `skip_git_hooks: false` to the `WorkflowSettings` sample object in `apps/fabro-web/app/routes/automation-detail.tsx`, since the generated API client now requires the field.
- Added machine-readable `default: false` to OpenAPI `RunCheckpointSettings.skip_git_hooks` in `docs/public/api-reference/fabro-api.yaml`.
Validation run:
- `cargo test -p fabro-api --test workflow_settings_round_trip`
- `cargo test -p fabro-config run_checkpoint_skip_git_hooks`
- `cargo test -p fabro-workflow skip_hooks`
- `git diff --check`
Attempted but could not complete due local tool/dependency environment:
- `cd apps/fabro-web && bun run typecheck` failed because `tsc` is not installed/found.
- `cd lib/packages/fabro-api-client && bun run generate` failed during OpenAPI generator CLI startup; no generated files were changed.
Current uncommitted cleanup changes:
- `apps/fabro-web/app/routes/automation-detail.tsx`
- `docs/public/api-reference/fabro-api.yaml`