SpaceAge Code Commenting Architecture Guide
SpaceAge Code Commenting Architecture Guide
Updated: 2026-07-31
Status: planning and critique complete; first contract-comment tranche inserted; full pass remains in progress
Audience: human maintainers, AI coding agents, reviewers, and future technical writers
1. Purpose
SpaceAge has grown into a composition system whose important behavior crosses UI, project state, real-time audio, MIDI hardware, persistence, and export boundaries. The goal of source comments is not to describe every statement. It is to preserve the decisions, contracts, and constraints that a competent maintainer cannot safely infer from one function in isolation.
This guide defines:
- What deserves a source comment.
- What should remain self-explanatory code.
- Which architectural boundaries need comments first.
- How comments should serve humans and AI agents without becoming duplicated documentation.
- How to add the comments in reviewable phases.
- How to keep comments true as the product changes.
The companion Whiteboard maps critical user flows end to end. This guide explains how those flows should be represented at their implementation boundaries.
2. Executive Critique
What is working
- Important invariants already appear near a few high-risk declarations, including the disjoint Drum Pad and private lane-Instrument source ranges.
- Automated gates encode substantial behavioral truth. In many places, a focused regression is a stronger explanation than prose.
- Safety-oriented MIDI code frequently distinguishes planning or preview work from operations that can transmit to hardware.
- Product vocabulary is increasingly consistent: Pad, Instrument, Instrument Bay, Pattern, Clip, Lane, Section Marker, Chord Marker, Mixer channel, and Hardware Passport.
What currently makes comprehension difficult
- Three implementation files dominate the system. PluginEditor.cpp, SpaceAgeMidi.cpp, and PluginProcessor.cpp are approximately 2.9 MB, 1.6 MB, and 1.0 MB. A maintainer cannot build a reliable mental model by reading them sequentially.
- High-risk functions have too few orienting comments. processBlock(), state restoration, lane-Instrument reassignment, recording-target resolution, and several async queues perform cross-subsystem work whose invariants are not visible at the entry point.
- Headers expose many models without subsystem grouping. SpaceAgeMidi.h is a broad protocol library, product-readiness model, hardware workflow model, import/export model, and automation model in one file.
- Some names preserve implementation history. CinematicDrumsAudioProcessor, pad, numPads, and Pad-oriented helper names can mislead maintainers now that private lane Instruments exist.
- The documentation set contains valuable history but is difficult to navigate. Several files are chronological journals hundreds of thousands of bytes long. They should remain evidence, while this guide and Whiteboard.md act as current maps.
- Commenting everything would make the problem worse. Narrating widget bounds, getters, arithmetic, or ordinary JUCE calls would bury the contracts that matter.
Central recommendation
Use contract comments at architectural boundaries, not line-by-line narration. A future coder should be able to enter a subsystem through its header, read a short contract, follow named flow anchors in Whiteboard.md, and confirm behavior in a focused test.
Pre-comment implementation blockers found by audit
The following behavior must be fixed or deliberately re-specified before source comments describe it as settled architecture:
processBlock()now acquires one immutable Sequencer Playback Snapshot for each audio block, andprocessSequencer()uses it for Chain mapping, lane audibility, routing, automation ownership, and clip traversal. Preserve this boundary; never reintroduce direct reads from mutable Chain or Arrangement containers in the scheduler.- Clip Local and Lane Local automation edits/deletions do not consistently republish the sequencer snapshot. Playback can remain stale until an unrelated edit publishes again.
buildEffectiveMidiExpressionEventsForArrangementClip()combines source-relative and Arrangement-relative time domains, while export also adds Lane Local events separately. Overlapping ranges may duplicate lane automation.- Project load, explicit save, and autosave still perform substantial synchronous file work on the message thread. Large sessions can appear frozen despite the progress UI.
- A failed MIDI-record arm attempt can create an undo checkpoint before target validation, clearing redo history without making a musical edit.
- Autosave failure feedback, recovery deletion confirmation, and cancellation for several long-running workers remain incomplete.
- WAV export has focused duration/progress coverage, but does not yet have one focused proof combining active shared effects with Clip/Lane automation. These are implementation findings, not reasons to weaken the intended contracts. Comment insertion should follow the corresponding fixes so comments record proven behavior rather than aspirations.
Resolved during the first comment-audit follow-up: buildHardwareSyncPolicyPreview() now delegates to the canonical policy builder, previewed values are bound to the confirmed save, receive-clock roles require confirmation, and clock-only output no longer depends on transport-send. The focused MIDI_SYNC_POLICY gate plus MIDI closeout and MIDI health gates verify the repaired boundary.
3. Comment Hierarchy
Comments should follow this order of value.
Level 1: File mission header
Use once near the top of a major file. State:
- The file's responsibility.
- What it deliberately does not own.
- The main collaborating files.
- The relevant execution threads.
- The best companion document or focused test.
Do not include release status, percentages, or a change log.
Level 2: Subsystem boundary
Use before a coherent family of declarations or implementations. Explain:
- The domain model represented by the block.
- The boundary to adjacent subsystems.
- Stable identity and ownership rules.
- Where mutations are allowed.
Examples: Arrangement ownership, MIDI input runtime, hardware output safety, project transactions, shared effects, and export.
Level 3: Function contract
Use on functions where a local implementation cannot reveal the full obligation. Include only applicable fields:
- Precondition
- Postcondition
- Thread
- Ownership
- Failure behavior
- Persistence
- Safety
Level 4: Non-obvious algorithm
Explain why an algorithm has a surprising step, bound, ordering rule, or conversion. Focus on the decision, not a translation of the loop.
Level 5: Temporary constraint
Use only when a real, current constraint cannot be represented in code. Include:
- Why it exists.
- The safe removal condition.
- A test or document that proves removal is safe.
Avoid ownerless TODO and FIXME notes.
4. Comment Templates
File mission
// Mission: Coordinates Arrangement editing UI and delegates musical state to the processor.
// Does not own: realtime playback state or hardware MIDI scheduling.
// Threads: JUCE message thread only unless a called processor API says otherwise.
// Map: docs/Whiteboard.md, Arrangement and MIDI-recording flows.
Ownership contract
// Ownership: the lane owns the private Instrument slot; clips own musical placement only.
// Reassigning the Instrument must preserve lane clips and Mixer destination.
Real-time contract
// Audio-thread contract: no file I/O, UI calls, blocking locks, heap growth, or hardware open/close.
// Message-thread mutations become audible through the published playback snapshot.
Transaction boundary
// Transaction: validate and stage the replacement before mutating the active project.
// On failure, the currently open project and destination file remain unchanged.
Hardware safety boundary
// Safety: this method builds a review plan only. It must not transmit MIDI or SysEx.
// Sending requires the explicit confirmed path in MidiHardwareOutputRouter.
Algorithm rationale
// Integrate each Arrangement slot at its tempo multiplier. Using only project BPM
// shortens or lengthens offline renders relative to live playback.
5. Comments That Should Not Be Added
Do not add:
- Comments that restate a function name or assignment.
- A comment for every control, label, slider, or rectangle.
- Product wish lists inside production source.
- Progress percentages or claims such as "MIDI complete."
- Historical narration that no longer constrains behavior.
- Duplicated parameter labels that will drift from the UI.
- Large theory explanations better stored in a theory data/specification document.
- Long copied standards text or third-party documentation.
- Comments that promise thread safety without naming the mechanism.
- "Temporary" workarounds without a removal condition.
- Comments that hide a poor name instead of improving the name.
When a function requires several paragraphs to explain, first consider extracting a named helper or subsystem. Comments are not a substitute for boundaries.
6. Architectural Invariants To Preserve
These are the intended high-value contracts for comments and tests. The audit exceptions in Section 2 must be corrected or explicitly re-specified before comments claim full conformance.
Source identity
- Drum Pads use public source slots 0 through 63.
- Non-drum Arrangement lanes use private Instrument source slots beginning at firstPrivateArrangementInstrumentSlot.
- Pad operations must not mutate private Instrument slots.
- An Instrument source and its Mixer destination are independent identities.
- User-facing code should resolve a lane Instrument through getArrangementLaneInstrumentSlot() rather than treating it as a Pad.
Arrangement identity
- laneId and clipId are stable identities; array indexes are positions that can change.
- A Clip owns timeline placement and Pattern reference. It does not own the lane Instrument or Mixer channel.
- Clip length, Pattern length, source start, and repeats are distinct concepts.
- Section Markers describe form. They do not own or destructively resize the musical content below them.
- Selection is editing context. The MIDI-armed lane is performance and recording context.
Musical ownership
- Drum lanes resolve through Pad/Drum Composer assignments.
- Instrument lanes own one independent Instrument instance.
- Replacing a lane Instrument preserves that lane's MIDI data and Mixer routing unless the user explicitly chooses otherwise.
- Instrument patches own synthesis and sampling parameters.
- Mixer channels own gain, pan, EQ, routing, shared-effect sends, and channel processing.
- Synth patches must not secretly store or restore Mixer effects state.
Automation ownership
- Shared PTN automation affects every linked Clip using the Pattern.
- Clip Local automation affects one Clip instance.
- Lane Local automation follows the lane.
- A missing automation drawing must not leave an active hidden payload.
- View and zoom operations never change automation ownership.
Transport and timing
- Arrangement playhead, selected loop, Pattern position, and recording activation are distinct clocks and anchors.
- Starting playback with an active Arrangement loop starts at that loop.
- MIDI recording must retain first-measure events and calculate note duration from source-aware timestamps.
- Offline duration must follow the same tempo-multiplier law as live Arrangement playback.
- Playback snapshots isolate the audio thread from mutable editor collections.
MIDI input and output
- Multiple direct MIDI devices retain source identity and generation.
- Host and direct input must not double-trigger the same performance stream.
- Note-off ownership is source and channel aware.
- Live monitoring should take the shortest safe path to the audio block.
- Hardware routing is lane owned and generation guarded.
- Planning, preview, reports, and project load must not transmit setup messages or SysEx.
- Panic retires queued messages, sustain, held notes, and hardware state safely.
Persistence and export
- Failed load/import leaves the active project unchanged.
- Long-running archive work stages and validates before commit.
- Missing asset repair commits against stable identity and expected old value, not a stale index.
- Full-song WAV export clones project state into an offline renderer.
- Destination files are replaced only after the staged result validates.
- MIDI exports preserve safe setup data but do not silently release quarantined SysEx.
- Lane-audio stems are a beta contract: isolate by Arrangement lane before Mixer processing, preserve saved mix state, and stage a manifest-backed aligned package.
7. Prioritized Source Comment Map
Priority 0: correctness and safety boundaries
| File or symbol | Comment needed | Why |
|---|---|---|
| Source/PluginProcessor.h top-level constants and ArrangementLane | Source ranges, stable identity, lane Instrument vs Mixer ownership | Historical Pad naming can cause cross-source mutation |
| Source/PluginProcessor.h snapshot publishers and Source/PluginProcessor.cpp snapshot publication | Writer/reader threads, lock preconditions, invalidation/publication obligation | Current migration and local-automation gaps must be fixed before documenting conformance |
| Source/SpaceAgeMidi.h automation models | Shared/Clip/Lane ownership, stable identity, and Pattern-relative vs Arrangement-relative tick units | Mixed time domains can duplicate or misplace events |
| Source/PluginProcessor.cpp:8717 processBlock() | Phase map, snapshot use, input merge, transport, recording, voice render, Mixer/returns, output | The central realtime function cannot be understood locally |
| Source/PluginProcessor.cpp:12464 startMidiRecording() and recording helpers | Armed-lane authority, activation timestamp, first-measure protection, source identity | Timing bugs are musically destructive |
| Source/PluginProcessor.cpp:15046 setArrangementLaneInstrumentSlot() | Preserve clips/Mixer, private-slot ownership, identity reset semantics | Instrument Bay correctness |
| Source/PluginProcessor.cpp:15572 addArrangementClip() | Stable ID, range validation, overlap/gap contract | Arrangement mutation hotspot |
| Source/PluginProcessor.cpp:16836 restoreStateObject() | Parse/validate/commit order, runtime reset, missing assets, no hardware send | Project trust boundary |
| Source/PluginProcessor.cpp:14599 exportChainAudio() | Offline clone, tempo integration, loop immunity, staged replacement | Render must match live song |
| Source/PluginProcessor.h runtime queue classes | Producer/consumer threads, bounded queues, overflow behavior, generation guards | Bounded behavior is otherwise easy to violate |
| Source/PluginProcessorMidiCompat.cpp export/import and hardware methods | Compatibility-file mission and preview-vs-send boundary | The name can imply obsolete code when it is active architecture |
| Source/SpaceAgeProjectArchive.cpp public operations | Path safety, staging, validation, commit/rollback | Hostile or broken archive protection |
Priority 1: workflow coordination
| File or symbol | Comment needed | Why |
|---|---|---|
| Source/PluginEditor.cpp:6340 constructor | Wiring phases and callback ownership | Constructor is a large topology map |
| Source/PluginEditor.cpp:22154 showPage() | Page lifecycle, panel dismissal, state preserved across pages | Prevent navigation side effects |
| Source/PluginEditor.cpp:25142 showAddArrangementLaneMenu() | Drum insertion order vs Instrument insertion order | User-visible structural rule |
| Source/PluginEditor.cpp:25490 openArrangementLaneInstrumentEditor() | Lane-owned target and caller-page restoration | Prevent fallback to Pad context |
| Source/PluginEditor.cpp:26393 showArrangementLaneInstrumentMenu() | Instrument Bay choice semantics | Avoid recreating top-level proxy workflows |
| Source/PluginEditor.cpp recording-target resolvers | Selection vs armed lane vs playhead/Clip resolution order | Recording predictability |
| Source/PluginEditor.cpp Arrangement clipboard/drag/gap helpers | Replace vs insert vs ripple rules | Past regressions came from ambiguous semantics |
| Source/PluginEditor.cpp:29681 showStartupChoiceDialog() and load helpers | Busy overlay, transactional load, destination state | Startup confidence |
| Source/PluginEditor.cpp:47460 saveCompleteProjectTo() and load paths | Save target, recovery, last-project, async chooser lifetime | Persistence workflow |
| Source/PluginEditor.cpp:48336 timerCallback() | UI-only polling responsibilities and prohibited state mutation | Timer can become a hidden behavior engine |
Priority 2: domain libraries and DSP
| File or symbol | Comment needed | Why |
|---|---|---|
| Source/SpaceAgeMidi.h major model families | Group boundaries and vocabulary, not per-field narration | Header contains several distinct domains |
| Source/SpaceAgeMidi.cpp policy/report builders | Pure-model/no-send guarantee | Reports must remain safe |
| Source/TG55Engine.* | Patch schema, zone selection, voice lifecycle, realtime allocation policy | Sampler/synth correctness |
| Source/SpectralProcessor.* | FFT layout, allocation boundary, overlap/add assumptions | DSP invariants are mathematical |
| Shared effect processors in PluginProcessor.h/.cpp | Prepare/reset/process contract, tail-liveness rule, send ownership | Effects and CPU lifecycle |
| Native synth engine branches in voice rendering | Engine dispatch contract and tuning/chord-safe assumptions | Prevent atonal preset regressions |
| Source/TempoCalc.* | Pure calculation vs UI/settings/export responsibilities | Small subsystem with several roles |
Priority 3: tests and release infrastructure
| File or symbol | Comment needed | Why |
|---|---|---|
| Tests/AudioSelfTest.cpp focused regression sections | User promise, fixture, exact assertion boundary | Tests should explain product truth |
| tools/run_tests.ps1 | Gate-name to environment mapping contract | Prevent orphaned gates |
| tools/run-release-convergence.ps1 | Focused vs broad gate policy | Release evidence architecture |
| Archive/package scripts | Staging, required payload, cleanup behavior | Distribution trust |
Areas to leave mostly uncommented
- Repetitive JUCE component setup.
- Straightforward slider and ComboBox attachments.
- Drawing coordinates that have no non-obvious scaling rule.
- Simple getters/setters and label formatting.
- Factory preset values; document preset design policy elsewhere.
- Self-contained arithmetic already named by a focused helper.
8. Proposed File-Level Indexes
The large files need short file headers plus internal section banners that can be found with rg.
Recommended searchable tags:
- ARCH:ARRANGEMENT
- ARCH:INSTRUMENT_OWNERSHIP
- ARCH:REALTIME
- ARCH:MIDI_INPUT
- ARCH:MIDI_OUTPUT
- ARCH:AUTOMATION
- ARCH:PERSISTENCE
- ARCH:EXPORT
- ARCH:HARDWARE_SAFETY
- ARCH:UI_NAVIGATION
These tags should be sparse. Each marks a subsystem entry, not every function.
9. Implementation Plan
Phase 0: terminology lock
Before source edits, confirm the vocabulary in Product_Glossary.md and SpaceAge_Feature_Outline.md. In particular:
- Pad vs Instrument.
- Instrument Bay vs Instrument.
- Pattern vs Clip.
- Clip length vs Pattern length.
- Lane selection vs MIDI arming.
- Mixer channel vs MIDI channel.
Phase 1: file headers and subsystem indexes
Add mission headers and searchable ARCH boundaries to the five largest architectural files:
- PluginProcessor.h
- PluginProcessor.cpp
- PluginEditor.h
- PluginEditor.cpp
- SpaceAgeMidi.h and SpaceAgeMidi.cpp
This phase should contain no behavioral code changes.
Phase 2: Priority 0 contracts
Add comments around realtime, ownership, persistence, export, and hardware safety. Review each comment against a focused regression or explicit invariant.
Phase 3: critical UI-flow anchors
Comment the editor methods that resolve user intent into mutations. Link them conceptually to named flows in Whiteboard.md.
Phase 4: DSP and domain contracts
Add mathematical and allocation comments to self-contained engines. Avoid explaining familiar DSP unless SpaceAge uses a surprising convention.
Phase 5: test intent
Give focused gates a short statement of the user promise they certify. Do not narrate every assertion.
Phase 6: adversarial review
For every new comment ask:
- Can the code prove this comment false?
- Does a test support the stated contract?
- Is this product truth or temporary progress reporting?
- Would renaming or extraction remove the need for the comment?
- Can a human understand it without knowing the development history?
- Can an AI locate the related implementation and verification path?
10. Efficiency Rules
- Limit most contract comments to 2-6 lines.
- Prefer one subsystem comment over repeated local warnings.
- Put long rationale in this guide or a focused specification and reference it briefly.
- Add comments in small batches by subsystem so review can detect drift.
- Never combine comment insertion with behavior changes.
- Run git diff --check and the relevant focused gate after each batch.
- Use exact symbol references, not fragile pasted line ranges, inside comments.
- Update Whiteboard.md when a critical flow changes; update this guide when a boundary changes.
11. Human Maintainer Entry Path
- Read SpaceAge_Feature_Outline.md for product vocabulary.
- Read Whiteboard.md for the flow being changed.
- Read the relevant file mission and ARCH boundary.
- Locate the focused test named by that boundary.
- Confirm ownership, thread, persistence, and failure behavior before editing.
- Make one coherent change and update the map if the contract changed.
12. AI Agent Entry Path
An AI agent should:
- Treat code and passing tests as stronger evidence than prose.
- Use this guide as a navigation index, not as permission to assume behavior.
- Search stable symbols and ARCH tags before broad file reads.
- State which thread and owner a proposed mutation affects.
- Avoid reviving deprecated Pad-proxy workflows for lane Instruments.
- Avoid broad refactors during bug fixes unless the boundary itself is the defect.
- Preserve unrelated dirty-worktree changes.
- Report contradictions between comments, code, tests, and customer-facing terminology.
- Update comments only when the underlying contract changes.
13. Definition Of Done For The Source-Comment Program
The comment implementation is complete when:
- Every Priority 0 boundary has a concise, accurate contract.
- The largest files have mission headers and sparse subsystem indexes.
- Thread transitions and bounded-queue behavior are explicit.
- Stable identity and ownership rules are visible where mutations occur.
- Preview/report methods that must not send hardware are clearly marked.
- Persistence and export transaction boundaries identify failure behavior.
- Focused tests state the user promise they protect.
- No meaningful increase in obvious or redundant comments occurred.
- A new maintainer can trace each critical Whiteboard.md flow without reading an entire monolithic file.
14. Implementation Progress And Review Boundary
The user authorized the first source-comment tranche on 2026-07-31. That tranche added sparse contracts for source coordinates, Arrangement identity, automation timebases, snapshot publication, hardware output epochs, lane Instrument/Mixer independence, state restoration, and archive staging. It deliberately changed no behavior and marked unresolved snapshot, automation, and hardware-preview gaps as incomplete.
Remaining phases should stay reviewable: add one coherent boundary family, inspect the comment-only diff, verify source anchors, and avoid broad narration. File mission headers, remaining Priority 0 sites, focused-test intent, and final adversarial review are still pending.
Automation Time-Domain Contract
- Comment any automation helper that changes time domains. Shared Pattern and Clip Local ticks are source-relative; Lane Local ticks are Arrangement-relative.
- Do not describe a mixed event list as "effective" unless its time domain is homogeneous or every event carries an explicit domain.
- Any mutation read by realtime playback must publish the corresponding immutable snapshot while holding the model lock.
- Restore code must publish after the complete model has been reconstructed, not after individual partial clears.
- Owner deletion and ID allocator reset belong in the same lifecycle transaction so stale payloads cannot attach to reused IDs.
Setter Identity And Import Transaction Contracts
- On replacement setters, comment that an existing positive logical ID is retained. Do not imply the array index is the owner identity.
- Keep creation semantics separate: insertion/addition may allocate or validate a new ID, while ordinary property edits may not re-key the object.
- For staged imports, identify the three boundaries precisely: parse without mutation, commit the accepted Pattern payload while locked, then publish once.
- State that post-commit expression refresh reads committed state. Do not claim refresh is part of the locked transaction.
- Do not describe Pattern plus SysEx Vault import as globally atomic. They use different mutexes and the vault is committed separately.
- A self-test publication counter proves publication cardinality only; it does not prove exception safety or arbitrary concurrent-writer serialization.
Hardware Delete And Live Channel Contracts
- At profile-removal code, describe the joint state boundary narrowly: registry removal, dependent lane cleanup, readiness refresh, and sequencer publication share the joint lock.
- State separately that hardware clock-output refresh occurs after unlocking. Do not imply external MIDI device work is atomic with project mutation.
- When multiple model mutexes are acquired together, name
std::scoped_lockas the deadlock-avoidance mechanism only for that acquisition. Do not claim a global lock order unless every caller has been audited. - In live MIDI voice code, distinguish
midiChannel/output routing frommidiControlChannel/input ownership. - The incoming control channel owns sustain, expression, note-on/off pairing, and channel-mode handling even when the lane remaps output to another channel.
- Do not claim the focused regression proves physical-device latency, driver ordering, or all multi-controller hardware behavior; it proves deterministic in-process ownership.
Recording Epoch And Quantization Contracts
- Describe a recording epoch as queued-work authority, not MIDI source identity or transport generation.
- State that restore advances the epoch and clears held recording bookkeeping while holding
patternMutex; do not imply restore closes notes or drains worker queues synchronously. - Queue commit comments should name the inside-lock epoch comparison because that is the race-closing boundary.
- Do not claim note, drum, and expression queues form one atomic batch. Each item commits independently when its epoch remains current.
- Quantization bounds use the stored Pattern length. Do not call the legacy
numStepsdrum-grid constant a general Pattern horizon. - Self-test worker holds make stale ordering deterministic; they do not model scheduler latency, queue throughput, or physical MIDI timing.
- Snapshot publication counters prove that rejected stale items did not publish; they do not prove arbitrary restore exception safety.
Count-In And Passport Deletion Comments
- At the count-in transition, say that
breakpreserves the unconsumed part of the current audio block. Do not describe it as merely starting recording; the important contract is continued scheduling atnumSamples - remaining. - Metronome and recording activation share the in-buffer boundary offset. Do not claim the first rendered sine sample must be non-zero; the deterministic scheduler event is the trustworthy assertion.
- Passport deletion comments should distinguish the editor transaction boundary from the processor lock transaction. The editor validates SysEx, checkpoints, calls the processor, and refreshes UI; the processor owns registry/lane/readiness/snapshot mutation.
- Never imply Passport removal deletes or detaches SysEx. Any attachment reported by the Passport or snapshot side blocks the customer action pending an explicit SysEx Vault decision.
- Confirmation tests that call the editor helper prove shared policy and mutation routing, not native dialog rendering or physical hardware behavior.
Recording Snapshot And Checkpoint Comments - 2026-07-31
- At realtime recording reads, state that the immutable snapshot is loaded once per dispatch and that callback code must not acquire patternMutex or fall back to try_lock event loss.
- At snapshot publishers, name the coherent fields: Pattern horizon, armed-lane routing, and Arrangement clip mapping.
- At record-arm target resolution, place the transaction comment immediately before preflight/checkpoint code: all bounded failure conditions precede the checkpoint; the checkpoint marks the first successful mutation.
- Do not claim lock-free recording writes. Queue enqueue is realtime-safe, while worker commits intentionally acquire patternMutex off the audio callback.
Loop Snapshot And Retirement Comments - 2026-07-31
Comment the contract at four boundaries: LoopPlaybackSnapshot owns every asset and user setting consumed by a block; LoopRuntimeState is fixed and audio-thread-owned; publishLoopPlaybackSnapshotLocked() requires sampleMutex and may defer destruction; and processBlock() captures one generation before loop work. At the retirement code, explain that atomic shared_ptr publication does not by itself keep the final release off the callback, and state the callback-epoch condition used for reclamation.
Keep the test-only diagnostics honest in comments: they detect loop-model lock calls, loop snapshot publication/allocation, and snapshot/asset-owner destruction while the marked callback is active. They are not a global allocator or lock detector. Leave straightforward setter forwarding, sample interpolation, compressor arithmetic, and per-sample filter math uncommented; comments there would narrate mechanics and obscure the ownership boundary.
Instrument Asset Generation And Retirement Comments - 2026-07-31
Comment this contract at five boundaries: cache types own complete immutable asset generations; publication helpers require the corresponding model mutex and atomically exchange complete generations; Voice generation tokens keep every selected leaf alive; retireVoice drops leaf handles before its generation token; retirement reclamation runs only on non-audio writer paths after use_count proves no callback or voice owner remains.
At sample-cache comments, explicitly name Liftoff and Lunacy user sources because they share the sample-layer ownership path. At Quasar comments, distinguish the immutable zone generation from the realtime round-robin cursor. At SoundFont comments, state that the generation owns both the master and prepared TSF rack; a shared_ptr to a prepared voice alone is not the retirement contract.
Keep diagnostics comments narrow and truthful: custom deleters detect callback AudioBuffer destruction, mapped-reader deletion/unmap, and TSF close, while publication hooks detect known asset-model locks and allocations. They are not global new/delete interception or a general mutex profiler.
Leave atomic load/exchange syntax, use_count erase mechanics, sample interpolation, TSF rendering calls, and straightforward setter forwarding uncommented. Comments there should explain only a non-obvious thread, ownership, or final-release invariant, not restate code.
Live Automation Source And Destination Comments - 2026-07-31
- At owner-aware live apply/reset helpers, state that the stored event channel is source identity, not the current internal output channel.
- Name the owner lookup precisely: Shared Pattern matches clips by Pattern, Clip Local matches stable
clipId, and Lane Local matches stablelaneId. - Explain that the immutable sequencer snapshot supplies lane routing, internal output channels are remapped per lane, and equal destinations are deduplicated.
- State the fallback boundary exactly: raw source-channel behavior is allowed only when there is no Arrangement destination; external-only ownership is an Arrangement destination and therefore does not trigger internal fallback.
- Keep hardware reset comments separate. The internal resolver does not replace or newly prove external MIDI send/reset behavior.
- Do not claim physical-device behavior or perceptual audio proof from
AUTOMATION_OWNERSHIP; it deterministically proves internal controller state, ownership isolation, reset, and routing decisions.
Explicit Recording Target Comments - 2026-07-31
- At
mapMidiRecordingStepToTargetClip(), describe an explicit positive clip ID as authoritative. A failed explicit mapping must return failure; it must not search another clip. - Define the playable Arrangement interval from clip start through
length * repeats. Note/drum starts and expression events at or after the final end are rejected; the note-close path may use the end boundary to finish an already valid held note. - Keep the tiny pre-roll clamp separate from interval validation. It protects callback ordering at the first measure and is not general out-of-range forgiveness.
- Inside the playable repeated duration, map through the clip source length. Do not describe valid repeats as post-end extension.
- Rejection occurs before queue publication and uses the existing note/drum or expression dropped-event diagnostic. This prevents hidden shared-Pattern data from appearing through a longer linked clip.
- The deterministic regression proves in-process mapping, diagnostics, payload cleanliness, and linked-lane playback isolation; it does not prove physical controller timing.