Skip to content

Latest commit

 

History

History
292 lines (251 loc) · 16.7 KB

File metadata and controls

292 lines (251 loc) · 16.7 KB

Maintainer's quickstart

Implementation status: introduced by spec-v10 §I.1.

One page. Every recurring task a maintainer performs and the command for each. Read top to bottom for orientation; jump by section header for routine work.

Repo layout (one-line orientation)

The site is one index.html, one styles.css, one app.js, a service worker (sw.js), per-group calc modules (calc-*.js), and a sharded data/ folder. Specs live in specs/. Per-area docs live in docs/. Build / lint / data scripts live in scripts/. Tests live in test/unit/ and test/integration/.

Recurring tasks

"I want to ship a new tile"

  1. Pick the group (A through Y per ../README.md; v12 added U Veterinary / V EMS / W Pilots / X Real Estate / Y Educators on top of A-T) and the next utility number per the active spec.

  2. Implement the exported compute<Name> function plus its renderer and a <NAME>_RENDERERS["id"] = render<Name> registration in calc-<group>.js (or the group's shared module). Put a // dims: annotation immediately above the exported compute function (the Phase C dimensional-analysis lint requires one per exported function), and export a <name>Example object.

  3. Wire the tile into the registries (each is a one-line add; the lint gates below enforce that none is missed):

    • { id, name, group, trades, desc } row in the TOOLS array in ../tools-data.js (the catalog registry, lazy-loaded out of app.js per spec-v17 §H.2 -- NOT in app.js).
    • [id, group] row in _TILES in ../tile-meta.js.
    • the tile id in the matching declare("./calc-<group>.js", "<NAME>_RENDERERS", [...]) list in ../tool-modules.js (the tile-id to renderer registry, lazy-loaded out of app.js per spec-v10 §§H.1/H.2 -- NOT in app.js; the check-wiring lint fails if a TOOLS id has no declared renderer).
    • { module, fn } entry in ../test/fixtures/compute-map.js.
    • a 3-6 id entry in ../scripts/related-tiles.mjs (check-related-tiles).
    • the tile id in ../test/fixtures/renderer-schema-coverage.json if the renderer exposes a field schema -- declarative _simpleRenderer tiles DO, bespoke hand-written renderers do not (check-renderer-schema ratchets this list and fails on a regression).
    • 3-5 search aliases in ../data/search/aliases.json (check-discoverability; terms must be unique catalog-wide).
    • Confirm the tile enters through the shared renderToolView path, which is its mandatory third door after the website and local MCP surfaces and adds Report a problem without per-tile code (check-feedback-loop).
  4. Add tests + fixtures:

    • At least one worked-example fixture row in ../test/fixtures/worked-examples.json (the spec-v10 Phase C.1 registry; coverage is enforced by scripts/check-worked-examples.mjs in npm run lint).
    • A test() block in ../test/unit/bounds-fuzzer.test.js pinning the worked example (both directions / unit systems where the tile solves both) and the degenerate-input error seams. This is the current per-tile cross-check + bounds-fuzzer coverage row the Phase D lint requires; the older ../test/unit/first-principles.test.js still runs but recent tiles pin in bounds-fuzzer.
    • Edge cases: zero, negative, max, missing input.
  5. Add the inline entry (formula / edition / freeAccess / governance) in ../citations.js -- check-citation-coverage fails on a TOOLS id with no CITATIONS row.

    Add a source-stamp row to citation-discipline.md only for a bespoke, hand-written renderer. build-citation-strings --check reads each row back out of the renderer it names, and it finds the literal by locating function render<Name> and matching the citationEl.textContent assignment inside it. A declarative _simpleRenderer tile has no such function -- its citation lives in the spec object -- so a row added for one fails the gate with "no citation literal found in its renderer". Every band since the declarative factory arrived has (correctly) left those tiles out of that table; citations.js is where their wording is reviewed.

  6. Regenerate the derived artifacts, in this order -- several read each other's output, and extract-citations reads a file the build emits, so running it early leaves renderer-citations.js stale and the count oscillates:

    node scripts/build-corpus.mjs
    node scripts/build-tile-index.mjs
    node scripts/build-field-index.mjs
    node scripts/build-alias-shards.mjs
    node scripts/extract-constant-notes.mjs
    node scripts/extract-bespoke-schemas.mjs --write
    node scripts/build-renderer-map.mjs
    npm run build
    node scripts/extract-citations.mjs --write   # LAST, after the build
    

    The --check forms of these run in npm run lint. Update the affected data/<folder>/manifest.json (edition, asOf) and run npm run data:refresh only if the tile uses a bundled dataset.

  7. Run the full gate: npm run audit (ten stages: lint -> test -> build -> check:dist -> check:shells -> check:module-sizes -> check:shell-values -> check:lastmod -> data:verify -> check:data-stamps, per spec-v12 §G.3 + spec-v13 Phase G). Update the catalog counts in all four files the check-readme-counts gate reads -- ../README.md, ../index.html (both the JSON-LD description and the home lede), ../AGENTS.md, and ../mcp/README.md -- covering the tile, module, group, and sitemap totals including the Mermaid-diagram nodes.

    Then update the count that no lint gate watches: ../test/integration/search-prefill.test.js asserts the home lede's tile count as a literal string. npm run lint stays green when it is stale and the failure surfaces ~15 minutes into npm run test:e2e, so change it in the same pass as index.html rather than discovering it later.

  8. Add a CHANGELOG stanza under "Unreleased" naming the tile, the group, the citation, and the worked example.

  9. Per-module gzipped-size check: enforced by ../scripts/check-module-sizes.mjs (part of npm run lint). Each calc-*.js module carries an explicit cap (current v12 caps in performance.md §"v12 per-module budgets"); the lint warns within 10 % of cap. The spec-v10 §H.1 5 KB per-tile cap remains the design target for the tile's contribution to its module.

  10. Group X (Real Estate) and Group Y (Educators) tiles use cite-strong governance verbiage in the source-stamp rather than a limitation banner. (Groups U, V and W are retired; the banner override this step used to describe applied to them.) The Phase F.2 mobile-responsive sweep at 320 / 375 / 414 / 760 px per mobile-responsive.md is required for every new tile.

"I want to review calculator problem reports"

Use calculator-reports.md. Quick version:

  1. Query open rows from roughlogic-reports through authenticated Wrangler.
  2. Reproduce from the saved URL, inputs, and output.
  3. Verify against the primary source and fix through the normal spec-first path.
  4. Mark the row resolved or wont_fix with a short audit note.
  5. Remove rate-counter buckets older than 14 days.

"I want to roll a code edition"

Use edition-rollover.md. Quick version:

  1. scripts/sources-cycle.json — bump the standard's edition.
  2. npm run lint — work through the warnings.
  3. Per-tile citation strings + per-folder manifest editions.
  4. CHANGELOG stanza per standard rolled.

"I want to ship a mid-cycle amendment"

Use edition-amendment.md. Quick version:

  1. Triage: language only, math correction, or parallel jurisdiction.
  2. Update citation; for a math change, update calc + worked- example fixture.
  3. CHANGELOG patch stanza naming the publisher reference.

"I want to retire a tile"

The 90-day deprecation per spec.md §10:

  1. Add a CHANGELOG entry naming the tile, the planned removal date (today + 90 days), and the rationale.
  2. Add a soft notice in the tile's renderer: "Scheduled for removal on YYYY-MM-DD."
  3. Wait 90 days.
  4. Remove the tile from the TOOLS array in ../tools-data.js and from the declare(...) renderer list in ../tool-modules.js.
  5. Add a URL-hash redirect in ../routing.js so stale bookmarks land on the closest replacement (or home, with a banner).
  6. Remove the calc renderer, the unit tests, and the citation row.
  7. CHANGELOG entry recording the removal.

"I want to update bundled data"

  1. Edit the canonical inline source in ../scripts/build-data.mjs (this is the build-time owner of every shard's content).
  2. npm run data:refresh — regenerates the shards on disk and re-stamps scripts/expected-hashes.json.
  3. npm run data:verify — confirms every shard hash matches.
  4. Bump the affected data/<folder>/manifest.json asOf and per-entry verifiedOn dates.
  5. CHANGELOG stanza naming the dataset and the source.
  6. Run the full gate (npm run audit).

"I want to refresh the WMM coefficient bundle"

WMM rolls every 5 years. The check-citation-freshness lint warns within 6 months of expiry and hard-fails after.

  1. Download the new WMM coefficients from ncei.noaa.gov/products/world-magnetic-model.
  2. Update the bundled coefficients at ../data/field/wmm/coefficients.json (the v9 §F.1 magnetic-declination tile's shard; the ../data/field/manifest.json edition line records the cycle).
  3. Update ../scripts/sources-cycle.json: bump current_edition, current_release, expires_on.
  4. Update the manifest edition string.
  5. Add WMM round-trip worked-example tests for at least three known declination values from the new coefficient set.
  6. CHANGELOG stanza naming the cycle (e.g., WMM2025 → WMM2030).

"I want to commission an outside review"

Annual minimum per spec-v10 §14. Append a row to audit-trail.md with date, reviewer, scope, and outcome. The audit trail is append-only and public.

Standard commands

Command What it does
npm run dev Builds dist/, then serves only that public tree on loopback.
npm run build Produces dist/ for deployment.
npm test Recursively discovers the full test/unit/ suite with Node's test runner; no shell-specific globbing.
npm run test:unit Same as npm test.
npm run test:e2e Playwright integration tests.
npm run test:a11y axe-core accessibility tests.
npm run lint grep checks, ngram bans (fingerprint-based; skips in the public repo, where the private hash list is absent), v6 discipline, v8 manifest discipline, v10 citation freshness, citation-strings sync check, discoverability, worked-examples coverage, tile-meta coverage, v12 G.2 wiring + G.4 renderer-export lints, module sizes, home payload budget.
npm run check:dist spec-v12 G.3 dist/-vs-runtime cross-check. Walks every shipped HTML / JS / CSS / JSON under dist/ and resolves every same-origin reference; dangling references fail. Wired into npm run audit as the fourth stage.
npm run data:refresh Run the data pipeline. Regenerates shards and expected-hashes.json.
npm run data:verify Verifies shard SHA-256 hashes against expected-hashes.json.
npm run lint (includes check-verified-on-ledger) Fails if a shard named in scripts/sources-cycle.json is missing verified_on, or carries one that differs from the oldest last_verified among the rows naming it. verified_on is a claim about research and belongs to the ledger; fetched is a fact about the build and moves freely. Do not hand-edit a tracked shard's verified_on -- update the ledger row and re-run npm run data:refresh.
npm run lint (includes check-future-stamps) Fails if any provenance stamp (verified_on, last_verified, _updated, fetched, asOf, built, generated, derived_at) in data/**, test/fixtures/worked-examples.json or scripts/sources-cycle.json is dated after tomorrow in UTC. A stamp records when the project looked, so a date that has not arrived records a look that has not happened -- on 2026-09-18 fifty worked-example rows claimed verification on 2026-09-19 through 09-22. It is the one clock comparison that cannot turn main red on its own: a stamp that passes today passes on every later day. Stamp the date the work was actually done.
npm run check:data-stamps Fails if any data/**/*.json provenance stamp (verified_on, fetched, asOf, built, a date-shaped manifest version) moves backwards against the base branch tip. Catches a stale data-refresh branch, which would otherwise revert hand-corrections while every other gate stays green. Needs git history, so CI runs it as its own step rather than inside lint; set DATA_STAMP_BASE to compare against a specific ref. A base stamp dated after tomorrow may move back -- that corrects an impossible date rather than reverting research. It fails if that ref resolves to HEAD, because an empty comparison reported as OK is how it was blind for its first day in CI.
npm run clean Removes dist/.
npm run audit Single-shot pre-PR gate (spec-v10 §2 / §14; ten stages): chains lint -> test -> build -> check:dist -> check:shells -> check:module-sizes -> check:shell-values -> check:lastmod -> data:verify -> check:data-stamps with per-stage banners. Short-circuits on first failure. The count and the chain are gated by check-ci-claims, which compares this sentence to scripts/audit.mjs.

Per-release ritual

For every minor or patch release:

  1. npm run audit — must report all 10 stages OK (lint -> test -> build -> check:dist -> check:shells -> check:module-sizes -> check:shell-values -> check:lastmod -> data:verify -> check:data-stamps).
  2. Confirm home-view payload is under cap (current check-home-payload budget: 100 KB gzipped, with the v10 §H.2 per-asset sub-budgets HTML 20 KB / CSS 25 KB / JS 45 KB enforced by npm run lint).
  3. CHANGELOG stanza: dated, lists every change, names every tile touched.
  4. package.json version bump per semver: patch for bug fixes and data refreshes, minor for new tiles or new platform features, major only with 90-day deprecation notice.

Performance budgets at a glance

Asset Budget
Home-view total (gzipped) 100 KB (HTML 20 / CSS 25 / JS 45 KB sub-budgets per spec-v10 §H.2)
Per-module dynamic-imported calc-*.js (spec-v12 §14.3 caps) enforced by ../scripts/check-module-sizes.mjs; live caps in performance.md. spec-v10 §H.1 5 KB-per-tile remains the design target.
First Contentful Paint (slow-3G) 1.5 s
Largest Contentful Paint (slow-3G) 2.5 s
Total Blocking Time 200 ms
Cumulative Layout Shift 0.05

Hard rules (do not break)

  • Calculator execution is 100% client-side with no account, analytics, or AI. The sole hosted write path is the isolated, user-initiated report Worker; persisted invocation logs are disabled and D1 records expire after 30 days.
  • No localStorage / sessionStorage / cookies / IndexedDB beyond rl-theme. URL hash is the only state mechanism. (The rl-bigbuttons key was retired in spec-v11.)
  • CSP default-src 'self', connect-src 'self', worker-src 'self'.
  • WCAG 2.2 AA, 48 px touch targets, single h1, voice input.
  • No emojis, no em-dashes, no decorative icons in shipped UI.
  • Plain ASCII in source-stamp strings.
  • 90-day deprecation for any utility removed or formula changed.

See also