Commit graph

6 commits

Author SHA1 Message Date
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
d330a9171c Add mutate_level_compound_fix: escape deceptive level-fix valley
When level_fix alone displaces a required room (e.g. t3) it triggers 5
oracle fails for the missing room — far worse than the starting 2 fails,
so lex always rejects it.  level_compound_fix atomically: moves the
constrained room to its required floor AND re-inserts the displaced room
by splitting the sibling of the largest C leaf on that floor.  The C
sibling is guaranteed adjacent to C (shared parent split), so the
displaced room keeps its required C-adjacency.

On programme-house this jumps the warmstart from 2 fails (l1 wrong
level + t3 size) to 1 fail (staircase volume), which lex accepts as an
improvement and provides a new base for further mutation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 22:46: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
507cf82d99 Add mutate_level_retype: swap leaf types between storeys
Cross-storey equivalent of mutate_retype. Directly addresses
level-constraint failures ("l1 on wrong level") by moving a room type
from one floor to another without changing topology or geometry.

Registered in MUTATIONS at default weight (1.0); no drastic geometry
perturbation so it does not need the reduced level_add/delete weight.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 10:52:48 +01:00
517a825505 Fix mutate_level_add: use generic C/O floor instead of room duplicate
Previously level_add copied the top storey exactly, duplicating all
named programme rooms and immediately triggering space-count failures
for every room on the new floor. The lex outer-search comparison
(-n_fails, score) then always rejected the multi-storey child because
its fail count was far higher than the single-storey parent.

Fix: retype all named-room leaves on the new storey to generic C or O
before admitting the child. The outer search then retypes them
incrementally via the normal retype operator. This allows level_add to
produce designs with the same fail count as the parent (storey_minimum
fail removed, no duplication fails added), making the multi-storey
transition visible to the lex selector.

Result on programme-house cold start (init.dom, 100k evals, 4 workers):
  before: 6 fails, single-storey, stuck after 40k evals
  after:  4 fails, two-storey, still improving at 100k

Also adds examples/harbor-house/ from urb/examples for future runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 10:33:05 +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
Renamed from src/homemaker/operators.py (Browse further)