@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-symbols.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// anno-symbols.ts -- the ONE authoritative place in this repo for the
|
|
3
3
|
// PRE-SPAWN half of the symbol round trip between an annotation store and
|
|
4
|
-
// stock VICE's symbol table (
|
|
4
|
+
// stock VICE's symbol table (ARCHITECTURE.md Rule A20).
|
|
5
5
|
//
|
|
6
|
-
// WHAT LEFT, WHAT STAYED, AND WHERE THE ROUTE RETURNS (
|
|
7
|
-
//
|
|
6
|
+
// WHAT LEFT, WHAT STAYED, AND WHERE THE ROUTE RETURNS (2026-08-30). Read this
|
|
7
|
+
// paragraph before looking for a function that is not
|
|
8
8
|
// here.
|
|
9
9
|
//
|
|
10
10
|
// WHAT LEFT: the ROUTE. `exportLabels()`, `importLabels()` and
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
// criterion of it mentioned `export-lbl` or `import-lbl`. So the forecast
|
|
47
47
|
// was wrong, and it is CORRECTED here rather than deleted, because deleting
|
|
48
48
|
// a withdrawal notice erases the record that a capability went missing and
|
|
49
|
-
// why.
|
|
49
|
+
// why. This project's own capability record carries the dated notice and
|
|
50
50
|
// says the same thing: this is a temporary loss of a capability that was
|
|
51
51
|
// genuinely Validated, not a completed one being tidied away. The
|
|
52
52
|
// demonstration was made end to end against genuine unpatched stock `x64sc`
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
//
|
|
68
68
|
// MEASURED FACTS, PAST TENSE, kept because they are the reasons for the
|
|
69
69
|
// discipline above rather than instructions to anyone:
|
|
70
|
-
// - `--export_lbl` exported USER labels only. Measured (
|
|
70
|
+
// - `--export_lbl` exported USER labels only. Measured (and
|
|
71
71
|
// re-confirmed by the round-trip test that was deleted with its subject):
|
|
72
72
|
// an annotated project emitted exactly the labels a caller had set, and
|
|
73
73
|
// the auto-generated `a_D011` / `a_D020` / `e_FFD2` externals were NOT
|
|
@@ -168,7 +168,7 @@ export interface ImportLabelsUnverified {
|
|
|
168
168
|
* read `result.importedNames` and mistake "the import call returned no error"
|
|
169
169
|
* for "the names are actually on disk".
|
|
170
170
|
*
|
|
171
|
-
* KEPT ACROSS THE CUT
|
|
171
|
+
* KEPT ACROSS THE CUT. The route that produced it is gone; the
|
|
172
172
|
* distinction it encodes is the whole lesson of the `--import_lbl` discard
|
|
173
173
|
* measured in this module's header. Because no phase currently owns rebuilding
|
|
174
174
|
* that route, this type is its only surviving contract; whenever a route IS
|
|
@@ -194,7 +194,7 @@ export interface ValidatedLabelFile {
|
|
|
194
194
|
/**
|
|
195
195
|
* THE PRE-SPAWN GATE (T-11-LBL-SIZE + T-11-NAME-INJECT, both closed) -- the
|
|
196
196
|
* half of the deleted `importLabels()` that never touched a child process,
|
|
197
|
-
* lifted out unchanged when the route around it was removed
|
|
197
|
+
* lifted out unchanged when the route around it was removed.
|
|
198
198
|
*
|
|
199
199
|
* In order, and the order matters:
|
|
200
200
|
* 1. A byte-size check against `stock-symbols.ts`'s own
|
package/anno-types.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
// The ONE place that writes down the annotation store's data-type vocabulary,
|
|
5
5
|
// its range row shape, and every validator the store runs before a caller's
|
|
6
|
-
// argument is allowed anywhere near SQL
|
|
6
|
+
// argument is allowed anywhere near SQL.
|
|
7
7
|
//
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
// WHY THIS FILE EXISTS
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
// path lands outside the root once symbolic links are followed, and that
|
|
59
59
|
// is a filesystem question that no string comparison can answer -- the
|
|
60
60
|
// earlier pure-string version accepted a symlinked subdirectory and let a
|
|
61
|
-
// store file be created outside the workspace root
|
|
62
|
-
//
|
|
61
|
+
// store file be created outside the workspace root, confirmed by a live
|
|
62
|
+
// symlink reproduction. Every OTHER export is still
|
|
63
63
|
// a pure function of its arguments and still unit-testable with no file
|
|
64
64
|
// on disk. The exception is named here, in `storePathWithinWorkspace`'s
|
|
65
65
|
// own doc comment, and in `anno-types.test.ts`'s mutable-state assertion
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
// `parseStoreAddress()` takes an integer, a `$hex` string and a
|
|
69
69
|
// `0x`/`0X` string, and refuses `"1024"`. This is a REAL, user-visible
|
|
70
70
|
// divergence from `stock-address.ts:155-160`, which accepts the bare
|
|
71
|
-
// decimal form AS DECIMAL
|
|
71
|
+
// decimal form AS DECIMAL and says so at
|
|
72
72
|
// `:89-105`. The reason the store diverges: a mis-based address written
|
|
73
73
|
// into the store is PERSISTENT and silently wrong -- every later reader
|
|
74
74
|
// inherits it -- whereas a mis-based memory read is transient and the
|
|
@@ -92,19 +92,21 @@
|
|
|
92
92
|
// sanitized or quoted."
|
|
93
93
|
// 8. NEVER restate the eleven auto-generated-name prefixes here. They live in
|
|
94
94
|
// exactly one place, `anno-coverage.ts`'s `AUTO_NAME_PREFIX_RE`, and
|
|
95
|
-
//
|
|
96
|
-
// five-prefix copy silently under-counts, which breaks the
|
|
95
|
+
// a short reimplementation causes the exact failure this project has
|
|
96
|
+
// already measured: a five-prefix copy silently under-counts, which breaks the
|
|
97
97
|
// `routine-queue-walker` skill's backlog construction while every test
|
|
98
98
|
// keeps passing. The store separates the two namespaces with its label
|
|
99
99
|
// `kind` field, not with a name pattern.
|
|
100
100
|
// 9. NEVER build a mnemonic-to-access-kind classifier here. Nothing derivable
|
|
101
101
|
// is stored (see `anno-store.ts`'s `putXref`), `OpcodeEntry` carries no
|
|
102
|
-
// access/reads/writes field at all, and
|
|
103
|
-
//
|
|
102
|
+
// access/reads/writes field at all, and analysis built on such a field is
|
|
103
|
+
// deliberately deferred until a named future consumer exists: the field
|
|
104
|
+
// is stored because it is free now and unrecoverable later, but no
|
|
105
|
+
// shipped caller reads it yet. A
|
|
104
106
|
// classifier written now would have no caller and no way to be wrong
|
|
105
107
|
// observably.
|
|
106
|
-
// 10. NEVER measure comment length in code units. `String.length` counts
|
|
107
|
-
// code units, so a multi-byte comment passes a code-unit check and then
|
|
108
|
+
// 10. NEVER measure comment length in code units. `String.length` counts
|
|
109
|
+
// 16-bit code units, so a multi-byte comment passes a code-unit check and then
|
|
108
110
|
// exceeds the byte bound on disk. `assertCommentText()` measures with a
|
|
109
111
|
// `TextEncoder`.
|
|
110
112
|
import { existsSync, lstatSync, readlinkSync, realpathSync } from "node:fs";
|
|
@@ -133,26 +135,26 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
133
135
|
*
|
|
134
136
|
* * TWO STORES IN ONE DIRECTORY SHARED ONE RING under the same
|
|
135
137
|
* `r<revision>.db` filenames, so `revertTo` on one store restored the
|
|
136
|
-
* OTHER store's whole database, silently and with no error
|
|
138
|
+
* OTHER store's whole database, silently and with no error.
|
|
137
139
|
* * RENAMING THE CONTAINING DIRECTORY invalidated every persisted absolute
|
|
138
140
|
* path at once, after which `retainedRevisions()` reported none and the
|
|
139
|
-
* next accepted write's prune destroyed the entire revert history
|
|
141
|
+
* next accepted write's prune destroyed the entire revert history.
|
|
140
142
|
*
|
|
141
143
|
* Version 2 drops `anno_snapshot.path` -- there is no persisted string left for
|
|
142
144
|
* a second namespace to disagree with -- and derives the location from the
|
|
143
145
|
* handle at every read and every delete via `snapshotDirFor()`.
|
|
144
146
|
*
|
|
145
147
|
* A VERSION-1 STORE IS REFUSED, NOT UPGRADED, and the reason is that the
|
|
146
|
-
* version-1 ring's OWNERSHIP is not recoverable:
|
|
148
|
+
* version-1 ring's OWNERSHIP is not recoverable: two stores may
|
|
147
149
|
* both have written into `<dir>/snapshots`, and nothing recorded which file
|
|
148
150
|
* belonged to which store. Any migration would have to guess, attributing one
|
|
149
|
-
* store's history to another --
|
|
150
|
-
* watching. The legacy directory is therefore left on disk untouched: never
|
|
151
|
+
* store's history to another -- the same failure shape recurring with a new
|
|
152
|
+
* cause and no test watching. The legacy directory is therefore left on disk untouched: never
|
|
151
153
|
* adopted, never migrated, never deleted, so the bytes stay recoverable by
|
|
152
154
|
* hand.
|
|
153
155
|
*
|
|
154
156
|
* ---------------------------------------------------------------------------
|
|
155
|
-
* VERSION 3, 2026-08-29
|
|
157
|
+
* VERSION 3, 2026-08-29 -- AND THE COST IS NAMED HERE RATHER THAN LEFT
|
|
156
158
|
* IN A PLANNING DIRECTORY, because a version number whose rationale lives
|
|
157
159
|
* somewhere else is a number the next reader has no way to weigh.
|
|
158
160
|
*
|
|
@@ -184,7 +186,7 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
184
186
|
* impossibility.
|
|
185
187
|
*
|
|
186
188
|
* ---------------------------------------------------------------------------
|
|
187
|
-
* VERSION 4, 2026-09-10
|
|
189
|
+
* VERSION 4, 2026-09-10 -- THE DECISION IS `reaffirm-refusal`, AND
|
|
188
190
|
* THE FACTUAL BASIS IS TRANSCRIBED HERE RATHER THAN LEFT IN A PLANNING
|
|
189
191
|
* DIRECTORY, for the same reason VERSION 3's paragraph gives.
|
|
190
192
|
*
|
|
@@ -205,7 +207,7 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
205
207
|
* 1. `find / -xdev -name '*.annostore'`, with `.git` directories excluded --
|
|
206
208
|
* empty. The broader `find "$HOME" -name '*.annostore'` (closing the `-xdev`
|
|
207
209
|
* mount-boundary gap) found five hits, all inside a dated (2026-08-27)
|
|
208
|
-
* scratch probe cache
|
|
210
|
+
* scratch probe cache directory, with
|
|
209
211
|
* fixture-pattern names (`t-half`, `t-zero`, `t-tail-100`, `p`, `proj`)
|
|
210
212
|
* and one file zero bytes -- synthetic test fixtures, not a real
|
|
211
213
|
* project's store.
|
|
@@ -259,7 +261,7 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
259
261
|
* refusal stays the default.
|
|
260
262
|
*
|
|
261
263
|
* ---------------------------------------------------------------------------
|
|
262
|
-
* VERSION 5, 2026-09-11
|
|
264
|
+
* VERSION 5, 2026-09-11 -- THE DECISION IS `reaffirm-refusal`, THE
|
|
263
265
|
* SAME OPTION VERSION 4 SELECTED, AND THE FACTUAL BASIS IS TRANSCRIBED HERE
|
|
264
266
|
* RATHER THAN LEFT IN A PLANNING DIRECTORY, for the same reason every prior
|
|
265
267
|
* version's paragraph gives.
|
|
@@ -267,7 +269,7 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
267
269
|
* WHAT THE BUMP BUYS: `anno_excluded_range`, the durable record of a
|
|
268
270
|
* user-requested exclusion -- its extent AND the reason the user gave -- so
|
|
269
271
|
* the export can emit the range's real bytes tagged with a visible marker
|
|
270
|
-
* comment instead of a hole, which is
|
|
272
|
+
* comment instead of a hole, which is this feature's whole invariant: an
|
|
271
273
|
* exclusion is a RECORDED, VISIBLE fact, never a silent drop. See
|
|
272
274
|
* `anno-store.ts`'s `DDL` and its three verbs, `addExcludedRange` /
|
|
273
275
|
* `listExcludedRanges` / `removeExcludedRange`.
|
|
@@ -289,7 +291,7 @@ import { ViceError, type ViceErrorOptions } from "./vice-errors.ts";
|
|
|
289
291
|
* NEW since VERSION 4's check: `.c64-re-tools/phase45-scratch/
|
|
290
292
|
* tracer.annostore`, inside THIS repository's own gitignored scratch
|
|
291
293
|
* directory, timestamped 2026-09-10 -- its path and name identify it as
|
|
292
|
-
*
|
|
294
|
+
* this project's own tracer/scratch fixture, not a real consuming project's
|
|
293
295
|
* store. Six real files, zero real stores.
|
|
294
296
|
* 2. `git log --oneline --diff-filter=A -- '*.annostore'` -- still empty.
|
|
295
297
|
* No `.annostore` has ever been added to this repository's tracked
|
|
@@ -343,8 +345,7 @@ export const ADDRESS_MAX = 0xffff;
|
|
|
343
345
|
* (`anno-store.ts`'s `snapshotDirFor()` -- a sibling named after the store
|
|
344
346
|
* FILE, not the fixed `<dir>/snapshots` version 1 used) may hold before the
|
|
345
347
|
* oldest is pruned. Declared here because the bound is a property of the
|
|
346
|
-
* store's format; the pruning that enforces it belongs to the revert surface
|
|
347
|
-
* (`STORE-04`). */
|
|
348
|
+
* store's format; the pruning that enforces it belongs to the revert surface. */
|
|
348
349
|
export const MAX_SNAPSHOT_REVISIONS = 32;
|
|
349
350
|
|
|
350
351
|
/**
|
|
@@ -451,7 +452,8 @@ export type LabelKind = (typeof LABEL_KINDS)[number];
|
|
|
451
452
|
* is written down, and its provenance needs stating precisely so a later reader
|
|
452
453
|
* does not over-trust it: these four spellings are CITED from an external
|
|
453
454
|
* analyser's reference documentation, flowed through this project's own research
|
|
454
|
-
* notes, and fixed by
|
|
455
|
+
* notes, and fixed by this project's own requirement that cross-reference rows
|
|
456
|
+
* carry their access kind. They are NOT read from any
|
|
455
457
|
* code in this repository, and no comment may present them as verified project
|
|
456
458
|
* vocabulary.
|
|
457
459
|
*
|
|
@@ -520,7 +522,7 @@ export interface CommentRow {
|
|
|
520
522
|
}
|
|
521
523
|
|
|
522
524
|
/**
|
|
523
|
-
* One stored comment that a retype has just made FALSE
|
|
525
|
+
* One stored comment that a retype has just made FALSE.
|
|
524
526
|
*
|
|
525
527
|
* The caller needs all four facts to act on the report without a second query:
|
|
526
528
|
* WHERE the comment is, WHAT it says, WHICH grade fired, and WHICH data type
|
|
@@ -539,7 +541,7 @@ export interface ContradictedComment {
|
|
|
539
541
|
}
|
|
540
542
|
|
|
541
543
|
/**
|
|
542
|
-
* One entry-address pairing of a split table
|
|
544
|
+
* One entry-address pairing of a split table.
|
|
543
545
|
*
|
|
544
546
|
* `pairs[i]` is the two ADDRESSES whose bytes form entry `i`, in table order:
|
|
545
547
|
* the first-half address and its second-half partner. `entryCount` is
|
|
@@ -552,8 +554,8 @@ export interface SplitEntryPairs {
|
|
|
552
554
|
}
|
|
553
555
|
|
|
554
556
|
/**
|
|
555
|
-
* One surviving fragment of a split table that a partial overwrite left behind
|
|
556
|
-
*
|
|
557
|
+
* One surviving fragment of a split table that a partial overwrite left behind.
|
|
558
|
+
* `entryPairs` is what that fragment reads NOW -- not what the addresses
|
|
557
559
|
* in it used to be paired with.
|
|
558
560
|
*/
|
|
559
561
|
export interface SplitTableSurvivor {
|
|
@@ -565,7 +567,7 @@ export interface SplitTableSurvivor {
|
|
|
565
567
|
|
|
566
568
|
/**
|
|
567
569
|
* What one accepted partial overwrite of a split table COST, reported as data on
|
|
568
|
-
* a successful `setDataType()` result
|
|
570
|
+
* a successful `setDataType()` result. Documented in the same
|
|
569
571
|
* register as `ContradictedComment` above, and for the same reason: a caller
|
|
570
572
|
* needs every fact it would otherwise have to re-query for.
|
|
571
573
|
*
|
|
@@ -615,14 +617,14 @@ export interface ScopeRow {
|
|
|
615
617
|
}
|
|
616
618
|
|
|
617
619
|
/** One user-requested exclusion as the store holds it, added at
|
|
618
|
-
* `SCHEMA_VERSION` 5
|
|
620
|
+
* `SCHEMA_VERSION` 5. Both ends are INCLUSIVE, matching every
|
|
619
621
|
* other range-shaped row this store persists. There is no `bank` column,
|
|
620
622
|
* because an exclusion is a statement about a span of the SUBJECT PROGRAM the
|
|
621
623
|
* user asked to leave out of the rebuild -- not a memory view -- and there is
|
|
622
624
|
* no confidence, verdict, grade or severity column, because this row holds
|
|
623
625
|
* WHAT THE USER ASKED FOR and nothing the tool concluded about it. A
|
|
624
626
|
* judgement column here would be the exact "tool is the decider" shape
|
|
625
|
-
*
|
|
627
|
+
* this project's own 2026-09-10 requirement rewording removed: the store answers "what did the
|
|
626
628
|
* user record", never "should this range be excluded". */
|
|
627
629
|
export interface ExcludedRangeRow {
|
|
628
630
|
id: number;
|
|
@@ -643,7 +645,7 @@ export interface ProjectEnumRow {
|
|
|
643
645
|
|
|
644
646
|
/**
|
|
645
647
|
* One enum usage as the store holds it: the association between ONE address
|
|
646
|
-
* and ONE project enum, added at `SCHEMA_VERSION` 3
|
|
648
|
+
* and ONE project enum, added at `SCHEMA_VERSION` 3.
|
|
647
649
|
*
|
|
648
650
|
* `enumId` IS WHAT THE STORE PERSISTS; `enumName` is resolved through the join
|
|
649
651
|
* at read time and is never a second on-disk copy of the name. A row that
|
|
@@ -674,7 +676,7 @@ export interface XrefRow {
|
|
|
674
676
|
|
|
675
677
|
/**
|
|
676
678
|
* The three memory regions `memmapshow` reports an execute observation
|
|
677
|
-
* against, `SCHEMA_VERSION` 4
|
|
679
|
+
* against, `SCHEMA_VERSION` 4. This is the ONE place this
|
|
678
680
|
* vocabulary is written down.
|
|
679
681
|
*
|
|
680
682
|
* ALL THREE ARE INCLUDED DELIBERATELY, not for symmetry: `AccessFlags`
|
|
@@ -690,7 +692,7 @@ export type EvidSourceBank = (typeof EVID_SOURCE_BANKS)[number];
|
|
|
690
692
|
|
|
691
693
|
/**
|
|
692
694
|
* The runtime evidence layer's own classification of an address, `SCHEMA_VERSION`
|
|
693
|
-
* 4
|
|
695
|
+
* 4. This is a TYPE-LEVEL control, not a runtime check: the union has
|
|
694
696
|
* exactly two members and NO `"data"` member exists for a caller to return,
|
|
695
697
|
* mistakenly or otherwise.
|
|
696
698
|
*
|
|
@@ -713,11 +715,10 @@ export type RuntimeExecClass = "code" | "unobserved";
|
|
|
713
715
|
/**
|
|
714
716
|
* One runtime-execution observation as the store holds it (`anno_evid_exec`,
|
|
715
717
|
* `SCHEMA_VERSION` 4). Keyed by the bare run-identity triple
|
|
716
|
-
* `(imageSha256, argvDigest, seed)` plus `address` plus `sourceBank` --
|
|
717
|
-
*
|
|
718
|
-
*
|
|
719
|
-
*
|
|
720
|
-
* `no-perturbation` at anchor hit depths 10 and 50.
|
|
718
|
+
* `(imageSha256, argvDigest, seed)` plus `address` plus `sourceBank` -- there is
|
|
719
|
+
* no `run_class` discriminator column: a live A/B measured `no-perturbation`
|
|
720
|
+
* from instrumentation at anchor hit depths 10 and 50, so a run-class
|
|
721
|
+
* distinction would encode a difference nothing observed.
|
|
721
722
|
*
|
|
722
723
|
* A row here asserts exactly ONE fact: this address was observed executing,
|
|
723
724
|
* in this source bank, during this run. There is no `bank`-reserved column
|
|
@@ -737,8 +738,8 @@ export interface EvidExecRow {
|
|
|
737
738
|
* One distinct run identity's accumulated observation count, as
|
|
738
739
|
* `listObservedRuns()` reports it. `observationCount` is a COUNT, never a
|
|
739
740
|
* percentage or rate -- see `listObservedRuns`'s own doc comment in
|
|
740
|
-
* `anno-store.ts` for the denominator this count is a fraction of (
|
|
741
|
-
*
|
|
741
|
+
* `anno-store.ts` for the denominator this count is a fraction of (a count
|
|
742
|
+
* with no denominator invites the reading "the rest is data").
|
|
742
743
|
*/
|
|
743
744
|
export interface ObservedRunRow {
|
|
744
745
|
imageSha256: string;
|
|
@@ -828,7 +829,7 @@ export interface AnnoRevisionArgumentErrorOptions {
|
|
|
828
829
|
* path is built, so nothing has been read and nothing has been written.
|
|
829
830
|
*
|
|
830
831
|
* WHY THIS IS NOT `AnnoStoreCorruptError`, WHICH IS THE WHOLE REASON THE CLASS
|
|
831
|
-
* EXISTS
|
|
832
|
+
* EXISTS. Until this class existed, `revertTo(handle, "0001")` matched
|
|
832
833
|
* revision 1's pointer row through SQLite's INTEGER affinity on a bound TEXT
|
|
833
834
|
* operand, while `snapshotPathFor` built `r0001.db` from the raw string -- so
|
|
834
835
|
* the two disagreed and the caller was told its snapshot was "not a readable
|
|
@@ -1082,7 +1083,8 @@ export interface AnnoCommentGradeErrorOptions {
|
|
|
1082
1083
|
*
|
|
1083
1084
|
* It is NEVER correct to swallow the original and treat the comment as ungraded:
|
|
1084
1085
|
* that would quietly exempt a malformed comment from contradiction reporting,
|
|
1085
|
-
* which is the same silent
|
|
1086
|
+
* which is the same silent-un-documenting failure this store's contradiction
|
|
1087
|
+
* reporting exists to prevent.
|
|
1086
1088
|
*/
|
|
1087
1089
|
export class AnnoCommentGradeError extends AnnoStoreError {
|
|
1088
1090
|
comment?: string;
|
|
@@ -1216,7 +1218,7 @@ const MAX_SYMLINK_HOPS = 40;
|
|
|
1216
1218
|
* Does the path ENTRY `p` exist -- that is, does this NAME exist in its
|
|
1217
1219
|
* directory?
|
|
1218
1220
|
*
|
|
1219
|
-
*
|
|
1221
|
+
* THE WHOLE OF THE DISTINCTION, IN TWO SENTENCES. `existsSync` answers a
|
|
1220
1222
|
* different question: "does this path RESOLVE to something?", which follows
|
|
1221
1223
|
* symbolic links and therefore reports `false` for a dangling one. `lstat`
|
|
1222
1224
|
* answers "does this NAME exist?", which does not follow the link. The two
|
|
@@ -1226,8 +1228,7 @@ const MAX_SYMLINK_HOPS = 40;
|
|
|
1226
1228
|
*
|
|
1227
1229
|
* `throwIfNoEntry: false` makes the ABSENT case a value rather than an
|
|
1228
1230
|
* exception, so the caller has one branch instead of a `try` around a
|
|
1229
|
-
* predicate. That option suppresses `ENOENT` AND NOTHING ELSE
|
|
1230
|
-
* whole of `WR-12`.
|
|
1231
|
+
* predicate. That option suppresses `ENOENT` AND NOTHING ELSE.
|
|
1231
1232
|
*
|
|
1232
1233
|
* REVERSED 2026-08-28, and the reversal is the record rather than a deletion
|
|
1233
1234
|
* (this module's header discipline, 28-07 P3). The premise that was RIGHT and
|
|
@@ -1247,7 +1248,7 @@ const MAX_SYMLINK_HOPS = 40;
|
|
|
1247
1248
|
* * `ELOOP` -- a symlink cycle in an ANCESTOR position, where the kernel
|
|
1248
1249
|
* refuses at `lstat` before the manual hop counter below ever runs.
|
|
1249
1250
|
*
|
|
1250
|
-
*
|
|
1251
|
+
* The `try` restores the
|
|
1251
1252
|
* family WITHOUT restoring the old blindness: the absent case is still a value
|
|
1252
1253
|
* and still one branch, and everything else is a decision naming both the entry
|
|
1253
1254
|
* the walk stopped on and the path being confined.
|
|
@@ -1294,8 +1295,7 @@ function pathEntryExists(p: string, resolved: string): boolean {
|
|
|
1294
1295
|
* /tmp/annosym-XXXX/ws/p.annostore`) and `openStore` created the store file
|
|
1295
1296
|
* OUTSIDE the workspace root (`A) file created OUTSIDE workspace: true`);
|
|
1296
1297
|
* separately, a dangling DIRECTORY link was accepted at the predicate
|
|
1297
|
-
* (`B dangling dir -> ACCEPTED`).
|
|
1298
|
-
* CR-04. The walk now stops on `pathEntryExists`, which is `lstat` and does not
|
|
1298
|
+
* (`B dangling dir -> ACCEPTED`). The walk now stops on `pathEntryExists`, which is `lstat` and does not
|
|
1299
1299
|
* follow the link.
|
|
1300
1300
|
*
|
|
1301
1301
|
* THE DANGLING STOPPING ENTRY IS RESOLVED BY HAND, because nothing else will:
|
|
@@ -1404,8 +1404,8 @@ function realpathOfNearestExisting(p: string): string {
|
|
|
1404
1404
|
* * The PATH must be a real path, because `resolve()` normalises `..` but
|
|
1405
1405
|
* does NOT follow symbolic links. The pure-string version accepted a
|
|
1406
1406
|
* symlinked subdirectory inside the workspace and the store file was
|
|
1407
|
-
* created outside the root
|
|
1408
|
-
*
|
|
1407
|
+
* created outside the root, confirmed by a live symlink reproduction.
|
|
1408
|
+
* A confinement check has to compare what the filesystem will
|
|
1409
1409
|
* actually do.
|
|
1410
1410
|
* * The ROOT must go through the SAME walk, for two independent reasons. A
|
|
1411
1411
|
* workspace root that does not exist is a legitimate input -- the pinned
|
|
@@ -1454,8 +1454,7 @@ export function storePathWithinWorkspace(path: string, workspaceRoot: string): s
|
|
|
1454
1454
|
* WHY THIS IS A SEAM RATHER THAN AN INLINE `relative()` AT ITS ONE CALL SITE.
|
|
1455
1455
|
* The spelling this returns goes into a **compared** artifact: the memory
|
|
1456
1456
|
* map's banner is re-rendered and diffed BYTE FOR BYTE by
|
|
1457
|
-
* `checkRenderedMemoryMap()`. The defect it closes
|
|
1458
|
-
* `.planning/phases/29-the-mcp-surface/29-VERIFICATION.md`) is that machine
|
|
1457
|
+
* `checkRenderedMemoryMap()`. The defect it closes is that machine
|
|
1459
1458
|
* identity leaked into that content comparison: the banner recorded the
|
|
1460
1459
|
* absolute realpaths, so the same store, the same sidecar and the same
|
|
1461
1460
|
* rendered file reported `drifted` as soon as the checkout sat at a different
|
|
@@ -1565,7 +1564,7 @@ export function assertRunIdentityDigest(value: unknown, what: string): string {
|
|
|
1565
1564
|
}
|
|
1566
1565
|
|
|
1567
1566
|
/** A non-empty string. `seed` is not a digest and carries no shape beyond
|
|
1568
|
-
* that --
|
|
1567
|
+
* that -- this store's run-identity composite treats it as an opaque token. */
|
|
1569
1568
|
export function assertRunIdentitySeed(value: unknown): string {
|
|
1570
1569
|
if (typeof value === "string" && value.length > 0) {
|
|
1571
1570
|
return value;
|
|
@@ -1846,7 +1845,8 @@ export function resolveSplitTargets(bytes: Uint8Array | readonly number[], dataT
|
|
|
1846
1845
|
*
|
|
1847
1846
|
* A resolver and a writer that each kept their own copy of this arithmetic could
|
|
1848
1847
|
* disagree about what an entry IS, and the disagreement would be silent: both
|
|
1849
|
-
* copies produce legal, decodable rows. That is
|
|
1848
|
+
* copies produce legal, decodable rows. That is exactly the class of bug a
|
|
1849
|
+
* second implementation would risk, so the rule
|
|
1850
1850
|
* has one home. `anno-types.test.ts`'s worked-arithmetic pin is the control --
|
|
1851
1851
|
* changing the couples here to an interleaved `[2i, 2i + 1]` reddens it.
|
|
1852
1852
|
*
|
package/package.json
CHANGED