{"_id":"@dbzdrums/notation","_rev":"4-94232f8a4efeb95dc85cf98fdb30df86","name":"@dbzdrums/notation","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@dbzdrums/notation","version":"0.1.0","keywords":["drums","drum-notation","musicxml","music-notation","svg","typescript"],"author":{"name":"DBZDrums"},"license":"BSD-3-Clause","_id":"@dbzdrums/notation@0.1.0","maintainers":[{"name":"debonzi","email":"debonzi@gmail.com"}],"homepage":"https://github.com/DBZDrums/dbzdrums-notation#readme","bugs":{"url":"https://github.com/DBZDrums/dbzdrums-notation/issues"},"dist":{"shasum":"c09aba0a1799830b63864e7febae333394f2a44b","tarball":"https://registry.npmjs.org/@dbzdrums/notation/-/notation-0.1.0.tgz","fileCount":9,"integrity":"sha512-ZJzdSkoepzJ/ippS6obIe7jbdIj2WODmSlnPs6CZ0CEpuSb0G1WiaP6R7Gwfcb71G195uTd+2DwwFENlU6lKaA==","signatures":[{"sig":"MEUCIFchZlDfhUhXV+IIDl8XAD+4aAJ8DHloAmaYy6fnmZaWAiEA/f+Tfq5kAmpWFpxBGC4p53thwTJ8GljgmWNM77Uacto=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dbzdrums%2fnotation@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":244182},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"1d377f1e80ae34d74cc9a17e3f0a1547ca4eebf1","scripts":{"dev":"vite","test":"npm run test:unit","build":"tsup","check":"npm run typecheck && npm run test:unit && npm run build","prepack":"npm run check","preview":"vite preview","test:unit":"vitest run","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:browser":"playwright test","setup:browsers":"playwright install chromium firefox"},"_npmUser":{"name":"debonzi","email":"debonzi@gmail.com"},"repository":{"url":"git+https://github.com/DBZDrums/dbzdrums-notation.git","type":"git"},"_npmVersion":"11.16.0","description":"Type-safe TypeScript library for authoring and rendering drum notation.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"opensheetmusicdisplay":"2.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"npm@12.0.1","devDependencies":{"tsup":"8.5.1","vite":"8.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.13.3","@xmldom/xmldom":"0.8.13","@changesets/cli":"2.29.8","@playwright/test":"1.62.0"},"_npmOperationalInternal":{"tmp":"tmp/notation_0.1.0_1785364527547_0.2681241852540672","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@dbzdrums/notation","version":"0.2.0","keywords":["drums","drum-notation","musicxml","music-notation","svg","typescript"],"author":{"name":"DBZDrums"},"license":"BSD-3-Clause","_id":"@dbzdrums/notation@0.2.0","maintainers":[{"name":"debonzi","email":"debonzi@gmail.com"}],"homepage":"https://github.com/DBZDrums/dbzdrums-notation#readme","bugs":{"url":"https://github.com/DBZDrums/dbzdrums-notation/issues"},"dist":{"shasum":"dedd233d5c0f852ab75a27f21d8d948ea09e3c04","tarball":"https://registry.npmjs.org/@dbzdrums/notation/-/notation-0.2.0.tgz","fileCount":9,"integrity":"sha512-TIiVAZSVHRGloOkdVHUnDRVyV6oxQZV8TYWI/5mNSoYOkejXUdY+yzIUgBtlcatq+kKQ2Fa2bpsc88GKYEzP5g==","signatures":[{"sig":"MEUCIQDhxh7CTM+kaWSouyTGTjEGRMNhbCKFrij7BYXKvTC2GQIgMeiwVLt9GD7PybOMIGT1u8YNlW0HZcLwcBCOK9Ak138=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dbzdrums%2fnotation@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":250924},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"119a038441e3e0b55bf2a4e88b2211f9d3fbe6b2","scripts":{"dev":"vite","test":"npm run test:unit","build":"tsup","check":"npm run typecheck && npm run test:unit && npm run build","prepack":"npm run check","preview":"vite preview","test:unit":"vitest run","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:browser":"playwright test","setup:browsers":"playwright install chromium firefox"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f2558411-c1e6-4def-81af-25848fb387f6"}},"repository":{"url":"git+https://github.com/DBZDrums/dbzdrums-notation.git","type":"git"},"_npmVersion":"11.16.0","description":"Type-safe TypeScript library for authoring and rendering drum notation.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"opensheetmusicdisplay":"2.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"npm@12.0.1","devDependencies":{"tsup":"8.5.1","vite":"8.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.13.3","@xmldom/xmldom":"0.8.13","@changesets/cli":"2.29.8","@playwright/test":"1.62.0"},"_npmOperationalInternal":{"tmp":"tmp/notation_0.2.0_1785370262954_0.8365464276280914","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@dbzdrums/notation","version":"0.2.1","keywords":["drums","drum-notation","musicxml","music-notation","svg","typescript"],"author":{"name":"DBZDrums"},"license":"BSD-3-Clause","_id":"@dbzdrums/notation@0.2.1","maintainers":[{"name":"debonzi","email":"debonzi@gmail.com"}],"homepage":"https://github.com/DBZDrums/dbzdrums-notation#readme","bugs":{"url":"https://github.com/DBZDrums/dbzdrums-notation/issues"},"dist":{"shasum":"e5d8e3482a712e5e31d11f4f235f725cf926b657","tarball":"https://registry.npmjs.org/@dbzdrums/notation/-/notation-0.2.1.tgz","fileCount":9,"integrity":"sha512-FsR4LEbpAiwwrh/o+/YiTYvrf4pu0j7o76MbZMCsbyJ107GkiAPUs8lt8txIbigaWZjNfSfYeZZHwtiXBkVLvw==","signatures":[{"sig":"MEYCIQCTDYhckigo90ccZPOjAZlmoo3ypnMrdhUXbO+MSDavIwIhAN0+NFz8Ck6AEMXj48tIMfQZ7JKCH+0dmsvWhVtTdttK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dbzdrums%2fnotation@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":251565},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"99ed8ebe4195b5c9feaf13d4184a7129a8c9fe1e","scripts":{"dev":"vite","test":"npm run test:unit","build":"tsup","check":"npm run typecheck && npm run test:unit && npm run build","prepack":"npm run check","preview":"vite preview","test:unit":"vitest run","typecheck":"tsc --noEmit","pack:check":"npm pack --dry-run","test:browser":"playwright test","setup:browsers":"playwright install chromium firefox"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f2558411-c1e6-4def-81af-25848fb387f6"}},"repository":{"url":"git+https://github.com/DBZDrums/dbzdrums-notation.git","type":"git"},"_npmVersion":"11.16.0","description":"Type-safe TypeScript library for authoring and rendering drum notation.","directories":{},"sideEffects":false,"_nodeVersion":"24.18.0","dependencies":{"opensheetmusicdisplay":"2.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"npm@12.0.1","devDependencies":{"tsup":"8.5.1","vite":"8.1.5","vitest":"4.1.10","typescript":"6.0.3","@types/node":"24.13.3","@xmldom/xmldom":"0.8.13","@changesets/cli":"2.29.8","@playwright/test":"1.62.0"},"_npmOperationalInternal":{"tmp":"tmp/notation_0.2.1_1785386376798_0.15073275506497597","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@dbzdrums/notation","version":"0.3.0","description":"Type-safe TypeScript library for authoring and rendering drum notation.","author":{"name":"DBZDrums"},"license":"BSD-3-Clause","keywords":["drums","drum-notation","musicxml","music-notation","svg","typescript"],"homepage":"https://github.com/DBZDrums/dbzdrums-notation#readme","repository":{"type":"git","url":"git+https://github.com/DBZDrums/dbzdrums-notation.git"},"bugs":{"url":"https://github.com/DBZDrums/dbzdrums-notation/issues"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"sideEffects":false,"engines":{"node":">=20"},"packageManager":"npm@12.0.1","publishConfig":{"access":"public"},"scripts":{"dev":"vite","preview":"vite preview","build":"tsup","docs:generate":"typedoc --options typedoc.json","docs:check":"node scripts/check-public-api-docs.mjs","typecheck":"tsc --noEmit","test":"npm run test:unit","test:unit":"vitest run","test:browser":"playwright test","setup:browsers":"playwright install chromium firefox","pack:check":"npm pack --dry-run","check":"npm run typecheck && npm run test:unit && npm run build && npm run docs:check","prepack":"npm run check"},"dependencies":{"opensheetmusicdisplay":"2.1.0"},"devDependencies":{"@changesets/cli":"2.29.8","@playwright/test":"1.62.0","@types/node":"24.13.3","@xmldom/xmldom":"0.8.13","prettier":"3.9.6","tsup":"8.5.1","typedoc":"0.28.20","typedoc-plugin-markdown":"4.12.0","typescript":"6.0.3","vite":"8.1.5","vitest":"4.1.10"},"gitHead":"bb95a5108b567fb8e34d8e3df80b245f7b3a44a7","_id":"@dbzdrums/notation@0.3.0","_nodeVersion":"24.18.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-Uts+S180Df1t/Z7Bow3/MkG/hi+OvB3CPxLMGHzVPRxRaDLjoA1LxPK5sGCe6Ue/cuxZ8D+ohEv2ad0kb2zJxQ==","shasum":"c75ae6410da3057e7b9e15c83b45ad7f02e90c4c","tarball":"https://registry.npmjs.org/@dbzdrums/notation/-/notation-0.3.0.tgz","fileCount":56,"unpackedSize":445224,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dbzdrums%2fnotation@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEWoEKU+KT202aKr+2StaNyPv/t1WfMjcXHyhVQBHkoBAiEAmaVCFMtguLQt48r9e9S2OloSZ5IwZ+fDzknUc/CUxt0="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:f2558411-c1e6-4def-81af-25848fb387f6"}},"directories":{},"maintainers":[{"name":"debonzi","email":"debonzi@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/notation_0.3.0_1785714775716_0.545325425866231"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-29T22:35:27.333Z","modified":"2026-08-02T23:52:56.168Z","0.1.0":"2026-07-29T22:35:27.693Z","0.2.0":"2026-07-30T00:11:03.116Z","0.2.1":"2026-07-30T04:39:36.932Z","0.3.0":"2026-08-02T23:52:55.857Z"},"bugs":{"url":"https://github.com/DBZDrums/dbzdrums-notation/issues"},"author":{"name":"DBZDrums"},"license":"BSD-3-Clause","homepage":"https://github.com/DBZDrums/dbzdrums-notation#readme","keywords":["drums","drum-notation","musicxml","music-notation","svg","typescript"],"repository":{"type":"git","url":"git+https://github.com/DBZDrums/dbzdrums-notation.git"},"description":"Type-safe TypeScript library for authoring and rendering drum notation.","maintainers":[{"name":"debonzi","email":"debonzi@gmail.com"}],"readme":"# @dbzdrums/notation\n\n`@dbzdrums/notation` turns concise, validated drum bars and phrases into standards-based MusicXML or a browser SVG chart. It is a standalone TypeScript library: it does not import React or any DBZDrums application type.\n\n## Project documentation\n\nThis README is the documentation for library users. Other audiences have dedicated guides:\n\n- [Contributors](CONTRIBUTING.md) — local development, tests, changesets, and pull requests.\n- [Coding agents](AGENTS.md) — repository boundaries, safe working rules, and required validation.\n- [Generative-AI use disclosure](AI_DISCLOSURE.md) — scope, accountability, and limits of AI assistance.\n- [Public API](docs/public-api/index.md) — complete installed-version concepts, examples, errors, and generated reference.\n- [Architecture](docs/architecture.md) — shared technical boundaries and design decisions.\n- [Release process](docs/releasing.md) — version tags, approval, and package publication.\n\n## Install\n\n```sh\nnpm install @dbzdrums/notation\n```\n\nThe npm package includes the [complete public API documentation](docs/public-api/index.md)\nand an official [Agent Skill](.agents/skills/dbzdrums-notation/SKILL.md). Agents can optionally\ndiscover installed library skills with:\n\n```sh\nnpx library-skills\n```\n\n## Use\n\n```ts\nimport { Bar, compileMusicXml, renderBarToSvg } from \"@dbzdrums/notation\";\n\nlet bar = new Bar({\n  meter: \"4/4\",\n  divisions: 8,\n  hits: {\n    bassDrum: [\"1.0\", \"3.0\"],\n    snare: [\"2.0\", \"4.0\"],\n    hiHat: [\"1.0\", \"1.1\", \"2.0\", \"2.1\", \"3.0\", \"3.1\", \"4.0\", \"4.1\"],\n  },\n});\n\nbar = bar.add(\"snare\", { at: \"4.1\", articulations: [\"rim\"] });\n\nconst { musicXml } = compileMusicXml(bar);\nconst { svg, dispose } = await renderBarToSvg(bar, document.querySelector(\"#chart\")!);\n```\n\n`renderBarToSvg()` owns and clears its target container. The target must be connected to the document and have a positive width. Call `dispose()` when the chart is no longer needed.\n\nAttach a single-line comment to a grid position with `annotations`. Text is written as a standard MusicXML direction and defaults to placement below the staff.\n\n```ts\nconst annotated = new Bar({\n  meter: \"4/4\",\n  divisions: 8,\n  hits: { snare: [\"1.0\", \"3.0\"] },\n  annotations: [{ at: \"1.0\", text: \"Lyrics starts\" }],\n});\n```\n\nOnly one annotation per position and placement is allowed; one above and one below may share a position. Some exact musical instruction words, such as `Fine`, `Coda`, and `D.C.`, can be interpreted specially by OSMD rather than as neutral comments.\n\nBoth SVG render functions accept an optional `signal` in `RenderOptions`. Cancellation is cooperative: it cannot interrupt synchronous OSMD work already in progress, but it prevents an obsolete result from being returned and clears the owned container at asynchronous checkpoints. An aborted render rejects with `NotationRenderError` code `\"RENDER_ABORTED\"`.\n\n### Phrases\n\nUse `Phrase` for an ordered, non-empty sequence of existing `Bar` values. Each bar may use a different meter or grid resolution, but every bar must use the same drum-kit instance.\n\n```ts\nimport { Bar, Phrase, compileMusicXml, renderPhraseToSvg } from \"@dbzdrums/notation\";\n\nconst phrase = new Phrase({\n  bars: [\n    new Bar({ meter: \"4/4\", divisions: 8, hits: { bassDrum: [\"1.0\", \"3.0\"] } }),\n    new Bar({ meter: \"6/8\", divisions: 6, hits: { snare: [\"3.0\", \"6.0\"] } }),\n  ],\n  annotations: [{ bar: 1, at: \"3.0\", text: \"Build\" }],\n});\n\nconst { musicXml } = compileMusicXml(phrase);\nconst { svg, dispose } = await renderPhraseToSvg(phrase, document.querySelector(\"#chart\")!);\n```\n\n`Phrase` deliberately has no name, semantic repeat marks, or visible measure numbers. An annotation stored on a `Bar` appears on every occurrence of that bar; `Phrase.annotations` targets one occurrence by its zero-based `bar` index.\n\n### Score presentation\n\nPass `presentation` to hide standard score markings in both the returned MusicXML and browser SVG. All markings are visible by default. A hidden clef or time signature remains in MusicXML with `print-object=\"no\"`, so the written meter and percussion context are retained. A hidden final barline is emitted with MusicXML `bar-style` `none`; in a phrase, this applies only to the final measure.\n\n```ts\nconst presentation = {\n  showClef: false,\n  showTimeSignature: false,\n  showFinalBarline: false,\n};\n\nconst { musicXml } = compileMusicXml(bar, { presentation });\nconst { svg, dispose } = await renderBarToSvg(bar, chart, { presentation });\n```\n\nSVG rendering also accepts `repeatCount`, a safe integer of 2 or greater. It adds a visual `xN` after the final barline, or after the staff end when the final barline is hidden. This is deliberately SVG-only: it does not change returned MusicXML or add semantic repeat marks.\n\n```ts\nconst { svg, dispose } = await renderPhraseToSvg(phrase, chart, {\n  repeatCount: 3,\n});\n```\n\n## Input model\n\n- `meter` is a string such as `\"4/4\"` or `\"6/8\"`. Supported denominators are 1, 2, 4, 8, 16, and 32.\n- `divisions` is the total count of grid positions and must be a multiple of the meter numerator. It defines coordinate precision, not a mandatory written note value: the compiler derives note and rest durations from attack spacing. v0.1 supports 1–32 subdivisions per written unit.\n- Positions are canonical strings: `writtenUnit.subdivision`. Written units start at 1; subdivisions start at 0. Thus 4/4 at eight divisions accepts `\"1.0\"` through `\"4.1\"`, while 6/8 at six divisions accepts `\"1.0\"` through `\"6.0\"`.\n- `grouping`, for example `[3, 3]` in 6/8, only controls beaming. It never changes coordinates.\n- `Bar` is immutable. `add()` returns a new value.\n- `Phrase` is immutable and preserves the input bar order. It validates that its bars share one drum-kit instance.\n\nThe default kit exposes `bassDrum`, `floorTom`, `snare`, `tom2`, `tom1`, `ride`, `hiHat`, and `crash`.\n\n### Drum techniques\n\nA hit written as a position string, such as `\"2.0\"`, is valid for every voice in the standard kit and uses that voice's base technique and display. In particular, an unqualified snare is normal and an unqualified hi-hat is closed. `\"normal\"` and `\"closed\"` remain accepted explicit techniques, but they are redundant for authoring; omit `articulations` for the base state. There is no public `\"default\"` technique — `defaultArticulations` is an internal kit-definition setting used to resolve an unqualified hit.\n\nEach standard-kit hit has at most one primary technique. Snare accepts `normal`, `rim`, or `flam`; hi-hat accepts `closed`, `open`, or `pedal`. Supplying two primary techniques for one hit, such as `rim` plus `flam`, is rejected with `ARTICULATION_CONFLICT`. The general custom-kit API also supports ordered modifier articulations alongside one primary technique, but the standard kit currently defines no modifiers.\n\n| Voice / technique | Staff display | Notehead |\n|---|---:|---|\n| bassDrum | F4 | normal |\n| floorTom | A4 | normal |\n| snare normal / flam | C5 | normal |\n| snare rim | C5 | x |\n| tom2 | D5 | normal |\n| tom1 | E5 | normal |\n| ride | F5 | x |\n| hiHat closed | G5 | x |\n| hiHat open | G5 | circle-x |\n| hiHat pedal | D4 | x |\n| crash | A5 | x |\n\n`rim` is written with an `x` notehead at C5. `flam` is emitted as a preceding slashed grace note and a normal main snare note, so it is written as `{ at: \"2.0\", articulations: [\"flam\"] }`; it is not combined with `normal` or `rim`. Hi-hat `open` uses a `circle-x` notehead at G5, while `pedal` uses an `x` notehead at D4. A custom kit is created with `defineDrumKit()` and can explicitly mark an articulation as `unsupported`. Compilation then retains the core event, emits its base visual fallback, and reports a diagnostic; `strict: true` turns that diagnostic into a `NotationCompilationError`.\n\n## MusicXML and SVG guarantees\n\nThe compiler produces a one-part MusicXML 4.0 `score-partwise` document with MIDI channel 10 instruments, a true five-line staff, rhythm inferred from attack spacing, rests, chords, beams, tuplets, and position-anchored text directions. By default it also shows a percussion clef, time signature, and final barline; `presentation` can hide those markings without removing their MusicXML semantics. A phrase compiles into ordered MusicXML measures and repeats attributes only when a meter or MusicXML division value changes. SVG rendering is delegated to OpenSheetMusicDisplay 2.1.0, loaded only by the browser renderer; visual `repeatCount` labels are added to the completed SVG.\n\n`compileMusicXml()` is usable in Node and browser environments. `renderBarToSvg()` and `renderPhraseToSvg()` are browser-only. Playback, MIDI output, PDF output, React bindings, semantic repeat conventions, and application-specific DBZDrums adapters are deliberately outside the package.\n\n## Local development\n\nThis is a quick reference for running the project. Human contribution expectations are in\n[CONTRIBUTING.md](CONTRIBUTING.md); automated agents must follow [AGENTS.md](AGENTS.md).\n\n```sh\nnpm install\nnpm run dev\nnpm run check\nnpm run setup:browsers\nnpm run test:browser\n```\n\n`npm run dev` opens the repository's interactive playground. It lets you toggle\ndrum hits in a grid, add, duplicate, remove, and select bars in a phrase, edit\nannotations in the corresponding JSON definition, preview an optional visual\nrepeat count, inspect the TypeScript call and MusicXML, download the generated\n`.musicxml`, and see the actual OSMD SVG. The playground\nis a development showcase, not part of the published package or its core runtime.\n\nPlaywright runs the real renderer in Chromium and Firefox. It asserts five visible, full-length staff lines, barlines, rendered notehead glyph counts, no browser errors, and a compact visual-regression screenshot in each browser.\n","readmeFilename":"README.md"}