@descryy/mcp 0.5.0 → 0.7.0

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 (260) hide show
  1. package/dist/action-handshake.d.ts +8 -75
  2. package/dist/action-handshake.d.ts.map +1 -1
  3. package/dist/action-handshake.js +9 -79
  4. package/dist/action-handshake.js.map +1 -1
  5. package/dist/bin/descry-mcp.d.ts +4 -15
  6. package/dist/bin/descry-mcp.d.ts.map +1 -1
  7. package/dist/bin/descry-mcp.js +12 -42
  8. package/dist/bin/descry-mcp.js.map +1 -1
  9. package/dist/browser/driver.d.ts +62 -178
  10. package/dist/browser/driver.d.ts.map +1 -1
  11. package/dist/browser/driver.js +14 -46
  12. package/dist/browser/driver.js.map +1 -1
  13. package/dist/browser/evidence.d.ts +11 -35
  14. package/dist/browser/evidence.d.ts.map +1 -1
  15. package/dist/browser/evidence.js +25 -51
  16. package/dist/browser/evidence.js.map +1 -1
  17. package/dist/browser/fake-driver.d.ts +12 -16
  18. package/dist/browser/fake-driver.d.ts.map +1 -1
  19. package/dist/browser/fake-driver.js +24 -17
  20. package/dist/browser/fake-driver.js.map +1 -1
  21. package/dist/browser/graph-write.d.ts +4 -45
  22. package/dist/browser/graph-write.d.ts.map +1 -1
  23. package/dist/browser/graph-write.js +8 -53
  24. package/dist/browser/graph-write.js.map +1 -1
  25. package/dist/browser/playwright-driver.d.ts +17 -67
  26. package/dist/browser/playwright-driver.d.ts.map +1 -1
  27. package/dist/browser/playwright-driver.js +169 -166
  28. package/dist/browser/playwright-driver.js.map +1 -1
  29. package/dist/browser/provider.d.ts +5 -34
  30. package/dist/browser/provider.d.ts.map +1 -1
  31. package/dist/browser/provider.js +4 -24
  32. package/dist/browser/provider.js.map +1 -1
  33. package/dist/browser/registry.d.ts +26 -106
  34. package/dist/browser/registry.d.ts.map +1 -1
  35. package/dist/browser/registry.js +20 -77
  36. package/dist/browser/registry.js.map +1 -1
  37. package/dist/browser/scenario-resolve.d.ts +10 -44
  38. package/dist/browser/scenario-resolve.d.ts.map +1 -1
  39. package/dist/browser/scenario-resolve.js +10 -41
  40. package/dist/browser/scenario-resolve.js.map +1 -1
  41. package/dist/browser/scenario-runner.d.ts +12 -70
  42. package/dist/browser/scenario-runner.d.ts.map +1 -1
  43. package/dist/browser/scenario-runner.js +33 -91
  44. package/dist/browser/scenario-runner.js.map +1 -1
  45. package/dist/browser/stack-parser.d.ts +4 -28
  46. package/dist/browser/stack-parser.d.ts.map +1 -1
  47. package/dist/browser/stack-parser.js +12 -39
  48. package/dist/browser/stack-parser.js.map +1 -1
  49. package/dist/browser/tool-support.d.ts +20 -67
  50. package/dist/browser/tool-support.d.ts.map +1 -1
  51. package/dist/browser/tool-support.js +22 -66
  52. package/dist/browser/tool-support.js.map +1 -1
  53. package/dist/browser/url-scheme.d.ts +14 -0
  54. package/dist/browser/url-scheme.d.ts.map +1 -0
  55. package/dist/browser/url-scheme.js +38 -0
  56. package/dist/browser/url-scheme.js.map +1 -0
  57. package/dist/cancellation.d.ts +11 -46
  58. package/dist/cancellation.d.ts.map +1 -1
  59. package/dist/cancellation.js +11 -46
  60. package/dist/cancellation.js.map +1 -1
  61. package/dist/capped.d.ts +17 -0
  62. package/dist/capped.d.ts.map +1 -0
  63. package/dist/capped.js +15 -0
  64. package/dist/capped.js.map +1 -0
  65. package/dist/disclosure-ledger.d.ts +6 -30
  66. package/dist/disclosure-ledger.d.ts.map +1 -1
  67. package/dist/disclosure-ledger.js +4 -26
  68. package/dist/disclosure-ledger.js.map +1 -1
  69. package/dist/index.d.ts +10 -26
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +7 -17
  72. package/dist/index.js.map +1 -1
  73. package/dist/module-trust.d.ts +24 -0
  74. package/dist/module-trust.d.ts.map +1 -0
  75. package/dist/module-trust.js +60 -0
  76. package/dist/module-trust.js.map +1 -0
  77. package/dist/path-confinement.d.ts +31 -0
  78. package/dist/path-confinement.d.ts.map +1 -0
  79. package/dist/path-confinement.js +44 -0
  80. package/dist/path-confinement.js.map +1 -0
  81. package/dist/protocol.d.ts +10 -53
  82. package/dist/protocol.d.ts.map +1 -1
  83. package/dist/protocol.js +14 -60
  84. package/dist/protocol.js.map +1 -1
  85. package/dist/registry.d.ts +10 -58
  86. package/dist/registry.d.ts.map +1 -1
  87. package/dist/registry.js +38 -90
  88. package/dist/registry.js.map +1 -1
  89. package/dist/render.d.ts +79 -11
  90. package/dist/render.d.ts.map +1 -1
  91. package/dist/render.js +126 -14
  92. package/dist/render.js.map +1 -1
  93. package/dist/runtime-registry.d.ts +8 -49
  94. package/dist/runtime-registry.d.ts.map +1 -1
  95. package/dist/runtime-registry.js +72 -63
  96. package/dist/runtime-registry.js.map +1 -1
  97. package/dist/scenarios/index.d.ts +1 -1
  98. package/dist/scenarios/index.d.ts.map +1 -1
  99. package/dist/scenarios/index.js +1 -1
  100. package/dist/scenarios/index.js.map +1 -1
  101. package/dist/scenarios/parse.d.ts +4 -18
  102. package/dist/scenarios/parse.d.ts.map +1 -1
  103. package/dist/scenarios/parse.js +14 -34
  104. package/dist/scenarios/parse.js.map +1 -1
  105. package/dist/scenarios/scenario.d.ts +18 -74
  106. package/dist/scenarios/scenario.d.ts.map +1 -1
  107. package/dist/scenarios/scenario.js +7 -34
  108. package/dist/scenarios/scenario.js.map +1 -1
  109. package/dist/scenarios/storage.d.ts +11 -41
  110. package/dist/scenarios/storage.d.ts.map +1 -1
  111. package/dist/scenarios/storage.js +57 -47
  112. package/dist/scenarios/storage.js.map +1 -1
  113. package/dist/server.d.ts.map +1 -1
  114. package/dist/server.js +55 -13
  115. package/dist/server.js.map +1 -1
  116. package/dist/session.d.ts +69 -239
  117. package/dist/session.d.ts.map +1 -1
  118. package/dist/session.js +76 -231
  119. package/dist/session.js.map +1 -1
  120. package/dist/tools/analyze.d.ts +27 -101
  121. package/dist/tools/analyze.d.ts.map +1 -1
  122. package/dist/tools/analyze.js +58 -148
  123. package/dist/tools/analyze.js.map +1 -1
  124. package/dist/tools/browser-click.d.ts +3 -21
  125. package/dist/tools/browser-click.d.ts.map +1 -1
  126. package/dist/tools/browser-click.js +10 -31
  127. package/dist/tools/browser-click.js.map +1 -1
  128. package/dist/tools/browser-close-session.d.ts +4 -13
  129. package/dist/tools/browser-close-session.d.ts.map +1 -1
  130. package/dist/tools/browser-close-session.js +4 -13
  131. package/dist/tools/browser-close-session.js.map +1 -1
  132. package/dist/tools/browser-fill.d.ts +5 -36
  133. package/dist/tools/browser-fill.d.ts.map +1 -1
  134. package/dist/tools/browser-fill.js +9 -44
  135. package/dist/tools/browser-fill.js.map +1 -1
  136. package/dist/tools/browser-navigate.d.ts +6 -27
  137. package/dist/tools/browser-navigate.d.ts.map +1 -1
  138. package/dist/tools/browser-navigate.js +6 -23
  139. package/dist/tools/browser-navigate.js.map +1 -1
  140. package/dist/tools/browser-run-scenario.d.ts +5 -31
  141. package/dist/tools/browser-run-scenario.d.ts.map +1 -1
  142. package/dist/tools/browser-run-scenario.js +10 -46
  143. package/dist/tools/browser-run-scenario.js.map +1 -1
  144. package/dist/tools/browser-save-scenario.d.ts +3 -28
  145. package/dist/tools/browser-save-scenario.d.ts.map +1 -1
  146. package/dist/tools/browser-save-scenario.js +102 -55
  147. package/dist/tools/browser-save-scenario.js.map +1 -1
  148. package/dist/tools/browser-snapshot.d.ts +6 -39
  149. package/dist/tools/browser-snapshot.d.ts.map +1 -1
  150. package/dist/tools/browser-snapshot.js +4 -31
  151. package/dist/tools/browser-snapshot.js.map +1 -1
  152. package/dist/tools/browser-start-session.d.ts +4 -23
  153. package/dist/tools/browser-start-session.d.ts.map +1 -1
  154. package/dist/tools/browser-start-session.js +38 -51
  155. package/dist/tools/browser-start-session.js.map +1 -1
  156. package/dist/tools/browser-type.d.ts +5 -35
  157. package/dist/tools/browser-type.d.ts.map +1 -1
  158. package/dist/tools/browser-type.js +10 -45
  159. package/dist/tools/browser-type.js.map +1 -1
  160. package/dist/tools/contracts.d.ts +17 -63
  161. package/dist/tools/contracts.d.ts.map +1 -1
  162. package/dist/tools/contracts.js +91 -47
  163. package/dist/tools/contracts.js.map +1 -1
  164. package/dist/tools/cross-pr.d.ts +56 -15
  165. package/dist/tools/cross-pr.d.ts.map +1 -1
  166. package/dist/tools/cross-pr.js +141 -38
  167. package/dist/tools/cross-pr.js.map +1 -1
  168. package/dist/tools/git-diff.d.ts +18 -2
  169. package/dist/tools/git-diff.d.ts.map +1 -1
  170. package/dist/tools/git-diff.js +143 -23
  171. package/dist/tools/git-diff.js.map +1 -1
  172. package/dist/tools/git-history.d.ts +5 -16
  173. package/dist/tools/git-history.d.ts.map +1 -1
  174. package/dist/tools/git-history.js +3 -10
  175. package/dist/tools/git-history.js.map +1 -1
  176. package/dist/tools/history.d.ts +4 -33
  177. package/dist/tools/history.d.ts.map +1 -1
  178. package/dist/tools/history.js +6 -31
  179. package/dist/tools/history.js.map +1 -1
  180. package/dist/tools/impact.d.ts +7 -51
  181. package/dist/tools/impact.d.ts.map +1 -1
  182. package/dist/tools/impact.js +15 -67
  183. package/dist/tools/impact.js.map +1 -1
  184. package/dist/tools/index.d.ts +3 -8
  185. package/dist/tools/index.d.ts.map +1 -1
  186. package/dist/tools/index.js +3 -8
  187. package/dist/tools/index.js.map +1 -1
  188. package/dist/tools/kit.d.ts +66 -113
  189. package/dist/tools/kit.d.ts.map +1 -1
  190. package/dist/tools/kit.js +60 -28
  191. package/dist/tools/kit.js.map +1 -1
  192. package/dist/tools/link-workspace.d.ts +7 -45
  193. package/dist/tools/link-workspace.d.ts.map +1 -1
  194. package/dist/tools/link-workspace.js +10 -48
  195. package/dist/tools/link-workspace.js.map +1 -1
  196. package/dist/tools/lookup.d.ts +4 -14
  197. package/dist/tools/lookup.d.ts.map +1 -1
  198. package/dist/tools/lookup.js +4 -14
  199. package/dist/tools/lookup.js.map +1 -1
  200. package/dist/tools/mark-incident.d.ts +7 -54
  201. package/dist/tools/mark-incident.d.ts.map +1 -1
  202. package/dist/tools/mark-incident.js +15 -68
  203. package/dist/tools/mark-incident.js.map +1 -1
  204. package/dist/tools/observe-runtime.d.ts +27 -210
  205. package/dist/tools/observe-runtime.d.ts.map +1 -1
  206. package/dist/tools/observe-runtime.js +258 -436
  207. package/dist/tools/observe-runtime.js.map +1 -1
  208. package/dist/tools/observe-tests.d.ts +9 -88
  209. package/dist/tools/observe-tests.d.ts.map +1 -1
  210. package/dist/tools/observe-tests.js +34 -108
  211. package/dist/tools/observe-tests.js.map +1 -1
  212. package/dist/tools/pr-analysis.d.ts +18 -2
  213. package/dist/tools/pr-analysis.d.ts.map +1 -1
  214. package/dist/tools/pr-analysis.js +73 -23
  215. package/dist/tools/pr-analysis.js.map +1 -1
  216. package/dist/tools/pre-push.d.ts +94 -9
  217. package/dist/tools/pre-push.d.ts.map +1 -1
  218. package/dist/tools/pre-push.js +139 -34
  219. package/dist/tools/pre-push.js.map +1 -1
  220. package/dist/tools/propagation.d.ts +11 -53
  221. package/dist/tools/propagation.d.ts.map +1 -1
  222. package/dist/tools/propagation.js +14 -57
  223. package/dist/tools/propagation.js.map +1 -1
  224. package/dist/tools/questions.d.ts +13 -63
  225. package/dist/tools/questions.d.ts.map +1 -1
  226. package/dist/tools/questions.js +33 -105
  227. package/dist/tools/questions.js.map +1 -1
  228. package/dist/tools/refusal-fetch.d.ts +4 -40
  229. package/dist/tools/refusal-fetch.d.ts.map +1 -1
  230. package/dist/tools/refusal-fetch.js +4 -40
  231. package/dist/tools/refusal-fetch.js.map +1 -1
  232. package/dist/tools/runtime-incident.d.ts +4 -63
  233. package/dist/tools/runtime-incident.d.ts.map +1 -1
  234. package/dist/tools/runtime-incident.js +10 -87
  235. package/dist/tools/runtime-incident.js.map +1 -1
  236. package/dist/tools/scope.d.ts +7 -25
  237. package/dist/tools/scope.d.ts.map +1 -1
  238. package/dist/tools/scope.js +17 -20
  239. package/dist/tools/scope.js.map +1 -1
  240. package/dist/tools/similar-incidents.d.ts +11 -86
  241. package/dist/tools/similar-incidents.d.ts.map +1 -1
  242. package/dist/tools/similar-incidents.js +7 -71
  243. package/dist/tools/similar-incidents.js.map +1 -1
  244. package/dist/tools/validate.d.ts +31 -47
  245. package/dist/tools/validate.d.ts.map +1 -1
  246. package/dist/tools/validate.js +133 -61
  247. package/dist/tools/validate.js.map +1 -1
  248. package/dist/tools/verification-status.d.ts +9 -64
  249. package/dist/tools/verification-status.d.ts.map +1 -1
  250. package/dist/tools/verification-status.js +9 -62
  251. package/dist/tools/verification-status.js.map +1 -1
  252. package/dist/tools/verify-claim.d.ts +5 -52
  253. package/dist/tools/verify-claim.d.ts.map +1 -1
  254. package/dist/tools/verify-claim.js +6 -56
  255. package/dist/tools/verify-claim.js.map +1 -1
  256. package/dist/transport.d.ts +15 -52
  257. package/dist/transport.d.ts.map +1 -1
  258. package/dist/transport.js +16 -60
  259. package/dist/transport.js.map +1 -1
  260. package/package.json +33 -16
