@henols/vice-mcp 0.2.2 → 0.2.4

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 (84) hide show
  1. package/README.md +2 -2
  2. package/THIRD-PARTY-NOTICES.md +422 -1
  3. package/anno-bank.ts +171 -0
  4. package/anno-cli.ts +1736 -163
  5. package/anno-confidence.ts +2 -2
  6. package/anno-derive.ts +6 -6
  7. package/anno-details.ts +4 -4
  8. package/anno-enum-gen.ts +416 -30
  9. package/anno-export-asm.ts +1211 -126
  10. package/anno-graphics.ts +338 -0
  11. package/anno-hazard-report.ts +1367 -0
  12. package/anno-import.ts +495 -0
  13. package/anno-index.ts +8 -8
  14. package/anno-join.ts +480 -0
  15. package/anno-memmap-render.ts +22 -21
  16. package/anno-provenance-ledger.ts +472 -0
  17. package/anno-regbits-gen.ts +13 -13
  18. package/anno-register.ts +159 -0
  19. package/anno-store-export.ts +661 -0
  20. package/anno-store.ts +635 -124
  21. package/anno-symbols.ts +7 -7
  22. package/anno-tools.ts +1169 -16
  23. package/anno-types.ts +313 -40
  24. package/backend-detect.mts +124 -312
  25. package/build.ts +3 -1
  26. package/capture-predicate.ts +597 -0
  27. package/channel-lock.ts +349 -0
  28. package/evid-ingest.ts +217 -0
  29. package/evid-reconcile.ts +316 -0
  30. package/host-tool-client.ts +430 -0
  31. package/incident-record.ts +23 -12
  32. package/install-resources.ts +29 -13
  33. package/memmap-lookup.ts +285 -0
  34. package/package.json +27 -8
  35. package/prg-image.ts +1 -2
  36. package/repo-root.ts +87 -3
  37. package/resources/backend-detect.mjs +98 -236
  38. package/resources/broker-control.mjs +220 -54
  39. package/resources/broker-epoch.mjs +7 -8
  40. package/resources/broker-kill.mjs +36 -31
  41. package/resources/broker-launch.mjs +511 -374
  42. package/resources/broker-state.mjs +69 -24
  43. package/resources/container-guard.mjs +1 -1
  44. package/resources/ghidra-project.mjs +790 -0
  45. package/resources/host-tool.mjs +2533 -0
  46. package/resources/vice-broker.mjs +434 -290
  47. package/resources/vice-launcher.sh +127 -9
  48. package/stock-address.ts +1 -1
  49. package/stock-condition.ts +1 -1
  50. package/stock-connect.ts +9 -5
  51. package/stock-derived.ts +29 -37
  52. package/stock-diagnose.ts +200 -36
  53. package/stock-dispatch.ts +179 -77
  54. package/stock-handler.ts +1 -1
  55. package/stock-paths.ts +18 -14
  56. package/stock-petscii.ts +1 -1
  57. package/stock-protocol.ts +1 -1
  58. package/stock-recycle.ts +83 -2
  59. package/stock-reproducible-run.ts +811 -0
  60. package/stock-run-until.ts +100 -1
  61. package/stock-symbols.ts +4 -4
  62. package/stock-timing.ts +1 -1
  63. package/stop-oracle.ts +167 -0
  64. package/text-capability-probe.ts +660 -0
  65. package/text-connect.ts +157 -0
  66. package/text-protocol.ts +810 -0
  67. package/text-tools.ts +778 -0
  68. package/textmon-backtrace.ts +385 -0
  69. package/textmon-cpuhistory.ts +335 -0
  70. package/textmon-memmap.ts +494 -0
  71. package/textmon-profile.ts +458 -0
  72. package/textmon-registers.ts +748 -0
  73. package/tools-manifest.stock.json +864 -3
  74. package/vice-broker-client.ts +253 -108
  75. package/vice-errors.ts +268 -0
  76. package/vice-proxy.ts +339 -2144
  77. package/vsf-slice.ts +640 -0
  78. package/anno-d64.ts +0 -310
  79. package/capability-registry.ts +0 -390
  80. package/refresh-manifest.ts +0 -124
  81. package/tools-manifest.json +0 -1223
  82. package/vice-probe.ts +0 -278
  83. package/vice-sync.ts +0 -336
  84. package/vice.ts +0 -772
@@ -2,17 +2,41 @@
2
2
  // Compiled by `tsc` from broker-state.mts. Edit the TypeScript source and rebuild;
3
3
  // changes made directly to this file are silently overwritten by the next build, and are never
