Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f7ad8de
fix(placement-plan): check the exit inventory and refuse failed place…
zoeyrose Oct 18, 2026
e36e51e
fix(placement-plan): verify every exit record field and data problem
zoeyrose Oct 18, 2026
808ea4a
fix(placement-plan): require a valid main connection for each placement
zoeyrose Oct 18, 2026
a1f5c17
fix(placement-plan): re-derive exit data problems from the inventory
zoeyrose Oct 18, 2026
0006dd7
fix(placement-plan): re-derive stairwell, site and placement metadata
zoeyrose Oct 18, 2026
9bc81aa
fix(placement-plan): bound targets, bends and the overworld map count
zoeyrose Oct 18, 2026
444de71
fix(placement-plan): require unique identities and hint-only exemptions
zoeyrose Oct 18, 2026
763010c
fix(placement-plan): validate source values and structure alignment h…
zoeyrose Oct 18, 2026
e91d40d
feat(placement-plan): check published artifacts against the content
zoeyrose Oct 18, 2026
3cdf8cd
fix(placement-plan): enforce search limits and alignment references
zoeyrose Oct 18, 2026
ea8907e
fix(placement-plan): require applied alignments and the 24-tile grid
zoeyrose Oct 18, 2026
5f5d85f
fix(placement-plan): bound wired targets, slots, reasons and --check
zoeyrose Oct 18, 2026
64dde92
fix(placement-plan): type-check the inventory and bound --check entries
zoeyrose Oct 18, 2026
63a5fd6
feat(placement-plan): verify the plan against a rebuild from the content
zoeyrose Oct 18, 2026
791b2c0
fix(placement-plan): keep bytecode caches out of the source tree
zoeyrose Oct 18, 2026
cc94be1
fix(placement-plan): guard malformed plans, bump the schema, run test…
zoeyrose Oct 18, 2026
85ed583
fix(placement-plan): keep the plan's numbers integers and bound compa…
zoeyrose Oct 18, 2026
24e1329
test(placement-plan): run the verifier tests in parallel workers
zoeyrose Oct 19, 2026
3d04cb7
perf(placement-plan): stop re-deriving the same relayering in every c…
zoeyrose Oct 19, 2026
7564152
fix(placement-plan): count wired crossing stairs from the records
zoeyrose Oct 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions migration/placement-plan/REPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Version 2 applies the owner's decisions of 2026-10-18 on top of version 1 (PR #4
- Placement changes from version 1: `ellamin` layer offset -4 -> -5; `rockforge_a` layer offset -4 -> -5; `rockforge_b` layer offset -5 -> -6; `rockforge_c` layer offset -6 -> -7.
- Why portals remain: 17 other-entrance-aligned; 1 slope-blocked; 1 stairwell-blocked. See [Portals that remain](#portals-that-remain).
- View radius: **16 tiles** (the classic server's limit; the shipped client sees 10). With radius 10 the plan would have 65 stairs, 48 stairwell exits and 19 portals; see [View radius](#view-radius).
- Independent check (`scripts/verify_plan.py`, JSON only): **PASS**: 207 placed member maps, 7 nearby owner pairs measured (closest unrelated pair 22 tiles apart, gap rule needs more than 16), 40 stairwells with 76 intermediate tiles, 1456 exit endpoints re-derived; relayering re-derived from 242,824 overworld tiles and 82,133 tile heights (12 regions, 243 units, 47,594 moved tiles, 904 cut edges in 44 seam pieces).
- Independent check (`scripts/verify_plan.py`, JSON only): **PASS**: 207 placed member maps, 7 nearby owner pairs measured (closest unrelated pair 22 tiles apart, gap rule needs more than 16), 40 stairwells with 76 intermediate tiles, 1,007 exit record copies matched against the inventory of 1,200 exit objects, 1456 exit endpoints re-derived; relayering re-derived from 242,824 overworld tiles and 82,133 tile heights (12 regions, 243 units, 47,594 moved tiles, 904 cut edges in 44 seam pieces).

| classification | reason | groups | maps |
|---|---|---:|---:|
Expand Down Expand Up @@ -881,10 +881,12 @@ Each image covers its regions and every storey or cave unit that moved because o
```sh
cd migration/placement-plan
python3 -I scripts/build_plan.py --content /home/zoey/dev/worktrees/content-plan-v2-input --out .
python3 -I scripts/verify_plan.py placement-plan.json
python3 -I scripts/verify_plan.py placement-plan.json --content /home/zoey/dev/worktrees/content-plan-v2-input
python3 -I scripts/test_placement_plan.py
python3 -I scripts/build_plan.py --content /home/zoey/dev/worktrees/content-plan-v2-input --out . --check
```

`--content` must be a clean checkout of `atrinik/content` at `3ad20150da76` (the shared checkout was behind `main`, so this run used a separate clone at the current `main`). The scripts need only the Python standard library (the PNGs are written by `raster.py`). The content checkout must be clean under `arch/` and `maps/` (`--allow-dirty` is for experiments and marks the JSON). Artifacts are generated in a staging directory, the staged JSON is verified again, and only then are `placement-plan.json`, `REPORT.md` and the PNGs replaced; a failed run leaves the old artifacts in place.
`--content` must be a clean checkout of `atrinik/content` at `3ad20150da76` (the shared checkout was behind `main`, so this run used a separate clone at the current `main`). The scripts need only the Python standard library (the PNGs are written by `raster.py`). The content checkout must be clean under `arch/` and `maps/` (`--allow-dirty` is for experiments and marks the JSON). Artifacts are generated in a staging directory, the staged JSON is verified again, and only then are `placement-plan.json`, `REPORT.md` and the PNGs replaced; a failed run leaves the old artifacts in place. A group that cannot be placed stays unplaced and fails verification, so such a plan is never published. `test_placement_plan.py` tampers with copies of the committed JSON and checks that the verifier rejects each one; it needs no content checkout. `verify_plan.py` makes two checks. Without `--content` it re-derives the placement rules from the JSON alone. With `--content` it also rebuilds the plan from the content with the generator and requires the published JSON to equal the rebuild field for field (the checkout path aside), so an edit that keeps the JSON consistent with itself (an exit dropped from `exit_inventory` together with its count, say) fails there. `build_plan.py --check` regenerates every artifact in a temporary directory and fails unless each is byte-identical (run it with the `--content` path the plan records).

The run is deterministic (sorted inputs, lexicographic tie-breaks) and read-only against the content checkout; rerunning with the same arguments on the same content rewrites `placement-plan.json`, `REPORT.md` and the PNGs byte-for-byte. `content_git_head`, `content_worktree_clean` and `content_inputs_digest` (SHA-256 over every file under `arch/` and `maps/`, checked again after the run) in the JSON identify the input. Scripts: `mapdata.py` (read-only reader, tile links, occupied tiles, floors per sub-layer, `no_pass` tiles), `analysis.py` (components, layout, exit resolution), `relayer.py` (the relayering: regions, units, conflicts, seams), `footprint.py` (gap rule, column and sloped stairwell chains), `build_plan.py` (classification, relayering, placement, stairwells, wiring, JSON, staged publication), `report.py`, `render.py` and `raster.py` (images), and `verify_plan.py` (independent check of the JSON). Tunables (`VIEW_RADIUS`, `CONTACT_MARGIN`, `MAX_EXTRA_LAYERS`, `MAX_SHIFT`, `STAIR_TOLERANCE`, `STAIRWELL_MAX_BEND`, `LAYER_HEIGHT_Z` in `build_plan.py`; `MIN_REGION_TILES`, `WALKABLE_DZ`, `SEAM_CELL` in `relayer.py`) and the hand-written inputs (system maps, owner decisions, the Rockforge mines alignment hint, version 1's placements for the comparison) are constants.

Expand Down
Loading
Loading