Skip to content

Commit 166349c

Browse files
feat: add project metadata and playlist marker navigation support to FL Studio controller
1 parent bf440b9 commit 166349c

33 files changed

Lines changed: 1320 additions & 106 deletions

agent-docs/concepts/api-capability-audit.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,37 @@ They now route through the safety layer. Piano Roll writes are backed by FL
101101
Studio undo: the generated scripts wrap edits in `flp.score.undoSection()` when
102102
available, and MCP rollback invokes `general.undoUp()`.
103103

104+
## Project Metadata and Playlist Markers
105+
106+
Status: `documented` for read-only project metadata getters and playlist marker
107+
names; `api-limited` for metadata setters and stable marker time readback.
108+
109+
Useful API:
110+
111+
- `general.getProjectTitle`
112+
- `general.getProjectAuthor`
113+
- `general.getProjectGenre`
114+
- `arrangement.getMarkerName`
115+
- `arrangement.jumpToMarker`
116+
117+
Current shipped behavior:
118+
119+
- `fl_get_project_metadata` reads title, author, and genre and reports metadata
120+
writes as API-limited because documented setters are not available.
121+
- `fl_transport(action="list_markers")` reads playlist marker names when the
122+
arrangement module exposes them.
123+
- `fl_transport(action="jump_to_marker")` and
124+
`fl_transport(action="jump_marker_relative")` are transient playback
125+
navigation controls. They do not edit playlist clips or marker data.
126+
127+
Known limitations:
128+
129+
- Marker time/position readback is not exposed through the documented
130+
arrangement API, so UI marker lists show names and navigate through transient
131+
marker jumps without claiming exact marker time readback.
132+
- Playlist clip placement, movement, deletion, and deep clip editing remain
133+
unsupported.
134+
104135
## Dynamic Mixer Track Handling
105136

106137
Status: `documented` for reading the current mixer-track count; `probe-needed`

agent-docs/machine/architecture-governance.snapshot.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"snapshot_version": 1,
3-
"as_of": "2026-06-20",
3+
"as_of": "2026-06-30",
44
"status": "governed",
5-
"governance_note": "Architecture snapshot unchanged. fls_pilot.packs (local_pack_metadata component) and fls_pilot.rules (analysis_runtime component) are already captured as governed source-of-truth paths in this snapshot. The corrective-patch changes in this batch — test isolation, audit_anti_vibe.py isinstance guard, and evals additions — are small-behaviour-preserving fixes with no public-surface, safety-posture, protocol/controller, or trust-boundary effect. No governed or generated architecture fact changed.",
5+
"governance_note": "Updated for read-only project metadata, playlist marker read/navigation, Control Center live playback controls, and Level 2 live-meter workflow declarations. Persistent-write safety posture is unchanged; new playback and marker navigation actions are transient.",
66
"project": {
77
"name": "fls-pilot",
88
"package_version": "3.0.0rc1",
@@ -238,8 +238,8 @@
238238
"registration_source": "src/fls_pilot/server.py",
239239
"tool_modules_source": "src/fls_pilot/tools/",
240240
"baseline": {
241-
"registered_public_tools": 91,
242-
"static_audited_tools": 167,
241+
"registered_public_tools": 92,
242+
"static_audited_tools": 168,
243243
"check": "python scripts/check_tool_registration_baseline.py"
244244
},
245245
"resources": [

agent-docs/machine/architecture/analysis-workflows.snapshot.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@
9191
"project_identity_change",
9292
"audio_source_hash_changed"
9393
]
94+
},
95+
{
96+
"id": "live_meter_window",
97+
"observation_kind": "live_meter_window",
98+
"required": false,
99+
"evidence_mode": "live_runtime",
100+
"invalidates_on": [],
101+
"ttl_seconds": 2
94102
}
95103
]
96104
},
@@ -163,6 +171,14 @@
163171
"project_identity_change",
164172
"audio_source_hash_changed"
165173
]
174+
},
175+
{
176+
"id": "live_meter_window",
177+
"observation_kind": "live_meter_window",
178+
"required": false,
179+
"evidence_mode": "live_runtime",
180+
"invalidates_on": [],
181+
"ttl_seconds": 2
166182
}
167183
]
168184
},

