c64bridge 1.0.7 → 1.1.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 (132) hide show
  1. package/.github/skills/assembly-program/SKILL.md +37 -0
  2. package/.github/skills/basic-program/SKILL.md +40 -0
  3. package/.github/skills/cross-platform-demo/SKILL.md +32 -0
  4. package/.github/skills/drive-manager/SKILL.md +33 -0
  5. package/.github/skills/graphics-demo/SKILL.md +30 -0
  6. package/.github/skills/hello-world/SKILL.md +36 -0
  7. package/.github/skills/memory-debug/SKILL.md +32 -0
  8. package/.github/skills/pr-converge/SKILL.md +33 -0
  9. package/.github/skills/printer-job/SKILL.md +30 -0
  10. package/.github/skills/sid-music/SKILL.md +35 -0
  11. package/.github/skills/software-launch/SKILL.md +31 -0
  12. package/.github/skills/stream-control/SKILL.md +29 -0
  13. package/.github/skills/system-control/SKILL.md +32 -0
  14. package/AGENTS.md +28 -7
  15. package/README.md +69 -14
  16. package/data/assembly/assembly-spec.md +2 -0
  17. package/dist/c64Client.js +238 -60
  18. package/dist/config.js +48 -26
  19. package/dist/device.js +92 -37
  20. package/dist/diagnostics.js +62 -2
  21. package/dist/hostPaths.js +128 -0
  22. package/dist/loggingHttpClient.js +59 -1
  23. package/dist/mcp-server.js +409 -286
  24. package/dist/numericArg.js +55 -0
  25. package/dist/petscii.js +13 -1
  26. package/dist/platform.js +12 -3
  27. package/dist/prompts/registry.js +6 -1
  28. package/dist/tools/access.js +66 -0
  29. package/dist/tools/debug.js +6 -0
  30. package/dist/tools/developer.js +67 -34
  31. package/dist/tools/errors.js +54 -3
  32. package/dist/tools/input.js +23 -6
  33. package/dist/tools/machineControl.js +112 -20
  34. package/dist/tools/memory.js +135 -30
  35. package/dist/tools/meta/artifacts.js +5 -5
  36. package/dist/tools/meta/background.js +216 -54
  37. package/dist/tools/meta/compilation.js +6 -5
  38. package/dist/tools/meta/config.js +15 -6
  39. package/dist/tools/meta/filesystem.js +16 -14
  40. package/dist/tools/meta/graphics.js +48 -20
  41. package/dist/tools/meta/memory.js +45 -19
  42. package/dist/tools/meta/program.js +10 -7
  43. package/dist/tools/meta/screen.js +116 -25
  44. package/dist/tools/pauseGuard.js +23 -0
  45. package/dist/tools/pollValidator.js +53 -8
  46. package/dist/tools/programRunners.js +62 -18
  47. package/dist/tools/registry/batch.js +16 -4
  48. package/dist/tools/registry/config.js +9 -2
  49. package/dist/tools/registry/disk.js +12 -2
  50. package/dist/tools/registry/drive.js +3 -0
  51. package/dist/tools/registry/extract.js +3 -0
  52. package/dist/tools/registry/graphics.js +59 -6
  53. package/dist/tools/registry/index.js +17 -1
  54. package/dist/tools/registry/memory.js +11 -1
  55. package/dist/tools/registry/platform.js +4 -1
  56. package/dist/tools/registry/printer.js +2 -1
  57. package/dist/tools/registry/program.js +5 -1
  58. package/dist/tools/registry/rag.js +1 -0
  59. package/dist/tools/registry/sound.js +12 -1
  60. package/dist/tools/registry/stream.js +2 -1
  61. package/dist/tools/registry/system.js +8 -1
  62. package/dist/tools/schema.js +7 -7
  63. package/dist/tools/streaming.js +34 -4
  64. package/dist/tools/translation/assembler.js +247 -24
  65. package/dist/tools/translation/basicDetokenizer.js +80 -0
  66. package/dist/tools/translation/basicTokenizer.js +8 -3
  67. package/dist/tools/translation/disassembler.js +14 -0
  68. package/dist/tools/types.js +258 -7
  69. package/dist/tools/vice.js +5 -16
  70. package/dist/vicBitmap.js +1 -1
  71. package/dist/vice/mockServer.js +3 -0
  72. package/dist/vice/process.js +19 -0
  73. package/dist/vice/resourcePolicy.js +36 -0
  74. package/dist/vice/viceClient.js +22 -5
  75. package/doc/vice/support-matrix.md +17 -11
  76. package/mcp/schemas/c64_batch.schema.json +2 -1
  77. package/mcp/schemas/c64_config.schema.json +25 -475
  78. package/mcp/schemas/c64_debug.schema.json +3 -602
  79. package/mcp/schemas/c64_disk.schema.json +17 -344
  80. package/mcp/schemas/c64_drive.schema.json +2 -157
  81. package/mcp/schemas/c64_extract.schema.json +10 -364
  82. package/mcp/schemas/c64_graphics.schema.json +19 -426
  83. package/mcp/schemas/c64_input.schema.json +5 -318
  84. package/mcp/schemas/c64_memory.schema.json +23 -491
  85. package/mcp/schemas/c64_printer.schema.json +3 -258
  86. package/mcp/schemas/c64_program.schema.json +16 -491
  87. package/mcp/schemas/c64_rag.schema.json +1 -81
  88. package/mcp/schemas/c64_select_backend.schema.json +2 -36
  89. package/mcp/schemas/c64_sound.schema.json +20 -822
  90. package/mcp/schemas/c64_stream.schema.json +4 -75
  91. package/mcp/schemas/c64_system.schema.json +28 -348
  92. package/mcp/schemas/c64_vice.schema.json +2 -71
  93. package/mcp/server.json +1 -1
  94. package/mcp/tools.json +1983 -6910
  95. package/mcp.json +21 -1
  96. package/package.json +16 -8
  97. package/scripts/mockC64Server.mjs +44 -0
  98. package/scripts/run-coverage.mjs +27 -1
  99. package/scripts/smoke-run.sh +3 -2
  100. package/scripts/start.mjs +23 -1
  101. package/server.json +35 -2
  102. package/dist/.tsbuildinfo +0 -1
  103. package/doc/agent-state-spec.md +0 -243
  104. package/doc/audit/secret-handling.md +0 -61
  105. package/doc/plans/bun/baseline-metrics.md +0 -16
  106. package/doc/plans/bun/migration-checklist.md +0 -55
  107. package/doc/plans/bun/migration.md +0 -83
  108. package/doc/plans/improve-knowledge/notes.md +0 -43
  109. package/doc/plans/improve-knowledge/plan.md +0 -121
  110. package/doc/plans/improve-knowledge/rollout.md +0 -110
  111. package/doc/plans/meta-tools/README.md +0 -110
  112. package/doc/plans/meta-tools/analysis.md +0 -272
  113. package/doc/plans/meta-tools/catalog.md +0 -435
  114. package/doc/plans/meta-tools/notes.md +0 -192
  115. package/doc/plans/meta-tools/rollout.md +0 -368
  116. package/doc/plans/prompts/README.md +0 -96
  117. package/doc/plans/prompts/user-prompt-ideas.md +0 -147
  118. package/doc/plans/tool-consolidation/notes.md +0 -28
  119. package/doc/plans/tool-consolidation/plan.md +0 -169
  120. package/doc/plans/tool-consolidation/rollout.md +0 -104
  121. package/doc/plans/vice-backend-switch/plan.md +0 -486
  122. package/doc/plans/vice-backend-switch-2/plan.md +0 -48
  123. package/doc/plans/vice-support/notes.md +0 -63
  124. package/doc/plans/vice-support/plan.md +0 -88
  125. package/doc/plans/vice-support/rollout.md +0 -99
  126. package/doc/reviews/audit.md +0 -143
  127. package/doc/reviews/hardening/01-fable/prompt-handover.md +0 -125
  128. package/doc/reviews/hardening/01-fable/prompt.md +0 -98
  129. package/doc/reviews/hardening/01-fable/review-prompt.md +0 -468
  130. package/doc/reviews/hardening/01-fable/review.md +0 -1234
  131. package/doc/reviews/vice-support-review.md +0 -185
  132. package/scripts/compare-rest/rest-compare-2025-11-01T00-25-21-830Z.json +0 -2513
