Skip to content

Commit 527049f

Browse files
committed
Update commit documentation to reflect default behavior of fast commit with deferred Codex review; clarify options for blocking review and configuration defaults.
1 parent 96f37f2 commit 527049f

11 files changed

Lines changed: 589 additions & 70 deletions

File tree

‎docs/commands/commit.md‎

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# f commit
22

3-
AI-powered commit with code review and GitEdit sync.
3+
AI-powered commit with deferred Codex review and GitEdit sync.
44

55
## Overview
66

7-
Stages all changes, runs AI code review for bugs and security issues, generates a commit message, commits, pushes, and syncs AI sessions to gitedit.dev.
7+
Stages all changes, commits quickly by default, runs Codex deep review asynchronously in the background, pushes, and syncs AI sessions to gitedit.dev.
88

99
## Quick Start
1010

1111
```bash
12-
# Standard commit with review
12+
# Default flow: commit now, Codex review runs in background
1313
f commit
1414

15-
# Fast commit (no AI review), then Codex reviews async in background
16-
f commit --quick
15+
# Blocking pre-commit review (legacy behavior)
16+
f commit --slow
1717

1818
# Fast commit with custom message (no AI review, no Codex follow-up)
1919
f commit --fast "fix typo"
@@ -42,7 +42,8 @@ f commit -m "Fixes #123"
4242
| `--sync` | | Run synchronously (don't delegate to hub) |
4343
| `--context` | | Include AI session context in code review |
4444
| `--dry` | | Dry run: show context without committing |
45-
| `--quick` | | Commit now, run Codex review async in background |
45+
| `--quick` | | Explicitly use fast commit + async Codex review (compat alias) |
46+
| `--slow` | | Run blocking pre-commit review before commit |
4647
| `--fast [MSG]` | | Fast commit with no AI review (defaults to ".") |
4748
| `--codex` | | Use Codex instead of Claude for review |
4849
| `--review-model <MODEL>` | | Choose specific review model |
@@ -69,15 +70,15 @@ f commit --review-model codex-high
6970

7071
## Fast Commit + Deferred Codex Review
7172

72-
Two flags for skipping the synchronous AI review when you want to commit quickly:
73+
`f commit` now uses this mode by default.
7374

74-
### `--quick` — commit now, Codex reviews later
75+
### Default (`f commit`) / `--quick` — commit now, Codex reviews later
7576

7677
Commits immediately (generates an AI commit message but skips the blocking code review), then spawns a background Codex review for that commit. The review result is queued and visible via `f commit-queue list`.
7778

7879
```bash
80+
f commit
7981
f commit --quick
80-
f commit --quick -m "wip: rough draft"
8182
```
8283

8384
What happens:
@@ -86,6 +87,15 @@ What happens:
8687
3. Spawns a background Codex process that reviews the diff
8788
4. You keep working — check results later with `f commit-queue list`
8889

90+
### `--slow` — run blocking review before commit
91+
92+
Runs the pre-commit AI review before creating the commit.
93+
94+
```bash
95+
f commit --slow
96+
f commit --slow --review-model codex-high
97+
```
98+
8999
### `--fast` — instant commit, no review at all
90100

91101
Commits with a provided message (or `"."` if omitted). No AI review, no async follow-up. Useful for trivial changes.
@@ -99,20 +109,21 @@ f commit --fast # message defaults to "."
99109

100110
| Flag | AI message | Code review | Async review | Best for |
101111
|------|-----------|-------------|-------------|----------|
102-
| (none) | Yes | Yes (blocking) | No | Normal workflow |
103-
| `--quick` | Yes | No | Yes (Codex background) | Fast iteration, review later |
112+
| (none) | Yes | No | Yes (Codex background) | Default fast workflow |
113+
| `--quick` | Yes | No | Yes (Codex background) | Explicit fast mode |
114+
| `--slow` | Yes | Yes (blocking) | No | Pre-commit deep check |
104115
| `--fast` | No (you provide) | No | No | Trivial/WIP commits |
105116

106-
### Default Fast Lane (No Extra Flags)
117+
### Opt Out Of Fast Default
107118

108-
If you want `f commit` to default to fast commit + deferred Codex review, set:
119+
If you want plain `f commit` to run blocking review by default, set:
109120

110121
```toml
111122
[commit]
112-
quick-default = true
123+
quick-default = false
113124
```
114125

115-
With this enabled, plain `f commit` behaves like `f commit --quick` unless you explicitly ask for blocking review options.
126+
With this set, plain `f commit` behaves like `f commit --slow` unless you explicitly pass `--quick`.
116127

117128
Run deep review in batches:
118129

@@ -291,7 +302,7 @@ Threshold: 500+ lines added/removed.
291302

292303
| Command | Description |
293304
|---------|-------------|
294-
| `f commit` | Full review + GitEdit sync (default) |
305+
| `f commit` | Fast commit + deferred Codex review (default) |
295306
| `f commitWithCheck` | Review without GitEdit sync |
296307
| `f commitSimple` | No review, just AI commit message |
297308

‎docs/fast-commit-deep-review-loop.md‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ This guide configures a speed-first commit workflow with deferred deep review:
99

1010
```toml
1111
[commit]
12-
quick-default = true
1312
queue = false
1413
queue_on_issues = false
1514

