@intentius/chant 0.124.46 → 0.124.49

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 (726) hide show
  1. package/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  2. package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  3. package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  4. package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  5. package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  6. package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  7. package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
  8. package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
  9. package/dist/__golden__/wave-loop/op-denied.json +16 -0
  10. package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  11. package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  12. package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
  13. package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
  14. package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
  15. package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  16. package/dist/__golden__/wave-loop/op-held-on.json +16 -0
  17. package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  18. package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  19. package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  20. package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  21. package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
  22. package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  23. package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
  24. package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  25. package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
  26. package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
  27. package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  28. package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  29. package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
  30. package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  31. package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  32. package/dist/__golden__/wave-loop/op-overridden.json +16 -0
  33. package/dist/__golden__/wave-loop/op-per-run.json +20 -0
  34. package/dist/__golden__/wave-loop/op-point.json +13 -0
  35. package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
  36. package/dist/__golden__/wave-loop/op-sealed.json +10 -0
  37. package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
  38. package/dist/__golden__/wave-loop/op-spend.json +10 -0
  39. package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
  40. package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
  41. package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
  42. package/dist/__golden__/wave-loop/op-wide.json +39 -0
  43. package/dist/action-pins.d.ts +61 -0
  44. package/dist/action-pins.d.ts.map +1 -0
  45. package/dist/action-pins.js +77 -0
  46. package/dist/cli/commands/carve.d.ts +3 -0
  47. package/dist/cli/commands/carve.d.ts.map +1 -1
  48. package/dist/cli/commands/carve.js +36 -7
  49. package/dist/cli/commands/import-report.d.ts +26 -0
  50. package/dist/cli/commands/import-report.d.ts.map +1 -0
  51. package/dist/cli/commands/import-report.js +65 -0
  52. package/dist/cli/commands/import.d.ts +11 -1
  53. package/dist/cli/commands/import.d.ts.map +1 -1
  54. package/dist/cli/commands/import.js +22 -3
  55. package/dist/cli/commands/migrate.d.ts +13 -1
  56. package/dist/cli/commands/migrate.d.ts.map +1 -1
  57. package/dist/cli/commands/migrate.js +134 -10
  58. package/dist/cli/handlers/approve.d.ts.map +1 -1
  59. package/dist/cli/handlers/approve.js +41 -14
  60. package/dist/cli/handlers/build.d.ts.map +1 -1
  61. package/dist/cli/handlers/build.js +6 -1
  62. package/dist/cli/handlers/graph-reader.d.ts +26 -0
  63. package/dist/cli/handlers/graph-reader.d.ts.map +1 -0
  64. package/dist/cli/handlers/graph-reader.js +41 -0
  65. package/dist/cli/handlers/graph.d.ts.map +1 -1
  66. package/dist/cli/handlers/graph.js +14 -0
  67. package/dist/cli/handlers/ledger.d.ts +3 -0
  68. package/dist/cli/handlers/ledger.d.ts.map +1 -0
  69. package/dist/cli/handlers/ledger.js +55 -0
  70. package/dist/cli/handlers/migrate.d.ts.map +1 -1
  71. package/dist/cli/handlers/migrate.js +18 -11
  72. package/dist/cli/handlers/misc.d.ts.map +1 -1
  73. package/dist/cli/handlers/misc.js +12 -1
  74. package/dist/cli/handlers/pr-env.js +2 -2
  75. package/dist/cli/handlers/pr.d.ts +15 -1
  76. package/dist/cli/handlers/pr.d.ts.map +1 -1
  77. package/dist/cli/handlers/pr.js +183 -40
  78. package/dist/cli/handlers/query.d.ts +7 -2
  79. package/dist/cli/handlers/query.d.ts.map +1 -1
  80. package/dist/cli/handlers/query.js +16 -4
  81. package/dist/cli/handlers/release.d.ts.map +1 -1
  82. package/dist/cli/handlers/release.js +6 -3
  83. package/dist/cli/handlers/search.d.ts +2 -4
  84. package/dist/cli/handlers/search.d.ts.map +1 -1
  85. package/dist/cli/handlers/search.js +13 -39
  86. package/dist/cli/main.d.ts.map +1 -1
  87. package/dist/cli/main.js +87 -14
  88. package/dist/cli/parse-args.d.ts.map +1 -1
  89. package/dist/cli/parse-args.js +47 -2
  90. package/dist/cli/registry.d.ts +22 -4
  91. package/dist/cli/registry.d.ts.map +1 -1
  92. package/dist/components/builders.d.ts +5 -1
  93. package/dist/components/builders.d.ts.map +1 -1
  94. package/dist/components/builders.js +5 -0
  95. package/dist/components/capability-plugin-loader.d.ts.map +1 -1
  96. package/dist/components/capability-plugin-loader.js +16 -1
  97. package/dist/components/capability-plugin.d.ts +14 -0
  98. package/dist/components/capability-plugin.d.ts.map +1 -1
  99. package/dist/components/pr-hooks.d.ts +21 -1
  100. package/dist/components/pr-hooks.d.ts.map +1 -1
  101. package/dist/components/pr-hooks.js +72 -4
  102. package/dist/components/pr-pipeline.d.ts +45 -10
  103. package/dist/components/pr-pipeline.d.ts.map +1 -1
  104. package/dist/components/pr-pipeline.js +47 -14
  105. package/dist/components/pr-policy.d.ts +36 -0
  106. package/dist/components/pr-policy.d.ts.map +1 -1
  107. package/dist/components/pr-policy.js +36 -0
  108. package/dist/components/pr-run.d.ts +3 -0
  109. package/dist/components/pr-run.d.ts.map +1 -1
  110. package/dist/components/pr-run.js +1 -0
  111. package/dist/components/starter-plugin.d.ts +1 -0
  112. package/dist/components/starter-plugin.d.ts.map +1 -1
  113. package/dist/components/starter-plugin.js +5 -1
  114. package/dist/components/verbs/index.d.ts +2 -0
  115. package/dist/components/verbs/index.d.ts.map +1 -1
  116. package/dist/components/verbs/index.js +2 -0
  117. package/dist/components/verbs/publish-artifact.d.ts +65 -0
  118. package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
  119. package/dist/components/verbs/publish-artifact.js +74 -0
  120. package/dist/components/verbs/publish-image.d.ts +129 -0
  121. package/dist/components/verbs/publish-image.d.ts.map +1 -0
  122. package/dist/components/verbs/publish-image.js +145 -0
  123. package/dist/config-environments.d.ts +20 -0
  124. package/dist/config-environments.d.ts.map +1 -1
  125. package/dist/config-environments.js +12 -0
  126. package/dist/config.d.ts +25 -1
  127. package/dist/config.d.ts.map +1 -1
  128. package/dist/config.js +10 -2
  129. package/dist/gate-decision.d.ts +20 -2
  130. package/dist/gate-decision.d.ts.map +1 -1
  131. package/dist/gate-decision.js +30 -3
  132. package/dist/graph-ir.d.ts +25 -0
  133. package/dist/graph-ir.d.ts.map +1 -1
  134. package/dist/graph-walk.d.ts +66 -0
  135. package/dist/graph-walk.d.ts.map +1 -0
  136. package/dist/graph-walk.js +70 -0
  137. package/dist/import/parser.d.ts +19 -0
  138. package/dist/import/parser.d.ts.map +1 -1
  139. package/dist/lexicon.d.ts +94 -6
  140. package/dist/lexicon.d.ts.map +1 -1
  141. package/dist/lifecycle/gate-ledger.d.ts +11 -0
  142. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  143. package/dist/lifecycle/git.d.ts +2 -5
  144. package/dist/lifecycle/git.d.ts.map +1 -1
  145. package/dist/lifecycle/ledger-read.d.ts +65 -0
  146. package/dist/lifecycle/ledger-read.d.ts.map +1 -0
  147. package/dist/lifecycle/ledger-read.js +160 -0
  148. package/dist/lifecycle/release-workstation.d.ts +7 -0
  149. package/dist/lifecycle/release-workstation.d.ts.map +1 -1
  150. package/dist/lifecycle/release-workstation.js +25 -0
  151. package/dist/lifecycle/run-ledger.d.ts +4 -3
  152. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  153. package/dist/lifecycle/run-ledger.js +1 -0
  154. package/dist/lint/discover.js +3 -1
  155. package/dist/lint/post-synth.d.ts +127 -1
  156. package/dist/lint/post-synth.d.ts.map +1 -1
  157. package/dist/lint/post-synth.js +84 -2
  158. package/dist/lint/rules/op/index.d.ts +1 -0
  159. package/dist/lint/rules/op/index.d.ts.map +1 -1
  160. package/dist/lint/rules/op/index.js +2 -0
  161. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
  162. package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
  163. package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
  164. package/dist/op/activities/activity-contracts.d.ts +9 -6
  165. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  166. package/dist/op/activities/activity-contracts.js +5 -2
  167. package/dist/op/activities/index.d.ts +2 -2
  168. package/dist/op/activities/index.d.ts.map +1 -1
  169. package/dist/op/activities/index.js +1 -1
  170. package/dist/op/activities/review-agent.d.ts +90 -4
  171. package/dist/op/activities/review-agent.d.ts.map +1 -1
  172. package/dist/op/activities/review-agent.js +217 -19
  173. package/dist/op/activities/work-evidence.d.ts +8 -1
  174. package/dist/op/activities/work-evidence.d.ts.map +1 -1
  175. package/dist/op/activities/work-evidence.js +1 -0
  176. package/dist/op/builders.d.ts +9 -5
  177. package/dist/op/builders.d.ts.map +1 -1
  178. package/dist/op/builders.js +9 -5
  179. package/dist/op/composites/apply-op.d.ts +29 -2
  180. package/dist/op/composites/apply-op.d.ts.map +1 -1
  181. package/dist/op/composites/apply-op.js +20 -1
  182. package/dist/op/gate-approval-base.d.ts +25 -0
  183. package/dist/op/gate-approval-base.d.ts.map +1 -0
  184. package/dist/op/gate-approval-base.js +71 -0
  185. package/dist/op/gate-approval.d.ts +18 -9
  186. package/dist/op/gate-approval.d.ts.map +1 -1
  187. package/dist/op/gate-approval.js +13 -31
  188. package/dist/op/gate-name.d.ts +13 -0
  189. package/dist/op/gate-name.d.ts.map +1 -1
  190. package/dist/op/gate-name.js +14 -1
  191. package/dist/op/gate-quorum.d.ts +100 -3
  192. package/dist/op/gate-quorum.d.ts.map +1 -1
  193. package/dist/op/gate-quorum.js +108 -6
  194. package/dist/op/gate-review.d.ts +9 -0
  195. package/dist/op/gate-review.d.ts.map +1 -1
  196. package/dist/op/gate-review.js +13 -0
  197. package/dist/op/gate.d.ts +47 -5
  198. package/dist/op/gate.d.ts.map +1 -1
  199. package/dist/op/gate.js +25 -4
  200. package/dist/op/index.d.ts +3 -3
  201. package/dist/op/index.d.ts.map +1 -1
  202. package/dist/op/index.js +1 -1
  203. package/dist/op/local-executor.d.ts +45 -3
  204. package/dist/op/local-executor.d.ts.map +1 -1
  205. package/dist/op/local-executor.js +68 -7
  206. package/dist/op/op-waves-run.d.ts +26 -1
  207. package/dist/op/op-waves-run.d.ts.map +1 -1
  208. package/dist/op/op-waves-run.js +259 -13
  209. package/dist/op/op-waves.d.ts +72 -5
  210. package/dist/op/op-waves.d.ts.map +1 -1
  211. package/dist/op/op-waves.js +110 -15
  212. package/dist/op/runtime.d.ts +11 -0
  213. package/dist/op/runtime.d.ts.map +1 -1
  214. package/dist/op/schedule-overdue.d.ts +16 -0
  215. package/dist/op/schedule-overdue.d.ts.map +1 -1
  216. package/dist/op/schedule-overdue.js +36 -0
  217. package/dist/op/stage-hooks.d.ts +9 -2
  218. package/dist/op/stage-hooks.d.ts.map +1 -1
  219. package/dist/op/stage-hooks.js +7 -5
  220. package/dist/op/workspace-run-env.d.ts +22 -0
  221. package/dist/op/workspace-run-env.d.ts.map +1 -0
  222. package/dist/op/workspace-run-env.js +21 -0
  223. package/dist/pr-forge.d.ts +24 -0
  224. package/dist/pr-forge.d.ts.map +1 -1
  225. package/dist/pr-forge.js +47 -0
  226. package/dist/pr-loop.d.ts +10 -0
  227. package/dist/pr-loop.d.ts.map +1 -1
  228. package/dist/pr-loop.js +4 -0
  229. package/dist/pr-migrations.d.ts +62 -0
  230. package/dist/pr-migrations.d.ts.map +1 -0
  231. package/dist/pr-migrations.js +50 -0
  232. package/dist/pr-post.d.ts +42 -0
  233. package/dist/pr-post.d.ts.map +1 -1
  234. package/dist/pr-post.js +68 -2
  235. package/dist/read-filter.d.ts +65 -0
  236. package/dist/read-filter.d.ts.map +1 -0
  237. package/dist/read-filter.js +179 -0
  238. package/dist/run-event.d.ts +1 -1
  239. package/dist/run-event.d.ts.map +1 -1
  240. package/dist/terraform/carve.d.ts +24 -3
  241. package/dist/terraform/carve.d.ts.map +1 -1
  242. package/dist/terraform/carve.js +32 -14
  243. package/dist/terraform/cuts.d.ts +97 -0
  244. package/dist/terraform/cuts.d.ts.map +1 -0
  245. package/dist/terraform/cuts.js +138 -0
  246. package/dist/terraform/folds.d.ts +26 -0
  247. package/dist/terraform/folds.d.ts.map +1 -0
  248. package/dist/terraform/folds.js +38 -0
  249. package/dist/terraform/graph.d.ts.map +1 -1
  250. package/dist/terraform/graph.js +10 -0
  251. package/dist/terraform/reach.d.ts +140 -0
  252. package/dist/terraform/reach.d.ts.map +1 -0
  253. package/dist/terraform/reach.js +170 -0
  254. package/dist/terraform/score.d.ts +14 -0
  255. package/dist/terraform/score.d.ts.map +1 -1
  256. package/dist/terraform/score.js +14 -31
  257. package/dist/terraform/state.d.ts.map +1 -1
  258. package/dist/terraform/state.js +4 -2
  259. package/dist/terraform/types.d.ts +8 -0
  260. package/dist/terraform/types.d.ts.map +1 -1
  261. package/dist/wave-blocked.d.ts +10 -1
  262. package/dist/wave-blocked.d.ts.map +1 -1
  263. package/dist/wave-blocked.js +31 -3
  264. package/dist/wave-runtime.mjs +264 -254
  265. package/dist/workspace/check.schema.json +13 -2
  266. package/dist/workspace/checks/ci-branch.d.ts +44 -0
  267. package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
  268. package/dist/workspace/checks/ci-branch.js +133 -0
  269. package/dist/workspace/checks/gate-approval.d.ts +58 -0
  270. package/dist/workspace/checks/gate-approval.d.ts.map +1 -0
  271. package/dist/workspace/checks/gate-approval.js +103 -0
  272. package/dist/workspace/checks/links.d.ts +3 -0
  273. package/dist/workspace/checks/links.d.ts.map +1 -1
  274. package/dist/workspace/checks/links.js +12 -1
  275. package/dist/workspace/checks/org.d.ts +48 -0
  276. package/dist/workspace/checks/org.d.ts.map +1 -0
  277. package/dist/workspace/checks/org.js +156 -0
  278. package/dist/workspace/checks.d.ts +12 -1
  279. package/dist/workspace/checks.d.ts.map +1 -1
  280. package/dist/workspace/checks.js +63 -7
  281. package/dist/workspace/ci-branches.d.ts +16 -0
  282. package/dist/workspace/ci-branches.d.ts.map +1 -1
  283. package/dist/workspace/ci-branches.js +27 -0
  284. package/dist/workspace/ci-green-cli.js +7 -7
  285. package/dist/workspace/ci-green-workflow.d.ts +1 -1
  286. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  287. package/dist/workspace/ci-green-workflow.js +13 -8
  288. package/dist/workspace/ci-green.d.ts +14 -0
  289. package/dist/workspace/ci-green.d.ts.map +1 -1
  290. package/dist/workspace/ci-green.js +44 -11
  291. package/dist/workspace/ci-run.d.ts +9 -1
  292. package/dist/workspace/ci-run.d.ts.map +1 -1
  293. package/dist/workspace/ci-run.js +67 -6
  294. package/dist/workspace/ci-serve.d.ts +9 -0
  295. package/dist/workspace/ci-serve.d.ts.map +1 -1
  296. package/dist/workspace/ci-serve.js +114 -76
  297. package/dist/workspace/compose-graph.d.ts +14 -0
  298. package/dist/workspace/compose-graph.d.ts.map +1 -1
  299. package/dist/workspace/composites.d.ts +4 -1
  300. package/dist/workspace/composites.d.ts.map +1 -1
  301. package/dist/workspace/composites.js +5 -2
  302. package/dist/workspace/composites.schema.json +22 -0
  303. package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  304. package/dist/workspace/cross-root-lint.d.ts +56 -0
  305. package/dist/workspace/cross-root-lint.d.ts.map +1 -0
  306. package/dist/workspace/cross-root-lint.js +111 -0
  307. package/dist/workspace/dbt-models-reader.d.ts +44 -0
  308. package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
  309. package/dist/workspace/dbt-models-reader.js +356 -0
  310. package/dist/workspace/dbt-project-common.d.ts +40 -0
  311. package/dist/workspace/dbt-project-common.d.ts.map +1 -0
  312. package/dist/workspace/dbt-project-common.js +106 -0
  313. package/dist/workspace/dbt-project-reader.d.ts +4 -3
  314. package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
  315. package/dist/workspace/dbt-project-reader.js +14 -108
  316. package/dist/workspace/decision-rank.d.ts +26 -0
  317. package/dist/workspace/decision-rank.d.ts.map +1 -0
  318. package/dist/workspace/decision-rank.js +16 -0
  319. package/dist/workspace/declaration.d.ts +50 -2
  320. package/dist/workspace/declaration.d.ts.map +1 -1
  321. package/dist/workspace/declaration.js +57 -11
  322. package/dist/workspace/declaration.schema.json +166 -24
  323. package/dist/workspace/environments.d.ts +26 -2
  324. package/dist/workspace/environments.d.ts.map +1 -1
  325. package/dist/workspace/environments.js +26 -2
  326. package/dist/workspace/exit-cli.d.ts +44 -0
  327. package/dist/workspace/exit-cli.d.ts.map +1 -0
  328. package/dist/workspace/exit-cli.js +198 -0
  329. package/dist/workspace/exit.d.ts +159 -0
  330. package/dist/workspace/exit.d.ts.map +1 -0
  331. package/dist/workspace/exit.js +480 -0
  332. package/dist/workspace/exit.schema.json +257 -0
  333. package/dist/workspace/flyway-dir.d.ts +39 -0
  334. package/dist/workspace/flyway-dir.d.ts.map +1 -0
  335. package/dist/workspace/flyway-dir.js +104 -0
  336. package/dist/workspace/flyway-layout.d.ts +96 -0
  337. package/dist/workspace/flyway-layout.d.ts.map +1 -0
  338. package/dist/workspace/flyway-layout.js +308 -0
  339. package/dist/workspace/graph-cache.d.ts +3 -1
  340. package/dist/workspace/graph-cache.d.ts.map +1 -1
  341. package/dist/workspace/graph-cache.js +12 -1
  342. package/dist/workspace/graph-cli.d.ts.map +1 -1
  343. package/dist/workspace/graph-cli.js +26 -8
  344. package/dist/workspace/graph.schema.json +34 -0
  345. package/dist/workspace/import-fetch.d.ts +38 -0
  346. package/dist/workspace/import-fetch.d.ts.map +1 -0
  347. package/dist/workspace/import-fetch.js +99 -0
  348. package/dist/workspace/import-init.d.ts +26 -0
  349. package/dist/workspace/import-init.d.ts.map +1 -0
  350. package/dist/workspace/import-init.js +130 -0
  351. package/dist/workspace/import-source.d.ts +147 -0
  352. package/dist/workspace/import-source.d.ts.map +1 -0
  353. package/dist/workspace/import-source.js +370 -0
  354. package/dist/workspace/init.d.ts +4 -0
  355. package/dist/workspace/init.d.ts.map +1 -1
  356. package/dist/workspace/init.js +70 -3
  357. package/dist/workspace/intent.d.ts +2 -3
  358. package/dist/workspace/intent.d.ts.map +1 -1
  359. package/dist/workspace/intent.js +5 -9
  360. package/dist/workspace/kind-link-readers.d.ts +59 -2
  361. package/dist/workspace/kind-link-readers.d.ts.map +1 -1
  362. package/dist/workspace/kind-link-readers.js +17 -1
  363. package/dist/workspace/kind-readers.d.ts +6 -0
  364. package/dist/workspace/kind-readers.d.ts.map +1 -1
  365. package/dist/workspace/kind-readers.js +18 -0
  366. package/dist/workspace/kinds.d.ts +90 -3
  367. package/dist/workspace/kinds.d.ts.map +1 -1
  368. package/dist/workspace/kinds.js +161 -7
  369. package/dist/workspace/ledger.schema.json +158 -0
  370. package/dist/workspace/lexicon-outputs.d.ts +20 -1
  371. package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
  372. package/dist/workspace/lexicon-outputs.js +102 -10
  373. package/dist/workspace/lineage-check.d.ts +3 -0
  374. package/dist/workspace/lineage-check.d.ts.map +1 -1
  375. package/dist/workspace/lineage-check.js +23 -4
  376. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  377. package/dist/workspace/lineage-upgrade.js +13 -4
  378. package/dist/workspace/links.d.ts +8 -1
  379. package/dist/workspace/links.d.ts.map +1 -1
  380. package/dist/workspace/links.js +25 -1
  381. package/dist/workspace/ls.d.ts +8 -0
  382. package/dist/workspace/ls.d.ts.map +1 -1
  383. package/dist/workspace/ls.js +7 -1
  384. package/dist/workspace/ls.schema.json +7 -0
  385. package/dist/workspace/member-commands.d.ts.map +1 -1
  386. package/dist/workspace/member-commands.js +54 -5
  387. package/dist/workspace/migrate-links.d.ts +45 -0
  388. package/dist/workspace/migrate-links.d.ts.map +1 -0
  389. package/dist/workspace/migrate-links.js +100 -0
  390. package/dist/workspace/migration-dirs.d.ts +74 -0
  391. package/dist/workspace/migration-dirs.d.ts.map +1 -0
  392. package/dist/workspace/migration-dirs.js +254 -0
  393. package/dist/workspace/new-migrations.d.ts +47 -0
  394. package/dist/workspace/new-migrations.d.ts.map +1 -0
  395. package/dist/workspace/new-migrations.js +91 -0
  396. package/dist/workspace/pr-report.schema.json +46 -0
  397. package/dist/workspace/promote.d.ts +96 -0
  398. package/dist/workspace/promote.d.ts.map +1 -0
  399. package/dist/workspace/promote.js +263 -0
  400. package/dist/workspace/reason-codes.d.ts +21 -0
  401. package/dist/workspace/reason-codes.d.ts.map +1 -1
  402. package/dist/workspace/reason-codes.js +25 -0
  403. package/dist/workspace/records-cli.d.ts +11 -0
  404. package/dist/workspace/records-cli.d.ts.map +1 -1
  405. package/dist/workspace/records-cli.js +57 -5
  406. package/dist/workspace/records.schema.json +5 -0
  407. package/dist/workspace/release-candidates.d.ts +2 -0
  408. package/dist/workspace/release-candidates.d.ts.map +1 -1
  409. package/dist/workspace/release-candidates.js +5 -2
  410. package/dist/workspace/release-train.d.ts +53 -0
  411. package/dist/workspace/release-train.d.ts.map +1 -0
  412. package/dist/workspace/release-train.js +134 -0
  413. package/dist/workspace/release-workflow.d.ts.map +1 -1
  414. package/dist/workspace/release-workflow.js +4 -3
  415. package/dist/workspace/repo-ref.d.ts +45 -0
  416. package/dist/workspace/repo-ref.d.ts.map +1 -0
  417. package/dist/workspace/repo-ref.js +114 -0
  418. package/dist/workspace/run-event.schema.json +2 -2
  419. package/dist/workspace/runs-cli.d.ts +9 -0
  420. package/dist/workspace/runs-cli.d.ts.map +1 -1
  421. package/dist/workspace/runs-cli.js +48 -3
  422. package/dist/workspace/runs.schema.json +7 -0
  423. package/dist/workspace/search-contract.d.ts +1 -1
  424. package/dist/workspace/search-contract.d.ts.map +1 -1
  425. package/dist/workspace/status-decisions.d.ts +37 -0
  426. package/dist/workspace/status-decisions.d.ts.map +1 -0
  427. package/dist/workspace/status-decisions.js +147 -0
  428. package/dist/workspace/status-gates.d.ts +9 -0
  429. package/dist/workspace/status-gates.d.ts.map +1 -1
  430. package/dist/workspace/status.d.ts +4 -0
  431. package/dist/workspace/status.d.ts.map +1 -1
  432. package/dist/workspace/status.js +14 -2
  433. package/dist/workspace/status.schema.json +6 -0
  434. package/dist/workspace/work-cli.d.ts.map +1 -1
  435. package/dist/workspace/work-cli.js +5 -3
  436. package/dist/workspace/work-evidence-ops.d.ts +83 -0
  437. package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
  438. package/dist/workspace/work-evidence-ops.js +169 -0
  439. package/dist/workspace/work-evidence.d.ts +12 -2
  440. package/dist/workspace/work-evidence.d.ts.map +1 -1
  441. package/dist/workspace/work-evidence.js +21 -3
  442. package/dist/workspace/work-evidence.schema.json +49 -2
  443. package/dist/workspace/workspace-gates.d.ts +110 -0
  444. package/dist/workspace/workspace-gates.d.ts.map +1 -0
  445. package/dist/workspace/workspace-gates.js +140 -0
  446. package/dist/workspace/workspace-kinds.schema.json +108 -10
  447. package/dist/workspace/workspace-ledger.d.ts +76 -0
  448. package/dist/workspace/workspace-ledger.d.ts.map +1 -0
  449. package/dist/workspace/workspace-ledger.js +91 -0
  450. package/dist/workspace/workspace-run.d.ts +112 -0
  451. package/dist/workspace/workspace-run.d.ts.map +1 -0
  452. package/dist/workspace/workspace-run.js +432 -0
  453. package/package.json +1 -1
  454. package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
  455. package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
  456. package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
  457. package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
  458. package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
  459. package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
  460. package/src/__golden__/wave-loop/op-cost-member.json +13 -0
  461. package/src/__golden__/wave-loop/op-denied-source.json +16 -0
  462. package/src/__golden__/wave-loop/op-denied.json +16 -0
  463. package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
  464. package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
  465. package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
  466. package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
  467. package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
  468. package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
  469. package/src/__golden__/wave-loop/op-held-on.json +16 -0
  470. package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
  471. package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
  472. package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
  473. package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
  474. package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
  475. package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
  476. package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
  477. package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
  478. package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
  479. package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
  480. package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
  481. package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
  482. package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
  483. package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
  484. package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
  485. package/src/__golden__/wave-loop/op-overridden.json +16 -0
  486. package/src/__golden__/wave-loop/op-per-run.json +20 -0
  487. package/src/__golden__/wave-loop/op-point.json +13 -0
  488. package/src/__golden__/wave-loop/op-pr-review.json +10 -0
  489. package/src/__golden__/wave-loop/op-sealed.json +10 -0
  490. package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
  491. package/src/__golden__/wave-loop/op-spend.json +10 -0
  492. package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
  493. package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
  494. package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
  495. package/src/__golden__/wave-loop/op-wide.json +39 -0
  496. package/src/action-pins.test.ts +78 -0
  497. package/src/action-pins.ts +92 -0
  498. package/src/cli/commands/carve-score-once.test.ts +99 -0
  499. package/src/cli/commands/carve.ts +37 -6
  500. package/src/cli/commands/check-lexicon.test.ts +2 -2
  501. package/src/cli/commands/import-report.ts +71 -0
  502. package/src/cli/commands/import.ts +33 -3
  503. package/src/cli/commands/migrate-dialect.test.ts +145 -0
  504. package/src/cli/commands/migrate.ts +132 -11
  505. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
  506. package/src/cli/handlers/approve.ts +33 -4
  507. package/src/cli/handlers/build.ts +7 -1
  508. package/src/cli/handlers/graph-reader.test.ts +31 -0
  509. package/src/cli/handlers/graph-reader.ts +51 -0
  510. package/src/cli/handlers/graph.ts +14 -0
  511. package/src/cli/handlers/ledger.ts +54 -0
  512. package/src/cli/handlers/migrate.ts +21 -12
  513. package/src/cli/handlers/misc.ts +10 -1
  514. package/src/cli/handlers/pr-env.ts +2 -2
  515. package/src/cli/handlers/pr.ts +176 -37
  516. package/src/cli/handlers/query.ts +16 -4
  517. package/src/cli/handlers/release.ts +6 -3
  518. package/src/cli/handlers/search.ts +13 -34
  519. package/src/cli/main.test.ts +17 -0
  520. package/src/cli/main.ts +87 -14
  521. package/src/cli/parse-args.ts +35 -2
  522. package/src/cli/registry.ts +22 -4
  523. package/src/components/builders.ts +8 -0
  524. package/src/components/capability-plugin-loader.ts +13 -1
  525. package/src/components/capability-plugin.ts +16 -0
  526. package/src/components/pr-env-run-bundle.test.ts +1 -0
  527. package/src/components/pr-hooks.test.ts +73 -5
  528. package/src/components/pr-hooks.ts +95 -5
  529. package/src/components/pr-pipeline.ts +64 -16
  530. package/src/components/pr-policy.test.ts +64 -1
  531. package/src/components/pr-policy.ts +53 -0
  532. package/src/components/pr-run.ts +4 -0
  533. package/src/components/registry.test.ts +1 -1
  534. package/src/components/starter-plugin.ts +6 -0
  535. package/src/components/verbs/index.ts +2 -0
  536. package/src/components/verbs/publish-artifact.test.ts +60 -0
  537. package/src/components/verbs/publish-artifact.ts +122 -0
  538. package/src/components/verbs/publish-image.test.ts +101 -0
  539. package/src/components/verbs/publish-image.ts +265 -0
  540. package/src/config-environments.ts +28 -1
  541. package/src/config.ts +24 -1
  542. package/src/gate-decision-bundle.test.ts +5 -2
  543. package/src/gate-decision-identity.test.ts +20 -0
  544. package/src/gate-decision.ts +46 -3
  545. package/src/graph-ir.ts +27 -0
  546. package/src/graph-walk.test.ts +44 -0
  547. package/src/graph-walk.ts +102 -0
  548. package/src/import/parser.ts +20 -0
  549. package/src/lexicon.ts +98 -6
  550. package/src/lifecycle/gate-ledger.ts +8 -0
  551. package/src/lifecycle/git.ts +2 -2
  552. package/src/lifecycle/ledger-read.test.ts +107 -0
  553. package/src/lifecycle/ledger-read.ts +195 -0
  554. package/src/lifecycle/release-workstation.ts +24 -0
  555. package/src/lifecycle/run-ledger.ts +5 -2
  556. package/src/lint/cross-root.test.ts +122 -0
  557. package/src/lint/discover.ts +3 -1
  558. package/src/lint/post-synth.ts +212 -2
  559. package/src/lint/rules/op/index.ts +2 -0
  560. package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
  561. package/src/op/activities/activity-contracts.ts +5 -2
  562. package/src/op/activities/index.ts +2 -2
  563. package/src/op/activities/review-agent.test.ts +221 -4
  564. package/src/op/activities/review-agent.ts +265 -22
  565. package/src/op/activities/work-evidence.ts +9 -1
  566. package/src/op/builders.ts +9 -5
  567. package/src/op/composites/apply-op.test.ts +108 -0
  568. package/src/op/composites/apply-op.ts +37 -2
  569. package/src/op/gate-approval-at-base.test.ts +97 -0
  570. package/src/op/gate-approval-base.ts +72 -0
  571. package/src/op/gate-approval.test.ts +6 -1
  572. package/src/op/gate-approval.ts +22 -27
  573. package/src/op/gate-name.ts +16 -1
  574. package/src/op/gate-quorum-at-base.test.ts +211 -0
  575. package/src/op/gate-quorum.ts +156 -8
  576. package/src/op/gate-review.ts +14 -0
  577. package/src/op/gate.ts +69 -9
  578. package/src/op/index.ts +3 -2
  579. package/src/op/local-executor.ts +91 -11
  580. package/src/op/op-waves-depends-on.test.ts +81 -0
  581. package/src/op/op-waves-hook-targets.test.ts +4 -2
  582. package/src/op/op-waves-quorum-product.test.ts +158 -0
  583. package/src/op/op-waves-run.ts +288 -14
  584. package/src/op/op-waves.ts +143 -14
  585. package/src/op/runtime.ts +8 -0
  586. package/src/op/schedule-overdue.ts +33 -0
  587. package/src/op/stage-hooks.ts +13 -5
  588. package/src/op/workspace-run-env.ts +29 -0
  589. package/src/pr-forge-bundle.test.ts +2 -2
  590. package/src/pr-forge.test.ts +47 -0
  591. package/src/pr-forge.ts +68 -0
  592. package/src/pr-loop-bundle.test.ts +3 -2
  593. package/src/pr-loop.test.ts +52 -0
  594. package/src/pr-loop.ts +12 -0
  595. package/src/pr-migrations.ts +97 -0
  596. package/src/pr-post-open.e2e.test.ts +36 -0
  597. package/src/pr-post.test.ts +102 -3
  598. package/src/pr-post.ts +90 -2
  599. package/src/read-filter.test.ts +54 -0
  600. package/src/read-filter.ts +193 -0
  601. package/src/run-event.ts +1 -1
  602. package/src/stage-hooks-bundle.test.ts +1 -0
  603. package/src/terraform/carve.ts +52 -15
  604. package/src/terraform/cuts.test.ts +173 -0
  605. package/src/terraform/cuts.ts +188 -0
  606. package/src/terraform/folds.ts +44 -0
  607. package/src/terraform/graph.ts +9 -0
  608. package/src/terraform/radius.test.ts +90 -0
  609. package/src/terraform/reach.test.ts +146 -0
  610. package/src/terraform/reach.ts +247 -0
  611. package/src/terraform/score.ts +27 -29
  612. package/src/terraform/state.ts +3 -1
  613. package/src/terraform/types.ts +8 -0
  614. package/src/wave-blocked.ts +28 -3
  615. package/src/wave-loop-golden.test.ts +4 -3
  616. package/src/workspace/__fixtures__/import/spacelift.json +9 -0
  617. package/src/workspace/__fixtures__/import/tfc.json +13 -0
  618. package/src/workspace/behold-kinds.test.ts +2 -1
  619. package/src/workspace/check-contract.test.ts +8 -6
  620. package/src/workspace/check.schema.json +13 -2
  621. package/src/workspace/checks/ci-branch.test.ts +128 -0
  622. package/src/workspace/checks/ci-branch.ts +141 -0
  623. package/src/workspace/checks/gate-approval.test.ts +77 -0
  624. package/src/workspace/checks/gate-approval.ts +121 -0
  625. package/src/workspace/checks/links.ts +12 -1
  626. package/src/workspace/checks/org.ts +169 -0
  627. package/src/workspace/checks.ts +68 -7
  628. package/src/workspace/ci-branches.ts +31 -0
  629. package/src/workspace/ci-green-branches.test.ts +153 -0
  630. package/src/workspace/ci-green-cli.ts +7 -7
  631. package/src/workspace/ci-green-workflow.test.ts +4 -3
  632. package/src/workspace/ci-green-workflow.ts +13 -9
  633. package/src/workspace/ci-green.ts +49 -12
  634. package/src/workspace/ci-run.test.ts +72 -1
  635. package/src/workspace/ci-run.ts +68 -8
  636. package/src/workspace/ci-serve.test.ts +95 -0
  637. package/src/workspace/ci-serve.ts +106 -65
  638. package/src/workspace/component-environments.test.ts +25 -2
  639. package/src/workspace/compose-graph.ts +9 -2
  640. package/src/workspace/composites.schema.json +22 -0
  641. package/src/workspace/composites.test.ts +39 -8
  642. package/src/workspace/composites.ts +6 -2
  643. package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
  644. package/src/workspace/cross-root-lint.test.ts +90 -0
  645. package/src/workspace/cross-root-lint.ts +126 -0
  646. package/src/workspace/dbt-kind.test.ts +3 -2
  647. package/src/workspace/dbt-models-reader.ts +362 -0
  648. package/src/workspace/dbt-models.test.ts +248 -0
  649. package/src/workspace/dbt-project-common.ts +113 -0
  650. package/src/workspace/dbt-project-reader.ts +29 -112
  651. package/src/workspace/decision-rank.ts +40 -0
  652. package/src/workspace/declaration.schema.json +166 -24
  653. package/src/workspace/declaration.ts +101 -15
  654. package/src/workspace/environments.ts +40 -4
  655. package/src/workspace/exit-cli.ts +219 -0
  656. package/src/workspace/exit.schema.json +257 -0
  657. package/src/workspace/exit.test.ts +185 -0
  658. package/src/workspace/exit.ts +560 -0
  659. package/src/workspace/flyway-dir.ts +113 -0
  660. package/src/workspace/flyway-layout.ts +337 -0
  661. package/src/workspace/graph-cache.ts +12 -2
  662. package/src/workspace/graph-cli.ts +25 -10
  663. package/src/workspace/graph-contract.test.ts +4 -2
  664. package/src/workspace/graph.schema.json +34 -0
  665. package/src/workspace/identity.test.ts +29 -2
  666. package/src/workspace/import-fetch.ts +151 -0
  667. package/src/workspace/import-init.ts +147 -0
  668. package/src/workspace/import-source.test.ts +183 -0
  669. package/src/workspace/import-source.ts +462 -0
  670. package/src/workspace/init.test.ts +55 -1
  671. package/src/workspace/init.ts +66 -4
  672. package/src/workspace/intent.ts +6 -14
  673. package/src/workspace/kind-link-readers.ts +68 -3
  674. package/src/workspace/kind-readers.test.ts +36 -0
  675. package/src/workspace/kind-readers.ts +18 -1
  676. package/src/workspace/kinds.test.ts +35 -7
  677. package/src/workspace/kinds.ts +212 -11
  678. package/src/workspace/ledger.schema.json +158 -0
  679. package/src/workspace/lexicon-outputs.ts +132 -13
  680. package/src/workspace/lineage-check.ts +30 -7
  681. package/src/workspace/lineage-upgrade.test.ts +20 -0
  682. package/src/workspace/lineage-upgrade.ts +16 -7
  683. package/src/workspace/links.ts +24 -1
  684. package/src/workspace/ls-contract.test.ts +1 -1
  685. package/src/workspace/ls.schema.json +7 -0
  686. package/src/workspace/ls.ts +10 -1
  687. package/src/workspace/member-commands.ts +60 -2
  688. package/src/workspace/member-file-schema.test.ts +124 -0
  689. package/src/workspace/migrate-links.test.ts +99 -0
  690. package/src/workspace/migrate-links.ts +108 -0
  691. package/src/workspace/migration-dirs.test.ts +272 -0
  692. package/src/workspace/migration-dirs.ts +267 -0
  693. package/src/workspace/new-migrations.test.ts +98 -0
  694. package/src/workspace/new-migrations.ts +109 -0
  695. package/src/workspace/org-scope.test.ts +238 -0
  696. package/src/workspace/pr-report.schema.json +46 -0
  697. package/src/workspace/promote.test.ts +114 -0
  698. package/src/workspace/promote.ts +302 -0
  699. package/src/workspace/reason-codes.test.ts +10 -1
  700. package/src/workspace/reason-codes.ts +25 -0
  701. package/src/workspace/records-cli.ts +58 -5
  702. package/src/workspace/records.schema.json +5 -0
  703. package/src/workspace/release-candidates.ts +7 -2
  704. package/src/workspace/release-train.ts +157 -0
  705. package/src/workspace/release-workflow.ts +4 -3
  706. package/src/workspace/repo-ref.ts +113 -0
  707. package/src/workspace/run-event.schema.json +2 -2
  708. package/src/workspace/runs-cli.ts +48 -4
  709. package/src/workspace/runs.schema.json +7 -0
  710. package/src/workspace/status-contract.test.ts +46 -1
  711. package/src/workspace/status-decisions.test.ts +100 -0
  712. package/src/workspace/status-decisions.ts +151 -0
  713. package/src/workspace/status-gates.ts +9 -0
  714. package/src/workspace/status.schema.json +6 -0
  715. package/src/workspace/status.ts +17 -3
  716. package/src/workspace/where-filters.test.ts +39 -0
  717. package/src/workspace/work-cli.ts +5 -3
  718. package/src/workspace/work-evidence-ops.test.ts +176 -0
  719. package/src/workspace/work-evidence-ops.ts +189 -0
  720. package/src/workspace/work-evidence.schema.json +49 -2
  721. package/src/workspace/work-evidence.ts +22 -3
  722. package/src/workspace/workspace-gates.ts +200 -0
  723. package/src/workspace/workspace-kinds.schema.json +108 -10
  724. package/src/workspace/workspace-ledger.ts +130 -0
  725. package/src/workspace/workspace-run.test.ts +322 -0
  726. package/src/workspace/workspace-run.ts +461 -0
