c64bridge 0.7.4 → 0.8.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 (107) hide show
  1. package/.github/prompts/README.md +14 -4
  2. package/.github/prompts/assembly-routine-session.prompt.md +9 -9
  3. package/.github/prompts/basic-program-session.prompt.md +11 -9
  4. package/.github/prompts/drive-management-session.prompt.md +9 -9
  5. package/.github/prompts/hello-world-session.prompt.md +17 -0
  6. package/.github/prompts/petscii-art-session.prompt.md +9 -9
  7. package/.github/prompts/play-classic-game.prompt.md +9 -9
  8. package/.github/prompts/pr-converge.prompt.md +13 -0
  9. package/.github/prompts/sid-music-session.prompt.md +9 -9
  10. package/AGENTS.md +59 -60
  11. package/README.md +550 -191
  12. package/data/assembly/assembly-spec.md +290 -1
  13. package/data/context/bootstrap.md +26 -2
  14. package/data/context/fast-paths.md +44 -0
  15. package/data/graphics/petscii-style-guide.md +6 -2
  16. package/data/graphics/sprite-charset-best-practices.md +5 -5
  17. package/dist/.tsbuildinfo +1 -1
  18. package/dist/c64Client.js +990 -26
  19. package/dist/config.js +5 -1
  20. package/dist/device.js +680 -57
  21. package/dist/diagnostics.js +371 -0
  22. package/dist/mcp/metadata.js +39 -0
  23. package/dist/mcp-server.js +170 -20
  24. package/dist/platform.js +10 -2
  25. package/dist/prompts/registry.js +166 -309
  26. package/dist/rag/init.js +37 -1
  27. package/dist/rag/knowledgeIndex.js +18 -6
  28. package/dist/rag/rateLimiter.js +2 -2
  29. package/dist/streamCapture.js +135 -0
  30. package/dist/tools/audio.js +3 -1
  31. package/dist/tools/debug.js +470 -0
  32. package/dist/tools/developer.js +10 -4
  33. package/dist/tools/graphics.js +183 -17
  34. package/dist/tools/machineControl.js +11 -5
  35. package/dist/tools/memory.js +19 -10
  36. package/dist/tools/meta/audio.js +240 -1
  37. package/dist/tools/meta/config.js +20 -28
  38. package/dist/tools/meta/configInventory.js +104 -0
  39. package/dist/tools/meta/diagnostics.js +45 -2
  40. package/dist/tools/meta/graphics.js +14 -6
  41. package/dist/tools/meta/index.js +1 -0
  42. package/dist/tools/meta/memory.js +20 -6
  43. package/dist/tools/meta/program.js +473 -0
  44. package/dist/tools/pollValidator.js +4 -2
  45. package/dist/tools/programRunners.js +8 -4
  46. package/dist/tools/registry/config.js +17 -0
  47. package/dist/tools/registry/disk.js +7 -0
  48. package/dist/tools/registry/drive.js +3 -0
  49. package/dist/tools/registry/graphics.js +111 -27
  50. package/dist/tools/registry/index.js +6 -0
  51. package/dist/tools/registry/memory.js +1 -0
  52. package/dist/tools/registry/platform.js +121 -0
  53. package/dist/tools/registry/program.js +26 -8
  54. package/dist/tools/registry/sound.js +96 -0
  55. package/dist/tools/registry/system.js +15 -2
  56. package/dist/tools/storage.js +1 -0
  57. package/dist/tools/streaming.js +1 -0
  58. package/dist/tools/types.js +38 -4
  59. package/dist/tools/vice.js +160 -0
  60. package/dist/vicBitmap.js +317 -0
  61. package/dist/vice/mockServer.js +439 -0
  62. package/dist/vice/process.js +310 -0
  63. package/dist/vice/readiness.js +18 -2
  64. package/dist/vice/viceClient.js +382 -22
  65. package/doc/developer.md +62 -24
  66. package/doc/img/backend-switch/hello-c64u.png +0 -0
  67. package/doc/img/backend-switch/hello-vice-and-c64u.png +0 -0
  68. package/doc/img/backend-switch/hello-vice.png +0 -0
  69. package/doc/img/backend-switch/metadata.json +50 -0
  70. package/doc/plans/vice-backend-switch/plan.md +486 -0
  71. package/doc/plans/vice-backend-switch-2/plan.md +48 -0
  72. package/doc/plans/vice-support/notes.md +1 -0
  73. package/doc/plans/vice-support/plan.md +5 -0
  74. package/doc/plans/vice-support/rollout.md +23 -17
  75. package/doc/reviews/vice-support-review.md +185 -0
  76. package/doc/troubleshooting-mcp.md +35 -6
  77. package/doc/vice/support-matrix.md +54 -0
  78. package/mcp/prompts.json +292 -0
  79. package/mcp/protocol-examples.json +46 -0
  80. package/mcp/resources.json +940 -0
  81. package/mcp/schemas/c64_config.schema.json +350 -0
  82. package/mcp/schemas/c64_debug.schema.json +380 -0
  83. package/mcp/schemas/c64_disk.schema.json +278 -0
  84. package/mcp/schemas/c64_drive.schema.json +120 -0
  85. package/mcp/schemas/c64_extract.schema.json +302 -0
  86. package/mcp/schemas/c64_graphics.schema.json +333 -0
  87. package/mcp/schemas/c64_memory.schema.json +155 -0
  88. package/mcp/schemas/c64_printer.schema.json +218 -0
  89. package/mcp/schemas/c64_program.schema.json +391 -0
  90. package/mcp/schemas/c64_rag.schema.json +67 -0
  91. package/mcp/schemas/c64_select_backend.schema.json +32 -0
  92. package/mcp/schemas/c64_sound.schema.json +644 -0
  93. package/mcp/schemas/c64_stream.schema.json +61 -0
  94. package/mcp/schemas/c64_system.schema.json +227 -0
  95. package/mcp/schemas/c64_vice.schema.json +63 -0
  96. package/mcp/server.json +15 -0
  97. package/mcp/tools.json +4517 -0
  98. package/mcp.json +83 -9
  99. package/package.json +8 -3
  100. package/scripts/capture-backend-switch-screenshots.mjs +276 -0
  101. package/scripts/generate-mcp-interface.ts +289 -0
  102. package/scripts/invoke-bun.mjs +67 -21
  103. package/scripts/mockC64Server.mjs +162 -6
  104. package/scripts/run-coverage.mjs +284 -0
  105. package/scripts/run-tests.mjs +95 -39
  106. package/scripts/run-tests.ts +378 -73
  107. package/scripts/update-readme.ts +147 -13
