๐ Testing Dashboard & Enforcement System
โYou read a scroll labeled TEST ENFORCEMENT SYSTEM. You feel a sense of discipline.โ
Overview
This project implements mandatory test logging with a visual dashboard to track test quality over time and prevent regressions. Itโs like the Rogue Monitor, but for your code quality.
The Oracle says: โA test not logged is a bug waiting to happen. Choose your commits wisely, for they shall be measured.โ
See also: docs/PARITY_TEST_MATRIX.md โ the canonical reference for what parity means operationally: test commands, session categories and counts, comparison channels, deterministic controls, and quality gates.
โ Official Test Run Paths
Use these as the canonical commands:
npm run test:unit # unit tests
npm run test:e2e # end-to-end browser tests
npm run test:session # C-parity session tests
Session-parity coverage (C-grounded coverage signal):
npm run coverage:session-parity
Notes:
- This coverage run is intentionally based on session replay only.
- Default scope is gameplay sessions (
--type=gameplay). - Report output is written to
/coverage/index.htmland/coverage/coverage-summary.json.
Aggregate commands:
npm test # unit + session
npm run test:all # unit + session + e2e
Session tests can include many logical subtypes (chargen, map, gameplay,
special, interface, options), but they all run through one path:
npm run test:session (test/comparison/sessions.test.js).
Runtime Guardrails
Fast feedback is required to catch hanging bugs early:
- Unit tests run with a strict
1000msper-test timeout. - Individual session replay runs use a strict
10000msper-session timeout by default.
๐ฏ Two Approaches Available
You see here two scrolls:
a) Git Notes Approach โญ (blessed)
Authoritative data: Git notes attached to commits Dashboard data: Mirrored JSONL (one commit behind)
Advantages:
- โ One commit per change (clean dungeonโฆ er, history)
- โ Notes can reference commit hash (the Amulet of Yendor of testing!)
- โ Test data travels with commits (like a bag of holding)
- โ Canโt forget (enforced by hooks, like a shop lock)
Documentation: docs/TESTING_GIT_NOTES.md
This scroll appears to be blessed. Would you like to read it? [yn]
b) Two-Commit Approach (uncursed, but dusty)
All data: In oracle/results.jsonl Workflow: Code commit + test log commit
Advantages:
- โ Simple (no git notes to manage)
- โ All data in one file (like a scroll of identify)
Disadvantages:
- โ Two commits per change (double movement speed, but youโre burdened)
- โ Cluttered git history (like a pack ratโs inventory)
- โ Easy to forget second commit (oops! You forgot to pray!)
Documentation: TESTING.md
This scroll looks old and worn. It might still work, but the blessed one is shinier.
๐ Quick Start (Git Notes)
The scroll reads: โSpeak these incantations to summon the Testing Daemonโฆโ
1. Enable Git Hooks & Configure Auto-Push
# Engrave Elbereth... er, enable hooks
git config core.hooksPath .githooks
# Auto-push notes with commits (like a wand of teleportation for your data)
git config --add remote.origin.push '+refs/notes/test-results:refs/notes/test-results'
# setup.sh now configures merge.keepnewest automatically for:
# _data/version.yml and js/version.js
# If needed manually:
# git config merge.keepnewest.name "keep higher version counter"
# git config merge.keepnewest.driver "bash scripts/git-merge-keepnewest.sh %O %A %B"
You feel your repository becoming more disciplined.
2. Make Changes & Commit
Use the magic helper scroll for easy workflow:
# Edit files (apply a blessed +1 fix to your code)
vim js/levels/themerms.js
# Commit with automatic testing (cast "test and log"!)
.githooks/commit-with-tests-notes.sh "Fix reservoir sampling" js/levels/themerms.js
# Push (ascend with the Amulet!)
git push
The voice of the Oracle echoes: โYour tests have been logged. The dashboard shows 137 passing tests. This is a good thing.โ
Thatโs it! The scroll of commit-with-tests handles:
- โ๏ธ Committing your code (mixing the potion)
- ๐ฌ Running tests and saving to git note (identifying the potion)
- ๐ Syncing notes to results.jsonl (updating your conduct)
- ๐พ Committing the updated JSONL (engraving Elbereth)
- โจ Ready to push! (ascending the stairs)
๐ View Dashboard
The Oracleโs Chamber (GitHub Pages):
https://davidbau.github.io/mazesofmenace/oracle/
A mysterious force prevents you from accessing this until you push to GitHub.
Local Divination:
open oracle/index.html
You gaze into the crystal ball and see the future of your test suiteโฆ
๐ฏ Key Features
Test Enforcement
The Wizard of Yendor enforces these rules:
- โ No regressions allowed - Passing tests canโt become failing (like the Amulet, they must not be lost!)
- โ Every commit logged - Test results tracked in git notes + JSONL mirror (your conduct is recorded)
- โ CI verification - GitHub Actions enforces test logging (the Wizard is watching)
- โ Pre-push protection - Local hook prevents bad pushes (trapped door!)
Violate these, and thou shalt not pass!
Dashboard
The Oracleโs crystal ball reveals:
- ๐ Timeline visualization - Pass/fail trends over commits (your ascension progress)
- ๐ Category breakdown - Tests grouped by type (map, gameplay, chargen) (like monster classes)
- ๐ Commit scrubber - Navigate through history (time travel via level teleport)
- โ ๏ธ Regression highlights - Visual warnings for test quality drops (cursed items blink red!)
- ๐ Detailed table - Recent commits with deltas (your score and conduct)
๐ Inventory
You are carrying:
oracle/
โโโ index.html # a) blessed scroll of Dashboard UI
โโโ dashboard.js # b) wand of Visualization (0:โ)
โโโ dashboard.css # c) cloak of Styling [+0]
โโโ results.jsonl # d) Book of Test History (mirrored from notes)
โโโ schema.json # e) scroll labeled "LOG FORMAT"
.githooks/
โโโ pre-push-notes # f) magic trap (triggers on push)
โโโ pre-commit # g) squeaky board (sync notes โ JSONL)
โโโ test-and-log-to-note.sh # h) wand of Testing
โโโ sync-notes-to-jsonl.sh # i) ring of Synchronization
โโโ commit-with-tests-notes.sh # j) blessed scroll of Easy Workflow
โโโ pre-push # k) dusty magic trap (legacy)
โโโ test-and-log.sh # l) old wand of Testing (uncharged)
โโโ commit-with-tests.sh # m) worn scroll (legacy)
โโโ README.md # n) scroll of Hook Documentation
docs/
โโโ TESTING_GIT_NOTES.md # o) spellbook of Git Notes โญ
โโโ TESTING.md # p) old spellbook (still readable)
.github/workflows/
โโโ test-enforcement.yml # q) Scroll of GitHub Actions
Your pack weighs 0 zorkmids. You are not burdened (everything is in git!)
๐ How Git Notes Workflow Works
The Oracle explains with a diagram:
graph LR
A[๐ Edit Code] --> B[๐พ Commit Code]
B --> C[๐งช Run Tests]
C --> D[๐ Save to Git Note]
D --> E[๐ Sync Notes โ JSONL]
E --> F[๐ฟ Commit JSONL]
F --> G[๐ Push Both]
The Chicken-and-Egg Problem (a.k.a. The Paradox of Temporal Causality)
Problem: โHow can a commit name itself ere it exists? โTis like trying to eat a cockatrice corpse before thou hast slain it!โ
A commit canโt contain its own hash in a file because the hash doesnโt exist until after the commit is created.
Solution: Git notes! โThe Wizards of old solved this with a clever trickโฆโ
- Test results stored as notes attached to commits (like name tags on corpses)
- Notes can reference the commit hash (because theyโre attached AFTER the commit exists!)
oracle/results.jsonlis rebuilt from notes (one commit behind for the dashboard)
โA blessed solution indeed! The Wizard approves.โ
Architecture (The Dungeon Layout)
Level 1: Git Notes (Authoritative)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ refs/notes/test-results โ
โ "The vaults where true knowledge is stored" โ
โ โ
โ commit abc123 โ {results for abc123} โ
โ commit def456 โ {results for def456} โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ sync-notes-to-jsonl.sh
โ (A stairway down...)
Level 2: JSONL Mirror
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ oracle/results.jsonl โ
โ "A magical mirror reflecting level 1" โ
โ โ
โ One entry per commit, chronologically sorted โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ GitHub Pages
โ (The astral plane...)
The Oracle's Chamber
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ https://github.io/.../oracle/ โ
โ "Where mortals come to seek wisdom" โ
โ โ
โ ๐ Timeline, Charts, Scrubber โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ Test Log Format (The Scroll of Recording)
JSONL (newline-delimited JSON) - one entry per commit:
{"commit":"abc123","date":"2026-02-11T10:30:00Z","stats":{"total":631,"pass":137,"fail":494},"regression":false,...}
Each line is a complete message. Together they form the Book of Testing.
Benefits (or: Why JSONL is a blessed +2 format):
- โ Append-only (like a !oW scroll - Write Only)
- โ Merge-friendly (sort by date, like sorting gems by value)
- โ Git-friendly (line-based diffs, like counting inventory)
- โ Easy to parse (jq is your friend, like a tame pet)
โ ๏ธ Handling Regressions
The Wizard is displeased. Your test count decreased! Choose thy path:
Path A: Fix the Regression (Lawful)
โThe righteous path. Make things right.โ
# Fix the issue (quaff a potion of restore ability)
vim js/file.js
git add js/file.js
git commit --amend --no-edit
# Re-run tests (pray at the altar)
.githooks/test-and-log-to-note.sh
The Wizard smiles upon you. +1 Wisdom.
Path B: Allow Regression (Neutral, Requires Justification)
โSometimes the greater good requires temporary setbacks. But thou must explain thyself!โ
# Run tests with override flag (eat a cursed scroll knowingly)
.githooks/test-and-log-to-note.sh --allow-regression
# Then follow normal workflow
The Wizard eyes you suspiciously. Youโd better have a good explanation in your commit message!
Example good justification:
Allow regression: fixing core algorithm
The reservoir sampling fix causes 25 test failures because it changes
the RNG sequence. The failures are cascading effects, not actual bugs.
The algorithm is now correct per C source verification. Like killing
the Wizard to get the Book - necessary, but temporarily painful.
Acceptable. -1 Charisma, but +3 Wisdom for being honest.
Path C: Push Anyway (Chaotic, Forbidden)
git push --no-verify # DON'T DO THIS
The Wizard of Yendor appears! โSo thou thought thou couldst cheat?โ โMoreโ
The Wizard casts a spell of CI FAILURE at you! GitHub Actions rejects your push.
You dieโฆ Do you want your possessions identified? [ynq]
๐ ๏ธ Troubleshooting (Common Mishaps)
โTests Not Runningโ (You see here a scroll that does nothing)
# Verify hook setup (check if you're wearing the amulet)
git config core.hooksPath
# Should output: .githooks
# Ensure executable (bless the scrolls)
chmod +x .githooks/*
The scrolls were cursed (not executable)! They work now.
โNotes Not Pushingโ (Your items scatter!)
# Check if notes exist (search the floor)
git notes --ref=test-results list
# Manual push (throw the items upstairs)
git push origin refs/notes/test-results
# Or configure automatic push (hire a pack animal)
git config --add remote.origin.push '+refs/notes/test-results:refs/notes/test-results'
Now your notes follow you everywhere! Like a loyal dog, but for git.
โDashboard Not Updatingโ (The crystal ball is cloudy)
# Rebuild JSONL from git notes (polish the crystal ball)
.githooks/sync-notes-to-jsonl.sh
# Commit and push (present it to the Oracle)
git add oracle/results.jsonl
git commit -m "Rebuild dashboard from git notes"
git push
The mists clear. You see your test results!
โMissing Notes After Cloneโ (You feel empty handed)
# Fetch notes (search the level you just arrived on)
git fetch origin refs/notes/test-results:refs/notes/test-results
# Rebuild dashboard (reconstruct from memory)
.githooks/sync-notes-to-jsonl.sh
You find everything where you left it! (Well, where git left it.)
๐ Scrolls of Knowledge
A library. The shelves are lined with dusty tomes:
- a) Quick Start: This file (you are here!)
- b) Git Notes Workflow โญ blessed
- c) Two-Commit Workflow uncursed (legacy)
- d) Hook Details โHooks, Runes, and Trigger Mechanismsโ
- e) Dashboard Info โThe Oracleโs Crystal Ball Manualโ
- f) Schema โThe Sacred Format of Test Logsโ
Which scroll would you like to read?
๐ฏ The Four Noble Truths of Testing
The Oracle speaks:
- Prevent regressions - โNever let test quality degrade silently, lest bugs multiply like killer beesโ
- Track progress - โVisualize test improvements over time, for what is measured improvesโ
- Enforce discipline - โEvery commit must be tested, as every meal must be eatenโ
- Enable debugging - โHistorical data helps identify when bugs were introduced, like tracking monster movementโ
๐ค Conduct for Adventurers (Contributing)
All who enter the dungeon must follow these rules:
-
Enable git hooks:
git config core.hooksPath .githooksโEquip your armor before battleโ -
Configure auto-push:
git config --add remote.origin.push '+refs/notes/test-results:refs/notes/test-results'โEnsure your achievements are recordedโ -
Run tests before pushing โLook before you leap into the pitโ
-
Never push regressions without explicit justification โDo not anger the Wizard without good reasonโ
-
Use
.githooks/commit-with-tests-notes.shhelper for easy workflow โUse your blessed scroll - why make things harder?โ
Violators will be turned into newts. (They might get better, but probably not.)
โ The Oracle Answers Common Questions
Q: Why git notes instead of files in commits? Oracle: โThe chicken-and-egg problem - a commit cannot name itself ere it exists! Git notes are attached AFTER creation, solving the paradox. โTis like casting identify AFTER picking up the ring.โ
Q: Why is the dashboard one commit behind? Oracle: โThe pre-commit hook syncs notes โ JSONL, so the current commitโs note isnโt synced yet. This is the price of temporal consistency. Fear not - the dashboard shows historical data, not real-time divination.โ
Q: Can I see notes in GitHub UI?
Oracle: โAlas, no. Notes dwell in the shadow plane, invisible to GitHubโs web interface. Use git notes commands or view the dashboard instead.โ
Q: What if I forget to push notes?
Oracle: โConfigure automatic push (see setup above). Then git push carries all - commits AND notes - like a bag of holding for your achievements.โ
Q: What happens on merge? Oracle: โNotes from both branches are preserved, like items from merged inventories. The sync script rebuilds JSONL sorted chronologically. All is well.โ
Q: Can I still use the two-commit approach? Oracle: โAye. Both scrolls work, though one is blessed. See TESTING.md for the ancient way.โ
Q: What if I break the build? Oracle: โThe Wizard will beโฆ displeased. Fix it quickly, or face the wrath of CI. Your shame will be recorded in the dashboard for all to see. This is the way.โ
You read the final line of the scrollโฆ
View live dashboard: https://davidbau.github.io/mazesofmenace/oracle/
The scroll crumbles to dust. You feel enlightened about testing.
Would you like to write your name in the high score table? [yn] y
.githooks/commit-with-tests-notes.sh
=====================================
Your Path to Testing Glory
May your tests always pass, and your merges always be conflict-free.
Happy hacking, adventurer!
๐ฎ Achievement Unlocked
- โ Read the Testing Scroll
- โณ Enable Git Hooks (pending)
- โณ Make First Commit with Tests (pending)
- โณ View Dashboard (pending)
- โณ Survive a Merge Conflict (pending)
- โณ Achieve 90% Pass Rate (pending)
- โณ Ascend (ship v1.0) (pending)
Your current conduct: Testing discipline (not broken). Keep it up!
๐ Backfilling Test History
โThe Oracle can see the pastโฆ if you help her remember.โ
Want to populate the dashboard with historical data? The backfill script runs tests on old commits:
Quick Start
# See what would be tested (dry run)
scripts/backfill-test-history-safe.sh --dry-run
# Backfill last 10 commits (safe, fast)
scripts/backfill-test-history-safe.sh
# Backfill more history
scripts/backfill-test-history.sh 50
# After backfilling, sync and commit
.githooks/sync-notes-to-jsonl.sh
git add oracle/results.jsonl
git commit -m "Backfill test history"
git push origin refs/notes/test-results
How It Works
The backfill script:
- โ Finds commits without test notes
- โ Checks out each commit
- โ Runs tests (if possible)
- โ Creates git note with results
- โ Skips commits where tests donโt work
- โ Restores your original state
Each git note contains only that commitโs results (not cumulative). The JSONL file aggregates all notes for the dashboard.
Safety Features
- Checks for clean working directory
- Restores original branch/commit when done
- Skips commits where tests donโt exist
- Handles npm install failures gracefully
- Logs all results for review
What Gets Skipped
- Commits without test directory
- Commits where npm install fails
- Commits where tests crash
- Very old commits (before tests existed)
This is fine! The backfill is best-effort.