generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives)#1611
Conversation
…uty-floor lesson Structurally-honest cycle-2 plates paneled 6-vs-9 OUT OF BAND 2/2 with a unanimous scorer critique: 'clean but generic — no narrative focal point, empty floor, asset-kit clutter'. The geometry-richness principle (CRYPT-REPLICATE, snug c3) says the lever is GEOMETRY, not prompt. dress_focal gives every generated room ONE deterministic focal set by door count: 1 door -> ALTAR + 2 flanking BRAZIERS (sealed shrine-store); 2 doors -> 2 BRAZIERS flanking the lane; 3+ -> 2 BRAZIERS at the crossing. Fire doubles as the paint's warm-core chiaroscuro anchor and the runtime's VFX anchor. Runs BEFORE dress_tall_anchors; same landing/connectivity safety machinery; self-gate still enforces. Anchor test relaxed to >=1 pillar (focal occupancy can leave one connectivity-safe pair; one tall mass clears the flat-interior bar).
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 21 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
evaOS review status: completedPR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives) evaOS review completed for this PR head. Automation note: agents should wait for this comment to reach PR URL: #1611 Review URL: #1611 (review) |
There was a problem hiding this comment.
Walkthrough
PR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives)
Head: 4f923bedfacf595607cfee69c7fe68e9a334522e into main. Review event: COMMENT.
Provider: GLM/Z.ai through ZCode (zcode-glm, zcode, model GLM-5.2).
Estimated review effort: 1/5 (~12 min)
Changed Files
| File | Status | Churn | Purpose | Risk |
|---|---|---|---|---|
qa/test_generate_town.py |
modified | +23/-5 | Test coverage | Moderate: validated P3 finding |
Review Signal
Validated inline findings: 2 (P0: 0, P1: 0, P2: 0, P3: 2).
Dropped findings before posting: 0. High-severity findings: 0.
Risk Taxonomy
- Docs only: 1
- Proof gap: 1
Validation and Proof
1 required validation/proof recommendation(s) selected from changed files.
- required: Unity editor or Play Mode smoke - WorldOS repo profile implies Unity runtime risk. Proof: Unity editor smoke; Play Mode log; scene/prefab screenshot or recording.
Proof status: missing - 1 required validation/proof recommendation(s) missing from PR metadata.
Profile validation hints: Prefer correctness, persistence, CI, release, and regression findings over style-only feedback.
Profile proof expectations: Look for Unity editor, play-mode, fixture, or focused smoke evidence when runtime behavior changes.
Related Context
Related issues/PRs: none detected from PR metadata.
Suggested labels: tests.
Suggested reviewers: none from current metadata.
Review Settings Preview
- Profile: assertive
- Enabled sections: Review summary (inline_review); Walkthrough (inline_review); Changed-files table (walkthrough); Effort estimate (walkthrough); Related issues/PRs (walkthrough); Suggested labels (suggestion_only); Review status comment (sticky_status)
- Path instructions:
Assets/**- Prioritize scene, prefab, save-state, asset-reference, and gameplay regressions. - Path instructions:
ProjectSettings/**- Treat build, platform, input, graphics, and release behavior changes as high risk. - Label suggestions: unity, gameplay, regression-hardening
- Reviewer suggestions: none
- Suggestion behavior: suggestions only; labels and reviewers are not auto-applied.
- Roadmap-only settings: auto-apply labels; auto-request reviewers; required status checks
Pre-merge checklist
- Inline comments target current RIGHT-side diff lines.
- No secret-like content survived into posted inline comments.
- REQUEST_CHANGES is only used when eligible P0/P1 findings survive validation.
- Required behavior proof is present or not applicable.
- Labels and reviewers are suggestions only; the bot did not auto-apply them.
| focal_cells = {tuple(c) for p in geo["props"] if p["kind"] in d2f._FOCAL_KINDS | ||
| for c in p["cells"]} | ||
| assert not (focal_cells & landings), f"{rid}: focal on a door landing" | ||
| assert check_geometry(rid, geo) == [], f"{rid}: static gate regressed after focal dressing" |
There was a problem hiding this comment.
P3: check_geometry name arg uses rid while sibling tests use f"{town}_{rid}"
test_every_generated_room_has_a_narrative_focal calls check_geometry(rid, geo) whereas test_committed_rooms_pass_static_gate uses check_geometry(f"{TOWN}{rid}", geo). The first argument to check_geometry is only a label (used inside failure strings), so behavior is identical, but the inconsistency makes the static-gate signal harder to grep/correlate across failures and breaks the local convention. Use f"{TOWN}{rid}" here for consistency.
Category: Docs only
Why this matters: Minor, but consistency in the gate label aids triage when the same geometry fails in two tests and reviewers correlate by the documented dwing_ id.
There was a problem hiding this comment.
Adopted — the focal test now labels with f"{_TOWN}_{rid}" matching the sibling tests.
🤖 Addressed by Claude Code
| for rid in ("room_0", "room_1"): | ||
| anchors = [p for p in town[rid]["props"] if p.get("id") in ("anchor_a", "anchor_b")] | ||
| assert {p["id"] for p in anchors} == {"anchor_a", "anchor_b"}, f"{rid} needs both anchors" | ||
| assert anchors, f"{rid} needs at least one pillar anchor" |
There was a problem hiding this comment.
P3: Anchor assertion weakened without a paired test pinning focal-placement success
test_flat_rooms_get_pillar_anchors was lowered from 'both anchor_a and anchor_b present' to 'at least one pillar anchor'. The new comment attributes this to focal dressing (brazier/altar) consuming connectivity-safe interior space. That causal link is plausible (dress_focal runs first and uses the same flood-fill gate), but there is no test that actually pins the focal pass succeeding, nor one that asserts the focal-vs-anchor floor budget directly. If a future layout or dress_focal change makes the focal consume MORE floor, the anchor count could silently drop from 1 to 0 and this weakened assertion would still pass while a flat-interior room regresses. Consider either (a) asserting a lower bound that encodes the intended budget (e.g. at least one anchor AND at least one focal), or (b) adding a dedicated test that dress_focal + dress_tall_anchors together still leave >=1 anchor on the committed rooms — making the weakening's premise observable rather than asserted in a comment.
Category: Proof gap
Why this matters: The PR's central behavior change is focal-first dressing that competes with anchor placement for the same interior floor; the suite now only asserts a loose lower bound on the loser of that competition, so the interaction it introduces is effectively untested for regression.
There was a problem hiding this comment.
Partially adopted. Note the joint coverage that already existed: anchors→0 FAILS both test_flat_rooms_get_pillar_anchors (asserts non-empty) and test_every_room_has_a_tall_prop (asserts a ≥2.6 mass in EVERY room) — only 2→1 was tolerated, deliberately. The deeper budget concern is now enforced at EMIT time, not just on the committed fixture: check_dressing_bars() folds tall-mass + focal presence into generate_town's self-gate (fails loud; --allow-undressed escape), with a dedicated unit.
🤖 Addressed by Claude Code
…-4 catch) Ortho-only pins were the 2026-07-15 camera-bug SHAPE. The #1591 client fix defaults the 30/45 contract rig when only ortho is pinned, so they're no longer dangerous — but every shipped manifest entry carries pitch/yaw explicitly and walk_static lints them when present; the emitter now matches the convention. + fragment test (10/10).
|
Round-4 sidecar catch folded in: the plates-fragment emitter stamped ortho-only cameraPins (the 2026-07-15 bug shape — safe since #1591's client default, but off-convention). Now stamps pitch/yaw + a fragment regression test. 10/10. |
evaOS review status: failedPR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives) evaOS review failed for this head and needs retry or operator attention. Automation note: agents should wait for this comment to reach PR URL: #1611 Details: Review failed; see bot evidence for operator-only details. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4f923bedfa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for rid in room_ids: | ||
| geo = _stamp_room(build_geometry(ctx, room=rid), | ||
| material=args.material, wall_height=args.wall_height) | ||
| geo = dress_focal(geo, name=loc_of[rid]) # narrative focal set FIRST (an altar also satisfies the tall-anchor bar) |
There was a problem hiding this comment.
Reserve tall-anchor space before focal dressing
In narrow flat crops (for example a one-cell-wide 3×6 room with a single perimeter door), adding the low brazier/altar focal props before dress_tall_anchors can occupy the only connectivity-safe vertical pair that the anchor pass would have used. Since those focal kinds are below _ANCHOR_MIN_TALL, the generator can now emit a static-green room with no tall interior mass, reintroducing the flat-interior drift class this path was meant to prevent; run/place tall anchors first or have focal placement reserve a valid anchor footprint.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Adopted via emit-time enforcement rather than reordering: placing anchors first would just flip the failure mode onto the focal pass (braziers/altar are LOW kinds, 2.0–2.2 — they never satisfy the tall bar; also corrected a wrong comment claiming otherwise). check_dressing_bars() now makes the generator FAIL LOUD when a crop leaves NO connectivity-safe tall footprint, so the flat-interior class can't ship silently; the operator/loop then treats that crop deliberately.
🤖 Addressed by Claude Code
| geo["props"].append({"id": pid, "kind": kind, "cells": [list(c) for c in cells]}) | ||
| used |= set(cells) | ||
| break | ||
| if used: |
There was a problem hiding this comment.
Fail when no focal can be placed
For small or densely occupied room crops where every connectivity-safe candidate is rejected (e.g. a 3×3 one-door crop whose only interior cell is the door landing), used stays empty and this function returns successfully without adding any _FOCAL_KINDS. generate_town then still passes the static gate and writes a room with no narrative focal point, so the new beauty-floor guarantee is silently skipped instead of failing or using a fallback placement.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Adopted — same mechanism: check_dressing_bars() in the self-gate fails loud when no _FOCAL_KINDS prop landed (the silent-return case you found), unit-tested on a crafted bare crop. --allow-undressed is the documented escape for genuinely bare classes.
🤖 Addressed by Claude Code
… consistency (evaos P3) check_dressing_bars(): emit-time enforcement that every generated room carries (1) a tall interior mass >= 2.6 (a narrow crop can defeat dress_tall_anchors AFTER focal placement) and (2) a narrative focal prop (dress_focal returns silently when every candidate is rejected). Either silent miss re-ships the class the dressing exists to fix -> the generator fails LOUD; --allow-undressed is the deliberate escape hatch (e.g. a bare corridor class). Also corrected a wrong code comment (altar is 2.0 < the 2.6 tall bar). 11/11 + end-to-end self-gate green on the committed wing.
evaOS review status: completedPR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives) evaOS review completed for this PR head. Automation note: agents should wait for this comment to reach PR URL: #1611 Review URL: #1611 (review) |
There was a problem hiding this comment.
Walkthrough
PR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives)
Head: 249b2bd8b60d73226d18ccb3d71956965c9c4909 into main. Review event: COMMENT.
Provider: GLM/Z.ai through ZCode (zcode-glm, zcode, model GLM-5.2).
Estimated review effort: 1/5 (~12 min)
Changed Files
| File | Status | Churn | Purpose | Risk |
|---|---|---|---|---|
qa/test_generate_town.py |
modified | +61/-5 | Test coverage | Moderate: validated P2 finding |
Review Signal
Validated inline findings: 2 (P0: 0, P1: 0, P2: 1, P3: 1).
Dropped findings before posting: 0. High-severity findings: 0.
Risk Taxonomy
- API compatibility: 1
- CI/build: 1
Validation and Proof
1 required validation/proof recommendation(s) selected from changed files.
- required: Unity editor or Play Mode smoke - WorldOS repo profile implies Unity runtime risk. Proof: Unity editor smoke; Play Mode log; scene/prefab screenshot or recording.
Proof status: missing - 1 required validation/proof recommendation(s) missing from PR metadata.
Profile validation hints: Prefer correctness, persistence, CI, release, and regression findings over style-only feedback.
Profile proof expectations: Look for Unity editor, play-mode, fixture, or focused smoke evidence when runtime behavior changes.
Related Context
Related issues/PRs: none detected from PR metadata.
Suggested labels: tests.
Suggested reviewers: none from current metadata.
Review Settings Preview
- Profile: assertive
- Enabled sections: Review summary (inline_review); Walkthrough (inline_review); Changed-files table (walkthrough); Effort estimate (walkthrough); Related issues/PRs (walkthrough); Suggested labels (suggestion_only); Review status comment (sticky_status)
- Path instructions:
Assets/**- Prioritize scene, prefab, save-state, asset-reference, and gameplay regressions. - Path instructions:
ProjectSettings/**- Treat build, platform, input, graphics, and release behavior changes as high risk. - Label suggestions: unity, gameplay, regression-hardening
- Reviewer suggestions: none
- Suggestion behavior: suggestions only; labels and reviewers are not auto-applied.
- Roadmap-only settings: auto-apply labels; auto-request reviewers; required status checks
Pre-merge checklist
- Inline comments target current RIGHT-side diff lines.
- No secret-like content survived into posted inline comments.
- REQUEST_CHANGES is only used when eligible P0/P1 findings survive validation.
- Required behavior proof is present or not applicable.
- Labels and reviewers are suggestions only; the bot did not auto-apply them.
| [sys.executable, str(_ROOT / "tools" / "generate_town.py"), str(_LAYOUT), | ||
| "--rooms", "room_0", "--town-id", "pin", "--out-dir", str(out), "--material", "stone"], | ||
| capture_output=True, text=True) | ||
| assert r.returncode == 0, r.stderr[-500:] |
There was a problem hiding this comment.
P2: Subprocess cameraPin test omits the PIL importorskip guard the sibling test uses for the same reason
test_plates_fragment_pins_carry_the_full_camera_contract shells out to tools/generate_town.py, which imports greybox_render_headless at module top-level (qa/greybox_render_headless.py:45 from PIL import Image, ImageDraw), so importing generate_town.py hard-requires PIL. The sibling test_generator_self_gate_passes calls pytest.importorskip("PIL") (line 169) for exactly this case, with the comment 'skip the end-to-end run where those render deps are absent (e.g. the minimal engine test venv)'. This new test omits that guard. In the minimal engine/servers test venv (PIL/numpy absent — the environment the sibling test explicitly anticipates), the subprocess crashes at import with ModuleNotFoundError, r.stderr[-500:] is non-empty, and the test FAILS (not skips) with an opaque traceback. Add pytest.importorskip("PIL") at the top of this test, mirroring line 169, so it skips cleanly where render deps are unavailable.
Category: CI/build
Why this matters: A test that errors instead of skipping in the documented minimal venv turns a green CI lane red for a non-defect, and the failure message (an ImportError buried in subprocess stderr) does not point at the real cause. The PR already establishes the correct pattern one test above; this is an inconsistency with a concrete CI-breaking footprint.
There was a problem hiding this comment.
Adopted — pytest.importorskip("PIL") added at the top of the fragment-pin test, mirroring test_generator_self_gate_passes' guard for the same subprocess in the minimal engine venv.
🤖 Addressed by Claude Code
| for rid in ("room_0", "room_1"): | ||
| anchors = [p for p in town[rid]["props"] if p.get("id") in ("anchor_a", "anchor_b")] | ||
| assert {p["id"] for p in anchors} == {"anchor_a", "anchor_b"}, f"{rid} needs both anchors" | ||
| assert anchors, f"{rid} needs at least one pillar anchor" |
There was a problem hiding this comment.
P3: Flat-room anchor assertion weakened from 'both anchors' to 'at least one'
test_flat_rooms_get_two_pillar_anchors was renamed and its contract weakened: it previously asserted {anchor_a, anchor_b} == {anchor_a, anchor_b} (both pillars present), now it asserts only anchors is truthy (≥1). The production contract in dress_tall_anchors' docstring still says it 'authors two pillar anchors (anchor_a/anchor_b)'. The weakening is justified in-comment (focal placement can consume the second connectivity-safe pair), and the new check_dressing_bars self-gate plus test_every_room_has_a_tall_prop still cover the flat-interior bar. But the renamed test no longer pins the two-anchor authoring contract; if dress_tall_anchors regressed to emitting a single anchor even when two would fit, this test would not catch it. Consider asserting len(anchors) >= 1 explicitly and adding a comment that the ≥2 case is best-effort under focal occupancy, or keep a separate test on a no-focal fixture that still expects both.
Category: API compatibility
Why this matters: Coverage assertions that name a contract ('two pillar anchors') and then silently drop to 'at least one' reduce the regression surface the suite was added to lock down. This is advisory: the underlying flat-interior bar is still enforced elsewhere.
There was a problem hiding this comment.
Adopted in the advisory form: the assertion is now an explicit len(anchors) >= 1 with an in-test rationale — ≥1 is the HARD flat-interior bar (also enforced end-to-end by check_dressing_bars + test_every_room_has_a_tall_prop), while two anchors is documented best-effort under focal occupancy (dress_focal runs first and may legitimately consume the second connectivity-safe pair, so pinning ==2 would flake on valid layouts).
🤖 Addressed by Claude Code
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 249b2bd8b6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| r = subprocess.run( | ||
| [sys.executable, str(_ROOT / "tools" / "generate_town.py"), str(_LAYOUT), | ||
| "--rooms", "room_0", "--town-id", "pin", "--out-dir", str(out), "--material", "stone"], | ||
| capture_output=True, text=True) | ||
| assert r.returncode == 0, r.stderr[-500:] |
There was a problem hiding this comment.
Skip the camera-pin subprocess when Pillow is absent
In environments without Pillow, this new test fails before it can inspect the generated fragment because generate_town.py imports greybox_render_headless, which imports PIL; the nearby test_generator_self_gate_passes already guards the same subprocess with pytest.importorskip("PIL") for the minimal engine/test venv case. Running python -m pytest qa/test_generate_town.py -q in that environment now goes red with ModuleNotFoundError: No module named 'PIL', so this test should use the same skip or avoid the Pillow-dependent script import.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Adopted — same fix as the evaOS twin thread: importorskip("PIL") guards the subprocess, so the minimal venv skips cleanly instead of failing on ModuleNotFoundError.
🤖 Addressed by Claude Code
…dex P2 — minimal-venv lane went red on a non-defect) + explicit >=1 anchor bar with the best-effort-two rationale (evaOS P3)
evaOS review status: completedPR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives) evaOS review completed for this PR head. Automation note: agents should wait for this comment to reach PR URL: #1611 Review URL: #1611 (review) |
There was a problem hiding this comment.
Walkthrough
PR: #1611 - generate_town: narrative FOCAL dressing (beauty-floor lever from the dwing panel negatives)
Head: 92124797e060386171a3e9dc5f2d9cac40866a02 into main. Review event: COMMENT.
Provider: GLM/Z.ai through ZCode (zcode-glm, zcode, model GLM-5.2).
Estimated review effort: 1/5 (~12 min)
Changed Files
| File | Status | Churn | Purpose | Risk |
|---|---|---|---|---|
qa/test_generate_town.py |
modified | +67/-5 | Test coverage | Moderate: validated P3 finding |
Review Signal
Validated inline findings: 2 (P0: 0, P1: 0, P2: 0, P3: 2).
Dropped findings before posting: 0. High-severity findings: 0.
Risk Taxonomy
- Flaky test risk: 1
- Release regression: 1
Validation and Proof
1 required validation/proof recommendation(s) selected from changed files.
- required: Unity editor or Play Mode smoke - WorldOS repo profile implies Unity runtime risk. Proof: Unity editor smoke; Play Mode log; scene/prefab screenshot or recording.
Proof status: missing - 1 required validation/proof recommendation(s) missing from PR metadata.
Profile validation hints: Prefer correctness, persistence, CI, release, and regression findings over style-only feedback.
Profile proof expectations: Look for Unity editor, play-mode, fixture, or focused smoke evidence when runtime behavior changes.
Related Context
Related issues/PRs: none detected from PR metadata.
Suggested labels: tests.
Suggested reviewers: none from current metadata.
Review Settings Preview
- Profile: assertive
- Enabled sections: Review summary (inline_review); Walkthrough (inline_review); Changed-files table (walkthrough); Effort estimate (walkthrough); Related issues/PRs (walkthrough); Suggested labels (suggestion_only); Review status comment (sticky_status)
- Path instructions:
Assets/**- Prioritize scene, prefab, save-state, asset-reference, and gameplay regressions. - Path instructions:
ProjectSettings/**- Treat build, platform, input, graphics, and release behavior changes as high risk. - Label suggestions: unity, gameplay, regression-hardening
- Reviewer suggestions: none
- Suggestion behavior: suggestions only; labels and reviewers are not auto-applied.
- Roadmap-only settings: auto-apply labels; auto-request reviewers; required status checks
Pre-merge checklist
- Inline comments target current RIGHT-side diff lines.
- No secret-like content survived into posted inline comments.
- REQUEST_CHANGES is only used when eligible P0/P1 findings survive validation.
- Required behavior proof is present or not applicable.
- Labels and reviewers are suggestions only; the bot did not auto-apply them.
| base = {"cols": 5, "rows": 5, "door_cells": [[0, 2]], "walls": [], | ||
| "props": [{"id": "w", "kind": "wall_run", "cells": [[0, 0]]}]} | ||
| both_missing = d2f.check_dressing_bars(dict(base, props=list(base["props"])), name="bare") | ||
| assert len(both_missing) == 2 and any("tall" in f for f in both_missing) and any("focal" in f for f in both_missing) |
There was a problem hiding this comment.
P3: Compound single-line assertion is hard to read and gives a poor failure message
Line 227 crams two any(...) substring checks and a length check into one assert ... and ... and ... on a single line. When this fails, pytest reports the whole boolean expression with no indication of which clause failed or the actual both_missing contents. Splitting into three separate asserts (length == 2; a 'tall' failure present; a 'focal' failure present) preserves intent and makes a future regression message immediately diagnostic. Purely a clarity/observability nit; behavior is correct as written (the 'NO tall interior mass' and 'NO narrative focal prop' substrings are both emitted by check_dressing_bars).
Category: Flaky test risk
Why this matters: This test is the emit-time enforcement guard for the codex P2 pair; when it fires in CI it should pinpoint which bar regressed without a maintainer having to re-run with prints.
| # test_every_room_has_a_tall_prop enforce it end-to-end). Two anchors is BEST-EFFORT under | ||
| # focal occupancy: dress_focal runs first and may consume the second connectivity-safe pair, | ||
| # so pinning ==2 here would make the suite flake on legitimate focal layouts (evaOS P3). | ||
| assert len(anchors) >= 1, f"{rid} needs at least one pillar anchor" |
There was a problem hiding this comment.
P3: Anchor-count assertion weakened from exactly-two to at-least-one; rationale mislabels deterministic behavior as 'flake'
The renamed test relaxes assert {p['id'] for p in anchors} == {'anchor_a','anchor_b'} to assert len(anchors) >= 1. The accompanying comment (lines 110-113) justifies this by claiming that pinning ==2 'would make the suite flake on legitimate focal layouts.' That rationale does not hold: _build_town_geometries (and dress_focal/dress_tall_anchors) are fully deterministic — no random module, fixed committed layout — so the post-dressing anchor count is a single fixed integer per room, not a distribution. Pinning the exact count would either always pass (proving the suite reliably yields two anchors) or always fail (surfacing a genuine placement regression introduced by running dress_focal first). The >= 1 bar therefore hides whether the focal-first ordering actually dropped room_0/room_1 from two anchors to one on this layout. The functional flat-interior bar is still enforced elsewhere (test_every_room_has_a_tall_prop + check_dressing_bars), so this is a test-strength gap, not a product regression. Recommendation: after merging, run the suite once and pin the actual emitted count per room (e.g. assert len(anchors) == N with the observed N, or assert the specific id set), and rewrite the comment to say 'deterministic count pinned to the observed post-focal value' rather than 'flake'.
Category: Release regression
Why this matters: A deterministic regression suite that asserts a weaker invariant than the code intends will silently accept a future change that drops the second anchor (the documented 'two pillar anchors' contract in dress_tall_anchors' docstring and the original #1588 fix), eroding the regression guard without any signal.
…geometry bar, #1618) The dwing recovery proved the focal braziers double as plate-registration beacons. Two braziers on the same row are a collinear pair, blind to vertical scale in the 2-point similarity fit (room_1: 0.07-cell beacon error beside ~1.5 cells of wall misfit — plate unfixable by warping). dress_focal v2: after the door-count plan lands its two lane/shrine braziers, author a THIRD fire beacon (corner watch-brazier) at the connectivity-safe cell that maximises the three-beacon triangle area — deterministic, reusing the existing candidate/landing-exclusion/flood-fill machinery. check_dressing_bars gains a third bar: >=3 fire-kind props with best triangle area >= 2.0 cell^2, or fail loud (beacon-geometry class). --allow-undressed still skips all bars. Tests: every committed wing room now carries 3 fire beacons (areas 12/5/11); the bar unit-tested on 2-fire, 3-collinear, 3-non-collinear geos; existing dressing-bar test updated for the third bar. Refs #1618 (lands after #1611).
…geometry bar, #1618) (#1621) The dwing recovery proved the focal braziers double as plate-registration beacons. Two braziers on the same row are a collinear pair, blind to vertical scale in the 2-point similarity fit (room_1: 0.07-cell beacon error beside ~1.5 cells of wall misfit — plate unfixable by warping). dress_focal v2: after the door-count plan lands its two lane/shrine braziers, author a THIRD fire beacon (corner watch-brazier) at the connectivity-safe cell that maximises the three-beacon triangle area — deterministic, reusing the existing candidate/landing-exclusion/flood-fill machinery. check_dressing_bars gains a third bar: >=3 fire-kind props with best triangle area >= 2.0 cell^2, or fail loud (beacon-geometry class). --allow-undressed still skips all bars. Tests: every committed wing room now carries 3 fire beacons (areas 12/5/11); the bar unit-tested on 2-fire, 3-collinear, 3-non-collinear geos; existing dressing-bar test updated for the third bar. Refs #1618 (lands after #1611). Co-authored-by: Eva <arncalso@gmail.com>
Cycle-2 of the generated dungeon wing produced STRUCTURALLY HONEST plates (the count/shape/door-wall
locks from the same cycle killed the Gemini feature-multiplication + reshape classes) — and the blind
control-anchored panels still returned 6-vs-9, Δ−3.0 OUT OF BAND, 2/2, with a unanimous critique:
"clean but generic — boxy symmetric composition, generic asset-kit clutter, empty floor, no narrative
focal point". Per the geometry-richness principle (CRYPT-REPLICATE; the snug c3 +1-median geometry
lever), the fix belongs in the GENERATOR, not the prompt.
dress_focal(tools/dungen_to_fixtures.py) gives every generated room one deterministic narrativefocal set chosen by door count: dead-end → ALTAR flanked by two BRAZIERS; through-room → two BRAZIERS
flanking the lane; hub → two BRAZIERS at the crossing. Fire also hands the paint stage its warm-core
chiaroscuro anchor (the panel's own lever) and the runtime its animated-VFX anchor. It runs BEFORE
dress_tall_anchors (an altar can satisfy the tall-mass bar) and reuses the same safety machinery:
deterministic candidates, door/landing/adjacency exclusion, flood-fill connectivity verification, and
the generator self-gate re-checks every room.
Wing regeneration: room_0 = altar + 2 braziers + 2 pillars; room_1 = 2 braziers + pillar; room_2 =
2 braziers + native pillar — all three
check_geometryGREEN. Tests: new focal unit (presence, off-landing, gate-green) + the anchor test relaxed to ≥1 pillar (focal occupancy can leave one
connectivity-safe pair; one tall mass clears the flat-interior bar). 9/9 + walk_static suite green.