@descryy/core 0.1.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 (366) hide show
  1. package/LICENSE +21 -0
  2. package/dist/capabilities/index.d.ts +3 -0
  3. package/dist/capabilities/index.d.ts.map +1 -0
  4. package/dist/capabilities/index.js +2 -0
  5. package/dist/capabilities/index.js.map +1 -0
  6. package/dist/capabilities/preconditions.d.ts +99 -0
  7. package/dist/capabilities/preconditions.d.ts.map +1 -0
  8. package/dist/capabilities/preconditions.js +94 -0
  9. package/dist/capabilities/preconditions.js.map +1 -0
  10. package/dist/contracts/engine.d.ts +90 -0
  11. package/dist/contracts/engine.d.ts.map +1 -0
  12. package/dist/contracts/engine.js +291 -0
  13. package/dist/contracts/engine.js.map +1 -0
  14. package/dist/contracts/index.d.ts +9 -0
  15. package/dist/contracts/index.d.ts.map +1 -0
  16. package/dist/contracts/index.js +5 -0
  17. package/dist/contracts/index.js.map +1 -0
  18. package/dist/contracts/orphans.d.ts +96 -0
  19. package/dist/contracts/orphans.d.ts.map +1 -0
  20. package/dist/contracts/orphans.js +241 -0
  21. package/dist/contracts/orphans.js.map +1 -0
  22. package/dist/contracts/paths.d.ts +132 -0
  23. package/dist/contracts/paths.d.ts.map +1 -0
  24. package/dist/contracts/paths.js +245 -0
  25. package/dist/contracts/paths.js.map +1 -0
  26. package/dist/contracts/shapes.d.ts +99 -0
  27. package/dist/contracts/shapes.d.ts.map +1 -0
  28. package/dist/contracts/shapes.js +196 -0
  29. package/dist/contracts/shapes.js.map +1 -0
  30. package/dist/governance/budget.d.ts +89 -0
  31. package/dist/governance/budget.d.ts.map +1 -0
  32. package/dist/governance/budget.js +101 -0
  33. package/dist/governance/budget.js.map +1 -0
  34. package/dist/governance/candidate-boundary.d.ts +49 -0
  35. package/dist/governance/candidate-boundary.d.ts.map +1 -0
  36. package/dist/governance/candidate-boundary.js +51 -0
  37. package/dist/governance/candidate-boundary.js.map +1 -0
  38. package/dist/governance/escalation.d.ts +63 -0
  39. package/dist/governance/escalation.d.ts.map +1 -0
  40. package/dist/governance/escalation.js +72 -0
  41. package/dist/governance/escalation.js.map +1 -0
  42. package/dist/governance/fact-boundary.d.ts +77 -0
  43. package/dist/governance/fact-boundary.d.ts.map +1 -0
  44. package/dist/governance/fact-boundary.js +91 -0
  45. package/dist/governance/fact-boundary.js.map +1 -0
  46. package/dist/governance/finding-funnel.d.ts +109 -0
  47. package/dist/governance/finding-funnel.d.ts.map +1 -0
  48. package/dist/governance/finding-funnel.js +137 -0
  49. package/dist/governance/finding-funnel.js.map +1 -0
  50. package/dist/governance/index.d.ts +11 -0
  51. package/dist/governance/index.d.ts.map +1 -0
  52. package/dist/governance/index.js +6 -0
  53. package/dist/governance/index.js.map +1 -0
  54. package/dist/graph/build.d.ts +127 -0
  55. package/dist/graph/build.d.ts.map +1 -0
  56. package/dist/graph/build.js +0 -0
  57. package/dist/graph/build.js.map +1 -0
  58. package/dist/graph/cross-language.d.ts +70 -0
  59. package/dist/graph/cross-language.d.ts.map +1 -0
  60. package/dist/graph/cross-language.js +104 -0
  61. package/dist/graph/cross-language.js.map +1 -0
  62. package/dist/graph/index.d.ts +11 -0
  63. package/dist/graph/index.d.ts.map +1 -0
  64. package/dist/graph/index.js +6 -0
  65. package/dist/graph/index.js.map +1 -0
  66. package/dist/graph/merge.d.ts +95 -0
  67. package/dist/graph/merge.d.ts.map +1 -0
  68. package/dist/graph/merge.js +131 -0
  69. package/dist/graph/merge.js.map +1 -0
  70. package/dist/graph/persist.d.ts +42 -0
  71. package/dist/graph/persist.d.ts.map +1 -0
  72. package/dist/graph/persist.js +52 -0
  73. package/dist/graph/persist.js.map +1 -0
  74. package/dist/graph/runtime-confirmation.d.ts +169 -0
  75. package/dist/graph/runtime-confirmation.d.ts.map +1 -0
  76. package/dist/graph/runtime-confirmation.js +318 -0
  77. package/dist/graph/runtime-confirmation.js.map +1 -0
  78. package/dist/index.d.ts +18 -0
  79. package/dist/index.d.ts.map +1 -0
  80. package/dist/index.js +19 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/ledger/index.d.ts +5 -0
  83. package/dist/ledger/index.d.ts.map +1 -0
  84. package/dist/ledger/index.js +3 -0
  85. package/dist/ledger/index.js.map +1 -0
  86. package/dist/ledger/mint.d.ts +81 -0
  87. package/dist/ledger/mint.d.ts.map +1 -0
  88. package/dist/ledger/mint.js +138 -0
  89. package/dist/ledger/mint.js.map +1 -0
  90. package/dist/ledger/resolve.d.ts +124 -0
  91. package/dist/ledger/resolve.d.ts.map +1 -0
  92. package/dist/ledger/resolve.js +290 -0
  93. package/dist/ledger/resolve.js.map +1 -0
  94. package/dist/multipr/fingerprint.d.ts +56 -0
  95. package/dist/multipr/fingerprint.d.ts.map +1 -0
  96. package/dist/multipr/fingerprint.js +169 -0
  97. package/dist/multipr/fingerprint.js.map +1 -0
  98. package/dist/multipr/hidden-dependency.d.ts +120 -0
  99. package/dist/multipr/hidden-dependency.d.ts.map +1 -0
  100. package/dist/multipr/hidden-dependency.js +185 -0
  101. package/dist/multipr/hidden-dependency.js.map +1 -0
  102. package/dist/multipr/index.d.ts +14 -0
  103. package/dist/multipr/index.d.ts.map +1 -0
  104. package/dist/multipr/index.js +8 -0
  105. package/dist/multipr/index.js.map +1 -0
  106. package/dist/multipr/mechanical.d.ts +239 -0
  107. package/dist/multipr/mechanical.d.ts.map +1 -0
  108. package/dist/multipr/mechanical.js +333 -0
  109. package/dist/multipr/mechanical.js.map +1 -0
  110. package/dist/multipr/migration-heads.d.ts +160 -0
  111. package/dist/multipr/migration-heads.d.ts.map +1 -0
  112. package/dist/multipr/migration-heads.js +212 -0
  113. package/dist/multipr/migration-heads.js.map +1 -0
  114. package/dist/multipr/overlap.d.ts +186 -0
  115. package/dist/multipr/overlap.d.ts.map +1 -0
  116. package/dist/multipr/overlap.js +254 -0
  117. package/dist/multipr/overlap.js.map +1 -0
  118. package/dist/multipr/scope-store.d.ts +105 -0
  119. package/dist/multipr/scope-store.d.ts.map +1 -0
  120. package/dist/multipr/scope-store.js +182 -0
  121. package/dist/multipr/scope-store.js.map +1 -0
  122. package/dist/multipr/superseded.d.ts +133 -0
  123. package/dist/multipr/superseded.d.ts.map +1 -0
  124. package/dist/multipr/superseded.js +128 -0
  125. package/dist/multipr/superseded.js.map +1 -0
  126. package/dist/query/confirmed-facts.d.ts +56 -0
  127. package/dist/query/confirmed-facts.d.ts.map +1 -0
  128. package/dist/query/confirmed-facts.js +64 -0
  129. package/dist/query/confirmed-facts.js.map +1 -0
  130. package/dist/query/declared-value-closure.d.ts +126 -0
  131. package/dist/query/declared-value-closure.d.ts.map +1 -0
  132. package/dist/query/declared-value-closure.js +156 -0
  133. package/dist/query/declared-value-closure.js.map +1 -0
  134. package/dist/query/index.d.ts +28 -0
  135. package/dist/query/index.d.ts.map +1 -0
  136. package/dist/query/index.js +15 -0
  137. package/dist/query/index.js.map +1 -0
  138. package/dist/query/memory.d.ts +20 -0
  139. package/dist/query/memory.d.ts.map +1 -0
  140. package/dist/query/memory.js +55 -0
  141. package/dist/query/memory.js.map +1 -0
  142. package/dist/query/provider.d.ts +127 -0
  143. package/dist/query/provider.d.ts.map +1 -0
  144. package/dist/query/provider.js +54 -0
  145. package/dist/query/provider.js.map +1 -0
  146. package/dist/query/queries.d.ts +119 -0
  147. package/dist/query/queries.d.ts.map +1 -0
  148. package/dist/query/queries.js +267 -0
  149. package/dist/query/queries.js.map +1 -0
  150. package/dist/query/refusal-fetch.d.ts +114 -0
  151. package/dist/query/refusal-fetch.d.ts.map +1 -0
  152. package/dist/query/refusal-fetch.js +200 -0
  153. package/dist/query/refusal-fetch.js.map +1 -0
  154. package/dist/query/refusal-questions.d.ts +123 -0
  155. package/dist/query/refusal-questions.d.ts.map +1 -0
  156. package/dist/query/refusal-questions.js +122 -0
  157. package/dist/query/refusal-questions.js.map +1 -0
  158. package/dist/query/root-cause-score.d.ts +218 -0
  159. package/dist/query/root-cause-score.d.ts.map +1 -0
  160. package/dist/query/root-cause-score.js +251 -0
  161. package/dist/query/root-cause-score.js.map +1 -0
  162. package/dist/query/row-closure-picture.d.ts +108 -0
  163. package/dist/query/row-closure-picture.d.ts.map +1 -0
  164. package/dist/query/row-closure-picture.js +131 -0
  165. package/dist/query/row-closure-picture.js.map +1 -0
  166. package/dist/query/similar-incidents.d.ts +76 -0
  167. package/dist/query/similar-incidents.d.ts.map +1 -0
  168. package/dist/query/similar-incidents.js +169 -0
  169. package/dist/query/similar-incidents.js.map +1 -0
  170. package/dist/query/sqlite.d.ts +13 -0
  171. package/dist/query/sqlite.d.ts.map +1 -0
  172. package/dist/query/sqlite.js +54 -0
  173. package/dist/query/sqlite.js.map +1 -0
  174. package/dist/query/traverse.d.ts +110 -0
  175. package/dist/query/traverse.d.ts.map +1 -0
  176. package/dist/query/traverse.js +0 -0
  177. package/dist/query/traverse.js.map +1 -0
  178. package/dist/query/unresolved.d.ts +195 -0
  179. package/dist/query/unresolved.d.ts.map +1 -0
  180. package/dist/query/unresolved.js +225 -0
  181. package/dist/query/unresolved.js.map +1 -0
  182. package/dist/query/verification-status.d.ts +134 -0
  183. package/dist/query/verification-status.d.ts.map +1 -0
  184. package/dist/query/verification-status.js +163 -0
  185. package/dist/query/verification-status.js.map +1 -0
  186. package/dist/recording/index.d.ts +26 -0
  187. package/dist/recording/index.d.ts.map +1 -0
  188. package/dist/recording/index.js +30 -0
  189. package/dist/recording/index.js.map +1 -0
  190. package/dist/recording/migrate.d.ts +22 -0
  191. package/dist/recording/migrate.d.ts.map +1 -0
  192. package/dist/recording/migrate.js +51 -0
  193. package/dist/recording/migrate.js.map +1 -0
  194. package/dist/recording/reader.d.ts +27 -0
  195. package/dist/recording/reader.d.ts.map +1 -0
  196. package/dist/recording/reader.js +55 -0
  197. package/dist/recording/reader.js.map +1 -0
  198. package/dist/recording/redact.d.ts +63 -0
  199. package/dist/recording/redact.d.ts.map +1 -0
  200. package/dist/recording/redact.js +98 -0
  201. package/dist/recording/redact.js.map +1 -0
  202. package/dist/recording/schema.d.ts +41 -0
  203. package/dist/recording/schema.d.ts.map +1 -0
  204. package/dist/recording/schema.js +104 -0
  205. package/dist/recording/schema.js.map +1 -0
  206. package/dist/recording/writer.d.ts +120 -0
  207. package/dist/recording/writer.d.ts.map +1 -0
  208. package/dist/recording/writer.js +81 -0
  209. package/dist/recording/writer.js.map +1 -0
  210. package/dist/scoping/fanout.d.ts +86 -0
  211. package/dist/scoping/fanout.d.ts.map +1 -0
  212. package/dist/scoping/fanout.js +95 -0
  213. package/dist/scoping/fanout.js.map +1 -0
  214. package/dist/scoping/index.d.ts +10 -0
  215. package/dist/scoping/index.d.ts.map +1 -0
  216. package/dist/scoping/index.js +6 -0
  217. package/dist/scoping/index.js.map +1 -0
  218. package/dist/scoping/score.d.ts +83 -0
  219. package/dist/scoping/score.d.ts.map +1 -0
  220. package/dist/scoping/score.js +125 -0
  221. package/dist/scoping/score.js.map +1 -0
  222. package/dist/scoping/tiers.d.ts +32 -0
  223. package/dist/scoping/tiers.d.ts.map +1 -0
  224. package/dist/scoping/tiers.js +35 -0
  225. package/dist/scoping/tiers.js.map +1 -0
  226. package/dist/scoping/traverse.d.ts +60 -0
  227. package/dist/scoping/traverse.d.ts.map +1 -0
  228. package/dist/scoping/traverse.js +172 -0
  229. package/dist/scoping/traverse.js.map +1 -0
  230. package/dist/scoping/weights.d.ts +97 -0
  231. package/dist/scoping/weights.d.ts.map +1 -0
  232. package/dist/scoping/weights.js +167 -0
  233. package/dist/scoping/weights.js.map +1 -0
  234. package/dist/sources/git/diff.d.ts +53 -0
  235. package/dist/sources/git/diff.d.ts.map +1 -0
  236. package/dist/sources/git/diff.js +140 -0
  237. package/dist/sources/git/diff.js.map +1 -0
  238. package/dist/sources/git/env.d.ts +2 -0
  239. package/dist/sources/git/env.d.ts.map +1 -0
  240. package/dist/sources/git/env.js +21 -0
  241. package/dist/sources/git/env.js.map +1 -0
  242. package/dist/sources/git/history.d.ts +140 -0
  243. package/dist/sources/git/history.d.ts.map +1 -0
  244. package/dist/sources/git/history.js +314 -0
  245. package/dist/sources/git/history.js.map +1 -0
  246. package/dist/sources/git/index.d.ts +7 -0
  247. package/dist/sources/git/index.d.ts.map +1 -0
  248. package/dist/sources/git/index.js +4 -0
  249. package/dist/sources/git/index.js.map +1 -0
  250. package/dist/sources/git/source.d.ts +95 -0
  251. package/dist/sources/git/source.d.ts.map +1 -0
  252. package/dist/sources/git/source.js +0 -0
  253. package/dist/sources/git/source.js.map +1 -0
  254. package/dist/sources/migrations/dialects.d.ts +59 -0
  255. package/dist/sources/migrations/dialects.d.ts.map +1 -0
  256. package/dist/sources/migrations/dialects.js +84 -0
  257. package/dist/sources/migrations/dialects.js.map +1 -0
  258. package/dist/sources/migrations/index.d.ts +3 -0
  259. package/dist/sources/migrations/index.d.ts.map +1 -0
  260. package/dist/sources/migrations/index.js +2 -0
  261. package/dist/sources/migrations/index.js.map +1 -0
  262. package/dist/sources/migrations/read.d.ts +113 -0
  263. package/dist/sources/migrations/read.d.ts.map +1 -0
  264. package/dist/sources/migrations/read.js +270 -0
  265. package/dist/sources/migrations/read.js.map +1 -0
  266. package/dist/sources/workspace/index.d.ts +3 -0
  267. package/dist/sources/workspace/index.d.ts.map +1 -0
  268. package/dist/sources/workspace/index.js +2 -0
  269. package/dist/sources/workspace/index.js.map +1 -0
  270. package/dist/sources/workspace/workspace.d.ts +64 -0
  271. package/dist/sources/workspace/workspace.d.ts.map +1 -0
  272. package/dist/sources/workspace/workspace.js +294 -0
  273. package/dist/sources/workspace/workspace.js.map +1 -0
  274. package/dist/store/driver/driver.d.ts +82 -0
  275. package/dist/store/driver/driver.d.ts.map +1 -0
  276. package/dist/store/driver/driver.js +31 -0
  277. package/dist/store/driver/driver.js.map +1 -0
  278. package/dist/store/driver/node-sqlite.d.ts +28 -0
  279. package/dist/store/driver/node-sqlite.d.ts.map +1 -0
  280. package/dist/store/driver/node-sqlite.js +188 -0
  281. package/dist/store/driver/node-sqlite.js.map +1 -0
  282. package/dist/store/index.d.ts +33 -0
  283. package/dist/store/index.d.ts.map +1 -0
  284. package/dist/store/index.js +46 -0
  285. package/dist/store/index.js.map +1 -0
  286. package/dist/store/migrate.d.ts +68 -0
  287. package/dist/store/migrate.d.ts.map +1 -0
  288. package/dist/store/migrate.js +140 -0
  289. package/dist/store/migrate.js.map +1 -0
  290. package/dist/store/reader.d.ts +127 -0
  291. package/dist/store/reader.d.ts.map +1 -0
  292. package/dist/store/reader.js +269 -0
  293. package/dist/store/reader.js.map +1 -0
  294. package/dist/store/schema.d.ts +87 -0
  295. package/dist/store/schema.d.ts.map +1 -0
  296. package/dist/store/schema.js +322 -0
  297. package/dist/store/schema.js.map +1 -0
  298. package/dist/store/writer.d.ts +116 -0
  299. package/dist/store/writer.d.ts.map +1 -0
  300. package/dist/store/writer.js +279 -0
  301. package/dist/store/writer.js.map +1 -0
  302. package/dist/tiers/certify.d.ts +375 -0
  303. package/dist/tiers/certify.d.ts.map +1 -0
  304. package/dist/tiers/certify.js +434 -0
  305. package/dist/tiers/certify.js.map +1 -0
  306. package/dist/tiers/index.d.ts +5 -0
  307. package/dist/tiers/index.d.ts.map +1 -0
  308. package/dist/tiers/index.js +3 -0
  309. package/dist/tiers/index.js.map +1 -0
  310. package/dist/tiers/ladder.d.ts +73 -0
  311. package/dist/tiers/ladder.d.ts.map +1 -0
  312. package/dist/tiers/ladder.js +197 -0
  313. package/dist/tiers/ladder.js.map +1 -0
  314. package/dist/validation/config-graph.d.ts +104 -0
  315. package/dist/validation/config-graph.d.ts.map +1 -0
  316. package/dist/validation/config-graph.js +205 -0
  317. package/dist/validation/config-graph.js.map +1 -0
  318. package/dist/validation/env.d.ts +243 -0
  319. package/dist/validation/env.d.ts.map +1 -0
  320. package/dist/validation/env.js +447 -0
  321. package/dist/validation/env.js.map +1 -0
  322. package/dist/validation/index.d.ts +16 -0
  323. package/dist/validation/index.d.ts.map +1 -0
  324. package/dist/validation/index.js +9 -0
  325. package/dist/validation/index.js.map +1 -0
  326. package/dist/validation/join-substitution.d.ts +186 -0
  327. package/dist/validation/join-substitution.d.ts.map +1 -0
  328. package/dist/validation/join-substitution.js +191 -0
  329. package/dist/validation/join-substitution.js.map +1 -0
  330. package/dist/validation/migrations.d.ts +133 -0
  331. package/dist/validation/migrations.d.ts.map +1 -0
  332. package/dist/validation/migrations.js +315 -0
  333. package/dist/validation/migrations.js.map +1 -0
  334. package/dist/validation/nodes.d.ts +32 -0
  335. package/dist/validation/nodes.d.ts.map +1 -0
  336. package/dist/validation/nodes.js +45 -0
  337. package/dist/validation/nodes.js.map +1 -0
  338. package/dist/validation/rollback.d.ts +124 -0
  339. package/dist/validation/rollback.d.ts.map +1 -0
  340. package/dist/validation/rollback.js +302 -0
  341. package/dist/validation/rollback.js.map +1 -0
  342. package/dist/validation/route-drift.d.ts +108 -0
  343. package/dist/validation/route-drift.d.ts.map +1 -0
  344. package/dist/validation/route-drift.js +103 -0
  345. package/dist/validation/route-drift.js.map +1 -0
  346. package/dist/validation/sources.d.ts +153 -0
  347. package/dist/validation/sources.d.ts.map +1 -0
  348. package/dist/validation/sources.js +409 -0
  349. package/dist/validation/sources.js.map +1 -0
  350. package/dist/worker/index.d.ts +5 -0
  351. package/dist/worker/index.d.ts.map +1 -0
  352. package/dist/worker/index.js +3 -0
  353. package/dist/worker/index.js.map +1 -0
  354. package/dist/worker/pool.d.ts +73 -0
  355. package/dist/worker/pool.d.ts.map +1 -0
  356. package/dist/worker/pool.js +203 -0
  357. package/dist/worker/pool.js.map +1 -0
  358. package/dist/worker/protocol.d.ts +91 -0
  359. package/dist/worker/protocol.d.ts.map +1 -0
  360. package/dist/worker/protocol.js +19 -0
  361. package/dist/worker/protocol.js.map +1 -0
  362. package/dist/worker/traversal.worker.d.ts +25 -0
  363. package/dist/worker/traversal.worker.d.ts.map +1 -0
  364. package/dist/worker/traversal.worker.js +124 -0
  365. package/dist/worker/traversal.worker.js.map +1 -0
  366. package/package.json +29 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * The refusal ledger is three populations, and reporting it as one produced a
