bd: sync issues.jsonl export after 9wi close / cdl file

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Bruno Postle 2026-07-26 21:09:20 +01:00
parent 67f0c38f45
commit 699b049333

View file

@ -22,7 +22,7 @@
{"id":"homemaker-py-1p0","title":"Geometry inner loop: full-objective equal-offset ratio optimiser","description":"DESIGN.md §5.1, §7 Phase 1. Productionise experiments/optimize_fullfitness.py into homemaker: optimise(topology, x0=None) -\u003e (geometry, fitness). DOF = equal-offset division ratios of free branches (solver.free_branches, lowest-storey cut ownership), clipped to [eps, 1-eps]. Objective = full oracle fitness (never a proxy — §4.2 falsified). Must support warm-start x0 (§5.6) and a population/batch evaluation mode so each iteration scores via one batched oracle call (§4.6).","acceptance_criteria":"Reproduces or exceeds §4.5 gains (x1.24x1.67, no new failures) on 2f45907, candidate-002, c964435; works as a library call on any corpus .dom","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:58Z","created_by":"Bruno Postle","updated_at":"2026-06-12T08:46:31Z","started_at":"2026-06-12T00:14:19Z","closed_at":"2026-06-12T08:46:31Z","close_reason":"innerloop.optimise() lands: batched CMA-ES sigma ladder (0.05/0.15, IPOP popsize doubling, deterministic seeding) over equal-offset free-branch ratios vs full oracle fitness; warm-start x0 supported. Acceptance vs unprojected originals: x1.65/x1.66/x1.58 against bars x1.24/x1.67/x1.59, no new failures, 46 oracle calls vs NM's 200. Two near-bar results accepted as reproduced-within-noise (1% tol) — draw spread brackets the single-NM-draw bars; approved by Bruno 2026-06-12. Gotchas: equal-offset projection of legacy unequal cuts loses fitness/adds failures (midpoint projection used); pycma seed=0 means clock-seeded.","dependencies":[{"issue_id":"homemaker-py-1p0","depends_on_id":"homemaker-py-av5","type":"blocks","created_at":"2026-06-12T00:39:33Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":3,"comment_count":0} {"id":"homemaker-py-1p0","title":"Geometry inner loop: full-objective equal-offset ratio optimiser","description":"DESIGN.md §5.1, §7 Phase 1. Productionise experiments/optimize_fullfitness.py into homemaker: optimise(topology, x0=None) -\u003e (geometry, fitness). DOF = equal-offset division ratios of free branches (solver.free_branches, lowest-storey cut ownership), clipped to [eps, 1-eps]. Objective = full oracle fitness (never a proxy — §4.2 falsified). Must support warm-start x0 (§5.6) and a population/batch evaluation mode so each iteration scores via one batched oracle call (§4.6).","acceptance_criteria":"Reproduces or exceeds §4.5 gains (x1.24x1.67, no new failures) on 2f45907, candidate-002, c964435; works as a library call on any corpus .dom","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:58Z","created_by":"Bruno Postle","updated_at":"2026-06-12T08:46:31Z","started_at":"2026-06-12T00:14:19Z","closed_at":"2026-06-12T08:46:31Z","close_reason":"innerloop.optimise() lands: batched CMA-ES sigma ladder (0.05/0.15, IPOP popsize doubling, deterministic seeding) over equal-offset free-branch ratios vs full oracle fitness; warm-start x0 supported. Acceptance vs unprojected originals: x1.65/x1.66/x1.58 against bars x1.24/x1.67/x1.59, no new failures, 46 oracle calls vs NM's 200. Two near-bar results accepted as reproduced-within-noise (1% tol) — draw spread brackets the single-NM-draw bars; approved by Bruno 2026-06-12. Gotchas: equal-offset projection of legacy unequal cuts loses fitness/adds failures (midpoint projection used); pycma seed=0 means clock-seeded.","dependencies":[{"issue_id":"homemaker-py-1p0","depends_on_id":"homemaker-py-av5","type":"blocks","created_at":"2026-06-12T00:39:33Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":3,"comment_count":0}
{"id":"homemaker-py-8cs","title":"Experiment: warm-vs-cold start of inner loop (Lamarckian inheritance)","description":"DESIGN.md §5.6, §4.6. Warm-starting a child topology's inner loop from the parent's optimised ratios is the main lever for cutting per-topology cost (~3 min/topology cold). Apply single topology mutations to optimised corpus designs, re-optimise warm (surviving cuts keep values, new cuts get heuristic defaults) vs cold, compare oracle-call counts to convergence at equal final fitness.","acceptance_criteria":"Speedup factor measured across \u003e=10 mutated topologies; decision recorded (expect order-of-magnitude; if \u003c2x, revisit §4.6 Phase-2 scoping)","notes":"Experiment script committed (experiments/warm_vs_cold.py, 1cc86c8) and machinery validated oracle-free; one mutated child scored through the oracle OK. Waiting on homemaker-py-gp2 reference run to finish, then execute under URB_NO_OCCLUSION=1 (3 parents x 400 evals + 12 children x 2 x 200 evals, ~1.5-2 h oracle time). Default budgets: parent 400, child 200; target = evals to 95% of best final.","status":"closed","priority":1,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:58Z","created_by":"Bruno Postle","updated_at":"2026-06-12T11:44:45Z","closed_at":"2026-06-12T11:44:45Z","close_reason":"Measured (URB_NO_OCCLUSION=1, parent budget 400, child 200, 12 single mutations across 3 designs): cold start reached 95% of warm final in 0/12 cases within budget — speedup unbounded at practical budgets; warm finals beat cold finals x1.2-x4 in 12/12; 6/12 warm starts were within 95% at 1 eval (near-neutral mutations). Decision: Lamarckian warm-starting is MANDATORY in the memetic driver (homemaker-py-b39), not an optimisation; cold starts produce strictly worse geometry at equal budget. Note: 2 undivides were exactly fitness-neutral (same-type merge == Merge_Divided equivalence) — locality datum for homemaker-py-nyb.","dependencies":[{"issue_id":"homemaker-py-8cs","depends_on_id":"homemaker-py-1p0","type":"blocks","created_at":"2026-06-12T00:39:34Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-8cs","title":"Experiment: warm-vs-cold start of inner loop (Lamarckian inheritance)","description":"DESIGN.md §5.6, §4.6. Warm-starting a child topology's inner loop from the parent's optimised ratios is the main lever for cutting per-topology cost (~3 min/topology cold). Apply single topology mutations to optimised corpus designs, re-optimise warm (surviving cuts keep values, new cuts get heuristic defaults) vs cold, compare oracle-call counts to convergence at equal final fitness.","acceptance_criteria":"Speedup factor measured across \u003e=10 mutated topologies; decision recorded (expect order-of-magnitude; if \u003c2x, revisit §4.6 Phase-2 scoping)","notes":"Experiment script committed (experiments/warm_vs_cold.py, 1cc86c8) and machinery validated oracle-free; one mutated child scored through the oracle OK. Waiting on homemaker-py-gp2 reference run to finish, then execute under URB_NO_OCCLUSION=1 (3 parents x 400 evals + 12 children x 2 x 200 evals, ~1.5-2 h oracle time). Default budgets: parent 400, child 200; target = evals to 95% of best final.","status":"closed","priority":1,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:58Z","created_by":"Bruno Postle","updated_at":"2026-06-12T11:44:45Z","closed_at":"2026-06-12T11:44:45Z","close_reason":"Measured (URB_NO_OCCLUSION=1, parent budget 400, child 200, 12 single mutations across 3 designs): cold start reached 95% of warm final in 0/12 cases within budget — speedup unbounded at practical budgets; warm finals beat cold finals x1.2-x4 in 12/12; 6/12 warm starts were within 95% at 1 eval (near-neutral mutations). Decision: Lamarckian warm-starting is MANDATORY in the memetic driver (homemaker-py-b39), not an optimisation; cold starts produce strictly worse geometry at equal budget. Note: 2 undivides were exactly fitness-neutral (same-type merge == Merge_Divided equivalence) — locality datum for homemaker-py-nyb.","dependencies":[{"issue_id":"homemaker-py-8cs","depends_on_id":"homemaker-py-1p0","type":"blocks","created_at":"2026-06-12T00:39:34Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-av5","title":"Batched oracle: score many .dom files per invocation","description":"oracle.py currently scores one .dom per urb-fitness.pl call (~1.65 s/dom). DESIGN.md §4.6: batching amortises Perl startup to ~0.99 s/dom and is required so population/batch optimisers can score a whole generation in one oracle call. Extend oracle.py with a batch API: write N .dom files, one perl invocation, parse N .score/.fails pairs. Keep the single-file path for compatibility.","acceptance_criteria":"Batch of 35 corpus files scores in one perl invocation; per-file results identical to single-file calls; measured s/dom reported","status":"closed","priority":1,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:56Z","created_by":"Bruno Postle","updated_at":"2026-06-12T00:14:06Z","started_at":"2026-06-11T23:50:40Z","closed_at":"2026-06-12T00:14:06Z","close_reason":"score_batch() lands in oracle.py; 35-file corpus parity verified single-vs-batch (1e-12 rel fitness, exact fail sets); 0.98 s/dom batched vs 1.27 single, x1.30","dependency_count":0,"dependent_count":1,"comment_count":0} {"id":"homemaker-py-av5","title":"Batched oracle: score many .dom files per invocation","description":"oracle.py currently scores one .dom per urb-fitness.pl call (~1.65 s/dom). DESIGN.md §4.6: batching amortises Perl startup to ~0.99 s/dom and is required so population/batch optimisers can score a whole generation in one oracle call. Extend oracle.py with a batch API: write N .dom files, one perl invocation, parse N .score/.fails pairs. Keep the single-file path for compatibility.","acceptance_criteria":"Batch of 35 corpus files scores in one perl invocation; per-file results identical to single-file calls; measured s/dom reported","status":"closed","priority":1,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:56Z","created_by":"Bruno Postle","updated_at":"2026-06-12T00:14:06Z","started_at":"2026-06-11T23:50:40Z","closed_at":"2026-06-12T00:14:06Z","close_reason":"score_batch() lands in oracle.py; 35-file corpus parity verified single-vs-batch (1e-12 rel fitness, exact fail sets); 0.98 s/dom batched vs 1.27 single, x1.30","dependency_count":0,"dependent_count":1,"comment_count":0}
{"id":"homemaker-py-9wi","title":"Adjacency-aware discrete assignment for finish-time collapse (QAP/CP-SAT)","description":"fitness.collapse_superposition (homemaker-py-9o5/94g family) already does exact optimal relabelling of superposed leaves via brute-force permutation (CLASS_CAP\u003c=4) or Hungarian (linear_sum_assignment) beyond that -- but _best_assignment's docstring is explicit that the objective is deliberately SEPARABLE per leaf (quality_size * quality_width * quality_proportion only); perpendicular/crinkliness/access/adjacency are assumed usage-invariant within a class and left out, because adjacency quality depends on PAIRS of leaf-label assignments, not one leaf at a time, which breaks the exact separable solve.\n\nProposal: extend the collapse step to account for adjacency between candidate labels -- either a quadratic-assignment-style local search (2-opt swaps over the current Hungarian solution, accepting swaps that improve total adjacency satisfaction) or a CP-SAT (OR-Tools) encoding of the labelling problem with pairwise adjacency terms. This directly extends the one search-adjacent technique (exact/near-exact discrete assignment) that has actually paid off in this project, into territory the current separable solve cannot reach.\n\nMeasure against the current Hungarian-only collapse on harbor-house (heavy interchange-class usage: neighborhoods, meeting rooms, individual rooms) where adjacency-blind relabelling is most likely to leave adjacency fails on the table.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:24Z","created_by":"Bruno Postle","updated_at":"2026-07-26T14:50:36Z","started_at":"2026-07-26T14:50:36Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-9wi","title":"Adjacency-aware discrete assignment for finish-time collapse (QAP/CP-SAT)","description":"fitness.collapse_superposition (homemaker-py-9o5/94g family) already does exact optimal relabelling of superposed leaves via brute-force permutation (CLASS_CAP\u003c=4) or Hungarian (linear_sum_assignment) beyond that -- but _best_assignment's docstring is explicit that the objective is deliberately SEPARABLE per leaf (quality_size * quality_width * quality_proportion only); perpendicular/crinkliness/access/adjacency are assumed usage-invariant within a class and left out, because adjacency quality depends on PAIRS of leaf-label assignments, not one leaf at a time, which breaks the exact separable solve.\n\nProposal: extend the collapse step to account for adjacency between candidate labels -- either a quadratic-assignment-style local search (2-opt swaps over the current Hungarian solution, accepting swaps that improve total adjacency satisfaction) or a CP-SAT (OR-Tools) encoding of the labelling problem with pairwise adjacency terms. This directly extends the one search-adjacent technique (exact/near-exact discrete assignment) that has actually paid off in this project, into territory the current separable solve cannot reach.\n\nMeasure against the current Hungarian-only collapse on harbor-house (heavy interchange-class usage: neighborhoods, meeting rooms, individual rooms) where adjacency-blind relabelling is most likely to leave adjacency fails on the table.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:24Z","created_by":"Bruno Postle","updated_at":"2026-07-26T19:57:55Z","started_at":"2026-07-26T14:50:36Z","closed_at":"2026-07-26T19:57:55Z","close_reason":"2-opt local search DELIVERED beyond collapse_global's Jacobi adjacency relaxation:\nFitness._collapse_value (refactored per-leaf-per-code value, shared by the\nassignment matrix and the polish) + Fitness._two_opt_adjacency_polish (same-level\npairwise label-swap search, kept only on strict improvement -- monotone by\nconstruction) + collapse_global(local_search=..., local_search_passes=...) +\nhomemaker-collapse --local-search CLI flag + regression test\n(test_two_opt_polish_escapes_jacobi_plateau) that proves the Jacobi loop can\n2-cycle between two labellings satisfying ZERO of a satisfiable adjacency set,\nand that 2-opt escapes it.\n\nWent with 2-opt over CP-SAT/OR-Tools: no new dependency (project has no\nortools), directly extends the existing Jacobi machinery, and the issue listed\nit as the first alternative. QAP is NP-hard in general so this is a local\nsearch, not an exact solve, but it strictly dominates the Jacobi-only result\n(never worse, by construction).\n\nMeasured against harbor-house per the issue's own instruction: swept all 11\nevolved-*/3m/materialised .dom files, comparing collapse_global(local_search=False)\nvs (local_search=True). 10/11 matched exactly (Jacobi was already at the local\n2-opt optimum), 0 regressed, 1 improved (evolved-anneal-3M.dom 21-\u003e19 fails --\nresolved a genuine mutual da1\u003c-\u003ek1 adjacency miss). Runtime \u003c1s even on the\nlargest file (90-fail evolved-3M.dom). Findings + the plateau proof saved via\nbd remember. Default left OFF (opt-in via local_search=True /\nhomemaker-collapse --local-search) pending a broader sweep and evolve.py CLI\nwiring -- spun off as homemaker-py-cdl.\n\n298/298 tests pass (7 in test_collapse_global.py, up from 6).","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-f1d","title":"Ruin-and-recreate LNS: rebuild wings with the adjacency-aware constructor mid-search","description":"DESIGN.md's own experiment log shows every 'search machinery' change (niching+restarts 11.5, graded objective 11.4, Wong-Liu reassociation+shape-feasibility 12.3, granularity 12.4, island model 14, grain annealing 16, circulation-repair ops 21/22) has come back null-to-negative, while construction/seeding quality (adjacency-aware seeding 11.6/11.7, proportion-aware seeding 12.2) is the only lever that has ever moved the fail count. operators._assign_adjacency_aware currently only runs once, at seeding.\n\nProposal: a large-neighbourhood-search move that periodically un-divides a whole wing/subtree of the CURRENT BEST individual and reconstructs just that region using the same proven adjacency-aware constructive heuristic (seeded from the surviving circulation spine as fixed_circ, same mechanism lift_base_to_storeys already uses for upper floors), instead of relying only on small local mutation operators to find improvements. Reuses the one technique with a real track record, applied repeatedly during search rather than once at initialisation.\n\nA/B against the current baseline on programme-house and harbor-house at a fixed worker count (see 12.4's determinism-fix note about serial vs parallel admission order before trusting sub-±3 effects).","notes":"Implementation landed (uncommitted, pending A/B): operators.mutate_ruin_recreate — picks a divided, live-cut wing of one storey (2..half its leaves), un-divides it, regrows+retypes it via a scope-generalised operators._assign_adjacency_aware (new 'scope' param restricts retyping to a leaf subset while fixed_circ seeds can be border leaves outside that subset), seeded from already-typed circulation leaves bordering the wing. Room-code budget inside the wing is preserved exactly; circ/outside counts rebuilt at circ_divisor=3/outside_divisor=3. Gated like reassociate/bridge_circulation: mutation_weights['ruin_recreate']=0.0 unless driver.search(enable_ruin_recreate=True); CLI flag --ruin-recreate/--no-ruin-recreate added to evolve.py (default off). 297 existing tests pass unchanged; added smoke coverage (200 applications on harbor-house constructive seeds: zero missing-space regressions, all canonical). A/B now running in background: experiments/run_f1d_ab.sh, qpk protocol (harbor-house budget=2500 seeds 1-3, programme-house budget=3000 seeds 1-5, workers=4, both arms finished with standard --collapse), results -\u003e scratch/f1d_ab_results.tsv.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:02Z","created_by":"Bruno Postle","updated_at":"2026-07-26T08:30:13Z","started_at":"2026-07-25T20:20:56Z","closed_at":"2026-07-26T08:30:13Z","close_reason":"DONE (positive, size-dependent). operators.mutate_ruin_recreate landed: un-divides one wing of a storey (2..half its leaves), rebuilds it via a scope-generalised _assign_adjacency_aware seeded from bordering circulation, mirroring lift_base_to_storeys' core-inheritance mechanism. Gated like reassociate/bridge_circulation (enable_ruin_recreate, default off; --ruin-recreate CLI flag). Initial uniform-weight A/B was null but underpowered (op fired ~1/32 children); a weight=3.0 follow-up (_MUTATION_WEIGHTS['ruin_recreate']=3.0, kept in source) showed a statistically significant win on programme-house across 15 seeds (8W/1L/6T, mean fails 7.07-\u003e6.00, Wilcoxon p=0.041, sign-test p=0.020) but no consistent effect on harbor-house across 8 seeds (3W/2L/3T, mean fails 73.0-\u003e74.5, slight negative lean). Kept default OFF pending a size-threshold follow-up (not filed) -- same conservative bar qpk/1ph applied before its own larger-N confirmation. Full writeup: DESIGN.md §23.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-f1d","title":"Ruin-and-recreate LNS: rebuild wings with the adjacency-aware constructor mid-search","description":"DESIGN.md's own experiment log shows every 'search machinery' change (niching+restarts 11.5, graded objective 11.4, Wong-Liu reassociation+shape-feasibility 12.3, granularity 12.4, island model 14, grain annealing 16, circulation-repair ops 21/22) has come back null-to-negative, while construction/seeding quality (adjacency-aware seeding 11.6/11.7, proportion-aware seeding 12.2) is the only lever that has ever moved the fail count. operators._assign_adjacency_aware currently only runs once, at seeding.\n\nProposal: a large-neighbourhood-search move that periodically un-divides a whole wing/subtree of the CURRENT BEST individual and reconstructs just that region using the same proven adjacency-aware constructive heuristic (seeded from the surviving circulation spine as fixed_circ, same mechanism lift_base_to_storeys already uses for upper floors), instead of relying only on small local mutation operators to find improvements. Reuses the one technique with a real track record, applied repeatedly during search rather than once at initialisation.\n\nA/B against the current baseline on programme-house and harbor-house at a fixed worker count (see 12.4's determinism-fix note about serial vs parallel admission order before trusting sub-±3 effects).","notes":"Implementation landed (uncommitted, pending A/B): operators.mutate_ruin_recreate — picks a divided, live-cut wing of one storey (2..half its leaves), un-divides it, regrows+retypes it via a scope-generalised operators._assign_adjacency_aware (new 'scope' param restricts retyping to a leaf subset while fixed_circ seeds can be border leaves outside that subset), seeded from already-typed circulation leaves bordering the wing. Room-code budget inside the wing is preserved exactly; circ/outside counts rebuilt at circ_divisor=3/outside_divisor=3. Gated like reassociate/bridge_circulation: mutation_weights['ruin_recreate']=0.0 unless driver.search(enable_ruin_recreate=True); CLI flag --ruin-recreate/--no-ruin-recreate added to evolve.py (default off). 297 existing tests pass unchanged; added smoke coverage (200 applications on harbor-house constructive seeds: zero missing-space regressions, all canonical). A/B now running in background: experiments/run_f1d_ab.sh, qpk protocol (harbor-house budget=2500 seeds 1-3, programme-house budget=3000 seeds 1-5, workers=4, both arms finished with standard --collapse), results -\u003e scratch/f1d_ab_results.tsv.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:02Z","created_by":"Bruno Postle","updated_at":"2026-07-26T08:30:13Z","started_at":"2026-07-25T20:20:56Z","closed_at":"2026-07-26T08:30:13Z","close_reason":"DONE (positive, size-dependent). operators.mutate_ruin_recreate landed: un-divides one wing of a storey (2..half its leaves), rebuilds it via a scope-generalised _assign_adjacency_aware seeded from bordering circulation, mirroring lift_base_to_storeys' core-inheritance mechanism. Gated like reassociate/bridge_circulation (enable_ruin_recreate, default off; --ruin-recreate CLI flag). Initial uniform-weight A/B was null but underpowered (op fired ~1/32 children); a weight=3.0 follow-up (_MUTATION_WEIGHTS['ruin_recreate']=3.0, kept in source) showed a statistically significant win on programme-house across 15 seeds (8W/1L/6T, mean fails 7.07-\u003e6.00, Wilcoxon p=0.041, sign-test p=0.020) but no consistent effect on harbor-house across 8 seeds (3W/2L/3T, mean fails 73.0-\u003e74.5, slight negative lean). Kept default OFF pending a size-threshold follow-up (not filed) -- same conservative bar qpk/1ph applied before its own larger-N confirmation. Full writeup: DESIGN.md §23.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-mi7","title":"Prototype: 3D bubble-diagram relaxation of programme adjacency as a fitness signal","description":"Explore building a spring/force relaxation over the programme's required-space adjacency graph (multiple random-restart solutions), then score how well an actual Dom layout's real adjacency-graph distances correlate with a relaxed target's distances. Goal: an additional fitness term / search-guidance signal beyond the existing binary adjacency checks in graph.py. Prototype module: bubble.py. Validate by correlating similarity score against existing fitness .score on examples/programme-house's 36 scored .dom files.","notes":"Harbor-house real trajectory (driver.search, budget=6000, n=75 recorded individuals, fitness 3e-28 -\u003e 3.9e-17, fails 83-\u003e51):\n- embedding similarity(): spearman=0.164 p=0.16 (n.s.)\n- topological_similarity(): spearman=-0.160 p=0.17 (n.s.)\n\nFINAL PICTURE across 4 tests (2 programmes x 2 metric formulations, plus 2 canned-batch tests earlier): no statistically significant correlation anywhere between either the spring/embedding bubble-diagram similarity or the pure topological/abstract-graph-fitting similarity, and existing programme-driven fitness score. programme-house's real-trajectory result (rho=0.05 / rho=-0.06, n=100) is the cleanest data point — that programme has zero multi-count anonymous codes, so matched_leaves' known centroid-order matching heuristic cannot be confounding it, and it's still flat. Harbor-house is noisier (heavy anonymous counts: n x5, m x3, t x6, r x10, of x2 — the fixed centroid-order matching there is a real, uncontrolled confound) but tells the same story.\n\nRecommendation: do not pursue graph-relaxation-derived or pure-topological adjacency-matching as a fitness signal for this project without a fundamentally different formulation — two independent formulations, tested on two programmes with real evolved trajectories (not just static examples), both came back null. If revisited later, the harbor-house confound (anonymous-code instance matching) would need a real assignment solver (Hungarian/brute-force per homemaker-py-9o5's CLASS_CAP pattern) before drawing any conclusion there specifically, but programme-house's clean null already argues against the core idea. bubble.py is left in the repo (uncommitted) as a documented, working prototype/reference — not wired into fitness.py.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T12:42:02Z","created_by":"Bruno Postle","updated_at":"2026-07-25T20:12:20Z","started_at":"2026-07-25T12:42:26Z","closed_at":"2026-07-25T20:12:20Z","close_reason":"Two independent formulations (spring/embedding bubble-diagram, pure topological hop-distance) both tested null against real evolve trajectories on programme-house (n=100, clean — no anonymous-code confound) and harbor-house (n=75). No positive correlation with existing fitness score found. bubble.py left in repo, uncommitted, as documented reference; not wired into fitness.py. Consistent with the project's broader pattern (see DESIGN.md §11.4/11.5/12.3/12.4/14/16/21/22): 'search machinery' / fitness-shaping changes have been null-to-negative essentially every time they've been tried; only construction/seeding quality and representation-relaxation changes (leaf-sharing, type superposition, global collapse) have ever moved the needle. This session's result is another data point for that pattern, not an exception.","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-mi7","title":"Prototype: 3D bubble-diagram relaxation of programme adjacency as a fitness signal","description":"Explore building a spring/force relaxation over the programme's required-space adjacency graph (multiple random-restart solutions), then score how well an actual Dom layout's real adjacency-graph distances correlate with a relaxed target's distances. Goal: an additional fitness term / search-guidance signal beyond the existing binary adjacency checks in graph.py. Prototype module: bubble.py. Validate by correlating similarity score against existing fitness .score on examples/programme-house's 36 scored .dom files.","notes":"Harbor-house real trajectory (driver.search, budget=6000, n=75 recorded individuals, fitness 3e-28 -\u003e 3.9e-17, fails 83-\u003e51):\n- embedding similarity(): spearman=0.164 p=0.16 (n.s.)\n- topological_similarity(): spearman=-0.160 p=0.17 (n.s.)\n\nFINAL PICTURE across 4 tests (2 programmes x 2 metric formulations, plus 2 canned-batch tests earlier): no statistically significant correlation anywhere between either the spring/embedding bubble-diagram similarity or the pure topological/abstract-graph-fitting similarity, and existing programme-driven fitness score. programme-house's real-trajectory result (rho=0.05 / rho=-0.06, n=100) is the cleanest data point — that programme has zero multi-count anonymous codes, so matched_leaves' known centroid-order matching heuristic cannot be confounding it, and it's still flat. Harbor-house is noisier (heavy anonymous counts: n x5, m x3, t x6, r x10, of x2 — the fixed centroid-order matching there is a real, uncontrolled confound) but tells the same story.\n\nRecommendation: do not pursue graph-relaxation-derived or pure-topological adjacency-matching as a fitness signal for this project without a fundamentally different formulation — two independent formulations, tested on two programmes with real evolved trajectories (not just static examples), both came back null. If revisited later, the harbor-house confound (anonymous-code instance matching) would need a real assignment solver (Hungarian/brute-force per homemaker-py-9o5's CLASS_CAP pattern) before drawing any conclusion there specifically, but programme-house's clean null already argues against the core idea. bubble.py is left in the repo (uncommitted) as a documented, working prototype/reference — not wired into fitness.py.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-25T12:42:02Z","created_by":"Bruno Postle","updated_at":"2026-07-25T20:12:20Z","started_at":"2026-07-25T12:42:26Z","closed_at":"2026-07-25T20:12:20Z","close_reason":"Two independent formulations (spring/embedding bubble-diagram, pure topological hop-distance) both tested null against real evolve trajectories on programme-house (n=100, clean — no anonymous-code confound) and harbor-house (n=75). No positive correlation with existing fitness score found. bubble.py left in repo, uncommitted, as documented reference; not wired into fitness.py. Consistent with the project's broader pattern (see DESIGN.md §11.4/11.5/12.3/12.4/14/16/21/22): 'search machinery' / fitness-shaping changes have been null-to-negative essentially every time they've been tried; only construction/seeding quality and representation-relaxation changes (leaf-sharing, type superposition, global collapse) have ever moved the needle. This session's result is another data point for that pattern, not an exception.","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-qi6","title":"Circulation placement to clear not-connected / access fails","description":"The 94g finish-time collapse cannot touch the \"not-connected\" (level N not\nconnected) and related access/inaccessible fails: they are properties of the\nCIRCULATION skeleton (c/o/s cells), which the collapse deliberately never\nrelabels (they form the structure the room assignment is layered onto). On the\nharbor-house best layout 2 of the 15 fails are not-connected (levels 0 and 1);\nthese are out of scope for any label optimisation.\n\nGOAL: a search/repair step that places or reshapes circulation so every usable\nspace is reachable and each storey's circulation graph is connected. Candidate\nmechanisms: (a) a mutation/operator that inserts a circulation cell to bridge a\ndisconnected component (graph.py already computes connected components +\nconnected_circulation); (b) a finish-time repair that re-types a boundary cell to\ncirculation where it reconnects the graph at least net-fail cost; (c) bias the\nouter search toward connected topologies via the graded signal.\n\nInteracts with 94g: circulation placement changes which cells are skeleton vs\nassignable, so it should run BEFORE the label collapse (collapse then optimises\nlabels over the improved skeleton). Also interacts with the public-access pin\n(94g) — better circulation placement can supply invariant inside public access,\nremoving the need to pin a room provider.\n\nMeasure on the 6 evolved layouts from the 94g sweep (not-connected + access +\ninaccessible fail counts). Related: 94g, homemaker-py-2g5.","notes":"LANDED (2026-07-18) mechanism (c) — graded circulation-connectivity signal (DESIGN §18). graph.circulation_connectivity(G) = largest-circ-component fraction [0,1]; summed over storeys it rides the score_with_grade proximity channel, gated by conf flag conn_grade (replaces the §11.4 leaf-grade on that channel). Secondary comparator key (-n_fails, grade, fitness) only — scalar fitness and fail count byte-identical (verified). Wired conn_grade through driver _overrides_for/_fitness_for/_evaluate/search (enabling it implies the grade key); evolve --conn-grade (HOMEMAKER_CONN_GRADE, default OFF). 9 new tests (tests/test_conn_grade.py), 276 pass; 60-eval CLI smoke confirms plumbing.\n\nA/B VERDICT (2026-07-22, qpk protocol, experiments/run_qi6_ab.sh) — NEGATIVE. conn_grade ON vs OFF, full-budget, both finished with --collapse: harbor-house (budget 2500, seeds 1-3) byte-identical output in every seed — the grade never fired. programme-house (budget 3000, seeds 1-5) 3/5 seeds tie exactly; seeds 1/2 diverge to a different topology with one fewer total fail, but the diff is adjacency/crinkliness/width/access/size, not connectivity. Zero cases (of 4) where a not-connected fail was present and cleared by the grade. Mechanism (b)/(c) (graded proximity as tertiary comparator key) is falsified, not just unconfirmed. Kept default OFF (already was). DESIGN.md §18 updated with full verdict.\n\nRemaining candidate: mechanism (a), an explicit insert/relocate-circulation mutation/repair operator that doesn't depend on the search stumbling onto a fail-count tie. Not started — filing as follow-on if this gets picked up; otherwise low priority (fitness fidelity, not search capability, per 94g framing).","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-18T10:12:27Z","created_by":"Bruno Postle","updated_at":"2026-07-23T17:22:14Z","started_at":"2026-07-18T12:17:08Z","closed_at":"2026-07-23T17:22:14Z","close_reason":"A/B measured negative (see notes + DESIGN.md §18); mechanism (a) follow-on filed as homemaker-py-8sh","dependencies":[{"issue_id":"homemaker-py-qi6","depends_on_id":"homemaker-py-94g","type":"discovered-from","created_at":"2026-07-18T11:12:27Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-qi6","title":"Circulation placement to clear not-connected / access fails","description":"The 94g finish-time collapse cannot touch the \"not-connected\" (level N not\nconnected) and related access/inaccessible fails: they are properties of the\nCIRCULATION skeleton (c/o/s cells), which the collapse deliberately never\nrelabels (they form the structure the room assignment is layered onto). On the\nharbor-house best layout 2 of the 15 fails are not-connected (levels 0 and 1);\nthese are out of scope for any label optimisation.\n\nGOAL: a search/repair step that places or reshapes circulation so every usable\nspace is reachable and each storey's circulation graph is connected. Candidate\nmechanisms: (a) a mutation/operator that inserts a circulation cell to bridge a\ndisconnected component (graph.py already computes connected components +\nconnected_circulation); (b) a finish-time repair that re-types a boundary cell to\ncirculation where it reconnects the graph at least net-fail cost; (c) bias the\nouter search toward connected topologies via the graded signal.\n\nInteracts with 94g: circulation placement changes which cells are skeleton vs\nassignable, so it should run BEFORE the label collapse (collapse then optimises\nlabels over the improved skeleton). Also interacts with the public-access pin\n(94g) — better circulation placement can supply invariant inside public access,\nremoving the need to pin a room provider.\n\nMeasure on the 6 evolved layouts from the 94g sweep (not-connected + access +\ninaccessible fail counts). Related: 94g, homemaker-py-2g5.","notes":"LANDED (2026-07-18) mechanism (c) — graded circulation-connectivity signal (DESIGN §18). graph.circulation_connectivity(G) = largest-circ-component fraction [0,1]; summed over storeys it rides the score_with_grade proximity channel, gated by conf flag conn_grade (replaces the §11.4 leaf-grade on that channel). Secondary comparator key (-n_fails, grade, fitness) only — scalar fitness and fail count byte-identical (verified). Wired conn_grade through driver _overrides_for/_fitness_for/_evaluate/search (enabling it implies the grade key); evolve --conn-grade (HOMEMAKER_CONN_GRADE, default OFF). 9 new tests (tests/test_conn_grade.py), 276 pass; 60-eval CLI smoke confirms plumbing.\n\nA/B VERDICT (2026-07-22, qpk protocol, experiments/run_qi6_ab.sh) — NEGATIVE. conn_grade ON vs OFF, full-budget, both finished with --collapse: harbor-house (budget 2500, seeds 1-3) byte-identical output in every seed — the grade never fired. programme-house (budget 3000, seeds 1-5) 3/5 seeds tie exactly; seeds 1/2 diverge to a different topology with one fewer total fail, but the diff is adjacency/crinkliness/width/access/size, not connectivity. Zero cases (of 4) where a not-connected fail was present and cleared by the grade. Mechanism (b)/(c) (graded proximity as tertiary comparator key) is falsified, not just unconfirmed. Kept default OFF (already was). DESIGN.md §18 updated with full verdict.\n\nRemaining candidate: mechanism (a), an explicit insert/relocate-circulation mutation/repair operator that doesn't depend on the search stumbling onto a fail-count tie. Not started — filing as follow-on if this gets picked up; otherwise low priority (fitness fidelity, not search capability, per 94g framing).","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-18T10:12:27Z","created_by":"Bruno Postle","updated_at":"2026-07-23T17:22:14Z","started_at":"2026-07-18T12:17:08Z","closed_at":"2026-07-23T17:22:14Z","close_reason":"A/B measured negative (see notes + DESIGN.md §18); mechanism (a) follow-on filed as homemaker-py-8sh","dependencies":[{"issue_id":"homemaker-py-qi6","depends_on_id":"homemaker-py-94g","type":"discovered-from","created_at":"2026-07-18T11:12:27Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
@ -58,6 +58,7 @@
{"id":"homemaker-py-nyb","title":"High-locality topology operators (mutation + subtree crossover)","description":"DESIGN.md §5, §7 Phase 2, §8.4. Mutation moves: divide/undivide leaf, swap children, rotate cut, retype leaf, per-floor delta edits, storey add/delete (cf. Urb Mutate.pm — but geometry sliding belongs to the inner loop, not the operator set). Crossover: area-matched subtree exchange (a subtree = a contiguous region, so crossover is meaningful — Crossover.pm). Operators must be high-locality: small genome change =\u003e small phenotype change, so warm-started inner loops stay cheap.","acceptance_criteria":"Each operator produces valid genomes (oracle scores them without error); locality measured (mean fitness/geometry perturbation per operator)","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:37:27Z","created_by":"Bruno Postle","updated_at":"2026-06-12T13:07:37Z","started_at":"2026-06-12T12:54:23Z","closed_at":"2026-06-12T13:07:37Z","close_reason":"operators.py lands: 7 mutations + area-matched crossover, valid-by-construction via genome.encode repair. 115/115 oracle-valid children; locality measured: geom-pert 0.07-0.33 per op, fitness-pert 0.68-0.99 (0.5^n cliff flags raw moves — warm restart + penalty reshaping confirmed load-bearing). Also fixed dom._link stale below-links on structural mutation.","dependencies":[{"issue_id":"homemaker-py-nyb","depends_on_id":"homemaker-py-k2g","type":"blocks","created_at":"2026-06-12T00:39:36Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0} {"id":"homemaker-py-nyb","title":"High-locality topology operators (mutation + subtree crossover)","description":"DESIGN.md §5, §7 Phase 2, §8.4. Mutation moves: divide/undivide leaf, swap children, rotate cut, retype leaf, per-floor delta edits, storey add/delete (cf. Urb Mutate.pm — but geometry sliding belongs to the inner loop, not the operator set). Crossover: area-matched subtree exchange (a subtree = a contiguous region, so crossover is meaningful — Crossover.pm). Operators must be high-locality: small genome change =\u003e small phenotype change, so warm-started inner loops stay cheap.","acceptance_criteria":"Each operator produces valid genomes (oracle scores them without error); locality measured (mean fitness/geometry perturbation per operator)","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:37:27Z","created_by":"Bruno Postle","updated_at":"2026-06-12T13:07:37Z","started_at":"2026-06-12T12:54:23Z","closed_at":"2026-06-12T13:07:37Z","close_reason":"operators.py lands: 7 mutations + area-matched crossover, valid-by-construction via genome.encode repair. 115/115 oracle-valid children; locality measured: geom-pert 0.07-0.33 per op, fitness-pert 0.68-0.99 (0.5^n cliff flags raw moves — warm restart + penalty reshaping confirmed load-bearing). Also fixed dom._link stale below-links on structural mutation.","dependencies":[{"issue_id":"homemaker-py-nyb","depends_on_id":"homemaker-py-k2g","type":"blocks","created_at":"2026-06-12T00:39:36Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
{"id":"homemaker-py-k2g","title":"Topology genome: base-floor tree + per-floor deltas + type assignment","description":"DESIGN.md §5.2, §7 Phase 2. Genome = base-floor slicing topology (primary) + per-leaf type assignment + per-floor divide/undivide deltas (Below-inheritance as regulariser; cut owned by lowest storey where its path is divided — §10). Must round-trip to/from dom.py Node trees so the oracle and inner loop consume it directly. Includes storey count and per-floor type overrides.","acceptance_criteria":"Genome \u003c-\u003e .dom round-trip on all 35 corpus files preserves fitness; multi-storey wall stacking preserved","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:37:26Z","created_by":"Bruno Postle","updated_at":"2026-06-12T12:52:34Z","started_at":"2026-06-12T10:55:21Z","closed_at":"2026-06-12T12:52:34Z","close_reason":"genome.py encode/decode lands. 35/35 oracle fitness parity after round-trip (flag-on); genome fixed-point + owned-projection tests. Dead-field discovery: corpus upper storeys carry drifted dead divisions (97) and rotations (187) — canonicalised by decode, validated fitness-neutral.","dependency_count":0,"dependent_count":1,"comment_count":0} {"id":"homemaker-py-k2g","title":"Topology genome: base-floor tree + per-floor deltas + type assignment","description":"DESIGN.md §5.2, §7 Phase 2. Genome = base-floor slicing topology (primary) + per-leaf type assignment + per-floor divide/undivide deltas (Below-inheritance as regulariser; cut owned by lowest storey where its path is divided — §10). Must round-trip to/from dom.py Node trees so the oracle and inner loop consume it directly. Includes storey count and per-floor type overrides.","acceptance_criteria":"Genome \u003c-\u003e .dom round-trip on all 35 corpus files preserves fitness; multi-storey wall stacking preserved","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:37:26Z","created_by":"Bruno Postle","updated_at":"2026-06-12T12:52:34Z","started_at":"2026-06-12T10:55:21Z","closed_at":"2026-06-12T12:52:34Z","close_reason":"genome.py encode/decode lands. 35/35 oracle fitness parity after round-trip (flag-on); genome fixed-point + owned-projection tests. Dead-field discovery: corpus upper storeys carry drifted dead divisions (97) and rotations (187) — canonicalised by decode, validated fitness-neutral.","dependency_count":0,"dependent_count":1,"comment_count":0}
{"id":"homemaker-py-d0s","title":"Experiment: inner-loop optimiser bake-off at equal oracle budgets","description":"DESIGN.md §7 Phase 1, §8.3. DOF is only ~rooms-1 (67 on corpus). Compare Nelder-Mead vs CMA-ES vs batched multi-start pattern search at equal oracle-call budgets, measuring fitness gained per oracle call and wall-clock (batch-friendliness matters — §4.6). Measure, don't commit blind.","acceptance_criteria":"Table of fitness-per-budget across \u003e=3 candidates; one optimiser chosen and recorded in DESIGN.md","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:59Z","created_by":"Bruno Postle","updated_at":"2026-06-13T08:48:13Z","started_at":"2026-06-12T21:22:15Z","closed_at":"2026-06-13T08:48:13Z","close_reason":"Bake-off complete: CMA-ES confirmed as Phase 1/2 optimiser. NM wins quality per eval but sequential architecture incompatible with batching (§4.6). Compass stalls on narrow valleys. Results in DESIGN.md §8.3 and experiments/bakeoff_innerloop.*","dependencies":[{"issue_id":"homemaker-py-d0s","depends_on_id":"homemaker-py-1p0","type":"blocks","created_at":"2026-06-12T00:39:35Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-d0s","title":"Experiment: inner-loop optimiser bake-off at equal oracle budgets","description":"DESIGN.md §7 Phase 1, §8.3. DOF is only ~rooms-1 (67 on corpus). Compare Nelder-Mead vs CMA-ES vs batched multi-start pattern search at equal oracle-call budgets, measuring fitness gained per oracle call and wall-clock (batch-friendliness matters — §4.6). Measure, don't commit blind.","acceptance_criteria":"Table of fitness-per-budget across \u003e=3 candidates; one optimiser chosen and recorded in DESIGN.md","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-11T23:36:59Z","created_by":"Bruno Postle","updated_at":"2026-06-13T08:48:13Z","started_at":"2026-06-12T21:22:15Z","closed_at":"2026-06-13T08:48:13Z","close_reason":"Bake-off complete: CMA-ES confirmed as Phase 1/2 optimiser. NM wins quality per eval but sequential architecture incompatible with batching (§4.6). Compass stalls on narrow valleys. Results in DESIGN.md §8.3 and experiments/bakeoff_innerloop.*","dependencies":[{"issue_id":"homemaker-py-d0s","depends_on_id":"homemaker-py-1p0","type":"blocks","created_at":"2026-06-12T00:39:35Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-cdl","title":"Consider defaulting collapse_global local_search on + expose on evolve --collapse","description":"homemaker-py-9wi added Fitness._two_opt_adjacency_polish (2-opt swap search after the Jacobi adjacency fixpoint), gated behind collapse_global(local_search=True)/homemaker-collapse --local-search, default OFF. Empirical sweep over the 11 harbor-house .dom files: 0 regressions, 1 real improvement (evolved-anneal-3M.dom 21-\u003e19 fails, a genuine mutual-adjacency miss the Jacobi loop couldn't reach). Monotone by construction (only strictly-improving swaps kept) and cheap (\u003c1s on the largest file), so it looks safe to default on, but the sample is small (11 files, one non-synthetic dataset) and evolve.py's --collapse hook (driver.collapse_best) does not expose the flag at all yet. Before flipping the default: (1) run a broader sweep (programme-house + any other example sets) to confirm no regressions elsewhere, (2) add a --collapse-local-search passthrough to evolve.py's CLI alongside driver.collapse_best's **collapse_kw. Low priority -- collapse_finish's keep-better wrapper already makes the current opt-in flag safe to use standalone via homemaker-collapse.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-07-26T19:57:32Z","created_by":"Bruno Postle","updated_at":"2026-07-26T19:57:32Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-xyu","title":"Resolve n=18 ruin_recreate trend: larger-N or a non-synthetic third example (homemaker-py-y51 follow-up)","description":"y51's synthetic room-count sweep (DESIGN.md section 24) found no clean monotonic size threshold for ruin_recreate's benefit: n=10 mild win (N=5, ns), n=14 clean null (N=10), n=18 strongest trend (7W/2L/1T, +9.3% mean fails, Wilcoxon p=0.098, N=10) despite sitting between two weaker sizes, n=22 near-null (N=5). Not significant at conventional levels but the largest effect of the four, sandwiched non-monotonically.\n\nTwo possible follow-ups, not mutually exclusive:\n(a) Extend n=18 to N=15+ seeds (matching the N needed for f1d's own programme-house confirmation) to see if the trend firms up or was noise.\n(b) The synthetic sweep scales room count by duplicating already-interchangeable room codes (count: on b1/t1/b2/t2) -- the same mechanism harbor-house itself uses 'to reduce complexity'. A genuinely distinct third example programme (real room-type diversity at an intermediate room count, not a duplicated-code scale-up) would avoid this confound and better isolate room count as the driving variable behind the wing-rebuild-fraction hypothesis.\n\nLow priority -- enable_ruin_recreate's default-OFF status and existing programme-house-scale guidance are unaffected either way.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-07-26T14:33:20Z","created_by":"Bruno Postle","updated_at":"2026-07-26T14:33:20Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-xyu","title":"Resolve n=18 ruin_recreate trend: larger-N or a non-synthetic third example (homemaker-py-y51 follow-up)","description":"y51's synthetic room-count sweep (DESIGN.md section 24) found no clean monotonic size threshold for ruin_recreate's benefit: n=10 mild win (N=5, ns), n=14 clean null (N=10), n=18 strongest trend (7W/2L/1T, +9.3% mean fails, Wilcoxon p=0.098, N=10) despite sitting between two weaker sizes, n=22 near-null (N=5). Not significant at conventional levels but the largest effect of the four, sandwiched non-monotonically.\n\nTwo possible follow-ups, not mutually exclusive:\n(a) Extend n=18 to N=15+ seeds (matching the N needed for f1d's own programme-house confirmation) to see if the trend firms up or was noise.\n(b) The synthetic sweep scales room count by duplicating already-interchangeable room codes (count: on b1/t1/b2/t2) -- the same mechanism harbor-house itself uses 'to reduce complexity'. A genuinely distinct third example programme (real room-type diversity at an intermediate room count, not a duplicated-code scale-up) would avoid this confound and better isolate room count as the driving variable behind the wing-rebuild-fraction hypothesis.\n\nLow priority -- enable_ruin_recreate's default-OFF status and existing programme-house-scale guidance are unaffected either way.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-07-26T14:33:20Z","created_by":"Bruno Postle","updated_at":"2026-07-26T14:33:20Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-y51","title":"Locate the size threshold where ruin_recreate stops helping (homemaker-py-f1d follow-up)","description":"f1d (DESIGN.md §23) landed operators.mutate_ruin_recreate (LNS wing rebuild via the adjacency-aware\nconstructor) and validated it at weight=3.0: a statistically significant win on programme-house\nacross 15 seeds (8W/1L/6T, mean fails 7.07-\u003e6.00, Wilcoxon p=0.041) but no consistent effect on\nharbor-house across 8 seeds (3W/2L/3T, mean fails 73.0-\u003e74.5, slight negative lean). Kept\nenable_ruin_recreate default OFF because the two example programmes disagree on direction and only\ntwo sizes were tested -- same conservative bar homemaker-py-qpk applied before its own 1ph larger-N\nconfirmation.\n\nProposal: locate the threshold this size split implies rather than inferring it from two data\npoints. Either (a) a third example programme sized between programme-house and harbor-house's room\ncounts, run through the same qpk protocol (weight=3.0 ON vs OFF, both arms finished with\n--collapse), or (b) a synthetic room-count sweep on programme-house's own patterns.config (scaling\nrequired-space counts up) if a natural third example isn't available. Candidate hypothesis from\n§23's interpretation: the wing-rebuild's benefit tracks how large a fraction of the whole floor's\ntopology one wing move samples, which shrinks as room count grows -- worth checking directly against\nroom count rather than just building size.\n\nIf a threshold is found, flip enable_ruin_recreate's default per-programme-size (or document the\ncutoff for users to opt in below it) instead of leaving it a blanket manual flag.","notes":"Measured (2026-07-26): synthetic room-count sweep (10/14/18/22 rooms, programme-house-derived, budget=3000, weight=3.0 ON vs OFF). No clean monotonic threshold found -- n=10 mild win (N=5, ns), n=14 clean null after N=10 confirmation, n=18 strongest trend (7W/2L/1T, +9.3%, p=0.098, N=10) despite sitting between two weaker sizes, n=22 near-null (N=5). Full results + interpretation in DESIGN.md section 24. enable_ruin_recreate stays default OFF; no per-size flip supported. Caveat: sweep scales room count via duplicated interchangeable room codes (same mechanism harbor-house uses to reduce complexity), which may not isolate the same variable as a genuinely diverse third example programme would.","status":"closed","priority":3,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-26T08:36:17Z","created_by":"Bruno Postle","updated_at":"2026-07-26T14:33:29Z","started_at":"2026-07-26T09:34:23Z","closed_at":"2026-07-26T14:33:29Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-y51","title":"Locate the size threshold where ruin_recreate stops helping (homemaker-py-f1d follow-up)","description":"f1d (DESIGN.md §23) landed operators.mutate_ruin_recreate (LNS wing rebuild via the adjacency-aware\nconstructor) and validated it at weight=3.0: a statistically significant win on programme-house\nacross 15 seeds (8W/1L/6T, mean fails 7.07-\u003e6.00, Wilcoxon p=0.041) but no consistent effect on\nharbor-house across 8 seeds (3W/2L/3T, mean fails 73.0-\u003e74.5, slight negative lean). Kept\nenable_ruin_recreate default OFF because the two example programmes disagree on direction and only\ntwo sizes were tested -- same conservative bar homemaker-py-qpk applied before its own 1ph larger-N\nconfirmation.\n\nProposal: locate the threshold this size split implies rather than inferring it from two data\npoints. Either (a) a third example programme sized between programme-house and harbor-house's room\ncounts, run through the same qpk protocol (weight=3.0 ON vs OFF, both arms finished with\n--collapse), or (b) a synthetic room-count sweep on programme-house's own patterns.config (scaling\nrequired-space counts up) if a natural third example isn't available. Candidate hypothesis from\n§23's interpretation: the wing-rebuild's benefit tracks how large a fraction of the whole floor's\ntopology one wing move samples, which shrinks as room count grows -- worth checking directly against\nroom count rather than just building size.\n\nIf a threshold is found, flip enable_ruin_recreate's default per-programme-size (or document the\ncutoff for users to opt in below it) instead of leaving it a blanket manual flag.","notes":"Measured (2026-07-26): synthetic room-count sweep (10/14/18/22 rooms, programme-house-derived, budget=3000, weight=3.0 ON vs OFF). No clean monotonic threshold found -- n=10 mild win (N=5, ns), n=14 clean null after N=10 confirmation, n=18 strongest trend (7W/2L/1T, +9.3%, p=0.098, N=10) despite sitting between two weaker sizes, n=22 near-null (N=5). Full results + interpretation in DESIGN.md section 24. enable_ruin_recreate stays default OFF; no per-size flip supported. Caveat: sweep scales room count via duplicated interchangeable room codes (same mechanism harbor-house uses to reduce complexity), which may not isolate the same variable as a genuinely diverse third example programme would.","status":"closed","priority":3,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-07-26T08:36:17Z","created_by":"Bruno Postle","updated_at":"2026-07-26T14:33:29Z","started_at":"2026-07-26T09:34:23Z","closed_at":"2026-07-26T14:33:29Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-2ax","title":"Spike: autodiff/gradient-based inner-loop ratio optimisation","description":"innerloop.py's default ratio optimiser is multi-start Nelder-Mead (nm_search), chosen because it 'outperforms CMA-ES across harbor-house scale' -- both derivative-free, a legacy of the Perl-subprocess oracle era when the fitness function was not differentiable. Fitness is now a native Python port (fitness.py) with geometry (geometry.py) built from ordinary arithmetic (Heron's-formula areas etc.) that is plausibly differentiable end-to-end. Nobody has revisited derivative-based optimisation now that this is possible.\n\nReal risk to test rather than assume: the deliberately-preserved 0.5^n failure-count penalty cliff (DESIGN.md 4.5, kept specifically to protect the inner loop from trading into new failures) is a sharp discontinuity by design, which could make raw gradients unreliable or misleading near failure boundaries.\n\nScope as a SPIKE: implement the ratio-to-fitness path in a differentiable form (JAX or PyTorch, autodiff over cut ratios for a frozen topology), compare convergence speed/quality against nm_search on a handful of frozen topologies from programme-house and harbor-house before deciding whether to invest further. If gradients are usable, the payoff is a much faster inner loop, which frees budget for more topology exploration elsewhere -- but per 12.3's finding that the current residual is NOT search/eval-count bound, this may only pay off in future phases at larger scale, not on the current residual.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:27Z","created_by":"Bruno Postle","updated_at":"2026-07-25T20:18:27Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-2ax","title":"Spike: autodiff/gradient-based inner-loop ratio optimisation","description":"innerloop.py's default ratio optimiser is multi-start Nelder-Mead (nm_search), chosen because it 'outperforms CMA-ES across harbor-house scale' -- both derivative-free, a legacy of the Perl-subprocess oracle era when the fitness function was not differentiable. Fitness is now a native Python port (fitness.py) with geometry (geometry.py) built from ordinary arithmetic (Heron's-formula areas etc.) that is plausibly differentiable end-to-end. Nobody has revisited derivative-based optimisation now that this is possible.\n\nReal risk to test rather than assume: the deliberately-preserved 0.5^n failure-count penalty cliff (DESIGN.md 4.5, kept specifically to protect the inner loop from trading into new failures) is a sharp discontinuity by design, which could make raw gradients unreliable or misleading near failure boundaries.\n\nScope as a SPIKE: implement the ratio-to-fitness path in a differentiable form (JAX or PyTorch, autodiff over cut ratios for a frozen topology), compare convergence speed/quality against nm_search on a handful of frozen topologies from programme-house and harbor-house before deciding whether to invest further. If gradients are usable, the payoff is a much faster inner loop, which frees budget for more topology exploration elsewhere -- but per 12.3's finding that the current residual is NOT search/eval-count bound, this may only pay off in future phases at larger scale, not on the current residual.","status":"open","priority":3,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-07-25T20:18:27Z","created_by":"Bruno Postle","updated_at":"2026-07-25T20:18:27Z","dependency_count":0,"dependent_count":0,"comment_count":0}
@ -93,27 +94,27 @@
{"id":"homemaker-py-erc.6","title":"Experiment: inner-loop slack-expansion objective term","description":"Inner-loop counterpart to plot-fill construction. If Diagnostic B shows the inner loop has room to expand leaves into slack but no objective gradient to do so (the scalar rewards hitting target area but not exceeding it where slack exists), add a term/incentive so the ratio optimiser pushes leaf boundaries out to consume neighbouring slack and satisfy size, rather than parking at target.\n\nCONDITIONAL on Diagnostic B: build this only if B localizes the gap to the inner loop (room to expand, no gradient); if B shows construction targets too-small dims, prefer the plot-fill construction sibling. Must preserve the §5.4 inner-loop cliff / §4.9 lexicographic protection — the term sits where it cannot displace the fail-count ordering. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.6.","notes":"DEPRIORITISED by Diagnostic B (§13.2). B shows the inner loop CANNOT repair undersize: the slack is depth-driven maldistribution baked into the frozen topology, and the equal-offset ratio DOF cannot shrink a 14x leaf to feed a starved one without trading into shape fails (0.5^n cliff). Wrong DOF and wrong direction — the blocker is slicing POSITION, not a missing expansion reward. Fix belongs upstream in construction/topology (erc.4 re-scoped, erc.3). Keep as a low-priority follow-up only if a depth-balanced construction still leaves a residual size gradient the inner loop could pick up.","status":"closed","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:24Z","created_by":"Bruno Postle","updated_at":"2026-06-28T13:22:22Z","closed_at":"2026-06-28T13:22:22Z","close_reason":"wont-fix (DESIGN §13.7): Diag B (§13.2) showed the inner loop cannot repair undersize (wrong DOF — slicing position, frozen-topology ratios). Superseded by depth-balanced construction (erc.4). Condition unmet.","dependencies":[{"issue_id":"homemaker-py-erc.6","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:23Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.6","depends_on_id":"homemaker-py-erc.2","type":"blocks","created_at":"2026-06-23T00:16:47Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-erc.6","title":"Experiment: inner-loop slack-expansion objective term","description":"Inner-loop counterpart to plot-fill construction. If Diagnostic B shows the inner loop has room to expand leaves into slack but no objective gradient to do so (the scalar rewards hitting target area but not exceeding it where slack exists), add a term/incentive so the ratio optimiser pushes leaf boundaries out to consume neighbouring slack and satisfy size, rather than parking at target.\n\nCONDITIONAL on Diagnostic B: build this only if B localizes the gap to the inner loop (room to expand, no gradient); if B shows construction targets too-small dims, prefer the plot-fill construction sibling. Must preserve the §5.4 inner-loop cliff / §4.9 lexicographic protection — the term sits where it cannot displace the fail-count ordering. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.6.","notes":"DEPRIORITISED by Diagnostic B (§13.2). B shows the inner loop CANNOT repair undersize: the slack is depth-driven maldistribution baked into the frozen topology, and the equal-offset ratio DOF cannot shrink a 14x leaf to feed a starved one without trading into shape fails (0.5^n cliff). Wrong DOF and wrong direction — the blocker is slicing POSITION, not a missing expansion reward. Fix belongs upstream in construction/topology (erc.4 re-scoped, erc.3). Keep as a low-priority follow-up only if a depth-balanced construction still leaves a residual size gradient the inner loop could pick up.","status":"closed","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:24Z","created_by":"Bruno Postle","updated_at":"2026-06-28T13:22:22Z","closed_at":"2026-06-28T13:22:22Z","close_reason":"wont-fix (DESIGN §13.7): Diag B (§13.2) showed the inner loop cannot repair undersize (wrong DOF — slicing position, frozen-topology ratios). Superseded by depth-balanced construction (erc.4). Condition unmet.","dependencies":[{"issue_id":"homemaker-py-erc.6","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:23Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.6","depends_on_id":"homemaker-py-erc.2","type":"blocks","created_at":"2026-06-23T00:16:47Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-erc.5","title":"Experiment: compactness-aware cuts (minimize leaf perimeter/area)","description":"Attacks the #1 factor, crinkliness (346) — a per-leaf perimeter/area property DISTINCT from proportion (aspect ratio). Proportion-aware seeding (leu.2) sizes splits but does not bias toward balanced, square-ish subdivision. Add a KD-tree-style 'keep both children compact' cut rule (prefer the cut orientation/position that minimises summed child perimeter/area) in construction.\n\nCONDITIONAL on Diagnostic A: if A shows per-leaf shape-fail is FLAT across densities (floor intrinsic to slicing density), better cuts at the same leaf count will not pay → this should be closed wont-fix in favour of leaf-sharing. Only build if A shows shape-fail RISES with density. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.5.","notes":"DEPRIORITISED by erc.1 verdict (§13.1): per-leaf shape-fail flat vs slicing density and cuts already squarest (_size_divisions_from_targets picks squarest rotation) yet still ~1.8 fails/leaf =\u003e little compactness headroom at fixed leaf count. Floor is intrinsic to leaf COUNT, not cut quality. Revisit only if leaf-sharing (erc.3) underdelivers.","status":"closed","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:21Z","created_by":"Bruno Postle","updated_at":"2026-06-28T13:22:17Z","closed_at":"2026-06-28T13:22:17Z","close_reason":"wont-fix (DESIGN §13.7): Diag A (§13.1) showed the floor is intrinsic to leaf COUNT not cut quality; revisit condition was 'only if leaf-sharing underdelivers' but leaf-sharing OVER-delivered (32…39%, §13.3). Condition unmet.","dependencies":[{"issue_id":"homemaker-py-erc.5","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:21Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.5","depends_on_id":"homemaker-py-erc.1","type":"blocks","created_at":"2026-06-23T00:16:43Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-erc.5","title":"Experiment: compactness-aware cuts (minimize leaf perimeter/area)","description":"Attacks the #1 factor, crinkliness (346) — a per-leaf perimeter/area property DISTINCT from proportion (aspect ratio). Proportion-aware seeding (leu.2) sizes splits but does not bias toward balanced, square-ish subdivision. Add a KD-tree-style 'keep both children compact' cut rule (prefer the cut orientation/position that minimises summed child perimeter/area) in construction.\n\nCONDITIONAL on Diagnostic A: if A shows per-leaf shape-fail is FLAT across densities (floor intrinsic to slicing density), better cuts at the same leaf count will not pay → this should be closed wont-fix in favour of leaf-sharing. Only build if A shows shape-fail RISES with density. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.5.","notes":"DEPRIORITISED by erc.1 verdict (§13.1): per-leaf shape-fail flat vs slicing density and cuts already squarest (_size_divisions_from_targets picks squarest rotation) yet still ~1.8 fails/leaf =\u003e little compactness headroom at fixed leaf count. Floor is intrinsic to leaf COUNT, not cut quality. Revisit only if leaf-sharing (erc.3) underdelivers.","status":"closed","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:21Z","created_by":"Bruno Postle","updated_at":"2026-06-28T13:22:17Z","closed_at":"2026-06-28T13:22:17Z","close_reason":"wont-fix (DESIGN §13.7): Diag A (§13.1) showed the floor is intrinsic to leaf COUNT not cut quality; revisit condition was 'only if leaf-sharing underdelivers' but leaf-sharing OVER-delivered (32…39%, §13.3). Condition unmet.","dependencies":[{"issue_id":"homemaker-py-erc.5","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:21Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.5","depends_on_id":"homemaker-py-erc.1","type":"blocks","created_at":"2026-06-23T00:16:43Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
{"id":"homemaker-py-2g5","title":"Rebuild occlusion/daylight/sun subsystem in Python (post-Phase-5, after optimisation fully native)","description":"DESIGN.md §6 port scope — a whole subsystem, not a term. quality_daylight (Leaf.pm:281-296) needs Urb::Misc::Sun + Urb::Field::Occlusion (+CIESky); quality_uncrinkliness also takes the occlusion object. Indoor spaces return 1 for daylight; cost is outdoor spaces + crinkliness. Port Sun_horizontal (262980-minute normalisation) and the occlusion wall set from Dom-\u003eWalls.","acceptance_criteria":"Daylight and crinkliness factors match Perl (float tolerance) across the corpus, including multi-storey cases","notes":"Re-scoped 2026-06-12: occlusion disabled in the Urb oracle instead of ported (see homemaker-py-gp2). Native fitness ships with simple crinkliness (illumination factor = 1, in homemaker-py-gnw). This issue is now the eventual Python occlusion rebuild, only after optimisation works entirely in Python. Restores outdoor-daylight and shaded-wall selection pressure.\nReframed 2026-06-17: orthogonal to epic homemaker-py-c4c. This is fitness FIDELITY (restoring daylight + shaded-wall selection pressure to match Perl), not search CAPABILITY — it changes what 'good' means, not the search's ability to find good. It will NOT improve final designs in the sense currently sought. Stays P4, deferred until the topology-search-quality epic lands and optimisation is fully native.","status":"open","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-11T23:38:25Z","created_by":"Bruno Postle","updated_at":"2026-06-17T19:14:48Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"id":"homemaker-py-2g5","title":"Rebuild occlusion/daylight/sun subsystem in Python (post-Phase-5, after optimisation fully native)","description":"DESIGN.md §6 port scope — a whole subsystem, not a term. quality_daylight (Leaf.pm:281-296) needs Urb::Misc::Sun + Urb::Field::Occlusion (+CIESky); quality_uncrinkliness also takes the occlusion object. Indoor spaces return 1 for daylight; cost is outdoor spaces + crinkliness. Port Sun_horizontal (262980-minute normalisation) and the occlusion wall set from Dom-\u003eWalls.","acceptance_criteria":"Daylight and crinkliness factors match Perl (float tolerance) across the corpus, including multi-storey cases","notes":"Re-scoped 2026-06-12: occlusion disabled in the Urb oracle instead of ported (see homemaker-py-gp2). Native fitness ships with simple crinkliness (illumination factor = 1, in homemaker-py-gnw). This issue is now the eventual Python occlusion rebuild, only after optimisation works entirely in Python. Restores outdoor-daylight and shaded-wall selection pressure.\nReframed 2026-06-17: orthogonal to epic homemaker-py-c4c. This is fitness FIDELITY (restoring daylight + shaded-wall selection pressure to match Perl), not search CAPABILITY — it changes what 'good' means, not the search's ability to find good. It will NOT improve final designs in the sense currently sought. Stays P4, deferred until the topology-search-quality epic lands and optimisation is fully native.","status":"open","priority":4,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-06-11T23:38:25Z","created_by":"Bruno Postle","updated_at":"2026-06-17T19:14:48Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"memory","key":"adjacency-in-binary-slicing-tree-is-structural-not","value":"Adjacency in binary slicing tree is structural, not geometric: the inner-loop NM cannot fix topological adjacency failures. Two paths exist: (1) tree-sibling adjacency — a node is adjacent to its sibling in the tree; (2) cross-zone geometric adjacency — leaves from different subtrees that happen to share a boundary. Staircase/adjacency fails require a topology mutation that changes which nodes are siblings or which zones touch. This was proved empirically on programme-house: staircase fail from rot=0 layout could not be fixed by NM but was fixed by level_retype creating a two-C topology (2026-06-14/15)."}
{"_type":"memory","key":"cli-tool-style-prefer-python-m-homemaker-module","value":"CLI tool style: prefer python -m homemaker.module --parameters pattern, installable via pip install -e . with pyproject.toml entry_points. Not standalone bin/ scripts."}
{"_type":"memory","key":"experiment-harness-gotcha-the-leaf-sharing-relaxed-objective","value":"Experiment harness gotcha: the leaf-sharing RELAXED objective (§13.3) is injected ONLY by monkeypatching fitness.load_config in the parent process (run_staged_search.py / probe scripts). This is parent-process-only and does NOT propagate into ProcessPoolExecutor workers (n_workers\u003e1), which re-import fitness fresh and score under the STRICT on-disk patterns.config -\u003e r.n_fails MISMATCH (worker strict vs parent relaxed re-score). ALL §13.x floor runs were therefore SERIAL. Any future PARALLEL leaf-sharing experiment will silently mis-score until leaf_sharing lives on disk/CLI (tracked: homemaker-py-x3b). The parallel driver itself is correct; both paths score via load_config(programme_dir)."}
{"_type":"memory","key":"experiment-seeding-pitfall-run-search-scaled-py-s","value":"Experiment seeding pitfall: run_search_scaled.py's default PH_SEED (c964…dom) is a FINISHED programme-house design — passing it warm-starts and floors at ~3 fails, NOT a blank-slate topology search. For blank-slate runs comparable to §11.5/§11.6 baselines, seed from examples/programme-house/init.dom (a bare undivided plot; driver bootstrap auto-triggers only on bare plots). Bit the 6zy sweep — first pass used c964 and falsely showed 3-fail floor across the whole grid."}
{"_type":"memory","key":"ld2-13-6-interior-o-seed-diagnostic-all","value":"ld2/§13.6 interior-O seed diagnostic: ALL crinkliness fails in the constructed bal+share seed are UNDER-exposed (crink\u003c0.62, landlocked rooms with no facade + no uncovered-O neighbour) — zero over-exposed sliver fails. So the erc crinkliness residual is genuine under-daylighting, validating the interior light-well premise. Default outside_divisor=6 was too sparse (null: harbor 147-\u003e142, crinkliness even rose). odiv=3 is the seed-optimal joint setting: harbor seed fails 147-\u003e129 (-18), maple 219-\u003e206 (-14), landlocked fails drop, at cost of more leaves (harbor +4, maple +8). Because it ADDS leaves it carries the §13.4 wash-out risk; A/B to convergence pending."}
{"_type":"memory","key":"programme-house-optimisation-result-2026-06-14-15","value":"Programme-house optimisation result (2026-06-14/15): best achievable is 1 fail (l1 wrong level, score ~0.005). 0 fails is geometrically impossible: l1 (min 27m²) must occupy ll (~23m²) at level 0, which eliminates the t3-adj-C provider; dividing ll into lll(l1)+llr(C) gives llr proportion ~6:1 (fails). Python memetic optimizer achieves 1 fail in 50k evals vs Perl optimiser's 2-3 fails. Winning topology: TWO C nodes at level 0 — ll(C) for t3-adj-C via geometric contact, rl(C) for staircase via tree-sibling adjacency to rrr(O). Best .dom: scratch/from-warmstart-fixed.dom and scratch/from-compound3-fixed.dom."}
{"_type":"memory","key":"collapse-global-s-jacobi-adjacency-relaxation-homemaker-py","value":"collapse_global's Jacobi adjacency relaxation (homemaker-py-94g) is a synchronous per-round linear-assignment re-solve, which can 2-cycle indefinitely between two labellings that each satisfy ZERO adjacency requirements even though a permutation satisfying ALL of them exists -- proven on a minimal 4-cell chain (p1-q1-p2-q2, two disjoint adjacency pairs p1\u003c-\u003ep2/q1\u003c-\u003eq2) in test_two_opt_polish_escapes_jacobi_plateau. homemaker-py-9wi added Fitness._two_opt_adjacency_polish: a same-level pairwise-swap local search run after the Jacobi fixpoint, gated behind collapse_global(local_search=True) (default off, exposed as homemaker-collapse --local-search). Monotone by construction (a swap is kept only if it strictly increases total reward). Empirically on the 11 harbor-house evolved-*.dom/3m.dom/materialised-3M.dom layouts: 10 matched Jacobi-only exactly, 0 regressed, and evolved-anneal-3M.dom improved 21-\u003e19 fails (fixed a genuine mutual da1\u003c-\u003ek1 adjacency miss the Jacobi loop couldn't reach)."}
{"_type":"memory","key":"urb-fitness-bug-found-fixed-2026-06-12","value":"Urb fitness bug found+fixed 2026-06-12 (patch in /home/bruno/src/urb, uncommitted): ProgrammeDriven.pm ratio_o/ratio_type grepped case-insensitively over the ratios hash and took the FIRST key — nondeterministic (x4.5 score swings) for designs with mixed-case type classes (both 'c' circulation and 'C' covered). Fixed to SUM the class (matches Is_Circulation//Is_Outside semantics); 35/35 corpus scores unchanged. CRITICAL for homemaker-py-3y7/gnw: the native port must implement class-SUM ratios. Building.pm has the same unpatched pattern (site-driven path, not used by our oracle). Also: the memetic search reward-hacked this bug before the fix — search results predating it are noise artifacts."}
{"_type":"memory","key":"urb-oracle-nondeterminism-urb-fitness-pl-output-varies","value":"Urb oracle nondeterminism: urb-fitness.pl output varies run-to-run from Perl hash-order randomisation — .fails line ORDER shuffles (compare sorted, use oracle.Score.fail_lines) and the score float can flip by ~1 ULP (compare with math.isclose rel_tol=1e-12, never ==). Not a batching artifact; affects single runs too. Matters for the Phase 3 native-fitness parity gate (homemaker-py-uxz)."}
{"_type":"memory","key":"user-preference-bruno-this-is-a-fedora-system","value":"User preference (Bruno): this is a Fedora system — NEVER install Python packages via pip without asking first; always ask whether to install the rpm via dnf (e.g. python3-cma) before considering pip. Applies to any dependency additions."}
{"_type":"memory","key":"homemaker-py-pythonpath-set-pythonpath-home-bruno-src","value":"homemaker-layout PYTHONPATH: package installed as 'homemaker-layout' via pip install -e . so 'import homemaker_layout' works from anywhere without PYTHONPATH. For running tests use 'python -m pytest' from project root /home/bruno/src/homemaker-layout (pyproject.toml adds src/ automatically). Never try pip show homemaker — that's the old homemaker-addon conflict."}
{"_type":"memory","key":"proportion-aware-constructive-seeding-leu-2-12-2","value":"Proportion-aware constructive seeding (leu.2/§12.2): sizing seed cuts from target AREAS only regresses (thin slivers wreck aspect); you must ALSO pick each cut's rotation for child squareness. It is a convergence ACCELERATOR via a deeper local optimum around the constructed topology: wins where that topology is roughly right and budget is scarce (harbor -13%, maple -10% at 20k evals) but DELAYS small programmes where the seed must be restructured by undivide (programme-house regresses at fixed budget, yet reaches the floor given budget - speed, not asymptote). Default-on. Also: n_storeys must honour storey_minimum, not just level: keys (programme-house storey_minimum:2, all rooms level:0 - was seeded 1 storey short; cq1)."}
{"_type":"memory","key":"unfold-strategy-for-shared-leaves-homemaker-py-8iv","value":"Unfold strategy for shared leaves (homemaker-py-8iv, resolved 2026-07-16): use the BALANCED GRID (operators._grow_balanced/_size_subtree_equal), NOT circulation-aware slicing. Slicing a shared leaf perpendicular to its access edge so every child touches the corridor was implemented + A/B-tested and LOST decisively (150k-eval warm-start polish from evolved-3M: slice 41 fails/3.5e-14 vs grid 25 fails/2.4e-09, grid ahead at every milestone). Reason: k rooms all touching one wall are intrinsically thin slices; that geometric debt (proportion/long/width) is unfixable without topology change, while the grid's squarer children let local search re-route access cheaply via level_retype/place_missing/level_fix. Lesson: at the sharing-\u003eno-sharing transition, prioritise squarer children and leave access to local search; do not reintroduce slicing in Schedule B (kpu)."}
{"_type":"memory","key":"never-use-corpus-filenames-candidate-001-dom-candidate","value":"Never use corpus filenames (candidate-001.dom, candidate-002.dom, generated.dom, init.dom, etc.) as --output targets when running experiments. These are test fixtures. Always write experimental outputs to scratch/ or a timestamped path. Lesson from 2026-06-14: warm-start runs overwrote candidate-001/002.dom and broke graph tests."}
{"_type":"memory","key":"run-to-run-reproducibility-in-homemaker-layout-serial","value":"Run-to-run reproducibility in homemaker-layout: serial search (workers=1) is byte-for-byte deterministic; parallel (workers\u003e1) is now deterministic too AFTER fixing driver._run_batch to admit futures in submission order (was as_completed/completion order, bug xcy). Reproducibility holds only for a FIXED worker count — serial vs parallel differ because children-per-iteration is 1 vs n_workers (different batch granularity), which is expected, not a bug. The constructive seeder was NEVER nondeterministic: _assign_adjacency_aware has unique idx tiebreaks; comparing topologies with Python builtin hash() of the signature STRING is invalid (PYTHONHASHSEED salts str hashing per process) — use a stable hash (sha1) or genome.signature equality."}
{"_type":"memory","key":"9o5-multi-use-leaves-is-path-a-superposition","value":"9o5 multi-use leaves is path (a) — superposition as SEARCH RELAXATION that COLLAPSES to specific usage at the end, NOT path (b) loose-fit/no-collapse. Bruno's intent: codes with SIMILAR leaf requirements form an interchangeable equivalence class; during evolution the solver doesn't commit which leaf serves which specific usage (smoother landscape, no fighting over exact leaf usage); at the end the layout is CONDENSED to specific usages by brute-forcing the in-class assignment (3 interchangeable usages over 3 leaves = 3! = 6 combinations to check, pick best). 'Derive automatically' compatibility = requirement-similarity grouping. This reverses the issue's stated 'path b preferred' note."}
{"_type":"memory","key":"correction-to-urb-fitness-bug-memory-bruno-2026","value":"CORRECTION to urb-fitness-bug memory (Bruno, 2026-06-12): 'C' is NOT a 'covered' type — Is_Covered is a geometric predicate (indoor space above). Urb's generic types are canonically UPPERCASE: C=circulation, O=outside, S=sahn (get_space_types qw/C O S/; corpus is 100% uppercase, never 'c'/'o' leaves). The mixed-case designs that fired the latent ratio_type first-match bug were created by homemaker's own operator type pool emitting lowercase 'c'/'o' — fixed: driver/operators now emit uppercase generics only, and class checks use t[0].lower() in 'cos'. The Urb class-sum patch stays as defensive hardening (zero impact on canonical designs). Native port (3y7/gnw): treat type classes case-insensitively, generics canonically uppercase."}
{"_type":"memory","key":"deceptive-valleys-in-topology-search-when-every-single","value":"Deceptive valleys in topology search: when every single-step mutation from a target state passes through a high-fail intermediary (e.g. level_fix displaces a room into 5+ new fails), a compound operator that atomically applies two coordinated changes can escape. Design compound operators to land on the low-fail state directly, bypassing the deceptive gradient. Programme-house example: level_compound_fix atomically moves the level-constrained room AND re-inserts the displaced room adjacent to C in one step (operators.py, 2026-06-14)."} {"_type":"memory","key":"deceptive-valleys-in-topology-search-when-every-single","value":"Deceptive valleys in topology search: when every single-step mutation from a target state passes through a high-fail intermediary (e.g. level_fix displaces a room into 5+ new fails), a compound operator that atomically applies two coordinated changes can escape. Design compound operators to land on the low-fail state directly, bypassing the deceptive gradient. Programme-house example: level_compound_fix atomically moves the level-constrained room AND re-inserts the displaced room adjacent to C in one step (operators.py, 2026-06-14)."}
{"_type":"memory","key":"strategy-decision-2026-06-12-bruno-occlusion-daylight","value":"Strategy decision 2026-06-12 (Bruno): occlusion/daylight is ORTHOGONAL to building a scalable optimiser. Disable it in Urb (env flag, homemaker-py-gp2) rather than port it; native fitness uses simple crinkliness (illumination factor = 1); rebuild occlusion in Python only after optimisation is fully native (homemaker-py-2g5, now P4). Consequence: all scores change when the flag flips — re-baseline corpus/.score, DESIGN \\$4.5 gains, gate bars at one clean boundary AFTER homemaker-py-1p0 closes; Phase-2 urb-evolve benchmark must run with the same flag."} {"_type":"memory","key":"homemaker-py-pythonpath-set-pythonpath-home-bruno-src","value":"homemaker-layout PYTHONPATH: package installed as 'homemaker-layout' via pip install -e . so 'import homemaker_layout' works from anywhere without PYTHONPATH. For running tests use 'python -m pytest' from project root /home/bruno/src/homemaker-layout (pyproject.toml adds src/ automatically). Never try pip show homemaker — that's the old homemaker-addon conflict."}
{"_type":"memory","key":"collapse-global-94g-and-any-label-usage-optimisation","value":"collapse_global (94g) and any label/usage optimisation CANNOT fix geometry-intrinsic fails. The harbor-house 15-fail best layout contains long-thin cells that are useless whatever room usage is assigned — their width/proportion/crinkliness fails are shape-bound, not label slack. Two consequences: (1) do not over-claim collapse gains — only ~2-3 of that layout's fails are reclaimable relabel slack, the rest are geometry- or building-level bound; (2) the threshold objective must not be tuned to 'pass' a degenerate cell via a permissive room type — a metric-pass on a physically useless space is gaming, not a fix. Real remedies for these are geometry/topology search (cell shape) and circulation placement, filed separately, not the collapse."}
{"_type":"memory","key":"homemaker-py-3l6-fix-leaf-sharing-evolve-runs","value":"homemaker-py-3l6 fix: leaf-sharing evolve runs now auto-finish before write via driver.polish_finish — unfold_shared_leaves() then a warm-started leaf_sharing=False polish search (--polish-budget, default budget//2). Makes the written .dom honest under canonical homemaker-fitness (internal==canonical when leaf_sharing off). Interrupt path forces polish_budget=0 (unfold+rescore only). This is yaa's unfold-then-polish, made automatic; Schedule B annealing is still kpu."} {"_type":"memory","key":"homemaker-py-3l6-fix-leaf-sharing-evolve-runs","value":"homemaker-py-3l6 fix: leaf-sharing evolve runs now auto-finish before write via driver.polish_finish — unfold_shared_leaves() then a warm-started leaf_sharing=False polish search (--polish-budget, default budget//2). Makes the written .dom honest under canonical homemaker-fitness (internal==canonical when leaf_sharing off). Interrupt path forces polish_budget=0 (unfold+rescore only). This is yaa's unfold-then-polish, made automatic; Schedule B annealing is still kpu."}
{"_type":"memory","key":"island-model-psk-14-is-a-null-priming","value":"Island model (psk, §14) is a NULL: priming a population from N converged independent elites + crossover-heavy migration does not beat best-of-N at equal total budget (maple island 124 vs control 116). The child_probe instrument shows WHY: area-matched crossover across independently-converged elites almost never synthesizes (1-3 of ~64 children beat the better parent, max drop 2-5) because the slicing encoding is non-canonical (9gp), so splices are disruptive not combinatorial. Search-machinery null #3 after graded-objective and niching/restarts; residual stays geometry/shape-bound."} {"_type":"memory","key":"island-model-psk-14-is-a-null-priming","value":"Island model (psk, §14) is a NULL: priming a population from N converged independent elites + crossover-heavy migration does not beat best-of-N at equal total budget (maple island 124 vs control 116). The child_probe instrument shows WHY: area-matched crossover across independently-converged elites almost never synthesizes (1-3 of ~64 children beat the better parent, max drop 2-5) because the slicing encoding is non-canonical (9gp), so splices are disruptive not combinatorial. Search-machinery null #3 after graded-objective and niching/restarts; residual stays geometry/shape-bound."}
{"_type":"memory","key":"warm-x0-initialization-bug-pattern-when-a-topology","value":"warm_x0 initialization bug pattern: when a topology operator explicitly sets division ratios on a newly-created node (e.g. compound_fix sets node.division=[0.25,0.25] for t3), parent.ratios has no entry for that node (it was a leaf). warm_x0 defaults it to 0.5, corrupting the inner loop's starting point and making the operator invisible to lex comparison. Fix: only propagate child ratios for nodes where the parent node was NOT already divided; stale hidden nodes revealed by structural mutations (swap flipping b.below) must NOT contribute their pre-writeback values. See driver.py lines 259-267 (fixed 2026-06-14)."} {"_type":"memory","key":"correction-to-urb-fitness-bug-memory-bruno-2026","value":"CORRECTION to urb-fitness-bug memory (Bruno, 2026-06-12): 'C' is NOT a 'covered' type — Is_Covered is a geometric predicate (indoor space above). Urb's generic types are canonically UPPERCASE: C=circulation, O=outside, S=sahn (get_space_types qw/C O S/; corpus is 100% uppercase, never 'c'/'o' leaves). The mixed-case designs that fired the latent ratio_type first-match bug were created by homemaker's own operator type pool emitting lowercase 'c'/'o' — fixed: driver/operators now emit uppercase generics only, and class checks use t[0].lower() in 'cos'. The Urb class-sum patch stays as defensive hardening (zero impact on canonical designs). Native port (3y7/gnw): treat type classes case-insensitively, generics canonically uppercase."}
{"_type":"memory","key":"ld2-13-6-interior-o-seed-diagnostic-all","value":"ld2/§13.6 interior-O seed diagnostic: ALL crinkliness fails in the constructed bal+share seed are UNDER-exposed (crink\u003c0.62, landlocked rooms with no facade + no uncovered-O neighbour) — zero over-exposed sliver fails. So the erc crinkliness residual is genuine under-daylighting, validating the interior light-well premise. Default outside_divisor=6 was too sparse (null: harbor 147-\u003e142, crinkliness even rose). odiv=3 is the seed-optimal joint setting: harbor seed fails 147-\u003e129 (-18), maple 219-\u003e206 (-14), landlocked fails drop, at cost of more leaves (harbor +4, maple +8). Because it ADDS leaves it carries the §13.4 wash-out risk; A/B to convergence pending."}
{"_type":"memory","key":"multi-storey-staircase-consistency-when-dividing-or-retyping","value":"Multi-storey staircase consistency: when dividing or retyping a circulation (C) leaf at one level, the same structural change should be propagated to the matching leaf on ALL other storeys so the stair core path is maintained. The optimizer cannot fix staircase disruptions through trial-and-error geometry alone — it requires a synchronized multi-level operator that applies the same topology change to every storey simultaneously."} {"_type":"memory","key":"multi-storey-staircase-consistency-when-dividing-or-retyping","value":"Multi-storey staircase consistency: when dividing or retyping a circulation (C) leaf at one level, the same structural change should be propagated to the matching leaf on ALL other storeys so the stair core path is maintained. The optimizer cannot fix staircase disruptions through trial-and-error geometry alone — it requires a synchronized multi-level operator that applies the same topology change to every storey simultaneously."}
{"_type":"memory","key":"warm-x0-initialization-bug-pattern-when-a-topology","value":"warm_x0 initialization bug pattern: when a topology operator explicitly sets division ratios on a newly-created node (e.g. compound_fix sets node.division=[0.25,0.25] for t3), parent.ratios has no entry for that node (it was a leaf). warm_x0 defaults it to 0.5, corrupting the inner loop's starting point and making the operator invisible to lex comparison. Fix: only propagate child ratios for nodes where the parent node was NOT already divided; stale hidden nodes revealed by structural mutations (swap flipping b.below) must NOT contribute their pre-writeback values. See driver.py lines 259-267 (fixed 2026-06-14)."}
{"_type":"memory","key":"cli-tool-style-prefer-python-m-homemaker-module","value":"CLI tool style: prefer python -m homemaker.module --parameters pattern, installable via pip install -e . with pyproject.toml entry_points. Not standalone bin/ scripts."}
{"_type":"memory","key":"collapse-global-s-jacobi-adjacency-relaxation-homemaker-py","value":"collapse_global's Jacobi adjacency relaxation (homemaker-py-94g) is a synchronous per-round linear-assignment re-solve, which can 2-cycle indefinitely between two labellings that each satisfy ZERO adjacency requirements even though a permutation satisfying ALL of them exists -- proven on a minimal 4-cell chain (p1-q1-p2-q2, two disjoint adjacency pairs p1\u003c-\u003ep2/q1\u003c-\u003eq2) in test_two_opt_polish_escapes_jacobi_plateau. homemaker-py-9wi added Fitness._two_opt_adjacency_polish: a same-level pairwise-swap local search run after the Jacobi fixpoint, gated behind collapse_global(local_search=True) (default off, exposed as homemaker-collapse --local-search). Monotone by construction (a swap is kept only if it strictly increases total reward). Empirically on the 11 harbor-house evolved-*.dom/3m.dom/materialised-3M.dom layouts: 10 matched Jacobi-only exactly, 0 regressed, and evolved-anneal-3M.dom improved 21-\u003e19 fails (fixed a genuine mutual da1\u003c-\u003ek1 adjacency miss the Jacobi loop couldn't reach)."}
{"_type":"memory","key":"9o5-multi-use-leaves-is-path-a-superposition","value":"9o5 multi-use leaves is path (a) — superposition as SEARCH RELAXATION that COLLAPSES to specific usage at the end, NOT path (b) loose-fit/no-collapse. Bruno's intent: codes with SIMILAR leaf requirements form an interchangeable equivalence class; during evolution the solver doesn't commit which leaf serves which specific usage (smoother landscape, no fighting over exact leaf usage); at the end the layout is CONDENSED to specific usages by brute-forcing the in-class assignment (3 interchangeable usages over 3 leaves = 3! = 6 combinations to check, pick best). 'Derive automatically' compatibility = requirement-similarity grouping. This reverses the issue's stated 'path b preferred' note."}
{"_type":"memory","key":"experiment-seeding-pitfall-run-search-scaled-py-s","value":"Experiment seeding pitfall: run_search_scaled.py's default PH_SEED (c964…dom) is a FINISHED programme-house design — passing it warm-starts and floors at ~3 fails, NOT a blank-slate topology search. For blank-slate runs comparable to §11.5/§11.6 baselines, seed from examples/programme-house/init.dom (a bare undivided plot; driver bootstrap auto-triggers only on bare plots). Bit the 6zy sweep — first pass used c964 and falsely showed 3-fail floor across the whole grid."}
{"_type":"memory","key":"strategy-decision-2026-06-12-bruno-occlusion-daylight","value":"Strategy decision 2026-06-12 (Bruno): occlusion/daylight is ORTHOGONAL to building a scalable optimiser. Disable it in Urb (env flag, homemaker-py-gp2) rather than port it; native fitness uses simple crinkliness (illumination factor = 1); rebuild occlusion in Python only after optimisation is fully native (homemaker-py-2g5, now P4). Consequence: all scores change when the flag flips — re-baseline corpus/.score, DESIGN \\$4.5 gains, gate bars at one clean boundary AFTER homemaker-py-1p0 closes; Phase-2 urb-evolve benchmark must run with the same flag."}
{"_type":"memory","key":"unfold-strategy-for-shared-leaves-homemaker-py-8iv","value":"Unfold strategy for shared leaves (homemaker-py-8iv, resolved 2026-07-16): use the BALANCED GRID (operators._grow_balanced/_size_subtree_equal), NOT circulation-aware slicing. Slicing a shared leaf perpendicular to its access edge so every child touches the corridor was implemented + A/B-tested and LOST decisively (150k-eval warm-start polish from evolved-3M: slice 41 fails/3.5e-14 vs grid 25 fails/2.4e-09, grid ahead at every milestone). Reason: k rooms all touching one wall are intrinsically thin slices; that geometric debt (proportion/long/width) is unfixable without topology change, while the grid's squarer children let local search re-route access cheaply via level_retype/place_missing/level_fix. Lesson: at the sharing-\u003eno-sharing transition, prioritise squarer children and leave access to local search; do not reintroduce slicing in Schedule B (kpu)."}
{"_type":"memory","key":"urb-fitness-bug-found-fixed-2026-06-12","value":"Urb fitness bug found+fixed 2026-06-12 (patch in /home/bruno/src/urb, uncommitted): ProgrammeDriven.pm ratio_o/ratio_type grepped case-insensitively over the ratios hash and took the FIRST key — nondeterministic (x4.5 score swings) for designs with mixed-case type classes (both 'c' circulation and 'C' covered). Fixed to SUM the class (matches Is_Circulation//Is_Outside semantics); 35/35 corpus scores unchanged. CRITICAL for homemaker-py-3y7/gnw: the native port must implement class-SUM ratios. Building.pm has the same unpatched pattern (site-driven path, not used by our oracle). Also: the memetic search reward-hacked this bug before the fix — search results predating it are noise artifacts."}
{"_type":"memory","key":"user-preference-bruno-this-is-a-fedora-system","value":"User preference (Bruno): this is a Fedora system — NEVER install Python packages via pip without asking first; always ask whether to install the rpm via dnf (e.g. python3-cma) before considering pip. Applies to any dependency additions."}
{"_type":"memory","key":"adjacency-in-binary-slicing-tree-is-structural-not","value":"Adjacency in binary slicing tree is structural, not geometric: the inner-loop NM cannot fix topological adjacency failures. Two paths exist: (1) tree-sibling adjacency — a node is adjacent to its sibling in the tree; (2) cross-zone geometric adjacency — leaves from different subtrees that happen to share a boundary. Staircase/adjacency fails require a topology mutation that changes which nodes are siblings or which zones touch. This was proved empirically on programme-house: staircase fail from rot=0 layout could not be fixed by NM but was fixed by level_retype creating a two-C topology (2026-06-14/15)."}
{"_type":"memory","key":"experiment-harness-gotcha-the-leaf-sharing-relaxed-objective","value":"Experiment harness gotcha: the leaf-sharing RELAXED objective (§13.3) is injected ONLY by monkeypatching fitness.load_config in the parent process (run_staged_search.py / probe scripts). This is parent-process-only and does NOT propagate into ProcessPoolExecutor workers (n_workers\u003e1), which re-import fitness fresh and score under the STRICT on-disk patterns.config -\u003e r.n_fails MISMATCH (worker strict vs parent relaxed re-score). ALL §13.x floor runs were therefore SERIAL. Any future PARALLEL leaf-sharing experiment will silently mis-score until leaf_sharing lives on disk/CLI (tracked: homemaker-py-x3b). The parallel driver itself is correct; both paths score via load_config(programme_dir)."}
{"_type":"memory","key":"urb-oracle-nondeterminism-urb-fitness-pl-output-varies","value":"Urb oracle nondeterminism: urb-fitness.pl output varies run-to-run from Perl hash-order randomisation — .fails line ORDER shuffles (compare sorted, use oracle.Score.fail_lines) and the score float can flip by ~1 ULP (compare with math.isclose rel_tol=1e-12, never ==). Not a batching artifact; affects single runs too. Matters for the Phase 3 native-fitness parity gate (homemaker-py-uxz)."}
{"_type":"memory","key":"proportion-aware-constructive-seeding-leu-2-12-2","value":"Proportion-aware constructive seeding (leu.2/§12.2): sizing seed cuts from target AREAS only regresses (thin slivers wreck aspect); you must ALSO pick each cut's rotation for child squareness. It is a convergence ACCELERATOR via a deeper local optimum around the constructed topology: wins where that topology is roughly right and budget is scarce (harbor -13%, maple -10% at 20k evals) but DELAYS small programmes where the seed must be restructured by undivide (programme-house regresses at fixed budget, yet reaches the floor given budget - speed, not asymptote). Default-on. Also: n_storeys must honour storey_minimum, not just level: keys (programme-house storey_minimum:2, all rooms level:0 - was seeded 1 storey short; cq1)."}
{"_type":"memory","key":"run-to-run-reproducibility-in-homemaker-layout-serial","value":"Run-to-run reproducibility in homemaker-layout: serial search (workers=1) is byte-for-byte deterministic; parallel (workers\u003e1) is now deterministic too AFTER fixing driver._run_batch to admit futures in submission order (was as_completed/completion order, bug xcy). Reproducibility holds only for a FIXED worker count — serial vs parallel differ because children-per-iteration is 1 vs n_workers (different batch granularity), which is expected, not a bug. The constructive seeder was NEVER nondeterministic: _assign_adjacency_aware has unique idx tiebreaks; comparing topologies with Python builtin hash() of the signature STRING is invalid (PYTHONHASHSEED salts str hashing per process) — use a stable hash (sha1) or genome.signature equality."}
{"_type":"memory","key":"programme-house-optimisation-result-2026-06-14-15","value":"Programme-house optimisation result (2026-06-14/15): best achievable is 1 fail (l1 wrong level, score ~0.005). 0 fails is geometrically impossible: l1 (min 27m²) must occupy ll (~23m²) at level 0, which eliminates the t3-adj-C provider; dividing ll into lll(l1)+llr(C) gives llr proportion ~6:1 (fails). Python memetic optimizer achieves 1 fail in 50k evals vs Perl optimiser's 2-3 fails. Winning topology: TWO C nodes at level 0 — ll(C) for t3-adj-C via geometric contact, rl(C) for staircase via tree-sibling adjacency to rrr(O). Best .dom: scratch/from-warmstart-fixed.dom and scratch/from-compound3-fixed.dom."}
{"_type":"memory","key":"collapse-global-94g-and-any-label-usage-optimisation","value":"collapse_global (94g) and any label/usage optimisation CANNOT fix geometry-intrinsic fails. The harbor-house 15-fail best layout contains long-thin cells that are useless whatever room usage is assigned — their width/proportion/crinkliness fails are shape-bound, not label slack. Two consequences: (1) do not over-claim collapse gains — only ~2-3 of that layout's fails are reclaimable relabel slack, the rest are geometry- or building-level bound; (2) the threshold objective must not be tuned to 'pass' a degenerate cell via a permissive room type — a metric-pass on a physically useless space is gaming, not a fix. Real remedies for these are geometry/topology search (cell shape) and circulation placement, filed separately, not the collapse."}
{"_type":"memory","key":"never-use-corpus-filenames-candidate-001-dom-candidate","value":"Never use corpus filenames (candidate-001.dom, candidate-002.dom, generated.dom, init.dom, etc.) as --output targets when running experiments. These are test fixtures. Always write experimental outputs to scratch/ or a timestamped path. Lesson from 2026-06-14: warm-start runs overwrote candidate-001/002.dom and broke graph tests."}