@@ -66,6 +65,6 @@ This replaces manual “copy `f commit` output into Codex and ask to address all
6665

6766
## Notes
6867

69-
- `quick-default = true` applies to plain `f commit` (not `f commit-with-check`) and uses the fast lane (`--quick`) unless you explicitly request blocking review options.
68+
- Plain `f commit` already uses the fast lane (`--quick`) by default. Set `quick-default = false` only if you want blocking review as the default.
7069
- Async queued Codex reviews now emit `commit_queue_review` mirror sync events to myflow/gitedit when the reviewed commit is current `HEAD` (the default `f commit --quick` flow).
7170
- `f reviews-todo codex --all` is a workflow alias over commit queue deep review.

‎docs/flow-toml-spec.md‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,19 @@ install = ["linear"] # optional: ensure skills are installed (local ~/.codex/sk
4343
# allow_direct_fallback = true
4444

4545
[commit] # optional: commit workflow defaults
46-
# quick-default = true # make `f commit` behave like `--quick` by default
46+
# quick-default = false # optional override: make plain `f commit` run blocking review (`--slow`)
4747
# queue = false # keep fast path pushing by default
4848
# queue_on_issues = false # do not force queue-only flow on review issues
4949
# message-fallbacks = ["rise:zai:glm-5", "rise:cerebras:gpt-oss-120b", "remote", "openai"]
5050
# review-fallbacks = ["glm5", "rise:cerebras:gpt-oss-120b", "codex-high"]
5151

52+
[task_resolution] # optional: nested-task disambiguation policy
53+
# preferred_scopes = ["mobile", "root"] # used when plain task name is ambiguous
54+
# warn_on_implicit_scope = true # print note when fallback routing is applied
55+
[task_resolution.routes]
56+
# dev = "mobile" # route ambiguous task name -> scope
57+
# test = "root"
58+
5259
[options] # optional: transport/runtime integrations
5360
# myflow_mirror = true # mirror commit + queue review events to myflow
5461
# myflow_url = "https://myflow.sh"
@@ -100,7 +107,8 @@ fr = "f run"
100107
- `[skills]`: optional skill enforcement; `sync_tasks` generates `.ai/skills` from tasks and `install` ensures registry skills are present (skills are gitignored by default).
101108
- `[skills.codex]`: optional Codex tuning; task skill `agents/openai.yaml` generation, post-sync force reload, and implicit invocation policy defaults.
102109
- `[skills.seq]`: optional defaults for `f skills fetch ...` (local seq scraper integration).
103-
- `[commit]`: optional commit workflow defaults; `quick-default = true` makes plain `f commit` use fast commit + deferred Codex deep review.
110+
- `[commit]`: optional commit workflow defaults; plain `f commit` uses fast commit + deferred Codex deep review by default. Set `quick-default = false` to make plain `f commit` run blocking review instead.
111+
- `[task_resolution]`: optional policy for nested task discovery (`f <scope>:<task>`, preferred scopes, and per-task routes when plain names collide).
104112
- `[options]`: optional integration/runtime toggles; use `myflow_mirror` for mirror sync and `codex_bin` to route review calls through a wrapper transport.
105113
- `[commit.testing]`: optional local testing gate evaluated during `f commit`; supports Bun-first strict mode plus optional AI scratch-test fallback (`.ai/test` by default).
106114
- `[commit.skill_gate]`: optional required-skill policy for `f commit`; can enforce presence and minimum skill versions.

