Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .claude/skills/add-data-source/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,21 +85,21 @@ errors guide you to the totality sites.
| 4 | Pick decode | `src/data/selectionEncoding.ts` (`PickResult` kind + `unpackPick`) | ⚠️ **silent** inverse map |
| 4b | WESL pick parity | `src/services/gpu/shaders/lib/selectionEncoding.wesl` (`SOURCE_CODE_X`) | ⚠️ parity test only |
| 5 | Click guard | `src/services/engine/interaction/clickHandler.ts` (`\|\| kind === 'X'`) | ⚠️ **silent** |
| 6 | Seed parser | `tools/parsers/parseClusterSeed.ts` (`VALID_CATEGORIES`) | ⚠️ **silent** |
| 6 | Seed parser | `tools/parsers/parseStructureSeed.ts` (`VALID_CATEGORIES`) | ⚠️ **silent** |
| 7 | Marker style row | `src/services/engine/presentation/structurePoiStyles.ts` | ✅ totality Record |
| 8 | Build records | `src/data/buildStaticAnchorStructures.ts` (`SeedEntry.category` + switch) | ✅ switch exhaustiveness |
| 9 | Marker renderer | `src/services/gpu/renderers/clusterMarkerRenderer.ts` (**~11 sites**, below) | mixed |
| 9 | Marker renderer | `src/services/gpu/renderers/structureMarkerRenderer.ts` (**~11 sites**, below) | mixed |
| 10 | UI naming | `src/data/poiCategoryInfo.ts` (`label` / `shortLabel` / `plural`) | ✅ totality Record |
| 11 | Settings lists | `src/components/SettingsPanel/SettingsPanel.tsx` (`STRUCTURE_CATEGORIES`, `LABEL_CATEGORIES`) | ⚠️ **silent** arrays |
| 12 | Bulk-fetch gate | `src/services/engine/wiring/assetWiring.ts` (`BULK_CATALOG_CATEGORIES`) | ⚠️ include **only if** it has a `.ccat` |
| 13 | Focus predicate | `src/services/engine/subsystems/clusterFocusSubsystem.ts` (`\|\| category === 'X'`) | ⚠️ **silent** |
| 13 | Focus predicate | `src/services/engine/subsystems/structureFocusSubsystem.ts` (`\|\| category === 'X'`) | ⚠️ **silent** |
| 14 | Settings count | `src/services/engine/wiring/wireStructureProjection.ts` (`emitCounts`) | ⚠️ **silent** — no count shown if missed |
| 15 | Visibility defaults | `useEngineSettings.ts` ×2, `engine.ts` ×2, **+ test fixtures** | ⚠️ **copy-paste ×8** |
| 16 | Debug panel | `src/components/DebugPanel/LabelEffectsSection.tsx` (`CATEGORIES`) | ⚠️ **silent** |
| 17 | Seed data | `data/cluster_anchors.seed.json` (**gitignored — `git add -f`**) | — |
| 17 | Seed data | `data/structure_anchors.seed.json` (**gitignored — `git add -f`**) | — |
| 18 | Runtime enumeration tests | `tests/data/poiCategories.test.ts` (key counts, "N-category" titles) | ⚠️ **silent** — assert the new total |

`clusterMarkerRenderer.ts` is the densest — the ~11 sites: `SOURCE_CODE_BY_CATEGORY`,
`structureMarkerRenderer.ts` is the densest — the ~11 sites: `SOURCE_CODE_BY_CATEGORY`,
`POI_CATEGORIES_WITH_MARKERS`, the per-category `Record` literals
(`bucketOffsets` / `bucketCounts` / `sourceBuffers` / `sourceBindGroups` /
`writeCursor`), the `setMarkers` reset / count-guard / write-guard, and the
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pnpm-debug.log*

# Exception: hand-curated catalog seed files (small, hand-authored, tracked).
!/data/famous_galaxies.seed.json
!/data/cluster_anchors.seed.json
!/data/structure_anchors.seed.json

# Exception: hand-curated override index produced by the famous-galaxy
# curator (tools/famous-curator). Small JSON (~75 entries × ~150 B) that
Expand Down Expand Up @@ -118,7 +118,7 @@ pnpm-debug.log*

