Data and safety
On this page
Distinguish live observations, deterministic composition artifacts and static Nitro evidence. They have different identities and verification boundaries. None alone proves a complete audible song.
Capability gate
For live graph work, read get_grid_capabilities and selected-device state.
The capability response reports protocol: 3, extension/host versions and
nested grid_graph capabilities. Inspect the returned fields rather than
assuming an installed extension can mutate the currently selected device.
| Capability | Meaning |
|---|---|
graph_available |
Selected device exposes the version-gated Grid graph surface |
graph_inspection |
Module, port, parameter and coordinate reads |
module_catalog |
Installed Grid package lookup |
module_insertion |
Known package insertion at explicit coordinates |
port_connections |
Live connection access |
native_undo |
Host undo/redo access, not a multi-operation transaction |
Package/extension 0.2.0 uses exact private Bitwig Studio 6.1.1 bindings, which fail closed on unknown runtimes. The public Controller API minimum and compile dependency are 25; read the current host API from capabilities. When graph access is unavailable, exposed controls may remain usable, but do not infer native topology from labels, pixels, old exports or static DSP data. Offline composition/export and local Nitro discovery do not need this live gate.
Selected-device and graph snapshots
Selected-device state describes the current exposed-control surface and may
include a graph. Its properties carry native instance_id, track_id,
selection_token, and selection_guard_available/selection_guard_reason.
These are current-document identities, not persistent project/device UUIDs.
Private identity lookup is optional for public state/inspect: null tokens
preserve those reads but cannot authorize native device insertion/removal.
For builtin devices, properties also expose the observed installed package_id;
nonbuiltin devices report null. An observed selected Grid package UUID can be
reused as an insertion device_id, rather than guessed. It is a package
identity, not a replacement for the selection-token guard.
grid_list_devices returns the selected device's 16-sibling window, native
identities and current selection_token. Check window_complete; this is not
a recursive or guaranteed complete chain inventory. Device insertion (including
replace) and removal require the observed 64-hex expected_selection_token.
The document-thread edit revalidates exact native selection; names are not guards.
Selection is shared with Bitwig's UI and other clients: re-read after navigation,
reload, a write or ambiguity.
A graph snapshot includes graph_id, 64-lowercase-hex revision, and
modules.items. Module records contain live instance_id, installed
package_id, x/y, local inputs/outputs, input connection source, and
native parameters with type, actual value, editability, range and/or options.
Native instance IDs, package UUIDs, parameter IDs and port indexes are distinct.
graph_id identifies the observed native graph object, not a saved project
file. revision hashes that identity and serialized graph state. Native guarded
writes recheck selection and revision at submission; stale state rejects. A
new read is required after insertion, connection, parameter changes, navigation,
undo, reload, failure or timeout. Do not reuse a revision after a write.
grid_clear_graph requires the reviewed expected_revision and explicit
authorization. Save the caller's reviewed snapshot before acting: a transport
error may prevent any response. The guarded native event also returns actual
before and resulting state snapshots. MCP preserves full native failure
payloads (ok: false), including any before; inspect ok, not just whether
a response arrived. These cover observable topology/parameters, not a complete
binary device/preset backup, executable restore or guaranteed multi-step undo
transaction. Clear is never an implicit patch retry or recovery action; verify
the resulting graph separately.
Parameter domains
| Surface | Domain |
|---|---|
Shaping controls and intensity |
Normalized 0–1 |
| MCP exposed-control batch | 0–128, converted by the adapter |
Native protocol set / batch |
Normalized 0–1 |
| Grid module parameter | Exact live native range, boolean type or option backing value |
Static native mix/device setters and automation point normalized |
Normalized 0–1 through the exact native destination scale |
Musical display_value |
Explicit units converted through the selected control's declared native scale |
A discrete label's position is not necessarily its backing value. Send the
actual option value from current metadata, including TIMEBASE when editable;
there is no blanket enum blacklist. Parameter IDs are exact printable strings,
including spaces and pitch names such as C#, not an uppercase-only grammar.
grid_resolve_parameter_value uses Bitwig's native scale for editable continuous
controls. It accepts compatible signed decimal musical displays with units such
as ms, s, Hz, kHz, dB, st, oct, cents, % or bpm; scientific
notation is not its display grammar. The result carries value, current_value,
current_display, requested_display, display_unit, revision and
mutates_project: false. It does not write or return a promised proposed display.
Use the returned value with the returned revision, then verify actual native
value/display. An envelope's native number must not be guessed to mean seconds.
Musical display, native scalar and normalized automation coordinates are not
interchangeable. grid_automation_normalize accepts an already-native
native_value and returns normalized_value with roundtrip_native_value;
it does not parse Hz/ms or assume a linear min/max range. Resolve a Grid musical
display first, then normalize that native scalar for the exact destination.
Native automation linear interpolation is linear in the native automation
domain, not necessarily in normalized display space.
Pitch origins are control-specific. Grid Pitch.VALUE is a C3-relative
semitone coordinate: MIDI note 37 is 37 - 60 = -23 st, not absolute MIDI 37.
Do not generalize that coordinate to every semitone-labelled control. The
resolver preserves the declared display unit and checks the inverse conversion;
it must not reinterpret st as another pitch origin. Drum selectors combine
per-voice Gate In with Pitch In comparison against that offset, using native
tolerant equality (EXACT: false) to avoid floating-point gate loss. This is
neither an all-notes trigger nor a velocity threshold.
The recorded 6.1.1 compatibility report covers 233 insertions and 640 cables (358 inputs/282 outputs). One all-catalog snapshot exposed 851 native controls with none unresolved; this is not 851 individually tested writes. Representative enum, float and boolean writes/undo, including TIMEBASE quarter→eighth→undo, were observed. Runtime metadata and read-back still govern each new operation.
Graph analysis and incremental patches
grid_analyze returns observed graph identity/revision, signal/control/unknown
edge lanes, active/orphan nodes, disconnected output inputs, unused outputs,
intent hypotheses, warnings and uncertainty. “Active” means explicit upstream
reachability from a recognized Audio Out label, not sound production. Port-name
classification is a topology hypothesis; precords and internal behavior can
invalidate a silence inference. Feedback detection is not a stability analysis.
Patch sessions bind recipe aliases to explicit existing instances or verified
insertion deltas, never guessed names. Their integer revision is distinct
from graph_revision. Responses include status (preview, completed or
frozen), bindings, next_action, verified completed steps,
remaining_steps, failure, recovery text and verification_scope.
One authorized step applies at most one operation and reads back the exact target effect while checking protected routing and unexpected collateral changes. A no-op can advance without a native write. External graph changes, failed verification and ambiguity freeze the session. An acknowledged feedback review permits the reviewed topology, not a claim of safe audio behavior.
Recipes are additive, bounded to 64 nodes and 256 operations. Sessions expire
one hour after creation; at most 32 are retained. The before-graph is retained
as evidence, not an executable topology restore. Parameter-only sessions can
preview their exact before-values with grid_patch_restore; applying that
preview is separately authorized. No automatic replay, rollback, replacement,
move or deletion is performed.
Recipes may bind role_id, a source_policy: native-only, and named controls.
Each control declares units, minimum/maximum, neutral, polarity, role scope
and exact alias/parameter destinations with scale/offset. Parameter entries
choose exactly one of native value or musical display_value; musical values
are resolved through the current native control scale before the guarded write.
Bounds are not guessed from normalized ranges.
grid_track_prepare_role associates stable score/voice IDs with a current
document generation, native track/device, graph and patch session. Initial
construction requires an empty native instrument Grid. Later preparation may
refine parameters on that exact binding, never replace modules or alter routing.
grid_track_observe_role requires the bound selection and current graph.
Bindings are process/document-local; names and bank indexes are not identity
substitutes. A completed graph is not complete note, audio or listening evidence.
After reload, grid_track_reconcile_role can establish a fresh read-only
binding from the current project token, selection token, graph revision and
complete explicit recipe-alias-to-native-instance module_bindings. It requires
unique instances, exactly the declared module inventory and explicit cables,
declared native base parameters and matching voice allocation. Extra modules,
unowned/missing routes or any required write reject; corrections need a separate
review. Known mapped host modulators reject, while an empty observation still
leaves host-modulation completeness unknown. Final observations must remain
unchanged before the binding is accepted; failure adopts no resumable patch.
Reconciliation does not revive cached authority or substitute a different role
device within the same native project. It sets audio_acceptance: not_recorded
and marks current-revision listening records as requiring fresh capture.
Source notes must be bound separately, and automation inspected separately.
It proves current structural agreement, not saved-file equivalence, complete
reload persistence or human acceptance.
Native voice configuration
grid_voice_state observes the selected Grid's inspector allocation rather than
assuming it appears on the direct parameter page. grid_set_voice_parameter
changes one of voices (1–64), voice_stacking (1–16), mono_mode,
retrigger_mode, note_priority, legato_glide or glide_ms (0–500).
Use exact supported option values, not option indexes or guessed labels.
Optional glide_ms on the read resolves the musical-unit request without a write.
Writes require authorization, expected_project_token,
expected_selection_token, expected_voice_revision and stopped,
non-recording transport. The document-thread operation rechecks selection and
configuration, uses native undo, and verifies both the requested property and
unchanged unrelated configuration. Static glide edits reject automated glide.
Allocation readback does not prove envelope lifetime, retrigger behavior, legato
sound or release quality; those require playback/capture and listening.
Score gate_ratio is duration as a fraction of a sixteenth note, bounded to
0.05–2; it is not a fraction of the distance to the next note. Values above
one can create overlapping different-pitch notes for legato playback without
changing the existing 0.65 default. Same-channel/same-pitch overlaps still
reject because their MIDI releases are ambiguous. A conflicting kick–bass
clearance policy rejects rather than silently shortening requested gates;
intentional overlap needs an explicit bounded policy.
Pitched role recipes leave Pitch In NOTE_PRIORITY at native Default (0)
and set note priority on the device inspector. This preserves the voice-aware
pitch path needed for device glide. A module-level Last override is not an
equivalent allocation setting; do not substitute it for the device control.
Song plans and exported artifacts
bitwig-track/2 is a deterministic musical plan, not a Bitwig project format.
Its core fields include:
brief, normalizedstyle/family,seed,controls,negative_constraints;tempo_bpm, integertempo_microseconds,meter,ppq: 480,key,root_pitch_class,scaleandscale_pitch_classes;phrase_bars,bar_ticks,bars,duration_ticks,duration_seconds,requested_duration_secondsandfinal_bar_partial;- role-specific
roles, contiguoussections, reusablepatterns,placements, boundedmodulation_routes,resolutionand explicitinferences; - independent
intentdomains,source_policy,synthesis_spec,automation_spec, stablephrases,locks,unresolved_requestsand separate planned/applied/readback/audio/listening evidence.
The default form is intro, development, break, build, peak and outro; explicit
custom forms can be shorter and contain partial final bars. Bars are one-based;
ticks start at zero. Pattern note tuples are
[relative_start_tick, duration_ticks, MIDI_note, velocity]; placement tick
ends are exclusive. Pitched roles use the selected scale. Percussion uses
channel 10 (zero-based channel 9), with 37 rim, 38 snare, 39 clap, 42 hat,
45/50 toms and 51 metallic voice; 36 belongs to the separate kick.
An instrument must still be constructed and verified.
The deterministic compiler enforces supported styles/tonality, explicit-field consistency, six phrases for the default form, at most 2048 bars/1800 seconds/200,000 notes, and non-overlapping same-channel/pitch note releases. Duration is quantized to MIDI ticks under integer microseconds-per-quarter tempo. See the accepted brief grammar, not an assumption that all natural-language adjectives become musical decisions.
Synth choices, envelopes, target headroom and modulation routes are intentions.
They are not installed instruments, measured mix levels or applied automation.
For example, a route's normalized depth is relative to a separately resolved
safe destination span; it is not a native parameter value or emitted MIDI CC.
section_depth_factors is keyed by stable section ID, not section name.
low_end_interaction evaluates scored envelope/gate timing only. Native
ducking, phase, masking and listening remain separate acceptance gates.
Scoped revision uses scope, exact target, flat changes and deliberate
regenerate. Timbre preserves MIDI bytes; local phrase changes preserve other
phrases; arrangement resizes expose downstream offsets. Locks cover notes,
rhythm, tuning, sound and arrangement. A conflict raises without replacing the
accepted review. No old whole-brief overrides revision alias remains.
A grid_track_start review has session_id, salted 64-hex revision, complete
plan, exports, import_attempted, current-revision listening records and
mutates_project: false. Revision makes a fresh identifier even for unchanged MIDI.
Revision is review authority, not a content hash. Sessions are process-local and do not survive
adapter restart.
Export writes a full-length type-1 MIDI conductor track plus role note tracks.
Tempo, meter, section markers, names and note events are present; every track
ends at duration_ticks. No program changes, instruments or audio are rendered.
The bitwig-track-artifact/1 manifest carries the source artifact_sha256,
byte_count, paths, session/revision, MIDI format, note-track count, timing,
sections, roles and complete plan. Files publish without overwrite in a unique
private export directory. Export is durable; its in-memory import authority is
not. Revising invalidates old exports for import.
Audio and human evidence
Audio captures are output evidence, not permitted inputs to sample instruments.
grid_audio_preview binds the current stopped, non-recording project and two
exact Bitwig output port/node serials, in left/right order, to a quarter-note
span and release tail. The engine must already be active, arranger loop off and
all observed tracks disarmed; none is silently changed. Proposals expire after
five minutes. Routing and transport require separate positive authorization.
grid_audio_capture consumes the proposal once and returns an asynchronous
capturing attempt; poll grid_audio_status, never resubmit it. Seek, play and
stop acknowledgements settle through observation, not command replay. At the
observed span end the transport is stopped and verified before recording the
requested release tail (tail_mode: stopped_transport). Output/routing checks
are sampled at most every 250 ms. observed_span_end_beats,
span_end_overshoot_beats, stopped_position_beats and stopped_tail_seconds
describe observed timing, not sample-accurate boundaries; recorder pre-roll and
stop latency remain in the decoded file.
measured requires completed playback, sufficient decoded audio, verified stop
and the bounded technical check. Failures retain requires_observation evidence
and partial files; sessions do not survive adapter restart. Independent recorder
sample/wall-clock bounds do not establish that transport stopped after adapter
loss. Inspect the retained directory and exact project before separately stopping
transport; never restart the consumed attempt.
Measurements contain SHA256, sample count/rate/channels, non-finite/clipped
samples, peak/RMS/crest, a 10 ms envelope summary, last-second tail RMS and
first-order 120 Hz low-band mid/side evidence. Phase coherence is
(mid_energy - side_energy) / (mid_energy + side_energy); null denotes silence
or an undefined ratio, not a mono pass. Mid/side levels disambiguate cancellation.
technical_pass covers only finite, non-silent, unclipped samples, as specified
by technical_pass_scope; it is not full track, phase or native-content acceptance.
Comparison attenuates to the quieter whole-file RMS and can render new verified
matched WAVs. It is not perceptual LUFS matching. grid_track_listening records
an explicitly supplied human judgment against exact audio/review digests in a
new JSON file. It never invents user approval from analysis. Revising the score
removes earlier judgments from the current-revision view without deleting history.
Keep captures, measurements, listening records and their runtime identities local. They are not documentation assets or release examples. Public capability descriptions must not disclose a private project or substitute for a human decision about its audio. Reconciliation and analysis cannot supply that decision.
Static native mix and capability gates
grid_inspect_mix observes native gain, pan and send controls on the document
thread. mix_revision covers exposed values, automation state and send routing.
Each control has an opaque native identity, normalized value, display string,
has_automation and writable. Send evidence includes its destination identity,
enabled state and pre/post-fader flag.
grid_set_mix requires the exact project token, mix revision, control identity
and expected normalized value. One static scalar is changed only at stopped,
non-recording transport with complete recording guards. Automated, disconnected,
disabled or read-only destinations reject. Native conversion and same-event
readback verify the target plus unrelated exposed mixer state. Values are finite
0–1; this is not a dB conversion, signed-pan API or automation writer.
Re-observe after every edit. Ambiguity requires observation, never replay; native
undo or a newly reviewed inverse scalar is the recovery path.
Song capabilities and capabilities.native_song advertise native_mix,
native_note_payload, native_note_refinement and native_score_automation
when the exact installed bindings resolve, with failure reasons otherwise.
These are supported guarded native surfaces, not claims that arranger summaries,
public note cells or automation-presence toggles provide the same contracts.
Complete native source notes
grid_inspect_notes(track_index, native_clip_id) reads the complete bounded
exclusive primary note source, not the summary from grid_inspect_arranger.
The snapshot carries complete, current-document native_id, exact document,
track, clip, content and source identities, content_revision, geometry,
primary_clip_inventory, lanes, channel_metadata and notes.
time_unit: source_quarter_notes and time_quantum: 1/1048576 describe source
coordinates, not loop-expanded arranger playback.
Each note retains note_id, note_identity, lane_identity, start, duration,
pitch, channel, velocity, native attributes and every point of its transpose,
gain, pan, timbre and pressure expressions. Attributes include release
velocity, velocity spread, chance/occurrence/recurrence/repeat semantics, mute
and native timing flags; expression evidence retains curve defaults/offsets,
point identities, shapes, curvature, flags and links. Observation is bounded to
16,384 notes, 2,048 lanes, 65,536 expression points and 512 primary clips.
Oversized, shared, linked/alternate/overlay or ambiguously owned source content
rejects rather than returning a partial payload as complete.
grid_track_bind_notes compares the full reviewed role score with that source
and records exact native note ownership plus the complete protected snapshot.
Names, counts, MIDI exports and arranger summaries cannot establish this binding.
grid_track_preview_notes computes a minimal in-place diff for the bound role's
current score revision. Unchanged notes match first; ambiguous chord, duplicate
or moved-note mappings reject rather than choosing whose expressions to lose.
Updates address start, duration, pitch, channel and velocity; unchanged native
semantics and every expression point stay attached to the same note object.
Insertions/deletions are explicit, and final same-lane overlaps reject before
Bitwig's native overlap trimming can alter another note.
Note and voice binding work in either order, but both must identify the same native project generation and track identity; a reused bank index is not identity. Preparation and reconciliation reject a conflicting current note owner. Reconciliation after reopening may establish the voice first, but the old source-note binding stays unusable until the reopened notes are explicitly inspected and rebound. Note edits and role automation recheck this relationship.
grid_track_apply_notes requires the exact preview digest, fresh project token,
unchanged complete before-state and stopped, non-recording transport. It submits
one native undo-scoped batch and verifies full readback: existing note identities,
unaddressed notes, untouched semantics/expressions, clip geometry, other clips
and exclusive source ownership. requires_observation consumes an ambiguous
attempt; no automatic retry or reimport is a recovery path. Bindings do not
survive process/document changes as authority: after reload, inspect and compare
the complete source again. Source equality is not playback or listening proof.
Primary score-time automation
grid_automation_inspect resolves one exact continuous automatable destination:
native mix gain/pan/enabled connected send, or a parameter of the exact selected
Grid device/module. Its complete bounded surface is the primary unsegmented
arranger curve. Clip, alternate, segmented, pending or generated automation and
unsupported curve attachments reject. Compiled engine psx bytes derive from
the primary authored points; they are not another event store and do not block
inspection.
Snapshots distinguish base_native_value/base_normalized,
automation_native_value/automation_normalized and
modulated_native_value/modulated_normalized, alongside scale metadata,
automation_revision, point identities and owned_spans. has_automation
means a native lane is attached, not that it has points or is playing.
has_timeline_points is the native timeline-point flag; it is not an
automation_overridden flag. Neither flag alone proves effective playback:
inspect the complete points/point_count and separately observe live values.
grid_automation_preview accepts 2–8,192 strictly ordered points with time
in absolute arranger quarter-note beats (0–24576), normalized in 0–1 and
outgoing interpolation: hold|linear. The first and last point delimit a
closed owned span. Both explicitly equal the preserved neutral, and the
final point is a hold reset. A new span must contain no unowned points, overlap
no owned span and not cut an existing shaped/sloped segment. The neutral is the
safe preceding held value or base value, not an arbitrary zero.
Replacement is allowed only for the exact already-owned span whose native
point identities and complete contents still match. Ownership is bridge-session
and native-object-local; reload/restart or external edits never authorize taking
over old curves. Readable saved points are not restored overwrite authority.
grid_automation_apply consumes one exact preview revision/project token while
stopped and non-recording, with native undo and readback of installed points,
unchanged base value and every outside-span point. Failures require observation,
not replay. grid_automation_status retains the receipt rather than refreshing
the live curve.
Curve application records stored-point and native evaluation evidence; it does not run a playback-time parameter-write loop, seek, toggle looping or capture audio. Uninterrupted playback, seek/loop behavior, reload persistence, output measurement and human acceptance remain separate evidence layers.
Song state, identity and import receipts
grid_song_state reports an extension session_id, context_epoch, observed
project name/existence/modified state, selected track, flat inventory, tempo,
meter, transport position, playing/recording state, native peak meters,
arranger_loop_enabled, arranger_loop_start_beats,
arranger_loop_duration_beats, project_save_pending, native_document_generation
and project_token. On 6.1.1, the native generation tracks the controller's
actual document object by reference identity, not just its name or inventory.
It uses a weak reference and a session-local generation rather than retaining
closed projects or relying on a potentially colliding object hash.
The token hashes that generation, observed context/inventory, tempo/meter and
all three arranger-loop fields; position, playing and save-pending are outside
that hash. If native identity is unavailable on 6.1.1, reads remain available
but project mutations reject. Unsupported versions retain explicitly labelled
public observation boundaries. This is not a persistent project UUID,
saved-file identity or complete arranger-note fingerprint.
The bank explicitly includes all channels, including hidden children of
collapsed groups, FX and master tracks. tracks[].index is the bank selector;
position is the native position and is not interchangeable. Capacity is 64
tracks and 16 launcher scenes. Launcher clip_slots describe launcher content,
not arranger notes. Meter values have range 16384, kind peak and unobserved
sentinel −1; a value alone does not establish a complete audible arrangement.
Recording detection is conservative, including arranger record, playing with
armed tracks, and observed recording/queued launcher clips.
Import requires the current workflow-owned export/revision, exact source hash/size, confirmation, fresh project token, supported native capability, unscrolled fully represented inventory, sufficient capacity including one extra group slot, and no recording. The selected target must be Group, Instrument, Audio or Hybrid. Native submission rechecks the exact selected native object, project context, recording and the request deadline before arranger insertion after that target at beat 0. FX/master are visible but are not import targets.
The source MIDI stays complete. Native submission uses a private derived MIDI
with tempo/time-signature metadata removed to avoid the observed tempo-import
modal. Receipts distinguish artifact_sha256 from submitted_sha256, include
source/submitted paths, note-track counts, before-state, target and retention
information. The private submitted file remains available for asynchronous host
consumption. Global tempo/meter require explicit grid_song_transport
operations; import does not set them or start playback.
The transformation removes tempo/meter metadata, not arbitrary raw MIDI events;
“notes/markers” describes compiler-generated delivery, not a generic sanitizer.
Bitwig may create default Organ instruments during import. Inventory each role
and explicitly replace an unintended instrument instead of stacking another.
Receipt status can be queued, submitted, native_rejected or
submission_error_observe_before_retry. The bridge continues to report
verified: false and requires_observation: true, even after a human observes
the arranger; external acceptance evidence is recorded separately.
Status queries add current observation, track-count delta and inventory changes,
but cannot prove note placement, correct instruments or audio. Review the actual
arranger and listen before claiming delivery. A workflow consumes its import
attempt before sending: ambiguous timeout does not authorize a duplicate.
Transport and mute/arm writes are explicit project-token-guarded operations
with submitted/unverified receipts. Playback refuses recording or armed tracks;
tempo/meter, seek, arranger-loop and mute/arm changes refuse recording. Seek requires finite
position_beats in 0–24576 quarter-note beats; use explicit seek to position
the controller-owned project rather than an application-wide PlayFromStart
action. Re-read grid_song_state.position_beats after seeking, then separately
authorize play. Freshly observe context between operations. Export/import
never implicitly play, seek or change tempo/meter.
Transport loop requires explicit boolean enabled. Optional paired
start_beats/duration_beats changes the global arranger range only while
stopped and non-recording, with either enabled state; the start must be finite
and nonnegative, duration positive, and end no later than 24576 quarter-note
beats. Omitting both preserves the range and changes only the flag. Neither
form edits a clip's loop_enabled. Submission is asynchronous, not verified
readback: observe all three arranger_loop_* fields and refresh the project
token before a dependent write.
Native project checkpoints
grid_song_save(expected_project_token, output_dir?, confirm?/cooperative?)
checkpoints the current controller-owned project, independently of any
composition session or MIDI export. Authorization, a fresh token,
recording: false, capabilities.project_save: true and no pending save are
required. Private save bindings support exactly Bitwig 6.1.1; Controller API 25
and bridge protocol 3 do not imply compatibility with other private runtimes.
output_dir names the parent root (default/configuration is shared with song
export). The adapter creates a fresh private bitwig-project-* child and sends
its resolved absolute path. The native UI-thread check requires a real,
canonical, nonsymlink, empty directory outside existing Bitwig project folders.
It rechecks the token, same native document, recording and deadline, rejecting
plugin-bridge documents. The host is asked to save that same document rather
than the application's focused project.
This is ordinary native save, not Collect and Save or rendered audio: external samples/assets may remain external. The host writer is replacement-capable. Caller-owned fresh empty directories avoid existing destinations, but do not provide a general atomic no-clobber promise.
Native success is ok: true, status: "native_save_completed", project_file,
error: null and verification_scope. The expected file is
output_directory/PromptTrack/PromptTrack.bwproject. Success means the native
completion callback ran and that regular nonsymlink file was observed, not
full saved-content equivalence, reload persistence of every property, asset
collection or audio acceptance. MCP adds output_directory,
retry_performed: false and limitations.
On bridge/native failure after allocation, MCP returns ok: false,
status: "requires_observation", the known output_directory, error,
native_response when available (otherwise null), and retry_performed: false.
Validation/filesystem failures before submission are errors, not save receipts.
Retain the directory and inspect it along with fresh grid_song_state.
project_save_pending is a native single-save gate: it clears at the native
callback or submission failure, not at transport loss. If still true, observe;
do not submit another save or delete output that the host may still be writing.
A cleared gate alone is not proof of success. There is no automatic replay,
rollback, durable save receipt ID or import-style revision-consumption ledger.
Any later checkpoint requires fresh observation and renewed intentional authority,
not a blind retry. Adapter restart does not establish that an earlier host save
stopped. Native completion and listening remain separate delivery evidence.
Native arranger and loop state
grid_inspect_arranger(track_index) returns {ok, project_token, track_index, track_name, atomic: false, arranger} for one bank track (0–63), not its
children, launcher, alternate takes or secondary event lists. Observation is
read-only and non-atomic. Private support is exactly Bitwig 6.1.1.
The bounded primary list exposes at most 512 clips, 200,000 inspected source
notes and 16,384 inspected primary lanes. Check available, clips_truncated,
clip_metadata_complete, note_counts_complete, note_details_complete,
per-clip completeness and unavailable_fields; count completeness does not
imply detail completeness.
Clip fields include native_id (current-document signed 32-bit ID),
start_beat, end_beat, length_beats, loop_enabled, loop_start_beats,
loop_length_beats, note_event_count and note_span. Times are quarter-note
beats regardless of meter, with native conversion factor 1. Source-note spans
are content coordinates, not song coordinates; no loop/play-offset expansion,
cropping, probability evaluation, audio analysis or semantic digest is supplied.
Source-media length and persistent IDs are unavailable, not inferred from clips.
For a linear score, disable each enabled clip loop with grid_set_clip_loop:
the observed native_id becomes native_clip_id; supply current
expected_loop_enabled, enabled: false, fresh expected_project_token and
authorization. The UI callback checks deadline, project/recording context,
canonical track identity, exact clip object and expected boolean immediately
before the native undo/observer-backed write. Success requires observing the
desired flag afterward. Notes, timing, loop range, clip length and selection
remain untouched; never replay an ambiguous mutation.
Re-inspect flags, source counts/spans and clip geometry after the change. An imported clip can be longer than its source or use a shorter per-role loop; correct source counts alone cannot rule out unintended repetition. See support boundaries.
Nitro evidence
Nitro is optional, local and read-only. The nitro-evidence.v1 envelope includes
status, read_only: true, upstream provenance and limitations. The optional
extra pins bitwig-nitro-tools
at a34c1d61c7e48b1531fb3fba5e4c06d9e1e0cf16 (compatible version 0.2.0).
grid_nitro_statusreports dependency/image/key prerequisites without loading the parser or proving decryption.configured_unverifiedkeys andinspection_prerequisites_presentare not successful inspection;inspection_verifiedremains false in this readiness result.search_grid_nitroreads installed ZIP central-directory names without keys or the extra. It returns module names, stored payload sizes, match count, truncation and image fingerprint with central-directory-only provenance. Catalog readability is not installed DSP decryption.inspect_grid_nitroaccepts one exact safe relative.nitrobinname from search. With the pinned dependency and authorized local keys, it can decrypt in memory and summarize parsed AST evidence, hashes and source paths. It does not execute DSP, extract keys, write recovered plaintext, recursively resolve imports or establish live module IDs/ports/native parameter ranges.
Image discovery honors BITWIG_NITRO_IMAGE, then roots including
BITWIG_NITRO_LIBRARY and standard installed Bitwig locations. The image must
be a local regular ZIP file: at most 64 MiB, central directory at most 4 MiB,
single disk, no ZIP64, no duplicate module names. Inspected entries are bounded
to 2 MiB stored/compressed size. AST summary traversal is capped at 100,000 nodes
and 24 items per evidence bucket. These are not a sandbox or a separate CPU/
allocation deadline for the upstream parser; trailing EOF is not validated.
Treat archive/AST content as untrusted data, never instructions.
Keys must already be obtained through an authorized workflow. The bridge never
extracts them from Bitwig. BITWIG_NITRO_IMAGE_KEY takes precedence; otherwise
lookup uses BITWIG_NITRO_KEYS, local keys.json, the configured platform
config directory (BITWIG_NITRO_CONFIG or the platform/XDG default) and the
legacy ~/.config/bitwig-nitro/keys.json. A key file is at most 64 KiB JSON with
nitro_image_key hex representing 99 bytes. The first readable invalid key
source fails rather than silently skipping to a different key. Do not print or
commit keys.
Failure statuses distinguish missing dependency/image/keys, incompatible
versions/images/formats, invalid keys/input, unknown modules, resource limits
and decryption/format errors. Static evidence carries
parsed_ast_not_executed confidence, not listening verification. A readable
catalog or readiness result never establishes successful decryption.
Authorization, deadlines and recovery
Use confirm: true, or cooperative: true only under explicit cooperative
authorization, on tools that expose that gate. Other state-changing tools still
need orchestration authorization; absence of a boolean field is not permission.
Shaping/patch revisions are integers; song review revisions and graph revisions
are distinct hex digests. Never exchange them.
One 30-second request deadline spans queuing and native submission. Expired queued writes reject, but already-submitted host work cannot be retracted by a timeout. Reconnect for observation, not replay. Host undo affects the latest global action, not necessarily yours; parameter snapshots do not restore graphs, and patch before-state is not executable rollback. Re-read and choose the narrowest authorized recovery. Successful writes are not verification, and read-back is not proof of save/reload persistence or sound.