mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-11 19:47:12 +03:00
* feat(ascii-city-engine): deep enrichment — street furniture, signage, dense Raleigh Enriches the merged v0.1 skill with a dense, real-data streetscape. Schema (backward-compatible): props gain optional label + provenance; new optional signs layer for street-name text; buildings gain name/address/use. world.schema.json admits signs; all v0.1 packs still validate. Validator: per-kind prop glyph map with unknown-kind flag; sign validation; signs included in content-bounds; v0.1 guards (isinstance crash-guard, O(n^2) DoS caps) intact. Engine: spatially-indexed prop billboards (signals, trees, crossings, transit stops, bollards, benches, hydrants) depth-tested at terrain(x,y); perspective-projected street-name sign text as an overlay pass; road surface-material and lit ground styling; crosswalk bands; wayfinding HUD naming the current street and the building faced. Reads spawn + first tile from manifest.json. Raleigh sample regenerated dense (same authoritative bbox): 159 buildings (64 named, addresses, uses), 899 surfaces (86 named, surface/lit/lanes), 298 props across 7 kinds, 29 real street-name signs. 520K, under 2 MB. Docs + evals: contract/engine-architecture/gis-ingestion/raleigh-poc updated for the new layers and acceptance checks; 2 new evals (no fabricated signage; props anchored to terrain). Verified: validator 1410 PASS / 0 FAIL; broken fixture + AttributeError repro exit 1; 5000-vertex DoS rejected in 31 ms; node --check OK; HTTP smoke 200 on engine/manifest/tile; validate-skills.rb 154 green; eval-coverage passes; blocklist clean; headless-Chrome render shows readable in-world 'North Wilmington Street' sign, signals, crosswalks, and on-street HUD. AI-assisted contribution (Hermes Agent, spec-driven-development pipeline). * fix(ascii-city-engine): address droid-review findings on PR #322 1. [P1] facingBuilding(): wrap the heading delta to [-pi,pi] before taking abs, so the Facing: HUD stops reporting a behind-the-camera building after the player turns past ~180 degrees. 2. [P2] buildIndices(): rasterize surface polyline edges into grid cells so long straight road segments register for surface styling and the On: HUD street name, instead of only indexing endpoint vertices. 3. [P1] validator: guard the new props kinds comprehension and the props/ signs loops in all_points() against null, so 'props: null' or 'signs: null' produce a structured FAIL instead of an uncaught TypeError traceback. 4. [P3][security] validator: enforce the previously-declared MAX_FEATURES_PER_TILE (buildings+surfaces+props+signs) to keep the O(n^2) geometry and duplicate-ID paths bounded in aggregate. 5. [P3] engine: paint marked crossings as a distinct ground band (=) instead of a floating billboard, matching the documented crosswalk rendering. 6. [P3] eval: align prop-null-terrain expected_output with the render-time skip behavior actually implemented. Verified: dense pack 1411/0 exit 0; broken/crash/dos/null packs all exit 1 with clean FAIL reports (no tracebacks); JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 2 on PR #322 1. [P1] Engine: skip crossing props in the billboard loop so crosswalks render only as the documented ground band (no more floating '=' above each of the 168 crossings — a regression from the prior fix). 2. [P3] Engine: nearestStreet() filters to kind==='road' so the HUD 'On:' line names the street, not a named plaza/sidewalk ('Market Plaza' etc). 3. [P2] Validator: require each sign's text to be a recorded road name (collected from surfaces), enforcing the documented never-invented signage contract. A fabricated 'Made Up Avenue' sign now FAILs. 4. [P2][security] Validator: short-circuit the tile loop when MAX_FEATURES_PER_TILE is exceeded, and replace O(n^2) duplicate-id .count() scans with single-pass Counters, bounding the quadratic paths. Verified: dense pack 1411/0 exit 0; fabricated-sign repro flags only the injected sign and exits 1; broken/crash/dos/null packs all exit 1 with no tracebacks; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 3 on PR #322 1. [P2] Validator: emit the signs rule unconditionally so a null/non-list 'signs' value FAILs instead of passing silently (was gated on a truthy list check). 2. [P2] Validator: validate sign text against a pack-wide road-name set gathered across all tiles, so a sign in one tile may name a road whose surface lives in another (the documented multi-tile case). 3. [P2] Schema: require non-empty id/kind/text (minLength 1) on props and signs so the schema and validator agree on empty-string rejection. 4. [P3] Engine: drop dead signGrid/IX.key (the sign overlay iterates world.signs directly); cap edge-rasterization steps so a degenerate resolution (0) or pathologically long edge cannot spin unboundedly. 5. [P3] Validator: unknown prop kinds now pass with a reported fallback-'?' note instead of hard-failing, matching the documented fallback glyph and the engine's behavior. Verified: dense pack 1411/0 exit 0; signs:null FAILs; fabricated sign FAILs; multi-tile sign-to-road reference PASSes; broken/crash/dos/null all exit 1; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 4 on PR #322 1. [P2] Engine: render props as once-per-frame perspective-projected one-cell billboards in an overlay pass (like signs) instead of during the ray march, eliminating the multi-row vertical streak a close prop produced. Verified in a live browser: signals/trees/crosswalks now render as discrete single cells. 2. [P3][security] Engine: bound aggregate rasterization in buildIndices() — cap surfaces (5000) and cells per surface (40000) so a crafted pack cannot freeze the tab on load (the validator's caps are not applied client-side). 3. [P2][security] Engine: guard sign text (missing/non-string text now skips the sign instead of throwing in the rAF loop and freezing the view). 4. [P3] Validator: still collect building/surface IDs for oversized tiles so pack-wide uniqueness detection runs even when the per-feature geometry checks are short-circuited (duplicates in an over-cap tile are no longer hidden). Verified: dense pack 1411/0 exit 0; live browser render shows discrete props (no streaks); broken/crash/dos/null/nullsign/fabric all exit 1, valid multi-tile pack exit 0; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 5 on PR #322 1. [P2][security] Engine: guard terrain() against non-finite x/y and guard the prop/sign overlay passes against non-array, non-object entries, so a malformed pack (missing y, signs=42, null entries) degrades gracefully instead of throwing in the rAF loop and freezing the view. Verified in a live browser: a pack with signs=42 + a prop missing y renders with the frame loop alive and no console errors beyond the favicon 404. 2. [P3] Engine: per-surface 'seen' set now dedupes cells across edges (was per-edge), eliminating the repeated linear includes() scan that made the rasterizer quadratic in the worst case. 3. [P3] Engine: raise the per-edge step cap to 20000 since the per-surface cell cap bounds total work, so long edges are fully sampled at the 2-5 m resolutions raleigh-poc.md recommends (fixes road-styling drops). 4. [P3] Validator: lower MAX_FEATURES_PER_TILE to 50,000 (shipped pack is 1,385), bounding the quadratic pair tests more tightly. 5. [P3] raleigh-poc: correct walkthrough step 3 — East Hargett sign is ~141 m behind the spawn, not ahead; only North Wilmington is ahead. HUD count guards signs/props as arrays. Verified: dense pack 1411/0 exit 0; broken/crash/dos/null/nullsign/fabric all exit 1, valid multi-tile pack exit 0; malformed-pack live render survives; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 6 on PR #322 1. [P1] Engine: props/signs overlay passes now use the corrected perpendicular distance (d*cos(ray_angle-heading)) for row projection, distance scaling, and the depth test — matching the ray march — so FOV-edge objects project to the right row and no longer falsely occlude or poison later depth tests. 2. [P2][security] Engine: terrain() guards malformed terrain metadata (missing terrain/resolution, non-positive resolution, missing origin, null elevations), so a crafted pack degrades to a clean error instead of freezing the tab. Verified live: a resolution-0/null-elevations pack shows 'Cannot load...' with no page errors. 3. [P3] raleigh-poc: walkthrough step 3 corrected — W/S only translate, so a 167-deg-off sign needs A/D rotation, not 'hold S'. 4. [P3][security] Validator: all_points() guards buildings/surfaces/props/signs against truthy non-iterables (e.g. props=42), matching the other null guards, so malformed packs report structured FAIL instead of an uncaught TypeError. Verified: dense pack 1411/0 exit 0; crash/dos/null/nullsign/fabric/props42/ broken all exit 1 (no tracebacks); valid multi-tile exit 0; malformed-terrain live render shows clean error, no freeze; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 7 on PR #322 1. [P2] Engine: spatial-index buildings (footprint bbox -> grid cells) so the render loop and collision test find nearby buildings in O(nearby) instead of scanning the whole O(buildings) list per ray sample. Browser-measured frame cost dropped ~62ms (16 FPS) to 12.5ms mean (~80 FPS) on the dense pack. 2. [P2][security] Engine: terrain() guards null/ragged elevation rows, so a pack with a null row degrades to a clean error instead of freezing the tab (live-verified: null-row pack shows 'Cannot load...', no page errors). 3. [P2][security] Engine: cap sign text at 80 chars in the overlay pass, so a pathological pack-supplied sign cannot drive an unbounded per-frame loop. 4. [P3] Validator: reference FALLBACK_GLYPH constant (was dead) in the unknown-kinds report message. 5. [P3] raleigh-poc: fix stale expected validator tail (was 30/25; actual is 159/899, rules_passed=1411). Verified: dense pack 1411/0 exit 0; crash/dos/null/nullsign/fabric/props42/ broken all exit 1, valid multi-tile exit 0; null-row pack shows clean error, no freeze; ~80 FPS browser-measured on dense pack; JS node --check OK; validate-skills 154 green; blocklist clean. * fix(ascii-city-engine): address droid-review round 8 on PR #322 1. [P1][security] Engine: bound the building spatial-index rasterization with MAX_BUILDING_PTS (2000) and MAX_BUILDING_CELLS (40000) and require >=3 finite footprint points, so a ~100-byte crafted footprint cannot drive a ~1e10- iteration synchronous hang on load (the surface rasterizer's cap, applied to the building index I added in round 7). 2. [P2][security] Engine: facingBuilding() filters footprints to finite points before reducing, so a building with a null element in its footprint no longer throws in the rAF loop on frame 1. 3. [P2][security] Engine: collides() and pointNearPolyline() filter footprints/ polylines to valid array points before edge tests, so null footprint points no longer throw once the player enters those cells. 4. [P3] Validator: correct the feature-cap comment to 'buildings + surfaces + props + signs combined' (signs were already counted). Verified: dense pack 1411/0 exit 0; ~85 FPS browser-measured (perf fix intact); badfoot pack (null-point + missing-footprint buildings) renders with zero page errors and frame loop alive; crash/dos/null/nullsign/fabric/props42/broken all exit 1, valid multi-tile exit 0; JS node --check OK; validate-skills 154 green; blocklist clean.