package/dist/registry.js CHANGED
@@ -1,47 +1,8 @@
1
- /**
2
- * How the server reaches adapters without this repository depending on them.
3
- *
4
- * `descry-core` must not import `descry-adapters`: the IR boundary is a
5
- * dependency-direction fact, and an import here would invert it in the one place
6
- * where it matters most — the process that runs everything. So sources are named
7
- * in configuration as module specifiers and loaded at runtime. The engine knows
8
- * `IRSource`; it never knows the word "python".
9
- *
10
- * ## The factory convention, and why it is a convention rather than an interface
11
- *
12
- * Every adapter in `descry-adapters` exports `ADAPTER_ID`, `ADAPTER_VERSION` and
13
- * a factory named `create<Something>Adapter` — `createGoAdapter`,
14
- * `createTypeScriptAdapter`, `createOpenApiAdapter`. There is no uniform name,
15
- * and inventing one now would be a breaking change across twelve packages to
16
- * save a regular expression. So: an explicit `export` in config wins; failing
17
- * that, the single export matching `create*Adapter` is used; **two matches is an
18
- * error, not a coin toss.**
19
- *
20
- * ## Failing to load a source is a disclosure, never a shrug
21
- *
22
- * An adapter that will not import is the difference between "we found no problem
23
- * in your Python service" and "we could not read your Python service" — §20.2
24
- * keeps those in different categories, and a registry that quietly skipped a
25
- * broken specifier would collapse them at the very bottom of the stack, where no
26
- * layer above could ever recover the distinction. Every failure comes back as a
27
- * `SourceLoadFailure` carrying the specifier and the reason, and the caller is
28
- * structurally unable to take the loaded sources without also taking the list of
29
- * ones that are missing.
30
- *
31
- * ## Two places to look, because the server and the repository are not the same tree
32
- *
33
- * `import(spec.module)` resolves relative to *this package's* location. That is
34
- * right for a side-by-side install — `npm i @descryy/mcp @descryy/adapter-x` puts
35
- * both under the repository's own `node_modules` — and useless under `npx -y
36
- * @descryy/mcp <repo>`, where the server runs out of an isolated npx cache
37
- * directory that contains no adapter the user ever installed. So a specifier is
38
- * resolved from the **repository root first** when one is known: that is where the
39
- * user installed the adapter and where their lockfile pins its version. The
40
- * server's own closure stays as the fallback, so the side-by-side install and the
41
- * absolute-path and `file:` specifiers that never needed a repository keep working
42
- * unchanged. When both fail, both are disclosed — a resolution nobody attempted is
43
- * the worst thing to make somebody debug.
44
- */
1
+ /** How the server reaches adapters without depending on them: `descry-core` must never
2
+ * import `descry-adapters` (rule 1, IR boundary) — sources are named as module specifiers
3
+ * in config and loaded at runtime via a `create*Adapter` convention (an ambiguous match
4
+ * errors, never guesses). A failed load is disclosed as `SourceLoadFailure`, never silently
5
+ * skipped (§20.2). Specifiers resolve from the repo root first (npx isolates adapters there), then this package's own closure. */
45
6
  var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
