homemaker-layout/examples/programme-house/patterns.config

119 lines
3 KiB
Text
Raw Permalink Normal View History

---
# Example patterns.config for programme-driven building evolution
#
# This file demonstrates how to define a building programme within
# the standard patterns.config file format. The presence of the
# 'spaces' key automatically triggers programme-driven mode.
# Building programme: 2-bedroom house with ensuite
spaces:
b1:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: bedroom
name: Master Bedroom
size:
- 16.0
- 4.0
width:
- 4.0
- 1.0
proportion:
- 1.5
- 0.5
adjacency:
- c
t1:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: toilet
name: Ensuite Bathroom
size:
- 5.0
- 1.5
width:
- 2.5
- 0.5
adjacency:
- b1
b2:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: bedroom
name: Second Bedroom
size:
- 12.0
- 3.0
width:
- 3.5
- 0.8
adjacency:
- c
t2:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: toilet
name: Guest Bathroom
size:
- 4.0
- 1.5
adjacency:
- c
l1:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: living
name: Living/Dining/Kitchen
size:
- 35.0
- 8.0
width:
- 4.5
- 1.0
proportion:
- 2.0
- 0.8
level: 0
adjacency:
- c
t3:
§39.7: access requirements become a declared `usage:` attribute (homemaker-py-sel) Closes the second namespace sharing a first character with programme codes: the usage prefixes b/t/l/k, under which a room silently inherited another room's connectivity rules from its spelling. usage is a plain, MANDATORY attribute of the space definition -- not a lookup table. An interim design proposed a top-level usage_classes: table binding author-coined names to behaviour; withdrawn, because an indirect name->behaviour mapping living apart from the thing it describes is exactly the shape of the prefix rule §39 exists to remove, it would be the only such table in a schema where every other space property is a plain attribute, and the need it served was already met -- "building specific" is about what a room is CALLED, and name: is already free text. Rule that settles it: a usage value exists iff the engine treats it differently somewhere. Config selects among behaviours; it cannot invent them. - programme.USAGES (living/kitchen/bedroom/toilet/utility/none) plus the behaviour groupings PRIVATE_USAGES / PRIVATE_STRIPS / TOILET_STRIPS / SOCIABLE_USAGES. Missing or unknown usage is a load error naming the code, from BOTH parse paths. - Code-level, never leaf-level: usage_of(leaf.type) is looked up fresh, so a retype changes the class automatically. 51 sites assign leaf.type, and share/share_type plus the r5a resurrection are the precedent for why leaf-level attributes rot. - graph.has_circulation takes the usage map and trims on declared class; fitness.access and the public-access check likewise. fitness._t0 is DELETED -- no first-character type test remains anywhere in the codebase. - utility is distinct from bedroom (same access requirements today) because it is a different use and gives derive_interchange_classes an axis to relax on. - A toilet now keeps its edge to a terminal room -- the Brand adjacency, which the old b-before-t loop ordering severed. - All 107 corpus entries migrated by experiments/migrate_usage_key.py, comments and layout preserved. MEASURED -- the connectivity model was ~4x too permissive. `none` is not neutral: nothing is trimmed, so the graph may route THROUGH the room, and 34 of 52 codes had no class (Dental Surgery, Records Room, Utilities Closet all served as corridors). Edges trimmed, prefix-inferred vs declared, 3 seeds each: harbor-house 18 (9%) -> 79 (39%) inaccessible fails 0 -> 4 health-centre 12 (8%) -> 59 (40%) inaccessible fails 2 -> 3 maple-court 53 (17%) -> 123 (39%) inaccessible fails 1 -> 5 Re-baseline (seed 1, 20k, harbor): 58 fails (15h/43s) -> 61 (16h/45s), now reporting 1-inaccessible-usable-space x2 plus level 0 and level 1 not connected. The count rose because the objective got honest -- those failures were always true of the layout and the old model could not see them. Every harbor number before this was measured against a graph crediting routes through store cupboards. Sharpens §38.2: the objective pays x60-85 to delete circulation, and until now the deleted corridors were not missed because storage stood in for them. With that substitution gone, homemaker-py-2v1 is the remaining half -- and now measurable, because the fails it should prevent actually fire. 350 passed (+5 new), same 7 pre-existing fixture failures, lint unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-08-26 13:39:41 +00:00
usage: toilet
name: Ground Floor WC
size:
- 3.0
- 1.0
adjacency:
- c
level: 0
# Building constraints
storey_minimum: 2
storey_limit: 5
Outdoor space: enforce the per-level rule, drop the fraction Owner: "maybe plot_ratio is having unintended consequences, Alexander simply says that all levels should have accessible outside space, he doesn't say how much." Both halves are right, and the codebase had the two rules the wrong way round. ratio_outside is a gaussian on the outdoor FRACTION, applied as a whole-building multiplier, and its declared targets have no stated basis and contradict each other: health-centre targets 0.06 and sits at 0.096-0.129, so it is penalised x0.39-x0.77 for having too MUCH; programme-house targets 0.30 and sits at 0.098-0.293, penalised x0.40-x0.999 for having too LITTLE. Penalties as large as the ratio_circulation ones 39.24 removed, pulling two programmes in opposite directions on the same quantity. force_roof_garden already implements the rule Alexander actually states -- per level, no outdoor space at all is a hard fail, no quantity attached. It has existed all along and was switched OFF in every corpus config. Near-miss worth recording: measuring first, I found zero "no outside space" fails across the twelve baseline runs and briefly read that as the requirement being met everywhere. It meant the check never ran. Same shape as 39.20's parity tests -- no failures from a test that is not executing looks exactly like no failures from a test that passes, and the tell was again the config, not the code. Enabled, it bites on 4 of 25 baseline levels: maple s0 level 1, and programme-house level 0 in all three seeds. A house with no outdoor space on its own ground floor is a fair criticism of the layout, and exactly what a building-level fraction cannot catch, since 22% outdoor concentrated on one storey satisfies it perfectly. The upper side ratio_outside used to provide is covered in a better currency by the minimum-internal-area factor (internal area >= 1.2x the programme's declared room area), which is live -- binding on harbor s0 x0.920 and programme-house s0 x0.787. This is the one change in 39.22-39.25 whose risk is NOT measured: nothing here proves the outdoor fraction will not drift up once the search is free to raise it, and outdoor space is profitable (1.64 return against a room's 0.66). The re-baseline (bk9) is what shows it, and 39.25 asks for the fraction to be recorded there. 4 hard fails added, none removed. 426 passed. Refs homemaker-py-hxi. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-09-06 15:41:22 +00:00
# homemaker-py-hxi (DESIGN.md §39.25): ENABLED. Fails a level that has no
# outdoor space at all -- Alexander's actual requirement, per level and with no
# quantity attached. It had been off in every corpus config, so the only thing
# expressing outdoor space was ratio_outside's arbitrary fraction.
force_roof_garden: 1
# Circulation ratio (penalise excessive corridors)
Remove ratio_circulation: the score is already a ratio Owner: "I think a corridor could be worth a sixth of a room, this is ok. maybe we should dump the ratio_circulation altogether if there is already a pressure in circulation caused by the cost benefit ratio per msq. this is the kind of thing we want to root out of the scoring model: anything that is double counting, or using a gaussian where a linear ramp is appropriate, etc." value_circulation = 50 stands; hxi's rate question is closed. The duplication argument is stronger than it first looks. score = value/cost is already a ratio, so the per-m2 economics (50 against a build cost of 200) is not merely an absolute pressure -- adding corridor moves value/cost by an amount that depends on how much of the building is already corridor. It is ALREADY proportional. ratio_circulation said the same thing again as a whole-building multiplier, on a curve where twice the corridor is far more than twice as bad. Correction to my own first measurement: I overrode ratio_circulation and got scores going DOWN when a <=1 multiplier was removed, which is impossible. All four corpus programmes DECLARE ratio_circulation, so the CONF_DEFAULTS value I had changed was never in play and the two arms differed only in sigma. Same trap as value_supported in 39.19. Against the keep-it case, recorded because it is the one real argument: three of four declare a POSITIVE target (harbor/maple 0.08, health-centre 0.10), making the term formally two-sided rather than "less is better". It does not survive the numbers -- the lower side is worth at most 13.3% on the large programmes against 99% on the upper side, and "a building needs some circulation" is enforced structurally by access and connectivity, which no amount of value can buy off. Disabled in CONF_DEFAULTS and the four corpus configs, each with the reason inline and a note that a [target, sigma] pair re-enables it. Fail sets unchanged; it was always a value multiplier. Scores +42% to +7712%. 39.24 also sweeps every remaining term against the owner's two tests. Verdicts: perpendicular, proportion, width, crinkliness, access, size's lower side, ratio_outside, staircase volume and the count/limit fails are all sound. Filed as homemaker-py-dpt: size's UPPER side (cost already charges area; 82% of size fails are over-target), the minimum-internal-area factor (a third statement of "build the rooms"), the 0.5**n_fails curve (a ruling, not a measurement), and two dead paths -- ratio_public/private_outside, which no config declares, and the daylight factor pinned to 1.0 since the descope. Also updated a test I added last turn which asserted ratio_circulation was the second charge; it now pins that the linear ramp is the ONLY one. 419 passed. Closes homemaker-py-hxi. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-09-06 15:28:33 +00:00
# homemaker-py-hxi (DESIGN.md §39.24): disabled. The score is value/cost, a
# ratio, so the per-m2 economics (circulation worth 50 against a build cost of
# 200) is ALREADY a proportional pressure against circulation -- this said the
# same thing a second time, and with a curve where twice the corridor is far
# more than twice as bad. Its other side, "a building needs some circulation",
# was worth at most 13% here and is enforced structurally anyway by the access
# and connectivity checks. Set a [target, sigma] pair to re-enable.
ratio_circulation:
# Outside space ratio
Outdoor space: enforce the per-level rule, drop the fraction Owner: "maybe plot_ratio is having unintended consequences, Alexander simply says that all levels should have accessible outside space, he doesn't say how much." Both halves are right, and the codebase had the two rules the wrong way round. ratio_outside is a gaussian on the outdoor FRACTION, applied as a whole-building multiplier, and its declared targets have no stated basis and contradict each other: health-centre targets 0.06 and sits at 0.096-0.129, so it is penalised x0.39-x0.77 for having too MUCH; programme-house targets 0.30 and sits at 0.098-0.293, penalised x0.40-x0.999 for having too LITTLE. Penalties as large as the ratio_circulation ones 39.24 removed, pulling two programmes in opposite directions on the same quantity. force_roof_garden already implements the rule Alexander actually states -- per level, no outdoor space at all is a hard fail, no quantity attached. It has existed all along and was switched OFF in every corpus config. Near-miss worth recording: measuring first, I found zero "no outside space" fails across the twelve baseline runs and briefly read that as the requirement being met everywhere. It meant the check never ran. Same shape as 39.20's parity tests -- no failures from a test that is not executing looks exactly like no failures from a test that passes, and the tell was again the config, not the code. Enabled, it bites on 4 of 25 baseline levels: maple s0 level 1, and programme-house level 0 in all three seeds. A house with no outdoor space on its own ground floor is a fair criticism of the layout, and exactly what a building-level fraction cannot catch, since 22% outdoor concentrated on one storey satisfies it perfectly. The upper side ratio_outside used to provide is covered in a better currency by the minimum-internal-area factor (internal area >= 1.2x the programme's declared room area), which is live -- binding on harbor s0 x0.920 and programme-house s0 x0.787. This is the one change in 39.22-39.25 whose risk is NOT measured: nothing here proves the outdoor fraction will not drift up once the search is free to raise it, and outdoor space is profitable (1.64 return against a room's 0.66). The re-baseline (bk9) is what shows it, and 39.25 asks for the fraction to be recorded there. 4 hard fails added, none removed. 426 passed. Refs homemaker-py-hxi. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-09-06 15:41:22 +00:00
# homemaker-py-hxi (DESIGN.md §39.25): disabled. Alexander says every level
# should have accessible outside space; he does not say how much. The
# qualitative requirement is force_roof_garden below. Set a [target, sigma]
# pair to re-enable this quantitative one.
ratio_outside:
# Staircase requirements
staircase_min: 1
staircase_max: 1
# Other standard parameters can be included
value_inside: 300.0
value_circulation: 50.0
value_outside: 100.0
A terrace is no longer worth more per m2 than a real internal room Owner's ruling. Measured over the twelve baseline layouts as realised value per m2 (rate x quality, not the rate alone): as shipped before this room 67.0 terrace 294.6 violates, 4.39x value_supported=100 only room 67.0 terrace 98.2 violates, 1.46x geometric mean only room 132.9 terrace 296.8 violates, 2.23x both room 132.9 terrace 98.9 satisfies The 4.4x is roughly 2.2x aggregation and 2.0x rate, so neither half alone is enough. That is why 39.18's geometric-mean aggregation moves from default-OFF to default-ON here rather than waiting on its own A/B: it is not an optional improvement, it is half of a ruling. value_supported 300 -> 100, and set to value_outside rather than to a number that makes the inequality come out -- back-solving from the corpus's measured mean room quality would rot the moment either changed. Outdoor space is worth the same to an occupant whatever level it sits on; the real difference between a ground garden and a roof terrace is what it takes to BUILD, and cost already says that (outside 10.0 vs outside_supported 110.0). Value describes worth, cost describes structure, and the level belongs in the second. Changed in CONF_DEFAULTS and the four corpus patterns.config files, which all declared 300.0 explicitly. NOT changed in harbor-house-l0 (a shape-curve test fixture) or y51-sweep-* (historical fixtures that exist to reproduce past measurements) -- repricing those would destroy what they are for. Neither change can move a fail, structurally rather than luckily: value rates never enter fail emission, and evaluate_leaf emits each fail from its factor before anything is combined. Verified corpus-wide: identical fail sets, scores +11% to +169% (and -5% once, on a layout that is mostly terrace). tests/test_terrace_value_ruling.py pins the ruling as an invariant of the objective, and asserts that reverting the aggregation breaks it again, so neither half can be quietly dropped. The 500k cold-start baseline (39.12) is superseded -- this changes what "good" means. The layouts stay valid and their fail counts are unchanged, but a fresh corpus run is needed before any new number is compared with them. Still untouched: circulation returns 0.07 per unit cost against a room's 0.66, by far the worst thing a building can contain. That is homemaker-py-hxi. Refs homemaker-py-ecx. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MJ84Feep79Hhm3E4zZJmnB
2026-09-05 19:25:02 +00:00
# homemaker-py-ecx (DESIGN.md §39.19): an upper-level terrace is worth what
# outdoor space is worth (value_outside); it is the COST that differs by level
# (outside 10.0 vs outside_supported 110.0), not the value. At 300.0 -- the
# `value_inside` rate -- a terrace was worth more per square metre than a real
# internal room, which the owner ruled out.
value_supported: 100.0