Commit graph

75 commits

Author SHA1 Message Date
bf3ff43837 erc.3: leaf-sharing mechanism + floor probe (§13.3)
Same-code rooms collapse into fewer, larger SHARED leaves so the ~1.8/leaf
shape tax (§13.1) is paid once per group. Multiplicity k is recovered from
area (k=clamp(round(area/target),1,max_share)) — no genome change — and used
in two default-OFF sites: graph.check_space_counts counts coverage (Σk vs
req.count) so one leaf covers several rooms without a missing fail, and
fitness.quality_size centres on k×target (σ scaled by k). Construction:
operators._share_rooms groups instances; _size_divisions_from_targets sizes
shared leaves to k×target via leaf_mult.

Floor probe (experiments/diag_leaf_sharing.py, harbor+maple, seeds 0/1/2,
+innerloop): total fails −27% harbor / −16% maple at share3, shape factors
fall ~linearly with leaf count (confirms §13.1). Cap: 17–44 missing fails
leak because depth maldistribution (§13.2) keeps shared leaves below k×target
so round() undercounts; inner loop can't close it. Net still positive.

Default-OFF reproduces baseline exactly (214 tests pass). Driver plumbing +
staged 20k A/B remain; §13.3 records the next design fork.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 08:30:26 +01:00
6a34bd675c bd: sync issues.jsonl (erc.2 close, erc.4 re-scope, erc.6 deprioritise)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 22:48:51 +01:00
be6857414d erc.2: Diagnostic B — undersize-despite-slack localization (§13.2)
The "56% empty plot" is a misreading: sized rooms already hold 1.4-1.5x
their aggregate target area; ~46% of plot is circulation, not claimable
void. Size fails are depth-driven MALDISTRIBUTION — the same type/target
leaf lands 0.05x..14.7x by binary-tree position. The inner loop cannot
repair it (frozen topology, budget-80 size fails move only -1.6/-3.7).

=> Falsifies plot-fill-as-claim-void: re-scope erc.4 to depth-balanced /
giant-splitting construction; deprioritise erc.6 (inner-loop term, wrong
DOF). Reinforces erc.3 leaf-sharing for the starved tail.

Script: experiments/diag_slack_localization.py (self-contained evidence).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 22:47:34 +01:00
c838fd694b bd: sync issues.jsonl (erc.1 close, erc.5 deprioritise)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 22:07:11 +01:00
7bd4adf32a erc.1: Diagnostic A — per-leaf shape-fail vs density (§13.1)
Controlled synthetic sweep (maple-court, room set fixed, circ_divisor 2->9)
shows per-leaf shape-fail is FLAT vs slicing density (1.72-1.94, no trend)
while TOTAL shape fails track leaf count linearly (139->116). Crinkliness
dominates (~0.8/leaf) and is flat; cuts are already squarest yet still pay
~1.8 fails/leaf. Floor is INTRINSIC to per-leaf slicing, not cut quality.

Verdict: prioritise leaf-sharing (erc.3); deprioritise compactness-cuts
(erc.5 -> P4). Adds experiments/diag_leaf_shapefail.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 22:06:04 +01:00
d33e2434dc bd: Phase 8 epic — fold harbor-house plateau fixes under erc
Add interior-O courtyard seeding (ld2, construction lever, P1) and a
Tier-3 failure-directed topology-repair operator (71d + subtasks) as
children of the erc Phase-8 epic. Diagnosis from the 3M harbor-house
run: 27 fails dominated by 13 crinkliness + 7 size; ~16 are invariant
to split ratios (landlocked rooms, fitness.py:339), so the lever is
construction/topology, not the inner loop — consistent with erc's
thesis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:52:39 +01:00
00939da27c bd: export — include psk island-model issue + flush memories
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 00:19:35 +01:00
b167909167 bd: Phase 8 issue tree — geometry-floor reduction levers
Add epic homemaker-py-erc (lower the geometry/shape floor) with two
read-first diagnostics gating four floor-lowering experiments, plus the
island-model search bet (psk). Diagnostics decide leaf-sharing vs
compactness-cuts (A) and construction-fill vs inner-loop-fill (B).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 00:18:51 +01:00
b2ac22d2ec bd: add homemaker-py-6zy (diversity × tournament-pressure A/B experiment)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:54:24 +01:00
d87deec237 bd: sync issues.jsonl
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:28:26 +01:00
e95a3477a8 Fix parallel search nondeterminism; re-diagnose homemaker-py-xcy
The constructive seeder was never nondeterministic: _assign_adjacency_aware
ends every max/min with a unique leaf-idx tiebreak and uses set unions only
for membership, so iteration order never leaks. constructive_topology(seed=0)
is byte-identical across processes for every example programme. The cited
"sig 4480 vs 16064" was a measurement artifact — Python's builtin hash() of a
str is salted per process (PYTHONHASHSEED), so an identical signature hashes to
different ints run-to-run.

