PROCITY/web/js/citygen/index.js
m3ultra dab5ecd273 Lane A R40 §40.2: D1-D4 settled — the poster that stood in the road, and no silent carry
D4 CLOSED with a fix: 8/108 gig plans placed a spine poster inside a NON-nearest edge's
carriageway (worst 1.78m inside a main, northbridge seed 42, behind a kerbless arcade at
1.45m) — the exact filing, reproduced before touching anything. gigs.js onCarriageway now
tests inside-ANY-edge; selfcheck's poster arm asserts minimum clearance over ALL edges.
After: 0/108. Poster counts 0 diffs across all 108 plans; synthetic byte-identical.
The 7 REAL_TOWN_GIG_GOLDENS re-pinned (D4 explicitly required it; old hashes in comments).

D1 A-side CLOSED: chunkIndexByCoverage is canonical (chunkIndex kept as verified alias);
the naive swap would multi-build 258/681 lots — measured, documented in CITY_SPEC.
D2 RE-FILED to F (isOpen still 0 importers; divergent predicate at index.html:541).
D3 RE-FILED to B (SHOP_REGISTRY missing pub/band_room/rsl; 81 venue lots wear op-shop
signage; bite drifted to buildings.js:465). Both re-filings carry numbers and a reason.

selfcheck ALL GREEN 157,647/157,647; fingerprint 0x5f76e76 and GIG_GOLDEN frozen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 12:27:51 +10:00

45 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// PROCITY citygen — canonical Lane A public entry point (barrel).
//
// Consumers import the whole CityGen API from here (not from plan.js directly), e.g. Lane B's shell:
// const citygen = await import('./js/citygen/index.js'); citygen.generatePlan(seed) → CityPlan
// Keep this the stable import surface for the lane; internals may move between files behind it.
//
// (Originated as a Lane F integration shim because the shell imports ./js/citygen/index.js while the
// generator ships as plan.js; adopted here as the real Lane A entry point, per the shim's own note.)
// R40 (§40.2 D1): `chunkIndexByCoverage` is the canonical name — AABB-coverage bucketing, plain-object
// container, id elements; answers "which cells does this thing touch?". It is NOT shape-compatible with
// Lane B's runtime `world/planutil.js chunkIndex(plan)` (centre-cell / Map / objects — the streamer's
// question). `chunkIndex` remains as a compat alias of the coverage form for existing importers.
export { generatePlan, chunkIndexByCoverage, chunkIndex, chunkKey, CHUNK, lotCorners, obbOverlap, isOpen } from './plan.js';
export { shopName, townName, bandName } from './names.js';
export { generatePlanOSM, osmTownKeys, registerTownCache, getTownCache, validateTownCache, MIN_TOWN_SHOPS,
medianShopSpacing, MAX_MEDIAN_SPACING_M } from './plan_osm.js';
export { withGigs, gigKeyFor, POSTER_CLEAR } from './gigs.js';
// v9 THE ADDRESS LAYER (ROUND39 item 39.1). Pure, no THREE, no fetch, no plan mutation — it derives
// from a plan and never writes to one, so it cannot move a golden. ONE consumer contract across both
// town types: print `localityOf(shopId).label`, never branch on `plan.source`. Full contract in the
// header of address.js and in LANE_A_NOTES §39.
export { createAddresses, STREET_TOLERANCE_M } from './address.js';
// The street-corridor law + venue vocabulary, re-exported so consumers get the whole Lane A contract
// from one import (ROUND13). `roadWidth`/`vergeBand`/`poleOffset` are the road-vs-verge split of
// `edge.width` — see the note in registry.js; `gigKeyFor` is the one and only genre→audio-key mapping.
export { SHOP_TYPES, VENUE_KINDS, genreForVenueKind, roadWidth, vergeBand, poleOffset } from '../core/registry.js';
// planSource selector (round 6; multi-town round 8). Default 'synthetic' → the byte-identical
// golden-hash generator; 'osm' → the real-data fixture importer. Lane F wires ?plansrc=osm (+ optional
// &town=<key>) to these args so the shell bootstrap picks the producer/town without BF caring which
// ran. Unknown source → synthetic; unknown town → the default town.
import { generatePlan as _synth } from './plan.js';
import { generatePlanOSM as _osm } from './plan_osm.js';
import { withGigs as _withGigs } from './gigs.js';
export function generatePlanFor(seed, source = 'synthetic', opts = {}) {
const plan = source === 'osm' ? _osm(seed, opts.town, opts) : _synth(seed);
// v3 gig layer, gated: ?gigs=1 → shell passes { gigs:true, customBands } and we augment; otherwise
// the base plan is returned untouched (byte-identical, goldens frozen — CITY_SPEC prime flag law).
return opts.gigs ? _withGigs(plan, seed, opts) : plan;
}
// Convenience default so `citygen.default` also resolves to the (synthetic) generator.
export { generatePlan as default } from './plan.js';