46
7
  if (typeof path === "string" && /^\.\.?\//.test(path)) {
47
8
  return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
@@ -52,19 +13,15 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
52
13
  };
53
14
  import { createRequire } from "node:module";
54
15
  import { join } from "node:path";
55
- import { pathToFileURL } from "node:url";
16
+ import { fileURLToPath, pathToFileURL } from "node:url";
17
+ import { checkModuleTrust, checkRepoResolvedModuleTrust } from "./module-trust.js";
56
18
  const FACTORY_PATTERN = /^create[A-Za-z0-9]*Adapter$/;
57
19
  export function normaliseSpec(entry) {
58
20
  return typeof entry === "string" ? { module: entry } : entry;
59
21
  }
60
- /**
61
- * A loaded module is a `LanguageAdapter` when it can be asked what it supports.
62
- *
63
- * Duck-typed on the two methods that matter rather than on a marker, because the
64
- * adapters are compiled separately and `instanceof` across package boundaries is
65
- * a well-known way to be wrong. `detect` and `capabilities` are the two the
66
- * server actually calls; a source with both is one it can treat as an adapter.
67
- */
22
+ /** A loaded module is a `LanguageAdapter` when it can be asked what it supports. Duck-typed
23
+ * on `detect`/`capabilities` — the two methods the server calls — since `instanceof` across
24
+ * separately-compiled adapter packages is unreliable. */
68
25
  function asAdapter(source) {
69
26
  const candidate = source;
70
27
  return typeof candidate.detect === "function" && typeof candidate.capabilities === "function"
@@ -78,11 +35,8 @@ function describe(error) {
78
35
  }
79
36
  return String(error);
80
37
  }