@@ -0,0 +1,248 @@
1
+ /**
2
+ * A dbt member's models as outputs (#3935): the `dbt-project` reader's
3
+ * `outputs`, the schema rules, and `chant workspace check` over a downstream
4
+ * member that links to a model.
5
+ */
6
+
7
+ import { readFileSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { afterAll, describe, expect, test } from "vitest";
10
+ import { cleanScratch, declaration, REPO, repo } from "./__fixtures__/contract-repo";
11
+ import { runDeclarationChecks } from "./checks";
12
+ import { parseDeclaration } from "./declaration";
13
+ import { readDbtProject } from "./dbt-project-reader";
14
+ import { resolveLinks, withReaderOutputs, type MemberHandles } from "./links";
15
+ import { workingTree } from "./tree";
16
+
17
+ afterAll(cleanScratch);
18
+
19
+ const SQL_KINDS = readFileSync(join(REPO, "lexicons", "sql", "workspace-kinds.json"), "utf-8");
20
+ const SQL_PACKAGE = JSON.stringify({ name: "@intentius/chant-lexicon-sql", version: "0.0.0", exports: { "./workspace-kinds": "./workspace-kinds.json" } });
21
+
22
+ const read = (files: Record<string, string>, fields: Record<string, unknown> = {}) => {
23
+ const root = repo({ "dbt_project.yml": "name: p\n", ...files });
24
+ return readDbtProject({ member: { name: "p" } as never, dir: "", fields: { sqlMember: null, dialect: "postgres", modelSchema: null, ...fields } as never, tree: workingTree(root) });
25
+ };
26
+ const names = (r: ReturnType<typeof read>) => (r.outputs ?? []).map((o) => o.name);
27
+
28
+ const ORDERS_SQL = "select 1 as id\n";
29
+ const ORDERS_YML = "version: 2\nmodels:\n - name: orders\n columns:\n - name: id\n - name: Total\n";
30
+
31
+ describe("model outputs with modelSchema (#3935)", () => {
32
+ test("each model is <modelSchema>.<model>, and each column its YAML lists is <modelSchema>.<model>.<column>", () => {
33
+ const r = read({ "models/orders.sql": ORDERS_SQL, "models/marts/customers.sql": ORDERS_SQL, "models/schema.yml": ORDERS_YML }, { modelSchema: "analytics" });
34
+ expect(names(r)).toEqual(["analytics.customers", "analytics.orders", "analytics.orders.id", "analytics.orders.total"]);
35
+ expect(r.gaps).toEqual([]);
36
+ expect(r.outputs!.find((o) => o.name === "analytics.orders")).toMatchObject({ file: "models/orders.sql", line: 1 });
37
+ expect(r.outputs!.find((o) => o.name === "analytics.orders.id")).toMatchObject({ file: "models/schema.yml", line: 5 });
38
+ });
39
+
40
+ test("dbt config is not read for the schema when modelSchema is set, even a templated one", () => {
41
+ const r = read(
42
+ { "models/a.sql": "{{ config(schema=var('s')) }}\nselect 1\n", "dbt_project.yml": "name: p\nmodels:\n p:\n +schema: \"{{ target.name }}\"\n" },
43
+ { modelSchema: "analytics" },
44
+ );
45
+ expect(names(r)).toEqual(["analytics.a"]);
46
+ expect(r.gaps).toEqual([]);
47
+ });
48
+
49
+ test("alias overrides the model name, from config(), the YAML or dbt_project.yml; the closest wins", () => {
50
+ const r = read(
51
+ {
52
+ "dbt_project.yml": "name: p\nmodels:\n p:\n marts:\n +alias: from_project\n",
53
+ "models/marts/a.sql": "select 1\n",
54
+ "models/marts/b.sql": "select 1\n",
55
+ "models/marts/c.sql": "{{ config(alias='from_sql') }}\nselect 1\n",
56
+ "models/marts/m.yml": "models:\n - name: b\n config:\n alias: from_yaml\n - name: c\n config:\n alias: from_yaml\n",
57
+ },
58
+ { modelSchema: "s" },
59
+ );
60
+ expect(names(r)).toEqual(["s.from_project", "s.from_yaml", "s.from_sql"]);
61
+ });
62
+
63
+ test("a templated alias is a gap at the model's file and line, and the model is left out", () => {
64
+ const r = read({ "models/a.sql": "select 1\n\n{{ config(alias=var('x')) }}\n", "models/b.sql": "select 1\n" }, { modelSchema: "s" });
65
+ expect(names(r)).toEqual(["s.b"]);
66
+ expect(r.gaps).toEqual([expect.objectContaining({ file: "models/a.sql", line: 3, outputs: true, message: expect.stringMatching(/^model a: alias var\('x'\) \(the model's config\(\)\) is a Jinja template/) })]);
67
+ });
68
+
69
+ test("a disabled model is left out, by config(), the YAML or the project", () => {
70
+ const r = read(
71
+ {
72
+ "dbt_project.yml": "name: p\nmodels:\n p:\n old:\n +enabled: false\n",
73
+ "models/old/x.sql": "select 1\n",
74
+ "models/y.sql": "{{ config(enabled=false) }}\nselect 1\n",
75
+ "models/z.sql": "select 1\n",
76
+ "models/m.yml": "models:\n - name: z\n config:\n enabled: false\n - name: w\n",
77
+ "models/w.sql": "select 1\n",
78
+ },
79
+ { modelSchema: "s" },
80
+ );
81
+ expect(names(r)).toEqual(["s.w"]);
82
+ });
83
+
84
+ test("postgres keeps a quoted name as written and folds an unquoted one; clickhouse keeps every name", () => {
85
+ const files = { "models/Orders.sql": "select 1\n", "models/m.yml": "models:\n - name: Orders\n columns:\n - name: CustomerId\n - name: OrderId\n quote: true\n" };
86
+ expect(names(read(files, { modelSchema: "Shop" }))).toEqual(["Shop.Orders", "Shop.Orders.customerid", "Shop.Orders.OrderId"]);
87
+ expect(names(read({ ...files, "dbt_project.yml": "name: p\nquoting:\n schema: false\n identifier: false\n" }, { modelSchema: "Shop" }))).toEqual(["shop.orders", "shop.orders.customerid", "shop.orders.OrderId"]);
88
+ expect(names(read(files, { modelSchema: "Shop", dialect: "clickhouse" }))).toEqual(["Shop.Orders", "Shop.Orders.CustomerId", "Shop.Orders.OrderId"]);
89
+ });
90
+
91
+ test("model-paths say where models live", () => {
92
+ const r = read({ "dbt_project.yml": "name: p\nmodel-paths: [transform]\n", "models/a.sql": "select 1\n", "transform/b.sql": "select 1\n" }, { modelSchema: "s" });
93
+ expect(names(r)).toEqual(["s.b"]);
94
+ });
95
+ });
96
+
97
+ describe("model outputs without modelSchema (#3935)", () => {
98
+ test("under dbt's default generate_schema_name a custom schema depends on the target: a gap that says to set modelSchema", () => {
99
+ const r = read({ "dbt_project.yml": "name: p\nmodels:\n p:\n +schema: marts\n", "models/a.sql": "select 1\n" });
100
+ expect(names(r)).toEqual([]);
101
+ expect(r.gaps).toHaveLength(1);
102
+ expect(r.gaps[0]).toMatchObject({ file: "models/a.sql", line: 1, outputs: true });
103
+ expect(r.gaps[0].message).toMatch(/schema "marts" \(\+schema in dbt_project\.yml\) is joined to the target's schema by dbt's default generate_schema_name \(<target_schema>_marts\), so the name depends on the target; set modelSchema on the dbt member/);
104
+ });
105
+
106
+ test("a model with no schema lands in the target's schema: a gap", () => {
107
+ const r = read({ "models/a.sql": "select 1\n" });
108
+ expect(r.gaps[0].message).toMatch(/it sets no schema, so it lands in the target's schema.*set modelSchema/);
109
+ });
110
+
111
+ test("a templated schema is a gap, whatever the macro", () => {
112
+ const r = read({ "models/a.sql": "{{ config(schema=\"{{ var('s') }}\") }}\nselect 1\n" });
113
+ expect(r.gaps[0].message).toMatch(/schema .* \(the model's config\(\)\) is a Jinja template, which chant does not render for a target; set modelSchema/);
114
+ });
115
+
116
+ const AS_IS = "{% macro generate_schema_name(custom_schema_name, node) -%}\n {%- set default_schema = target.schema -%}\n {%- if custom_schema_name is none -%}\n {{ default_schema }}\n {%- else -%}\n {{ custom_schema_name | trim }}\n {%- endif -%}\n{%- endmacro %}\n";
117
+
118
+ test("with the usual generate_schema_name override, a custom schema names the model; config precedence is config(), YAML, project", () => {
119
+ const r = read({
120
+ "macros/schema.sql": AS_IS,
121
+ "dbt_project.yml": "name: p\nmodels:\n p:\n +schema: from_project\n marts:\n +schema: marts\n",
122
+ "models/a.sql": "select 1\n",
123
+ "models/marts/b.sql": "select 1\n",
124
+ "models/marts/c.sql": "select 1\n",
125
+ "models/marts/d.sql": "{{ config(schema='from_sql') }}\nselect 1\n",
126
+ "models/m.yml": "models:\n - name: c\n config:\n schema: from_yaml\n - name: d\n config:\n schema: from_yaml\n",
127
+ });
128
+ expect(names(r)).toEqual(["from_project.a", "marts.b", "from_yaml.c", "from_sql.d"]);
129
+ expect(r.gaps).toEqual([]);
130
+ });
131
+
132
+ test("under the override, a model with no custom schema still lands in the target's schema: a gap", () => {
133
+ const r = read({ "macros/schema.sql": AS_IS, "models/a.sql": "select 1\n" });
134
+ expect(names(r)).toEqual([]);
135
+ expect(r.gaps[0].message).toMatch(/lands in the target's schema/);
136
+ });
137
+
138
+ test("any other generate_schema_name override is not evaluated: every model is a gap at the macro's line", () => {
139
+ const r = read({
140
+ "macros/schema.sql": "-- ours\n{% macro generate_schema_name(custom_schema_name, node) -%}\n {{ target.name }}_{{ custom_schema_name }}\n{%- endmacro %}\n",
141
+ "dbt_project.yml": "name: p\nmodels:\n p:\n +schema: marts\n",
142
+ "models/a.sql": "select 1\n",
143
+ });
144
+ expect(names(r)).toEqual([]);
145
+ expect(r.gaps[0].message).toMatch(/overrides generate_schema_name \(macros\/schema\.sql:2\).*set modelSchema/);
146
+ });
147
+
148
+ test("modelSchema still names the models under an override chant can't evaluate", () => {
149
+ const r = read({ "macros/schema.sql": "{% macro generate_schema_name(c, n) %}{{ target.name }}{% endmacro %}", "models/a.sql": "select 1\n" }, { modelSchema: "s" });
150
+ expect(names(r)).toEqual(["s.a"]);
151
+ expect(r.gaps).toEqual([]);
152
+ });
153
+
154
+ test("config() is found past comments and across lines; a config call in a comment is not read", () => {
155
+ const r = read(
156
+ { "models/a.sql": "-- {{ config(alias='no') }}\n{#- {{ config(alias='nor') }} -#}\n{{\n config(\n materialized='table',\n alias='yes'\n )\n}}\nselect 1\n" },
157
+ { modelSchema: "s" },
158
+ );
159
+ expect(names(r)).toEqual(["s.yes"]);
160
+ });
161
+ });
162
+
163
+ describe("withReaderOutputs (#3935)", () => {
164
+ const base: MemberHandles = { member: "analytics", outputs: [{ name: "kept" }], inputs: [], complete: true, why: null, exposesNone: false };
165
+ test("adds the reader's outputs, keeps the member's own and does not repeat a name", () => {
166
+ const out = withReaderOutputs(new Map([["analytics", base]]), new Map([["analytics", { reader: "dbt-project" as const, links: [], gaps: [], outputs: [{ name: "s.a", file: "f", line: 1 }, { name: "kept", file: "f", line: 1 }] }]]));
167
+ expect(out.get("analytics")!.outputs.map((o) => o.name)).toEqual(["kept", "s.a"]);
168
+ expect(out.get("analytics")!.complete).toBe(true);
169
+ });
170
+ test("a gap flagged outputs makes the member incomplete, and a link to a name it lacks is unresolved", () => {
171
+ const out = withReaderOutputs(new Map([["analytics", base]]), new Map([["analytics", { reader: "dbt-project" as const, links: [], gaps: [{ file: "m.sql", line: 1, message: "model a: x", outputs: true }, { file: "s.yml", line: 1, message: "a source gap" }], outputs: [] }]]));
172
+ expect(out.get("analytics")).toMatchObject({ complete: false, why: "model a: x" });
173
+ });
174
+ test("returns the handles as they are when no reader reports outputs", () => {
175
+ const handles = new Map([["analytics", base]]);
176
+ expect(withReaderOutputs(handles, new Map([["analytics", { reader: "dbt-project" as const, links: [], gaps: [{ file: "s.yml", line: 1, message: "a source gap" }] }]]))).toBe(handles);
177
+ expect(withReaderOutputs(handles, undefined)).toBe(handles);
178
+ });
179
+ test("resolveLinks resolves a declared link to a reader output", () => {
180
+ const decl = parseDeclaration(
181
+ declaration([
182
+ { name: "analytics", dir: "analytics", kind: "other", because: "x" },
183
+ { name: "dash", dir: "dash", kind: "other", because: "x", links: [{ member: "analytics", output: "s.a" }] },
184
+ ]),
185
+ "chant.workspace.json",
186
+ );
187
+ const handles = new Map([["analytics", base]]);
188
+ const read = new Map([["analytics", { reader: "dbt-project" as const, links: [], gaps: [], outputs: [{ name: "s.a", file: "f", line: 1 }] }]]);
189
+ expect(resolveLinks(decl, handles, undefined, read)[0]).toMatchObject({ origin: "declared", status: "resolved" });
190
+ expect(resolveLinks(decl, handles)[0]).toMatchObject({ status: "missing" });
191
+ });
192
+ });
193
+
194
+ describe("a downstream member links to a dbt model, in chant workspace check (#3935)", () => {
195
+ const workspace = (opts: { models?: Record<string, string>; fields?: Record<string, unknown>; output?: string } = {}) =>
196
+ repo({
197
+ "chant.workspace.json": declaration(
198
+ [
199
+ { name: "analytics", dir: "analytics", kind: "dbt", fields: opts.fields ?? { modelSchema: "analytics" } },
200
+ { name: "dash", dir: "dash", kind: "other", because: "reads a model", suppress: [{ check: "WSP009", because: "a stand-in" }], links: [{ member: "analytics", output: opts.output ?? "analytics.orders" }] },
201
+ ],
202
+ { pins: [{ path: "plugins/sql" }] },
203
+ ),
204
+ "plugins/sql/package.json": SQL_PACKAGE,
205
+ "plugins/sql/workspace-kinds.json": SQL_KINDS,
206
+ "dash/README": "",
207
+ "analytics/dbt_project.yml": "name: analytics\n",
208
+ "analytics/models/orders.sql": ORDERS_SQL,
209
+ "analytics/models/orders.yml": ORDERS_YML,
210
+ ...(opts.models ?? {}),
211
+ });
212
+
213
+ test("a link to a model and to a column resolves", async () => {
214
+ for (const output of ["analytics.orders", "analytics.orders.id"]) {
215
+ const report = await runDeclarationChecks(workspace({ output }));
216
+ expect(report.diagnostics).toEqual([]);
217
+ expect(report.links.find((r) => r.origin === "declared")).toMatchObject({ status: "resolved", producer: "analytics", output });
218
+ }
219
+ });
220
+
221
+ test("removing the model fails check, naming the model and the outputs left", async () => {
222
+ expect((await runDeclarationChecks(workspace())).ok).toBe(true);
223
+ const gone = workspace();
224
+ const fs = await import("node:fs");
225
+ fs.rmSync(join(gone, "analytics/models/orders.sql"));
226
+ fs.rmSync(join(gone, "analytics/models/orders.yml"));
227
+ fs.writeFileSync(join(gone, "analytics/models/other.sql"), "select 1\n");
228
+ const failed = await runDeclarationChecks(gone);
229
+ expect(failed.ok).toBe(false);
230
+ expect(failed.diagnostics.map((d) => `${d.ruleId}:${d.severity}:${d.entity}`)).toEqual(["WSP093:error:dash"]);
231
+ expect(failed.diagnostics[0].message).toMatch(/analytics has no output analytics\.orders.*its outputs: analytics\.other/);
232
+ });
233
+
234
+ test("removing a column from the model's YAML fails check", async () => {
235
+ const report = await runDeclarationChecks(workspace({ output: "analytics.orders.id", models: { "analytics/models/orders.yml": "models:\n - name: orders\n" } }));
236
+ expect(report.diagnostics.map((d) => d.ruleId)).toEqual(["WSP093"]);
237
+ });
238
+
239
+ test("a model the reader can't name leaves the member's outputs incomplete: the link is unresolved, not missing, and WSP099 says why", async () => {
240
+ const report = await runDeclarationChecks(
241
+ workspace({ fields: {}, output: "analytics.orders", models: { "analytics/dbt_project.yml": "name: analytics\nmodels:\n analytics:\n +schema: analytics\n" } }),
242
+ );
243
+ expect(report.links.find((r) => r.origin === "declared")).toMatchObject({ status: "unresolved" });
244
+ const ids = report.diagnostics.map((d) => `${d.ruleId}:${d.severity}`);
245
+ expect(ids).toContain("WSP099:info");
246
+ expect(report.diagnostics.find((d) => d.ruleId === "WSP099")!.message).toMatch(/set modelSchema on the dbt member/);
247
+ });
248
+ });
@@ -0,0 +1,113 @@
1
+ /**
2
+ * What the dbt readers share (#3932, #3935): YAML and line helpers, the
3
+ * `quoting:` rules, and the project's `model-paths`.
4
+ */
5
+
6
+ import { posix } from "node:path";
7
+ import type { KindReadGap } from "./kind-link-readers";
8
+ import { joinPath, skippedDir, type WorkspaceTree } from "./tree";
9
+
10
+ export const DBT_PROJECT_FILE = "dbt_project.yml";
11
+ export const DEFAULT_MODEL_PATHS = ["models"];
12
+
13
+ /** The dialects whose naming the reader follows; the member's `dialect` field picks one. */
14
+ export const DBT_DIALECTS = ["postgres", "clickhouse"] as const;
15
+ export type Dialect = (typeof DBT_DIALECTS)[number];
16
+
17
+ export interface Quoting {
18
+ schema: boolean;
19
+ identifier: boolean;
20
+ }
21
+
22
+ export const isTemplated = (v: string) => /\{\{|\{%/.test(v);
23
+ export const isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === "object" && !Array.isArray(v);
24
+
25
+ /** A name as text: a string, or a number or boolean YAML read as one. */
26
+ export function scalar(v: unknown): string | undefined {
27
+ if (typeof v === "string") return v;
28
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
29
+ return undefined;
30
+ }
31
+
32
+ /** Whether an entry is enabled: `enabled`, or `config.enabled`. A templated value is a gap, and the entry is left out. */
33
+ export function readEnabled(entry: Record<string, unknown>, file: string, line: number, where: string, gaps: KindReadGap[]): boolean {
34
+ const config = isObject(entry.config) ? entry.config : {};
35
+ const raw = entry.enabled ?? config.enabled;
36
+ if (raw === undefined || raw === null || raw === true) return true;
37
+ if (raw === false) return false;
38
+ gaps.push({ file, line, message: `${where}: enabled is ${JSON.stringify(raw)}, which chant does not render; it was not read` });
39
+ return false;
40
+ }
41
+
42
+ /** `base` with a `quoting:` block's schema and identifier applied. A value that isn't a boolean is a gap and keeps the base. */
43
+ export function readQuoting(base: Quoting, raw: unknown, file: string, line: number, where: string, gaps: KindReadGap[]): Quoting {
44
+ if (raw === undefined || raw === null) return base;
45
+ if (!isObject(raw)) {
46
+ gaps.push({ file, line, message: `${where} is not a mapping; the quoting above it applies` });
47
+ return base;
48
+ }
49
+ const out = { ...base };
50
+ for (const key of ["schema", "identifier"] as const) {
51
+ const v = raw[key];
52
+ if (v === undefined) continue;
53
+ if (typeof v === "boolean") out[key] = v;
54
+ else gaps.push({ file, line, message: `${where}.${key} is ${JSON.stringify(v)}, not true or false; the quoting above it applies` });
55
+ }
56
+ return out;
57
+ }
58
+
59
+ /** Every `.yml` and `.yaml` file under tree-relative directory `dir`, skipping dot directories and node_modules. */
60
+ export function yamlFiles(tree: WorkspaceTree, dir: string): string[] {
61
+ if (dir !== "" && tree.stat(dir) !== "dir") return [];
62
+ const out: string[] = [];
63
+ const walk = (at: string) => {
64
+ for (const e of tree.list(at) ?? []) {
65
+ const path = joinPath(at, e.name);
66
+ if (e.type === "dir") {
67
+ if (!skippedDir(e.name)) walk(path);
68
+ } else if (/\.ya?ml$/.test(e.name)) {
69
+ out.push(path);
70
+ }
71
+ }
72
+ };
73
+ walk(dir);
74
+ return out;
75
+ }
76
+
77
+ export function lines(text: string): string[] {
78
+ return text.replace(/\r\n/g, "\n").split("\n");
79
+ }
80
+
81
+ export function escapeRegExp(text: string): string {
82
+ return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
83
+ }
84
+
85
+ /** The line (from 1) of top-level key `key`, or 1. */
86
+ export function keyLine(fileLines: string[], key: string): number {
87
+ const re = new RegExp(`^${escapeRegExp(key)}\\s*:`);
88
+ const i = fileLines.findIndex((l) => re.test(l));
89
+ return i < 0 ? 1 : i + 1;
90
+ }
91
+
92
+ /**
93
+ * The line of the first `name: <value>` entry after line `from`, or `from`
94
+ * itself. Sources, tables and columns are listed in file order, so
95
+ * searching on from the parent's line finds each one's own line. A file in
96
+ * flow style has no such lines, and its entries are reported at the parent.
97
+ */
98
+ export function nameLine(fileLines: string[], value: string | undefined, from: number): number {
99
+ return value === undefined ? from : valueLineOf(fileLines, "name", value, from);
100
+ }
101
+
102
+ /** The line of the first `<key>:` after line `from`, or `from`. */
103
+ export function valueLine(fileLines: string[], key: string, from: number): number {
104
+ const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:`);
105
+ for (let i = Math.max(from, 0); i < fileLines.length; i++) if (re.test(fileLines[i])) return i + 1;
106
+ return from;
107
+ }
108
+
109
+ export function valueLineOf(fileLines: string[], key: string, value: string, from: number): number {
110
+ const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:\\s*(["']?)${escapeRegExp(value)}\\1\\s*(?:#.*)?$`);
111
+ for (let i = Math.max(from, 0); i < fileLines.length; i++) if (re.test(fileLines[i])) return i + 1;
112
+ return from;
113
+ }
@@ -27,27 +27,33 @@
27
27
  * - The producer is the member the `sqlMember` field names. Unset, each link
28
28
  * leaves the producer to `resolveLinks`, which picks the one member that
29
29
  * exposes the table.
30
+ *
31
+ * The same pass reads the project's models as outputs (#3935); see
32
+ * `./dbt-models-reader.ts`.
30
33
  */
31
34
 
32
35
  import { posix } from "node:path";
33
36
  import { parseYAMLDocument, YAMLParseError } from "../yaml";
34
37
  import type { KindLinkRead, KindReadGap, KindReadLink, KindReaderInput } from "./kind-link-readers";
35
- import { joinPath, skippedDir, type WorkspaceTree } from "./tree";
36
-
37
- export const DBT_PROJECT_FILE = "dbt_project.yml";
38
- const DEFAULT_MODEL_PATHS = ["models"];
39
-
40
- /** The dialects whose naming the reader follows; the member's `dialect` field picks one. */
41
- export const DBT_DIALECTS = ["postgres", "clickhouse"] as const;
42
- type Dialect = (typeof DBT_DIALECTS)[number];
43
-
44
- interface Quoting {
45
- schema: boolean;
46
- identifier: boolean;
47
- }
48
-
49
- const isTemplated = (v: string) => /\{\{|\{%/.test(v);
50
- const isObject = (v: unknown): v is Record<string, unknown> => v !== null && typeof v === "object" && !Array.isArray(v);
38
+ import { joinPath } from "./tree";
39
+ import { readDbtModels } from "./dbt-models-reader";
40
+ import {
41
+ DBT_PROJECT_FILE,
42
+ DEFAULT_MODEL_PATHS,
43
+ isObject,
44
+ isTemplated,
45
+ keyLine,
46
+ lines,
47
+ nameLine,
48
+ readEnabled,
49
+ readQuoting,
50
+ scalar,
51
+ valueLine,
52
+ yamlFiles,
53
+ type Dialect,
54
+ } from "./dbt-project-common";
55
+
56
+ export { DBT_DIALECTS, DBT_PROJECT_FILE } from "./dbt-project-common";
51
57
 
52
58
  export function readDbtProject(input: KindReaderInput): KindLinkRead {
53
59
  const { dir, tree, fields } = input;
@@ -63,11 +69,11 @@ export function readDbtProject(input: KindReaderInput): KindLinkRead {
63
69
  try {
64
70
  project = parseYAMLDocument(tree.read(projectFile));
65
71
  } catch (err) {
66
- gaps.push({ file: projectFile, line: err instanceof YAMLParseError ? err.line : 1, message: `${DBT_PROJECT_FILE} could not be read (${(err as Error).message}), so no source was read` });
72
+ gaps.push({ file: projectFile, line: err instanceof YAMLParseError ? err.line : 1, message: `${DBT_PROJECT_FILE} could not be read (${(err as Error).message}), so no source was read`, outputs: true });
67
73
  return result;
68
74
  }
69
75
  if (!isObject(project)) {
70
- gaps.push({ file: projectFile, line: 1, message: `${DBT_PROJECT_FILE} is not a mapping, so no source was read` });
76
+ gaps.push({ file: projectFile, line: 1, message: `${DBT_PROJECT_FILE} is not a mapping, so no source was read`, outputs: true });
71
77
  return result;
72
78
  }
73
79
  const projectLines = lines(tree.read(projectFile));
@@ -77,17 +83,17 @@ export function readDbtProject(input: KindReaderInput): KindLinkRead {
77
83
  const rawPaths = key ? project[key] : DEFAULT_MODEL_PATHS;
78
84
  const paths: string[] = [];
79
85
  if (!Array.isArray(rawPaths)) {
80
- gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} is not a list, so no source was read` });
86
+ gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} is not a list, so no source was read`, outputs: true });
81
87
  return result;
82
88
  }
83
89
  for (const p of rawPaths) {
84
90
  if (typeof p !== "string" || isTemplated(p)) {
85
- gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${JSON.stringify(p)} is not a plain path; its sources were not read` });
91
+ gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${JSON.stringify(p)} is not a plain path; its sources were not read`, outputs: true });
86
92
  continue;
87
93
  }
88
94
  const at = posix.normalize(joinPath(dir, p));
89
95
  if (at.startsWith("../") || at === ".." || posix.isAbsolute(p)) {
90
- gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${p} lies outside the workspace; its sources were not read` });
96
+ gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${p} lies outside the workspace; its sources were not read`, outputs: true });
91
97
  continue;
92
98
  }
93
99
  paths.push(at === "." ? "" : at);
@@ -106,7 +112,7 @@ export function readDbtProject(input: KindReaderInput): KindLinkRead {
106
112
  text = tree.read(file);
107
113
  doc = parseYAMLDocument(text);
108
114
  } catch (err) {
109
- gaps.push({ file, line: err instanceof YAMLParseError ? err.line : 1, message: `the file could not be read as YAML (${(err as Error).message}); any sources in it were not read` });
115
+ gaps.push({ file, line: err instanceof YAMLParseError ? err.line : 1, message: `the file could not be read as YAML (${(err as Error).message}); any sources or models in it were not read`, outputs: true });
110
116
  continue;
111
117
  }
112
118
  if (!isObject(doc) || doc.sources === undefined || doc.sources === null) continue;
@@ -197,95 +203,6 @@ export function readDbtProject(input: KindReaderInput): KindLinkRead {
197
203
  }
198
204
  }
199
205
  }
206
+ readDbtModels({ input, project, projectFile, paths, quoting, dialect, result });
200
207
  return result;
201
208
  }
202
-
203
- /** A name as text: a string, or a number or boolean YAML read as one. */
204
- function scalar(v: unknown): string | undefined {
205
- if (typeof v === "string") return v;
206
- if (typeof v === "number" || typeof v === "boolean") return String(v);
207
- return undefined;
208
- }
209
-
210
- /** Whether an entry is enabled: `enabled`, or `config.enabled`. A templated value is a gap, and the entry is left out. */
211
- function readEnabled(entry: Record<string, unknown>, file: string, line: number, where: string, gaps: KindReadGap[]): boolean {
212
- const config = isObject(entry.config) ? entry.config : {};
213
- const raw = entry.enabled ?? config.enabled;
214
- if (raw === undefined || raw === null || raw === true) return true;
215
- if (raw === false) return false;
216
- gaps.push({ file, line, message: `${where}: enabled is ${JSON.stringify(raw)}, which chant does not render; it was not read` });
217
- return false;
218
- }
219
-
220
- /** `base` with a `quoting:` block's schema and identifier applied. A value that isn't a boolean is a gap and keeps the base. */
221
- function readQuoting(base: Quoting, raw: unknown, file: string, line: number, where: string, gaps: KindReadGap[]): Quoting {
222
- if (raw === undefined || raw === null) return base;
223
- if (!isObject(raw)) {
224
- gaps.push({ file, line, message: `${where} is not a mapping; the quoting above it applies` });
225
- return base;
226
- }
227
- const out = { ...base };
228
- for (const key of ["schema", "identifier"] as const) {
229
- const v = raw[key];
230
- if (v === undefined) continue;
231
- if (typeof v === "boolean") out[key] = v;
232
- else gaps.push({ file, line, message: `${where}.${key} is ${JSON.stringify(v)}, not true or false; the quoting above it applies` });
233
- }
234
- return out;
235
- }
236
-
237
- /** Every `.yml` and `.yaml` file under tree-relative directory `dir`, skipping dot directories and node_modules. */
238
- function yamlFiles(tree: WorkspaceTree, dir: string): string[] {
239
- if (dir !== "" && tree.stat(dir) !== "dir") return [];
240
- const out: string[] = [];
241
- const walk = (at: string) => {
242
- for (const e of tree.list(at) ?? []) {
243
- const path = joinPath(at, e.name);
244
- if (e.type === "dir") {
245
- if (!skippedDir(e.name)) walk(path);
246
- } else if (/\.ya?ml$/.test(e.name)) {
247
- out.push(path);
248
- }
249
- }
250
- };
251
- walk(dir);
252
- return out;
253
- }
254
-
255
- function lines(text: string): string[] {
256
- return text.replace(/\r\n/g, "\n").split("\n");
257
- }
258
-
259
- function escapeRegExp(text: string): string {
260
- return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
261
- }
262
-
263
- /** The line (from 1) of top-level key `key`, or 1. */
264
- function keyLine(fileLines: string[], key: string): number {
265
- const re = new RegExp(`^${escapeRegExp(key)}\\s*:`);
266
- const i = fileLines.findIndex((l) => re.test(l));
267
- return i < 0 ? 1 : i + 1;
268
- }
269
-
270
- /**
271
- * The line of the first `name: <value>` entry after line `from`, or `from`
272
- * itself. Sources, tables and columns are listed in file order, so
273
- * searching on from the parent's line finds each one's own line. A file in
274
- * flow style has no such lines, and its entries are reported at the parent.
275
- */
276
- function nameLine(fileLines: string[], value: string | undefined, from: number): number {
277
- return value === undefined ? from : valueLineOf(fileLines, "name", value, from);
278
- }
279
-
280
- /** The line of the first `<key>:` after line `from`, or `from`. */
281
- function valueLine(fileLines: string[], key: string, from: number): number {
282
- const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:`);
283
- for (let i = Math.max(from, 0); i < fileLines.length; i++) if (re.test(fileLines[i])) return i + 1;
284
- return from;
285
- }
286
-
287
- function valueLineOf(fileLines: string[], key: string, value: string, from: number): number {
288
- const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:\\s*(["']?)${escapeRegExp(value)}\\1\\s*(?:#.*)?$`);
289
- for (let i = Math.max(from, 0); i < fileLines.length; i++) if (re.test(fileLines[i])) return i + 1;
290
- return from;
291
- }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * How decisions are ranked, most relevant first: the order of `why.decisions`
3
+ * in the intent graph (#3034) and of a gate's `decisions` in `workspace
4
+ * status` (#3616). One comparator, so the two reads can't drift apart.
5
+ */
6
+
7
+ /** Why a decision is in `why`, most relevant first (#3034). */
8
+ export type WhyRelevance = "carried" | "path" | "contract" | "issue" | "member" | "related";
9
+
10
+ const ORDER: readonly WhyRelevance[] = ["carried", "path", "contract", "issue", "member", "related"];
11
+
12
+ /** What the ranking reads of one decision. */
13
+ export interface DecisionRankKey {
14
+ /** The decision's node id, `record:<kind>/<id>`: the last tie-break. */
15
+ id: string;
16
+ /** Not superseded. */
17
+ current: boolean;
18
+ relevance: WhyRelevance;
19
+ /** How many of the region's current lines were made as its own work; 0 when history isn't read. */
20
+ lines: number;
21
+ /** Its state is one its kind closes. */
22
+ closed: boolean;
23
+ /** The length of its longest `path:` entry covering the region: a narrower path is more specific. */
24
+ specificity: number;
25
+ /** The date of the commit that decided it, or null. */
26
+ decidedOn: string | null;
27
+ }
28
+
29
+ /** Current first, then relevance, own lines, closed, specificity, newest decided, and id. */
30
+ export function compareDecisionRank(a: DecisionRankKey, b: DecisionRankKey): number {
31
+ return (
32
+ Number(b.current) - Number(a.current) ||
33
+ ORDER.indexOf(a.relevance) - ORDER.indexOf(b.relevance) ||
34
+ b.lines - a.lines ||
35
+ Number(b.closed) - Number(a.closed) ||
36
+ b.specificity - a.specificity ||
37
+ (b.decidedOn ?? "").localeCompare(a.decidedOn ?? "") ||
38
+ a.id.localeCompare(b.id)
39
+ );
40
+ }