Full harbor+maple/3-seed/20k-budget run superseded the earlier inconclusive
pilot table; section now records the closed verdict (no clear win, both
flags stay default off) instead of "driver-level INCONCLUSIVE at pilot
scale".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Adds src/homemaker_layout/cpsat.py (OR-Tools CP-SAT) as an exact alternative
to operators._assign_adjacency_aware's greedy/beam room-code placement,
wired in as assign_solver="greedy"|"cpsat" (EXPERIMENTAL, default "greedy",
byte-identical to before) through constructive_topology/lift_base_to_storeys/
driver.search, plus a new operators.mutate_reassign in-search repair
operator (driver.search's enable_reassign=False default, mirrors
enable_ruin_recreate). Both found and fixed a resize-fragility bug (a
second CP-SAT pass against settled geometry, operators._cpsat_relabel_settled)
and a CP-SAT symmetry-blowup stall (explicit interchangeable-code grouping).
Seeder-level A/B on harbor-house is a solid, low-noise positive (~13% fewer
real fitness-scored secondary-adjacency fails, 10 seeds). Full driver.search
A/B is only pilot-scale (budget=3000 vs the bead's own 20k target) and
inconclusive -- both flags stay default-off pending a larger-N confirmation.
Full writeup: DESIGN.md §37.7. Bead left in_progress (own acceptance
criteria not fully met); homemaker-py-5bv tracks the deferred post-collapse
repair item.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Generalise shapecurve.py's DP to process dom.levels(root) bottom-up per
storey instead of assuming a single free tree. A divided node's split is
free only per solver.free_branches' own criterion (below is None or
undivided there) -- geometry.coordinate always mirrors a below-linked
node's corners from the storey below regardless of whether that storey's
counterpart is divided, so every free region at any storey reduces to the
exact same single-region problem the pre-existing _check/realise already
solved. New _region_roots finds below-fixed leaves (checked directly,
gridless) and below-fixed-box/free-split fringe nodes per storey;
_solve_all_levels realises each storey before checking the one above and
snapshots+restores on any infeasibility, preserving solve()'s all-or-nothing
and is_feasible()'s never-writes contracts across the whole tree.
eligible() now allows any storey count.
Validated on the real (non-de-risked) examples/harbor-house: 200 random
2-storey topologies, DP-vs-NM agreement 99.5%, 0 false negatives, 117.7x
speedup (DESIGN.md §37.6). Full suite 397 passed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Adds shapecurve.is_feasible() (a non-mutating refactor of solve()'s check
phase) and a shapecurve_prune flag composing the DP's exact feasible/
infeasible verdict with operators.predicted_shape_fails' existing heuristic
prune: DP-feasible vetoes a heuristic prune outright; DP-infeasible only
hard-prunes when the incumbent already has zero total fails (exact, since
infeasible proves the shape-fail floor is >=1); otherwise defers unchanged
to today's heuristic threshold. Conservative by design since a wrong prune
is unrecoverable.
Validated 0/400 false negatives across two structurally distinct plots
(harbor-house-l0 + a newly-added programme-house sweep, the first genuinely
non-rectangular plot this DP has been checked against). The real
driver.search A/B on harbor-house-l0 measured NULL (byte-identical off/on)
for a root-caused, pre-existing reason: predicted_shape_fails rarely
triggers organically at this scale, so neither new branch had an opening to
fire -- not a defect in this change. Full writeup: DESIGN.md §37.5.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Promotes the validated shape-curve DP (experiments/shapecurve_spike.py,
2g7.4, DESIGN.md §37.2) from a reference-only spike into
src/homemaker_layout/shapecurve.py, and wires it into driver._evaluate as a
warm-start for innerloop.optimise: when eligible (single storey, no
leaf_sharing/superpose/max_share/multi_use) and no caller-supplied x0, the
DP's exact shape-feasible ratio point is written onto the tree before NM
runs, off by default (shapecurve_warmstart=/--shapecurve-warmstart).
Caught and fixed a latent bug promoting the spike: realise() could leave
numpy.float64 in `division`, which yaml.safe_dump can't serialise — the
original spike never round-tripped through dom.dumps so this was never hit.
A/B on harbor-house-l0 (experiments/ab_shapecurve_warmstart.py, budget=2000,
5 seeds): mean total fails 16.6 (on) vs 19.6 (off), ~3.5x mean fitness
improvement; mean hard-fail count alone was a noise-level wash at this
sample size. Full writeup in DESIGN.md §37.4.
Deliberately deferred to new tracked beads (children of 2g7): DP-exact hard
pre-filter (wkh), multi-storey below-link support (koo), leaf_sharing/
co_type modelling (tym), true skew-quad polygon algebra (ekc) — 6xh stays
in_progress pending those.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Composer half of the ground-truth bead: examples/harbor-house/drawings/
harbor-house 1.svg turned out to be a Bonsai/Blender render of 3m.dom's own
IFC (32 IfcSpace paths == 3m.dom's upper-storey leaf count), not a human
trace, so no usable reference exists yet -- this builds and tests the
pipeline that will consume one once traced. compose.py parses storey-N
Inkscape layers of cut-lines + labels against a boundary-stub .dom (plot/
height/elevation only, no room shapes to keep aligned across storeys) and
recursively detects guillotine cuts, mirroring geometry.py's own
division-line algebra; non-slicible regions and label mismatches are
reported by location rather than guessed at. homemaker-compose CLI added.
Renamed dom._link to public dom.link since compose.py needs to re-link from
outside dom.py. Full design writeup in DESIGN.md sec 37.3; actual human
tracing of harbor-house/programme-house is tracked as follow-up under
2g7.1, still open.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
User review caught a real gap: the DP approximated each quad's (w,h)
via its axis-aligned bounding box in global x/y, correct only because
harbor-house-l0's plot happens to be near-parallel to its own axes
(~7.5% area error). A real building's orthogonal walls need not align
to the survey/CRS axes at all -- confirmed by rotating the plot 45deg,
where the old bbox error jumped to 102% (up to 2x for a rotated square).
Fixed in two steps: (1) measure (w,h) from edge lengths
((edge0+edge2)/2, (edge1+edge3)/2, the geometry.aspect() pairing)
instead of global bbox -- rotation-invariant by construction. (2) this
alone regressed accuracy (99.0% -> 95.5%) because a child's own
rotation parity determines whether its local edge0/edge2 pair aligns
with its parent's edge0/edge2 or edge1/edge3 -- not a matter of degree
to measure empirically (as attempted first) but an exact algebraic
identity (verified float-exact: left.w + right.h == parent.w whenever
left.rotation is even and right.rotation is odd). _child_contrib now
applies this directly, replacing the empirical _orientation/
annotate_orientations machinery entirely -- simpler and correct.
Re-validated: 99.0% agreement on harbor-house-l0 unrotated (back to
matching the original result, same 2 residual mismatches, 0 false
negatives), 100% agreement at 97x speedup on the same plot rotated
45deg (new, via validate_shapecurve.py's rotated_plot_dir helper).
DESIGN.md §37.2 updated with the full correction history.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Prototype + validation for an exact size/width/proportion feasibility DP
over a frozen slicing topology, replacing the ~80-200 eval Nelder-Mead
inner loop's approximate answer to the same question with one bottom-up
pass (experiments/shapecurve_spike.py). Leaf feasible regions are exact
FAIL_THRESHOLD-inversions of fitness.py's quality_size/width/proportion;
internal-node composition runs on a shared discretised grid.
Validated on harbor-house-l0 (experiments/validate_shapecurve.py, 200
random topologies vs NM minimising shape-fail-count directly): 99.0%
agreement (0 false negatives), 93.6x speedup at grid_n=150, plot-level
bbox approximation error quantified at +7.5% (root-causing both observed
false positives). All three acceptance criteria cleared -- see DESIGN.md
§37.2 for full results and the caveats/scope not covered (multi-storey,
leaf_sharing/co_type, true skew-quad regions). Kept as a reference spike,
same status as experiments/autodiff_spike.py (§34); production wiring
into driver.py filed as homemaker-py-6xh.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
DESIGN.md §37.1: hard/soft tiering A/B (harbor-house + maple-court, 3 seeds,
20k evals/run) shows hard-fail mean strictly better under the tiered
comparator on both programmes (harbor 11.67->5.33, maple 19.33->14.00) at
the cost of higher soft/total fails — the intended trade. ACCEPTANCE: PASS.
Filed homemaker-py-p6t as a non-blocking follow-up: race tiered vs flat to
0 hard fails (convergence speed) rather than composition at a fixed budget.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LSwQwpEaHFBkeVSDDWd75S
Review of fitness.py/solver.py/collapse_cmd.py/innerloop.py/driver.py for
silent score-corrupting bugs (the iio class). Filed with verified repros:
r5a (stale-share resurrection via collapse commit), cvw (parallel staged
stale id()-keyed geometry cache), sd3 (collapse_best keep-better guard
vacuous under baked-in collapse_insearch), pek (shadowed process_storey).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjyStTdLWFMtdScrpbgQur
Adds a full writeup of the root cause (already fixed in 929be5b) plus a
same-codebase fix-vs-no-fix re-verification: harbor-house qpk-protocol
seeds 1-3 show collapse_insearch=OFF unaffected, but ON diverges by 5-8
fails on 2/3 seeds, non-directionally. Confirms the bug was not merely
theoretical for historical leaf_sharing+collapse_insearch runs, though the
noise is unlikely to have flipped 1ph's aggregate N=20 verdict. Adds a
caveat postscript to §20 (qpk) and files homemaker-py-d86 for the rigorous
historical-commit re-verification this session didn't do.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
Re-ran the §13.1/§13.2-style per-leaf fail-breakdown diagnostic on real
driver.search_staged runs (budget 20000, seeds 0-2, harbor-house and
maple-court) under the current full default stack (leaf-sharing x3,
depth-balanced, interior-O, share-aware edge cap) -- never decomposed by
category since those defaults were flipped on.
Finding: crinkliness (48%) and size (20.6%) now dominate the residual on
both programmes (~69% combined); construction-completeness fails
(missing space, adjacency, level, connectivity) are down to a small
tail (<=6% each). This revises erc.1's old recommendation to deprioritise
compactness-cuts in favour of leaf-sharing -- leaf-sharing is now fully
deployed and crinkliness is proportionally more dominant than ever, so
DESIGN.md §13.11 recommends reopening a compactness/crinkliness-targeted
construction lever as the next concrete step.
Also files two bugs found while validating the methodology: dumping and
reloading a .dom under leaf_sharing+collapse_insearch does not reproduce
the search's own in-process fail count (homemaker-py-iio), and
run_staged_search.py's own sanity rescore omits the collapse_insearch
override (homemaker-py-7ua). experiments/run_and_capture_91f.py sidesteps
this by capturing the true in-process fails list instead of rescoring
from disk; experiments/diag_residual_91f.py tallies fail categories from
those sidecars.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
Build a torch-differentiable local proxy for the ratio-to-fitness path (exact
port of geometry.py's coordinate recursion + the 5 continuous per-leaf quality
factors, with discrete/structural facts frozen from a real fitness.py
snapshot and the 0.5^n cliff relaxed to a sigmoid) and compare Adam ascent
against nm_search on frozen topologies from programme-house and harbor-house.
Result: ~30-35x slower per unit of search progress than nm_search at both
6 DOF and 36 DOF (per-op torch tensor dispatch overhead with no batching
opportunity, plus snapshot/resnapshot cost on par with a full oracle eval),
and no better quality at matched budget. A step-size sensitivity check
confirmed the flagged 0.5^n cliff risk is real, but autodiff doesn't make the
gradient direction any cheaper to obtain here. Not recommended; kept as
reference only, not wired into innerloop.py. Full writeup in DESIGN.md §34.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
The N=3 A/B (previous commits) found the precision-weighted shape
combination improved both example programmes (harbor-house -1.4%,
health-centre -13.9%), but N=3 is a thin sample by this project's own
standard (xyu/9yx use N=15). Two confirmations:
- N=15, plain search, budget=3000 (mirrors xyu/9yx's own protocol exactly):
both programmes trend NEGATIVE (harbor +6.1%, health-centre +6.6%,
Wilcoxon p=0.044)
- N=15, staged search, budget=20000 (true same-conditions replication --
identical to the original A/B except seed count): both programmes AGAIN
trend negative (harbor +6.6% p=0.15, health-centre +4.7% p=0.48)
The same-conditions replication disagrees with the original result's
direction on both programmes. Conclusion: the N=3 positive signal was
sampling noise, not a real effect -- health-centre's -13.9% was driven
substantially by one seed (71->43 fails) that didn't hold up.
multi_use stays default OFF and is not recommended even as a promising
lever -- this is a clean NULL, closing out both halves of §26's original
multi-use-leaves question (path a was NULL/NEGATIVE, path b is NULL after
replication). Mechanism itself is unchanged, complete, and fully tested.
DESIGN.md §33 rewritten with all three measurements and the honest verdict.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
Follow-up to the previous commit: user flagged that quality_width/
quality_proportion's "stricter of both" (max target, min sigma) combination
for a fused leaf's two codes was an ad hoc hack. Tried two more principled
alternatives and A/B'd all three against the harbor-house/health-centre
example programmes (20k evals x 3 seeds each):
1. stricter-of-both (original) -> health-centre +24.5% worse
2. precision-weighted Gaussian product -> health-centre -13.9% better
3. mixture (max of two Gaussians) -> health-centre +20.4% worse
Landed #2 (fitness._gaussian_product): combining two Gaussian evidence
sources about the same quantity via precision-weighting gives an
intermediate target with a narrower spread, unlike the naive max/min hack.
#3's building block (_clipped_gaussian) is kept, documented, and unit-tested
as a recorded negative alternative -- somewhat counterintuitively, the more
philosophically appealing "let the leaf collapse toward whichever code fits"
mixture model was empirically worse, because max() lets a leaf score 1.0 by
satisfying only the weaker of the two codes' targets.
multi_use stays default OFF -- the precision-weighted result improves both
example programmes on average but isn't the clean sweep needed for a
default flip (harbor-house loses 1/3 seeds). DESIGN.md §33 rewritten with
the full three-way comparison.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
Builds path (b) from §26 -- a leaf permanently serving two DIFFERENT
compatible programme codes at once, extending leaf-sharing's same-code
multiplicity mechanism to different-but-compatible codes. Architect-declared
`co_locate` pairs (validated against interchangeable()'s S1-S4 bounds, no
transitive closure so the b3v chain problem can't recur), threaded through
graph.py's checks via a new leaf_codes() resolver and fitness.py's quality
terms (additive size, stricter-of-both width/proportion). Construction-time
only, gated behind `multi_use` (default OFF, bit-identical when off).
End-to-end A/B (20k evals x 3 seeds x 2 programmes) came back net negative:
harbor-house -4.0% but health-centre +24.5% worse (3/3 seeds), because
fusing different codes' shape targets via stricter-of-both can impose a
tighter joint constraint than either code needed alone, which the tightly-
packed health-centre programme can't absorb. Written up as DESIGN.md §33;
multi_use stays default OFF, no default-flip recommended.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
run_9gp_ab.sh never threaded a worker count through run_staged_search.py, so
every §12.3 arm ran at n_workers=1 (serial) — the one mode §12.4 already
proved byte-for-byte reproducible even before the completion-order
determinism fix (that bug is ProcessPoolExecutor as_completed-only).
Spot-checked empirically: same config run twice gave identical fail counts
at every checkpoint. Closes homemaker-py-h10 as confirmed-null without
re-spending the ~8 core-hours a full sweep re-run would cost.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
N=15 seeds, xyu's own ruin_recreate ON/OFF protocol, against a real 20-room
diverse programme instead of programme-house's duplicated-code sweep: 2.2%
mean-fails delta, p=0.40 two-sided — much weaker than xyu's own inconclusive
6.4%/p=0.059 reading at the same room count, and converging with
harbor-house's null-to-negative result instead. Closes the diversity-axis
gap xyu's larger-N pass could not reach; enable_ruin_recreate stays OFF on a
now-broader evidence base. Issue closed.
Extends y51's n=18 synthetic sweep (strongest of four sizes at N=10) to
N=15 seeds, matching f1d's own confirmation sample size. Effect shrank
(9.3%->6.4%, two-sided Wilcoxon p 0.098->0.059) but didn't evaporate or
reverse — an ambiguous middle case, not a clean confirm or null. Refiled
option (b) (non-synthetic third example programme) as homemaker-py-9yx
since extending N alone doesn't address the interchangeable-room-code
confound §24 already flagged. enable_ruin_recreate stays default OFF.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
N=15 driver.search sweep of construction_beam_width 1 vs 4 (protocol
identical to c94's original 5-seed run, DESIGN.md §29): 6W/4L/5T, mean
fails 57.0->56.6, Wilcoxon p=0.84. Excluding seed 2's outlier the mean
flips slightly negative (56.3->56.9), confirming the §29 5-seed
"improvement" was that one outlier. construction_beam_width stays
default 1 on confirmed rather than precautionary grounds. DESIGN.md §30.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
The raw-seed diagnostic (single constructed tree, byte-identical across
beam widths) was wrongly taken as proof a full driver.search run would
also be byte-identical. Actually running it (5 seeds/programme, budget
1500, n_workers=1) shows harbor-house diverges: 2 wins/1 loss/2 ties vs
greedy — a full bootstrap population hits beam-vs-greedy tie-breaks a
lone raw seed sample missed. programme-house stayed tied 5/5. Verdict
corrected from a confident null to inconclusive/mixed on harbor-house;
practical disposition unchanged (construction_beam_width stays default 1).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
operators._assign_adjacency_aware gains beam_width (default 1 = exact
prior greedy behaviour), threaded through constructive_topology/
lift_base_to_storeys/driver.search/search_staged as
construction_beam_width. Verified functioning on an adversarial
synthetic case, but byte-identical raw-seed output to greedy at every
width tested (1/4/8/20) on both example programmes -- no headroom for
the beam to find on this repo's programmes. DESIGN.md section 29.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R8agJBT2ZpmF3ErW7wi2wY
§25 still said the evolve.py wiring and broader sweep were pending on
homemaker-py-cdl; that closed in the previous commit, so update §25's
stale forward-references and add §28 with the 46-file sweep results and
the collapse_insearch hot-path reasoning for leaving collapse_global's
own default off.
Two closed, substantive experiments were missing their DESIGN.md write-up
despite being referenced as prior art by later sections:
- 9o5/xi7/b3v (closed 2026-06-30/07-17): multi-use-leaf type superposition,
a full feature build + real A/B validation (negative — OFF beats ON on
both programme-house and harbor-house) + a veto-hatch follow-up for the
one genuine false-positive interchange class found. §17 and §20 both cite
its verdict directly but it never got its own section.
- mi7 (closed 2026-07-25): 3D bubble-diagram / topological-hop-distance
fitness signal prototype, tested against real evolved trajectories on two
programmes, both formulations null. bubble.py was left in the tree
uncommitted "as documented reference" by the closing session -- committing
it now (with two trivial ruff fixes: unused import, ambiguous var name) so
the reference this write-up makes to it is actually resolvable, plus a
CLAUDE.md module-list entry.
Numbered §26/§27 (appended, not inserted chronologically) to avoid
renumbering every cross-reference in §14-§25.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Locates the threshold f1d's programme-house/harbor-house split implied,
using four synthetic sizes (10/14/18/22 rooms) derived from programme-house
by scaling its bedroom+ensuite module count, since no natural third example
programme sits between the two. Results are noisy and non-monotonic (n=10
mild win, n=14 clean null, n=18 strongest trend at p=0.098, n=22 near-null)
rather than a clean decay with room count -- documented in DESIGN.md #24.
enable_ruin_recreate stays default OFF; filed homemaker-py-xyu as a
low-priority follow-up (larger-N at n=18, or a non-synthetic third example).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds operators.mutate_ruin_recreate: un-divides one wing of a storey and
rebuilds it with the same adjacency-aware constructor the seeders use
(_assign_adjacency_aware, generalised with a new `scope` param), seeded
from the surviving circulation bordering the wing. Gated behind
enable_ruin_recreate (default off) / --ruin-recreate, same pattern as
reassociate/bridge_circulation.
A/B (qpk protocol, DESIGN.md §23): initial uniform-weight run was
underpowered (fired ~1/32 children), null. A weight=3.0 follow-up
(_MUTATION_WEIGHTS["ruin_recreate"]) showed a statistically significant
win on programme-house across 15 seeds (8W/1L/6T, mean fails 7.07->6.00,
Wilcoxon p=0.041) but no consistent effect on harbor-house across 8 seeds
(3W/2L/3T). Kept default off pending a size-threshold follow-up.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Combined follow-up to 8sh (DESIGN.md §22): raised bridge_circulation's
_MUTATION_WEIGHTS entry to 2.0 (lj3) and re-ran the qi6/qpk-protocol A/B
at 4x the sample size (qjg) in one sweep, since the two variables were
confounded if tested separately. Result is null in the opposite direction
from 8sh's small-N signal -- no total-fail benefit (p=0.71 programme-house
N=20, p=0.69 harbor-house N=12) and a higher rate of trajectory-divergence
-induced new not-connected fails than at the original uniform weight.
Reverted the weight bump; enable_bridge_circulation stays default off.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDZjAATDWW1xFfc7xnJqSt
Adds operators.mutate_bridge_circulation: retypes the cheapest path between
two disconnected circulation components to circulation, directly clearing a
'level N not connected' fail instead of relying on the qi6 graded comparator
key (measured negative, DESIGN.md §18). Gated off by default via
driver.search's enable_bridge_circulation flag and evolve.py
--bridge-circulation, mirroring enable_reassociate's clean-toggle pattern.
qi6/qpk-protocol A/B (DESIGN.md §21) is directionally positive but mixed at
N=3/N=5 (never worse on total fails; clears 2/5 baseline not-connected fails
vs qi6's 0/4; one seed's RNG-trajectory divergence adds 2 new not-connected
fails) — kept default off pending a larger-N confirmation sweep
(homemaker-py-qjg) and a mutation-weight bump experiment (homemaker-py-lj3).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDZjAATDWW1xFfc7xnJqSt
20-seed programme-house sweep (vs the original 5) resolves the qpk A/B's
mixed 3/5 result as small-sample noise around a true small positive: mean
fails 7.95->7.10 (~10.7%), 11W/6L/3T, paired t-test p~0.028. Flips
collapse_insearch's default from OFF to ON in evolve.py and driver.py
(_overrides_for/_fitness_for/_evaluate/search/polish_finish); opt out with
--no-collapse-insearch. fitness.Fitness itself is unchanged.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDZjAATDWW1xFfc7xnJqSt
161 (2026-07-22) answered the "remaining open question" §19 left dangling —
threading fit into driver.search so shape_rotate/deslim can fire mid-GA —
but the result only ever landed in bd notes, never here. Also negative:
full-budget harbor-house A/B (seeds 0-3) shows no improvement, confirming
the finish-time finding at in-search scale. Both halves of §19's mechanism
space are now closed negative in the doc, matching bd state.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDZjAATDWW1xFfc7xnJqSt
conn_grade ON vs OFF (qpk protocol, experiments/run_qi6_ab.sh): harbor-house
(budget 2500, seeds 1-3) byte-identical output in every seed — the secondary
comparator key never fired. programme-house (budget 3000, seeds 1-5) 3/5 seeds
tie exactly; seeds 1/2 diverge to a different topology but the fail delta is
adjacency/crinkliness/width/access/size, never connectivity. Zero of 4 cases
where a not-connected fail was present got cleared by the grade.
Mechanism (b)/(c) (graded proximity as tertiary comparator key) is falsified,
not just unconfirmed. Kept default OFF (already was). Closed qi6; filed
homemaker-py-8sh for the remaining candidate (mechanism (a): an explicit
insert/relocate-circulation operator that doesn't depend on the search
stumbling onto a fail-count tie).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GDZjAATDWW1xFfc7xnJqSt
Runs the 94g finish-time cell↔room collapse inside every fitness eval
(collapse_insearch conf flag, default off, bit-identical when off) instead
of once at the end, so search optimises the collapsed objective directly.
Plumbed through fitness.py/driver.py/evolve.py the same way superpose/
conn_grade are; --collapse-insearch CLI flag.
A/B validated against the xi7 protocol (equal budget, both arms finished
with standard finish-time --collapse): POSITIVE, opposite of the 9o5/xi7
prior. harbor-house ON wins 3/3 (mean fails 80.3->72.0); programme-house
mixed 3/5 (mean fails 8.4->7.8). Kept default off pending a larger
programme-house sample; documented as a working opt-in for harbor-house-
scale-or-larger programmes. Full writeup in DESIGN.md §20.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diagnosed the geometry-intrinsic residual from 94g's collapse: ratio
re-optimisation isn't the bottleneck (1500-eval NM makes zero difference on
the 12-fail collapsed best layout); the causes are upstream area starvation
and cut-orientation mismatch. Added mutate_shape_rotate/mutate_deslim
targeting each, gated on a Fitness instance like the existing reqs-gated
repair ops.
Evaluated as a finish-time exhaustive hill-climb on the same 6-layout
harbor-house sweep 94g used: zero improving moves found anywhere — every
candidate move traded the shape fail for a new adjacency/access fail on the
co-evolved layout (§4.2's lesson, now confirmed for topology repair). Closes
homemaker-py-7fm; spun homemaker-py-161 for the open in-search-GA question.
See DESIGN.md §19 for the full writeup.
The dominant post-collapse fail is the binary "level N not connected",
which is flat across fragmentation (a 7-component storey scores the same
as a 2-component one), so the outer search has no gradient toward
connected circulation. A finish-time convert-to-circulation repair was
prototyped and measured NEGATIVE (195->560 fails: bridging needed rooms
costs more missing-room fails than the one binary fail it clears).
Instead add graph.circulation_connectivity(G) = largest-circ-component
fraction, summed over storeys onto the score_with_grade proximity channel
(conf flag conn_grade; replaces the §11.4 leaf-grade there). It is a
secondary comparator key only — scalar fitness and fail count stay
byte-identical — restoring the gradient the binary fail lacks. Threaded
through driver (_overrides_for/_fitness_for/_evaluate/search; enabling it
implies the grade key) and evolve --conn-grade (default off).
A/B on full-budget runs pending; short smoke run confirms plumbing.
Tests: tests/test_conn_grade.py x9 (fraction contract, non-circ ignored,
monotone under (dis)connection, score/fail invariance); 276 pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8566xAxTnwtJTkpXjYNZm
Document the collapse as built (default-on in evolve + homemaker-collapse CLI):
label-relative vs geometry-intrinsic fails, collapse_global mechanism (c/o/s
partition, hard level, adjacency relaxation, threshold objective, public-access
pin), the two measurement corrections, keep-better wrapper + wiring, and the
6-layout sweep verification. DESIGN.md is the system-of-record for users without
beads access.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8566xAxTnwtJTkpXjYNZm
harbor-house 3M (500k/grain x3 + 1.5M polish, workers 4, ~22h): the in-run
grain anneal reached 1.26e-08 / 23 fails (canonical byte-for-byte), losing
decisively to both the direct --no-leaf-sharing baseline (5.14e-06 / 15) and
yaa's single-hard-transition warm chain (4.19e-06 / 15) — ~400x worse fitness,
+8 fails.
Each grain step spikes the fail count as its unfolded leaves acquire
independent shape fails (phase-end 19->21->27, final de-share 27->36); the
per-phase budget re-polishes a partially-materialised state the next step
materialises further, so coarse-grain gains do not carry forward. The polish
phase started from a deeper hole (36) than the warm chain's single clean
transition and 1.5M evals recovered only to 23. The sharing-phase topology
skeleton is best cashed in once, at full grain — not annealed.
Machinery retained (search_annealed, --anneal-grain, unfold above=, seed_pop,
max_share override): correct, tested, honest, reusable. Default finish stays
§15's single-transition unfold+polish. DESIGN §16 records the verdict; closes
homemaker-py-kpu.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8566xAxTnwtJTkpXjYNZm
Ramp the leaf-share grain down within one continuous run (e.g. 4->3->2->off),
carrying the whole population across each step — graduated non-convexity over
the single hard sharing->off transition of the §15 finish.
- operators.unfold_shared_leaves(above=cap): unfold only leaves whose share
exceeds the new grain cap, leaving smaller-share leaves collapsed for the
next step. above=1 (default) keeps the full-unfold §15 behaviour.
- driver: max_share override threaded through _overrides_for/_fitness_for/
_evaluate so a phase can rebuild the evaluator at a lower leaf_share_max cap;
search(seed_pop=) evaluates an explicit initial population so a phase hands
its whole population to the next instead of restarting from a single best.
- driver.search_annealed: one phase per descending grain then a de-share
polish; unfold-above-cap between steps; cumulative accounting + grain-tagged
history; honest canonical best (byte-for-byte verified vs homemaker-fitness).
- evolve: --anneal-grain LADDER CLI (self-finishing; §15 finish not applied).
8iv settled the primitive (grid unfold beat the circulation-aware slice), so
the ramp reuses the plain balanced-grid unfold at every step.
Tests: unfold above-cap selectivity, seed_pop seeding, search_annealed phase
stitching / honest finish / degenerate-ladder fallback. 258 pass. DESIGN §16.
Head-to-head A/B on harbor-house still to run; verdict pending (issue open).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8566xAxTnwtJTkpXjYNZm
Add DESIGN.md §15 recording the leaf-sharing output-honesty bug (internal
sharing objective diverges from canonical scorer), yaa's conclusive
unfold-then-polish investigation, and the driver.polish_finish auto-finish
fix + --polish-budget CLI knob. Matches §13.10's documentation of the
original leaf-sharing feature.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8566xAxTnwtJTkpXjYNZm
Expose tournament_k (default 2) on search()/search_staged(), threaded into
both _tournament call sites and the staged path's internal search() calls;
HOMEMAKER_TOURNAMENT_K env knob in the scaled/staged harnesses; run_6zy_ab.sh
joint niche×k grid (RESUME-able).
Result (negative, acceptable): no (niche,k) cell beats the legacy (off,k=2)
baseline. Blank-slate programme-house (5 seeds) baseline mean 4.80 fails is the
best of the 6-cell grid; every k>2 and every niche=on cell is 6.0-7.0. Niching
bites (pop_distinct 16/16 vs 4-11) but sharper pressure does not convert it to
lower fails — §11.5 'diffuses effort' null is robust to selection pressure;
plateau stays reachability-bound (confirms §11.4/§11.5).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prime a population from N independent converged elites + crossover-heavy
migration phase, vs best-of-N at equal total budget. Island does NOT win:
harbor 68 vs control 67 (within parallel noise), maple 124 vs control 116
(decisive). Default-off child_probe hook on driver.search instruments the
deciding mechanism: area-matched crossover across independently-converged
elites rarely synthesizes (1/65 harbor, 3/63 maple beat the better parent,
max fail-drop 2-5), confirming the alignment hypothesis (non-canonical 9gp
encoding -> disruptive splice). Search-machinery null #3; residual stays
geometry/shape-bound. 233 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
§13.8 verdict was positive and monotone-harmless, so default the share-aware
edge-too-long cap to leaf_sharing when share_edge_cap is unset — mirrors the
pll bal+share and §13.6 interior_outside default flips. Explicit
share_edge_cap=False still reproduces the pre-flip control arm.
- fitness.Fitness.__init__: cap defaults to self._leaf_sharing when the conf
key is unset (None); explicit True/False honoured.
- run_staged_search.py: pin conf["share_edge_cap"] = share_edge in both A/B
arms so SHAREEDGE=0 stays a clean control post-flip.
- tests: control arm now pins share_edge_cap=False; new
test_edge_cap_defaults_on_under_leaf_sharing guards the flip.
- DESIGN.md §13.9: rebaseline §13.x floor (maple 80.3→74.0, harbor 34.7→31.0).
Non-sharing runs untouched: programme-house control re-score reproduces
bit-for-bit. 222 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
§13.7 flagged edge-too-long as harbor's top fail class. Dissection showed the
bulk are a leaf-sharing REPRESENTATION ARTIFACT: a share=k leaf aggregates k
same-code rooms, so its walls run ~k× the flat 8 m cap purely for being big —
the same §13.3 leak (size/missing relaxed for shared leaves) on the wall measure,
since edge_cost/outside_edge_cost ignored leaf.share.
Fix: Fitness._edge_cap(*leaves) scales the 8 m cap by the largest type-guarded
leaf_share among adjoining leaves, mirroring quality_size's k×target; non-shared
leaves keep the flat cap so genuine narrow/oversize pathologies stay flagged.
Gated behind a share_edge_cap config knob (SHAREEDGE env), default OFF so the
§13.x controls reproduce.
A/B (full Phase-8 stack, staged, 20k evals, seeds 0/1/2): control reproduces
§13.7 (maple 80.3 exact, harbor 34.7≈34.0); share-aware arm maple 80.3→74.0
(−7.9%), harbor 34.7→31.0 (−10.6%), zero regressions across 6 seeds. Positive
and monotone-harmless (only ever removes a false-positive fail). Verdict:
recommend default-ON; follow-up issue flips the default + rebaselines the floor.
Tests: 6 new unit tests for _edge_cap (221 pass).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JygRv4n2dcyDQqMiDRe7TN
500k serial full-stack harbor probe (probe_harbor_floor.py): 20 fails,
crinkliness 13→4, landlocked crinkliness ~13→2 of 20. Interior-O (default-ON,
erc.8) is 71d's named fix and dissolved its landlocked-crinkliness target;
residual now diffuse (top class edge-too-long). NO-GO on 71d.
Cumulative Phase-8 floor vs §12.2 baseline (leaf-share-relaxed): maple
136.0→80.3 (−41%), harbor 74.0→34.0 (−54%) — all from construction levers,
none from search machinery, per the epic thesis.
Closes erc epic: 71d/7u5/jrb/u8x superseded-by-construction; erc.5/erc.6
wont-fix (Diag A/B revisit conditions unmet). DESIGN §13.7.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JygRv4n2dcyDQqMiDRe7TN
Seed O as interior light wells (most-landlocked leaves first, count scaled
by room count via outside_divisor) instead of one peripheral O, attacking the
erc crinkliness residual: seed diagnostic confirms every crinkliness fail is
under-exposed (landlocked), none over-exposed.
A/B (20k evals, seeds 0/1/2, bal+share stack, §13.6): control reproduces §13.5;
interior odiv=3 gives harbor -16.4% (all seeds improve) and maple -2.8%
(net-neutral). Default-optimal divisor 3 found by seed sweep (6 was null).
Lever default OFF; default-ON flip tracked as erc.8.
- operators: interior_outside + outside_divisor through constructive_topology,
lift_base_to_storeys, _assign_adjacency_aware (fix n_circ budget for >1 O)
- driver.search/search_staged threading; run_staged_search.py INTERIORO/ODIV env
- test_interior_outside_seeds_landlocked_wells_and_scales_count
- experiments/run_interioro_ab.sh; DESIGN.md §13.6
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
End-to-end 20k A/B (seeds 0/1/2): depth-balancing gives −5.8% maple / −3.2%
harbor with OVERLAPPING arms — far less than the −11/−12% seed-floor probe,
because the 20k search erodes most of the seed advantage via divide/undivide
mutations (unlike leaf-sharing's structural leaf-count cut, which the search
cannot undo). Baseline reproduces §12.2 (maple 137.0 vs 136.0, harbor 74.0).
Promise is the additive floor with leaf-sharing (probe: bal+sh3 << share3-alone);
the decisive test is erc.7 synergy. Keep depth_balanced default OFF; close erc.4,
advance erc.7.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>