3
+ * wrong number that a lane then reasoned from.
4
+ *
5
+ * ## The conflation
6
+ *
7
+ * `UnresolvedRef` records what an adapter saw and could not resolve, and
8
+ * everything filed there reads as a **gap**. Two unrelated things are filed:
9
+ *
10
+ * - An outbound call to a third party, **read perfectly**. There is no endpoint
11
+ * in this workspace for it and there never will be. That is §20.2's *not
12
+ * applicable* — a fact, not a gap.
13
+ * - A call against this workspace's own surface whose target is not statically
14
+ * determinable. That is the gap, and it is *not analysable*.
15
+ *
16
+ * A read-rate census across nine repositories reported **90 edges read against
17
+ * 773 recognised-and-refused, a 10% read rate**, and concluded that `USES_API`
18
+ * resolution was the system's largest deficit. On one repository **115 of 163
19
+ * ledger rows are calls to Microsoft, Zoom, Hitpay and Zoho** — correctly
20
+ * refused, counted as deficit. The deficit there is real and it is 47%, not 20%.
21
+ *
22
+ * ## What running it on real code established, and it is not what was expected
23
+ *
24
+ * **`rawTarget` does not carry the target.** On the reference repository every
25
+ * one of the 64 `USES_API` refusals carries the *callee* — `"fetch"`,
26
+ * `"api.get"`, `"api.post"` — because the URL was an expression the adapter
27
+ * could not evaluate, and the expression text is not what gets filed. So the
28
+ * ledger **cannot** be split from stored data by any engine-side rule, and this
29
+ * module reports all 64 as `undetermined`, which is the correct answer and a
30
+ * useless one.
31
+ *
32
+ * The distinction nevertheless **already exists** — in `reason`, as prose. Two
33
+ * sentence forms account for all 64, and they split it exactly as a hand count
34
+ * of the source did:
35
+ *
36
+ * | `reason` says | count | what it means |
37
+ * | --- | --- | --- |
38
+ * | *"the path is not repository-relative"* | **39** | outbound. A fact |
39
+ * | *"the request path is not a literal or template"* | **25** | the gap |
40
+ *
41
+ * 39 + 25 = 64, and the independent hand count of that repository was 39 outbound
42
+ * and 25 genuinely unread. **The adapter knows which population a refusal is in
43
+ * and says so in a sentence.** Parsing that sentence is not an option: it is
44
+ * free text, it is written per producer, and a consumer that greps it breaks
45
+ * silently the first time one is reworded — the CRLF-stripper failure exactly.
46
+ *
47
+ * So the conclusion is the opposite of this module's premise: **the
48
+ * discriminator has to be a field**, and this module is the evidence for that
49
+ * rather than a substitute for it. It classifies what the text can carry, and
50
+ * discloses everything it cannot, which is what makes the gap measurable.
51
+ *
52
+ * ## Why the field is still not added here
53
+ *
54
+ * The `category` discriminator is the right end state and is deliberately **not**
55
+ * added here, for two reasons that are the same reason:
56
+ *
57
+ * 1. **No adapter would set it today.** Shipping a consumer that reads a carrier
58
+ * no producer emits is exactly the defect DEC-112 names, and it has already
59
+ * cost this project three checks that were dead on every real repository. A
60
+ * field added ahead of its producer is a dead carrier however obviously
61
+ * correct it looks — so the field lands with an adapter emitting it, not
62
+ * before.
63
+ * 2. **The storage column needs the migration policy** that is still open
64
+ * (architecture §32). An engine-side classifier needs neither, works on graphs
65
+ * already written, and turns the IR change into a request backed by measured
66
+ * populations rather than a speculative one.
67
+ *
68
+ * ## DEC-242 landed, and this module now defers to it where it can
69
+ *
70
+ * The heuristic above is what this module reasoned its way to before a
71
+ * discriminator field existed. It now does: `attrs.refusalClass` (DEC-242),
72
+ * producer-declared and persisted (the store gained a real `attrs` column
73
+ * for it — DEC-224). `classifyRefusal` checks `refusalClass === "out-of-scope"`
74
+ * first and trusts it outright, ahead of the text heuristic below — a
75
+ * producer that resolved the target and declared it out of scope did real
76
+ * analysis, which is better evidence than this module re-deriving the same
77
+ * fact from `rawTarget` text. DEC-242's other three classes
78
+ * (`value-unknown`, `capability-gap`, `varies-per-call`) answer a different
79
+ * question — whether a human sentence could close the row — and say nothing
80
+ * about scope, so they and an unset field both fall through to the
81
+ * unchanged heuristic rather than being read as "not out-of-scope." Every
82
+ * row written before DEC-242 shipped is graded exactly as it always was.
83
+ *
84
+ * The practical consequence, per DEC-242's own note: any future recall
85
+ * figure computed over `unresolved.length` must exclude `refusalClass ===
86
+ * "out-of-scope"` rows from its deficit denominator, the same way
87
+ * `readRate` below already excludes this module's own `outOfScope`
88
+ * verdict — measured at 3 of ~215 rows on the corpora checked so far
89
+ * (DEC-260), small today and not distorting any published number, but
90
+ * expressible now in a way it was not before the field existed.
91
+ *
92
+ * ## The third population is the point
93
+ *
94
+ * A ledger row whose target is a runtime value cannot be classified either way:
95
+ * `fetch(url)` may be outbound or internal and the text does not say. Several
96
+ * such rows on the census repository turned out to be outbound, discovered by
97
+ * hand. **So this returns three counts and refuses to return one rate.** Folding
98
+ * `undetermined` into either side is the same error one level down — the whole
99
+ * defect was a denominator that quietly absorbed a population it should have
100
+ * disclosed.
101
+ */
102
+ import type { UnresolvedRef } from "@descryy/ir";
103
+ /**
104
+ * `outOfScope` — read correctly, targets something this workspace does not
105
+ * serve. `unreadable` — recognised, target not determinable. `undetermined` —
106
+ * the evidence does not say, and pretending otherwise is what produced the
107
+ * wrong number in the first place.
108
+ */
109
+ export type RefusalClass = "outOfScope" | "unreadable" | "undetermined";
110
+ export interface RefusalScope {
111
+ /**
112
+ * Hosts this workspace serves. An absolute target on one of these is
113
+ * *internal* and therefore a genuine gap, not an outbound call.
114
+ *
115
+ * Empty means "no host is known to be ours", which is honest rather than
116
+ * convenient: with no known host every absolute target classifies as
117
+ * `outOfScope`, so a caller that has hosts and does not pass them will
118
+ * understate its own deficit. `classifyRefusals` reports `scopeKnown` so that
119
+ * cannot happen silently.
120
+ */
121
+ readonly internalHosts?: readonly string[];
122
+ }
123
+ /**
124
+ * Classify one refusal.
125
+ *
126
+ * **A producer's own `attrs.refusalClass: "out-of-scope"` (DEC-242) is
127
+ * trusted directly, ahead of everything below.** DEC-242 landed after this
128
+ * module's own heuristic did, and it is strictly better evidence for the same
129
+ * question: a producer that read the call, resolved the target, and declared
130
+ * it out of scope did real analysis (Lane F's DEC-260 origin check, for one),
131
+ * where this module's `hostOf`/`isOpaque` pair is inference from `rawTarget`
132
+ * text alone. Rule 3's "declared beats re-derived" reordering, not a new rule.
133
+ *
134
+ * **A row with no `refusalClass`, or one of DEC-242's other three values
135
+ * (`value-unknown`, `capability-gap`, `varies-per-call`), falls through to
136
+ * the text heuristic unchanged — a deliberate choice, not an oversight.**
137
+ * Those three classes answer "is a human sentence enough to close this row,"
138
+ * a different question from "is this target inside or outside the
139
+ * workspace," and none of them says a row is or is not out of scope; reading
140
+ * absence as "therefore not out-of-scope" would be exactly the silent
141
+ * behaviour change this module's own module-header history warns against.
142
+ * Every row written before DEC-242 shipped, and every row a producer has not
143
+ * classified yet, is graded identically to how it always was.
144
+ *
145
+ * **Below that: absolute target on a host that is not ours → `outOfScope`.**
146
+ * The only positive classification made here from text alone, so it is as
147
+ * reliable as the text. Everything else is `unreadable` when it looks like a
148
+ * path this workspace could serve, and `undetermined` when the target says
149
+ * nothing about where the call goes.
150
+ */
151
+ export declare function classifyRefusal(ref: UnresolvedRef, scope?: RefusalScope): RefusalClass;
152
+ export interface RefusalCensus {
153
+ readonly total: number;
154
+ readonly outOfScope: number;
155
+ readonly unreadable: number;
156
+ readonly undetermined: number;
157
+ /**
158
+ * False when the caller supplied no internal hosts. Every absolute target is
159
+ * then `outOfScope`, which **understates the deficit**, and a report that does
160
+ * not say so is making a claim it cannot support.
161
+ */
162
+ readonly scopeKnown: boolean;
163
+ /** Hosts seen on absolute targets, most frequent first — the evidence for `internalHosts`. */
164
+ readonly hosts: readonly {
165
+ readonly host: string;
166
+ readonly count: number;
167
+ }[];
168
+ }
169
+ export declare function classifyRefusals(refs: readonly UnresolvedRef[], scope?: RefusalScope): RefusalCensus;
170
+ /**
171
+ * Two rates and a disclosure, never one number.
172
+ *
173
+ * `overRecognised` is the census's original figure and it is kept because
174
+ * deleting a published number is worse than captioning it. `overInternal` is
175
+ * the one that describes the analyser's actual deficit. **Both are `null` when
176
+ * their denominator is zero** — `decisions()`'s rule, one level out: a rate over
177
+ * nothing is not 0% and not 100%, it is undefined, and returning a number there
178
+ * is how a dead component scores well.
179
+ */
180
+ export interface ReadRate {
181
+ readonly read: number;
182
+ readonly census: RefusalCensus;
183
+ /** read / (read + every refusal). Understates the analyser by counting facts as gaps. */
184
+ readonly overRecognised: number | null;
185
+ /** read / (read + refusals that could plausibly be ours). The deficit that is actually ours. */
186
+ readonly overInternal: number | null;
187
+ /**
188
+ * Why the two differ, and what neither of them settles. Always non-empty when
189
+ * the numbers differ, because the gap between them is exactly the thing a
190
+ * single figure hid.
191
+ */
192
+ readonly disclosure: readonly string[];
193
+ }
194
+ export declare function readRate(read: number, refs: readonly UnresolvedRef[], scope?: RefusalScope): ReadRate;
195
+ //# sourceMappingURL=unresolved.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unresolved.d.ts","sourceRoot":"","sources":["../../src/query/unresolved.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,cAAc,CAAC;AAExE,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;OASG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAiCD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,GAAE,YAAiB,GAAG,YAAY,CAQ1F;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,8FAA8F;IAC9F,QAAQ,CAAC,KAAK,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9E;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,aAAa,EAAE,EAC9B,KAAK,GAAE,YAAiB,GACvB,aAAa,CAgBf;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,yFAAyF;IACzF,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,gGAAgG;IAChG,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,wBAAgB,QAAQ,CACtB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,aAAa,EAAE,EAC9B,KAAK,GAAE,YAAiB,GACvB,QAAQ,CAwCV"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * The refusal ledger is three populations, and reporting it as one produced a
3
+ * wrong number that a lane then reasoned from.
4
+ *
5
+ * ## The conflation
6
+ *
7
+ * `UnresolvedRef` records what an adapter saw and could not resolve, and
8
+ * everything filed there reads as a **gap**. Two unrelated things are filed:
9
+ *
10
+ * - An outbound call to a third party, **read perfectly**. There is no endpoint
11
+ * in this workspace for it and there never will be. That is §20.2's *not
12
+ * applicable* — a fact, not a gap.
13
+ * - A call against this workspace's own surface whose target is not statically
14
+ * determinable. That is the gap, and it is *not analysable*.
15
+ *
16
+ * A read-rate census across nine repositories reported **90 edges read against
17
+ * 773 recognised-and-refused, a 10% read rate**, and concluded that `USES_API`
18
+ * resolution was the system's largest deficit. On one repository **115 of 163
19
+ * ledger rows are calls to Microsoft, Zoom, Hitpay and Zoho** — correctly
20
+ * refused, counted as deficit. The deficit there is real and it is 47%, not 20%.
21
+ *
22
+ * ## What running it on real code established, and it is not what was expected
23
+ *
24
+ * **`rawTarget` does not carry the target.** On the reference repository every
25
+ * one of the 64 `USES_API` refusals carries the *callee* — `"fetch"`,
26
+ * `"api.get"`, `"api.post"` — because the URL was an expression the adapter
27
+ * could not evaluate, and the expression text is not what gets filed. So the
28
+ * ledger **cannot** be split from stored data by any engine-side rule, and this
29
+ * module reports all 64 as `undetermined`, which is the correct answer and a
30
+ * useless one.
31
+ *
32
+ * The distinction nevertheless **already exists** — in `reason`, as prose. Two
33
+ * sentence forms account for all 64, and they split it exactly as a hand count
34
+ * of the source did:
35
+ *
36
+ * | `reason` says | count | what it means |
37
+ * | --- | --- | --- |
38
+ * | *"the path is not repository-relative"* | **39** | outbound. A fact |
39
+ * | *"the request path is not a literal or template"* | **25** | the gap |
40
+ *
41
+ * 39 + 25 = 64, and the independent hand count of that repository was 39 outbound
42
+ * and 25 genuinely unread. **The adapter knows which population a refusal is in
43
+ * and says so in a sentence.** Parsing that sentence is not an option: it is
44
+ * free text, it is written per producer, and a consumer that greps it breaks
45
+ * silently the first time one is reworded — the CRLF-stripper failure exactly.
46
+ *
47
+ * So the conclusion is the opposite of this module's premise: **the
48
+ * discriminator has to be a field**, and this module is the evidence for that
49
+ * rather than a substitute for it. It classifies what the text can carry, and
50
+ * discloses everything it cannot, which is what makes the gap measurable.
51
+ *
52
+ * ## Why the field is still not added here
53
+ *
54
+ * The `category` discriminator is the right end state and is deliberately **not**
55
+ * added here, for two reasons that are the same reason:
56
+ *
57
+ * 1. **No adapter would set it today.** Shipping a consumer that reads a carrier
58
+ * no producer emits is exactly the defect DEC-112 names, and it has already
59
+ * cost this project three checks that were dead on every real repository. A
60
+ * field added ahead of its producer is a dead carrier however obviously
61
+ * correct it looks — so the field lands with an adapter emitting it, not
62
+ * before.
63
+ * 2. **The storage column needs the migration policy** that is still open
64
+ * (architecture §32). An engine-side classifier needs neither, works on graphs
65
+ * already written, and turns the IR change into a request backed by measured
66
+ * populations rather than a speculative one.
67
+ *
68
+ * ## DEC-242 landed, and this module now defers to it where it can
69
+ *
70
+ * The heuristic above is what this module reasoned its way to before a
71
+ * discriminator field existed. It now does: `attrs.refusalClass` (DEC-242),
72
+ * producer-declared and persisted (the store gained a real `attrs` column
73
+ * for it — DEC-224). `classifyRefusal` checks `refusalClass === "out-of-scope"`
74
+ * first and trusts it outright, ahead of the text heuristic below — a
75
+ * producer that resolved the target and declared it out of scope did real
76
+ * analysis, which is better evidence than this module re-deriving the same
77
+ * fact from `rawTarget` text. DEC-242's other three classes
78
+ * (`value-unknown`, `capability-gap`, `varies-per-call`) answer a different
79
+ * question — whether a human sentence could close the row — and say nothing
80
+ * about scope, so they and an unset field both fall through to the
81
+ * unchanged heuristic rather than being read as "not out-of-scope." Every
82
+ * row written before DEC-242 shipped is graded exactly as it always was.
83
+ *
84
+ * The practical consequence, per DEC-242's own note: any future recall
85
+ * figure computed over `unresolved.length` must exclude `refusalClass ===
86
+ * "out-of-scope"` rows from its deficit denominator, the same way
87
+ * `readRate` below already excludes this module's own `outOfScope`
88
+ * verdict — measured at 3 of ~215 rows on the corpora checked so far
89
+ * (DEC-260), small today and not distorting any published number, but
90
+ * expressible now in a way it was not before the field existed.
91
+ *
92
+ * ## The third population is the point
93
+ *
94
+ * A ledger row whose target is a runtime value cannot be classified either way:
95
+ * `fetch(url)` may be outbound or internal and the text does not say. Several
96
+ * such rows on the census repository turned out to be outbound, discovered by
97
+ * hand. **So this returns three counts and refuses to return one rate.** Folding
98
+ * `undetermined` into either side is the same error one level down — the whole
99
+ * defect was a denominator that quietly absorbed a population it should have
100
+ * disclosed.
101
+ */
102
+ const ABSOLUTE = /^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//;
103
+ /** The host of an absolute target, lowercased and without a port; `null` if the target is not absolute. */
104
+ function hostOf(rawTarget) {
105
+ if (!ABSOLUTE.test(rawTarget))
106
+ return null;
107
+ try {
108
+ return new URL(rawTarget).hostname.toLowerCase();
109
+ }
110
+ catch {
111
+ return null;
112
+ }
113
+ }
114
+ /**
115
+ * A target is **not** a literal path or URL if it carries no path-like evidence
116
+ * at all — a bare identifier, a call expression, a template with nothing fixed.
117
+ * These are the rows that cannot be classified, and they must stay visible.
118
+ */
119
+ function isOpaque(rawTarget) {
120
+ const t = rawTarget.trim();
121
+ if (t === "")
122
+ return true;
123
+ // Looked absolute and had no parseable host — `https://` and friends. It says
124
+ // nothing about where the call goes, so it is opaque rather than internal.
125
+ // Reached only when `hostOf` has already returned null for it.
126
+ if (ABSOLUTE.test(t))
127
+ return true;
128
+ if (t.startsWith("/"))
129
+ return false;
130
+ // A bare `{param}` or `${...}` with no fixed segment says nothing about where
131
+ // the call goes. Anything containing a `/` outside a placeholder does.
132
+ const withoutPlaceholders = t.replace(/\$?\{[^}]*\}/g, "");
133
+ return !withoutPlaceholders.includes("/");
134
+ }
135
+ /**
136
+ * Classify one refusal.
137
+ *
138
+ * **A producer's own `attrs.refusalClass: "out-of-scope"` (DEC-242) is
139
+ * trusted directly, ahead of everything below.** DEC-242 landed after this
140
+ * module's own heuristic did, and it is strictly better evidence for the same
141
+ * question: a producer that read the call, resolved the target, and declared
142
+ * it out of scope did real analysis (Lane F's DEC-260 origin check, for one),
143
+ * where this module's `hostOf`/`isOpaque` pair is inference from `rawTarget`
144
+ * text alone. Rule 3's "declared beats re-derived" reordering, not a new rule.
145
+ *
146
+ * **A row with no `refusalClass`, or one of DEC-242's other three values
147
+ * (`value-unknown`, `capability-gap`, `varies-per-call`), falls through to
148
+ * the text heuristic unchanged — a deliberate choice, not an oversight.**
149
+ * Those three classes answer "is a human sentence enough to close this row,"
150
+ * a different question from "is this target inside or outside the
151
+ * workspace," and none of them says a row is or is not out of scope; reading
152
+ * absence as "therefore not out-of-scope" would be exactly the silent
153
+ * behaviour change this module's own module-header history warns against.
154
+ * Every row written before DEC-242 shipped, and every row a producer has not
155
+ * classified yet, is graded identically to how it always was.
156
+ *
157
+ * **Below that: absolute target on a host that is not ours → `outOfScope`.**
158
+ * The only positive classification made here from text alone, so it is as
159
+ * reliable as the text. Everything else is `unreadable` when it looks like a
160
+ * path this workspace could serve, and `undetermined` when the target says
161
+ * nothing about where the call goes.
162
+ */
163
+ export function classifyRefusal(ref, scope = {}) {
164
+ if (ref.attrs?.["refusalClass"] === "out-of-scope")
165
+ return "outOfScope";
166
+ const internal = new Set((scope.internalHosts ?? []).map((h) => h.toLowerCase()));
167
+ const host = hostOf(ref.rawTarget);
168
+ if (host !== null)
169
+ return internal.has(host) ? "unreadable" : "outOfScope";
170
+ if (isOpaque(ref.rawTarget))
171
+ return "undetermined";
172
+ return "unreadable";
173
+ }
174
+ export function classifyRefusals(refs, scope = {}) {
175
+ const counts = { outOfScope: 0, unreadable: 0, undetermined: 0 };
176
+ const hosts = new Map();
177
+ for (const ref of refs) {
178
+ counts[classifyRefusal(ref, scope)] += 1;
179
+ const host = hostOf(ref.rawTarget);
180
+ if (host !== null)
181
+ hosts.set(host, (hosts.get(host) ?? 0) + 1);
182
+ }
183
+ return {
184
+ total: refs.length,
185
+ ...counts,
186
+ scopeKnown: (scope.internalHosts ?? []).length > 0,
187
+ hosts: [...hosts]
188
+ .map(([host, count]) => ({ host, count }))
189
+ .sort((a, b) => b.count - a.count || a.host.localeCompare(b.host)),
190
+ };
191
+ }
192
+ export function readRate(read, refs, scope = {}) {
193
+ const census = classifyRefusals(refs, scope);
194
+ const recognisedDenominator = read + census.total;
195
+ const internalDenominator = read + census.unreadable + census.undetermined;
196
+ const disclosure = [];
197
+ if (census.outOfScope > 0) {
198
+ disclosure.push(`${census.outOfScope} of ${census.total} refusals target a host this workspace does not serve. ` +
199
+ `They were read correctly and there is nothing here to resolve them to — "not applicable", not "not analysable". ` +
200
+ `Counting them as deficit is what made the published rate wrong.`);
201
+ }
202
+ if (census.undetermined > 0) {
203
+ disclosure.push(`${census.undetermined} refusals carry a target the text does not locate — a runtime value. ` +
204
+ `Some are outbound and some are ours, and this cannot tell which, so they are counted against the internal rate. ` +
205
+ `The internal deficit is therefore an upper bound, not a measurement.`);
206
+ }
207
+ if (!census.scopeKnown && census.hosts.length > 0) {
208
+ disclosure.push(`No internal hosts were supplied, so every absolute target counted as outbound. ` +
209
+ `If any of these are ours the internal rate is optimistic: ${census.hosts
210
+ .slice(0, 5)
211
+ .map((h) => `${h.host} (${h.count})`)
212
+ .join(", ")}.`);
213
+ }
214
+ if (recognisedDenominator === 0) {
215
+ disclosure.push("Nothing was recognised on this repository, so neither rate is defined.");
216
+ }
217
+ return {
218
+ read,
219
+ census,
220
+ overRecognised: recognisedDenominator === 0 ? null : read / recognisedDenominator,
221
+ overInternal: internalDenominator === 0 ? null : read / internalDenominator,
222
+ disclosure,
223
+ };
224
+ }
225
+ //# sourceMappingURL=unresolved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unresolved.js","sourceRoot":"","sources":["../../src/query/unresolved.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The static half of `verification_status` — `ai-tool-contract.md` §5.6, §8
3
+ * endpoint 13; AI layer §19/§20 (`Verification status` moved off the
4
+ * confidence axis); `ai-layer-plan.md` §2 (the trigger → stage mask), §4
5
+ * technique 6 (a dedicated tool, not appended to every response).
6
+ *
7
+ * ## Scope boundary — read this before assuming more than this module builds
8
+ *
9
+ * A complete `Verification status` also depends on **which pipeline stages
10
+ * ran under which trigger mask** (`ai-layer-plan.md` §2: the fast path skips
11
+ * stages 8-13 entirely) — that is runtime information about one specific
12
+ * run, and it does not exist in `descry-core`. This repo is the static
13
+ * knowledge plane; there is no live run here to ask "did stage 9 actually
14
+ * execute against this file." **This module builds the static half only:**
15
+ * what a static reading of the graph and a language's declared capabilities
16
+ * can determine about analysability and resolution. Combining that with the
17
+ * runtime half — which stages actually ran — is `descry-runtime`/the
18
+ * pipeline's job, not this one's.
19
+ *
20
+ * ## Output shape: `@descryy/ir`'s `VerificationStatus`, not a parallel one
21
+ *
22
+ * `packages/ir/src/finding.ts` already defines the shared shape two
23
+ * repositories (the pipeline and the desktop golden-report test) assert
24
+ * against — `{ exercised: string[], notExercised: UntestedScope[] }`. This
25
+ * module produces exactly that, deliberately, rather than a second
26
+ * "coverage" record: two structures answering the same question would be
27
+ * exactly the kind of divergence `finding.ts`'s own module doc warns about
28
+ * for `Finding` itself, one level down.
29
+ *
30
+ * An `exercised` entry is `"<ref> (R<resolution>)"` — the scope item's
31
+ * identifier plus the real resolution level the graph actually holds for it,
32
+ * because a present node's resolution is a fact worth keeping even though
33
+ * `VerificationStatus.exercised` is typed as bare strings; see
34
+ * {@link formatExercised} for the exact grammar and
35
+ * {@link resolutionOfExercised} for the matching parser. A present item's
36
+ * resolution is reported as-is and is **never filtered against the
37
+ * requested check's `minResolution`** — whether R1 is "enough" for a given
38
+ * claim is a judgement for something above this layer (rule 3's cap, or G4),
39
+ * not a fact this function may assert.
40
+ *
41
+ * ## Hard constraint: no report category, ever
42
+ *
43
+ * §19's five report categories (`confirmed` / `strongly supported` /
44
+ * `unconfirmed` / `not analysable` / `unsupported`) are assigned at G4,
45
+ * above this surface (`ai-tool-contract.md` §1.2 draws the same line for
46
+ * result states). This module returns only the raw coverage facts —
47
+ * reachable-or-not, resolution, a named reason — and never the literal
48
+ * category vocabulary; a test asserts none of the five strings ever appear
49
+ * in the output.
50
+ *
51
+ * ## Reuses `tiers/certify.ts`'s capability comparison, not a second one
52
+ *
53
+ * "Does this language's declared `CapabilityMatrix` cover what a check
54
+ * needs" is the same question `certify.ts`'s `checkCapability` already
55
+ * answers for a whole adapter's tier. {@link capabilityGaps} restates that
56
+ * comparison — declared node/edge types, declared `maxResolution` — at
57
+ * per-scope-item granularity rather than adapter-wide, so the two never
58
+ * quietly disagree about what "this language's capabilities satisfy this
59
+ * requirement" means. It is a restatement rather than an import because
60
+ * `certify.ts`'s function also folds in precision-draw attestation and
61
+ * corpus conformance, both properties of a *published tier*, not of one live
62
+ * scope item — pulling those in here would answer a different question than
63
+ * the one being asked.
64
+ *
65
+ * ## Why this never looks up capabilities by language itself
66
+ *
67
+ * `ScopeItem.capabilities` is supplied by the caller, already resolved, per
68
+ * item — never looked up here from a `language` string. A `Map.get(item.
69
+ * language)` shape inside `packages/core/src/query/` would be exactly the
70
+ * IR-boundary leak `descry-boundary/no-language-branch` exists to catch
71
+ * (architecture principle 7 / `CLAUDE.md` rule 1): deciding behaviour from
72
+ * *which* language a node came from, not merely from whether one is known.
73
+ * `certify.ts` holds the same discipline one layer up — it takes one
74
+ * `GateEvidence` per call and never builds a language-keyed registry inside
75
+ * `packages/core` either. Resolving "which capabilities apply to this
76
+ * item's language" is the caller's job, done above this boundary; `language`
77
+ * is read here only for disclosure (naming it in a reason string), never for
78
+ * a branch, comparison or lookup.
79
+ */
80
+ import type { CapabilityMatrix, EdgeType, IRNode, NodeType, ResolutionLevel, VerificationStatus } from "@descryy/ir";
81
+ /**
82
+ * What a caller wants to know is answerable, for the whole scope in one
83
+ * call. Mirrors the three targeting fields `tiers/ladder.ts`'s `Requirement`
84
+ * uses (`nodeTypes`/`edgeTypes`/`minResolution`), restated rather than
85
+ * imported: a live per-scope-item check is not a tier-ladder promotion row
86
+ * and carries none of `Requirement`'s `id`/`kind`/`statement`. Every field
87
+ * omitted asks only "was this item reached at all".
88
+ */
89
+ export interface CoverageCheck {
90
+ readonly nodeTypes?: readonly NodeType[];
91
+ readonly edgeTypes?: readonly EdgeType[];
92
+ readonly minResolution?: ResolutionLevel;
93
+ }
94
+ /**
95
+ * One item of the scope being asked about — a file or a node.
96
+ *
97
+ * `node` is the strongest fact available: when the graph holds real,
98
+ * analysed content for this item, its own `resolution` is reported as-is,
99
+ * never re-derived. `capabilities` is consulted only when `node` is `null`,
100
+ * to explain *why* nothing is there — `undefined` means no adapter is
101
+ * registered for whatever this item is at all.
102
+ */
103
+ export interface ScopeItem {
104
+ /** The identifier this item is reported under — a node id or a file path. Opaque to this module. */
105
+ readonly ref: string;
106
+ /** Read only for disclosure text, never for a lookup or branch — see the module header. `null` means genuinely unknown. */
107
+ readonly language: string | null;
108
+ /** The graph's own node for this item, when one exists. `null` means this item is not in the graph. */
109
+ readonly node: IRNode | null;
110
+ /** The declared capabilities of whatever would produce this item, when the caller can supply them. `undefined` means no adapter is registered. */
111
+ readonly capabilities: CapabilityMatrix | undefined;
112
+ }
113
+ /** Parses an `exercised` entry back into its ref and resolution. `null` if `entry` was not produced by {@link formatExercised}. */
114
+ export declare function resolutionOfExercised(entry: string): {
115
+ readonly ref: string;
116
+ readonly resolution: ResolutionLevel;
117
+ } | null;
118
+ /**
119
+ * Compute the static half of `VerificationStatus` for a scope.
120
+ *
121
+ * Per item, one of three outcomes — see the module header for the full
122
+ * reasoning:
123
+ *
124
+ * 1. **Present in the graph** → `exercised`, carrying its real resolution.
125
+ * 2. **Absent, no capabilities supplied** → `notExercised`, naming the
126
+ * language (or that none could be determined).
127
+ * 3. **Absent, capabilities supplied** → `notExercised`, naming the specific
128
+ * declared gap against `check` when there is one, or — the honest edge
129
+ * case — that a registered adapter declares everything asked for and a
130
+ * static capability comparison alone cannot say why the item is still
131
+ * absent.
132
+ */
133
+ export declare function computeVerificationStatus(scope: readonly ScopeItem[], check?: CoverageCheck): VerificationStatus;
134
+ //# sourceMappingURL=verification-status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification-status.d.ts","sourceRoot":"","sources":["../../src/query/verification-status.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,eAAe,EAEf,kBAAkB,EACnB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,eAAe,CAAC;CAC1C;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,SAAS;IACxB,oGAAoG;IACpG,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2HAA2H;IAC3H,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uGAAuG;IACvG,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kJAAkJ;IAClJ,QAAQ,CAAC,YAAY,EAAE,gBAAgB,GAAG,SAAS,CAAC;CACrD;AAuCD,mIAAmI;AACnI,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAA;CAAE,GAAG,IAAI,CAI1H;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,SAAS,SAAS,EAAE,EAC3B,KAAK,GAAE,aAAkB,GACxB,kBAAkB,CAkCpB"}