The real run-to-run noise was parallel-only: driver._run_batch admitted futures
via as_completed (completion order), and admit() is order-sensitive (accrues
n_evals per result; keeps the first individual of an equal-key tie as best). A
long parallel run diverged 167 vs 161 fails (maple seed 0). Fix: admit futures
in submission order (block on each result in turn; all still run concurrently),
reproducing the serial admission sequence. Two workers=4 runs are now
byte-identical. Serial (workers=1) was already byte-for-byte reproducible.

Per-seed numbers are reproducible only at a fixed worker count; serial != parallel
is expected (children/iteration 1 vs n_workers changes batch granularity).

- driver: iterate futs in submission order, not as_completed
- test: test_search_parallel_is_reproducible (fails on pre-fix, passes on fix)
- DESIGN.md §12.4: corrected the reproducibility note

Closes homemaker-py-xcy

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 23:25:50 +01:00
cfb0518531 §12.4: construction-granularity A/B — NULL; close c3g; note determinism bug
End-to-end A/B (maple div6/div8, harbor div6, seeds 0/1/2, 20000 evals) vs the
§12.3 div=3 baseline: every arm within ±1.7 of baseline (maple 136.0 -> 137.0 /
134.3; harbor 74.0 -> 75.3), inside the measured ±3 noise floor with large
per-seed spread. Coarsening the circulation spine lowers the raw shape floor but
raises access/adjacency by as much; end-to-end they wash out. Verdict: keep
circ_divisor=3; the maple/harbor residual is the geometry floor of the slicing
representation at this room density — neither search machinery (§12.3) nor
construction granularity (§12.4) moves it beyond noise.