agent-docs/machine/architecture/controller-surface.snapshot.json

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@
9090
"constant": "CMD_GET_PROJECT_STATE",
9191
"command": "get_project_state"
9292
},
93+
{
94+
"constant": "CMD_GET_PROJECT_METADATA",
95+
"command": "get_project_metadata"
96+
},
9397
{
9498
"constant": "CMD_MIXER_LIST_TRACKS",
9599
"command": "mixer_list_tracks"
@@ -230,6 +234,10 @@
230234
"constant": "CMD_MIXER_GET_PEAKS",
231235
"command": "mixer_get_peaks"
232236
},
237+
{
238+
"constant": "CMD_MIXER_GET_ALL_PEAKS",
239+
"command": "mixer_get_all_peaks"
240+
},
233241
{
234242
"constant": "CMD_MIXER_SET_COLOR",
235243
"command": "mixer_set_color"
@@ -270,6 +278,18 @@
270278
"constant": "CMD_ARRANGE_ADD_MARKER",
271279
"command": "arrange_add_marker"
272280
},
281+
{
282+
"constant": "CMD_LIST_PLAYLIST_MARKERS",
283+
"command": "list_playlist_markers"
284+
},
285+
{
286+
"constant": "CMD_JUMP_PLAYLIST_MARKER",
287+
"command": "jump_playlist_marker"
288+
},
289+
{
290+
"constant": "CMD_JUMP_PLAYLIST_MARKER_RELATIVE",
291+
"command": "jump_playlist_marker_relative"
292+
},
273293
{
274294
"constant": "CMD_ENSURE_PIANO_ROLL",
275295
"command": "ensure_piano_roll"
@@ -358,6 +378,18 @@
358378
"constant": "CMD_MIXER_PROBE_EQ_TYPE",
359379
"command": "mixer_probe_eq_type"
360380
},
381+
{
382+
"constant": "CMD_MIXER_PROBE_EQ_GAIN",
383+
"command": "mixer_probe_eq_gain"
384+
},
385+
{
386+
"constant": "CMD_MIXER_PROBE_EQ_FREQ",
387+
"command": "mixer_probe_eq_freq"
388+
},
389+
{
390+
"constant": "CMD_MIXER_PROBE_EQ_Q",
391+
"command": "mixer_probe_eq_q"
392+
},
361393
{
362394
"constant": "CMD_GET_TIME_SIG",
363395
"command": "get_time_sig"
@@ -376,10 +408,6 @@
376408
"command": "ping",
377409
"handler": "_h_ping"
378410
},
379-
{
380-
"command": "bridge_eval",
381-
"handler": "lambda"
382-
},
383411
{
384412
"command": "get_tempo",
385413
"handler": "_h_get_tempo"
@@ -428,6 +456,10 @@
428456
"command": "get_project_state",
429457
"handler": "_h_get_project_state"
430458
},
459+
{
460+
"command": "get_project_metadata",
461+
"handler": "_h_get_project_metadata"
462+
},
431463
{
432464
"command": "mixer_list_tracks",
433465
"handler": "_h_mixer_list_tracks"
@@ -588,6 +620,18 @@
588620
"command": "arrange_add_marker",
589621
"handler": "_h_arrange_add_marker"
590622
},
623+
{
624+
"command": "list_playlist_markers",
625+
"handler": "_h_list_playlist_markers"
626+
},
627+
{
628+
"command": "jump_playlist_marker",
629+
"handler": "_h_jump_playlist_marker"
630+
},
631+
{
632+
"command": "jump_playlist_marker_relative",
633+
"handler": "_h_jump_playlist_marker_relative"
634+
},
591635
{
592636
"command": "channel_select",
593637
"handler": "_h_channel_select"
@@ -696,22 +740,6 @@
696740
"command": "mixer_set_eq",
697741
"handler": "_h_mixer_set_eq"
698742
},
699-
{
700-
"command": "mixer_probe_eq_type",
701-
"handler": "_h_mixer_probe_eq_type"
702-
},
703-
{
704-
"command": "mixer_probe_eq_gain",
705-
"handler": "_h_mixer_probe_eq_gain"
706-
},
707-
{
708-
"command": "mixer_probe_eq_freq",
709-
"handler": "_h_mixer_probe_eq_freq"
710-
},
711-
{
712-
"command": "mixer_probe_eq_q",
713-
"handler": "_h_mixer_probe_eq_q"
714-
},
715743
{
716744
"command": "mixer_format_event_value",
717745
"handler": "_h_mixer_format_event_value"
@@ -727,9 +755,25 @@
727755
{
728756
"command": "channel_set_steps",
729757
"handler": "_h_channel_set_steps"
758+
},
759+
{
760+
"command": "mixer_probe_eq_type",
761+
"handler": "_h_mixer_probe_eq_type"
762+
},
763+
{
764+
"command": "mixer_probe_eq_gain",
765+
"handler": "_h_mixer_probe_eq_gain"
766+
},
767+
{
768+
"command": "mixer_probe_eq_freq",
769+
"handler": "_h_mixer_probe_eq_freq"
770+
},
771+
{
772+
"command": "mixer_probe_eq_q",
773+
"handler": "_h_mixer_probe_eq_q"
730774
}
731775
],
732-
"handler_count": 89
776+
"handler_count": 92
733777
},
734778
"source_files": {
735779
"protocol": "src/fls_pilot/protocol.py",

agent-docs/machine/architecture/mcp-surface.snapshot.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414
"payload": {
1515
"tool_safety_summary": {
1616
"external-write": 2,
17-
"read-only": 70,
17+
"read-only": 71,
1818
"server-state": 5,
1919
"transient": 6,
2020
"write-safe-required": 84
2121
},
22-
"tools_total": 167,
22+
"tools_total": 168,
2323
"tool_module_slices": {
2424
"arrange": {
2525
"path": "agent-docs/machine/architecture/mcp-tools/arrange.snapshot.json",
@@ -140,12 +140,12 @@
140140
},
141141
"mixer_core": {
142142
"path": "agent-docs/machine/architecture/mcp-tools/mixer_core.snapshot.json",
143-
"tools_total": 30,
143+
"tools_total": 31,
144144
"safety_class_counts": {
145-
"external-write": 1,
146-
"read-only": 9,
145+
"read-only": 10,
146+
"write-safe-required": 16,
147147
"server-state": 4,
148-
"write-safe-required": 16
148+
"external-write": 1
149149
},
150150
"destructive_hint_true_count": 2
151151
},

agent-docs/machine/architecture/mcp-tools/index.snapshot.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@
124124
},
125125
"mixer_core": {
126126
"path": "agent-docs/machine/architecture/mcp-tools/mixer_core.snapshot.json",
127-
"tools_total": 30,
127+
"tools_total": 31,
128128
"safety_class_counts": {
129-
"external-write": 1,
130-
"read-only": 9,
129+
"read-only": 10,
130+
"write-safe-required": 16,
131131
"server-state": 4,
132-
"write-safe-required": 16
132+
"external-write": 1
133133
},
134134
"destructive_hint_true_count": 2
135135
},

0 commit comments

Comments
 (0)