@@ -1,213 +1,52 @@
1
1
  import { listKnowledgeResources } from "../rag/knowledgeIndex.js";
2
2
  import { toolRegistry } from "../tools/registry/index.js";
3
- const BASE_SEGMENTS = {
4
- "intro/core": {
5
- id: "intro/core",
6
- role: "assistant",
7
- content: [
8
- "You operate the Commodore 64 Ultimate hardware through MCP tools and documented workflows.",
9
- "Consult the listed knowledge resources before generating code or issuing device commands.",
10
- "State each intended MCP tool invocation explicitly and explain why it is required before running it.",
11
- ].join("\n"),
12
- },
13
- "safety/reset": {
14
- id: "safety/reset",
15
- role: "assistant",
16
- content: [
17
- "Safety guardrails:",
18
- "- Ask the user before resets, power cycles, disk swaps, or destructive writes.",
19
- "- Offer an undo or recovery path (reload prior program, remount image, or restore settings).",
20
- "- Highlight side effects that could halt running software or corrupt data.",
21
- ].join("\n"),
22
- },
23
- "workflow/basic-verify": {
24
- id: "workflow/basic-verify",
25
- role: "assistant",
26
- content: [
27
- "Verification for BASIC programs:",
28
- "- After uploading, call `c64_memory` (op `read_screen`) to capture PETSCII output and confirm `READY.` appears when expected.",
29
- "- Use `c64_memory` (op `read`) around the BASIC program area when verifying that lines tokenised correctly.",
30
- "- Call out newline and quotation handling quirks so the user can interpret the output accurately.",
31
- ].join("\n"),
32
- },
33
- "workflow/asm-irq": {
34
- id: "workflow/asm-irq",
35
- role: "assistant",
36
- content: [
37
- "IRQ discipline:",
38
- "- Wrap installation in `SEI`/`CLI`, set vectors, and configure `$D01A` masks explicitly.",
39
- "- Acknowledge interrupts via `$D019` before returning, and document any timing assumptions.",
40
- "- Describe zero-page and workspace usage so other routines can coexist safely.",
41
- ].join("\n"),
42
- },
43
- "workflow/sid-iterate": {
44
- id: "workflow/sid-iterate",
45
- role: "assistant",
46
- content: [
47
- "SID feedback loop:",
48
- "- Compose the sequence, waveform, ADSR, and modulation plan referencing SID register names.",
49
- "- Explain how to play it (e.g., `c64_sound` ops `generate` or `note_on`, or uploading executable code).",
50
- "- After playback, run `analyze_audio` and describe how to adjust envelope, tuning, or rhythm.",
51
- ].join("\n"),
52
- },
53
- "workflow/graphics-verify": {
54
- id: "workflow/graphics-verify",
55
- role: "assistant",
56
- content: [
57
- "Graphics verification:",
58
- "- List register writes for mode setup, colour RAM, and sprite pointers.",
59
- "- Suggest capturing output with `c64_memory` (op `read_screen`) or noting expected border/background colours.",
60
- "- Include timing checks (raster lines, badline windows) when applicable.",
61
- ].join("\n"),
62
- },
63
- "workflow/printer": {
64
- id: "workflow/printer",
65
- role: "assistant",
66
- content: [
67
- "Printer workflow:",
68
- "- Confirm printer type and device number before printing.",
69
- "- Include channel open/write/close steps and eject the page with `CHR$(12)` when appropriate.",
70
- "- Recommend checking printer status or repeating `print_text` if paper alignment is uncertain.",
71
- ].join("\n"),
72
- },
73
- "workflow/memory-snapshot": {
74
- id: "workflow/memory-snapshot",
75
- role: "assistant",
76
- content: [
77
- "Memory safety:",
78
- "- Pause running code before writes, capture the target range with `c64_memory` (op `read`), then resume when safe.",
79
- "- Explain how to revert the change (rewriting original bytes or power-cycling if needed).",
80
- "- Document address ranges, register dependencies, and any expected side effects.",
81
- ].join("\n"),
82
- },
83
- "workflow/drive": {
84
- id: "workflow/drive",
85
- role: "assistant",
86
- content: [
87
- "Drive management protocol:",
88
- "- List currently mounted images before altering drives to avoid disrupting active workflows.",
89
- "- Warn if IEC bus operations could interfere with running programs or disk writes.",
90
- "- Verify results with `drives_list` or relevant status tools after each action.",
91
- ].join("\n"),
92
- },
3
+ const ASSEMBLY_HARDWARE_NOTES = {
4
+ sid: [
5
+ "When routing this request, keep SID register usage, voice allocation, and timing side effects in scope.",
6
+ ],
7
+ vic: [
8
+ "When routing this request, keep VIC-II register usage, raster timing, and display-mode side effects in scope.",
9
+ ],
10
+ cia: [
11
+ "When routing this request, keep CIA timer, interrupt, and I/O side effects in scope.",
12
+ ],
13
+ multi: [
14
+ "When routing this request, keep cross-chip coordination across SID, VIC-II, and CIA state in scope.",
15
+ ],
93
16
  };
94
- const BASIC_CORE_SEGMENT = {
95
- id: "family/basic-core",
96
- role: "assistant",
97
- content: [
98
- "BASIC workflow:",
99
- "- Restate the request and outline a short plan citing `c64://specs/basic` for syntax or device usage.",
100
- "- Generate a numbered BASIC listing with inline remarks when clarity is required.",
101
- "- Describe how `c64_program` (op `upload_run_basic`) loads the program and what output to inspect.",
102
- "- Suggest follow-up diagnostics (screen capture, memory snapshot, or tool reruns).",
103
- ].join("\n"),
17
+ const GRAPHICS_MODE_NOTES = {
18
+ text: [
19
+ "When routing this request, keep screen-code layout, PETSCII constraints, and colour RAM updates in scope.",
20
+ ],
21
+ multicolour: [
22
+ "When routing this request, keep multicolour cell constraints, palette choices, and VIC-II mode flags in scope.",
23
+ ],
24
+ bitmap: [
25
+ "When routing this request, keep bitmap memory layout, colour sources, and frame-capture validation in scope.",
26
+ ],
27
+ sprite: [
28
+ "When routing this request, keep sprite data layout, sprite pointers, enable masks, and expansion flags in scope.",
29
+ ],
104
30
  };
105
- function assemblyCoreSegment(hardware) {
106
- const focus = (() => {
107
- switch (hardware) {
108
- case "sid":
109
- return "- Emphasise SID register usage, voice mixing, and timing derived from `c64://specs/sid`.";
110
- case "vic":
111
- return "- Highlight VIC-II raster, sprite, or bitmap setup drawing from `c64://specs/vic`.";
112
- case "cia":
113
- return "- Cover CIA timer/port configuration and interrupt hand-offs carefully.";
114
- case "multi":
115
- return "- Coordinate SID, VIC-II, and CIA interactions; call out contention risks.";
116
- default:
117
- return "- Declare which hardware blocks (SID, VIC-II, CIA) you will touch and why.";
118
- }
119
- })();
120
- return {
121
- id: "family/assembly-core",
122
- role: "assistant",
123
- content: [
124
- "Assembly workflow:",
125
- focus,
126
- "- Provide memory layout, zero-page usage, and register effects for the routine.",
127
- "- Explain how to build and deploy via `c64_program` (op `upload_run_asm`) or targeted `c64_memory` (op `write`) calls.",
128
- "- Include verification steps using `c64_memory` operations or hardware-specific checks.",
129
- ].join("\n"),
130
- };
131
- }
132
- const SID_CORE_SEGMENT = {
133
- id: "family/sid-core",
31
+ const ROUTING_CORE_SEGMENT = {
32
+ id: "routing/core",
134
33
  role: "assistant",
135
34
  content: [
136
- "SID composition workflow:",
137
- "- Summarise the musical goal, tempo, and character before presenting notes or SIDWAVE data.",
138
- "- Reference `c64://specs/sid` and `c64://specs/sidwave` when detailing registers and data formats.",
139
- "- Provide a playback plan (tool calls, SID register writes, or PRG execution) and note required buffers.",
35
+ "Prompts in this repository define intent and routing only.",
36
+ "Execution logic, validation steps, and safety rules live exclusively in `.github/skills/*/SKILL.md`.",
37
+ "Use the referenced skill, extract missing inputs from the user request, execute the skill, and summarize the outcome.",
140
38
  ].join("\n"),
141
39
  };
142
- function graphicsCoreSegment(mode) {
143
- const intro = (() => {
144
- switch (mode) {
145
- case "text":
146
- return "- Focus on PETSCII screen composition and character set considerations.";
147
- case "multicolour":
148
- return "- Detail multicolour bitmap setup, shared colour registers, and memory banking.";
149
- case "bitmap":
150
- return "- Lay out bitmap memory, screen RAM, and colour RAM usage explicitly.";
151
- case "sprite":
152
- return "- Describe sprite data, pointer tables, and multiplexing or animation timing.";
153
- default:
154
- return "- State which VIC-II mode or technique you will use and justify the choice.";
155
- }
156
- })();
157
- return {
158
- id: "family/graphics-core",
159
- role: "assistant",
160
- content: [
161
- "Graphics workflow:",
162
- intro,
163
- "- Summarise VIC-II register writes, memory banking, and colour usage with references to `c64://specs/vic`.",
164
- "- Explain how to deploy the routine (BASIC loader vs assembly) and required assets.",
165
- "- Include clean-up or teardown steps so the user can restore the display state.",
166
- ].join("\n"),
167
- };
168
- }
169
- function printerCoreSegment(printerType) {
170
- const detail = (() => {
171
- switch (printerType) {
172
- case "commodore":
173
- return "- Reference Commodore device 4 character codes and PETSCII control sequences.";
174
- case "epson":
175
- return "- Reference Epson ESC/P control codes, especially for fonts and bit-image modes.";
176
- default:
177
- return "- Clarify whether the target is Commodore MPS or Epson FX to select correct control codes.";
178
- }
179
- })();
40
+ function buildSkillRoutingSegment(skillPath, routingNotes) {
180
41
  return {
181
- id: "family/printer-core",
42
+ id: `routing/${skillPath}`,
182
43
  role: "assistant",
183
44
  content: [
184
- "Printer workflow:",
185
- detail,
186
- "- Outline data preparation, channel open/write/close, and any required delays.",
187
- "- Mention how to recover if paper jams or alignment differs from expectations.",
45
+ `Use the skill defined in \`${skillPath}\` as the single source of truth for execution.`,
46
+ ...routingNotes,
188
47
  ].join("\n"),
189
48
  };
190
49
  }
191
- const MEMORY_CORE_SEGMENT = {
192
- id: "family/memory-core",
193
- role: "assistant",
194
- content: [
195
- "Memory debugging workflow:",
196
- "- Restate the target address ranges and relate them to symbols from `c64://specs/assembly` or the memory map.",
197
- "- Plan safe inspection or patching steps using `c64_memory` operations alongside `pause` and `resume`.",
198
- "- Encourage logging or diffing memory before and after changes for auditability.",
199
- ].join("\n"),
200
- };
201
- const DRIVE_CORE_SEGMENT = {
202
- id: "family/drive-core",
203
- role: "assistant",
204
- content: [
205
- "Drive management workflow:",
206
- "- Summarise desired drive state and confirm affected slots before issuing commands.",
207
- "- Use `drives_list` to baseline the system and to verify outcomes after each operation.",
208
- "- Provide contingency steps if mounting or power commands fail.",
209
- ].join("\n"),
210
- };
211
50
  function mergeUniqueStrings(base, extras) {
212
51
  if (!extras || extras.length === 0) {
213
52
  return [...base];
@@ -230,12 +69,12 @@ function prepareAssemblyArgs(args) {
230
69
  if (typeof hardware !== "string") {
231
70
  throw new Error("assembly-program prompt argument \"hardware\" must be a string");
232
71
  }
233
- const normalised = hardware.trim().toLowerCase();
72
+ const normalized = hardware.trim().toLowerCase();
234
73
  const allowed = ["sid", "vic", "cia", "multi"];
235
- if (!allowed.includes(normalised)) {
236
- throw new Error(`assembly-program prompt does not support hardware "${hardware}". Expected one of: ${allowed.join(", ")}`);
74
+ if (!allowed.includes(normalized)) {
75
+ throw new Error(`assembly-program prompt does not support hardware \"${hardware}\". Expected one of: ${allowed.join(", ")}`);
237
76
  }
238
- return { hardware: normalised };
77
+ return { hardware: normalized };
239
78
  }
240
79
  function prepareGraphicsArgs(args) {
241
80
  const mode = args.mode;
@@ -245,12 +84,12 @@ function prepareGraphicsArgs(args) {
245
84
  if (typeof mode !== "string") {
246
85
  throw new Error("graphics-demo prompt argument \"mode\" must be a string");
247
86
  }
248
- const normalised = mode.trim().toLowerCase();
87
+ const normalized = mode.trim().toLowerCase();
249
88
  const allowed = ["text", "multicolour", "bitmap", "sprite"];
250
- if (!allowed.includes(normalised)) {
251
- throw new Error(`graphics-demo prompt does not support mode "${mode}". Expected one of: ${allowed.join(", ")}`);
89
+ if (!allowed.includes(normalized)) {
90
+ throw new Error(`graphics-demo prompt does not support mode \"${mode}\". Expected one of: ${allowed.join(", ")}`);
252
91
  }
253
- return { mode: normalised };
92
+ return { mode: normalized };
254
93
  }
255
94
  function preparePrinterArgs(args) {
256
95
  const printerType = args.printerType;
@@ -260,53 +99,97 @@ function preparePrinterArgs(args) {
260
99
  if (typeof printerType !== "string") {
261
100
  throw new Error("printer-job prompt argument \"printerType\" must be a string");
262
101
  }
263
- const normalised = printerType.trim().toLowerCase();
102
+ const normalized = printerType.trim().toLowerCase();
264
103
  const allowed = ["commodore", "epson"];
265
- if (!allowed.includes(normalised)) {
266
- throw new Error(`printer-job prompt does not support printerType "${printerType}". Expected one of: ${allowed.join(", ")}`);
104
+ if (!allowed.includes(normalized)) {
105
+ throw new Error(`printer-job prompt does not support printerType \"${printerType}\". Expected one of: ${allowed.join(", ")}`);
267
106
  }
268
- return { printerType: normalised };
107
+ return { printerType: normalized };
269
108
  }
270
109
  export function createPromptRegistry() {
271
110
  const knowledgeByUri = new Map(listKnowledgeResources().map((resource) => [resource.uri, resource]));
272
111
  const toolByName = new Map(toolRegistry.list().map((tool) => [tool.name, tool]));
273
112
  const definitions = [
113
+ {
114
+ descriptor: {
115
+ name: "hello-world",
116
+ title: "Hello World Workflow",
117
+ description: "Route ultra-fast hello-world and smoke-test requests to the canonical greeting skill.",
118
+ requiredResources: ["c64://context/bootstrap", "c64://context/fast-paths", "c64://docs/index"],
119
+ optionalResources: [],
120
+ tools: ["c64_program"],
121
+ tags: ["hello", "demo", "greeting", "smoke-test"],
122
+ },
123
+ skillPath: ".github/skills/hello-world/SKILL.md",
124
+ routingNotes: [
125
+ "Use this prompt for the narrowest hello-world, greeting, or smoke-test path.",
126
+ "Backend-pinned requests such as `vice: write a small BASIC program that clears the screen and prints HELLO VICE` should prefer this prompt over the bespoke BASIC prompt.",
127
+ "`c64_program` is a grouped tool, so every direct invocation must include `op`; for this prompt the canonical call is `{ op: \"cross_platform_greeting\", ... }`.",
128
+ "If the current agent cannot directly call `c64_program`, immediately delegate the same request to the `C64` agent instead of exploring repository files or manifests.",
129
+ "For visible single-backend VICE greetings, prefer the no-probe fast path unless the user explicitly asks for screenshots or verification.",
130
+ ],
131
+ },
274
132
  {
275
133
  descriptor: {
276
134
  name: "basic-program",
277
135
  title: "BASIC Program Workflow",
278
- description: "Plan, implement, and verify Commodore BASIC v2 programs safely.",
279
- requiredResources: [
280
- "c64://specs/basic",
281
- "c64://context/bootstrap",
282
- "c64://docs/index",
283
- ],
284
- optionalResources: [],
136
+ description: "Route bespoke Commodore BASIC v2 requests to the canonical BASIC skill.",
137
+ requiredResources: ["c64://specs/basic", "c64://context/bootstrap", "c64://docs/index"],
138
+ optionalResources: ["c64://context/fast-paths"],
285
139
  tools: ["c64_program", "c64_memory"],
286
140
  tags: ["basic", "program"],
287
141
  },
288
- buildMessages: () => [
289
- BASE_SEGMENTS["intro/core"],
290
- BASE_SEGMENTS["safety/reset"],
291
- BASIC_CORE_SEGMENT,
292
- BASE_SEGMENTS["workflow/basic-verify"],
142
+ skillPath: ".github/skills/basic-program/SKILL.md",
143
+ routingNotes: [
144
+ "This prompt is for bespoke BASIC programs rather than generic quick demos.",
145
+ "If the request collapses to a hello-world or smoke test, the selected skill should redirect to the hello-world flow.",
146
+ ],
147
+ },
148
+ {
149
+ descriptor: {
150
+ name: "cross-platform-demo",
151
+ title: "Cross-Platform Demo Workflow",
152
+ description: "Route quick visible demo requests to the cross-platform demo skill.",
153
+ requiredResources: ["c64://context/bootstrap", "c64://context/fast-paths", "c64://docs/index"],
154
+ optionalResources: [],
155
+ tools: ["c64_program"],
156
+ tags: ["demo", "platform", "greeting"],
157
+ },
158
+ skillPath: ".github/skills/cross-platform-demo/SKILL.md",
159
+ routingNotes: [
160
+ "This prompt is for the shortest visible confirmation path across one or more configured backends.",
161
+ "`c64_program` is a grouped tool, so always call it with `op: \"cross_platform_greeting\"` for this workflow.",
162
+ ],
163
+ },
164
+ {
165
+ descriptor: {
166
+ name: "preset-music-demo",
167
+ title: "Preset Music Demo Workflow",
168
+ description: "Route quick recognizable tune requests to the SID music skill.",
169
+ requiredResources: ["c64://specs/sid", "c64://specs/sidwave", "c64://context/fast-paths"],
170
+ optionalResources: ["c64://docs/sid/best-practices"],
171
+ tools: ["c64_sound"],
172
+ tags: ["sid", "music", "demo"],
173
+ },
174
+ skillPath: ".github/skills/sid-music/SKILL.md",
175
+ routingNotes: [
176
+ "This prompt is for the built-in preset playback path, using `fuer_elise` as the canonical preset.",
293
177
  ],
294
178
  },
295
179
  {
296
180
  descriptor: {
297
181
  name: "assembly-program",
298
182
  title: "Assembly Program Workflow",
299
- description: "Author 6502/6510 assembly routines with precise hardware guidance.",
300
- requiredResources: [
301
- "c64://specs/assembly",
302
- "c64://specs/vic",
303
- "c64://specs/sid",
304
- "c64://context/bootstrap",
305
- ],
183
+ description: "Route 6502/6510 routine requests to the canonical assembly skill.",
184
+ requiredResources: ["c64://specs/assembly", "c64://specs/vic", "c64://specs/sid", "c64://context/bootstrap"],
306
185
  optionalResources: ["c64://docs/sid/best-practices"],
307
186
  tools: ["c64_program", "c64_memory"],
308
187
  tags: ["assembly", "program"],
309
188
  },
189
+ skillPath: ".github/skills/assembly-program/SKILL.md",
190
+ routingNotes: [
191
+ "Use this prompt when the user needs assembly-level control, IRQ handling, or direct register work.",
192
+ ],
310
193
  arguments: [
311
194
  {
312
195
  name: "hardware",
@@ -317,57 +200,54 @@ export function createPromptRegistry() {
317
200
  prepareArgs: prepareAssemblyArgs,
318
201
  selectOptionalResources: (args) => {
319
202
  const hardware = args.hardware;
320
- if (hardware === "sid" || hardware === "multi") {
321
- return ["c64://docs/sid/best-practices"];
322
- }
323
- return [];
203
+ return hardware === "sid" || hardware === "multi"
204
+ ? ["c64://docs/sid/best-practices"]
205
+ : [];
324
206
  },
325
- buildMessages: (args) => {
207
+ renderRoutingNotes: (args) => {
326
208
  const hardware = args.hardware;
327
- return [
328
- BASE_SEGMENTS["intro/core"],
329
- BASE_SEGMENTS["safety/reset"],
330
- assemblyCoreSegment(hardware),
331
- BASE_SEGMENTS["workflow/asm-irq"],
332
- BASE_SEGMENTS["workflow/memory-snapshot"],
333
- ];
209
+ return hardware
210
+ ? [
211
+ `Prompt argument hardware is set to \`${hardware}\`; keep that focus while executing the skill.`,
212
+ ...ASSEMBLY_HARDWARE_NOTES[hardware],
213
+ ]
214
+ : [];
334
215
  },
335
216
  },
336
217
  {
337
218
  descriptor: {
338
219
  name: "sid-music",
339
220
  title: "SID Composition Workflow",
340
- description: "Compose SID music with expressive phrasing and iterative audio verification.",
221
+ description: "Route SID playback and composition work to the canonical SID skill.",
341
222
  requiredResources: [
342
223
  "c64://specs/sid",
343
224
  "c64://specs/sidwave",
344
225
  "c64://docs/sid/file-structure",
345
226
  "c64://docs/sid/best-practices",
346
227
  ],
347
- optionalResources: [],
228
+ optionalResources: ["c64://context/fast-paths"],
348
229
  tools: ["c64_sound"],
349
230
  tags: ["sid", "music"],
350
231
  },
351
- buildMessages: () => [
352
- BASE_SEGMENTS["intro/core"],
353
- SID_CORE_SEGMENT,
354
- BASE_SEGMENTS["workflow/sid-iterate"],
355
- BASE_SEGMENTS["safety/reset"],
232
+ skillPath: ".github/skills/sid-music/SKILL.md",
233
+ routingNotes: [
234
+ "Use this prompt for custom SID work or when the user wants to move beyond the preset demo path.",
356
235
  ],
357
236
  },
358
237
  {
359
238
  descriptor: {
360
239
  name: "graphics-demo",
361
240
  title: "Graphics Demo Workflow",
362
- description: "Create VIC-II graphics demos with safe setup and validation steps.",
363
- requiredResources: [
364
- "c64://specs/vic",
365
- "c64://context/bootstrap",
366
- ],
241
+ description: "Route graphics requests to the canonical graphics skill.",
242
+ requiredResources: ["c64://specs/vic", "c64://context/bootstrap"],
367
243
  optionalResources: ["c64://specs/assembly", "c64://specs/charset", "c64://docs/petscii-style"],
368
244
  tools: ["c64_program", "c64_memory", "c64_graphics"],
369
245
  tags: ["graphics", "vic"],
370
246
  },
247
+ skillPath: ".github/skills/graphics-demo/SKILL.md",
248
+ routingNotes: [
249
+ "Use this prompt for PETSCII, sprite, bitmap, or frame-capture work.",
250
+ ],
371
251
  arguments: [
372
252
  {
373
253
  name: "mode",
@@ -376,39 +256,22 @@ export function createPromptRegistry() {
376
256
  },
377
257
  ],
378
258
  prepareArgs: prepareGraphicsArgs,
379
- selectTools: (args) => {
380
- const mode = args.mode;
381
- if (mode === "sprite") {
382
- return ["c64_graphics", "c64_memory"];
383
- }
384
- if (mode === "bitmap" || mode === "multicolour") {
385
- return ["c64_graphics", "c64_memory"];
386
- }
387
- if (mode === "text") {
388
- return ["c64_graphics", "c64_memory"];
389
- }
390
- return ["c64_graphics", "c64_memory"];
391
- },
392
- buildMessages: (args) => {
259
+ renderRoutingNotes: (args) => {
393
260
  const mode = args.mode;
394
- return [
395
- BASE_SEGMENTS["intro/core"],
396
- BASE_SEGMENTS["safety/reset"],
397
- graphicsCoreSegment(mode),
398
- BASE_SEGMENTS["workflow/graphics-verify"],
399
- ];
261
+ return mode
262
+ ? [
263
+ `Prompt argument mode is set to \`${mode}\`; keep that mode constraint while executing the skill.`,
264
+ ...GRAPHICS_MODE_NOTES[mode],
265
+ ]
266
+ : [];
400
267
  },
401
268
  },
402
269
  {
403
270
  descriptor: {
404
271
  name: "printer-job",
405
272
  title: "Printer Job Workflow",
406
- description: "Send formatted output to Commodore or Epson printers with safe teardown steps.",
407
- requiredResources: [
408
- "c64://specs/printer",
409
- "c64://docs/printer/guide",
410
- "c64://docs/printer/prompts",
411
- ],
273
+ description: "Route printer work to the canonical printer skill.",
274
+ requiredResources: ["c64://specs/printer", "c64://docs/printer/guide", "c64://docs/printer/prompts"],
412
275
  optionalResources: [
413
276
  "c64://docs/printer/commodore-text",
414
277
  "c64://docs/printer/commodore-bitmap",
@@ -418,6 +281,10 @@ export function createPromptRegistry() {
418
281
  tools: ["c64_printer"],
419
282
  tags: ["printer"],
420
283
  },
284
+ skillPath: ".github/skills/printer-job/SKILL.md",
285
+ routingNotes: [
286
+ "Use this prompt when the user needs Commodore or Epson printer workflows.",
287
+ ],
421
288
  arguments: [
422
289
  {
423
290
  name: "printerType",
@@ -436,56 +303,41 @@ export function createPromptRegistry() {
436
303
  }
437
304
  return [];
438
305
  },
439
- selectTools: () => ["c64_printer"],
440
- buildMessages: (args) => {
306
+ renderRoutingNotes: (args) => {
441
307
  const printerType = args.printerType;
442
- return [
443
- BASE_SEGMENTS["intro/core"],
444
- printerCoreSegment(printerType),
445
- BASE_SEGMENTS["workflow/printer"],
446
- BASE_SEGMENTS["safety/reset"],
447
- ];
308
+ return printerType
309
+ ? [`Prompt argument printerType is set to \`${printerType}\`; preserve that choice while executing the skill.`]
310
+ : [];
448
311
  },
449
312
  },
450
313
  {
451
314
  descriptor: {
452
315
  name: "memory-debug",
453
316
  title: "Memory Debug Workflow",
454
- description: "Inspect or patch memory ranges with reversible steps and logging.",
455
- requiredResources: [
456
- "c64://context/bootstrap",
457
- "c64://specs/assembly",
458
- "c64://docs/index",
459
- ],
317
+ description: "Route reversible memory inspection or patching work to the canonical memory skill.",
318
+ requiredResources: ["c64://context/bootstrap", "c64://specs/assembly", "c64://docs/index"],
460
319
  optionalResources: [],
461
320
  tools: ["c64_memory", "c64_system"],
462
321
  tags: ["memory", "debug"],
463
322
  },
464
- buildMessages: () => [
465
- BASE_SEGMENTS["intro/core"],
466
- BASE_SEGMENTS["safety/reset"],
467
- MEMORY_CORE_SEGMENT,
468
- BASE_SEGMENTS["workflow/memory-snapshot"],
323
+ skillPath: ".github/skills/memory-debug/SKILL.md",
324
+ routingNotes: [
325
+ "Use this prompt for screen reads, memory reads, polling, and carefully scoped writes.",
469
326
  ],
470
327
  },
471
328
  {
472
329
  descriptor: {
473
330
  name: "drive-manager",
474
331
  title: "Drive Manager Workflow",
475
- description: "Mount, create, or power drives while preserving running workloads.",
332
+ description: "Route disk-image and drive-state requests to the canonical drive skill.",
476
333
  requiredResources: ["c64://context/bootstrap"],
477
334
  optionalResources: [],
478
- tools: [
479
- "c64_disk",
480
- "c64_drive",
481
- ],
335
+ tools: ["c64_disk", "c64_drive"],
482
336
  tags: ["drive", "storage"],
483
337
  },
484
- buildMessages: () => [
485
- BASE_SEGMENTS["intro/core"],
486
- BASE_SEGMENTS["safety/reset"],
487
- DRIVE_CORE_SEGMENT,
488
- BASE_SEGMENTS["workflow/drive"],
338
+ skillPath: ".github/skills/drive-manager/SKILL.md",
339
+ routingNotes: [
340
+ "Use this prompt for image mounts, blank media creation, drive resets, and mode changes.",
489
341
  ],
490
342
  },
491
343
  ];
@@ -528,15 +380,20 @@ export function createPromptRegistry() {
528
380
  throw new Error(`Prompt ${name} missing required knowledge resources after resolution`);
529
381
  }
530
382
  const toolNames = mergeUniqueStrings(definition.descriptor.tools, definition.selectTools ? definition.selectTools(prepared) : undefined);
531
- const tools = toolNames
532
- .map((toolName) => {
383
+ const tools = toolNames.map((toolName) => {
533
384
  const tool = toolByName.get(toolName);
534
385
  if (!tool) {
535
386
  throw new Error(`Prompt ${name} references unknown tool: ${toolName}`);
536
387
  }
537
388
  return tool;
538
389
  });
539
- const messages = definition.buildMessages(prepared);
390
+ const routingNotes = definition.renderRoutingNotes
391
+ ? [...definition.routingNotes, ...definition.renderRoutingNotes(prepared)]
392
+ : [...definition.routingNotes];
393
+ const messages = [
394
+ ROUTING_CORE_SEGMENT,
395
+ buildSkillRoutingSegment(definition.skillPath, routingNotes),
396
+ ];
540
397
  return {
541
398
  name: definition.descriptor.name,
542
399
  description: definition.descriptor.description,