Skip to content

feat(events): richer notedetect:hit/miss payloads for stats plugins - #78

Closed
mattromano wants to merge 1 commit into
got-feedBack:mainfrom
mattromano:feature/77-richer-judgment-events
Closed

mattromano wants to merge 1 commit into
got-feedBack:mainfrom
mattromano:feature/77-richer-judgment-events

Conversation

@mattromano

Copy link
Copy Markdown

What

Closes #77

Every emitted judgment (notedetect:hit / notedetect:miss, both DOM copies, and note:hit / note:miss on the bus, which all share one detail object) now also carries:

Field What
key note id, the same key getNoteState hands back as popKey ("<t>_<s>_<f>" / "<t>_chord")
strings per-string verdicts [{ s, f, hit, centsError, snr?, detectedAt? }]: every chord judgment (engine, scoreChord and browser paths; a missed browser chord reports the best frame the scorer saw in its window) and engine-path single notes (the raw engine verdict). null when nothing was measured
techniques named techniques from the chart note's wire flags (bend, slide, palmMute, hammerOn, …). [] for a plain note
latencyMs / avOffsetMs the compensation already applied to timingError
detector the path that judged it (desktop-engine-verifier, web-yin, …, external)
section the section the note sits in, by chart time (engine verdicts land ~0.4 s late, so the playhead's section would be wrong)
counted / points / multiplier / streak / isDefault score state after the judgment, and which detector instance emitted it

Implementation:

  • _ndEnrichJudgment stamps the fields once in recordJudgment, right before dispatch. It's best-effort and never changes scoring.
  • strings is built at the sites that have the data: _ndFinalizeChordVerdict (each member's engine verdict), the engine single-note drain, and the matchNotes chord hit. The _chordLastResult best-frame snapshot now keeps per-string results for checkMisses' miss and voicing-rescue judgments.
  • The pure helpers _ndTechniqueNames, _ndStringVerdicts and _ndSectionAt are top-level so tests can reach them.

Existing fields are unchanged. README "Events" documents each field plus a small example, and CLAUDE.md's consumer table points to it.

Version bumped 1.32.0 → 1.33.0 in plugin.json, package.json and _ND_VERSION. This collides with #72 and the other open note_detect PRs, which bump to the same version. Whichever merges later needs a one-line re-bump. It's independent of #72 functionally. It shares _ndFinalizeChordVerdict with the fast-chord-runs fix, so expect a small textual conflict.

Tests

  • New test/judgment_events.test.js (4 tests, driving the real detector in the vm harness and capturing the dispatched events):
    • _ndTechniqueNames reads wire flags correctly (sl: -1 / bn: 0 → none)
    • engine partial chord (2 of 3 strings): key, strings with each string's hit/cents/snr/detectedAt, techniques, latencyMs, avOffsetMs, detector, section, counted, points, multiplier, streak, isDefault
    • engine single-note miss carries the raw verdict (cents + SNR)
    • scoreChord-path chord miss retired by checkMisses reports the best frame's strings
    • All 4 fail before the change.
  • npm test: 357/357 pass. node --check screen.js is OK, and feedBack-plugin-spec/tools/validate.py reports ok.

Checklist

  • Tests added/updated for new behaviour
  • README documents the new contract
  • Version bumped in all three places (version_sync.test.js green)
  • Commits are DCO signed off (git commit -s)

🤖 Generated with Claude Code

A stats or scorecard plugin could only get per-string chord results,
technique names, latency or section by patching screen.js. Every
emitted judgment now also carries:

- key: the note id (same as getNoteState's popKey)
- strings: per-string verdicts { s, f, hit, centsError, snr?,
  detectedAt? } for chords on every path (a missed browser chord
  reports its best frame) and for engine-path single notes
- techniques: named techniques from the chart note's wire flags
- latencyMs / avOffsetMs, detector, section (by note time)
- counted, points, multiplier, streak, isDefault

All additive; existing fields are unchanged. README documents the
contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mattromano <42412983+mattromano@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 46 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a015d850-cd2c-4360-90db-11218d09b6fa

📥 Commits

Reviewing files that changed from the base of the PR and between 412433d and 6ede4dc.


📒 Files selected for processing (6)
  • CLAUDE.md
  • README.md
  • package.json
  • plugin.json
  • screen.js
  • test/judgment_events.test.js


  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mattromano

Copy link
Copy Markdown
Author

Consolidated into #84 (commits kept, rebased onto main, plus the review fixes).

@mattromano mattromano closed this Oct 15, 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.

notedetect:hit/miss should carry per-string chord verdicts, techniques, latency and section for stats plugins

1 participant