Owner's daylight ruling: corridors need it; retract the 61% headline

Ruling: corridors need daylight. Only rooms not occupied from day to day --
a cupboard, a store, a plant room -- do without it.

That overturns the classification 38.8 and 38.9 rested on. Those sections
exempted internal circulation, covered courtyards, WCs, laundries and
reception on my inference rather than any ruling. None are exempt: a
corridor is occupied all day every day, a waiting room likewise, a laundry
is a room people spend time in, a sterilisation room is a workplace.

Re-measured with the classification READ FROM THE CORPUS (a space is exempt
exactly when its own patterns.config declares crinkliness: none) instead of
inferred: 24 of 271 crinkliness fails (9%) were not defects -- not 136
(50%), not 61%. Overstated by about six times.

  - uncrinkliness_circulation stays at [5/6, 1.1/3]. 38.10 called its
    equality with the habitable target the purest case of an untuned value;
    it is not a bug, it is the correct answer reached by default, since
    corridors want daylight on the same terms as rooms.
  - corpus declarations narrowed 18 -> 14. usage: utility was too coarse and
    swept in Laundry Rooms and a Sterilisation Room. What remains is
    storage, plant/mechanical, utilities closets and a records room.
  - audit_crinkliness_truth.py rebuilt to read the classification from the
    configs rather than infer it from usage:, so it cannot drift from the
    ruling again.
  - 38.8/38.9's inflated figures flagged in place, with 38.11 carrying the
    correction.

What survives, none of it dependent on the classification: the 38.6
critique of the three modes; usage_daylight being mis-keyed; the 38.8 A/B
yardstick being wrong; and the per-space crinkliness mechanism itself.

ssz's opening measurement was right but its reading was wrong -- under this
ruling a buried leaf usually IS a defect, so scoring it zero is largely
correct. The narrowed remnant is that the score is FLAT rather than low, so
two equally-buried layouts cannot be ranked. Filed as homemaker-py-9gj; it
is a search-mechanics problem, not a calibration one.

Lint at parity (46); tests 369 passed, 2 pre-existing failures (ut5's stale
baseline and 1ue), both failing identically before this change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
This commit is contained in:
Claude 2026-08-28 23:14:21 +00:00
parent 31d50ba72b
commit c9b9eafef6
No known key found for this signature in database
7 changed files with 127 additions and 35 deletions

File diff suppressed because one or more lines are too long

View file

