Staging - Add, bpm management - #350
Merged
Merged
Conversation
Pure computeTimelineOccupancy over clips/tracks: occupied span vs clip-duration-sum (distinct numbers), per-track and global gaps/overlaps, MIDI stack tracks never report overlaps, unassigned-track bucket, deterministic ordering, 1e-6 epsilon. First consumer of the single duration semantics; existing 14 ad-hoc computations migrate later. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
withTimelineRevision wraps the store creator: one atomic increment per set/setState call whose watched keys (clips, tracks, clipKeyframes, markers, masterAudioState) change identity. Covers all 52 direct setState sites and history restores without per-action edits. Monotonic within a session; revision-only writes never self-bump. getTimelineRevision() exposes the counter for stale-plan detection. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cancelBatch() gives historyStore a real abort (restore pre-batch snapshot, stacks untouched). beginAgentTransaction/commit/abort wrap tool-call groups: one transaction per chat turn instead of one undo entry per tool, inner calls suppressed, executeBatch paths only close batches they own, revisions captured via getTimelineRevision. Thrown errors roll back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… (WP2-D) Additive occupancy block from computeTimelineOccupancy plus the central timelineRevision. First bridge-visible consumer of the canonical semantics; also the calibration surface for the agent-kernel adapter. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
youtube/localImport append points now use computeTimelineOccupancy; export.ts documented as state.duration-based (semantics preserved). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rnel adapter calibration) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
split/splitEvenly/splitAtTimes/cutRanges/trim additively report entities.created/updated/deleted (clip refs incl. linked audio) and stateRevisionBefore/After. Kills the model-copied-ID-list problem at the source: dependent edits can consume returned identities directly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rage startBatch flushes pending debounced captures (user edits become their own undo entry, never swallowed into an AI batch); cancelBatch drops pending timers (no redo-clearing no-op entries). Grouped tool execution aborts on any failed mutating result instead of committing partials; suppressHistory honored; transaction ownership verified at commit/abort. Revision watches duration/in-out/tempo fields, skips store cloning for unwatched patches, and the bridge occupancy block reads revision from its own snapshot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dits (WP2-FIX2) Monotonic batch counter replaces Date.now collisions; beginAgentTransaction re-reads batch state after the pre-start flush; audits complete after group outcome with rolledBack markers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…led (WP2-FIX3)
startBatch returns {opened,batchId}; transactions never adopt foreign batches as owned. Rolled-back mutations audit as success:false partialTransaction with the original result preserved.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nel WP7) Store-agnostic timeline checks (counts, gaps, overlaps, order, AV-link, occupancy) with a registry; guided validation delegates without behavior change. One verification core, no parallel systems. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, move/reorder/speed (WP4) Shared mutationEntityResults helper; additive entities+revision blocks on nine more mutating handlers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ng locked (agent-kernel WP3) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… WP11 prep) Typed HTTP client for run/validate/manifests/runs/amend/health; no kernel logic, structural types only, per plan 21.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…11 slice 1) The in-app chat tries the kernel service before the legacy provider loop (strangler pattern). Default OFF via localStorage flag; not-mechanical, service-down, and network errors fall through untouched; succeeded runs answer with a Kernel-verified summary and fingerprint. Zero behavior change when disabled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packets 1 and 4 of the BPM management plan. Packet 1 — tempo editing core: - new pure src/timeline/tempo/tempoEdits.ts owning every invariant (sort, dedupe by time, pinned first event, clamps, id backfill/repair) - TempoEvent.id, required at runtime and optional in the project tier; normalizeRulerLaneState now normalizes instead of passing through, so pre-#299 projects gain ids at the single load seam - editable BPM range [20, 999] — deliberately NOT the 60/200 detection bins from beatGridEstimation, which would reject 40 and 240 BPM - new tempoSlice (setProjectTempo / add / update / removeTempoChange), capturing history AFTER the mutation like midiClipSlice - tempoMap threaded through all 12 history sites; restore falls back to the live map so a pre-#299 entry cannot clobber it on undo Packet 4 — tempo-driven body grid and snapping: - new pure src/timeline/tempo/barsGrid.ts: explicit bar/beat/subdivision line times plus the pixel thresholds the bars ruler also uses, so ruler ticks and grid lines can never disagree - an ENABLED Bars+Beats ruler lane wins the grid (not activeRulerLaneId, which is retired as a grid seam); bars replace the time/frame grid - grid snapping in both snap paths with a pixel-derived threshold, since a 1/16 at 120 BPM is narrower than the fixed 0.15 s window - timelineGridSubdivision view preference (localStorage) with the picker in the Rulers menu Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Completes commit 41c8929, which referenced this export from registrySnapshot.ts while the export itself was left uncommitted. Build verified green at HEAD+fix in a clean worktree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packet 2 of the BPM management plan, plus a Rulers menu UX fix. Content follows tempo: - new pure src/timeline/tempo/tempoRemap.ts — remapAcrossMaps, trackFollowsTempo, remapMidiClip, remapTimelineClipsForTempo - MIDI clips, notes and the four CC automation lanes are remapped through old map -> bar/beat -> new map; video/audio/image clips keep their seconds and their object identity - durations are never scaled by a factor: ends are remapped and the remapped start subtracted, which is the only correct answer across a tempo boundary - everything is anchored on the clip's content origin, so noteAbsoluteStart stays exact and the window cannot drift from its notes - tempoSlice commits the remapped clips and the new map in one set under one snapshot, so a single undo reverts tempo and notes together TempoMap fix: - barBeatToSeconds now extrapolates through segment 0 below the first segment. With more than one segment every range test failed and it fell through to the LAST segment, returning nonsense for bar <= 0 — reachable through a left-extended MIDI clip's negative inPoint - new barBeatToSecondsAt object wrapper Rulers menu: - clicking a lane row toggles the lane again (checkmark + highlight); the grid resolution moved behind a + expander on the Bars + Beats row and is indented under it, so one click never means two things Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e/transform tools (agent-kernel WP4) Shared helper consolidation replaces three private snapshot helpers; entity kind union extended to the kernel contract vocabulary (mediaItem/composition/folder). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…proper media entity kinds (agent-kernel WP4) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…y (agent-kernel WP2) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ings expose mediaId (agent-kernel WP4/WP2 calibration) Restores the kernel adapter contract after envelope consolidation and gives linked A/V pairs a shared source identity in tool listings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…c (agent-kernel WP15 app side) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ion core (agent-kernel WP7/WP11) New-tool integration touched exactly: one definition group, one policy entry, handler + dispatch, tests - the WP11 tool-addition evidence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packet 3 plus two model fixes found while testing it in the app. Tempo lane (Rulers -> Tempo, stacked under Bars + Beats, never selectable as the active lane): - flags read "4/4 - BPM = 120"; editing swaps only the value being changed for a field, so the rest of the label stays readable - right-click the lane: Add tempo change / Add time signature change, inserted at the nearest bar with the relevant editor already armed and selected - right-click a flag: Change tempo / Change time signature / Ramp toggle / Delete (Delete disabled on the project tempo) - drag to move, snapped to bars, Alt for free placement; one undo per gesture - the menu portals to document.body: the lane lives inside .time-ruler, which has a transform and two overflow:hidden wrappers, so a fixed-position menu was being positioned against the wrong box and clipped away - dismissal listens in the CAPTURE phase, since the flags themselves stop mousedown propagation and a bubble listener never fired Ramps (plan 3.3 said out of scope; now supported): - TempoEvent.curve = 'jump' | 'ramp'; 'ramp' reaches the tempo by interpolating from the previous event across the interval leading into it - TempoMap integrates a linearly varying tempo: elapsed beats are quadratic in time and the inverse solves that quadratic in closed form, so 60 -> 120 over 8 s covers 12 beats (the average), not 8 - dashed sloped indicator across the ramped interval plus an arrow on the flag Model fixes: - content is anchored to its QUARTER-NOTE position, not to (bar, beat). Bar and beat made a pure meter change (4/4 -> 3/4 at the same BPM) drag every note sideways even though no note's duration changed - tempo marks are re-anchored on every edit so they stay on their BAR. They are stored in seconds, so a ramp changing the length of the preceding interval used to slide a flag placed on bar 11 to bar 11.5. An explicitly set position (insert or drag) still wins, so a dragged flag lands where it was dropped Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…mark passes report cancelled - deleteMediaItem test expects the WP4 envelope - OCR gate fixtures carry the new baseline identity fields - legacy artifact events include camera-motion - precise type-module imports keep the foundation barrel budget - localBenchmarkRunner: warm-cache blocking applies to completed runs only Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A read-only mirror of the timeline's tempo lane, stacked between the Time and Bars rulers so tempo sits directly above the bars it drives. - follows the timeline's Rulers -> Tempo toggle, so one setting drives both views instead of a second hidden one (and it is already project-persisted through rulerLanes, from #257) - same labels, ramp arrow and dashed sloped indicator as the timeline lane; flags are pointer-events:none so they never swallow ruler scrubbing - built as a separate inline-styled renderer rather than reusing TempoRulerLane: the piano roll is a detached popup, and in dev the app CSS is injected as <style> tags that are not mirrored into it, so Timeline.css classes do not exist there - PIANO_ROLL_RULER_H replaced by pianoRollRulerHeight(laneCount), since the ruler is no longer a fixed two lanes Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Selecting a MIDI track defaulted to Track controls. The instrument is what you actually reach for on a MIDI track — volume/pan already live in the mixer — so it now opens there. Audio tracks still open on Track effects and every other track type on Track controls. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…P11 deletion item) Plan authorizes absorb-or-retire; the kernel path replaces the options-preflight prototype. FlashBoardChatOptionsPlanner (general provider/model logic) stays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ion local execution, fingerprint completion (agent-kernel WP11) Default-on when kernel url+token are configured; v1 run-string gateway test retired in favor of the cutover suite. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packets 5 and 6 of the BPM management plan. Engine: - src/engine/audio/metronomeVoice.ts — one oscillator + gain with a ~40 ms exponential decay; 1000 Hz at full level on the downbeat, 800 Hz at 0.7 otherwise. No assets, no sample loading. A click whose time has already passed fires immediately rather than being dropped - src/services/audio/metronomeScheduler.ts — the look-ahead pattern from midiPlaybackScheduler: 25 ms timer, 0.12 s window, timeline<->context anchor, re-anchor on a >0.25 s seek, silence at non-1x speed, dedup so a beat inside two windows fires once - beat times come from iterateBarBeatLines, so the click tracks meter, mid-window tempo changes and RAMPS with no new math - routing per plan 3.4: its own GainNode straight to AudioContext.destination, never a registered node route, so it cannot reach master metering, the FX/limiter chain or an export; an isExporting guard sits on top UI: - MetronomeButton after the Rulers menu: the button toggles, a separate caret opens a popover with volume and Every beat / Bars only - metronomeEnabled / metronomeVolume / metronomeMode are per-user localStorage view state like snappingEnabled, never project content (plan 3.6). Pulled forward from Packet 6 into Packet 5 because the engine needs something to read Count-in is deliberately NOT included. A real pre-count sounds the click for N bars while content stays silent, which needs a new transport phase rather than a playhead roll-back; play() has nowhere for "running but not advancing". The plan allows shipping the toggle and volume first rather than bending playback. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nel WP11) Bridge and in-app audits now see kernel-first turns; verified E2E: in-app sentence -> /kernel/compile -> one local transaction -> fingerprint-complete -> Kernel-verifiziert with runId reference. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…call; deferred rollback never falls back silently Sequential per-call execution builds the sim-to-real binding from the split segments payload; abortNoop transactions report honest failure instead of double-editing via legacy fallback. Live E2E: split+shuffle kernel-verified (20+20, non-monotonic order, fingerprint match). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Packet 7, plus three architecture-ratchet fixes the full chain surfaced from the metronome packets (which were fast-committed without checks). Docs: - new docs/Features/Tempo-And-Metronome.md — what you can do, then the three ideas the feature rests on, each written around WHY, since each was wrong at least once while building: BPM sets duration while the meter only groups; MIDI is musical and media is linear; a tempo mark is a musical object - Timeline-Rulers.md gets a superseded-in-part banner and its two now-false claims corrected in place: it no longer "ships no grid/snap behavior", and the click-to-select active-lane seam was retired in favour of "an enabled bars lane wins the grid" - Features/README.md indexes the new page; ongoing/README.md marks the plan complete - the plan doc gains per-packet landing notes and a new section 11 recording where the shipped feature diverges from it (ramps, quarter-note anchoring, musical re-anchoring, the smaller deviations, and the two bugs that mutation-testing our own tests caught) Ratchet fixes: - the metronome bootstrap moved from useLayerSync (which is under a hard LOC cap it pushed over) into editorBoot, where the other app-wide services start. A global audio service was never part of layer sync - metronomeScheduler registered in the getState access policy at 4 hits, the same class as midiPlaybackScheduler; baselines bumped with the reason - kept the registry file inside its own 300-line budget Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The architecture registry budget test measures split(/\r?\n/).length, so a newline-terminated file scores content lines + 1. Both staging and this branch sat at 299 content lines = exactly 300, so the merge of the two (staging's muscriptor adapter grant + this branch's metronomeScheduler entry) scored 301 and failed CI, even though neither branch fails alone. Drop the per-packet bookkeeping comments left over from the closed Complete Refactor (packets 231/267/291/306/307/342/343/345, the dockStore-folder note, and the multi-line ratchet log in the baselines); that history lives in git and in docs/completed/refactor/. No entries, paths or baseline numbers change, so the file is 281 lines with real headroom instead of zero. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Conflict in src/architecture/getStateAccessPolicy.ts resolved by keeping this branch's trimmed baseline block and combining both sides' numbers: staging's allowedAdapterPathCount 26 (muscriptor adapter grant) plus this branch's metronomeScheduler entry on top of staging's ledger (237 -> 238 files, 674 -> 678 hits). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
299 add bpm management
Deploying masterselects with
|
| Latest commit: |
63b7e93
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://fedb4755.masterselects.pages.dev |
| Branch Preview URL: | https://staging.masterselects.pages.dev |
# Conflicts: # src/editorBoot.ts
…ecise type-module imports kernelChatGateway builds its snapshot through executeAIToolCalls instead of reading the store (getState access policy, plan 8.3); two BPM-PR barrel imports narrowed to types/timeline (foundation type budget). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ry section replaces stale 86-tool count Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nel gateway (agent-kernel story cutover, app side) Moments are built on-device from getClipTranscript pages (text+timings only, 400-word cap) and sent solely to the configured kernel service; story compiles create/open the target composition inside the same agent transaction before executing resolved calls. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pile timeout, Logger-visible fallback reasons Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Transcripts are persisted on the media file, but agent-facing reads (getClipTranscript, findSilentSections, listings, clip details) only saw the clip-instance copy, so re-added or restored clips reported hasTranscript while returning no words. All reads now go through resolveClipTranscriptWords: clip words win, media-file words are the fallback; hasTranscript is computed from the same resolver. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Matches the kernel-side rename; keeps kernel-internal vocabulary out of the public client per the isolation test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…properties panel falls back to media transcript History edit states only carry transcriptStatus, so undo/redo and history-mediated rebuilds produced clips with status ready but no words. Restore now reuses the live clip words or re-derives them from the media store, and the properties panel transcript tab reads through the same media-anchored resolver. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ent schema Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tures use storySummary Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#299