4
4
  // deployed to the host on their own -- install-resources.mjs copies THIS file's on-disk contents
5
- // verbatim to tools/, so an edit made only here reaches the host but is lost on the very next
5
+ // verbatim to .c64-re-tools/bin/, so an edit made only here reaches the host but is lost on the very next
6
6
  // rebuild.
7
7
  import { createServer } from "node:net";
8
- /** Clears `monitorClient` as a side effect of release, recycle, or the
9
- * instance's own process exit (see InstanceRecord.monitorClient's own header
10
- * comment for the three call sites) -- so a dead or torn-down client can
11
- * never hold this lock forever. A no-op when no monitor client is currently
12
- * recorded (idempotent, matching monitor_release's own tolerance for an
13
- * already-cleared record). */
14
- export function clearMonitorClient(record) {
15
- record.monitorClient = undefined;
8
+ // ---------------------------------------------------------------------------
9
+ // MonitorChannel: exactly two channels exist -- stock VICE
10
+ // exposes precisely the binary monitor and the `-remotemonitor` text
11
+ // channel -- and this project has no plan to add a third. Frozen so a
12
+ // consumer cannot accidentally push a third value onto it at runtime.
13
+ //
14
+ // Declared here a SECOND time in channel-lock.ts (and a third time, as a
15
+ // local literal union, in vice-broker-client.ts) rather than imported from a
16
+ // single shared home: channel-lock.ts is a container-side module and this
17
+ // module is host-bound and compiled into resources/*.mjs, so neither can
18
+ // import the other at runtime. The shared thing between the declarations is
19
+ // the two-value CONTRACT ("binary" | "text"), not the declaration itself.
20
+ // ---------------------------------------------------------------------------
21
+ export const MONITOR_CHANNELS = Object.freeze(["binary", "text"]);
22
+ /** Clears ONE channel's entry when `channel` is passed (an explicit
23
+ * `monitor_release` for that channel), or EVERY channel's entry when it is
24
+ * omitted (the whole record's ownership is going away -- recycle, release,
25
+ * or the instance's own process exit; see InstanceRecord.monitorClients'
26
+ * own header comment for the exact call sites of each case) -- so a dead or
27
+ * torn-down client can never hold this lock forever, on any channel. The
28
+ * ONE place a holder entry is cleared, apart from broker-launch.mts's
29
+ * handleExit(), which assigns `{}` directly for a documented reason (see
30
+ * that function's own comment). A no-op when the targeted channel (or, with
31
+ * no channel, every channel) is not currently held -- idempotent, matching
32
+ * monitor_release's own tolerance for an already-cleared record. */
33
+ export function clearMonitorClient(record, channel) {
34
+ if (channel !== undefined) {
35
+ delete record.monitorClients[channel];
36
+ return;
37
+ }
38
+ for (const ch of MONITOR_CHANNELS)
39
+ delete record.monitorClients[ch];
16
40
  }
17
41
  export function createBrokerState() {
18
42
  return { instances: new Map(), grants: new Map(), blockedPorts: new Set() };
@@ -23,13 +47,26 @@ export function createBrokerState() {
23
47
  * trip. */
24
48
  export function _snapshotState(state) {
25
49
  return {
26
- instances: Array.from(state.instances.values()).map((r) => ({ ...r, viceArgs: [...r.viceArgs] })),
50
+ // `profile` is the SECOND nested object on an
51
+ // InstanceRecord (after `viceArgs`), so it needs its own copy for this
52
+ // function's documented "deep, plain-object copy" contract to stay true --
53
+ // a spread alone would hand a caller a reference into live broker state,
54
+ // and this file's own snapshot test asserts that mutating a nested value
55
+ // in the result leaves the broker's state unchanged. The key is
56
+ // reproduced only when present, so an absent profile stays absent in the
57
+ // snapshot (absent means profile-less, and a snapshot must not invent a
58
+ // `profile: undefined` key that the record itself does not carry).
59
+ instances: Array.from(state.instances.values()).map((r) => ({
60
+ ...r,
61
+ viceArgs: [...r.viceArgs],
62
+ ...(r.profile === undefined ? {} : { profile: { ...r.profile } }),
63
+ })),
27
64
  grants: Array.from(state.grants.values()).map((g) => ({ ...g })),
28
65
  blockedPorts: Array.from(state.blockedPorts).sort((a, b) => a - b),
29
66
  };
30
67
  }
31
- /** VICE_BROKER_BASE_PORT's default (D-18): the broker's port band moves
32
- * from 6510 to 6600 in this phase -- 6510-6599 stays reserved by convention
68
+ /** VICE_BROKER_BASE_PORT's default: the broker's port band moved
69
+ * from 6510 to 6600 -- 6510-6599 stays reserved by convention
33
70
  * for an x64sc a human launches for their own work. */
34
71
  export const DEFAULT_BASE_PORT = 6600;
35
72
  /** Scan ceiling matching vice-broker.sh's own next_free_port(): exactly one
@@ -80,8 +117,8 @@ export function isPortBlocked(state, port) {
80
117
  export function blockPort(state, port) {
81
118
  state.blockedPorts.add(port);
82
119
  }
83
- /** Allocates the lowest free port at or above the base port (default 6600
84
- * per D-18, overridable via VICE_BROKER_BASE_PORT -- the same env var name
120
+ /** Allocates the lowest free port at or above the base port (default 6600,
121
+ * overridable via VICE_BROKER_BASE_PORT -- the same env var name
85
122
  * the bash daemon used), scanning up to PORT_SCAN_CEILING candidates.
86
123
  * "Free" means: not already recorded in the instance map (granted,
87
124
  * launching or ready all occupy their port), not already in the
@@ -91,8 +128,7 @@ export function blockPort(state, port) {
91
128
  * set before scanning continues, so it is never re-offered or re-probed by
92
129
  * this process again. Never throws -- returns a typed failure naming
93
130
  * exhaustion when every candidate in the window is taken. */
94
- // Gap closure (plan 14, discovered live during Task 2's own end-to-end
95
- // proof -- see RE-FINDINGS.md's dated entry for the full account):
131
+ // Discovered live during an end-to-end proof of this allocator:
96
132
  // EADDRINUSE is delivered to defaultPortInUse()'s `error` listener without
97
133
  // ever yielding to libuv's poll phase, so a scan running against MANY
98
134
  // already-bound candidates in a row does not merely take longer -- for its
@@ -149,14 +185,23 @@ export function countReady(state) {
149
185
  export function countTotal(state) {
150
186
  return state.instances.size;
151
187
  }
152
- /** Counts instances currently "launching" -- THE single counter both launch
153
- * paths (a cold acquire, via handleAcquire in vice-broker.mts, and warm
154
- * floor maintenance, via maintainWarmFloor in broker-launch.mts) consult
155
- * before starting a new launch. Two counters that could ever disagree about
156
- * whether a boot is already under way is exactly how the two bash launch
157
- * paths raced each other into the 2026-08-01 outage (three simultaneous
158
- * x64sc launches: one SEGV, one exit 1, one exit 0 at the identical spawn
159
- * second) -- there is now exactly one, read here and nowhere else. */
188
+ /** Counts instances currently "launching". The warm floor and its own
189
+ * maintainWarmFloor() were retired -- that was the SECOND launch path
190
+ * that used to read this counter as a pre-check before starting a new
191
+ * launch, alongside the cold-acquire arm's own equivalent check. With only
192
+ * one launch path left (vice-broker.mts's handleAcquire(), guarded by
193
+ * acquirePortAndLaunch()'s own single-owner `inFlight` boolean in
194
+ * broker-launch.mts -- a SEPARATE, synchronous primitive, not this
195
+ * function), nothing in production calls this counter today; it remains
196
+ * exported alongside countReady()/countTotal() as status-shaped
197
+ * infrastructure. It is named here, and its history preserved, because it
198
+ * is why a SINGLE counter -- not two, one per launch path -- was the fix
199
+ * for the 2026-08-01 outage (three simultaneous x64sc launches: one SEGV,
200
+ * one exit 1, one exit 0 at the identical spawn second): two counters that
201
+ * could ever disagree about whether a boot was already under way is exactly
202
+ * how that outage happened, and the discipline of reading exactly one is
203
+ * what this function's own existence still documents, even with one launch
204
+ * path left to (potentially) consult it. */
160
205
  export function countLaunching(state) {
161
206
  let n = 0;
162
207
  for (const record of state.instances.values()) {
@@ -2,7 +2,7 @@
2
2
  // Compiled by `tsc` from container-guard.mts. Edit the TypeScript source and rebuild;
3
3
  // changes made directly to this file are silently overwritten by the next build, and are never
4
4
  // deployed to the host on their own -- install-resources.mjs copies THIS file's on-disk contents
5
- // verbatim to tools/, so an edit made only here reaches the host but is lost on the very next
5
+ // verbatim to .c64-re-tools/bin/, so an edit made only here reaches the host but is lost on the very next
6
6
  // rebuild.
7
7
  // container-guard.mts
8
8
  //