@ -5156,8 +5156,9 @@ sits in?
| maple-court | 46 | 13 (28%) | **33 (72%)** |
| health-centre | 18 | 9 (50%) | 9 (50%) |
**Roughly two thirds of the zero-value leaves are spaces that architecturally
do not want a window at all** — a broom cupboard, a WC, a plant room, an
**RETRACTED, see §38.11 — the real share is under a tenth.** As written this
claimed that roughly two thirds of the zero-value leaves are spaces that
architecturally do not want a window at all — a broom cupboard, a WC, a plant room, an
internal corridor, a covered courtyard. The objective scores them identically
with a windowless bedroom. That is the miscalibration, and it is not a gradient
problem to be patched with an epsilon; it is the wrong requirement applied to
@ -5255,8 +5256,14 @@ leaf's declared usage:
| maple-court `generated.dom` (evolved) | 67 | 43 (64%) |
| **overall** | **271** | **164 (61%)** |
**61% of the crinkliness failures the objective reports are not defects**, and
it holds on evolved artefacts, not just seeds. Under
**RETRACTED — the true figure is 9%, see §38.11.** The table above classifies a
fail as a non-defect using `usage:`, exempting corridors, WCs, laundries and
reception; the owner exempts none of those. Only rooms not occupied from day to
day — a cupboard, a store, a plant room — do without daylight. The paragraph as
written said:
> **61% of the crinkliness failures the objective reports are not defects**, and
> it holds on evolved artefacts, not just seeds. Under
`value *= 0.5 ** len(failures)` every one of them halves the fitness of a design
that has done nothing wrong — a design is punished for putting the store in the
middle of the plan, which is what a competent architect does. That is a
@ -5334,8 +5341,8 @@ programme-house has no utility spaces).
| | crinkliness fails | not defects |
|---|---|---|
| before | 271 | 136 (50%) |
| after the utility declarations | **243** | 108 (44%) |
| before | 271 | ~~136 (50%)~~ **24 (9%)** — see §38.11 |
| after the declarations | **247** | **0** |
The 28 that went are exactly the utility fails. What remains is two populations
the corpus cannot reach, because neither is a `spaces:` entry:
@ -5354,6 +5361,79 @@ settable to `none` like any space (tested), but the default is deliberately
on, and this is 63% of the remaining phantom fails, so it is not a call to make
by inference.
### 38.11 Owner's ruling on daylight, and the retraction of §38.8's headline
**Ruling: corridors need daylight. Only rooms that are not occupied from day to
day — a cupboard, a store, a plant room — do without it.**
That overturns the classification §38.8 and §38.9 were built on, and with it
their headline number. Those sections exempted, on my inference rather than any
ruling: internal circulation, covered courtyards, WCs and bathrooms, laundries,
and reception/waiting/foyer. **None of those are exempt.** A corridor is
occupied all day, every day; so is a waiting room; a laundry is a room people
spend time in; a sterilisation room is a workplace.
Re-measured against the ruling, with the classification read from the corpus
(a space is exempt exactly when its own `patterns.config` declares
`crinkliness: none`) rather than inferred:
| layout | crinkliness fails | not defects |
|---|---|---|
| harbor-house, 3 constructed seeds | 67 | 8 (12%) |
| maple-court, 3 constructed seeds | 112 | 9 (8%) |
| health-centre, 3 constructed seeds | 20 | 2 (10%) |
| harbor-house `generated.dom` (evolved) | 5 | 1 (20%) |
| maple-court `generated.dom` (evolved) | 67 | 4 (6%) |
| **overall** | **271** | **24 (9%)** |
**9%, not 61%.** The objective's daylight requirement was mildly miscalibrated,
not massively so, and I overstated it by a factor of about six by inventing a
classification instead of asking for one.
**`uncrinkliness_circulation` is therefore left at `[5/6, 1.1/3]`.** §38.10
called its equality with the habitable target "the purest case of a value never
tuned". It is not a bug: corridors want daylight on the same terms as rooms, so
the two targets agreeing is the correct answer, arrived at by default. The key
stays available for a programme that wants to differ.
**The corpus declarations are narrowed to match.** `usage: utility` was too
coarse a proxy — it swept in Laundry Rooms and a Sterilisation Room, all of
which are occupied. 14 spaces now declare `crinkliness: none`, and every one is
genuinely unoccupied:
| programme | declared `crinkliness: none` |
|---|---|
| harbor-house | Ground/First Floor Storage, Mechanical/Electrical Room, Utilities Closet |
| harbor-house-l0 | Ground Floor Storage, Mechanical/Electrical Room |
| health-centre | General Storage, Plant / Mechanical Room, Records Room |
| maple-court | Ground/First/Second Floor Storage, Mechanical/Electrical Room, Utilities Closet |
*(Records Room is the one debatable entry — a store you fetch a file from, not a
desk. Flip it to a declared target if it is meant to be worked in.)*
**What survives §38.8/§38.9 unchanged**, because none of it depended on the
classification:
- the §38.6 critique. `floor` returns 0.01 for a buried leaf, `compact_ok`
contradicted itself, and `exempt_circulation` reached a third at most. Those
are facts about the code, and they are why §38.6 measured a null;
- `usage_daylight` was mis-keyed. §38.9's reasoning for that was right even
though its numbers were not — `usage:` is an access axis;
- the §38.8 A/B's yardstick was wrong: scoring the repair under the objective
it repairs penalises it for repairing;
- the mechanism. Crinkliness was the only leaf quality factor with no per-space
target, and §38.10's fix stands on the owner's design, not on my numbers.
**What this does to `ssz` as a whole.** The issue opened on "4556% of interior
leaves are zero-exposure and score a hard zero, so the objective assigns no
value to any interior room". That measurement was right, but the reading was
wrong: under this ruling **a buried leaf usually IS a defect**, corridors and
WCs included, so scoring it zero is largely *correct*. What remains of the
complaint is narrower and is about search mechanics rather than truth — a hard
`0.0` cannot rank two bad layouts against each other, so the objective is
flat where it should be merely low. That is worth a separate issue; it is not
the calibration fault this section spent its length chasing.
## 39. Config audit: requirements that actively fight the engine (`homemaker-py-ju3`) — measured 2026-08-25
The corpus `patterns.config` targets and `costs.config` values were estimated

View file

@ -98,7 +98,6 @@ spaces:
count: 3
la1:
crinkliness: none # no window needed
usage: utility
name: Laundry Room
size:

View file

@ -141,7 +141,6 @@ spaces:
count: 6 # 3 ground + 3 first floor
la1:
crinkliness: none # no window needed
usage: utility
name: Laundry Room
size:

View file

@ -130,7 +130,6 @@ spaces:
- ms1
zt1:
crinkliness: none # no window needed
usage: utility
name: Sterilisation Room
size:

View file

@ -94,7 +94,6 @@ spaces:
- o
la1:
crinkliness: none # no window needed
usage: utility
name: Laundry Room
size:

View file