81
- /**
82
- * @param repoPath Repository being analysed, when one is known. Specifiers are
83
- * resolved from here first; without it only the server's own closure is searched,
84
- * which is correct for callers that name modules by absolute path or `file:` URL.
85
- */
38
+ /** @param repoPath Repo being analysed, when known — specifiers resolve from here first;
39
+ * without it only this package's closure is searched (correct for absolute-path/`file:` callers). */
86
40
  export async function loadSources(entries, repoPath) {
87
41
  const loaded = [];
88
42
  const failed = [];
@@ -97,20 +51,9 @@ export async function loadSources(entries, repoPath) {
97
51
  }
98
52
  return { loaded, failed };
99
53
  }
100
- /**
101
- * Resolve a specifier as the repository itself would, from its own `node_modules`.
102
- *
103
- * `createRequire` anchored at the repository's `package.json` is the resolution a
104
- * script run inside that repository would get. It is CommonJS resolution, so it
105
- * reads `exports` under the `require`/`default` conditions — every adapter here
106
- * publishes a `default`, and one that did not would fall through to the server's
107
- * closure rather than fail the load. The resolved path is imported as a URL, so
108
- * the module itself is still loaded as ESM.
109
- *
110
- * Returns the reason on failure rather than throwing: a specifier the repository
111
- * cannot see is not yet a failure, only a fact worth disclosing if the second
112
- * attempt fails too.
113
- */
54
+ /** Resolves a specifier as the repo's own `node_modules` would, via `createRequire` anchored
55
+ * at its `package.json` (CJS resolution, `require`/`default` conditions), then imports the
56
+ * resolved path as ESM. Returns the reason on failure rather than throwing — not yet a failure until the fallback also fails. */
114
57
  function resolveFromRepo(specifier, repoPath) {
115
58
  try {
116
59
  const require = createRequire(pathToFileURL(join(repoPath, "package.json")));
@@ -145,18 +88,29 @@ async function instantiate(spec, repoPath) {
145
88
  }
146
89
  return { source, adapter: asAdapter(source) };
147
90
  }
148
- /**
149
- * Repository root first, the server's own closure second.
150
- *
151
- * Only a *resolution* failure falls through. A module that resolves and then
152
- * throws while evaluating is that module's failure, and reporting it as "could
153
- * not be found" — or quietly loading a different copy from the server's closure
154
- * instead — would hide a broken adapter behind a wrong explanation.
155
- */
91
+ /** Repository root first, the server's own closure second. Only a resolution failure falls
92
+ * through — a module that resolves and then throws is that module's own failure, not "could not be found". */
156
93
  async function importSource(specifier, repoPath) {
94
+ // A-F1: specifier can come straight from the repo's own .descry/config.json (module-trust.ts).
95
+ // Checked on the raw string before either resolution attempt, since `resolveFromRepo` always
96
+ // turns its result into a `file:` URL regardless of whether the specifier was path-like.
97
+ const trust = checkModuleTrust(specifier);
98
+ if (!trust.allowed)
99
+ throw new Error(trust.reason);
157
100
  const fromRepo = repoPath === undefined ? { reason: "no repository root" } : resolveFromRepo(specifier, repoPath);
158
- if ("url" in fromRepo)
101
+ if ("url" in fromRepo) {
102
+ // A-F1 follow-up: checkModuleTrust only sees the raw specifier, not that it resolves into
103
+ // the repo's own git-tracked node_modules — closes the gap where a hostile repo commits
104
+ // node_modules/<name> and delivers a payload on clone alone; override: DESCRY_ALLOW_TRACKED_NODE_MODULES=1.
105
+ const repoTrust = await checkRepoResolvedModuleTrust({
106
+ specifier,
107
+ repoPath: repoPath,
108
+ resolvedAbsolutePath: fileURLToPath(fromRepo.url),
109
+ });
110
+ if (!repoTrust.allowed)
111
+ throw new Error(repoTrust.reason);
159
112
  return await import(__rewriteRelativeImportExtension(fromRepo.url));
113
+ }
160
114
  try {
161
115
  return await import(__rewriteRelativeImportExtension(specifier));
162
116
  }
@@ -167,15 +121,9 @@ async function importSource(specifier, repoPath) {
167
121
  `(${fromRepo.reason})`, { cause: error });
168
122
  }
169
123
  }
