c64bridge 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/.github/prompts/steer.prompt.md +55 -0
  2. package/AGENTS.md +9 -7
  3. package/README.md +139 -95
  4. package/data/embeddings_asm.json +1 -1
  5. package/data/embeddings_basic.json +1 -1
  6. package/data/embeddings_hardware.json +1 -1
  7. package/data/embeddings_mixed.json +1 -1
  8. package/data/embeddings_other.json +1 -1
  9. package/data/graphics/petscii-style-guide.md +4 -4
  10. package/data/graphics/sprite-charset-best-practices.md +9 -9
  11. package/data/vice/vice-binary-monitor-spec.md +921 -0
  12. package/dist/.tsbuildinfo +1 -1
  13. package/dist/device.js +86 -10
  14. package/dist/mcp-server.js +1 -1
  15. package/dist/prompts/registry.js +27 -25
  16. package/dist/rag/knowledgeIndex.js +112 -79
  17. package/dist/rag/resourceUris.js +93 -0
  18. package/dist/tools/audio.js +11 -11
  19. package/dist/tools/debug.js +1 -1
  20. package/dist/tools/developer.js +13 -13
  21. package/dist/tools/graphics.js +10 -10
  22. package/dist/tools/machineControl.js +5 -5
  23. package/dist/tools/memory.js +19 -11
  24. package/dist/tools/meta/index.js +1 -1
  25. package/dist/tools/printer.js +11 -12
  26. package/dist/tools/programRunners.js +16 -16
  27. package/dist/tools/rag.js +9 -9
  28. package/dist/tools/registry/config.js +1 -1
  29. package/dist/tools/registry/disk.js +1 -1
  30. package/dist/tools/registry/drive.js +1 -1
  31. package/dist/tools/registry/extract.js +1 -1
  32. package/dist/tools/registry/graphics.js +1 -1
  33. package/dist/tools/registry/memory.js +1 -1
  34. package/dist/tools/registry/platform.js +1 -1
  35. package/dist/tools/registry/printer.js +1 -1
  36. package/dist/tools/registry/program.js +1 -1
  37. package/dist/tools/registry/rag.js +1 -1
  38. package/dist/tools/registry/sound.js +1 -1
  39. package/dist/tools/registry/stream.js +1 -1
  40. package/dist/tools/registry/system.js +1 -1
  41. package/dist/tools/storage.js +15 -15
  42. package/dist/tools/streaming.js +3 -3
  43. package/dist/tools/types.js +41 -4
  44. package/dist/tools/vice.js +2 -5
  45. package/dist/vice/process.js +79 -2
  46. package/dist/vice/readiness.js +35 -0
  47. package/dist/vice/smokeOptions.js +44 -0
  48. package/dist/viceRunner.js +2 -0
  49. package/doc/plans/prompts/README.md +7 -7
  50. package/mcp/prompts.json +42 -59
  51. package/mcp/protocol-examples.json +2 -2
  52. package/mcp/resources.json +179 -166
  53. package/mcp/schemas/c64_config.schema.json +109 -326
  54. package/mcp/schemas/c64_debug.schema.json +158 -337
  55. package/mcp/schemas/c64_disk.schema.json +180 -262
  56. package/mcp/schemas/c64_drive.schema.json +31 -111
  57. package/mcp/schemas/c64_extract.schema.json +193 -291
  58. package/mcp/schemas/c64_graphics.schema.json +208 -308
  59. package/mcp/schemas/c64_memory.schema.json +94 -144
  60. package/mcp/schemas/c64_printer.schema.json +151 -205
  61. package/mcp/schemas/c64_program.schema.json +229 -367
  62. package/mcp/schemas/c64_rag.schema.json +25 -59
  63. package/mcp/schemas/c64_select_backend.schema.json +19 -26
  64. package/mcp/schemas/c64_sound.schema.json +346 -622
  65. package/mcp/schemas/c64_stream.schema.json +25 -54
  66. package/mcp/schemas/c64_system.schema.json +79 -212
  67. package/mcp/schemas/c64_vice.schema.json +24 -55
  68. package/mcp/server.json +1 -1
  69. package/mcp/tools.json +1935 -3443
  70. package/mcp.json +3 -3
  71. package/package.json +17 -14
  72. package/scripts/fetch-external-sources.mjs +1 -2
  73. package/scripts/run-coverage.mjs +26 -1
  74. package/scripts/run-tests.mjs +2 -2
  75. package/scripts/run-tests.ts +273 -52
  76. package/scripts/update-readme.ts +54 -2
  77. package/server.json +2 -2
