Repository navigation
contract(shared): reject impossible transcription intervals before rehearsal rendering #1255
Description
Finding
The shared TranscriptionNote contract admitted finite but impossible audio-relative intervals after #1253 fixed only non-finite representation. GrooveMap uses onset as horizontal position and offset - onset as note width, so negative onset or non-positive duration reaches buyer-visible rehearsal geometry.
Protected producer evidence closes the domain decision: _note_events_from_frames() derives start time from non-negative frame indices and drops events with duration below MIN_NOTE_DURATION_SECONDS = 0.05. The repository-owned producer does not intentionally emit negative starts or non-positive durations.
Canonical repair / single-writer succession
No parallel shared-contract branch was created. Draft PR #1254 owns validateTranscriptionNote() and remains the timing-policy writer.
Current #1254 exact head: c21c18ccd630614feee1fef3e0b7e5cf4fdce658, stacked by ordinary ancestry on formatter prerequisite #1176 8fe6b6d99c009527ef0bcba419e6f6debdb23c23.
- RED
9a27a87f8c2c74614d84acb23458845949f948a0adds hostile finite intervals through bothisRehearsalSong()andparseRehearsalSong(): negative onset, zero-duration interval, inverted interval, plus zero/negative-zero and ordinary positive controls. - Causal repair
95356c11a76716dde927bfe311dffb5eec4cf9e1requires finiteonset >= 0and finiteoffset > onsetin the shared validator. - Doctoring
02e85d3150bfd32472a23793b36af577fd55e331records producer evidence, rendering consequence, persistence/recovery boundary and rejected alternatives. - Two-parent descendant
c21c18...makes repair(ci): format consolidated supply-chain policy test #1176 actual ancestry without duplicating its formatter source delta.
Velocity policy remains separate because repository evidence does not yet establish one canonical scale/range.
Persistence / recovery boundary
Desktop saveProject() parses before native persistence and loadProject() parses the native response before returning a RehearsalSong. Malformed durable project timing therefore fails closed at the shared parser boundary; this repair does not silently clamp, swap, reorder or normalize durable timing.
A separate persisted analysis final-result cache consumer in #970 was found to be out of sync: _valid_transcription_note() accepted any finite onset/offset pair. #970 now has #1254 as actual ancestry and carries a focused downstream consumer RED 3314730077b7c24c077e2f15cec73eb627b8d75e for negative, zero-duration and inverted intervals, followed by causal repair 3dfd77e11187211e9b7ed2317b8f559e5e1fb018 adding only onset >= 0 and offset > onset after the existing finite checks. That is a consumer adaptation, not a second timing-policy owner.
If a historical project or cache carrying malformed note intervals is discovered, recovery/migration must classify it explicitly rather than weakening the shared invariant.
Evidence boundary
Before #1176 stacking, #1254 semantic head 02e85d... had build-baseline, Security Scan, Semgrep and SBOM terminal SUCCESS. Repository CI failed only on protected-base test_supply_chain_policy.py Ruff formatting, now owned by #1176. The current stacked #1254 head has no repository-owned workflow generation; zero runs is absence of evidence, not GREEN. The #970 downstream stacked head likewise has no hosted generation after its timing consumer repair.
No predecessor GREEN is promoted to either current stacked head. No no-op freshness commit, blind rerun, force push, destructive rebase, self-approval or gate weakening is used.
Acceptance
- Hostile finite-interval RED precedes the shared production repair.
-
onset < 0fails at the exact.onsetfield path. -
offset === onsetandoffset < onsetfail at the exact.offsetfield path. -
onset = 0and JavaScript-0with positive duration remain accepted. - One shared validator owns the invariant; no consumer-side clamp or duplicate shared policy is introduced.
- Save/open paths use the same parser and do not silently correct malformed durable input.
- Doctoring records producer evidence, rendering consequence, migration boundary and rejected alternatives.
- Known fix(project): enforce crash-safe revision-bound persistence #970 final-result-cache consumer drift has a source RED and minimal downstream adaptation while consuming fix(shared): enforce valid transcription timing intervals #1254 as ancestry.
- repair(ci): format consolidated supply-chain policy test #1176 becomes protected ancestry and fix(shared): enforce valid transcription timing intervals #1254 is ordinarily reconciled to protected
develop. - fix(shared): enforce valid transcription timing intervals #1254 final exact-head shared-types/desktop/repository/security/SBOM/CodeQL evidence settles terminally.
- fix(project): enforce crash-safe revision-bound persistence #970 later reacquires final exact-head evidence for its persisted-cache consumer adaptation.
- Zero valid unresolved findings and qualifying independent non-author current-head approval.
- fix(shared): enforce valid transcription timing intervals #1254 or a verified complete successor becomes protected ancestry.
Do not close this issue merely because source deltas exist. Protected integration or verified complete succession remains required.
Activity
seonghobae commentedon Sep 22, 2026
Canonical #1254 update: exact head is now
c21c18ccd630614feee1fef3e0b7e5cf4fdce658, base #11768fe6b6d99c009527ef0bcba419e6f6debdb23c23, Open / Draft / mergeable. The ordinary two-parent descendant makes #1176 actual ancestry without adding a second validator or copying its formatter delta into the #1254 diff; fresh compare from #1176 is ahead=8 / behind=0 and the PR still changes only the timing doctoring, shared validator, and focused timing test.Direct-
developsemantic head02e85d...had build/Security/Semgrep/SBOM SUCCESS. Repository CI failed only because protected-basetest_supply_chain_policy.pywas not Ruff-formatted; exact hosted log reports that single path. The finite interval invariant itself has no new failure finding from that generation. Current stacked head has zero repository-owned workflow runs, which is absence of final evidence rather than GREEN.Keep #1255 open until #1176 is protected ancestry, #1254 is ordinarily reconciled and receives final exact-head gates plus qualifying independent review, then reaches protected ancestry or complete verified succession.