diff --git a/.pql/changelog/ticket_history/2026-06.sql b/.pql/changelog/ticket_history/2026-06.sql index 870ebd500..9f4339db2 100644 --- a/.pql/changelog/ticket_history/2026-06.sql +++ b/.pql/changelog/ticket_history/2026-06.sql @@ -1478,3 +1478,72 @@ Round-3 batch refinement (2026-05-26): also define the MorphologyZone enum here 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; +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 ('06FBPQ02VWJGXWDYT2SMXM9DTC', 'status', 'backlog', 'in_progress', NULL, '2026-06-12 10:56:40', '2026-06-12 10:56:40', '2026-06-12 10:56:40', NULL, '86e9a9835a72c905c4a146424394a2ac', 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 ('06FBPQ02QTVSZ1PXTGNCN6Y8KM', 'status', 'backlog', 'in_progress', NULL, '2026-06-12 10:56:40', '2026-06-12 10:56:40', '2026-06-12 10:56:40', NULL, '8db3a6e729e0e759c285140d5d719fd7', 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', 'status', 'backlog', 'in_progress', NULL, '2026-06-12 10:56:40', '2026-06-12 10:56:40', '2026-06-12 10:56:40', NULL, 'd15bc65a5d3cb3a7684db663d746fdc6', 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 ('06FBPQ02VWJGXWDYT2SMXM9DTC', 'status', 'in_progress', 'done', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '7d7f08dc0287b09239cb88d16a4b3369', 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 ('06FBPQ02QTVSZ1PXTGNCN6Y8KM', 'status', 'in_progress', 'done', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '9a11d274476fe793f12ba654e311a9e3', 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', 'status', 'in_progress', 'done', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '9d1b883e6f874776efe1e574149ac37e', 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 ('06FBPQ02QTVSZ1PXTGNCN6Y8KM', 'description', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: channel centrelines are anchored to the world-origin axis. compute_channel_state (AlluvialPlain, server/src/atlas/voxel.rs:1648-1707) and compute_meander_channel_state (MeanderReach, :1556-1595) compute perp_distance = (cross - meander_displacement).abs() (:1694, :1583) where cross is the raw world-space voxel coordinate (derive_voxel_column takes tile_x/tile_y in world metres, :328-338; cross = vx or vy at :1653-1661). The channel centreline is therefore the world x=0/y=0 axis plus-or-minus meander amplitude: only chunks within ~(channel_width/2 + amplitude + jitter) metres of the world origin axis ever contain channel water, regardless of ChunkContext.has_active_channel / channel_width_m (chunk_context.rs:103-110). in_levee_band (:1602-1633) inherits the same defect, so levees are origin-locked too. Every has_active_channel chunk elsewhere on the body silently renders dry floodplain. + +Intended model (workshopped): channel positions derive from region/chunk-scale data, not world axes — D-239 §10 (one basin-direction + global meander-curve params; wavelength > 64 m seeds Region-or-higher) and tile-derivation-contract/gestalt-round1.md:152-162 (channel branch positions from a multi-seed Voronoi partition of the chunk area with D8 flow direction as attractor; meander_intensity controls deviation from the straight downslope path). + +Fix, two stages: +1. Minimal correctness: derive a deterministic cross-offset channel anchor at region scale (alongside meander_phase in derive_chunk_context, chunk_context.rs:124-141 — same Region-or-higher seed path) and measure perp_distance from that anchor, so an active channel actually crosses the chunks the region says it crosses, continuously across chunk boundaries. +2. Full model: gestalt''s multi-seed Voronoi + D8-attractor branch placement when BraidedDelta sub-classification (D-239 implementation note: deferred to ChunkContext) lands. + +Add a T-1031-harness believability check: a has_active_channel chunk at an arbitrary large world offset (e.g. chunk_pos (1000, -750)) contains in-channel voxels; channel position is continuous across adjacent chunk pairs. Sibling bug: landform-64m-repeat (same family, opposite direction — channels appear nowhere, landforms appear everywhere). Parent: T-750. Refs: D-239 §10, D-208 (D8), D-010; T-1029 (origin), T-1031 (harness).', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: channel centrelines are anchored to the world-origin axis. compute_channel_state (AlluvialPlain, server/src/atlas/voxel.rs:1648-1707) and compute_meander_channel_state (MeanderReach, :1556-1595) compute perp_distance = (cross - meander_displacement).abs() (:1694, :1583) where cross is the raw world-space voxel coordinate (derive_voxel_column takes tile_x/tile_y in world metres, :328-338; cross = vx or vy at :1653-1661). The channel centreline is therefore the world x=0/y=0 axis plus-or-minus meander amplitude: only chunks within ~(channel_width/2 + amplitude + jitter) metres of the world origin axis ever contain channel water, regardless of ChunkContext.has_active_channel / channel_width_m (chunk_context.rs:103-110). in_levee_band (:1602-1633) inherits the same defect, so levees are origin-locked too. Every has_active_channel chunk elsewhere on the body silently renders dry floodplain. + +Intended model (workshopped): channel positions derive from region/chunk-scale data, not world axes — D-239 §10 (one basin-direction + global meander-curve params; wavelength > 64 m seeds Region-or-higher) and tile-derivation-contract/gestalt-round1.md:152-162 (channel branch positions from a multi-seed Voronoi partition of the chunk area with D8 flow direction as attractor; meander_intensity controls deviation from the straight downslope path). + +Fix, two stages: +1. Minimal correctness: derive a deterministic cross-offset channel anchor at region scale (alongside meander_phase in derive_chunk_context, chunk_context.rs:124-141 — same Region-or-higher seed path) and measure perp_distance from that anchor, so an active channel actually crosses the chunks the region says it crosses, continuously across chunk boundaries. +2. Full model: gestalt''s multi-seed Voronoi + D8-attractor branch placement when BraidedDelta sub-classification (D-239 implementation note: deferred to ChunkContext) lands. + +Add a T-1031-harness believability check: a has_active_channel chunk at an arbitrary large world offset (e.g. chunk_pos (1000, -750)) contains in-channel voxels; channel position is continuous across adjacent chunk pairs. Sibling bug: landform-64m-repeat (same family, opposite direction — channels appear nowhere, landforms appear everywhere). Parent: T-750. Refs: D-239 §10, D-208 (D8), D-010; T-1029 (origin), T-1031 (harness). + +Fixed 2026-06-12, commit 408bd39e (+ fmt fixup 993333fa). Region-anchored channel axes (channel_anchor_m) derived from the Region-or-higher seed path; perp_distance measured from the anchor, not the world origin. has_active_channel made honest in both directions (band-crossing gate, delta-belt floor). Harness: channel presence + gate honesty asserted at chunk (1000,-750), cross-boundary continuity under production chunk lookup. Golden case A now pins a genuinely in-channel Shallow voxel. Adversarially reviewed (approved; 3 minors fixed in-line). Gate: 1488 tests green.', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '96ea743771ea1e9a742ccb420d6efce7', 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 ('06FBPQ02VWJGXWDYT2SMXM9DTC', 'description', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: four morphology generators fold world coordinates into the 64 m chunk frame, so region-scale landforms repeat every chunk — violating D-239 §10 (''features with wavelength > 64 m seed from Region-or-higher, not the chunk seed''; deliberately strengthened from Block-or-higher in the adversarial verification pass, tile-derivation-contract/workshop-outcomes.md:83). + +Sites (server/src/atlas/voxel.rs): +- generate_fjord_wall :594-597 — cross.rem_euclid(64)-32: a complete fjord (floor|moraine|wall cross-section) centred in EVERY chunk of a FjordWall region; a real fjord valley is one feature spanning the region. +- generate_cliff_coast :721 — seaward_coord.rem_euclid(64): the cliff face sits at intra-chunk offset 48-55 in every chunk, sawtoothing the coastline at 64 m pitch. +- generate_braided_delta :825 — cross.rem_euclid(64): the same three braid threads restart per chunk instead of anastomosing across the fan. +- generate_incised_gorge :1054-1057 — same fold: a gorge per chunk. + +Fix: compute each landform''s axis/centreline in REGION-anchored coordinates — derive the feature anchor (centreline position, coast-face line) once per region from the region-scale seed path that meander_phase/basin_direction already use correctly (chunk_context.rs:124-141), then measure each voxel''s distance to that anchor in continuous world coordinates (no rem_euclid against the chunk size). This matches the workshop''s seam-freedom principle: the algorithm must see positions with no knowledge of the chunk grid (tyre-round1.md:174-176). Preserve D-239 §9 chokepoint widths (fjord floor 4-8 m, gorge floor 2-8 m — currently honoured at :607-609, :1059-1062). + +Harness gap to close (T-1031 follow-up): current tests check per-chunk boundary smoothness, not feature uniqueness — add a multi-chunk assertion that a FjordWall/IncisedGorge region contains ONE valley spanning its chunks, and a CliffCoast region one continuous (warp-displaced) coast line. Sibling bug: river-channel-anchor (channels are origin-anchored and appear nowhere; landforms are chunk-folded and appear everywhere — fix both against the same region-anchor mechanism). Depends on scale-anchoring Q for the region''s physical extent, but the region-index anchor works regardless. Parent: T-750. Refs: D-239 §5/§8/§9/§10, D-010; T-1029, T-1031.', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: four morphology generators fold world coordinates into the 64 m chunk frame, so region-scale landforms repeat every chunk — violating D-239 §10 (''features with wavelength > 64 m seed from Region-or-higher, not the chunk seed''; deliberately strengthened from Block-or-higher in the adversarial verification pass, tile-derivation-contract/workshop-outcomes.md:83). + +Sites (server/src/atlas/voxel.rs): +- generate_fjord_wall :594-597 — cross.rem_euclid(64)-32: a complete fjord (floor|moraine|wall cross-section) centred in EVERY chunk of a FjordWall region; a real fjord valley is one feature spanning the region. +- generate_cliff_coast :721 — seaward_coord.rem_euclid(64): the cliff face sits at intra-chunk offset 48-55 in every chunk, sawtoothing the coastline at 64 m pitch. +- generate_braided_delta :825 — cross.rem_euclid(64): the same three braid threads restart per chunk instead of anastomosing across the fan. +- generate_incised_gorge :1054-1057 — same fold: a gorge per chunk. + +Fix: compute each landform''s axis/centreline in REGION-anchored coordinates — derive the feature anchor (centreline position, coast-face line) once per region from the region-scale seed path that meander_phase/basin_direction already use correctly (chunk_context.rs:124-141), then measure each voxel''s distance to that anchor in continuous world coordinates (no rem_euclid against the chunk size). This matches the workshop''s seam-freedom principle: the algorithm must see positions with no knowledge of the chunk grid (tyre-round1.md:174-176). Preserve D-239 §9 chokepoint widths (fjord floor 4-8 m, gorge floor 2-8 m — currently honoured at :607-609, :1059-1062). + +Harness gap to close (T-1031 follow-up): current tests check per-chunk boundary smoothness, not feature uniqueness — add a multi-chunk assertion that a FjordWall/IncisedGorge region contains ONE valley spanning its chunks, and a CliffCoast region one continuous (warp-displaced) coast line. Sibling bug: river-channel-anchor (channels are origin-anchored and appear nowhere; landforms are chunk-folded and appear everywhere — fix both against the same region-anchor mechanism). Depends on scale-anchoring Q for the region''s physical extent, but the region-index anchor works regardless. Parent: T-750. Refs: D-239 §5/§8/§9/§10, D-010; T-1029, T-1031. + +Fixed 2026-06-12, commit 408bd39e. All four rem_euclid(64) chunk-frame folds removed (fjord :594-597, cliff :721, delta :825/:865, gorge :1054-1057); landform axes anchored once per region in continuous world coords. D-239 §9 chokepoint widths preserved; two i32 wall-rise overflows on region-scale distances fixed (clamp before multiply). Harness: one-valley-per-region, one-continuous-coastline-per-region, braid-belt confinement. CliffCoast semantics deliberately changed: one coast split per region (the §10 intent), not 75% inland per chunk. L0/L1 goldens byte-identical — no upstream leak. Adversarially reviewed (approved).', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '38698057cdc7d982034b33e860a8028c', 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) + +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).', '(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). + +Fixed 2026-06-12, commit 49a74e93 (+ review hardening). FrameAccumulator state machine holds partial prefix/payload across non-blocking receive() calls; drain loop with per-tick cap covers inputs + atlas requests. Review fix_required item resolved: EOF mid-frame now escalates to Disconnected (peer dead, frame can never complete) instead of per-tick Io error spam — regression test added (2 prefix bytes then drop). Minors: comment reworded; corrupt-stream escalation filed as T-1072; split-frame test hardening noted on T-1072. Gate: 1488 tests green.', NULL, '2026-06-12 11:50:14', '2026-06-12 11:50:14', '2026-06-12 11:50:14', NULL, '1190693a7a76c2f98e87b560d0f7cfab', 2) ON CONFLICT(hash) DO NOTHING; diff --git a/.pql/changelog/tickets/2026-06.sql b/.pql/changelog/tickets/2026-06.sql index 416655eb9..6fcd673d5 100644 --- a/.pql/changelog/tickets/2026-06.sql +++ b/.pql/changelog/tickets/2026-06.sql @@ -1638,3 +1638,69 @@ Fix: compute each landform''s axis/centreline in REGION-anchored coordinates — Harness gap to close (T-1031 follow-up): current tests check per-chunk boundary smoothness, not feature uniqueness — add a multi-chunk assertion that a FjordWall/IncisedGorge region contains ONE valley spanning its chunks, and a CliffCoast region one continuous (warp-displaced) coast line. Sibling bug: river-channel-anchor (channels are origin-anchored and appear nowhere; landforms are chunk-folded and appear everywhere — fix both against the same region-anchor mechanism). Depends on scale-anchoring Q for the region''s physical extent, but the region-index anchor works regardless. Parent: T-750. Refs: D-239 §5/§8/§9/§10, D-010; T-1029, T-1031.', 'in_progress', 'high', NULL, 'server', 'D-239', '2026-06-12 10:23:49', '2026-06-12 10:56:40', NULL, 'c1189a915611efac3027617e7915776a', 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 ('06FBQ8WGMA3552756BQAAFPMER', 'task', '06FB0TNSRZXCHGS16BFHSSGSV4', 'Bridge: escalate persistent corrupt-stream errors to shutdown (oversized-prefix poison)', 'Follow-up from the T-1045 review (2026-06-12). The receive_bridge_inputs catch-all arm logs unknown bridge errors once per tick and retries; a protocol-violating stream is unrecoverable by design (the FrameAccumulator oversized-prefix guard deliberately re-reports InvalidData on every poll), so a corrupt stream logs at 20 Hz forever with no escalation and no client feedback. Roughly parity with pre-T-1045 behavior (garbage cascade), so not a regression — but decide and implement escalation: map InvalidData to a fatal arm in receive_bridge_inputs, or count consecutive identical-error ticks and shut down after N. See the catch-all comment in server/src/bridge/mod.rs (receive_bridge_inputs) and the poison-state comment in framing.rs. Optional rider from the same review: harden assert_split_frame_does_not_desync (server/tests/bridge_tcp.rs) with channel synchronization so the mid-frame poll is guaranteed rather than timing-likely.', 'backlog', 'low', NULL, 'server', NULL, '2026-06-12 11:41:59', '2026-06-12 11:41:59', NULL, '77ded3c2d4cf7c6c623868bdb7ff5dd5', 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 ('06FBPQ02VWJGXWDYT2SMXM9DTC', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'BUG: fjord/cliff/gorge/delta landforms repeat on the 64 m chunk grid (D-239 §10 violation)', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: four morphology generators fold world coordinates into the 64 m chunk frame, so region-scale landforms repeat every chunk — violating D-239 §10 (''features with wavelength > 64 m seed from Region-or-higher, not the chunk seed''; deliberately strengthened from Block-or-higher in the adversarial verification pass, tile-derivation-contract/workshop-outcomes.md:83). + +Sites (server/src/atlas/voxel.rs): +- generate_fjord_wall :594-597 — cross.rem_euclid(64)-32: a complete fjord (floor|moraine|wall cross-section) centred in EVERY chunk of a FjordWall region; a real fjord valley is one feature spanning the region. +- generate_cliff_coast :721 — seaward_coord.rem_euclid(64): the cliff face sits at intra-chunk offset 48-55 in every chunk, sawtoothing the coastline at 64 m pitch. +- generate_braided_delta :825 — cross.rem_euclid(64): the same three braid threads restart per chunk instead of anastomosing across the fan. +- generate_incised_gorge :1054-1057 — same fold: a gorge per chunk. + +Fix: compute each landform''s axis/centreline in REGION-anchored coordinates — derive the feature anchor (centreline position, coast-face line) once per region from the region-scale seed path that meander_phase/basin_direction already use correctly (chunk_context.rs:124-141), then measure each voxel''s distance to that anchor in continuous world coordinates (no rem_euclid against the chunk size). This matches the workshop''s seam-freedom principle: the algorithm must see positions with no knowledge of the chunk grid (tyre-round1.md:174-176). Preserve D-239 §9 chokepoint widths (fjord floor 4-8 m, gorge floor 2-8 m — currently honoured at :607-609, :1059-1062). + +Harness gap to close (T-1031 follow-up): current tests check per-chunk boundary smoothness, not feature uniqueness — add a multi-chunk assertion that a FjordWall/IncisedGorge region contains ONE valley spanning its chunks, and a CliffCoast region one continuous (warp-displaced) coast line. Sibling bug: river-channel-anchor (channels are origin-anchored and appear nowhere; landforms are chunk-folded and appear everywhere — fix both against the same region-anchor mechanism). Depends on scale-anchoring Q for the region''s physical extent, but the region-index anchor works regardless. Parent: T-750. Refs: D-239 §5/§8/§9/§10, D-010; T-1029, T-1031.', 'done', 'high', NULL, 'server', 'D-239', '2026-06-12 10:23:49', '2026-06-12 11:50:14', NULL, '153926bd42d88e318fae1709cc047fc3', 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 ('06FBPQ02QTVSZ1PXTGNCN6Y8KM', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'BUG: river channel centrelines anchored to the world-origin axis — channels absent in almost every chunk', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: channel centrelines are anchored to the world-origin axis. compute_channel_state (AlluvialPlain, server/src/atlas/voxel.rs:1648-1707) and compute_meander_channel_state (MeanderReach, :1556-1595) compute perp_distance = (cross - meander_displacement).abs() (:1694, :1583) where cross is the raw world-space voxel coordinate (derive_voxel_column takes tile_x/tile_y in world metres, :328-338; cross = vx or vy at :1653-1661). The channel centreline is therefore the world x=0/y=0 axis plus-or-minus meander amplitude: only chunks within ~(channel_width/2 + amplitude + jitter) metres of the world origin axis ever contain channel water, regardless of ChunkContext.has_active_channel / channel_width_m (chunk_context.rs:103-110). in_levee_band (:1602-1633) inherits the same defect, so levees are origin-locked too. Every has_active_channel chunk elsewhere on the body silently renders dry floodplain. + +Intended model (workshopped): channel positions derive from region/chunk-scale data, not world axes — D-239 §10 (one basin-direction + global meander-curve params; wavelength > 64 m seeds Region-or-higher) and tile-derivation-contract/gestalt-round1.md:152-162 (channel branch positions from a multi-seed Voronoi partition of the chunk area with D8 flow direction as attractor; meander_intensity controls deviation from the straight downslope path). + +Fix, two stages: +1. Minimal correctness: derive a deterministic cross-offset channel anchor at region scale (alongside meander_phase in derive_chunk_context, chunk_context.rs:124-141 — same Region-or-higher seed path) and measure perp_distance from that anchor, so an active channel actually crosses the chunks the region says it crosses, continuously across chunk boundaries. +2. Full model: gestalt''s multi-seed Voronoi + D8-attractor branch placement when BraidedDelta sub-classification (D-239 implementation note: deferred to ChunkContext) lands. + +Add a T-1031-harness believability check: a has_active_channel chunk at an arbitrary large world offset (e.g. chunk_pos (1000, -750)) contains in-channel voxels; channel position is continuous across adjacent chunk pairs. Sibling bug: landform-64m-repeat (same family, opposite direction — channels appear nowhere, landforms appear everywhere). Parent: T-750. Refs: D-239 §10, D-208 (D8), D-010; T-1029 (origin), T-1031 (harness).', 'done', 'high', NULL, 'server', 'D-239', '2026-06-12 10:23:49', '2026-06-12 11:50:14', NULL, '7358e6296911def4afa30c6e36bbe9e6', 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).', 'done', 'high', NULL, 'server', 'D-225', '2026-06-12 10:40:58', '2026-06-12 11:50:14', NULL, 'b873911a4635f336e9988abf7ddb2625', 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 ('06FBPQ02QTVSZ1PXTGNCN6Y8KM', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'BUG: river channel centrelines anchored to the world-origin axis — channels absent in almost every chunk', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: channel centrelines are anchored to the world-origin axis. compute_channel_state (AlluvialPlain, server/src/atlas/voxel.rs:1648-1707) and compute_meander_channel_state (MeanderReach, :1556-1595) compute perp_distance = (cross - meander_displacement).abs() (:1694, :1583) where cross is the raw world-space voxel coordinate (derive_voxel_column takes tile_x/tile_y in world metres, :328-338; cross = vx or vy at :1653-1661). The channel centreline is therefore the world x=0/y=0 axis plus-or-minus meander amplitude: only chunks within ~(channel_width/2 + amplitude + jitter) metres of the world origin axis ever contain channel water, regardless of ChunkContext.has_active_channel / channel_width_m (chunk_context.rs:103-110). in_levee_band (:1602-1633) inherits the same defect, so levees are origin-locked too. Every has_active_channel chunk elsewhere on the body silently renders dry floodplain. + +Intended model (workshopped): channel positions derive from region/chunk-scale data, not world axes — D-239 §10 (one basin-direction + global meander-curve params; wavelength > 64 m seeds Region-or-higher) and tile-derivation-contract/gestalt-round1.md:152-162 (channel branch positions from a multi-seed Voronoi partition of the chunk area with D8 flow direction as attractor; meander_intensity controls deviation from the straight downslope path). + +Fix, two stages: +1. Minimal correctness: derive a deterministic cross-offset channel anchor at region scale (alongside meander_phase in derive_chunk_context, chunk_context.rs:124-141 — same Region-or-higher seed path) and measure perp_distance from that anchor, so an active channel actually crosses the chunks the region says it crosses, continuously across chunk boundaries. +2. Full model: gestalt''s multi-seed Voronoi + D8-attractor branch placement when BraidedDelta sub-classification (D-239 implementation note: deferred to ChunkContext) lands. + +Add a T-1031-harness believability check: a has_active_channel chunk at an arbitrary large world offset (e.g. chunk_pos (1000, -750)) contains in-channel voxels; channel position is continuous across adjacent chunk pairs. Sibling bug: landform-64m-repeat (same family, opposite direction — channels appear nowhere, landforms appear everywhere). Parent: T-750. Refs: D-239 §10, D-208 (D8), D-010; T-1029 (origin), T-1031 (harness). + +Fixed 2026-06-12, commit 408bd39e (+ fmt fixup 993333fa). Region-anchored channel axes (channel_anchor_m) derived from the Region-or-higher seed path; perp_distance measured from the anchor, not the world origin. has_active_channel made honest in both directions (band-crossing gate, delta-belt floor). Harness: channel presence + gate honesty asserted at chunk (1000,-750), cross-boundary continuity under production chunk lookup. Golden case A now pins a genuinely in-channel Shallow voxel. Adversarially reviewed (approved; 3 minors fixed in-line). Gate: 1488 tests green.', 'done', 'high', NULL, 'server', 'D-239', '2026-06-12 10:23:49', '2026-06-12 11:50:14', NULL, '9d388b1ef84c48755de71466e0f4c3d5', 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 ('06FBPQ02VWJGXWDYT2SMXM9DTC', 'bug', '06FB0TNSRZXCHGS16BFHSSGSV4', 'BUG: fjord/cliff/gorge/delta landforms repeat on the 64 m chunk grid (D-239 §10 violation)', 'Workshopped-but-unticketed cascade work captured 2026-06-12 (cascade-refocus grounding pass). Full grounded scope follows. + +BUG: four morphology generators fold world coordinates into the 64 m chunk frame, so region-scale landforms repeat every chunk — violating D-239 §10 (''features with wavelength > 64 m seed from Region-or-higher, not the chunk seed''; deliberately strengthened from Block-or-higher in the adversarial verification pass, tile-derivation-contract/workshop-outcomes.md:83). + +Sites (server/src/atlas/voxel.rs): +- generate_fjord_wall :594-597 — cross.rem_euclid(64)-32: a complete fjord (floor|moraine|wall cross-section) centred in EVERY chunk of a FjordWall region; a real fjord valley is one feature spanning the region. +- generate_cliff_coast :721 — seaward_coord.rem_euclid(64): the cliff face sits at intra-chunk offset 48-55 in every chunk, sawtoothing the coastline at 64 m pitch. +- generate_braided_delta :825 — cross.rem_euclid(64): the same three braid threads restart per chunk instead of anastomosing across the fan. +- generate_incised_gorge :1054-1057 — same fold: a gorge per chunk. + +Fix: compute each landform''s axis/centreline in REGION-anchored coordinates — derive the feature anchor (centreline position, coast-face line) once per region from the region-scale seed path that meander_phase/basin_direction already use correctly (chunk_context.rs:124-141), then measure each voxel''s distance to that anchor in continuous world coordinates (no rem_euclid against the chunk size). This matches the workshop''s seam-freedom principle: the algorithm must see positions with no knowledge of the chunk grid (tyre-round1.md:174-176). Preserve D-239 §9 chokepoint widths (fjord floor 4-8 m, gorge floor 2-8 m — currently honoured at :607-609, :1059-1062). + +Harness gap to close (T-1031 follow-up): current tests check per-chunk boundary smoothness, not feature uniqueness — add a multi-chunk assertion that a FjordWall/IncisedGorge region contains ONE valley spanning its chunks, and a CliffCoast region one continuous (warp-displaced) coast line. Sibling bug: river-channel-anchor (channels are origin-anchored and appear nowhere; landforms are chunk-folded and appear everywhere — fix both against the same region-anchor mechanism). Depends on scale-anchoring Q for the region''s physical extent, but the region-index anchor works regardless. Parent: T-750. Refs: D-239 §5/§8/§9/§10, D-010; T-1029, T-1031. + +Fixed 2026-06-12, commit 408bd39e. All four rem_euclid(64) chunk-frame folds removed (fjord :594-597, cliff :721, delta :825/:865, gorge :1054-1057); landform axes anchored once per region in continuous world coords. D-239 §9 chokepoint widths preserved; two i32 wall-rise overflows on region-scale distances fixed (clamp before multiply). Harness: one-valley-per-region, one-continuous-coastline-per-region, braid-belt confinement. CliffCoast semantics deliberately changed: one coast split per region (the §10 intent), not 75% inland per chunk. L0/L1 goldens byte-identical — no upstream leak. Adversarially reviewed (approved).', 'done', 'high', NULL, 'server', 'D-239', '2026-06-12 10:23:49', '2026-06-12 11:50:14', NULL, '54193ccc0271e35ba5d9721568a099e8', 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). + +Fixed 2026-06-12, commit 49a74e93 (+ review hardening). FrameAccumulator state machine holds partial prefix/payload across non-blocking receive() calls; drain loop with per-tick cap covers inputs + atlas requests. Review fix_required item resolved: EOF mid-frame now escalates to Disconnected (peer dead, frame can never complete) instead of per-tick Io error spam — regression test added (2 prefix bytes then drop). Minors: comment reworded; corrupt-stream escalation filed as T-1072; split-frame test hardening noted on T-1072. Gate: 1488 tests green.', 'done', 'high', NULL, 'server', 'D-225', '2026-06-12 10:40:58', '2026-06-12 11:50:14', NULL, '5f314f655cd285f4e8ad7e481e254cb6', 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);