@@ -1,644 +1,368 @@
1
1
  {
2
2
  "type": "object",
3
- "description": "Sound operations available via the c64_sound tool.",
4
- "oneOf": [
5
- {
6
- "type": "object",
7
- "description": "Capture raw stereo PCM samples from the C64 Ultimate audio UDP stream.",
8
- "properties": {
9
- "op": {
10
- "const": "capture_samples"
11
- },
12
- "count": {
13
- "type": [
14
- "integer",
15
- "null"
16
- ],
17
- "description": "Number of stereo sample pairs to capture.",
18
- "minimum": 1,
19
- "maximum": 65536,
20
- "default": 256
21
- },
22
- "encoding": {
23
- "type": [
24
- "string",
25
- "null"
26
- ],
27
- "description": "Encoding used for the PCM sample payload.",
28
- "enum": [
29
- "base64",
30
- "hex"
31
- ],
32
- "default": "base64"
33
- }
34
- },
35
- "required": [
36
- "op"
3
+ "properties": {
4
+ "op": {
5
+ "type": "string",
6
+ "enum": [
7
+ "capture_samples",
8
+ "set_volume",
9
+ "reset",
10
+ "note_on",
11
+ "note_off",
12
+ "silence_all",
13
+ "play_sid_file",
14
+ "play_mod_file",
15
+ "generate",
16
+ "compile_play",
17
+ "play_preset",
18
+ "pipeline",
19
+ "analyze",
20
+ "record_analyze"
37
21
  ],
38
- "additionalProperties": false
39
- },
40
- {
41
- "type": "object",
42
- "description": "Set the SID master volume register at $D418 (0-15).",
43
- "properties": {
44
- "volume": {
45
- "type": "number",
46
- "description": "Desired SID master volume. Values outside 0-15 are clamped.",
47
- "minimum": 0,
48
- "maximum": 15
49
- },
50
- "op": {
51
- "const": "set_volume"
52
- }
53
- },
54
- "required": [
55
- "volume",
56
- "op"
22
+ "description": "Selects the operation."
23
+ },
24
+ "count": {
25
+ "type": [
26
+ "integer",
27
+ "null"
57
28
  ],
58
- "additionalProperties": false
59
- },
60
- {
61
- "type": "object",
62
- "description": "Soft or hard reset of SID registers to clear glitches.",
63
- "properties": {
64
- "hard": {
65
- "type": "boolean",
66
- "description": "If true, perform a hard register scrub; otherwise silence voices softly.",
67
- "default": false
68
- },
69
- "op": {
70
- "const": "reset"
71
- }
72
- },
73
- "additionalProperties": false,
74
- "required": [
75
- "op"
76
- ]
29
+ "description": "Number of stereo sample pairs to capture.",
30
+ "minimum": 1,
31
+ "maximum": 65536,
32
+ "default": 256
77
33
  },
78
- {
79
- "type": "object",
80
- "description": "Trigger a SID voice with configurable waveform, ADSR, and pitch.",
81
- "properties": {
82
- "voice": {
83
- "type": "integer",
84
- "description": "SID voice to trigger (1-3).",
85
- "minimum": 1,
86
- "maximum": 3,
87
- "default": 1
88
- },
89
- "note": {
90
- "type": [
91
- "string",
92
- "null"
93
- ],
94
- "description": "Musical note like A4, C#5, or Bb3. Overrides frequencyHz if provided.",
95
- "pattern": "^([A-Ga-g])([#b]?)(-?\\d+)$"
96
- },
97
- "frequencyHz": {
98
- "type": [
99
- "number",
100
- "null"
101
- ],
102
- "description": "Explicit frequency in Hz. Used when note is omitted.",
103
- "minimum": 1
104
- },
105
- "system": {
106
- "type": "string",
107
- "description": "Video system for frequency calculation.",
108
- "enum": [
109
- "PAL",
110
- "NTSC"
111
- ],
112
- "default": "PAL"
113
- },
114
- "waveform": {
115
- "type": "string",
116
- "description": "SID waveform to enable.",
117
- "enum": [
118
- "pulse",
119
- "saw",
120
- "tri",
121
- "noise"
122
- ],
123
- "default": "pulse"
124
- },
125
- "pulseWidth": {
126
- "type": "integer",
127
- "description": "Pulse width (0-4095). Used for pulse waveform.",
128
- "minimum": 0,
129
- "maximum": 4095,
130
- "default": 2048
131
- },
132
- "attack": {
133
- "type": "integer",
134
- "description": "Attack rate nibble (0-15).",
135
- "minimum": 0,
136
- "maximum": 15,
137
- "default": 1
138
- },
139
- "decay": {
140
- "type": "integer",
141
- "description": "Decay rate nibble (0-15).",
142
- "minimum": 0,
143
- "maximum": 15,
144
- "default": 1
145
- },
146
- "sustain": {
147
- "type": "integer",
148
- "description": "Sustain level nibble (0-15).",
149
- "minimum": 0,
150
- "maximum": 15,
151
- "default": 15
152
- },
153
- "release": {
154
- "type": "integer",
155
- "description": "Release rate nibble (0-15).",
156
- "minimum": 0,
157
- "maximum": 15,
158
- "default": 3
159
- },
160
- "op": {
161
- "const": "note_on"
162
- }
163
- },
164
- "additionalProperties": false,
165
- "required": [
166
- "op"
167
- ]
34
+ "encoding": {
35
+ "type": [
36
+ "string",
37
+ "null"
38
+ ],
39
+ "description": "Encoding used for the PCM sample payload.",
40
+ "enum": [
41
+ "base64",
42
+ "hex"
43
+ ],
44
+ "default": "base64"
45
+ },
46
+ "volume": {
47
+ "type": "number",
48
+ "description": "Desired SID master volume. Values outside 0-15 are clamped.",
49
+ "minimum": 0,
50
+ "maximum": 15
51
+ },
52
+ "hard": {
53
+ "type": "boolean",
54
+ "description": "If true, perform a hard register scrub; otherwise silence voices softly.",
55
+ "default": false
56
+ },
57
+ "voice": {
58
+ "type": "integer",
59
+ "description": "SID voice to trigger (1-3).",
60
+ "minimum": 1,
61
+ "maximum": 3,
62
+ "default": 1
168
63
  },
169
- {
170
- "type": "object",
171
- "description": "Release a SID voice by clearing its gate bit.",
172
- "properties": {
173
- "voice": {
174
- "type": "integer",
175
- "description": "SID voice to release (1-3).",
176
- "minimum": 1,
177
- "maximum": 3
178
- },
179
- "op": {
180
- "const": "note_off"
181
- }
182
- },
183
- "required": [
184
- "voice",
185
- "op"
64
+ "note": {
65
+ "type": [
66
+ "string",
67
+ "null"
186
68
  ],
187
- "additionalProperties": false
188
- },
189
- {
190
- "type": "object",
191
- "description": "Silence all SID voices with optional audio verification.",
192
- "properties": {
193
- "verify": {
194
- "type": [
195
- "boolean",
196
- "null"
197
- ],
198
- "description": "When true, record audio after silencing to confirm the SID output is quiet.",
199
- "default": false
200
- },
201
- "op": {
202
- "const": "silence_all"
203
- }
204
- },
205
- "additionalProperties": false,
206
- "required": [
207
- "op"
208
- ]
69
+ "description": "Musical note like A4, C#5, or Bb3. Overrides frequencyHz if provided.",
70
+ "pattern": "^([A-Ga-g])([#b]?)(-?\\d+)$"
209
71
  },
210
- {
211
- "type": "object",
212
- "description": "Play a SID file stored on the Ultimate filesystem.",
213
- "properties": {
214
- "path": {
215
- "type": "string",
216
- "description": "Absolute or Ultimate filesystem path to the SID, PRG, or audio file.",
217
- "minLength": 1
218
- },
219
- "songnr": {
220
- "type": [
221
- "integer",
222
- "null"
223
- ],
224
- "description": "Song number within the SID file (0-based index).",
225
- "minimum": 0
226
- },
227
- "op": {
228
- "const": "play_sid_file"
229
- }
230
- },
231
- "required": [
232
- "path",
233
- "op"
72
+ "frequencyHz": {
73
+ "type": [
74
+ "number",
75
+ "null"
234
76
  ],
235
- "additionalProperties": false
236
- },
237
- {
238
- "type": "object",
239
- "description": "Play a MOD tracker module via the Ultimate SID player.",
240
- "properties": {
241
- "path": {
242
- "type": "string",
243
- "description": "Absolute or Ultimate filesystem path to the SID, PRG, or audio file.",
244
- "minLength": 1
245
- },
246
- "op": {
247
- "const": "play_mod_file"
248
- }
249
- },
250
- "required": [
251
- "path",
252
- "op"
77
+ "description": "Explicit frequency in Hz. Used when note is omitted.",
78
+ "minimum": 1
79
+ },
80
+ "system": {
81
+ "type": "string",
82
+ "description": "Video system for frequency calculation.",
83
+ "enum": [
84
+ "PAL",
85
+ "NTSC"
253
86
  ],
254
- "additionalProperties": false
255
- },
256
- {
257
- "type": "object",
258
- "description": "Generate a lightweight SID arpeggio playback sequence.",
259
- "properties": {
260
- "root": {
261
- "type": "string",
262
- "description": "Root note for the arpeggio such as C4 or A#3.",
263
- "pattern": "^([A-Ga-g])([#b]?)(-?\\d+)$",
264
- "default": "C4"
265
- },
266
- "pattern": {
267
- "type": "string",
268
- "description": "Comma-separated semitone offsets (e.g. '0,4,7').",
269
- "minLength": 1,
270
- "default": "0,4,7"
271
- },
272
- "steps": {
273
- "type": "integer",
274
- "description": "Number of notes to schedule.",
275
- "minimum": 1,
276
- "maximum": 128,
277
- "default": 16
278
- },
279
- "tempoMs": {
280
- "type": "integer",
281
- "description": "Delay in milliseconds between notes.",
282
- "minimum": 20,
283
- "maximum": 2000,
284
- "default": 120
285
- },
286
- "waveform": {
287
- "type": "string",
288
- "description": "Waveform for playback.",
289
- "enum": [
290
- "pulse",
291
- "saw",
292
- "tri",
293
- "noise"
294
- ],
295
- "default": "tri"
296
- },
297
- "preset": {
298
- "type": [
299
- "string",
300
- "null"
301
- ],
302
- "description": "Optional musical preset to influence timing/expression.",
303
- "enum": [
304
- "classic",
305
- "expression"
306
- ],
307
- "default": "classic"
308
- },
309
- "op": {
310
- "const": "generate"
311
- }
312
- },
313
- "additionalProperties": false,
314
- "required": [
315
- "op"
316
- ]
87
+ "default": "PAL"
88
+ },
89
+ "waveform": {
90
+ "type": "string",
91
+ "description": "SID waveform to enable.",
92
+ "enum": [
93
+ "pulse",
94
+ "saw",
95
+ "tri",
96
+ "noise"
97
+ ],
98
+ "default": "pulse"
99
+ },
100
+ "pulseWidth": {
101
+ "type": "integer",
102
+ "description": "Pulse width (0-4095). Used for pulse waveform.",
103
+ "minimum": 0,
104
+ "maximum": 4095,
105
+ "default": 2048
106
+ },
107
+ "attack": {
108
+ "type": "integer",
109
+ "description": "Attack rate nibble (0-15).",
110
+ "minimum": 0,
111
+ "maximum": 15,
112
+ "default": 1
113
+ },
114
+ "decay": {
115
+ "type": "integer",
116
+ "description": "Decay rate nibble (0-15).",
117
+ "minimum": 0,
118
+ "maximum": 15,
119
+ "default": 1
120
+ },
121
+ "sustain": {
122
+ "type": "integer",
123
+ "description": "Sustain level nibble (0-15).",
124
+ "minimum": 0,
125
+ "maximum": 15,
126
+ "default": 15
127
+ },
128
+ "release": {
129
+ "type": "integer",
130
+ "description": "Release rate nibble (0-15).",
131
+ "minimum": 0,
132
+ "maximum": 15,
133
+ "default": 3
134
+ },
135
+ "verify": {
136
+ "type": [
137
+ "boolean",
138
+ "null"
139
+ ],
140
+ "description": "When true, record audio after silencing to confirm the SID output is quiet.",
141
+ "default": false
142
+ },
143
+ "path": {
144
+ "type": "string",
145
+ "description": "Absolute or Ultimate filesystem path to the SID, PRG, or audio file.",
146
+ "minLength": 1
147
+ },
148
+ "songnr": {
149
+ "type": [
150
+ "integer",
151
+ "null"
152
+ ],
153
+ "description": "Song number within the SID file (0-based index).",
154
+ "minimum": 0
155
+ },
156
+ "root": {
157
+ "type": "string",
158
+ "description": "Root note for the arpeggio such as C4 or A#3.",
159
+ "pattern": "^([A-Ga-g])([#b]?)(-?\\d+)$",
160
+ "default": "C4"
161
+ },
162
+ "pattern": {
163
+ "type": "string",
164
+ "description": "Comma-separated semitone offsets (e.g. '0,4,7').",
165
+ "minLength": 1,
166
+ "default": "0,4,7"
167
+ },
168
+ "steps": {
169
+ "type": "integer",
170
+ "description": "Number of notes to schedule.",
171
+ "minimum": 1,
172
+ "maximum": 128,
173
+ "default": 16
174
+ },
175
+ "tempoMs": {
176
+ "type": "integer",
177
+ "description": "Delay in milliseconds between notes.",
178
+ "minimum": 20,
179
+ "maximum": 2000,
180
+ "default": 120
181
+ },
182
+ "preset": {
183
+ "type": [
184
+ "string",
185
+ "null"
186
+ ],
187
+ "description": "Optional musical preset to influence timing/expression.",
188
+ "enum": [
189
+ "classic",
190
+ "expression"
191
+ ],
192
+ "default": "classic"
317
193
  },
318
- {
319
- "type": "object",
320
- "description": "Compile SIDWAVE or CPG source and optionally play it immediately.",
321
- "properties": {
322
- "sidwave": {
323
- "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
324
- "type": [
325
- "string",
326
- "object",
327
- "null"
328
- ]
329
- },
330
- "cpg": {
331
- "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
332
- "type": [
333
- "string",
334
- "object",
335
- "null"
336
- ]
337
- },
338
- "format": {
339
- "type": [
340
- "string",
341
- "null"
342
- ],
343
- "description": "Source format hint when providing raw text.",
344
- "enum": [
345
- "yaml",
346
- "json"
347
- ]
348
- },
349
- "output": {
350
- "type": [
351
- "string",
352
- "null"
353
- ],
354
- "description": "Playback target format.",
355
- "enum": [
356
- "prg",
357
- "sid"
358
- ],
359
- "default": "prg"
360
- },
361
- "dryRun": {
362
- "type": [
363
- "boolean",
364
- "null"
365
- ],
366
- "description": "When true, skip playback and only return compilation metadata.",
367
- "default": false
368
- },
369
- "op": {
370
- "const": "compile_play"
371
- }
372
- },
373
- "additionalProperties": false,
374
- "required": [
375
- "op"
194
+ "sidwave": {
195
+ "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
196
+ "type": [
197
+ "string",
198
+ "object",
199
+ "null"
376
200
  ]
377
201
  },
378
- {
379
- "type": "object",
380
- "description": "Compile and play a built-in SID preset such as Für Elise by Beethoven.",
381
- "properties": {
382
- "preset": {
383
- "type": [
384
- "string",
385
- "null"
386
- ],
387
- "description": "Named SID preset to compile and play. Canonical public preset: fuer_elise.",
388
- "minLength": 1,
389
- "default": "fuer_elise"
390
- },
391
- "platforms": {
392
- "type": [
393
- "array",
394
- "null"
395
- ],
396
- "items": {
397
- "type": "string",
398
- "description": "Backends to target in sequence.",
399
- "minLength": 1,
400
- "enum": [
401
- "vice",
402
- "c64u"
403
- ]
404
- }
405
- },
406
- "verify": {
407
- "type": [
408
- "boolean",
409
- "null"
410
- ],
411
- "description": "Capture and analyze audio on supported backends after playback starts.",
412
- "default": true
413
- },
414
- "analysisDurationSeconds": {
415
- "type": [
416
- "number",
417
- "null"
418
- ],
419
- "description": "Length of the verification recording on analyzable backends.",
420
- "minimum": 0.5,
421
- "maximum": 20,
422
- "default": 4
423
- },
424
- "waitBeforeCaptureMs": {
425
- "type": [
426
- "number",
427
- "null"
428
- ],
429
- "description": "Delay between starting playback and beginning verification capture.",
430
- "minimum": 0,
431
- "maximum": 5000,
432
- "default": 400
433
- },
434
- "restoreActiveBackend": {
435
- "type": [
436
- "boolean",
437
- "null"
438
- ],
439
- "description": "Restore the backend that was active before the workflow started.",
440
- "default": true
441
- },
442
- "op": {
443
- "const": "play_preset"
444
- }
445
- },
446
- "additionalProperties": false,
447
- "required": [
448
- "op"
202
+ "cpg": {
203
+ "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
204
+ "type": [
205
+ "string",
206
+ "object",
207
+ "null"
449
208
  ]
450
209
  },
451
- {
452
- "type": "object",
453
- "description": "Compile a SIDWAVE score, play it, and analyze the recording.",
454
- "properties": {
455
- "sidwave": {
456
- "type": [
457
- "string",
458
- "null"
459
- ],
460
- "description": "SIDWAVE source in YAML or JSON format.",
461
- "minLength": 1
462
- },
463
- "cpg": {
464
- "type": [
465
- "string",
466
- "null"
467
- ],
468
- "description": "Legacy CPG input format.",
469
- "minLength": 1
470
- },
471
- "output": {
472
- "type": [
473
- "string",
474
- "null"
475
- ],
476
- "description": "Playback artifact format.",
477
- "enum": [
478
- "prg",
479
- "sid"
480
- ],
481
- "default": "prg"
482
- },
483
- "waitBeforeCaptureMs": {
484
- "type": [
485
- "number",
486
- "null"
487
- ],
488
- "description": "Delay between starting playback and beginning analysis capture (milliseconds).",
489
- "minimum": 0,
490
- "maximum": 5000,
491
- "default": 500
492
- },
493
- "analysisDurationSeconds": {
494
- "type": [
495
- "number",
496
- "null"
497
- ],
498
- "description": "Audio capture length in seconds.",
499
- "minimum": 0.5,
500
- "maximum": 20,
501
- "default": 3
502
- },
503
- "expectedSidwave": {
504
- "type": [
505
- "string",
506
- "null"
507
- ],
508
- "description": "Optional expected SIDWAVE used to refine analysis comparisons.",
509
- "minLength": 1
510
- },
511
- "verifySilenceBefore": {
512
- "type": [
513
- "boolean",
514
- "null"
515
- ],
516
- "description": "Run silence verification before playback to ensure a quiet baseline.",
517
- "default": true
518
- },
519
- "verifySilenceAfter": {
520
- "type": [
521
- "boolean",
522
- "null"
523
- ],
524
- "description": "Run silence verification after playback to ensure voices are released.",
525
- "default": true
526
- },
527
- "silenceDurationSeconds": {
528
- "type": [
529
- "number",
530
- "null"
531
- ],
532
- "description": "Audio capture length used for silence verification.",
533
- "minimum": 0.5,
534
- "maximum": 10,
535
- "default": 1.5
536
- },
537
- "silenceRmsThreshold": {
538
- "type": [
539
- "number",
540
- "null"
541
- ],
542
- "description": "RMS threshold applied to silence verification captures.",
543
- "minimum": 0,
544
- "maximum": 1,
545
- "default": 0.02
546
- },
547
- "postSilenceWaitMs": {
548
- "type": [
549
- "number",
550
- "null"
551
- ],
552
- "description": "Delay between main analysis capture and the post-playback silence check (milliseconds).",
553
- "minimum": 0,
554
- "maximum": 5000,
555
- "default": 200
556
- },
557
- "silenceWaitMs": {
558
- "type": [
559
- "number",
560
- "null"
561
- ],
562
- "description": "Delay between silencing the SID and recording during pre/post checks (milliseconds).",
563
- "minimum": 0,
564
- "maximum": 5000,
565
- "default": 150
566
- },
567
- "op": {
568
- "const": "pipeline"
569
- }
570
- },
571
- "additionalProperties": false,
572
- "required": [
573
- "op"
210
+ "format": {
211
+ "type": [
212
+ "string",
213
+ "null"
214
+ ],
215
+ "description": "Source format hint when providing raw text.",
216
+ "enum": [
217
+ "yaml",
218
+ "json"
574
219
  ]
575
220
  },
576
- {
577
- "type": "object",
578
- "description": "Automatically analyze SID playback when verification is requested.",
579
- "properties": {
580
- "request": {
581
- "type": "string",
582
- "description": "Natural language user request describing the verification goal.",
583
- "minLength": 1
584
- },
585
- "durationSeconds": {
586
- "type": [
587
- "number",
588
- "null"
589
- ],
590
- "description": "Override capture duration in seconds.",
591
- "minimum": 0.5,
592
- "maximum": 30
593
- },
594
- "expectedSidwave": {
595
- "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
596
- "type": [
597
- "string",
598
- "object",
599
- "null"
600
- ]
601
- },
602
- "op": {
603
- "const": "analyze"
604
- }
605
- },
606
- "required": [
607
- "request",
608
- "op"
221
+ "output": {
222
+ "type": [
223
+ "string",
224
+ "null"
225
+ ],
226
+ "description": "Playback target format.",
227
+ "enum": [
228
+ "prg",
229
+ "sid"
230
+ ],
231
+ "default": "prg"
232
+ },
233
+ "dryRun": {
234
+ "type": [
235
+ "boolean",
236
+ "null"
237
+ ],
238
+ "description": "When true, skip playback and only return compilation metadata.",
239
+ "default": false
240
+ },
241
+ "platforms": {
242
+ "type": [
243
+ "array",
244
+ "null"
245
+ ],
246
+ "items": {
247
+ "type": "string",
248
+ "description": "Backends to target in sequence.",
249
+ "minLength": 1,
250
+ "enum": [
251
+ "vice",
252
+ "c64u"
253
+ ]
254
+ }
255
+ },
256
+ "analysisDurationSeconds": {
257
+ "type": [
258
+ "number",
259
+ "null"
260
+ ],
261
+ "description": "Length of the verification recording on analyzable backends.",
262
+ "minimum": 0.5,
263
+ "maximum": 20,
264
+ "default": 4
265
+ },
266
+ "waitBeforeCaptureMs": {
267
+ "type": [
268
+ "number",
269
+ "null"
270
+ ],
271
+ "description": "Delay between starting playback and beginning verification capture.",
272
+ "minimum": 0,
273
+ "maximum": 5000,
274
+ "default": 400
275
+ },
276
+ "restoreActiveBackend": {
277
+ "type": [
278
+ "boolean",
279
+ "null"
280
+ ],
281
+ "description": "Restore the backend that was active before the workflow started.",
282
+ "default": true
283
+ },
284
+ "expectedSidwave": {
285
+ "type": [
286
+ "string",
287
+ "null"
609
288
  ],
610
- "additionalProperties": false
611
- },
612
- {
613
- "type": "object",
614
- "description": "Record audio for a fixed duration and return SID analysis metrics.",
615
- "properties": {
616
- "durationSeconds": {
617
- "type": "number",
618
- "description": "Capture duration in seconds (0.5 - 30).",
619
- "minimum": 0.5,
620
- "maximum": 30
621
- },
622
- "expectedSidwave": {
623
- "description": "SIDWAVE composition represented as YAML/JSON text or an already parsed object.",
624
- "type": [
625
- "string",
626
- "object",
627
- "null"
628
- ]
629
- },
630
- "op": {
631
- "const": "record_analyze"
632
- }
633
- },
634
- "required": [
635
- "durationSeconds",
636
- "op"
289
+ "description": "Optional expected SIDWAVE used to refine analysis comparisons.",
290
+ "minLength": 1
291
+ },
292
+ "verifySilenceBefore": {
293
+ "type": [
294
+ "boolean",
295
+ "null"
296
+ ],
297
+ "description": "Run silence verification before playback to ensure a quiet baseline.",
298
+ "default": true
299
+ },
300
+ "verifySilenceAfter": {
301
+ "type": [
302
+ "boolean",
303
+ "null"
304
+ ],
305
+ "description": "Run silence verification after playback to ensure voices are released.",
306
+ "default": true
307
+ },
308
+ "silenceDurationSeconds": {
309
+ "type": [
310
+ "number",
311
+ "null"
312
+ ],
313
+ "description": "Audio capture length used for silence verification.",
314
+ "minimum": 0.5,
315
+ "maximum": 10,
316
+ "default": 1.5
317
+ },
318
+ "silenceRmsThreshold": {
319
+ "type": [
320
+ "number",
321
+ "null"
322
+ ],
323
+ "description": "RMS threshold applied to silence verification captures.",
324
+ "minimum": 0,
325
+ "maximum": 1,
326
+ "default": 0.02
327
+ },
328
+ "postSilenceWaitMs": {
329
+ "type": [
330
+ "number",
331
+ "null"
332
+ ],
333
+ "description": "Delay between main analysis capture and the post-playback silence check (milliseconds).",
334
+ "minimum": 0,
335
+ "maximum": 5000,
336
+ "default": 200
337
+ },
338
+ "silenceWaitMs": {
339
+ "type": [
340
+ "number",
341
+ "null"
342
+ ],
343
+ "description": "Delay between silencing the SID and recording during pre/post checks (milliseconds).",
344
+ "minimum": 0,
345
+ "maximum": 5000,
346
+ "default": 150
347
+ },
348
+ "request": {
349
+ "type": "string",
350
+ "description": "Natural language user request describing the verification goal.",
351
+ "minLength": 1
352
+ },
353
+ "durationSeconds": {
354
+ "type": [
355
+ "number",
356
+ "null"
637
357
  ],
638
- "additionalProperties": false
358
+ "description": "Override capture duration in seconds.",
359
+ "minimum": 0.5,
360
+ "maximum": 30
639
361
  }
362
+ },
363
+ "required": [
364
+ "op"
640
365
  ],
641
- "discriminator": {
642
- "propertyName": "op"
643
- }
366
+ "description": "Sound operations available via the c64_sound tool.\n\nOperations:\n- capture_samples: Capture raw stereo PCM samples from the C64 Ultimate audio UDP stream.\n- set_volume: Set the SID master volume register at $D418 (0-15).\n- reset: Soft or hard reset of SID registers to clear glitches.\n- note_on: Trigger a SID voice with configurable waveform, ADSR, and pitch.\n- note_off: Release a SID voice by clearing its gate bit.\n- silence_all: Silence all SID voices with optional audio verification.\n- play_sid_file: Play a SID file stored on the Ultimate filesystem.\n- play_mod_file: Play a MOD tracker module via the Ultimate SID player.\n- generate: Generate a lightweight SID arpeggio playback sequence.\n- compile_play: Compile SIDWAVE or CPG source and optionally play it immediately.\n- play_preset: Compile and play a built-in SID preset such as Für Elise by Beethoven.\n- pipeline: Compile a SIDWAVE score, play it, and analyze the recording.\n- analyze: Automatically analyze SID playback when verification is requested.\n- record_analyze: Record audio for a fixed duration and return SID analysis metrics.",
367
+ "additionalProperties": false
644
368
  }