@ -1,17 +1,20 @@
"""Are the crinkliness failures the objective emits real defects? (`homemaker-py-ssz`)
Not an A/B. This asks a correctness question the search cannot answer: of the
`crinkliness` failures the STOCK objective reports, how many are on a space
that architecturally wants daylight at all?
`crinkliness` failures the GLOBAL-target objective reports -- one daylight
requirement for every space, which is what the engine did before §38.10 -- how
many are on a space that does not want daylight at all?
A `crinkliness` fail says "this leaf has too little exposed wall for its area".
For a bedroom or a living room that is a real defect. For a broom cupboard, a
WC, a plant room, an internal corridor or a covered courtyard it is not -- those
are ordinary buried architecture, and the fail is an artefact of applying one
daylight requirement to every space regardless of use (DESIGN.md §38.8).
For anything occupied day to day that is a real defect. For a cupboard, a store
or a plant room it is not.
Every fail is classified by the leaf's DECLARED `usage:` (§39.7), so nothing
here rests on how a code is spelled.
**The classification is read from the corpus, not guessed here.** A fail counts
as a non-defect exactly when that space declares `crinkliness: none` in its own
`patterns.config`. An earlier version of this script inferred it from `usage:`
instead and got a much larger, wrong answer -- it exempted corridors, WCs,
laundries and reception, none of which the owner exempts (DESIGN.md §38.11).
Corridors, courtyards and every occupied room want daylight.
Usage::
@ -36,12 +39,11 @@ from homemaker_layout import operators, programme
CORPUS = ["examples/harbor-house", "examples/maple-court", "examples/health-centre"]
# Ruled by the project owner: everything a person occupies wants a window --
# WCs and bathrooms included, reception/waiting/foyer included, offices and
# consulting rooms included. Only stores, plant, records and laundry do not,
# together with the generic structural types (a corridor has its own
# `uncrinkliness_circulation` target; a courtyard is not a room).
NO_DAYLIGHT = {"utility"}
# Ruled by the project owner: only rooms that are not occupied from day to day
# -- a cupboard, a store, a plant room -- do without daylight. Corridors need
# it. So does everything else: WCs, laundries, reception, waiting rooms,
# offices, consulting rooms. Which spaces those are is read from the configs
# themselves (a declared `crinkliness: none`), never inferred here.
def stock_fitness(progdir: str) -> fitness.Fitness:
@ -64,7 +66,12 @@ def constructed(progdir: str, s: int) -> dom_mod.Node:
def audit(fit: fitness.Fitness, root: dom_mod.Node) -> collections.Counter:
"""usage -> count, over the leaves that emit a stock `crinkliness` fail."""
"""label -> count over the leaves that fail under ONE GLOBAL daylight target.
Each is labelled with the leaf's usage, and marked exempt when that space
declares `crinkliness: none` -- i.e. when the failure the old objective
emitted was not a defect.
"""
tree = copy.deepcopy(root)
geometry.clear_cache()
dom_mod.canonicalize_shares(tree)
@ -79,25 +86,33 @@ def audit(fit: fitness.Fitness, root: dom_mod.Node) -> collections.Counter:
for leaf in lvl.leaves():
if dom_mod.is_outside(leaf) and not dom_mod.is_covered(leaf):
continue
if fit.quality_uncrinkliness(leaf, graphs[li], groups) >= fitness.FAIL_THRESHOLD:
continue # not a failure
out[fit.usage_of(leaf) or f"<generic {leaf.type}>"] += 1
# the PRE-§38.10 objective: one global target for every leaf
crink = fit.crinkliness(leaf, graphs[li], groups)
if crink:
distance, sigma = fit.conf("uncrinkliness")
q = fitness.gaussian(1 / crink, 1.0, distance, sigma)
else:
q = 0.0
if q >= fitness.FAIL_THRESHOLD:
continue # not a failure even then
label = fit.usage_of(leaf) or f"<generic {leaf.type}>"
if fit.crinkliness_params(leaf) is None:
label += " [declares crinkliness: none]"
out[label] += 1
return out
def report(label: str, tally: collections.Counter) -> tuple[int, int]:
total = sum(tally.values())
real = sum(n for u, n in tally.items() if u not in NO_DAYLIGHT
and not u.startswith("<generic"))
real = sum(n for u, n in tally.items() if "crinkliness: none" not in u)
print(f"=== {label}: {total} crinkliness fails")
if not total:
print(" none\n")
return 0, 0
for usage, n in tally.most_common():
exempt = usage in NO_DAYLIGHT or usage.startswith("<generic")
verdict = ("not a defect -- no daylight wanted" if exempt
else "REAL DEFECT")
print(f" {usage:<18}{n:>4} {verdict}")
verdict = ("not a defect -- not occupied day to day"
if "crinkliness: none" in usage else "REAL DEFECT")
print(f" {usage:<44}{n:>4} {verdict}")
print(f" -> {total - real}/{total} ({100 * (total - real) / total:.0f}%) "
f"are reported against spaces that do not want daylight\n")
return real, total