@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.
Files changed (108) hide show
  1. package/README.md +4 -3
  2. package/THIRD-PARTY-NOTICES.md +423 -25
  3. package/{r2000-acme-ident.ts → anno-acme-ident.ts} +13 -13
  4. package/anno-bank.ts +171 -0
  5. package/anno-cli.ts +3040 -0
  6. package/{r2000-confidence.ts → anno-confidence.ts} +22 -22
  7. package/anno-coverage.ts +2465 -0
  8. package/anno-derive.ts +590 -0
  9. package/anno-details.ts +169 -0
  10. package/anno-enum-gen.ts +919 -0
  11. package/anno-export-asm.ts +2396 -0
  12. package/anno-graphics.ts +338 -0
  13. package/anno-hazard-report.ts +1367 -0
  14. package/anno-import.ts +495 -0
  15. package/anno-index.ts +150 -0
  16. package/anno-join.ts +480 -0
  17. package/{r2000-memmap-render.ts → anno-memmap-render.ts} +236 -95
  18. package/anno-provenance-ledger.ts +472 -0
  19. package/{r2000-regbits-gen.ts → anno-regbits-gen.ts} +20 -15
  20. package/{r2000-regbits.json → anno-regbits.json} +2 -2
  21. package/anno-register.ts +399 -0
  22. package/anno-store-export.ts +661 -0
  23. package/anno-store.ts +4002 -0
  24. package/anno-symbols.ts +266 -0
  25. package/anno-tools.ts +3264 -0
  26. package/anno-types.ts +1909 -0
  27. package/backend-detect.mts +124 -312
  28. package/block-class.ts +201 -0
  29. package/build.ts +4 -2
  30. package/capture-predicate.ts +597 -0
  31. package/channel-lock.ts +349 -0
  32. package/disasm-decoder.ts +14 -14
  33. package/disasm-opcodes.ts +4 -4
  34. package/disasm-renderer.ts +2 -2
  35. package/evid-ingest.ts +217 -0
  36. package/evid-reconcile.ts +316 -0
  37. package/host-tool-client.ts +430 -0
  38. package/hostpath.ts +1 -1
  39. package/incident-record.ts +23 -12
  40. package/install-resources.ts +30 -14
  41. package/memmap-lookup.ts +285 -0
  42. package/package.json +48 -23
  43. package/prg-image.ts +118 -0
  44. package/repo-root.ts +107 -8
  45. package/resources/backend-detect.mjs +98 -236
  46. package/resources/broker-control.mjs +189 -16
  47. package/resources/broker-epoch.mjs +1 -1
  48. package/resources/broker-kill.mjs +8 -2
  49. package/resources/broker-launch.mjs +373 -214
  50. package/resources/broker-state.mjs +64 -18
  51. package/resources/container-guard.mjs +1 -1
  52. package/resources/ghidra-project.mjs +790 -0
  53. package/resources/host-tool.mjs +2561 -0
  54. package/resources/vice-broker.mjs +330 -184
  55. package/resources/vice-launcher.sh +130 -12
  56. package/stock-address.ts +6 -6
  57. package/stock-cia.ts +2 -2
  58. package/stock-condition.ts +8 -8
  59. package/stock-connect.ts +10 -6
  60. package/stock-derived.ts +29 -37
  61. package/stock-diagnose.ts +200 -36
  62. package/stock-dispatch.ts +200 -68
  63. package/stock-execution.ts +5 -3
  64. package/stock-handler.ts +1 -1
  65. package/stock-input.ts +9 -9
  66. package/stock-machine.ts +17 -6
  67. package/stock-paths.ts +18 -14
  68. package/stock-petscii.ts +1 -1
  69. package/stock-protocol.ts +17 -12
  70. package/stock-recycle.ts +83 -2
  71. package/stock-registers.ts +54 -29
  72. package/stock-reproducible-run.ts +811 -0
  73. package/stock-run-until.ts +100 -1
  74. package/stock-sprites.ts +3 -3
  75. package/stock-symbols.ts +13 -13
  76. package/stock-timing.ts +2 -2
  77. package/stock-vicii.ts +1 -1
  78. package/stop-oracle.ts +167 -0
  79. package/text-capability-probe.ts +660 -0
  80. package/text-connect.ts +157 -0
  81. package/text-protocol.ts +810 -0
  82. package/text-tools.ts +778 -0
  83. package/textmon-backtrace.ts +385 -0
  84. package/textmon-cpuhistory.ts +335 -0
  85. package/textmon-memmap.ts +494 -0
  86. package/textmon-profile.ts +458 -0
  87. package/textmon-registers.ts +748 -0
  88. package/tools-manifest.stock.json +864 -3
  89. package/version.ts +1 -1
  90. package/vice-broker-client.ts +189 -42
  91. package/vice-errors.ts +268 -0
  92. package/vice-proxy.ts +392 -2175
  93. package/vsf-slice.ts +640 -0
  94. package/capability-registry.ts +0 -388
  95. package/r2000-cli.ts +0 -1103
  96. package/r2000-d64.ts +0 -310
  97. package/r2000-enum-gen.ts +0 -574
  98. package/r2000-launch.ts +0 -357
  99. package/r2000-mcp-client.ts +0 -596
  100. package/r2000-project.ts +0 -190
  101. package/r2000-symbols.ts +0 -388
  102. package/r2000-tools.ts +0 -914
  103. package/r2000-verify.ts +0 -184
  104. package/refresh-manifest.ts +0 -124
  105. package/tools-manifest.json +0 -1223
  106. package/vice-probe.ts +0 -278
  107. package/vice-sync.ts +0 -336
  108. package/vice.ts +0 -772
