@metabase/cli 0.3.1-alpha.transform-tests.3fbcf8b → 0.3.1-alpha.transform-tests.d9ed765

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 (266) hide show
  1. package/dist/{add-collection-C-XJPp3F.mjs → add-collection-v_uw_8VC.mjs} +6 -9
  2. package/dist/{alert-Klz8Bhst.mjs → alert-2MDhiuxT.mjs} +7 -7
  3. package/dist/{alerts-Bp2vByJf.mjs → alerts-BDoIryWj.mjs} +7 -7
  4. package/dist/{append-D16_s1HW.mjs → append-CeHVEN3m.mjs} +5 -5
  5. package/dist/{archive-RzzXt2V0.mjs → archive-B9DiDia8.mjs} +6 -6
  6. package/dist/{archive-nDvHMzTv.mjs → archive-BMQBzQMw.mjs} +4 -4
  7. package/dist/{archive-C9iNjXcI.mjs → archive-BU3VZ1An.mjs} +5 -5
  8. package/dist/{archive-CA-HIfQq.mjs → archive-BopUoNoz.mjs} +4 -4
  9. package/dist/{archive-BOJUGwyL.mjs → archive-BuHy5_kr.mjs} +4 -4
  10. package/dist/{archive-Q_qUuYh8.mjs → archive-CVTpSQ0H.mjs} +6 -6
  11. package/dist/{archive-Dd7ZTibw.mjs → archive-CYaJZhBs.mjs} +4 -4
  12. package/dist/{archive-vzu8ghZZ.mjs → archive-CxzoUCE_.mjs} +6 -6
  13. package/dist/{archive-D4nGMs8A.mjs → archive-D5QNFMmn.mjs} +4 -4
  14. package/dist/{archive-Bj4MjbJY.mjs → archive-IBEbIm_S2.mjs} +6 -6
  15. package/dist/{archive-lDnTIypd.mjs → archive-M2_D7zAj.mjs} +6 -6
  16. package/dist/{auth-kyPQfiND.mjs → auth-DuGPC1Q0.mjs} +5 -5
  17. package/dist/{body-DxRSAMNC.mjs → body-hAwPMqBg.mjs} +3 -3
  18. package/dist/{branches-QixvzIpl.mjs → branches-CIP60haa.mjs} +4 -7
  19. package/dist/{cancel-CPStS4zJ.mjs → cancel-C9hrQ1yg.mjs} +4 -4
  20. package/dist/{cancel-task--cuSISnl.mjs → cancel-task-BeviniVd.mjs} +5 -8
  21. package/dist/{card-zyUkr2nS.mjs → card-CEkp1mcI.mjs} +1 -1
  22. package/dist/card-DqPrL79i.mjs +24 -0
  23. package/dist/{card-DZxRmver.mjs → card-voh1k4hl.mjs} +14 -11
  24. package/dist/{cards-CNbV8aGO.mjs → cards-CvWT-tKQ.mjs} +7 -7
  25. package/dist/cli.mjs +567 -70
  26. package/dist/client-yPhazV6T.mjs +4093 -0
  27. package/dist/collection-BsXk1V41.mjs +20 -0
  28. package/dist/{collection-CfulNRBG.mjs → collection-BxdPxD38.mjs} +1 -1
  29. package/dist/{collection-CGoVLvcD.mjs → collection-DYM0p3Xl.mjs} +1 -1
  30. package/dist/{collection-namespace-CEoQ7G08.mjs → collection-namespace-C5SNf6Yw.mjs} +2 -2
  31. package/dist/{content-translation-CxTabpLF.mjs → content-translation-BNYQ8fJ3.mjs} +3 -3
  32. package/dist/{create-CEP4Jsrd.mjs → create-BVd4Y4py2.mjs} +6 -6
  33. package/dist/{create-ku05K1Oj.mjs → create-BZyLtvg5.mjs} +6 -6
  34. package/dist/{create-UxWtLwXT.mjs → create-BsiUuwSb.mjs} +5 -5
  35. package/dist/{create-WIIp7MVV.mjs → create-C1fVgFBd.mjs} +4 -4
  36. package/dist/{create-M8qXs24L.mjs → create-C4U9DGDG.mjs} +7 -7
  37. package/dist/{create-BTvSwLws.mjs → create-CHn7P-Bz.mjs} +5 -5
  38. package/dist/{create-BikaTHCw.mjs → create-CL4xkZ4j.mjs} +6 -6
  39. package/dist/{create-CYhsYOOJ.mjs → create-CcOTodqT.mjs} +4 -4
  40. package/dist/{create-BGV7ejai.mjs → create-Cmgq35ZB.mjs} +4 -4
  41. package/dist/{create-U15wd8_9.mjs → create-DPb3b69Y.mjs} +4 -4
  42. package/dist/{create-DMLjSEkF.mjs → create-DRyA-nuP.mjs} +5 -5
  43. package/dist/{create-CtDaASGO.mjs → create-DTfaHMNw.mjs} +6 -6
  44. package/dist/{create-BGy4L_yh.mjs → create-Db3QVXRi.mjs} +7 -7
  45. package/dist/{create-BsvpUxJq.mjs → create-DqKDw2zq.mjs} +5 -8
  46. package/dist/{create-CsABLrSI.mjs → create-S0jXAtl2.mjs} +11 -7
  47. package/dist/{create-BMokmmLp2.mjs → create-Z_gzD_p-2.mjs} +8 -8
  48. package/dist/{create-branch-Bkq9rtf7.mjs → create-branch-hYwnfY8X.mjs} +5 -9
  49. package/dist/{csv-GincCch9.mjs → csv-DOEqRG95.mjs} +5 -5
  50. package/dist/{current-task-CbnNWQ7H.mjs → current-task-DVo5aDfA.mjs} +5 -8
  51. package/dist/{dashboard-CKUR8ZpQ.mjs → dashboard-D0hwTC-f.mjs} +11 -2
  52. package/dist/{dashboard-ReNaou5J.mjs → dashboard-D8Yjjwfr.mjs} +10 -10
  53. package/dist/{dashboard-BlbNszi8.mjs → dashboard-DgK81azj.mjs} +1 -1
  54. package/dist/{database-B19qlLKZ.mjs → database-C3E9PZSx.mjs} +1 -1
  55. package/dist/{database-C8G6ZKG0.mjs → database-JtHTqSpq.mjs} +1 -1
  56. package/dist/{db-2hSYsqHk.mjs → db-ntq1NYVT.mjs} +7 -7
  57. package/dist/{delete-Bv3_SIqh.mjs → delete-BQWk6Ogb.mjs} +5 -5
  58. package/dist/{delete-CZqleA9Q.mjs → delete-C2iVm203.mjs} +5 -5
  59. package/dist/{delete-C1YmyeVy.mjs → delete-CPzdQGKf.mjs} +5 -5
  60. package/dist/{delete-DNsY94Ok.mjs → delete-CW8xJwDm.mjs} +5 -5
  61. package/dist/{delete-BEPw7WRT.mjs → delete-CZqaDxkf.mjs} +5 -5
  62. package/dist/{delete-B2wmUpj_.mjs → delete-Qsf-OKkl.mjs} +5 -5
  63. package/dist/{delete-runtime-D74s6vhu.mjs → delete-runtime-BKEzJn22.mjs} +1 -2
  64. package/dist/{delete-table-DySwoEaq.mjs → delete-table-DLufNvzW.mjs} +5 -5
  65. package/dist/{dependencies-ygT6uMu4.mjs → dependencies-BGtd-eIR.mjs} +7 -7
  66. package/dist/{dirty-BkiHZ8gb.mjs → dirty-BiiJ5Ngh.mjs} +6 -9
  67. package/dist/{document-Cd2mmqCp.mjs → document-BHpLJbKU.mjs} +5 -0
  68. package/dist/document-BiS-U56S.mjs +19 -0
  69. package/dist/{document-D6OybtP2.mjs → document-CA0Q6lqu.mjs} +1 -1
  70. package/dist/{download-Chr-YNTG.mjs → download-DrcL0yRr.mjs} +3 -6
  71. package/dist/{eid-BvY-YGpN.mjs → eid-Bn3Impnq.mjs} +4 -5
  72. package/dist/{events-B01P0G7C.mjs → events-CfnrXbim.mjs} +5 -5
  73. package/dist/{export-CG23iezf.mjs → export-CFK8cMvK.mjs} +7 -10
  74. package/dist/{field-Cr2DPUG9.mjs → field-CcN4oZy6.mjs} +16 -1
  75. package/dist/{field-DikmNcAt.mjs → field-CeP-41qf.mjs} +5 -5
  76. package/dist/{field-BPsNa-TO.mjs → field-fDtIrY6D.mjs} +1 -1
  77. package/dist/{fields-C9BF3jHL.mjs → fields-B3tJI4X2.mjs} +7 -7
  78. package/dist/{get-B3jvGI0b.mjs → get-3ymehUjQ.mjs} +6 -6
  79. package/dist/{get-gFM8-HHP.mjs → get-B9fPTBEQ.mjs} +5 -8
  80. package/dist/{get-PKhv8WUf.mjs → get-BFh5ctuV.mjs} +6 -6
  81. package/dist/{get-N5EUCDL0.mjs → get-BMZ3UoJz.mjs} +6 -6
  82. package/dist/{get-DZpRq_Fw.mjs → get-Be9oShms.mjs} +4 -4
  83. package/dist/{get-DvqYIBp5.mjs → get-BkTiIo_7.mjs} +4 -4
  84. package/dist/{get-Blbcl76m.mjs → get-C-E-I10i.mjs} +6 -6
  85. package/dist/{get-FJofgEPB.mjs → get-CIlXE4zy.mjs} +6 -6
  86. package/dist/{get-UW0DOjH5.mjs → get-Cqfb4zZM.mjs} +4 -4
  87. package/dist/{get-BtauixMx.mjs → get-Cxvi9pSj.mjs} +6 -6
  88. package/dist/{get-Buxkx-RX.mjs → get-D2Bt3r3M.mjs} +4 -4
  89. package/dist/{get-DdSB-fpR.mjs → get-DJDV3NMU.mjs} +5 -5
  90. package/dist/{get-DY-e5oP7.mjs → get-D_f0INnl.mjs} +6 -6
  91. package/dist/{get-BHpVRSbm.mjs → get-Diozf-D0.mjs} +6 -6
  92. package/dist/{get-C1V7vZse.mjs → get-Dl9WoeCd.mjs} +4 -4
  93. package/dist/{get-C99cjjD0.mjs → get-DlPhNHPX.mjs} +6 -6
  94. package/dist/{get-BYSFFlsd.mjs → get-DnVGJfW42.mjs} +6 -6
  95. package/dist/get-Dx4k6_Qt.mjs +93 -0
  96. package/dist/{get-CkMLxzVy.mjs → get-lRUl1Dnb.mjs} +4 -4
  97. package/dist/{get-CMMXBVff.mjs → get-pGqPQ0Of.mjs} +6 -6
  98. package/dist/{get-run-F7ARJeAD.mjs → get-run-DmtNpSbG.mjs} +6 -6
  99. package/dist/{git-sync-BDnxPrqU.mjs → git-sync-BwBRmEhE.mjs} +18 -1
  100. package/dist/{git-sync-DxD_ng48.mjs → git-sync-TjX1r_wF.mjs} +1 -1
  101. package/dist/git-sync-jvNlPu2I.mjs +28 -0
  102. package/dist/{group-DBM87IgC.mjs → group-YQQ5GIcP.mjs} +2 -2
  103. package/dist/{has-remote-changes-Bwyp8mc-.mjs → has-remote-changes-BS6jOb2-.mjs} +5 -8
  104. package/dist/{import-CPY8aM8d.mjs → import-Cur2I6Yc.mjs} +7 -10
  105. package/dist/{input-DH9i67x_.mjs → input-DEvkIjGr.mjs} +1 -1
  106. package/dist/{is-dirty-0F_UJY7Q.mjs → is-dirty-7Jo0tglq.mjs} +3 -6
  107. package/dist/{items-FUop0zGR.mjs → items-BBJSvqWt.mjs} +7 -7
  108. package/dist/{key-BEhqIzIQ.mjs → key-PYetuQ13.mjs} +1 -1
  109. package/dist/library-BPIzb3K_.mjs +81 -0
  110. package/dist/{library-DpOtb0E0.mjs → library-CpDosMc5.mjs} +5 -5
  111. package/dist/{library-DfYAT2Ep.mjs → library-PGCfm0UA.mjs} +1 -1
  112. package/dist/{list-B-74c1BD.mjs → list--Frwwg4i.mjs} +7 -7
  113. package/dist/{list-BASNYNJr.mjs → list-40V_8T3H.mjs} +4 -4
  114. package/dist/{list-xC99-2X0.mjs → list-BAO7rPNU.mjs} +4 -4
  115. package/dist/{list--B2EUWJg.mjs → list-BAaBsdMk.mjs} +6 -6
  116. package/dist/{list-rQ-6XSua.mjs → list-BCD9lkxc.mjs} +4 -4
  117. package/dist/{list-BQaXU1bp.mjs → list-BuZaFlV-.mjs} +4 -4
  118. package/dist/{list-Beoh2AYD.mjs → list-C7kqJAc8.mjs} +4 -4
  119. package/dist/{list-CGkgypYz.mjs → list-CBGsfTib.mjs} +7 -7
  120. package/dist/{list-Uc1OxV36.mjs → list-CFJyXUsF.mjs} +14 -13
  121. package/dist/{list-DfbsmsHv.mjs → list-CQJoLqy0.mjs} +7 -7
  122. package/dist/{list-DdFViPYS.mjs → list-CVs3TyU7.mjs} +6 -6
  123. package/dist/{list-DMlFbccD.mjs → list-CX2668xz.mjs} +6 -6
  124. package/dist/{list-ba7lI44w.mjs → list-CcyZu5Jp.mjs} +6 -6
  125. package/dist/{list-C2qxVTu7.mjs → list-DPvJihmj.mjs} +7 -7
  126. package/dist/{list-BQrk4Ua4.mjs → list-D_Kv8Ezq.mjs} +7 -7
  127. package/dist/{list-GyP4b_tU.mjs → list-DuZlYCTl.mjs} +5 -5
  128. package/dist/{list-Bqm0F1Y-.mjs → list-_6JwpPXA.mjs} +6 -6
  129. package/dist/{list-lzIKVtE9.mjs → list-bCtszwHJ.mjs} +4 -4
  130. package/dist/list-rojRNBu5.mjs +60 -0
  131. package/dist/{login-D5jt0q9K.mjs → login-BCxYB6ii.mjs} +15 -12
  132. package/dist/{logout-DViy0VzV.mjs → logout-BVEYg9pV.mjs} +3 -4
  133. package/dist/{measure-IPlonpqU.mjs → measure-DYmGuTVW.mjs} +6 -6
  134. package/dist/{notification-Fcq1fIPw.mjs → notification-DVrLkjFT.mjs} +1 -1
  135. package/dist/{parameter-DUKR8NXo.mjs → parameter-Celg0wZa.mjs} +1 -1
  136. package/dist/{parameter-values-CHyOCxmR.mjs → parameter-values-D4qte8qc.mjs} +5 -6
  137. package/dist/{parse-enum-D0Jfm_Bz.mjs → parse-enum-Dc0dMZ3P.mjs} +1 -1
  138. package/dist/{parse-id-CPINxy7h.mjs → parse-id-BSdAXN-r.mjs} +1 -1
  139. package/dist/{parse-ref-ibKVB0J4.mjs → parse-ref-DTDld_LJ.mjs} +1 -1
  140. package/dist/{path-bMZzUOVo.mjs → path-BNZf4ETt.mjs} +5 -5
  141. package/dist/{poll-75SvT7Zv.mjs → poll-CZeXepUQ.mjs} +2 -2
  142. package/dist/{preflight-CoF1Em99.mjs → preflight-BsT-Ik4Z.mjs} +3 -4
  143. package/dist/{process-DBOOrmET.mjs → process-CTrfxxaC.mjs} +1 -1
  144. package/dist/{publish-Cs-OUG6n.mjs → publish-3Qlrs4CC.mjs} +9 -9
  145. package/dist/{pulse-BmsDenXm.mjs → pulse-Dz0ocv0l.mjs} +1 -1
  146. package/dist/{pulse-DhG6I9mI.mjs → pulse-x0gFxWfG.mjs} +2 -2
  147. package/dist/{query-CEdmSEq8.mjs → query-B8MCziCM.mjs} +9 -10
  148. package/dist/{query-CpD46hL6.mjs → query-DxjE4Hq2.mjs} +10 -12
  149. package/dist/{query-result-DBDwk8TS.mjs → query-result-E4Q-Gra6.mjs} +1 -1
  150. package/dist/{remove-collection-DynsqkwG.mjs → remove-collection-CNWmp8C-.mjs} +6 -9
  151. package/dist/{render-CI93iP0I.mjs → render-MoT089RO.mjs} +13 -2
  152. package/dist/{replace-C6YqqCG9.mjs → replace-DOmUXCyk.mjs} +5 -5
  153. package/dist/{rescan-values-C6PB02uT.mjs → rescan-values-DpU_Ex0F.mjs} +6 -6
  154. package/dist/{run-C7PXBBEl.mjs → run-B8Vys-6V.mjs} +5 -5
  155. package/dist/{run-Cb86sH_c.mjs → run-CCPUWI0V.mjs} +6 -6
  156. package/dist/{run-CpmWoOGp.mjs → run-cyUFpMX3.mjs} +26 -14
  157. package/dist/{runs-CCRszsbB.mjs → runs-92XSK8ij.mjs} +7 -7
  158. package/dist/{runtime-BMJv4VOi.mjs → runtime-DzVkvFHY.mjs} +946 -246
  159. package/dist/{schema-tables-BQdFNy1B.mjs → schema-tables-lMGk2fyi.mjs} +7 -7
  160. package/dist/{schemas-CNAPFh4n.mjs → schemas-C83Q8dYY.mjs} +5 -5
  161. package/dist/{search-DFBwUc6d.mjs → search-BAXg-EJw.mjs} +2 -1
  162. package/dist/{search-BKVV6YtB.mjs → search-D6qBaNsw.mjs} +6 -6
  163. package/dist/{segment-CDoZHSYX.mjs → segment-BFJd2-ck.mjs} +6 -6
  164. package/dist/{selectors-BXbjj36S.mjs → selectors-Dcp25rNo.mjs} +3 -3
  165. package/dist/{send-D2eXL9lt.mjs → send-Be-_KmWr.mjs} +4 -4
  166. package/dist/{set-sHBtSGLi.mjs → set-Bg_4elCb.mjs} +5 -5
  167. package/dist/{set-active-DT61WwV0.mjs → set-active-CtQiMzt7.mjs} +5 -5
  168. package/dist/{setting-dkfKvCxc.mjs → setting-BNEblMco.mjs} +4 -4
  169. package/dist/{setup-TOwWatgm.mjs → setup-DFnxwJGX.mjs} +4 -4
  170. package/dist/{signal-CMd0EFUa.mjs → signal-k7cm5N6h.mjs} +11 -2
  171. package/dist/skill-list-Ro6J0pyV.mjs +76 -0
  172. package/dist/skills-BdrMrbXh.mjs +351 -0
  173. package/dist/{skills-BcOjZldN.mjs → skills-CGYk6b2r.mjs} +3 -3
  174. package/dist/snippet-vMnFtNwi.mjs +19 -0
  175. package/dist/{stash-BgWw2lyu.mjs → stash-C9SZwusp.mjs} +7 -11
  176. package/dist/{status-B14FO8n7.mjs → status-D0n7AuQU.mjs} +12 -11
  177. package/dist/{status-J4pEIm-c.mjs → status-Dj04FCCv.mjs} +11 -9
  178. package/dist/{subscription-B1uuKxM7.mjs → subscription-B5Iax7Ci.mjs} +6 -6
  179. package/dist/{subscriptions-BHIATSN6.mjs → subscriptions-DwvHRO1v.mjs} +7 -7
  180. package/dist/{summary-B1V5TXaZ.mjs → summary-DaA6Twxk.mjs} +6 -6
  181. package/dist/{sync-schema-D1vX-rpv.mjs → sync-schema-BFWKEC3r.mjs} +7 -7
  182. package/dist/{sync-task-BACcrs0i.mjs → sync-task-BXeWuARG.mjs} +1 -1
  183. package/dist/{table-CsIJNPFf.mjs → table-C6h4tIRw.mjs} +1 -1
  184. package/dist/{table-CDeO1WbH.mjs → table-DW1dG3Rl.mjs} +5 -5
  185. package/dist/{table-CeeTJgQb.mjs → table-DfuY0N8e.mjs} +51 -4
  186. package/dist/timeline-C0rqHF4p.mjs +21 -0
  187. package/dist/{timeline-event-oGmne082.mjs → timeline-event-D1MUnexK.mjs} +6 -6
  188. package/dist/{transform-DoTyyXAu.mjs → transform-CtqB1WYo.mjs} +2 -2
  189. package/dist/transform-D08iA4H_.mjs +28 -0
  190. package/dist/{transform-D3QX0jxA.mjs → transform-DiW7bREn.mjs} +68 -5
  191. package/dist/{transform-job-50GZHhKH.mjs → transform-job-AaMZRxAq.mjs} +1 -1
  192. package/dist/{transform-job-DRrK28IH.mjs → transform-job-CCguL6LP.mjs} +41 -4
  193. package/dist/transform-job-Me5CeV2z.mjs +22 -0
  194. package/dist/{transform-tag-Bpj8l5Ci.mjs → transform-tag-CbgjSy76.mjs} +5 -5
  195. package/dist/{transform-test-BJOPAwKl.mjs → transform-test-B-gVzODx.mjs} +1 -1
  196. package/dist/transform-test-BB_IFtZS.mjs +163 -0
  197. package/dist/transform-test-CwonhnyQ.mjs +16 -0
  198. package/dist/{transforms-K7Y4ON_q.mjs → transforms-Bhtk_Gil.mjs} +7 -7
  199. package/dist/{tree-CtFtroe4.mjs → tree-DLorrdEm.mjs} +4 -5
  200. package/dist/{unpublish-D7UaaIWA.mjs → unpublish-DOQhmLAx.mjs} +4 -7
  201. package/dist/{update-BvbPpgOL.mjs → update-BF4DWRT5.mjs} +6 -6
  202. package/dist/{update-dRAPKE3c.mjs → update-BeU02D8b.mjs} +6 -6
  203. package/dist/{update-C_wTtrtX.mjs → update-Bpb2V8Gm.mjs} +9 -9
  204. package/dist/{update-DUNJEk8m.mjs → update-CHNSRFKO.mjs} +7 -7
  205. package/dist/{update-BpuZsX9z.mjs → update-CSqPKfTk.mjs} +8 -8
  206. package/dist/{update-bix8NoKq.mjs → update-CTCcgeaY.mjs} +7 -7
  207. package/dist/{update-BlBEKrNE.mjs → update-Ch43eYU-.mjs} +5 -5
  208. package/dist/{update-MWaDj2VX.mjs → update-D2dis8s_.mjs} +8 -8
  209. package/dist/{update-YkB3xWUh.mjs → update-DEULsCgK.mjs} +6 -6
  210. package/dist/{update-B7veBLhx.mjs → update-DTZ07XFM.mjs} +5 -5
  211. package/dist/{update-CGJXd_E3.mjs → update-DWhC3xYc.mjs} +5 -5
  212. package/dist/{update-HqUKBeM2.mjs → update-DeA4gyTG.mjs} +5 -5
  213. package/dist/{update-BicO3Lio.mjs → update-Dq-KEeyS.mjs} +7 -7
  214. package/dist/{update-dashcard-BGqKMqQb.mjs → update-dashcard-CfDqxOlj.mjs} +7 -7
  215. package/dist/{update-3ksm443P.mjs → update-ezD5XTpy.mjs} +7 -7
  216. package/dist/{update-e4ufwrkF.mjs → update-mmeImeUo.mjs} +7 -7
  217. package/dist/{update-D9Nfv864.mjs → update-xjuN7bdu.mjs} +7 -7
  218. package/dist/{upgrade-DkQ1wk4z.mjs → upgrade-DgmbeOoJ.mjs} +6 -8
  219. package/dist/upload-BsPrAjN-.mjs +13 -0
  220. package/dist/{upload-CD555ui1.mjs → upload-Do2PBSeH.mjs} +2 -2
  221. package/dist/{upload-BfGc-L4t.mjs → upload-DzFBdNxM.mjs} +4 -7
  222. package/dist/{uuid-BLBLkWAF.mjs → uuid-DYYGRv9y.mjs} +3 -4
  223. package/dist/{validate-BWchyW0V.mjs → validate-EAB-1EkK.mjs} +1 -1
  224. package/dist/{validate-query-DaGYSmpQ.mjs → validate-query-CQG86147.mjs} +2 -3
  225. package/dist/{values-8CrXBkyg.mjs → values-Dk2CAR4T.mjs} +6 -6
  226. package/dist/{verify-nNVN-0CR.mjs → verify-8TnYrSNm.mjs} +3 -18
  227. package/dist/{wait-YrD7UYFF.mjs → wait-Oz6xFpyA.mjs} +7 -10
  228. package/dist/{wait-flags-CDtMS8FP.mjs → wait-flags-ClJx9LJ9.mjs} +2 -2
  229. package/dist/{window-BkvrP0gB.mjs → window-DSb1tqSe.mjs} +1 -1
  230. package/package.json +1 -1
  231. package/skill-data/core/SKILL.md +29 -13
  232. package/skill-data/data-workflow/references/building-clean-tables.md +6 -2
  233. package/skill-data/data-workflow/references/reusable-definitions.md +11 -3
  234. package/skill-data/document/SKILL.md +4 -1
  235. package/skill-data/git-sync/SKILL.md +5 -0
  236. package/skill-data/mbql/SKILL.md +1 -1
  237. package/skill-data/mbql/references/operators.md +20 -15
  238. package/skill-data/metadata/SKILL.md +1 -1
  239. package/skill-data/metadata/references/semantic-types.md +7 -1
  240. package/skill-data/native-sql/references/template-tags.md +6 -2
  241. package/skill-data/notification/SKILL.md +7 -1
  242. package/skill-data/transform/SKILL.md +25 -7
  243. package/skill-data/transform-test-plan/SKILL.md +171 -0
  244. package/skill-data/transform-test-plan/references/checklist.md +81 -0
  245. package/skill-data/transform-test-plan/references/checks.md +259 -0
  246. package/skill-data/visualization/SKILL.md +11 -3
  247. package/skill-data/visualization/references/settings.md +6 -4
  248. package/skills/metabase-cli/SKILL.md +1 -1
  249. package/dist/card-p2r_szeS.mjs +0 -24
  250. package/dist/client-DynvZqa0.mjs +0 -2282
  251. package/dist/collection-CAM47Der.mjs +0 -20
  252. package/dist/document-DGbDloCb.mjs +0 -19
  253. package/dist/get-B4GltkXP.mjs +0 -80
  254. package/dist/git-sync-IW4T2sKq.mjs +0 -28
  255. package/dist/library-ClLgrAXy.mjs +0 -19
  256. package/dist/list-CvzWE6CS.mjs +0 -98
  257. package/dist/network-error-D6CiOEBw.mjs +0 -431
  258. package/dist/predicates-Bkm2IoeX.mjs +0 -170
  259. package/dist/skills-DTCrMcix.mjs +0 -216
  260. package/dist/snippet-DMdFqvNq.mjs +0 -19
  261. package/dist/timeline-MQFX3Fla.mjs +0 -21
  262. package/dist/transform-CWIqW64R.mjs +0 -28
  263. package/dist/transform-job-DpF2MARE.mjs +0 -22
  264. package/dist/transform-test-BhkpwFqD.mjs +0 -16
  265. package/dist/transform-test-Dhcj7u-U.mjs +0 -142
  266. package/dist/upload-JN6EK96c.mjs +0 -13
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: transform-test-plan
3
+ description: Derive a comprehensive test plan for a transform — the fixture cast, the expectations, hand-derived expected rows, and a coverage matrix — from the model's declared design. Covers input partitioning (zero-case, multiplicity, dirty rows), grain / conservation / recomputation / conformance checks, and known-quirk conventions. Load when the user wants tests planned or written for transforms — "write tests for my transforms", "is my model right", "test plan for this pipeline", "add data quality checks" — whether the model is mid-build or already deployed. The `mb transform-test` command and body shapes live in the `transform` skill; this one decides what to test.
4
+ allowed-tools: Read, Write, Edit, Bash, AskUserQuestion
5
+ requires: [transformTests]
6
+ ---
7
+
8
+ # Planning transform tests
9
+
10
+ Turn a transform into a fixture cast that proves the logic on small known rows, expectations that
11
+ state the model's invariants, and a coverage matrix showing what's checked and what's deliberately
12
+ not. Mechanics — the `inputs`/`expectations` body shape and every `mb transform-test` verb — live in
13
+ the `transform` skill (`mb skills get transform`); load it before authoring, and never restate it
14
+ here.
15
+
16
+ Every check derives from what the model **declares** — detected from its SQL, confirmed with its
17
+ owner — never from conformance to a modeling doctrine. One plan serves two moments: while the model
18
+ is **built**, checks pin each design decision; once **deployed**, the same SQL screens production
19
+ tables for anomalies.
20
+
21
+ ## Operating rules
22
+
23
+ - **Detect, then derive.** Classify what the transform is and which conventions it uses (the
24
+ checklist); derive checks only from that. Star, one-big-table, partial denormalization — all
25
+ fine; never flag a style.
26
+ - **Judgment calls go through the checklist.** The session's autonomy setting governs which answers
27
+ you supply yourself and which you bring to the user — it never makes the checklist a formality.
28
+ Every answer you supply yourself is recorded in the plan as a stated assumption, paired with the
29
+ named expectation that enforces it — reversing the decision then breaks a test, not a paragraph.
30
+ And regardless of setting, when genuinely unsure, ask — a wrong-but-confident grain poisons every
31
+ downstream check.
32
+ - **Expected rows are derived by hand** from the fixture story and business meaning — never captured
33
+ from the transform's output, which asserts only that the transform equals itself.
34
+ - **Batteries stay off until declared structure switches them on.** No snapshot-density checks
35
+ without a snapshot, no version-history checks without effective/end/current columns. An empty
36
+ section beats a speculative one.
37
+
38
+ ## The procedure
39
+
40
+ 1. **Profile the real inputs**: per table, row count; per column, min/max/distinct-count/null
41
+ incidence; orphan counts across declared links (`mb field summary`, `mb query`). Profiling feeds
42
+ domains, bounds, null partitions, and key candidates — and every fixture edge cites the real-data
43
+ condition that warrants it, with its count ("the warehouse has 67 ship-before-order rows").
44
+ 2. **Detect.** Read the transform's SQL (`mb transform get <id> --full --json`) for: grain
45
+ candidates (`GROUP BY` keys, the joins' driving table), join types (orphan handling), correlated
46
+ aggregates (stored aggregates), `<entity>_<attr>` naming (copies), effective/end/current columns
47
+ (version history), `now()`/`current_date` (volatile columns). A transform whose grain you cannot
48
+ state in one phrase is itself a finding — raise it before writing any test.
49
+ 3. **Confirm.** Walk [references/checklist.md](references/checklist.md). Three stages: classify the
50
+ model, per-table declarations, per-column declarations. Each question carries its detection hint;
51
+ answer autonomously where the hint resolves, ask where it doesn't. In build-along mode these are
52
+ design questions — treat an undecided answer as a decision to make together, not a blocker.
53
+ 4. **Derive.** Route every output column through [references/checks.md](references/checks.md) —
54
+ declared property → expectation shape, fixture implication, expected-row convention. Read it in
55
+ full once per plan; it is the plan's content.
56
+ 5. **Design the fixture cast**: one small cast per transform (≈5–10 rows per table), human-named
57
+ rows ("Alice Premium"), every row a named edge — zero-case entities for every outer join and
58
+ aggregation, ≥2-member groups for every grouping and join, one dirty row per screenable defect,
59
+ boundary dates. Document it as a table (row → attributes → purpose) in the plan.
60
+
61
+ Express the cast as literal rows rather than as a query, so the story stays legible in the test
62
+ itself; a query is worth it only when the rows are mechanical to generate. A cast is written
63
+ against one warehouse and does not carry to another.
64
+
65
+ 6. **Hand-derive the expected rows**, arithmetic recorded in the plan (premium: 3 orders / 350.50 /
66
+ 3.0). Every fixture row's fate appears in some expected cell. Pin NULL-vs-0-vs-empty for every
67
+ zero-case row — that cell is the null policy's only enforcement.
68
+ 7. **Author the test.** One test per transform, per coherent story: an `equals` pinning the output,
69
+ and `empty` expectations stating the invariants that survive a change to the cast.
70
+
71
+ Give each expectation a name that states the invariant, because the name is what a
72
+ failure leads with ("revenue never negative", not "check 3"), and open each `empty` expectation's
73
+ SQL with a `--` contract comment: the invariant, and the failure modes it catches ("catches both
74
+ dropped orders and join fan-out").
75
+
76
+ Where one invariant applies to several transforms, duplicate the SQL. Nothing is shared between
77
+ tests, so give each copy its own name and comment rather than one that only makes sense next to
78
+ its twin.
79
+
80
+ 8. **Emit the coverage matrix** in the plan: rows = output columns with the table's grain; columns =
81
+ check classes (grain, conservation, recomputation, conformance, domains, referential integrity,
82
+ temporal, screens); cells name the covering expectation or expected-row cell, or state
83
+ `gap: <reason>`. Scan shared-attribute columns across transforms for cross-table agreement
84
+ obligations. Empty cells are honest; silent gaps are not.
85
+ 9. **Prove the tests have teeth.** Once per test: corrupt one expected cell, `run`, confirm
86
+ `cell-mismatches` names exactly that column; revert. Then perturb one input cell and confirm
87
+ exactly the declared output cells move. Every `empty` expectation passes against an empty output,
88
+ so a green test can still be vacuous.
89
+
90
+ ## Severity: error, or the tolerated oddity
91
+
92
+ Every expectation is pass or fail, and one failure fails the run. **error** = forbidden, and it
93
+ becomes an `empty` expectation. There is no warn severity, so **never author an expectation you
94
+ expect to fire**: a permanently red test trains everyone to ignore the result, and a red run gates
95
+ everyone else's work.
96
+
97
+ A tolerated-but-surfaced oddity — one the owner lives with, like orphan rows or ship-before-order
98
+ dates — gets encoded the two ways that hold: **pin it in the `equals` rows** (an orphan passing
99
+ through with NULLs is a cell in the expected output, so reversing the tolerance breaks the test),
100
+ and **record it in the plan's known-quirks list** with its real-data count, so the tolerance stays a
101
+ conscious choice.
102
+
103
+ Under budget pressure cut business-rule checks first, then cross-table structure checks; never
104
+ single-column screens (domains, ranges, nulls) — cheapest, and the last line.
105
+
106
+ ## When a check exposes a live bug
107
+
108
+ Non-negotiable: **never soften the test to green** — expected values state correct behavior; matching
109
+ them to buggy output documents the bug as intended — and **surface the finding with its blast radius
110
+ at both scales**, fixture ("1530.24 of 1600.74 fixture dollars survive") and warehouse ("908 of
111
+ 2,050 orders dropped"). What happens next follows the session's terms, not a fixed protocol: propose
112
+ and apply the fix now (when the user wants it or the autonomy setting covers it), or — when the fix
113
+ must wait — hold the correct expectation and record the red in the plan with the minimal fix body.
114
+ A stored test has no red-by-design state, so a deferred
115
+ fix must be visible in the plan or the test reads as broken. Either way, once green the test stays
116
+ as the regression guard.
117
+
118
+ ## When the doctrine doesn't apply
119
+
120
+ The vocabulary follows Kimball's dimensional modeling (grain, additivity, conformed attributes,
121
+ slowly changing dimensions) — precise, widely understood terms. Real models are Kimball-inspired at
122
+ most; no check may score adherence:
123
+
124
+ - Full calendar date dimensions are rare. Never demand one; test date _semantics_ — ranges,
125
+ orderings, volatile derivations.
126
+ - Surrogate keys are doctrine, natural-key joins are practice. Test whichever key the model
127
+ declares; never flag natural-key joins.
128
+ - "No NULL FKs / no NULL attributes" is doctrine routinely dropped. Null policy is three independent
129
+ declarations — measures, attributes, FKs — each detected and confirmed, never presumed.
130
+ - One-big-table is legitimate: it still has a grain, its copies still need agreement checks, its
131
+ functional dependencies still hold.
132
+ - A transform-level `ORDER BY` has no testable effect — output tables carry no row order and the
133
+ `equals` comparison is a multiset. Flag it as probable dead weight (clustering hints aside); never
134
+ write an ordering expectation.
135
+
136
+ ## One transform at a time
137
+
138
+ Each test covers one transform. When the transform under test reads another transform's output,
139
+ that target table is an input like any other: declare it and fake it. Derive those rows from the
140
+ base transform's own expected output, so the two tests tell one story, and note the coupling in both
141
+ plans — changing the base's expected rows means changing this test's input.
142
+
143
+ ## Worked example, condensed
144
+
145
+ `orders` + `customers` → _enriched_orders_ (order grain; LEFT JOIN attaches `customer_name`,
146
+ `tier`).
147
+
148
+ Cast, 7 orders: two tiers; Alice and Carol with 2 orders each (multiplicity); two never shipped
149
+ (zero-case for the shipping join); order 106 shipped before ordered (real oddity, count cited);
150
+ order 107's customer_id matches no customer (orphan). Two `rows` inputs, one per source table.
151
+
152
+ Derived, per catalog: grain uniqueness on `order_id`; row and amount conservation from input to
153
+ output, as scalar subqueries over the target and the seeded input; `tier` domain ⊆ {standard,
154
+ premium}; orphan = keep-with-NULLs → an expected row pinning the NULL pass-through; ship-before-order
155
+ tolerated → the plan's known-quirks list with the warehouse count. The whole output pinned in one
156
+ `equals`, hand-computed, arithmetic in the plan. The inner-vs-LEFT-join bug this cast catches —
157
+ unshipped orders silently dropped from revenue — is what the zero-case rows exist for.
158
+
159
+ ## Don't
160
+
161
+ - Don't author expectations before loading the `transform` skill — the body shape, the closed
162
+ create/update contract, and the verb flags live there.
163
+ - Don't capture expected rows from the transform's own output — hand-derive them or they assert
164
+ nothing.
165
+ - Don't emit checks for structure the model doesn't declare (snapshot density, version history,
166
+ bridge weights) — an inapplicable battery buries real findings.
167
+ - Don't let a fixture cast go all-clean — no zero-case, no orphan, no dirty row proves the happy
168
+ path and nothing else; the bugs live in the edges.
169
+ - Don't write an expectation you expect to fail.
170
+ - Don't surface bare check-ids ("per C3…") to the user — name the check in plain words; the ids are
171
+ for your cross-referencing, not their reading.
@@ -0,0 +1,81 @@
1
+ # Confirmation checklist
2
+
3
+ The judgment calls a plan depends on, in derivation order. Each question carries a **detect** hint —
4
+ how to answer it from the SQL, the metadata, or profiling. Answer autonomously where the hint
5
+ resolves cleanly; ask where it doesn't. Every answer you supply yourself goes into the emitted plan
6
+ as a stated assumption, phrased so the owner can falsify it at a glance ("Assuming `discount` can
7
+ never be negative — correct?").
8
+
9
+ In build-along mode these are design questions: the owner is deciding, not recalling. An undecided
10
+ answer is a decision to make together — surface the options and the check each implies (the
11
+ `checks.md` entry named in parentheses).
12
+
13
+ ## Stage 1 — classify the model (per transform)
14
+
15
+ 1. **Grain: one row per what?** (G1, G2)
16
+ Detect: `GROUP BY` keys; otherwise the driving table of the joins. Confirm whenever detection and
17
+ any written description disagree — that disagreement is itself a finding.
18
+ 2. **Fact-table type — and if periodic snapshot, dense or sparse?** (F2)
19
+ Detect: event-grain with a single event date → transaction; entity×period grain → periodic
20
+ snapshot (density is the one yes/no that flips its whole invariant set — always confirm); one row
21
+ per pipeline occurrence with milestone-date columns → accumulating snapshot.
22
+
23
+ ## Stage 2 — per-table declarations
24
+
25
+ 3. **Conservation ties: output rows/sums tie to which input, with which declared exclusions?** (A2)
26
+ Detect: `WHERE` clauses and join types name the exclusions (filtered rows, dropped duplicates).
27
+ Exclusions must be declared, or conservation appears to fail.
28
+ 4. **Zero-group policy: does a group with no contributing rows appear (with zeros) or stay absent?**
29
+ (A5)
30
+ Detect: driving table of the rollup — grouping the detail can't produce empty groups; joining a
31
+ dimension first can.
32
+ 5. **Orphan handling per join: drop / keep-with-NULLs / default row — and is an orphan tolerated or
33
+ forbidden?** (C3, I5)
34
+ Detect: join type. INNER = drop, LEFT = keep-with-NULLs, COALESCE to a sentinel = default row.
35
+ Tolerated-vs-forbidden is the owner's call — profiling says whether orphans exist today, not
36
+ whether they're acceptable. Forbidden becomes an `empty` expectation; tolerated is pinned in the
37
+ expected rows and recorded in the known-quirks list.
38
+ 6. **Version history: effective/end/current columns anywhere? If not, confirm overwrite-everywhere.**
39
+ (T1)
40
+ Detect: column names. Absence means history is silently rewritten in rollups — state that
41
+ consequence when confirming, not just the mechanism.
42
+ 7. **Does this transform read another transform's output?** (A5)
43
+ Detect: another transform's target table in this one's SQL. It becomes a declared input like any
44
+ other, faked from that transform's own expected output — confirm which rows, and record the
45
+ coupling in both plans.
46
+
47
+ ## Stage 3 — per-column declarations
48
+
49
+ 8. **Each measure: additive, semi-additive, or non-additive?** (A1)
50
+ Detect: sums and counts are additive; balances and levels are semi-additive; ratios, rates, and
51
+ unit prices are non-additive. Confirm the ambiguous ones (a "score"? a "quantity on hand"?).
52
+ 9. **Legal bounds per measure?** (Q1)
53
+ Detect: profiling min/max suggests, business meaning decides — can `discount` be negative? can
54
+ `quantity` be zero? Derived bounds are free (a sum of non-negatives is non-negative).
55
+ 10. **Each derived measure: the exact recomputation rule?** (A3)
56
+ Detect: the SELECT expression is the rule — but rounding, business-day adjustments, and NULL
57
+ handling are conventions to confirm, not read.
58
+ 11. **Which columns are stored aggregates, over which detail and filter?** (A4)
59
+ Detect: correlated subqueries / joined-aggregate CTEs in the SQL.
60
+ 12. **Which categorical columns have closed domains — enumerate; is NULL a member?** (C2)
61
+ Detect: profiling distinct values gives today's set; the owner confirms it's closed rather than
62
+ merely small so far.
63
+ 13. **Which columns are denormalized copies, of which owning attribute?** (C1)
64
+ Detect: `<entity>_<attr>` naming; any column functionally dependent on a non-grain key. Every hit
65
+ must be classified: copy (C1), stored aggregate (A4), or smuggled coarser-grain fact — a
66
+ finding.
67
+ 14. **Which many-to-one edges hold within one output table?** (C4)
68
+ Detect: hierarchy-shaped column pairs (product/category, zip/state). Applies where no owning
69
+ table is in scope; otherwise C1 covers it.
70
+ 15. **Which date orderings are business-guaranteed vs. known-violated and tolerated (with real-data
71
+ counts)?** (T2)
72
+ Detect: profiling counts the violations that exist; the owner decides tolerated vs. bug.
73
+ 16. **Null policy per column — measures, attributes, FKs separately.** (Q2)
74
+ Detect: the SQL shows what's produced (COALESCE, CASE); the owner confirms intent — "count of
75
+ nothing": 0 or NULL? empty date: NULL or sentinel?
76
+ 17. **Which columns are volatile across runs?** (T3)
77
+ Detect: `now()` / `current_date` / run-metadata expressions in the SQL. A volatile column is left
78
+ out of the `equals` columns; its form can still be asserted with an `empty`.
79
+ 18. **Per tolerated oddity: does it stay tolerated, and what is its current count?** (Q3)
80
+ Detect: can't — this is the conscious-choice question, and the plan's known-quirks list is where
81
+ it survives.
@@ -0,0 +1,259 @@
1
+ # Check catalog
2
+
3
+ Every check the plan can derive, grouped by theme. Per entry: **when it applies** (the declared
4
+ property that switches it on — blank means always), **assert** (the expectation shape), and
5
+ **fixtures** (what the input cast must contain for the check to have teeth).
6
+
7
+ Expectation SQL names the transform's **target table** and its **declared input tables** under their
8
+ real names; both are rewritten to the run's temp tables, so per-row recomputation joins against
9
+ inputs are writable. Anything else you name is left exactly as written and reads the real table.
10
+
11
+ Ids (G1, A2, …) are for cross-referencing within the plan documents only — never surface them to the
12
+ user bare.
13
+
14
+ Throughout, `<target>` stands for the transform's target table as written in the transform's own
15
+ definition, and `<input>` for a declared input table.
16
+
17
+ ## Grain & keys
18
+
19
+ **G1 — Declared grain.** Every output table states "one row per X"; the declaration anchors every
20
+ other check.
21
+
22
+ - Applies: always. Elicit or detect (GROUP BY keys; the join's driving table).
23
+ - Assert: nothing directly — G1 is the plan's opening move. A table with no statable grain, or a
24
+ grain stated inconsistently between docs and SQL, is a finding before any SQL runs.
25
+ - Fixtures: the grain declaration decides the cast's row structure.
26
+
27
+ **G2 — Grain-key uniqueness.** The grain key stays a key; doubles as the fan-out guard for every
28
+ enriching join.
29
+
30
+ - Applies: always — one-big-table, rollups, and stars all have a grain.
31
+ - Assert (`empty`): `SELECT <grain cols>, COUNT(*) FROM <target> GROUP BY <grain cols> HAVING
32
+ COUNT(*) > 1`. NULL grain values form their own bucket.
33
+ - Fixtures: a parent with ≥2 children on every join (I4) is what makes this check able to fail.
34
+
35
+ ## Additivity & reconciliation
36
+
37
+ **A1 — Measure additivity classification.** Additive / semi-additive (balances) / non-additive
38
+ (ratios, rates, unit prices) decides which aggregations are valid tests.
39
+
40
+ - Applies: every numeric measure; per-column declaration.
41
+ - Assert: routes the measure — additive → A2; semi-additive → sum across non-time slices only (a
42
+ test summing a balance over time is a bug in the plan); non-additive → A3 recomputation, never
43
+ reconciled by summing.
44
+ - Fixtures: none directly; one coverage-matrix axis (measure × valid aggregation set).
45
+
46
+ **A2 — Conservation reconciliation.** Row counts and additive-measure sums tie from input to output;
47
+ catches dropped rows and join double-counting at once.
48
+
49
+ - Applies: per declared tie (which input, which declared exclusions).
50
+ - Assert (`empty`): independent scalar subqueries compared with `IS DISTINCT FROM`, returning the
51
+ mismatched pair:
52
+ `SELECT (SELECT SUM(t.m) FROM <target> t) AS output_sum, (SELECT SUM(s.m) FROM <input> s) AS
53
+ input_sum WHERE (…) IS DISTINCT FROM (…)`.
54
+ Never reconcile via a fact-to-fact join — cardinality is uncontrollable and wrong results are
55
+ silent.
56
+ - Fixtures: amounts chosen so partial survival is visible (distinct values, odd cents).
57
+
58
+ **A3 — Derived-measure recomputation.** Averages, lags, ratios, rounded presentations recompute from
59
+ their components per row.
60
+
61
+ - Applies: every derived column, with its declared rule (rounding, business-day adjustment, NULL
62
+ handling).
63
+ - Assert (`empty`): `SELECT <key> FROM <target> t WHERE t.<derived> IS DISTINCT FROM <recomputation
64
+ from inputs or sibling columns>`.
65
+ - Fixtures: component values whose derivation is non-trivial (a NULL in the AVG, a negative lag).
66
+
67
+ **A4 — Stored aggregates on entity tables.** Lifetime/rollup stats carried on an entity-grain table
68
+ (`lifetime_orders`, `review_count`, `first_order_date`) equal recomputation from detail — per row
69
+ _and_ in total.
70
+
71
+ - Applies: columns detected as correlated aggregates over a detail table.
72
+ - Assert (`empty`), two per column: per-row — `WHERE t.<agg> IS DISTINCT FROM (SELECT
73
+ COUNT(*)/SUM(…)/MIN(…) FROM <detail> d WHERE d.<fk> = t.<key>)`; total — the A2 scalar-pair shape.
74
+ Totals alone cancel offsetting per-row errors; the per-row form is the one that catches them.
75
+ - Fixtures: an entity with several detail rows and an entity with none (I3/I4).
76
+
77
+ **A5 — Rollup consistency.** A layered rollup always agrees with its base.
78
+
79
+ - Applies: any transform reading another transform's output. The base is a declared input like any
80
+ other, faked with rows taken from the base transform's own expected output.
81
+ - Assert (`empty`): every rollup measure equals the corresponding aggregation over the base (A2
82
+ shape); group-set equality both directions — `SELECT <group> FROM <target> EXCEPT SELECT DISTINCT
83
+ <group col> FROM <base>` and the reverse, filtered by the declared zero-group policy.
84
+ - Fixtures: a group with no contributing rows pins the zero-group policy.
85
+
86
+ ## Fact-table type
87
+
88
+ **F2 — Fact-table type bundle.** Transaction / periodic snapshot / accumulating snapshot each carry
89
+ a distinct invariant set.
90
+
91
+ - Applies: per fact-shaped output, always classified; **transaction** needs nothing beyond G2 + A2
92
+ (sparsity is legitimate).
93
+ - Periodic snapshot, if declared _dense_: `COUNT(*) = |entities| × |periods|` (or the declared
94
+ subset); per-entity gap detection in the period series; inactive-period representation (zero vs
95
+ NULL) pinned in the expected rows. If sparse, density checks off — the one yes/no flips the whole
96
+ set.
97
+ - Accumulating snapshot: milestone dates monotone in pipeline order where set (`WHERE <later> <
98
+ <earlier>` per adjacent pair); unset-milestone default (NULL vs sentinel) pinned in the expected
99
+ rows; completion flags ∈ {0,1} and consistent with their date's set-ness; lags via A3.
100
+ - Fixtures (accumulating): occurrences at every completion stage — none, some, all milestones.
101
+
102
+ ## Conformance & domains
103
+
104
+ **C1 — Denormalized-copy agreement.** Every copied attribute agrees with the owning table's value
105
+ for that key.
106
+
107
+ - Applies: columns declared as copies (detect: `<entity>_<attr>` naming; any column functionally
108
+ dependent on a non-grain key). Each such column must be a declared copy (this check), a stored
109
+ aggregate (A4), or it's a smuggled coarser-grain fact — a finding: it double-counts under
110
+ summation.
111
+ - Assert (`empty`): `SELECT t.<key>, t.<copy>, d.<attr> FROM <target> t JOIN <owning input> d ON
112
+ t.<key> = d.<key> WHERE t.<copy> IS DISTINCT FROM d.<attr>`.
113
+ - Scope: in a test, the copies are produced by the very join under test, so this join-form is near-
114
+ tautological — the C4 functional-dependency form plus expected-row cell pinning carries the test.
115
+ The join-form against an independently materialized owning table is the _drift_ check, which
116
+ belongs to whatever screens the deployed tables.
117
+ - Fixtures: copies with distinct values per entity so a crossed join is visible.
118
+
119
+ **C2 — Closed-domain screen.** A categorical column's values stay inside the declared enumeration.
120
+
121
+ - Applies: per column declared closed (detect from profiling; confirm the set and whether NULL is a
122
+ member).
123
+ - Assert (`empty`): `SELECT <key>, <col> FROM <target> WHERE <col> IS NOT NULL AND <col> NOT IN
124
+ (<domain>)`.
125
+ - Fixtures: every domain value represented where practical; one out-of-domain input row if the
126
+ source can produce one (I5).
127
+
128
+ **C3 — Referential integrity / orphan policy.** Every FK resolves, or the declared orphan handling is
129
+ pinned.
130
+
131
+ - Applies: per join, conditioned on the declared response — drop / keep-with-NULLs / default row;
132
+ tolerated or forbidden.
133
+ - Assert, forbidden (`empty`): `SELECT t.<fk> FROM <target> t LEFT JOIN <dim input> d ON t.<fk> =
134
+ d.<key> WHERE t.<fk> IS NOT NULL AND d.<key> IS NULL`.
135
+ Tolerated: not an expectation — pin the orphan's pass-through as a row in the `equals` (NULL in
136
+ the copied attributes), and record the tolerance with its warehouse count in the plan.
137
+ Default-row convention adds: distinct unknown keys must not collapse into one output row.
138
+ - Fixtures: one orphan row (I5). Without it the join direction is untested — an inner join silently
139
+ dropping unmatched rows is the classic bug this catches.
140
+
141
+ **C4 — Many-to-one consistency.** Each declared many-to-one edge holds within the output (product →
142
+ one category; zip → one state).
143
+
144
+ - Applies: per declared edge; where an owning table is in scope, C1 subsumes it — this is the
145
+ one-big-table variant with nothing to join against.
146
+ - Assert (`empty`): `SELECT t.<many>, COUNT(DISTINCT t.<one>) FROM <target> t GROUP BY t.<many>
147
+ HAVING COUNT(DISTINCT t.<one>) > 1`.
148
+ - Fixtures: a violating input row if the source can produce one (I5), pinning the transform's
149
+ behavior on dirty input.
150
+
151
+ ## Temporal & version history
152
+
153
+ **T1 — Change handling per attribute.** How the model treats a changed source attribute decides the
154
+ temporal fixtures.
155
+
156
+ - Applies: detect effective/end/current housekeeping columns.
157
+ - Present → version-history battery (`empty` each): per durable key exactly one current row;
158
+ `effective < end` per row; intervals contiguous and non-overlapping; current row's end = the
159
+ declared far-future default; fact rows join the version whose interval contains the fact date.
160
+ - Absent → confirm overwrite-everywhere as a stated assumption (history is silently rewritten in
161
+ rollups), and derive the propagation probe: change an attribute in an input, run, assert the
162
+ output regrouped.
163
+ - Fixtures: a before/after change pair; for version history, an entity with ≥2 versions and a fact
164
+ row dated inside each interval.
165
+
166
+ **T2 — Date-pair ordering.** Business-guaranteed orderings asserted; known violations recorded.
167
+
168
+ - Applies: per declared date pair (ordered ≤ shipped ≤ delivered; signup ≤ first order), each
169
+ classified guaranteed vs. tolerated-violated.
170
+ - Assert: guaranteed (`empty`) — `SELECT <key>, <earlier>, <later> FROM <target> WHERE <later> <
171
+ <earlier>`. Tolerated — pin the violating row's downstream arithmetic (a negative lag inside an
172
+ average) in the expected rows, and record the real-data count in the plan.
173
+ - Fixtures: one violating row for every tolerated ordering.
174
+
175
+ **T3 — Volatile columns.** Values that change across runs can't be pinned.
176
+
177
+ - Applies: columns derived from `now()`/`current_date` (age), run metadata (load timestamps, batch
178
+ ids).
179
+ - Assert: leave the column out of the `equals` `columns` list — an undeclared column never enters the
180
+ comparison. Separately assert its form where warranted (`empty`): `WHERE age NOT BETWEEN 0 AND
181
+ 120`. The stable source column (`birth_date`) stays exact in the expected rows.
182
+ - Fixtures: none special; the split is the point — omit the volatile, pin the stable.
183
+
184
+ ## Screens & severity
185
+
186
+ **Q1 — Range / sign screens.** Each measure's declared bounds hold.
187
+
188
+ - Applies: per bounded measure; bounds from business meaning plus profiling (derived bounds are
189
+ free: a sum of non-negatives is non-negative).
190
+ - Assert (`empty`): `SELECT <key>, <col> FROM <target> WHERE <col> < <lo> OR <col> > <hi>` (one-sided
191
+ where only one bound exists).
192
+ - Fixtures: boundary values where the bound is business-set.
193
+
194
+ **Q2 — Null policy, three ways.** Measures, descriptive attributes, and FKs carry independent null
195
+ policies; never presume one from another.
196
+
197
+ - Applies: per column, asked separately — "count of nothing": 0 or NULL? empty date: NULL or
198
+ sentinel? FK: see C3.
199
+ - Assert: declared non-null columns get `WHERE <col> IS NULL` (`empty`). Otherwise the policy is
200
+ enforced by the expected-row cell of a zero-case fixture row — NULL vs 0 vs empty is invisible
201
+ until a fixture forces the choice into a cell.
202
+ - Fixtures: the zero-case row (I3) is the enforcement mechanism.
203
+
204
+ **Q3 — Naming & the tolerated oddity.** Every expectation declares its meaning.
205
+
206
+ - Applies: always, every expectation.
207
+ - Convention: the expectation's `name` states the invariant in plain words, because a failure leads
208
+ with it. Each `empty` SQL opens with 1–3 comment lines naming the invariant and the failure modes
209
+ it catches. Budget cuts drop business-rule checks first, then cross-table structure checks, never
210
+ single-column screens.
211
+ - A forbidden condition is an `empty` expectation. A tolerated one is pinned in the expected rows
212
+ and recorded in the plan's known-quirks list with its warehouse count. Never author an expectation
213
+ designed to fire.
214
+
215
+ ## Input modeling (fixture-design rules)
216
+
217
+ **I1 — Profiling-derived partitions.** Fixture edges and tolerated non-ties cite profiled reality
218
+ with counts; the plan's known-quirks section carries each tolerated oddity with its reason and
219
+ count.
220
+
221
+ **I2 — Shared fixture cast.** One small human-named cast per transform, every row a named edge,
222
+ documented as a story table (row → attributes → purpose) in the plan. Where one transform's output
223
+ is another's input, derive the faked rows from the first's expected output so the two tests tell one
224
+ story.
225
+
226
+ **I3 — Zero-case partitions.** For every outer join and aggregation relation: one entity with zero
227
+ matches. Its expected row pins the absence representation (Q2) and the join direction (C3) — the
228
+ all-clean cast is the single most common cause of vacuous tests. When the schema distinguishes
229
+ states the profiled data never exhibits (a literal zero in a source that only has NULLs and
230
+ positives), fixture the missing state — nothing else forces it onto an expected cell.
231
+
232
+ **I4 — Multiplicity partitions.** Every aggregation gets a >1-member group and an exactly-1 group
233
+ (the 0 case is I3); every join gets a parent with ≥2 children. Expected values then differ from any
234
+ single row's, so copy-through bugs can't pass.
235
+
236
+ **I5 — Dirty-input pinning.** Per screenable defect the source can carry (orphan FK, out-of-domain
237
+ value, duplicate natural key, hierarchy violation, ordering violation): one fixture row exhibiting
238
+ it, an expected row pinning the transform's response (drop / pass-through / default), and — where
239
+ the defect is forbidden — the matching `empty` expectation. Which duplicate survives a dedupe is
240
+ invisible until a conflicting-duplicate fixture pins it.
241
+
242
+ **I6 — Mutation probes.** Run at plan-validation time, not on every run: corrupt one expected cell →
243
+ `cell-mismatches` must name that exact column; perturb one input cell → exactly the declared output
244
+ cells move. Both guard against vacuous tests: every `empty` expectation passes against an empty
245
+ output.
246
+
247
+ ## Plan-level artifacts
248
+
249
+ **P1 — Coverage matrix.** Output columns (with the table's grain) × check classes; cells name the
250
+ covering expectation or expected-row cell, or state `gap: <reason>`; shared-attribute columns scanned
251
+ across transforms for agreement obligations (C1).
252
+
253
+ **P2 — Hand-derived expected rows.** From the fixture story and business meaning, arithmetic recorded
254
+ in the plan; never captured from output; every fixture row's fate appears in some expected cell.
255
+
256
+ **P3 — Live-bug handling.** A check failing against a deployed transform is a real finding: never
257
+ soften the test to green; quantify the damage at fixture and warehouse scale. Then fix now, or record
258
+ the red in the plan with the minimal fix body, per the session's terms. A stored test has no
259
+ red-by-design state, so a deferred fix must be visible in the plan or the test reads as broken.
@@ -27,7 +27,10 @@ Decide which relationship in the data matters most, then pick the chart. The sha
27
27
  - **Compare a measure across categories** → `bar` (vertical). Use `row` (horizontal bar) when labels are long or there are many categories. Sort by value unless the dimension has a natural order.
28
28
  - **Change over time / trend** → `line` for a continuous series; `bar`/`area` for a few discrete periods. Two measures on unlike scales → `combo` (line + bar, dual-axis) — only when the metrics are genuinely related.
29
29
  - **Part-to-whole, one snapshot** → `pie`, but only for a meaningful whole with **≤5 slices**; beyond that use a sorted `bar`/`row`. Composition over time → stacked `area`/`bar`.
30
- - **Distribution / spread / outliers** → a `bar` histogram (bin the measure — see `mbql` binning); on **v59+** servers `boxplot` compares several groups' spread directly.
30
+ - **Distribution / spread / outliers** → a `bar` histogram (bin the measure — see `mbql` binning).
31
+ <!-- requires: boxplotDisplay -->
32
+ - **Spread across several groups** → `boxplot` compares the groups' distributions directly.
33
+ <!-- /requires -->
31
34
  - **Correlation between two measures** → `scatter` (a third measure → bubble size).
32
35
  - **Sequential additive contributions** (start → +/− steps → total) → `waterfall`.
33
36
  - **Stage drop-off in an ordered, cumulative funnel** → `funnel`.
@@ -35,7 +38,7 @@ Decide which relationship in the data matters most, then pick the chart. The sha
35
38
  - **Geographic** → `map`: region/choropleth (a region dimension + a measure), pin (lat + long), or grid/heat (coordinates + measure).
36
39
  - **Precise values, many columns, mixed types, or no chart fits** → `table`; `pivot` for a cross-tab of two dimensions; `object` for a single record's detail.
37
40
 
38
- Valid `display` values — the registered visualizations: `table`, `bar`, `line`, `area`, `row`, `pie`, `scalar`, `smartscalar`, `combo`, `pivot`, `funnel`, `map`, `scatter`, `waterfall`, `progress`, `gauge`, `object`, `sankey`. The API types `display` as a plain string and accepts any value — it renders an unknown one as nothing. (`boxplot` is registered only on **v59+** servers — older ones render it blank; use a `bar` histogram for distributions instead. `scalar` **is** the "Number" viz — `display: number` is a legacy serialization alias, not a registered visualization; use `scalar`. `list` exists but is hidden — don't pick it. `heading`/`text`/`link`/`iframe`/`action` are dashcard virtuals, not standalone cards — see references.) A typo like `bargraph`/`linechart` is accepted and renders blank — the most common "why is my chart blank" cause.
41
+ Valid `display` values — the registered visualizations: `table`, `bar`, `line`, `area`, `row`, `pie`, `scalar`, `smartscalar`, `combo`, `pivot`, `funnel`, `map`, `scatter`, `waterfall`, `progress`, `gauge`, `object`, `sankey`. The API types `display` as a plain string and accepts any value — it renders an unknown one as nothing. (`scalar` **is** the "Number" viz — `display: number` is a legacy serialization alias, not a registered visualization; use `scalar`. `list` exists but is hidden — don't pick it. `heading`/`text`/`link`/`iframe`/`action` are dashcard virtuals, not standalone cards — see references.) A typo like `bargraph`/`linechart` is accepted and renders blank — the most common "why is my chart blank" cause.
39
42
 
40
43
  ## Step 2 — bind data columns and set options
41
44
 
@@ -53,7 +56,6 @@ Valid `display` values — the registered visualizations: `table`, `bar`, `line`
53
56
  | `row` | as bar; prefer for long/many category labels | `graph.dimensions`, `graph.metrics` |
54
57
  | `scatter` | two numeric measures (correlation) | `graph.dimensions`, `graph.metrics` (`scatter.bubble` opt) |
55
58
  | `waterfall` | exactly 1 dimension + ≥1 measure; sequential | `graph.dimensions` (1), `graph.metrics` (1) |
56
- | `boxplot` _(v59+)_ | ≥3 cols, ≥2 dimensions, ≥1 measure | `graph.dimensions`, `graph.metrics` |
57
59
  | `pie` | ≥2 rows, ≥2 cols, ≥1 dimension + ≥1 measure; ≤~5 slices | `pie.dimension`, `pie.metric` |
58
60
  | `funnel` | 2 columns (stage + value); ordered stages | `funnel.dimension`, `funnel.metric` |
59
61
  | `map` (region) | a string/region dimension + a measure | `map.region`, `map.dimension`, `map.metric` |
@@ -62,6 +64,12 @@ Valid `display` values — the registered visualizations: `table`, `bar`, `line`
62
64
  | `pivot` | ≥2 cols, all aggregated/breakout | — (`pivot_table.column_split` auto) |
63
65
  | `table` `object` | anything (table is the universal fallback) | — (always renders) |
64
66
 
67
+ <!-- requires: boxplotDisplay -->
68
+
69
+ `boxplot` is registered too: ≥3 cols, ≥2 dimensions, ≥1 measure, on **unaggregated** rows; required keys `graph.dimensions`, `graph.metrics`.
70
+
71
+ <!-- /requires -->
72
+
65
73
  ### The rule that trips everyone: settings name **output columns**, by name
66
74
 
67
75
  `graph.dimensions`, `graph.metrics`, `pie.dimension`, `pie.metric`, `scalar.field`, `funnel.metric`, `map.latitude_column`, `sankey.source`, … all take **output column-name strings** — the names the query _produces_, not field ids. A `count` aggregation outputs the column `count`; a breakout on a field outputs that field's name; a named aggregation outputs its `name`. These strings are **identical in the API form and the portable (git-sync) form** — no numeric-vs-name footgun here.
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Contents
4
4
 
5
- - [Cartesian — `bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`, `boxplot`](#cartesian--bar-line-area-combo-scatter-waterfall-row-boxplot) — shared keys (binding, stacking, goal/trend, data labels, axes, tooltip) plus `scatter`, `waterfall`, `row`, `boxplot` extras
5
+ - [Cartesian — `bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`](#cartesian--bar-line-area-combo-scatter-waterfall-row) — shared keys (binding, stacking, goal/trend, data labels, axes, tooltip) plus `scatter`, `waterfall`, `row` extras
6
6
  - [Part-to-whole & single value — `pie`, `funnel`, `gauge`, `progress`, `scalar`, `smartscalar`](#part-to-whole--single-value--pie-funnel-gauge-progress-scalar-smartscalar)
7
7
  - [Tabular, geographic & flow — `table`, `pivot`, `object`, `map`, `sankey`](#tabular-geographic--flow--table-pivot-object-map-sankey) — includes `table.column_formatting` conditional formatting
8
8
  - [`column_settings` — per-column formatting](#column_settings--per-column-formatting) — number/date/currency, `view_as`, alignment, mini bars
@@ -18,7 +18,7 @@ All column-naming keys (`graph.dimensions`, `pie.dimension`, `table.columns[].na
18
18
 
19
19
  ---
20
20
 
21
- # Cartesian — `bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`, `boxplot`
21
+ # Cartesian — `bar`, `line`, `area`, `combo`, `scatter`, `waterfall`, `row`
22
22
 
23
23
  `bar`/`line`/`area`/`combo` share an identical key set (combo just defaults the first series to a line, the rest to bars). `scatter`/`waterfall`/`row`/`boxplot` use a subset plus their own extras. Most allow up to 2 dimensions and unlimited metrics; **waterfall is 1 dimension + 1 metric**, boxplot allows 2 dimensions.
24
24
 
@@ -102,9 +102,9 @@ Use for sequential additive contributions (start → +/− steps → total). **U
102
102
 
103
103
  Horizontal bars — use when category labels are long or numerous. Here `graph.dimensions` is the y-axis (categories) and `graph.metrics` the x-axis (values). X-scale is `"ordinal"` only; no trend line, tooltip columns, or split panels. **Required:** `graph.dimensions`, `graph.metrics`.
104
104
 
105
- ## boxplot
105
+ <!-- requires: boxplotDisplay -->
106
106
 
107
- _Registered only on **v59+** servers — older ones render `display: boxplot` blank; use a `bar` histogram there._
107
+ ## boxplot
108
108
 
109
109
  Use for distribution/spread/outliers, especially across several groups. Needs **unaggregated** rows. **Use for:** ≥3 columns, ≥2 dimensions, ≥1 measure. **Required:** `graph.dimensions`, `graph.metrics`. X-scale is `"ordinal"`.
110
110
 
@@ -115,6 +115,8 @@ Use for distribution/spread/outliers, especially across several groups. Needs **
115
115
  | `boxplot.show_mean` | boolean | | `true` |
116
116
  | `boxplot.show_values_mode` | string | `"median"`, `"all"` (when `graph.show_values`) | `"median"` |
117
117
 
118
+ <!-- /requires -->
119
+
118
120
  ---
119
121
 
120
122
  # Part-to-whole & single value — `pie`, `funnel`, `gauge`, `progress`, `scalar`, `smartscalar`
@@ -17,7 +17,7 @@ Before running any `mb` command, load the workflow content from the CLI:
17
17
 
18
18
  ```bash
19
19
  mb skills get core # auth, flag conventions, every command group
20
- mb skills list # everything available on the installed version
20
+ mb skills list # every bundled skill the profile's server can use (--unfiltered for all of them)
21
21
  ```
22
22
 
23
23
  **Doing a whole job, not one command?** If the user wants an outcome — "make sense of my data", "build a data model", "go from raw data to a dashboard", "answer questions about my data", "be my data analyst", "set up analytics for X" — load the guided end-to-end skill instead and let it drive:
@@ -1,24 +0,0 @@
1
- import { t as defineCommandGroup } from "./group-DBM87IgC.mjs";
2
- //#region src/commands/card/index.ts
3
- var card_default = defineCommandGroup({
4
- name: "card",
5
- description: "Manage Metabase cards (questions, models, metrics)",
6
- skills: [{
7
- skill: "mbql",
8
- purpose: "author the dataset_query"
9
- }, {
10
- skill: "visualization",
11
- purpose: "choose display and visualization_settings"
12
- }],
13
- subCommands: {
14
- list: () => import("./list-C2qxVTu7.mjs").then((mod) => mod.default),
15
- get: () => import("./get-N5EUCDL0.mjs").then((mod) => mod.default),
16
- query: () => import("./query-CpD46hL6.mjs").then((mod) => mod.default),
17
- alerts: () => import("./alerts-Bp2vByJf.mjs").then((mod) => mod.default),
18
- create: () => import("./create-BGy4L_yh.mjs").then((mod) => mod.default),
19
- update: () => import("./update-MWaDj2VX.mjs").then((mod) => mod.default),
20
- archive: () => import("./archive-lDnTIypd.mjs").then((mod) => mod.default)
21
- }
22
- });
23
- //#endregion
24
- export { card_default as default };