@henols/vice-mcp 0.2.1 → 0.2.3
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.
- package/README.md +4 -3
- package/THIRD-PARTY-NOTICES.md +423 -25
- package/{r2000-acme-ident.ts → anno-acme-ident.ts} +13 -13
- package/anno-bank.ts +171 -0
- package/anno-cli.ts +3040 -0
- package/{r2000-confidence.ts → anno-confidence.ts} +22 -22
- package/anno-coverage.ts +2465 -0
- package/anno-derive.ts +590 -0
- package/anno-details.ts +169 -0
- package/anno-enum-gen.ts +919 -0
- package/anno-export-asm.ts +2396 -0
- package/anno-graphics.ts +338 -0
- package/anno-hazard-report.ts +1367 -0
- package/anno-import.ts +495 -0
- package/anno-index.ts +150 -0
- package/anno-join.ts +480 -0
- package/{r2000-memmap-render.ts → anno-memmap-render.ts} +236 -95
- package/anno-provenance-ledger.ts +472 -0
- package/{r2000-regbits-gen.ts → anno-regbits-gen.ts} +20 -15
- package/{r2000-regbits.json → anno-regbits.json} +2 -2
- package/anno-register.ts +399 -0
- package/anno-store-export.ts +661 -0
- package/anno-store.ts +4002 -0
- package/anno-symbols.ts +266 -0
- package/anno-tools.ts +3264 -0
- package/anno-types.ts +1909 -0
- package/backend-detect.mts +124 -312
- package/block-class.ts +201 -0
- package/build.ts +4 -2
- package/capture-predicate.ts +597 -0
- package/channel-lock.ts +349 -0
- package/disasm-decoder.ts +14 -14
- package/disasm-opcodes.ts +4 -4
- package/disasm-renderer.ts +2 -2
- package/evid-ingest.ts +217 -0
- package/evid-reconcile.ts +316 -0
- package/host-tool-client.ts +430 -0
- package/hostpath.ts +1 -1
- package/incident-record.ts +23 -12
- package/install-resources.ts +30 -14
- package/memmap-lookup.ts +285 -0
- package/package.json +48 -23
- package/prg-image.ts +118 -0
- package/repo-root.ts +107 -8
- package/resources/backend-detect.mjs +98 -236
- package/resources/broker-control.mjs +189 -16
- package/resources/broker-epoch.mjs +1 -1
- package/resources/broker-kill.mjs +8 -2
- package/resources/broker-launch.mjs +373 -214
- package/resources/broker-state.mjs +64 -18
- package/resources/container-guard.mjs +1 -1
- package/resources/ghidra-project.mjs +790 -0
- package/resources/host-tool.mjs +2561 -0
- package/resources/vice-broker.mjs +330 -184
- package/resources/vice-launcher.sh +130 -12
- package/stock-address.ts +6 -6
- package/stock-cia.ts +2 -2
- package/stock-condition.ts +8 -8
- package/stock-connect.ts +10 -6
- package/stock-derived.ts +29 -37
- package/stock-diagnose.ts +200 -36
- package/stock-dispatch.ts +200 -68
- package/stock-execution.ts +5 -3
- package/stock-handler.ts +1 -1
- package/stock-input.ts +9 -9
- package/stock-machine.ts +17 -6
- package/stock-paths.ts +18 -14
- package/stock-petscii.ts +1 -1
- package/stock-protocol.ts +17 -12
- package/stock-recycle.ts +83 -2
- package/stock-registers.ts +54 -29
- package/stock-reproducible-run.ts +811 -0
- package/stock-run-until.ts +100 -1
- package/stock-sprites.ts +3 -3
- package/stock-symbols.ts +13 -13
- package/stock-timing.ts +2 -2
- package/stock-vicii.ts +1 -1
- package/stop-oracle.ts +167 -0
- package/text-capability-probe.ts +660 -0
- package/text-connect.ts +157 -0
- package/text-protocol.ts +810 -0
- package/text-tools.ts +778 -0
- package/textmon-backtrace.ts +385 -0
- package/textmon-cpuhistory.ts +335 -0
- package/textmon-memmap.ts +494 -0
- package/textmon-profile.ts +458 -0
- package/textmon-registers.ts +748 -0
- package/tools-manifest.stock.json +864 -3
- package/version.ts +1 -1
- package/vice-broker-client.ts +189 -42
- package/vice-errors.ts +268 -0
- package/vice-proxy.ts +392 -2175
- package/vsf-slice.ts +640 -0
- package/capability-registry.ts +0 -388
- package/r2000-cli.ts +0 -1103
- package/r2000-d64.ts +0 -310
- package/r2000-enum-gen.ts +0 -574
- package/r2000-launch.ts +0 -357
- package/r2000-mcp-client.ts +0 -596
- package/r2000-project.ts +0 -190
- package/r2000-symbols.ts +0 -388
- package/r2000-tools.ts +0 -914
- package/r2000-verify.ts +0 -184
- package/refresh-manifest.ts +0 -124
- package/tools-manifest.json +0 -1223
- package/vice-probe.ts +0 -278
- package/vice-sync.ts +0 -336
- package/vice.ts +0 -772
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# src/mcp/vice/resources/vice-launcher.sh
|
|
3
3
|
#
|
|
4
4
|
# HAND-AUTHORED -- not generated. It lives beside the generated vice-broker.mjs
|
|
5
5
|
# purely because install-resources.mjs deploys the whole resources/ directory
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
# --check-container is now forwarded through to the Node entry point, which
|
|
16
16
|
# answers it, preserving the exact same exit-code contract this launcher
|
|
17
17
|
# always had: 2 when the guard refuses, 3 for the report path, 0 for
|
|
18
|
-
# --print-paths
|
|
18
|
+
# --print-paths, and (new below) 4 when no interpreter this launcher is
|
|
19
|
+
# willing to exec into could be resolved -- distinct from 2/3 so a triage
|
|
20
|
+
# reader can tell "no usable interpreter" from "container guard refused"
|
|
21
|
+
# at a glance.
|
|
19
22
|
#
|
|
20
23
|
# Copies vice-broker.sh's own opening shape: SELF_PATH/SELF_DIR resolution,
|
|
21
24
|
# resolve_repo_root(). Plan 11 INLINES resolve_repo_root() here (it used to
|
|
@@ -38,7 +41,7 @@ SELF_DIR="$(cd "$(dirname "$SELF_PATH")" && pwd)"
|
|
|
38
41
|
#
|
|
39
42
|
# WHY THIS FUNCTION EXISTS AT ALL: a fixed `".."` hop (`REPO_ROOT="$(cd
|
|
40
43
|
# "$(dirname "$SELF_PATH")/.." && pwd)"`) is wrong from this launcher's own
|
|
41
|
-
# location,
|
|
44
|
+
# location, `src/mcp/vice/resources/` -- four levels below the repo root,
|
|
42
45
|
# not one. NOTHING would error on a wrong fixed hop count: the script would
|
|
43
46
|
# just read a permanently-empty `.vice-supervisor` state directory forever,
|
|
44
47
|
# and restart detection would quietly stop working while every command kept
|
|
@@ -73,7 +76,7 @@ _REPO_ROOT_WARNED_NO_MARKER=0
|
|
|
73
76
|
# paths.
|
|
74
77
|
# 4. Otherwise, a location-shaped last resort, also with a one-time stderr
|
|
75
78
|
# note: FOUR levels up when <absolute-dir>'s own directory is named
|
|
76
|
-
# `resources` (matching `<root
|
|
79
|
+
# `resources` (matching `<root>/src/mcp/vice/resources`),
|
|
77
80
|
# ONE level up otherwise.
|
|
78
81
|
resolve_repo_root() {
|
|
79
82
|
local from="$1" dir parent base
|
|
@@ -131,12 +134,105 @@ REPO_ROOT="$(resolve_repo_root "$SELF_DIR")"
|
|
|
131
134
|
# deployed tools/ copy that may be stale or hand-edited.
|
|
132
135
|
BROKER_ARTIFACT="$SELF_DIR/vice-broker.mjs"
|
|
133
136
|
|
|
137
|
+
# ---------------------------------------------------------------- interpreter resolution
|
|
138
|
+
#
|
|
139
|
+
# WHY THIS EXISTS: this launcher used to `exec node ...`, trusting whatever
|
|
140
|
+
# `node` a shell's PATH resolved first. On a development host with several
|
|
141
|
+
# Node majors installed side by side that is an accident waiting to happen,
|
|
142
|
+
# and a service environment (a systemd unit's own PATH, carrying no
|
|
143
|
+
# interactive-shell version-manager entry) resolves a DIFFERENT one than an
|
|
144
|
+
# interactive shell -- the same script started two different ways running
|
|
145
|
+
# two different interpreters, with no record of which. Nothing spawns this
|
|
146
|
+
# script (the broker never spawns itself; the only thing that ever prints
|
|
147
|
+
# this path is a message telling a HUMAN to run it), so there is no parent
|
|
148
|
+
# process whose own interpreter this launcher could inherit or receive as an
|
|
149
|
+
# argument -- the ladder below, plus a refusal, is the whole of it.
|
|
150
|
+
#
|
|
151
|
+
# NODE_FLOOR_MAJOR mirrors src/mcp/vice/package.json's `engines.node` --
|
|
152
|
+
# pinned to that single number by a test (host-scripts.test.ts) precisely so
|
|
153
|
+
# this floor cannot silently drift into a second, disagreeing number, which
|
|
154
|
+
# is the same failure class as the bare-interpreter exec this section
|
|
155
|
+
# replaces.
|
|
156
|
+
NODE_FLOOR_MAJOR=24
|
|
157
|
+
|
|
158
|
+
# probe_node_version <candidate-path>
|
|
159
|
+
#
|
|
160
|
+
# On success, sets NODE_RESOLVED_VERSION (the raw "vX.Y.Z" string) and
|
|
161
|
+
# NODE_RESOLVED_MAJOR (just the leading number) and returns 0. On any
|
|
162
|
+
# failure -- not executable, crashes, or prints something this launcher
|
|
163
|
+
# cannot parse as a version -- returns 1 and sets neither. Called only from
|
|
164
|
+
# inside an `if`, so a failure here becomes a named refusal downstream
|
|
165
|
+
# rather than aborting the whole script under `set -e`.
|
|
166
|
+
probe_node_version() {
|
|
167
|
+
local candidate="$1" raw major
|
|
168
|
+
if ! raw="$("$candidate" --version 2>/dev/null)"; then
|
|
169
|
+
return 1
|
|
170
|
+
fi
|
|
171
|
+
case "$raw" in
|
|
172
|
+
v[0-9]*) : ;;
|
|
173
|
+
*) return 1 ;;
|
|
174
|
+
esac
|
|
175
|
+
major="${raw#v}"
|
|
176
|
+
major="${major%%.*}"
|
|
177
|
+
case "$major" in
|
|
178
|
+
''|*[!0-9]*) return 1 ;;
|
|
179
|
+
esac
|
|
180
|
+
NODE_RESOLVED_VERSION="$raw"
|
|
181
|
+
NODE_RESOLVED_MAJOR="$major"
|
|
182
|
+
return 0
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
# Resolution ladder -- exactly two rungs, then a refusal. There is no third
|
|
186
|
+
# rung to invent: see the WHY note above for why the broker's own
|
|
187
|
+
# interpreter can never be threaded in as a candidate.
|
|
188
|
+
#
|
|
189
|
+
# 1. VICE_BROKER_NODE, an absolute-path override, accepted only when it
|
|
190
|
+
# names an executable file -- this is the rung that fixes a service
|
|
191
|
+
# unit whose PATH carries no usable node at all: point it at one
|
|
192
|
+
# directly instead of depending on PATH.
|
|
193
|
+
# 2. `node` as found on PATH.
|
|
194
|
+
NODE_BIN=""
|
|
195
|
+
NODE_VERSION=""
|
|
196
|
+
NODE_MAJOR=""
|
|
197
|
+
NODE_RESOLUTION_ERROR=""
|
|
198
|
+
|
|
199
|
+
if [ -n "${VICE_BROKER_NODE:-}" ]; then
|
|
200
|
+
if [ -f "${VICE_BROKER_NODE}" ] && [ -x "${VICE_BROKER_NODE}" ]; then
|
|
201
|
+
if probe_node_version "$VICE_BROKER_NODE"; then
|
|
202
|
+
NODE_BIN="$VICE_BROKER_NODE"
|
|
203
|
+
NODE_VERSION="$NODE_RESOLVED_VERSION"
|
|
204
|
+
NODE_MAJOR="$NODE_RESOLVED_MAJOR"
|
|
205
|
+
else
|
|
206
|
+
NODE_RESOLUTION_ERROR="VICE_BROKER_NODE is set to '$VICE_BROKER_NODE', but running it with --version failed or produced output this launcher could not parse. Set VICE_BROKER_NODE to an absolute path to a working node executable, or unset it to fall back to node on PATH."
|
|
207
|
+
fi
|
|
208
|
+
else
|
|
209
|
+
NODE_RESOLUTION_ERROR="VICE_BROKER_NODE is set to '$VICE_BROKER_NODE', which does not resolve to an executable file. Set VICE_BROKER_NODE to an absolute path to an executable node interpreter, or unset it to fall back to node on PATH."
|
|
210
|
+
fi
|
|
211
|
+
else
|
|
212
|
+
NODE_CANDIDATE="$(command -v node 2>/dev/null || true)"
|
|
213
|
+
if [ -n "$NODE_CANDIDATE" ]; then
|
|
214
|
+
if probe_node_version "$NODE_CANDIDATE"; then
|
|
215
|
+
NODE_BIN="$NODE_CANDIDATE"
|
|
216
|
+
NODE_VERSION="$NODE_RESOLVED_VERSION"
|
|
217
|
+
NODE_MAJOR="$NODE_RESOLVED_MAJOR"
|
|
218
|
+
else
|
|
219
|
+
NODE_RESOLUTION_ERROR="Resolved 'node' on PATH at '$NODE_CANDIDATE', but running it with --version failed or produced output this launcher could not parse. Install a working Node >= v${NODE_FLOOR_MAJOR} and put it on PATH, or set VICE_BROKER_NODE to an absolute path to one."
|
|
220
|
+
fi
|
|
221
|
+
else
|
|
222
|
+
NODE_RESOLUTION_ERROR="No 'node' executable was found on PATH and VICE_BROKER_NODE is not set. Install Node >= v${NODE_FLOOR_MAJOR} and put it on PATH, or set VICE_BROKER_NODE to an absolute path to one."
|
|
223
|
+
fi
|
|
224
|
+
fi
|
|
225
|
+
|
|
134
226
|
# ---------------------------------------------------------------- --print-paths
|
|
135
227
|
#
|
|
136
|
-
# Prints already-resolved variables only -- writes no state
|
|
137
|
-
# so (like vice-broker.sh's own
|
|
138
|
-
#
|
|
139
|
-
#
|
|
228
|
+
# Prints already-resolved variables only -- writes no state and spawns
|
|
229
|
+
# nothing beyond the version probe above, so (like vice-broker.sh's own
|
|
230
|
+
# --print-paths) it needs no guard enforcement to report what this launcher
|
|
231
|
+
# would use. Checked BEFORE --check-container is forwarded, since
|
|
232
|
+
# --print-paths needs no guard verdict at all, and BEFORE the floor is
|
|
233
|
+
# enforced below: this diagnostic reports what it found, or reports it
|
|
234
|
+
# found nothing, but never refuses -- a diagnostic that dies exactly when
|
|
235
|
+
# the thing it diagnoses is broken is worthless.
|
|
140
236
|
PRINT_PATHS=0
|
|
141
237
|
for arg in "$@"; do
|
|
142
238
|
case "$arg" in
|
|
@@ -150,9 +246,29 @@ if [ "$PRINT_PATHS" -eq 1 ]; then
|
|
|
150
246
|
echo "repo_root=$REPO_ROOT"
|
|
151
247
|
echo "self_dir=$SELF_DIR"
|
|
152
248
|
echo "broker_artifact=$BROKER_ARTIFACT"
|
|
249
|
+
echo "node_bin=$NODE_BIN"
|
|
250
|
+
echo "node_version=$NODE_VERSION"
|
|
153
251
|
exit 0
|
|
154
252
|
fi
|
|
155
253
|
|
|
254
|
+
# ---------------------------------------------------------------- interpreter gate
|
|
255
|
+
#
|
|
256
|
+
# Refuses BEFORE exec, by name, with a remedy -- a below-floor or
|
|
257
|
+
# unresolvable interpreter must never reach the broker artifact, because
|
|
258
|
+
# once it does, whatever fails next presents as a wedge with no obvious
|
|
259
|
+
# cause. This project detects and refuses by name; it never installs
|
|
260
|
+
# anything and never shells out to a package manager.
|
|
261
|
+
if [ -z "$NODE_BIN" ]; then
|
|
262
|
+
printf 'vice-launcher: refusing to start -- %s\n' "$NODE_RESOLUTION_ERROR" >&2
|
|
263
|
+
exit 4
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
if [ "$NODE_MAJOR" -lt "$NODE_FLOOR_MAJOR" ]; then
|
|
267
|
+
printf 'vice-launcher: refusing to start -- resolved node interpreter %s reports %s, which is below the required floor v%s.x. Install a Node >= v%s and put it on PATH, or set VICE_BROKER_NODE to an absolute path to one that satisfies the floor.\n' \
|
|
268
|
+
"$NODE_BIN" "$NODE_VERSION" "$NODE_FLOOR_MAJOR" "$NODE_FLOOR_MAJOR" >&2
|
|
269
|
+
exit 4
|
|
270
|
+
fi
|
|
271
|
+
|
|
156
272
|
# ---------------------------------------------------------------- exec
|
|
157
273
|
#
|
|
158
274
|
# The guard now runs INSIDE the Node entry point, at its own process
|
|
@@ -161,9 +277,11 @@ fi
|
|
|
161
277
|
# enforcement path (exit 2, refusal) are the broker's own job now. This
|
|
162
278
|
# launcher forwards every argument, including --repo-root, unchanged, and
|
|
163
279
|
# no longer inspects --check-container itself; the exit-code contract this
|
|
164
|
-
# launcher always exposed (2/3/0) is preserved because the guard
|
|
165
|
-
# ported into container-guard.mts return the SAME codes
|
|
280
|
+
# launcher always exposed (2/3/0, now also 4) is preserved because the guard
|
|
281
|
+
# functions ported into container-guard.mts return the SAME codes
|
|
166
282
|
# container_guard_enforce()/container_guard_report() always did. Signal
|
|
167
283
|
# delivery still passes straight through to the broker process with no bash
|
|
168
|
-
# trap in between
|
|
169
|
-
|
|
284
|
+
# trap in between -- exec replaces the process image with the RESOLVED
|
|
285
|
+
# interpreter, never a bare command name, so the interpreter this launcher
|
|
286
|
+
# actually gated is the one that actually runs.
|
|
287
|
+
exec "$NODE_BIN" "$BROKER_ARTIFACT" --repo-root "$REPO_ROOT" "$@"
|
package/stock-address.ts
CHANGED
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
// hex by default" rule belongs to the checkpoint-condition emitter, not
|
|
24
24
|
// this parser. Do not conflate the two.
|
|
25
25
|
// - Never implement symbol resolution in Phase 3. setSymbolResolver() is
|
|
26
|
-
//
|
|
27
|
-
//
|
|
26
|
+
// the one extension point for it: it starts `null` and stays that way
|
|
27
|
+
// until stock-symbols.ts's `vice_symbols_load` installs a real resolver.
|
|
28
28
|
// - Never add a second resolver holder. `nameFor` (address -> name,
|
|
29
29
|
// DISASM-06's first consumer, Phase 4) and `resolve` (name -> address,
|
|
30
30
|
// Phase 3) live on the SAME `SymbolResolver` object, read from the SAME
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
// installs one object implementing both; a second holder or a
|
|
33
33
|
// re-derived address->name map in a family module would force it to
|
|
34
34
|
// install itself twice.
|
|
35
|
-
import { ViceError, type ViceErrorOptions } from "./vice.ts";
|
|
35
|
+
import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
36
36
|
|
|
37
37
|
export interface SymbolResolver {
|
|
38
38
|
resolve(name: string): number | undefined;
|
|
@@ -46,9 +46,9 @@ export interface SymbolResolver {
|
|
|
46
46
|
// -- no symbol resolution happens until a later phase installs one.
|
|
47
47
|
let symbolResolver: SymbolResolver | null = null;
|
|
48
48
|
|
|
49
|
-
/** The
|
|
50
|
-
*
|
|
51
|
-
* loaded" refusal. */
|
|
49
|
+
/** The extension point stock-symbols.ts's `vice_symbols_load` fills at
|
|
50
|
+
* runtime. Passing `null` (the default before any load) restores the "no
|
|
51
|
+
* symbol table loaded" refusal. */
|
|
52
52
|
export function setSymbolResolver(resolver: SymbolResolver | null): void {
|
|
53
53
|
symbolResolver = resolver;
|
|
54
54
|
}
|
package/stock-cia.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// field naming the sharing address.
|
|
24
24
|
//
|
|
25
25
|
// Bit-field names below were transcribed ONCE from
|
|
26
|
-
//
|
|
26
|
+
// `src/skills/c64-memory-mapping/memmap.json`'s entries for $DC00,
|
|
27
27
|
// $DC01, $DC02, $DC03, $DC08-$DC0F, $DD00, $DD01 and $DD0D, and
|
|
28
28
|
// cross-checked at write time -- the same "committed literal, cross-checked
|
|
29
29
|
// once, no automated drift check" posture Phase 4's D-06 already accepted
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
// - This is NOT a keyboard-matrix read. $DC00/$DC01 expose only the
|
|
37
37
|
// current column selection and row result; the full matrix is
|
|
38
38
|
// `vice_keyboard_matrix`, which is provably unrecoverable on stock
|
|
39
|
-
// (`docs/stock-vice-parity.md` SS A item 2) and
|
|
39
|
+
// (`docs/stock-vice-parity.md` SS A item 2) -- the wire protocol has no matrix command, and `KEYBOARD_FEED` (0x72) injects buffer text only.
|
|
40
40
|
// - WR-02 (2026-08-17): the port A/B joystick bits share their PINS with
|
|
41
41
|
// the keyboard matrix's column-select ($DC00) and row-read ($DC01), and
|
|
42
42
|
// a stock read halts the machine at an arbitrary PC -- often inside the
|
package/stock-condition.ts
CHANGED
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
// last gate before the wire and re-validates every literal and every
|
|
36
36
|
// kind itself, even though parseConditionString() and conditionFromJson()
|
|
37
37
|
// also validate on the way in.
|
|
38
|
-
// -
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
//
|
|
38
|
+
// - GAIN-06's raster-semantics extension (finer-grained raster/cycle
|
|
39
|
+
// conditions) was cut with the whole of Stock-Only Gains, 2026-08-17
|
|
40
|
+
// (see docs/stock-vice-parity.md's dated cut record). Widening this AST
|
|
41
|
+
// is unclaimed scope with no owner -- grow these types, never fork them.
|
|
42
42
|
//
|
|
43
43
|
// This module has no handlers and no dispatch entries -- a later plan
|
|
44
44
|
// consumes emitCondition()'s output as the only thing a condition-set
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
// session, never touches a socket, never imports anything from the
|
|
47
47
|
// session/session-handler layer.
|
|
48
48
|
|
|
49
|
-
import { ViceError } from "./vice.ts";
|
|
49
|
+
import { ViceError } from "./vice-errors.ts";
|
|
50
50
|
|
|
51
51
|
// ---------------------------------------------------------------------------
|
|
52
52
|
// Errors
|
|
@@ -545,9 +545,9 @@ function parseSingleComparison(text: string, originalExpr: string): ConditionNod
|
|
|
545
545
|
* conditionFromJson() produces and returns it; it never emits text itself,
|
|
546
546
|
* so emitCondition() remains the only producer of wire text.
|
|
547
547
|
*
|
|
548
|
-
* Accepted input, deliberately narrow (
|
|
549
|
-
*
|
|
550
|
-
* expression parser):
|
|
548
|
+
* Accepted input, deliberately narrow (GAIN-06's plan to widen this grammar
|
|
549
|
+
* was cut along with Stock-Only Gains, 2026-08-17; widening it is unclaimed
|
|
550
|
+
* scope with no owner -- do not implement a general expression parser):
|
|
551
551
|
* - a single comparison, with or without surrounding parentheses:
|
|
552
552
|
* "A == $42", "(PC == $c000)", "SP <= $ff", "RL == $64"
|
|
553
553
|
* - a conjunction/disjunction where EVERY comparison is individually
|
package/stock-connect.ts
CHANGED
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
StockRequestTimeoutError,
|
|
43
43
|
} from "./stock-protocol.ts";
|
|
44
44
|
import { readCapabilityRecord, writeCapabilityRecord, type CapabilityDeps } from "./backend-detect.mts";
|
|
45
|
-
import { MachineRestartedError, ViceError, readEpoch, type EpochResult } from "./vice.ts";
|
|
45
|
+
import { MachineRestartedError, ViceError, readEpoch, type EpochResult } from "./vice-errors.ts";
|
|
46
46
|
import {
|
|
47
47
|
MonitorOwnershipError,
|
|
48
48
|
type ClaimMonitorOptions,
|
|
@@ -402,12 +402,14 @@ async function safeResume(client: ViceMonitorClient): Promise<void> {
|
|
|
402
402
|
* leave a frozen C64 behind either.
|
|
403
403
|
*/
|
|
404
404
|
export async function stockConnect({ host, port, targetId, brokerControl, deps = {} }: StockConnectOptions): Promise<StockConnectSession> {
|
|
405
|
-
|
|
405
|
+
// Plan 41-03 (D-14): explicit, not relying on claimMonitor()'s own default
|
|
406
|
+
// -- the binary path names its own channel at the call site.
|
|
407
|
+
const claimOutcome = await brokerControl.claimMonitor({ targetId, channel: "binary" });
|
|
406
408
|
if (!claimOutcome.ok) {
|
|
407
409
|
if (claimOutcome.reason === "monitor_owned") {
|
|
408
410
|
throw new MonitorOwnershipError(
|
|
409
411
|
`stockConnect: monitor for target ${targetId} on port ${port} is already claimed by grant ${claimOutcome.holder.grantId}`,
|
|
410
|
-
{ holderGrantId: claimOutcome.holder.grantId, holderClaimedAt: claimOutcome.holder.claimedAt, port },
|
|
412
|
+
{ holderGrantId: claimOutcome.holder.grantId, holderClaimedAt: claimOutcome.holder.claimedAt, port, channel: claimOutcome.holder.channel },
|
|
411
413
|
);
|
|
412
414
|
}
|
|
413
415
|
// "timeout" (the broker did not answer) is kept strictly distinct from
|
|
@@ -474,7 +476,9 @@ export async function stockConnect({ host, port, targetId, brokerControl, deps =
|
|
|
474
476
|
// reason. Both outcomes are now reported on stderr and neither can
|
|
475
477
|
// displace `err`.
|
|
476
478
|
try {
|
|
477
|
-
|
|
479
|
+
// Plan 41-03 (D-14): explicit "binary" -- never releases the "text"
|
|
480
|
+
// claim as a side effect of a failed binary handshake.
|
|
481
|
+
const released = await brokerControl.releaseMonitor({ targetId, channel: "binary" });
|
|
478
482
|
if (!released.ok) {
|
|
479
483
|
console.error(
|
|
480
484
|
`stockConnect: monitor release for target ${targetId} after a failed handshake was refused (${released.reason}) -- the instance may still be claimed`,
|
|
@@ -493,7 +497,7 @@ export async function stockConnect({ host, port, targetId, brokerControl, deps =
|
|
|
493
497
|
* stockConnect()'s own failure-path release above. */
|
|
494
498
|
export async function stockDisconnect(session: StockConnectSession): Promise<void> {
|
|
495
499
|
await safeDisconnect(session.client);
|
|
496
|
-
await session.brokerControl.releaseMonitor({ targetId: session.targetId });
|
|
500
|
+
await session.brokerControl.releaseMonitor({ targetId: session.targetId, channel: "binary" });
|
|
497
501
|
}
|
|
498
502
|
|
|
499
503
|
// ---------------------------------------------------------------------------
|
|
@@ -534,7 +538,7 @@ export async function stockReconnect(session: StockConnectSession, { lastToolCal
|
|
|
534
538
|
|
|
535
539
|
if (baselineEpoch === null || currentEpoch === null || currentEpoch !== baselineEpoch) {
|
|
536
540
|
throw new MachineRestartedError(
|
|
537
|
-
`
|
|
541
|
+
`stockReconnect: reconnect to target ${session.targetId} could not prove machine identity across the reconnect ` +
|
|
538
542
|
`(baseline epoch ${String(baselineEpoch)}, current epoch ${String(currentEpoch)})`,
|
|
539
543
|
{ baselineEpoch, currentEpoch, where: "stock-connect.ts:stockReconnect", lastToolCall },
|
|
540
544
|
);
|
package/stock-derived.ts
CHANGED
|
@@ -18,48 +18,32 @@
|
|
|
18
18
|
// hazard. There, NOT translating an emulator-side path is the bug -- four
|
|
19
19
|
// tools carry a filename stock VICE opens on the HOST, and stock-paths.ts's
|
|
20
20
|
// whole job is making sure that translation happens. HERE, translating a
|
|
21
|
-
// CLIENT-SIDE-DERIVED path is the bug:
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
// derived tool's handler is reached BEFORE `forwardToVice()` runs
|
|
27
|
-
// `rewriteArguments()` at all.
|
|
21
|
+
// CLIENT-SIDE-DERIVED path is the bug: a derived tool answers from data this
|
|
22
|
+
// proxy already holds, so handing its arguments through a HOST path
|
|
23
|
+
// translator meant for a forwarded call would act on a translated path
|
|
24
|
+
// INSIDE THE CONTAINER instead of the untranslated one the derived handler
|
|
25
|
+
// actually needs.
|
|
28
26
|
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
// CLAUDE.md's derived-tool constraint, so its citations are load-bearing. Line
|
|
42
|
-
// numbers in this file drift every phase; grep for the symbol instead.
|
|
43
|
-
//
|
|
44
|
-
// WHY THE HAZARD IS UNREACHABLE ON STOCK TODAY -- restated in terms of what
|
|
45
|
-
// actually enforces it (WR-12 again; the previous reason had gone stale):
|
|
46
|
-
// `buildBackendAwareTool()` routes EVERY stock tool call to
|
|
47
|
-
// `dispatchStock()`, so `forwardToVice()`, `handleRecycle()` and
|
|
48
|
-
// `gatherWedgeEvidence()` are reachable only on the fork arm. That is a
|
|
49
|
-
// structural property of the registration, not of any tool's name. The reason
|
|
50
|
-
// this header used to give -- "handleRecycle() is backend-aware and refused by
|
|
51
|
-
// name after CR-07, and vice_display_screenshot does not exist on stock until
|
|
52
|
-
// Phase 5" -- is now WRONG on its first clause: Phase 7 implemented
|
|
53
|
-
// `vice_recycle` on stock (`handleRecycleStock`) and registered it in
|
|
54
|
-
// STOCK_DERIVED_TOOLS below. The conclusion held; the stated reason did not,
|
|
55
|
-
// which is worse than no reason for a constraint a future reader will
|
|
56
|
-
// re-derive.
|
|
27
|
+
// WHY THE HAZARD IS UNREACHABLE ON STOCK TODAY: it no longer has anywhere to
|
|
28
|
+
// come FROM. The fork-only generic forwarding function and its own
|
|
29
|
+
// per-call argument path-rewriter, and the fork-only wedge-evidence
|
|
30
|
+
// gatherer that also ran that rewriter for `vice_display_screenshot`, are
|
|
31
|
+
// both deleted outright -- there is no remaining call site anywhere in this
|
|
32
|
+
// package that translates a host path before dispatch. Every stock tool
|
|
33
|
+
// call, derived or direct, reaches `dispatchStock()` in stock-dispatch.ts
|
|
34
|
+
// through exactly one registration seam in vice-proxy.ts, with no
|
|
35
|
+
// per-backend branch left to route around it. The hazard this file was
|
|
36
|
+
// built to close is now closed by construction, not merely by a runtime
|
|
37
|
+
// backend check: there is no path-translating function left for a derived
|
|
38
|
+
// tool's runner to be reached behind.
|
|
57
39
|
//
|
|
58
40
|
// WHAT NOT TO DO:
|
|
59
41
|
// - Never `import` hostpath.ts from this file, or from any module listed
|
|
60
42
|
// in STOCK_DERIVED_TOOLS' implementations -- hostpath-consumers.test.ts
|
|
61
43
|
// fails the build if you do.
|
|
62
|
-
// - Never `import` vice-proxy.ts, and never call
|
|
44
|
+
// - Never `import` vice-proxy.ts, and never re-introduce a per-call
|
|
45
|
+
// argument path-translator that a derived tool's runner could be
|
|
46
|
+
// reached behind.
|
|
63
47
|
// - Never add a client-side-derived tool to stock-paths.ts's
|
|
64
48
|
// STOCK_EMULATOR_SIDE_PATH_TOOLS -- that file's own header already warns
|
|
65
49
|
// against exactly this.
|
|
@@ -76,7 +60,7 @@
|
|
|
76
60
|
// withDerivedTool() refuses on this set, and a declared-but-unshipped
|
|
77
61
|
// module fails at module load in the published tarball rather than at
|
|
78
62
|
// dispatch.
|
|
79
|
-
import { ViceError, type ViceErrorOptions } from "./vice.ts";
|
|
63
|
+
import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
80
64
|
import type { StockToolResult } from "./stock-handler.ts";
|
|
81
65
|
import type { StockDispatchDeps } from "./stock-dispatch.ts";
|
|
82
66
|
|
|
@@ -114,6 +98,14 @@ export const STOCK_DERIVED_TOOLS: ReadonlySet<string> = new Set([
|
|
|
114
98
|
"vice_run_until", // Phase 7, TIME-02
|
|
115
99
|
"vice_diagnose", // Phase 7, TIME-04
|
|
116
100
|
"vice_recycle", // Phase 7, TIME-04
|
|
101
|
+
"vice_device_console", // Plan 41-06, CHAN-03 -- text-channel remedy tool, needsSession:false (text-tools.ts)
|
|
102
|
+
"vice_warp_set", // Plan 41-06, CHAN-03 -- text-channel remedy tool, needsSession:false (text-tools.ts)
|
|
103
|
+
"vice_memmap_show", // Plan 42-01, PARSE-01 -- text-channel access-map tool, needsSession:false (text-tools.ts)
|
|
104
|
+
"vice_memmap_zap", // Plan 43-03, EVID-05 -- text-channel access-map bracket-reset tool, needsSession:false (text-tools.ts)
|
|
105
|
+
"vice_cpu_history", // Plan 42-07, PARSE-02 -- text-channel CPU-history tool, needsSession:false (text-tools.ts)
|
|
106
|
+
"vice_profile_flat", // Plan 42-07, PARSE-02 -- text-channel flat-profile tool, needsSession:false (text-tools.ts)
|
|
107
|
+
"vice_backtrace", // Plan 42-07, PARSE-02/D-42-4 -- text-channel backtrace tool, shares the fork's own name, needsSession:false (text-tools.ts)
|
|
108
|
+
"vice_io_registers", // Plan 42-07, PARSE-02 -- text-channel register-decode tool, needsSession:false (text-tools.ts)
|
|
117
109
|
]);
|
|
118
110
|
|
|
119
111
|
/**
|