b7f277ea04714a46cf6b40ad7a59818b12676cfc
17
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7d07921d69 |
Say what the project is, in the two places people arrive
The README opened without mentioning that the thing is deployed, and the HTML document carried a title and nothing else — no description, no link preview. Both matter more now that there is a public URL to land on. README: the live link up top; the object card and the measured/derived split from #3, which were built but never written down; `shared/format/`, `public/` and `.github/workflows/` in the layout. index.html: a description, a theme colour matching --color-void so the browser chrome does not flash white around a black sky, and Open Graph/Twitter tags so a shared link renders as something other than a bare URL. Those URLs are absolute and name the deployment outright — a scraper has no document to resolve a relative path against, so they cannot follow <base> the way the rest of the app's paths do. A custom domain later means editing these three lines. The preview image is the galactic view, copied into `public/` so it is served by the site itself rather than linked out to raw.githubusercontent. Verified: the built document keeps every tag, the base href still rewrites to /star-map/, the image answers 200 at the path the og:image names, and both the root and a deep link still render. 527 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
433bcca8a2 |
Stop publishing the repo as a plugin marketplace, and refresh the run skill
Three small things. Removed `.claude-plugin/marketplace.json`. It is the file `/plugin marketplace add` reads, so without it this repo no longer offers itself as a marketplace — which is the odd part of an Angular app carrying one. The caveman plugin's own files stay, so it can be listed from a marketplace of its own later; only the listing is gone. That left four documents asserting an install path that no longer exists, including a README section handing out `/plugin marketplace add` and `/plugin install` commands that would now fail. All four now say what is actually true. `.junie/plans/nasa-star-map.md` still describes the repo as containing only a marketplace, and is left alone: it records what was here before the app was written, and is not a claim about the present. The run skill's numbers had drifted a release behind — 496 tests in 28 files against a real 527 in 31, and a build timed at 9s that now takes 12. Measured rather than guessed. The pinned Playwright version it names was correct. It also gains the Pages build, which is not a plain `npm run build`: the base href and the 404.html copy are both required for a project site, and the artifact root is `dist/star-map/browser` rather than its parent. Plus the matching gotcha, since a Pages build served at `/` looks broken in a way that tells you nothing about whether it would work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
8191254b3c |
Put the four views in the README, and correct what one of them showed
The README described the app without showing it. Adds a screenshot to each of the four sections it describes, captured from a real run at the current state of the code rather than assembled or touched up. Capturing them caught a claim that had gone stale. The galactic view's readout still said everything inside 50 pc was real, which was true when that string was written and has been wrong since the catalogue reached 250 pc. It now quotes the catalogue's own size and reach, so it cannot drift again — and, usefully, that makes a stale screenshot self-evident: the numbers are in the picture. JPEG rather than PNG, at 1.1 MB for all four instead of about five. These are dark scenes with fine gradients, where JPEG can band, so they were checked at quality 88 rather than assumed to be fine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
efa9e4084a |
Draw the whole catalogue, and build the aggregation the rest would need
Two things, one verified and one that cannot be. The render budget is now the whole catalogue: 68388 stars, one instanced draw call, which is what a GPU should be asked to do. The budget itself stays, because the catalogue is meant to grow past what any machine should draw at once — Gaia alone could contribute a million — and at that point the selection is what keeps the field legible rather than a grey wash. A `?stars=` override handles the machines that cannot, including the software rasterizer the end-to-end suite runs against, whose frame rate is two orders of magnitude below a real GPU's and which was measuring the rasterizer rather than the app. The aggregation is the second thing, and none of it has run. Every ESA, NOIRLab, SDSS and Euclid endpoint is unreachable from here — only GitHub raw is, which is why HYG and OpenNGC are the current sources. So this is infrastructure and a Gaia query written against the published DR3 schema, not data. What the framework encodes is that these surveys are not interchangeable. The distinction is not size but whether a catalogue knows how far away its objects are, because a 3D map cannot place a star it only has a direction for. Gaia is the only one of the five that can add stars here, because it is the only one that measures parallaxes. DECaPS2 has fifty times Gaia's object count and photometry alone — not one of its 3.32 billion objects can be placed in depth. Euclid's bulge is 8 kpc away, where a parallax is microarcseconds; its contribution would be imagery. SDSS-V and SAGA are keyed to stars something else already places, so they enrich rather than extend. Those roles are recorded as data the ETL prints, not as prose that can drift. Overlapping catalogues are reconciled on direction rather than on 3D proximity, which is the one non-obvious part. Two surveys agree on a star's direction to within an arcsecond and disagree on its distance by tens of per cent, so a star at 200 pc is 50 pc from itself between catalogues while being unmistakably the same object. Matching in 3D would need a tolerance so loose it swallowed real neighbours. The better parallax wins where both reach; where only one does, the star stays. Names become dense-with-holes with a source dictionary, because a survey catalogue has no proper names — writing "Gaia DR3 4472832130942575872" once per star would cost 25 MB per million to repeat what two adjacent fields already say. An empty entry costs three bytes and is regenerated on load. The Sun needed its own case in the merge: it sits at the origin, has no direction to compare, and appears in every catalogue. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
29fd92d118 |
Widen the star catalogue, and separate what is drawn from what is known
The map held 8750 stars within 50 pc and rendered 371 systems. Both were lower than they needed to be, for different reasons. The star catalogue was capped by its own encoding as much as by the cutoff: one JSON object per star, eight key names repeated each time, 157 bytes a star. At the range HYG actually reaches that is 17 MB to download and parse before the first frame. So the numbers move into two binary column stores — positions in stars.bin, which the GPU is handed verbatim, and id/magnitude/colour/spectral index in stars-meta.bin — and the JSON keeps only the strings, with 2600 distinct spectral classifications collapsed to a dictionary. The layout is defined once, in star-catalog.ts, and the ETL and the app both use it, so the writer and the reader cannot drift. The cutoff then goes to 250 pc: 68388 stars, 7.8x as many for 1.7x the bytes. That is where HYG's measurements stop rather than a round number — 98.6% of its rows are Hipparcos, whose parallaxes are good to about a milliarcsecond, so beyond 250 pc it would be plotting noise. Drawing all of them is a separate question from knowing them, and it is answered separately. The field draws a budget: every star inside 25 pc, because the nearest are faint red dwarfs and Proxima Centauri is magnitude 11, then the brightest of everything beyond. Search, navigation and the planet cross-reference still see the whole catalogue. A real GPU would draw all 68388 without noticing; the budget is for the machines that would not, and it is one constant. Systems were limited by something else entirely. The archive data already shipped named 4735 host stars and only 388 resolved, because the rest lay outside a 50 pc catalogue — and the cross-reference kept only its own result, so redoing it meant re-downloading an archive that is not reachable from here. Host coordinates are now stored with each planet, and the match is re-resolved at build time against whatever catalogue the run produced. Even name matching alone, which needs no coordinates and so works on the records already shipped, rescues 335 planets across 238 systems: 371 renderable systems become 609. Two selection rules were tuned for a 50 pc bubble and no longer fit. Tethers followed the Sun's nearest neighbours, which are a speck at this range, and now follow the brightest; labels were ranked by proximity, which named whatever sat nearest the middle of the screen, and are now ranked by brightness — so the view names Canopus, Achernar and Spica rather than a clump of catalogue designations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
029162ff52 |
Lower the star halo floor so the inner orbits stay legible
The floor that stopped the Sun disappearing reached past Venus and up to Earth, covering the two orbits it most needed to leave alone. Halved, from 3.5% of the framed radius to 2%. The halo's visual radius is half its extent, so that puts its edge at 1% of the framed radius, and the orbits it has to clear sit at their own fraction of the same radius: in the solar system, framed to hold Pluto, Venus is at 1.3% and Earth at 1.8%. Both are now outside it, and the star still reads at about nine pixels across on a typical window. Mercury, at 0.7%, is still inside — and would be at any halo large enough to see, since its orbit is only three pixels wide at that range. That is now a pinned test rather than an oversight. The floor was only ever the lower bound; the tests now state the upper one too, in the terms the trade is actually made in — pixels on screen for visibility, AU against real orbits for clearance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
be19d9cbcc |
Keep the star visible at the distance that frames its system
Framing the whole system pushed the camera far enough back that the star at the centre became a speck — about a pixel across for the Sun. The cause is a constraint that cannot be tuned away. A star is sized against its system's innermost orbit, because it must never swallow its closest planet, while the camera is placed to frame the outermost ring. In the solar system those differ by a factor of a hundred: at the distance that fits Pluto in view, a disc that stays clear of Mercury is a pixel across. No radius satisfies both, because the information genuinely does not fit on one screen at that zoom. So the disc stays honest to the orbits and the halo carries the visibility. Light is not a surface: a glow that reaches past the innermost orbit says the star is bright, not that it is large. Its extent is still a multiple of the star — so a compact system keeps exactly the corona it had — but floored against the framed radius, which is what the wide systems needed. The disc grows a little too: it may now reach 45% of the innermost orbit rather than 35%, which still leaves clear space between the star's limb and the closest orbit. Also makes createGlowSprite take the extent it will draw rather than a radius and a multiplier. The two were only ever multiplied together, and how large a star's halo should be is not a property of the star — it depends on how its system is framed, which is a decision that belongs with the framing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
6019987fc4 |
Frame the system view from the camera it actually has
The grid overflowed the frame in 368 of the 371 systems the datasets contain — median fill 1.11, and the outermost ring cut off by the viewport edge in almost every one. Two compounding causes. The framing distance was a fixed multiple of the outermost orbit, tuned by eye against a 55-degree field of view; the engine's camera is 50. And it framed the outermost *orbit*, while the widest thing actually drawn is the grid's outer ring, which by construction always sits beyond it. Neither is fixable by adjusting the multiple, because a multiple is the wrong shape of answer: what has to fit is a radius on screen, and how much radius a given distance buys depends entirely on the lens. So the distance now comes from the camera's own vertical field of view and aspect — picking whichever screen axis is the tighter one, so a portrait window backs off further rather than clipping — applied to the grid's outer ring with an explicit margin around it. The ceiling goes up with it. Eighty AU could not frame the solar system out to Pluto once the real field of view was accounted for; that needs 120 on a landscape display and 140 on a portrait one. Only companions hundreds of AU out reach the new ceiling, and those still arrive framed on their inner region. Measured across every system in the data, at three window shapes: the overflow count drops from 368 to 2, the fill settles at exactly 0.89 — the margin, uniformly — and the outer ring still encloses the outermost orbit everywhere, so neither invariant was traded for the other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
ac296f5133 |
Derive a surface for every body that was never photographed
Fifteen bodies here have a real photograph. Every exoplanet does not, and never will on current instruments — none has ever been imaged — and nor do several of the solar system's own moons. Those all shared one crude stand-in: a few noisy bands tinted by category, cached per colour, so every exoplanet in the app was literally the same picture. They now get a surface reasoned from what has actually been measured. The chain is standard at every link. A host star's luminosity comes from its catalogued apparent magnitude and its parallax distance — that pair is exactly an absolute magnitude — plus a bolometric correction for its spectral class. The correction is not optional: an M dwarf radiates most of its light in the infrared, so its visual magnitude understates it more than tenfold, and M dwarfs are what most nearby planet hosts are. Luminosity and the semi-major axis then give an equilibrium temperature, mass and radius give a bulk density, and size, temperature and density together give a class of world. Checked against the solar system the temperatures land on Earth 255 K, Jupiter 112 K, Neptune 46 K, all within a kelvin or two of published values, and 51 Pegasi b comes out at 1227 K against a published 1200. Each class carries a palette reasoned from its chemistry — methane absorbs red light, which is why the ice giants are blue — and a structure: zonal bands for a body with a fluid envelope, because a rapidly rotating atmosphere organises into them, and fractal terrain for one with a solid surface. Polar caps grow and shrink with the derived temperature, which is the clearest visible consequence of the whole chain. The generator samples three-dimensional noise along the sphere rather than a flat field, so there is no seam to stitch at the antimeridian and no pinching at the poles, and it writes into a byte array rather than a canvas — a pure function, testable, with no 2D context to be unavailable. Two things the derivation cannot do, both stated on screen next to the measurements it rests on. Equilibrium temperature ignores greenhouse warming and internal heat, so Venus comes out at 300 K against a real surface of 737 K and Io, kept molten by tides, classifies as ice. And these are illustrations: reasoned, but not observations. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
a84e2d3a69 |
Put a reference grid under the system view
A system was a handful of ellipses floating in the dark. You could see that one orbit was bigger than another, but not how big, and not that a planet sat above or below the plane the others share. Adds the same plane-and-tether reading aid the outer scales got: a polar grid in the system's own reference plane, with a drop line from each body onto it. Ring radii snap to a 1-2-5 ladder rather than dividing the system evenly, because the point is to put a number on a distance — 5, 10, 15 AU can be read at a glance and 4.34, 8.68, 13.02 cannot. That holds across the four orders of magnitude real systems span: the solar system gets 5 AU rings, TRAPPIST-1 gets 0.01 AU ones. The outermost ring encloses the outermost orbit rather than falling just inside it. The rings are dashed. Solid ones would sit in the same plane as the orbit ellipses, which are themselves rings, and at a glance a reference circle and a circular orbit are the same picture. Dashes are cut by dropping whole segments rather than by a dashed material: the ring is already built from independent segment pairs, so a material's dash pattern would restart at every one. Drawing the grid exposed a framing bug it made unmissable. The camera settled along one fixed direction derived from the ecliptic, which is face-on only for the one system whose elements are ecliptic. Every exoplanet system — measured against the plane of the sky, perpendicular to the line of sight to its own host star — was being presented nearly edge-on, a smear of overlapping ellipses. The settle direction is now taken relative to whichever plane the system was measured in, so all of them read as discs. The solar system is unmoved, which a test pins. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
2e525fb5c3 |
Open the map out to the whole Milky Way
The map stopped at the catalogued 50 pc around the Sun — 0.33% of the Galaxy's width — and looked like a point cloud with a search box. Adds the galactic scale above it and the heads-up display the reference map is built from. The Galaxy is not a third coordinate space. It is the same parsec space four orders of magnitude further out, so the model and the star field crossfade against camera distance instead of switching, and the Sun stays where it really is: 8.18 kpc out, on the Orion Spur, between the Sagittarius and Perseus arms. The depth range scales with that distance — one fixed near/far pair cannot both fly into a star and hold the Galaxy. The structure in shared/astro/galaxy.ts is measured: the directions of the centre and the north galactic pole, which fix the disc's 63 degree tilt against the celestial equator; the Sun's galactocentric distance; and a radius, azimuth and pitch angle per arm. The particles scattered around it are not, and cannot be — dust hides the disc, so no catalogue holds the Galaxy's stars. The view says so, and the model fades out before the camera reaches the 50 pc where the real stars are. The rest is the look: polar grids lying in the galactic plane with drop lines from the Sun's neighbours, a scale ladder, a readout panel, range, reticle and frame brackets. Two things had to give way for it. The deep-sky shell is the sky as seen from here, so it dissolves rather than letting the camera fly through a wall of nebulae, and so does the skybox, which is a photograph taken from inside the thing now being viewed from outside. Labels are picked by screen separation rather than distance alone: the Sun's fifteen nearest neighbours are all inside four parsecs and printed as one unreadable clump. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
2f45fa7fef |
Measure exoplanet inclination from the plane of the sky
The Exoplanet Archive measures orbital inclination from the plane of the sky — the plane perpendicular to our line of sight to the host star. Ninety degrees means edge-on as seen from Earth, which is why transiting planets pile up there: 1643 of the 2061 published inclinations are within five degrees of 90. The renderer fed that straight into a propagator that reads inclination as an angle from the reference plane, so every transiting system was tilted against a plane its inclination was never measured against. Each body's elements are now rotated out of their own reference plane into the scene by a per-body quaternion. Solar-system elements keep the ecliptic rotation from the previous commit. Exoplanets get a rotation carrying the elements' +Z onto the line of sight to their host, which is exactly the star's own position — so an inclination of i means the orbit's normal sits i from our line of sight, which is the definition. The rotation about that axis is the node's position angle on the sky. The archive does not publish it and the ETL does not request it, so the shortest arc is used: deterministic, and no less arbitrary than anything else given no data. Planets with no published inclination default to face-on, which is the honest reading of an unconstrained orbit rather than a guess at a tilt. Unifying this replaced the direct eclipticToEquatorial call in the renderer, so solar-system bodies and moons come out exactly where they did before — verified against Sol side by side. Tests: 253 passing, up from 247. The strongest one is the definition itself: a 90-degree planet must pass through our line of sight to the star, which is what a transit is. One test of mine had to be corrected rather than the code — it asserted that two systems at the same inclination must occupy different planes, which is not guaranteed once the node angle is arbitrary, while each still sits at the correct angle to its own host. Note the e2e camera-flight test flaked once under parallel load during this work, then passed in isolation and on two further full runs. Its click-until- entered poll has a fixed 15s budget that a loaded machine can exceed; that is pre-existing and unrelated to this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
2293585940 |
Put orbits and stars in the same reference frame
The app's two sources disagree about which frame they are in, and nothing reconciled them. HYG star positions are equatorial J2000 — that is what raDecDistanceToXyz produces and what the galaxy view renders directly. Orbital elements come from JPL Horizons, whose default reference plane for element output is the ecliptic, and the ETL never overrides it. The two are tilted 23.4 degrees apart, so the orbits sat that far off the sky they are drawn against. Confirmed rather than assumed, from both ends: the Horizons request in lib/horizons.ts sets no REF_PLANE, and the resulting solar-system inclinations are 0 to 17 degrees with Earth exactly 0.00 — which is only true of the ecliptic, since Earth's orbit defines it. eclipticToEquatorial now rotates orbit positions into the scene frame, so a direction means the same thing in the galaxy view and the system view. The rotation is about the vernal-equinox axis, which both frames share. That exposed a presentation problem the old code had been hiding. The renderer mapped the propagator's z straight onto the scene's vertical, which silently redefined the frame but did make systems render flat. In a properly equatorial scene, orbital planes lie 23.4 degrees off the scene's own axes, so a system would be presented edge-on. Rather than rotate the world back into a comfortable pose — which would only put the orbits at odds with the sky again — the camera now settles relative to the orbital plane: a three-quarter view about 37 degrees off the ecliptic normal. The arrival still begins along the approach direction and swings round as it settles, so the transition stays continuous, and the framing is now the same every time rather than inherited from wherever the camera happened to be. Tests: 247 passing, up from 237. The frame tests are the discriminating kind — Earth's orbit must lie perpendicular to the ecliptic pole rather than to the scene's vertical, and must reach 23.4 degrees of declination a quarter orbit on, where it used to read zero. Verified in a browser against Sol and Gl 357. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
c1feb4b74e |
Rewrite the star field as instanced billboards
Plan step 3 promises glow and size driven by magnitude and spectral type, but the star field was a THREE.Points cloud and the WebGPU backend — the renderer this app targets — caps point primitives at a single pixel. Every one of the 8750 stars drew as an identical 1 px dot with a hard edge, discarding the magnitude sizing entirely; the class comment already admitted sizeNode only did anything on the WebGL2 fallback. Each star is now an instanced camera-facing quad on a SpriteNodeMaterial, which behaves the same on both backends. That material takes each instance's centre from positionNode rather than from an instance matrix, so position, colour and size ride on instanced buffer attributes and the mesh itself never moves. A radial falloff in opacityNode gives each star a bright core inside a soft halo. Sizes are angular rather than world-space. That keeps a star the same apparent size at any camera distance, which is both what the old screen-space points did and what is physically right: real stars are unresolvable point sources, so apparent size follows brightness, not distance. World-space quads would instead have made the whole field vanish at the camera's 2000 pc limit. Picking had to be rebuilt. Billboarding happens in the vertex shader, so the CPU-side geometry is one quad at the origin and Raycaster cannot see the star field at all. Selection is now done in screen space against the size each star is actually drawn at, which is strictly better than the fixed 1.2 pc world radius it replaces — that radius was over-permissive up close and sub-pixel at the far end of a 4000x camera range. Stars behind the camera need an explicit depth guard, because project() mirrors them back onto the screen. Two things only caught by running it. The colour attribute was declared with node type 'color', which is not a GLSL type, so the generated shader failed to compile — it has to be vec3. And the click tolerance was first written as a floor on the drawn radius, which flattened every star to one hit size, since a floor generous enough for the faintest star exceeds the brightest star's radius; adding the slop instead keeps a brighter star the easier target. Tests: 151 passing, up from 145. Verified in a real browser — shaders compile clean and the Playwright click-to-select flight passes against the new picking. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
3a859360ba |
Add the deep-sky backdrop, the last unbuilt piece of the plan
The design doc scopes deep-sky objects as a galaxy-view backdrop and lists fetchDeepSky.ts, deepsky.json and deepsky.model.ts, but none of it existed — it was the only part of the plan with no implementation behind it. ETL: fetchDeepSky.ts pulls the OpenNGC catalog, classifies each object as a galaxy/nebula/cluster, and keeps the ~460 worth drawing (everything Messier, everything with a common name, and anything brighter than magnitude 9) out of ~12,000 mostly-anonymous rows. build.ts runs it and validates the output. Distances are the hard part: OpenNGC has no distance column, and both fallbacks fail for the best-known objects. M31, M33 and M42 are Local Group members whose redshift is negative or absent, and a galaxy's catalog parallax comes from a cross-matched foreground star — 6 mas for M31 would put a 780 kpc galaxy at 167 pc. So records store a unit direction on the celestial sphere rather than a position (the line of sight is always known precisely, and the objects are drawn on a fixed backdrop shell where true distance is unusable anyway), and distance is optional metadata carrying its own provenance. Parallax is trusted only for galactic objects, redshift only above z=0.003 where expansion outweighs peculiar velocity. 330 of 463 get a distance; the rest honestly report none. Rendering: DeepSkyRenderer paints the objects as soft additive billboards on a 2500 pc shell — clear of the 50 pc star field, beyond the camera's 2000 pc orbit limit, and inside its 5000 pc far plane. Size comes from real angular extent, so Andromeda is six times wider than the full Moon, clamped at both ends. Sprites rather than points because the WebGPU backend caps point primitives at one pixel; materials are shared per kind and brightness band, so 460 objects cost nine of them. The brightest dozen get permanent labels, which needed the label overlay to accept string ids alongside numeric star ids. The backdrop is decorative, so a failure to load its dataset is logged and the star field comes up regardless. Also documents the app in the README, which until now covered only the plugin marketplace. Tests: 112 passing, up from 54. Build, both typechecks and the Playwright suite are green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G |
||
|
|
d7e8ea1d4d |
@
Add star-map Angular app, ETL pipeline, and caveman plugin Angular 3D star map (galaxy/system/body views, Three.js rendering, navigation store) plus the NASA ETL tooling that builds the star, exoplanet and solar-system datasets, Playwright e2e suite, and the cs:caveman Claude Code plugin (command, agent, skill). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> @ |
||
|
|
1e1b58b0e9 | Initial commit |