diff --git a/.pql/changelog/ticket_history/2026-06.sql b/.pql/changelog/ticket_history/2026-06.sql index 462ba790c..870ebd500 100644 --- a/.pql/changelog/ticket_history/2026-06.sql +++ b/.pql/changelog/ticket_history/2026-06.sql @@ -1227,3 +1227,254 @@ Scope (the TODO already prescribes it): 4. Validate combined cost against the D-239 §10 ~45 ms/body budget in the T-1031 verification harness (the TODO''s own acceptance criterion). Pure refactor: derivation inputs unchanged, so T-952 golden-seed outputs must be byte-identical — assert it. Also update the stale TODO text (it references a closed ticket). Parent: T-750. Refs: D-239 §10, D-203; T-1028/T-1031/T-1032 (context), T-952 (determinism gate).', NULL, '2026-06-12 10:23:50', '2026-06-12 10:23:50', '2026-06-12 10:23:50', NULL, 'b61e0502d60fee942b85061e5b511087', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXNWWGS3S0RFMFYQC9BWR', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-01, S-02; citations adversarially verified). +DESYNC (S-01, high): the stream is non-blocking (tcp.rs:48-52); read_framed uses read_exact for the 4-byte prefix and payload with no partial-frame state (framing.rs:36-61); read_exact hitting WouldBlock mid-frame irrecoverably consumes bytes, and receive() maps WouldBlock to Ok(None) (tcp.rs:211) — a frame split across TCP segments permanently desyncs the stream (next read treats mid-frame bytes as a length prefix). Works today only because localhost frames arrive in single segments; BufReader is bypassed via get_mut(). Fix: persistent partial-frame accumulation buffer on TcpBridge (or blocking reader thread feeding a channel). Regression test: deliver one frame in two writes with flush+delay. +DRAIN (S-02, med): receive_bridge_inputs calls receive() exactly once per 50 ms tick (bridge/mod.rs:162, no loop; tick at main.rs:306) — an input batch + AtlasLayerRequest in one window backlogs and drains one frame per tick. Fix: loop receive() until Ok(None) with a per-tick cap. The D-225 atlas channel shares this path, so both fixes gate Atlas streaming reliability. +Extension constraint when touching this code: D-225 amendment 2026-06-12 (tagged envelope for the next inbound type).', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '7e756a6ddb6078e69321bebb72709c94', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP19FFZEVED140S1708W', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-27 — the audit''s headline finding; citations adversarially verified). +The D-239 three-carrier chain is implemented and T-1031-harness-verified but has ZERO production call sites: BodyWorldState.regions is written (cascade.rs:100-111) and read only by tests; no function maps a ChunkPos to its covering RegionPos (ChunkPos exists only in chunk_context.rs:67); AtlasLayerResponse carries only Layer1Output (layer_proxy.rs:56-60), so the D-225 proxy cannot serve regions/chunks/voxels and the T-960 Atlas viewer cannot show the tiers that exist. +Scope: (1) ChunkPos→RegionPos mapping — REQUIRES Q-110 (scale anchoring) answered first; (2) region + voxel layers in the D-225 proxy protocol; (3) surface them in the T-960 viewer (additive overlays per D-226). Treat as the spine of remaining Phase-4 work, alongside T-959 (tile fill). +Related: Q-110 (blocker for (1)), T-959/T-987 (tile fill), T-960 (viewer), T-1042 (seam blend), T-1040/T-1041 (voxel bugs). +Audit layer map (verified produce/consume graph, 2026-06-12): +# Layer chain — actual produce/consume graph + +| Stage | Module | Consumes | Produces | Production-wired? | +|---|---|---|---|---| +| L0 Heightmap | heightmap.rs (D-202) | wiki `heightmap.png` 16-bit gray + `sea_level` tEXt | `BodyHeightmap` (f32 [0,1]); downsampled to GRID 512×256 (gen_queue.rs:374-379) | yes | +| L1 Topography | layer1.rs → drainage.rs (D-208), features.rs (D-209), subbiome.rs (D-210) | heightmap | RiverNetwork, DrainageBasins (4–12), flow accumulation, TerrainAnalysis, ≤256 attractors w/ sub-biome+cost+water_bearing | yes | +| L3 Settlement | attractor_matching.rs (D-211/212/213/214/215) | attractors + CityRecords (systems.db `atlas_city_names`) + dominant_faction | CityPlacement {position, archetype, arrangement, founding_orientation} | yes | +| L4 RegionProfile | region_profile.rs (D-239 §1-§8, D-240, T-1023-1027) | seed + BodyParams (planet_class/atmosphere/hydrosphere/tectonic) + TerrainAnalysis | per-region (8×8 grid cells): slope_q/elev_q/ocean_fraction_q, temperature/moisture, precipitation/glaciation/vegetation, river_threshold, 17-zone MorphologyZone → `BodyWorldState.regions` | populated, **never read** | +| L4 QuarterSkeleton | skeleton_gen.rs + district_mix.rs + block_irregularity.rs + tile_condition.rs (D-194/196/197/199/216/217/220/229/233/234) | CityGenerationContext (D-199 read-set + stubs) | QuarterSkeleton: 4×4 blocks (512×512 tiles), zoning, reservations (park/transit-terminal base_z=-1), access points, ±45° corridors (Ribbon/HubSpoke/Mesh), BSP building footprints + BuildingPropertyTags → `BodyWorldState.quarters` | yes (L3→L4 dispatch, plugin.rs:100-131) | +| ChunkContext 64 m | chunk_context.rs (T-1028) | one RegionProfile + seed | basin_direction (seed-random), meander phase/wavelength, has_active_channel, channel_width | **no callers outside tests** | +| VoxelColumn 1 m | voxel.rs (T-1028/1029/1030) | RegionProfile + ChunkContext + domain_warp (±8 m f64→i32 cast) | D-228 axes: TerrainMaterial/FloorMaterial(None-only)/Vegetation/Water/elevation_m/SeasonalCover; 8 family generators; VoxelCache LRU 8192 | **no callers outside tests** | +| Chunk→Tile fill | gen_queue.rs:444-450 | — | `FillChunk` returns immediate no-op success | stub (T-959/T-987 backlog) | +| Client bridge | layer_proxy.rs (D-225) | cache | serves **Layer1Output only**; regions/quarters/voxels not served | yes | + +# Economics → spatial placement bridge + +| Economic input | Source | Spatial consumer | Status | +|---|---|---|---| +| economic_role, population, settlement_class | systems.db `atlas_city_names` (static) | attractor matching score matrix; district_mix 10×9 table; reservations; zone tags | wired | +| dominant_faction | `system_factions` | TerritorialStatus → archetype/arrangement on placement | derived, then **dropped at L3→L4 dispatch** | +| prosperity_baseline_bps | derived D-197 (role+pop+noise; terrain term = 0) | tile_condition bands, entry class, era | wired (partial) | +| world_tier ← system_economy.economic_tier | systems.db | ComplexityTier | stub `Waypoint` (T-1007 backlog) | +| dominant_bulk_class / production_ubiquity | — | roofed coverage / footprints | stub (T-982 in_progress) | +| Live econ sim (D-181 7 signals, EconStateResource) | econ_sim per (system, commodity) | **none** — IPC snapshot + debug only | no path to generation | +| Supply chains / transport → roads, rail | — | — | does not exist | + +Counts: 24 atlas modules; 8/8 voxel family generators implemented; 16/17 morphology zones reachable at region scale (BraidedPlain deferred); cache: 50 bodies (D-203), 8192 voxel columns.', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '200e6c9eba13e5d8602f1b15741b86c7', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP5N42SSGW300FEDTS3M', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-36; citations adversarially verified). +derive_basin_direction (chunk_context.rs:211-231) branches only on ocean_fraction_q then picks a direction from seed bits in both branches; the doc comment (:201-210) falsely claims an elev_q-gradient proxy; the module contract (:12-13, :40-42) claims D8-thalweg derivation. BodyWorldState.river_network exists (body_world_state.rs:79) and is never consulted — chunk-scale water has no guarantee of flowing downhill or connecting across the 16-chunk region-seed boundary. D-239 §8 binding law: respect the D8 thalweg. +Fix: compute the covering region''s dominant D8 direction during the RegionProfile pass (DrainageResult is in scope there) and thread it into RegionProfile for derive_chunk_context to read; fix the misleading comments either way. Composes with T-1040 (channel anchor) and T-1042 (seam blend).', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'a4837e987b043709ff7ddb08d73fd043', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPA5JGWACAGGZ3XJ24K0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-38; low severity — citations agent-reported, spot-check at pickup). +D-203 budgets ~100KB/entry, ~5MB total, and a player-location pinning policy. Reality: BodyWorldState stores the full 512×256 f32 working raster (~524KB, gen_queue.rs:374-379 via cascade.rs:103) plus regions + quarters per body — ~26MB+ at CACHE_CAPACITY=50 (body_world_state.rs:26); .pin()/.unpin() exist but the only caller is their own unit test (body_world_state.rs:258). Capacity and LRU semantics match the decision. +Action: amend D-203 with current per-entry sizes (the bigger raster is a deliberate D-202 consequence) or store a decimated display raster; wire pinning to the player-location system when Phase-5 tracking exists (note it on T-749 scope then).', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'd9ff405352738922bdb4f54da0fbd71d', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPE8FR7TGEM7X6QVPV4M', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-43; citations adversarially verified). +T-961 (two-sentence description, no acceptance criteria, no brief links) is the only asset-production ticket under T-750, while the epic names eight classes; cars, barns, TVs, billboards appear in NO ticket at all (verified against the full corpus). Refine into child stories per class — station walls, rural walls, doors, floors, furniture/props, street furniture (lamp posts), signage/screens (billboards/TVs), rural structures (barns) — each gated on a one-page brief; explicitly record which classes are deferred (cars: see Q-067 audit note). Decide Q-119 (generic-parent placeholder set as first milestone) before sequencing. +Audit per-class status matrix (verified 2026-06-12): +# docs/assets/ survey (13 files + downloads/) + +| File | One-line summary | +|---|---| +| README.md | Master index: audio/visual/video pipelines, status vocabulary (planned/in-progress/placeholder/final), structure that promises visual/{sprites,furniture,tilesets,icons,effects}.md | +| _templates/audio.md | Row + detailed-entry template for audio assets | +| _templates/sprite.md | Row + detailed-entry template for sprites (ID prefixes SPR/FUR/TILE/ICO/FX, status, method, directions columns) | +| _templates/video.md | Row + detailed-entry template for video | +| audio/README.md | ACTIVE production-status catalog — per-category counts table (12 assets tracked), generation tools, bus architecture | +| audio/palette.md | Sonic style bible | +| audio/ambient.md / sfx.md / ui.md | Per-category audio asset tables | +| visual/README.md | STUB — links 5 category files that do not exist, all counts 0 | +| visual/palette.md | STUB — 4 bullet decisions (D-019/D-033/D-045, "functional warmth"), defers to art-direction workshop | +| video/README.md / palette.md | Stubs | +| downloads/ | Purchased character sources (Quaternius Universal Base Characters, Modular Character Outfits FBX) — characters only | + +# Per-asset-class matrix + +| Class | Written brief | Style guide | Naming/res conventions | Gen path | Produced assets | Tickets | +|---|---|---|---|---|---|---| +| Walls (station) | art-direction workshop-outcomes.md §3.3 (v0.1.1 set, pre-cascade) + docs/design/placeholder-art-spec-v01.md §2.1 | visual-grammar-v01.md §1/§4.3, workshop-outcomes §1.8 era palette (partly superseded by D-235), D-235 WallMaterial vocab | renderer/README.md:80-95 (`__.png`, 1024→256→64 chain) | working — renderer/models/wall_structural.tscn rendered | wall_structural ×4 dirs in client/assets/sprites/; wall_bar_green model unrendered; 2 textures | T-961 (backlog), T-988 (token vocab, backlog) | +| Walls (rural) | none found | D-235 tokens only (timber/rammed-earth etc.) | renderer/README.md (generic) | same path, unused | none | T-961 text mention only | +| Doors | placeholder-art-spec-v01.md §2.1 (procedural rects, v0.1) + workshop-outcomes §3.3 `door_sliding` | none for generated world | none for open/closed state frames | same path, unused | none | T-979/T-998 (DoorSpec — logical only), T-961 | +| Floors | placeholder-art-spec-v01.md §2.1 + workshop-outcomes §3.3 (4 floor sprites) | D-228 FloorMaterial axis (open vocab) | 64px visual tile (placeholder-art-spec §1) | same path, unused | none — client/assets/tilesets/ is .gitkeep only | T-959 (tile fill, logical), T-961 | +| Styled buildings | D-232 + D-235 + wiki/economics/architecture_trait_catalog.toml (T-1005 done, ~35 visual bundles) | D-235 material/color-register grammar — tokens only, no rendered art direction | token→fallback-parent chain (catalog header :34-44) | no model/texture path defined for building exteriors | none | T-977, T-988, T-994, T-1004 (all backlog), T-1005 (done) | +| Furniture | docs/assets/visual/furniture.md MISSING (linked); workshop-outcomes §3.3 lists 8-10 objects (pre-cascade) | era table §1.8 only | character-asset-organization.md explicitly excludes furniture ("follow Trellis spike conventions") | proven in spike | spikes/3dpipeline/models/furniture/ ×3 GLB (unpromoted); zero in client/assets | T-961, T-995 (ObjectTag vocab, backlog) | +| Items | docs/design/icon-set-v01.md (HUD/inventory icons only) | D-086 icon constraints | SVG icon_ prefix (client/assets/icons/) | n/a for icons | 13 SVGs in client/assets/icons/ | none for in-world item sprites | +| Cars/vehicles | none found | none | none | spike only | spikes/3dpipeline/models/props/vw_beetle.glb (spike) | none — Q-067 open ("driveable vs NPC traffic?") | +| Lamp posts | none found (zero repo hits) | none | none | unused | none | T-961 text mention only | +| Barns | none found (only T-750 epic text) | none | none | unused | none | none | +| TVs | none found (only T-750 epic text) | none | none | unused | none | none | +| Billboards | none found (only T-750 epic text; other hits = LOD impostors) | none | none | unused | none | none | +| Characters (reference class — the working model) | docs/architecture/character-asset-organization.md + docs/design/character-visuals-spec.md | yes | full (manifest.json, seg_ naming, body-type keys) | proven end-to-end | 1002 files in client/assets/characters/ | done | + +# Generation path (verified files) +image-gen (.claude/skills/image-gen/SKILL.md + scripts/image_connector.py, Gemini) → glb-gen (SKILL.md + tooling/db/trellis_connector.py + tooling/trellis-batch.sh + Blender postprocess scripts) → sprite-gen (SKILL.md + scripts/render.sh) → renderer/ (project.godot, render_scene.tscn, render_export.gd; D-019 camera, 3-light rig, 1024/256/64 chain) → client/assets/sprites/. renderer/output/ holds only .gdignore (intermediates gitignored). + +# Produced assets in client/assets (non-.import files) +audio 16 · characters 1002 · fonts 3 · icons 13 · planets 7 · sprites 9 (npc_generic ×4, wall_structural ×4, .gitkeep) · theme 1 · tilesets 1 (.gitkeep only)', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'ff0ab8cda23bec0163c85610d4b11f10', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPJ910NNR5T2R9F9NWQR', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-44 + S-50 task half; citations adversarially verified). +CATALOG: T-750''s deliverable includes an "asset creation catalog with production status". docs/assets/visual/README.md:14-20 links sprites.md/furniture.md/tilesets.md/icons.md/effects.md — none exist. The row template is ready (docs/assets/_templates/sprite.md:10-24, SPR/FUR/TILE/ICO/FX prefixes + status column) and the audio side shows the working model (docs/assets/audio/README.md:14-19). Instantiate the five files, seed with existing assets (wall_structural, npc_generic, 13 icons) + the T-750 class list as planned rows, and make updating them part of /sprite-gen. +GLB-GEN PATH: .claude/skills/glb-gen/SKILL.md:115 names client/assets/models/ as the production destination — the directory does not exist; proven spike GLBs sit unpromoted (and are now local-only per D-241, so promotion is also preservation). Define the production model directory + promotion convention (mirror the characters/ manifest pattern), update the SKILL. +CONVENTIONS: extend naming beyond entity/wall sprites — Godot TileSet resource organization (client/assets/tilesets/ is .gitkeep-only), door state-frame suffixes, multi-tile footprint metadata, renderer/textures/ naming keyed to D-235 tokens.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '260202dd414801fe0a5c75d23efcd848', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPPHC9FZ4T0GNKR615PR', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-46; citations adversarially verified). +Four asset classes named in T-750''s epic text have no brief, no style guidance, no convention, no ticket beyond the epic sentence, and zero produced assets — repo-wide grep for lamp posts returns zero hits in any .md/.toml/.rs/.gd. Either author one-page briefs per class (audio _templates pattern: function, era/zone placement, footprint, palette, D-235 token parent) or record deferral so the epic stops implying scope. Cars are NOT in this ticket — gated on Q-067 (see its 2026-06-12 audit note).', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '7a2cab69cc8534c446dd26e1f0a7b6c0', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-48; citations adversarially verified). +Current style guidance is: a stub (palette.md:10,23 "to be populated"), a pre-cascade workshop whose per-class guidance targets the dropped hand-made bar scene and whose era-palette model D-235 explicitly reframed (era = maintenance/wear, not a material gate — architecture.md:1705), and a third divergent style block inside the image-gen skill (SKILL.md:60-79: toon-shaded, near-white base, Invisible Inc reference). No document reconciles these for the D-235 token vocabulary the generator will request. +Write: per-token-family art direction (WallMaterial/RoofForm/FacadeRhythm/StreetSurface registers), surviving constants (D-019 camera, D-043 outline/resolution chain, D-033 tinting, "functional warmth"), explicit supersession note for the workshop §1.8 era table. Owner: Araminta (D-235 co-maintainer).', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'f3e40d4dc421292c6faf61d9342a3cf1', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPZ0ZTM1QQXD5K972CMM', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-49; citations adversarially verified). +The visual-art-director briefing is dated 2026-03-13 (:7): it references the retired tooling/db/ticket CLI (:14-15), frames work around the dropped v0.2 pivot (:17), cites a nonexistent /asset-gen skill (:78), and predates D-228/D-232/D-235, the trait catalog, and the whole T-750 asset scope — while D-235 names Araminta co-maintainer of the material vocabulary (architecture.md:1711) and T-995 assigns her the ObjectTag co-maintenance. Rewrite around: D-232/D-235 vocabulary co-maintenance, the production-status catalog ownership, the image-gen → glb-gen → sprite-gen toolchain (+ D-241 storage boundary), and the no-in-world-rendering-until-Phase-5 rule.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '61a84c1811a28cebe8e24b13b5651063', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ3EC348VN37Q2X8JXM0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-51 + S-58 rider; citations adversarially verified). +The player starting system is the only stub among 302: GJ-280B/index.md:4 stub banner, all-em-dash profile (:11-17), no bodies/ directory, no markers.json, no globe renders, no Supply Dependency/Silence Topic/Calibration Note — while 301/301 other systems are fully dressed. Phase-1 epic T-746 closed done over this gap. Sova canon is meanwhile triplicated: the wiki stub, wiki/corporations/sova-station-works.md:17-23, and docs/design/sova-station-profile.md ("canonical", 2026-02-25). +Scope: author through the standard pipeline (scaffold_bodies.py + atlas generation + prose pass), folding in docs/design/sova-station-profile.md and sova-texture-appendix.md; wiki becomes canonical; both design docs then get superseded-with-pointer markers (they were deliberately kept active in the 2026-06-12 docs sweep pending this fill). Phase-4 relevance: Sova is the Phase-5 start location — its generation inputs (heightmap, bodies, markers) must exist for the cascade.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '788c4c1e2b95938eb20e476c5f8e4352', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ7P014H0PM4QWZFTWN4', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C4; gated on Q-120 — garment-token vocabulary). +The validated production recipe (Tyre research, spikes/quaternius-aesthetic/reviews/ai-clothing-pipeline-research.md:509-527, 614-628): ~30 base meshes × 4-16 shape-key variants × AI texture variation × region-mask tints ≈ 20,000 unique visuals. Trellis CANNOT make garments (sculptures, not fitted clothing; auto-rigging failed at 4-22% vertex match — VERDICT.md:115). D-162 fixes the fit model: author on reference body, offline Surface Deform per body type. +Stories on refinement: (1) base-mesh acquisition (Quaternius packs + hand-authored fill to ~30); (2) shape-key variant authoring; (3) texture-variation loop through the self-hosted stack — NOTE: the research assumed Meshy retexture credits; validating a LOCAL retexture path is an explicit sub-task, not assumed; (4) region-mask + tint conventions per Q-120 tokens; (5) Surface-Deform batch fit to the 11 body types + manifest registration (client/assets/characters/clothing/ pattern exists with the 4-item peasant set). Each garment lands as production-status catalog rows. +Related: Q-114/Q-115 (server contract), Q-121 (who wears what), the corp uniform spec ticket.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c29918218e2a376e71d366cc717c0cb8', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQBTNGTDMYE6EHVA48PG', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C5; corp files verified to contain zero dress specification). +Four apparel corps have rich supply-chain lore and no uniform/dress specs: wiki/corporations/workshift-apparel.md (HeavyWork/FieldWork/StationWork lines; institutional contracts ≈70% revenue — the contract lore IS the uniform-assignment rule, write it as data), shetland-wool.md, kalahari-leatherworks.md, thrds.md. Add a spec section per corp page (or wardrobe-catalog stanzas per Q-120): silhouettes, palette/marks, which roles wear which line. Gameplay hook preserved: worn HeavyWork gear = exposure history (the respiratory-sensitizer scandal becomes wearable evidence — see Q-115). +Sequence after Q-120/Q-121 decide the vocabulary + canon home.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '1441e313471c6718ad6a8f80988dd9a8', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQGAX5GT4PTTBQYGJCV4', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-64 remainder; verified: all four open with zero linked tickets). +The remaining Phase-4 spine is T-959 (Layer 5 tile fill) → T-962 (validation + Phase-5 gate). Four open architecture questions sit directly under that work with no owners: Q-103 (tile-mutator op schema — needed before T-959 Layer 5), Q-102 (cohesion-matrix seam-free variation — needed for tile fill; relates to T-1042), Q-105 (region seasonal/clock state), Q-109 (generation-source dispatch: planet/station/mod/save). Answer or ticket each before T-959 kicks off; Q-103 and Q-102 are the most load-bearing. Also now open from the audit: Q-110 (scale anchoring — blocks the spine ticket) and Q-111 (live-econ coupling — gates T-1007/T-982 sequencing).', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'ac09032417df50ecd5339e75eebdac74', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQN3J95WE3GZJJEF3HG0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-68 remainder; low severity). +D-179 (Stability Acceptance Criteria) and D-183 (Iterative Economics Development Cycle) mandate ongoing verification of the econ sim but have zero linked tickets and Phase 2 is closed; whether stability criteria get re-checked when Phase-4 generation starts reading economic state (D-199 read-set, Q-111) is untracked. Decide: re-validate under Phase-4 load (ticket it under T-962) or amend both records as satisfied-at-Phase-2-close. +Also: question records mostly lack raised dates (pql decisions list --type question emits empty dates), making staleness unmeasurable — add "raised" dates to new Q records going forward (the 2026-06-12 batch Q-110..Q-122 already does this) and consider a validate rule.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'dbb1a7d6415e4e8eb683f2f0932e1350', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQS7HFJJHDW5FBM609EG', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-23; Phase-5 surface — do NOT refactor before Phase 5 reopens it, per D-166). +client/ui/meta/screens/character_creation/character_creation.gd is 2,442 lines / 105 funcs — ~3× the next-largest production script — mixing camera control (_cam_zoom_toward_cursor, _update_camera_angle), manifest loading, and UI state in one MetaScreen. It is a meta screen (D-169 component rule does not apply) and part of the frozen character/rendering surface. Extract when Phase 5 starts.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'ad13735ef827afc5a68666460176737f', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQXH3Z2VEDSV1636XW58', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-42; verified including git history). +client/scripts/rendering/character_visual_descriptor.gd:5 says its fields "must match server/src/bridge/types.rs" — NO such struct exists there and git log -S shows none ever did; VisibleEntity carries only entity_id/position/kind/visibility/relationship/observation/tell_state. The comment is aspirational. +Scope (after Q-114 decides the generation contract): mirror struct in types.rs; MessagePack round-trip test against the GD from_dict/to_dict; entity-snapshot field gated by perception (you see clothes only when you see the NPC). Quick interim action: soften the .gd comment so it stops claiming a contract that does not exist.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '9439a680dd0787cf36ba4ad3bbbe1262', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR27XGNCP92JN7BDQ454', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C6; gated on Q-114/Q-115/Q-120). +workers/stubs.rs:86 is the declared home ("real implementation pre-generates NPC appearance, inventory, mood"); the 10-axis generation in npc/generate.rs shows the deterministic per-axis pattern to extend. Wardrobe = pure function of (entity seed, culture register, role, employer, prosperity band) → token per slot (Q-120 vocabulary) → manifest item id + tints. Assignment logic per Q-121: role picks garment family (corp institutional contracts = workforce uniforms = information), culture/system picks materials/registers, prosperity band picks condition/wear, faction/corp adds marks. Pairs with the bridge wire-struct ticket (Phase 5) and the Q-114 contract.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '71db77b977f17e0d4326c84bfeef0442', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR79W28XNN1TB7HKGBP8', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-03; citations adversarially verified). +simulation/input.rs: 2,739 lines, imports 9 domains (bookmark, bridge::debug, knowledge, settings, economy, interaction, inventory, movement, save_io), 9× type_complexity allows (:485-1120) + 1 too_many_arguments — the dispatch hub for every player verb. simulation/dialogue.rs: 2,785 lines, 3 allows. +Extract per-domain input handlers into their owning modules behind a thin dispatch table; split dialogue into talk-selection / confrontation / response-assembly. Mechanical, no behavior change; gate with the existing determinism.rs byte-identical goldens.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '02dca0d3a22f8e3e69a3dce8739922e9', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRBRFW4MH5G8C0X12YGR', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-05; verified — zero tests exist for BackgroundWorkerPool anywhere). +workers/stubs.rs:7 claims the pool infrastructure is "real and tested" — false. pool.rs:8-13 documents that a worker-thread panic silently loses in-flight requests (TODO #843); for ModalLock consumers that means the player waits forever. SimulationPlugin spawns 4 live stub threads every session (simulation/mod.rs:85-87) for Phase-5+ functionality. +Do now: correct the doc claim; unit tests (spawn/push/poll/shutdown + worker-panic). Before any ModalLock consumer ships (Phase 5): heartbeat/re-enqueue or downgrade ModalLock to an error path. Optional: defer thread spawn until a real handler registers.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '441b39f6be251d47bb89512f09537f77', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRG23G1RAREVHQJ14BWC', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-06, S-07, S-08, S-09, S-12; low severity — spot-check citations at pickup). +1. S-06: add the consumer contract ("every consumer must sort before state/wire use") to the three perception disallowed-types allows (shadowcast.rs:17, query.rs:11, interpretation.rs:9). +2. S-07: delete unused bytemuck (Cargo.toml:30, zero references); fix the stale rayon comment (says "not yet called"; used in atlas/gen_queue.rs:192-228). +3. S-08: delete or feature-gate bin/generator_spike.rs (1,153 lines reimplementing npc/generate.rs outside ECS, 3 TODO(integration) duplication admissions); extract the shared surname corpus copied between generate_brands/names.rs and generate_corporations/names.rs (already drifted; both feed the systems.db stamp); prune or justify the 24 allow(dead_code) in generate_corporations. +4. S-09: pin execute_save_load with a lower-bound constraint (currently only .before(compute_observer_snapshot), simulation/mod.rs:106-114 — the scheduler may legally run it before Input, changing what a save captures); note the exclusive-system exception in tick_phases.rs rules. +5. S-12: unit tests for simulation/economy.rs signal derivation (382 lines, no cfg(test); fixtures set economy_snapshot: None) — trend windowing, first-tick baseline, zero-demand stockpile edge.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '0c19e69ff8a6b79d8ecde0e98a9afb3f', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRMET5CBB0ENBZGJQKX0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-13; citations adversarially verified). +The pre-push hook is the ONLY automatic correctness gate (its own comment, .config/hooks/pre-push:101-110) and there is no CI — but for client/ changes it runs only a headless parse check (:38-54). The gdUnit4 suite (tests/run-godot: 300s-capped, one-line JSON summary, agent-safe) is invoked only manually. A GDScript regression reaches main unverified, while team-patterns.md claims the gate is "deliberately comprehensive". +Fix: run tests/run-godot in pre-push when CLIENT_CHANGED > 0 — or record manual-only explicitly and fix team-patterns.md. Related decision: Q-116 (gdlint blocking). Prerequisite worth checking: T-973 (pre-existing bare-run failures, under this initiative) so the new gate starts green.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '64f70991b5c8aa2512edcf83d052e563', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRRDGJ5GFPGHZV3WS0D0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-18; citations adversarially verified). +22,340 lines of tooling Python (including the systems.db generator) are verified only by a 4-rule ruff subset (pyproject.toml:26-31: E9/F401/F811/F821); zero pytest anywhere; the one real test (tooling/planet-gen/test_sim_determinism.py, guarding the expensive 271-body bake, exit codes 0/1/2) is wired into nothing. +Fix: make test-tooling = test_sim_determinism.py + import_economics --dry-run against the committed DB; call from pre-push when TOOLING_CHANGED > 0; widen the ruff selection.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c533e28b728c137c18ddc57cf86ad95b', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRX067NBNG76MV84MDQ0', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-19; citations adversarially verified). +tooling/economy-db/import_economics.py (2,617 lines, 31 top-level defs) owns schema migration, brand regeneration (shells to Rust), 16 import steps, validation, and the meta stamp. Its source-file list is hand-maintained in THREE places guarded only by comments: IMPORT_ECONOMICS_SOURCES (:81-99), GENERATOR_SOURCES (tooling/check-systems-db-stamp:48-63), and the /pr-push watch list (.claude/skills/pr-process/SKILL.md:222-243). Error handling itself is good (single transaction, rollback, distinct exit codes at :2350-2613). +Fix: extract one shared tooling/generator_sources.py imported by the script + stamp checker and read by /pr-push; then split importers/validators into modules under tooling/economy-db/; finish type hints during the split. Also fold in S-25''s connector dedup: move CONFIG_PATH/load_config/get_base_url into tooling/db/common.py (currently copy-pasted across audio/trellis/image connectors).', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '9fb2f5c4d124c53422bc0c0bc97a06cb', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS18RSVRHC7Y9TAX06HG', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-21, S-22, S-24; low severity — spot-check citations at pickup). +1. S-21 now: delete 7 tracked orphan .gd.uid files whose scripts are gone (client/scripts/rendering/fog_renderer.gd.uid; client/ui/{bug_report_dialog,character_select,debug_console,loading_screen,main_menu,settings_dialog}.gd.uid). Phase-5 rider: remove time_display.gd/.tscn + its 199-line test (superseded by the merged HUD row per hud.gd:4 / #786) with the Phase-5 rendering pass, not before (D-166). +2. S-22: deduplicate _format_pop — byte-identical 12-line implementations in planet_screen.gd:105-116 and system_screen.gd:685-696 (plus _format_radius) into a shared atlas helper. +3. S-24: triage the 9 permanently disabled skip_test_ functions (test_sprint2_proof.gd:117,147,169; test_etalk_overlay_sprint17.gd:267-273; test_client_p2.gd:70,100,198) — re-enable, delete, or attach a T-id; convert the push_warning-then-return soft-skip pattern (test_fog_shader, test_audio_sprint13, test_monologue_display, test_input_roundtrip:54) to gdUnit4 skip reporting so missing prerequisites are visible in the JSON summary, not silently green.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '7feb0574bf8570c62ff13e1b6f297344', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS5YZ04F4CPPYNZS4Z2W', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-11, S-15, S-16, S-25, S-26, S-39; S-15/S-16 adversarially verified). +1. S-15: docs/DEVOPS.md:211-230 documents three generators, .claude/rules/asset-pipeline.md:22,27,36 documents two with a literal command for a file that does not exist (tooling/planet-gen/generate_atlas.py, retired #951/D-223); truth is one (import_economics — Makefile:334-352, stamp registry). Fix both + the CLAUDE.md asset-pipeline snippet. +2. S-16: delete make check-protocol (Makefile:123-130 greps constants deleted under D-192 via T-874/T-875 — empty==empty always passes); drop from build dep (:132) and help (:42). +3. S-25: rewrite DEVOPS.md hook/config sections from current sources (pre-push table omits cargo test/deny/clerk + advisory gdlint status; .config/ description never materialized; pre-commit row omits pql validate/export). +4. S-26: project.yaml says version 0.2.0 under the 0.{phase}.{n} scheme with Phase 4 active, and its description still narrates the v0.1 Sova slice — bump to 0.4.n (or document the bump trigger) + refresh description. +5. S-39: update voxel.rs module doc (:41-48) and MorphologyFamily variant comments (:256-280) still claiming 7 families are unimplemented stubs (T-1029 landed them all); fix cascade.rs:219 TODO citing closed T-1028 (now tracked by T-1044). +6. S-11: comment sweep — main.rs:126-127 claims a protocol_version handshake that D-192 removed; npc/relationships.rs:92 TODO(v0.2); chunk_streaming.rs:6,21-22 v0.3+ — rephrase version targets as phase numbers.', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '7def7071e58e7e765e9cc66f673044cd', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSA4WFXPD21YK7N8SF60', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-53; counts independently reproduced by verifier). +The body-page scaffold links ![Heightmap](heightmap.png) for all non-gas-giant bodies (scaffold_bodies.py:94-96) but heightmaps exist for only 267 bodies (vs 2,398 reliefmap.png / 3,256 globe.png) — 2,131 of the wiki''s 2,180 broken links are this one pattern, rendered as dead images in the implant wiki view. Fix: make the link conditional in the scaffold and regenerate the Visual section of body pages (or backfill heightmaps where Phase 4 wants them anyway — they are a generation input).', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c870982f1558a4a41c2e12034d641a28', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSEC1F0RKJVH7JVPS8NW', 'description', '(description follows in first append)', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-54, S-55, S-56, S-59; S-54/S-55/S-56 adversarially verified, S-59 agent-reported). +1. S-54 (~26 real breaks): knowledge/→concepts/ rename leftovers (3 contraband files, triangles/hub-power.md:420, authoring/monologue-guide.md ×7); pre-governance decisions/ anchors (monologue-guide.md:834-836); 9 phantom companion-system links in star-systems/catalog.md (index.md handles the same companions correctly as unlinked text); factions/cygni-b-combines.md absent (linked from stalownia-kowalski.md:111); concepts/entity-attributes.md:280 wrong relative path to an existing doc. +2. S-55: wiki/index.md:12 claims "10 fully written" vs ~301 reality; corporations/index.md links 38/155 (117 orphaned); zero nav link to economics/ (39 md + 20 TOML, the primary generator source); 25 station-level gttr-*.md orphaned from their system pages. Regenerate counts from the catalog (or let wiki_sync own them); autogenerate the corp index from frontmatter. +3. S-56: wiki/GOVERNANCE.md:39-54 prescribes a star-systems/{system}/{station}/{district} hand-authored tree that has zero instances, and _templates/star-system.md:1-18 mandates frontmatter that 0/302 system pages have — rewrite both to the generated model (wiki_sync.py: DB owns structured fields, wiki owns prose) or decide system pages should carry frontmatter and have wiki_sync emit it. +4. S-59: convert the 4 pre-D-223 geometry-bearing Sol markers.json (GJ-0 bodies, authored coordinates/populations) to names-only, moving the authored data to the Sol special-case home; add wiki/triangles/index.md or de-link it from wiki/index.md:19. +Audit wiki survey (verified 2026-06-12): +# wiki/ directory map + +| Directory | Files | Format | Machine-readable (feeds DB)? | Completeness | +|---|---|---|---|---| +| star-systems/ | 3,262 md + 2,398 json + 5,921 png | md (no frontmatter on system pages; YAML frontmatter on body pages), markers.json, png | YES — body frontmatter (axial_tilt → import_economics.py:1286), markers.json city names (:1451), gttr.md → gttr_hook (populate_gttr_hook.py); system infobox/bodies tables generated FROM systems.db (wiki_sync.py) | 302 system dirs; 301 full prose (Supply Dependency 301, Silence Topic 288, Calibration Note 261); 2,625 body pages all with EMPTY Description; 302 gttr.md + 6 corridor + 24 station GTTRs; heightmap.png only 267 vs globe 3,256/reliefmap 2,398; GJ-280B = sole stub | +| economics/ | 39 md + 20 toml | TOML (source of truth) + md prose | YES — commodities.toml, production_chains.toml, currency_zones.toml, specialization_vocabulary.toml (27), system_specialization.toml (240/301 pins), architecture_trait_catalog.toml (28 templates) + bias, brands/generated_brands/tier1/tier2 | Complete for current decisions (D-173..D-182, D-232, D-237; T-1016 done); not linked from wiki/index.md | +| corporations/ | 156 md | md + YAML frontmatter | YES — frontmatter slug/title/headquarters/tags/scope → corporations + corp_presence (import_economics.py:734-790, D-182 wiki-is-truth) | 155 canonical pages ~8-16KB; index.md lists only 38 (117 orphaned from nav) | +| factions/ | 9 md | md + frontmatter | No (prose; dominant_faction comes from economics TOML) | Complete: 6 major + 1 regional + 1 local worked example, all canonical, clean index | +| technology/ | 7 md | md | No | Complete (6 entries + index) | +| contraband/ | 4 md | md + frontmatter | No | Complete (3 entries + index); stale ../knowledge/ links | +| concepts/ | 4 md | md | No | Complete (fact-catalog, entity-attributes, relationship-states); renamed from knowledge/, inbound links broken | +| authoring/ | 12 md (incl. npc-patterns/ 3) | md | No (authoring guides) | Complete; monologue-guide has 9 stale links (knowledge/, pre-governance decisions/ paths) | +| triangles/ | 1 md | md + frontmatter | No | One worked example (hub-power.md); index.md missing (broken link from wiki root) | +| cultural-groups/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| institutions/ | 0 (.gitkeep) | — | — | EMPTY (template exists; covered under factions/) | +| lore/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| species/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| _templates/ | 17 md | md | — | Complete but drifted: star-system template ≠ generated reality; station/district/location/cultural-group/species/lore/institution templates have 0 instances | +| glossary.md / GOVERNANCE.md / index.md | 3 md | md | No | Glossary current (incl. TOML/DB terminology + anti-drift list); GOVERNANCE spatial hierarchy + status lifecycle stale; index.md counts stale (''10 fully written'' vs ~301) | + +# Star-systems census +- Systems: 302 dirs (catalog claims 301; 220 named / 81 unnamed); 9 catalog rows link nonexistent companion dirs +- Bodies: 2,625 body pages (planets, moons, belts, oort clouds; no per-type subdirs — flat bodies/ per system) +- Stations: 0 wiki pages; rows in systems.db rendered into ''Stations & Facilities'' tables per system index + 24 station GTTR prose files +- Markers: 2,394 names-only (D-223) + 4 legacy geometry (all GJ-0/Sol) + +# Generation data flow (verified) +wiki/economics/*.toml + wiki/corporations/*.md frontmatter + wiki/star-systems body frontmatter + markers.json names → tooling/economy-db/import_economics.py → server/data/systems.db (stamped, tooling/check-systems-db-stamp) → client Atlas (gttr_excerpt popups, reach_screen.gd:178) + direct runtime load of wiki globe.png (system_screen.gd:482-492). wiki_sync.py: DB owns structured fields, wiki owns prose sections. + +# docs/ health snapshot +- docs/architecture/ (19): current — pql-migration.md (2026-06-06), atlas-naming-pipeline, implant-app-pattern; historical — sprint-36/37 audits, v01-yaml-content-audit, eval/risk-godot-rust-bridge (2026-03-13) +- docs/design/ (60+): ~35 files frozen at 2026-02-19→03-14, status:active but v0.1/v0.2-era (wow-moments, first-5-minutes, spatial-layout-*-v01, dueling content-structure docs); still-load-bearing: star-map.json (Topology source), gj-catalog-full.json, planetary-terrain-generation.md, cultural-diversity-audit.md (remediated, T-793 done), sova-station-profile.md (canon for the stub system)', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c10ead0f413f1efdcc7a3dd7f26a4b2e', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZQKSQQQ1T5Q696AAM', 'status', 'in_progress', 'backlog', NULL, '2026-06-12 10:41:25', '2026-06-12 10:41:25', '2026-06-12 10:41:25', NULL, '40da79cdbd4bb436e0f13a24fac52141', 2) ON CONFLICT(hash) DO NOTHING; +INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZQKSQQQ1T5Q696AAM', 'description', 'Define BulkClass{BulkSolid|BulkLiquid|PrecisionDense|Perishable|NonPhysical} + ProductionUbiquity{Ubiquitous|Common|Specialist|MonopolySource}; back-fill D-184 bulk_class values; build-time lookup of the settlement dominant commodity from the systems.db catalog. Seed-independent. + +Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here (closed set: Fjord, Canyon, Delta, AlluvialPlain, Island, MountainPass, Coastal, Lake, Sea, OpenOcean, MeanderReach, Other) -- it had no home and 954/976/1005 all need it. bulk_class is the 8->5 PROJECTION (size variants bulk/standard/compact/oversized -> BulkSolid; precision -> PrecisionDense; the 8 stay on commodities). Note: the bare enum/struct type DEFS now live in the foundational types task; 982 owns the projection + dominant-commodity DERIVATION logic (derived from highest-output location-bound production chain, D-178, not an authored role->commodity table).', 'Define BulkClass{BulkSolid|BulkLiquid|PrecisionDense|Perishable|NonPhysical} + ProductionUbiquity{Ubiquitous|Common|Specialist|MonopolySource}; back-fill D-184 bulk_class values; build-time lookup of the settlement dominant commodity from the systems.db catalog. Seed-independent. + +Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here (closed set: Fjord, Canyon, Delta, AlluvialPlain, Island, MountainPass, Coastal, Lake, Sea, OpenOcean, MeanderReach, Other) -- it had no home and 954/976/1005 all need it. bulk_class is the 8->5 PROJECTION (size variants bulk/standard/compact/oversized -> BulkSolid; precision -> PrecisionDense; the 8 stay on commodities). Note: the bare enum/struct type DEFS now live in the foundational types task; 982 owns the projection + dominant-commodity DERIVATION logic (derived from highest-output location-bound production chain, D-178, not an authored role->commodity table). + +Status check 2026-06-12 (fable-ous audit S-62): flipped in_progress → backlog. Verified the enum/type half landed via T-1006 (BulkClass/ProductionUbiquity + context fields, generator.rs:1016/1039/1097-1100), but this ticket''s remaining scope — the 8→5 bulk_class projection, D-184 backfill, and the dominant-commodity DERIVATION (highest-output location-bound chain per D-178) — has zero hits in city_context_reader.rs. Nobody is actively on it; it was stale-WIP for 18 days while being T-1014''s sole live blocker. Sequencing input: Q-111 (live-econ coupling) decides whether the dominant-commodity lookup stays static build-time.', NULL, '2026-06-12 10:41:25', '2026-06-12 10:41:25', '2026-06-12 10:41:25', NULL, 'cf73c7d49a616fcc49d535dd16d5f029', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/ticket_idmap/2026-06.sql b/.pql/changelog/ticket_idmap/2026-06.sql index ab7d00077..cdbb6793b 100644 --- a/.pql/changelog/ticket_idmap/2026-06.sql +++ b/.pql/changelog/ticket_idmap/2026-06.sql @@ -52,3 +52,30 @@ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_ INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPQ0308CFF9WKNGBBYQ763W', 'T-1042', '2026-06-12 10:23:50', '2026-06-12 10:23:50', NULL, 'fd4f910a04f93cb960046faeded4d0f5', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPQ034DKN4ENSGX5HTYTBJG', 'T-1043', '2026-06-12 10:23:50', '2026-06-12 10:23:50', NULL, '86eea4e94a5cb3f6947fcbdb0a0cfaed', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPQ0381QWDAQABZAY7MRD8M', 'T-1044', '2026-06-12 10:23:50', '2026-06-12 10:23:50', NULL, '32d7b3362db0a95735536be0ad4036a2', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXNWWGS3S0RFMFYQC9BWR', 'T-1045', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'ee9f19d1a501a09b4dd00ceb44c0aec7', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP19FFZEVED140S1708W', 'T-1046', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '0e8489c97faed6d90d6532ed5fd7aaeb', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP5N42SSGW300FEDTS3M', 'T-1047', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '94323ce176e1577bf6b4cc16845bdbca', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPA5JGWACAGGZ3XJ24K0', 'T-1048', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '0deef24e598cfc7152503b5711c887d1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPE8FR7TGEM7X6QVPV4M', 'T-1049', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'd8c1ba268e0478521afae88716a88472', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPJ910NNR5T2R9F9NWQR', 'T-1050', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '1aaabaf67faa19300cd759dd029188f0', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPPHC9FZ4T0GNKR615PR', 'T-1051', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'db5d4992e2597c8b1cf29ecb5bc6064a', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'T-1052', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '8e7a864b8f873a62d01d897e8d734b5b', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPZ0ZTM1QQXD5K972CMM', 'T-1053', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'e258dc43d2af403743c8243136735cd1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ3EC348VN37Q2X8JXM0', 'T-1054', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'f2a4a4eb2039d0a94e293f36f044921d', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ7P014H0PM4QWZFTWN4', 'T-1055', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c2903bf1a8fc015a28322ccd4543dae9', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQBTNGTDMYE6EHVA48PG', 'T-1056', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'afb5cd4d7ed40db8b389f4f4cd704cb1', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQGAX5GT4PTTBQYGJCV4', 'T-1057', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '1cc26f7ef18d3de793bfacc1a123d9c3', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQN3J95WE3GZJJEF3HG0', 'T-1058', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'dda05a2807ba172a4eb30b2ac60768e5', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQS7HFJJHDW5FBM609EG', 'T-1059', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '39d8a65ff1c5975f333a898e4fdd7f90', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQXH3Z2VEDSV1636XW58', 'T-1060', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'f4d68d10802ddffaa18d729b67099bbe', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR27XGNCP92JN7BDQ454', 'T-1061', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b7263c0ea0a383a2cb32fe2c068aefac', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR79W28XNN1TB7HKGBP8', 'T-1062', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '86676b18c54a799d14f863ed4fe90c96', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRBRFW4MH5G8C0X12YGR', 'T-1063', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b73b85ce602083668294ad6561d9cbdd', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRG23G1RAREVHQJ14BWC', 'T-1064', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '46db5d1249f149bda5cfd8589d8fc285', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRMET5CBB0ENBZGJQKX0', 'T-1065', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '567fed4adce1c5075d94008516fcb18d', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRRDGJ5GFPGHZV3WS0D0', 'T-1066', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'fad5808aba618c9ee16135e83dc39a09', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRX067NBNG76MV84MDQ0', 'T-1067', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '98860e1c2329c6128f717d47fe6a493d', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS18RSVRHC7Y9TAX06HG', 'T-1068', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '49776c91143098ec74cd25734d6561b3', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS5YZ04F4CPPYNZS4Z2W', 'T-1069', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b91a55eefa15f117a0222e7fe8656d6e', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSA4WFXPD21YK7N8SF60', 'T-1070', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '7a1bce4e8c3705623cf50834005ba19a', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); +INSERT INTO ticket_idmap (record_id, ticket_id, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSEC1F0RKJVH7JVPS8NW', 'T-1071', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b3f82a325e1724e3d218fe54ba344f64', 2) ON CONFLICT(record_id) DO UPDATE SET ticket_id=excluded.ticket_id, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > ticket_idmap.updated_at OR (excluded.updated_at = ticket_idmap.updated_at AND excluded.hash > ticket_idmap.hash); diff --git a/.pql/changelog/tickets/2026-06.sql b/.pql/changelog/tickets/2026-06.sql index b0e684f75..673efe217 100644 --- a/.pql/changelog/tickets/2026-06.sql +++ b/.pql/changelog/tickets/2026-06.sql @@ -1329,3 +1329,281 @@ Scope (the TODO already prescribes it): 4. Validate combined cost against the D-239 §10 ~45 ms/body budget in the T-1031 verification harness (the TODO''s own acceptance criterion). Pure refactor: derivation inputs unchanged, so T-952 golden-seed outputs must be byte-identical — assert it. Also update the stale TODO text (it references a closed ticket). Parent: T-750. Refs: D-239 §10, D-203; T-1028/T-1031/T-1032 (context), T-952 (determinism gate).', 'backlog', 'medium', NULL, 'server', 'D-203', '2026-06-12 10:23:50', '2026-06-12 10:23:50', NULL, '63b7bd8220b902524fb879256990dfb1', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXNWWGS3S0RFMFYQC9BWR', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Bridge: fix TCP partial-read frame desync; drain all ready inbound frames per tick', '(description follows in first append)', 'backlog', 'high', NULL, 'server', 'D-225', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '1a5d68b512ba445e1e4d8afc34106920', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXNWWGS3S0RFMFYQC9BWR', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Bridge: fix TCP partial-read frame desync; drain all ready inbound frames per tick', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-01, S-02; citations adversarially verified). +DESYNC (S-01, high): the stream is non-blocking (tcp.rs:48-52); read_framed uses read_exact for the 4-byte prefix and payload with no partial-frame state (framing.rs:36-61); read_exact hitting WouldBlock mid-frame irrecoverably consumes bytes, and receive() maps WouldBlock to Ok(None) (tcp.rs:211) — a frame split across TCP segments permanently desyncs the stream (next read treats mid-frame bytes as a length prefix). Works today only because localhost frames arrive in single segments; BufReader is bypassed via get_mut(). Fix: persistent partial-frame accumulation buffer on TcpBridge (or blocking reader thread feeding a channel). Regression test: deliver one frame in two writes with flush+delay. +DRAIN (S-02, med): receive_bridge_inputs calls receive() exactly once per 50 ms tick (bridge/mod.rs:162, no loop; tick at main.rs:306) — an input batch + AtlasLayerRequest in one window backlogs and drains one frame per tick. Fix: loop receive() until Ok(None) with a per-tick cap. The D-225 atlas channel shares this path, so both fixes gate Atlas streaming reliability. +Extension constraint when touching this code: D-225 amendment 2026-06-12 (tagged envelope for the next inbound type).', 'backlog', 'high', NULL, 'server', 'D-225', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '6ff607cfd4110152e375d51223685837', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP19FFZEVED140S1708W', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Wire the Region→Chunk→Voxel tier into production — ChunkPos→RegionPos mapping, proxy layers, Atlas surfacing', '(description follows in first append)', 'backlog', 'high', NULL, 'server', 'D-239', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'ba71152b74fde9fbe4233090ca6c2526', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP19FFZEVED140S1708W', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Wire the Region→Chunk→Voxel tier into production — ChunkPos→RegionPos mapping, proxy layers, Atlas surfacing', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-27 — the audit''s headline finding; citations adversarially verified). +The D-239 three-carrier chain is implemented and T-1031-harness-verified but has ZERO production call sites: BodyWorldState.regions is written (cascade.rs:100-111) and read only by tests; no function maps a ChunkPos to its covering RegionPos (ChunkPos exists only in chunk_context.rs:67); AtlasLayerResponse carries only Layer1Output (layer_proxy.rs:56-60), so the D-225 proxy cannot serve regions/chunks/voxels and the T-960 Atlas viewer cannot show the tiers that exist. +Scope: (1) ChunkPos→RegionPos mapping — REQUIRES Q-110 (scale anchoring) answered first; (2) region + voxel layers in the D-225 proxy protocol; (3) surface them in the T-960 viewer (additive overlays per D-226). Treat as the spine of remaining Phase-4 work, alongside T-959 (tile fill). +Related: Q-110 (blocker for (1)), T-959/T-987 (tile fill), T-960 (viewer), T-1042 (seam blend), T-1040/T-1041 (voxel bugs). +Audit layer map (verified produce/consume graph, 2026-06-12): +# Layer chain — actual produce/consume graph + +| Stage | Module | Consumes | Produces | Production-wired? | +|---|---|---|---|---| +| L0 Heightmap | heightmap.rs (D-202) | wiki `heightmap.png` 16-bit gray + `sea_level` tEXt | `BodyHeightmap` (f32 [0,1]); downsampled to GRID 512×256 (gen_queue.rs:374-379) | yes | +| L1 Topography | layer1.rs → drainage.rs (D-208), features.rs (D-209), subbiome.rs (D-210) | heightmap | RiverNetwork, DrainageBasins (4–12), flow accumulation, TerrainAnalysis, ≤256 attractors w/ sub-biome+cost+water_bearing | yes | +| L3 Settlement | attractor_matching.rs (D-211/212/213/214/215) | attractors + CityRecords (systems.db `atlas_city_names`) + dominant_faction | CityPlacement {position, archetype, arrangement, founding_orientation} | yes | +| L4 RegionProfile | region_profile.rs (D-239 §1-§8, D-240, T-1023-1027) | seed + BodyParams (planet_class/atmosphere/hydrosphere/tectonic) + TerrainAnalysis | per-region (8×8 grid cells): slope_q/elev_q/ocean_fraction_q, temperature/moisture, precipitation/glaciation/vegetation, river_threshold, 17-zone MorphologyZone → `BodyWorldState.regions` | populated, **never read** | +| L4 QuarterSkeleton | skeleton_gen.rs + district_mix.rs + block_irregularity.rs + tile_condition.rs (D-194/196/197/199/216/217/220/229/233/234) | CityGenerationContext (D-199 read-set + stubs) | QuarterSkeleton: 4×4 blocks (512×512 tiles), zoning, reservations (park/transit-terminal base_z=-1), access points, ±45° corridors (Ribbon/HubSpoke/Mesh), BSP building footprints + BuildingPropertyTags → `BodyWorldState.quarters` | yes (L3→L4 dispatch, plugin.rs:100-131) | +| ChunkContext 64 m | chunk_context.rs (T-1028) | one RegionProfile + seed | basin_direction (seed-random), meander phase/wavelength, has_active_channel, channel_width | **no callers outside tests** | +| VoxelColumn 1 m | voxel.rs (T-1028/1029/1030) | RegionProfile + ChunkContext + domain_warp (±8 m f64→i32 cast) | D-228 axes: TerrainMaterial/FloorMaterial(None-only)/Vegetation/Water/elevation_m/SeasonalCover; 8 family generators; VoxelCache LRU 8192 | **no callers outside tests** | +| Chunk→Tile fill | gen_queue.rs:444-450 | — | `FillChunk` returns immediate no-op success | stub (T-959/T-987 backlog) | +| Client bridge | layer_proxy.rs (D-225) | cache | serves **Layer1Output only**; regions/quarters/voxels not served | yes | + +# Economics → spatial placement bridge + +| Economic input | Source | Spatial consumer | Status | +|---|---|---|---| +| economic_role, population, settlement_class | systems.db `atlas_city_names` (static) | attractor matching score matrix; district_mix 10×9 table; reservations; zone tags | wired | +| dominant_faction | `system_factions` | TerritorialStatus → archetype/arrangement on placement | derived, then **dropped at L3→L4 dispatch** | +| prosperity_baseline_bps | derived D-197 (role+pop+noise; terrain term = 0) | tile_condition bands, entry class, era | wired (partial) | +| world_tier ← system_economy.economic_tier | systems.db | ComplexityTier | stub `Waypoint` (T-1007 backlog) | +| dominant_bulk_class / production_ubiquity | — | roofed coverage / footprints | stub (T-982 in_progress) | +| Live econ sim (D-181 7 signals, EconStateResource) | econ_sim per (system, commodity) | **none** — IPC snapshot + debug only | no path to generation | +| Supply chains / transport → roads, rail | — | — | does not exist | + +Counts: 24 atlas modules; 8/8 voxel family generators implemented; 16/17 morphology zones reachable at region scale (BraidedPlain deferred); cache: 50 bodies (D-203), 8192 voxel columns.', 'backlog', 'high', NULL, 'server', 'D-239', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'b5d7eeaea1c4bf4467ce39a2b93e4432', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP5N42SSGW300FEDTS3M', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Derive ChunkContext basin_direction from the L1 D8 thalweg; fix the false doc comment', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', 'D-239', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '9661de339845395e05ba0fb7fd15378a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXP5N42SSGW300FEDTS3M', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Derive ChunkContext basin_direction from the L1 D8 thalweg; fix the false doc comment', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-36; citations adversarially verified). +derive_basin_direction (chunk_context.rs:211-231) branches only on ocean_fraction_q then picks a direction from seed bits in both branches; the doc comment (:201-210) falsely claims an elev_q-gradient proxy; the module contract (:12-13, :40-42) claims D8-thalweg derivation. BodyWorldState.river_network exists (body_world_state.rs:79) and is never consulted — chunk-scale water has no guarantee of flowing downhill or connecting across the 16-chunk region-seed boundary. D-239 §8 binding law: respect the D8 thalweg. +Fix: compute the covering region''s dominant D8 direction during the RegionProfile pass (DrainageResult is in scope there) and thread it into RegionProfile for derive_chunk_context to read; fix the misleading comments either way. Composes with T-1040 (channel anchor) and T-1042 (seam blend).', 'backlog', 'medium', NULL, 'server', 'D-239', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, 'bc9a55b06e41b82b728e748a18c814c3', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPA5JGWACAGGZ3XJ24K0', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Amend D-203 to the actual cache contract — per-entry size ~5× the budget, pinning never invoked', '(description follows in first append)', 'backlog', 'low', NULL, 'server', 'D-203', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '8089846a1d94dcbadb71337f03e449b1', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPA5JGWACAGGZ3XJ24K0', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Amend D-203 to the actual cache contract — per-entry size ~5× the budget, pinning never invoked', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-38; low severity — citations agent-reported, spot-check at pickup). +D-203 budgets ~100KB/entry, ~5MB total, and a player-location pinning policy. Reality: BodyWorldState stores the full 512×256 f32 working raster (~524KB, gen_queue.rs:374-379 via cascade.rs:103) plus regions + quarters per body — ~26MB+ at CACHE_CAPACITY=50 (body_world_state.rs:26); .pin()/.unpin() exist but the only caller is their own unit test (body_world_state.rs:258). Capacity and LRU semantics match the decision. +Action: amend D-203 with current per-entry sizes (the bigger raster is a deliberate D-202 consequence) or store a decimated display raster; wire pinning to the player-location system when Phase-5 tracking exists (note it on T-749 scope then).', 'backlog', 'low', NULL, 'server', 'D-203', '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '050def8ff073db4453d3f708603b93c8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPE8FR7TGEM7X6QVPV4M', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Refine T-961 into per-asset-class stories, each gated on a written brief', '(description follows in first append)', 'backlog', 'high', NULL, 'visual', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:58', NULL, '3cafbe48a73971b296864c88e3f21187', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPE8FR7TGEM7X6QVPV4M', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Refine T-961 into per-asset-class stories, each gated on a written brief', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-43; citations adversarially verified). +T-961 (two-sentence description, no acceptance criteria, no brief links) is the only asset-production ticket under T-750, while the epic names eight classes; cars, barns, TVs, billboards appear in NO ticket at all (verified against the full corpus). Refine into child stories per class — station walls, rural walls, doors, floors, furniture/props, street furniture (lamp posts), signage/screens (billboards/TVs), rural structures (barns) — each gated on a one-page brief; explicitly record which classes are deferred (cars: see Q-067 audit note). Decide Q-119 (generic-parent placeholder set as first milestone) before sequencing. +Audit per-class status matrix (verified 2026-06-12): +# docs/assets/ survey (13 files + downloads/) + +| File | One-line summary | +|---|---| +| README.md | Master index: audio/visual/video pipelines, status vocabulary (planned/in-progress/placeholder/final), structure that promises visual/{sprites,furniture,tilesets,icons,effects}.md | +| _templates/audio.md | Row + detailed-entry template for audio assets | +| _templates/sprite.md | Row + detailed-entry template for sprites (ID prefixes SPR/FUR/TILE/ICO/FX, status, method, directions columns) | +| _templates/video.md | Row + detailed-entry template for video | +| audio/README.md | ACTIVE production-status catalog — per-category counts table (12 assets tracked), generation tools, bus architecture | +| audio/palette.md | Sonic style bible | +| audio/ambient.md / sfx.md / ui.md | Per-category audio asset tables | +| visual/README.md | STUB — links 5 category files that do not exist, all counts 0 | +| visual/palette.md | STUB — 4 bullet decisions (D-019/D-033/D-045, "functional warmth"), defers to art-direction workshop | +| video/README.md / palette.md | Stubs | +| downloads/ | Purchased character sources (Quaternius Universal Base Characters, Modular Character Outfits FBX) — characters only | + +# Per-asset-class matrix + +| Class | Written brief | Style guide | Naming/res conventions | Gen path | Produced assets | Tickets | +|---|---|---|---|---|---|---| +| Walls (station) | art-direction workshop-outcomes.md §3.3 (v0.1.1 set, pre-cascade) + docs/design/placeholder-art-spec-v01.md §2.1 | visual-grammar-v01.md §1/§4.3, workshop-outcomes §1.8 era palette (partly superseded by D-235), D-235 WallMaterial vocab | renderer/README.md:80-95 (`__.png`, 1024→256→64 chain) | working — renderer/models/wall_structural.tscn rendered | wall_structural ×4 dirs in client/assets/sprites/; wall_bar_green model unrendered; 2 textures | T-961 (backlog), T-988 (token vocab, backlog) | +| Walls (rural) | none found | D-235 tokens only (timber/rammed-earth etc.) | renderer/README.md (generic) | same path, unused | none | T-961 text mention only | +| Doors | placeholder-art-spec-v01.md §2.1 (procedural rects, v0.1) + workshop-outcomes §3.3 `door_sliding` | none for generated world | none for open/closed state frames | same path, unused | none | T-979/T-998 (DoorSpec — logical only), T-961 | +| Floors | placeholder-art-spec-v01.md §2.1 + workshop-outcomes §3.3 (4 floor sprites) | D-228 FloorMaterial axis (open vocab) | 64px visual tile (placeholder-art-spec §1) | same path, unused | none — client/assets/tilesets/ is .gitkeep only | T-959 (tile fill, logical), T-961 | +| Styled buildings | D-232 + D-235 + wiki/economics/architecture_trait_catalog.toml (T-1005 done, ~35 visual bundles) | D-235 material/color-register grammar — tokens only, no rendered art direction | token→fallback-parent chain (catalog header :34-44) | no model/texture path defined for building exteriors | none | T-977, T-988, T-994, T-1004 (all backlog), T-1005 (done) | +| Furniture | docs/assets/visual/furniture.md MISSING (linked); workshop-outcomes §3.3 lists 8-10 objects (pre-cascade) | era table §1.8 only | character-asset-organization.md explicitly excludes furniture ("follow Trellis spike conventions") | proven in spike | spikes/3dpipeline/models/furniture/ ×3 GLB (unpromoted); zero in client/assets | T-961, T-995 (ObjectTag vocab, backlog) | +| Items | docs/design/icon-set-v01.md (HUD/inventory icons only) | D-086 icon constraints | SVG icon_ prefix (client/assets/icons/) | n/a for icons | 13 SVGs in client/assets/icons/ | none for in-world item sprites | +| Cars/vehicles | none found | none | none | spike only | spikes/3dpipeline/models/props/vw_beetle.glb (spike) | none — Q-067 open ("driveable vs NPC traffic?") | +| Lamp posts | none found (zero repo hits) | none | none | unused | none | T-961 text mention only | +| Barns | none found (only T-750 epic text) | none | none | unused | none | none | +| TVs | none found (only T-750 epic text) | none | none | unused | none | none | +| Billboards | none found (only T-750 epic text; other hits = LOD impostors) | none | none | unused | none | none | +| Characters (reference class — the working model) | docs/architecture/character-asset-organization.md + docs/design/character-visuals-spec.md | yes | full (manifest.json, seg_ naming, body-type keys) | proven end-to-end | 1002 files in client/assets/characters/ | done | + +# Generation path (verified files) +image-gen (.claude/skills/image-gen/SKILL.md + scripts/image_connector.py, Gemini) → glb-gen (SKILL.md + tooling/db/trellis_connector.py + tooling/trellis-batch.sh + Blender postprocess scripts) → sprite-gen (SKILL.md + scripts/render.sh) → renderer/ (project.godot, render_scene.tscn, render_export.gd; D-019 camera, 3-light rig, 1024/256/64 chain) → client/assets/sprites/. renderer/output/ holds only .gdignore (intermediates gitignored). + +# Produced assets in client/assets (non-.import files) +audio 16 · characters 1002 · fonts 3 · icons 13 · planets 7 · sprites 9 (npc_generic ×4, wall_structural ×4, .gitkeep) · theme 1 · tilesets 1 (.gitkeep only)', 'backlog', 'high', NULL, 'visual', NULL, '2026-06-12 10:40:58', '2026-06-12 10:40:59', NULL, '759d17b938cfb9c12e8e2f9d1fae408c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPJ910NNR5T2R9F9NWQR', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Create the visual production-status catalog; fix glb-gen production path + naming conventions', '(description follows in first append)', 'backlog', 'high', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b0278edb8f6556348eb274f7d5176b17', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPJ910NNR5T2R9F9NWQR', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Create the visual production-status catalog; fix glb-gen production path + naming conventions', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-44 + S-50 task half; citations adversarially verified). +CATALOG: T-750''s deliverable includes an "asset creation catalog with production status". docs/assets/visual/README.md:14-20 links sprites.md/furniture.md/tilesets.md/icons.md/effects.md — none exist. The row template is ready (docs/assets/_templates/sprite.md:10-24, SPR/FUR/TILE/ICO/FX prefixes + status column) and the audio side shows the working model (docs/assets/audio/README.md:14-19). Instantiate the five files, seed with existing assets (wall_structural, npc_generic, 13 icons) + the T-750 class list as planned rows, and make updating them part of /sprite-gen. +GLB-GEN PATH: .claude/skills/glb-gen/SKILL.md:115 names client/assets/models/ as the production destination — the directory does not exist; proven spike GLBs sit unpromoted (and are now local-only per D-241, so promotion is also preservation). Define the production model directory + promotion convention (mirror the characters/ manifest pattern), update the SKILL. +CONVENTIONS: extend naming beyond entity/wall sprites — Godot TileSet resource organization (client/assets/tilesets/ is .gitkeep-only), door state-frame suffixes, multi-tile footprint metadata, renderer/textures/ naming keyed to D-235 tokens.', 'backlog', 'high', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '9eea295dcbd97bccdb8034fb68993b78', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPPHC9FZ4T0GNKR615PR', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Author one-page briefs (or record formal deferral) for lamp posts, barns, TVs, billboards', '(description follows in first append)', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'a08ec3974c6918b655d0162592766ce4', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPPHC9FZ4T0GNKR615PR', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Author one-page briefs (or record formal deferral) for lamp posts, barns, TVs, billboards', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-46; citations adversarially verified). +Four asset classes named in T-750''s epic text have no brief, no style guidance, no convention, no ticket beyond the epic sentence, and zero produced assets — repo-wide grep for lamp posts returns zero hits in any .md/.toml/.rs/.gd. Either author one-page briefs per class (audio _templates pattern: function, era/zone placement, footprint, palette, D-235 token parent) or record deferral so the epic stops implying scope. Cars are NOT in this ticket — gated on Q-067 (see its 2026-06-12 audit note).', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '15ed194dfe50c13df32029fce912c9fb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Write the Phase-4 visual style bible into docs/assets/visual/palette.md', '(description follows in first append)', 'backlog', 'medium', NULL, 'visual', 'D-235', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'bb2e8e7ee2652e0c73bd1e8540a87800', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPV39JX54HYP83RZJFDM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Write the Phase-4 visual style bible into docs/assets/visual/palette.md', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-48; citations adversarially verified). +Current style guidance is: a stub (palette.md:10,23 "to be populated"), a pre-cascade workshop whose per-class guidance targets the dropped hand-made bar scene and whose era-palette model D-235 explicitly reframed (era = maintenance/wear, not a material gate — architecture.md:1705), and a third divergent style block inside the image-gen skill (SKILL.md:60-79: toon-shaded, near-white base, Invisible Inc reference). No document reconciles these for the D-235 token vocabulary the generator will request. +Write: per-token-family art direction (WallMaterial/RoofForm/FacadeRhythm/StreetSurface registers), surviving constants (D-019 camera, D-043 outline/resolution chain, D-033 tinting, "functional warmth"), explicit supersession note for the workshop §1.8 era table. Owner: Araminta (D-235 co-maintainer).', 'backlog', 'medium', NULL, 'visual', 'D-235', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '001c313c9c1544506ced14ec030da162', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPZ0ZTM1QQXD5K972CMM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Rewrite docs/briefings/araminta.md around the Phase-4 asset pipeline', '(description follows in first append)', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'b61a448bedd06f4a8f9a57bc4d86a784', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXPZ0ZTM1QQXD5K972CMM', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Rewrite docs/briefings/araminta.md around the Phase-4 asset pipeline', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-49; citations adversarially verified). +The visual-art-director briefing is dated 2026-03-13 (:7): it references the retired tooling/db/ticket CLI (:14-15), frames work around the dropped v0.2 pivot (:17), cites a nonexistent /asset-gen skill (:78), and predates D-228/D-232/D-235, the trait catalog, and the whole T-750 asset scope — while D-235 names Araminta co-maintainer of the material vocabulary (architecture.md:1711) and T-995 assigns her the ObjectTag co-maintenance. Rewrite around: D-232/D-235 vocabulary co-maintenance, the production-status catalog ownership, the image-gen → glb-gen → sprite-gen toolchain (+ D-241 storage boundary), and the no-in-world-rendering-until-Phase-5 rule.', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'a171ca1e2722d72bcd1a92d227eca7b2', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ3EC348VN37Q2X8JXM0', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Fill GJ-280B (Sova) through the standard wiki pipeline; resolve the canon triplication', '(description follows in first append)', 'backlog', 'high', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '361d0883192ad48fa3fa2258616cfe92', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ3EC348VN37Q2X8JXM0', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Fill GJ-280B (Sova) through the standard wiki pipeline; resolve the canon triplication', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-51 + S-58 rider; citations adversarially verified). +The player starting system is the only stub among 302: GJ-280B/index.md:4 stub banner, all-em-dash profile (:11-17), no bodies/ directory, no markers.json, no globe renders, no Supply Dependency/Silence Topic/Calibration Note — while 301/301 other systems are fully dressed. Phase-1 epic T-746 closed done over this gap. Sova canon is meanwhile triplicated: the wiki stub, wiki/corporations/sova-station-works.md:17-23, and docs/design/sova-station-profile.md ("canonical", 2026-02-25). +Scope: author through the standard pipeline (scaffold_bodies.py + atlas generation + prose pass), folding in docs/design/sova-station-profile.md and sova-texture-appendix.md; wiki becomes canonical; both design docs then get superseded-with-pointer markers (they were deliberately kept active in the 2026-06-12 docs sweep pending this fill). Phase-4 relevance: Sova is the Phase-5 start location — its generation inputs (heightmap, bodies, markers) must exist for the cascade.', 'backlog', 'high', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '2d549675e4487a1d478b0dd50e0f588a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ7P014H0PM4QWZFTWN4', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Clothing asset pipeline: base meshes × shape keys × AI retexture × region tints, Surface-Deform batch fit', '(description follows in first append)', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '143e21a295a4c4bd8619024dc1dff5c1', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQ7P014H0PM4QWZFTWN4', 'story', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Clothing asset pipeline: base meshes × shape keys × AI retexture × region tints, Surface-Deform batch fit', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C4; gated on Q-120 — garment-token vocabulary). +The validated production recipe (Tyre research, spikes/quaternius-aesthetic/reviews/ai-clothing-pipeline-research.md:509-527, 614-628): ~30 base meshes × 4-16 shape-key variants × AI texture variation × region-mask tints ≈ 20,000 unique visuals. Trellis CANNOT make garments (sculptures, not fitted clothing; auto-rigging failed at 4-22% vertex match — VERDICT.md:115). D-162 fixes the fit model: author on reference body, offline Surface Deform per body type. +Stories on refinement: (1) base-mesh acquisition (Quaternius packs + hand-authored fill to ~30); (2) shape-key variant authoring; (3) texture-variation loop through the self-hosted stack — NOTE: the research assumed Meshy retexture credits; validating a LOCAL retexture path is an explicit sub-task, not assumed; (4) region-mask + tint conventions per Q-120 tokens; (5) Surface-Deform batch fit to the 11 body types + manifest registration (client/assets/characters/clothing/ pattern exists with the 4-item peasant set). Each garment lands as production-status catalog rows. +Related: Q-114/Q-115 (server contract), Q-121 (who wears what), the corp uniform spec ticket.', 'backlog', 'medium', NULL, 'visual', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '8da4fc9b51b06614c2c2c48ec1454893', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQBTNGTDMYE6EHVA48PG', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Author corp uniform/dress specs: Workshift Apparel, Shetland Wool, Kalahari Leatherworks, thrds', '(description follows in first append)', 'backlog', 'low', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '1011f33d615f3b8d0c0c04649a893e36', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQBTNGTDMYE6EHVA48PG', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Author corp uniform/dress specs: Workshift Apparel, Shetland Wool, Kalahari Leatherworks, thrds', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C5; corp files verified to contain zero dress specification). +Four apparel corps have rich supply-chain lore and no uniform/dress specs: wiki/corporations/workshift-apparel.md (HeavyWork/FieldWork/StationWork lines; institutional contracts ≈70% revenue — the contract lore IS the uniform-assignment rule, write it as data), shetland-wool.md, kalahari-leatherworks.md, thrds.md. Add a spec section per corp page (or wardrobe-catalog stanzas per Q-120): silhouettes, palette/marks, which roles wear which line. Gameplay hook preserved: worn HeavyWork gear = exposure history (the respiratory-sensitizer scandal becomes wearable evidence — see Q-115). +Sequence after Q-120/Q-121 decide the vocabulary + canon home.', 'backlog', 'low', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'dfe0f8f3bda3d6f510fd60da42c65a44', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQGAX5GT4PTTBQYGJCV4', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Triage the Phase-4 question set before T-959 starts: Q-102, Q-103, Q-105, Q-109', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '965ad24ea067cd931bd88a8f635f0c22', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQGAX5GT4PTTBQYGJCV4', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Triage the Phase-4 question set before T-959 starts: Q-102, Q-103, Q-105, Q-109', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-64 remainder; verified: all four open with zero linked tickets). +The remaining Phase-4 spine is T-959 (Layer 5 tile fill) → T-962 (validation + Phase-5 gate). Four open architecture questions sit directly under that work with no owners: Q-103 (tile-mutator op schema — needed before T-959 Layer 5), Q-102 (cohesion-matrix seam-free variation — needed for tile fill; relates to T-1042), Q-105 (region seasonal/clock state), Q-109 (generation-source dispatch: planet/station/mod/save). Answer or ticket each before T-959 kicks off; Q-103 and Q-102 are the most load-bearing. Also now open from the audit: Q-110 (scale anchoring — blocks the spine ticket) and Q-111 (live-econ coupling — gates T-1007/T-982 sequencing).', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '60d7cdbc61138b6f06fdb7a897fd54bb', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQN3J95WE3GZJJEF3HG0', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Disposition D-179/D-183 (economics process decisions); backfill question dates going forward', '(description follows in first append)', 'backlog', 'low', NULL, NULL, 'D-179', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'a0ca74f2bd30f8389075b142c65c0f84', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQN3J95WE3GZJJEF3HG0', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Disposition D-179/D-183 (economics process decisions); backfill question dates going forward', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-68 remainder; low severity). +D-179 (Stability Acceptance Criteria) and D-183 (Iterative Economics Development Cycle) mandate ongoing verification of the econ sim but have zero linked tickets and Phase 2 is closed; whether stability criteria get re-checked when Phase-4 generation starts reading economic state (D-199 read-set, Q-111) is untracked. Decide: re-validate under Phase-4 load (ticket it under T-962) or amend both records as satisfied-at-Phase-2-close. +Also: question records mostly lack raised dates (pql decisions list --type question emits empty dates), making staleness unmeasurable — add "raised" dates to new Q records going forward (the 2026-06-12 batch Q-110..Q-122 already does this) and consider a validate rule.', 'backlog', 'low', NULL, NULL, 'D-179', '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '366029950e126d2798b8d93a6059678c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQS7HFJJHDW5FBM609EG', 'task', '06FB0TNSRXX29H5X0EB0F0GBW4', 'Extract character_creation.gd (2,442 lines) into camera rig / manifest loader / appearance state', '(description follows in first append)', 'backlog', 'low', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '2238ebe85b8d85048a09039110ac0991', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQS7HFJJHDW5FBM609EG', 'task', '06FB0TNSRXX29H5X0EB0F0GBW4', 'Extract character_creation.gd (2,442 lines) into camera rig / manifest loader / appearance state', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-23; Phase-5 surface — do NOT refactor before Phase 5 reopens it, per D-166). +client/ui/meta/screens/character_creation/character_creation.gd is 2,442 lines / 105 funcs — ~3× the next-largest production script — mixing camera control (_cam_zoom_toward_cursor, _update_camera_angle), manifest loading, and UI state in one MetaScreen. It is a meta screen (D-169 component rule does not apply) and part of the frozen character/rendering surface. Extract when Phase 5 starts.', 'backlog', 'low', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '15abdd277a9134da743e2a3c80b9a178', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQXH3Z2VEDSV1636XW58', 'task', '06FB0TNSRXX29H5X0EB0F0GBW4', 'Add the CharacterVisualDescriptor wire struct to bridge/types.rs + MessagePack round-trip test', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '19a7439ceaa617785eb3f33b5201919d', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXQXH3Z2VEDSV1636XW58', 'task', '06FB0TNSRXX29H5X0EB0F0GBW4', 'Add the CharacterVisualDescriptor wire struct to bridge/types.rs + MessagePack round-trip test', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-42; verified including git history). +client/scripts/rendering/character_visual_descriptor.gd:5 says its fields "must match server/src/bridge/types.rs" — NO such struct exists there and git log -S shows none ever did; VisibleEntity carries only entity_id/position/kind/visibility/relationship/observation/tell_state. The comment is aspirational. +Scope (after Q-114 decides the generation contract): mirror struct in types.rs; MessagePack round-trip test against the GD from_dict/to_dict; entity-snapshot field gated by perception (you see clothes only when you see the NPC). Quick interim action: soften the .gd comment so it stops claiming a contract that does not exist.', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '750c8f04d6aafb6a88e16f3ad6df1ab6', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR27XGNCP92JN7BDQ454', 'task', '06FB0TNSRZGGNZMAP8GDMXSCMW', 'Wardrobe assignment in NPC generation — deterministic (seed, culture, role, employer, prosperity) → garment tokens', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '49c552648add593bb6f2b76ddb5bcbd1', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR27XGNCP92JN7BDQ454', 'task', '06FB0TNSRZGGNZMAP8GDMXSCMW', 'Wardrobe assignment in NPC generation — deterministic (seed, culture, role, employer, prosperity) → garment tokens', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-C6; gated on Q-114/Q-115/Q-120). +workers/stubs.rs:86 is the declared home ("real implementation pre-generates NPC appearance, inventory, mood"); the 10-axis generation in npc/generate.rs shows the deterministic per-axis pattern to extend. Wardrobe = pure function of (entity seed, culture register, role, employer, prosperity band) → token per slot (Q-120 vocabulary) → manifest item id + tints. Assignment logic per Q-121: role picks garment family (corp institutional contracts = workforce uniforms = information), culture/system picks materials/registers, prosperity band picks condition/wear, faction/corp adds marks. Pairs with the bridge wire-struct ticket (Phase 5) and the Q-114 contract.', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '6c991a1a32b8890ed41b4a031abcc8c8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR79W28XNN1TB7HKGBP8', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Split the input.rs and dialogue.rs god-module dispatchers', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '235773c7e91589b0cc916fed5aa0f30c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXR79W28XNN1TB7HKGBP8', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Split the input.rs and dialogue.rs god-module dispatchers', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-03; citations adversarially verified). +simulation/input.rs: 2,739 lines, imports 9 domains (bookmark, bridge::debug, knowledge, settings, economy, interaction, inventory, movement, save_io), 9× type_complexity allows (:485-1120) + 1 too_many_arguments — the dispatch hub for every player verb. simulation/dialogue.rs: 2,785 lines, 3 allows. +Extract per-domain input handlers into their owning modules behind a thin dispatch table; split dialogue into talk-selection / confrontation / response-assembly. Mechanical, no behavior change; gate with the existing determinism.rs byte-identical goldens.', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '014d95390a4cafb49f668e06f6f3cd60', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRBRFW4MH5G8C0X12YGR', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Workers pool: add tests, fix panic-loss, correct the false "tested" doc claim', '(description follows in first append)', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'becd1955a353c824f35670c0842471f3', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRBRFW4MH5G8C0X12YGR', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Workers pool: add tests, fix panic-loss, correct the false "tested" doc claim', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-05; verified — zero tests exist for BackgroundWorkerPool anywhere). +workers/stubs.rs:7 claims the pool infrastructure is "real and tested" — false. pool.rs:8-13 documents that a worker-thread panic silently loses in-flight requests (TODO #843); for ModalLock consumers that means the player waits forever. SimulationPlugin spawns 4 live stub threads every session (simulation/mod.rs:85-87) for Phase-5+ functionality. +Do now: correct the doc claim; unit tests (spawn/push/poll/shutdown + worker-panic). Before any ModalLock consumer ships (Phase 5): heartbeat/re-enqueue or downgrade ModalLock to an error path. Optional: defer thread spawn until a real handler registers.', 'backlog', 'medium', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '7a1639eb9162f046e21c3f38aa46652a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRG23G1RAREVHQJ14BWC', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Server hygiene batch: exemption contracts, dead deps, generator_spike quarantine, save/load ordering, economy.rs tests', '(description follows in first append)', 'backlog', 'low', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'c8306d2cd939c3e989d4d6f31954e88a', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRG23G1RAREVHQJ14BWC', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Server hygiene batch: exemption contracts, dead deps, generator_spike quarantine, save/load ordering, economy.rs tests', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-06, S-07, S-08, S-09, S-12; low severity — spot-check citations at pickup). +1. S-06: add the consumer contract ("every consumer must sort before state/wire use") to the three perception disallowed-types allows (shadowcast.rs:17, query.rs:11, interpretation.rs:9). +2. S-07: delete unused bytemuck (Cargo.toml:30, zero references); fix the stale rayon comment (says "not yet called"; used in atlas/gen_queue.rs:192-228). +3. S-08: delete or feature-gate bin/generator_spike.rs (1,153 lines reimplementing npc/generate.rs outside ECS, 3 TODO(integration) duplication admissions); extract the shared surname corpus copied between generate_brands/names.rs and generate_corporations/names.rs (already drifted; both feed the systems.db stamp); prune or justify the 24 allow(dead_code) in generate_corporations. +4. S-09: pin execute_save_load with a lower-bound constraint (currently only .before(compute_observer_snapshot), simulation/mod.rs:106-114 — the scheduler may legally run it before Input, changing what a save captures); note the exclusive-system exception in tick_phases.rs rules. +5. S-12: unit tests for simulation/economy.rs signal derivation (382 lines, no cfg(test); fixtures set economy_snapshot: None) — trend windowing, first-tick baseline, zero-demand stockpile edge.', 'backlog', 'low', NULL, 'server', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'cac03779bc12bad69a2f2de713c5e536', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRMET5CBB0ENBZGJQKX0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Add a client-test gate to pre-push — the 63-file GDScript suite never runs automatically', '(description follows in first append)', 'backlog', 'high', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '84194a9682318e89ce9643c16afabb95', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRMET5CBB0ENBZGJQKX0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Add a client-test gate to pre-push — the 63-file GDScript suite never runs automatically', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-13; citations adversarially verified). +The pre-push hook is the ONLY automatic correctness gate (its own comment, .config/hooks/pre-push:101-110) and there is no CI — but for client/ changes it runs only a headless parse check (:38-54). The gdUnit4 suite (tests/run-godot: 300s-capped, one-line JSON summary, agent-safe) is invoked only manually. A GDScript regression reaches main unverified, while team-patterns.md claims the gate is "deliberately comprehensive". +Fix: run tests/run-godot in pre-push when CLIENT_CHANGED > 0 — or record manual-only explicitly and fix team-patterns.md. Related decision: Q-116 (gdlint blocking). Prerequisite worth checking: T-973 (pre-existing bare-run failures, under this initiative) so the new gate starts green.', 'backlog', 'high', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '5b1d44406a1ed829b8dd23ff02f4113e', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRRDGJ5GFPGHZV3WS0D0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Wire tooling tests into a gate: make test-tooling + pre-push on tooling changes', '(description follows in first append)', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '2c8ec25fd9d236f28a4362bd3cfb0701', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRRDGJ5GFPGHZV3WS0D0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Wire tooling tests into a gate: make test-tooling + pre-push on tooling changes', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-18; citations adversarially verified). +22,340 lines of tooling Python (including the systems.db generator) are verified only by a 4-rule ruff subset (pyproject.toml:26-31: E9/F401/F811/F821); zero pytest anywhere; the one real test (tooling/planet-gen/test_sim_determinism.py, guarding the expensive 271-body bake, exit codes 0/1/2) is wired into nothing. +Fix: make test-tooling = test_sim_determinism.py + import_economics --dry-run against the committed DB; call from pre-push when TOOLING_CHANGED > 0; widen the ruff selection.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '32eaced9201f8ed58a608e4a056e5ebe', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRX067NBNG76MV84MDQ0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Split the 2,617-line import_economics.py monolith; single shared generator-source registry', '(description follows in first append)', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'd39639902762616c3bf57562f1e233bc', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXRX067NBNG76MV84MDQ0', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Split the 2,617-line import_economics.py monolith; single shared generator-source registry', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-19; citations adversarially verified). +tooling/economy-db/import_economics.py (2,617 lines, 31 top-level defs) owns schema migration, brand regeneration (shells to Rust), 16 import steps, validation, and the meta stamp. Its source-file list is hand-maintained in THREE places guarded only by comments: IMPORT_ECONOMICS_SOURCES (:81-99), GENERATOR_SOURCES (tooling/check-systems-db-stamp:48-63), and the /pr-push watch list (.claude/skills/pr-process/SKILL.md:222-243). Error handling itself is good (single transaction, rollback, distinct exit codes at :2350-2613). +Fix: extract one shared tooling/generator_sources.py imported by the script + stamp checker and read by /pr-push; then split importers/validators into modules under tooling/economy-db/; finish type hints during the split. Also fold in S-25''s connector dedup: move CONFIG_PATH/load_config/get_base_url into tooling/db/common.py (currently copy-pasted across audio/trellis/image connectors).', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '93093fc2f768f079757d4ef22bc8cdf0', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS18RSVRHC7Y9TAX06HG', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Client hygiene batch: orphan .gd.uid files, time_display removal rider, _format_pop dedupe, skip_test_ triage', '(description follows in first append)', 'backlog', 'low', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'a5eb748e9057655cdb239f1ab0320cf3', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS18RSVRHC7Y9TAX06HG', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Client hygiene batch: orphan .gd.uid files, time_display removal rider, _format_pop dedupe, skip_test_ triage', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-21, S-22, S-24; low severity — spot-check citations at pickup). +1. S-21 now: delete 7 tracked orphan .gd.uid files whose scripts are gone (client/scripts/rendering/fog_renderer.gd.uid; client/ui/{bug_report_dialog,character_select,debug_console,loading_screen,main_menu,settings_dialog}.gd.uid). Phase-5 rider: remove time_display.gd/.tscn + its 199-line test (superseded by the merged HUD row per hud.gd:4 / #786) with the Phase-5 rendering pass, not before (D-166). +2. S-22: deduplicate _format_pop — byte-identical 12-line implementations in planet_screen.gd:105-116 and system_screen.gd:685-696 (plus _format_radius) into a shared atlas helper. +3. S-24: triage the 9 permanently disabled skip_test_ functions (test_sprint2_proof.gd:117,147,169; test_etalk_overlay_sprint17.gd:267-273; test_client_p2.gd:70,100,198) — re-enable, delete, or attach a T-id; convert the push_warning-then-return soft-skip pattern (test_fog_shader, test_audio_sprint13, test_monologue_display, test_input_roundtrip:54) to gdUnit4 skip reporting so missing prerequisites are visible in the JSON summary, not silently green.', 'backlog', 'low', NULL, 'client', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '11940c97f3dff188beedb2e11f43f657', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS5YZ04F4CPPYNZS4Z2W', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Docs-drift sweep: one-generator reality, dead check-protocol target, DEVOPS hook sections, project.yaml version, stale code comments', '(description follows in first append)', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'e8ca3e11543d0f54b3b1df66bc9e6141', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXS5YZ04F4CPPYNZS4Z2W', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Docs-drift sweep: one-generator reality, dead check-protocol target, DEVOPS hook sections, project.yaml version, stale code comments', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-11, S-15, S-16, S-25, S-26, S-39; S-15/S-16 adversarially verified). +1. S-15: docs/DEVOPS.md:211-230 documents three generators, .claude/rules/asset-pipeline.md:22,27,36 documents two with a literal command for a file that does not exist (tooling/planet-gen/generate_atlas.py, retired #951/D-223); truth is one (import_economics — Makefile:334-352, stamp registry). Fix both + the CLAUDE.md asset-pipeline snippet. +2. S-16: delete make check-protocol (Makefile:123-130 greps constants deleted under D-192 via T-874/T-875 — empty==empty always passes); drop from build dep (:132) and help (:42). +3. S-25: rewrite DEVOPS.md hook/config sections from current sources (pre-push table omits cargo test/deny/clerk + advisory gdlint status; .config/ description never materialized; pre-commit row omits pql validate/export). +4. S-26: project.yaml says version 0.2.0 under the 0.{phase}.{n} scheme with Phase 4 active, and its description still narrates the v0.1 Sova slice — bump to 0.4.n (or document the bump trigger) + refresh description. +5. S-39: update voxel.rs module doc (:41-48) and MorphologyFamily variant comments (:256-280) still claiming 7 families are unimplemented stubs (T-1029 landed them all); fix cascade.rs:219 TODO citing closed T-1028 (now tracked by T-1044). +6. S-11: comment sweep — main.rs:126-127 claims a protocol_version handshake that D-192 removed; npc/relationships.rs:92 TODO(v0.2); chunk_streaming.rs:6,21-22 v0.3+ — rephrase version targets as phase numbers.', 'backlog', 'medium', NULL, NULL, NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '39cb0a32123855d2006c94c132aa8612', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSA4WFXPD21YK7N8SF60', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Fix 2,131 broken heightmap.png body-page links — conditional scaffold link + regenerate', '(description follows in first append)', 'backlog', 'medium', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '9cfbd41687054da3d55865b940bb7594', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSA4WFXPD21YK7N8SF60', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Fix 2,131 broken heightmap.png body-page links — conditional scaffold link + regenerate', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-53; counts independently reproduced by verifier). +The body-page scaffold links ![Heightmap](heightmap.png) for all non-gas-giant bodies (scaffold_bodies.py:94-96) but heightmaps exist for only 267 bodies (vs 2,398 reliefmap.png / 3,256 globe.png) — 2,131 of the wiki''s 2,180 broken links are this one pattern, rendered as dead images in the implant wiki view. Fix: make the link conditional in the scaffold and regenerate the Visual section of body pages (or backfill heightmaps where Phase 4 wants them anyway — they are a generation input).', 'backlog', 'medium', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'f18205da33c6ad487454ce1bac6afb3e', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSEC1F0RKJVH7JVPS8NW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Wiki sweep: real link breaks, stale nav surfaces, GOVERNANCE/template reconcile, Sol legacy markers, triangles index', '(description follows in first append)', 'backlog', 'medium', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, '1aa8a8377eae25a54a831d3e3aca41d8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FBPTXSEC1F0RKJVH7JVPS8NW', 'task', '06FBPPMZNNEV052DBYYY3A897C', 'Wiki sweep: real link breaks, stale nav surfaces, GOVERNANCE/template reconcile, Sol legacy markers, triangles index', '(description follows in first append) + +Filed 2026-06-12 from the fable-ous.md audit (S-54, S-55, S-56, S-59; S-54/S-55/S-56 adversarially verified, S-59 agent-reported). +1. S-54 (~26 real breaks): knowledge/→concepts/ rename leftovers (3 contraband files, triangles/hub-power.md:420, authoring/monologue-guide.md ×7); pre-governance decisions/ anchors (monologue-guide.md:834-836); 9 phantom companion-system links in star-systems/catalog.md (index.md handles the same companions correctly as unlinked text); factions/cygni-b-combines.md absent (linked from stalownia-kowalski.md:111); concepts/entity-attributes.md:280 wrong relative path to an existing doc. +2. S-55: wiki/index.md:12 claims "10 fully written" vs ~301 reality; corporations/index.md links 38/155 (117 orphaned); zero nav link to economics/ (39 md + 20 TOML, the primary generator source); 25 station-level gttr-*.md orphaned from their system pages. Regenerate counts from the catalog (or let wiki_sync own them); autogenerate the corp index from frontmatter. +3. S-56: wiki/GOVERNANCE.md:39-54 prescribes a star-systems/{system}/{station}/{district} hand-authored tree that has zero instances, and _templates/star-system.md:1-18 mandates frontmatter that 0/302 system pages have — rewrite both to the generated model (wiki_sync.py: DB owns structured fields, wiki owns prose) or decide system pages should carry frontmatter and have wiki_sync emit it. +4. S-59: convert the 4 pre-D-223 geometry-bearing Sol markers.json (GJ-0 bodies, authored coordinates/populations) to names-only, moving the authored data to the Sol special-case home; add wiki/triangles/index.md or de-link it from wiki/index.md:19. +Audit wiki survey (verified 2026-06-12): +# wiki/ directory map + +| Directory | Files | Format | Machine-readable (feeds DB)? | Completeness | +|---|---|---|---|---| +| star-systems/ | 3,262 md + 2,398 json + 5,921 png | md (no frontmatter on system pages; YAML frontmatter on body pages), markers.json, png | YES — body frontmatter (axial_tilt → import_economics.py:1286), markers.json city names (:1451), gttr.md → gttr_hook (populate_gttr_hook.py); system infobox/bodies tables generated FROM systems.db (wiki_sync.py) | 302 system dirs; 301 full prose (Supply Dependency 301, Silence Topic 288, Calibration Note 261); 2,625 body pages all with EMPTY Description; 302 gttr.md + 6 corridor + 24 station GTTRs; heightmap.png only 267 vs globe 3,256/reliefmap 2,398; GJ-280B = sole stub | +| economics/ | 39 md + 20 toml | TOML (source of truth) + md prose | YES — commodities.toml, production_chains.toml, currency_zones.toml, specialization_vocabulary.toml (27), system_specialization.toml (240/301 pins), architecture_trait_catalog.toml (28 templates) + bias, brands/generated_brands/tier1/tier2 | Complete for current decisions (D-173..D-182, D-232, D-237; T-1016 done); not linked from wiki/index.md | +| corporations/ | 156 md | md + YAML frontmatter | YES — frontmatter slug/title/headquarters/tags/scope → corporations + corp_presence (import_economics.py:734-790, D-182 wiki-is-truth) | 155 canonical pages ~8-16KB; index.md lists only 38 (117 orphaned from nav) | +| factions/ | 9 md | md + frontmatter | No (prose; dominant_faction comes from economics TOML) | Complete: 6 major + 1 regional + 1 local worked example, all canonical, clean index | +| technology/ | 7 md | md | No | Complete (6 entries + index) | +| contraband/ | 4 md | md + frontmatter | No | Complete (3 entries + index); stale ../knowledge/ links | +| concepts/ | 4 md | md | No | Complete (fact-catalog, entity-attributes, relationship-states); renamed from knowledge/, inbound links broken | +| authoring/ | 12 md (incl. npc-patterns/ 3) | md | No (authoring guides) | Complete; monologue-guide has 9 stale links (knowledge/, pre-governance decisions/ paths) | +| triangles/ | 1 md | md + frontmatter | No | One worked example (hub-power.md); index.md missing (broken link from wiki root) | +| cultural-groups/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| institutions/ | 0 (.gitkeep) | — | — | EMPTY (template exists; covered under factions/) | +| lore/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| species/ | 0 (.gitkeep) | — | — | EMPTY (template exists) | +| _templates/ | 17 md | md | — | Complete but drifted: star-system template ≠ generated reality; station/district/location/cultural-group/species/lore/institution templates have 0 instances | +| glossary.md / GOVERNANCE.md / index.md | 3 md | md | No | Glossary current (incl. TOML/DB terminology + anti-drift list); GOVERNANCE spatial hierarchy + status lifecycle stale; index.md counts stale (''10 fully written'' vs ~301) | + +# Star-systems census +- Systems: 302 dirs (catalog claims 301; 220 named / 81 unnamed); 9 catalog rows link nonexistent companion dirs +- Bodies: 2,625 body pages (planets, moons, belts, oort clouds; no per-type subdirs — flat bodies/ per system) +- Stations: 0 wiki pages; rows in systems.db rendered into ''Stations & Facilities'' tables per system index + 24 station GTTR prose files +- Markers: 2,394 names-only (D-223) + 4 legacy geometry (all GJ-0/Sol) + +# Generation data flow (verified) +wiki/economics/*.toml + wiki/corporations/*.md frontmatter + wiki/star-systems body frontmatter + markers.json names → tooling/economy-db/import_economics.py → server/data/systems.db (stamped, tooling/check-systems-db-stamp) → client Atlas (gttr_excerpt popups, reach_screen.gd:178) + direct runtime load of wiki globe.png (system_screen.gd:482-492). wiki_sync.py: DB owns structured fields, wiki owns prose sections. + +# docs/ health snapshot +- docs/architecture/ (19): current — pql-migration.md (2026-06-06), atlas-naming-pipeline, implant-app-pattern; historical — sprint-36/37 audits, v01-yaml-content-audit, eval/risk-godot-rust-bridge (2026-03-13) +- docs/design/ (60+): ~35 files frozen at 2026-02-19→03-14, status:active but v0.1/v0.2-era (wow-moments, first-5-minutes, spatial-layout-*-v01, dueling content-structure docs); still-load-bearing: star-map.json (Topology source), gj-catalog-full.json, planetary-terrain-generation.md, cultural-diversity-audit.md (remediated, T-793 done), sova-station-profile.md (canon for the stub system)', 'backlog', 'medium', NULL, 'content', NULL, '2026-06-12 10:40:59', '2026-06-12 10:40:59', NULL, 'e969fdaff30c443687a7bba65e8863f9', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZQKSQQQ1T5Q696AAM', 'task', '06FB0TNSRWN78KNTHMER9HN7QR', 'BulkClass + ProductionUbiquity enums + D-184 bulk_class backfill + dominant-commodity lookup', 'Define BulkClass{BulkSolid|BulkLiquid|PrecisionDense|Perishable|NonPhysical} + ProductionUbiquity{Ubiquitous|Common|Specialist|MonopolySource}; back-fill D-184 bulk_class values; build-time lookup of the settlement dominant commodity from the systems.db catalog. Seed-independent. + +Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here (closed set: Fjord, Canyon, Delta, AlluvialPlain, Island, MountainPass, Coastal, Lake, Sea, OpenOcean, MeanderReach, Other) -- it had no home and 954/976/1005 all need it. bulk_class is the 8->5 PROJECTION (size variants bulk/standard/compact/oversized -> BulkSolid; precision -> PrecisionDense; the 8 stay on commodities). Note: the bare enum/struct type DEFS now live in the foundational types task; 982 owns the projection + dominant-commodity DERIVATION logic (derived from highest-output location-bound production chain, D-178, not an authored role->commodity table).', 'backlog', 'medium', NULL, 'server', 'D-233', '2026-05-25 19:11:05', '2026-06-12 10:41:25', NULL, '74c5df94a1c8a5396f68734fc7681cc4', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); +INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FB0TNSRZQKSQQQ1T5Q696AAM', 'task', '06FB0TNSRWN78KNTHMER9HN7QR', 'BulkClass + ProductionUbiquity enums + D-184 bulk_class backfill + dominant-commodity lookup', 'Define BulkClass{BulkSolid|BulkLiquid|PrecisionDense|Perishable|NonPhysical} + ProductionUbiquity{Ubiquitous|Common|Specialist|MonopolySource}; back-fill D-184 bulk_class values; build-time lookup of the settlement dominant commodity from the systems.db catalog. Seed-independent. + +Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here (closed set: Fjord, Canyon, Delta, AlluvialPlain, Island, MountainPass, Coastal, Lake, Sea, OpenOcean, MeanderReach, Other) -- it had no home and 954/976/1005 all need it. bulk_class is the 8->5 PROJECTION (size variants bulk/standard/compact/oversized -> BulkSolid; precision -> PrecisionDense; the 8 stay on commodities). Note: the bare enum/struct type DEFS now live in the foundational types task; 982 owns the projection + dominant-commodity DERIVATION logic (derived from highest-output location-bound production chain, D-178, not an authored role->commodity table). + +Status check 2026-06-12 (fable-ous audit S-62): flipped in_progress → backlog. Verified the enum/type half landed via T-1006 (BulkClass/ProductionUbiquity + context fields, generator.rs:1016/1039/1097-1100), but this ticket''s remaining scope — the 8→5 bulk_class projection, D-184 backfill, and the dominant-commodity DERIVATION (highest-output location-bound chain per D-178) — has zero hits in city_context_reader.rs. Nobody is actively on it; it was stale-WIP for 18 days while being T-1014''s sole live blocker. Sequencing input: Q-111 (live-econ coupling) decides whether the dominant-commodity lookup stays static build-time.', 'backlog', 'medium', NULL, 'server', 'D-233', '2026-05-25 19:11:05', '2026-06-12 10:41:25', NULL, 'fe1326ed22e42707c3b33575638db3a8', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash); diff --git a/docs/audits/2026-06-12-fable-ous-filing-ledger.md b/docs/audits/2026-06-12-fable-ous-filing-ledger.md new file mode 100644 index 000000000..db88ecaac --- /dev/null +++ b/docs/audits/2026-06-12-fable-ous-filing-ledger.md @@ -0,0 +1,98 @@ +# fable-ous audit — filing ledger (2026-06-12) + +The whole-repo audit report (`fable-ous.md`, repo root, never committed) was fully +processed into DQR/T records and then deleted. This ledger preserves the stub→record +mapping. Every record carries its own evidence (file:line citations, adversarially +verified for high/med findings at audit time); the audit's factual maps were embedded +into the tickets that need them (cascade layer-chain → T-1046, asset-class matrix → +T-1049, wiki survey → T-1071). + +Method: inventory + 8 deep dives + adversarial citation verification (50/50 dive +citations confirmed; 10/12 carried-over claims verified, 2 corrected). Severity +high/med citations were independently re-checked; low-severity stubs carry +agent-reported citations — spot-check at pickup. + +## Stub → record + +| Stub | Finding (short) | Filed as | +|---|---|---| +| S-01 | TCP partial-read frame desync | T-1045 | +| S-02 | Drain all inbound frames per tick | T-1045 | +| S-03 | input.rs / dialogue.rs god-module split | T-1062 | +| S-04 | Storyteller f32 vs bps convention | Q-112 | +| S-05 | Workers pool untested + panic-loss | T-1063 | +| S-06 | Determinism-exemption consumer contracts | T-1064 | +| S-07 | Unused bytemuck / stale rayon comment | T-1064 | +| S-08 | generator_spike quarantine + surname dedup | T-1064 | +| S-09 | Save/load exclusive-system ordering pin | T-1064 | +| S-10 | Inbound-demux tagged-envelope constraint | D-225 amendment (2026-06-12) | +| S-11 | v0.2/protocol comment sweep | T-1069 | +| S-12 | economy.rs signal-derivation tests | T-1064 | +| S-13 | Client-test gate in pre-push | T-1065 | +| S-14 | 1.7 G tracked spike binaries | D-241 + untracking commit 27ed13e35 | +| S-15 | One-generator doc drift | T-1069 | +| S-16 | Dead check-protocol target | T-1069 | +| S-17 | GDScript lint blocking vs advisory | Q-116 | +| S-18 | Tooling test gate | T-1066 | +| S-19 | import_economics split + registry dedup | T-1067 | +| S-20 | whatsinagame/ extraction | Q-117 | +| S-21 | Orphan .gd.uid + time_display rider | T-1068 | +| S-22 | _format_pop dedupe | T-1068 | +| S-23 | character_creation.gd extraction (Phase 5) | T-1059 | +| S-24 | skip_test_ / soft-skip triage | T-1068 | +| S-25 | DEVOPS hook sections + connector helpers | T-1069 (+ connector half in T-1067) | +| S-26 | project.yaml version/description drift | T-1069 | +| S-27 | **Wire Region→Chunk→Voxel into production** | T-1046 | +| S-28 | River channels anchored to world origin (bug) | T-1040 | +| S-29 | 64 m landform repetition (bug) | T-1041 | +| S-30 | L3→L4 dispatch drops archetype/morphology | T-1039 | +| S-31 | Region/chunk physical-scale anchoring | Q-110 | +| S-32 | Live-econ → generation coupling | Q-111 | +| S-33 | Inter-settlement roads/rail | T-1038 | +| S-34 | road_entry_directions derivation | T-1043 | +| S-35 | Cross-region seam blending | T-1042 | +| S-36 | basin_direction from D8 thalweg | T-1047 | +| S-37 | Redundant drainage re-run | T-1044 | +| S-38 | D-203 cache contract drift | T-1048 | +| S-39 | Stale voxel.rs "not implemented" docs | T-1069 | +| S-40 | Cross-platform f32 goldens / budget gate | Q-113 | +| S-41 | NPC appearance generation contract | Q-114 | +| S-42 | CharacterVisualDescriptor wire struct | T-1060 | +| S-C1 | Garment-token vocabulary | Q-120 | +| S-C2 | Garments: simulated vs visual-only | Q-115 | +| S-C3 | Cultural dress canon home | Q-121 | +| S-C4 | Clothing asset pipeline | T-1055 | +| S-C5 | Corp uniform specs (4 apparel corps) | T-1056 | +| S-C6 | Wardrobe assignment in NPC generation | T-1061 | +| S-43 | T-961 per-class refinement | T-1049 | +| S-44 | Visual production-status catalog | T-1050 | +| S-45 | Generic-parent first production slice | Q-119 | +| S-46 | Lamp posts/barns/TVs/billboards briefs | T-1051 | +| S-47 | Vehicle scope | Q-067 audit note (2026-06-12) | +| S-48 | Phase-4 visual style bible | T-1052 | +| S-49 | araminta.md briefing rewrite | T-1053 | +| S-50 | glb-gen path + conventions / sourcing policy | T-1050 (task) + Q-122 (policy) | +| S-51 | GJ-280B (Sova) fill + canon triplication | T-1054 | +| S-52 | Signature materials into consolidation | Q-107 audit note (2026-06-12) | +| S-53 | 2,131 broken heightmap links | T-1070 | +| S-54 | Wiki link breaks (~26) | T-1071 | +| S-55 | Stale wiki nav surfaces | T-1071 | +| S-56 | GOVERNANCE.md / template reconcile | T-1071 | +| S-57 | Empty category dirs + blank Descriptions | Q-118 | +| S-58 | docs/design re-status sweep | done — commit ca255dc16 (20 files) | +| S-59 | Sol legacy markers + triangles index | T-1071 | +| S-60 | Re-parent 147 stray backlog tickets | done — commit ca255dc16 | +| S-61 | v0.2 decision cluster + T-605 | done — D-114/115/117/118/120 superseded; T-605 → T-1036 | +| S-62 | T-982 stale in_progress | done — verified unfinished, flipped to backlog with note | +| S-63 | T-9 + resolved-question mirrors | done — T-9 closed; T-21/22/23/27 cancelled | +| S-64 | Answered-by-events Qs + Phase-4 Q triage | done (Q-077/Q-036/Q-068 resolved) + T-1057 | +| S-65 | Pre-seed Phase 5/6 epics | done — re-homing under T-749/T-751 | +| S-66 | Done-parent/open-children inversions | done — T-871 children → T-1037; T-683 children → T-749 | +| S-67 | D-221 milestone language | done — amendment 2026-06-12 | +| S-68 | T-981 edge, T-745 status, D-179/D-183, Q dates | done (T-981, T-745) + T-1058 | + +Related records created during the same cleanup, outside the stub list: D-166 +amendment 2026-06-12 (outside-in build order, parallel Phase-5 ramp), T-1036 +(post-cascade gameplay parking epic), T-1037 (maintenance initiative), T-1038–T-1044 +(workshop-WIP capture, grounded in docs/workshops/ per the planet-down-cascade and +tile-derivation-contract outputs). diff --git a/governance/README.md b/governance/README.md index 1fde3d6f6..9d823187c 100644 --- a/governance/README.md +++ b/governance/README.md @@ -383,6 +383,17 @@ line in place — keep the Q-record for the audit trail rather than deleting it. - [Q-109: Cascade generation-source dispatch — planetary / station / mod-DLC-forked / save-only](questions/architecture.md#q-109-cascade-generation-source-dispatch--planetary--station--mod-dlc-forked--save-only) — _architecture_ - [Q-110: Region/chunk physical-scale anchoring — what is a region in metres, and what anchors a heightmap pixel?](questions/architecture.md#q-110-regionchunk-physical-scale-anchoring--what-is-a-region-in-metres-and-what-anchors-a-heightmap-pixel) — _architecture_ - [Q-111: Live-econ coupling of generation inputs — which inputs refresh from the rolling sim vs stay static-authored?](questions/architecture.md#q-111-live-econ-coupling-of-generation-inputs--which-inputs-refresh-from-the-rolling-sim-vs-stay-static-authored) — _architecture_ +- [Q-112: Storyteller engagement scoring — move to bps integer arithmetic or sanction f32?](questions/architecture.md#q-112-storyteller-engagement-scoring--move-to-bps-integer-arithmetic-or-sanction-f32) — _architecture_ +- [Q-113: Is cross-platform f32 bit-identity required for saves? (golden vectors are x86_64-only)](questions/architecture.md#q-113-is-cross-platform-f32-bit-identity-required-for-saves-golden-vectors-are-x86-64-only) — _architecture_ +- [Q-114: Server-side NPC appearance generation contract — seed+culture+role → CharacterVisualDescriptor](questions/architecture.md#q-114-server-side-npc-appearance-generation-contract--seedculturerole--charactervisualdescriptor) — _architecture_ +- [Q-115: Are garments simulated inventory items or visual-only descriptor fields?](questions/architecture.md#q-115-are-garments-simulated-inventory-items-or-visual-only-descriptor-fields) — _architecture_ +- [Q-116: GDScript lint gate — flip to blocking or record advisory-forever?](questions/process.md#q-116-gdscript-lint-gate--flip-to-blocking-or-record-advisory-forever) — _process_ +- [Q-117: whatsinagame/ — extract the embedded starter-kit product or record why it stays vendored?](questions/scope.md#q-117-whatsinagame--extract-the-embedded-starter-kit-product-or-record-why-it-stays-vendored) — _scope_ +- [Q-118: Empty wiki category dirs (cultural-groups, institutions, lore, species) and blank body Descriptions — Phase-6 scope or retire?](questions/scope.md#q-118-empty-wiki-category-dirs-cultural-groups-institutions-lore-species-and-blank-body-descriptions--phase-6-scope-or-retire) — _scope_ +- [Q-119: Is the generic-parent placeholder set the first asset-production milestone?](questions/content.md#q-119-is-the-generic-parent-placeholder-set-the-first-asset-production-milestone) — _content_ +- [Q-120: Adopt a garment-token vocabulary with generic fallback parents (the D-235 pattern, applied to clothing)?](questions/content.md#q-120-adopt-a-garment-token-vocabulary-with-generic-fallback-parents-the-d-235-pattern-applied-to-clothing) — _content_ +- [Q-121: Where does cultural dress canon live — TOML registers now, prose pages in Phase 6?](questions/content.md#q-121-where-does-cultural-dress-canon-live--toml-registers-now-prose-pages-in-phase-6) — _content_ +- [Q-122: Third-party asset sourcing policy — when to use CC0/purchased bases vs Trellis generation, per asset class?](questions/content.md#q-122-third-party-asset-sourcing-policy--when-to-use-cc0purchased-bases-vs-trellis-generation-per-asset-class) — _content_ ## Resolved questions diff --git a/governance/decisions/architecture.md b/governance/decisions/architecture.md index 53adb8060..e5f4323a8 100644 --- a/governance/decisions/architecture.md +++ b/governance/decisions/architecture.md @@ -1525,6 +1525,7 @@ Technical foundation decisions that constrain implementation: engine, client-ser - **Deferred / spun off:** the full `BridgeMessage` envelope-everywhere migration (later cleanup, not this ticket); the mod **content catalog** — mods adding *new* bodies need body rows + `terrain_reference` discoverable, but `systems.db` is binary / source-canonical (D-189) and mods cannot append to it → **Q-099**. D-225 resolves mod *file* resolution only; base-install resolution is enough to ship T-960. - **Implementation:** T-960 (client viewer + proxy) plus the `AnalyzeBody` activation ticket. New surface: `server/src/atlas/source_resolver.rs`, `server/src/atlas/layer_proxy.rs`; `gen_queue.rs` `run_work_item` activation + `GenCompletion` payload; bridge receive/send branching; client `protocol.gd` / `sim_bridge.gd` / `atlas_viewer.gd`. - **Raised by:** Jeroen (mod-first directive) + Tyre (design pass) + Claude, `/whats-next` refinement of T-960, 2026-05-23. +- **Amendment (2026-06-12, extension constraint — fable-ous.md S-10):** `decode_inbound` (`bridge/mod.rs:38-74`) distinguishes the two inbound message types purely by MessagePack shape (array = `Vec`, map = `AtlasLayerRequest`) and serde ignores unknown map fields — so a future second map-shaped inbound type with overlapping required fields would silently mis-decode as an atlas request. Constraint: **the next inbound message type must introduce a tagged envelope** (or a required marker field) rather than extending shape-based detection. - **Cross-reference:** Q-098 (resolved by this), Q-099 (mod content catalog — spun off), [D-191](#d-191) (Atlas viewer), [D-166](#d-166) (per-layer Atlas progress viewer), [D-200](#d-200) / [D-203](#d-203) (three-tier execution, LRU cache), [D-005](#d-005) / [D-192](#d-192) (client+server co-ship — no version handshake), [D-224](#d-224) (SeedChain — feeds the cascade the proxy runs) - **Dissent:** None diff --git a/governance/questions/architecture.md b/governance/questions/architecture.md index 2fcbccbc9..92e3590b8 100644 --- a/governance/questions/architecture.md +++ b/governance/questions/architecture.md @@ -133,6 +133,7 @@ Technical foundation questions: engine, protocols, data structures, performance, ### Q-067: Vehicle physics for in-world transport - **Status:** Open - **Question:** Evaluate vehicle physics plugins for player/NPC transport between zones. Two candidates: (a) MAdvanced Vehicle System (https://godotengine.org/asset-library/asset/3697) — full car physics with gearbox, AI traffic, traffic management, lights, sounds, steering wheel support. Godot 4.6, MIT, actively updated. (b) Godot Simple Motorcycle Physics (https://godotengine.org/asset-library/asset/4670) — raycast-based motorcycle, simpler scope. Questions: does the game need driveable vehicles or just NPC traffic? Is vehicle movement client-side physics or server-authoritative? The AI traffic and traffic management in MAdvanced could serve NPC vehicle simulation. Scope for v0.2: probably not, but worth tracking for when districts/zones need inter-zone travel. +- **Audit note (2026-06-12, fable-ous.md S-47):** T-750's Phase-4 asset-class list names "cars", but this question is open and its own text says "Scope for v0.2: probably not" (and v0.2 is dropped). Answer at least to the level of *are vehicle assets a Phase-4 deliverable or Phase-5+*: if yes, ticket the asset brief; if no, amend T-750's description to drop cars from the class list. Only vehicle artifact today: `spikes/3dpipeline/models/props/vw_beetle.glb` (spike, untracked binary per D-241). - **Cross-reference:** D-010 (server authority), world generation --- @@ -408,7 +409,8 @@ Technical foundation questions: engine, protocols, data structures, performance, ### Q-107: Wiki → Atlas content-set consolidation - **Status:** Open — raised by Jeroen (2026-05-25) - **Question:** The wiki pages live semi-outside game scope yet are piped into Atlas content screens AND are now a generator input (D-232 architecture-flavor distilled from wiki prose). Where authored per-body content lives (frontmatter vs companion file vs a consolidated tree) should follow a consolidation of ALL wiki content — pages + heightmaps + markers + architecture-flavor — into one first-class, baked Atlas content set (the "move it into a `gamedata/` subtree" instinct), not a per-feature hack. The generator-facing tables (`trait_templates` + `atlas_body_trait_bias`, D-232) are invariant to the source location, so this does not block the fill seam. -- **Cross-reference:** [D-232](../decisions/architecture.md#d-232), [D-223](../decisions/architecture.md#d-223), [D-191](../decisions/architecture.md#d-191) (Atlas/settlement), and the development cascade (Phase 1 wiki + Phase 3 Atlas) +- **Audit note (2026-06-12, fable-ous.md S-52):** include a **signature materials/crafts** structured field (per-system or per-body) in the consolidation scope. Distinctive material canon exists only as prose today — granite dry-stack tradition (`wiki/star-systems/GJ-4053/index.md:22-26`), peat-wood carving (`GJ-1248/index.md:30`), basalt crater farms (`GJ-285/index.md:28-38`), structural timber (`GJ-588/index.md:30-34`) — while markers are names-only (D-223) and the structured counterpart is only the 28-template trait catalog + 240 D-237 pins. Consolidating it lets D-232 bias be authored from existing prose instead of re-invented; also feeds the dress-canon registers (Q-121). +- **Cross-reference:** [D-232](../decisions/architecture.md#d-232), [D-223](../decisions/architecture.md#d-223), [D-191](../decisions/architecture.md#d-191) (Atlas/settlement), and the development cascade (Phase 1 wiki + Phase 3 Atlas); Q-121 --- @@ -447,4 +449,26 @@ Technical foundation questions: engine, protocols, data structures, performance, --- -*60 questions (13 resolved, 1 partially resolved, 46 open). Last updated: 2026-06-12.* +### Q-112: Storyteller engagement scoring — move to bps integer arithmetic or sanction f32? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-04) +- **Question:** `bps.rs:1-8` documents the D-010 convention: fractional values in determinism-sensitive paths are integer basis points, f32 only at the edge. But storyteller anchor selection — which mutates game state via triangle activation — computes engagement scores in f32 (weights 2.0/0.005/8.0 at `storyteller/mod.rs:102-112`, f64→f32 cast at `:445-446`) and sorts by `partial_cmp` (`:546`) with a SimRng tie-break (`:550-558`). Replay-deterministic on one binary, but contradicts the convention. Separately `generator.rs:1086` declares `footprint_radius_km: f32` in the Phase-4 CityGenerationContext directly below a field documented "Integer to avoid f32 non-determinism (D-010)"; it is currently a 5.0 stub (D-204 formula deferred, `city_context_reader.rs:482`). Either record that f32-with-integer-derived-inputs + SimRng tie-break is sanctioned for storyteller scoring, or convert the weights to bps (u32). For `footprint_radius_km`, specify the D-204 formula in integer metres/bps before it lands in the cascade. Note: no dedicated D-record for the integer-discipline convention exists — it lives only in code docs and `.clippy.toml`; answering this is the natural moment to record it. +- **Cross-reference:** D-010, D-204; `server/src/bps.rs`, `server/src/storyteller/mod.rs`, `server/.clippy.toml`; Q-113 + +### Q-113: Is cross-platform f32 bit-identity required for saves? (golden vectors are x86_64-only) +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-40) +- **Question:** D-227 reclassified generation determinism as save-critical, but the L1 cascade goldens self-declare x86_64-only f32 sensitivity (`cascade_golden.rs:17-20`: "a different architecture could in principle round differently" — slope/elev_pct/downsample paths). If cross-platform bit-identity is required for saves, the remaining f32 L1 paths need the same scaled-integer treatment drainage already has (`drainage.rs:4-7`). Related gate hygiene: the per-family chunk budget assertion runs only under `BUDGET_ASSERT=1` (`derivation_harness.rs:19-23`) and its 5 ms gate is looser than the D-239 §10 stated 2.2–4.2 ms — enable it in a release-mode periodic job and reconcile the figures. +- **Cross-reference:** D-010, D-227, D-239 §10; `server/tests/cascade_golden.rs`, `server/tests/derivation_harness.rs`; Q-112 + +### Q-114: Server-side NPC appearance generation contract — seed+culture+role → CharacterVisualDescriptor +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-41); Phase 5/6 work, recorded now so the contract exists before that work starts +- **Question:** The client rendering architecture (D-159..D-164) is implemented and validated, but no server-side appearance generation exists: `npc/generate.rs:465-535` spawns the 10 behavioral axes plus sim-state components with zero visual fields, and the appearance pre-generation worker is an explicit stub (`workers/stubs.rs:86`: "real implementation pre-generates NPC appearance, inventory, mood"). `CultureProfile` (blueprint.rs) carries speech/behavior modifiers but no visual attributes. The contract to decide: where the descriptor is generated (NpcPrepWorker per the stub's own intent), its inputs (culture register, role, faction, corp employment, prosperity band), its determinism requirement (pure function of EntityRng/SeedChain like every other NPC axis), and that the client `CharacterVisualDescriptor` schema is the single source of truth for fields. Companion work: the wire struct (T ticket, Phase 5) and wardrobe assignment (Phase 6); garment policy in Q-115/Q-120/Q-121. +- **Cross-reference:** D-122, D-159..D-164; `server/src/npc/generate.rs`, `server/src/workers/stubs.rs`, `client/scripts/rendering/character_visual_descriptor.gd`; Q-115, Q-120, Q-121 + +### Q-115: Are garments simulated inventory items or visual-only descriptor fields? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-C2); shapes the Q-114 schema, so answer before Phase-5 appearance work +- **Question:** Server inventory is a 9-slot CarriedBy grid with no equipment concept (`simulation/inventory.rs:12-36`). Visual-only garments (descriptor fields) are cheap and ship with Phase 5. Simulated garments (equip/remove/trade) touch inventory, perception, and economy — but fit the game's thesis: in an asymmetric-information game a uniform is a *claim about identity that can be false* (disguises, the Workshift HeavyWork exposure-history hook as wearable evidence). Recommendation embedded from the audit: visual-only descriptor in Phase 5, with the descriptor schema reserving item-id compatibility so an equipment-slot upgrade remains an explicit Phase-6 decision rather than a migration. +- **Cross-reference:** D-024 (NPC axes), D-159..D-162; `server/src/simulation/inventory.rs`, `wiki/corporations/workshift-apparel.md`; Q-114, Q-120 + +--- + +*64 questions (13 resolved, 1 partially resolved, 50 open). Last updated: 2026-06-12.* diff --git a/governance/questions/content.md b/governance/questions/content.md index 6bc846bd9..df33f4b3d 100644 --- a/governance/questions/content.md +++ b/governance/questions/content.md @@ -249,4 +249,26 @@ Narrative, NPCs, dialogue, templates, setting, worldbuilding, and storyteller me --- -*26 questions (11 resolved, 2 partially resolved, 13 open). Last updated: 2026-05-02 (Q-097 corp silences)* +### Q-119: Is the generic-parent placeholder set the first asset-production milestone? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-45) +- **Question:** D-235's fallback chain means every specific token degrades to a generic parent that must exist as an always-present placeholder asset ("temple_wall_wood → generic wood_wall placeholder until the specific asset ships", `governance/decisions/architecture.md:1707`; `wiki/economics/architecture_trait_catalog.toml:33-41` lists generic_wall/generic_roof/generic_facade/generic_street). That guarantees a small, enumerable minimum asset set unblocks the entire rendering chain — but no document or ticket enumerates the generic-parent assets as the pipeline's first deliverable (T-1004 covers token logic, not art). Decide: first asset-production milestone = the complete generic-parent set (walls, roof, facade, street + generic door/floor/furniture parents) with target counts, before any specific-token assets. +- **Cross-reference:** D-235, D-232, D-228; T-961, T-1004; the T-961 per-class refinement ticket (filed alongside) + +### Q-120: Adopt a garment-token vocabulary with generic fallback parents (the D-235 pattern, applied to clothing)? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-C1); cheap to decide, unblocks clothing asset planning +- **Question:** The client already fixes the slot taxonomy (torso/legs/footwear + 12 accessory slots with multi-region tints — `character_visual_descriptor.gd`, `docs/design/compositor-api-spec.md:98-146`), and the architecture side has a proven pattern: open token vocabulary per slot with always-present generic fallback parents (D-232/D-235). Decide the closed slot set and the wardrobe-catalog TOML (e.g. `workwear_torso_heavy → generic_torso`), authored alongside the architecture trait catalog, co-maintained Miri + Araminta (mirroring T-995). Economic grounding already exists: textiles commodity with brach-fiber cultural premium (`wiki/economics/commodities/textiles.md`), four apparel corps (`workshift-apparel.md`, `shetland-wool.md`, `kalahari-leatherworks.md`, `thrds.md`). +- **Cross-reference:** D-232, D-235, D-159..D-162; T-995; Q-114, Q-115, Q-121; the clothing-pipeline ticket (filed alongside) + +### Q-121: Where does cultural dress canon live — TOML registers now, prose pages in Phase 6? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-C3) +- **Question:** `wiki/cultural-groups/` is a lone `.gitkeep`; no faction/corp dress specs exist anywhere. The structural alternative is proven: D-232 trait catalog + D-237 per-system pins shipped culture as TOML. Recommendation embedded from the audit: follow the architecture precedent — dress registers as TOML (per-system/per-corp garment-token weights, consumable by generation) now, prose dress lore deferred to Phase-6 detail coloring with the other empty category dirs (Q-118). The who-wears-what logic: role picks garment family (Workshift institutional contracts mean whole workforces dress alike — uniforms are *information* in a perception game), culture/system picks materials and registers, prosperity band picks condition/wear (the D-217 era-as-maintenance move applied to bodies), faction/corp adds marks. +- **Cross-reference:** D-232, D-237, D-217; Q-107 (audit note re signature materials), Q-118, Q-120; `wiki/corporations/{workshift-apparel,shetland-wool,kalahari-leatherworks,thrds}.md` + +### Q-122: Third-party asset sourcing policy — when to use CC0/purchased bases vs Trellis generation, per asset class? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-50, decision half) +- **Question:** Sourcing practice exists but is undocumented as policy: Poly Haven CC0 for environment + purchased Quaternius for characters, everything through the toon render pipeline — stated only in a workshop brief (`docs/workshops/world-generation/BRIEF.md:26,50`) and proven in practice for characters. No record canonicalizes per-class sourcing order (e.g. CC0/purchased base where silhouette quality matters, Trellis generation for bespoke sci-fi objects), license constraints, or the requirement that all sourced assets pass `renderer/` for style unification. D-241 covers the *storage* boundary (spike binaries local-only, promotion to client/assets/ is canon); this covers the *sourcing* order. +- **Cross-reference:** D-241, D-235; `.claude/skills/{image-gen,glb-gen,sprite-gen}/SKILL.md`; reference memory: polyhaven.com/models; Q-119 + +--- + +*30 questions (11 resolved, 2 partially resolved, 17 open). Last updated: 2026-06-12 (Q-119..Q-122 filed from the fable-ous audit)* diff --git a/governance/questions/process.md b/governance/questions/process.md index 1cfb932ab..9472c8280 100644 --- a/governance/questions/process.md +++ b/governance/questions/process.md @@ -181,4 +181,11 @@ The findings file separates the agent's reasoning from its authority. Binary gat --- -*Open count: 0.* +### Q-116: GDScript lint gate — flip to blocking or record advisory-forever? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-17) +- **Question:** Rust gets fmt + clippy `-D warnings` as hard pre-push blockers; GDScript gets a parse check plus *advisory* gdlint/gdformat that print counts and never block (`.config/hooks/pre-push:56-76`, scope excludes `client/tests/`). A `.gdlintrc` exists but nothing blocking consumes it, and `docs/DEVOPS.md:138` misdocuments `make lint-client` as running gdlint. The hook's own comment says "advisory only until codebase is clean" — and that condition was met months ago: T-783 (done 2026-04-05) resolved all 354 warnings to a zero-warnings state. Decide: flip gdlint/gdformat to blocking (the cleanup precondition is satisfied; include `client/tests/` or exclude it explicitly), or record advisory-forever. Either way align `make lint-client` and DEVOPS.md, and align `make lint-server` (clippy without `--all-targets`, `Makefile:246-248`) with the stricter pre-push clippy. +- **Cross-reference:** T-783 (zero-warnings cleanup, done); `.config/hooks/pre-push`, `.gdlintrc`, `docs/DEVOPS.md`; related ticket: client-test pre-push gate (same hook, filed separately) + +--- + +*Open count: 1. Last updated: 2026-06-12.* diff --git a/governance/questions/scope.md b/governance/questions/scope.md index 5d2dd5fe0..8f6de006b 100644 --- a/governance/questions/scope.md +++ b/governance/questions/scope.md @@ -119,4 +119,16 @@ Game concept, prototype boundaries, production pipeline, and feature decisions. --- -*17 questions (7 resolved, 3 partially resolved, 7 open). Last updated: 2026-06-12 (Q-036 closed as resolved — quarter skeleton shipped)* +### Q-117: whatsinagame/ — extract the embedded starter-kit product or record why it stays vendored? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-20) +- **Question:** `whatsinagame/` is a complete separate product ("A Claude Code starter kit that bootstraps multi-agent team infrastructure for any project" — its README:3) living in the game repo: 73 tracked files including its own LICENSE and tests. Nothing in the build, Makefile, skills, or active docs references it (only archival records: sprint-22 notes, CHANGELOG history, pql-migrate provenance). Its templates snapshot infrastructure this repo has since replaced (the retired sqlite ticket CLI, the pre-governance decisions/ layout), so it drifts further from house practice with every migration and its retired-tooling templates risk being mistaken for current convention. Decide: extract to its own repository (it is explicitly designed to be cloned independently) or record the reason it stays vendored. +- **Cross-reference:** `whatsinagame/README.md`; `.claude/rules/ticket-cli.md` (the CLI its templates still ship) + +### Q-118: Empty wiki category dirs (cultural-groups, institutions, lore, species) and blank body Descriptions — Phase-6 scope or retire? +- **Status:** Open — filed 2026-06-12 from the fable-ous.md audit (S-57) +- **Question:** Two halves. (a) Four template-backed wiki category dirs have held only a `.gitkeep` since 2026-02-13 while Phase 1 ("wiki content complete", T-746) closed done — the cultural layer shipped structurally instead (D-232 trait catalog + D-237 system pins as TOML), and institutions are covered under `factions/`. Retire the dirs + templates (recording an R if prose cultural-group pages are rejected in favor of the TOML layer), or scope them explicitly as Phase-6 detail-coloring deliverables so they stop reading as Phase-1 debt. (b) All 2,625 body pages have empty Description sections (2,621 scaffold placeholders + 4 GJ-0 pages without the section), including inhabited worlds like 2.0B-pop Kallast (`GJ-144/bodies/GJ144d/index.md:72-74`) — decide whether body-level prose is in scope (then prioritize the ~100 inhabited bodies) or the system-level dual-lens prose is the canonical narrative unit and the empty scaffold section should be removed/marked optional. Interacts with Q-121 (dress canon home) and Q-107 (content consolidation). +- **Cross-reference:** D-232, D-237, D-223; T-746 (done), Q-107, Q-121; `wiki/_templates/`, `tooling/planet-gen/scaffold_bodies.py` + +--- + +*19 questions (7 resolved, 3 partially resolved, 9 open). Last updated: 2026-06-12 (Q-117/Q-118 filed from the fable-ous audit)*