@henols/vice-mcp 0.2.3 → 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.
- package/anno-cli.ts +156 -158
- package/anno-confidence.ts +2 -2
- package/anno-derive.ts +6 -6
- package/anno-details.ts +4 -4
- package/anno-export-asm.ts +100 -101
- package/anno-graphics.ts +16 -16
- package/anno-hazard-report.ts +2 -2
- package/anno-import.ts +15 -15
- package/anno-index.ts +8 -8
- package/anno-join.ts +35 -35
- package/anno-memmap-render.ts +22 -21
- package/anno-provenance-ledger.ts +4 -4
- package/anno-regbits-gen.ts +13 -13
- package/anno-store-export.ts +11 -11
- package/anno-store.ts +139 -144
- package/anno-symbols.ts +7 -7
- package/anno-types.ts +55 -55
- package/package.json +1 -1
- package/resources/broker-control.mjs +85 -92
- package/resources/broker-epoch.mjs +6 -7
- package/resources/broker-kill.mjs +29 -30
- package/resources/broker-launch.mjs +352 -370
- package/resources/broker-state.mjs +9 -10
- package/resources/host-tool.mjs +636 -664
- package/resources/vice-broker.mjs +189 -191
- package/vice-broker-client.ts +98 -100
package/anno-memmap-render.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// anno-memmap-render.ts -- the ONE authoritative place in this repo that
|
|
3
3
|
// renders the human-readable Markdown memory map from this project's own
|
|
4
|
-
// annotation store
|
|
5
|
-
//
|
|
4
|
+
// annotation store plus a validated run-scoped provenance sidecar, using
|
|
5
|
+
// the reconciliation between those two sources this file implements.
|
|
6
6
|
//
|
|
7
|
-
// WHY THIS MODULE EXISTS
|
|
7
|
+
// WHY THIS MODULE EXISTS: the store is canonical; the Markdown memory
|
|
8
8
|
// map becomes a rendered VIEW. Criterion 1 says findings must be queryable
|
|
9
9
|
// "instead of re-deriving from Markdown prose" -- that is only true by
|
|
10
10
|
// construction if the prose is GENERATED from the queryable thing. Nothing
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
// `listRanges()`/`listLabels()`/`listComments()` readers, never from a
|
|
14
14
|
// human editing the output file directly.
|
|
15
15
|
//
|
|
16
|
-
// THE
|
|
16
|
+
// THE RECONCILIATION THIS FILE IMPLEMENTS, BETWEEN THE STORE AND THE
|
|
17
|
+
// RUN-SCOPED SIDECAR: run-scoped facts (the
|
|
17
18
|
// capture's SHA-256, `$01`, `$DD00`, the derived graphics chain, the video
|
|
18
19
|
// standard, the live vector pair, observed raster positions) are facts about
|
|
19
20
|
// a RUN, not about an address -- the store is address-keyed and has no shape
|
|
@@ -24,8 +25,8 @@
|
|
|
24
25
|
// `<placeholder>` for one.
|
|
25
26
|
//
|
|
26
27
|
// WHY THE LAYOUT IS EMBEDDED IN TYPESCRIPT RATHER THAN READ FROM A TEMPLATE
|
|
27
|
-
// FILE AT RUNTIME (the second decision this plan records):
|
|
28
|
-
// established that `.claude/mcp/vice/*.ts` exists as files on disk only
|
|
28
|
+
// FILE AT RUNTIME (the second decision this plan records): an earlier
|
|
29
|
+
// finding established that `.claude/mcp/vice/*.ts` exists as files on disk only
|
|
29
30
|
// under the Claude Code plugin route -- both npm-installer routes launch via
|
|
30
31
|
// `npx`. A renderer that resolved a template path into the skills tree at
|
|
31
32
|
// runtime would silently fail to resolve for an npm-installed user. The
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
// - drift detection (`checkRenderedMemoryMap()`) -- the one place a
|
|
42
43
|
// rendered file on disk is compared against what the store (plus the
|
|
43
44
|
// sidecar) would produce right now;
|
|
44
|
-
// - Markdown-cell escaping (`escapeMarkdownCell()
|
|
45
|
+
// - Markdown-cell escaping (`escapeMarkdownCell()`) --
|
|
45
46
|
// every store-derived text interpolation in the generated document
|
|
46
47
|
// (comment evidence, symbol names) is escaped through this one
|
|
47
48
|
// function, never a second ad hoc `.replace()` at a call site.
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
// - Never hand-edit the rendered output. The banner exists precisely so a
|
|
51
52
|
// human editor is caught by `checkRenderedMemoryMap()` -- see the
|
|
52
53
|
// `render_digest` comment below for exactly what it covers.
|
|
53
|
-
// - Never read the layout from the skills tree at runtime (
|
|
54
|
+
// - Never read the layout from the skills tree at runtime (see the module header for why).
|
|
54
55
|
// This module's own non-vacuity test asserts a zero-count grep for the
|
|
55
56
|
// recon skill's template filename -- if you are tempted to add a
|
|
56
57
|
// `readFileSync()` call reaching into `.claude/skills/`, don't; the
|
|
@@ -101,14 +102,14 @@ function errMsg(err: unknown): string {
|
|
|
101
102
|
* offset at which parsing stopped, as ` (at byte offset N)`, or `""` when the
|
|
102
103
|
* runtime did not name one.
|
|
103
104
|
*
|
|
104
|
-
* WHY THIS IS A DIGIT EXTRACTOR AND NOT A MESSAGE PASS-THROUGH
|
|
105
|
+
* WHY THIS IS A DIGIT EXTRACTOR AND NOT A MESSAGE PASS-THROUGH. V8's
|
|
105
106
|
* JSON `SyntaxError` embeds a SNIPPET OF THE INPUT in its own message --
|
|
106
107
|
* `Unexpected token 'Q', "QQZZORACLE"... is not valid JSON` -- so any code
|
|
107
108
|
* that forwards `err.message` from a JSON parse over caller-supplied bytes is
|
|
108
109
|
* a content-disclosure oracle. The capture group here is `(\d+)` and nothing
|
|
109
110
|
* else, so no byte of the parsed file can reach the returned string however
|
|
110
111
|
* the runtime words its message. Widening this regex to capture anything but
|
|
111
|
-
* digits reopens
|
|
112
|
+
* digits reopens the same content-disclosure risk.
|
|
112
113
|
*
|
|
113
114
|
* Returns `""` rather than guessing when no position is present (`Unexpected
|
|
114
115
|
* end of JSON input` carries none) -- an absent offset is reported by absence,
|
|
@@ -280,9 +281,9 @@ export function parseProvenanceHeader(json: unknown): ProvenanceHeader {
|
|
|
280
281
|
* distinguishable from drift under the same one.
|
|
281
282
|
*
|
|
282
283
|
* Version 2 (260821-a86) escaped Markdown table cells via
|
|
283
|
-
* `escapeMarkdownCell()
|
|
284
|
+
* `escapeMarkdownCell()`, an output-shape change.
|
|
284
285
|
*
|
|
285
|
-
* Version 3
|
|
286
|
+
* Version 3 is an INPUT change: `computeRenderDigest()` canonicalises
|
|
286
287
|
* this store's own `RangeRow`/`LabelRow`/`CommentRow` instead of the three
|
|
287
288
|
* wire shapes recorded above, so the same underlying annotations hash
|
|
288
289
|
* differently either side of it. Leaving the version at "2" across that
|
|
@@ -298,7 +299,7 @@ export const RENDERER_VERSION = "3";
|
|
|
298
299
|
* other leg), because comment `evidence` legitimately contains `|` and
|
|
299
300
|
* embedded newlines (`anno_set_comment`'s own schema documents multi-line
|
|
300
301
|
* support) -- refusing here would refuse valid data, not an attack. Closes
|
|
301
|
-
*
|
|
302
|
+
* this control's own render leg of T-11-NAME-INJECT: an unescaped `|` or newline in
|
|
302
303
|
* store text used to be able to inject an extra table cell or split a row
|
|
303
304
|
* across lines in the generated Markdown. A plain string or an empty string
|
|
304
305
|
* is returned unchanged. */
|
|
@@ -348,7 +349,7 @@ export interface RenderMemoryMapOptions {
|
|
|
348
349
|
* reaching an equally real `readFileSync`, carried nothing -- so a reader
|
|
349
350
|
* comparing the two would reasonably conclude the difference was
|
|
350
351
|
* deliberate. It was not: the CLI read this argument raw, making it an
|
|
351
|
-
* arbitrary-file read oracle
|
|
352
|
+
* arbitrary-file read oracle. An absent comment
|
|
352
353
|
* beside a present one is a claim, and this one was false. */
|
|
353
354
|
provenancePath: string;
|
|
354
355
|
/** The workspace root both confinement checks are taken against. REQUIRED
|
|
@@ -396,7 +397,7 @@ export async function renderMemoryMap(opts: RenderMemoryMapOptions): Promise<Ren
|
|
|
396
397
|
try {
|
|
397
398
|
sidecarJson = JSON.parse(sidecarBytes);
|
|
398
399
|
} catch (err) {
|
|
399
|
-
// NEVER INTERPOLATE THE UNDERLYING PARSE ERROR HERE
|
|
400
|
+
// NEVER INTERPOLATE THE UNDERLYING PARSE ERROR HERE. Node's
|
|
400
401
|
// SyntaxError quotes a snippet of the input it choked on -- e.g.
|
|
401
402
|
// `Unexpected token 'Q', "QQZZORACLE"... is not valid JSON` -- so passing
|
|
402
403
|
// it through turns a read refusal into a CONTENT-DISCLOSURE ORACLE. That
|
|
@@ -410,7 +411,7 @@ export async function renderMemoryMap(opts: RenderMemoryMapOptions): Promise<Ren
|
|
|
410
411
|
// where parsing stopped and not about what the file contains.
|
|
411
412
|
throw new Error(
|
|
412
413
|
`renderMemoryMap: provenance sidecar at "${provenancePath}" is not valid JSON${jsonParsePosition(err)}. ` +
|
|
413
|
-
"The underlying parser message is deliberately NOT included -- it quotes the file's own bytes
|
|
414
|
+
"The underlying parser message is deliberately NOT included -- it quotes the file's own bytes.",
|
|
414
415
|
);
|
|
415
416
|
}
|
|
416
417
|
const provenance = parseProvenanceHeader(sidecarJson);
|
|
@@ -460,7 +461,7 @@ export async function renderMemoryMap(opts: RenderMemoryMapOptions): Promise<Ren
|
|
|
460
461
|
// load-bearing detail rather than a formatting preference: every byte below
|
|
461
462
|
// is re-rendered and compared BYTE FOR BYTE by `checkRenderedMemoryMap()`,
|
|
462
463
|
// so an absolute path here would make the drift verdict a function of where
|
|
463
|
-
// the checkout sits
|
|
464
|
+
// the checkout sits. `workspaceRelativePath()` is the one definition
|
|
464
465
|
// of that spelling; it computes a location and refuses one that escapes the
|
|
465
466
|
// root. It is NOT a confinement check -- this module still performs no
|
|
466
467
|
// confinement of its own, exactly as `RenderMemoryMapOptions` documents.
|
|
@@ -587,13 +588,13 @@ export interface CheckRenderedMemoryMapOptions {
|
|
|
587
588
|
/** See `RenderMemoryMapOptions.provenancePath` -- same argument, one layer
|
|
588
589
|
* up. The CALLER (`anno-cli.ts`'s `cmdRenderMemmap()`) confines it through
|
|
589
590
|
* `storePathWithinWorkspace()`; this module performs no confinement of its
|
|
590
|
-
* own
|
|
591
|
+
* own. */
|
|
591
592
|
provenancePath: string;
|
|
592
593
|
/** The rendered file to compare against, read RAW by `readFileSync` below.
|
|
593
594
|
* The CALLER confines it through `storePathWithinWorkspace()` -- the SAME
|
|
594
595
|
* resolution that produces the write path on the non-`--check` branch, so
|
|
595
596
|
* the drift check and the write are one confined value rather than two
|
|
596
|
-
* rules. This module performs no confinement of its own
|
|
597
|
+
* rules. This module performs no confinement of its own. */
|
|
597
598
|
renderedPath: string;
|
|
598
599
|
/** See `RenderMemoryMapOptions.workspaceRoot`. */
|
|
599
600
|
workspaceRoot: string;
|
|
@@ -626,8 +627,8 @@ export type CheckRenderedMemoryMapResult =
|
|
|
626
627
|
* the workspace root;
|
|
627
628
|
* - a renderer change (output shape, or a `RENDERER_VERSION` bump).
|
|
628
629
|
*
|
|
629
|
-
* AND THE NEGATIVE, which is the defect this list was corrected for
|
|
630
|
-
*
|
|
630
|
+
* AND THE NEGATIVE, which is the defect this list was corrected for: relocating
|
|
631
|
+
* the checkout -- the same tree at a
|
|
631
632
|
* different absolute path -- does NOT drift. The banner records
|
|
632
633
|
* workspace-relative locations, so no compared byte is a function of where the
|
|
633
634
|
* checkout sits. Before that fix this returned `drifted` for a byte-identical
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// anno-provenance-ledger.ts -- the ONE place `recovery/PROVENANCE.md`'s
|
|
2
|
-
// generated tier is turned back into typed rows
|
|
2
|
+
// generated tier is turned back into typed rows.
|
|
3
3
|
//
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
5
|
// WHY THIS FILE EXISTS
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
7
7
|
// Nothing in this repository has ever READ the provenance ledger. It has one
|
|
8
8
|
// writer -- `renderLedger()` in `src/skills/c64-provenance-diff/scripts/
|
|
9
|
-
// diff-images.mjs` -- and zero readers, because
|
|
10
|
-
// the verdict be READ from the existing ledger, "never
|
|
11
|
-
//
|
|
9
|
+
// diff-images.mjs` -- and zero readers, because the requirement governing this
|
|
10
|
+
// module requires the verdict be READ from the existing ledger, "never
|
|
11
|
+
// re-derived". Recomputing it in-process would force the
|
|
12
12
|
// exporter to import a registry-resolution path it has no other reason to
|
|
13
13
|
// know about, and would make "ledger absent" ambiguous between three
|
|
14
14
|
// different missing things. This module exists so "read" has an implementation
|
package/anno-regbits-gen.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// anno-regbits-gen.ts -- the ONE authoritative place in this repo that turns
|
|
3
3
|
// c64-memory-mapping's memmap.json into the curated address->bit-name table
|
|
4
|
-
// anno-enum-gen.ts decodes register values against
|
|
4
|
+
// anno-enum-gen.ts decodes register values against.
|
|
5
5
|
//
|
|
6
|
-
// WHY THIS EXISTS
|
|
6
|
+
// WHY THIS EXISTS: neither register the phase's own pinned criterion-3
|
|
7
7
|
// target needs ($D011) nor the registers a real game writes to constantly
|
|
8
8
|
// ($D015/$D017/$D01A-$D01D) can be named from memmap.json's own `bits` prose
|
|
9
9
|
// alone -- some of that prose is OCR-damaged ("O = Blank" uses a letter O for
|
|
@@ -54,11 +54,11 @@ const HERE = dirname(fileURLToPath(import.meta.url));
|
|
|
54
54
|
|
|
55
55
|
/** The sole read of c64-memory-mapping's own memmap.json -- this generator is
|
|
56
56
|
* its only consumer for this purpose (per this plan's key_links entry).
|
|
57
|
-
* 2026-08-22
|
|
57
|
+
* 2026-08-22: the skills tree moved from `.claude/skills/`
|
|
58
58
|
* (two levels up from `.claude/mcp/vice`) to `src/skills/` (three levels up,
|
|
59
59
|
* since `src/` sits directly under the repo root rather than under `.claude/`).
|
|
60
|
-
* This literal was not in
|
|
61
|
-
* test
|
|
60
|
+
* This literal was not in the original enumerated consumer list, and a
|
|
61
|
+
* test failure caught the gap live. */
|
|
62
62
|
const MEMMAP_PATH = join(HERE, "..", "..", "..", "src", "skills", "c64-memory-mapping", "memmap.json");
|
|
63
63
|
|
|
64
64
|
/** Where the generated, committed artifact lives -- always a sibling of this
|
|
@@ -163,14 +163,14 @@ export interface RegbitsRegisterOverride {
|
|
|
163
163
|
* entries by their `bit` string. */
|
|
164
164
|
fields?: readonly RegbitsFieldOverride[];
|
|
165
165
|
/** A COMPLETE field list for an address memmap.json's `io` parser produced
|
|
166
|
-
* no `bits` entry for at all
|
|
166
|
+
* no `bits` entry for at all -- used only when no
|
|
167
167
|
* memmap entry exists for this address, never to replace one that does. */
|
|
168
168
|
synthetic?: readonly RegBitsField[];
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/** Builds the 8 independent "bit N = sprite N" flag fields the five VIC
|
|
172
172
|
* sprite-plane registers ($D015/$D017/$D01B/$D01C/$D01D) all share the same
|
|
173
|
-
* shape for
|
|
173
|
+
* shape for -- each bit is silent (empty token) when
|
|
174
174
|
* clear and names the specific sprite when set, so a typical enum (most
|
|
175
175
|
* sprites off, one or two on) renders as a short, readable name instead of
|
|
176
176
|
* naming all eight sprites' negative state every time.
|
|
@@ -236,15 +236,15 @@ export const OVERRIDES: readonly RegbitsRegisterOverride[] = [
|
|
|
236
236
|
label: "CIA Interrupt Control Register (Read NMIs/Write Mask)",
|
|
237
237
|
},
|
|
238
238
|
{
|
|
239
|
-
// WHY: memmap.json's `io` parser produced no `bits` entry at all for this address
|
|
240
|
-
//
|
|
239
|
+
// WHY: memmap.json's `io` parser produced no `bits` entry at all for this address,
|
|
240
|
+
// even though a real game writes to it constantly -- sprite enable, one flag bit
|
|
241
241
|
// per sprite, is trivially regular and does not need memmap's own prose to describe correctly.
|
|
242
242
|
address: 53269, // $D015 -- Sprite Enable
|
|
243
243
|
label: "Sprite Enable",
|
|
244
244
|
synthetic: spriteBitFields("EN"),
|
|
245
245
|
},
|
|
246
246
|
{
|
|
247
|
-
// WHY: same
|
|
247
|
+
// WHY: same missing-`bits`-entry gap as $D015 -- Sprite Y-Expand, one flag bit per sprite.
|
|
248
248
|
address: 53271, // $D017 -- Sprite Y-Expand
|
|
249
249
|
label: "Sprite Y-Expand",
|
|
250
250
|
synthetic: spriteBitFields("YEXP"),
|
|
@@ -264,20 +264,20 @@ export const OVERRIDES: readonly RegbitsRegisterOverride[] = [
|
|
|
264
264
|
],
|
|
265
265
|
},
|
|
266
266
|
{
|
|
267
|
-
// WHY: same
|
|
267
|
+
// WHY: same missing-`bits`-entry gap as $D015 -- Sprite Priority (behind/in-front of background), one flag bit
|
|
268
268
|
// per sprite.
|
|
269
269
|
address: 53275, // $D01B -- Sprite Data Priority
|
|
270
270
|
label: "Sprite Data Priority",
|
|
271
271
|
synthetic: spriteBitFields("BG"),
|
|
272
272
|
},
|
|
273
273
|
{
|
|
274
|
-
// WHY: same
|
|
274
|
+
// WHY: same missing-`bits`-entry gap as $D015 -- Sprite Multicolor, one flag bit per sprite.
|
|
275
275
|
address: 53276, // $D01C -- Sprite Multicolor
|
|
276
276
|
label: "Sprite Multicolor",
|
|
277
277
|
synthetic: spriteBitFields("MC"),
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
|
-
// WHY: same
|
|
280
|
+
// WHY: same missing-`bits`-entry gap as $D015 -- Sprite X-Expand, one flag bit per sprite.
|
|
281
281
|
address: 53277, // $D01D -- Sprite X-Expand
|
|
282
282
|
label: "Sprite X-Expand",
|
|
283
283
|
synthetic: spriteBitFields("XEXP"),
|
package/anno-store-export.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// anno-store-export.ts
|
|
3
3
|
//
|
|
4
|
-
//
|
|
4
|
+
// The general JSON export/import module for a
|
|
5
5
|
// per-fixture `.annostore` -- NOT Ghidra-shaped (that is `anno-import.ts`'s
|
|
6
6
|
// job, and it writes cross-references only). No general store-JSON round
|
|
7
7
|
// trip exists anywhere else in this tree today (RESEARCH.md Section 5,
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
//
|
|
17
17
|
// WHAT THIS IS THE ONE AUTHORITATIVE PLACE FOR:
|
|
18
18
|
// - The JSON schema for a full store export: typed ranges, labels,
|
|
19
|
-
// comments (tagged `provenance: "derived" | "authored"`
|
|
19
|
+
// comments (tagged `provenance: "derived" | "authored"`),
|
|
20
20
|
// project enums and their usage bindings, cross-references, and
|
|
21
21
|
// runtime-execution-observation rows.
|
|
22
22
|
// - The three decline/provenance comment-text conventions
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// successfully (`anno-import.ts`'s own rule, copied deliberately: a
|
|
34
34
|
// partial import must never leave the store in a state that is neither
|
|
35
35
|
// the old nor the new content).
|
|
36
|
-
// - Never collapse the derived/authored provenance tag
|
|
36
|
+
// - Never collapse the derived/authored provenance tag -- the
|
|
37
37
|
// export schema exists specifically so a diff shows an authored
|
|
38
38
|
// purpose-comment change, which a binary `.annostore` cannot.
|
|
39
39
|
// - Never resolve a workspace path here -- the caller does, through
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
// - Never persist `provenance` as a real store column. It is NOT one:
|
|
42
42
|
// `RangeRow`/`CommentRow` (`anno-types.ts`) carry no such field, and
|
|
43
43
|
// `setDataType()`/`setComment()` accept no such argument. Ranges are
|
|
44
|
-
// ALWAYS the derived half (
|
|
44
|
+
// ALWAYS the derived half ("block types ... regenerate
|
|
45
45
|
// deterministically from the bytes") -- there is no per-row fact in the
|
|
46
46
|
// schema that could ever make one authored instead, so `"derived"` is a
|
|
47
47
|
// constant for every exported range, not a per-row classification.
|
|
48
|
-
// Comments are ALWAYS the authored half (
|
|
48
|
+
// Comments are ALWAYS the authored half (confirmed again by
|
|
49
49
|
// RESEARCH.md Section 5: "labels/comments/(and ... decline-comments) are
|
|
50
50
|
// the authored half") -- `provenanceForComment()` is written as a
|
|
51
51
|
// function of the comment's own text (rather than a bare constant) only
|
|
@@ -123,7 +123,7 @@ import type { DataType, CommentType, LabelKind, XrefAccessKind, EvidSourceBank }
|
|
|
123
123
|
* standing decline-by-name pattern), never best-effort imported. */
|
|
124
124
|
export const STORE_EXPORT_SCHEMA_VERSION = 1;
|
|
125
125
|
|
|
126
|
-
/** The two provenance classes
|
|
126
|
+
/** The two provenance classes the store is split into (derived vs authored). See this file's
|
|
127
127
|
* own header for why this is never a real store column. */
|
|
128
128
|
export type RowProvenance = "derived" | "authored";
|
|
129
129
|
|
|
@@ -137,7 +137,7 @@ export const DECLINE_COMMENT_PREFIX = "DECLINED:";
|
|
|
137
137
|
* reviewed and chose to accept rather than reclassify. */
|
|
138
138
|
export const DISAGREEMENT_ACCEPTED_COMMENT_PREFIX = "DISAGREEMENT-ACCEPTED:";
|
|
139
139
|
|
|
140
|
-
/**
|
|
140
|
+
/** The per-range authored marker: an explicit statement that a range's
|
|
141
141
|
* typing rests on authored judgement rather than derivation or runtime
|
|
142
142
|
* observation. */
|
|
143
143
|
export const AUTHORED_PROVENANCE_COMMENT_PREFIX = "PROVENANCE: authored";
|
|
@@ -227,7 +227,7 @@ export interface StoreExportXrefRow {
|
|
|
227
227
|
* and no `provenance`: `ScopeRow` (`anno-types.ts`) is a bare `{id, start,
|
|
228
228
|
* endInclusive}` -- a lexical region, not a memory view, and not itself
|
|
229
229
|
* derived from or authored over bytes the way a range or a comment is. Added
|
|
230
|
-
* for the multi-file export path
|
|
230
|
+
* for the multi-file export path: `exportAsmTree()` reads scopes
|
|
231
231
|
* straight off an open store handle via `listScopes()`, never from this
|
|
232
232
|
* document, so a scope this generic export omitted would silently vanish the
|
|
233
233
|
* moment a committed export got re-imported into a fresh store ahead of that
|
|
@@ -314,7 +314,7 @@ function assertRowProvenance(value: unknown, what: string): RowProvenance {
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
/**
|
|
317
|
-
*
|
|
317
|
+
* This fix: `bank` is exported faithfully by `exportStoreDocument()`
|
|
318
318
|
* for every row kind (`StoreExportRangeRow.bank`, `StoreExportLabelRow.bank`,
|
|
319
319
|
* `StoreExportCommentRow.bank`, `StoreExportEnumUsageRow.bank`,
|
|
320
320
|
* `StoreExportXrefRow.bank`), but no write call on `anno-store.ts`'s current
|
|
@@ -322,8 +322,8 @@ function assertRowProvenance(value: unknown, what: string): RowProvenance {
|
|
|
322
322
|
* accepts a `bank` argument -- every fresh insert hard-codes `bank: null`
|
|
323
323
|
* (`anno-store.ts:1890`). Threading a real value through five write calls with
|
|
324
324
|
* no bank-carrying writer anywhere in the codebase to prove it against would be
|
|
325
|
-
* exactly the kind of speculative widening this project's other modules refuse
|
|
326
|
-
*
|
|
325
|
+
* exactly the kind of speculative widening this project's other modules refuse.
|
|
326
|
+
* Refusing a non-null
|
|
327
327
|
* `bank` BY NAME instead -- this project's standing "refuse by name, never
|
|
328
328
|
* silently drop" convention (`enumUsage[i]` naming an undefined enum, above, is
|
|
329
329
|
* the same shape) -- means the moment a real writer starts producing a
|