@@ -1,486 +0,0 @@
1
- # C64Bridge: Multi-Backend Runtime Switching — Implementation Brief
2
-
3
- ## Context
4
-
5
- You are working in the repository at `/home/chris/dev/c64/c64bridge`.
6
-
7
- This is a TypeScript MCP (Model Context Protocol) server that bridges Commodore 64
8
- hardware and emulator backends to AI agents. Two backends exist:
9
-
10
- - **C64U** (`c64u`): REST API to physical C64 Ultimate hardware at `http://c64u`
11
- - **VICE** (`vice`): Binary monitor protocol to the VICE C64 emulator
12
-
13
- The server is started via `node scripts/start.mjs` (stdio MCP transport).
14
-
15
- ---
16
-
17
- ## Mandatory Process
18
-
19
- Before writing any code you **must** create `plans.md` at the repo root with the
20
- full multi-phase plan described below. Every task in `plans.md` must be a checkbox.
21
- Tick each checkbox the moment that task is complete — never batch. Alongside
22
- `plans.md`, maintain `worklog.md` at the repo root. Append a timestamped entry to
23
- `worklog.md` whenever you start a phase, complete a phase, or make a decision that
24
- deviates from this brief.
25
-
26
- Format for `worklog.md` entries:
27
-
28
- ```
29
- ## YYYY-MM-DD HH:MM — <one-line summary>
30
-
31
- <Free prose: what was done, any surprises, decisions made.>
32
- ```
33
-
34
- **Do not proceed to the next phase until all checkboxes in the current phase are
35
- ticked.** If you discover that a later phase must be restructured because of
36
- something you learned in an earlier phase, update `plans.md` and add a worklog
37
- entry explaining why.
38
-
39
- ---
40
-
41
- ## Test Coverage Mandate
42
-
43
- **Minimum 91% line + branch coverage across all modified and new source files.**
44
-
45
- - Run the existing test suite with `./build test` (mock backend) after every phase.
46
- - After the final phase run `./build coverage` and verify the threshold.
47
- - If coverage drops below 91% on any modified file, write additional tests before
48
- marking that phase complete.
49
- - Tests live in `src/**/*.test.ts` (co-located) or `test/**/*.ts` — follow the
50
- existing pattern for the file you are modifying.
51
- - Do not delete or weaken existing tests.
52
-
53
- ---
54
-
55
- ## Bug Report: Why Vice Is Never Selected
56
-
57
- When the server starts, `mcp-server.ts` calls `config.ts::loadConfig()`, which is a
58
- **C64U-only** legacy loader. It reads `~/.c64bridge.json` or the project root
59
- `.c64bridge.json` but only ever extracts `c64u.*` fields; the `vice` section is
60
- silently ignored.
61
-
62
- Separately, `device.ts::readConfigFile()` — used by `createFacade()` — scans
63
- candidate paths in order and **returns on the first match**:
64
-
65
- 1. `C64BRIDGE_CONFIG` env var path
66
- 2. `.c64bridge.json` in the project root
67
- 3. `~/.c64bridge.json` in the home directory
68
-
69
- The project root `.c64bridge.json` currently contains:
70
-
71
- ```json
72
- { "c64u": { "host": "c64u", "port": 80 } }
73
- ```
74
-
75
- Because this file is found first and contains no `vice` section,
76
- `createFacade()` always selects c64u — the user's `~/.c64bridge.json` vice config
77
- is never reached.
78
-
79
- A second issue: after `createFacade()` resolves, `platform.ts::currentPlatform`
80
- remains `"c64u"` (its hardcoded default) even when vice was selected, because
81
- `mcp-server.ts` never calls `setPlatform()` with the result of the facade selection.
82
-
83
- ---
84
-
85
- ## Existing Architecture — Key Files
86
-
87
- Read every file listed here before writing code.
88
-
89
- | File | Role |
90
- |---|---|
91
- | `src/mcp-server.ts` | MCP entry point. Creates `C64Client`, registers MCP handlers. |
92
- | `src/config.ts` | Legacy C64U-only config loader used by `mcp-server.ts`. |
93
- | `src/device.ts` | `C64uBackend`, `ViceBackend`, `C64Facade` interface, `createFacade()`, `readConfigFile()`. |
94
- | `src/c64Client.ts` | Orchestration wrapper around a single `C64Facade`. All tool methods delegate here. |
95
- | `src/platform.ts` | Global `currentPlatform` state, `setPlatform()`, tool gating helpers. |
96
- | `src/tools/types.ts` | `ToolExecutionContext` — passed to every tool invocation. |
97
- | `src/tools/registry/index.ts` | Registers all tool modules; `toolRegistry.invoke()`. |
98
- | `src/tools/registry/system.ts` | Example of a multi-operation tool module. |
99
- | `src/tools/vice.ts` | Vice-specific tool (`supportedPlatforms: ["vice"]`). Study this as a pattern. |
100
- | `mcp.json` | MCP server descriptor with documented env vars. |
101
- | `.vscode/mcp.json` | VS Code MCP config — stdio invocation. |
102
- | `data/context/bootstrap.md` | LLM bootstrap prompt injected before every session. |
103
- | `AGENTS.md` | LLM-facing setup and usage guide. |
104
-
105
- Also read:
106
-
107
- - `src/tools/types.ts` fully (especially `ToolExecutionContext` and `ToolModule`).
108
- - One complete tool module (e.g. `src/tools/registry/system.ts`) to understand the
109
- pattern before implementing the new tool.
110
-
111
- ---
112
-
113
- ## Phase Breakdown for `plans.md`
114
-
115
- Use exactly the following phase and task names. Add sub-tasks as needed, but do not
116
- remove or rename the top-level items.
117
-
118
- ---
119
-
120
- ### Phase 0 — Bootstrap
121
-
122
- - [ ] Read every file listed in the architecture table above.
123
- - [ ] Read `README.md` sections on configuration and VS Code setup.
124
- - [ ] Read `AGENTS.md` and `data/context/bootstrap.md`.
125
- - [ ] Run `./build test` and record baseline pass/fail count in `worklog.md`.
126
- - [ ] Record current `./build coverage` output in `worklog.md`.
127
- - [ ] Create `plans.md` with all phases and tasks.
128
- - [ ] Create `worklog.md` with the Phase 0 start entry.
129
-
130
- ---
131
-
132
- ### Phase 1 — Merge Config Across Files
133
-
134
- **Goal**: `readConfigFile()` in `src/device.ts` collects backend sections from
135
- *all* candidate config files rather than stopping at the first match.
136
-
137
- **Specification**:
138
-
139
- - Iterate all candidate paths in order (env var → project root → home dir).
140
- - Accumulate: take the `c64u` section from the **first** file that contains one;
141
- take the `vice` section from the **first** file that contains one.
142
- - Stop iterating early only when both sections have been found.
143
- - If no file yields a section, that section remains `undefined`.
144
- - Return `null` only when no candidate file exists at all.
145
- - The function signature and return type (`C64BridgeConfigFile | null`) must not
146
- change.
147
- - Do not change any other behaviour of `createFacade()`.
148
-
149
- **Tasks**:
150
-
151
- - [ ] Implement the merge logic in `readConfigFile()`.
152
- - [ ] Write/update unit tests: config from project root only, home only, both split
153
- across files, env-var path overrides, missing files.
154
- - [ ] Run `./build test` — all tests pass.
155
- - [ ] Coverage ≥ 91% on `src/device.ts`.
156
- - [ ] Append Phase 1 completion entry to `worklog.md`.
157
-
158
- ---
159
-
160
- ### Phase 2 — Env-Var Overrides for C64U Backend
161
-
162
- **Goal**: The C64U backend respects env-var overrides analogous to the existing
163
- `VICE_BINARY`, `VICE_HOST`, `VICE_PORT` vars, so a user can fully configure it
164
- from `.vscode/mcp.json` without a config file.
165
-
166
- **New env vars** (read inside `C64uBackend` constructor, same pattern as
167
- `ViceBackend`):
168
-
169
- | Env var | Overrides |
170
- |---|---|
171
- | `C64U_HOST` | `config.host` / `config.hostname` |
172
- | `C64U_PORT` | `config.port` |
173
- | `C64U_PASSWORD` | `config.networkPassword` |
174
-
175
- **Precedence within `C64uBackend`** (highest → lowest):
176
-
177
- 1. Env var (`C64U_HOST`, etc.)
178
- 2. Constructor `config` argument (from config file)
179
- 3. Built-in defaults (`c64u`, port `80`)
180
-
181
- **Tasks**:
182
-
183
- - [ ] Read env vars in `C64uBackend` constructor.
184
- - [ ] Document the three new vars in `mcp.json` `env` section with `description`
185
- and `default` fields matching the existing format.
186
- - [ ] Write unit tests: env var alone, config alone, env var beats config,
187
- neither present → defaults.
188
- - [ ] Run `./build test` — all tests pass.
189
- - [ ] Coverage ≥ 91% on the modified constructor path.
190
- - [ ] Append Phase 2 completion entry to `worklog.md`.
191
-
192
- ---
193
-
194
- ### Phase 3 — Dual-Facade Support in `C64Client`
195
-
196
- **Goal**: When both backends are configured, `C64Client` initialises both facades
197
- at construction time and exposes a `switchBackend()` method for zero-reconnect
198
- runtime switching.
199
-
200
- **Specification**:
201
-
202
- Add a new exported async function to `src/device.ts`:
203
-
204
- ```typescript
205
- export interface AllFacadesResult {
206
- primary: FacadeSelection; // the initially selected backend
207
- secondary: C64Facade | null; // the other backend, if configured
208
- secondaryType: DeviceType | null;
209
- }
210
-
211
- export async function createAllFacades(
212
- logger?: { info: (...a: any[]) => void },
213
- options?: FacadeOptions,
214
- ): Promise<AllFacadesResult>
215
- ```
216
-
217
- Logic:
218
-
219
- 1. Call the existing `createFacade()` to determine the primary selection.
220
- 2. Read the merged config (via the updated `readConfigFile()`).
221
- 3. If the config contains the OTHER backend (the one not selected as primary),
222
- construct it immediately (no probing required — just instantiate).
223
- 4. Return both.
224
-
225
- Modify `C64Client`:
226
-
227
- - Change constructor so that when `forceC64uFacade` is `false` it calls
228
- `createAllFacades()` instead of `createFacade()`.
229
- - Store results in:
230
- ```typescript
231
- private readonly allFacades: Map<DeviceType, Promise<C64Facade>>;
232
- private activeType: DeviceType;
233
- private facadePromise: Promise<C64Facade>; // points to allFacades.get(activeType)
234
- ```
235
- - Add:
236
- ```typescript
237
- switchBackend(type: DeviceType): void
238
- // Throws if the type is not in allFacades.
239
- // Updates this.facadePromise = this.allFacades.get(type).
240
- // Updates this.activeType.
241
- // Does NOT call setPlatform() — that is the caller's responsibility.
242
-
243
- getActiveBackendType(): Promise<DeviceType>
244
- // Returns activeType (already resolved, but keep async for consistency).
245
-
246
- getAvailableBackends(): DeviceType[]
247
- // Returns Array.from(allFacades.keys()).
248
- ```
249
- - All existing delegate methods in `C64Client` continue to work unchanged because
250
- they already use `this.facadePromise`.
251
-
252
- **Tasks**:
253
-
254
- - [ ] Add `createAllFacades()` to `src/device.ts`.
255
- - [ ] Modify `C64Client` constructor and add the three new methods.
256
- - [ ] Write unit tests for `C64Client`: single c64u, single vice, both configured
257
- (verify both facades initialised), `switchBackend()` swaps the active facade,
258
- `switchBackend()` to unconfigured type throws.
259
- - [ ] Run `./build test` — all tests pass.
260
- - [ ] Coverage ≥ 91% on modified `c64Client.ts` paths.
261
- - [ ] Append Phase 3 completion entry to `worklog.md`.
262
-
263
- ---
264
-
265
- ### Phase 4 — Sync Platform State on Init and Switch
266
-
267
- **Goal**: `platform.ts::currentPlatform` always reflects the actually active
268
- backend, from server start through any subsequent switches.
269
-
270
- **In `src/mcp-server.ts`**:
271
-
272
- After constructing `C64Client` and before registering MCP handlers, add:
273
-
274
- ```typescript
275
- const initialBackendType = await client.getActiveBackendType();
276
- setPlatform(initialBackendType);
277
- writeDiagnosticEvent("platform_initialised", { platform: initialBackendType });
278
- ```
279
-
280
- **In `C64Client::switchBackend()`** — the platform sync is **not** done here;
281
- it remains the tool's responsibility (see Phase 5). Document this contract in a
282
- comment.
283
-
284
- **Tasks**:
285
-
286
- - [ ] Add the `setPlatform()` call in `mcp-server.ts` after client construction.
287
- - [ ] Add the `writeDiagnosticEvent` call.
288
- - [ ] Write/update integration or unit tests that assert the platform matches the
289
- backend that was selected from config at startup (both the c64u-only and
290
- vice-only cases).
291
- - [ ] Run `./build test` — all tests pass.
292
- - [ ] Append Phase 4 completion entry to `worklog.md`.
293
-
294
- ---
295
-
296
- ### Phase 5 — `c64_select_backend` Tool
297
-
298
- **Goal**: A new MCP tool lets the LLM (or user) switch the active backend at
299
- runtime without restarting the server.
300
-
301
- **Tool name**: `c64_select_backend`
302
-
303
- **Module placement**: Add a new file `src/tools/registry/platform.ts` following the
304
- same `ToolModule` / `defineToolModule` / `operationPlatforms` pattern as
305
- `src/tools/registry/system.ts`. Register it in `src/tools/registry/index.ts`.
306
-
307
- **Tool specification**:
308
-
309
- ```
310
- Input schema
311
- op: "select" (discriminator, required)
312
- backend: "c64u" | "vice" (required)
313
-
314
- Supported platforms: ["c64u", "vice"] — available on both
315
-
316
- Behaviour
317
- 1. Call ctx.client.getAvailableBackends().
318
- 2. If backend is not in the list, return an error result explaining which
319
- backends are configured (do not throw).
320
- 3. Call ctx.client.switchBackend(backend).
321
- 4. Call ctx.setPlatform(backend).
322
- 5. Return a success result that includes:
323
- - The newly active backend name
324
- - The list of tool names now available on that backend
325
- - The list of tool names now unavailable
326
- - A one-line usage hint reminding the user they can switch back
327
- ```
328
-
329
- **Tasks**:
330
-
331
- - [ ] Create `src/tools/registry/platform.ts` with the `c64_select_backend` tool.
332
- - [ ] Register the module in `src/tools/registry/index.ts`.
333
- - [ ] Write unit tests: select available backend succeeds and updates platform,
334
- select unavailable backend returns error result (not throw), both backends
335
- configured round-trip switch.
336
- - [ ] Run `./build test` — all tests pass.
337
- - [ ] Coverage ≥ 91% on `src/tools/registry/platform.ts`.
338
- - [ ] Append Phase 5 completion entry to `worklog.md`.
339
-
340
- ---
341
-
342
- ### Phase 6 — LLM Routing Instructions
343
-
344
- **Goal**: The LLM automatically calls `c64_select_backend` when the user expresses
345
- a preference for a specific backend in natural language, without requiring any
346
- server-side prompt parsing.
347
-
348
- **Update `data/context/bootstrap.md`**:
349
-
350
- Add a section (before the existing tool listing, or at the top of the "Platform"
351
- section if one exists) with these exact routing rules:
352
-
353
- ```markdown
354
- ## Backend Selection
355
-
356
- Two backends may be available: `c64u` (physical C64 Ultimate hardware) and `vice`
357
- (VICE emulator). Use `c64_select_backend` to switch.
358
-
359
- **Routing rules — call `c64_select_backend` first when the user:**
360
- - Says "use vice", "on vice", "in the emulator", "via vice", or similar
361
- - Says "use c64u", "on hardware", "on the Ultimate", "on the real machine", or similar
362
- - Prefixes a request with a backend name, e.g. "vice: run this program"
363
-
364
- Do not assume the current backend is correct without checking
365
- `c64://platform/status` if the user has expressed a preference.
366
- ```
367
-
368
- **Update `AGENTS.md`**:
369
-
370
- Add a short "Runtime Backend Switching" subsection under the configuration section
371
- that explains:
372
- - Both backends can be live simultaneously when configured
373
- - `c64_select_backend` switches without restarting
374
- - The platform status resource (`c64://platform/status`) always reflects the
375
- currently active backend
376
-
377
- **Tasks**:
378
-
379
- - [ ] Add backend routing rules to `data/context/bootstrap.md`.
380
- - [ ] Add "Runtime Backend Switching" subsection to `AGENTS.md`.
381
- - [ ] Verify that the bootstrap content is included in RAG (check
382
- `src/rag/init.ts` or equivalent to confirm `bootstrap.md` is indexed).
383
- - [ ] Append Phase 6 completion entry to `worklog.md`.
384
-
385
- ---
386
-
387
- ### Phase 7 — Update Platform Status Resource
388
-
389
- **Goal**: The `c64://platform/status` resource rendered in `mcp-server.ts` now
390
- also reports which backends are available (not just which is active) and removes
391
- the stale notice about needing a restart to switch.
392
-
393
- **In `mcp-server.ts::renderPlatformStatusMarkdown()`**:
394
-
395
- - Add a "## Available Backends" section listing each backend from
396
- `client.getAvailableBackends()`, marking the active one.
397
- - Remove or update the trailing line:
398
- > Switching platforms currently requires restarting the MCP server with an
399
- > updated configuration.
400
-
401
- Replace with a line explaining `c64_select_backend`.
402
-
403
- **Tasks**:
404
-
405
- - [ ] Update `renderPlatformStatusMarkdown()`.
406
- - [ ] Pass `client` into the function (or use a closure — follow the existing
407
- style in `mcp-server.ts`).
408
- - [ ] Write/update tests for the rendered markdown output.
409
- - [ ] Run `./build test` — all tests pass.
410
- - [ ] Append Phase 7 completion entry to `worklog.md`.
411
-
412
- ---
413
-
414
- ### Phase 8 — Final Validation
415
-
416
- - [ ] Run `./build test` (full mock suite) — zero failures.
417
- - [ ] Run `./build test:matrix` if available — zero failures.
418
- - [ ] Run `./build coverage` — overall coverage ≥ 91%.
419
- - [ ] Manually inspect `plans.md` — every checkbox ticked.
420
- - [ ] Review `worklog.md` — every phase has a completion entry.
421
- - [ ] Read `README.md` configuration section and update it to document:
422
- - The new `C64U_HOST`, `C64U_PORT`, `C64U_PASSWORD` env vars.
423
- - The config-merging behaviour (both config files are read; first-found per
424
- section wins).
425
- - The dual-backend runtime switching capability and `c64_select_backend`.
426
- - [ ] Append Phase 8 completion entry to `worklog.md`.
427
-
428
- ---
429
-
430
- ## Constraints and Non-Goals
431
-
432
- - **Do not** delete or rename any existing public API on `C64Client` or
433
- `C64Facade`.
434
- - **Do not** remove `config.ts` or change its `loadConfig()` signature — it is
435
- used by `mcp-server.ts` for diagnostics and may be used by external callers.
436
- - **Do not** change the `createFacade()` function signature or its behaviour when
437
- called with `preferredC64uBaseUrl` set (that path is used by tests).
438
- - **Do not** add `npm` dependencies beyond what is already in `package.json`.
439
- - **Do not** modify generated files under `generated/`.
440
- - Keep all new source in TypeScript with strict types — no `any` except where the
441
- existing code already uses it for generated API types.
442
- - The `switchBackend()` method on `C64Client` must be synchronous (just a pointer
443
- swap); do not await or re-connect anything inside it.
444
- - The `createAllFacades()` secondary facade is constructed eagerly but its
445
- underlying process (VICE) must **not** be started until the first method call
446
- on it — this matches the existing lazy-start behaviour in `ViceBackend`.
447
-
448
- ---
449
-
450
- ## Precedence Order (for reference and tests)
451
-
452
- After all phases are complete, the effective configuration precedence for backend
453
- selection is, from highest to lowest:
454
-
455
- 1. `C64_MODE` env var (`"c64u"` or `"vice"`) → forces a single backend
456
- 2. `C64U_HOST` / `C64U_PORT` / `C64U_PASSWORD` env vars → override c64u fields
457
- 3. `VICE_BINARY` / `VICE_HOST` / `VICE_PORT` env vars → override vice fields
458
- 4. `C64BRIDGE_CONFIG` env var → explicit config file path (first-found wins per
459
- backend section across this and subsequent candidates)
460
- 5. `.c64bridge.json` in project root → merged into accumulated config
461
- 6. `~/.c64bridge.json` in home directory → merged into accumulated config
462
- 7. Built-in defaults (`c64u:80`, `127.0.0.1:6502`, `x64sc`)
463
-
464
- ---
465
-
466
- ## Acceptance Criteria
467
-
468
- The implementation is complete when:
469
-
470
- 1. Starting the server with only `{ "vice": { "exe": "/usr/bin/x64sc" } }` in
471
- `~/.c64bridge.json` and `{ "c64u": { "host": "c64u" } }` in the project root
472
- results in **both** backends being available and `vice` being selected if
473
- `C64_MODE=vice` is set (or c64u if not set).
474
- 2. Starting with only `{ "vice": ... }` in `~/.c64bridge.json` and **no** project
475
- root config results in the vice backend being selected automatically.
476
- 3. `C64U_HOST=192.168.1.99` in the environment overrides the host from any config
477
- file.
478
- 4. After the server is running with both backends configured, calling the
479
- `c64_select_backend` tool with `backend: "vice"` returns a success result and
480
- subsequent tool calls use the vice facade.
481
- 5. Calling `c64_select_backend` with a backend that is not configured returns an
482
- error result (not a thrown exception) listing which backends are available.
483
- 6. `c64://platform/status` correctly lists available backends and the active one.
484
- 7. `./build coverage` reports ≥ 91% overall.
485
- 8. `plans.md` has every checkbox ticked and `worklog.md` has a completion entry
486
- for every phase.
@@ -1,48 +0,0 @@
1
- # VICE Backend Switch 2
2
-
3
- ## Goal
4
-
5
- Make backend switching feel instantaneous in normal LLM-driven use, keep both backends available in one MCP session, and make visible VICE execution match what the MCP server reads programmatically.
6
-
7
- ## Phase 1: Deterministic VICE Launch
8
-
9
- - Detect and use a valid VICE resource directory automatically instead of assuming the emulator can locate ROMs by itself.
10
- - Allow explicit VICE resource-directory overrides for local setups that install binaries and ROM assets in different prefixes.
11
- - Keep visible desktop launches on the user display by default and avoid silent fallback to hidden sessions unless explicitly requested.
12
- - Add launcher coverage for resource-directory forwarding and startup argument construction.
13
-
14
- ## Phase 2: Always-Ready Mixed Backend Runtime
15
-
16
- - Make the MCP runtime provision both backends inside one `C64Client` when the session can reasonably address both.
17
- - Ensure a VICE-first session can still switch to C64U without restarting the MCP server or editing config files mid-session.
18
- - Preserve platform gating so tools still report accurate compatibility after a switch.
19
- - Add tests for backend availability and switch behavior in split-config and VICE-first scenarios.
20
-
21
- ## Phase 3: Instant Switch Path
22
-
23
- - Warm available backends eagerly after MCP startup so the first post-switch tool call does not pay process-start or probe penalties.
24
- - Serialize VICE monitor access so concurrent tool calls cannot double-start VICE or race the single-client Binary Monitor transport.
25
- - Keep `c64_select_backend` as a local state change only: no probing, no process launch, no extra round trips.
26
- - Add tests for eager warmup behavior and race-free VICE access where feasible.
27
-
28
- ## Phase 4: End-to-End Validation
29
-
30
- - Validate the MCP flow exactly as an LLM would use it: switch backend, run BASIC, read the screen, switch back, repeat.
31
- - Measure switch-plus-run behavior and confirm the steady-state switch path stays under two seconds on this machine.
32
- - Confirm that VICE visibly shows the same BASIC screen state that MCP reports from screen RAM.
33
- - Update user-facing docs and config metadata for the new VICE launch controls.
34
-
35
- ## Phase 5: Environment Override Consistency
36
-
37
- - Ensure every documented runtime environment variable in `mcp.json` is actually honored when the server is launched from a user-provided MCP client config such as `.vscode/mcp.json`.
38
- - Make the override model consistent: environment variable override first, merged JSON config next when applicable, built-in defaults last.
39
- - Keep a generated README table of all supported runtime environment variables, their defaults, and any JSON config key they override.
40
- - Add concrete `.vscode/mcp.json` examples so it is obvious which settings are env-only flags and which map to JSON config fields.
41
-
42
- ## Success Criteria
43
-
44
- - `c64_select_backend` returns immediately for already provisioned backends.
45
- - A VICE-configured session can switch to C64U and back without restarting the server.
46
- - VICE starts visibly on the desktop with a usable C64 screen instead of an inert grey window caused by missing resources.
47
- - `vice: run HELLO WORLD` and `c64u: run HELLO WORLD` both work through the grouped MCP tools.
48
- - Repeated backend switches in one MCP session remain stable and do not spawn duplicate VICE processes.
@@ -1,63 +0,0 @@
1
- # Vice Support — Working Notes
2
-
3
- These notes summarize the current state of VICE support in the MCP server, gaps vs. C64U REST, and design constraints for a robust Binary Monitor (BM) integration.
4
-
5
- ## Current State (as of this branch)
6
-
7
- - Backend abstraction exists (`src/device.ts`) with a `ViceBackend` facade, but it only supports:
8
- - `runPrg(prg)` and `runPrgFile(path)` by spawning `x64sc` with `-autostart -warp -silent`.
9
- - Everything else throws `UNSUPPORTED` (memory, system control, config, drives, etc.).
10
- - A VICE runner utility exists for SID → WAV capture (`src/viceRunner.ts`) but is unrelated to BM.
11
- - Tools mark some operations as `supportedPlatforms: ["c64u", "vice"]`, yet under VICE most calls fail because the facade is a stub.
12
- - `read_screen` relies on `client.readMemoryRaw` (screen RAM at `$0400`), which currently fails on the VICE path because `ViceBackend.readMemory` is unsupported.
13
-
14
- ## Protocol & Feature Parity Summary
15
-
16
- Reference docs:
17
-
18
- - VICE Binary Monitor protocol: `doc/vice/vice-binary-monitor-spec.md`
19
- - Comparison: `doc/vice/vice-bm-vs-c64u-rest.md`
20
-
21
- Key signals from the comparison:
22
-
23
- - BM excels at debugger primitives: memory read/write, breakpoints, single-stepping, register IO, display framebuffer, palette, keyboard feed.
24
- - C64U REST excels at hardware orchestration: DMA-based program runners, drive management, persistent configuration, audio/video/debug streaming.
25
- - Overlap areas: reset and memory IO are available in both; semantics differ (BM supports memspaces and banks, REST exposes a flattened DMA map).
26
-
27
- Implications for MCP:
28
-
29
- - We can deliver strong memory/screen/debug flows via BM under VICE.
30
- - We cannot reasonably replicate drive management, file image creation, streams, or Ultimate firmware configuration on VICE; these remain unsupported or receive emulator-specific resource controls (VICE "resources").
31
- - Program execution can be handled in two ways under VICE:
32
- 1) BM RAM injection on a long‑lived process (default): fast, DMA‑like, precise control.
33
- 2) BM `0xDD` Autostart (fallback): file‑based, minimal pointer logic.
34
- 3) Per‑run `x64sc -autostart` spawn (last resort): slowest; avoids long‑lived state.
35
- - For tests, provide a BM stub controlled via `VICE_TEST_TARGET=mock`; default behavior is to use real VICE when available.
36
- 2) Manage a long‑lived VICE process with BM and implement Autostart (`0xDD`) or direct program injection + `Keyboard Feed` for `RUN` (faster iteration, enables pause/step/breakpoints).
37
-
38
- ## Design Constraints & Decisions
39
-
40
- - Single monitor client at a time: BM accepts one TCP client; keep a singleton session and serialize requests.
41
- - Pause/resume semantics: the BM halts CPU while processing; explicitly resume (`0xAA Exit`) between polling reads so emulation continues (used in readiness helpers and smoke test).
42
- - Request/response framing: implement strict STX, API version (use `0x02`), length, request ID, and per‑command bodies; buffer and parse responses until the expected `(cmdId, reqId)` is observed.
43
- - Timeouts and error mapping: translate BM error codes (0x80–0x8F) into `ToolExecutionError` details; implement clear timeout and ECONNREFUSED handling.
44
- - Screen capture: map `read_screen` to deferred memory reads of `$0400..$07E7` and conversion via `screenCodesToAscii`; later, optionally provide framebuffer snapshots via `0x84`.
45
- - Keyboard automation: use `0x72` for `RUN`/`RETURN` when injecting BASIC; require API header `0x02`.
46
- - Safety: do not emulate hardware operations that do not exist on VICE (drives, poweroff); leave them unsupported with explicit messages.
47
-
48
- ## Viability Evidence
49
-
50
- - `test/vice/viceSmokeTest.ts` (TS) demonstrates hard/soft reset, memory write/read, keyboard feed, screen polling with resume hooks, and clean process teardown (visible or headless).
51
-
52
- ## Scope Clarifications
53
-
54
- - Long‑lived VICE process: the default workflow keeps a supervised emulator running and injects programs into RAM for speed and parity with C64U DMA.
55
- - Autostart remains an optional fallback (BM `0xDD`) but is not the default. Per‑run spawn is a last resort.
56
- - `src/viceRunner.ts` is kept for SID→WAV audio export only; general VICE control is implemented behind the facade using `src/vice/viceClient.ts` + `src/vice/readiness.ts` and a supervisor.
57
-
58
- ## Targeted Scope per Phase (high level)
59
-
60
- 1) Core BM client + memory/screen + reset + pause/resume (keep current ephemeral PRG runner).
61
- 2) Long‑lived VICE process mgmt + Autostart (`0xDD`) or injection + keyboard feed; stable program runners; keyboard tool.
62
- 3) Debugger features: breakpoints, stepping, registers; bank/memspace awareness surfaced; optional display get.
63
- 4) Emulator resources & display capture polish; finalize platform descriptors and docs.