Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
af68591
refactor(objects): galaxies, nebulae and clusters with a package are …
alowpoly Oct 1, 2026
3be22a6
refactor(registry): a package the world's host draws is an entry buil…
alowpoly Oct 1, 2026
260e947
refactor: select galaxies, clusters and nebulae as world bodies, not …
alowpoly Oct 1, 2026
a22678b
feat(universe): the Local Group has its own marker among the galaxy c…
alowpoly Oct 1, 2026
7510ee4
docs(local-group): the marker's capture
alowpoly Oct 1, 2026
68029c9
docs(local-group): the view before
alowpoly Oct 1, 2026
aaef7c8
fix(shell): one gap above and below every card divider
alowpoly Oct 1, 2026
9e644e9
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
40450d1
chore: re-pin the Sun's world context after merging main
alowpoly Oct 1, 2026
1fe312e
refactor(registry): one entry shape with capabilities instead of thre…
alowpoly Oct 1, 2026
b6f248a
refactor: a hosted package's card reads its own descriptor, never a c…
alowpoly Oct 1, 2026
423f5bb
refactor: galaxies, clusters and nebulae are ordinary scenes; delete …
alowpoly Oct 1, 2026
8febe28
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
04938e6
refactor(renderer): a bank is drawn as its scene's dataset companion,…
alowpoly Oct 1, 2026
821162e
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
1bf541c
refactor(objects): Virgo is an authored object with no surface that h…
alowpoly Oct 1, 2026
5be72db
refactor(objects): Fornax is an authored object with no surface that …
alowpoly Oct 1, 2026
2af9cb8
refactor(objects): NGC 300 is an authored object with no surface that…
alowpoly Oct 1, 2026
db5d3a4
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
ecb5564
fix(site): the Local Group frames its galaxies by their world frames,…
alowpoly Oct 1, 2026
5b2f802
refactor(objects): the six image-layer galaxies are authored objects …
alowpoly Oct 1, 2026
920b74b
refactor(objects): the ten volume objects host their banks; delete th…
alowpoly Oct 1, 2026
af419c5
fix(objects): each renamed bank's investigation ledger names the bank
alowpoly Oct 1, 2026
13625a4
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
530544c
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
a161756
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
1805607
fix(objects): a context bank names the object that shows it, so its c…
alowpoly Oct 1, 2026
a962c33
refactor(registry): the registry holds objects only; a level of the z…
alowpoly Oct 1, 2026
034b79c
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
c4369b4
fix(objects): only an extended object may declare no surface or input…
alowpoly Oct 1, 2026
f54f4e5
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
a1482a4
Merge remote-tracking branch 'origin/main' into refactor/one-object-path
alowpoly Oct 1, 2026
fc76bd7
fix(telescope): a galaxy's Cepheids read the disc from the galaxy's l…
alowpoly Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .github/scripts/architecture/nebula-packages.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ test('actual illegal imports, missing exports and line overflows fail the packag
assert.ok(checkNebulaBoundaries(root).some(error => error.includes('relative import leaves package')));
write(source, '\n'.repeat(601));
assert.ok(checkNebulaBoundaries(root).some(error => error.includes('exceeds 600')));
write(source, "const source = 'src/objects/m42/source/config.json';\n");
write(source, "const source = 'src/objects/m42-volume/source/config.json';\n");
assert.ok(checkNebulaBoundaries(root).some(error => error.includes('object/source path')));
write(source, 'const load = (name: string) => import(name);\n');
assert.ok(checkNebulaBoundaries(root).some(error => error.includes('unchecked boundary')));
Expand All @@ -64,7 +64,7 @@ test('the main volume entry keeps volume-core\'s platform ban and never reaches
assert.ok(check(node, `import '${bakeVolumeEntries.main}';`).some(error => error.includes('bake topic imports a bake entry')));
assert.ok(check(node, "import '@cssearth/nebula-lab/cli';").some(error => error.includes('forbidden import lab')));
assert.ok(check(node, "import 'undeclared-library';").some(error => error.includes('undeclared external dependency undeclared-library')));
assert.ok(check(node, "const source = 'src/objects/m42/source/config.json';").some(error => error.includes('object/source path')));
assert.ok(check(node, "const source = 'src/objects/m42-volume/source/config.json';").some(error => error.includes('object/source path')));
assert.ok(check(node, 'const load = (name: string) => import(name);').some(error => error.includes('unchecked boundary')));
assert.ok(check(main, '\n'.repeat(601)).some(error => error.includes('exceeds 600')));
write('packages/bake/package.json', JSON.stringify({ name: bakePackage, private: true, exports: { './volume': './dist/volume.js' } }));
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/ci/prepare-ci-inputs.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ async function fixture(t: { after: (cleanup: () => Promise<unknown>) => void })
await inventory('milky-way', 'prepared', ['volume.json', 'slices/z/one.webp']);
await inventory('helix', 'prepared', ['datasets.json', 'slice.webp', 'presentation.json']);
await inventory('helix', 'runtime', ['unrelated-preview.webp']);
await json('src/objects/helix/source/presentation.json', { schema: 'cssearth-volume-presentation-source@2', objectId: 'helix' });
await json('src/objects/helix-volume/source/presentation.json', { schema: 'cssearth-volume-presentation-source@2', objectId: 'helix' });
await inventory('local-group', 'runtime', ['catalogue.json'], 'prepared');
await json('src/objects/local-group/source/presentation.json', { provenance: { products: [] } });
const fetcher: typeof fetch = async url => {
Expand Down
40 changes: 20 additions & 20 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ output/playwright/
# Reacquirable binary source inputs. Source manifests, hashes, provenance,
# licenses, configuration, and authored source modules remain tracked.
src/objects/*/source/**/*.csv
# LGGS M31 star table (12.5 MB); restored from its CDS origin (src/objects/m31/source/lggs-stars/points.json).
src/objects/m31/source/lggs-stars/table4.dat.gz
# LGGS M31 star table (12.5 MB); restored from its CDS origin (src/objects/m31-layers/source/lggs-stars/points.json).
src/objects/m31-layers/source/lggs-stars/table4.dat.gz
# Earth's dated NASA MUR tile archives (45 MB a day); restored from the source mirror (src/objects/earth/source/manifest.json).
src/objects/earth/source/science/mur/*/tiles.tar.gz
src/objects/*/source/**/*.fits
Expand Down Expand Up @@ -69,10 +69,10 @@ src/objects/venus/source/akatsuki/*.nc
!src/objects/mercury/source/features/tectonic/global-tectonic-map.zip

# Offline-authored galaxy overview crops with no acquisition plan to restore them.
!src/objects/lmc/source/source.jpg
!src/objects/m31/source/source.jpg
!src/objects/m33/source/source.jpg
!src/objects/smc/source/source.jpg
!src/objects/lmc-volume/source/source.jpg
!src/objects/m31-layers/source/source.jpg
!src/objects/m33-layers/source/source.jpg
!src/objects/smc-volume/source/source.jpg
!src/objects/milky-way/source/sky/nasa-preview.jpg

# Retained upstream catalogue bytes with no acquisition plan to restore them.
Expand Down Expand Up @@ -207,12 +207,12 @@ src/objects/*/source/**/*.bpc
!src/objects/*/source/science/geology-*/Screenshot *.png

# SMC compact replay inputs: small PNGs prepare:nebulae needs to rebuild the dataset bank and the neutral emission volume.
!src/objects/smc/source/compact/lenses/*/*.png
!src/objects/smc/source/compact/neutral/slices/*/*.png
!src/objects/smc-volume/source/compact/lenses/*/*.png
!src/objects/smc-volume/source/compact/neutral/slices/*/*.png
# LMC compact replay inputs, the same shape plus the model projection its dataset tone curves read.
!src/objects/lmc/source/compact/lenses/*/*.png
!src/objects/lmc/source/compact/neutral/slices/*/*.png
!src/objects/lmc/source/compact/fit-projection.png
!src/objects/lmc-volume/source/compact/lenses/*/*.png
!src/objects/lmc-volume/source/compact/neutral/slices/*/*.png
!src/objects/lmc-volume/source/compact/fit-projection.png

# USGS Gazetteer nomenclature archives re-pinned this phase: named explicitly (not a glob) so tracking stays limited
# to the bodies actually verified here; each manifest documents these as a committed public-domain snapshot.
Expand Down Expand Up @@ -314,15 +314,15 @@ src/objects/*/source/**/*.bpc
/src/objects/eps-eridani-disc/.prepared-*/
/src/objects/hd-181327-disc/.prepared-*/
/src/objects/pds-70-disc/.prepared-*/
/src/objects/m42/.prepared-*/
/src/objects/helix/.prepared-*/
/src/objects/m2-9/.prepared-*/
/src/objects/m1/.prepared-*/
/src/objects/smc/.prepared-*/
/src/objects/lmc/.prepared-*/
/src/objects/m45/.prepared-*/
/src/objects/m8/.prepared-*/
/src/objects/omega-centauri/.prepared-*/
/src/objects/m42-volume/.prepared-*/
/src/objects/helix-volume/.prepared-*/
/src/objects/m2-9-volume/.prepared-*/
/src/objects/m1-volume/.prepared-*/
/src/objects/smc-volume/.prepared-*/
/src/objects/lmc-volume/.prepared-*/
/src/objects/m45-volume/.prepared-*/
/src/objects/m8-volume/.prepared-*/
/src/objects/omega-centauri-volume/.prepared-*/
# SPICE kernels are restored from their origins, never committed: bank kernels by packages/bake/cli/kernel-bank.mts,
# body kernels by their acquisition steps (packages/bake/cli/restore-source-inputs.mts), evidence kernels by the script
# that reads them.
Expand Down
12 changes: 6 additions & 6 deletions data/chandra/ledger.json
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@
"raDeg": 337.4107083333334,
"decDeg": -20.83717222222222
},
"source": "src/objects/helix/source/nebula.json",
"source": "src/objects/helix-volume/source/nebula.json",
"observations": 2,
"totalExposureKs": 47.7,
"longest": [
Expand Down Expand Up @@ -565,7 +565,7 @@
"raDeg": 83.6334511837,
"decDeg": 22.0151236394
},
"source": "src/objects/m1/source/nebula.json",
"source": "src/objects/m1-volume/source/nebula.json",
"observations": 102,
"totalExposureKs": 688.8,
"longest": [
Expand Down Expand Up @@ -601,7 +601,7 @@
"raDeg": 256.407962101,
"decDeg": -10.1425459988
},
"source": "src/objects/m2-9/source/nebula.json",
"source": "src/objects/m2-9-volume/source/nebula.json",
"observations": 1,
"totalExposureKs": 19.6,
"longest": [
Expand Down Expand Up @@ -693,7 +693,7 @@
"raDeg": 83.78715182853901,
"decDeg": -5.400382551151912
},
"source": "src/objects/m42/source/nebula.json",
"source": "src/objects/m42-volume/source/nebula.json",
"observations": 111,
"totalExposureKs": 3736.5,
"longest": [
Expand Down Expand Up @@ -729,7 +729,7 @@
"raDeg": 56.75,
"decDeg": 24.1167
},
"source": "src/objects/m45/source/nebula.json",
"source": "src/objects/m45-volume/source/nebula.json",
"observations": 6,
"totalExposureKs": 254.9,
"longest": [
Expand Down Expand Up @@ -765,7 +765,7 @@
"raDeg": 270.76531645904527,
"decDeg": -24.30622861770443
},
"source": "src/objects/m8/source/nebula.json",
"source": "src/objects/m8-volume/source/nebula.json",
"observations": 5,
"totalExposureKs": 318.2,
"longest": [
Expand Down
7 changes: 2 additions & 5 deletions docs/flight-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ runtime forwards them without remeasuring the camera DOM. Application navigation
owns history restoration; each detail only writes its current saved view.

`createCameraFlight` owns scheduling, acceleration, cancellation and completion
for world navigation, prepared-focus flights and native surface fly-to. Each
for world navigation and native surface fly-to. Each
path supplies its existing camera sampling math. World navigation retains one
document wheel listener for the navigation owner's lifetime and switches only
its active callback. Adding or removing a nonpassive document wheel listener at
Expand Down Expand Up @@ -235,10 +235,7 @@ A newly mounted world receives the latest settings. Playback permission remains
governed by the shared runtime policy.

`site/scene/scene-selection.mts` owns the committed subject and projects its URL.
Prepared-focus navigation owns the acquired target and executes camera/dataset
commands. It publishes one result to the selection owner, including whether a
saved camera must be discarded. It neither mirrors the selected ID nor formats
another selection URL. Native camera focus remains the geometric pivot.
Every subject is an object's scene; the geometric pivot is that object's centre.

## Scene activation and prepared ownership

Expand Down
8 changes: 4 additions & 4 deletions docs/galaxies/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The [source recipe](../../labs/nebula/models/image-candidates.json) retains the
| Point stars | [Bonanos et al. (2009)](https://arxiv.org/abs/0905.1328), [CDS J/AJ/138/1003](https://cdsarc.cds.unistra.fr/viz-bin/cat/J/AJ/138/1003) | 943 stars with measured sky positions and photometry. Depths are assigned from the density. All three datasets use identical positions. |
| Surface color | The three registered observations above | Native star removal, then color sampling onto the fixed density. Uncovered density keeps neutral color. |

The [accepted bake recipe](../../labs/nebula/models/lmc/bake.json) pins image placement and color settings; the [app settings](../../src/objects/lmc/README.md#evidence) retain cloud and star display. Switching datasets changes the material while retaining the cloud, stars and camera.
The [accepted bake recipe](../../labs/nebula/models/lmc/bake.json) pins image placement and color settings; the [app settings](../../src/objects/lmc-volume/README.md#evidence) retain cloud and star display. Switching datasets changes the material while retaining the cloud, stars and camera.

## Extragalactic datasets

Expand All @@ -44,9 +44,9 @@ The [accepted bake recipe](../../labs/nebula/models/lmc/bake.json) pins image pl
| --- | --- | --- |
| Milky Way exterior | [OpenSpace/AMNH/NAOJ volume](https://docs.openspaceproject.com/latest/content/milky-way/galaxy/milky-way-volume/index.html) | 1,024 × 1,024 × 128 RGBA model, baked into its bulge and inner disc only. Simulation-based visualization. [Provenance](../../src/objects/milky-way/source/provenance.json). |
| Milky Way interior | [NASA SVS, Deep Star Maps 2020](https://svs.gsfc.nasa.gov/4851/) | 8,192 × 4,096 Milky Way-only map derived from star catalogues; the panorama shell adds authored visual depth. Credits: NASA/Goddard SVS, Ernie Wright (USRA), ESA/Gaia/DPAC. [Provenance](../../src/objects/milky-way/source/sky/provenance.json). |
| M31 | [ESA/Hubble & Digitized Sky Survey 2, heic1112f](https://esahubble.org/images/heic1112f/) | 4,783 × 5,000 crop/resample; 1 kpc parametric depth. Acknowledgment: Davide De Martin (ESA/Hubble). [Provenance](../../src/objects/m31/source/provenance.json). |
| M33 | [ESO VST/OmegaCAM, eso1424a](https://www.eso.org/public/images/eso1424a/) | 4,000 × 3,355, g/r/Hα; 1.2 kpc parametric envelope. Excludes the larger H I outskirts. [Provenance](../../src/objects/m33/source/provenance.json). |
| SMC | [SMASH/NOIRLab, noirlab2030b](https://noirlab.edu/public/images/noirlab2030b/) | 3,000 × 2,501, g/r/i/z; authored 25 kpc envelope. Excludes the full Bridge, Wing and tidal debris. [Full credit and provenance](../../src/objects/smc/source/provenance.json). |
| M31 | [ESA/Hubble & Digitized Sky Survey 2, heic1112f](https://esahubble.org/images/heic1112f/) | 4,783 × 5,000 crop/resample; 1 kpc parametric depth. Acknowledgment: Davide De Martin (ESA/Hubble). [Provenance](../../src/objects/m31-layers/source/provenance.json). |
| M33 | [ESO VST/OmegaCAM, eso1424a](https://www.eso.org/public/images/eso1424a/) | 4,000 × 3,355, g/r/Hα; 1.2 kpc parametric envelope. Excludes the larger H I outskirts. [Provenance](../../src/objects/m33-layers/source/provenance.json). |
| SMC | [SMASH/NOIRLab, noirlab2030b](https://noirlab.edu/public/images/noirlab2030b/) | 3,000 × 2,501, g/r/i/z; authored 25 kpc envelope. Excludes the full Bridge, Wing and tidal debris. [Full credit and provenance](../../src/objects/smc-volume/source/provenance.json). |

The Milky Way overview enables the galaxy's prepared depth layers; other destinations keep its distant views. M31, M33 and the SMC use image-derived parametric layers, not the LMC's star-removal and density-coloring pipeline.

Expand Down
47 changes: 25 additions & 22 deletions docs/navigation-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,37 @@ nebula catalogues. Search, aliases and classification tabs use this inventory.

| Concept | Meaning and owner |
| --- | --- |
| Scene destination | A body package with a route, prepared world frame and scene loader. |
| Prepared-focus destination | A catalogue subject the map can open: a galaxy cluster, or a subject an object package details. Its page, `/<id>/`, is its host scene’s page with the subject selected; `?dataset=` selects its dataset, as on every page. Other catalogue rows are labels with no page. |
| Overview | The Milky Way, the Local Group, the Nearby and the Observable Universe: registry entries of kind `overview`, authored under `properties.overview` in their packages: name, description, order, the zoom thresholds and framing of their level, the classifications they hold and the packages they draw. The zoom ladder, the cards, the breadcrumbs and the sidebar tree's sections are built from these entries. Its page, `/<id>/`, is the world host's scene page with the overview selected. |
| Object | A package with a catalogue entry: a route, a prepared world frame and a scene loader. A planet, a star, a galaxy, a nebula and a cluster of galaxies are all this. `?dataset=` selects one of its datasets. |
| Level | The Milky Way, the Local Group, the Nearby and the Observable Universe: views of a scene on the zoom ladder, not objects, authored under `properties.overview` in their packages (name, description, order, zoom thresholds, what they hold). A level's page, `/<id>/`, is the world host's scene at that zoom. |
| Rendering resource | A volume, image bank, point field or other prepared content. A resource descriptor alone does not publish a destination. |
| Dataset view | A selectable `(objectId, datasetId)` presentation, which may combine several products and published sources. |
| Published source | A scientific work, release or product identified in the source catalogue; a local file hash identifies retained bytes separately. |

Every page is `/<id>/`, one URL system for all three kinds of page:
Every page is `/<id>/`, one URL system for every object:
[`navigation-scope.mts`](../site/navigation/navigation-scope.mts) reads and
writes them. A scene's page mounts that scene. A catalogue subject or an overview
is drawn by a mounted scene: opened cold, its page mounts the world host, the Sun,
which every catalogue subject and overview is placed from. In place, a catalogue
subject keeps the mounted scene; an overview is always the host's, as zooming out
of any system reaches it. Their pages carry none of the scene's own selections
(`dataset`, `feature`), so a cold open never reads them as the host's.

`SCENE_OBJECTS` filters `OBJECTS` by scene capability. Routes, body preparation
and scene conformance use this filter because a prepared focus does not own
another scene. `requireObject` resolves either destination kind;
`requireSceneObject` rejects a focus when a caller needs a scene loader.

One object has one id. A catalogue row that an object package details takes the
package's id when the catalogue is prepared: Andromeda is `m31` in the catalogue,
the registry, its page and its links, and the LVDB key `m_031` stays in its source
references. Non-navigable context resources remain outside `OBJECTS`.
writes them. Every object has a scene of its own, and its page mounts it. A level
of the zoom ladder (the Milky Way, the Local Group, the nearby and the observable
universe) is not an object: it is a view of a scene, reached by zooming out of any
system. Its page, opened cold, mounts the world host, the Sun, at that zoom. A
level's page carries none of the scene's own selections (`dataset`, `feature`), so
a cold open never reads them as the host's.

`OBJECTS` has one entry shape and no kinds. Each entry is built from its package's
own descriptor: a catalogue block, a world frame and a scene. A galaxy, a nebula
and a cluster of galaxies are objects like any body; their recipe declares no
surface, and their imagery is a context bank a dataset names. `SCENE_OBJECTS` is
the same list. The levels are a separate short list (`OVERVIEWS`), each authored
under its package's `properties.overview`. The Local Group is a level with a
place of its own, so the world context also draws and names it.

One object has one id. The spatial catalogues (Local Group galaxies, galaxy
clusters, the nearby field) are data the world draws as dots: a row makes no page
and no registry entry, and nothing in the application reads a row for an object's
identity, position or facts. Non-navigable context resources remain outside
`OBJECTS`.
Adding a classification does not add a renderer, shell or camera owner.

`sceneHostId` identifies the scene displaying a prepared focus. A galaxy's
A catalogue galaxy's
`hostId` identifies its physical host. Referenced hosts excluded from positional
selection remain in the catalogue's `unpositionedHosts`, with a source reference
and exclusion reason. They acquire no position or destination. The reader rejects
Expand Down Expand Up @@ -157,6 +160,6 @@ owners. Its test preload rejects accidental use of application boot; it does
not prove the Vite-generated context inventory or browser startup.

Scene conformance remains derived from the scene capability filter. Run
`pnpm test:site` (the browser suites were retired; scene retention is checked in `site/test/scene-session.test.mts`) to check prepared-focus search, selection, saved links and retained
`pnpm test:site` (the browser suites were retired; scene retention is checked in `site/test/scene-session.test.mts`) to check search, selection, saved links and retained
camera ownership. These checks do not establish the scientific accuracy of a
catalogue measurement or a reconstructed volume.
Loading
Loading