En route: the div=3 control (129 vs §12.3's 126) exposed a reproducibility bug —
_assign_adjacency_aware iterates id()-ordered sets of Node objects, so the
constructive seed is nondeterministic across processes (~±3 fail noise). Filed
homemaker-py-xcy (P2); per-seed ledger numbers are not reproducible, only
multi-seed means.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 00:49:56 +01:00
613f773303 File determinism bug (nondeterministic constructive seeder) found during c3g
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:40:03 +01:00
e9684ea7ef c3g: circ-per-room granularity knob (circ_divisor) + A/B harness
Threads circ_divisor (default 3 = unchanged) through
operators.constructive_topology/lift_base_to_storeys and
driver.search/search_staged; env CIRCDIV in run_staged_search.py. Adds
experiments/run_c3g_ab.sh.

Motivation (DESIGN.md §12.3 diagnostic): the maple shape residual is
over-granular construction (73 small leaves -> crinkliness+size). Cheap raw-seed
probe: a coarser spine lowers the SHAPE floor (maple 135->110, harbor 83->66)
but raises access/adjacency, leaving the raw TOTAL floor flat-to-worse. Because
§12.3 showed shape is the HARD residual and access/adjacency are cheap to
repair, only an end-to-end A/B settles whether trading them pays — this is the
plumbing for that run. Tests green (default path byte-identical).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 21:10:18 +01:00
e700090c5c §12.3 residual diagnostic: over-granularity, not placement; file c3g
Per-leaf breakdown of maple-court constructive seeds (6 seeds) overturns the
earlier 'shape-aware placement' handoff guess: shape fails are UNIFORM
(~68/73 leaves fail) at only 0.44 plot utilisation, dominated by crinkliness
(perimeter/area) then size (undersize). So the residual is neither a room->leaf
placement mismatch (no well-shaped leaves to place into) nor density-bound — it
is over-granular construction (73 small leaves for 52 rooms). Corrected the
§12.3 verdict accordingly and filed homemaker-py-c3g (construction granularity /
leaf-shape lever) as an unproven, must-be-A/B'd hypothesis.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 20:56:49 +01:00
7e39bf5870 Phase 7 §12.3: 9gp A/B measured — NEGATIVE; close 9gp + epic leu
24-run sweep (maple-court + harbor, seeds 0/1/2, 20000 evals): M3 reassociate
and the shape-feasibility filter are both neutral-to-slightly-worse vs the
§12.2 baseline (maple 136.0 -> 139-140, harbor 74.0 -> 77-78). Baseline controls
reproduce §12.2 exactly, so the negative is real.

Verdict: the Phase-7 residual is the geometry/shape floor of the constructed
slicing layouts, not reachability/feasibility-bound — third independent negative
on search machinery (§11.4/§11.5/§12.3) vs four construction/seed wins
(§11.2/§11.6/§11.7/§12.2). A full canonical Polish rewrite is not justified: its
one testable promise (associativity reachability) was tested and did not pay.
Both operators kept default-OFF.

Closes 9gp.1, 9gp.2, 9gp; epic leu (Phase 7) auto-closed (3/3). Adds the
reproducible sweep harness experiments/run_9gp_ab.sh.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-21 07:21:51 +01:00
8fe5879b9d Sync beads jsonl after 9gp.1/9gp.2 create + notes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:55:47 +01:00
6ee5d4b4ae Phase 7 §12.3: re-scoped 9gp — shape-feasibility filter + M3 reassociate (9gp.1, 9gp.2)
Land the two evidence-supported parts of the re-scoped 9gp capstone as
operators on the existing decoded Node tree (no Polish-expression rewrite),
each default-OFF and measured against the §12.2 leu.2 baseline.

9gp.1 shape-feasibility pre-filter: operators.predicted_shape_fails lays a
topology out at its proportion-aware target geometry and counts shape fails
(size/width/proportion/crinkliness); driver._evaluate prunes clearly-infeasible
topologies before the inner loop (1 eval vs ~80), guarded so nothing that could
beat the incumbent is discarded. search/search_staged feasibility_filter,
feasibility_max_shape_fails (env FEAS/MAXSHAPE), default OFF.

9gp.2 M3 Wong-Liu reassociate: operators.mutate_reassociate adds associativity
(a|b)|c <-> a|(b|c) on same-orientation live cuts — the canonical-slicing move
missing from swap(M1)/rotate(M2), attacking the §11.4/§11.5 reachability
bottleneck. enable_reassociate (env REASSOC), default OFF (weight 0 -> baseline
byte-identical).

Unit tests (operators + driver) green, full suite 211 passed; maple-court smoke
run clean under native fitness. A/B sweep handed off per the plan; DESIGN.md
§12.3 documents the design and the pending measurement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:54:48 +01:00
0170cf2122 Sync beads jsonl after leu.2 + cq1 close
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:06:10 +01:00
995342d0a4 Phase 7 §12.2: proportion-aware constructive seeding + storey_minimum fix (leu.2, cq1)
Size each constructive-seed cut from leaf TARGET areas (division=[f,f] gives
left area-fraction f) and pick each cut's rotation for child squareness — both
derived from target dims, topology/type assignment untouched. Area-only
regressed (slivers); rotation choice is what makes it pay.

End-to-end (20000 evals, 3 seeds, staged): harbor 85.3->74.0 (-13%, best 69),
maple-court 151.7->136.0 (-10%, best 126). PROP=0 reproduces the §11.7/§12.1
baselines exactly. programme-house regresses at fixed budget (deeper local
optimum walls off the undivide restructuring path) but a budget sweep shows
it's convergence speed, not a worse asymptote (PROP=1 reaches 1 fail at 150k).
Default-on (seed_proportion_aware=True, env PROP=1).

cq1: n_storeys now honours storey_minimum, not just level: keys — programme-house
(storey_minimum:2, all rooms level:0) was seeded one storey short and fell
through to plain search. New programme.storey_minimum()/n_storeys_for();
driver.search passes min_storeys to the seeder; search_staged routes on the max.
No-op for harbor/maple; programme-house single-stage 8.0->5.0.

New maple-court best (126) saved as generated.dom. 204 tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 14:04:42 +01:00
7d7994e7a3 Phase 7 §12.1: larger-than-house benchmark maple-court + baseline (leu.1)
26 programme entries / 52 rooms / 3 storeys (~1015 m2 internal). Mirrors
harbor's adjacency-to-c load + secondary adjacencies; room codes avoid the
generic c/o/s leading-letter trap. Staged adjacency-aware baseline (20000
evals, URB_NO_OCCLUSION=1): 145/158/152 fails, mean 151.7; all native
re-score OK. Best (145) saved as generated.dom. Recorded in DESIGN.md §12.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 14:00:21 +01:00
73b9e2ae23 Sync beads jsonl after ld5 close
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:48:59 +01:00
d004e4c937 Phase 6 §11.7: adjacency-aware lift + secondary adjacencies (ld5)
_assign_adjacency_aware gains fixed_circ (seed the connected-dominating-set from
given circulation leaves) and secondary-adjacency-aware room placement: codes
with the most non-c adjacency requirements are placed first, each onto the open
slot satisfying the most of its requirements against already-typed neighbours
(clustering k1<->da1, da1<->o). lift_base_to_storeys(reqs, adjacency_aware=True)
grows the upper-floor circulation spine off the inherited vertical core and
assigns rooms around it; threaded through driver.search_staged
(seed_adjacency_aware) and run_staged_search.py (ADJ env).

End-to-end staged harbor, 20000 evals, mean total fails over 3 seeds:
ADJ=0 99.0 (reproduces the §11.4 staged lex baseline exactly), ADJ=1 85.3
(-13.7, -14%; best 78). New best harbor configuration overall: staged baseline
99.0 -> single-stage adjacency-aware (§11.6) 90.7 -> staged + adjacency-aware
lift 85.3. Staging and adjacency-aware seeding compose.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:47:40 +01:00
22ad9ed914 Sync beads jsonl after s44 dolt push
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:32:14 +01:00
c1586237ca Phase 6 §11.6: adjacency-aware constructive seeding (s44)
operators._assign_adjacency_aware spends ~one extra leaf per three rooms on a
greedy connected-dominating-set of circulation leaves (read from the geometric
leaf_graph, type-independent), so every room borders a connected circulation
spine and adjacency-to-c + access are satisfied by construction. Default-on via
constructive_topology(adjacency_aware=True), threaded through
driver.search(seed_adjacency_aware) and run_search_scaled.py (ADJ env).

End-to-end single-stage, 20000 evals, mean total fails over 3 seeds:
harbor 110.0 -> 90.7 (-17.5%; ADJ=0 reproduces the §11.2 105 baseline exactly),
programme-house 12.3 -> 9.3 (-24%). Adjacency-aware single-stage harbor (mean
90.7, best 85) beats the §11.3 staged best of 95 — the first Phase-6 fail-count
reduction from seeding. Follow-ups (lift_base_to_storeys, secondary adjacencies)
filed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:23:12 +01:00
0f5932794d Sync beads jsonl after c4c.5 dolt push
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:51:21 +01:00
059964ee05 Phase 6 §11.5: structural niching + restarts — negative result (c4c.5)
genome.signature: ratio-invariant structural topology hash (per-storey tree
shape + cut orientation + leaf types), the cheap stand-in for the 9gp canonical
encoding. driver gains niche_by_signature (one individual per topology, replaces
the fitness-scalar dedup) and restart_patience (soft restart: keep elites,
refill with fresh seeds); SearchResult gains n_distinct_signatures /
diversity_history / n_restarts.

Diversity criterion MET (final-pop distinct ~5/16 -> 16/16). Gate NOT met:
blank-slate programme-house mean fails 12.3(legacy)/12.7(niche)/13.0(restart)
over 3 seeds at 20000 evals; harbor staged 95/94/108. Niching is a tie within
seed noise, restarts strictly worse — falsifies the premise that the
fitness-scalar dedup causes premature convergence. Both flags default-off,
kept for reuse. Epic c4c complete.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 23:42:39 +01:00
6a5f9c4a8a Sync beads jsonl after c4c.4 close
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:36:36 +01:00
ed2869074b Phase 6 §11.4: graded high-fail objective — negative result (c4c.4)
Implement a graded proximity comparator key (-n_fails, grade, fitness) behind
a default-off use_grade flag: fitness._leaf_grade / score_with_grade sum
f/FAIL_THRESHOLD over failing per-leaf quality factors; scalar fitness and fail
count stay untouched so the inner-loop 0.5^n cliff (§5.4) is unaffected (0/9
regression check: PASS). Read once per child in driver._evaluate off the
already-optimised tree; threaded through search_staged (Stage 2 only).

Harbor staged A/B (20000 evals, seeds 0/1/2): lex 95/96/106 (mean 99.0) vs
lex+grade 99/98/102 (mean 99.7) — grade wins 1/3, no plateau escape. Premise
falsified: within a fixed fail-tier 0.5^n is constant so fitness still spans
~6 orders of magnitude; grade above fitness displaces that working signal.
Verdict: reject; lexicographic (-n_fails, fitness) stands. Flag kept default-off
for reproducibility / possible reuse as a §11.5 diversity signal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:33:29 +01:00
bbbbdedde8 Sync beads jsonl after c4c.3 close
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 06:06:41 +01:00
6ed9e0b4b1 Phase 6 §11.3: staged per-floor search (c4c.3)
Search the genome in causal dependency order. Stage 1 evolves a single-storey
base over the level-0 room set (programme auto-derived to a tempdir), ranked
with a substrate-readiness bonus (reserved core × divisible capacity) so the
base is selected as a good substrate, not just a good ground floor (anti-§4.2).
Stage 2 lifts the best base into a full multi-storey design — preserving the
inherited core, instantiating each upper storey's required set by construction —
and searches the deltas with the base mutable at low probability (base_p=0.15).

New: programme.{n_storeys_required,partition_rooms_by_storey,write_stage1_programme},
graph.substrate_readiness, operators.{lift_base_to_storeys,_pick_weighted_by_storey},
base_p threading, driver.search rank_bonus_fn/seed_factory/base_p hooks +
search_staged orchestrator, experiments/run_staged_search.py, tests/test_staging.py.

Result (harbor, 20000 evals, seed 0): staged 95 fails vs single-stage 105
(-10, -9.5%), gain in crinkliness 27->18 + edge 12->8. Anti-bungalow confirmed
(Stage-2 core moves all noop — core inherited, not carved). Programme-house
regression PASS (warmstart-2f4 still reaches whole-pop 1-fail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 06:05:53 +01:00
debb7dc26b Sync beads jsonl after c4c.2 close
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:53:49 +01:00
de60200bbc Phase 6 §11.2: programme-aware construction + missing-room repair (c4c.2)
Make the required programme room set a constructive invariant instead of
something the topology search must stumble onto by random divide+retype.

- operators.constructive_topology: bootstrap seeder that sizes each storey to
  its required rooms (partitioned by level; level-free rooms distributed),
  +1 core C and +1 O per storey, then assigns types. Stochastic for population
  diversity. Wired into driver bootstrap when the programme has required spaces.
- operators.mutate_place_missing: repair op that inserts a missing required
  space by dividing a host leaf into [room | remainder]. Lex-safe host ranking
  (generic O first, never displace a required room); honours required level.
  Weight 2.0 in the mutation mix; noops cheaply once the set is complete.

A/B on harbor-house (20k evals, seed 0, identical config):
  old random-bootstrap 133 fails (103 missing, 77%)
  new constructive     105 fails ( 12 missing, 11%)  -21% total, missing-stack
  collapsed; seed head-start 163->139.
§4.10 regression PASS: warmstart-2f4 still reaches a 1-fail population at 50k.

Verdict (DESIGN.md §11.2): construction is necessary and reframes the
bottleneck to quality-fail packing of a complete dense design (crinkliness/
size/access/edge) -> unblocks §11.3 staging, motivates §11.4 graded objective.
Follow-up filed (homemaker-py-s44): adjacency-aware seeding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:51:58 +01:00
43be2fe5ab Phase 6 §11.1: single-storey harbor experiment — construction is the bottleneck
Built examples/harbor-house-l0/ (10 explicit level:0 codes, 13 instances,
single-storey constraints) and ran the memetic search from a bare plot. Best
33 fails at 20000 evals; whole population stuck 33–35, deep in the 0.5^n
high-fail regime. Fail histogram is dominated by 'missing' (13/33 = 39%): the
counted space m×3 is never constructed, with adjacency/access/size fails
downstream of the unbuilt room set.

Verdict: per-floor CONSTRUCTION is the bottleneck, not multi-storey coupling —
c4c.2 (programme-aware construction + missing-room repair) is the prerequisite
and staging (c4c.3) alone won't rescue it. Closes homemaker-py-c4c.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:16:06 +01:00
6de610ccca Restructure backlog: Phase 6 topology-search-quality epic (homemaker-py-c4c)
Diagnosis-driven backlog redo: delivered speedups (native fitness, geometry
inner loop) polish within a failure tier but final design quality is gated by
topology-search quality on full/multi-storey programmes. New epic + children:
construction (c4c.2), staged per-floor search (c4c.3), graded high-fail
objective (c4c.4), topology diversity (c4c.5), plus a premise experiment
(c4c.1). Reframed 9gp (canonical encoding) as the capstone and deprioritised
2g5 (occlusion) as fitness-fidelity, orthogonal to design quality.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:16:44 +01:00
e68bfe53e5 Fix parity gap: oracle.py must run with URB_NO_OCCLUSION=1
Python fitness always pins quality_daylight to 1.0 (URB_NO_OCCLUSION semantics),
but oracle.py was invoking urb-fitness.pl without the flag, causing outside leaves
to receive real sun-model daylight scores and producing a ~9% gap.

Changes:
- oracle.py: add URB_NO_OCCLUSION=1 to score_batch env
- oracle.py: Score.fail_lines now parses structured YAML failures from the
  llm-agent-mcp branch and converts them to plain-text equivalents, so
  parity tests can compare oracle vs native failure sets regardless of format
- Regenerated all 36 corpus .score/.fails files with URB_NO_OCCLUSION=1
  (no .score files are tracked in git; the script generates them locally)
- All 183 tests pass; closes homemaker-py-gpx

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 18:40:56 +01:00
e623a76bd4 bd dolt push sync 2026-06-15 08:22:30 +01:00
85fc848e4e Document programme-house deceptive valley findings in DESIGN.md §4.10
Records: the level-fix deceptive valley, compound operator design,
warm_x0 initialization bug and fix, two-C topology breakthrough,
0-fails geometric impossibility proof, and final 1-fail results
beating the Perl optimiser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 08:00:57 +01:00
69eb721c7c Close homemaker-py-g0b 2026-06-14 17:18:23 +01:00
191f603440 Add core_divide, core_undivide, level_fix operators; wire reqs to mutate()
core_divide: divides a C leaf simultaneously on ALL storeys that share that
path, maintaining staircase consistency as an atomic invariant rather than
requiring multi-step recovery.

core_undivide: reverses core_divide consistently across all floors, merging
a C sub-core back into a single C leaf everywhere.

level_fix: atomically moves a level-constrained room to its required floor
by retyping the largest leaf there and vacating the wrong-floor leaf to C.
Requires `reqs` (SpaceReq dict); disabled (zero probability) without it.

mutate() gains `reqs=None` parameter; driver.search() passes its already-
loaded reqs so level_fix fires during the main memetic loop.

Together these let the optimiser escape the deceptive valley around the
2-fail warmstart: level_fix moves l1 to level 0 (reducing fails 2→1),
then core_divide can split the C core to accommodate the displaced t3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 16:10:20 +01:00
3c8f7aba07 Lexicographic outer-search comparison, preserve inner-loop cliff (homemaker-py-yg5)
Outer search now ranks individuals by (-n_fails, fitness) instead of raw
fitness scalar.  This prevents high-score 3-fail designs from displacing
2-fail designs in tournament selection and population replacement — the
root cause of the §4.8 pathology where flag count dominates geometry.

Inner loop is unchanged: it still optimises against the raw 0.5^n fitness
scalar, so the cliff that prevents trading into new failures remains intact
(0/9 regressions in experiments/penalty_reshape.py).

Also removes stale _CHILD_INNER_KW = {"sigmas": (0.05,)}: this was left
over from the CMA-ES era; the NM inner loop default (homemaker-py-d6d)
does not accept a sigmas parameter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 09:20:03 +01:00
0e5e607c4f Swap inner loop default from CMA-ES to Nelder-Mead (homemaker-py-d6d)
Bakeoff with native fitness shows NM wins at all DOF sizes: +9% at
child_budget=80 for programme-house (6-7 DOF), and decisively at
harbor-house scale (35-40 DOF) where CMA-ES exhausts its convergence
detector after ~3 generations (46 evals) and adds failures on 12/15
runs.  NM uses the full budget, is parameter-free, and has zero new
failures across all test cases.

- Add nm_search() to innerloop.py; change optimise() default to "nm"
- Add nm_search to parametrised test cases
- Add bakeoff_native.py and bakeoff_harbor.py experiments with results

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 08:51:22 +01:00
646ee30ab6 Rename package: homemaker → homemaker-layout
- src/homemaker/ → src/homemaker_layout/; all imports updated
- pyproject.toml: name = homemaker-layout, entry point updated
- .beads/config.yaml: dolt sync.remote updated to homemaker-layout.git
- Delete temporary debug/perl scripts from project root
- README.md, DESIGN.md: package path references updated
- GitHub repo renamed; git remote updated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 08:18:06 +01:00
c6dd9434d3 Config inheritance: load parent patterns.config as base layer (homemaker-py-n5k)
programme.load_programme_dir(directory) mirrors urb-evolve.pl: loads
../patterns.config first, then merges local patterns.config on top (shallow,
local top-level keys win). driver.search now uses load_programme_dir instead
of hardcoding the local path, so the type pool respects parent config.

fitness.load_config already had this behaviour; programme now matches.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 07:50:39 +01:00
a0f56b7cdf Add homemaker-evolve CLI tool (homemaker-py-2wc)
python -m homemaker.evolve seed.dom [--budget N] [--pop N] [--workers N] ...
Installed as homemaker-evolve entry point via pyproject.toml.

Takes a single .dom file; infers programme dir from its parent. All parameters
available as --flags or HOMEMAKER_* env vars. Output defaults to
<seed_stem>_evolved.dom; use --output - for stdout. SIGINT/SIGTERM returns
best-so-far via new driver.SearchResult.interrupted flag.

Also adds dom.dumps() for string serialisation and refactors dom.dump() to use it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 07:48:13 +01:00
7ee51caf62 Parallelise outer search population evaluation (homemaker-py-5l6)
Add n_workers parameter to driver.search(). When n_workers > 1, a
ProcessPoolExecutor evaluates the bootstrap batch and main-loop children
in parallel, giving near-linear speedup with core count. The geometry
module-level cache is cleared in each worker after fork to prevent stale
id-keyed entries. Serial behaviour (n_workers=1, default) is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 06:55:58 +01:00
304d514573 Add unit tests for geometry and fitness modules
26 tests for geometry (area, angles, aspect, boundary ids, centroid,
offset, etc.) and 35 tests for fitness (gaussian, config lookup,
quality terms, value rates, costs, stair helpers). Suite: 175 passed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 00:06:02 +01:00
fadb4f191f Close homemaker-py-hqw in beads 2026-06-13 23:40:00 +01:00
c37f03f1a1 Close homemaker-py-hqw: make project standalone (no Perl/Urb dependency)
Copy programme-house corpus (36 .dom + .score + .fails + patterns.config)
into examples/ and update all 5 test files to use project-relative paths.
Native Python fitness (use_native=True) was already the default; tests now
run without /home/bruno/src/urb present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 23:39:20 +01:00
33d79be3fe Cold-start bootstrap: diverse initial population for blank-slate search
When the seed is an undivided bare plot (init.dom), auto-generate pop_size
random topologies before the memetic loop starts, each evaluated at
child_budget.  This crosses the zero-feasibility region that single-seed
chaining cannot escape — the programme-house cold start was stalling at 18
fails after 2000 evals vs urb-evolve's 6.

Auto-detection via seed_root.divided preserves the existing single-seed
path for warm starts from existing designs; all previous tests pass unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 23:29:12 +01:00