@@ -0,0 +1,399 @@
1
+ // anno-register.ts -- the ONE authoritative, committed record of WHY a verb on
2
+ // the `anno_*` surface exists when the Phase 19 upstream procedure manifest
3
+ // does not classify it, and of the one verb whose route deliberately answers
4
+ // something OTHER than what the manifest's upstream contract described.
5
+ //
6
+ // WHY THIS FILE EXISTS (MCP-01, D-08). `MCP-01`'s whole claim is that the tool
7
+ // surface is DERIVED rather than CHOSEN: every verb the manifest disposes
8
+ // `curated` or `adapt-to-address-input` has a route, every verb it disposes
9
+ // `omit` is absent, and the verb with zero callers anywhere is not carried.
10
+ // `anno-derivation.test.ts` checks that half mechanically. This file is the
11
+ // OTHER half, and without it the derivation is a half-truth: four verbs on the
12
+ // surface appear in no manifest procedure at all, and one of them --
13
+ // `anno_search` -- is POSITIVELY REQUIRED by `STORE-06`. A derivation with an
14
+ // unrecorded remainder is not a derivation; it is a derivation plus an
15
+ // unwritten allow-list.
16
+ //
17
+ // D-08 rejected the alternative explicitly, and the reason is worth restating
18
+ // where it will be read: the manifest could have been amended to carry these
19
+ // four names, and must not be. It describes UPSTREAM at a pinned commit, and it
20
+ // carries its own re-sync trigger and per-procedure sha256 digests. Writing this
21
+ // project's verbs into it makes it describe US, and the next re-hash against a
22
+ // real upstream clone would then be comparing a record that had been quietly
23
+ // edited to agree with the thing it was supposed to audit.
24
+ //
25
+ // WHAT THIS IS THE ONE AUTHORITATIVE PLACE FOR:
26
+ // - every surface verb the manifest does not classify, with the named
27
+ // consumers and the cited requirement ids that justify its existence;
28
+ // - every surface verb the manifest DOES classify but whose route answers
29
+ // something other than upstream's contract, recorded as a deviation so a
30
+ // later reader does not mistake a deliberate reporting route for an
31
+ // oversight.
32
+ // Nothing else in the repo may hold a second copy of this judgement. A consumer
33
+ // that needs it in another shape imports `ANNO_VERB_REGISTER` and reshapes it.
34
+ //
35
+ // WHAT MAKES THIS AN OBLIGATION RATHER THAN A DOCUMENT: `anno-register.test.ts`
36
+ // enumerates the surface, subtracts the manifest-classified names, and FAILS --
37
+ // naming the offending verb -- the moment a verb has no entry. D-08's wording is
38
+ // literal and is the wording the failure uses: a verb added later with no named
39
+ // consumer FAILS rather than being reviewed.
40
+ //
41
+ // WHAT NOT TO DO, named concretely:
42
+ // - AN ENTRY CITING NO REQUIREMENT ID AND NO CONSUMER IS NOT AN ENTRY. The
43
+ // enforcing test reports it by name. Do not "temporarily" add a verb with a
44
+ // rationale and nothing else; a rationale is prose, and prose is what this
45
+ // register exists to stop being the whole basis.
46
+ // - Do not let this grow into an unbounded allow-list. Every entry added here
47
+ // makes "derived from the manifest" a little more decorative. Four entries
48
+ // and one deviation is the measured state at the time of writing; a fifth is
49
+ // a decision, not paperwork.
50
+ // - CITATION DISCIPLINE, carried over verbatim in intent from
51
+ // `module-classification.ts`: `path` is ALWAYS repository-root-relative,
52
+ // never relative to this directory, because consumers legitimately live
53
+ // under `.planning/`, `scripts/` and `src/skills/` as well as beside this
54
+ // file. `symbol` names what the consumer actually TAKES from the verb (an
55
+ // imported binding, a store entry point, or -- for a documentation consumer
56
+ // -- the identifier the cited line names); it is a CITATION, never a
57
+ // justification. `line` is OPTIONAL AND ADVISORY: where present the
58
+ // enforcing test asserts that line of that file contains `symbol` and never
59
+ // trusts the number, so OMIT IT RATHER THAN GUESS.
60
+ //
61
+ // Deliberately a plain `.ts` module and never a `.test.ts` file, for the reason
62
+ // `module-classification.ts` gives: importing a `.test.ts` module for its
63
+ // exports also re-runs every `test(...)` it registers, as an import side effect.
64
+ // This module imports nothing at all.
65
+
66
+ /** One cited consumer of a registered verb. See the header's citation
67
+ * discipline: `path` is repository-root-relative, `symbol` is a citation and
68
+ * never a justification, and `line` is optional and advisory -- omit it rather
69
+ * than guess. */
70
+ export interface AnnoVerbConsumer {
71
+ path: string;
72
+ symbol: string;
73
+ line?: number;
74
+ }
75
+
76
+ /**
77
+ * The two reasons a verb is in this register, kept DISTINGUISHABLE on purpose:
78
+ * a reader must be able to tell "this verb has no manifest classification" from
79
+ * "this verb has one and we answered it differently".
80
+ *
81
+ * - "unclassified": the manifest's five procedures never mention the upstream
82
+ * name this verb derives from, so the derivation says nothing about it. Its
83
+ * existence rests entirely on the consumers and requirement ids below.
84
+ * - "manifest-deviation": the manifest DOES classify it, and it has a route,
85
+ * so the derivation check is satisfied -- but the route answers something
86
+ * other than what upstream's contract described. Recorded so the difference
87
+ * is a decision on the record rather than something a reader discovers by
88
+ * calling the verb and being surprised.
89
+ */
90
+ export type AnnoVerbEntryKind = "unclassified" | "manifest-deviation";
91
+
92
+ /**
93
+ * One registered verb.
94
+ *
95
+ * `verb` is the EXACT surface tool name, including the family prefix, because
96
+ * the enforcing test compares it as a literal string against
97
+ * `ANNO_TOOL_DEFINITIONS[].name` in both directions.
98
+ *
99
+ * `consumers` and `requirements` are the BASIS. At least one of each is
100
+ * required -- not "one or the other", which is the weaker rule
101
+ * `module-classification.ts` could afford because its subject was a module that
102
+ * already existed. A verb is a public surface commitment; D-08 asks for a named
103
+ * consumer AND a cited requirement, and the enforcing test asks for both.
104
+ *
105
+ * `rationale` states, in terms of what the verb DOES, why it is on the surface.
106
+ *
107
+ * `note` carries anything the basis cannot say -- a consequence measured
108
+ * elsewhere, or the shape of the recorded finding this entry discharges.
109
+ */
110
+ export interface AnnoVerbRegisterEntry {
111
+ verb: string;
112
+ kind: AnnoVerbEntryKind;
113
+ consumers: readonly AnnoVerbConsumer[];
114
+ requirements: readonly string[];
115
+ rationale: string;
116
+ note?: string;
117
+ }
118
+
119
+ export const ANNO_VERB_REGISTER: readonly AnnoVerbRegisterEntry[] = Object.freeze([
120
+ // --- unclassified: the manifest's five procedures never name these ---
121
+ {
122
+ verb: "anno_add_scope",
123
+ kind: "unclassified",
124
+ consumers: [
125
+ { path: "src/mcp/vice/anno-store.ts", symbol: "addScope" },
126
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_add_scope" },
127
+ ],
128
+ requirements: ["STORE-01"],
129
+ rationale:
130
+ "Scopes are one of the five things STORE-01 requires the store to hold -- labels, comments, per-range " +
131
+ "data typing, scopes and project enums -- and four of those five reached the surface through a " +
132
+ "manifest-classified verb. Scopes did not, because the absorbed upstream procedures never used them: " +
133
+ "they are how a routine's local symbols are kept out of the global namespace, which is an EXPORT-side " +
134
+ "concern the procedures had no reason to touch. Without this verb the store persists a table no caller " +
135
+ "on this surface can write, which is a stored capability with no route -- exactly the shape STORE-01 " +
136
+ "was written against.",
137
+ },
138
+ {
139
+ verb: "anno_remove_scope",
140
+ kind: "unclassified",
141
+ consumers: [
142
+ { path: "src/mcp/vice/anno-store.ts", symbol: "removeScope" },
143
+ { path: ".planning/phases/28-the-store-core/28-REVIEW.md", symbol: "removeScope" },
144
+ ],
145
+ requirements: ["STORE-01"],
146
+ rationale:
147
+ "The inverse of the overlap refusal, and the register's clearest case of a verb existing because a " +
148
+ "recorded finding demanded it rather than because a procedure used it. 28-REVIEW's round-6 WARNING is " +
149
+ "the named consumer: the store refuses any scope overlapping an existing one, and had no removal verb " +
150
+ "for a scope, a label, a comment, a cross-reference or an enum. A write verb whose mistakes cannot be " +
151
+ "undone is a data-loss surface even when every individual refusal is correct, so the inverse ships in " +
152
+ "the same phase as the refusal.",
153
+ note:
154
+ "The measured consequence, which is why this is not merely tidiness: `anno_add_scope($1000, $ffff)` -- " +
155
+ "ONE TRANSPOSED END, arriving from a transport whose validator returns its input unchanged -- makes " +
156
+ "every future scope from $1000 upward permanently unaddable. The only route back was `revertTo`, and " +
157
+ "the snapshot ring is bounded at MAX_SNAPSHOT_REVISIONS: 32 further writes and the store's own " +
158
+ "published floor refuses, by name, the revision that would undo it.",
159
+ },
160
+ {
161
+ verb: "anno_search",
162
+ kind: "unclassified",
163
+ consumers: [
164
+ { path: "src/mcp/vice/anno-derive.ts", symbol: "searchAnnotations" },
165
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_search" },
166
+ // Re-pointed at the v0.7.0 close, 2026-09-01: `/gsd-complete-milestone`
167
+ // `git rm`s `.planning/REQUIREMENTS.md` and archives it under
168
+ // `milestones/<version>-REQUIREMENTS.md`. The cited text is unchanged --
169
+ // this names the file STORE-06 is actually declared in today, so
170
+ // DIRECTION 5's "every path exists" check stays a real check.
171
+ { path: ".planning/milestones/v0.7.0-REQUIREMENTS.md", symbol: "STORE-06" },
172
+ ],
173
+ requirements: ["STORE-06"],
174
+ rationale:
175
+ "POSITIVELY REQUIRED by STORE-06, which names search across labels, comments and instructions as one " +
176
+ "of its two halves and says in terms that it is built on the surviving decoders with the old route " +
177
+ "gone rather than kept as a fallback. The manifest cannot classify it: the upstream call it derives " +
178
+ "from appears in no absorbed procedure, so the derivation is silent and the requirement is the whole " +
179
+ "basis. That is the second of the two admissible bases and not a weaker one -- it is the strongest " +
180
+ "kind of entry this register holds, because a requirement id is checkable against a committed document " +
181
+ "whereas a consumer can be deleted by the next refactor.",
182
+ note:
183
+ "This entry is load-bearing for a check in another file. The skill-coverage script's non-vacuity " +
184
+ "control is re-pointed onto this verb (C-5): it is STORE-06's named requirement AND it lives here, so " +
185
+ "if it ever silently leaves the surface, BOTH the coverage control and this register's completeness " +
186
+ "relation fire. Do not remove this entry to make a count come out.",
187
+ },
188
+ {
189
+ verb: "anno_update_project_enum",
190
+ kind: "unclassified",
191
+ consumers: [
192
+ { path: "src/mcp/vice/anno-store.ts", symbol: "updateProjectEnum" },
193
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_update_project_enum" },
194
+ ],
195
+ requirements: ["STORE-01"],
196
+ rationale:
197
+ "Project enums are STORE-01's fifth stored kind. The manifest classifies creation and application " +
198
+ "(both `curated`, from the routine and symbol procedures) but not update, because the absorbed " +
199
+ "procedures create an enum once from a fresh reading and never revise one. This project does revise " +
200
+ "them: the register-bit and enum generators emit a variant set from a data file, and a regenerated " +
201
+ "set must be able to REPLACE an earlier one rather than collide with it. Without update, the only " +
202
+ "route to a corrected variant set is delete-and-recreate -- and delete is the one verb with zero " +
203
+ "callers anywhere, which MCP-01 requires this surface not to carry.",
204
+ note:
205
+ "This is the entry that explains why the absent delete verb costs nothing. The delete route existed " +
206
+ "upstream to support exactly the delete-and-recreate cycle update makes unnecessary; carrying update " +
207
+ "instead is what lets MCP-01's zero-caller clause hold without losing a capability.",
208
+ },
209
+
210
+ {
211
+ verb: "anno_exclude_range",
212
+ kind: "unclassified",
213
+ consumers: [
214
+ { path: "src/mcp/vice/anno-store.ts", symbol: "addExcludedRange" },
215
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_exclude_range" },
216
+ ],
217
+ requirements: ["BUILD-05", "BUILD-07"],
218
+ rationale:
219
+ "BUILD-05 requires that any exclusion be one the user asked for, made explicit and recorded rather than " +
220
+ "silently applied. BUILD-07 requires a user-requested exclusion be emitted as a recorded excluded range " +
221
+ "rather than a hole. Both clauses presuppose a route by which the user STATES the request. Without this " +
222
+ "verb the store persists a table no caller on this surface can write -- a stored capability with no " +
223
+ "route, which is the same shape anno_add_scope's own entry was written against. The surface is the right " +
224
+ "home rather than the CLI because an exclusion is a small bounded piece of state a session sets while " +
225
+ "looking at a range, not a filesystem artefact.",
226
+ note:
227
+ "This verb's existence is what makes the requirement's 'never the tool's' clause CHECKABLE rather than " +
228
+ "aspirational. As long as the only way a range can be excluded is a user calling this verb, there is no " +
229
+ "code path by which the tool excludes anything on its own judgement. The alternative rejected: a " +
230
+ "confidence or verdict threshold inside the exporter would have 'implemented' the same user-visible " +
231
+ "outcome and would have made the tool the decider -- the failure mode the 2026-09-10 rewording of " +
232
+ "BUILD-05 removed.",
233
+ },
234
+ {
235
+ verb: "anno_include_range",
236
+ kind: "unclassified",
237
+ consumers: [
238
+ { path: "src/mcp/vice/anno-store.ts", symbol: "removeExcludedRange" },
239
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_include_range" },
240
+ ],
241
+ requirements: ["BUILD-07"],
242
+ rationale:
243
+ "The inverse of the overlap refusal, on the same terms anno_remove_scope's entry states: the store " +
244
+ "refuses any exclusion overlapping an existing one, so a single transposed end would otherwise make a " +
245
+ "whole region permanently unexcludable, with the only route back being a revert through the bounded " +
246
+ "snapshot ring. A write verb whose mistakes cannot be undone is a data-loss surface even when every " +
247
+ "individual refusal is correct, so the inverse ships in the same phase as the refusal.",
248
+ note:
249
+ "The measured mechanism, not an asserted risk: the snapshot ring is bounded at MAX_SNAPSHOT_REVISIONS, so " +
250
+ "a mistake that is not directly undoable becomes permanently undoable after that many further writes.",
251
+ },
252
+ {
253
+ verb: "anno_import_ghidra_export",
254
+ kind: "unclassified",
255
+ consumers: [
256
+ { path: "src/mcp/vice/anno-import.ts", symbol: "importGhidraExport" },
257
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_import_ghidra_export" },
258
+ ],
259
+ requirements: ["IMP-01", "IMP-02"],
260
+ rationale:
261
+ "The manifest's five absorbed upstream procedures predate this store having any Ghidra-derived import path " +
262
+ "at all, so the derivation is silent about a verb that did not exist when the manifest was written. IMP-01 " +
263
+ "requires a container-side importer reading a host-written transfer file through the store's single seam, " +
264
+ "and IMP-02 requires that transfer file to be transient evidence -- digested, consumed and deleted in the " +
265
+ "same call, never a second on-disk model. This verb is the only route either requirement has: without it, " +
266
+ "a Ghidra export sits on disk as a file no curated verb ever reads.",
267
+ },
268
+ {
269
+ verb: "anno_join_memmap",
270
+ kind: "unclassified",
271
+ consumers: [
272
+ { path: "src/mcp/vice/anno-join.ts", symbol: "runMemmapJoin" },
273
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_join_memmap" },
274
+ ],
275
+ requirements: ["AUTO-01"],
276
+ rationale:
277
+ "AUTO-01 requires machine addresses to annotate themselves into the store mechanically -- no agent call, no " +
278
+ "queue walk and no skill invocation anywhere in the loop -- by joining stored cross-references against " +
279
+ "c64-memory-mapping's memmap.json. The manifest's five procedures never describe this join at all, because " +
280
+ "it answers a question this project's own store creates (what does a stored cross-reference's target " +
281
+ "address MEAN against the published memory map), not one upstream's absorbed procedures ever asked. Without " +
282
+ "this verb the annotation the join produces has no route onto the surface at all.",
283
+ },
284
+ {
285
+ verb: "anno_evid_ingest",
286
+ kind: "unclassified",
287
+ consumers: [
288
+ { path: "src/mcp/vice/evid-ingest.ts", symbol: "ingestAccessMap" },
289
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_evid_ingest" },
290
+ ],
291
+ requirements: ["EVID-01", "EVID-04"],
292
+ rationale:
293
+ "EVID-01 requires what the emulator observed executing to become durable, accumulating rows in `.annostore`, " +
294
+ "keyed by run identity, so a later session queries the evidence instead of re-running the program. EVID-04 " +
295
+ "requires the write path be unable to state, imply or render that an address is data on the strength of " +
296
+ "never having been observed executing. The manifest's five absorbed upstream procedures predate this store " +
297
+ "having any runtime-evidence table at all, so the derivation is silent about a verb that did not exist when " +
298
+ "the manifest was written. This verb is the ONE place a parsed memmapshow access map becomes store rows: " +
299
+ "without it, an observed execute bit has no route onto the surface at all, and EVID-01's own goal (query the " +
300
+ "evidence instead of re-running the program) is unreachable.",
301
+ },
302
+ {
303
+ verb: "anno_evid_disagreements",
304
+ kind: "unclassified",
305
+ consumers: [
306
+ { path: "src/mcp/vice/evid-reconcile.ts", symbol: "reconcileObservedExecution" },
307
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_evid_disagreements" },
308
+ ],
309
+ requirements: ["EVID-03", "EVID-04"],
310
+ rationale:
311
+ "EVID-03 requires a user be able to ask where the byte-derived block classification and the observed-execution " +
312
+ "evidence disagree, and get the disagreements first, with the block table never silently overwritten and " +
313
+ "agreement reported as a count rather than a wall of rows. EVID-04 requires that no summary this surface " +
314
+ "produces can state, imply or render that a never-observed address is data, and that every count carries the " +
315
+ "denominator it is a fraction of. This verb is the ONE place `reconcileObservedExecution()`'s pure join is " +
316
+ "reached from the MCP surface: without it, the reconciliation module a prior plan built has no caller at all, " +
317
+ "and EVID-03's own goal (a user can ask) is unreachable.",
318
+ },
319
+ {
320
+ verb: "anno_evid_runs",
321
+ kind: "unclassified",
322
+ consumers: [
323
+ { path: "src/mcp/vice/anno-store.ts", symbol: "listObservedRuns" },
324
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_evid_runs" },
325
+ ],
326
+ requirements: ["EVID-04"],
327
+ rationale:
328
+ "EVID-04 requires that any summary carry the denominator it is a fraction of and that a union across however " +
329
+ "many runs never be presented as exhaustive. This verb is the ONE surface route to `listObservedRuns()`'s " +
330
+ "per-run observation counts and their shared denominator, so a later session can see what evidence a store " +
331
+ "already holds -- across however many runs contributed -- without re-running the program and without ever " +
332
+ "reading the counts as coverage of the image.",
333
+ },
334
+ {
335
+ verb: "anno_evid_reset",
336
+ kind: "unclassified",
337
+ consumers: [
338
+ { path: "src/mcp/vice/anno-store.ts", symbol: "deleteExecObservationsForRun" },
339
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_evid_reset" },
340
+ ],
341
+ requirements: ["EVID-05"],
342
+ rationale:
343
+ "EVID-05 requires that a bracket can be reset and re-measured without a previous run's observations leaking " +
344
+ "into it. This verb is the store-side half of that reset (beside plan 43-03's emulator-side `vice_memmap_zap`): " +
345
+ "it derives the run identity through the same `runIdentityFrom()` `anno_evid_ingest` uses and deletes only " +
346
+ "that identity's rows, leaving every other identity and the byte-derived block table untouched. Without it, " +
347
+ "`deleteExecObservationsForRun()` -- the store function EVID-05's own requirement asks for -- has no route " +
348
+ "onto the surface at all.",
349
+ },
350
+ {
351
+ verb: "anno_hazard_report",
352
+ kind: "unclassified",
353
+ consumers: [
354
+ { path: "src/mcp/vice/anno-hazard-report.ts", symbol: "buildHazardReport" },
355
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_hazard_report" },
356
+ ],
357
+ requirements: ["BUILD-04"],
358
+ rationale:
359
+ "A movement-blocking construction must be askable and enumerable, with its detection mechanism and its " +
360
+ "detection strength reported beside it, and with a third undecided outcome that is never rendered as " +
361
+ "clean. This verb is the ONE place the pure hazard-report function is reached from the surface: without " +
362
+ "it, the module a prior task built has no caller at all, and the goal it exists for (a user can ask what " +
363
+ "blocks a program's code from being moved) is unreachable. The manifest's five absorbed upstream " +
364
+ "procedures predate any movement-hazard concept in this store at all, so the derivation is silent about a " +
365
+ "verb that answers a question upstream never asked. This verb opens no new store table and writes " +
366
+ "nothing -- it is a derived query over tables the surface already writes through other verbs.",
367
+ },
368
+
369
+ // --- manifest-deviation: classified, routed, and answering differently ---
370
+ {
371
+ verb: "anno_save_project",
372
+ kind: "manifest-deviation",
373
+ consumers: [
374
+ { path: "src/mcp/vice/anno-store.ts", symbol: "currentRevision" },
375
+ { path: "src/mcp/vice/anno-tools.ts", symbol: "anno_save_project" },
376
+ ],
377
+ requirements: ["STORE-04", "MCP-04"],
378
+ rationale:
379
+ "The manifest disposes this verb `curated` in two procedures and it has a route, so the derivation " +
380
+ "check is satisfied -- but THE ROUTE PERFORMS NO WRITE. It reports the store's current revision and " +
381
+ "states the no-write property in its own body. Upstream's contract was an explicit flush of unsaved " +
382
+ "editor state; this store has none, because STORE-04 makes every mutating verb commit and fsync its " +
383
+ "own write before it returns. Durability belongs to the store, not to a verb an agent has to remember " +
384
+ "to call. Recorded HERE, as a deviation, because a route that reports rather than writes is precisely " +
385
+ "what a later reader would otherwise diagnose as an oversight and 'fix'.",
386
+ note:
387
+ "Routed honestly rather than refused, which is the MCP-04 half. Refusing an absorbed procedure's own " +
388
+ "step would break the procedures this project inherited for no gain; answering it with the revision " +
389
+ "gives the caller something genuinely useful -- the value a subsequent compare-and-swap needs, and the " +
390
+ "confirmation that a pass advanced the store as far as expected.",
391
+ },
392
+ ]);
393
+
394
+ /** The registered entry for a verb, or `undefined`. Exported so a consumer
395
+ * asking "why is this verb here?" reads the record rather than re-deriving it,
396
+ * and so the enforcing test and any later caller share one lookup. */
397
+ export function annoRegisterEntryFor(verb: string): AnnoVerbRegisterEntry | undefined {
398
+ return ANNO_VERB_REGISTER.find((entry) => entry.verb === verb);
399
+ }