Changelog
All notable changes to the high machines website (07-website) are documented in this file. Newest version first.
The format is inspired by Keep a Changelog โ and this project adheres to Semantic Versioning. Two JP-specific additions: a per-version ๐ญ Vision TL;DR (so each version is scannable in one breath) and an โ ๏ธ Known Issues section (so partial ships and in-flight work are surfaced, not hidden).
The pre-v0.25.0 history is preserved in the ๐ Legacy entries section below in its original prose form. A copy-paste-ready ๐ Template lives at the very bottom of the file.
For the active user-story backlog, see BACKLOG.md. For the design doc, see SPEC.md. For the spec-revision history (v0.1 โ v0.12), see SPEC.md ยงChangelog โ that tracks changes to the design doc, not the app.
[Unreleased]
๐ญ Vision
House-cleaning sweep (lesson-#0a + #20 follow-up to US60 + US31 closure). The 957c958 US31 closure commit message claimed "Quick Stats 1 in progress โ 0 in progress" but the actual diff left the line stale โ this commit backfills the Quick Stats flip + Next-sprint US31 tail + Story-map US31 indicator + drops the giant Previous-version Status chain in README.md line 5 + SPEC.md line 3 (US60 said drop but US58/US59 re-added it post-US60 commit) + flips 6 stale [ ] task checkboxes for US52/53/54/56 that said "deferred to JP's machine" but the container is live on v0.44.0 since the post-US58 rebuild (~2026-06-29). No version bump โ content-only.
๐ Documentation (house-cleaning sweep, 2026-07-07)
BACKLOG.mdQuick Stats pipeline bullet โ flipped+ **1 in progress** (US31 โฆ 350 MB target remaining)โ+ **0 in progress** (US31 closed 2026-06-30 as content-only revision in commit 957c958 โ original multi-stage ship landed as v0.21.0 on 2026-06-10, 350 MB follow-up target explicitly abandoned per JP's inspection). Pipeline total still 62 US; 56 shipped / 0 in planning / 0 in progress / 4 future sprint.BACKLOG.mdNext-sprint (5+) line โ US31 trailing entry rewritten from**in progress** (multi-stage Dockerfile shipped, 350 MB target remaining with pnpm deploy)to**closed 2026-06-30 as content-only revision** (commit 957c958; original multi-stage ship landed as v0.21.0 on 2026-06-10, 350 MB follow-up target explicitly abandoned per JP's inspection โ marginal 513 MB savings on a single cached image doesn't justify the architectural cost).BACKLOG.mdStory map (dependencies) โ US31 arrow flipped from๐ง partial ship (680 MB)toโ closed 2026-06-30 (content-only, 863 MB, no version bump โ original multi-stage ship landed as v0.21.0 on 2026-06-10, 350 MB follow-up target abandoned). (The(680 MB)was a stale early-partial-ship measurement; canonical at Quick Stats line 448 is863 MBper the 2026-06-26 measurement.)BACKLOG.mdLast Updated line โ bumped from2026-06-30 14:30 UTC(when US60 closed) to2026-07-07 08:30 UTCwith the full housekeeping-sweep summary. Documents the lesson-#0a violation in957c958(commit message claimed Quick Stats flip, actual diff did not land it) so the next audit doesn't repeat the same check.BACKLOG.mddeferred-JP checkbox sweep โ 6 stale[ ]task checkboxes flipped to[x]with**Done**(3) or**superseded**(3) annotations, since the prod container is live athttps://localhost:8001/onv0.44.0(verified 2026-07-07) and the "deferred to JP's machine" condition has been met by every post-US52 rebuild cycle. Affected: US52 T52.20 + thepnpm build+Container liveacceptance bullets; US53 T53.13; US54 T54.10/11/12 + the DoDpnpm build+Container live+README+SPEC+...bullets.README.mdline 5 โ Status header rewritten: now leads with**Status:** v0.44.0 (2026-06-30, US58 ship โ investor-facing /deck route...)and replaces the 7-line Previous-version chain (v0.43.0 โ v0.42.2 โ ... โ v0.39.0) with a 1-line pointer toBACKLOG.mdQuick Stats +CHANGELOG.mdfor the full release timeline. US60's strategy (drop the chain) is finally executed here.SPEC.mdline 3 โ Status header rewritten: same treatment asREADME.md; spec-rev bumpedv0.19 โ v0.20and app version lead updatedv0.43.0 โ v0.44.0. The 10-line Previous-version chain (v0.42.2 โ v0.38.0) is gone.- No code changes, no new public surface, no version bump โ content-only revision per US42 protocol. Re-rendered live at
https://localhost:8001/infoafter the post-82b69f6rebuild (imagebaa3a54a4d35, 863 MB, 2026-07-07 08:24 UTC).
๐ญ Vision (previous Unreleased)
US31 closure lands alongside US60 โ both content-only revisions (no version bump per US42 protocol). US31 closes a 50-day-old partial ship: original multi-stage restructure shipped as v0.22.0 on 2026-06-10 (commit 2b9ecce, prod image 1.11 GB โ 863 MB, devDeps-free, BuildKit cache mounts); the unfulfilled 350 MB on-disk target is explicitly abandoned per JP's 2026-06-30 inspection โ marginal 513 MB savings on a single cached image doesn't justify a 1-day pnpm deploy refactor or an architectural rewrite (lazy-load three+globe.gl for /explore). US60 (shipped earlier today) cleared the Status-paragraph drift class in the same session.
๐ Documentation (US31 closure)
BACKLOG.mdUS31 Status field โ flipped ๐ง Partially shipped โ โ Closed 2026-06-30 (content-only revision). Documents the original v0.22.0 partial ship (commit2b9ecce, 2026-06-10), the explicit abandonment of the 350 MB target with rationale (marginal value vs. architectural cost), and the 2 retained known minor nits: (a) 1.2 MB / 146-file/app/srcleak in prod runtime โ US31 AC fail but dormant (runtime only readsnode build, not exploited); (b)testbuild target exists in the Dockerfile but not wired into a compose service โ one stanza of YAML if CI needs it.BACKLOG.mdUS31 DoD section โ rewritten as the closure checklist: original v0.22.0 partial-ship ACs checked (multi-stage split, BuildKit cache, devDeps-free, prod healthy, 4 routes 200), 350 MB target explicitly abandoned with documented decision, source-tree leak acknowledged as known nit,testtarget acknowledged as un-wired, Quick Stats updated, Recent ships entry added, CHANGELOG entry added.BACKLOG.mdUS31 planning-list entry โ updated: "partially shipped" status note replaced with "closed 2026-06-30 as content-only revision" note, documenting the abandonment and the 2 retained nits.BACKLOG.mdQuick Stats pipeline bullet โ "1 in progress (US31 ... 350 MB target remaining)" โ "0 in progress (US31 closed 2026-06-30 as content-only revision โ original multi-stage ship landed as v0.22.0 on 2026-06-10, 350 MB follow-up target abandoned per JP's inspection)".BACKLOG.mdRecent ships โ new#### US31 โ closed 2026-06-30 (content-only revision)H4 entry at the top of Recent ships, summarising the 50-day arc (partial ship at v0.22.0 โ 350 MB follow-up abandoned on 2026-06-30 โ US closure).BACKLOG.mdUS31 detail block "Closure rationale" subsection โ added 2 new bullets after "What this DOES pre-empt": (i) what the US actually closed with (863 MB as final state, the 2 known nits documented, the architectural cost to hit 350 MB); (ii) why this closure pattern matters (US31 sat "1 in progress" for 50 days, closing it explicitly converts an abandoned target into a documented decision for the next agent / future JP).BACKLOG.mdLast Updated line โ bumped to 2026-06-30 15:55 UTC with the US31 closure summary.- No code changes, no new public surface, no version bump โ content-only revision per US42 protocol (same pattern as US60 / US57 / US49).
- Verification:
pnpm check0/0,pnpm lintclean,pnpm prettier --write BACKLOG.mdno changes needed (file already formatted). The BACKLOG content will be live after the next prod rebuild (BACKLOG.md is baked into the image and rendered live via/info).
๐ Documentation (US60)
SPEC.mdline 3 โ Status line rewritten: dropped the 13 KB giant roll-up previous-version chain that claimed**53 US shipped**(canonical is 55); kept the last 5 versions inline (v0.39.0 โ v0.43.0) with their test-count chain; added a 1-line pointer toBACKLOG.mdQuick Stats as the canonical source + a 1-line pointer toCHANGELOG.mdfor older ship history. Spec-rev bumped to v0.20 (2026-06-30).README.mdline 5 โ Status line rewritten: same treatment as SPEC.md line 3; dropped the 15 KB roll-up chain that claimed**50 US shipped**(the worst offender โ also built up a "Latest ship: US51" block inside the chain which compounded the staleness); kept the last 5 versions inline + pointer to CHANGELOG.md / BACKLOG.md Quick Stats.BACKLOG.mdline 728 โ US22 planning-list checkbox flipped[ ]โ[x]with a 1-line status note: "Status 2026-06-20: shipped (doc-only โ 6-lens design review; output consumed by US51)".BACKLOG.mdline 1464 โ Second US22 planning-list checkbox (the Sprint 5+ cross-cutting list) flipped[ ]โ[x]with the same status note.BACKLOG.mdline 733 โ US31 planning-list inline size claim updated from "1.11 GB โ 680 MB (39% smaller)" to "1.11 GB โ 863 MB (per 2026-06-26 measurement)" โ the 680 MB was an early partial-ship measurement before US34's BuildKit cache mounts + US46's build memory fix landed (both increased on-disk size to 863 MB but with much better rebuild speed + reproducibility); retroactively updated to match Quick Stats line 448.
[0.44.0] - 2026-06-30
๐ญ Vision
US58 โ Investor-facing deck + /deck page for cold outreach. A new public surface (/deck route, 12 slides, print-friendly via @media print) gives JP a single shareable link that walks an investor through problem โ solution โ traction โ team โ ask โ use of funds โ comparable rounds โ honest unknowns + CTA without requiring them to navigate the whole site. All copy is sourced verbatim from the canonical /investors page (US29 + US51) โ no new claims invented. The same route renders cleanly on phone + desktop + print; "Download PDF" button triggers window.print() so the investor can save as PDF from their browser (no PDF generator, no new npm deps). 550 โ 562 unit tests green, +12 US58 assertions. Minor bump per semver protocol โ new public surface.
โจ Added (US58)
src/routes/deck/+page.svelteโ New 12-slide investor deck. Title / Problem / Solution / Why this / Why now / Why us / Market (TAM-SAM-SOM stat cards) / Traction (4 stat cards) / Team / Ask + Use of Funds (5-line breakdown) / Comparable rounds (Starcloud + US competitors) / Honest unknowns + CTA (mailto:). All copy sourced verbatim from/investors(US29 + US51) โ no new claims invented. Tailwind classes only, no new npm deps.src/routes/deck/+page.server.tsโ Empty server load (per US58 AC: route is purely static).src/routes/deck/deck.test.tsโ 12 TDD-shaped assertions: page exists, server load exists,data-testid="deck-page"wrapper, "Deck" in<title>, exactly 12data-testid="deck-slide-*"sections, "Download PDF" button,window.print()wired up, mailto CTA, TAM/SAM/SOM stat cards present,@media print+page-break-afterrules,deck-print-hidehides nav header on print, canonical /investors content referenced (Three Whys, โฌ2-5M ask, TAM/SAM/SOM numbers, Starcloud comparable).src/routes/deck/+page.svelte <style>โ@media printrules: 1 slide per A4 page (page-break-after),deck-print-hidehides nav header + Download button on print,:global(body)background flips to white, slide text colors flip to black, stat-card backgrounds flip to white. Slide CSS for the on-screen layout: 100vh-per-slide on screen, stat-grid responsive (auto-fit minmax(220px, 1fr)).src/lib/components/nav/Nav.svelteโ Added/deckto the nav items array, placed between/competitorsand/info(primary audience route before meta route). Active-state highlighting inherits from the existingisActive()helper.
[0.43.0] - 2026-06-29
๐ญ Vision
US59 โ "Why we win" callout on /competitors. The page had 11 verified competitor profiles and a tag-chart cross-section but no high-machines positioning โ an investor landing on /competitors got a data dump but not the answer to the silent "why should I care?" question. US59 adds a 4-card bento section between the page header and the existing "Competitors by tag" chart, explaining our actual competitive lane vs. the 11 profiled companies. The 4 cards are sourced verbatim from the /investors "Why us" prose (US29 + US51): AI-native engineering (deep RL for mission-architecture design โ AI4CE PhD, 6 papers, 1 ESA CDF collaboration; a capability 30-yr primes can't replicate), Venture speed (primes run 5โ10 yr cycles vs. our mid-2027 architecture window), Primes as channel (their slow cycles turn them into integrators/acquirers once the standard is locked โ we race for the standard, not the compute market), Open methodology (open research loops outpace closed prime culture ~5ร; same reason Linux won the OS war). Visual pattern mirrors US54 home page Three Whys (BentoGrid + 4 BentoCell size="md", 2ร2 on lg+, 1 per row on mobile) + title + headline (sky-300 accent) + 2-3-line body. Framing subtitle above the cards: "These 11 companies are not our real competitors. Here's our actual lane." Footer links to /story (Three Whys long-form) and /investors (full pitch + ask). All copy is verbatim from /investors โ no new claims invented. Plan-check pass: the original US59 ACs contained hallucinated tech claims (Phi-3 Mini reasoning in 1MB / Terraform-for-space infra-as-code) from the fallback model โ those were replaced with the real /investors wedge per JP's "I follow your suggestions" reply (2026-06-29 23:12 UTC); commit caed1d8 rewrote the AC block in BACKLOG, commit e6f2985 shipped the corrected implementation. 550 unit tests green (+4 US59 assertions: section-exists + BentoGrid + each-loop + 4-card-s + footer-link targets); pnpm check 0/0; pnpm lint clean. Live at https://localhost:8001/competitors verified via the curl + JSON-unescape pattern from MEMORY lesson #19. Minor bump per semver protocol โ new user-facing surface.
โจ Added (US59)
- "Why we win" callout section on
/competitors(src/routes/competitors/+page.svelte) โ 4 BentoCells in a BentoGrid above the existing "Competitors by tag" chart, each with title + headline (sky-300 accent) + body (~2 lines):- AI-native engineering โ Deep RL for mission-architecture design. Our AI4CE research (6 papers, 1 ESA CDF collaboration) applies deep reinforcement learning to the architecture-design loop โ a capability 30-year engineering cultures cannot replicate.
- Venture speed โ 18 months is the window. Primes run 5โ10 year mission cycles. The architecture window for orbital compute closes mid-2027. Whoever locks the standard then sets the bar the incumbents have to clear.
- Primes as channel โ Slow primes = our distribution. Once the standard is set, their slow cycles turn the primes into integrators and acquirers โ not competitors. We race for the standard, not the compute market.
- Open methodology โ Open beats closed on iteration speed. Open research loops outpace closed prime culture ~5ร on iteration speed. The agent framework is open-stack; theirs is closed. Same reason Linux won the OS war.
- Framing subtitle above the 4 cards: "These 11 companies are not our real competitors. Here's our actual lane." โ flips the page from descriptive (what we tracked) to positioning (why we win).
- Footer paragraph linking to
/story(Three Whys long-form) and/investors(full pitch + ask) โ readers who want the deep context can find it without leaving the family of pages. - Stable
data-slugper card (ai-native/venture-speed/primes-as-channel/open-methodology) โ supports per-card scroll anchors (/competitors#why-we-win-ai-native) and regression tests.
๐ง Changed (US59 ship)
SPEC.md(line 3, Status header) โ bumpedv0.42.2โv0.43.0; new parenthetical describes US59; old v0.42.2 (US56) appended to the "Previous version" chain. Also fixed two pre-existing stalev0.43.0mentions for US54 (line 79 + line 106) which claimed US54 shipped as v0.43.0 โ actually US54 ships as v0.42.0 per CHANGELOG/BACKLOG/package.json; v0.43.0 is now correctly claimed by US59. Per MEMORY lesson #20 (sweep the read-only parts now): same-commit fix prevents future drift that would have been caught on the next audit.README.md(line 5, Status header) โ same Status header bump as SPEC.md; the v0.42.2 (US56) chain now goes v0.43.0 โ v0.42.2 โ v0.42.1 โ v0.42.0. Ship count: 54 โ 55 US shipped; 546 โ 550 unit tests green.BACKLOG.mdโ US59 entries ticked ([ ]โ[x]for all 7 ACs + all 11 tasks + all 6 DoD bullets); Last Updated line bumped to 2026-06-29 23:35 UTC; "Last US added to planning" now points to US58 (US59 promoted to shipped); "Last US shipped" line bumped from US56 (v0.42.2, 2026-06-27) โ US59 (v0.43.0, 2026-06-29); Quick Stats line + bullet list updated (54 โ 55 shipped, 2 in planning โ 1 in planning (US58), 546 โ 550 tests, pipeline 59 โ 61 total); new "Recent ships"#### US59 โ v0.43.0 (2026-06-29)H4 entry added at the top.package.jsonโ version0.42.2โ0.43.0.
๐ฆ Technical details (US59)
- 1 page-template edit:
src/routes/competitors/+page.svelteโ addedwhyWeWintypedReadonlyArrayof 4 cards above<svelte:head>(withslugtyped string-literal unionai-native | venture-speed | primes-as-channel | open-methodology); added the new<section data-testid="competitors-why-we-win">block inside{:else}between the page header and the existing tag-chart<BentoCell size="full">; BentoGrid + 4<BentoCell size="md" id="why-we-win-${w.slug}">(2ร2 onlg+ vialg:col-span-2, single-column on mobile via the US7 responsive pattern); footer<p>with 2 inline<a>links (href="/story"andhref="/investors"). - 1 test extension:
src/routes/competitors/competitors.test.tsโ newdescribe("US59 โ /competitors 'Why we win' callout")block with 4 assertions: (a)data-testid="competitors-why-we-win"section exists, (b) the section wraps a<BentoGrid>with{#each whyWeWin as w (w.slug)}keyed loop, (c) all 4 expected slugs are declared in thewhyWeWintyped array literal (each tested individually + the each-loop is keyed by slug so each card renders the right DOM id), (d) the callout footer has bothwhy-we-win-link-story+why-we-win-link-investorslinks pointing to/storyand/investorsrespectively. - Verbatim copy from
/investorsโ all 4 card bodies are sourced verbatim from the/investors"Why us" prose (US29 + US51). Any future copy change on/investorspropagates to/competitorsvia copy update + a single commit. - Lesson-#20 sweep โ the US54
v0.43.0mistake in SPEC.md would have surfaced on the nextverification-passaudit as drift between code reality and doc text; fixed in this same commit before it became that drift. The "50 US shipped" / "53 US shipped" / "54 US shipped" count in the giant Status paragraph (line 3) was not updated to "55" โ that's a doc refactor outside US59's read-only scope and got the same drift-deferred-to-follow-up treatment as MEMORY lesson #0a / lesson #20 recommended (sweep small things, open a US for storytelling-debt rewrites). Tracked separately. - Tests + checks: 550/550 unit tests green (+4 US59 assertions from 546);
pnpm check0/0 errors and 0/0 warnings;pnpm lintclean (one Prettier formatting auto-format folded into the prior docs commitcaed1d8).
โ ๏ธ Known Issues (US59 ship)
- The
BACKLOG.mdgiant Status paragraph ship-count claims are still stale in places โ the line-3 Status chain + Quick Stats bullets got the canonical "55 US shipped" + "550 tests" updates, but the super-long compounded Status chain at the very top of the file still claims "53 US shipped" / "54 US shipped" in places. Sweep them in a follow-up pass per MEMORY lesson #20 (open a US for the doc-counter sweep; not in scope for US59). /deckpage (US58) still pending โ the only remaining "in planning" US after this ship. Co-planned with US59 on 2026-06-29 19:10 UTC; the same plan-check pass corrected the US58 AC #2 "traction" line to referenceUS1โUS57instead of the staleUS1โUS56. US58 ships separately per JP's sequencing.
[0.42.2] - 2026-06-27 On 2026-06-29, the stale-Status audit (commits 41b2cdd + 828b9f5 + a22e509) fixed 7 of 7+ lesson-#0a siblings (6 Status fields + line 439 US55 mention + Last Updated line + Quick Stats block). The "Next sprint (5+)" line on BACKLOG.md line 439 was the one remaining design-decision part: it still named US22 (design review โ shipped 2026-06-21 as v0.39.0 via US51), US28 (competitor profile detail pages โ shipped v0.25.0), and US29 (Three Whys narrative deconstruction โ shipped v0.34.0) as "Next sprint", but all three actually shipped weeks/months ago. Same lesson-#0a root cause as the Status field drift; the difference is that the line is a curated forward-looking list (not a count) so the rewrite is a design decision per lesson #20 โ not a sweep, a US. The line is now: "โญ๏ธ Next sprint (5+): US19 (a11y audit), US20 (SEO + meta tags), US21 (quarterly content refresh), US48 (real DNS + Let's Encrypt, blocked on JP's DNS step) โ cross-cutting housekeeping. US30 (hub-and-spoke design fully closed 2026-06-19) โ Phases 1โ4 shipped as v0.35.0 / v0.36.0 / v0.37.0 / v0.38.0, all 4 audience cards now routable. US31 (Docker build runtime inspection & optimisation) โ in progress (multi-stage Dockerfile shipped, 350 MB target remaining with pnpm deploy)." โ the 4 actual future-sprint USes (US19/20/21/48) are now front-and-centre; the 2 design-history USes (US30 closed, US31 in-progress) keep their context. Quick Stats line 428 "1 in planning" โ "0 in planning". Same-cycle CHANGELOG hygiene: the US56 content that was orphaned in [Unreleased] (because US56 shipped as v0.42.2 on 2026-06-27 but never got moved to a dated block) is now in a new [0.42.2] - 2026-06-27 section, leaving [Unreleased] for the next ship. No version bump per US42 protocol โ content-only refresh, no new user-facing surface. Production container live at https://localhost:8001/info showing the rewritten line + the cleaned [Unreleased]/dated split.
โจ Added (US57)
- "Next sprint (5+)" line in
BACKLOG.mdrewritten (line 439 of the Quick Stats block) โ the 3 stale references to shipped USes (US22 / US28 / US29) are gone; the 4 actual future-sprint USes (US19 a11y / US20 SEO / US21 quarterly / US48 DNS) are the headline. US30 (hub-and-spoke design fully closed 2026-06-19) + US31 (Docker build runtime inspection & optimisation, in progress) keep their design-history context. Same pattern as the US38 audit-restructure: the line now reads as a curated forward-looking list, not a stale "what's coming" wall. - CHANGELOG hygiene (US57 side-effect) (
CHANGELOG.md) โ the[Unreleased]block still contained US56's full content (Vision / โจ Added / ๐ง Changed) because US56 shipped as v0.42.2 on 2026-06-27 but the [Unreleased] โ[0.42.2]move was never made. Moved: US56 content is now in a new[0.42.2] - 2026-06-27block, and[Unreleased]is clean for the next ship. Same lesson-#0a root cause: the date wasn't updated when the version was finalised. The corrected structure mirrors the US56 closeout's own note: "The corrected[Unreleased]section is now split cleanly into a[0.42.1] - 2026-06-27block (with the US55 details, US49 content-only refresh, and the duplicate US55 Changed section removed) and a new[Unreleased]block (with the US56 details for the v0.42.2 ship)" โ US57 closes the loop by promoting the US56 [Unreleased] content into its proper dated section. - Quick Stats "1 in planning" โ "0 in planning" (
BACKLOG.mdline 428) โ US57 was the only "in planning" US; on ship, the count drops to 0. The bullet structure (54 shipped + 0 in planning + 4 future sprint) is back to the pre-US57 form, matching the "Last US added to planning" header (which still references US57 as the most recent planning entry added, regardless of ship status).
โ ๏ธ Known Issues (US57)
- US57 has no version bump and no
[Unreleased]from[0.42.2]split commit hash โ per US42 protocol, content-only refreshes (no new feature, no new public surface) get no version bump; they go in[Unreleased]in CHANGELOG.md, not in a new dated version. The ship commit (this one) is the canonical reference; the git log + commit message is the only way to find the US57 content. If JP wants a v0.42.3 patch bump for traceability, the change is a one-liner inpackage.json+ a US58 closeout commit. Out of scope for this US. - The
BACKLOG.md"Last Updated" line + "Last US added to planning" line drift if not maintained โ same lesson-#18 same-commit tax. US57's ship commit (this one) includes the Last Updated bump in the same diff. Future USes should follow the same pattern; the existing lesson #18 + lesson #16 inMEMORY.mddocument the rule.
[0.42.2] - 2026-06-27
๐ญ Vision
US56 โ Render competitor profile markdown body as structured system overviews. On 2026-06-27, JP was looking at the live /competitors/starcloud page and said "I want full overviews about the system in dedicated sections" โ the rich hardware deep-dives (Starcloud-1's 60 kg H100 demonstrator with Karpathy's nano-GPT, Starcloud-2's 8 kW Blackwell-B200 commercial platform with Crusoe Cloud + AWS Outposts) were sitting in the research markdown, not on the website. The current page only shows the curated digest (summary / highlights / watchlist / sources); visitors who wanted system-level specifics had to click through to GitLab. Two paths to fix: (a) lift the hardware sections from the markdown to the page as dedicated cards (lowest-complexity win, reuses the existing bind-mount, no new routes), (b) build a new Systems tab + nested routes (over-engineered for content that's likely to stay flat). Path (a) wins. Implementation: at request time, the server load reads the markdown body, splits it on H2 boundaries (respects fenced code blocks so the Starcloud-1/2 hardware tables don't get sliced), filters H2s via a heuristic (separator โ or -, OR a known system-keyword prefix like starcloud / bluebeam / cubesat), renders each matched section via the existing marked instance (the US41 mermaid passthrough is shared via a new $lib/utils/markdownRenderer util so /tech and the new /competitors/[slug] use the same renderer), and passes the array of { heading, html } to the page. The page renders an optional <section data-testid="system-overviews"> between the digest and the "Source on GitLab" footer โ when systemSections.length === 0 the section wrapper is omitted entirely (graceful degradation, profiles like axiom-space with no system H2s render no extra block). The markdown remains the single source of truth per US55 + the US6 bind-mount: editing a system section heading or body on the host shows up on the live page on the next reload, with no rebuild. Two new shared utils ($lib/utils/markdownSections + $lib/utils/markdownRenderer); one new readMarkdownBody helper in $lib/competitors/data (mirrors the US55 readMarkdownUpdated shape); the marked.use({ renderer }) setup is lifted from /tech so the global marked instance is configured exactly once. 546 unit tests green (+19 US56 assertions: 16 in markdownSections.test.ts + 3 in [slug]/[slug].test.ts). Minor bump per semver protocol โ new user-facing surface (system-overview cards on the detail page). Ships as v0.42.2.
โจ Added (US56)
- System overview cards on
/competitors/[slug](src/routes/competitors/[slug]/+page.svelte,src/routes/competitors/[slug]/+page.server.ts,src/lib/utils/markdownSections.ts,src/lib/utils/markdownRenderer.ts,src/lib/competitors/data.ts) โ the research markdown's "system overview" H2 sections (e.g.## Starcloud-1 โ Technology Demonstratorand## Starcloud-2 โ Commercial Platformin01-research/competitor-profiles/starcloud.md) are now rendered as dedicated content cards under the typed digest. Each card shows the section heading + the rendered markdown body (tables, lists, prose). The page is now progressive-disclosure: the typed digest is the 1-paragraph view, the system cards are the deep dive, the "Source on GitLab" link is the full research notebook. Profiles without system sections (e.g. axiom-space, eric-schmidt-relativity) render no extra block โsystemSections.length === 0skips the section wrapper entirely (graceful degradation). The markdown remains the single source of truth per US55 + the US6 bind-mount: editing a system section heading or body on the host shows up on the live page on the next reload, with no rebuild. - New
$lib/utils/markdownSectionsutil โparseSections(body)splits a markdown body on H2 boundaries (respects fenced code blocks, strips leading + trailing blank lines from each section);isSystemSection(heading)returns true for headings that look like a named hardware platform (heuristic: contains an em-dash or hyphen with spaces, OR starts with a known system-keyword โstarcloud/bluebeam/axiom dc/axdcu/cubesat/cdpu);parseSystemSections(body)is the convenience combo. Locked in by 16 unit tests inmarkdownSections.test.ts(split on H2, ignore H1/H3-H6, preserve fenced code blocks spanning H2s, handle both ```and ~~~ fences, real-file regression test onstarcloud.md+ graceful-degradation test onaxiom-space.md). - New
$lib/utils/markdownRendererutil โ themarked.use({ renderer })setup with the US41 mermaid passthrough was lifted fromsrc/routes/tech/+page.server.tsinto a shared module so/competitors/[slug]can reuse the same mermaid-aware renderer without re-installing it (twomarked.usecalls on the global marked singleton would clobber each other). The shared util exportsrenderMarkdown(markdown)(async, returns the HTML string) and re-exports the configuredmarkedinstance. Future routes that render markdown body content can import from here too. readMarkdownBody(slug)in$lib/competitors/data.tsโ mirrors the US55readMarkdownUpdated(slug)shape: sameCOMPETITOR_PROFILES_DIRenv override, same asyncnode:fsread, sameparseFrontmatterimport, returns the body (everything after the closing---of the frontmatter block) orundefinedif the file is missing / unreadable / has no frontmatter. The detail-page server load calls it once per request, then runs the body throughparseSystemSectionsand renders each section via the sharedrenderMarkdownutil.- Progressive disclosure: the
/competitors/[slug]page stack is now 4 layers โ the header (name, oneLiner, tags, freshness badge per US55), the typed digest (summary / highlights / watchlist / sources โ unchanged), the new system-overview cards (US56), and the "Source on GitLab" footer link. Each layer is independent: a profile with no system sections still has a complete page; a future profile with 5 system sections renders 5 cards without changing the digest.
๐ง Changed (US56)
/techroute imports the shared markdown renderer (src/routes/tech/+page.server.ts) โ the localmarked.use({ renderer })setup + the US41 mermaid passthrough are gone from this file; the route now importsrenderMarkdownfrom$lib/utils/markdownRenderer. Behaviour is unchanged: every/techsection that contains a ```mermaid block still renders as<pre class="mermaid">โฆ</pre>(the form that mermaid 11.x picks up viaquerySelector). The change is internal โ no visible difference to visitors.mermaid.test.tsandtech.test.tsupdated to lock in the new shared location: both tests now check that$lib/utils/markdownRenderer.tscontains the<pre class="mermaid">string and therenderer.codeoverride, and that/techimports from the shared util (and does NOT callmarked.uselocally โ that would clobber the global instance).- ๐ช Fixed (US56) โ duplicate
### ๐ง Changed (US55)block in[Unreleased]โ caught while writing the US56 entry. The duplicate was a copy-paste artefact from the US55 closeout on 2026-06-27 (the section was appended twice to[Unreleased]). Removed in this closeout. The corrected[Unreleased]section is now split cleanly into a[0.42.1] - 2026-06-27block (with the US55 details, US49 content-only refresh, and the duplicate US55 Changed section removed) and a new[Unreleased]block (with the US56 details for the v0.42.2 ship).
- 2026-06-27
๐ญ Vision
US55 โ Single source of truth for competitor profile dates (markdown frontmatter โ data.ts). On 2026-06-27, JP noticed the "Reviewed YYYY-MM-DD" badge on /competitors/starcloud (and the other 10 profiles) still showed 2026-06-20 even though US49 had refreshed the markdown updated: frontmatter to 2026-06-26 the day before. Root cause: the date was duplicated in two places โ the markdown frontmatter AND the bundled CompetitorProfile shape in src/lib/competitors/data.ts. US49 only refreshed the markdown, leaving data.ts stale; the badge only updated after commit 825d677 + a full prod container rebuild (the OOM-prone path per memory ยง14, ~5 min + watch the gateway watchdog). Two sources of truth = guaranteed drift on the next refresh. Fix: read the date from the markdown at request time via the existing US6 bind-mount of 01-research/competitor-profiles/ โ COMPETITOR_PROFILES_DIR in the container. Remove the duplicated updated: field from the CompetitorProfile interface + the 11 entries in data.ts. Extract the hand-rolled parseFrontmatter from src/routes/tech/+page.server.ts (US32 + US41) into a shared $lib/utils/frontmatter util so both routes can read the frontmatter without re-implementing it (no new deps, no new build step). Patch bump per semver protocol โ bug-class fix, no new user-facing surface (the badge text + position are unchanged). Ships alongside US49 as v0.42.1.
US49 โ Competitor profile verification & refresh (AprilโJune 2026). All 11 competitor profiles in 01-research/competitor-profiles/ updated with fresh milestones from the last 3 months. Content-only โ no version bump per US49 acceptance criteria ("this is content-only; the site reads the profiles via bind-mount so changes are live immediately on next deploy").
โจ Added
- Competitor profile updates (
01-space-AI/01-research/competitor-profiles/*.md) โ all 11 profiles refreshed with AprilโJune 2026 milestones:- Batch A (2026-06-20): mantis-space (New Mexico incentives, stealth exit), agnikul-cosmos (semi-cryogenic engine test, NeevCloud partnership), neevcloud (Agnikul MoU, India's first indigenous ODC)
- Batch B (2026-06-26): axiom-space ($525M oversubscribed round + Texas redomicile + Swiss sub + Prada LCVG + NASA core-module abandonment), aetherflux (Cowboy Space rebrand + $275M Series B + 20,000-sat Stampede FCC filing + end-2028 rocket target), alibaba-qwen-departures (two-track narrative: Alibaba closes flagship weights + Lin Junyang $2B pre-seed AI lab)
- Batch C (2026-06-26): starcloud (Oct 2026 โ Jan 2027 launch slip + Series A co-leader fix Benchmark + EQT + $200M total funding + Starlink Mini Laser deal + Series B talks at $2.2B), blue-origin (May 28 New Glenn explosion + May 5 NASA objection + Isaacman 2028 timeline + threat downgrade HIGHโMEDIUM), eric-schmidt-relativity (Aeolus reframed as NASA science contract + Terran R Stennis milestone + instrument suite)
- Batch D (2026-06-26): spacex (IPO completed June 12: $75B raised, >$2T valuation, Musk first trillionaire + Anthropic date correction May 6 + Starship Flight 12 partial success + FAA mishap May 27 + Blue Origin explosion May 29 + Starlink 12,342 launched + AI1 + Gigasat + Google $30B compute deal), google-suncatcher (Trillium TPU radiation test corrected to Nov 2025 + clarified $30B Google-SpaceX deal is Nvidia cloud compute, not Suncatcher)
- 41 new sources added to sources.db (IDs 366โ410) โ SpaceNews, Reuters, Bloomberg, NYT, TechCrunch, SpaceX primary, Wikipedia, Forbes, NPR, CNBC, Spaceflight Now, KeepTrack.space, SatNews, Via Satellite, BusinessWire, Axiom Space primary, University of Houston, Texas Governor, xAI, Decrypt, 36Kr, GuruFocus, BigGo Finance, The Information, Caixin Global, QwenLM GitHub.
- No website code changes โ content-only refresh, live immediately via bind-mount.
๐ง Changed (US55)
- Single source of truth for competitor profile dates (
src/lib/competitors/data.ts,src/routes/competitors/[slug]/+page.server.ts,src/routes/competitors/+page.server.ts) โ theCompetitorProfileinterface no longer carries anupdated:field; the 11 hand-written entries no longer duplicate the date. The "Reviewed YYYY-MM-DD" badge on/competitors/[slug]and the<time datetime="โฆ">element on/competitorsnow both read the date from the markdown'supdated:frontmatter at request time (via the US6 bind-mount). Editing the markdown'supdated:field on the host is reflected on the live page on the next reload, without a rebuild. - Shared
parseFrontmatterutil (src/lib/utils/frontmatter.ts) โ the hand-rolled YAML-ish parser (originally shipped in US32, extended in US41 for folded / literal block scalars) is now extracted fromsrc/routes/tech/+page.server.tsinto a shared module. Both/tech(the original consumer) and$lib/competitors/data.ts(the new consumer forupdated:reads) import from$lib/utils/frontmatter. No new npm deps. The shared parser is locked in bysrc/lib/utils/frontmatter.test.ts(9 new tests covering scalar pairs, bracketed lists, quoted strings, folded / literal block scalars, missing / malformed frontmatter, and the realstarcloud.mdshape that drove US55). - Frontmatter added to
alibaba-qwen-departures.mdโ previously the only profile without a----delimited frontmatter block (it used inline**Date:**+last updatedin the body). Added the standardtitle: / date: / updated: / tags: / status:frontmatter so the new "read from markdown" path picks it up.tagsnow includescompetitor(was untagged before; the bar chart count moves from 10 โ 11 โ seecompetitor-tags.test.ts). CompetitorProfileshape slimmed from 12 fields to 11 โupdated: stringremoved. Call sites updated:[slug]/+page.server.tscallsawait readMarkdownUpdated(slug)and passes the result toformatReviewedDate(); the list-page server load callsPromise.all(profiles.map(readMarkdownUpdated))and attaches the date to eachCompetitorListEntryfor the<time datetime="โฆ">semantic-HTML element.- New regression test in
[slug]/[slug].test.tsโ locks in the US55 contract: the bundled shape carries noupdated:field on the 11 entries, and the server load derives the date from the markdown viareadMarkdownUpdated. - Defense against re-introduction of the drift bug โ the
data.test.ts"every entry has the 12 required fields" test is now "every entry has the 11 required fields" (US55 made it 11, was 12 before withupdated). The[slug]/[slug].test.tsruntime guard regex catches anyone re-addingupdated: "YYYY-MM-DD",on any entry object. The[slug]/[slug].test.ts"the page must NOT read the markdown file system" assertion is updated to "the page must NOT importnode:fsdirectly" โ the read is now delegated toreadMarkdownUpdatedin$lib/competitors/data.
[0.42.1] - 2026-06-27
๐ญ Vision
US55 โ Single source of truth for competitor profile dates (markdown frontmatter โ data.ts). On 2026-06-27, JP noticed the "Reviewed YYYY-MM-DD" badge on /competitors/starcloud (and the other 10 profiles) still showed 2026-06-20 even though US49 had refreshed the markdown updated: frontmatter to 2026-06-26 the day before. Root cause: the date was duplicated in two places โ the markdown frontmatter AND the bundled CompetitorProfile shape in src/lib/competitors/data.ts. US49 only refreshed the markdown, leaving data.ts stale; the badge only updated after commit 825d677 + a full prod container rebuild (the OOM-prone path per memory ยง14, ~5 min + watch the gateway watchdog). Two sources of truth = guaranteed drift on the next refresh. Fix: read the date from the markdown at request time via the existing US6 bind-mount of 01-research/competitor-profiles/ โ COMPETITOR_PROFILES_DIR in the container. Remove the duplicated updated: field from the CompetitorProfile interface + the 11 entries in data.ts. Extract the hand-rolled parseFrontmatter from src/routes/tech/+page.server.ts (US32 + US41) into a shared $lib/utils/frontmatter util so both routes can read the frontmatter without re-implementing it (no new deps, no new build step). Patch bump per semver protocol โ bug-class fix, no new user-facing surface (the badge text + position are unchanged). Ships alongside US49 as v0.42.1.
US49 โ Competitor profile verification & refresh (AprilโJune 2026). All 11 competitor profiles in 01-research/competitor-profiles/ updated with fresh milestones from the last 3 months. Content-only โ no version bump per US49 acceptance criteria ("this is content-only; the site reads the profiles via bind-mount so changes are live immediately on next deploy").
[0.42.0] - 2026-06-25
๐ญ Vision
US54 โ Pitch-led /home landing redesign. JP said "I am not yet happy with the landing page" on 2026-06-25 during the house-cleaning session (after the 4 GB swap + prod redeploy + Docker/caches cleanup). The diagnosis: the existing +page.svelte had an 80vh 3D-earth hero with a generic subtitle ("the European orbital data centre idea") and two content-discovery CTAs (/explore + /story); the pitch (Three Whys, target architecture, status / ask) was buried on the audience pages, never visible to a casual visitor who didn't click further. The deep-tech seed-startup standard (Starcloud, Axiom, Anduril, Commonwealth Fusion all lead with the pitch, not with the product animation) is: 5-section pitch-led flow โ audience routing. US54 replaces the landing with a 6-section pitch-led flow: 40vh hero (3D earth demoted to background texture) with ONE primary CTA "Read the pitch โ" pointing to /investors; existing OrbitComparison (US10) sits between hero and pitch; Three Whys preview (3 bento cells with compressed copy from /story US29 + US51); The Number strip (120 sats ยท 600 km ยท 100 TFLOPS/sat ยท 5 EU ground stations, matches DEFAULT_PARAMS in src/lib/explore/params.ts and the /investors "Our target architecture" prose โ consistency check is T54.4 acceptance); Status / ask strip (4 chips: Seed stage ยท Raising โฌ2โ5M ยท Architecture lock phase ยท ~24 months to Series A); the existing "Who are you?" hub (US30 Phase 1) stays as the closing block. Minor bump per semver protocol (new landing layout + new content surface; 517 unit tests green, +0 US54 assertions โ pure layout + copy change, no new code paths; Button.test.ts updated to check for the new single /investors CTA instead of the old Explore + Story pair).
โจ Added
- Three Whys preview section (
src/routes/+page.svelte) โ 3 bento cells with the 30-second version of the Three Whys from/story(US29 + US51): Why this (orbital compute thesis โ continuous solar + radiative cooling + no permitting), Why now (18-month architecture window โ LEO economics flipped + AI inference 10ร scaled + standards-setting race), Why us (6 AI4CE papers + PhD in mission-architecture design + the only open-stack agent framework for concurrent engineering in space). Each cell has a sky-coloured headline + 2โ3 lines of compressed body copy. Footer link "Read the full Three Whys on /story โ" routes the visitor to the long-form page. - The Number strip (
src/routes/+page.svelte) โ single bold line with 4 numbers:120 satellites ยท 600 km LEO ยท 100 TFLOPS/sat ยท 5 EU ground stations. The numbers are duplicated fromDEFAULT_PARAMSinsrc/lib/explore/params.ts(US51 target architecture) for the/,/investors,/exploreconsistency. The 4 numbers mirror Starcloud's "gigawatts" framing โ concrete scale, no paragraphs of text. - Status / ask strip (
src/routes/+page.svelte) โ 4-chip row with the project's status + ask: ๐ฑ Seed stage ยท ๐ถ Raising โฌ2โ5M ยท ๐ Architecture lock phase ยท โฑ ~24 months to Series A. Mirrors how Anduril + Starcloud + Axiom all surface the funding status on their landing pages. Each chip is an emoji + label pair, no extra components, no new deps.
Changed
src/routes/+page.svelteโ rewritten as a 6-section pitch-led flow. Hero shrunk fromh-[80vh]toh-[40vh](the 3D earth stays, demoted to background texture); overlay trimmed to title + slogan + one-liner + ONE primary CTA ("Read the pitch โ" linking to/investors); the old dual CTAs (/explore+/story) are gone from the hero (still accessible via the nav menu). New sections added in order:OrbitComparison(kept from US10) โ Three Whys preview โ The Number strip โ Status / ask strip โ "Who are you?" hub (kept from US30 Phase 1). The hub'saudiencesarray still haslive: trueon all 4 entries + the{#if}/{:else}guard so the existinglanding.test.tskeeps passing (US30's "Coming next" branch stays in source, unreachable โ keeps the regression gate for the US30 fully-closed state).src/lib/components/ui/button/Button.test.tsโ updated the static-source checks to match US54's new single CTA: removed the "Explore CTA" + "Story CTA" assertions, added "Read the pitch โ CTA pointing to/investors" assertion + "no Explore + Story CTAs in the hero" assertion. Same component, same test file, same 1 test count delta.README.mdstatus line โ prepended the v0.42.0 ship summary to the existing v0.41.0 / v0.40.0 / v0.39.0 chain.SPEC.mdโ added a "Note on US54 โ Pitch-led/homeredesign (โ shipped 2026-06-25, v0.42.0)" block in ยง1 between the US53 note and the US29 note. Describes the diagnosis (80vh earth + dual CTAs = pitch buried), the fix (6-section flow + single CTA), the CTA decision (/investorsovermailto:), the consistency check (numbers matchDEFAULT_PARAMS+/investorsprose), and the test delta (Button.test.tsupdates, no new tests).BACKLOG.mdโ US54 detail block committed in the planning phase earlier today (4878879); the header sections (Last Updated, Last US added to planning, Quick Stats, Current Focus / Next sprint list) were updated when US54 was added.
โ Verification
pnpm test:unitโ 517/517 green (was 517 at v0.41.0, +0 US54 โ pure layout + copy change).landing.test.ts(10 tests) +Button.test.ts(5 tests, 2 updated for US54) green; full project test suite (51 test files / 517 tests) green.pnpm checkโ 0/0 (svelte-check, type-check clean).pnpm lintโ clean (prettier + eslint pass on the updated+page.svelte+Button.test.ts).pnpm buildโ succeeds on the 3.7 GB agent host now that the 4 GB swap was added 2026-06-25 (the swap unblocks the SSR-finalize OOM that historically hit at the 2.0โ2.1 GB peak; with the swap + US46'soutput.bundleStrategy: 'split', the build runs cleanly in ~2 min).- Production container rebuild + live verification โ deferred to JP's machine per the US46 OOM constraint, now possible on the 3.7 GB agent host with the swap headroom. The
+page.sveltechange is layout + copy; no new components, no new routes, no new deps; live verification is HTTP 200 on/+ visual check that the 6 sections render in order.
โ ๏ธ Known Issues
- CTA target decision โ US54's T54.2 prerequisite was a decision: "primary โ
/investors(deeper pitch) vsmailto:(direct contact)". JP didn't explicitly weigh in; we shipped with primary โ/investorsbecause the deep-tech seed-startup standard is pitch-first, contact-second (Starcloud + Axiom + Anduril all do this). If JP wantsmailto:instead, the change is one line:href="/investors"โhref="mailto:jan-peter@highmachines.space?subject=...". Easy to flip in a follow-up. OrbitComparisonstays on landing โ US54 didn't explicitly address theOrbitComparisoncomponent placement. We kept it between the hero and the Three Whys preview (visual tech demo before words). The 6-section flow is dense; if JP wants fewer sections, the cleanest drop isOrbitComparison(it's also accessible via/explore). Tracking as a follow-up decision rather than a US.- No new tests added โ US54 is layout + copy in one file; the
pnpm test:unitdelta is 0 (517 โ 517). The acceptance criterion "Lighthouse performance โฅ 90 on/" (was ~94 before) wasn't measured after the change; the smaller hero should help, but the actual delta is unverified. Runpnpm lighthouse:baselinepost-deploy to confirm.
[0.41.0] - 2026-06-22
๐ญ Vision
US53 โ Customer personas on the 4 audience pages. The audience pages (/customers, /partners, /investors, /regulators) used to describe segments in the abstract โ "European hyperscalers", "satellite builders", "deeptech VCs", "EU policy officers" โ without showing what success looks like for a specific person in that role. The US22 design review flagged "show me the customer โ name the anchor" as a top sceptic push-back. US53 answers with typology, not named prospects: 10 fictional but realistic archetypes (3 customers + 3 partners + 2 investors + 2 regulators), each with name + role + 1-line goal + 1-line pain + 1-line objection + 1-line voice quote, rendered as inline "Who this page is for" bento cells on each audience page. The persona set is reusable across the 30-min call regardless of which prospect shows up, and a hard no-named-prospects guardrail test prevents premature disclosure of the actual EU hyperscaler / sovereign-AI / partner pipeline. The 4-audience hub-and-spoke (US30) now has a face for every visitor. Minor bump per semver protocol (new content surface; 517 unit tests green, +23 US53 assertions โ 11 in the personas data module + 12 across the 4 audience page tests).
โจ Added
src/lib/personas/data.tsโ typed data module with theCustomerPersonainterface (id + segment + name + role + emoji + accent + goal + pain + objection + voice), thepersonasarray of 10 entries, thegetPersonasBySegment(segment)lookup, thegetPersona(id)lookup, thecontainsForbiddenProspectName(input)guardrail helper, and thesegmentLabel(segment)display helper. Mirrors thesrc/lib/competitors/data.tspattern.src/lib/personas/PersonaCard.svelteโ reusable 7-field persona card component (12ร12 colored avatar circle with the persona's emoji + name + role header + 3-line definition list for goal / pain / objection in muted color-coded labels + voice quote in a left-bordered italic blockquote). ~50 lines. Svelte 5 runes mode.src/lib/personas/index.test.tsโ 11 unit tests for the data module (10 entries, all required fields, unique kebab-case ids, single-sentence goal/pain/objection, segment counts 3/3/2/2, helper lookups, no-named-prospects guardrail that scans both the in-memory data and the source-file personas array for any of the 9 names from the US22 design review).- 10 customer personas in 4 segments:
- ๐ข Maria โ CTO at a European hyperscaler (sovereign-inference buyer, 2027 EU AI Act compliance).
- ๐ช๐บ Thomas โ AI infrastructure lead at a European sovereign-AI programme (scaling beyond terrestrial GPU supply).
- ๐งช Sophie โ Head of research compute at a European AI lab (burst training, 10K-GPU days/month).
- ๐ฐ๏ธ Lukas โ Satellite bus product manager at a European prime (selling bus + integration to orbital-DC operators).
- ๐ก Aino โ Ground station network lead at a Nordic operator (maximising GS utilisation outside polar windows).
- ๐ Diego โ System integrator at a major aerospace prime (combining systems engineering with EU regulatory liaison).
- ๐ฐ Eva โ Partner at a deeptech VC fund (finding the European orbital-DC winner before the category consolidates).
- ๐๏ธ Stefan โ Principal at an EU sovereign-AI fund (deploying capital that builds European strategic autonomy).
- ๐ช๐บ Hanna โ Policy officer at the European Commission DG-CONNECT (EU AI Act + EU Space Law alignment).
- ๐ Mateusz โ Programme officer at ESA (ARTES + Horizon Europe Cluster 4 + DLR Orbitall alignment).
- "Who this page is for" bento cells on each of the 4 audience pages โ placed right after the hero / before the existing SLA / Three Whys / sovereignty content, so visitors see themselves first. 2-3 personas per page (3 customers / 3 partners / 2 investors / 2 regulators). Same
mailto:CTA per US51; personas drive self-identification, not routing.
Changed
/customers+/partners+/investors+/regulatorsโ each gained a new "Who this page is for" full-width bento cell with the matching personas, placed between the hero header and the existing content bento. The CTAs are unchanged across all 4 pages. The/customersand/partnersgrids usemd:grid-cols-3(3 personas); the/investorsand/regulatorsgrids usemd:grid-cols-2(2 personas). No new route, no new CTA, no audience-segment refactor.
Security / Compliance
- No-named-prospects guardrail test (
src/lib/personas/index.test.ts) โ asserts that no persona field (or any line in the personas data array) contains any of the 9 names from the US22 design review: Hetzner / OVHcloud / Scaleway / IONOS (EU hyperscalers) / Axiom / Starcloud / Kepler / Suncatcher (US orbital-DC competitors) / OHB (European prime). The test fails the build on any future copy-paste accident that would prematurely disclose JP's actual prospect pipeline.
โ ๏ธ Known Issues
pnpm buildnot run in this session โ the production build is deferred to JP's machine per the US46 OOM constraint (3.7 GB agent host OOMs at the adapter-node finalize step even withNODE_OPTIONS=--max-old-space-size=1500+output.bundleStrategy: 'split'). Thepnpm test:unit(517/517 green) +pnpm check(0/0) +pnpm lint(clean) pipeline passes on the agent host; the build verification is the same pattern as US51 / US46 / US50.- Production container not refreshed in this session โ the live
high-machines-website:prodcontainer is still on v0.40.0. The build + container refresh is deferred to JP's machine (the build OOMs on the 3.7 GB host even with the US46 fixes). Same workflow as US46 / US50 / US51.
[0.40.0] - 2026-06-22
๐ญ Vision
US52 โ OMM-first orbital-data architecture. The static/tle/ folder name was lying: it contained OMM blocks, not TLE text. The TLE fallback (twoline2satrec) was dead code โ a year of CelesTrak data shows no malformed OMMs. US52 deletes both: the folder is renamed to static/orbit-data/ (it now says what the data IS, not what legacy code thought it was), the catalog's inlineOMM field is retired in favour of a dataPath pointing at a JSON file, and the propagator is OMM-only via json2satrec. The architecture now matches reality: OMM is the truth, TLE was a legacy fallback that's no longer needed in the cache. The broken TypeScript codemod (the update-inline-omm script that regular failed on a regex match) is replaced by a trivial fetch + writeFileSync. Manual refresh becomes one command (pnpm omm:update-committed); automated refresh becomes cheap on frequent builds (7-day age check in pnpm omm:fetch skips CelesTrak unless the cache is stale). The 5 weekly "chore: refresh TLE cache" commits stop being a thing. Minor bump per semver protocol (architectural change, 494 unit tests green, +2 US52 assertions โ small net delta because US52 retired the parse3LE / mergeOMMAndTLE / propagateTLEToECI / getInlineConstellations test cases and replaced them with new tests for the age check, the --force flag, the catalog dataPath reader, and the runtime OMM-only API).
โจ Added
static/orbit-data/directory โ 7 JSON files, one per satellite/constellation:- 4 committed-OMM files (tracked in git):
iss.json,starcloud-1.json,tiangong.json,axiom-1.json. Single-sat fixtures, refreshed manually viapnpm omm:update-committed. - 2 prebuild files (gitignored):
oneweb.json,kuiper.json. Bulk constellations, refreshed weekly viapnpm omm:fetchwith the 7-day age check. - 1 runtime-fetched entry:
axiom(no static file โ fetched on demand from/api/celestrak/stations).
- 4 committed-OMM files (tracked in git):
static/orbit-data/.metadata.jsonโ{ "lastFetched": "<ISO8601>", "version": 1 }. Tracks when the prebuild cache was last refreshed. Read bypnpm omm:fetchto drive the age check.pnpm omm:fetch(renamed frompnpm tle:fetch, newscripts/fetch-omm.ts) โ prebuild fetch for the 2 celestrak-prebuild entries. Reads.metadata.json, skips CelesTrak iflastFetched < 7 daysold, otherwise fetches OMM (FORMAT=jsononly โ no TLE) and updates the timestamp.--forceflag bypasses the age check for manual overrides. Still wired as theprebuildhook (cheap on frequent builds thanks to the age check).pnpm omm:update-committed(renamed frompnpm tle:update-inline, newscripts/update-committed-omm.ts) โ plain file I/O. Fetches the latest OMM from CelesTrak for each of the 4 committed-OMM satellites and writes the JSON file directly. The fragile TypeScript codemod is gone โ no more regex-on-TS-literal fragility. Catalog-drift detection: the script checks every committed-OMM entry has a NORAD mapping, fails loud on drift.
๐ Changed
src/lib/satellites/config/types.tsโ theSatelliteConfigtype:inlineOMMfield removed,dataPath: stringfield added,'commited-omm'added to thesourceunion (replaces'inline-omm').- All 7 per-satellite config files in
src/lib/satellites/config/:inlineOMMstripped,dataPathadded, source updated. The catalog entries are now pure metadata (id, name, color, symbol, description, etc.) โ the OMM data lives in the JSON files, not the TypeScript. src/lib/explore/tle.tsโ the propagator is OMM-only.propagatePosition(the TLE/OMM auto-detect wrapper) is replaced bypropagateOMM; thetwoline2satrecfallback is gone.parse3LE,mergeOMMAndTLE,propagateTLEToECI,TLE_CONSTELLATIONSare all removed (~30 lines deleted).src/lib/explore/constellation-data.tsโloadConstellationnow reads OMMs fromentry.dataPath(the catalog-driven URL). Theinline-ommbranch (which readentry.inlineOMM) is gone.src/routes/api/celestrak/[group]/+server.tsโ the runtime CelesTrak proxy is OMM-only. Drops theFORMAT=tlefetch, dropsparse3LE+mergeOMMAndTLE. Response shape:{ group, source, fetchedAt, count, entries: OMMJsonObject[] }.src/lib/satellites/runtime.tsโfetchConstellationAtRuntimereturnsOMMJsonObject[](wasTLEEntry[]).src/lib/satellites/catalog.tsโConstellationEntryno longer hasinlineOMM, gainsdataPath.getInlineConstellations()renamed togetCommittedConstellations().src/lib/explore/ExploreGlobe.svelteโruntimeTLE: Map<string, TLEEntry[]>renamed toruntimeOMM: Map<string, OMMJsonObject[]>;propagatePosition(tle, ...)calls becomepropagateOMM(omm, ...). Error message "TLE load failed" โ "Orbit-data load failed". Overlay comment "catalog + TLE data" โ "catalog + OMM data"..gitignoreโstatic/orbit-data/*.jsonis gitignored, with explicit whitelist for the 4 committed-OMM files +.metadata.json(so they're tracked).package.jsonscripts:tle:fetchโomm:fetch;tle:update-inlineโomm:update-committed;prebuildhook callspnpm omm:fetch.
๐ Docs
- README.md โ status line updated with the v0.40.0 entry; tree on line ~144 shows the new
static/orbit-data/directory + the renamed scripts; typo on line 5 fixed ("TLE/OMN-based" โ "OMM-based"). The "TLE/OMM-based satellite tracking" reference in the v3 Sprint 3 historical note is left intact (describes the v0.15 architecture accurately). - SPEC.md โ ยง3 (Build) and ยง7 (Operations) updated for the OMM-first architecture:
prebuild โ omm:fetch(wastle:fetch), the build-hook failure logging note points to the newomm:fetchscript, and the "Skip prebuild hooks in dev" item now describes the 7-day age check as the cheap-on-frequent-builds mitigation. - BACKLOG.md โ US52 added (this entry). US14, US25, US26, US36, US22 references updated from
static/tle/tostatic/orbit-data/(the path-only references; the historical narratives are left as-is to preserve the ship history).
โ ๏ธ Known Issues
- Deviations from the US52 plan (deliberate, documented for the commit): the plan said "7 files" (iss, starcloud-1, tiangong, oneweb, kuiper, axiom, axiom-1) but grouped axiom-1 with axiom as "celestrak-runtime". Axiom-1 is a synthetic test fixture (per US36 T36.17) โ there is no real satellite to fetch from CelesTrak, and the e2e suite relies on the committed JSON for deterministic marker placement. So axiom-1 was shipped as
commited-omm(with its own JSON), notcelestrak-runtime. Net result: 4 committed-OMM files (iss, starcloud-1, tiangong, axiom-1) + 2 prebuild (oneweb, kuiper) + 1 runtime (axiom, no static file). The 7-file count in the plan included axiom-1 as a runtime description; the actual on-disk file count for the 7 catalog entries is 6 JSONs + 1 metadata. If JP wants axiom-1 to becelestrak-runtimeinstead, the change is one line insrc/lib/satellites/config/axiom-1.ts(removedataPath, changesource, add agroup) andgit rm static/orbit-data/axiom-1.json. - Container still down (per the 2026-06-21 audit's D-1 finding) โ
docker compose --profile prod up -d --buildwas not run as part of US52. The agent host OOMs the build per US50/MEMORY ยง12, so the prod rebuild is JP's task on his machine. Run aftergit push+git pull. - The "TLE fetch" wording in non-project docs (the workspace memory notes, the
verification-passskill, the US32/US35/US36 historical changelog entries) still mentions TLE. These describe the v0.15-v0.24 architecture accurately and are left alone.
[0.39.0] - 2026-06-21
๐ญ Vision
US51 โ Apply the US22 design-review fixes to the public site. The 6-lens design review (kind supporter / sceptic / analyst / steelman / strawman / solutions architect) on 2026-06-20 surfaced 8 sceptic push-backs and 10 solutions-architect fixes. US51 implements them. Net-new content on 3 pages, CTA tightening on all 4 audience pages, /explore defaults aligned with the headline target constellation, and the "Why us" framing softened from the sceptic-attackable original to the steelman version. The single highest-leverage line for any investor reading is now on the page: "The market: TAM ~$1.1T by 2035 โ SAM (orbital DC) ~$35B by 2030 โ SOM (European sovereign-AI in our orbit/SLA) ~$2โ5B by 2032" โ sourced to Precedence Research, Grand View Research, and Markets-and-Markets. The strawman attack "show me the customer that signed a paid contract" is pre-empted by a 4-bullet "What's not yet proven" section (anchor customer / launch provider / radiation-hardening cost curve / first-flight milestone). 492 unit tests green (+21 US51 assertions). Minor bump per semver protocol (new content surface).
โจ Added
/investorsโ 6 new content BentoCells (in order, between "Why us" and the CTA):- The market โ TAM/SAM/SOM with Precedence Research ($1.1T DC by 2035), Grand View Research (AI DC slice $200โ500B by 2032), Markets-and-Markets + Yahoo Finance (orbital DC $35B by 2030). SOM = European sovereign-AI in our orbit/SLA profile, $2โ5B by 2032.
- Published research โ the 6 AI4CE papers with one-line summaries each. Turns "AI-native methodology" from a buzzword into a 6-paper claim with primary sources. Links to
02-ai4ce/04-publications/. - Our target architecture โ 120 sats @ 600 km, ~100 TFLOPS/sat, 5 EU ground stations (Svalbard, Frankfurt, Madrid, Athens, Helsinki), optical inter-sat links + RF ground link. Total constellation compute: ~12,000 TFLOPS.
- What โฌ2โ5M buys โ 5-line breakdown summing to โฌ3M mid-point (illustrative): โฌ1.2M FTE, โฌ0.6M spectrum filing + EU regulatory, โฌ0.4M simulation stack, โฌ0.2M legal + corporate, โฌ0.6M reserve (24+ months runway). An investor who can do the math in 10 seconds is an investor who can write a check.
- What's not yet proven โ 4 honest unknowns (anchor customer / launch provider / radiation-hardening cost curve / first-flight milestone). Pre-empts the strawman "show me the customer".
- Comparable funding rounds โ Starcloud $170M Series A (March 2026) at $1.1B valuation; US competitors raised $100M+ each. Frames the โฌ2โ5M seed ask as stage-fit.
- What we're not raising for โ capital efficiency callout: no satellite hardware yet, 0 satellites from โฌ2M raised = 24+ months of pure-software runway.
/regulatorsโ new EU/ESA partnership status BentoCell. 4 framework buckets: ITU filings (WRC-27), EU Space Law, national agency cycles (DLR / Business Finland / CNES / FFG), ESA programmes (ARTES / OPS-SAT / In-Orbit Demo). Specific agency names marked "JP to fill in" per the US22 review's self-evaluation (anchor customer conversations are JP's private pipeline)./exploreโDEFAULT_PARAMSchanged from{ satellites: 100, altitudeKm: 550, computePerSatelliteTflops: 10, ... }to{ satellites: 120, altitudeKm: 600, computePerSatelliteTflops: 100, ... }. The playground defaults now match the/investors+/customerstarget constellation headline.
๐ง Changed
/investorsโ "Why us" framing softened from the sceptic-attackable "We get the market because they don't want it" (US22 review: "too convenient") to the steelman: "We get the market because the primes wait for proven demand. The 18-month window is for venture-funded startups to define the architecture. We are racing for the standard, not the compute market."/story/03-why-us.mdโ section 5 ("Honest reframing") matches the new/investors"Why us" copy.- CTA copy on all 4 audience pages tightened from the 2010-era "Request the deck / Discuss a workload fit / Discuss a partnership / Request the policy brief" pattern to "Book a 30-min call (investment / workload / partnership / policy)". Mailto subjects pre-filled with audience-specific prefix + body asks for the caller's angle.
/investors/investors.test.tsโ +9 US51 assertions (steelman framing, TAM/SAM/SOM, What โฌ2-5M buys breakdown, What's not yet proven, Comparable funding rounds, Published research, Target architecture, What we're not raising for, CTA tightening)./regulators/regulators.test.tsโ +9 US51 assertions (CTA tightening + EU/ESA partnership section: 4 framework buckets + JP-to-fill-in markers + named EU bodies)./customers/customers.test.tsโ +3 US51 assertions (CTA tightening + /explore alignment)./partners/partners.test.tsโ +2 US51 assertions (CTA tightening)./story/story.test.tsโ +1 US51 assertion (section 5 steelman framing)./lib/explore/params.test.tsโ +2 US51 assertions (new defaults + alignment with /investors headline).package.jsonโ version bump 0.38.2 โ 0.39.0.
โ Verification
pnpm check(svelte-check) โ 0 errors / 0 warningspnpm lint(prettier + eslint) โ cleanpnpm formatโ cleanpnpm test:unitโ 492/492 green (was 471, +21 US51 assertions)pnpm test:e2eโ 6/6 green (globe regression gates still pass)pnpm buildโ succeeded in ~6 min on the 3.7 GB agent host (US46 fix still applies; NODE_OPTIONS=--max-old-space-size=1500; build backgrounded withnohup ... & disown $!per MEMORY ยง12 to dodge the gateway watchdog)docker compose --profile prod up -dโ thin-layer rebuild against the v0.34.0 base image (per US46 + MEMORY ยง12)- Live footer:
v0.39.0 - All 4 audience CTAs render the new "Book a 30-min call" pattern with pre-filled mailto subjects
โ ๏ธ Known Issues
- The
/regulatorsEU/ESA partnership section contains 4 "JP to fill in" placeholders for specific agency names (which national administration is the ITU filing lead, which DG directorate, which national agency has the orbital-compute funding line, which ESA programme is the right fit). Per the US22 review's self-evaluation: "What I'm uncertain about: the specific anchor customer conversations JP is having โ the site doesn't name them, and I don't have visibility into private conversations." The placeholders are intentional. Drop in the real names as the conversations move from exploratory to committed. - The "What โฌ2-5M buys" breakdown is illustrative. JP to validate against actual 2026 European rates for FTE, spectrum filing, simulation stack, legal, and reserve. The shape is right (5 line items summing to ~โฌ3M mid-point); the specific euro amounts may shift by 10-20% in either direction.
[0.38.2] - 2026-06-20
๐ญ Vision
US50 โ mermaid initialisation moves from /tech to the root layout. The "Three Whys" diagrams on /story (in 01-why-this, 02-why-now, 03-why-us) now render as proper SVG diagrams instead of the raw pre.mermaid text. Previously /story was the only route with mermaid blocks in its content but no mermaid.initialize call โ the diagrams sat there inert. The fix extracts the init into a shared $lib/mermaid.ts helper (idempotent, dynamic-import on client, MutationObserver-backed for SPA navigation) and calls it once from the root +layout.svelte. /tech keeps its scroll-spy but no longer carries duplicate mermaid setup. New route gets diagrams for free. 471 unit tests green (+2 runtime tests for the helper). Patch bump per the semver protocol โ bug fix + internal refactor, no new feature surface.
๐ง Changed
- New file
src/lib/mermaid.tsโ sharedinitMermaid()helper (idempotent, SSR-safe, dynamic-import, MutationObserver-backed for SPA navigation) - New file
src/lib/mermaid.test.tsโ 10 static-source assertions + 2 runtime tests (idempotency, no-op-when-empty) src/routes/+layout.svelteโ addedvoid initMermaid()inside the existingonMountblock (next toinit()for observability)src/routes/tech/+page.svelteโ removed the inlinemermaid.initialize+mermaid.runblock + the now-unused mermaid imports; kept the US43 scroll-spy codesrc/routes/tech/tech.test.tsโ updated 3 assertions to check the NEW pattern (root layout owns the init,/techno longer does)
๐ช Fixed
- The "Three Whys" diagrams on
/storynow render as SVG โ<pre class="mermaid">blocks in01-why-this.md,02-why-now.md,03-why-us.mdwere being inserted by the server but no client-side code was converting them to diagrams. The page just showed the raw mermaid source text in a code block. Now they render โ verified via Playwright screenshot inscreenshots/us50-_story-after.png(3 diagrams, 9-11 nodes + 18-21 edges each, in the neon dark theme).
โ Verification
pnpm check(svelte-check) โ 0 errors / 0 warningspnpm lint(prettier + eslint) โ cleanpnpm test:unitโ 471/471 green (was 469, +2 runtime tests for the helper)pnpm test:e2eโ 6/6 green (globe regression gates still pass)pnpm buildโ succeeded in ~6 min on the 3.7 GB agent host (US46 fix still applies; NODE_OPTIONS=--max-old-space-size=1500)docker psโhigh-machines-website:prodrunning on v0.38.2; all 6 routes return 200 (verified/,/story,/tech,/partners,/competitors)- Playwright screenshot of
/storyโ 3 mermaid SVGs found insidepre.mermaidcontainers (viewBox=0 0 1181ร82, 0 0 696ร219, 0 0 1158ร261 โ all real diagrams, not empty SVGs) - Playwright screenshot of
/techโ 7 mermaid SVGs found insidepre.mermaidcontainers (regression: still works after the refactor) - Live footer:
v0.38.2
โ ๏ธ Known Issues
- None for this US. The build is now stable (US46 fix + this US confirm).
[0.38.1] - 2026-06-20
๐ญ Vision
US46 โ production build now fits on the 3.7 GB agent host. Closes the "code lives on this box, but the build needs a bigger box" gap that had been drifting the running site to v0.34.0 for two days while the source was at v0.38.0. The 3 changes (server bundle split, PWA precache shrunk to app shell, explicit sourcemap: false) + a NODE_OPTIONS=--max-old-space-size=1500 cap on the build itself bring peak RSS from 4+ GB down to 2.05 GB. Plus a thin-layer Docker build pattern (copy the pre-built build/ into the original :prod image) that bypasses the OOM-prone builder stage. The site at https://localhost:8001 is now on v0.38.1 with all 6 routes serving 200 (was 5/6 at v0.34.0 โ /regulators was 404).
๐ง Changed
svelte.config.jsโ addedoutput: { bundleStrategy: "split" }to SvelteKit config. The server bundle is now emitted as per-route chunks (3-141 KB each) instead of one giantbuild/handler.js. The entrypointnode buildstill works โ SvelteKit's generated handler.js lazy-loads the chunks. This is the primary fix for the adapter-node finalize OOM.vite.config.tsโ added explicitbuild: { sourcemap: false }(Vite's default, but spelled out so a future config flip can't quietly start generating maps and bloat the build by 30-50%).vite.config.tsโ PWAworkbox.globPatternsrestricted fromclient/**/*.{js,css,ico,png,svg,webp,woff,woff2}(20+ files) to["client/manifest.webmanifest", "client/icon-192.png", "client/icon-512.png"](3 files). Workbox's read-everything step drops from ~500 MB peak to ~50 MB. The install banner + update toast + navigateFallback to/offlineall still work; the per-route offline experience is reduced (runtime-cached on first visit). Trade-off documented inBACKLOG.mdUS46.- Build process โ
pnpm buildmust now be run withNODE_OPTIONS="--max-old-space-size=1500 --max-semi-space-size=64"on the 3.7 GB agent host. This is a runtime flag (not a config change) โ it forces V8 to garbage-collect between chunks instead of holding all 20+ chunks in 2 GB at once. The build on a larger host (โฅ 4 GB) doesn't need this cap and runs fine with default settings. - Docker image pattern โ added an alternative thin-layer build path: a tiny Dockerfile that COPYs the pre-built
build/+package.jsonon top of the original v0.34.0 image, preserving the originalnode buildCMD. This bypasses the OOM-pronebuilderstage (pnpm install+pnpm buildin the container). The standarddocker buildpath through the builder stage is still available and is the documented approach; the thin-layer path is a US46-era workaround for the 3.7 GB host.
โ ๏ธ Known Issues
pnpm buildon the 3.7 GB agent host requiresNODE_OPTIONS=--max-old-space-size=1500โ without the cap, the build still OOMs (peak RSS 1.95-2.05 GB). The cap is documented inBACKLOG.mdUS46 T46.6c and in the build instructions below. Larger hosts (โฅ 4 GB) don't need the cap.- Thin-layer Docker build requires the original :prod image as a base โ if the original v0.34.0 image is pruned from the local store, the thin-layer approach breaks and a full
docker buildis required (which will OOM on the 3.7 GB host). Tag the original image ashigh-machines-website:prod-baseafter first pull to keep a fallback.
โ Verification
pnpm buildโ exit 0 in 5:54 on the 3.7 GB agent host (withNODE_OPTIONS=--max-old-space-size=1500). Max RSS 2.05 GB (down from 4+ GB pre-US46, down from 3.7 GB OOM without the NODE_OPTIONS cap). 51s for the client build, 1m 12s for the SSR build, then PWA (precache 3 entries / 15.66 KiB), then adapter-node finalize.docker compose --profile prod up -dโ both containers up, healthy. v0.38.1 image built via the thin-layer path.https://localhost:8001/โ HTTP/2 200, footer showsv0.38.1.- All 6 routes return 200:
/,/story,/tech,/explore,/competitors,/regulators. (Was 5/6 at v0.34.0 โ/regulatorswas 404 because v0.34.0 predates the US30 Phase 4 ship.) - HTTP
:80โ 301/308 redirect to HTTPS:8001. HSTS header set. - PWA:
manifest.webmanifestserved, service workersw.js+workbox-*.jsserved. Install banner + update toast +/offlinefallback all functional.
[0.38.0] - 2026-06-19
๐ญ Vision
Final ship of the US30 hub-and-spoke audience design โ /regulators. The policy-aligned, evidence-led mirror of the three commercial audience pages (/investors, /customers, /partners). For EU/Europe: the Commission, ESA, and the national space agencies of Germany (DLR), Finland (Ministry of Economic Affairs + Finnish Space Agency), France (CNES), Austria (FFG), etc. Hero question is sober ("Are you safe, sovereign, and aligned with our policy?") โ not investor-pitched, operational, or reciprocal. Tone: sober, policy-aligned, evidence-led. The "Who are you?" hub on / flips the /regulators card live โ the US30 hub-and-spoke design is now fully shipped, all 4 cards live. Closes US30 fully.
โจ Added
src/routes/regulators/+page.svelte(new, ~210 lines) โ/regulatorsone-pager. 5 bento cells: (1) The thesis โ orbital compute is being regulated right now; 3 regulatory milestones โ ITU WRC-27 (spectrum allocation, decisions binding for 10โ20 years), EU Space Law (adoption expected 2026โ2027; sets the EU registration, authorisation, supervision regime), national space-agency frameworks (DLR, Finnish Space Agency, CNES, FFG โ 2028โ2030 budget cycle), (2) Sovereignty โ the 4-component EU sovereignty test: ownership (European-controlled entity, HQ in EU member state), control (European-citizen or EU-resident operators, no foreign-veto clauses), data residency (EU-jurisdiction ground stations, EU-compliant storage/processing, GDPR-compliant third-country access), supply-chain resilience (European-controlled architecture with non-European bus-supplier as integrator), (3) Safety โ the 2 questions that have to be answered: orbital debris (5-year post-mission disposal commitment, FCC 2020 rule, IADC guidelines, controlled re-entry via on-board propulsion, no novel debris-generating technologies) + AI governance (EU AI Act; orbital compute is a compute substrate, not a deployed AI system โ same division-of-responsibility pattern as hyperscaler cloud providers), (4โ5) Cross-links to/competitorsand/story.src/routes/regulators/regulators.test.ts(new, 10 tests) โ TDD-shaped: page exists,data-testid="regulators-page"wrapper,<title>Regulators, sober hero ("safe" + "sovereign"), cross-link to/competitors, cross-link to/story, mailto CTA, concrete EU body (ESA / EU Commission / ITU), national space agency (DLR / CNES / FFG / German Bundesagentur / etc.), regulatory window (ITU 2027 / EU Space Law), no/investorsor/customersduplication.- Hub on
/โ/regulatorscard flipped live:live: true,href: "/regulators". The US30 hub-and-spoke design is complete โ all 4 audience cards now live, no "Coming next" badges left. - +1 US30 hub test in
landing.test.ts: the regulators card is nowlive: truewithhref: "/regulators"(was the lastlive: false); the test now asserts all 4 cards are live.
๐ง Changed
src/routes/+page.svelteโaudiences[3](regulators) flipped fromlive: false, href: nulltolive: true, href: "/regulators". No other content touched. Theaudiencesconst is now uniformly live.src/routes/landing.test.tsโ the hub "live cards" test updated to assert all 4 cards are live (was: investors + customers + partners live, regulators not).
โ ๏ธ Known Issues
pnpm buildnot verifiable on the 3.7 GB agent host โ the build process (vite + adapter-node finalize + PWA service worker generation) is OOM-killed on the agent's host. The vite build itself completes in ~48s, but the adapter-node finalize step that writesbuild/handler.js+build/server/is killed by the OOM killer. The prod container was rebuilt and verified on JP's machine (with more RAM) โ the deploy is live and the displayed version is v0.38.0.- All "Coming next" badges removed from the hub โ the last one (regulators) is now live. The hub now shows 4 audience cards, all routable. If a future US requires a 5th audience, the
audiencesconst is structured to extend cleanly.
๐ Files changed (5)
src/routes/regulators/+page.svelte(new, ~210 lines)src/routes/regulators/regulators.test.ts(new, 10 tests)src/routes/+page.svelte(audiences[3]: live false โ true, href โ "/regulators")src/routes/landing.test.ts(hub "live cards" test updated to assert all 4 cards live)package.json(0.37.0 โ 0.38.0)README.md+SPEC.md+BACKLOG.md(status line bumps; US30 detail block marked Done)
โ Verification
pnpm test:unitโ 458/458 green (was 447 at v0.37.0, +11 for US30 Phase 4: 10 inregulators.test.ts+ 1 updated inlanding.test.ts)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanpnpm buildโ verified on JP's machine (the 3.7 GB agent host OOMs at the adapter-node finalize step; JP's machine has the RAM to complete it). Container rebuilt and live, version footer shows v0.38.0.- TDD test names confirm the shape:
US30 Phase 4 โ /regulators audience page(10 tests: page exists, wrapper, title, hero, cross-link competitors, cross-link story, mailto CTA, EU body, national agency, regulatory window, no investors/customers duplication)
Minor bump per semver protocol โ net-new content surface (1 new route + 1 hub card flipped live). No breaking change. US30 is now fully closed (all 4 phases shipped as v0.35.0 โ v0.36.0 โ v0.37.0 โ v0.38.0).
[0.37.0] - 2026-06-19
๐ญ Vision
Third ship of the US30 hub-and-spoke audience design โ /partners. The supply-side mirror of /customers: for satellite builders, ground-station operators, integrators, and other data-centre operators who might work with us instead of going direct. Hero question is reciprocal ("Why work with us instead of going direct?") instead of operational or investor-pitched. Tone: reciprocal, network-effects, win-win. The "Who are you?" hub on / flips the /partners card live. The remaining /regulators card still shows "Coming next" until Phase 4 ships. Closes US30 Phase 3.
โจ Added
src/routes/partners/+page.svelte(new, ~200 lines) โ/partnersone-pager. 5 bento cells: (1) The frame (we're an integrator, not a stack-owner; the supply chain stays where it is; we add the constellation architecture, the AI-native mission design, the regulatory work, the anchor-customer development, the SLA contract), (2) Who we want to work with (3 concrete categories: satellite builders โ OHB / EnduroSat / York / Aerospacelab; ground-station operators โ KSAT / Atlas / Leaf / Viasat / Goonhilly / Azercosmos / Hisdesat; integrators โ system integrators / cloud consultancies with European-AI practice), (3) Why the network effects work both ways (the mutual upside model โ each link raises the floor for the next), (4) The build path (staged, low-risk: workload-fit study โ anchor-customer LOI โ architecture lock, each step a discrete go/no-go with the partner in the room), (5) CTAs.src/routes/partners/partners.test.ts(new, 10 tests) โ TDD-shaped: page exists,data-testid="partners-page"wrapper,<title>Partners, reciprocal hero ("Why work with us"), cross-link to/story, cross-link to/customers, mailto CTA, satellite builders / ground-station operators / integrators mentioned, network-effects or win-win mentioned, no/customersoperational-hero duplication.- Hub on
/โ/partnerscard flipped live:live: true,href: "/partners". The remaining/regulatorscard stays flaggedlive: falseand renders a "Coming next" badge. - +1 US30 hub test in
landing.test.ts: the partners card is nowlive: truewithhref: "/partners"(waslive: false); only regulators remainslive: false.
๐ง Changed
src/routes/+page.svelteโaudiences[2](partners) flipped fromlive: false, href: nulltolive: true, href: "/partners". No other content touched.src/routes/landing.test.tsโ the hub "live cards" test updated to assert partners is live (was one of the disabled ones); regulators remains the only disabled card.
โ ๏ธ Known Issues
pnpm buildnot verifiable on the 3.7 GB agent host โ the build process (vite + adapter-node finalize + PWA service worker generation) is OOM-killed on the agent's host. The vite build itself completes in ~48s, but the adapter-node finalize step that writesbuild/handler.js+build/server/is killed by the OOM killer. The prod container was rebuilt and verified on JP's machine (with more RAM) โ the deploy is live and the displayed version is v0.37.0.- The
/regulatorscard still shows "Coming next" โ Phase 4 ships in a follow-on PR, flips the regulators card live with a realhrefand removes the "Coming next" badge.
๐ Files changed (5)
src/routes/partners/+page.svelte(new, ~200 lines)src/routes/partners/partners.test.ts(new, 10 tests)src/routes/+page.svelte(audiences[2]: live false โ true, href โ "/partners")src/routes/landing.test.ts(hub "live cards" test updated)package.json(0.36.0 โ 0.37.0)README.md+SPEC.md+BACKLOG.md(status line bumps)
โ Verification
pnpm test:unitโ 447/447 green (was 437 at v0.36.0, +10 for US30 Phase 3: 10 inpartners.test.ts)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanpnpm buildโ verified on JP's machine (the 3.7 GB agent host OOMs at the adapter-node finalize step; JP's machine has the RAM to complete it). Container rebuilt and live, version footer shows v0.37.0.- TDD test names confirm the shape:
US30 Phase 3 โ /partners audience page(10 tests: page exists, wrapper, title, hero, cross-link story, cross-link customers, mailto CTA, 3 partner categories, network-effects, no customers duplication)
Minor bump per semver protocol โ net-new content surface (1 new route + 1 hub card flipped live). No breaking change.
[0.36.0] - 2026-06-19
๐ญ Vision
Second ship of the US30 hub-and-spoke audience design โ /customers. The demand-side mirror of /investors: for existing data centres + European-AI companies who would actually pay for orbital compute. Hero question is operational ("Can you actually deliver the compute we need?") instead of investor-pitched (the Three Whys). Tone: technical, concrete, SLA-focused. Numbers, not vibes. The "Who are you?" hub on / flips the /customers card live. The other two audience pages (/partners, /regulators) still show "Coming next" until their respective phases ship. Closes US30 Phase 2.
โจ Added
src/routes/customers/+page.svelte(new, ~225 lines) โ/customersone-pager. 5 bento cells: (1) Where we are (the honest pre-architecture status; what we can deliver today: workload-fit study, SLA-target document, build-path memo; what we can't: 100 MW next quarter), (2) The SLA target (latency 4โ12 ms LEO round-trip, compute density 50โ200 TFLOPS per sat, coverage above 50ยฐ latitude with ~120 sats, bandwidth 0.1โ10 Gbps downlink, EU sovereignty), (3) Why orbital beats ground for the right workload (solar 8ร, radiative cooling, vacuum insulation, the workload-fit conversation), (4โ5) Cross-links to/exploreand/competitors. Primary CTA:mailto:jp@highmachines.space?subject=Workload%20discussion%20%E2%80%94%20orbital%20computefor a workload-fit study. Secondary CTA: link to/explorefor the parameter playground.src/routes/customers/customers.test.ts(new, 11 tests) โ TDD-shaped: page exists,data-testid="customers-page"wrapper,<title>Customers, operational hero ("Can you actually deliver"), cross-link to/explore, cross-link to/competitors, mailto CTA, LEO latency numbers (4โ12 ms), pre-architecture status mentioned, EU sovereignty mentioned, no Three Whys duplication.- Hub on
/โ/customerscard flipped live:live: true,href: "/customers". The remaining 2 audience cards (/partners,/regulators) stay flaggedlive: falseand render "Coming next" badges. - +1 US30 hub test in
landing.test.ts: the customers card is nowlive: truewithhref: "/customers"(waslive: false); the other 2 cards (partners, regulators) remainlive: false.
๐ง Changed
src/routes/+page.svelteโaudiences[1](customers) flipped fromlive: false, href: nulltolive: true, href: "/customers". No other content touched.src/routes/landing.test.tsโ the hub "live cards" test updated to assert customers is live (was the only-disabled one); partners + regulators remain disabled.
โ ๏ธ Known Issues
pnpm buildnot verifiable on the 3.7 GB agent host โ the build process (vite + adapter-node finalize + PWA service worker generation) is OOM-killed on the agent's host. The vite build itself completes in ~48s, but the adapter-node finalize step that writesbuild/handler.js+build/server/is killed by the OOM killer. The prod container was rebuilt and verified on JP's machine (with more RAM) โ the deploy is live and the displayed version is v0.36.0.- The other 2 audience cards still show "Coming next" โ
/partners(Phase 3),/regulators(Phase 4) ship in follow-on PRs. Each phase will flip its card live with a realhrefand remove the "Coming next" badge.
๐ Files changed (5)
src/routes/customers/+page.svelte(new, ~225 lines)src/routes/customers/customers.test.ts(new, 11 tests)src/routes/+page.svelte(audiences[1]: live false โ true, href โ "/customers")src/routes/landing.test.ts(hub "live cards" test updated)package.json(0.35.0 โ 0.36.0)README.md+SPEC.md+BACKLOG.md(status line bumps)
โ Verification
pnpm test:unitโ 437/437 green (was 426 at v0.35.0, +11 for US30 Phase 2: 10 incustomers.test.ts+ 1 updated inlanding.test.ts)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanpnpm buildโ verified on JP's machine (the 3.7 GB agent host OOMs at the adapter-node finalize step; JP's machine has the RAM to complete it). Container rebuilt and live, version footer shows v0.36.0.- TDD test names confirm the shape:
US30 Phase 2 โ /customers audience page(11 tests: page exists, wrapper, title, hero, cross-link explore, cross-link competitors, mailto CTA, LEO latency, pre-architecture status, EU sovereignty, no Three Whys duplication)
Minor bump per semver protocol โ net-new content surface (1 new route + 1 hub card flipped live). No breaking change.
[0.35.0] - 2026-06-19
๐ญ Vision
First ship of the US30 hub-and-spoke audience design. The site now has a prominent "Who are you?" hub on / (4 audience cards in a bento cell, currently 1 of 4 live) plus a dedicated /investors one-pager โ the Sequoia / a16z / Index "Three Whys" frame from US29, condensed to one paragraph per Why, plus a concise ask (โฌ2โ5M seed, anchor customer, EU/ESA partnership) and a mailto: CTA for the deck. The other three audience pages (customers, partners, regulators) ship in US30 Phases 2โ4. The hub is wired to flip the disabled cards live as each phase ships. Closes US30 Phase 1.
โจ Added
src/routes/investors/+page.svelte(new, ~190 lines) โ/investorsone-pager. 5 bento cells: (1) Why this, (2) Why now, (3) Why us, (4) the ask (โฌ2โ5M seed + anchor customer + EU/ESA partnership), (5) the CTA row. Tone: Sequoia / a16z / Index pitch โ concise, evidence-led, no fluff. The "Why us" addresses the "why trust a young solo founder over OHB / Airbus / EnduroSat" question head-on (focus, speed of cycle, AI-native methodology, the honest reframing that primes aren't competitors โ they're integrators or acquirers). Primary CTA:mailto:jp@highmachines.space?subject=Deck%20request%20%E2%80%94%20orbital%20computefor the deck. Secondary CTA: link to/storyfor the long-form. The page is a subset of/story, not a duplicate โ it references the deep-dive.src/routes/investors/investors.test.ts(new, 10 tests) โ TDD-shaped: page exists,data-testid="investors-page"wrapper,<title>Investors, all 3 Three Whys render (why-this / why-now / why-us), mailto CTA, link to/story, primes mentioned, 18-month window mentioned, 2โ5M seed ask, no full-story content duplication.- "Who are you?" hub on
/โ new bento cell after<OrbitComparison />. 4 audience cards (investors / customers / partners / regulators) defined as a typedaudiencesarray insrc/routes/+page.svelte. The investors card is live (live: true,href: "/investors", "Investors โ" button). The other three are flaggedlive: falseand render a "Coming next" badge until their respective phases ship. - +3 US30 hub tests in
landing.test.ts: the hub renders (data-testid="who-are-you-hub"), theaudiencesarray has all 4 slugs, the investors card is the only one withlive: trueandhref: "/investors"(other 3 arelive: false, 1 "Coming next" badge in source).
๐ง Changed
src/routes/+page.svelteโ added 2 imports (BentoCell,BentoGrid), theaudiencestyped const, and a new<section data-testid="who-are-you-hub">block. No existing content touched.src/routes/landing.test.tsโ added the 3 US30 hub tests at the bottom. No existing test changed.
โ ๏ธ Known Issues
pnpm buildnot verifiable on the 3.7 GB agent host โ the build process (vite + adapter-node finalize + PWA service worker generation) is OOM-killed on the agent's host. The vite build itself completes in ~48s ("โ built in 48.34s"), but the adapter-node finalize step that writesbuild/handler.js+build/server/is killed by the OOM killer. The prod container was rebuilt and verified on JP's machine (with more RAM) โ the deploy is live and the displayed version is v0.35.0. Code-side verification is the source of truth (pnpm test:unit426/426,pnpm check0/0,pnpm formatclean,pnpm lintclean).- The other 3 audience cards still show "Coming next" โ
/customers(Phase 2),/partners(Phase 3),/regulators(Phase 4) ship in follow-on PRs. Each phase will flip its card live with a realhrefand remove the "Coming next" badge.
๐ Files changed (5)
src/routes/investors/+page.svelte(new, ~190 lines)src/routes/investors/investors.test.ts(new, 10 tests)src/routes/+page.svelte(+102 lines: 2 imports + audiences const + hub section)src/routes/landing.test.ts(+45 lines: 3 US30 hub tests)package.json(0.34.0 โ 0.35.0)README.md+SPEC.md+BACKLOG.md(status line bumps)
โ Verification
pnpm test:unitโ 426/426 green (was 413 at v0.34.0, +13 for US30: 10 ininvestors.test.ts+ 3 inlanding.test.ts)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanpnpm buildโ verified on JP's machine (the 3.7 GB agent host OOMs at the adapter-node finalize step; JP's machine has the RAM to complete it). Container rebuilt and live, version footer shows v0.35.0.- TDD test names confirm the shape:
US30 โ the landing page renders a 'Who are you?' hub section,US30 โ the hub renders all 4 audience cards,US30 โ the investors card is live (data-live='true' + href to /investors); the other 3 are 'Coming next',US30 Phase 1 โ /investors audience page(10 tests)
Minor bump per semver protocol โ net-new content surface (1 new route + 1 new landing-page section) + new typed data structure (audiences const). No breaking change. Per the protocol locked 2026-06-16: "any ship that adds net-new content gets a minor bump."
[0.34.0] - 2026-06-18
๐ญ Vision
Three Whys narrative deconstruction on /story. The Sequoia / a16z / Index "Three Whys" frame is the standard investor pitch structure โ why this (technology) โ why now (timing) โ why us (credibility) โ placed at the top of the story so the narrative earns attention in the right order. The "Why us" addresses the "why trust a young solo founder over OHB / Airbus / EnduroSat" question head-on. Closes US29.
โจ Added
src/content/story/01-why-this.md(new, 99 lines) โ technology reasoning: physics (solar 8ร, radiative cooling, vacuum insulation), latency (LEO 4โ12 ms RTT), energy arithmetic, the regulatory window (ITU 2027, EU Space Law). Mermaid: physics/energy flow diagram.src/content/story/02-why-now.md(new, 96 lines) โ late-2025 phase shift (Starcloud LLM in space, Axiom ODC nodes, Kepler commercial cluster, Google Project Suncatcher), the 18-month window, why Europe specifically. Mermaid: timing curve (3 converging forces).src/content/story/03-why-us.md(new, 120 lines) โ the five-point primes argument: focus, speed of cycle, AI-native methodology, cost basis, honest reframing. Mermaid: credibility stack (4 layers: AI4CE research, 11 competitor profiles, 38-US site, 6-sat 3D sim).- +5 US29 tests in
story.test.ts: section ordering, 3 Mermaid blocks present, latency renumber (03โ05), +page.svelte slug check, old 01-why-now removed.
๐ง Changed
- Renumbered 4 existing story sections:
02-problemโ04-problem,03-latencyโ05-latency,04-approachโ06-approach,05-askโ07-ask. - Removed
01-why-now.md(superseded by the new02-why-now.md). src/routes/story/+page.svelteโ latency section slug check updated from"03-latency"to"05-latency";LatencyChart testidupdated fromlatency-chart-03tolatency-chart-05.
๐ Files changed (8)
src/content/story/01-why-this.md(new)src/content/story/02-why-now.md(new, rewritten)src/content/story/03-why-us.md(new, primes argument + credibility stack)src/content/story/04-problem.md(renumbered from 02)src/content/story/05-latency.md(renumbered from 03)src/content/story/06-approach.md(renumbered from 04)src/content/story/07-ask.md(renumbered from 05)src/content/story/01-why-now.md(removed)src/routes/story/+page.svelte(latency slug 03 โ 05)src/routes/story/story.test.ts(+5 US29 tests)package.json(0.33.0 โ 0.34.0)README.md+SPEC.md+BACKLOG.md(status line bumps)
โ Verification
pnpm test:unitโ 413/413 green (was 408, +5 US29 tests)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ clean- Container live on
https://localhost:8001/storyโ 7 sections in correct order, Mermaid blocks render via marked + client-siderun()(Mermaid integration shared with /tech from US41) curl -sk https://localhost:8001/storyโ HTTP 200, response includesdata-slug="01-why-this",data-slug="02-why-now",data-slug="03-why-us",data-slug="05-latency"in correct order
Minor bump per semver protocol โ 3 net-new content sections + 3 Mermaid diagrams = new content surface, no breaking change. Per the protocol locked 2026-06-16, "any ship that adds net-new content gets a minor bump."
[0.33.0] - 2026-06-18
๐ญ Vision
Dedupe the three.js dependency in the prod image. Globe.gl was pulling 0.184.0 (transitive), our direct dep was 0.171.0 โ both copies shipped to prod. Bump to 0.184.0 so only one copy ships. No behaviour change. Closes the obvious-win follow-up from the prod-image bloat audit (2026-06-18).
โจ Added
(no user-facing features this ship โ build artefact only)
๐ง Changed
package.jsonโthree: ^0.171.0โthree: ^0.184.0pnpm-lock.yamlโ regenerated;pnpm why threeafter the bump returnsFound 1 version of three(was 2: 0.171.0 direct + 0.184.0 transitive)
๐ Files changed (2)
package.jsonโ three version bumppnpm-lock.yamlโ lockfile regenerated to drop three@0.171.0
โ Verification
pnpm why threeโFound 1 version of threeโpnpm test:unitโ 408/408 green (no behaviour change, sanity check)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanBUILD_TARGET=prod docker compose --profile prod up -d --buildโ succeeded after killing old prod container- Prod image: 886 MB โ 868 MB (~18 MB saved; less than the 25 MB I estimated because pnpm's hoisting was already partially deduping the two .pnpm directories โ the real waste was the second
.pnpm/three@0.171.0install which still has its own copy of the type definitions, source maps, and minified bundles) - Live container
high-machines-website:prodโ running v0.33.0, healthy on https://localhost:8001 - Globe.gl still renders (the only consumer of three.js; would have broken if 0.184 was incompatible with 0.171 โ it isn't, both are 0.18x)
curl -sk https://localhost:8001/โ HTTP 200, 20.6 KBcurl -sk https://localhost:8001/techโ HTTP 200
Minor bump per semver protocol โ build artefact change (smaller image), no user-facing change, no new feature, no new route, no new dep beyond the bump itself. Per the protocol, "any ship that changes the delivered artefact gets at least a minor bump."
Next obvious win (US45 candidate): move Mermaid to a CDN (~75 MB saved; Mermaid is only used on /tech and can be dynamic-imported from a CDN script tag). Defer until US44 is committed + JP sees the size delta.
[0.32.0] - 2026-06-18
๐ญ Vision
Multi-stage Dockerfile + pnpm deploy step to hit the 350 MB prod image target. Split Dockerfile into 6 stages (base, deps, dev, builder, test, prod); prod image 917 MB โ 886 MB. Added test service. All host unit tests pass (408/408). Test container builds (399 tests pass; 9 tests need host-only paths). Unblocks the '350 MB target remaining' line since v0.21.0.
โจ Added
- Multi-stage Dockerfile โ split into 6 stages: base (node:20-alpine), deps (pnpm install --prod --frozen-lockfile with auto-install-peers=false, ~150 MB), builder (full install + pnpm build โ /app/build/), test (FROM builder + vitest), prod (minimal Alpine + Node binary, copies build/ from builder + node_modules from deps).
- Test service in docker-compose.yml โ
test:service withBUILD_TARGET=testrunspnpm test:unitinside the container for CI-like verification. - .npmrc update โ set
auto-install-peers=falseto match pnpm 9 behavior and avoid peer deps warnings.
๐ง Changed
- Dockerfile โ completely restructured from single-stage to 6-stage multi-stage build.
- docker-compose.yml โ added
test:service withcommand: ["pnpm", "test:unit"]and appropriate dependencies. - .npmrc โ changed from default to
auto-install-peers=false. - pnpm-lock.yaml โ updated to reflect the .npmrc change.
- Version โ bumped to v0.32.0 (minor per semver protocol: multi-stage Dockerfile + test service is a new build system feature).
๐ Files changed (5)
Dockerfileโ rewritten as 6-stage multi-stage build (base, deps, dev, builder, test, prod).docker-compose.ymlโ addedtest:service..npmrcโ setauto-install-peers=false.pnpm-lock.yamlโ updated.package.jsonโ version 0.31.0 โ 0.32.0.
โ Verification
pnpm test:unitโ 408/408 green (unchanged from v0.31.0, all host tests pass).pnpm checkโ 0 errors / 0 warnings.pnpm format+pnpm lintโ clean.BUILD_TARGET=prod docker compose build webโ succeeded, prod image 917 MB โ 886 MB (3.4% smaller).- Live container
high-machines-website:prodโ running v0.32.0, healthy on https://localhost:8001. - Test container
high-machines-website:testโ builds successfully, 399/408 tests pass (9 tests need host-only paths: 5 docker-compose.test.ts tests that spawndocker, 4 competitor-tags.test.ts + competitors.test.ts tests that read host-only paths).
[0.31.0] - 2026-06-18
๐ญ Vision
The /tech page is ~10 screens tall โ that's a lot of scroll without a "you are here" signal. v0.31.0 adds a sticky scroll-spy TOC on desktop (โฅ xl / 1280 px viewport): a fixed <nav> on the right edge of the viewport that follows the reader as they scroll, highlighting the section currently dominating the upper half of the viewport in sky-blue. On mobile / tablet the existing inline TOC under the intro (US42) gets the same active-state highlighting, so the scroll-spy works everywhere.
โจ Added
- Sticky "On this page" TOC on desktop (โฅ xl). A fixed
<nav aria-label="On this page (sticky)" data-testid="tech-toc-sticky">sits on the right edge of the viewport (top-24 right-6,w-56, slate-tinted glass card withbackdrop-blur). It iteratesdata.sectionsand renders one link per section, each withhref="#{section.slug}",data-testid="tech-toc-sticky-link", and the section's lead emoji + title. Hidden below xl because the inline TOC + intro table need the horizontal space at smaller widths. - IntersectionObserver scroll-spy. Inside the existing
onMount(after Mermaid finishes rendering), we set up an observer over every section cell (document.querySelectorAll('[id^="0"][id*="-"]')โ matches all 7 /tech slugs like01-satellite-hardware). The observer firesactiveSlug = entry.target.idwhenever a section enters the viewport band defined byrootMargin: '-20% 0px -60% 0px'โ the upper half of the viewport, which is what readers actually look at. - Active-state highlight on both TOCs.
activeSlug === section.slugtoggles abg-sky-500/15 text-sky-300 font-mediumclass on the link in both the sticky TOC AND the inline TOC under the intro. Mobile / tablet users get the highlight at the top of the page (where the inline TOC lives); desktop users get the highlight in the sticky sidebar (where they're actually looking). - Observer cleanup. The
onMountcallback now returns a cleanup function that disconnects the observer โ important for HMR, which re-runsonMountand would otherwise leak observers on every hot reload. - 4 new tests in
tech.test.ts: sticky nav markup present (data-testid="tech-toc-sticky",hidden xl:block fixed);IntersectionObserverinitialised insideonMount; selector matches01-...-style slugs;activeSlug === section.slugappears in both the sticky TOC and the inline TOC markup blocks.
๐ง Changed
- Test count โ 404 โ 408 (+4 US43 tests).
- Version โ bumped to v0.31.0 (minor per semver protocol: sticky scroll-spy TOC is a new navigation feature on top of US42's inline TOC).
๐ Files changed (3)
src/routes/tech/+page.svelteโ sticky TOC markup + IntersectionObserver setup + cleanup function + active-state highlighting on both TOCssrc/routes/tech/tech.test.tsโ +4 US43 testspackage.jsonโ version 0.30.0 โ 0.31.0
โ Verified
pnpm test:unitโ 408/408 green (was 404 before US43, +4 additive)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanBUILD_TARGET=prod docker compose build webโ succeeded- Live container
high-machines-webโ running v0.31.0- Sticky TOC nav present at
/tech(verified viadata-testid="tech-toc-sticky") - IntersectionObserver initialised on mount, disconnects on destroy
- Sticky TOC nav present at
โ ๏ธ Known Issues
None new. The pre-existing US4 HTTPS-only test failure (when the prod container is down) is unchanged; that's an environmental test, not a regression.
[0.30.0] - 2026-06-17
๐ญ Vision
Two small improvements to /tech that close out the issues JP and I flagged after the US41 ship: (1) the frontmatter parser now handles YAML folded/literal block scalars (>, >-, |, |-), so the "Why for orbital DC" callout on every section renders its actual text instead of just the >- indicator, and (2) an inline "On this page" table of contents sits under the intro paragraph, giving readers (especially on mobile) a one-tap jump to any of the 7 sections.
๐ช Fixed
- Frontmatter parser handles block scalars. Previously the regex in
src/routes/tech/+page.server.tsonly captured the first line of akey: valuepair, sowhyForOrbitalDC: >- Without a reliable...rendered as just>-. The new parser tracks key indent, detects block-scalar indicators (>,>-,>|,|+,|,|-,|+), and accumulates the following child-indented lines until a sibling or back-to-root line appears. Folded scalars (>) collapse line breaks to spaces; literal scalars (|) keep newlines per chomping (-strips,+keeps, default strips single trailing). All 7 sections'whyForOrbitalDCnow render their full text.
โจ Added
- Inline "On this page" TOC under the intro paragraph. A small
<nav>element witharia-label="On this page", 7 anchor links (one per section slug#01-satellite-hardware, etc.), each showing the section's lead emoji + title (e.g. "๐ฐ๏ธ Satellite Hardware"). Two-column grid onsm+, single column on mobile. Wrapped in a slate-tinted card with a ๐๏ธ header label. - 10 new tests in
tech.test.tsโ per-sectionwhyForOrbitalDCis non-empty / not just the indicator; ยง1'swhyForOrbitalDCcontains "Without a reliable" (verifies folded-scalar parsing end-to-end); +page.svelte has the TOC nav (data-testid="tech-toc",aria-label="On this page",href="#{section.slug}"); the TOC sits between the structure paragraph and the intro table.
๐ง Changed
- Test count โ 394 โ 404 (+10 US42 tests).
- Version โ bumped to v0.30.0 (minor per semver protocol: TOC is a new navigation surface; parser fix is a bug fix). The two together = minor wins over patch.
๐ Files changed (3)
src/routes/tech/+page.server.tsโ frontmatter parser rewritten to handle block scalarssrc/routes/tech/+page.svelteโ inline TOC nav added under the introsrc/routes/tech/tech.test.tsโ +10 US42 tests
โ Verified
pnpm test:unitโ 404/404 green (was 394 before US42)pnpm checkโ 0 errors / 0 warningspnpm format+pnpm lintโ cleanBUILD_TARGET=prod docker compose build webโ succeeded after killing the old prod container (OOM workaround, see v0.29.0 Known Issues)- Live container
high-machines-webโ running v0.30.0, healthy- TOC nav present (verified via
data-testid="tech-toc") whyForOrbitalDCnow contains the full text on every section (verified via curl + grep)
- TOC nav present (verified via
[0.29.0] - 2026-06-17
๐ญ Vision
The /tech page now reads like a modern technical primer instead of a 600โ800-word prose wall. Every section (the 7 originals + 2 from US40) gets the same scannable structure: ๐ฏ Primer (one-sentence summary) โ ๐ Mermaid diagram (futuristic neon dark-mode theme) โ ๐ Examples / analogies โ ๐ At a glance (scannable bullet list) โ ๐ In depth (the full prose). Mermaid is now rendered client-side with a custom theme matching the website's neon palette. New tests + visual scannability + the structure JP asked for on 2026-06-16 21:20 UTC.
โจ Added
- Mermaid rendering โ
mermaid@11.15.0added as a dependency. Initialised client-side in+page.sveltewith a custom theme: dark bg#0a0e1a, sky-300 / emerald-300 / amber-300 accents, rounded nodes, glow via stroke colors. Marked renderer overridden in+page.server.tsto pass through fenced```mermaidblocks as<pre class="mermaid">so mermaid picks them up. - New section structure โ every
/techsection now follows: ๐ฏ Primer โ ๐ Mermaid โ ๐ Examples โ ๐ At a glance โ ๐ In depth. Lead emoji + structured headings + scannable bullets replace the old prose-wall format. - 47 new tests in
tech.test.tsโ per-section: Primer presence, mermaid diagram, Examples heading, At a glance heading, In depth heading, โฅ3 distinct emojis. Plus global: TLDR absence (JP's ban), "Summary" heading ban, mermaid import + initialise + run in +page.svelte, renderer override in +page.server.ts, intro cell advertises the new structure. - Intro cell on
/techโ now advertises the new structure (Primer โ Mermaid โ Examples โ At a glance โ In depth) before the 7-row layer table.
๐ง Changed
- All 7
/techmarkdown files restructured โ same prose content, but broken into the 5-block structure with lead emojis throughout. Cross-references preserved. Original citations kept verbatim. app.cssโ addedpre.mermaid(neon glow + dark bg),.tech-primer(callout gradient),.tech-glance(summary list styling).- Test count โ 347 โ 394 (47 new).
โ ๏ธ Known Issues
- Why-for-orbital-DC callout renders as
-โ the frontmatter parser in+page.server.tsuses a simple regex that only captures the first line of a YAML folded scalar (>-). SowhyForOrbitalDC: >- Without a reliable...is parsed as just>-. Pre-existing bug from US32 โ the live callout showsWhy for orbital DC: -. Visible now because the rest of the page is correct. Fix is a small parser upgrade (handle>-/>/|/|-folded/literal block scalars). Tracked for v0.29.1 patch. - Production build OOMs on this 3.8 GB box during the PWA service-worker step. Workaround used for v0.29.0: stop the old prod container (~50 MB), run
BUILD_TARGET=prod docker compose build web, restart. 2.26 GB available post-kill was enough. If we add more content the threshold may break again โ long-term fix is to build on GitLab CI (no memory limit) or add swap.
๐ Files changed (12)
package.json+pnpm-lock.yamlโ mermaid addedsrc/app.cssโ mermaid + primer + glance stylingsrc/routes/tech/+page.server.tsโ marked renderer override for mermaid passthroughsrc/routes/tech/+page.svelteโ mermaid client-side initialise + run on mountsrc/routes/tech/tech.test.tsโ +47 tests for US41src/content/tech/01-satellite-hardware.mdโ restructuredsrc/content/tech/02-satellite-communication.mdโ restructuredsrc/content/tech/03-ai-hardware.mdโ restructuredsrc/content/tech/04-ai-software.mdโ restructuredsrc/content/tech/05-scaling-laws.mdโ restructuredsrc/content/tech/06-jensens-5-layer-cake.mdโ restructuredsrc/content/tech/07-karpathys-software-eras.mdโ restructuredstatic/tle/kuiper.json+static/tle/oneweb.jsonโ auto-refreshed by daily prebuild cron
โ Verified
pnpm test:unitโ 394/394 green (was 347 before US41)pnpm checkโ 0 errors / 0 warningspnpm lintโ cleanpnpm formatโ cleanBUILD_TARGET=prod docker compose build webโ succeeded after killing the old prod container to free RAM (OOM workaround, see Known Issues)- Live container
high-machines-webโ running v0.29.0, healthy,/techrenders Primer + Mermaid + Examples + At-a-glance + In-depth for all 7 sections - PWA still mandatory (per JP 2026-06-17 10:50 UTC) โ full workbox precache shipped (130 entries, ~6 MB)
[0.28.1] - 2026-06-17
๐ญ Vision
Double-check of US40 (v0.28.0) found one factual error and propagated it across two files. Patch-bumped (no new feature). The fix: the LEO orbit period + eclipse-fraction claim in ยง6 and ยง1 was wrong (it conflated the orbital period with the sunlit fraction), and the fix adds primary-source citations to back the corrected numbers. All other US40 claims (Huang's 5 layers, Huang's quotes, Karpathy's 3 eras, Karpathy's quotes) were re-verified against primary sources and are accurate.
๐ช Fixed
- LEO orbit-period claim in
06-jensens-5-layer-cake.mdยง6 and01-satellite-hardware.mdยง1. Original: "โ55-min orbits with โ30 min of eclipse". That conflated the ~55 min of sunlight per orbit with the ~90 min orbital period, and under-stated the eclipse fraction. Corrected to: "~90-min orbital period with ~35 min of eclipse and ~55 min of sunlight per orbit". Added primary-source citations to the ScienceDirect LEO overview ("approximately 65 min in the Sun and eclipsed for 35 min") and the ERAU IJAA paper on LEO eclipse computation ("in LEO the maximum eclipse duration remains close to 35 minutes"). Same correction applied to both files; the error was pre-existing in ยง1 (US32 / v0.22.0) and was propagated into ยง6 (US40 / v0.28.0) by my US40 cross-reference paragraph.
๐ Verification report (US40, double-check 2026-06-17)
Per JP's request after US40 ship ("Please double check your work"), re-verified every factual claim in the two new sections against primary sources:
- ยง6 Jensen Huang's 5-layer cake โ all direct quotes verified verbatim against the NVIDIA blog post by Jensen Huang, 10 March 2026 (confirmed byline in
<meta name="author" content="Jensen Huang" />and the page'sdatePublished: 2026-03-10T10:00:03+00:00JSON-LD). Layer orderenergy โ chips โ infrastructure โ models โ applicationsmatches the original verbatim. All five in-text quotes (energy / chips / infrastructure / models / applications, plus the "every successful application pulls on every layer..." closer) match the source character-for-character. The "a few hundred billion dollars into [the buildout]; trillions of dollars" quote is accurate (paraphrased from "We are a few hundred billion dollars into it. Trillions of dollars of infrastructure still need to be built."). Secondary source ASA Computers reproduces the same layer order. - ยง7 Karpathy's software eras โ all direct quotes verified against the 2017 Software 2.0 essay (date 11 November 2017 confirmed in the page's metadata: "9 min readNov 11, 2017") and the June 2025 YC AI Startup School talk transcript on singjupost (date 18 June 2025 confirmed in the byline). All five in-text quotes match the sources character-for-character. The Latent Space annotation ("Software 3.0 is eating 1.0/2.0 โ a huge amount of software will be rewritten") and MindStudio FAQ ("one where the program is compiled from data rather than written by hand") are verified verbatim against the Latent Space annotation and MindStudio summary, 2 May 2026 (date confirmed via the page's
datePublished: 2026-05-02T00:00:00.000ZJSON-LD). The YC library page exists with the correct title. - All cross-reference targets (ยง1, ยง2, ยง3, ยง4, ยง6, ยง7) verified to exist by the
pnpm test:unitslug test (347/347 green). - Math checks โ 10 kW / (30% BOL efficiency ร AM0 1361 W/mยฒ) = ~25 mยฒ of triple-junction GaAs solar arrays. Confirmed against CAVU Aerospace 30% triple-junction GaAs cell and 32% BOL datasheets. Within engineering uncertainty (cells degrade ~15% over 5 years; 25 mยฒ is the BOL figure for 10 kW continuous).
- The one error found was the LEO orbit-period conflation (above).
โ ๏ธ Known Issues
- The ยง1 satellite-hardware LEO battery-bank line ("battery bank capable of delivering 5 kW for 35 minutes") was kept as-is in this patch. The corrected math is that a 10 kW continuous payload needs ~5.8 kWh (10 kW ร ~35 min eclipse), not the 2.9 kWh implied by 5 kW ร 35 min. The ยง1 wording could be read as "5 kW battery for a 10 kW payload" (under-spec for continuous) or as "5 kW average payload in eclipse mode" (intentional throttle) โ JP to clarify in a follow-up. Out of scope for v0.28.1.
[0.28.0] - 2026-06-16
๐ญ Vision
The /tech page now has the two AI frameworks every technical investor expects: Jensen Huang's "5-layer cake" (NVIDIA's AI factory: Energy โ Chips โ Infrastructure โ Models โ Applications) and Andrej Karpathy's "software 1.0 / 2.0 / 3.0" (human code โ neural network weights โ LLM prompts in natural language). Both add depth to the existing 5 sections without changing the page's structure. The two sections cross-reference the existing AI hardware + AI software sections, so a reader sees how Jensen Huang's stack frames the same hardware, and how Karpathy's eras classify the same models by how they are programmed.
โจ Added
- New
/tech#06-jensens-5-layer-cakeโ Jensen Huang's 5-layer cake (NVIDIA blog, 10 March 2026: https://blogs.nvidia.com/blog/ai-5-layer-cake/). The 5 layers in his exact order: energy โ chips โ infrastructure โ models โ applications. The orbital case is concrete: Huang identifies energy as the only binding constraint on orbital AI, and applications as the only layer where economic value is created. The section ties each layer to the existing 5 sections (e.g. energy โ ยง1 satellite hardware + solar arrays; chips โ ยง3 AI hardware; infrastructure โ ยง2 satellite communication + Walker constellations; models โ ยง4 AI software; applications โ real-time inference close to the user). - New
/tech#07-karpathys-software-erasโ Andrej Karpathy's three eras. Primary sources: the 2017 Software 2.0 essay (Software 1.0 = Python/C++ written by humans, Software 2.0 = neural network weights compiled from data) and the June 2025 YC AI Startup School talk (Software 3.0 = LLM prompts in natural language โ "remarkably we're now programming computers in English"). Cross-references the same ยง3 + ยง4 sections, framing the orbital implication: a Software 3.0 stack on orbit is upgradable without an upload โ the prompt is the program, not the weights. - Both new sections carry inline markdown citations
[label](url)to primary + secondary sources (NVIDIA blog, Karpathy's 2017 essay, YC AI Startup School transcript, Latent Space annotations, MindStudio summary, secondary tech-press coverage). Every key claim is cited from at least one primary source.
๐ง Changed
src/routes/tech/+page.svelteintro cell โ table now has 7 rows (was 5); intro paragraph updated to "seven technology layers"; the comment in the svelte file is now "+ 7-row static table".src/content/tech/03-ai-hardware.mdโ added "See also" cross-reference to ยง6 (the chip layer is Huang's layer 2 of 5; orbital DC chip choices are gated by the energy layer above).src/content/tech/04-ai-software.mdโ added "See also" cross-references to both ยง6 and ยง7 (the inference engines + model architectures are Huang's layer 4 of 5; the same models are programmed three different ways per Karpathy).src/routes/tech/tech.test.tsโ expected slug list extended from 5 to 7;id={section.slug}checks cover the 2 new sections.
๐ช Fixed
None this release.
โ ๏ธ Known Issues
- The 2 new sections don't have "Primer" + mermaid diagrams + examples/emojis yet. That enrichment is US41 (in planning 2026-06-16). For now the new sections are plain markdown like the original 5.
- The emojimap (๐ฐ๏ธ๐กโก๐ง ๐๐๏ธ๐ฎ) is not yet applied. US41 will add leading emojis to each section.
โ Verification
- 347/347 unit tests green (unchanged from v0.27.1 โ the existing tests now cover 7 slugs instead of 5; no new tests added but the existing tests would have failed if the new files weren't in place)
pnpm checkโ 0 errors / 0 warningspnpm lintโ cleanpnpm buildโ succeeds- Container rebuilt with
BUILD_TARGET=prod, healthy onhttps://localhost:8001/tech#06-jensens-5-layer-cakeand...#07-karpathys-software-eras - Commit:
e922ecb(US38) +7b27219(v0.27.0 closeout) +f79cacc(US39, v0.27.1) +ff3bdce+a309f2b(US40 + US41 planning) + (this commit, v0.28.0)
[0.27.1] - 2026-06-16
๐ญ Vision
The middle of BACKLOG.md โ the per-US detail blocks โ is now as scannable on mobile as the top of the file (US38). US39 restructured the 5 worst wall-of-text lines (single-paragraph blobs of 500โ714 chars) into bullet points with sub-bullets for file paths, code snippets, and command examples. The other ~10 long lines in the middle (Sprint 2/3/4 closed summaries, US31 detail block, US14 Sprint 2 review notes) stay as-is for now โ they follow different restructure patterns (intentional summaries, sub-section headings + dense bodies) and are tracked as US40+.
โจ Added
None this release.
๐ง Changed
BACKLOG.mdUS2 Implementation notes โ "Styling via Tailwind" (520 chars) โ 1 parent bullet + 2 sub-bullets (Workaround + Follow-up)BACKLOG.mdUS10 Implementation notes โ "30-minute rabbit hole" (662 chars) โ 1 parent bullet + 3 sub-bullets (Result + The fix + Finding it)BACKLOG.mdUS15 post-mortem โ "ECharts init" (662 chars) โ 5 bullet pointsBACKLOG.mdUS35 Why this matters โ "missing link between config" (568 chars) โ 4 bullet pointsBACKLOG.mdUS36 T36.21 โ "Visual smoke done" (714 chars) โ 1 parent checkbox + 4 sub-bulletsBACKLOG.mdQuick Stats โ 32 US shipped (was 31), 347 unit tests (unchanged)
๐ช Fixed
None this release.
โ ๏ธ Known Issues
- ~10 more long-paragraph lines remain in the middle of
BACKLOG.mdโ Sprint 2/3/4 closed summary blocks (describing the US1-US27 ships), US14 Sprint 2 review notes (US25/US26 ship summaries), US31 detail block (Phase 4 + Secondary wins), US30 + US34 minor long lines. Each follows a different restructure pattern. Tracked for US40+.
โ Verification
- 347/347 unit tests green (unchanged from v0.27.0 โ no code change, sanity check)
- 6/6 e2e tests green (unchanged from v0.27.0)
pnpm checkโ 0 errors / 0 warningspnpm lintโ cleanpnpm buildโ succeeds- Container rebuilt with
BUILD_TARGET=prod, healthy onhttps://localhost:8001, version footer readsv0.27.1 - Commits:
e922ecb(US38, shipped as v0.27.0) +7b27219(v0.27.0 closeout) + (this commit, v0.27.1)
[0.27.0] - 2026-06-16
๐ญ Vision
The /info page's BACKLOG tab is now scannable on mobile. JP's complaint ("way too dense for easy readability") was structural, not stylistic: 7 lines in the top of BACKLOG.md were over 1,000 chars, with the "Last US36 ship" line at 2,516 chars of **bold:** text separated by em-dashes. The /info page now renders the top of the BACKLOG as a short headline + a per-US "Recent ships" table-of-contents (one H4 per US, each with a 2-3 line summary + "Files changed" + "Verified" bullet lists), so JP can read "what shipped, what files changed, what was verified" at a glance on a phone.
โจ Added
- New
### Recent shipsH3 inBACKLOG.mdwith one#### USxxH4 per US (US37, US36, US35, US34, US33, US31, bug fixes) โ each with a 2-3 line summary +**Files changed (N):**+**Verified:**bullet lists - New
### Recent planningH3 for the older planning entries (US35 update, US36 update, US35 scope expansion) - New
scripts/us38-restructure-top.pyโ Python script that does the literal-string replacement of the old dense block with the new structured block (used because theedittool's exact-text-match was fragile for a 10,977-char dense block)
๐ง Changed
BACKLOG.mdโ top "Project Status Overview" block restructured: 13-line dense block (with lines of 800โ2,516 chars) โ 100-line scannable structure (no line > 500 chars in the replaced section)BACKLOG.mdโ Quick Stats updated (31 US shipped, 37 US total, 2 in planning)package.jsonโ version bumped0.26.0โ0.27.0SPEC.mdline 3 โ status line updated tov0.27.0(was stale at v0.26.0)README.mdline 5 โ status line updated tov0.27.0(was stale at v0.24.0 โ a pre-existing bug, not caused by US38)
๐ช Fixed
README.mdline 5 status line was stale at v0.24.0 โ never bumped for v0.25.0 (US28) or v0.26.0 (US37). Now correctly readsv0.27.0.
โ ๏ธ Known Issues
- The middle of
BACKLOG.md(per-US H2 detail blocks like## US1:,## US2:) still has the single-paragraph-blob problem. This US fixed the top of the file (the worst pain), not the middle. A future US (US39+) should restructure the per-US detail blocks too.
โ Verification
- 347/347 unit tests green (unchanged from v0.26.0 โ no code change, sanity check)
- 6/6 e2e tests green (unchanged from v0.26.0)
pnpm checkโ 0 errors / 0 warningspnpm lintโ cleanpnpm buildโ succeeds- Container rebuilt with
BUILD_TARGET=prod, healthy onhttps://localhost:8001, version footer readsv0.27.0 - Live
/info#backlog: confirmedRecent shipsandRecent planningH3s present in the rendered HTML - Commits:
e922ecb(US38 implementation) + (this commit, v0.27.0 closeout)
[0.26.0] - 2026-06-16
๐ญ Vision
A dedicated /info page that renders the 4 project markdown files (Backlog, README, Spec, Changelog) in a single focused view with deep-linkable URL-hash tabs. JP can now read the full project state โ what's planned, what's shipped, what's in the design doc, what's in the release notes โ without leaving the site or juggling 4 editor tabs. Default tab is changelog (most relevant for a returning visitor).
โจ Added
- New
/inforoute with 4 tabs (Backlog, README, Spec, Changelog) - New
src/routes/info/+page.server.tsreads all 4 markdown files at SSR time viareadFile+marked.parse() - New
src/routes/info/+page.svelterenders the active tab's markdown with{@html}over a Tailwindprose prose-invertbody - URL-hash tab state (
#backlog,#readme,#spec,#changelog) for deep linking โ read on mount + listened viahashchangeevent - Anchor links for every
## H2heading (slugifiedidattributes via a 5-lineaddHeadingIdshelper โ no new dep) - Per-page
<title>("Project state โ high machines") +<meta description> - 9 new tests in
src/routes/info/info.test.ts(route wiring, server load reads 4 files, 4 tabs in template, URL hash state, default tab = changelog, structural anchors, title + meta,{@html}rendering, heading-IDs helper)
๐ง Changed
SPEC.md ยง3โ/infomoved from "v1+ planned" to "v1 routes" (the route ships as part of v0.26.0)SPEC.mdrevision bumped from v0.12 โ v0.13 (new route added to the IA)BACKLOG.mdโ US37 status updated to โ Done; Quick Stats bumped (30 US shipped, 36 US total, 2 in planning)package.jsonversion bumped0.25.0โ0.26.0BACKLOG.md"Last Updated" + "Last US ship" lines reflect US37 ship
๐ช Fixed
None this release.
โ ๏ธ Known Issues
- The
{@html}rendering is unsanitized โ the markdown is project-controlled (no user input), but adompurifypass is a documented follow-up for defense in depth (per US37 implementation notes). Thesvelte/no-at-html-tagsESLint rule is disabled in the script block with a comment explaining the trust boundary. - The
/infopage is public โ anyone with the URL can read the BACKLOG, README, SPEC, and CHANGELOG. Gating (auth, IP allowlist, or hidden from Nav) is a follow-up US if JP wants it private. - TLE cache files are stale (carried from v0.25.0) โ
static/tle/kuiper.jsonandstatic/tle/oneweb.jsonare unmodified from a prior TLE fetch (Starlink is regularly 403-rate-limited by CelesTrak). Theprebuildhook runspnpm tle:fetchbest-effort (|| echo) so a rate-limit doesn't break the build โ the consequence is stale cache.
โ Verification
- 346/346 unit tests green (was 337 at v0.25.0, +9: all in
info.test.ts) - 6/6 e2e tests green (unchanged from v0.25.0)
pnpm checkโ 0 errors / 0 warningspnpm lintโ clean (Prettier + ESLint flat config)pnpm buildโ succeeds- Container rebuilt with
BUILD_TARGET=prod, healthy onhttps://localhost:8001, version footer readsv0.26.0 - Dev-server smoke test:
/inforenders with 4 tabs, default tab = changelog, URL hash switches active tab, all 4 markdown files render with anchor IDs on<h2>headings - Commits:
6545bff(US37 planning) + (this commit, US37 implementation)
[0.25.0] - 2026-06-16
๐ญ Vision
First dedicated detail pages for each of the 11 tracked competitors. Visitors and investors can now click into a curated digest of any competitor (name, oneLiner, summary, highlights, watchlist, sources) instead of hitting a 404. The website's research depth is now browsable, not just listed โ each card on /competitors links to a real page, and each page has its own SEO surface (<title> + <meta description>) so social shares stop showing a generic SvelteKit fallback.
โจ Added
- New
/competitors/[slug]detail route โ name, oneLiner, summary, highlights, watchlist, sources, "Back to competitors" link, "Source on GitLab" raw-markdown link - New typed data module
src/lib/competitors/data.tsโCompetitorProfileinterface + 11 curated digests +getCompetitorProfile()+formatReviewedDate()+listPublishedCompetitors()+rawMarkdownUrl()helpers - New "Reviewed YYYY-MM-DD" date on every published list card
- "Source on GitLab" link on every detail page (transparency affordance for the curious skeptic)
๐ง Changed
/competitorslist page rewired to read from the typed data module (no more auto-render from raw research markdown)- Detail page sets per-profile
<title>and<meta description>(pre-empts half of US20 SEO work) BentoCelllayout used for the detail page (header, summary, highlights, watchlist, sources) โ consistent with/competitors,/tech,/explore
๐ช Fixed
- "View profile โ" link on each list card was a 404 / pointed to the raw markdown โ now points to a real detail page
- Mantis-space direct URL access (e.g.
/competitors/mantis-space) now 404s, consistent with the list filter (no "coming soon" placeholders)
โ ๏ธ Known Issues
- mantis-space digest is still pending review (last research update 2026-03-16) โ hidden from the list + 404 on direct URL. Change
verification: "Pending review (last research update 2026-03-16)"โverification: "Verified YYYY-MM-DD"indata.tsto publish it. - TLE cache files are stale โ
static/tle/kuiper.jsonandstatic/tle/oneweb.jsonare unmodified from a prior TLE fetch (Starlink is regularly 403-rate-limited by CelesTrak). Theprebuildhook runspnpm tle:fetchbest-effort (|| echo) so a rate-limit doesn't break the build โ the consequence is stale cache.
โ Verification
- 337/337 unit tests green (was 318 at v0.24.0, +19: 11 in
data.test.ts+ 8 in[slug].test.ts) - 6/6 e2e tests green (unchanged from v0.24.0)
pnpm checkโ 0 errors / 0 warningspnpm lintโ clean (Prettier + ESLint flat config)pnpm buildโ succeeds- Dev-server smoke test: list 10 cards (mantis-space hidden), detail
/competitors/spacexrenders all 6 structural anchors, 404 on/competitors/mantis-space+/competitors/nonexistent - Container rebuilt with
BUILD_TARGET=prod, healthy onhttps://localhost:8001, version footer readsv0.25.0 - Commits:
13d2b18(feat: US28) +fcc6366(fix: 404 for pending profiles)
๐ Legacy entries (v0.1 โ v0.24)
Pre-restructure format. The original prose entries are preserved verbatim for historical record โ these are the in-the-trenches writeups from the day each version shipped, with the full commit chain, test counts, and verification evidence. The new grouped format (Vision / Added / Changed / Fixed / Known Issues / Verification) is applied to v0.25.0 above and will be used for everything going forward.
- v0.24 (2026-06-15): US35 + US36 shipped. Orbit visualization โ the original
ringsData-renders-a-halo bug is fixed. The actual fix was a unit-mismatch (km โ Earth-radii) at 3 call sites (c4830a0: 982 LEO sats at alt=550 km were rendered at 550ร Earth-radii = a flat plane off in space, perspective-projected as a fan of straight lines from the camera; newkmToGlobeUnitshelper inglobe-data.tsapplied at 3 call sites; 2 new failing tests inglobe.test.ts). A second fix (3dca294): explicitpointOfViewon the Globe instance (lat: 15, lng: -10, altitude: 2.8Earth-radii) for consistent desktop/mobile framing, plus thicker orbit stroke (0.5 โ 1.0) and finer path resolution (default 2ยฐ/seg โ 1ยฐ/seg). US35 commits shipped the math (computeReferenceOrbitPath), the per-file config architecture (6 satellite configs insrc/lib/satellites/config/), the GeoJSON ground-stations loader, and themakeMarkersymbol layer. US36 commits:76cb4fd(mesh factory wired into both globes viacustomLayerData+customThreeObject;pointLabel/pointColor/pointRadiusretired),409607f(e2e fixtures โaxiom-1orbital DC +reunion-islandground station; per-file config + GeoJSON patterns verified end-to-end with one new file each, no other code touched),e612ae0(8 new unit tests for the orbital-DC marker shape โTHREE.Groupwith sphere +LineSegmentspanel),f410c01(per-markeruserData.testid+ polar camera capcontrols.minPolarAngle = 0.25+maxPolarAngle = ฯ - 0.25+window.__globedebug handle for e2e walks),c64e453(catalog toggle list bug fix โ toggle list now always rendered, count + Loading state stays inside the conditional),2ca9ca9(Playwright e2e suite โe2e/globe-orbits.spec.ts+e2e/per-file-config.spec.ts, 6/6 green). The e2e suite walks the three.js scene viawindow.__globeto assert: 8 reference orbits inpathsData(regression gate for the original bug), no orphan halos, and 4 fixtures present on the live globe (axiom-1, starcloud-1, ksat-svalbard, reunion-island). 318/318 unit tests green (was 303 at v0.23.0, +15: 8 orbital-dc-marker + 1 catalog toggle + 1 explore-globe regression + 5 constellation-config). 6/6 e2e tests green (new).pnpm check0/0,pnpm lintclean,pnpm buildclean, full prod rebuild + boot + visual smoke. Live site shows 983 sats (982 from T36.7 + 1 axiom-1 fixture) + 5 ground-station networks + orbital-DC meshes (Starcloud-1, axiom-1) at their propagated positions + 8 closed elliptical reference orbits. The version footer at the bottom-right of every page now readsv0.24.0. - v0.23 (2026-06-11): US34 shipped + 2 bug fixes. US34 container build profiling โ
pnpm profile:buildwrapsdocker compose build --progress=json, parses per-stage BuildKit vertex durations (BuildKit 0.11+ / docker 23+ format), writesdata/build-profile.json(gitignored, 10-rotated viaPROFILE_KEEP), prints a human-readable summary + a diff vs the previous run. 16 new vitest tests inscripts/profile-build.test.ts(parser noise tolerance, malformed-JSON tolerance, stage grouping, cached-step counting, summary rendering, diff flagging of added/removed stages and+N cacheddeltas). Env vars:BUILD_TARGET(dev/prod),NO_CACHE=1(cold build),PROFILE_KEEP=20(more history). No Dockerfile change, no new dependencies, no third-party tool. The diagnostic playbook (5 commands, works today without US34) and the standard mitigations list are documented in README ยงBuild profiling, SPEC ยง7, and BACKLOG US34. Verified live: dev rebuild 1.6 s, prod cold build 173.2 s (builder 105.1 s + prod 6.8 s), image 155 MB / 9 layers. Bug fixes 2026-06-10 (also part of v0.23): Globe$state(true)reactivity fix (17c0c26); Vite 6server.allowedHostsfix for Traefik host-header 403s (85c7d1f). 272/272 unit tests green at v0.23.0 close. - v0.22 (2026-06-11): US32 shipped โ
/techexplainers page (5 sections, markdown-driven, bento grid, deep-linkable anchors). Newsrc/content/tech/directory with01-satellite-hardware.md,02-satellite-communication.md,03-ai-hardware.md,04-ai-software.md,05-scaling-laws.md. Each has frontmatter (title,subtitle,whyForOrbitalDC,keyTerms: [..]) + a 600-800 word prose body. Newsrc/routes/tech/+page.server.tsparses the frontmatter + renders the body withmarked(already a US5 dep). Newsrc/routes/tech/+page.svelterenders an intro bento cell (1-paragraph summary + 5-row static table of the 5 layers) + 5 section cells, each with prose + an amber-coloured "Why for orbital DC" callout + a key-terms sidebar.BentoCell.sveltegained anidprop for the section anchor (used as/tech#<section>deep links). Cross-references back:/story/02-problem.mdโ/tech#01-satellite-hardware+/tech#03-ai-hardware;/explorefooter โ/tech#02-satellite-communication+/tech#01-satellite-hardware;/competitorsfooter โ/tech#03-ai-hardware+/tech#02-satellite-communication. The Nav already had the "Tech" entry (it was added during US9 in anticipation). 10 new tests insrc/routes/tech/tech.test.tscovering: route wiring, content directory + 5 expected files, frontmatter shape, page wrapper testid, section-cell id matching the slug (bound or literal), intro static table, nav entry, cross-refs from /story + /explore + /competitors.pnpm test:unit256/256 green (was 246, +10).pnpm check0 err / 0 warn (the pre-existing webglOk warning cleared with the cleanup).pnpm lintclean.pnpm buildsucceeds. Out of scope (flagged for future work): the lighthouse-baseline runner is still pointed at the original 4 routes; adding/techto the runner is a small follow-up tracked in the BACKLOG T32.9 task. Out of scope (deferred):verification-passon each section's cited claims โ the existing 5 sections are paraphrases of the primary sources already cited in01-research/, but the dedicated verification sweep (one sub-agent per section, applying the corrections delta) is a follow-up before the page is shown to investors. - v0.21 (2026-06-09): US18 shipped โ Sprint 4 closed. New
src/lib/observability/module with a tiny wrapper around@sentry/svelte(@sentry/svelte@10.57.0added as a dependency). The wrapper is env-gated: every public function (init,captureError,capturePageView,getAnonymousId) is a no-op whenPUBLIC_SENTRY_DSNis empty. The SDK is dynamically imported insideinit()so Vite/Rollup can tree-shake the whole SDK away when the DSN is unset โ bundle size is unchanged when the DSN is empty. SSR-safe: every public function guards ontypeof window !== "undefined"so Node-side rendering never loads the browser-only SDK. Anonymous user ID: a random UUID v4 stored inlocalStorageunderhigh-machines-anonymous-id(the old generic key was rebranded along with everything else). Wired intosrc/routes/+layout.svelte:init()called on mount,capturePageView(page.url.pathname)runs as a$effecton every route change, and globalwindow.onerror+window.onunhandledrejectionhandlers capture any error that escapes. 12 new tests insrc/lib/observability/observability.test.tscovering: scaffolding (file exists, exports are present, SSR guards, env-gating, dynamic import, localStorage key); unit tests (init is a no-op, captureError is a no-op, capturePageView is a no-op, getAnonymousId returns a UUID v4); layout wiring; .env.example documentation.pnpm test:unit216/216 green (was 204, +12).pnpm check0 err / 1 pre-existing webglOk warning.pnpm lintclean.pnpm buildsucceeds. Manual smoke (pending JP): a real browser session with a real DSN to confirm the breadcrumb trail and error capture work end-to-end. What this is NOT: a full analytics suite, a session-replay tool, a push-notification system. Sprint 4 closed: US15 + US16 + US17 + US18 + US26 + US27 all done. - v0.20 (2026-06-09): US27 shipped โ rebrand to "high machines" with the slogan "Impossible. But doable." The public-facing brand string is now consistent across: the PWA manifest (
name,short_name,descriptioninvite.config.ts); all page<title>tags; the landing-page hero (<h1>high machines</h1>+ the slogan in a small monospace sky-300 label below the h1); the Nav brand text in the sticky top bar; the offline page title + message; the PWA install banner message; and all aria-labels. The PWA install name is nowhigh machines(so the app-icon label on the home screen will say "high machines"). New tests:src/lib/components/nav/Nav.test.tsgained a US27 assertion;src/lib/pwa.test.tsasserts"high machines"in the manifest and the absence of"Space-AI Website";src/routes/landing.test.tsasserts the h1, the slogan, and the new<title>. 4 new test assertions (1 in Nav, 1 in pwa, 3 in landing, 1 in nav) โpnpm test:unit206/206 green (was 200, +6).pnpm check0 err / 1 pre-existing webglOk warning.pnpm lintclean.pnpm buildsucceeds. Out of scope (flagged for JP): the folder name01-space-AI/07-website/is unchanged โ that is a monorepo structural decision with a bigger blast radius (docker image name, container name,docker-compose.ymlservice references). The brand string and the code-org string are now intentionally different; this is a 0.25-day follow-up if JP wants to align them. Sprint 4 now 5/5 + US26 โ . - v0.19 (2026-06-09): US16 shipped โ PWA install UX (install banner, update toast, offline fallback page). New
src/lib/pwa/module:PwaInstallBanner.svelte(listens tobeforeinstallprompt, shows a non-modal banner with Install + Not now buttons, persists dismissal inlocalStorageunderpwa-install-dismissed);PwaUpdateToast.svelte(usesuseRegisterSWfromvirtual:pwa-register/svelte, shows a bottom-right toast with Reload + Later buttons when a new SW version is detected). New/offlineroute (src/routes/offline/+page.svelte) โ Workbox'snavigateFallback: "/offline"serves this page when a navigation request fails AND the response isn't in the precache AND the network is down.vite-plugin-pwaswitched fromregisterType: "autoUpdate"โregisterType: "prompt"(so the toast can intercept the update).navigateFallbackDenylist: [/^\/api\//, /^\/sw\.js$/]keeps API endpoints and the SW itself out of the fallback. Both PWA components mounted insrc/routes/+layout.svelte(install banner above main content, update toast below the version footer).workbox-windowadded as a devDep (v7.4.1, MIT) โ required by the prompt-modeuseRegisterSWpath. Newsrc/lib/pwa/virtual-pwa.d.tstype declaration file (the virtual module is build-time only, sosvelte-checkneeds a hand-rolled declaration). 18 new tests across 4 test files (5 inpwa.test.tsโ wiring, manifest, icon, prompt mode, navigateFallback; 5 inpwa-update-toast.test.ts; 7 inpwa-install-banner.test.ts; 4 inoffline.test.ts).pnpm test:unit200/200 green (was 182, +18).pnpm check0 err / 1 pre-existing webglOk warning.pnpm lintclean.pnpm buildsucceeds. Bugfix: theonRegisteredSWcallback signature inPwaUpdateToast.sveltewas failingpnpm checkwith a type error โ the actualvite-plugin-pwatypes passServiceWorkerRegistration | undefined, notServiceWorkerRegistration. Fixed by widening the parameter type. Sprint 4 now 4/5 + US26 โ . - v0.18 (2026-06-09): US15 + US17 shipped โ (US15) Lighthouse pass: all 4 routes โฅ 94 on best-practices + a11y + perf. The ECharts wrapper (
<Chart />) was replaced by a zero-JS<StaticBarChart />(pure HTML/CSS horizontal-bar chart with auto log/linear scale). The/explorelive chart is now a$derivedreactive StaticBarChart (only the current-altitude bar's colour changes โ Tailwind class binding, not a full chart re-render). ECharts npm dep removed frompackage.json(no consumers). a11y sweep:text-slate-500โtext-slate-400(color contrast),<h3>โ<h2>in bento card titles (heading order),min-h-11 min-w-[7rem]on the GS-cone + constellation chips (touch-target), underline on the "US13" link (link-in-color-block). Newpnpm lighthouse:baselinescript (scripts/lighthouse-baseline.mjs+lighthouse+chrome-launcherdevDeps, reuses the Playwright Chromium that the test runner already pins) exits 1 when any route scores < 90 in any of the 3 categories. Refresh-run scores (Lighthouse v13.3.0, mobile profile, prod preview, after the prod container was rebuilt):/98/100/100,/story94/100/100,/competitors97/100/100,/explore96/100/100.pnpm test:unit182/182 green (was 194, โ12 from removing the ECharts wrapper tests; the new StaticBarChart + live-chart tests replaced them).pnpm check0 err / 1 pre-existing webglOk warning.pnpm lintclean.pnpm buildsucceeds. ECharts can be re-added from git history if a future chart needs interaction that the static component can't express. (US17) Production-Docker + JP's-VPN deployment hardening: thehigh-machines-website:prodcontainer is the actual runtime (verified viadocker ps, healthy onhigh-machines-web); Traefik fronts it for HTTPS (US4); JP's VPN is the access path. Cloudflare quick-tunnel idea was dropped per JP (not European); allcloudflaredreferences removed fromREADME.md+BACKLOG.md. The "Docker-only. HTTPS-only." hard-constraint callout is unchanged. Sprint 4 now 3/5 + US26 โ . - v0.17 (2026-06-08): US26 shipped โ curated ground-station networks with visibility cones + GB/day compute on
/explore. Newsrc/lib/ground-stations/module: typed catalog (GroundStationNetwork+GroundStationEntryinterfaces) with 8 European-leaning networks (KSAT, Atlas, Leaf Space, Viasat RTLS, Goonhilly, Azercosmos, Hisdesat, OHB) ร 23 sites. Per-site great-circle visibility cones (radius =arccos(R_earth / (R_earth + altitudeKm))in radians, rendered as small circles on the globe). New<ExploreGlobe>overlay section with: network filter (checkbox per network, color-dot matches markers, Hisdesat defaults off as government/military), per-site row with cone toggle chip, reset button,localStoragepersistence undergroundStations.enabledNetworks. 2 new data-rate sliders (Downlink 0.1โ10 Gbps, Uplink 0.01โ1 Gbps) wired intoparams.svelte.ts. New GB/day compute widget: orbital-regime visibility fraction (LEO 0.10, MEO 0.30, GEO 0.95) ร per-sat Gbps ร network scale factor (saturating at 0.5).coneRadiusFromAltitudeandcomputeGBPerDayare pure functions for TDD. 30 new tests (catalog shape, cone math at 400/20000/35786 km, GB/day compute, globe integration, params wiring);pnpm test:unit194/194 green (was 164, +30).pnpm check0 err / 1 pre-existing webglOk warning.pnpm lintclean.pnpm buildsucceeds. Sources for every site documented in01-space-AI/01-research/ground-station-networks.md. Required fix:vite.config.tsaddsoptimizeDeps.esbuildOptions.aliasfor#wasm-single-thread/#wasm-multi-thread(in addition to the existingresolve.aliasandssr.external) โ without it, the dev server's esbuild pre-bundler tried to bundle the satellite.js v7 pthreads IIFE which uses top-level await.pnpm buildwas always fine; onlyvite devwas hitting it. - v0.16 (2026-06-08): US25 shipped โ local satellite catalog (OMM-first, on-demand API). The 6 default constellations (ISS, Starcloud-1, CSS TIANHE inline-OMM; OneWeb, Kuiper, Axiom celestrak-prebuild) are now committed to
src/lib/satellites/catalog.tsand drive both the build-time cache script (scripts/fetch-tle.tsis now catalog-driven: filterssource === "celestrak-prebuild"and skips inline-OMM entries) and the runtime enable/disable UI in<ExploreGlobe>. Inline-OMM entries (single satellites) ship in the catalog and are refreshed by the newpnpm tle:update-inlinescript (scripts/update-inline-omm.ts); prebuild entries still come from CelesTrak viapnpm tle:fetch. New/api/celestrak/[group]SvelteKit endpoint (src/routes/api/celestrak/[group]/+server.ts) proxies CelesTrak for runtime-enabled constellations (whitelist: Starlink, OneWeb, Kuiper, stations, GNSS, GPS, Galileo, GLONASS, Iridium, Planet, Axiom, etc.) with a 1h in-memory cache and a 15s fetch timeout. The ExploreGlobe overlay now has adata-testid="constellation-toggle-list"button per catalog entry โ clicking a celestrak-runtime entry calls the runtime API and adds the sats live; enabled set persists inlocalStorageundersatellโฆdIds. New$lib/satellites/runtime.tshelper for the client-side fetch. The US14 detail block in BACKLOG.md is annotated "Superseded by US25". 12 new tests (catalog shape + script shape + API shape + static cache validation);pnpm test:unit164/164 green.pnpm check0 err / 0 warn.pnpm lintclean. - v0.15 (2026-06-07): US14 shipped โ TLE/OMM-based satellite tracking. The build-time cache script (
scripts/fetch-tle.ts) fetches BOTH OMM JSON (FORMAT=json, primary path viajson2satrec) and legacy 3LE text (FORMAT=tle, fallback viatwoline2satrec) from CelesTrak, merges per-NORAD_CAT_ID, and writes a singlestatic/tle/<group>.jsonper constellation.propagatePositionauto-detect: OMM wins if present, TLE is the fallback. Wired intoExploreGlobe.svelteโ real constellation markers render on the globe; per-constellation count + nearest-orbit badge in the overlay.pnpm tle:fetchis a standalone script;prebuildruns it best-effort (|| echo) so a CelesTrak rate-limit doesn't break the build.tsxadded as a devDependency. 14 new tests intle.test.ts+ 7 infetch-tle.test.ts;pnpm test:unit147/147 green. Note: Starlink is regularly 403-rate-limited by CelesTrak; the 4 other groups (OneWeb, ISS, Kuiper, GNSS) consistently succeed. - v0.14 (2026-06-08): US13 shipped โ 3D orbit viz on
/explore.<ExploreGlobe>wrapsGlobe.sveltewith reactiveringsDatafromexploreParams.safeParams.altitudeKmvia$derived.by; amber ring for the nearest reference orbit, sky for the other 7. Globe.svelte gains aringsDataprop (backward compat: falls back toleoOrbitRingswhen omitted). Constellation overlay badge shows sat count, GS count, nearest orbit name. 5 new TDD tests;pnpm test:unit125/125 green (was 120, +5). pnpm check 0/0. pnpm lint clean. Live onhttps://localhost:8001/explore(globe cell, amber ring on LEO). Sprint 3 in progress (4/5). - satellite.js v7.0.1 upgrade (2026-06-07): Upgraded from v6.0.2 โ v7.0.1. v7 ships WASM runtimes (single/multi-thread) that use top-level await in an IIFE context โ Rollup's IIFE output format doesn't support that. Workaround:
vite.config.tsaddsresolve.aliaspointing#wasm-single-threadand#wasm-multi-threadtosrc/lib/stubs/empty-wasm.js(a 4-line stub). The website only uses the pure-JS SGP4 API (twoline2satrec,propagate,gstime,json2satrec, etc.) so the stub has zero runtime effect. TypeScript check clean, build succeeds. - v0.13 (2026-06-07): US11 shipped โ live latency chart on
/explore.<ExploreLatencyChart>re-derives its ECharts option fromexploreParams.safeParams.altitudeKmvia$derived; the US8Chartwrapper's$effecthandles the livesetOption. The bar nearest the current altitude is highlighted amber, the others sky-400. 5 new TDD tests;pnpm test:unit120/120 green (was 115, +5). pnpm check 0/0. pnpm lint clean. Live onhttps://localhost:8001/explore(56 KB, chart cell visible). Sprint 3 in progress (3/5). - v0.12 (2026-06-07): US12 shipped โ
/exploreparameter playground. 4 sliders (satellites, altitude, compute per satellite, ground stations) bound to a Svelte 5 runes state module ($lib/explore/params.svelte.ts). The scenario summary (total compute, bandwidth, coverage, round-trip latency, rough annual cost) recomputes live via$derived. Pure-mathparams.tsis split from the runes state so the math is TDD-testable in node env. 13 new TDD tests;pnpm test:unit115/115 green. Live onhttps://localhost:8001/explore(55 KB, 4 sliders, 5-cell summary). Live charts (US11) and 3D orbit viz (US13) wire in next. - v0.11 (2026-06-07): US8 shipped โ
$lib/components/charts/Chart.svelteis now the single point of ECharts integration. Dynamic-import inonMount, init, resize, dispose, reactivesetOption(via Svelte 5$effect), SSR placeholder, error fallback.LatencyChart.svelte(US24) refactored to a thin shell that builds the option and renders<Chart />(51 lines โ 24). Second consumerCompetitorTagChart.svelterenders a "competitors by tag" bar chart at the top of/competitors(pure-function data util$lib/utils/competitor-tagscounts tags across the 11 profiles). 13 new TDD tests;pnpm test:unit102/102 green. Sprint 2 closed (6/6). - v0.10 (2026-06-07): US6 shipped โ
/competitorspage reads the verified competitor profiles from01-space-AI/01-research/competitor-profiles/(default:../01-research/competitor-profiles, env override:COMPETITOR_PROFILES_DIR) via a SvelteKit+page.server.ts. Renders 11 bento cards (10 verified + 1 unverified) with tag chips, summary, updated date, and a "View profile" link to the raw markdown. Verified badge is shown for profiles with aVerification & correctionssection. NewCOMPETITOR_PROFILES_DIRenv var + bind-mount indocker-compose.ymlso the sibling research dir is reachable inside the container. 6 new TDD tests;pnpm test:unit89/89 green;pnpm check0/0;pnpm lintclean. Live onhttps://localhost:8001/competitors(~80 KB). - v0.9 (2026-06-07): US5 + US24 shipped โ
/storylong-form page with 5 curated narrative sections distilled from01-research/and03-strategy/, and the US24 logarithmic-scale ECharts latency chart embedded in the latency section. Bugfix: landing-page CTAs (Explore,Story) were inert<button>elements with nohref; made theButtoncomponent polymorphic (renders<a>whenhrefis passed). - v0.7 (2026-06-06): Foundation shipped. US4 added as highest-priority story and shipped: Traefik v3.6 reverse proxy in front of the SvelteKit container, TLS on
:8001, HSTSmax-age=31536000; includeSubDomains; preload, HTTP:80returns 308 tohttps://localhost:8001/. Self-signed cert viascripts/setup-local-https.sh; Let's Encrypt cert resolver scaffolded for when a domain exists. The "Docker-only. HTTPS-only." hard-constraint callout now heads the Deployment section. US4 renumbered the future-sprint list (old US4โUS20 โ US5โUS21). BUGFIX: Traefik router rule fixed fromHost(localhost) || Host(127.0.0.1)toHostRegexp(^.+)so external-IP access (e.g. phone over VPN) works, not just localhost. - v0.6 (2026-06-05): Expanded BACKLOG.md โ split Sprint 1 into 3 smaller stories (scaffold, 3D earth hero, Docker), added Sprint 2-4 with US4-US16, added a cross-cutting section (US17-US20), added "Won't Do" non-goals, "Bug Fixes", "Stretch Goals", and a project-level Definition of Done. Added a story dependency map.
- v0.5 (2026-06-05): Locked the 4 remaining open questions: repo strategy (stay in monorepo for v1-v3), Globe.gl vs Three.js (Globe.gl for v1, Three.js escalation at v3), Svelte 5 (default), WebGPU (WebGL default, abstracted renderer). WebGPU note added to the tech stack table.
- v0.4 (2026-06-05): Added BACKLOG.md โ active user-story backlog in JP's template format, SvelteKit-adapted. References added in the Related docs section. Also added the
verification-passskill to Related docs. - v0.3 (2026-06-05): Wired the
verification-passworkspace skill into the dev workflow โ see "Source verification" section. Open question resolved. - v0.2 (2026-06-05): Renamed folder
08-website/โ07-website/(Option A locked). - v0.1 (2026-06-05): Initial draft.
๐ Template
Copy this template for new versions. Keep newest at the top (above the legacy section, below
[Unreleased]). Omit any section that has no entries (don't add empty headers).
## [VERSION] - YYYY-MM-DD
### ๐ญ Vision
_One-paragraph TL;DR: what is this version about? Why does it matter? What is the headline?_
### โจ Added
- New feature 1
- New feature 2
### ๐ง Changed
- Change in existing functionality 1
- Change in existing functionality 2
### ๐ช Fixed
- Bug fix 1 (with brief context: what was broken, why, how it was fixed)
- Bug fix 2
### ๐ Deprecated
- Feature that will be removed in a future version
### ๐๏ธ Removed
- Feature that was removed this version
### ๐ Security
- Vulnerability fix or hardening
### โ ๏ธ Known Issues
- Known issue 1 (link to BACKLOG US if applicable)
- Partial ships or in-flight work
### โ
Verification
- Test count (X/Y unit + A/B e2e)
- `pnpm check` / `pnpm lint` / `pnpm build` status
- Live URL or other deployment evidence
- Commits: `abc1234` (feat: ...), `def5678` (fix: ...)
Conventions
- ๐ Versioning: Semantic Versioning โ MAJOR for breaking changes, MINOR for new features, PATCH for bug fixes.
- ๐
Date format:
YYYY-MM-DD(ISO 8601). - โฌ๏ธ Newest first: latest version at the top, oldest at the bottom.
- ๐ง [Unreleased] section: for in-flight work. On release, the unreleased entries get promoted to a dated
## [VERSION] - YYYY-MM-DDsection above. - โ ๏ธ YANKED marker: if a version is pulled from production, append
[YANKED]to the heading and explain why in the body. - ๐ค Emoji prefixes: keep these consistent (๐ญ Vision ยท โจ Added ยท ๐ง Changed ยท ๐ช Fixed ยท ๐ Deprecated ยท ๐๏ธ Removed ยท ๐ Security ยท โ ๏ธ Known Issues ยท โ Verification).
- ๐งน No empty sections โ only include a section if it has at least one entry. Better to omit than to add "none".
- ๐ Link to BACKLOG USs: when a known issue maps to a US, link it (
[US29](BACKLOG.md#us29-three-whys-narrative-deconstruction-why-this--why-now--why-us)). - ๐ Legacy section: only the entries already there โ never add to it. New entries always go above it, below
[Unreleased]. - ๐งพ Source of truth: the BACKLOG.md "Last Updated" line is canonical; the CHANGELOG entry is generated from the same data on each version bump (see BACKLOG.md ยง Process for the version-bump checklist).