170
- /**
171
- * Ask each loaded adapter whether it claims this repository.
172
- *
173
- * A source that is not a `LanguageAdapter` — the git history reader is the
174
- * standing example — has nothing to detect and always runs. A `detect` that
175
- * throws is treated as "did not detect", **with the reason recorded**: a broken
176
- * detector must not be able to fail the whole run, and must not be able to hide
177
- * either.
178
- */
124
+ /** Asks each loaded adapter whether it claims this repository. A non-`LanguageAdapter`
125
+ * source (the git reader) always runs. A throwing `detect` counts as "did not detect",
126
+ * with the reason recorded — it can't fail the whole run, and can't hide either. */
179
127
  export async function detectSources(sources, root) {
180
128
  const applicable = [];
181
129
  const skipped = [];
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
package/dist/render.d.ts CHANGED
@@ -35,6 +35,20 @@
35
35
  * 4. `class == "action"` returning anything other than a handshake envelope on
36
36
  * the first call → throw (§7) — enforced in `action-handshake.ts` and
37
37
  * `server.ts`, not here: this module never sees a mint, only a redeemed run.
38
+ *
39
+ * ## A fifth invariant, B6: a truncated answer must carry real counts
40
+ *
41
+ * `result.truncated === true` with no `answer.truncatedDetail` used to fall
42
+ * back to a sentinel, `{shown: -1, total: -1}` — chosen to be "unmistakably
43
+ * fake," except that it is a number, so it passes any presence check and then
44
+ * poisons whatever arithmetic reads `total - shown`. A field that lies is
45
+ * worse than a field that is absent, which is the same argument the five
46
+ * result states rest on. So the sentinel is gone: a tool that sets
47
+ * `result.truncated` without a `truncatedDetail` is a programming error,
48
+ * thrown in every environment except production, where the envelope instead
49
+ * reports `truncated: null` plus a disclosure naming the gap — degraded
50
+ * honestly rather than dishonestly precise. See `capped()` in `./capped.ts`
51
+ * for how a tool is meant to avoid ever hitting this.
38
52
  */
39
53
  import { type ReliabilityClass, type ReportCategory } from "@descryy/ir";
40
54
  import type { ResultState, SignalTypeCount, ToolClass } from "@descryy/ir";
@@ -231,6 +245,19 @@ export interface AnswerEnvelope<T = unknown> {
231
245
  readonly tool: string;
232
246
  /** Contract §6, rule 8. A behaviour change is a version bump; recorded with the run. */
233
247
  readonly toolVersion: string;
248
+ /**
249
+ * B10 — this call's own id in `Session#recordedCalls()`, minted before
250
+ * rendering (`Session#allocateCallId`) so it can be carried here rather
251
+ * than only discovered after the fact. A caller reads this off a real
252
+ * reply and cites it in `verify_claim`'s `callId` — the positive path that
253
+ * was previously unreachable because the id used to be minted only when
254
+ * `Session#recordCall` ran, one step after the envelope that would have
255
+ * carried it was already built and sent. Not recorded here — `verify_claim`
256
+ * itself is excluded from `Session#recordCall` (MK-12) and every other
257
+ * path still records under this same value, so the id an agent reads is
258
+ * always the id `recordedCall` will actually find.
259
+ */
260
+ readonly callId: string;
234
261
  readonly state: ResultState;
235
262
  /** DEC-278's three classes — §6's retry table reads this. */
236
263
  readonly class: ToolClass;
@@ -332,13 +359,16 @@ export interface AnswerEnvelope<T = unknown> {
332
359
  */
333
360
  export declare const ANSWER_ENVELOPE_SCHEMA: Record<string, unknown>;
334
361
  /**
335
- * The other shape a `tools/call` can return — `renderToolError`'s.
336
- *
337
- * Declared rather than quietly excluded. A bad argument is the most ordinary
338
- * failure a tool has, it deliberately does not use the five-state envelope
339
- * (see `renderToolError`), and a schema that admitted only the envelope would
340
- * be one the server itself violates on that path. Declaring a union that is
341
- * true beats declaring a single shape that is tidy.
362
+ * The other shape a `tools/call` can return — `renderToolError`'s, now
363
+ * narrowed to the two cases where no tool was ever resolved (`name` not a
364
+ * string, or a name the registry does not have): there is no `ToolDefinition`
365
+ * to draw a real envelope from. A bad argument against a *resolved* tool goes
366
+ * through `renderRefusedInput` instead and is a real `state: "refused"`
367
+ * envelope — see that function's doc.
368
+ *
369
+ * Declared rather than quietly excluded. A schema that admitted only the
370
+ * envelope would be one the server itself violates on this narrower path.
371
+ * Declaring a union that is true beats declaring a single shape that is tidy.
342
372
  */
343
373
  export declare const TOOL_ERROR_SCHEMA: Record<string, unknown>;
344
374
  /**
@@ -360,6 +390,16 @@ export interface RenderOptions {
360
390
  readonly toolTier: ToolTier;
361
391
  readonly elapsedMs: number;
362
392
  readonly limitMs: number;
393
+ /**
394
+ * B10 — the id this call will be recorded under, minted by
395
+ * `Session#allocateCallId()` before `renderAnswer` runs so it can be
396
+ * threaded into the envelope's own `callId`. Optional so every direct
397
+ * `renderAnswer` call in a test — none of which has a session's id
398
+ * sequence to draw from, and none of which asserts on `callId` — keeps
399
+ * compiling unchanged; a random id fills the gap there. `server.ts` is the
400
+ * one caller for which this matters and it always supplies a real one.
401
+ */
402
+ readonly callId?: string;
363
403
  /**
364
404
  * This connection's record of which standing disclosures it has already been
365
405
  * given in full. Optional: a caller with no session to dedupe within (every
@@ -389,18 +429,46 @@ export interface RenderOptions {
389
429
  */
390
430
  export declare function renderAnswer<T>(tool: string, answer: ToolAnswer<T>, options: RenderOptions): CallToolResult;
391
431
  /**
392
- * A failure that is the caller's to fix — a bad argument, a missing graph.
432
+ * A malformed call the server cannot even attribute to one tool — the RPC
433
+ * named no string tool, or named a tool that does not exist in the registry.
393
434
  *
394
435
  * Returned as a tool result with `isError`, not as a JSON-RPC error, which is
395
436
  * what the MCP spec asks for: protocol errors are for malformed protocol, tool
396
437
  * errors are for tools, and an agent can act on the second only if it arrives as
397
438
  * content it can read.
398
439
  *
399
- * Deliberately outside the five-state envelope: a bad argument is not a
400
- * statement about what Descry found or could not find, it is "fix your call
401
- * and retry" — a different kind of thing than `refused`/`failed`.
440
+ * Deliberately outside the five-state envelope, and narrowly so: there is no
441
+ * resolved `ToolDefinition` here to draw `toolVersion`/`class`/`tier` from, so
442
+ * no real envelope can be built — inventing placeholder values for them would
443
+ * be worse than the bare shape. Once a tool *is* identified, a bad argument
444
+ * against it is `renderRefusedInput`'s case, not this one — see that
445
+ * function's doc for why the two are different claims.
402
446
  */
403
447
  export declare function renderToolError(tool: string, message: string): CallToolResult;
448
+ /**
449
+ * `state: "refused"` — the call named a real, resolved tool, but its input
450
+ * was wrong, so the tool never ran (`ToolInputError`, thrown by a tool's own
451
+ * argument reading, or by the dispatcher's own shape check on `arguments`
452
+ * once a tool is known).
453
+ *
454
+ * This used to fall through to `renderToolError`'s bare `{tool, status,
455
+ * message}` shape — measured as a real defect (a live `observe_runtime` call
456
+ * with a malformed `profile` field returned that bare shape instead of an
457
+ * envelope), because unlike the two cases `renderToolError` still covers, a
458
+ * `ToolDefinition` *is* available here: `toolVersion`, `class` and `tier` are
459
+ * all real, so a real envelope can be built rather than invented. "The tool
460
+ * was never run because its input was wrong" is a fact about this call, not
461
+ * about the code being examined — exactly what `state: "refused"` already
462
+ * means everywhere else in this file, so it is rendered the same way rather
463
+ * than through a second, parallel shape.
464
+ *
465
+ * `data` is always `null` (§2.2): nothing ran, so there is nothing to stamp.
466
+ * `isError` stays `true` for the same reason `renderFailed`/`renderTimedOut`
467
+ * set it — a generic client that only reads the transport-level signal still
468
+ * sees a failure; an AI-layer-aware caller additionally gets the real
469
+ * `state`/`disclosures`/`reportCategory` to reason about.
470
+ */
471
+ export declare function renderRefusedInput(tool: string, message: string, options: RenderOptions): CallToolResult;
404
472
  /**
405
473
  * `state: "failed"` — §1.1: "promoted from a transport error to a result."
406
474
  *
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAQL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAmB,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,UAAU,qCAAsC,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAC;IACnC,yEAAyE;IACzE,QAAQ,CAAC,kBAAkB,EAAE,KAAK,CAAC;CACpC;AASD,MAAM,WAAW,gBAAgB;IAC/B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,sBAAsB,EAAE,eAAe,CAAC;CAClD;AAED,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,iBAAiB,CAAC;IAC7C;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,gBAAgB,CAAC;IAC5C;;;;;;;;OAQG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACzG;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,QAAS,CAAC;AAEtC;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ,CAAC,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,6EAA6E;IAC7E,QAAQ,CAAC,eAAe,CAAC,EAAE,gBAAgB,CAAC;CAC7C;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc,CAAC,CAAC,GAAG,OAAO;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wFAAwF;IACxF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,kGAAkG;IAClG,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,4EAA4E;QAC5E,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;QACxC,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAC;KAC3C,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC5C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzG,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,sFAAsF;IACtF,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;IAC/C,mEAAmE;IACnE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;CACjC;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAgI1D,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAYrD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAGtD,CAAC;AAEF,qBAAa,eAAgB,SAAQ,KAAK;gBAC5B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAuCD;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,EACrB,OAAO,EAAE,aAAa,GACrB,cAAc,CA4GhB;AAoDD;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAM7E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,GACrB,cAAc,CA4BhB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,cAAc,CA8BhB;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc,CA+BnF"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
package/dist/render.js CHANGED
@@ -35,7 +35,22 @@
35
35
  * 4. `class == "action"` returning anything other than a handshake envelope on
36
36
  * the first call → throw (§7) — enforced in `action-handshake.ts` and
37
37
  * `server.ts`, not here: this module never sees a mint, only a redeemed run.
38
+ *
39
+ * ## A fifth invariant, B6: a truncated answer must carry real counts
40
+ *
41
+ * `result.truncated === true` with no `answer.truncatedDetail` used to fall
42
+ * back to a sentinel, `{shown: -1, total: -1}` — chosen to be "unmistakably
43
+ * fake," except that it is a number, so it passes any presence check and then
44
+ * poisons whatever arithmetic reads `total - shown`. A field that lies is
45
+ * worse than a field that is absent, which is the same argument the five
46
+ * result states rest on. So the sentinel is gone: a tool that sets
47
+ * `result.truncated` without a `truncatedDetail` is a programming error,
48
+ * thrown in every environment except production, where the envelope instead
49
+ * reports `truncated: null` plus a disclosure naming the gap — degraded
50
+ * honestly rather than dishonestly precise. See `capped()` in `./capped.ts`
51
+ * for how a tool is meant to avoid ever hitting this.
38
52
  */
53
+ import { randomUUID } from "node:crypto";
39
54
  import { RELIABILITY_CLASSES, REPORT_CATEGORIES, RESULT_STATES, TOOL_CLASSES, reliabilityCap, reliabilityDisclosure, reportCategory as deriveReportCategory, } from "@descryy/ir";
40
55
  /**
41
56
  * MK-5 — which of the sixteen tools states a conclusion about the user's code
@@ -136,6 +151,11 @@ export const ANSWER_ENVELOPE_SCHEMA = {
136
151
  type: "string",
137
152
  description: "Bumped on any behaviour change; recorded with the run.",
138
153
  },
154
+ callId: {
155
+ type: "string",
156
+ description: "This call's own id in this session's recorded tool calls. Cite it in verify_claim's " +
157
+ "\"callId\" to check a claim against this exact call's real result.",
158
+ },
139
159
  state: {
140
160
  type: "string",
141
161
  enum: [...RESULT_STATES],
@@ -233,6 +253,7 @@ export const ANSWER_ENVELOPE_SCHEMA = {
233
253
  required: [
234
254
  "tool",
235
255
  "toolVersion",
256
+ "callId",
236
257
  "state",
237
258
  "class",
238
259
  "headline",
@@ -247,13 +268,16 @@ export const ANSWER_ENVELOPE_SCHEMA = {
247
268
  ],
248
269
  };
249
270
  /**
250
- * The other shape a `tools/call` can return — `renderToolError`'s.
271
+ * The other shape a `tools/call` can return — `renderToolError`'s, now
272
+ * narrowed to the two cases where no tool was ever resolved (`name` not a
273
+ * string, or a name the registry does not have): there is no `ToolDefinition`
274
+ * to draw a real envelope from. A bad argument against a *resolved* tool goes
275
+ * through `renderRefusedInput` instead and is a real `state: "refused"`
276
+ * envelope — see that function's doc.
251
277
  *
252
- * Declared rather than quietly excluded. A bad argument is the most ordinary
253
- * failure a tool has, it deliberately does not use the five-state envelope
254
- * (see `renderToolError`), and a schema that admitted only the envelope would
255
- * be one the server itself violates on that path. Declaring a union that is
256
- * true beats declaring a single shape that is tidy.
278
+ * Declared rather than quietly excluded. A schema that admitted only the
279
+ * envelope would be one the server itself violates on this narrower path.
280
+ * Declaring a union that is true beats declaring a single shape that is tidy.
257
281
  */
258
282
  export const TOOL_ERROR_SCHEMA = {
259
283
  type: "object",
@@ -342,6 +366,26 @@ export function renderAnswer(tool, answer, options) {
342
366
  '"we found nothing" from "we could not look" from "something broke"; with no reason attached ' +
343
367
  "this reply says none of them.");
344
368
  }
369
+ // B6, fifth invariant (module header): a truncated answer must carry real
370
+ // counts. The old fallback here was a sentinel, `{shown: -1, total: -1}` —
371
+ // worse than absent, because it passes a presence check and then poisons
372
+ // arithmetic. A tool that sets `result.truncated` without supplying
373
+ // `answer.truncatedDetail` has not held the two together the way
374
+ // `capped()` (`./capped.ts`) makes automatic, so this is a defect in that
375
+ // tool, caught here rather than shipped: thrown everywhere except
376
+ // production, where the honest degradation is `null` plus a disclosure
377
+ // that the count itself is unavailable — never a fabricated one.
378
+ let missingTruncationDetail = null;
379
+ if (result.truncated && answer.truncatedDetail === undefined) {
380
+ if (process.env["NODE_ENV"] !== "production") {
381
+ throw new DisclosureError(`${tool} set result.truncated without a truncatedDetail (shown/total). Build the capped ` +
382
+ 'slice and its detail together — see capped() in "./capped.ts" — rather than capping ' +
383
+ "and reporting separately, where one of the two can be forgotten.");
384
+ }
385
+ missingTruncationDetail =
386
+ "this reply was truncated, but how much was withheld is unavailable — a defect in this " +
387
+ "tool, not a fact about your code";
388
+ }
345
389
  const resolutionFloor = result.stamp.resolutionFloor;
346
390
  const cap = reliabilityCap(resolutionFloor, nameLevel);
347
391
  // Full the first time this connection meets this category, a short reference
@@ -350,6 +394,7 @@ export function renderAnswer(tool, answer, options) {
350
394
  const reliability = reliabilityDisclosure(resolutionFloor, nameLevel);
351
395
  const disclosures = [
352
396
  ...result.notes,
397
+ ...(missingTruncationDetail === null ? [] : [missingTruncationDetail]),
353
398
  options.disclosureLedger?.firstSighting(reliability.key) === false
354
399
  ? reliability.brief
355
400
  : reliability.full,
@@ -360,9 +405,15 @@ export function renderAnswer(tool, answer, options) {
360
405
  ]
361
406
  : []),
362
407
  ];
408
+ // B10 — minted by the caller before this call, so it is threaded through
409
+ // rather than generated here; a fallback exists only for the direct callers
410
+ // (tests) that have no session id sequence to draw from. See `callId`'s own
411
+ // doc on `AnswerEnvelope` and `RenderOptions`.
412
+ const callId = options.callId ?? randomUUID();
363
413
  const build = (data, extraNotes, fitTruncation) => ({
364
414
  tool,
365
415
  toolVersion: options.toolVersion,
416
+ callId,
366
417
  state,
367
418
  class: options.toolClass,
368
419
  headline: answer.headline,
@@ -376,10 +427,7 @@ export function renderAnswer(tool, answer, options) {
376
427
  resolutionFloor,
377
428
  reliabilityCap: cap,
378
429
  },
379
- truncated: fitTruncation ??
380
- (!result.truncated
381
- ? null
382
- : (answer.truncatedDetail ?? { shown: -1, total: -1, more: null })),
430
+ truncated: fitTruncation ?? (!result.truncated ? null : (answer.truncatedDetail ?? null)),
383
431
  refusals: answer.refusalSummary ?? null,
384
432
  budget: { elapsedMs: options.elapsedMs, limitMs: options.limitMs },
385
433
  // The fit's own notes go first among the disclosures it added, ahead of
@@ -464,16 +512,20 @@ function narrate(envelope) {
464
512
  return lines.join("\n");
465
513
  }
466
514
  /**
467
- * A failure that is the caller's to fix — a bad argument, a missing graph.
515
+ * A malformed call the server cannot even attribute to one tool — the RPC
516
+ * named no string tool, or named a tool that does not exist in the registry.
468
517
  *
469
518
  * Returned as a tool result with `isError`, not as a JSON-RPC error, which is
470
519
  * what the MCP spec asks for: protocol errors are for malformed protocol, tool
471
520
  * errors are for tools, and an agent can act on the second only if it arrives as
472
521
  * content it can read.
473
522
  *
474
- * Deliberately outside the five-state envelope: a bad argument is not a
475
- * statement about what Descry found or could not find, it is "fix your call
476
- * and retry" — a different kind of thing than `refused`/`failed`.
523
+ * Deliberately outside the five-state envelope, and narrowly so: there is no
524
+ * resolved `ToolDefinition` here to draw `toolVersion`/`class`/`tier` from, so
525
+ * no real envelope can be built — inventing placeholder values for them would
526
+ * be worse than the bare shape. Once a tool *is* identified, a bad argument
527
+ * against it is `renderRefusedInput`'s case, not this one — see that
528
+ * function's doc for why the two are different claims.
477
529
  */
478
530
  export function renderToolError(tool, message) {
479
531
  return {
@@ -482,6 +534,63 @@ export function renderToolError(tool, message) {
482
534
  isError: true,
483
535
  };
484
536
  }
537
+ /**
538
+ * `state: "refused"` — the call named a real, resolved tool, but its input
539
+ * was wrong, so the tool never ran (`ToolInputError`, thrown by a tool's own
540
+ * argument reading, or by the dispatcher's own shape check on `arguments`
541
+ * once a tool is known).
542
+ *
543
+ * This used to fall through to `renderToolError`'s bare `{tool, status,
544
+ * message}` shape — measured as a real defect (a live `observe_runtime` call
545
+ * with a malformed `profile` field returned that bare shape instead of an
546
+ * envelope), because unlike the two cases `renderToolError` still covers, a
547
+ * `ToolDefinition` *is* available here: `toolVersion`, `class` and `tier` are
548
+ * all real, so a real envelope can be built rather than invented. "The tool
549
+ * was never run because its input was wrong" is a fact about this call, not
550
+ * about the code being examined — exactly what `state: "refused"` already
551
+ * means everywhere else in this file, so it is rendered the same way rather
552
+ * than through a second, parallel shape.
553
+ *
554
+ * `data` is always `null` (§2.2): nothing ran, so there is nothing to stamp.
555
+ * `isError` stays `true` for the same reason `renderFailed`/`renderTimedOut`
556
+ * set it — a generic client that only reads the transport-level signal still
557
+ * sees a failure; an AI-layer-aware caller additionally gets the real
558
+ * `state`/`disclosures`/`reportCategory` to reason about.
559
+ */
560
+ export function renderRefusedInput(tool, message, options) {
561
+ const envelope = {
562
+ tool,
563
+ toolVersion: options.toolVersion,
564
+ callId: options.callId ?? randomUUID(),
565
+ state: "refused",
566
+ class: options.toolClass,
567
+ headline: `${tool} could not run: ${message}`,
568
+ data: null,
569
+ graph: {
570
+ commitSha: null,
571
+ builtAt: null,
572
+ irSchemaVersion: 0,
573
+ resolutionFloor: null,
574
+ reliabilityCap: "C",
575
+ },
576
+ truncated: null,
577
+ refusals: null,
578
+ budget: { elapsedMs: options.elapsedMs, limitMs: options.limitMs },
579
+ disclosures: [message],
580
+ // Same rule `deriveEnvelopeCategory` applies everywhere else: a
581
+ // conclusion-tier tool states its verdict in `headline`'s own words, so
582
+ // this stays null there; an evidence-tier tool's refusal maps to "not
583
+ // analysable" — "could not look" either way, whether the graph refused
584
+ // the query or the call never reached the graph at all.
585
+ reportCategory: options.toolTier === "conclusion" ? null : "not analysable",
586
+ provenance: PROVENANCE,
587
+ };
588
+ return {
589
+ content: [{ type: "text", text: narrate(envelope) }],
590
+ structuredContent: envelope,
591
+ isError: true,
592
+ };
593
+ }
485
594
  /**
486
595
  * `state: "failed"` — §1.1: "promoted from a transport error to a result."
487
596
  *
@@ -497,6 +606,7 @@ export function renderFailed(tool, message, options) {
497
606
  const envelope = {
498
607
  tool,
499
608
  toolVersion: options.toolVersion,
609
+ callId: options.callId ?? randomUUID(),
500
610
  state: "failed",
501
611
  class: options.toolClass,
502
612
  headline: `${tool} failed.`,
@@ -540,6 +650,7 @@ export function renderHandshake(tool, token, willDo, options) {
540
650
  const envelope = {
541
651
  tool,
542
652
  toolVersion: options.toolVersion,
653
+ callId: options.callId ?? randomUUID(),
543
654
  state: "ok",
544
655
  class: options.toolClass,
545
656
  headline: `Confirmation required: ${willDo}`,
@@ -580,6 +691,7 @@ export function renderTimedOut(tool, options) {
580
691
  const envelope = {
581
692
  tool,
582
693
  toolVersion: options.toolVersion,
694
+ callId: options.callId ?? randomUUID(),
583
695
  state: "timed_out",
584
696
  class: options.toolClass,
585
697
  headline: `${tool} timed out.`,