# Exception: MCXC + MSCC cluster/supercluster raw-data READMEs + sha256
# sidecars. The .dat tables and VizieR ReadMes stay gitignored (fetched
# on demand via `npm run fetch-clusters`), but the READMEs document
# on demand via `npm run fetch-structures`), but the READMEs document
# provenance and the .sha256 files let the parser detect truncated
# downloads — both must be in git.
!/data/raw/mcxc/README.md
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions docs/BACKLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Diagnosed but unplanned. Captured here so they don't get lost; promote to a spec

- **Mobile layout reflow** — hover-on-touch is handled (`disable hover on touch input`, #226: hover-only affordances now route through tap). What remains is the general responsive layout pass: reflow the InfoCard / SettingsPanel / StatusBar for narrow viewports so the UI is usable on a phone, not just non-broken.
- **Lower-tier "close to home" weighting** — retune the small/medium tier subsampling so more galaxies survive near the camera's home position for maximum visual density on first load, while keeping the on-screen count fast. Distinct from the deliberate SDSS far-shell sample (memory `project_sdss_medium_intentionally_far`).
- **Densely seed the Local Volume across all tiers (group explorability)** — surfaced 2026-06-04 with the `group` category. The 16 Local Volume groups are only interesting to fly into if their *member* galaxies are present, but `subsampleByAbsMag` (`tools/catalog/`) thins the nearby volume by absolute-magnitude cut, so faint dwarfs in the Local Group / M81 / Cen A / Sculptor etc. get culled — a group ring you focus into can be nearly empty at small/medium tier. Bias the subsampling to **keep galaxies inside (or near) the featured group spheres** regardless of `M_abs`, across small + medium and ideally large tiers, so each group has as many members as possible. Related to but distinct from the "close to home" weighting above: that's camera-home density; this is per-group membership density keyed off the structure seed. Implementation hooks: the group seed positions/radii (`data/cluster_anchors.seed.json`) are available to the build, so the subsampler can spare points within `apparentRadiusMpc` of each group centre. Keep an eye on the on-screen count budget. Pairs with the cluster-focus member count (`PoiDetailCard` "Galaxies" row) — denser seeding makes that number meaningful at lower tiers.
- **Densely seed the Local Volume across all tiers (group explorability)** — surfaced 2026-06-04 with the `group` category. The 16 Local Volume groups are only interesting to fly into if their *member* galaxies are present, but `subsampleByAbsMag` (`tools/catalog/`) thins the nearby volume by absolute-magnitude cut, so faint dwarfs in the Local Group / M81 / Cen A / Sculptor etc. get culled — a group ring you focus into can be nearly empty at small/medium tier. Bias the subsampling to **keep galaxies inside (or near) the featured group spheres** regardless of `M_abs`, across small + medium and ideally large tiers, so each group has as many members as possible. Related to but distinct from the "close to home" weighting above: that's camera-home density; this is per-group membership density keyed off the structure seed. Implementation hooks: the group seed positions/radii (`data/structure_anchors.seed.json`) are available to the build, so the subsampler can spare points within `apparentRadiusMpc` of each group centre. Keep an eye on the on-screen count budget. Pairs with the cluster-focus member count (`PoiDetailCard` "Galaxies" row) — denser seeding makes that number meaningful at lower tiers.
- **Milliquas colour check** — Milliquas points currently all render blue; verify the colour-index / colour mapping for the quasar source isn't collapsing to a single hue.
- **Tour feature (full)** — finish the camera tour beyond the Part-2 seed. Tracked design: [splash-screen Part 2 plan](superpowers/plans/2026-05-20-splash-screen-02-stub-tour.md) (ready to execute; engine-side `engine.tour` seed, verified current 2026-06-04) and [2026-05-07 tour-animation spec](superpowers/specs/2026-05-07-tour-animation-design.md) (re-grounded 2026-06-04; labels + MW impostor + engine-API decisions resolved, cinematic palette documented). Execute Part 2 first, then resolve the spec's remaining open decisions (rotation slerp, caption producer, beat list/timing), promote to a plan, and extend the seed into the real waypoint tour.
- **Thumbnail quality (SDSS / DSS branches)** — the auto-fetched SDSS-cutout and CDS-DSS thumbnails still have the original quality issues: ranked fix options are mask, sky-sub, per-galaxy size, DESI source, brightness norm (see memory `project_thumbnail_quality`). The *famous-galaxy* branch is now fully addressed — procedural-disk fade-out, high-res LOD (#214), and thumbnail calibration + square deproject + disk-plane unification (#229/#234/#235/#240) all shipped — so this item is scoped to the non-curated SDSS/DSS path only.
Expand All @@ -80,9 +80,9 @@ Diagnosed but unplanned. Captured here so they don't get lost; promote to a spec
- **Promote the Milky Way to a first-class `Source` (streamline its identity)** — surfaced 2026-06-04 alongside the category-DRY item. The Milky Way is **first-class on the rendering axis** (`milkyWayRenderer` procedural impostor, `milkyWayPass`, `EngineMilkyWayHandle`) but a **pseudo-everything on the identity axis**, modelled ~5 different ways: a `FamousMetaEntry` palette pseudo-entry with sentinel id `__milky-way__` intercepted in `App.tsx` onSelect (`data/milkyWayEntry.ts`); "expressed via the famousGalaxy category" for the settings toggle (`SettingsPanel.tsx:812`); a bespoke `'youAreHere'` member bolted onto `PoiCategory` via `LabelStyleOverrideTarget = 'youAreHere' | PoiCategory` (`labelStyleOverride.ts:40`); and a bespoke visibility/fade path (`youAreHereSubsystem`, `youAreHereVisibility`) that bypasses the `labelCategoryVisibility` Record every other category uses. `data/milkyWayEntry.ts` even documents the deferral: *"we don't promote the Milky Way to a real `Source` (that's a larger architectural decision the user deferred)."*

**Goal:** make the MW a real `Source` (next free code = **16**, pick-only / not persisted to `.bin`, non-breaking — same as the POI codes) so its visibility, label identity, selection, and focus flow through the *same* plumbing as every other source, retiring the sentinel hack, the famousGalaxy masquerade, the `'youAreHere'` union extension, and the bespoke youAreHere subsystem. **Boundary (important):** "similar to other sources" means the *identity / visibility / selection / focus* plumbing — the MW's bespoke **renderer** (the procedural impostor disk) stays its own subsystem; it just hangs off a registry entry. **Open design decisions for the brainstorm:** (a) does MW reuse an existing `SourceEntry` `type` or get a new one (e.g. `'impostor'`)?; (b) the **pick surface** — today you can't click the MW; making it selectable needs a pick target (the impostor billboard? a galactic-centre marker?); (c) mapping `focusOnHome` onto the standard selection→focus path (a MW-specific framing distance); (d) keep or retire the palette pseudo-entry. **Depends on / co-designs with** the structure-category-identity consolidation above — both hinge on making the *marker-bearing vs label-only* distinction explicit (the MW is label-only + bespoke-render; famousGalaxy is label-only + point-picked). Needs a brainstorm → spec → plan; do **not** drop-in.
- **`cluster*` → `structure*` naming migration** — surfaced 2026-06-04 while adding `group`. The featured-structure seam is named after one of the four categories it now holds (cluster / supercluster / void / group): the seed file `data/cluster_anchors.seed.json`, the `rawDataRegistry` key `clusters.seed`, `parseClusterSeed` / `ClusterSeedEntry` / `validateClusterSeedEntry`, plus `clusterMarkerRenderer`, `clusterFocusSubsystem`, `clusterCatalogSlot`, `clusters.ccat` / `clusters_meta.json`. The rest of the codebase moved to `Structure*` vocabulary in #253/#254 (`StructureCategory`, `StructureRecord`, `structures` store, `structurePoiStyles`, `produceStructure*`), so these are the holdouts. Rename to `structure_anchors.seed.json` / `parseStructureSeed` / `StructureSeedEntry` / `structureMarkerRenderer` etc. Pure clarity (no behaviour change), but touches a tracked data file (`git mv` + `.gitignore` exception update), the registry key, the parser, and consumers (`buildClusters.ts`, audit scripts) — own focused diff, pairs with the identity consolidation above. Mechanical; typecheck + tests are the safety net.
- ~~**`cluster*` → `structure*` naming migration**~~ — **DONE (PR #280).** The featured-structure seam was named after one of the four categories it holds (cluster / supercluster / void / group); the rest of the codebase had already moved to `Structure*` vocabulary in #253/#254. The whole holdout set is now renamed: the catalog family (`StructureCatalog*`, `structureCatalogFormat`, `structureCatalogSlot`, `structureCatalogFetcher`, `structureCatalogToStructures`), the focus subsystem (`structureFocusSubsystem`), the seed parser (`parseStructureSeed` / `StructureSeedEntry`) + seed file (`data/structure_anchors.seed.json`) + registry key (`structures.seed`), the membership util (`structureMembership`), the build tool (`tools/structures/buildStructures.ts`) and fetcher (`fetchStructureCatalogs`), and the served artifacts (`structures.ccat` / `structures_meta.json`) + their npm scripts (`build-structures` / `fetch-structures`). The cluster CATEGORY (`Source.Cluster`, the `'cluster'` id, X-ray clusters/MCXC, member clusters/MSCC) and the `.ccat` extension / `CCAT` magic stay verbatim. **Deploy:** the artifact rename means a `npm run build-structures` + `npm run sync-r2-secure` re-publish from the main worktree is required so R2 serves `structures.ccat` / `structures_meta.json` under the new names.
- **Cosmic zoom plan** — 60-doc "Powers of Ten" walkthrough plan drafted in worktree `cosmic-zoom-plan` (2026-05-08), awaiting user review. See memory `project_cosmic_zoom_plan`.
- **Structure search (cluster / supercluster / void)** — the command palette (`CommandPalette.tsx`) only indexes the famous-galaxy atlas (~75) and the PGC alias index (~48k GLADE+2MRS rows). Structure POIs — clusters, superclusters, and voids (MCXC + MSCC, names + Abell numbers + descriptions already in `public/data/clusters_meta.json`) — aren't searchable, so there's no way to look up "Coma", "A2703", "MSCC 216", a named void, etc. and fly to them. Add a third search index over the structure catalog (all three categories) + a select handler that selects the structure POI and frames the camera. Naturally pairs with naming large-scale structures (e.g. a "Sloan Great Wall" / "CfA Great Wall" entry) so they become navigable by name.
- **Structure search (cluster / supercluster / void)** — the command palette (`CommandPalette.tsx`) only indexes the famous-galaxy atlas (~75) and the PGC alias index (~48k GLADE+2MRS rows). Structure POIs — clusters, superclusters, and voids (MCXC + MSCC, names + Abell numbers + descriptions already in `public/data/structures_meta.json`) — aren't searchable, so there's no way to look up "Coma", "A2703", "MSCC 216", a named void, etc. and fly to them. Add a third search index over the structure catalog (all three categories) + a select handler that selects the structure POI and frames the camera. Naturally pairs with naming large-scale structures (e.g. a "Sloan Great Wall" / "CfA Great Wall" entry) so they become navigable by name.
- **No general `add-data-source` skill (+ its checklist)** — surfaced 2026-06-04 while adding `group`. Skills exist for the *narrow* cases (`add-famous` for the famous-galaxy pipeline, `link-data` for symlinking real catalogs into a worktree) but there's no skill that walks the full "add a new data source / featured category" path, so steps get missed piecemeal. Concrete checklist items discovered the hard way, each of which should live in such a skill:
- **Settings-panel per-category count.** A new structure category must be added to the `onStructureCountsChange` emission (`wireStructureProjection.ts` `emitCounts`) — the SettingsPanel only renders a count when `structureCounts?.[cat] !== undefined`, so a missing category shows a toggle with no number (the `group` bug, fixed 2026-06-04 + guarded by a test). Any per-source/per-category count surfaced in the UI has this shape.
- **Seed the real data early** (memory `feedback_seed_data_early`): wire real data right after the parser, not as a late task, so the rest of the work has something to look at.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ plugin), Vitest (`node` env). No build-time additions.
`EngineSettingsState` and `requestRender()`. The projection picks
them up next frame.
- `src/services/gpu/renderers/filamentRenderer.ts`,
`pointRenderer.ts`, `clusterMarkerRenderer.ts` — drop their own
`pointRenderer.ts`, `structureMarkerRenderer.ts` — drop their own
`fadeBuffer` / `fadeBindGroup` per-instance fields; ask the registry
for the bind group at bind time.
- `src/services/gpu/renderers/labelRenderer*.ts` — same (only if their
Expand Down Expand Up @@ -457,12 +457,12 @@ Per ADR 0001 §Decision items 3.

**Files:**
- Modify: `filamentRenderer.ts`, `pointRenderer.ts`,
`clusterMarkerRenderer.ts`, and the label renderers if applicable.
`structureMarkerRenderer.ts`, and the label renderers if applicable.

Mechanical repeat of T9. Per ADR 0001 §Implementation Notes item 1,
order is lowest-risk first:

- [ ] **Step 1: `clusterMarkerRenderer`** (smallest surface, fewest
- [ ] **Step 1: `structureMarkerRenderer`** (smallest surface, fewest
tests touched). Follow T9's Step 1–4 shape: failing buffer-spy test
→ migrate → strip from type → green.
- [ ] **Step 2: `filamentRenderer`.** Same shape.
Expand Down
2 changes: 1 addition & 1 deletion docs/superpowers/plans/2026-06-06-focus-recession-fade.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Large diffuse fields (filaments/volumes) recede harder; markers/labels dim moder

`blend` is `FocusUniformsValue.blend`, produced once per frame by
`state.subsystems.clusterFocus.produceFocusUniforms(nowMs)`
(`clusterFocusSubsystem.ts:104`). That call **ticks the fade controller**, so it must
(`structureFocusSubsystem.ts:104`). That call **ticks the fade controller**, so it must
run **exactly once per frame** — calling it twice double-advances the ramp.

Today it's computed late, at `runFrame.ts:262–296`, after the label director
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ two parts and combine them with their focused-instance exemption.

The obvious-looking move — have the registry store the blend (`setFocusBlend`) and
return `toggle × recession` from `opacityOf` — **complects two independent concerns
and mirrors state**. The blend's authoritative home is `clusterFocusSubsystem`
and mirrors state**. The blend's authoritative home is `structureFocusSubsystem`
(`FocusUniformsValue.blend`); caching it in the registry is a value×place mirror
(stale-mirror bug class), and it drags the focus concept into a module whose sole
job is fade controllers. Toggle fade and focus recession vary independently, so
they are *composed*, not braided. (Radar finding, 2026-06-06 — see
`docs/superpowers/conventions/simplicity.md` #5, #8.)

`blend` is the **same 0→1 value `clusterFocusSubsystem` already produces** —
`FocusUniformsValue.blend` (`clusterFocusSubsystem.ts:106`), already computed once
`blend` is the **same 0→1 value `structureFocusSubsystem` already produces** —
`FocusUniformsValue.blend` (`structureFocusSubsystem.ts:106`), already computed once
per frame at `runFrame.ts:296` and threaded into the render settings. Consumers
read it from there as a **value** (an argument), never from a mirror. It already
gates render-on-demand via `clusterFocus.isAwake()`, so no wake logic changes.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"build-cf4-density": "tsx tools/volumes/buildCf4Density.ts",
"build-flow-field": "tsx tools/flow/buildFlowField.ts",
"verify-flow-field": "tsx tools/flow/verifyFlowField.ts",
"build-clusters": "tsx tools/clusters/buildClusters.ts",
"build-structures": "tsx tools/structures/buildStructures.ts",
"build-mcpm": "tsx tools/volumes/buildMcpmVolume.ts --all",
"build-famous": "tsx tools/famous/buildFamous.ts",
"build-famous-hires": "tsx tools/famous/copyHiResToPublic.ts",
Expand All @@ -54,7 +54,7 @@
"dev": "vite",
"fetch-2mass-xsc": "tsx tools/fetch/fetch2massXsc.ts",
"fetch-cf4": "tsx tools/fetch/fetchCosmicflows4.ts",
"fetch-clusters": "tsx tools/fetch/fetchClusterCatalogs.ts",
"fetch-structures": "tsx tools/fetch/fetchStructureCatalogs.ts",
"fetch-famous-images": "tsx tools/famous/fetchFamousImages.ts",
"fetch-hyperleda": "tsx tools/fetch/fetchHyperLeda.ts",
"fetch-milliquas": "tsx tools/fetch/fetchMilliquas.ts",
Expand Down
Loading
Loading