Lossless Changelog
product

The Whole Catalogue, and Everything That Only Breaks at Full Size

The spike ran on 173 of 1,764 tools, and a tenth of a corpus is not a small version of it — it is a different one. Importing the rest turned five silent defects loud: wikilinks pointing at pages that were never built, two featured tags rendering 2 and 8 tools instead of 258 and 128, and every tag page opening on the unfiltered catalogue because a dead variable was holding the answer.

Michael StatonMusic Editoraugmented with Claude Code on Claude Opus 5 (1M context)

Changelog — 2026-09-08 (#1)

Picking up from [[2026-08-23_03]], which gave the URL a single owner and made the tag chips clickable. That entry closed on a surface that worked — on a tenth of the corpus. This one is mostly about what a tenth of a corpus hides.

[[Page]] rendered as literal [[Page]] in both spikes. It now resolves through @lossless-group/lfm@0.6.0, published to JSR during this run.

The site supplies two facts and no mechanics: which files exist, and where each vault folder publishes to. Both come from src/lib/content-map.ts, a new single declaration of how a vault folder becomes a site route. That fact had four copies before — the Astro collection's loader base, the import.meta.glob in content-api, the literal /tools/ scattered through pages and the state atom, and the route template a resolver would need — with nothing checking them against each other.

Vault and route are deliberately allowed to differ. Obsidian authors under Tooling/; the site publishes under /toolkit/. Neither name derives from the other, which is exactly why the mapping has to be written down. /tools/ is renamed to /toolkit/ throughout as part of this.

The corpus, at last, entire

tools       173  ->  1,766 pages
verticals    26  ->    148 files, 11 group pages
tags         48  ->    745 pages
total             ->  2,524 pages, built in 10 seconds

scripts/sync-content.sh makes the import repeatable. Content stays vendored — the site has to build from its own repo alone — so this is how the vendored copy gets refreshed. rsync without --delete, deliberately: the three fixtures (empty file, precedence chain, publish: false) are site-owned and have no vault counterpart.

Five defects that a 10% sample could not show

Sixteen wikilinks pointed at pages that do not exist. A page's slug comes from frontmatter slug when present and only falls back to the filename, so Beam.ai.md publishes at /toolkit/beam-ai/ while a filename-derived guess produces beamai. Deriving one slug twice, from two inputs, in two places is the whole bug. content-api now exports the authoritative map and the resolver reads it.

Seven more pointed at /verticals/<company>/. Verticals do not publish one page per file — they group by top-level folder into 11 pages — so every per-entry destination was a 404.

Two of the five featured tags were nearly empty. The corpus drifts in casing: Check-It-Out (256) and Check-it-Out (2) are the same tag typed twice, as are Agentic-AI (127) and Agentic-Ai (8). Keyed by their literal string they became separate facets that then collided on an identical slug, and since one page is built per slug, the last variant won:

/tags/check-it-out/    2 tools  ->  258
/tags/agentic-ai/      8 tools  ->  128

The label was wrong too — "Agentic Ai", the minority spelling. Facets now fold by slug and display the most frequent variant. This is the same disease the wikilink resolver already treats as load-bearing (Tooling 3,572 vs tooling 38) showing up in a second dimension; assume any hand-maintained field here drifts in case.

Every tag page opened unfiltered. The server seeded the island correctly, so the static HTML was right. Then hydrateFromUrl found no ?tags= param and set the shared atom to [], and the atom-to-local bridge wiped the seed. The fix gave pendingSlug — flagged in the handoff as written and never read — an actual consumer. The dead variable had been holding the answer the whole time.

A drive assertion was silently invalid at scale. The chip drive counted rendered cards, but the explorer pages at 48 and AI-Toolkit covers 514 of 1,765 tools, so a working filter leaves a full page full. It reported a false failure for a feature that was fine.

The landing page leads with filters

The headline is now "The tools we've found worth saving…", and the hero carries five curated calls to action: AI-Toolkit (514), Check-It-Out (258), Agentic-AI (128), Founder-Toolkit (81), Must-Have (47). Counts are read from the live facets rather than typed in, so a content sync cannot make them stale and a tag that leaves the corpus drops out rather than becoming a dead link.

On verification

Every defect above passed pnpm build. Four of five passed curl as well — the static HTML was correct and only the hydrated view was wrong. That is the same lesson the spike session ended on, and it held.

Counting things is not enough either. The first check of the tag-page fix counted cards and declared the filter broken; it was measuring a page cap. tests/tag-page-drive.mjs now compares rendered titles against the authoritative set in /api/tools.json, which is true at any corpus size.

Final state: 437 unique wikilink targets with zero missing, 991 resolved links, zero literal [[...]] in output, for_clients absent from all output, 18 unit tests and three browser drives green.

  • [[2026-08-23_03]] — the URL owner and the chips, which this builds on

  • [[2026-08-23_01]] — the opening explorations