1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct ForgeConfig {
6 #[serde(default = "default_mode")]
8 pub mode: String,
9
10 #[serde(default = "default_auto")]
12 pub execution_backend_preference: String,
13
14 #[serde(default = "default_auto")]
16 pub container_runtime_preference: String,
17
18 #[serde(default)]
19 pub allow_test_modifications: bool,
20
21 #[serde(default)]
22 pub sealed_allow_host_backend: bool,
23
24 #[serde(default = "default_forbidden_paths")]
25 pub forbidden_paths: Vec<String>,
26
27 #[serde(default)]
28 pub caps: CapsConfig,
29
30 #[serde(default)]
31 pub mindstate: MindstateConfig,
32
33 #[serde(default)]
34 pub novelty: NoveltyConfig,
35
36 #[serde(default)]
37 pub stabilization: StabilizationConfig,
38
39 #[serde(default)]
40 pub container: ContainerConfig,
41
42 #[serde(default)]
43 pub lab: LabConfig,
44
45 #[serde(default)]
46 pub cea: CeaConfig,
47
48 #[serde(default)]
49 pub danger: DangerConfig,
50
51 #[serde(default)]
52 pub limits: ForgeLimits,
53
54 #[serde(default)]
55 pub workspace: crate::baseline::WorkspacePolicy,
56
57 #[serde(default)]
58 pub statistics: crate::experiment::StatisticsPolicy,
59
60 #[serde(default)]
61 pub comparability: crate::baseline::ComparabilityPolicy,
62}
63
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct CapsConfig {
66 #[serde(default = "default_max_files")]
67 pub max_files_changed: usize,
68 #[serde(default = "default_max_total_lines")]
69 pub max_total_lines_changed: usize,
70 #[serde(default = "default_max_lines_per_file")]
71 pub max_lines_changed_per_file: usize,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct MindstateConfig {
76 #[serde(default = "default_token_budget")]
77 pub token_budget: usize,
78 #[serde(default = "default_evidence_budget")]
79 pub evidence_budget: usize,
80 #[serde(default = "default_max_steps")]
81 pub max_steps: usize,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct NoveltyConfig {
86 #[serde(default = "default_delta_amp_default")]
87 pub delta_amp_default: f64,
88 #[serde(default = "default_delta_amp_stabilize1")]
89 pub delta_amp_stabilize1: f64,
90 #[serde(default = "default_delta_amp_stabilize2")]
91 pub delta_amp_stabilize2: f64,
92 #[serde(default = "default_delta_amp_clamp")]
93 pub delta_amp_clamp: f64,
94 #[serde(default = "default_orthogonality_target")]
95 pub orthogonality_target: f64,
96 #[serde(default = "default_min_traces")]
97 pub min_traces_for_orthogonality: usize,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct StabilizationConfig {
102 #[serde(default = "default_max_attempts")]
103 pub max_attempts: usize,
104 #[serde(default = "default_stabilize1_force_family")]
105 pub stabilize1_force_family: String,
106 #[serde(default = "default_true")]
107 pub stabilize2_force_minimal_diff: bool,
108 #[serde(default = "default_stabilize_weight_factor")]
109 pub increase_stabilize_weight_factor: f64,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ContainerConfig {
114 #[serde(default = "default_rust_image")]
115 pub rust_image: String,
116 #[serde(default = "default_command_timeout")]
117 pub command_timeout_secs: u64,
118 #[serde(default = "default_memory_limit")]
119 pub memory_limit: String,
120 #[serde(default = "default_cpu_limit")]
121 pub cpu_limit: String,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct LabConfig {
126 #[serde(default = "default_batch_size")]
127 pub generation_batch_size: usize,
128 #[serde(default = "default_eval_parallelism")]
129 pub eval_parallelism: usize,
130 #[serde(default = "default_min_pass_rate")]
131 pub promotion_min_suite_pass_rate: f64,
132 #[serde(default = "default_min_improvement")]
133 pub promotion_min_weighted_improvement: f64,
134 #[serde(default)]
135 pub archive: ArchiveConfig,
136 #[serde(default)]
137 pub allow_raw_spec: bool,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct ArchiveConfig {
142 #[serde(default = "default_novelty_bins")]
143 pub novelty_bins: Vec<NoveltyBin>,
144 #[serde(default = "default_stability_variance_threshold")]
145 pub stability_variance_threshold: f64,
146 #[serde(default = "default_approach_families")]
147 pub approach_families: Vec<String>,
148 #[serde(default = "default_correctness_gate")]
149 pub correctness_gate: f64,
150}
151
152#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct NoveltyBin {
154 pub name: String,
155 pub lo: f64,
156 pub hi: f64,
157}
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct CeaConfig {
161 #[serde(default = "default_true")]
162 pub enabled: bool,
163 #[serde(default)]
165 pub enable_zero_shot: bool,
166 #[serde(default = "default_zero_shot_coverage")]
167 pub zero_shot_coverage_threshold: f64,
168 #[serde(default = "default_risk_confidence")]
169 pub risk_confidence_threshold: f64,
170 #[serde(default = "default_max_line_distance")]
171 pub max_line_distance_for_attribution: u32,
172 #[serde(default = "default_attribution_decay")]
173 pub attribution_decay_factor: f64,
174 #[serde(default = "default_causal_drift_threshold")]
175 pub causal_drift_warning_threshold: f64,
176 #[serde(default = "default_min_runs")]
177 pub min_runs_before_prediction: usize,
178}
179
180#[derive(Debug, Clone, Default, Serialize, Deserialize)]
181pub struct DangerConfig {
182 #[serde(default)]
183 pub allow_semantic_memory_write: bool,
184}
185
186fn default_mode() -> String {
189 "standard".to_string()
190}
191fn default_auto() -> String {
192 "auto".to_string()
193}
194fn default_forbidden_paths() -> Vec<String> {
195 vec![
196 "tests/**".to_string(),
197 "**/*_test.rs".to_string(),
198 "**/fixtures/**".to_string(),
199 "**/*.snap".to_string(),
200 "Cargo.lock".to_string(),
201 ".github/**".to_string(),
202 ]
203}
204fn default_max_files() -> usize {
205 8
206}
207fn default_max_total_lines() -> usize {
208 400
209}
210fn default_max_lines_per_file() -> usize {
211 200
212}
213fn default_token_budget() -> usize {
214 1800
215}
216fn default_evidence_budget() -> usize {
217 8
218}
219fn default_max_steps() -> usize {
220 8
221}
222fn default_delta_amp_default() -> f64 {
223 0.7
224}
225fn default_delta_amp_stabilize1() -> f64 {
226 0.2
227}
228fn default_delta_amp_stabilize2() -> f64 {
229 0.1
230}
231fn default_delta_amp_clamp() -> f64 {
232 0.0
233}
234fn default_orthogonality_target() -> f64 {
235 0.10
236}
237fn default_min_traces() -> usize {
238 2
239}
240fn default_max_attempts() -> usize {
241 4
242}
243fn default_stabilize1_force_family() -> String {
244 "mechanical".to_string()
245}
246fn default_true() -> bool {
247 true
248}
249fn default_stabilize_weight_factor() -> f64 {
250 2.5
251}
252fn default_rust_image() -> String {
253 "rust:1.78-slim".to_string()
254}
255fn default_command_timeout() -> u64 {
256 120
257}
258fn default_memory_limit() -> String {
259 "2g".to_string()
260}
261fn default_cpu_limit() -> String {
262 "2.0".to_string()
263}
264fn default_batch_size() -> usize {
265 32
266}
267fn default_eval_parallelism() -> usize {
268 4
269}
270fn default_min_pass_rate() -> f64 {
271 0.95
272}
273fn default_min_improvement() -> f64 {
274 0.05
275}
276fn default_novelty_bins() -> Vec<NoveltyBin> {
277 vec![
278 NoveltyBin {
279 name: "low".to_string(),
280 lo: 0.00,
281 hi: 0.33,
282 },
283 NoveltyBin {
284 name: "med".to_string(),
285 lo: 0.33,
286 hi: 0.66,
287 },
288 NoveltyBin {
289 name: "high".to_string(),
290 lo: 0.66,
291 hi: 1.00,
292 },
293 ]
294}
295fn default_stability_variance_threshold() -> f64 {
296 0.15
297}
298fn default_approach_families() -> Vec<String> {
299 vec![
300 "mechanical".to_string(),
301 "pattern_refactor".to_string(),
302 "architectural".to_string(),
303 "perf".to_string(),
304 "safety".to_string(),
305 ]
306}
307fn default_correctness_gate() -> f64 {
308 0.95
309}
310fn default_zero_shot_coverage() -> f64 {
311 0.80
312}
313fn default_risk_confidence() -> f64 {
314 0.60
315}
316fn default_max_line_distance() -> u32 {
317 50
318}
319fn default_attribution_decay() -> f64 {
320 10.0
321}
322fn default_causal_drift_threshold() -> f64 {
323 0.25
324}
325fn default_min_runs() -> usize {
326 5
327}
328
329impl Default for ForgeConfig {
330 fn default() -> Self {
331 Self {
332 mode: default_mode(),
333 execution_backend_preference: default_auto(),
334 container_runtime_preference: default_auto(),
335 allow_test_modifications: false,
336 sealed_allow_host_backend: false,
337 forbidden_paths: default_forbidden_paths(),
338 caps: CapsConfig::default(),
339 mindstate: MindstateConfig::default(),
340 novelty: NoveltyConfig::default(),
341 stabilization: StabilizationConfig::default(),
342 container: ContainerConfig::default(),
343 lab: LabConfig::default(),
344 cea: CeaConfig::default(),
345 danger: DangerConfig::default(),
346 limits: ForgeLimits::default(),
347 workspace: crate::baseline::WorkspacePolicy::default(),
348 statistics: crate::experiment::StatisticsPolicy::default(),
349 comparability: crate::baseline::ComparabilityPolicy::default(),
350 }
351 }
352}
353
354impl Default for CapsConfig {
355 fn default() -> Self {
356 Self {
357 max_files_changed: default_max_files(),
358 max_total_lines_changed: default_max_total_lines(),
359 max_lines_changed_per_file: default_max_lines_per_file(),
360 }
361 }
362}
363
364impl Default for MindstateConfig {
365 fn default() -> Self {
366 Self {
367 token_budget: default_token_budget(),
368 evidence_budget: default_evidence_budget(),
369 max_steps: default_max_steps(),
370 }
371 }
372}
373
374impl Default for NoveltyConfig {
375 fn default() -> Self {
376 Self {
377 delta_amp_default: default_delta_amp_default(),
378 delta_amp_stabilize1: default_delta_amp_stabilize1(),
379 delta_amp_stabilize2: default_delta_amp_stabilize2(),
380 delta_amp_clamp: default_delta_amp_clamp(),
381 orthogonality_target: default_orthogonality_target(),
382 min_traces_for_orthogonality: default_min_traces(),
383 }
384 }
385}
386
387impl Default for StabilizationConfig {
388 fn default() -> Self {
389 Self {
390 max_attempts: default_max_attempts(),
391 stabilize1_force_family: default_stabilize1_force_family(),
392 stabilize2_force_minimal_diff: true,
393 increase_stabilize_weight_factor: default_stabilize_weight_factor(),
394 }
395 }
396}
397
398impl Default for ContainerConfig {
399 fn default() -> Self {
400 Self {
401 rust_image: default_rust_image(),
402 command_timeout_secs: default_command_timeout(),
403 memory_limit: default_memory_limit(),
404 cpu_limit: default_cpu_limit(),
405 }
406 }
407}
408
409impl Default for LabConfig {
410 fn default() -> Self {
411 Self {
412 generation_batch_size: default_batch_size(),
413 eval_parallelism: default_eval_parallelism(),
414 promotion_min_suite_pass_rate: default_min_pass_rate(),
415 promotion_min_weighted_improvement: default_min_improvement(),
416 archive: ArchiveConfig::default(),
417 allow_raw_spec: false,
418 }
419 }
420}
421
422impl Default for ArchiveConfig {
423 fn default() -> Self {
424 Self {
425 novelty_bins: default_novelty_bins(),
426 stability_variance_threshold: default_stability_variance_threshold(),
427 approach_families: default_approach_families(),
428 correctness_gate: default_correctness_gate(),
429 }
430 }
431}
432
433impl Default for CeaConfig {
434 fn default() -> Self {
435 Self {
436 enabled: true,
437 enable_zero_shot: false,
438 zero_shot_coverage_threshold: default_zero_shot_coverage(),
439 risk_confidence_threshold: default_risk_confidence(),
440 max_line_distance_for_attribution: default_max_line_distance(),
441 attribution_decay_factor: default_attribution_decay(),
442 causal_drift_warning_threshold: default_causal_drift_threshold(),
443 min_runs_before_prediction: default_min_runs(),
444 }
445 }
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
452pub struct ForgeLimits {
453 #[serde(default = "default_max_hypotheses")]
455 pub max_hypotheses: usize,
456 #[serde(default = "default_max_experiments")]
458 pub max_concurrent_experiments: usize,
459 #[serde(default = "default_max_bundles")]
461 pub max_bundles_per_candidate: usize,
462 #[serde(default = "default_max_verification_steps")]
464 pub max_verification_steps: usize,
465 #[serde(default)]
467 pub max_db_bytes: u64,
468 #[serde(default)]
470 pub max_retained_logs_bytes: u64,
471 #[serde(default = "default_max_artifacts")]
473 pub max_retained_artifacts: usize,
474 #[serde(default = "default_failure_retention_days")]
476 pub failed_run_retention_days: u32,
477 #[serde(default = "default_max_patch_files")]
479 pub max_patch_files: usize,
480 #[serde(default = "default_max_patch_bytes")]
482 pub max_patch_bytes: u64,
483 #[serde(default = "default_max_check_runtime")]
485 pub max_check_runtime_secs: u64,
486 #[serde(default = "default_max_check_output_bytes")]
488 pub max_check_output_bytes: u64,
489 #[serde(default = "default_max_graph_nodes")]
491 pub max_graph_nodes: usize,
492 #[serde(default = "default_max_graph_edges")]
494 pub max_graph_edges: usize,
495}
496
497fn default_max_hypotheses() -> usize {
498 100
499}
500fn default_max_experiments() -> usize {
501 4
502}
503fn default_max_bundles() -> usize {
504 50
505}
506fn default_max_verification_steps() -> usize {
507 20
508}
509fn default_max_artifacts() -> usize {
510 100
511}
512fn default_failure_retention_days() -> u32 {
513 30
514}
515fn default_max_patch_files() -> usize {
516 16
517}
518fn default_max_patch_bytes() -> u64 {
519 1_000_000 }
521fn default_max_check_runtime() -> u64 {
522 300 }
524fn default_max_check_output_bytes() -> u64 {
525 10_000_000 }
527fn default_max_graph_nodes() -> usize {
528 10_000
529}
530fn default_max_graph_edges() -> usize {
531 50_000
532}
533
534impl Default for ForgeLimits {
535 fn default() -> Self {
536 Self {
537 max_hypotheses: default_max_hypotheses(),
538 max_concurrent_experiments: default_max_experiments(),
539 max_bundles_per_candidate: default_max_bundles(),
540 max_verification_steps: default_max_verification_steps(),
541 max_db_bytes: 0,
542 max_retained_logs_bytes: 0,
543 max_retained_artifacts: default_max_artifacts(),
544 failed_run_retention_days: default_failure_retention_days(),
545 max_patch_files: default_max_patch_files(),
546 max_patch_bytes: default_max_patch_bytes(),
547 max_check_runtime_secs: default_max_check_runtime(),
548 max_check_output_bytes: default_max_check_output_bytes(),
549 max_graph_nodes: default_max_graph_nodes(),
550 max_graph_edges: default_max_graph_edges(),
551 }
552 }
553}