Skip to content

Engagement and model viewer (spec 006, SRD Annex A Part A) - #51

Merged
IanMayo merged 3 commits into
mainfrom
viewer/impl
Oct 17, 2026
Merged

IanMayo merged 3 commits into
mainfrom
viewer/impl

Conversation

@IanMayo

@IanMayo IanMayo commented Oct 17, 2026

Copy link
Copy Markdown
Member

Summary

Implements SRD Annex A Part A, spec 006 tasks T003 to T009. Stacked on #50: this branch contains #50's commit, so merge #50 first.

Browser-safe subpaths (T003, FR-009).

  • New subpaths: @tma/features/browser, @tma/classical/browser, @tma/eval/browser and @tma/data/canonical. They re-export the existing modules with no forks.
  • outputsToPrediction moves from models into features/decode.ts, and models re-exports it. It gains an optional first row, used by the viewer to show pre-zig rows. Goldens are unchanged.

@tma/demos core (T004).

  • Catalogue types and scenario regeneration from a seed.
  • Plan geometry, with a 1–2–5 grid between 100 m and 10 km.
  • Time series and legs.
  • Model inference glue that takes tfjs as a parameter.
  • Classical rows: per-timestep, plus a whole-window batch track for time-late mode.
  • Naive rows, per-row and scenario errors through @tma/eval, URL state, and NDJSON export.

Tests (T005).

  • Browser bundle (FR-001): esbuild for the browser platform, run in a VM. Scenarios and classical rows are byte-identical to Node.
  • Agreement (FR-007): tfjs CPU backend against tfjs-node on the 2c LSTM, 2c BiLSTM and i1 LSTM, to float32 tolerance.
  • Golden view model and server render of all three modes from URLs.

React viewer (T006).

  • Plan view with pan, zoom and a labelled grid. It shows the legs, turn and zig, headings, and observed bearing rays up to the cursor, with optional true bearings.
  • Instantaneous mode adds the estimate trail, a velocity vector and a range ring. Time-late mode adds the model and classical tracks.
  • Plots of range, course, speed, bearing and bearing rate on a shared cursor, with the gate points marked and the pre-zig period labelled unobservable.
  • A readout at the cursor gives truth, model, classical and naive values with their errors. A summary gives the scenario's post-zig medians.
  • Panels show the scenario metadata and the model pair. A note appears when the source is a fresh seed or lies outside the training ranges.
  • Controls: dataset, index, previous, next, random (crypto), bookmarks (featured and saved locally), mode, model pair, overlays, play, and the time slider. PNG and NDJSON export.

Site (T007).

  • The /viewer page loads the viewer browser-only and lazily, with a navbar link.
  • Prebuild builds the catalogue from the four gate experiments' dataset headers, manifests and verdicts. The gate label is the panel decision, so iteration 1 shows "G1 pass".
  • Prebuild copies the eight carried models (4.5 MB) into site/static/viewer/, which is git-ignored.
  • site:build now runs tsc -b first, because the page imports @tma/demos from dist/.

Smoke and post (T008, T009).

  • scripts/viewer-smoke.mjs is a Playwright smoke test of the served page. It passes here with no console errors and every pair runs.
  • The 2c BiLSTM takes 1.08 s, against SC-001's 2 s target. The LSTM takes 0.46 s.
  • Exports were checked in Chromium. The PNG renders. The NDJSON's scenario is byte-identical to the Node generator, and its predictions parse against the schema.
  • The algorithm note site/docs/algorithms/viewer.md explains how the viewer works.
  • The blog post links three views (SC-003): a typical case, the 2c LSTM's largest speed error at zig + 10 min (σ = 1°), and a held-out 26 km case.

Findings from the cases. These illustrate; they do not measure frequency.

  • Jagged time-late track. The BiLSTM's positions form a jagged path, not a constant-velocity track.
  • Worst speed case. The target opens nearly along the line of sight, so speed is weakly observable there. The classical solver also struggles: 13 of its 101 rows do not converge.
  • Held-out range. On the 26 km held-out case, the model's range starts near 18 km, below the truth. Training ranges ended at 20 km.

Bug found and fixed. The site's Babel compiles [...nodeList] to [].concat(nodeList), which broke the PNG export. It now uses Array.from, and the pitfall is recorded in AGENTS.md.

T010, the owner's realism check, remains open.

Constitution check

  • Data types defined only in schema/tma.yaml; pnpm schema:gen run (I): no schema change. The catalogue types describe viewer configuration, not pipeline records (plan, Constitution I).
  • Deterministic: seeded PRNG only; golden files updated deliberately, with the reason stated (II): there is a new packages/demos/test/golden/views.ndjson, and other goldens are unchanged. Inference uses the CPU backend. Random scenario choice uses crypto.getRandomValues and affects no output.
  • sim/features stay pure functions; one CLI per stage; Keras-equivalent layers only (III): they are reused through subpaths, and the decode function moved into features unchanged.
  • Any reported result sits beside naive and classical numbers on the same test set (IV): every model figure in the viewer and the blog post is shown beside classical and naive.
  • Respects the current gate: no training before G0, no scope beyond SRD §1 (V): nothing was trained or scored.

Site pages

  • Glossary entry (site/docs/glossary.md) for any new term: no new term
  • Data dictionary: regenerated automatically from the schema (nothing to edit)
  • Algorithm note (site/docs/algorithms/viewer.md)
  • Blog post (site/blog/2026-10-17-engagement-viewer.md)
  • Not applicable: this PR adds none of the above

Checks

  • pnpm lint && pnpm typecheck && pnpm test && pnpm schema:check && pnpm site:build: all pass, with 302 tests.
  • node scripts/viewer-smoke.mjs against the built site: pass.

Generated by Claude Code

- docs/SRD.md: §7 stop clause lifted (Annex A Part B), hyperparameter cap
  replaced by pre-registration; §4 wall-clock cap replaced by chained CI jobs;
  §6 packages/demos holds the viewer; §8 decision 21 and D1-D3.
- AGENTS.md: gate status (what comes next) and the demos package.
- specs/006-engagement-viewer: spec (V-001..V-018 minus V-014), plan
  (browser-safe subpaths, @tma/demos core + React viewer, site page, tests),
  tasks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv4979qzsScV5ohT5RNUoG
…ost, smoke script

- /viewer page (BrowserOnly, lazy) with navbar link; prebuild writes the
  catalogue from the gate experiments' dataset headers and manifests and
  copies the carried models (4.5 MB) into site/static/viewer (ignored)
- Featured bookmarks from the 2c predictions on seeds 203 and 201 held-out
- Algorithm note and blog post with linked views (SC-003)
- scripts/viewer-smoke.mjs: Playwright smoke of the served page
- PNG export: Array.from, not a NodeList spread (Babel loose mode)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gv4979qzsScV5ohT5RNUoG
@github-actions

Copy link
Copy Markdown
Contributor

Site preview: https://debrief.github.io/Gitma/pr/51/ (updates on every push; removed when the PR closes).

@IanMayo
IanMayo merged commit c8fc0b5 into main Oct 17, 2026
2 checks passed
@IanMayo
IanMayo deleted the viewer/impl branch October 17, 2026 11:03
github-actions Bot added a commit that referenced this pull request Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants