Skip to content

Commit 4d61ec2

Browse files
nikivdevclaude
andcommitted
Add steward, codex memory daemon, sync resolve config, cleanup binary, and disk headroom
Introduces project steward for repo health scanning and guarded repair, codex memory session sync daemon over Unix socket, AI merge-resolution tuning via [sync.resolve] in flow.toml, Go cleanup binary in deploy/install scripts, disk headroom daemon config, and improved git-guard branch attachment for jj-colocated repos. Scrubs private path references from config and test fixtures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a3905ad commit 4d61ec2

30 files changed

+8020
-234
lines changed

config/disk_headroom.toml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
[volume]
2+
path = "/System/Volumes/Data"
3+
4+
[thresholds]
5+
hard_floor_gb = 50
6+
warning_gb = 70
7+
emergency_gb = 40
8+
stop_target_gb = 85
9+
10+
[daemon]
11+
poll_interval_minutes = 10
12+
max_bytes_per_pass_gb = 120
13+
14+
[state]
15+
root = "~/.config/flow-state/disk-headroom"
16+
protected_roots_ledger = "~/.config/flow-state/disk-headroom/protected-roots.json"
17+
18+
[protection]
19+
roots = [
20+
"~/code/workspace",
21+
"~/code/flow",
22+
"~/work/code",
23+
"~/work/designer-origin-main",
24+
]
25+
pin_markers = [".keep-workspace"]
26+
27+
[tier2]
28+
workspace_roots = ["~/work"]
29+
generated_cleanup_horizon_days = 5
30+
whole_workspace_prune_horizon_days = 21
31+
generated_dirs = [
32+
"node_modules",
33+
".reactron",
34+
".reactron-native",
35+
"target",
36+
"dist",
37+
"build",
38+
]
39+
max_scan_depth = 6
40+
41+
[[tier1.allowlist]]
42+
path = "~/Library/Caches/zed/local-deploy-target"
43+
kind = "cache"
44+
reason = "Zed local deploy cache is rebuildable"
45+
46+
[[tier1.allowlist]]
47+
path = "~/Library/Caches/zed/sccache"
48+
kind = "cache"
49+
reason = "Zed compiler cache is rebuildable"
50+
51+
[[tier1.allowlist]]
52+
path = "~/Library/Caches/codex/local-build-target"
53+
kind = "build-output"
54+
reason = "Codex local build target is rebuildable"
55+
56+
[[tier1.allowlist]]
57+
path = "~/code/flow/target"
58+
kind = "build-output"
59+
reason = "Flow Rust target dir is rebuildable"
60+
61+
[[tier1.allowlist]]
62+
path = "~/code/workspace/target"
63+
kind = "build-output"
64+
reason = "Workspace Rust target dir is rebuildable"
65+
66+
[[tier1.allowlist]]
67+
path = "~/.cache/uv"
68+
kind = "package-cache"
69+
reason = "uv package cache is rebuildable"
70+
71+
[[tier1.allowlist]]
72+
path = "~/Library/Caches/pnpm"
73+
kind = "package-cache"
74+
reason = "pnpm package cache is rebuildable"
75+
76+
[[tier1.allowlist]]
77+
path = "~/Library/Caches/reactron-rs"
78+
kind = "build-cache"
79+
reason = "reactron-rs cache is rebuildable"
80+
81+
[[tier1.allowlist]]
82+
path = "~/Library/Caches/go-build"
83+
kind = "build-cache"
84+
reason = "Go build cache is rebuildable"

crates/flow_commit_scan/src/lib.rs

Lines changed: 63 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,24 @@ fn extract_first_quoted_value(s: &str) -> Option<&str> {
119119
Some(&s[qpos + 1..end])
120120
}
121121

