the MEASURED CITY
ALTITUDE 3½ — the same city as sheet 3, surveyed by mass · 52 members in 4 districts, footprint ∝ √sloc, height ∝ authored files, spec mass drawn as an annex, gate severity in colour · counted at origin/main @ 3f55e419 (2026-10-31)
STRUCTURE SCHEDULE — authored source per member · files · sloc · spec annex · gate tier
| # | member | files | sloc | annex files | annex sloc | gate tier | note |
|---|---|---|---|---|---|---|---|
| 1 | lit-ui-router | 25 | 3,262 | 33 | 9,354 | the material | the subject of this set · annex 2.9× the source |
| 2 | ui-router-server | 21 | 3,006 | 26 | 6,856 | the material | the server adapter · annex 2.3× |
| 3 | lit-ui-router-mobx | 5 | 144 | 4 | 579 | the material | the mobx companion · annex 4.0× |
| 4 | navigation-location-plugin | 2 | 214 | 7 | 1,064 | the material | the location seat, core's pushStateLocation swapped out · annex 5.0× |
| 5 | sample-app-shared | 44 | 2,582 | 8 | 883 | the material | the routes + views every sample app mounts |
| 6 | sample-app-lit-vanilla | 8 | 428 | — | — | the material | the plain-lit demo |
| 7 | sample-app-lit-mobx | 8 | 450 | — | — | the material | the mobx demo |
| 8 | sample-app-routes | 7 | 104 | 4 | 392 | the material | the shared route table, server-side too |
| 9 | sample-app-lit-e2e | 9 | 425 | 12 | 860 | STOPS THE PR LINE | cypress · drives the docs build |
| 10 | docs | 21 | 2,153 | 10 | 1,309 | the material | vitepress + the worker that serves it |
| 11 | examples | 33 | 5,915 | 1 | 74 | the material | stackblitz-ready copies, own lockfiles |
| 12 | @tools/release | 54 | 2,772 | 24 | 3,027 | HALTS A PUBLISH | hosts published-diff — the one publish halt |
| 13 | @tools/typedoc-plugin | 2 | 350 | — | — | never gates | builds the API pages, gates nothing |
| 14 | @tools/dts-backtest | 9 | 619 | — | — | STOPS THE PR LINE | 9 files · 619 lines hold the TS 5.0 floor |
| 15 | @tools/build_and_test | 15 | 2,933 | 7 | 3,343 | never gates | the CI graph helper — and its error summary |
| 16 | @tools/shared | 11 | 516 | 8 | 527 | never gates | the library under the instruments |
| 17 | @tools/workers-builds | 7 | 889 | 3 | 1,153 | gates a later stage | the docs deploy watch |
| 18 | @tools/bundle-probe | 6 | 535 | 3 | 216 | never gates | size probe, advisory |
| 19 | @tools/compat-guards | 11 | 540 | 3 | 556 | STOPS THE PR LINE | the lit 2 / mobx 6 / peer-floor lanes |
| 20 | @tools/oxc-emit | 6 | 487 | 3 | 284 | the material | both build passes, one emitter |
| 21 | @tools/release-config | 2 | 122 | 1 | 255 | the material | the shared release-it config |
| 22 | @tools/lit-template-lint | 3 | 151 | 1 | 46 | never gates | the lit-analyzer wrapper |
| 23 | @tools/lit-test-env | 4 | 366 | 2 | 336 | STOPS THE PR LINE | the browser harness every suite loads |
| 24 | @tools/vue-check | 1 | 36 | — | — | never gates | vue-tsc over the docs components |
| 25 | @tools/lcov-rebase | 2 | 30 | 1 | 30 | never gates | coverage path rewriting |
| 26 | @tools/happy-dom | 2 | 14 | 1 | 59 | STOPS THE PR LINE | the node-side DOM the unit suites run in |
| # | member | files | sloc | annex files | annex sloc | gate tier | note |
|---|---|---|---|---|---|---|---|
| 27 | @tools/wintercg-globals | — | — | — | — | types only — not massed | ambient types only — nothing to mass |
| 28 | @tools/lint-elements | — | — | 1 | 33 | STOPS THE PR LINE | the custom-element rules as an oxlint jsPlugins config the root extends |
| 30 | @tools/eslint-ts-parser | 1 | 1 | — | — | never gates | a one-line parser shim — the smallest thing in the yard |
| 31 | eslint-plugin-lit-ui-router | 12 | 1,481 | 13 | 2,560 | the material | vendored uiSref lint rules · annex 1.7× |
| 32 | @tools/embed-heights | 3 | 354 | 1 | 53 | never gates | docs embed heights, measured in Chromium — outside ci |
| 33 | @tools/bootstrap | 3 | 58 | 3 | 107 | never gates | zero-dep manifest reads — the one thing that runs before pnpm install |
| 34 | @tools/eslint | 5 | 254 | 1 | 157 | never gates | the repo rule plugin, the complexity ceiling and the Actions formatter root eslint.config.ts composes |
| 35 | @tools/repo-checks | 15 | 1,532 | 12 | 1,464 | STOPS THE PR LINE | graph edges, inputs, versions, coverage, patches, deps |
| 36 | sample-app-lit-effect | 9 | 473 | — | — | the material | the effect demo — the fourth app shell the docs site serves |
| 37 | lit-ui-router-effect | 4 | 285 | 5 | 1,093 | the material | the effect bindings · annex 3.8× |
| 38 | lit-ui-router-ssr | 18 | 1,485 | 24 | 5,085 | the material | the prerender bridge · verdicts in, @lit-labs/ssr pages out · annex 3.4× |
| 39 | @tools/crap | 2 | 124 | 1 | 78 | never gates | CRAP hotspots from coverage — reports, gates nothing |
| 40 | @tools/oxlint-anti-slop | 35 | 3,665 | — | — | never gates | the vendored anti-slop rules every oxlint lane loads |
| 41 | lit-ui-router-signals | 4 | 170 | 4 | 855 | the material | the signals bindings · annex 5.0× |
| 42 | ui-router-signals | 4 | 104 | 2 | 185 | the material | the framework-agnostic signal mirror · annex 1.8× |
| 43 | ui-router-effect | 3 | 30 | 2 | 62 | the material | the framework-agnostic SubscriptionRef · annex 2.1× |
| 44 | @repo/route-snapshot | 1 | 45 | 1 | 65 | the material | private · inlined into each consumer's dist by oxc-emit · annex 1.4× |
| 45 | sample-app-lit-signals | 8 | 465 | — | — | the material | the signals demo — no test script, the fifth app shell the docs site serves |
| 46 | @tools/a11y | 5 | 491 | 3 | 213 | never gates | axe over the docs pages and app mounts — acceptance, gates nothing |
| 47 | ui-router-mobx | 3 | 117 | 2 | 143 | the material | the framework-agnostic MobX store · annex 1.2× |
| 48 | @tools/ci-logs | 4 | 404 | 3 | 440 | never gates | a CI run's task logs fetched into one file — run by hand, gates nothing |
| 49 | @repo/dev-gate | 2 | 3 | 1 | 24 | the material | private · both halves of each package's #dev-gate import, inlined by oxc-emit · annex 8.0× |
| 50 | ui-router-registry | 5 | 362 | 3 | 63 | the material | typed state names and params · types only · annex 0.2× |
| 51 | @tools/release-ledger | 2 | 516 | 2 | 588 | never gates | the ledger's model — one fold over npm and GitHub |
| 52 | release-diffs | 2 | 14 | — | — | the material | a worker that answers 404 · no test script |
| 53 | release-ledger | 9 | 1,491 | 8 | 2,203 | the material | OIDC claims in, a D1 ledger of every release out |
TOTAL — 52 members, 50 massed · 477 authored files · 42,967 sloc · plus 254 spec files · 46,674 sloc of annex · counted at origin/main @ 3f55e419 (2026-10-31) (sloc = scc Code)
ROAD REGISTER — NO ROAD IS DRAWN THAT THE REPO DOES NOT CARRY
| road | kind | the edge in the repo |
|---|---|---|
| A | builds into | packages/* → the sample apps · lit-ui-router → 4 of them, ui-router-server → routes |
| B | builds into | @tools/oxc-emit → all twelve published packages · devDep of each · runs build:js + build:types |
| C | tests exercise | @tools/dts-backtest → the runtime packages it deps on, and ui-router-registry · #test dependsOn ^build |
| D | tests exercise | @tools/lit-test-env + @tools/happy-dom → the annex · devDep of lit-ui-router + -mobx |
| E | tests exercise | sample-app-lit-e2e → docs · workspace dep · e2e dependsOn ^build, with @www/lit-ui-router.dev#wrangler:dev |
| F | typecheck reads | lit-ui-router src AND specs → docs · tsconfig include src/** · turbo dependsOn ^build:types |
| G | library under | @tools/shared → @tools/release · one of 24 dependents; only this road is drawn |
apps → docs is road A continued: docs depends on three sample apps and on ui-router-server
GENERAL NOTES
Method — one basis, two series. Every count on this sheet is read at build time from the checked-in plate www/, counted at origin/main @ 3f55e419 (2026-10-31): .ts/ under each member's source directory, excluding *.d.ts, *.test-d.ts, fixtures, dist/ and node_modules/; sloc is scc's Code count — string-aware, so the interior of a template literal counts as code rather than as one line. Sheet 3 throws test code away; this sheet does not — anything matching *.{spec,test,cy}.* or living under specs/ is counted into a second series and drawn as that member's annex. 52 members: 477 authored files and 42,967 sloc of source, plus 254 files and 46,674 sloc of spec. The packages district's 14 buildings reconcile exactly with sheet 3's source slab — 109 files, 10,708 lines — because both are queries over one census rather than two hand counts.
Every shipped building but ui-router-registry carries an annex bigger than itself. lit-ui-router: 3,262 authored lines against 9,354 of spec (2.9×). ui-router-server: 3,006 vs 6,856 (2.3×). lit-ui-router-mobx: 144 vs 579 (4.0×). eslint-plugin-lit-ui-router: 1481 vs 2560 (1.7×). lit-ui-router-effect: 285 vs 1093 (3.8×). lit-ui-router-ssr: 1485 vs 5085 (3.4×). navigation-location-plugin: 214 lines in 2 files under 7 spec files (5.0×). lit-ui-router-signals: 170 vs 855 (5.0×). ui-router-signals: 104 vs 185 (1.8×). ui-router-effect: 30 vs 62 (2.1×). ui-router-mobx: 117 vs 143 (1.2×). ui-router-registry is types only: 362 lines against a 63-line fixture (0.2×), because its tests are *.test-d.ts type assertions, which the census leaves out. The test budget lives exactly where the repo says it should — in packages/, and nowhere else at that ratio.
Every road is citable. Solid roads are build edges: packages/ into the sample apps, the apps into docs, @tools/ into all twelve published packages — each a workspace: dependency, each backed by turbo's build/docs tasks depending on ^build. Dashed soft roads are the test lane: @tools/ depends on the runtime packages of the district and backtests their emitted d.ts against the TS 5.0 floor; @tools/ and @tools/ run up into lit-ui-router's annex because they are its devDependencies and the harness its suites load; sample-app-lit-e2e depends on docs, and turbo's e2e depends on ^build and runs with @www/, so Cypress drives the built shopfront under its worker rather than a vite dev server. The accent road is the one that leaves a member twice — once from the source block and once from the spec annex — because the package's typecheck reads both: tsconfig.json includes src/, specs and all (only the narrower typecheck:src excludes them), while the ^build:types dependency is what carries the result into the next district. One faint road stands for 24: that many members depend on @tools/, 17 of them instruments, and its src/ (#655) holds the custom-element glob three lanes share. Only the road to the largest is drawn, because drawing all 24 would turn the yard into hatching.
Severity in colour, mass in geometry — and they disagree. The tiers are sheet 3's, applied to whole members: @tools/ is solid red because it hosts published-diff, the only structure that halts a publish; red hatch marks the seven members that can stop a pull request — Cypress e2e, dts-backtest, compat-guards, lit-test-env, happy-dom, lint-elements, whose eslint lane runs at --max-warnings 0, and repo-checks, whose six checks — graph edges, task inputs, single version, patches, knip and dedupe — ride the lint lane; accent hatch marks @tools/, which gates the docs deploy and nothing earlier. Here the two encodings happen to agree once, on release, and disagree everywhere else: the harness that can stop every pull request in the repo is 14 authored lines of @tools/, sitting on the drawing's minimum footprint.
What the districts say. The product is 14 modest buildings — 10,708 lines — against 17,759 in the instrument yard and 4,927 in the proving ground. The broadest source block on the sheet is examples — 5,915 lines of stackblitz copies — with @tools/ just behind at 3,665 and sample-app-shared, which ships to nobody and gates nothing, undefined at 2,582; two spec annexes outbuild examples. @tools/ is drawn on the floor with no mass at all: it is ambient types, and a census that hides its empty members is not a census.
Numbers by import, not by paste. Every count above and on the drawing is read from www/, the snapshot census-city.mjs writes out of the master per-file census; this module holds placement, tiers and prose only. The plate is measured at a named ref rather than at whatever a working tree happens to hold — counted at origin/main @ 3f55e419 (2026-10-31) — so every number here is citable to a committed file, and a member the sheet draws but the plate does not carry is a build error rather than a stale constant.
KEY
| a member, massed — footprint ∝ √sloc, height ∝ files | |
| its spec annex — the test mass, same rule | |
| halts a publish (@tools/release) | |
| stops the PR line | |
| gates a later stage (the docs deploy) | |
| never gates — reporters, libraries, the material | |
| builds into — a workspace dep feeding a build | |
| tests exercise — harness in, backtest out | |
| typecheck reads — from src AND annex | |
| library under the instruments | |
| district (workspace glob) |