‎src/ask.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,8 @@ mod tests {
460460
config_path: PathBuf::from("flow.toml"),
461461
relative_dir: String::new(),
462462
depth: 0,
463+
scope: "root".to_string(),
464+
scope_aliases: vec!["root".to_string()],
463465
}
464466
}
465467

‎src/cli.rs‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ pub enum Commands {
223223
Branches(BranchesCommand),
224224
#[command(
225225
about = "AI-powered commit with code review and optional GitEdit sync.",
226-
long_about = "Stages all changes (or only paths passed via --path), runs code review for bugs/security, generates commit message, commits, pushes (unless commit queue is enabled), and syncs AI sessions to gitedit.dev when enabled in global config.",
226+
long_about = "Stages all changes (or only paths passed via --path), commits quickly by default, starts deferred Codex deep review in the background, and syncs AI sessions to gitedit.dev when enabled in global config. Use --slow to run blocking review before commit.",
227227
alias = "c"
228228
)]
229229
Commit(CommitOpts),
@@ -792,13 +792,25 @@ pub struct TasksCommand {
792792
pub enum TasksAction {
793793
/// List tasks from the current project flow.toml.
794794
List(TasksListOpts),
795+
/// Show duplicate task names discovered across nested flow.toml files.
796+
Dupes(TasksDupesOpts),
795797
}
796798

797799
#[derive(Args, Debug, Clone)]
798800
pub struct TasksListOpts {
799801
/// Path to the project flow config (flow.toml).
800802
#[arg(long, default_value = "flow.toml")]
801803
pub config: PathBuf,
804+
/// Show only duplicate task names and their scopes.
805+
#[arg(long)]
806+
pub dupes: bool,
807+
}
808+
809+
#[derive(Args, Debug, Clone)]
810+
pub struct TasksDupesOpts {
811+
/// Path to the project flow config (flow.toml).
812+
#[arg(long, default_value = "flow.toml")]
813+
pub config: PathBuf,
802814
}
803815

804816
#[derive(Args, Debug, Clone)]
@@ -1450,6 +1462,9 @@ pub struct CommitOpts {
14501462
/// Commit immediately and run Codex review asynchronously in the background.
14511463
#[arg(long, conflicts_with = "dry")]
14521464
pub quick: bool,
1465+
/// Run blocking review before committing (legacy commitWithCheck behavior).
1466+
#[arg(long, conflicts_with = "quick")]
1467+
pub slow: bool,
14531468
/// Use Codex instead of Claude for code review (default: Claude).
14541469
#[arg(long)]
14551470
pub codex: bool,

‎src/commit.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1136,7 +1136,7 @@ pub fn commit_quick_default_enabled() -> bool {
11361136
}
11371137
}
11381138

1139-
false
1139+
true
11401140
}
11411141

