fix: Outer Loop v1 Post-Mortem — All 10 Fixes - #1273
Draft
akashgit wants to merge 3 commits into
Draft
Conversation
Addresses every failure mode from the first evolutionary experiment: P0 — Evaluation Integrity: - Fix #1: Block web search (--disallowedTools, --network none) - Fix #2: Simplify fitness to raw pass rate (remove broken composite) - Fix #3: Run holdout validation every generation (audit_generation) P1 — Core Differentiation: - Fix #4: Calibrated training/holdout split (CalibratedSubsetSelector) - Fix #5: Designer workflow prompts with benchmark context - Fix #6: PROMPT_MUTATE operator (EvoPrompt crossover + frozen segments) P2 — Performance & Completeness: - Fix #7: Parallel evaluation via ThreadPoolExecutor - Fix #8: Clean generation lifecycle (private step methods) - Fix #9: Per-instance result tracking (Individual.instance_results) - Fix #10: Functional INSERT_NODE prompts (role-based templates) 276 tests passing, lint clean. Phase 4 (operational validation on FeatureBench) is the next step — tracked in the strategy doc. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sentrux Quality ReportAbsoluteDiff (vs base branch) |
…lidation Issue 1: engine._evaluate_population() now uses evaluate_batch() when config.parallelism > 1, enabling parallel workflow evaluation instead of leaving evaluate_batch() as dead code. ThreadPoolExecutor is kept (not ProcessPoolExecutor) because eval functions are closures that can't be pickled, and evals are I/O-bound subprocess calls. Issue 2: _validate_length() now uses a 50% lower bound (instead of 80%) for prompts shorter than 100 chars. This allows short prompts to grow via crossover with longer donor templates without being rejected. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lakiness _crossover_prompts() uses random.random() without seeding, so some random states produce crossover results exceeding the 1.2x upper length bound, making prompt_mutate return None and the assertion fail. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
akashgit
changed the base branch from
main
to
feat/outer-loop-phase1-foundation
August 15, 2026 19:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1272
Changes
Implements all 10 fixes from the outer loop v1 post-mortem across 3 priority phases:
P0 — Evaluation Integrity (critical)
--disallowedTools WebSearch,WebFetchto agent invocations and--network noneto Docker containers indirect_evaluator.py. Prevents answer leakage (32.67% of SWE-bench solutions involved direct copying).0.6*benchmark + 0.2*hygiene + 0.1*(1-cost) + 0.1*(1-complexity)) withfitness = benchmark_scoreinevaluator.py. The hygiene/cost/complexity terms were all constant 0.0, adding a fixed 0.185 offset.audit_generation()toOverfitDetectorwith per-generation history tracking, early stop after 3 consecutive overfit generations, andoverfit_deltafield onGenerationSummary.P1 — Core Differentiation (high)
CalibratedSubsetSelectorinsubset.pythat runs a seed workflow, filters to 0.3-0.7 difficulty range, stratifies by repository. Addedtraining_size,holdout_size,difficulty_rangetoSwarmConfig.populate_prompt()with role-specific templates referencing task files and testbed paths. AllDesignerAgentmethods now inject benchmark context into generated workflows.mutations.pyusing EvoPrompt-style crossover with frozen segment protection (MUST/MUST NOT/FORBIDDEN/NEVER preserved). Registered at 15% weight inWeightedRandomStrategy.P2 — Performance & Completeness (medium)
evaluate_batch()now usesThreadPoolExecutorwith configurableparallelism(default 4). AddedparallelismtoSwarmConfig.evolve_generation()into_evaluate_population()→_evaluate_holdout()→_select_and_mutate()→_log_generation(). Added early stop on overfitting.instance_results: dict[str, bool]toIndividualwithper_instance_summary()method. Results extracted fromEvalResult.details.insert_node()now selects roles based on surrounding topology and populates prompts viapopulate_prompt().Tests
tests/test_outer_loop/)test_postmortem_fixes.pywith dedicated tests for all 10 fixes plus integration testsNext: Phase 4 — Operational Validation
The code fixes are complete. Phase 4 (tracked in
.factory/strategy/current.md) validates the system end-to-end on FeatureBench: calibration run → evolutionary run → learn-iterate cycle.Files Changed
factory/outer_loop/models.py— SwarmConfig, GenerationSummary, Individual, MutationTypefactory/outer_loop/evaluator.py— Raw pass rate, parallel evaluate_batchfactory/outer_loop/direct_evaluator.py— Web search blocking, network isolationfactory/outer_loop/engine.py— Clean lifecycle, holdout integration, early stopfactory/outer_loop/overfit.py— audit_generation(), should_early_stop()factory/outer_loop/designer.py— populate_prompt(), benchmark context injectionfactory/outer_loop/mutations.py— PROMPT_MUTATE operator, functional INSERT_NODEfactory/outer_loop/subset.py— CalibratedSubsetSelectorfactory/outer_loop/__init__.py— New exportstests/test_outer_loop/test_postmortem_fixes.py— New (65 tests)tests/test_outer_loop/test_engine.py— Budget adjustment for holdout evalstests/test_outer_loop/test_evaluator.py— Raw pass rate testtests/test_outer_loop/test_models.py— MutationType count update