homemaker-py-2g7: file Phase 9 epic — ground truth, exact evaluation, solver-directed search (DESIGN.md §37)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NjyStTdLWFMtdScrpbgQur
This commit is contained in:
parent
7257fce7ca
commit
522f9b1d68
2 changed files with 73 additions and 19 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
{"id":"homemaker-py-2g7.4","title":"Exact shape-curve inner loop (Otten/Stockmeyer DP) replacing Nelder-Mead","description":"The classic slicing-floorplan result applied to our exact representation: each leaf's size/width/proportion constraints define a feasible-shape region; these compose bottom-up through the slicing tree as piecewise shape curves, yielding in ONE linear pass (no iteration): (a) whether ANY ratio assignment satisfies all per-leaf shape constraints, and (b) the ratios that realize a chosen point on the root curve. Today the same question costs an 80-eval NM run per child (~all of the 3M-eval budget) and answers it only approximately. Plan: (1) prototype on harbor-house-l0 with a rectangular plot approximation; (2) validate against innerloop.optimise — DP-feasible topologies must score \u003e= NM result when polished, DP-infeasible must never reach 0 shape fails under NM; (3) wire as a PRE-FILTER: prune shape-infeasible children before any native eval, and warm-start NM from DP ratios (or replace NM entirely where the plot is near-rectangular; keep NM as final polish for skew). CAVEATS to model honestly: crinkliness/access/adjacency are NOT in the DP (graph terms, not per-leaf shape) — the DP handles the size/width/proportion family only, which is fine for pruning; equal-offset skew-quad geometry means DP areas are approximate — measure the approximation error on real plots first (harbor plot is a near-rect quad). Expected payoff: 100-1000x cheaper feasibility, turning topology search into enumerate-and-prune and unlocking the racing/MAP-Elites/CP issues. Cf. §34: autodiff failed on wall-clock; this is a different attack — exactness via structure, not gradients.","acceptance_criteria":"on harbor-house-l0: DP verdict agrees with NM-polished shape-fail outcome on \u003e=95% of 200 random topologies; measured speedup \u003e=50x per feasibility decision; approximation error on the skew plot quantified","status":"open","priority":1,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-08-02T09:15:04Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:15:04Z","dependencies":[{"issue_id":"homemaker-py-2g7.4","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:15:04Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7.3","title":"Hard/soft fail tiering: 'solved' = zero hard fails","description":"Lex-by-total-count treats a crinkly wall the same as a missing room, so search polishes shape taxes instead of fixing structure — the 3M-run best still carries 'level 0/1 not connected' and wrong-level fails after 1.7M evals. Split fails into HARD (missing space, wrong/required level, level connectivity, circulation connectivity, stairs, covered-outside) and SOFT (crinkliness, proportion, size, width, edge-too-long) tiers. Outer comparator becomes (-hard, -soft, fitness); 'solved' is defined as zero hard fails. GUARDS: (1) the inner-loop 0.5^n cliff must keep protecting against trading into new fails (§4.5/§4.9 — rerun the 0/9 inner-loop-protection check); (2) rerun the §4.9 outer A/B: the scheme must not reintroduce the scalar pathology; (3) §11.4 warns comparator reshaping alone does not escape topology basins — the claim here is narrower: budget stops being spent on soft fails while hard fails remain, and reporting becomes meaningful. The tier map lives in fitness.py next to the fail emission sites so new fail strings must declare a tier. Can start before the calibration issue lands but final tier assignments should be reviewed against its findings.","acceptance_criteria":"tiered comparator behind a flag with A/B on harbor+maple (3 seeds, 20k evals): hard-fail count at budget strictly better or equal on mean, no §4.9 regression; report shows hard/soft split","status":"open","priority":1,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-08-02T09:14:14Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:14:14Z","dependencies":[{"issue_id":"homemaker-py-2g7.3","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:14:14Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7.2","title":"Calibrate the objective against human reference designs","description":"Score the traced human solutions (from the plan-\u003edom composer issue) and classify EVERY fail they raise as one of: (a) genuine spec violation (fix the trace or accept), (b) representation artifact (fix scoring, cf. §13.3/§13.8 share leaks), or (c) miscalibrated threshold (fix the constant/curve). Prime suspect: crinkliness — 48% of the evolved residual (§13.11), flat ~0.8/leaf tax even on squarest layouts (§13.1); if a real human plan pays it broadly, the gaussian on 1/crink is mis-tuned, not the designs. Outcome: either the human reference scores at/near 0 hard fails (objective validated, search is the gap) or a concrete list of scoring fixes. This finally makes 'the examples are solvable' a measured statement. Also record the human design's score as the per-programme target line on all future runs.","acceptance_criteria":"every fail on each human reference classified with evidence; miscalibrations filed/fixed; per-programme target scores recorded in DESIGN.md","status":"open","priority":1,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-08-02T09:14:11Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:14:11Z","dependencies":[{"issue_id":"homemaker-py-2g7.2","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:14:11Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-2g7.2","depends_on_id":"homemaker-py-2g7.1","type":"blocks","created_at":"2026-08-02T10:14:11Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7.1","title":"Human reference corpus: plan-\u003edom composer + first traced human solutions","description":"There are NO human-generated plans in the corpus — every non-empty .dom is evolution output, so the system has no ground truth for what a good design scores. Build the missing pipeline: (1) a plan-\u003edom composer — input a traced rectangular partition (rooms as rects/quads with type codes, per storey), validate it, extract the binary slicing tree by recursive guillotine-cut detection, and emit a .dom (levels, heights, perimeter, divisions). Non-slicible partitions are REPORTED with the offending region rather than rejected silently — whether human plans even lie in the slicing class is itself a first-order representability finding. (2) Trace at least one human-drawn solution for harbor-house (the plateau benchmark) and one for programme-house. Practical input path: trace in Inkscape over the scan and parse SVG rects (examples/harbor-house/drawings/ already holds SVG assets), or a simple YAML room list; avoid automatic raster vectorization for now. Uses: (a) calibration ground truth for the objective, (b) search seeds, (c) representability test of the slicing-tree phenotype, (d) later, few-shot examples for the LLM repair operator.","acceptance_criteria":"composer round-trips a synthetic slicible partition to a scoring .dom; at least one human harbor-house solution traced, composed, and scored with homemaker-fitness; non-slicible input produces a diagnostic naming the unsliceable region","status":"open","priority":1,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-08-02T09:14:10Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:14:10Z","dependencies":[{"issue_id":"homemaker-py-2g7.1","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:14:09Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":1,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7","title":"Phase 9: ground truth, exact evaluation, and solver-directed search","description":"Strategic pivot from the Phase 6-8 evidence (DESIGN.md §11-§13, §36 review follow-up). The ledger shows: every fail-count win came from construction/objective-honesty levers; every search-machinery lever (grade, niching, restarts, tournament-k, islands, annealing, beam) was null/negative; 3M-eval runs (evolve-3M-nols-3.log: 1.7M evals, 2.4 days) plateau inside a 15-fail tier with hard structural fails (level connectivity, wrong-level) surviving millions of evals despite dedicated repair operators. Diagnosis: (a) NO GROUND TRUTH — every .dom in the repo is evolution output; nobody knows what a known-good human design scores under this fitness, so 'solvable' is unfalsifiable and the fail taxonomy (crinkliness = 48% of residual, §13.11) may be miscalibrated; (b) evaluation is ~1000x more expensive than necessary (80-eval NM inner loop where an exact slicing-floorplan shape-curve DP answers feasibility+optimal-ratios in one pass); (c) evolution is being used as a constraint solver for discrete subproblems (type assignment, adjacency realization) that CP methods solve directly. Phase 9 attacks all three, in dependency order: human reference corpus -\u003e objective calibration -\u003e hard/soft fail tiering; shape-curve inner loop -\u003e parallel racing + MAP-Elites; CP-SAT assignment; LLM-directed repair. Prerequisite hygiene: the open scoring-path bugs (cvw, r5a, 7ua, sd3 + §36 trio) should land first so A/Bs measure a sound objective.","status":"open","priority":1,"issue_type":"epic","owner":"bruno@postle.net","created_at":"2026-08-02T09:13:10Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:13:10Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-ld2","title":"Interior-O courtyard seeding option","description":"_assign_adjacency_aware (operators.py:528) currently places the single O leaf on the MOST PERIPHERAL leaf, where adjacent rooms already have facade. For dense floors (harbor-house ~19 rooms/floor) this wastes the daylight source. Add an option to seed O INTERIOR (as a light well) and to scale O-leaf count with room count, so landlocked rooms get an adjacent uncovered-outside neighbour by construction -\u003e fewer crinkliness fails in the seed. A/B against current peripheral placement.","notes":"Implemented: interior_outside flag + outside_divisor (default 3) threaded through operators.constructive_topology / lift_base_to_storeys, _assign_adjacency_aware (interior light-well placement: most-landlocked leaves first, greedy spread), driver.search/search_staged, run_staged_search.py (INTERIORO/ODIV env). Test test_interior_outside_seeds_landlocked_wells_and_scales_count. A/B script experiments/run_interioro_ab.sh. Seed diagnostic confirmed mechanism (all crinkliness fails landlocked under-exposure) and tuned odiv 6-\u003e3. Full 20k A/B (maple+harbor seeds 0/1/2, control=peripheral must reproduce §13.5 maple 82.3/harbor 40.0) running; DESIGN.md §13.6 verdict pending results.","status":"closed","priority":1,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-23T20:40:19Z","created_by":"Bruno Postle","updated_at":"2026-06-28T06:19:38Z","started_at":"2026-06-27T20:37:42Z","closed_at":"2026-06-28T06:19:38Z","close_reason":"interior-O light-well seeding implemented + A/B done (§13.6): positive on dense floor (harbor -16.4%, all seeds), marginal/neutral on maple (-2.8%). Default-ON flip tracked as follow-up.","dependencies":[{"issue_id":"homemaker-py-ld2","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T21:49:30Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-ld2","title":"Interior-O courtyard seeding option","description":"_assign_adjacency_aware (operators.py:528) currently places the single O leaf on the MOST PERIPHERAL leaf, where adjacent rooms already have facade. For dense floors (harbor-house ~19 rooms/floor) this wastes the daylight source. Add an option to seed O INTERIOR (as a light well) and to scale O-leaf count with room count, so landlocked rooms get an adjacent uncovered-outside neighbour by construction -\u003e fewer crinkliness fails in the seed. A/B against current peripheral placement.","notes":"Implemented: interior_outside flag + outside_divisor (default 3) threaded through operators.constructive_topology / lift_base_to_storeys, _assign_adjacency_aware (interior light-well placement: most-landlocked leaves first, greedy spread), driver.search/search_staged, run_staged_search.py (INTERIORO/ODIV env). Test test_interior_outside_seeds_landlocked_wells_and_scales_count. A/B script experiments/run_interioro_ab.sh. Seed diagnostic confirmed mechanism (all crinkliness fails landlocked under-exposure) and tuned odiv 6-\u003e3. Full 20k A/B (maple+harbor seeds 0/1/2, control=peripheral must reproduce §13.5 maple 82.3/harbor 40.0) running; DESIGN.md §13.6 verdict pending results.","status":"closed","priority":1,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-23T20:40:19Z","created_by":"Bruno Postle","updated_at":"2026-06-28T06:19:38Z","started_at":"2026-06-27T20:37:42Z","closed_at":"2026-06-28T06:19:38Z","close_reason":"interior-O light-well seeding implemented + A/B done (§13.6): positive on dense floor (harbor -16.4%, all seeds), marginal/neutral on maple (-2.8%). Default-ON flip tracked as follow-up.","dependencies":[{"issue_id":"homemaker-py-ld2","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T21:49:30Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-erc.4","title":"Experiment: depth-balanced / giant-splitting construction (re-scoped by Diag B)","description":"Attacks the #2 factor (size/undersize 242) via the §12.3 paradox: rooms are undersize while 56% of the plot is empty. The shape floor is computed at TARGET dims, so construction never spends the slack. Scale leaves up to consume available plot area (proportionally, preserving target aspect) so rooms reach/exceed target — bigger leaves are also easier to keep compact, so this may help crinkliness/width too.\n\nBuilds on leu.2 (proportion-aware splits sized FROM target dims) by adding a fill step that scales the whole layout (or per-region) to the plot envelope instead of leaving slack as empty plot. Implementation in operators construction / _size_divisions_from_targets.\n\nNOTE: exact fix-site (construction vs inner loop) is decided by Diagnostic B — if B shows leaves park at target with unused plot, this construction lever is correct; if B shows the inner loop simply lacks an expansion gradient, prefer the inner-loop slack-expansion sibling instead. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.4.","notes":"RE-SCOPED by Diagnostic B (§13.2). Original premise (rooms parked at target, scale leaves up into 56%-empty plot) is FALSIFIED: sized rooms already hold 1.4-1.5x aggregate target area; the empty-looking plot is ~46% circulation, not claimable void. Real defect: MALDISTRIBUTION by slicing position — same type/target leaf lands 0.05x..14.7x by binary-tree depth; inner loop cannot fix (frozen topology). NEW SCOPE: construction that balances tree DEPTH so equal-target rooms land at comparable depth and/or splits/caps giant leaves so area tracks target. NOT a uniform scale-to-envelope (that would just inflate the giants further). A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.4. Synergy with erc.3 (leaf-sharing for the starved tail).","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:19Z","created_by":"Bruno Postle","updated_at":"2026-06-26T06:06:51Z","started_at":"2026-06-24T21:18:57Z","closed_at":"2026-06-26T06:06:51Z","close_reason":"Closed","dependencies":[{"issue_id":"homemaker-py-erc.4","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:19Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.4","depends_on_id":"homemaker-py-erc.2","type":"blocks","created_at":"2026-06-23T00:16:45Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-erc.4","title":"Experiment: depth-balanced / giant-splitting construction (re-scoped by Diag B)","description":"Attacks the #2 factor (size/undersize 242) via the §12.3 paradox: rooms are undersize while 56% of the plot is empty. The shape floor is computed at TARGET dims, so construction never spends the slack. Scale leaves up to consume available plot area (proportionally, preserving target aspect) so rooms reach/exceed target — bigger leaves are also easier to keep compact, so this may help crinkliness/width too.\n\nBuilds on leu.2 (proportion-aware splits sized FROM target dims) by adding a fill step that scales the whole layout (or per-region) to the plot envelope instead of leaving slack as empty plot. Implementation in operators construction / _size_divisions_from_targets.\n\nNOTE: exact fix-site (construction vs inner loop) is decided by Diagnostic B — if B shows leaves park at target with unused plot, this construction lever is correct; if B shows the inner loop simply lacks an expansion gradient, prefer the inner-loop slack-expansion sibling instead. A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.4.","notes":"RE-SCOPED by Diagnostic B (§13.2). Original premise (rooms parked at target, scale leaves up into 56%-empty plot) is FALSIFIED: sized rooms already hold 1.4-1.5x aggregate target area; the empty-looking plot is ~46% circulation, not claimable void. Real defect: MALDISTRIBUTION by slicing position — same type/target leaf lands 0.05x..14.7x by binary-tree depth; inner loop cannot fix (frozen topology). NEW SCOPE: construction that balances tree DEPTH so equal-target rooms land at comparable depth and/or splits/caps giant leaves so area tracks target. NOT a uniform scale-to-envelope (that would just inflate the giants further). A/B vs §12.2 baseline, seeds 0/1/2, 20000 evals, staged, default-OFF. Record DESIGN.md §13.4. Synergy with erc.3 (leaf-sharing for the starved tail).","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:19Z","created_by":"Bruno Postle","updated_at":"2026-06-26T06:06:51Z","started_at":"2026-06-24T21:18:57Z","closed_at":"2026-06-26T06:06:51Z","close_reason":"Closed","dependencies":[{"issue_id":"homemaker-py-erc.4","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:19Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.4","depends_on_id":"homemaker-py-erc.2","type":"blocks","created_at":"2026-06-23T00:16:45Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-erc.3","title":"Experiment: leaf-sharing / multi-room leaves in construction","description":"Strongest untried construction lever. §12.3 named 'merge or share leaves across same-class rooms' but c3g never tested it — c3g only coarsened the circulation spine (circ_divisor), trading shape gains for equal access/adjacency damage (null). Leaf-sharing is DIFFERENT: it reduces leaf count by collapsing same-class rooms (e.g. several O/storage, or same-type repeated rooms) into a shared leaf, attacking crinkliness(346)+size(242) directly WITHOUT coarsening circulation — so it should dodge the access penalty that sank c3g.\n\nImplementation sketch: in operators.constructive_topology (+ lift path), allow rooms of the same class/type (and compatible adjacency) to be instantiated as one larger leaf rather than one-leaf-per-room, lowering leaves-per-room from ~1.4 toward 1.0 or below. Honour storey_minimum and required-room presence (a shared leaf must still satisfy each merged room's presence/area in the fitness check, or the merge must be limited to rooms the fitness treats as fungible).\n\nTests the deepest open question: whether 52 rooms simply cannot be well-shaped as 52 leaves at this density. A/B vs §12.2 baseline (maple 136.0, harbor 74.0), seeds 0/1/2, 20000 evals, staged; default-OFF toggle so controls reproduce. Record DESIGN.md §13.3.","notes":"A/B DONE (§13.3): staged 20k, seeds 0/1/2, factor 3. maple 137.0→86.3 (−37%), harbor 74.0→50.3 (−32%). Baseline arm reproduces §12.2 exactly (maple 137 vs 136, harbor 74.0 vs 74.0). Total separation: every share run beats every baseline run same-programme. ~35% faster (fewer leaves). First Phase-8 floor-mover; 5th construction/seed win. Closing.","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:15Z","created_by":"Bruno Postle","updated_at":"2026-06-24T20:51:20Z","started_at":"2026-06-23T21:51:08Z","closed_at":"2026-06-24T20:51:20Z","close_reason":"Closed","dependencies":[{"issue_id":"homemaker-py-erc.3","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:15Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.3","depends_on_id":"homemaker-py-erc.1","type":"blocks","created_at":"2026-06-23T00:16:42Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-erc.3","title":"Experiment: leaf-sharing / multi-room leaves in construction","description":"Strongest untried construction lever. §12.3 named 'merge or share leaves across same-class rooms' but c3g never tested it — c3g only coarsened the circulation spine (circ_divisor), trading shape gains for equal access/adjacency damage (null). Leaf-sharing is DIFFERENT: it reduces leaf count by collapsing same-class rooms (e.g. several O/storage, or same-type repeated rooms) into a shared leaf, attacking crinkliness(346)+size(242) directly WITHOUT coarsening circulation — so it should dodge the access penalty that sank c3g.\n\nImplementation sketch: in operators.constructive_topology (+ lift path), allow rooms of the same class/type (and compatible adjacency) to be instantiated as one larger leaf rather than one-leaf-per-room, lowering leaves-per-room from ~1.4 toward 1.0 or below. Honour storey_minimum and required-room presence (a shared leaf must still satisfy each merged room's presence/area in the fitness check, or the merge must be limited to rooms the fitness treats as fungible).\n\nTests the deepest open question: whether 52 rooms simply cannot be well-shaped as 52 leaves at this density. A/B vs §12.2 baseline (maple 136.0, harbor 74.0), seeds 0/1/2, 20000 evals, staged; default-OFF toggle so controls reproduce. Record DESIGN.md §13.3.","notes":"A/B DONE (§13.3): staged 20k, seeds 0/1/2, factor 3. maple 137.0→86.3 (−37%), harbor 74.0→50.3 (−32%). Baseline arm reproduces §12.2 exactly (maple 137 vs 136, harbor 74.0 vs 74.0). Total separation: every share run beats every baseline run same-programme. ~35% faster (fewer leaves). First Phase-8 floor-mover; 5th construction/seed win. Closing.","status":"closed","priority":1,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-06-22T23:16:15Z","created_by":"Bruno Postle","updated_at":"2026-06-24T20:51:20Z","started_at":"2026-06-23T21:51:08Z","closed_at":"2026-06-24T20:51:20Z","close_reason":"Closed","dependencies":[{"issue_id":"homemaker-py-erc.3","depends_on_id":"homemaker-py-erc","type":"parent-child","created_at":"2026-06-23T00:16:15Z","created_by":"Bruno Postle","metadata":"{}"},{"issue_id":"homemaker-py-erc.3","depends_on_id":"homemaker-py-erc.1","type":"blocks","created_at":"2026-06-23T00:16:42Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||||
|
|
@ -22,6 +27,9 @@
|
||||||
{"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.24–x1.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.24–x1.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-2g7.7","title":"LLM repair operator at stagnation (dom+fails -\u003e targeted compound edits)","description":"Generalize the §4.10 lesson: deceptive valleys are crossed by COMPOUND edits (move room + re-home displaced room + fix ratios atomically), which we currently hand-code one per valley (mutate_level_compound_fix). Our fail messages are semantically rich and localized ('me1 on wrong level', 'level 1 not connected', '0/rlrlr proportion') and the .dom is readable — ideal LLM input. Loop: on stagnation (no fail-tier improvement for N evals), serialize best individual + .fails + programme summary -\u003e LLM proposes 3-5 multi-step repairs as structured edit scripts (a small DSL over existing operator primitives: swap/divide/retype/rotate with explicit paths — NOT freeform dom text, so proposals are always well-formed) -\u003e apply, inner-loop, lex-accept as usual. Native fitness disposes; a bad proposal costs one child budget. Cost discipline: one LLM call ~ thousands of native evals, so plateau-only, cache by (signature, fails) key. Benchmark: the 3M-run best sat on 'level 0 not connected' + 'me1 on wrong level' for \u003e1M evals — moves a plan-reader fixes in one edit. Use claude via API (see claude-api skill); temperature\u003e0 for diverse proposals. Later extension (separate issue): AlphaEvolve-style operator-code synthesis using our existing A/B harness as the evaluator.","acceptance_criteria":"on the evolved-3M-nols-3 15-fail plateau seed: repair loop reduces hard-fail count where 1M+ blind evals did not, within \u003c=20 LLM calls; edit-DSL rejects malformed proposals; A/B at equal native-eval budget shows strictly better final fails on \u003e=2/3 seeds","status":"open","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-08-02T09:15:54Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:15:54Z","dependencies":[{"issue_id":"homemaker-py-2g7.7","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:15:53Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7.6","title":"Spike: graph-first construction — adjacency-realizing slicing trees / rectangular dualization","description":"Research spike, timeboxed. Literature: rectangular dualization (planar triangulated graph -\u003e rectangular floorplan) and characterizations of slicible adjacency graphs. Our programme already IS an adjacency graph (every room wants c, plus secondary pairs); instead of mutating trees hoping adjacency emerges, construct trees that realize the required adjacency by construction — the direction §11.6/§11.7 crawled toward greedily. Deliverable is a WRITTEN assessment (DESIGN.md section): can harbor's programme graph (16 rooms + spine, 2 storeys with stacking constraint) be dualized into slicing trees, how many, and is enumeration of realizing trees tractable? Prototype only if the answer is clearly yes. Watch for: multi-storey Below-inheritance constrains both floors' trees jointly; circulation spine is a connected dominating set requirement, not a simple adjacency.","acceptance_criteria":"DESIGN.md section with go/no-go verdict, the relevant algorithms named, and complexity estimate for harbor-scale programmes","status":"open","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-08-02T09:15:07Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:15:07Z","dependencies":[{"issue_id":"homemaker-py-2g7.6","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:15:07Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
{"id":"homemaker-py-2g7.5","title":"CP-SAT type assignment for a fixed tree (replace swap/retype random walk)","description":"For a FIXED topology, assigning room codes to leaves subject to counts, required levels, adjacency-to-circulation-spine, secondary adjacencies (k1-da1, da1-o...), and share grouping is a small discrete problem (~30-70 leaves, ~16-26 codes) — well within OR-Tools CP-SAT range, solvable optimally in milliseconds. Today swap/retype/level_retype random-walk this space; §11.6/§11.7's greedy constructive assignment was the single biggest fail-count win of Phase 6, and CP-SAT is its exact big brother. Plan: model leaf-graph adjacency (geometry.leaf_graph) as fixed at seed geometry; objective = weighted satisfied adjacencies + level compliance; use as (a) seeder replacing the greedy _assign_adjacency_aware, (b) periodic 'reassign' operator inside search (the assignment analogue of ruin_recreate §23), (c) post-collapse repair. Note the §11.2 lesson: assignment quality at SEED geometry can shift after the inner loop moves ratios — re-run assignment after geometry settles (alternating minimization).","acceptance_criteria":"A/B vs greedy seeder (harbor+maple, 3 seeds, 20k evals): adjacency+access seed fails strictly lower; end-to-end mean fails no worse; reassign operator fires and is accepted at least once per run","status":"open","priority":2,"issue_type":"feature","owner":"bruno@postle.net","created_at":"2026-08-02T09:15:06Z","created_by":"Bruno Postle","updated_at":"2026-08-02T09:15:06Z","dependencies":[{"issue_id":"homemaker-py-2g7.5","depends_on_id":"homemaker-py-2g7","type":"parent-child","created_at":"2026-08-02T10:15:05Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-cvw","title":"Parallel staged runs: substrate_readiness reads stale id()-keyed geometry cache in the parent process","description":"Found by the homemaker-py-zrx expert review. geometry._cache is keyed by (id(node), idx) and relies on every reader being preceded by clear_cache(). In driver.search_staged stage 1 with n_workers\u003e1 that contract breaks: the PARENT process never runs score_with_fails (children are scored in the pool workers), so its cache is never cleared, yet _rank_fitness -\u003e rank_bonus_fn -\u003e graph.substrate_readiness(ind.root) reads geometry.area()/coordinate() in the parent on every tournament/admit comparison. Evicted individuals are eventually gc'd (Node trees are parent\u003c-\u003echild reference cycles, freed by the cycle collector) while their cache entries linger; freshly unpickled worker results reuse those addresses, and substrate_readiness then serves another (dead) tree's coordinates.\n\nVerified with a probe simulating the parent's allocation pattern (unpickle jittered harbor-house trees, pop-16 eviction churn, periodic gc.collect): 24/300 readiness computations returned a corrupted value, worst absolute error 0.999 on the [0,1] readiness scale (i.e. completely wrong), and the parent cache grew without bound (38k entries after 300 children — it is never cleared for the whole run). Serial staged runs are safe (every in-process score_with_fails clears the cache between children, and live/dead id coexistence prevents collisions).\n\nImpact: silently biases stage-1 substrate selection in every parallel staged run (run_staged_search.py with WORKERS\u003e1 — the default experimental harness), and makes the bias address-dependent, i.e. NON-DETERMINISTIC across byte-identical re-runs. This is a concrete, static-read-visible candidate mechanism for part of homemaker-py-b8g's irreproducibility (it is not BLAS): it perturbs the stage-1 trajectory, not a single fixed-genome score. Reported fitness numbers are unaffected (the bonus only reorders the comparator).\n\nRecommended fix: geometry.clear_cache() at substrate_readiness entry (cheap: the readiness read is a handful of areas on the base level; serial-mode behaviour is unchanged because the cache there is already cold at that point). The durable fix for the whole bug class — also covering the (unobserved but real) gc-timing hazard in collapse_finish's cand deepcopy, probed 0/6 today only because cyclic trees outlive the deepcopy window — is to cache on the Node object itself (as Urb does, per geometry.py's own comment) or key by a per-tree epoch, so a recycled address can never alias. Also add a defensive geometry.clear_cache() at collapse_global entry (one line, zero practical cost: finish-time it is one-shot, in-search the cache was just cleared by _evaluate_full).","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-08-02T08:19:18Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:19:18Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-cvw","title":"Parallel staged runs: substrate_readiness reads stale id()-keyed geometry cache in the parent process","description":"Found by the homemaker-py-zrx expert review. geometry._cache is keyed by (id(node), idx) and relies on every reader being preceded by clear_cache(). In driver.search_staged stage 1 with n_workers\u003e1 that contract breaks: the PARENT process never runs score_with_fails (children are scored in the pool workers), so its cache is never cleared, yet _rank_fitness -\u003e rank_bonus_fn -\u003e graph.substrate_readiness(ind.root) reads geometry.area()/coordinate() in the parent on every tournament/admit comparison. Evicted individuals are eventually gc'd (Node trees are parent\u003c-\u003echild reference cycles, freed by the cycle collector) while their cache entries linger; freshly unpickled worker results reuse those addresses, and substrate_readiness then serves another (dead) tree's coordinates.\n\nVerified with a probe simulating the parent's allocation pattern (unpickle jittered harbor-house trees, pop-16 eviction churn, periodic gc.collect): 24/300 readiness computations returned a corrupted value, worst absolute error 0.999 on the [0,1] readiness scale (i.e. completely wrong), and the parent cache grew without bound (38k entries after 300 children — it is never cleared for the whole run). Serial staged runs are safe (every in-process score_with_fails clears the cache between children, and live/dead id coexistence prevents collisions).\n\nImpact: silently biases stage-1 substrate selection in every parallel staged run (run_staged_search.py with WORKERS\u003e1 — the default experimental harness), and makes the bias address-dependent, i.e. NON-DETERMINISTIC across byte-identical re-runs. This is a concrete, static-read-visible candidate mechanism for part of homemaker-py-b8g's irreproducibility (it is not BLAS): it perturbs the stage-1 trajectory, not a single fixed-genome score. Reported fitness numbers are unaffected (the bonus only reorders the comparator).\n\nRecommended fix: geometry.clear_cache() at substrate_readiness entry (cheap: the readiness read is a handful of areas on the base level; serial-mode behaviour is unchanged because the cache there is already cold at that point). The durable fix for the whole bug class — also covering the (unobserved but real) gc-timing hazard in collapse_finish's cand deepcopy, probed 0/6 today only because cyclic trees outlive the deepcopy window — is to cache on the Node object itself (as Urb does, per geometry.py's own comment) or key by a per-tree epoch, so a recycled address can never alias. Also add a defensive geometry.clear_cache() at collapse_global entry (one line, zero practical cost: finish-time it is one-shot, in-search the cache was just cleared by _evaluate_full).","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-08-02T08:19:18Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:19:18Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-r5a","title":"Stale leaf-share stamp resurrects when collapse_global commits a leaf back to its stamped code","description":"Found by the homemaker-py-zrx expert review. The homemaker-py-iio fix stops _collapse_value/_usage_quality PROBES from seeing a stale share (share\u003e1, share_type != type), but the COMMIT path still resurrects it: when collapse_global's assignment (or a 2-opt swap in _two_opt_adjacency_polish) relabels a leaf back to its stale share_type, leaf.type == share_type again, graph.leaf_share goes live, and the leaf immediately counts as k rooms with a k*target size centre — a credit the Hungarian matrix valued at 1x (the iio guard cleared the stamp for exactly that probe). The resurrected stamp then SERIALISES (dom._emit's guard passes once type == share_type), so it persists in the output.\n\nConsequences: (1) in-process eval vs dump/reload eval of the SAME tree diverge again — the exact 91f/iio divergence class, reopened through the commit door. Repro (verified today): 12x8 two-leaf tree, left leaf typed b1 carrying stale share=3/share_type=n, programme n(count 3, size 24+-5, w 3+-0.8, p 2+-0.6) + b1(count 1, size 24+-5, w 12+-0.5, p 2+-0.6), leaf_sharing+collapse_insearch on: live eval = 12 fails / score 7.43e-08; dump+reload twin = 19 fails / 7.29e-11 (twin gains '0/l size', 'missing required space n#1' + critical + 3 would-need lines; live instead has 'too many spaces: n (found 4, expected 3)'). (2) The Jacobi valuation (1x, post-iio) and the committed reality (kx) disagree, so assignments are made under one objective and scored under another; the 2-opt reward() sees the kx credit during trial swaps while the Jacobi matrix never did — the two phases of the same optimiser price the same relabel differently. (3) An ordinary retype mutation that happens to restore a leaf's old code resurrects the stamp the same way (no collapse needed), with the same live-vs-reloaded divergence.\n\nRecommended fix: canonicalise stale stamps instead of guarding readers one by one — at _evaluate_full entry (or minimally at collapse_global entry over the supply set), drop share/share_type whenever share_type is set and != type, exactly mirroring dom._emit's serialisation guard, so the in-memory tree can never disagree with its canonical dumped form. Add a dump/reload-agreement regression test in the style of test_collapse_global_dump_reload_agree_with_stale_share but driving the COMMIT (use the repro above: assignment must relabel the stamped leaf back to its stamped code). Note this slightly changes search dynamics (accidental resurrection credit disappears), so re-run a quick harbor-house sanity A/B when landing. Feeds homemaker-py-d86 (historical re-verification should use the post-fix semantics).","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-08-02T08:18:36Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:18:36Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-r5a","title":"Stale leaf-share stamp resurrects when collapse_global commits a leaf back to its stamped code","description":"Found by the homemaker-py-zrx expert review. The homemaker-py-iio fix stops _collapse_value/_usage_quality PROBES from seeing a stale share (share\u003e1, share_type != type), but the COMMIT path still resurrects it: when collapse_global's assignment (or a 2-opt swap in _two_opt_adjacency_polish) relabels a leaf back to its stale share_type, leaf.type == share_type again, graph.leaf_share goes live, and the leaf immediately counts as k rooms with a k*target size centre — a credit the Hungarian matrix valued at 1x (the iio guard cleared the stamp for exactly that probe). The resurrected stamp then SERIALISES (dom._emit's guard passes once type == share_type), so it persists in the output.\n\nConsequences: (1) in-process eval vs dump/reload eval of the SAME tree diverge again — the exact 91f/iio divergence class, reopened through the commit door. Repro (verified today): 12x8 two-leaf tree, left leaf typed b1 carrying stale share=3/share_type=n, programme n(count 3, size 24+-5, w 3+-0.8, p 2+-0.6) + b1(count 1, size 24+-5, w 12+-0.5, p 2+-0.6), leaf_sharing+collapse_insearch on: live eval = 12 fails / score 7.43e-08; dump+reload twin = 19 fails / 7.29e-11 (twin gains '0/l size', 'missing required space n#1' + critical + 3 would-need lines; live instead has 'too many spaces: n (found 4, expected 3)'). (2) The Jacobi valuation (1x, post-iio) and the committed reality (kx) disagree, so assignments are made under one objective and scored under another; the 2-opt reward() sees the kx credit during trial swaps while the Jacobi matrix never did — the two phases of the same optimiser price the same relabel differently. (3) An ordinary retype mutation that happens to restore a leaf's old code resurrects the stamp the same way (no collapse needed), with the same live-vs-reloaded divergence.\n\nRecommended fix: canonicalise stale stamps instead of guarding readers one by one — at _evaluate_full entry (or minimally at collapse_global entry over the supply set), drop share/share_type whenever share_type is set and != type, exactly mirroring dom._emit's serialisation guard, so the in-memory tree can never disagree with its canonical dumped form. Add a dump/reload-agreement regression test in the style of test_collapse_global_dump_reload_agree_with_stale_share but driving the COMMIT (use the repro above: assignment must relabel the stamped leaf back to its stamped code). Note this slightly changes search dynamics (accidental resurrection credit disappears), so re-run a quick harbor-house sanity A/B when landing. Feeds homemaker-py-d86 (historical re-verification should use the post-fix semantics).","status":"open","priority":2,"issue_type":"bug","owner":"bruno@postle.net","created_at":"2026-08-02T08:18:36Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:18:36Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
{"id":"homemaker-py-zrx","title":"Targeted expert review of core numeric/scoring path (fitness/solver/collapse) for silent correctness bugs","description":"Run a deep, expensive-model code review scoped to the core numeric/scoring\nlogic: fitness.py, solver.py, collapse_cmd.py, and the collapse_insearch\npath in innerloop.py/driver.py. Motivated by homemaker-py-iio: a stale\nleaf-share leak in collapse_global's probe valuation silently corrupted\nscores for an unknown period before being caught by manual diagnostic\nreview (see DESIGN.md §35 for the retroactive-impact writeup). That bug\nclass - subtle numeric/state bugs that don't crash, just quietly bias\nscores - is exactly what a careful full-context review with a stronger\nmodel is suited to catching, and exactly what a quick pass would miss.\n\nScope: read fitness.py, solver.py, collapse_cmd.py, and the\ncollapse_insearch code path end-to-end looking for:\n- other stale-state/leak bugs analogous to iio (shared mutable state\n reused across probes/leaves without proper reset)\n- valuation/accounting mismatches between search-time scoring and\n finish-time collapse scoring (the class of bug behind 7ua)\n- non-determinism sources under n_workers\u003e1 (b8g) if visible from a\n static read\n- anything else that would bias .score output without raising an\n exception or failing a test\n\nOut of scope: CLI wrappers, dom.py parsing, genome/operators (topology\nsearch), occlusion/daylight (2g5) - not on the numeric-correctness path.\n\nRelated: d86 (re-verify qpk/1ph historical numbers against the iio fix)\nand 7ua (false MISMATCH bug) are follow-ups from the same root cause\nclass this review is meant to catch earlier next time. This review\nshould probably run before/alongside d86 so any new findings feed into\nthe historical re-verification rather than requiring a second pass.","notes":"REVIEW COMPLETE (2026-08-02). Files read end-to-end: fitness.py, solver.py, collapse_cmd.py, innerloop.py, driver.py (collapse_insearch path), plus geometry.py/graph.py/dom.py support and evolve.py plumbing. Three confirmed bugs and one hygiene task filed:\n\n- homemaker-py-r5a (P2, CONFIRMED by minimal repro): stale leaf-share stamps resurrect when collapse_global's COMMIT relabels a leaf back to its stamped code — the iio fix guarded the probes but not the commit; live vs dump/reload evals of the same tree diverge again (12 vs 19 fails, score 7.4e-08 vs 7.3e-11 in the repro), and the resurrected stamp serialises and persists. Recommend canonicalising stale stamps at _evaluate_full (or collapse_global) entry, mirroring dom._emit.\n- homemaker-py-cvw (P2, CONFIRMED by probe): n_workers\u003e1 search_staged stage 1 — parent process never clears geometry._cache but substrate_readiness reads geometry there every ranking comparison; dead individuals' id()-keyed entries alias freshly unpickled children (24/300 readiness values corrupted, worst error ~1.0). Address-dependent selection bias; candidate mechanism for part of b8g. Serial runs safe.\n- homemaker-py-sd3 (P3, CONFIRMED on 5 evolved files): driver.collapse_best builds its evaluator with collapse_insearch=True baked in (no way to thread the run flag); the 94g keep-better guard is vacuous (base==coll 5/5, e.g. logs 12-\u003e12 where canonical shows 15-\u003e12) and a canonically fail-increasing collapse would be silently applied. Same gap in search_annealed's final rescore.\n- homemaker-py-pek (P3): fitness.py has two process_storey definitions; the first (~line 1146) is dead code silently shadowed by the second (~1452).\n\nReviewed clean (no defect found): solver.py (experiments-only, not on the scoring path; its residuals ignore share/co_type but nothing in search calls it); gaussian/truncated-e and clipped-gaussian ports; _gaussian_product combination; check_space_counts coverage arithmetic and missing-id suppression; collapse_global's pin/slot accounting, forbid handling, Jacobi synchronous update and the xcy submission-order determinism fix; merge_divided (merges only o/s leaves, so no share-stamp loss); NativeEvaluator deepcopy hygiene (per-eval clear_cache at _evaluate_full entry protects the whole in-eval path including collapse_insearch); collapse_finish's cand-deepcopy id-reuse hazard probed 0/6 (cyclic trees outlive the deepcopy window) — defensive clear recommended in cvw. Cross-links added to b8g and d86.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-08-02T07:46:56Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:20:42Z","started_at":"2026-08-02T07:58:03Z","closed_at":"2026-08-02T08:20:42Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
{"id":"homemaker-py-zrx","title":"Targeted expert review of core numeric/scoring path (fitness/solver/collapse) for silent correctness bugs","description":"Run a deep, expensive-model code review scoped to the core numeric/scoring\nlogic: fitness.py, solver.py, collapse_cmd.py, and the collapse_insearch\npath in innerloop.py/driver.py. Motivated by homemaker-py-iio: a stale\nleaf-share leak in collapse_global's probe valuation silently corrupted\nscores for an unknown period before being caught by manual diagnostic\nreview (see DESIGN.md §35 for the retroactive-impact writeup). That bug\nclass - subtle numeric/state bugs that don't crash, just quietly bias\nscores - is exactly what a careful full-context review with a stronger\nmodel is suited to catching, and exactly what a quick pass would miss.\n\nScope: read fitness.py, solver.py, collapse_cmd.py, and the\ncollapse_insearch code path end-to-end looking for:\n- other stale-state/leak bugs analogous to iio (shared mutable state\n reused across probes/leaves without proper reset)\n- valuation/accounting mismatches between search-time scoring and\n finish-time collapse scoring (the class of bug behind 7ua)\n- non-determinism sources under n_workers\u003e1 (b8g) if visible from a\n static read\n- anything else that would bias .score output without raising an\n exception or failing a test\n\nOut of scope: CLI wrappers, dom.py parsing, genome/operators (topology\nsearch), occlusion/daylight (2g5) - not on the numeric-correctness path.\n\nRelated: d86 (re-verify qpk/1ph historical numbers against the iio fix)\nand 7ua (false MISMATCH bug) are follow-ups from the same root cause\nclass this review is meant to catch earlier next time. This review\nshould probably run before/alongside d86 so any new findings feed into\nthe historical re-verification rather than requiring a second pass.","notes":"REVIEW COMPLETE (2026-08-02). Files read end-to-end: fitness.py, solver.py, collapse_cmd.py, innerloop.py, driver.py (collapse_insearch path), plus geometry.py/graph.py/dom.py support and evolve.py plumbing. Three confirmed bugs and one hygiene task filed:\n\n- homemaker-py-r5a (P2, CONFIRMED by minimal repro): stale leaf-share stamps resurrect when collapse_global's COMMIT relabels a leaf back to its stamped code — the iio fix guarded the probes but not the commit; live vs dump/reload evals of the same tree diverge again (12 vs 19 fails, score 7.4e-08 vs 7.3e-11 in the repro), and the resurrected stamp serialises and persists. Recommend canonicalising stale stamps at _evaluate_full (or collapse_global) entry, mirroring dom._emit.\n- homemaker-py-cvw (P2, CONFIRMED by probe): n_workers\u003e1 search_staged stage 1 — parent process never clears geometry._cache but substrate_readiness reads geometry there every ranking comparison; dead individuals' id()-keyed entries alias freshly unpickled children (24/300 readiness values corrupted, worst error ~1.0). Address-dependent selection bias; candidate mechanism for part of b8g. Serial runs safe.\n- homemaker-py-sd3 (P3, CONFIRMED on 5 evolved files): driver.collapse_best builds its evaluator with collapse_insearch=True baked in (no way to thread the run flag); the 94g keep-better guard is vacuous (base==coll 5/5, e.g. logs 12-\u003e12 where canonical shows 15-\u003e12) and a canonically fail-increasing collapse would be silently applied. Same gap in search_annealed's final rescore.\n- homemaker-py-pek (P3): fitness.py has two process_storey definitions; the first (~line 1146) is dead code silently shadowed by the second (~1452).\n\nReviewed clean (no defect found): solver.py (experiments-only, not on the scoring path; its residuals ignore share/co_type but nothing in search calls it); gaussian/truncated-e and clipped-gaussian ports; _gaussian_product combination; check_space_counts coverage arithmetic and missing-id suppression; collapse_global's pin/slot accounting, forbid handling, Jacobi synchronous update and the xcy submission-order determinism fix; merge_divided (merges only o/s leaves, so no share-stamp loss); NativeEvaluator deepcopy hygiene (per-eval clear_cache at _evaluate_full entry protects the whole in-eval path including collapse_insearch); collapse_finish's cand-deepcopy id-reuse hazard probed 0/6 (cyclic trees outlive the deepcopy window) — defensive clear recommended in cvw. Cross-links added to b8g and d86.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-08-02T07:46:56Z","created_by":"Bruno Postle","updated_at":"2026-08-02T08:20:42Z","started_at":"2026-08-02T07:58:03Z","closed_at":"2026-08-02T08:20:42Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||||
|
|
@ -110,27 +118,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":"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":"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":"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":"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":"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":"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-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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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-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":"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":"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-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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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."}
|
||||||
|
|
|
||||||
46
DESIGN.md
46
DESIGN.md
|
|
@ -3892,3 +3892,49 @@ trees are reference cycles, so the dead copy outlives the reuse window); a defen
|
||||||
`collapse_global` entry is folded into `cvw`. Verdict on the method: the §35 hypothesis held — all
|
`collapse_global` entry is folded into `cvw`. Verdict on the method: the §35 hypothesis held — all
|
||||||
three confirmed bugs are silent, non-crashing, and invisible to the test suite (337/337 green
|
three confirmed bugs are silent, non-crashing, and invisible to the test suite (337/337 green
|
||||||
throughout), and two of them sit exactly on the leaf-share/collapse seam `iio` came from.
|
throughout), and two of them sit exactly on the leaf-share/collapse seam `iio` came from.
|
||||||
|
|
||||||
|
## 37. Phase 9 plan: ground truth, exact evaluation, solver-directed search (`homemaker-py-2g7`)
|
||||||
|
|
||||||
|
**Epic:** `homemaker-py-2g7`. **Status:** scoped 2026-08-02, pre-implementation.
|
||||||
|
Strategic review of §11–§13 + the 3M-eval runs (`examples/harbor-house/evolve-3M*.log`:
|
||||||
|
1.7 M evals / 2.4 days inside one 15-fail tier, hard structural fails — level
|
||||||
|
connectivity, wrong-level — surviving > 1 M evals despite dedicated repair
|
||||||
|
operators). The scoreboard is lopsided: every fail-count win of Phases 6–8 was a
|
||||||
|
construction/objective-honesty lever; every search-machinery lever (§11.4 grade,
|
||||||
|
§11.5 niching/restarts, §11.8 tournament-k, §14 islands, §16 annealing, §29/§30
|
||||||
|
beam, §27 bubble, §34 autodiff) was null or negative. Three root causes, three
|
||||||
|
tracks:
|
||||||
|
|
||||||
|
1. **No ground truth.** Every non-empty `.dom` in the repo is evolution output —
|
||||||
|
there are *no human-generated plans in the corpus*, so nobody has ever
|
||||||
|
measured what a known-good design scores; "the examples are solvable" is
|
||||||
|
currently unfalsifiable, and the residual taxonomy (crinkliness = 48 %,
|
||||||
|
§13.11) may be miscalibrated rather than unmet.
|
||||||
|
→ `2g7.1` plan→dom composer + traced human solutions (guillotine-cut
|
||||||
|
extraction from rectangular partitions; non-slicible input is itself a
|
||||||
|
representability finding) → `2g7.2` objective calibration against them →
|
||||||
|
`2g7.3` hard/soft fail tiering ("solved" = 0 hard fails; guards: §4.5/§4.9
|
||||||
|
inner-loop cliff protection must survive).
|
||||||
|
2. **Evaluation is ~10²–10³× too expensive.** The 80-eval NM inner loop answers
|
||||||
|
a question the classic Otten/Stockmeyer slicing-floorplan shape-curve DP
|
||||||
|
answers exactly in one bottom-up pass (feasibility + optimal ratios for the
|
||||||
|
size/width/proportion family). → `2g7.4` (prototype on harbor-house-l0,
|
||||||
|
rectangular-plot approximation, DP as pre-filter + NM warm start), unlocking
|
||||||
|
`2g7.9` parallel best-of-N + racing (blocked by `cvw`/`b8g`; §14 showed
|
||||||
|
best-of-N ≥ islands; the box has 4 cores and 3M runs used 1–2 workers) and
|
||||||
|
`2g7.10` MAP-Elites (elite-per-niche archive — mechanically distinct from the
|
||||||
|
failed §11.5/§11.8 diversity-under-one-selection).
|
||||||
|
3. **Evolution used as a constraint solver.** Discrete subproblems have exact
|
||||||
|
methods: `2g7.5` CP-SAT type assignment for a fixed tree (the optimal big
|
||||||
|
brother of the §11.6/§11.7 greedy assignment — the biggest Phase-6 win);
|
||||||
|
`2g7.6` spike on graph-first construction (rectangular dualization /
|
||||||
|
adjacency-realizing slicing trees); `2g7.7` LLM repair operator at stagnation
|
||||||
|
(generalising the §4.10 compound-operator lesson: fails are semantic and
|
||||||
|
localized, so an LLM proposes the valley-crossing multi-edit; native fitness
|
||||||
|
disposes; plateau-only for cost) and later `2g7.8` AlphaEvolve-style operator
|
||||||
|
synthesis against the existing A/B harness.
|
||||||
|
|
||||||
|
Prerequisite hygiene: the open scoring-path bugs (`cvw`, `r5a`, `7ua`, `sd3`,
|
||||||
|
`pek`) land first so Phase-9 A/Bs measure a sound objective. Recommended
|
||||||
|
opening moves: `2g7.1`+`2g7.2` (days, and they redefine the target for
|
||||||
|
everything else) in parallel with `2g7.4` (the compute multiplier).
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue