@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,197 @@
1
+ /**
2
+ * The four capability tiers of §11A.11, expressed as requirements a machine can
3
+ * check — and the ones it cannot, named as such.
4
+ *
5
+ * ## Why this file exists at all
6
+ *
7
+ * Nine adapters state a tier in a doc comment. **DEC-075 §6 says a tier is
8
+ * generated from `capabilities()` and the gate results, never written in
9
+ * prose**, and until now nothing implemented that, so the only tier claims in
10
+ * the repository were the ones a human typed. That is the single piece of
11
+ * standing dishonesty in the codebase: a claim about what works for a language,
12
+ * made by the person who wanted it to be true, in a comment nothing checks.
13
+ *
14
+ * ## The ladder, from §11A.11
15
+ *
16
+ * | tier | what works | what it costs |
17
+ * | --- | --- | --- |
18
+ * | **S — Full** | contract *shape* matching, data propagation, oracle-derived tests | R3 + router extractor + ORM extractor |
19
+ * | **A — Contract** | endpoint matching, path-level orphans, migration DAG | R2/R3 + router extractor |
20
+ * | **B — Graph** | blast radius, impact scoring, test discovery, in-language root cause | R2 adapter |
21
+ * | **C — Signal** | env/config, rollback readiness, hidden dependency, file-level blast radius | R0, one grammar and one query set |
22
+ *
23
+ * A tier is **cumulative**: S implies A implies B implies C. So a language is
24
+ * awarded the highest tier whose requirements are *all* met, and the
25
+ * requirements of every tier below it are re-checked rather than assumed —
26
+ * because an adapter can reach R3 and still not emit a `FUNCTION`, and a ladder
27
+ * that assumed monotonicity would hand it an A on the strength of its routes.
28
+ *
29
+ * ## What a requirement may be
30
+ *
31
+ * Three kinds, and the split is the honest part:
32
+ *
33
+ * - **`capability`** — read straight off `capabilities()`. Machine-checked, no
34
+ * judgement. `capabilities()` is itself machine-checked against what the
35
+ * adapter actually emitted (DEC-070), so this is evidence, not a promise.
36
+ * - **`conformance`** — the corpus passes at the resolution the tier claims.
37
+ * Machine-checked by running the harness.
38
+ * - **`attested`** — a fact no machine in this repository can establish, so it
39
+ * is *declared* with its evidence and marked as declared. There is exactly
40
+ * one, and it is DEC-075's second condition: a ≥200-edge precision draw on
41
+ * two repositories **the adapter's author did not choose**. A machine can
42
+ * check the 200 and the two; it cannot check "did not choose", which is a
43
+ * fact about a person's intent. Recording it as attested is what stops the
44
+ * generator laundering a human judgement into a computed result.
45
+ */
46
+ /** Highest first. The order the generator walks, and the only place it lives. */
47
+ export const TIERS = ["S", "A", "B", "C"];
48
+ // ---------------------------------------------------------------------------
49
+ // There is deliberately no list of framework names here.
50
+ //
51
+ // The first version of this file carried three: ROUTER_EXTRACTORS with
52
+ // `express`, `fastapi`, `flask`, `django`; ORM_EXTRACTORS with `sqlalchemy`,
53
+ // `prisma`, `gorm`; SCHEMA_EXTRACTORS with `pydantic`, `zod`. The boundary lint
54
+ // rejected all twelve, and it was right on the merits rather than pedantic:
55
+ // **that is engine code above the Canonical IR knowing what a Python web
56
+ // framework is called**, which is rule 1, and a list that must grow every time
57
+ // anyone writes an extractor is the shape rule 1 exists to prevent.
58
+ //
59
+ // The fix is not an allowlist entry. It is that the requirement was
60
+ // **redundant**. "A router extractor is bound" was asking, indirectly, whether
61
+ // the adapter can produce routes — and the requirement immediately above it
62
+ // already asks that directly, in vocabulary terms: does it emit `API_ROUTE`,
63
+ // `API_ENDPOINT` and `SERVES_API`. An adapter emitting those has a router
64
+ // extractor by definition, whatever it is called, and one that does not cannot
65
+ // be rescued by a name in `frameworkExtractors`. The same held for the ORM
66
+ // requirement against `MODEL`/`READS`/`WRITES`, and for the schema requirement
67
+ // against `DTO`/`USES_TYPE`.
68
+ //
69
+ // So the name check bought nothing and cost the boundary. Deleting it changed
70
+ // no adapter's tier, which is the evidence that it was never load-bearing.
71
+ //
72
+ // The general form, worth keeping: **when engine code needs to know what a
73
+ // framework is, ask what it produced.** The vocabulary is the shared language
74
+ // precisely so the engine never has to learn a framework's name.
75
+ // ---------------------------------------------------------------------------
76
+ // ---------------------------------------------------------------------------
77
+ // The ladder itself.
78
+ // ---------------------------------------------------------------------------
79
+ const C_REQUIREMENTS = [
80
+ {
81
+ id: "C.parses",
82
+ kind: "capability",
83
+ statement: "the adapter produces a file-level graph",
84
+ // `MODULE`, not `FILE`. The vocabulary has both, and this requirement first
85
+ // asked for both — at which point every adapter in the repository failed
86
+ // Tier C. Checked against a real run rather than assumed: **no adapter
87
+ // emits or declares `FILE`**, and `MODULE` is what a file resolves to in
88
+ // all nine. A requirement no producer can satisfy does not make a generator
89
+ // strict, it makes it useless, and the ladder would have been "corrected"
90
+ // by whoever needed a tier first.
91
+ nodeTypes: ["MODULE"],
92
+ },
93
+ {
94
+ id: "C.corpus-r0",
95
+ kind: "conformance",
96
+ statement: "the conformance corpus passes at R0",
97
+ minResolution: 0,
98
+ },
99
+ ];
100
+ const B_REQUIREMENTS = [
101
+ {
102
+ id: "B.declarations",
103
+ kind: "capability",
104
+ statement: "declarations and calls are resolved, so blast radius has edges to walk",
105
+ nodeTypes: ["FUNCTION", "CLASS"],
106
+ edgeTypes: ["CALLS", "IMPORTS"],
107
+ },
108
+ {
109
+ id: "B.tests",
110
+ kind: "capability",
111
+ statement: "tests are discoverable, which is what makes impact scoring actionable",
112
+ nodeTypes: ["TEST_CASE"],
113
+ edgeTypes: ["TESTS"],
114
+ },
115
+ {
116
+ id: "B.r2",
117
+ kind: "capability",
118
+ statement: "the adapter reaches R2 — references resolved, not only parsed",
119
+ minResolution: 2,
120
+ },
121
+ {
122
+ id: "B.corpus-r2",
123
+ kind: "conformance",
124
+ statement: "the conformance corpus passes at R2",
125
+ minResolution: 2,
126
+ },
127
+ ];
128
+ const A_REQUIREMENTS = [
129
+ {
130
+ id: "A.routes",
131
+ kind: "capability",
132
+ statement: "routes are emitted from source and joined to the shared endpoint node",
133
+ nodeTypes: ["API_ROUTE", "API_ENDPOINT"],
134
+ edgeTypes: ["SERVES_API"],
135
+ },
136
+ {
137
+ id: "A.callers",
138
+ kind: "capability",
139
+ statement: "a caller reaches an endpoint through USES_API, which is the other half of the join",
140
+ edgeTypes: ["USES_API"],
141
+ },
142
+ {
143
+ id: "A.precision-draw",
144
+ kind: "attested",
145
+ statement: "a >=200-edge precision draw passes on two repositories the adapter's author did not choose (DEC-075 §6.2)",
146
+ },
147
+ ];
148
+ const S_REQUIREMENTS = [
149
+ {
150
+ id: "S.r3",
151
+ kind: "capability",
152
+ statement: "the adapter reaches R3 — shapes, not only names, which is what shape matching compares",
153
+ minResolution: 3,
154
+ },
155
+ {
156
+ id: "S.shapes",
157
+ kind: "capability",
158
+ statement: "transport shapes are emitted, so a caller's body can be compared against a route's",
159
+ nodeTypes: ["DTO"],
160
+ edgeTypes: ["USES_TYPE"],
161
+ },
162
+ {
163
+ id: "S.persistence",
164
+ kind: "capability",
165
+ statement: "models and their storage are in the graph, so propagation reaches the database",
166
+ nodeTypes: ["MODEL"],
167
+ edgeTypes: ["READS", "WRITES"],
168
+ },
169
+ {
170
+ id: "S.corpus-r3",
171
+ kind: "conformance",
172
+ statement: "the conformance corpus passes at R3",
173
+ minResolution: 3,
174
+ },
175
+ ];
176
+ export const LADDER = [
177
+ { tier: "C", name: "Signal", requires: C_REQUIREMENTS },
178
+ { tier: "B", name: "Graph", requires: B_REQUIREMENTS },
179
+ { tier: "A", name: "Contract", requires: A_REQUIREMENTS },
180
+ { tier: "S", name: "Full", requires: S_REQUIREMENTS },
181
+ ];
182
+ /**
183
+ * Every requirement a tier needs, including the tiers beneath it.
184
+ *
185
+ * Cumulative and re-checked rather than assumed — see the header. `C` is the
186
+ * floor, so `requirementsFor("C")` is C's own list.
187
+ */
188
+ export function requirementsFor(tier) {
189
+ const order = ["C", "B", "A", "S"];
190
+ const upTo = order.indexOf(tier);
191
+ if (upTo < 0)
192
+ throw new Error(`unknown tier ${tier}`);
193
+ return order
194
+ .slice(0, upTo + 1)
195
+ .flatMap((t) => LADDER.find((d) => d.tier === t)?.requires ?? []);
196
+ }
197
+ //# sourceMappingURL=ladder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ladder.js","sourceRoot":"","sources":["../../src/tiers/ladder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * §15.3's config dependency graph — *"track env vars, secrets, flags, config
3
+ * files and what uses them"*, and the row whose note reads *"feeds the
4
+ * deploy-target check"*.
5
+ *
6
+ * ## This is a query, not a check, and the distinction is the design
7
+ *
8
+ * Checks 1 and 2 emit findings. This one emits **structure**: for every variable
9
+ * the repository knows about, where it is declared, where it is read, and what
10
+ * transitively depends on the files that read it. §15.3 says it feeds check 1,
11
+ * and that is exactly what it is for — a missing variable read by a module forty
12
+ * others import is a different sentence from one read by a single script, and
13
+ * until now the check had no way to tell them apart.
14
+ *
15
+ * Because it produces no findings of its own, it has **no precision gate of its
16
+ * own**, and that is stated rather than quietly skipped. Its correctness rests
17
+ * entirely on the `IMPORTS` edges beneath it, whose precision is already gated
18
+ * elsewhere. What this module can get wrong on its own is the *join* — attaching
19
+ * the wrong file to a variable — and that is what its bench exercises.
20
+ *
21
+ * ## No new vocabulary, which is the whole reason it is shaped this way
22
+ *
23
+ * *"New capabilities are new queries over these edges, not new types."* A
24
+ * variable still has no node (DEC-120). The dependent set is `scopeChange`
25
+ * seeded with the **file that reads the variable** — impact flowing outward from
26
+ * a changed file is precisely the existing traversal, with its budgets, its decay
27
+ * scoring and its truncation disclosure already correct.
28
+ *
29
+ * Taking the scope rather than re-deriving it is deliberate: a second traversal
30
+ * with its own rules would drift from the one the rest of the engine uses, and
31
+ * the first symptom would be two different blast radiuses for the same file.
32
+ *
33
+ * ## Why R1, and what it degrades to
34
+ *
35
+ * Reaching *"what depends on this"* needs module resolution — `IMPORTS` edges
36
+ * that actually resolve. At R0 there are none, so the dependent set is empty and
37
+ * the report says the graph carried no import edges rather than reporting zero
38
+ * dependents as a fact. **An empty dependent set from a graph with no imports and
39
+ * an empty one from a genuinely unimported module are different statements**, and
40
+ * only the second is information.
41
+ *
42
+ * ## The completeness fence
43
+ *
44
+ * Every count here is *what this graph can see* and is worded that way. NFR-9's
45
+ * rule, and §15.3's own instruction for the neighbouring DB-impact check —
46
+ * *"output must state what the tool can see, never implying completeness"* —
47
+ * applies with equal force: a dependent set is a lower bound, always.
48
+ */
49
+ import type { AdjacencyProvider, QueryResult } from "../query/provider.ts";
50
+ import type { SurfaceScan } from "./sources.ts";
51
+ export interface ConfigDeclaration {
52
+ readonly file: string;
53
+ readonly line: number;
54
+ readonly commented: boolean;
55
+ readonly role: "declaration" | "deployTarget";
56
+ }
57
+ export interface ConfigReadSite {
58
+ readonly file: string;
59
+ readonly line: number;
60
+ /** The read fails when the variable is unset — DEC-121's discriminator. */
61
+ readonly required: boolean;
62
+ }
63
+ export interface ConfigVariable {
64
+ readonly name: string;
65
+ readonly declaredAt: readonly ConfigDeclaration[];
66
+ readonly readAt: readonly ConfigReadSite[];
67
+ /**
68
+ * Files that transitively depend on a file reading this variable, as far as
69
+ * this graph can see.
70
+ *
71
+ * **A lower bound, never a total.** Null when the dependent set could not be
72
+ * computed at all — no reading file is in the graph, or the graph carries no
73
+ * import edges — which is not the same as zero.
74
+ */
75
+ readonly dependents: number | null;
76
+ /** A few dependent files, for a reader who wants to look. */
77
+ readonly dependentSample: readonly string[];
78
+ /** True when the traversal's budget stopped it short. */
79
+ readonly dependentsTruncated: boolean;
80
+ }
81
+ export interface ConfigGraph {
82
+ readonly variables: readonly ConfigVariable[];
83
+ /** Variables named by a declaration, a read, or both. */
84
+ readonly counts: {
85
+ readonly total: number;
86
+ readonly declaredOnly: number;
87
+ readonly readOnly: number;
88
+ readonly both: number;
89
+ /** Variables whose dependent set could be computed at all. */
90
+ readonly withDependents: number;
91
+ };
92
+ /** True when the graph carried at least one resolved import edge. */
93
+ readonly importsAvailable: boolean;
94
+ }
95
+ export interface ConfigGraphOptions {
96
+ /** Cap on variables whose dependent set is computed. Traversal is not free. */
97
+ readonly maxTraversals?: number;
98
+ /** Cap on file nodes enumerated. */
99
+ readonly limit?: number;
100
+ /** Budget handed to each dependent traversal. */
101
+ readonly budget?: number;
102
+ }
103
+ export declare function buildConfigGraph(provider: AdjacencyProvider, scan: SurfaceScan, options?: ConfigGraphOptions): QueryResult<ConfigGraph>;
104
+ //# sourceMappingURL=config-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-graph.d.ts","sourceRoot":"","sources":["../../src/validation/config-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAc,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAIvF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAAC;CAC/C;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAClD,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,yDAAyD;IACzD,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,yDAAyD;IACzD,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,8DAA8D;QAC9D,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;KACjC,CAAC;IACF,qEAAqE;IACrE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAED,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,oCAAoC;IACpC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAMD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE,kBAAuB,GAC/B,WAAW,CAAC,WAAW,CAAC,CAgL1B"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * §15.3's config dependency graph — *"track env vars, secrets, flags, config
3
+ * files and what uses them"*, and the row whose note reads *"feeds the
4
+ * deploy-target check"*.
5
+ *
6
+ * ## This is a query, not a check, and the distinction is the design
7
+ *
8
+ * Checks 1 and 2 emit findings. This one emits **structure**: for every variable
9
+ * the repository knows about, where it is declared, where it is read, and what
10
+ * transitively depends on the files that read it. §15.3 says it feeds check 1,
11
+ * and that is exactly what it is for — a missing variable read by a module forty
12
+ * others import is a different sentence from one read by a single script, and
13
+ * until now the check had no way to tell them apart.
14
+ *
15
+ * Because it produces no findings of its own, it has **no precision gate of its
16
+ * own**, and that is stated rather than quietly skipped. Its correctness rests
17
+ * entirely on the `IMPORTS` edges beneath it, whose precision is already gated
18
+ * elsewhere. What this module can get wrong on its own is the *join* — attaching
19
+ * the wrong file to a variable — and that is what its bench exercises.
20
+ *
21
+ * ## No new vocabulary, which is the whole reason it is shaped this way
22
+ *
23
+ * *"New capabilities are new queries over these edges, not new types."* A
24
+ * variable still has no node (DEC-120). The dependent set is `scopeChange`
25
+ * seeded with the **file that reads the variable** — impact flowing outward from
26
+ * a changed file is precisely the existing traversal, with its budgets, its decay
27
+ * scoring and its truncation disclosure already correct.
28
+ *
29
+ * Taking the scope rather than re-deriving it is deliberate: a second traversal
30
+ * with its own rules would drift from the one the rest of the engine uses, and
31
+ * the first symptom would be two different blast radiuses for the same file.
32
+ *
33
+ * ## Why R1, and what it degrades to
34
+ *
35
+ * Reaching *"what depends on this"* needs module resolution — `IMPORTS` edges
36
+ * that actually resolve. At R0 there are none, so the dependent set is empty and
37
+ * the report says the graph carried no import edges rather than reporting zero
38
+ * dependents as a fact. **An empty dependent set from a graph with no imports and
39
+ * an empty one from a genuinely unimported module are different statements**, and
40
+ * only the second is information.
41
+ *
42
+ * ## The completeness fence
43
+ *
44
+ * Every count here is *what this graph can see* and is worded that way. NFR-9's
45
+ * rule, and §15.3's own instruction for the neighbouring DB-impact check —
46
+ * *"output must state what the tool can see, never implying completeness"* —
47
+ * applies with equal force: a dependent set is a lower bound, always.
48
+ */
49
+ import { scopeChange } from "../scoping/traverse.js";
50
+ import { readEnvReads } from "./env.js";
51
+ import { fileScopedNodes } from "./nodes.js";
52
+ const DEFAULT_MAX_TRAVERSALS = 50;
53
+ const DEFAULT_BUDGET = 200;
54
+ const SAMPLE = 5;
55
+ export function buildConfigGraph(provider, scan, options = {}) {
56
+ const maxTraversals = options.maxTraversals ?? DEFAULT_MAX_TRAVERSALS;
57
+ const budget = options.budget ?? DEFAULT_BUDGET;
58
+ const notes = [];
59
+ // --- declarations, from the repository -----------------------------------
60
+ const declarations = new Map();
61
+ for (const surface of scan.surfaces) {
62
+ for (const declaration of surface.declarations) {
63
+ let bucket = declarations.get(declaration.name);
64
+ if (bucket === undefined)
65
+ declarations.set(declaration.name, (bucket = []));
66
+ bucket.push({
67
+ file: surface.file,
68
+ line: declaration.line,
69
+ commented: declaration.commented,
70
+ role: surface.role,
71
+ });
72
+ }
73
+ }
74
+ // --- reads, from the graph -----------------------------------------------
75
+ const files = fileScopedNodes(provider, options.limit);
76
+ const reads = new Map();
77
+ const readingFile = new Map();
78
+ let importEdges = 0;
79
+ for (const node of files.nodes) {
80
+ const path = node.file;
81
+ if (path === null)
82
+ continue;
83
+ // Counted across every file, not only the reading ones: "this graph has no
84
+ // import edges" is a property of the graph, and sampling it from the files
85
+ // that happen to read configuration would be a property of those files.
86
+ importEdges += provider.outgoing(node.id, { types: ["IMPORTS"], limit: 1 }).length;
87
+ const extracted = readEnvReads(node.attrs, path, node.resolution);
88
+ if (extracted.reads.length === 0)
89
+ continue;
90
+ readingFile.set(path, node);
91
+ for (const read of extracted.reads) {
92
+ let bucket = reads.get(read.name);
93
+ if (bucket === undefined)
94
+ reads.set(read.name, (bucket = []));
95
+ bucket.push({ file: read.file, line: read.line, required: read.required });
96
+ }
97
+ }
98
+ const importsAvailable = importEdges > 0;
99
+ // --- assemble, and traverse for the ones worth traversing ----------------
100
+ const names = [...new Set([...declarations.keys(), ...reads.keys()])].sort();
101
+ const variables = [];
102
+ let declaredOnly = 0;
103
+ let readOnly = 0;
104
+ let both = 0;
105
+ let withDependents = 0;
106
+ let traversals = 0;
107
+ let floor = 4;
108
+ let anyTruncated = false;
109
+ // Variables with a read site come first: a dependent set is only meaningful
110
+ // for one with a reading file, and the traversal budget should not be spent on
111
+ // declarations nothing reads.
112
+ const ordered = names.sort((a, b) => {
113
+ const ar = reads.has(a) ? 0 : 1;
114
+ const br = reads.has(b) ? 0 : 1;
115
+ return ar - br || a.localeCompare(b);
116
+ });
117
+ for (const name of ordered) {
118
+ const declaredAt = declarations.get(name) ?? [];
119
+ const readAt = reads.get(name) ?? [];
120
+ if (declaredAt.length > 0 && readAt.length > 0)
121
+ both += 1;
122
+ else if (declaredAt.length > 0)
123
+ declaredOnly += 1;
124
+ else
125
+ readOnly += 1;
126
+ let dependents = null;
127
+ let dependentSample = [];
128
+ let truncated = false;
129
+ const seeds = readAt
130
+ .map((site) => readingFile.get(site.file))
131
+ .filter((node) => node !== undefined)
132
+ .map((node) => node.id);
133
+ if (seeds.length > 0 && importsAvailable && traversals < maxTraversals) {
134
+ traversals += 1;
135
+ const scope = scopeChange(provider, [...new Set(seeds)], { budget });
136
+ // `changed` is the seed set itself — the files that read the variable —
137
+ // so the dependent count is `affected` alone. Including the seeds would
138
+ // report a variable read in one file as having one dependent.
139
+ const affected = scope.data.affected;
140
+ dependents = affected.length;
141
+ dependentSample = affected
142
+ .map((entry) => entry.node.file)
143
+ .filter((file) => file !== null)
144
+ .slice(0, SAMPLE);
145
+ truncated = scope.truncated || scope.data.dropped.length > 0;
146
+ if (truncated)
147
+ anyTruncated = true;
148
+ if (scope.stamp.resolutionFloor < floor)
149
+ floor = scope.stamp.resolutionFloor;
150
+ withDependents += 1;
151
+ }
152
+ variables.push({
153
+ name,
154
+ declaredAt,
155
+ readAt,
156
+ dependents,
157
+ dependentSample,
158
+ dependentsTruncated: truncated,
159
+ });
160
+ }
161
+ variables.sort((a, b) => (b.dependents ?? -1) - (a.dependents ?? -1) || a.name.localeCompare(b.name));
162
+ // --- disclosures ---------------------------------------------------------
163
+ if (!importsAvailable) {
164
+ notes.push("No resolved import edge is in this graph, so no dependent set could be computed for any " +
165
+ "variable. Every dependent count is reported as unknown rather than as zero: a module " +
166
+ "nothing imports and a graph that resolved no imports produce the same empty set, and " +
167
+ "only the first is information. This needs R1 — module resolution — which the producer " +
168
+ "did not reach.");
169
+ }
170
+ if (reads.size === 0) {
171
+ notes.push("No file in the graph carries environment reads, so this graph describes declarations only " +
172
+ "and nothing about what uses them. The engine reads attrs.envReads on a file-scoped node.");
173
+ }
174
+ if (traversals >= maxTraversals) {
175
+ notes.push(`Dependent sets were computed for the first ${maxTraversals} variable(s) with a read ` +
176
+ "site; the rest carry an unknown dependent count rather than zero. Raise " +
177
+ '"maxTraversals" to widen it.');
178
+ }
179
+ if (anyTruncated) {
180
+ notes.push("At least one dependent traversal hit its budget, so those counts are a floor rather than a " +
181
+ "total. The dropped nodes were the lowest-scoring ones reached.");
182
+ }
183
+ if (files.truncated) {
184
+ notes.push("More files exist in the graph than were enumerated, so this covers a prefix of the " +
185
+ "repository rather than all of it.");
186
+ }
187
+ notes.push("Every dependent count is what this graph can see, and is a lower bound. A consumer in a " +
188
+ "language with no adapter, in another repository, or reached through a call this analysis " +
189
+ "could not resolve does not appear here.");
190
+ const stamp = {
191
+ ...provider.baseStamp(),
192
+ resolutionFloor: withDependents === 0 ? 1 : floor,
193
+ };
194
+ return {
195
+ data: {
196
+ variables,
197
+ counts: { total: names.length, declaredOnly, readOnly, both, withDependents },
198
+ importsAvailable,
199
+ },
200
+ stamp,
201
+ truncated: files.truncated || anyTruncated,
202
+ notes,
203
+ };
204
+ }
205
+ //# sourceMappingURL=config-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-graph.js","sourceRoot":"","sources":["../../src/validation/config-graph.ts"],"names":[],"mappings":"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"}