11421142
fn commit_review_fail_open_enabled(repo_root: &Path) -> bool {

‎src/config.rs‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ pub struct Config {
108108
/// Setup defaults (global or project-level).
109109
#[serde(default)]
110110
pub setup: Option<SetupConfig>,
111+
/// Task lookup resolution policy for nested flow.toml discovery.
112+
#[serde(
113+
default,
114+
rename = "task_resolution",
115+
alias = "task-resolution",
116+
alias = "taskResolution"
117+
)]
118+
pub task_resolution: Option<TaskResolutionConfig>,
111119
/// SSH defaults (global or project-level).
112120
#[serde(default)]
113121
pub ssh: Option<SshConfig>,
@@ -593,6 +601,7 @@ impl Default for Config {
593601
git: None,
594602
jj: None,
595603
setup: None,
604+
task_resolution: None,
596605
ssh: None,
597606
macos: None,
598607
proxy: None,
@@ -812,6 +821,30 @@ pub struct SetupServerConfig {
812821
pub host: Option<crate::deploy::HostConfig>,
813822
}
814823

824+
/// Task lookup policy for nested flow.toml discovery.
825+
#[derive(Debug, Clone, Deserialize, Default)]
826+
pub struct TaskResolutionConfig {
827+
/// Preferred scope order for ambiguous task names (e.g. ["mobile", "root"]).
828+
#[serde(
829+
default,
830+
rename = "preferred_scopes",
831+
alias = "preferred-scopes",
832+
alias = "preferredScopes"
833+
)]
834+
pub preferred_scopes: Vec<String>,
835+
/// Exact task-name routes (task -> scope), used before preferred scope order.
836+
#[serde(default)]
837+
pub routes: HashMap<String, String>,
838+
/// Print a note when implicit scope routing chooses a target.
839+
#[serde(
840+
default,
841+
rename = "warn_on_implicit_scope",
842+
alias = "warn-on-implicit-scope",
843+
alias = "warnOnImplicitScope"
844+
)]
845+
pub warn_on_implicit_scope: Option<bool>,
846+
}
847+
815848
/// Global feature toggles.
816849
#[derive(Debug, Clone, Default, Deserialize)]
817850
pub struct OptionsConfig {
@@ -947,6 +980,26 @@ impl OptionsConfig {
947980
}
948981
}
949982

983+
impl TaskResolutionConfig {
984+
fn merge(&mut self, other: TaskResolutionConfig) {
985+
if self.preferred_scopes.is_empty() {
986+
self.preferred_scopes = other.preferred_scopes;
987+
} else {
988+
for scope in other.preferred_scopes {
989+
if !self.preferred_scopes.iter().any(|s| s == &scope) {
990+
self.preferred_scopes.push(scope);
991+
}
992+
}
993+
}
994+
if self.warn_on_implicit_scope.is_none() {
995+
self.warn_on_implicit_scope = other.warn_on_implicit_scope;
996+
}
997+
for (task, scope) in other.routes {
998+
self.routes.entry(task).or_insert(scope);
999+
}
1000+
}
1001+
}
1002+
9501003
/// Configuration for a single managed HTTP server process.
9511004
#[derive(Debug, Clone, PartialEq, Eq)]
9521005
pub struct ServerConfig {
@@ -1882,6 +1935,13 @@ fn merge_config(base: &mut Config, other: Config) {
18821935
}
18831936
}
18841937
}
1938+
if base.task_resolution.is_none() {
1939+
base.task_resolution = other.task_resolution;
1940+
} else if let (Some(base_resolution), Some(other_resolution)) =
1941+
(base.task_resolution.as_mut(), other.task_resolution)
1942+
{
1943+
base_resolution.merge(other_resolution);
1944+
}
18851945
if base.analytics.is_none() {
18861946
base.analytics = other.analytics;
18871947
}
@@ -2416,6 +2476,36 @@ codex_bin = "/tmp/codex-jazz"
24162476
assert_eq!(cfg.options.codex_bin.as_deref(), Some("/tmp/codex-jazz"));
24172477
}
24182478

2479+
#[test]
2480+
fn task_resolution_config_parses() {
2481+
let toml = r#"
2482+
[task_resolution]
2483+
preferred_scopes = ["mobile", "root"]
2484+
warn_on_implicit_scope = true
2485+
2486+
[task_resolution.routes]
2487+
dev = "mobile"
2488+
test = "root"
2489+
"#;
2490+
let cfg: Config = toml::from_str(toml).expect("task_resolution should parse");
2491+
let resolution = cfg
2492+
.task_resolution
2493+
.expect("task_resolution config expected");
2494+
assert_eq!(
2495+
resolution.preferred_scopes,
2496+
vec!["mobile".to_string(), "root".to_string()]
2497+
);
2498+
assert_eq!(resolution.warn_on_implicit_scope, Some(true));
2499+
assert_eq!(
2500+
resolution.routes.get("dev").map(String::as_str),
2501+
Some("mobile")
2502+
);
2503+
assert_eq!(
2504+
resolution.routes.get("test").map(String::as_str),
2505+
Some("root")
2506+
);
2507+
}
2508+
24192509
#[test]
24202510
fn commit_testing_config_parses() {
24212511
let toml = r#"

0 commit comments

Comments
 (0)