122+
fn extract_assignment_value(s: &str) -> Option<&str> {
123+
s.split_once('=')
124+
.or_else(|| s.split_once(':'))
125+
.map(|(_, rhs)| rhs.trim())
126+
}
127+
128+
fn strip_matching_quotes(value: &str) -> &str {
129+
let v = value.trim();
130+
if v.len() >= 2 {
131+
let first = v.as_bytes()[0];
132+
let last = v.as_bytes()[v.len() - 1];
133+
if (first == b'"' && last == b'"') || (first == b'\'' && last == b'\'') {
134+
return &v[1..v.len() - 1];
135+
}
136+
}
137+
v
138+
}
139+
122140
fn looks_like_identifier_reference(value: &str) -> bool {
123141
let v = value.trim();
124142
!v.is_empty()
@@ -161,30 +179,25 @@ fn looks_like_secret_lookup(value: &str) -> bool {
161179
}
162180

163181
fn generic_secret_assignment_is_false_positive(content: &str, matched: &str) -> bool {
164-
if let Some((_, rhs)) = matched.split_once('=') {
182+
if let Some(rhs) = extract_assignment_value(matched) {
165183
let rhs = rhs.trim_start();
166184
if rhs.starts_with("\"$(") || rhs.starts_with("'$(") || rhs.starts_with("`") {
167185
return true;
168186
}
169187
if rhs.starts_with("\"$") || rhs.starts_with("'$") {
170188
return true;
171189
}
172-
} else if let Some((_, rhs)) = matched.split_once(':') {
173-
let rhs = rhs.trim_start();
174-
if rhs.starts_with("\"$(") || rhs.starts_with("'$(") || rhs.starts_with("`") {
175-
return true;
176-
}
177-
if rhs.starts_with("\"$") || rhs.starts_with("'$") {
190+
191+
let value = strip_matching_quotes(rhs);
192+
if looks_like_identifier_reference(value) {
178193
return true;
179194
}
180-
}
181-
182-
if let Some(val) = extract_first_quoted_value(matched) {
183-
let v = val.trim();
184-
if looks_like_identifier_reference(v) {
195+
if looks_like_secret_lookup(value) {
185196
return true;
186197
}
187-
if looks_like_secret_lookup(v) {
198+
} else if let Some(val) = extract_first_quoted_value(matched) {
199+
let value = val.trim();
200+
if looks_like_identifier_reference(value) || looks_like_secret_lookup(value) {
188201
return true;
189202
}
190203
}
@@ -283,7 +296,7 @@ pub fn scan_diff_for_secrets(repo_root: &Path) -> Vec<SecretFinding> {
283296
continue;
284297
}
285298

286-
if *name == "Generic Secret Assignment"
299+
if matches!(*name, "Generic Secret Assignment" | "Env Var Secret")
287300
&& generic_secret_assignment_is_false_positive(content, matched)
288301
{
289302
continue;
@@ -312,3 +325,39 @@ pub fn scan_diff_for_secrets(repo_root: &Path) -> Vec<SecretFinding> {
312325

313326
findings
314327
}
328+
329+
#[cfg(test)]
330+
mod tests {
331+
use super::*;
332+
333+
fn find_pattern<'a>(name: &str) -> &'a Regex {
334+
compiled_secret_patterns()
335+
.iter()
336+
.find(|(pattern_name, _)| *pattern_name == name)
337+
.map(|(_, re)| re)
338+
.expect("secret pattern exists")
339+
}
340+
341+
#[test]
342+
fn env_var_secret_ignores_config_key_metadata() {
343+
let line = r#"{ key = "REACTRON_DESIGNER_HERMES_BASE_URL", default = "http://hermes.data.svc.od2.prometheus.co" }"#;
344+
let matched = find_pattern("Env Var Secret")
345+
.find(line)
346+
.map(|m| m.as_str())
347+
.expect("pattern should match the metadata assignment");
348+
349+
assert_eq!(matched, r#"key = "REACTRON_DESIGNER_HERMES_BASE_URL""#);
350+
assert!(generic_secret_assignment_is_false_positive(line, matched));
351+
}
352+
353+
#[test]
354+
fn env_var_secret_keeps_real_secret_like_assignment() {
355+
let line = r#"OPENAI_API_KEY = "abcdEFGHijklMNOPqrstUVWXyz0123456789""#;
356+
let matched = find_pattern("Env Var Secret")
357+
.find(line)
358+
.map(|m| m.as_str())
359+
.expect("pattern should match a real env-style assignment");
360+
361+
assert!(!generic_secret_assignment_is_false_positive(line, matched));
362+
}
363+
}

docs/commands/sync.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,25 @@ remote = "origin" # default push remote
145145
home_branch = "alice" # optional long-lived personal integration branch
146146
```
147147

148+
### AI conflict-resolution tuning
149+
150+
Set in `flow.toml` under `[sync.resolve]`:
151+
152+
```toml
153+
[sync.resolve]
154+
effort = "xhigh"
155+
instructions = ["Preserve fork-specific behavior."]
156+
prioritize_paths = ["src/hot.rs", "tests/*"]
157+
deprioritize_paths = ["schema/*", "*.snap"]
158+
```
159+
160+
Notes:
161+
162+
- `effort` is passed through to the Codex merge helper.
163+
- `instructions` are appended to the merge-resolution prompt.
164+
- `prioritize_paths` and `deprioritize_paths` use simple `*` wildcards over repo-relative file paths.
165+
- This is the preferred place for repo-specific fork heuristics; avoid hard-coding them in Flow.
166+
148167
### Fork push
149168

150169
When a fork push target is configured, sync redirects push to the fork remote automatically.

docs/flow-toml-spec.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ install = ["linear"] # optional: ensure skills are installed (local ~/.codex/sk
8383
# codex_bin = "~/code/flow/scripts/codex-jazz-wrapper"
8484
# You can set this in repo flow.toml or global ~/.config/flow/flow.toml
8585

86+
[sync.resolve] # optional: AI merge-resolution tuning for `f sync`
87+
# effort = "xhigh" # reasoning effort passed to the Codex helper
88+
# instructions = ["Preserve fork-specific behavior."]
89+
# prioritize_paths = ["src/hot.rs", "tests/*"]
90+
# deprioritize_paths = ["schema/*", "*.snap"]
91+
8692
[commit.testing] # optional: local commit-time test gate
8793
# mode = "warn" # "warn" | "block" | "off"
8894
# runner = "bun" # currently optimized for bun in Bun repos
@@ -154,6 +160,7 @@ fr = "f run"
154160
- `f up` task fallback order: `up`, then `dev` (unless `up_task` is set).
155161
- `f down` task fallback: `down`; if missing and `down_task` is unset, Flow falls back to project-wide `f kill --all`.
156162
- `[options]`: optional integration/runtime toggles; use `myflow_mirror` for mirror sync and `codex_bin` to route review calls through a wrapper transport.
163+
- `[sync.resolve]`: optional AI merge-resolution tuning for `f sync`; use it to set higher reasoning effort, append repo-specific merge instructions, and declare wildcard path priorities instead of hard-coding fork heuristics in Flow.
157164
- `[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).
158165
- `[commit.skill_gate]`: optional required-skill policy for `f commit`; can enforce presence and minimum skill versions.
159166
- `[invariants]`: optional policy checks for forbidden patterns, dependency allowlists, terminology context, and file-size limits. `mode = "block"` makes invariant warnings fail `f invariants` and commit-time invariant gate checks.
@@ -195,6 +202,12 @@ inject_as = "linear"
195202
[options]
196203
codex_bin = "~/code/flow/scripts/codex-flow-wrapper"
197204

205+
[sync.resolve]
206+
effort = "xhigh"
207+
instructions = ["Preserve fork-specific behavior."]
208+
prioritize_paths = ["src/hot.rs"]
209+
deprioritize_paths = ["schema/*", "*.snap"]
210+
198211
[commit.testing]
199212
mode = "block"
200213
runner = "bun"

0 commit comments

Comments
 (0)