- make test-tooling: planet-gen determinism guard + import_economics
--dry-run, wired into pre-push on TOOLING_CHANGED; ruff widened to
E4/E7/E9/F/W (90 safe auto-fixes applied; E402/E702/F841 ignored with
documented counts)
- one-generator reality fixed in DEVOPS.md, asset-pipeline rule, CLAUDE.md
(import_economics sole generator since #951/D-223); dead check-protocol
target deleted; DEVOPS hook/config sections rewritten from the actual
hook sources; team-patterns gate description updated (client+tooling)
- project.yaml: 0.2.0 → 0.4.0 per the 0.{phase}.{n} scheme, description
refreshed from the v0.1 Sova narration to cascade reality
- stale comment sweep: voxel.rs stub claims (all 8 families implemented),
cascade.rs TODO recited to T-1044, main.rs D-192 handshake claim,
relationships.rs/chunk_streaming.rs version targets → phase language
- gitignore: client/settings.db* e2e-run artifacts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- workers/pool.rs: 5 new tests; catch_unwind keeps worker threads alive on
handler panic (in-flight request loss unchanged, pinned by test + #843
docs); stubs.rs no longer falsely claims the pool is tested
- save/load: execute_save_load pinned .after(Storyteller) so the scheduler
cannot legally save pre-Input state; exclusive-system exception recorded
in tick_phases.rs rules
- surname corpus extracted to bin/shared/surname_corpus.rs (both economy
generators import it; byte-identical output verified on 23.6MB+1.45MB
TOMLs); all three stamp/watch registries updated
- generator_spike gated behind non-default 'generator-spike' feature
- economy.rs: 11 new D-181 signal-derivation tests on the new
econ_sim Simulation::from_economy in-memory constructor
- perception exemption comments now state the consumer sort contract;
unused bytemuck removed; rayon comment corrected; the 22 allow(dead_code)
documented as serde schema enforcement
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Production fixes surfaced by honest test triage:
- hud_groups.gd: _set_group_z crashed on freed HUD nodes — the typed loop
variable errors before the is_instance_valid guard runs; prune first
- fog_state.gd: _resize cleared _prev_visible (world-space keys survive
resizes), so pre-resize tiles never decayed VISIBLE→EXPLORED (D-059)
Test debt (T-928/929/934/935/936/937/938/939, T-864, T-973): lambda
local-capture bugs rewritten with array captures (now assert exact
emission counts), e2e suites updated to the current handshake +
StartupMessage protocol and stream-aware reads against the live binary,
fog perf test measures steady state, chime test pins the shipped 800ms
catalog asset (D-067 amended separately), monologue gdUnit4 API typo,
battery-warning tests follow the MetaScreen on_open lifecycle. 3 sprint2
proof tests revived (corner_reveal had passed from the wrong tile — NPC3
blocks (18,14); route corrected). Soft-skips converted to real do_skip
reporting. T-1068: 7 orphan .gd.uid deleted, _format_pop/_format_radius
deduped into atlas_format.gd (preload, no class_name — headless cache).
Suite: 1264 cases/20 failures → 1268/0, independently re-verified
(2536/2536, exit 0).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
derive_chunk_context now derives channel_anchor_m and coast_anchor_m from
the Region-or-higher seed path (D-239 §10); all five voxel placement sites
measure distance to these anchors in continuous world coordinates:
- T-1040: compute_channel_state / compute_meander_reach_channel /
in_levee_band subtract the region anchor instead of measuring from the
world origin axis — active channels now exist in their chunks anywhere
on the body, continuous across chunk boundaries. has_active_channel is
honest in both directions (band-crossing gate; floor covers the
BraidedDelta belt at short wavelengths).
- T-1041: fjord/cliff/gorge/delta drop their rem_euclid(64) chunk-frame
folds — one valley/coastline/fan per region instead of one per chunk.
D-239 §9 chokepoint widths preserved; two i32 wall-rise overflows on
region-scale distances fixed by clamping before multiply.
Harness: 6 new believability tests (channel presence + gate honesty at
chunk (1000,-750), cross-boundary continuity, one-landform-per-region,
braid-belt confinement); drainage sweeps strengthened with anchor-band
chunks. Voxel golden regenerated deliberately: case A now pins a genuinely
in-channel Shallow voxel on the anchor, case C a Deep trough voxel
matching its label; case B byte-identical and L0/L1 cascade golden
untouched (no upstream leak). Review: approved, three minors addressed
(truncation-convention docs, delta gate floor, case C relocation).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
FrameAccumulator state machine in framing.rs holds partial prefix/payload
bytes across non-blocking receive() calls — a frame split across TCP
segments no longer desyncs the stream (read_exact previously discarded
partially-consumed bytes on WouldBlock). receive_bridge_inputs now drains
all ready frames per tick (capped) instead of exactly one, covering input
batches + atlas requests in the same window.
Review hardening: EOF mid-frame escalates to Disconnected like clean EOF
(peer died with a truncated stream) instead of logging an Io error every
tick. Tests: frame split inside prefix / inside payload, multi-frame
drain, mid-frame-EOF disconnect. Corrupt-stream escalation tracked as
T-1072.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mapping is redundant: every filed record (T-1038..T-1071, Q-110..Q-122,
D-225/D-241 amendments) cites its audit stub ID in its own body, and the
ledger itself remains in history at d23d54b3d if ever needed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
416 binary files (~1.7 GB: .glb/.gltf/.bin/.png) removed from the index,
kept on disk; spikes/ keeps verdict/review markdown + spike code tracked
(61 files). .gitignore extended to cover model/texture/render binaries
under spikes/ going forward. Reproducible from purchased packs in
docs/assets/downloads/ + tracked scripts; zero markdown-embedded images
in spikes/, so no docs break. History rewrite deliberately NOT done —
recorded as out of scope in D-241. Closes fable-ous.md finding S-14.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rewrites the committed .pql/changelog/ from the old T-NNN-keyed format to
the record_id identity model (pql 1.10.0, D-26): tickets keyed by a ULID
record_id, the friendly T-NNN in ticket_idmap, references and hashes
recomputed. Produced by the one-off cmd/migrate-ids in the pql repo.
Other clones: install pql >= 1.10.0, then rm .pql/pql.db && pql plan
rebuild to regenerate the local DB from this changelog.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The four voice::lookup tests shared one on-disk cache directory (base_dir
temp/sr-voice-lookup-test + world_seed 99). VoiceCacheStore persists on Drop
(save_all) and reloads on first zone access (load_zone), and cache_hit stores
'Voiced line.' under the identical (zone_id=100, CacheKey) that cache_miss looks
up — so under parallel execution the hit test's Drop/save could leak into the
miss test's lookup, returning 'Voiced line.' instead of 'Base line.'.
Give each test a directory keyed by test label + process id, so neither parallel
tests nor concurrent cargo test runs collide. Verified clean across repeated runs.
Closes T-1035.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
derive_moisture_q matched hydrosphere on 'ocean'/'rivers'/'subsurface', but the
real bodies.hydrosphere vocab in systems.db is dominated by 'liquid_water' (175
bodies) — so most surface-water worlds fell to the '_ => 30' default, propagating
wrong precipitation_class / glaciation_grade / vegetation. Same root cause as
D-240 (code keyed on a vocab the data doesn't use).
Align the match to the canonical vocab, grouped by available surface moisture
(mirrors the [hydrosphere_maritime] table from T-1033): surface liquid
(liquid_water/ocean/ocean-coastal/extensive) -> 80; rivers/rivers-lakes/moderate
-> 55; ice -> 20; subsurface_liquid -> 15; subsurface/subsurface_ice -> 10;
minimal/trace -> 5; none -> 0. Add a liquid_water regression test and broaden the
clamp sweep to the full vocabulary.
Closes T-1034 — last open ticket under epic T-974 (Atlas-to-tile derivation),
which is now complete.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe review findings — close silent-pass gaps in the §8 drainage tests:
- assert_drainage_monotonicity now returns whether it actually checked (chunk
had both wet and dry tiles); the three sweep tests (Alluvial/Meander/Braided
Delta) assert at least one chunk exercised the law, so a regression that
zeroes all channels fails loudly instead of passing vacuously.
- The fjord-floor test scans the full 64x64 chunk instead of a single Y=32 row
and asserts the deep-water trough exists, so the sea-level floor law can no
longer be skipped by a probe that missed the trough.
- Remove the unreferenced make_test_terrain_analysis helper (was behind
#[allow(dead_code)] with a 'future use' comment — the maintenance trap the
review flagged); make_dry_terrain_analysis covers the validation bodies.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adapt the believability/budget verification harness to the T-1033 BodyParams
strip: validation-body fixtures (Kallast/Glødberg/Marevna) no longer set the
removed orbit/star fields (orbital_period_days, axial_tilt_deg, spectral_class,
star_type). Temperature is now derived from the planet_class envelope (D-240),
so the Marevna validation note/assertion is rewritten — oceanic band [-12,28]°C
+ maritime 0.6 + standard-atmosphere greenhouse yields ~+26°C at the equator
(was a stale ~-56°C orbit-equilibrium note). Add the seed→tile golden fixture
(tests/golden/derivation_harness.json) that the determinism regression locks.
Also fmt the harness and fix one clippy lint (iter().copied().collect() ->
to_vec()) — the file predated the pre-push gate's cargo-test/clippy coverage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-review of the maritime moderation addition (Hoshe REQUEST_CHANGES, Tyre APPROVE):
- every_planet_class_derives_within_its_band now sweeps hydrosphere
(none/ocean/liquid_water/rivers/ice) as well, so the maritime-compressed
gradient path is covered by the band invariant — not just the None/1.0 case.
(Hoshe #1, Tyre #1)
- Update the BodyParams.hydrosphere doc comment to the real systems.db vocabulary
(liquid_water/ocean-coastal/extensive/etc.) the maritime table keys on. (Hoshe #2)
cargo test passes (the band sweep now ~59k in-band assertions), clippy -D warnings
clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the D-240 hydrosphere modulator: water-rich worlds compress the equator->pole
temperature gradient toward the band midpoint (milder at both ends); dry worlds
swing the full class band.
- [hydrosphere_maritime] table in climate_constants.toml + ClimateConstants
field/method (maritime_factor). Keyed on the ACTUAL bodies.hydrosphere vocab
(liquid_water/ocean/extensive=0.6, rivers/moderate=0.8, ice=0.85, subsurface*
=0.9-0.95; minimal/trace/none/NULL -> 1.0).
- derive_temperature_c step 2 now lerps across a maritime-compressed sub-band
(mid +/- band_half*factor) instead of the full band. Clamp still guarantees the
class-band invariant.
- New maritime_hydrosphere_compresses_the_gradient test (ocean delta < dry delta).
Verified on real worlds: liquid_water/ocean temperate worlds now delta ~24 (milder)
vs dry ~40, all in-band. cargo test passes, clippy -D warnings clean, fmt clean.
Note: discovered derive_moisture_q has the SAME vocab mismatch (expects 'ocean',
DB uses 'liquid_water' for 175 bodies -> falls to default moisture). Pre-existing,
out of scope here — filing a follow-up.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Band-invariant test now sweeps high altitude (6 km) as well as sea level, so
the lapse term + cold-end clamp are exercised jointly, not lat alone. (Hoshe #1, Tyre #3)
- Clarify the temp() helper comment: seed 0 is deterministic but still applies a
constant non-zero nudge. (Hoshe #2)
- (Hoshe #3: confirmed tectonic_activity is genuinely absent from systems-schema.sql;
the reader's 'not in schema' comment is accurate — no change.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the sun-driven Stefan-Boltzmann temperature with the D-240 class-envelope
model. Temperature derives only from authored fields — no orbit/star physics.
- [planet_class_temperature] envelope table in climate_constants.toml (approved
bands: frozen [-90,-25] .. hot_arid [20,58] .. volcanic [30,90]); cold_/hot_/
warm_ prefix parsing; temperate fallback for unknowns.
- derive_temperature_c(params, constants, body_seed): band = envelope(planet_class);
latitude lerps across it (equator=warm, pole=cold); atmosphere greenhouse +
elevation lapse modulate within; small seed nudge for per-body variety; CLAMP to
band — a body can never escape its class. Airless -> None.
- Delete the dead astrophysics: derive_distance_au, ClimateConstants::luminosity(),
the [star_luminosity] table. Strip orbital_period_days/spectral_class/star_type/
axial_tilt_deg from BodyParams + BodyParamsReader (read 3 cols from bodies, no
star_systems join). DB columns left in place (no regen).
- New every_planet_class_derives_within_its_band test (13 classes x 5 atmo x 19 lat
x 4 seeds, all in band) — the D-240 consistency guard.
Verified on 25 diverse real bodies: the worlds that derived to +356C now sit inside
their class bands (temperate capped at 28C). cargo test passes, clippy -D warnings
clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Record D-240: a body's orbital position and stellar assignment are placeholder
registry data with no authored physical intent, so no derivation may use them as
physical inputs. Climate derives from authored planet_class (temperature envelope)
+ atmosphere + hydrosphere + seed. Supersedes the sun-driven Stefan-Boltzmann
portion of D-239 §2, which produced +356 C 'temperate' worlds (NULL spectral_class
-> G-Sun default on an M-dwarf catalog).
File T-1033 under T-974: rewrite derive_temperature_c to the class-envelope model,
drop the orbit/star inputs, regen the T-1031 golden. Audit confirmed the blast
radius is one function (derive_temperature_c).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe found a CRITICAL coherence defect (Tyre APPROVE):
- CRITICAL: cluster_scatter received the per-voxel sub_chunk_seed as its cluster
seed, so voxels in the same 6m cell got different scatter -> salt-and-pepper,
not the §3-mandated clustered patches. Re-key on (world, body, cluster-cell):
add SeedDomain::Cover=10 (pinned); cluster_scatter(world_seed, body_id, x, y)
derives for_body(world_seed,body_id).derive(Cover, cluster_pair_id). derive_cover
now takes (world_seed, body_id, ...). (Hoshe #1)
- The coherence test was tautological (constant seed bypassed the broken path).
Rewritten to the production derive_cover signature in a cold-lake scatter band;
it FAILED at 20% on the old code, passes 100% now. (Hoshe #2)
- Zigzag-encode cluster (cx,cy) before Cantor pairing (negatives were cast as u64
directly); fix the misleading 'no collision' comment. (Hoshe #3, Tyre)
- Sea-ice band was inverted (~85% ice at the -2 onset). Now monotonic: ice grows
~8% (onset) -> ~92% (cold edge); leads (open gaps) layered only in the cold half
via a 3x super-cell, passing the super-cell index directly. Dead depth==0 guard
removed. (Hoshe #4, Tyre #1/#3)
cargo test passes, clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D-239 §3 — the static mean-state freeze/snow cover. New SeasonalCover
{None,Snow,Ice} overlay axis on VoxelColumn (D-228 cover, NOT TerrainMaterial),
derived after the family generator in derive_voxel_column.
- Spatially-COHERENT cluster scatter (never per-tile dice): coarse 6m cluster
cells (div_euclid) -> Cantor pair -> splitmix64 ^ sub_chunk_seed, so voxels in
a cell share the freeze decision -> ragged patches. All integer (D-010).
- Bands by surface (classify_surface from morphology_zone + water): freshwater
+5..-10C; salt water (OpenOcean) -2C onset / -14C, 3x-coarser sheets+leads;
land snow +2..-10C, moisture-gated (moisture_q<30 -> None). Linear frozen
fraction across the band; permanent below the band (poles/glaciers).
- Airless (temperature_c None) -> cover None.
- Transient/clock-bound layer (dawn frost melting by noon) doc'd as a Q-105
forward contract; only the static model is built.
16 new cover tests incl real spatial-coherence (>=90% intra-cluster agreement),
band edges per surface, moisture gating, determinism. cargo test passes, clippy
-D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe REQUEST_CHANGES + Tyre APPROVE:
- Cache key omitted world_seed → a cache reused across worlds could return
another seed's column. CacheKey is now (world_seed, body_id_hash, voxel_pos).
(Hoshe #1)
- Sub-chunk voxel seed reused SeedDomain::ChunkContext (tier-collision risk vs
the region meander seed). Add SeedDomain::Voxel = 9 (append-only, pin test
updated) and use it. (Hoshe #2, Tyre #1)
- get_or_derive forced callers to pre-compute body_id_hash while fnv1a_64 is
pub(crate). Drop the param; compute the hash internally. (Tyre #2)
- Fix two inaccurate comments (micro-relief range [-4,+3] not ±2; scatter mask
is 4-bit [0,15] not bits [4:6]). (Hoshe #3/#4)
- Strengthen the LRU eviction test: add a test-only contains_voxel() helper and
assert WHICH entry was evicted (refreshed pos survives, LRU pos evicted). (Hoshe #5)
- LRU O(capacity)-scan perf flagged on T-1031 (Tyre #3, deferred to the budget harness).
cargo test passes, clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D-239 §1/§7/§10 — the lower derivation chain end-to-end with the AlluvialPlain
fallback only (specialized families are T-1029).
- chunk_context.rs: ChunkContext (64m) — basin_direction + meander phase/wavelength
+ active-channel params. NO per-tile flow_direction[64x64] (D8 ~152m coarser than
a chunk, D-239 §10); features >64m seed from Region-or-higher. SeedDomain::ChunkContext=8.
- voxel.rs: VoxelColumn (1m) composing the D-228 tile axes (TerrainMaterial /
FloorMaterial=None / Vegetation / Water / elevation_m). Derive-on-demand + VoxelCache
(LRU BTreeMap, never persisted per D-227). Domain warp (T-1026) wired through:
f64 warp -> as-i32 truncation to the voxel address; all material/morphology gates
integer (D-010 — the meander wavelength f64 is truncated before the Water decision).
- AlluvialPlain generator: Soil/Wetland terrain, climate vegetation, integer-meander
channel (Shallow/Deep) from ChunkContext. The other 7 families are dispatch stubs
(canonical terrain material, fall back to AlluvialPlain geometry) — no panic.
29 new tests incl end-to-end determinism (same seed/pos -> identical column),
cache hit/miss/eviction/re-derivation, warp-applied. cargo test 1563 pass,
clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe REQUEST_CHANGES + Tyre APPROVE:
- Riparian vegetation logic was doubly-wrong: it granted the micro-oasis only
in the impossible cold case (temp < -50, no liquid water) and DENIED it in the
intended hyper-arid case. Split: extreme cold -> Barren always; hyper-arid ->
RiparianScrub iff near perennial water. (Hoshe #2)
- morphology_zone_has_exactly_17_variants was misleading (asserted >=16). Rename
to morphology_zone_region_scale_emits_16_of_17, tighten to ==16, and document
that BraidedPlain is the lone region-unreachable zone (needs lithology, deferred
to ChunkContext) and that Lake IS reachable. Tyre's 'Lake also deferred' was a
false positive (ocean 60-79 -> Lake). (Hoshe #1, Tyre #1)
- derive_morphology_zone docstring now lists the real multi-path emission sites
for TidalFlat/Wetland, ValleyFloor/RiverBank as their own gates, and BraidedPlain's
deferral — the §6 parent-family names are descriptive, not exhaustive. (Hoshe #3, Tyre #2/#3/#4)
- D-239 record: added a T-1025/T-1027 implementation note (enum freeze location,
16/17 region reachability + BraidedPlain deferral, §7 gate-ordering interpretation).
No vocabulary change. cargo test passes, clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Hoshe: body_without_system_row test inserted a NULL system_id, impossible
under production schema (system_id NOT NULL REFERENCES star_systems). Rewrite
as body_with_orphan_system_id_* — non-NULL system_id with no matching
star_systems row (the real case the LEFT JOIN guards) + NOT NULL in the test
schema + corrected comment.
- Tyre: cascade.rs PERF/TODO comment said the region path 'defers to T-1032';
T-1032 IS this PR, so production dispatch is now live. Update to track T-1028
only and note the cost is live in production.
No production logic change. cargo test body_params_reader 7 pass, clippy clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The D-239 carrier layer (T-1023/1024/1026) only ran in tests because every
production AnalyzeBody enqueue passed body_params: None. Wire the real path:
- New BodyParamsReader (server/src/atlas/body_params_reader.rs): read-only
systems.db reader, joins bodies -> star_systems (LEFT JOIN) for the climate/
tectonic inputs. SQL verified against systems-schema.sql. All fields Option,
NULLs handled; tectonic_activity absent from schema -> None (derives from
planet_class). 5 unit tests.
- layer_proxy.rs: on cache miss, read the body's params and pass
Some(Box::new(..)). On read error, warn + fall back to None (cascade stops at
Settlement, no panic) — graceful degradation.
- plugin.rs / main.rs: register BodyParamsReaderResource (CityContextReader
pattern) and thread it through serve_atlas_requests.
BodyWorldState.regions now populates for real bodies in the D-206 background
pass. End-to-end tests cover wired (regions populated) + unwired (empty) paths.
cargo test 1504 pass, clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D-239 three-carrier foundation merged to main. Review found a correctness
bug (per-region elevation) + hollow determinism tests, both fixed before merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Re-review (Hoshe + Tyre, both APPROVE) caught one stale comment: after the
per-region elevation fix, derive_region_profile owns elevation_km (from elev_q),
not the caller. Update the comment so maintainers don't read it as caller-supplied.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe + Tyre review (CHANGES REQUESTED):
- domain_warp golden tests were hollow (discarded values, only asserted
dx!=dy). Consolidate into one real golden_vector test with pinned f64
literals as the regression anchor. (Hoshe #1, Tyre #2)
- Per-region temperature used body-level elevation_km for every region, so
alpine and sea-level regions on a body got identical lapse — defeats the
D-239 §2 per-district temperature. Derive elevation_km per region from the
region's own elev_q (× MAX_REGION_ELEVATION_KM). (Tyre #1)
- Region seed was derived under SeedDomain::DomainWarp (collision risk with
the tile warp) and discarded unused. Remove it + the orphaned region_pos_id
and SeedDomain import; keep a reserved _seed param for T-1027/T-1028. (Hoshe #2)
- Fix inverted tilt_factor comment. (Hoshe #3)
- ClimateConstants doc referenced a load() that doesn't exist; correct it —
embedded default() is authoritative today, climate_constants.toml is the
canonical mirror, runtime load lands with T-1032. (Hoshe + Tyre)
- cascade.rs: drainage re-run was mislabeled 'cheap'/'no drainage needed';
document the real cost + PERF/TODO(T-1028/T-1032) against the D-239 §10
budget. (Tyre #3)
cargo test 1497 pass, clippy -D warnings clean, fmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add step 1a: check open PRs first and recommend /pr-review (review -> merge)
before selecting a batch. Open PRs are in-flight WIP; starting new work on top
piles up the board, and the cascade-correct next batch is often dependency-gated
on an in-review PR (won't show as --unblocked, or must stack on an unmerged
branch). Renumber the existing 1a-1d substeps to 1b-1e.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add `cargo test --quiet` to the pre-push Rust block (sharing clippy's
target/ guard) so the suite runs automatically on every push touching
server/. Nothing ran the tests before — pre-push did only fmt/clippy/deny
and there is no CI — so a Rust regression could reach main unverified.
Document the resulting agent-spawn rule in team-patterns.md: don't have
implementation agents pre-run fmt/clippy/test pre-emptively, since the push
gate now enforces all three. The gate is authoritative; the lead patches any
fallout at push.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T-1023/1024/1026 implemented and pushed as PR #158; moved to review.
T-1032 (new, under T-974) tracks wiring the production AnalyzeBody dispatch
to read BodyParams from the DB — currently always None, so the carrier layer
only runs in tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First foundation slice of the Atlas-to-tile derivation model (epic T-974),
building the carrier layer ahead of its T-1027+ consumers.
T-1026 — Anti-squaring domain warp (D-239 §4): stateless pure
fn(seed,body_id,pos)->(f64,f64), ±8m, f64 to the final voxel then as-i32
truncation for IEEE-754 cross-target determinism. New domain_warp.rs,
SeedDomain::DomainWarp; golden-vector + cross-thread tests. Position math
only — D-010 integer discipline preserved downstream. Marked dead_code
until the T-1028 VoxelColumn pipeline consumes it.
T-1023 — RegionProfile carrier (D-239 §1,§10): new RegionProfile +
TectonicClass/GlaciationGrade/PrecipitationClass enums + BodyParams; derived
per-region river_threshold replacing the global 200 for tile consumers.
regions: BTreeMap on BodyWorldState, populated via the cascade's new
RegionProfile layer (runs when body_params is Some, else falls back to
Settlement). D-010 integer discipline, BTree ordering.
T-1024 — District climate primitives (D-239 §2): nullable temperature_c +
moisture on RegionProfile, mean-annual scalar (no clock dep; dynamic branch
deferred to Q-105). Hybrid inputs — new bodies.axial_tilt_deg column imported
from planet-gen body-defs (populate_axial_tilt_deg, 2611 bodies), luminosity
and orbital distance derived at runtime; greenhouse + diurnal-swing tables in
source-canonical climate_constants.toml. D-239 implementation note added.
cargo test: 1498 passed, 0 failed. clippy clean (pre-existing
large_enum_variant only). make check-systems-db: stamp fresh.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR #157 merged -> T-1022 done. Activate the D-239 three-carrier foundation
batch via /whats-next: T-1023 (RegionProfile), T-1026 (domain warp), and
T-1024 (district climate) with refinement notes. T-1024 blocked-by T-1023
(temperature fields live on the RegionProfile struct).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The file was last updated 2026-04-05 (Sprint 32) and had gone
comprehensively stale: it claimed Phase 1 active / Sprint 32 current,
listed D-001..D-170 (now D-239), and showed the pre-D-166 phase
ordering (player control before world gen, with a 2-floor test map) —
directly contradicting the canonical cascade in CLAUDE.md. All of its
content is canonical elsewhere (cascade in CLAUDE.md, phase + decision
status in pql/governance), and no briefing references it anymore.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The repo moved to /var/mnt/data/projects/settled-reach (flat layout,
no more /main worktree subdir). Drop the stale autoMemoryDirectory
override (pointed at the old /home path; revert to the native
per-slug memory store) and gitignore .worktrees/, which now holds
per-machine git worktrees under the repo root.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Layer-4 quarter-skeleton geometry (D-234: morphology-correct streets +
the D-234b waterfront rule) was fully implemented but dormant — no
production call site dispatched GenerateSkeleton from a settlement
placement, so founding_orientation stayed pinned to the
context_from_read_set Cardinal stub.
Expand the BodyAnalyzed arm of drain_generation_completions to, before
caching the body, submit one GenerateSkeleton per CityPlacement: build the
D-199 context from the read-set, override founding_orientation with the
attractor-matched value carried on the placement (D-213), and derive a
canonical namespace-isolated quarter_id from (world_seed, body, city)
(D-194/D-230) instead of the city_id*10 placeholder. Dispatch logic is
extracted into the pure build_skeleton_work_item helper for DB-free testing.
Reader + world seed are optional system params (mirrors serve_atlas_requests);
absent either, dispatch is skipped and the body is still cached. Empty
placements and per-placement read_set errors are handled (warn + skip).
Station/multi-source dispatch (Q-109) is out of scope — BodyAnalyzed only
fires on the planetary AnalyzeBody path.
Tests: orientation-override + canonical-quarter_id unit test and a
determinism/city-scoping test on the helper. Full lib suite green (1327).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
T2: background agent / lead writes are confined to the session root, so an
out-of-root sibling worktree (.worktrees/<branch>) is unwritable — the
agent could design but not write, and there's no permission to grant. Fix
options for clide noted. Plus a positive: clide image show works first-try.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Architecture diagram for D-239: inputs -> three-carrier refinement chain
(RegionProfile -> ChunkContext -> VoxelColumn), the district-temperature
climate primitive + derived freeze/snow, the 8 gated morphology families
over the frozen 17-zone vocabulary, and the anti-squaring domain warp.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hand-off material for the clide team. Headline: team mode works at the
Claude layer but is invisible in clide's UI — teammates ran in-process
(no pane), the Team Chat view stayed inert, no `clide team` verb. Captured
live during the Q-101 workshop; suggested fixes included.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- T-1017: removed 5 stale done-blocker edges (T-957/993/1005/1010/1016); only
T-977 (architecture-flavor pipeline) genuinely blocks it now, so it auto-unblocks
when T-977 ships.
- T-999: resolved the description contradiction — appended a clarification that the
condition overlay does NOT feed D-100 DamageOverlay (the T-979 refinement is
authoritative); BuildingConditionState is standalone.
- T-960: noted the sole remaining gap to close (gen_l0_heightmap overlay absent from
OVERLAY_DEFS, required by D-226 acceptance criteria).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Si one-pass sweep of T-750's 38 open children (2026-06-07) found 3 more done-but-open:
- T-958 block irregularity (block_irregularity.rs, tested, wired)
- T-983 CityGenerationContext extension (all 4 fields, PR #145)
- T-975 ocean/lake water mask (features.rs, D-209/D-223)
Rest of T-750 is genuinely open or blocked — drift was concentrated in the #957
walkable-quarter merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Si vet (2026-06-07) of the next batch found the same drift as T-985/986: the street &
footprint geometry already landed under T-957. Marked done with evidence notes:
- T-989 morphology->street-pattern lookup (street_topology/derive_corridors)
- T-990 corridor/access-point network (Prim-MST, ±45° snap)
- T-991 BSP footprint subdivision + D-233 coverage + D-234b waterfront rule
- T-976 (parent) — all four geometry deliverables done+tested
Filed T-1022 for the genuine residual: the Layer-3 -> Layer-4 GenerateSkeleton
dispatch (founding_orientation wiring) that activates the dormant geometry in
production. A distinct cross-layer concern, not street geometry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D-229 makes BuildingPropertyTag the typed step-3 output that replaces the era/
society_profile/zone_palette String stubs on the skeleton. The tag + its derivation
(zone_type_id, flavor_ref, era/ConstructionEra, FloorExtent) all landed under T-957/
T-1006; this removes the now-dead stub fields they superseded:
- BlockSkeleton.era_modifications: Vec<EraModification> (era is per-footprint on
BuildingPropertyTag.era now; era_cause retained as the block-level cause)
- QuarterSkeleton.society_profile: SocietyProfileRef (culture → tag.flavor_ref)
- QuarterSkeleton.zone_palette: Vec<ZoneDefinition> (zoning → tag.zone_type_id;
distinct from FloorZone.zone_palette: ZonePalette, the real D-101 palette, kept)
- the now-orphaned `EraModification` and `SocietyProfileRef` String aliases
Kept: chunk_layout (real ChunkLayout / D-234 street network), z_band_zones (still
uses the ZoneDefinition alias), boundaries (separate stub, not D-229 scope).
cargo check + clippy -D warnings --all-targets clean; full server lib suite
1325 passed / 0 failed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Board cleanup surfaced by /whats-next + Si refinement: both tasks' work was already
merged (QuarterWorldState{skeleton,block_tags} + assign_all_block_tags + GenCompletion
state carrying for T-985; the four zone/entry/era/condition derivation fns + 31 D-142
RON files for T-986), but the tickets had drifted in backlog. Marked done with notes;
verified against server/src. T-984's residual (society_profile/zone_palette/EraModification
String stubs) is genuine remaining work — handled next on its own branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Log the pql migration (PR #154/#155): planning system moved off settledreach.db
onto pql (governance DQR tree + git-tracked changelog, T-NNN ids, phases gated on the
cascade hierarchy), the clide IDE skill, and the Phase-6 removal of the legacy SQLite
ticket/decision tooling. Corrected the unreleased D-221 entry's stale "many-to-many
milestones" claim.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The migration shipped (Phases 0-5 in PR #154; phases-as-hierarchy + Phase-6 SQLite
retirement in PR #155), so the plan is done. Moved pql-migration.md from the repo root
to docs/architecture/, flipped status approved -> completed, and added a header pointing
to the current-usage docs (CLAUDE.md, ticket-cli.md, governance/README.md) and the
tooling/pql-migrate/ transforms. Kept as a why/how record of the move off the binary
SQLite DB. pql-requirements.md stays at root — still-open feedback for the pql team.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hoshe (QA): docs/DEVOPS.md Repository Layout still listed `decisions/` — corrected to
`governance/` (the DQR tree) and added a `.pql/` entry for the planning store.
Tyre (architecture, non-blocking): tooling/db/common.py docstring named deleted scripts
as consumers and `resolve_db_path`/`load_config`/`get_connection` were dead settledreach.db
code. Trimmed common.py to just `ensure_venv` (the only symbol any kept connector imports)
and rewrote the docstring to name the real consumers.
ruff clean; common.py parses; ensure_venv intact.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The pql cutover is stable, so remove the superseded SQLite planning tooling. Surgical
— only the ticket/decision/raw-SQL scripts (all settledreach.db-bound and replaced by
pql) are deleted; the asset/audio/wiki connectors and shared common.py stay.
Removed:
- tooling/db/{ticket,decision,decisions-sync,decisions_sync.py,sqlite-query,sqlite-exec,
sqlite-init,sqlite-seed,sqlite_connector.py}
- tooling/{db-backup,db-install} + docs/backups/settledreach.db.backup (the binary-DB
backup ritual; tickets now live in the git-tracked .pql/changelog/)
- tooling/check-decision-ids (dead stub, superseded by `pql decisions validate`)
- Makefile db-backup/db-install targets; SR_DB_PATH + tooling/db/{ticket,sqlite-*,
decision*} entries from .claude/settings.json (audio entries kept)
Updated docs to pql: DEVOPS.md (SQLite Access + Decisions System → pql), project
structure, ticket-cli closing note, asset-pipeline raw-SQL warning.
Kept (verified still imported by the asset connectors via common.ensure_venv): common.py,
config.json, audio/image/trellis/wiki connectors. The live settledreach.db file
(gitignored, repo-parent) is left on disk as a cold rollback only.
ruff clean; pql decisions validate ok (357 decisions / 1013 tickets).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replaces the labels-as-milestones pattern (carried over from the retired SQLite
milestone subsystem) with pql's native initiative/epic hierarchy, which already
modelled this: initiative T-745 (Development Cascade) holds the six phases as epics.
A ticket is in a phase by being parented under that phase epic — self-maintaining,
no label to apply or forget.
The `phase:4` label had already drifted (66 tickets under the Phase-4 epic T-750 but
only 42 labelled). Fixes:
- T-750 (Phase 4) -> in_progress to mark the active phase (sequential per D-166).
- Re-parented the 2 strays (T-974 Atlas-to-tile epic, T-1008 economy task) under T-750.
- Dropped all 42 phase:4 labels (tombstoned in the changelog).
- /whats-next, /ticket, ticket-cli.md, CLAUDE.md now gate on
`pql ticket list --under <active-phase-epic> --unblocked` instead of `--label phase:4`.
- Fixed the label-action verb in the docs: pql uses `add|rm`, not `add|remove`.
- pql-requirements #9 flipped: no milestone entity / labels-as-milestones needed — the
initiative/epic tree is the answer.
Verified: `pql plan rebuild` reconstructs the mutations; `--under T-750 --unblocked`
returns the active phase's ready work.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The session now runs inside the clide IDE, which exposes its UI surface as a
`clide <subsystem> <verb>` CLI (observe + drive parity). Skill copied from the
clide project; documents `clide capabilities` as the authoritative discovery
command and the observe/drive verbs (editor/files/git/search/pane/ui/pql).
clide has the pql planning store wired in (Tickets + Decisions sidebar panels),
so the just-merged migration powers the IDE's planning UI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tyre (architecture review):
- .gitattributes: `.pql/changelog/*.sql` matched nothing (files are one level
deeper at .pql/changelog/<table>/<YYYY-MM>.sql), so the union-merge driver never
applied — `git check-attr merge` returned `unspecified`. Fixed to
`.pql/changelog/**/*.sql`; now resolves to `merge: union` for monthly + schema
files. Restores the changelog's conflict-free merge guarantee.
- Migration scripts: the re-runnable ones (seed_tickets.py, add_workshop_provenance.py)
now derive the repo root from `git rev-parse --show-toplevel` instead of a hardcoded
/main path, so re-running from a worktree/clone targets the right checkout. The three
one-shot transforms (restructure_decisions, repath_references, retag_ticket_refs)
get a comment noting they're already-applied and unsafe to re-run (git mv on moved
sources) — keeping the path honest rather than implying re-runnability.
Hoshe approved (all QA checks passed). ruff clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the Phase 4 consumer cutover: adds Bash(pql) / Bash(pql *) to
.claude/settings.json so the pql workflow runs without prompts. Added manually by
the lead — the auto-mode classifier blocks an agent from self-widening wildcard Bash
permissions even via /update-config (a deliberate security boundary).
SR_DB_PATH and the Bash(tooling/db/*) allowlist stay until Phase 6 (rollback path).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Workshop -> decision provenance was prose-only. Adds a `decision_refs:` YAML
frontmatter list (the confirmed D-records each workshop-outcomes.md touches,
filtered against the governance decision set) to all 17 workshop outcomes; the two
that lacked frontmatter (commodity-catalog, system-economic-specialization) get a
minimal block. pql indexes the list and `SELECT fm.decision_refs` round-trips it, so
"which workshops touch D-NNN" is answerable via SELECT + filter or `pql search`.
decision_refs is a relevance signal (decisions a workshop discusses/produces), not a
strict authorship claim — historical bare refs aren't disambiguated. Generated wiki
read-only sections are left untouched.
Noted in pql-requirements #5: 1.6.2 has no working DSL operator for frontmatter
list-membership (`~`/`contains` error, `in` matches nothing), so membership queries
need a client-side filter for now.
Reproducible via tooling/pql-migrate/add_workshop_provenance.py (idempotent).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Repoints the kanban workflow skills from tooling/db/* to the pql CLI:
- /whats-next: milestone queries -> `pql ticket list --label phase:4 --unblocked`
(--unblocked does the dependency walk, collapsing the old milestone + per-ticket
deps + milestone_deps steps); WIP via `pql ticket list --status in_progress` (pql
doesn't enforce the limit — warn manually); refinement append via `pql ticket append`;
activation via `pql ticket status`.
- /ticket: full reference rewritten to `pql ticket`/`pql plan`; milestone subcommands
-> phase labels; points at .claude/rules/ticket-cli.md.
- /pr-process: step 8 extracts T-NNN (maps bare #NNN -> T-NNN) and calls
`pql ticket status T-<id> review`.
- /bug-report: bug creation via `pql ticket new bug`.
- clerk: decisions-sync mechanism line -> `pql decisions sync` (factual fix only; the
agent's review logic stays for the #965 re-enable).
- workshop-start IMPROVEMENTS: the old `decision claim` non-idempotency footgun no
longer applies — `pql decisions claim` is side-effect-free.
pr-review/git-commit needed only the Phase-1 path repoint (no command refs); the
settledreach.db.backup exclusion in pr-review stays until Phase 6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrites the canonical command reference (.claude/rules/ticket-cli.md) and CLAUDE.md
to the pql CLI: `pql ticket`/`pql plan`/`pql decisions` replace `tooling/db/ticket`,
`sqlite-query`/`sqlite-exec`, and `tooling/db/decision`. Documents T-NNN ids, the
markdown-sourced governance decision tree, the rebuildable changelog-backed pql.db,
and labels-as-milestones (phase:4) in place of the removed milestone entity.
Maps the old surface accurately: ticket new (positional type+title), show
--with-context/--with-blockers, block --by / unblock --from, label add/remove,
decisions claim/list/show/validate/sync, plan whatsnext/review/status.
Behavioral/command cutover only — the legacy tooling/db/* and SR_DB_PATH stay as the
rollback path until Phase 6.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Folds pql's planning logic into the version-controlled .config/hooks/* (pql's own
.pql/hooks installer is dead under core.hooksPath=.config/hooks):
- pre-commit: + `pql decisions validate` (decision-ID/format gate, supersedes the
never-built check-decision-ids TODO) and `pql plan export --stage` (flush ticket
mutations to the git-tracked changelog and stage them into the commit). Both
guarded by `command -v pql`; export is a clean no-op when nothing changed.
- post-merge: `pql plan import` + `pql decisions sync` (replay incoming changelog,
re-sync markdown decisions).
- post-checkout (branch only): `pql plan rebuild` + `decisions sync`.
- post-rewrite (rebase/amend): `pql plan rebuild`.
- install-hooks chmods the three new hooks.
Makefile decision targets repointed to pql: decisions-sync -> `pql decisions sync`,
decisions-active -> `pql decisions list --type confirmed`, new decisions-validate ->
`pql decisions validate`. Dropped the SQLite-query conveniences (coverage/orphan/
orphan-tickets); per-decision coverage is `pql decisions show <id> --with-tickets`.
db-backup/db-install and SR_DB_PATH are intentionally kept until Phase 6 so the
legacy SQLite store stays intact as the migration rollback path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adopts the T-NNN convention (T-N == old #N == pql ticket id) across the active
operational layer: governance/ decision records, .claude/{rules,agents,skills},
CLAUDE.md, DECISIONS.md. 283 references rewritten.
Guarded against false positives (17 correctly skipped, each logged):
- PR references kept (PR #136/#138/... — PRs are a separate #-namespace)
- non-ticket numbers kept (#4122; the "#1 process failure" idiom; "task #3")
- only #N where N is an actual ticket id is rewritten; the 1-4 digit word-bounded
match also excludes 6-digit hex colours in the visual decision records
Git history is NOT rewritten (a commit's #N already equals T-N numerically), and
historical archives (docs/sprints, docs/discussions, docs/workshops) keep their
point-in-time #N. The /pr-process ticket-ID extraction logic moves to T-NNN in the
Phase 4 consumer cutover.
Verified: pql decisions validate ok; sync 357 records / 1057 refs / broken 0 (the
prose edits don't affect decision parsing or the tickets.decision_ref linkage).
Transform committed at tooling/pql-migrate/retag_ticket_refs.py.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pql was developed off the lessons of this repo's own planning structures, so the
"requirements" are feedback to a descendant, not gaps in a foreign tool — and some
items are deliberate simplifications to adopt rather than ask pql to re-add.
- Item #1 (seeded ids) downgraded Critical -> Resolved: Phase 2 proved direct-INSERT
seeding + pql's max-id counter (inherited from our own CLI) mints T-1022 after
T-1021, so there is no recycling/collision. The --id flag is a low-priority nicety.
- Item #9 (milestones): pql's omission of the milestone entity validates our
vestigial finding; labels-as-milestones is the right call and we adopt it.
- Intro reframed around the lineage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
One-way ticket data migration from the legacy settledreach.db into pql's
git-tracked changelog. Establishes the T-N == #N id bijection (old #440 -> T-440)
so thousands of #NNN git-commit references stay a trivial mapping.
Migrated (verified by full `pql plan rebuild` from changelog):
- 1013 tickets (status + type distributions match source exactly)
- 481 dependencies
- 16 history rows (deterministic content hash so ON CONFLICT(hash) dedups)
- 90 labels = 48 source + 42 milestone-derived
(active "Phase 4" milestone -> phase:4; "Process Rewire" ->
milestone:process-rewire; milestone_deps was empty/vestigial)
Transforms: ids T-prefixed, sprint_id dropped (legacy/archival), decision_ref
and the one 'server,client' comma-team (#575) kept verbatim, deleted_at NULL,
canonical_version 1. Seeded rows carry hash=NULL on tickets/deps/labels — proven
safe: PK-based ON CONFLICT, updated_at drives LWW, and replay is idempotent.
Key finding that dissolves pql-requirements item #1 ("Critical"): seeding via
direct-INSERT does NOT require explicit ticket ids from `ticket new`. The id
counter derives from max(id), so after seeding T-1..T-1021 the next native
`pql ticket new` mints T-1022 — no recycling, no collision. The blocker only
applied to the `ticket new --id` path we never use for bulk seeding.
Scaffolding: .pql/changelog/<table>/0000-schema.sql (canonical pql 1.6.2 schema,
byte-identical across the 4 table dirs) + .gitattributes union-merge driver so
changelog SQL never produces binary-style merge conflicts. Seed is reproducible
via tooling/pql-migrate/seed_tickets.py (read-only on the source, idempotent).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1 follow-up: update the active instruction layer (CLAUDE.md, project
structure rule, DECISIONS.md redirect, agent personalities, skill docs) to
reference governance/{decisions,questions,rejected}/<domain>.md instead of the
retired flat decisions/*.md layout.
Path references only — command-surface references (tooling/db/decision*,
decisions-sync, Makefile targets, clerk) are repointed to the pql CLI in the
Phase 4 consumer cutover. Historical archives (docs/sprints, docs/discussions,
docs/workshops) keep their point-in-time decisions/ paths; the separate
whatsinagame/ template distribution is untouched. Agent-memory is gitignored
and out of scope.
The agent/skill repath was applied by tooling/pql-migrate/repath_references.py
(ordered, meaning-preserving replacements; bare-dir rule uses a negative
lookbehind so it can't corrupt a freshly-created governance/decisions/ path),
committed for provenance. CLAUDE.md, project-structure.md, and DECISIONS.md
were hand-edited (structural tree/table changes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 1 of the pql migration. Moves the flat decisions/*.md layout into
governance/{decisions,questions,rejected}/<domain>.md — the tree pql's
`decisions sync` parses natively (record type from subdir, domain from
filename stem). Proven against pql 1.6.2: sync reports 357 records
(237 D / 108 Q / 12 R), 1057 refs, broken: 0; validate ok.
- 6 D-domain files -> governance/decisions/ (git renames)
- 5 questions-<domain>.md -> governance/questions/<domain>.md (prefix dropped)
- rejected.md split by domain -> governance/rejected/{architecture(R-001..010),
economics(R-011),perception(R-012)}.md
- decisions/README.md + questions.md index folded into governance/README.md;
pql's `decisions sync` now auto-maintains the record index appended below
the hand-written domain guidance (no more manual ID-list table upkeep).
- .pql/config.yaml: canonical vault config (tracked, not ignored).
Link rewrites are token-preserving: only the relative `foo.md` path portion
changes (e.g. `rejected.md#r-011` -> `../rejected/economics.md#r-011`); every
`[D-NNN]` bracket text and `#anchor` stays byte-identical, so pql's reference
extraction is unaffected. The one-shot transform is committed at
tooling/pql-migrate/restructure_decisions.py for provenance.
Codebase path references to decisions/ (CLAUDE.md, rules, skills, docs) are
updated in a follow-up commit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Phase 0 of the pql migration: the decision markdown had two genuine
canonical-ID integrity bugs that pql decisions sync silently LWW-collapses.
- D-035 was defined twice: a content.md tag-taxonomy record and a
perception.md shadowcasting/LOS record, both dated the same day. The
tag-taxonomy record keeps D-035; the shadowcasting record is renumbered
to D-238 (freshly claimed) with a Renumbered note preserving the history.
Inbound refs repointed in architecture.md (x4), questions-architecture.md,
and the README perception index row.
- R-011 (single currency for Phase 2) was defined three times: once
canonically in rejected.md and twice identically in economics.md. The two
economics.md copies are removed; rejected.md absorbs the Proposal/Raised-by
lines and gains a dedupe note. The economics.md dissent link now points at
rejected.md and the footer count drops the rejected-alternative clause.
Verified: tooling/db/decision check-dupes reports 0 duplicates;
pql decisions validate returns ok.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The blanket `.pql/` ignore would have hidden `.pql/changelog/` — pql's durable,
git-versioned planning state — making the whole migration's output invisible to
git. Narrow to ignore only the rebuildable DBs (index/pql .db + WAL/SHM) and
track config.yaml + changelog/.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deep analysis of migrating decisions + ticketing from the SQLite CLI to pql:
- pql-migration.md: phased branch-only plan (decisions→DQR tree, ticket changelog
seed with T-N≡#N, #N→T-N find-replace, big-bang consumer cutover, docs/workshops/
wiki fold-in, SQLite retirement) + verification gate + benefits.
- pql-requirements.md: 9 surfaced gaps for the pql team (critical: seeded ticket
ids + counter-advance; high: dup-id detection, core.hooksPath awareness, changelog
seed-format docs).
Key finding: milestones are vestigial (milestone_deps empty, 42/1013 tickets
linked) → mapped to a label, dropped as an entity.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>