@pikku/cli 0.12.100 → 0.12.103

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 (259) hide show
  1. package/console-app/assets/{abnfDiagram-VRR7QNED-Icjp9hnB.js → abnfDiagram-VRR7QNED-BLi9JHGg.js} +1 -1
  2. package/console-app/assets/{arc-BfGls--L.js → arc-B3b5uYlL.js} +1 -1
  3. package/console-app/assets/architecture-TIHT7OUA-BYeDayHv.js +1 -0
  4. package/console-app/assets/{architectureDiagram-ZJ3FMSHR-CpnsLBns.js → architectureDiagram-ZJ3FMSHR-Dkd8kxIa.js} +1 -1
  5. package/console-app/assets/{blockDiagram-677ZJIJ3-ByKRMGSr.js → blockDiagram-677ZJIJ3-DnH0nNlb.js} +1 -1
  6. package/console-app/assets/{c4Diagram-LMCZKHZV-CzJSbsUo.js → c4Diagram-LMCZKHZV-BlelCS5i.js} +1 -1
  7. package/console-app/assets/channel-CTa6nggO.js +1 -0
  8. package/console-app/assets/{chunk-32BRIVSS-D_tc4HCY.js → chunk-32BRIVSS-D7tMgtT1.js} +1 -1
  9. package/console-app/assets/{chunk-52WLFC77-wkQkuUXG.js → chunk-52WLFC77-CRepS35y.js} +1 -1
  10. package/console-app/assets/{chunk-C7G6YPKG-BFW3xG3R.js → chunk-C7G6YPKG-CUldlJz4.js} +1 -1
  11. package/console-app/assets/{chunk-EX3LRPZG-Car090Sw.js → chunk-EX3LRPZG-DODbrqEj.js} +1 -1
  12. package/console-app/assets/{chunk-FWX5IMBZ-c2ud9kQ-.js → chunk-FWX5IMBZ-nZa59wGD.js} +2 -2
  13. package/console-app/assets/{chunk-HOUHSVGY-RYmQka5R.js → chunk-HOUHSVGY-BaawVZCa.js} +1 -1
  14. package/console-app/assets/{chunk-ICXQ74PX-C-dqYC_9.js → chunk-ICXQ74PX-C86LrIRs.js} +1 -1
  15. package/console-app/assets/{chunk-MOJQB5TN-Cu3FUWwl.js → chunk-MOJQB5TN-ovUDQlyW.js} +1 -1
  16. package/console-app/assets/{chunk-OGEWGWER-Z7f1yArD.js → chunk-OGEWGWER-ByZKAcGu.js} +1 -1
  17. package/console-app/assets/{chunk-PUDLZKDR-Bp68DuRj.js → chunk-PUDLZKDR-DdeJN3wJ.js} +1 -1
  18. package/console-app/assets/{chunk-Q4XR5HBZ-CdKSYWZ4.js → chunk-Q4XR5HBZ-Blp5W9-b.js} +1 -1
  19. package/console-app/assets/{chunk-RYQCIY6F-9ISCAKm2.js → chunk-RYQCIY6F-DehwjyPp.js} +1 -1
  20. package/console-app/assets/{chunk-V7JOEXUC-2EOc1nQB.js → chunk-V7JOEXUC-Ca1xeVdo.js} +1 -1
  21. package/console-app/assets/chunk-VAUOI2AC-BCngaLxk.js +1 -0
  22. package/console-app/assets/{chunk-VR4S4FIN-BPvN0PUm.js → chunk-VR4S4FIN-Cj7ZlsLr.js} +1 -1
  23. package/console-app/assets/{chunk-WYO6CB5R-DOpurCTP.js → chunk-WYO6CB5R-CsdBQ1HS.js} +1 -1
  24. package/console-app/assets/chunk-XXDRQBXY-CGIlOoBU.js +1 -0
  25. package/console-app/assets/{chunk-ZGVPDNZ5-Bu2weVOL.js → chunk-ZGVPDNZ5-DMnFdLEO.js} +1 -1
  26. package/console-app/assets/classDiagram-OUVF2IWQ-Bwt1ZVOR.js +1 -0
  27. package/console-app/assets/classDiagram-v2-EOCWNBFH-Bwt1ZVOR.js +1 -0
  28. package/console-app/assets/{cose-bilkent-JH36ORCC-nau-QGCX.js → cose-bilkent-JH36ORCC-CiYBhiBv.js} +1 -1
  29. package/console-app/assets/{cynefin-VYW2F7L2-BBw-E7lg.js → cynefin-VYW2F7L2-BXuNC8qm.js} +1 -1
  30. package/console-app/assets/{cynefinDiagram-TSTJHNR4-BvnMvOvH.js → cynefinDiagram-TSTJHNR4-Ck53b-Nr.js} +1 -1
  31. package/console-app/assets/{dagre-VKFMJZFB-CHEqPR29.js → dagre-VKFMJZFB-C9hZCnOv.js} +1 -1
  32. package/console-app/assets/{diagram-FQU43EPY-JijKRWyb.js → diagram-FQU43EPY-DuEKSLPE.js} +1 -1
  33. package/console-app/assets/{diagram-G47NLZAW-G5UsB31f.js → diagram-G47NLZAW-B_yO-zKt.js} +1 -1
  34. package/console-app/assets/{diagram-NH7WQ7WH-BhuJ6fPu.js → diagram-NH7WQ7WH-CtKFjoB4.js} +1 -1
  35. package/console-app/assets/{diagram-OA4YK3LP-DaUF-8N4.js → diagram-OA4YK3LP-T9eIYXYs.js} +1 -1
  36. package/console-app/assets/{diagram-WEI45ONY-wLsJIhoM.js → diagram-WEI45ONY-BTgu-I69.js} +1 -1
  37. package/console-app/assets/{dist-fbBkbDNG.js → dist-DSVj7qxi.js} +1 -1
  38. package/console-app/assets/{ebnfDiagram-CCIWWBDH-BZCEa3Dz.js → ebnfDiagram-CCIWWBDH-BdyNRX2k.js} +1 -1
  39. package/console-app/assets/{erDiagram-Q63AITRT-4XoEUtEh.js → erDiagram-Q63AITRT-B0cr0nxe.js} +1 -1
  40. package/console-app/assets/eventmodeling-45OFAUF4-BeHdsPzc.js +1 -0
  41. package/console-app/assets/flowDiagram-23GEKE2U-6N6mIkfB.js +1 -0
  42. package/console-app/assets/{ganttDiagram-NO4QXBWP-BXU7pfq6.js → ganttDiagram-NO4QXBWP-Cr1R_nGh.js} +1 -1
  43. package/console-app/assets/{gitGraph-TEB2WS4Q-BdMAmvpU.js → gitGraph-TEB2WS4Q-zcmQoWd4.js} +1 -1
  44. package/console-app/assets/{gitGraphDiagram-IHSO6WYX-3Hn0zwZR.js → gitGraphDiagram-IHSO6WYX-CHB9Fnch.js} +1 -1
  45. package/console-app/assets/{index-Din2vBeb.js → index-BbIUXgNl.js} +150 -150
  46. package/console-app/assets/{index-BXMjqLQ5.css → index-C9U-Zyvx.css} +1 -1
  47. package/console-app/assets/{info-DKCQHKI2-Dc_oQkp5.js → info-DKCQHKI2-BGPZGp_E.js} +1 -1
  48. package/console-app/assets/{infoDiagram-FWYZ7A6U-B3v4xCUn.js → infoDiagram-FWYZ7A6U-Br_p6SR_.js} +1 -1
  49. package/console-app/assets/{ishikawaDiagram-FXEZZL3T-DzWq9Vtp.js → ishikawaDiagram-FXEZZL3T-Ma2d4IuN.js} +1 -1
  50. package/console-app/assets/{journeyDiagram-5HDEW3XC-C0buWi_a.js → journeyDiagram-5HDEW3XC-LdCblEX2.js} +1 -1
  51. package/console-app/assets/{kanban-definition-HUTT4EX6-DRAN9HhV.js → kanban-definition-HUTT4EX6-CRWetzV4.js} +1 -1
  52. package/console-app/assets/{line-UqgRNiAC.js → line-DrceqMYY.js} +1 -1
  53. package/console-app/assets/{linear-FTAGuk_3.js → linear-acWbtwAj.js} +1 -1
  54. package/console-app/assets/{mermaid-parser.core-DIHI27FL.js → mermaid-parser.core-n773Jf0G.js} +3 -3
  55. package/console-app/assets/{mermaid.core-D4q8kvcu.js → mermaid.core-DyTRkSqH.js} +3 -3
  56. package/console-app/assets/{mindmap-definition-LN4V7U3C-DN-_CNLb.js → mindmap-definition-LN4V7U3C-CBU-ehFU.js} +1 -1
  57. package/console-app/assets/{packet-7NZHBO7P-8a3PoQAb.js → packet-7NZHBO7P-DL_fgdX1.js} +1 -1
  58. package/console-app/assets/{pegDiagram-2B236MQR-Bh2MhzCN.js → pegDiagram-2B236MQR-CrFaAHHj.js} +1 -1
  59. package/console-app/assets/{pie-RZYD4A2V-Bi6zbJDl.js → pie-RZYD4A2V-STtzW8Tz.js} +1 -1
  60. package/console-app/assets/{pieDiagram-ENE6RG2P-D2Z0W5UU.js → pieDiagram-ENE6RG2P-DsUOr1Ud.js} +1 -1
  61. package/console-app/assets/{quadrantDiagram-ABIIQ3AL-DNOKka0p.js → quadrantDiagram-ABIIQ3AL-DmuSe_qW.js} +1 -1
  62. package/console-app/assets/{radar-I7S5WNFK-CAxa68Sg.js → radar-I7S5WNFK-L8w2lEOb.js} +1 -1
  63. package/console-app/assets/{railroad-3IZDKUUU-CZb1usP7.js → railroad-3IZDKUUU-CxqlE5vc.js} +1 -1
  64. package/console-app/assets/railroad-abnf-AHOZXSZD-CkJOR_Em.js +1 -0
  65. package/console-app/assets/railroad-ebnf-EBAXGLYW-BH_pRGgm.js +1 -0
  66. package/console-app/assets/railroad-peg-LSFZ7HO6-B50bKcii.js +1 -0
  67. package/console-app/assets/{railroadDiagram-RFXS5EU6-B1K2hbTD.js → railroadDiagram-RFXS5EU6-CJ8Lpbeo.js} +1 -1
  68. package/console-app/assets/{requirementDiagram-TGXJPOKE-K8wcOO0Q.js → requirementDiagram-TGXJPOKE-8OXQXUud.js} +1 -1
  69. package/console-app/assets/{sankeyDiagram-HTMAVEWB-WBPBkgNx.js → sankeyDiagram-HTMAVEWB-Bezd2CqZ.js} +1 -1
  70. package/console-app/assets/{sequenceDiagram-DBY2YBRQ-Dz80qZZv.js → sequenceDiagram-DBY2YBRQ-DHb5js3D.js} +1 -1
  71. package/console-app/assets/{src-CnJCXDL0.js → src-DfFamOl-.js} +1 -1
  72. package/console-app/assets/{stateDiagram-2N3HPSRC-DMur7lZf.js → stateDiagram-2N3HPSRC-UpyJm2mi.js} +1 -1
  73. package/console-app/assets/stateDiagram-v2-6OUMAXLB-C6gAfg82.js +1 -0
  74. package/console-app/assets/{swimlanes-5IMT3BWC-BlLdYcPU.js → swimlanes-5IMT3BWC-yUrV5f4O.js} +1 -1
  75. package/console-app/assets/swimlanesDiagram-G3AALYLV-Ch2_j5W5.js +8 -0
  76. package/console-app/assets/{timeline-definition-FHXFAJF6-CBOit0JY.js → timeline-definition-FHXFAJF6-B6w-rZeZ.js} +1 -1
  77. package/console-app/assets/{treeView-QDETBFTQ-DM1i1ast.js → treeView-QDETBFTQ-0k2QpnXc.js} +1 -1
  78. package/console-app/assets/{treemap-6X3UGDF4-ACrBEfY6.js → treemap-6X3UGDF4-ByCuDcGA.js} +1 -1
  79. package/console-app/assets/{vennDiagram-L72KCM5P-BmeFWb5N.js → vennDiagram-L72KCM5P-BH4374lw.js} +1 -1
  80. package/console-app/assets/{wardley-OPB4EBWU-BpIbeh58.js → wardley-OPB4EBWU-DNVwuJz6.js} +1 -1
  81. package/console-app/assets/{wardleyDiagram-EHGQE667-CxL7Mv7y.js → wardleyDiagram-EHGQE667-EXnQ6lkx.js} +1 -1
  82. package/console-app/assets/{xychartDiagram-FW5EYKEG-DkV75xT2.js → xychartDiagram-FW5EYKEG-rFh-UdgH.js} +1 -1
  83. package/console-app/index.html +10 -3
  84. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +6 -2
  85. package/dist/.pikku/agent/pikku-agent-types.gen.js +3 -0
  86. package/dist/.pikku/agent/pikku-model-aliases.gen.d.ts +1 -0
  87. package/dist/.pikku/agent/pikku-model-aliases.gen.js +5 -0
  88. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  89. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  90. package/dist/.pikku/cli/pikku-cli-channel.js +13 -8
  91. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  92. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  93. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  94. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  95. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  96. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  97. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  98. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +18 -12
  99. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  100. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  101. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  102. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  103. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  104. package/dist/.pikku/function/pikku-function-types.gen.d.ts +6 -25
  105. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  106. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  107. package/dist/.pikku/function/pikku-functions-meta.gen.json +51 -27
  108. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  109. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  110. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  111. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  112. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  113. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
  114. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
  115. package/dist/.pikku/pikku-bootstrap.gen.d.ts +2 -1
  116. package/dist/.pikku/pikku-bootstrap.gen.js +2 -1
  117. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  118. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  119. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  120. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  121. package/dist/.pikku/pikku-types.gen.js +1 -1
  122. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  123. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  124. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  125. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  126. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  127. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  128. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +2 -1
  129. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  130. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  131. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  132. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  133. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
  134. package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
  135. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  136. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  137. package/dist/.pikku/schemas/register.gen.js +7 -5
  138. package/dist/.pikku/schemas/schemas/DevInput.schema.json +1 -1
  139. package/dist/.pikku/schemas/schemas/PikkuAIScorerOutput.schema.json +1 -0
  140. package/dist/.pikku/schemas/schemas/ServeInput.schema.json +1 -1
  141. package/dist/.pikku/schemas/schemas/ValidateOutput.schema.json +1 -0
  142. package/dist/.pikku/scopes/pikku-personas.gen.js +1 -1
  143. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +1 -1
  144. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  145. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  146. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  147. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  148. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  149. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  150. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  151. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  152. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  153. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  154. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  155. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  156. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  157. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +8 -2
  158. package/dist/.pikku/workflow/pikku-personas.gen.d.ts +2 -1
  159. package/dist/.pikku/workflow/pikku-personas.gen.js +1 -1
  160. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +11 -18
  161. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  162. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  163. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  164. package/dist/bin/pikku-bin.mjs +2 -2
  165. package/dist/src/cli.wiring.js +20 -11
  166. package/dist/src/deploy/analyzer/analyzer.js +44 -0
  167. package/dist/src/deploy/analyzer/manifest.d.ts +37 -0
  168. package/dist/src/fabric/functions/smoke.function.js +7 -4
  169. package/dist/src/fabric/functions/validate.function.js +3 -1
  170. package/dist/src/functions/commands/db-export.js +1 -1
  171. package/dist/src/functions/commands/db-shared.d.ts +0 -14
  172. package/dist/src/functions/commands/dev.d.ts +3 -0
  173. package/dist/src/functions/commands/dev.js +41 -2
  174. package/dist/src/functions/commands/knowledge-index.d.ts +3 -3
  175. package/dist/src/functions/commands/new-addon.js +6 -3
  176. package/dist/src/functions/commands/scenario-browser.d.ts +25 -2
  177. package/dist/src/functions/commands/scenario-browser.js +5 -1
  178. package/dist/src/functions/commands/scenario-formatter.d.ts +1 -1
  179. package/dist/src/functions/commands/scenario-ladder.d.ts +1 -1
  180. package/dist/src/functions/commands/scenario-ladder.js +1 -1
  181. package/dist/src/functions/commands/scenario-plan.d.ts +2 -1
  182. package/dist/src/functions/commands/scenario-plan.js +1 -1
  183. package/dist/src/functions/commands/scenario.d.ts +7 -1
  184. package/dist/src/functions/commands/scenario.js +28 -7
  185. package/dist/src/functions/commands/serve.d.ts +3 -0
  186. package/dist/src/functions/commands/serve.js +15 -1
  187. package/dist/src/functions/commands/{workspace-validate.d.ts → validate.d.ts} +18 -3
  188. package/dist/src/functions/commands/validate.js +9 -0
  189. package/dist/src/functions/db/local-db.d.ts +2 -1
  190. package/dist/src/functions/db/local-db.js +2 -2
  191. package/dist/src/functions/surface/collect-surface.d.ts +14 -0
  192. package/dist/src/functions/surface/collect-surface.js +215 -0
  193. package/dist/src/functions/validate/addon-package-checks.d.ts +26 -0
  194. package/dist/src/functions/validate/addon-package-checks.js +258 -0
  195. package/dist/src/functions/validate/persona-checks.d.ts +1 -1
  196. package/dist/src/functions/validate/persona-checks.js +1 -1
  197. package/dist/src/functions/validate/scenario-file-checks.js +33 -0
  198. package/dist/src/functions/validate/shared-checks.d.ts +1 -1
  199. package/dist/src/functions/validate/shared-checks.js +1 -1
  200. package/dist/src/functions/validate/type-identity-checks.d.ts +25 -0
  201. package/dist/src/functions/validate/type-identity-checks.js +218 -0
  202. package/dist/src/functions/validate/validate-registry.d.ts +52 -0
  203. package/dist/src/functions/validate/validate-registry.js +111 -0
  204. package/dist/src/functions/validate/validate.d.ts +47 -0
  205. package/dist/src/functions/validate/{workspace-validate.js → validate.js} +46 -12
  206. package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent-types.js +3 -2
  207. package/dist/src/functions/wirings/ai-agent/pikku-command-ai-agent.js +5 -1
  208. package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.d.ts +1 -1
  209. package/dist/src/functions/wirings/ai-agent/serialize-ai-agent-types.js +15 -2
  210. package/dist/src/functions/wirings/ai-agent/serialize-model-aliases.d.ts +5 -0
  211. package/dist/src/functions/wirings/ai-agent/serialize-model-aliases.js +12 -0
  212. package/dist/src/functions/wirings/ai-scorer/pikku-command-ai-scorer.d.ts +1 -0
  213. package/dist/src/functions/wirings/ai-scorer/pikku-command-ai-scorer.js +51 -0
  214. package/dist/src/functions/wirings/ai-scorer/serialize-scorer-names.d.ts +10 -0
  215. package/dist/src/functions/wirings/ai-scorer/serialize-scorer-names.js +17 -0
  216. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +27 -10
  217. package/dist/src/functions/wirings/cli/serialize-channel-cli.js +9 -4
  218. package/dist/src/functions/wirings/console/serialize-console-functions.js +9 -56
  219. package/dist/src/functions/wirings/functions/serialize-function-types.js +7 -30
  220. package/dist/src/functions/wirings/middleware/serialize-middleware-imports.js +5 -1
  221. package/dist/src/functions/wirings/package/pikku-command-package.js +12 -1
  222. package/dist/src/functions/wirings/package/serialize-package.d.ts +1 -1
  223. package/dist/src/functions/wirings/package/serialize-package.js +5 -2
  224. package/dist/src/functions/wirings/rpc/serialize-typed-rpc-map.js +1 -6
  225. package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +30 -0
  226. package/dist/src/functions/wirings/scenarios/serialize-feature-meta.d.ts +1 -1
  227. package/dist/src/functions/wirings/scenarios/serialize-scenario-registration.js +6 -5
  228. package/dist/src/functions/wirings/workflow/serialize-personas.js +2 -5
  229. package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +12 -4
  230. package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +10 -17
  231. package/dist/src/functions/workflows/all.workflow.js +11 -1
  232. package/dist/src/server/bun-server-runner.js +3 -0
  233. package/dist/src/server/dev-server-runner.interface.d.ts +10 -0
  234. package/dist/src/server/node-server-runner.js +3 -0
  235. package/dist/src/services.js +1 -0
  236. package/dist/src/utils/meta-diff.d.ts +1 -1
  237. package/dist/src/utils/meta-diff.js +2 -0
  238. package/dist/src/utils/model-alias-override.d.ts +7 -0
  239. package/dist/src/utils/model-alias-override.js +33 -0
  240. package/dist/src/utils/pikku-cli-config.js +16 -0
  241. package/dist/tsconfig.tsbuildinfo +1 -1
  242. package/package.json +17 -17
  243. package/console-app/assets/architecture-TIHT7OUA-C8l7I5Lm.js +0 -1
  244. package/console-app/assets/channel-BgJ-Z0cx.js +0 -1
  245. package/console-app/assets/chunk-VAUOI2AC-DwKsbf70.js +0 -1
  246. package/console-app/assets/chunk-XXDRQBXY-RuYSFsQb.js +0 -1
  247. package/console-app/assets/classDiagram-OUVF2IWQ-ohoLCI8g.js +0 -1
  248. package/console-app/assets/classDiagram-v2-EOCWNBFH-ohoLCI8g.js +0 -1
  249. package/console-app/assets/eventmodeling-45OFAUF4-DZ7z4YJO.js +0 -1
  250. package/console-app/assets/flowDiagram-23GEKE2U-rd7-NwZT.js +0 -1
  251. package/console-app/assets/railroad-abnf-AHOZXSZD-DkQZciri.js +0 -1
  252. package/console-app/assets/railroad-ebnf-EBAXGLYW-CPBeASA9.js +0 -1
  253. package/console-app/assets/railroad-peg-LSFZ7HO6-CXEVIZ0g.js +0 -1
  254. package/console-app/assets/stateDiagram-v2-6OUMAXLB-BDgLCrot.js +0 -1
  255. package/console-app/assets/swimlanesDiagram-G3AALYLV-CZ5rQIcE.js +0 -8
  256. package/dist/.pikku/schemas/schemas/WorkspaceValidateOutput.schema.json +0 -1
  257. package/dist/src/functions/commands/workspace-validate.js +0 -9
  258. package/dist/src/functions/validate/workspace-validate.d.ts +0 -33
  259. /package/dist/.pikku/schemas/schemas/{WorkspaceValidateInput.schema.json → ValidateInput.schema.json} +0 -0
@@ -7,7 +7,7 @@
7
7
  * making the driver's optional isolation and diagnostics safe to call
8
8
  * unconditionally.
9
9
  */
10
- import type { ScenarioBrowserFailure, ScenarioBrowserProvider } from '@pikku/core/workflow';
10
+ import type { ScenarioBrowserFailure, ScenarioBrowserProvider } from '@pikku/core/scenario';
11
11
  import type { ResolvedPersona } from '@pikku/core/services';
12
12
  /** The default driver, used when a project names no other. */
13
13
  export declare const DEFAULT_BROWSER_DRIVER = "@pikku/playwright";
@@ -16,6 +16,7 @@ export interface ScenarioBrowserDriverOptions {
16
16
  actors: Record<string, ResolvedPersona>;
17
17
  signInPath?: string;
18
18
  failureDir?: string;
19
+ capture?: ScenarioCaptureOptions;
19
20
  config: unknown;
20
21
  }
21
22
  /**
@@ -43,6 +44,21 @@ export interface ScenarioBrowserDriver {
43
44
  apiUrl: string;
44
45
  }) => unknown;
45
46
  }
47
+ /**
48
+ * Artifacts a run may produce. Mirrors the driver's own CaptureOptions rather
49
+ * than importing it: the CLI must not depend on a driver package it resolves
50
+ * dynamically, and this shape is the contract between them.
51
+ */
52
+ export interface ScenarioCaptureOptions {
53
+ /** Root directory for the run's artifacts. */
54
+ dir: string;
55
+ /** The invocation these artifacts belong to. */
56
+ runId: string;
57
+ /** Record a video per scenario. */
58
+ video?: boolean;
59
+ /** Re-encode with ffmpeg when available. Defaults on — the footage is nearly static. */
60
+ compress?: boolean;
61
+ }
46
62
  export interface ResolveScenarioBrowserProviderOptions {
47
63
  /** The environment name, for error messages that tell the user what to edit. */
48
64
  environment: string;
@@ -53,6 +69,12 @@ export interface ResolveScenarioBrowserProviderOptions {
53
69
  signInPath?: string;
54
70
  /** Where failure screenshots are written. */
55
71
  failureDir: string;
72
+ /**
73
+ * Artifacts for this run — named screenshots, and optionally a video per
74
+ * scenario. Undefined leaves capture off, which is the default: most runs
75
+ * ask a pass/fail question and writing video to answer it is waste.
76
+ */
77
+ capture?: ScenarioCaptureOptions;
56
78
  /** The scenarios that declared browser steps, named in the missing-driver error. */
57
79
  browserScenarios: string[];
58
80
  /** Package to drive the browser. Defaults to `@pikku/playwright`. */
@@ -71,13 +93,14 @@ export interface ResolveScenarioBrowserProviderOptions {
71
93
  * because a run against a placeholder URL is worse than one that refuses to
72
94
  * start.
73
95
  */
74
- export declare const resolveScenarioBrowserProvider: ({ environment, apiUrl, appUrl, secret, actors, signInPath, failureDir, browserScenarios, driver, importDriver, }: ResolveScenarioBrowserProviderOptions) => Promise<ScenarioBrowserProvider>;
96
+ export declare const resolveScenarioBrowserProvider: ({ environment, apiUrl, appUrl, secret, actors, signInPath, failureDir, capture, browserScenarios, driver, importDriver, }: ResolveScenarioBrowserProviderOptions) => Promise<ScenarioBrowserProvider>;
75
97
  /**
76
98
  * The three calls the run loop makes, safe against a run with no browser and
77
99
  * against a driver that implements neither optional member.
78
100
  */
79
101
  export interface ScenarioBrowserLifecycle {
80
102
  reset(): Promise<void>;
103
+ beginScenario(scenario: string): void;
81
104
  captureFailure(label: string): Promise<ScenarioBrowserFailure[]>;
82
105
  close(): Promise<void>;
83
106
  }
@@ -12,7 +12,7 @@ export const DEFAULT_BROWSER_DRIVER = '@pikku/playwright';
12
12
  * because a run against a placeholder URL is worse than one that refuses to
13
13
  * start.
14
14
  */
15
- export const resolveScenarioBrowserProvider = async ({ environment, apiUrl, appUrl, secret, actors, signInPath, failureDir, browserScenarios, driver = DEFAULT_BROWSER_DRIVER, importDriver = (specifier) => import(specifier), }) => {
15
+ export const resolveScenarioBrowserProvider = async ({ environment, apiUrl, appUrl, secret, actors, signInPath, failureDir, capture, browserScenarios, driver = DEFAULT_BROWSER_DRIVER, importDriver = (specifier) => import(specifier), }) => {
16
16
  const module = await importDriver(driver).catch(() => {
17
17
  const install = driver === DEFAULT_BROWSER_DRIVER
18
18
  ? `Run 'yarn add -D ${driver} @playwright/test'`
@@ -33,6 +33,7 @@ export const resolveScenarioBrowserProvider = async ({ environment, apiUrl, appU
33
33
  actors,
34
34
  signInPath,
35
35
  failureDir,
36
+ capture,
36
37
  config,
37
38
  };
38
39
  if (module.createScenarioBrowserProvider) {
@@ -52,6 +53,9 @@ export const scenarioBrowserLifecycle = (provider) => ({
52
53
  reset: async () => {
53
54
  await provider?.reset?.();
54
55
  },
56
+ beginScenario: (scenario) => {
57
+ provider?.beginScenario?.(scenario);
58
+ },
55
59
  captureFailure: async (label) => {
56
60
  try {
57
61
  return (await provider?.captureFailure?.(label)) ?? [];
@@ -7,7 +7,7 @@
7
7
  * second formatter (JSON, JUnit) a matter of writing one function rather than
8
8
  * unpicking the runner.
9
9
  */
10
- import type { ScenarioBrowserFailure } from '@pikku/core/workflow';
10
+ import type { ScenarioBrowserFailure } from '@pikku/core/scenario';
11
11
  /** The longest gherkin keyword ("Given"), so sentences line up under each other. */
12
12
  declare const KEYWORD_WIDTH = 5;
13
13
  /** One step of a run, already joined to the prose that declared it. */
@@ -1,4 +1,4 @@
1
- import type { ScenarioStepPhase, ScenarioSurface } from '@pikku/core/workflow';
1
+ import type { ScenarioStepPhase, ScenarioSurface } from '@pikku/core/scenario';
2
2
  import type { WorkflowStepMeta } from '@pikku/core/workflow/types';
3
3
  import type { FunctionsMeta } from '@pikku/core';
4
4
  import type { ScenarioFailureDetail, ScenarioStepRow } from './scenario-formatter.js';
@@ -8,7 +8,7 @@
8
8
  * belongs to `scenario-formatter.ts`; this module only decides what each step
9
9
  * is called.
10
10
  */
11
- import { composeStepProse } from '@pikku/core/workflow';
11
+ import { composeStepProse } from '@pikku/core/scenario';
12
12
  import { KEYWORD_WIDTH } from './scenario-formatter.js';
13
13
  /**
14
14
  * Walk a workflow's steps — including the ones nested inside branches, fanouts
@@ -1,4 +1,5 @@
1
- import type { CoreFeature, CoreWorkflow } from '@pikku/core/workflow';
1
+ import type { CoreWorkflow } from '@pikku/core/workflow';
2
+ import type { CoreFeature } from '@pikku/core/scenario';
2
3
  /** One scenario run: a scenario name and, for a feature's paired entry, its input. */
3
4
  export type ScenarioPlanEntry = {
4
5
  scenarioName: string;
@@ -1,4 +1,4 @@
1
- import { resolveFeatureScenarios } from '@pikku/core/workflow';
1
+ import { resolveFeatureScenarios } from '@pikku/core/scenario';
2
2
  /**
3
3
  * Turn the registered scenarios and features into an ordered list of run units.
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { ScenarioSurface } from '@pikku/core/workflow';
1
+ import type { ScenarioSurface } from '@pikku/core/scenario';
2
2
  export declare const scenarioList: import("#pikku").PikkuFunctionConfig<{}, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{}, void, "rpc" | "session", import("#pikku").WiredServices, unknown> | import("#pikku").PikkuFunction<{}, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
3
3
  export declare const scenarioRun: import("#pikku").PikkuFunctionConfig<{
4
4
  environment: string;
@@ -13,6 +13,8 @@ export declare const scenarioRun: import("#pikku").PikkuFunctionConfig<{
13
13
  spawn?: boolean;
14
14
  keepAlive?: boolean;
15
15
  trace?: boolean;
16
+ screenshots?: boolean;
17
+ video?: boolean;
16
18
  apiUrl?: string;
17
19
  appUrl?: string;
18
20
  }, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
@@ -28,6 +30,8 @@ export declare const scenarioRun: import("#pikku").PikkuFunctionConfig<{
28
30
  spawn?: boolean;
29
31
  keepAlive?: boolean;
30
32
  trace?: boolean;
33
+ screenshots?: boolean;
34
+ video?: boolean;
31
35
  apiUrl?: string;
32
36
  appUrl?: string;
33
37
  }, void, "rpc" | "session", import("#pikku").WiredServices, unknown> | import("#pikku").PikkuFunction<{
@@ -43,6 +47,8 @@ export declare const scenarioRun: import("#pikku").PikkuFunctionConfig<{
43
47
  spawn?: boolean;
44
48
  keepAlive?: boolean;
45
49
  trace?: boolean;
50
+ screenshots?: boolean;
51
+ video?: boolean;
46
52
  apiUrl?: string;
47
53
  appUrl?: string;
48
54
  }, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { resolve, join } from 'node:path';
2
3
  import { mkdirSync, writeFileSync } from 'node:fs';
3
4
  import { pikkuSessionlessFunc } from '#pikku';
@@ -5,10 +6,10 @@ import { InMemoryWorkflowService } from '@pikku/core/services';
5
6
  import { createHttpPersonas } from '@pikku/core/persona';
6
7
  import { PikkuScenarioService } from '@pikku/core/scenario';
7
8
  import { pikkuState, getAllPackageStates } from '@pikku/core/ecosystem';
8
- import { resolveFeatureScenarios } from '@pikku/core/workflow';
9
+ import { resolveFeatureScenarios } from '@pikku/core/scenario';
9
10
  import { loadScenarioBootstrap } from './load-user-project.js';
10
11
  import { collectScenarioStepProse, scenarioBrowserSteps, scenarioFailureFromSteps, scenarioStepRows, scenarioStepsWithoutBinding, scenarioSurfaceCoverage, } from './scenario-ladder.js';
11
- import { SCENARIO_SURFACES } from '@pikku/core/workflow';
12
+ import { SCENARIO_SURFACES } from '@pikku/core/scenario';
12
13
  import { formatScenarioReport } from './scenario-formatter.js';
13
14
  import { resolveScenarioBrowserProvider, scenarioBrowserLifecycle, } from './scenario-browser.js';
14
15
  import { resolvePersonas } from '../../utils/resolve-personas.js';
@@ -87,7 +88,7 @@ export const scenarioList = pikkuSessionlessFunc({
87
88
  },
88
89
  });
89
90
  export const scenarioRun = pikkuSessionlessFunc({
90
- func: async ({ logger, config, getInspectorState, variables }, { environment, flows, features, tags, excludeTags, coverage, browser = true, run: runSurface = 'default', strict = false, spawn = false, keepAlive = false, trace = false, apiUrl, appUrl, }) => {
91
+ func: async ({ logger, config, getInspectorState, variables }, { environment, flows, features, tags, excludeTags, coverage, browser = true, run: runSurface = 'default', strict = false, spawn = false, keepAlive = false, trace = false, screenshots = false, video = false, apiUrl, appUrl, }) => {
91
92
  if (!SCENARIO_SURFACES.includes(runSurface)) {
92
93
  throw new Error(`Unknown --run surface '${runSurface}'. Expected one of: ${SCENARIO_SURFACES.join(', ')}.`);
93
94
  }
@@ -285,6 +286,17 @@ export const scenarioRun = pikkuSessionlessFunc({
285
286
  const needsBrowser = effectiveSurface === 'browser' &&
286
287
  groups.some((group) => group.entries.some((entry) => browserStepsByFlow.has(entry.scenarioName)));
287
288
  const failureDir = join(resolve(config.rootDir, config.outDir), 'scenario-failures');
289
+ // Artifacts are filed under the run, not the scenario, so one run's output
290
+ // is one folder to open, keep or delete. `--video` implies capture is on:
291
+ // recording without somewhere to put it is not a thing anyone wants.
292
+ const captureDir = join(resolve(config.rootDir, config.outDir), 'scenario-runs');
293
+ // One id for the whole invocation, distinct from a scenario's own runId:
294
+ // reviewing artifacts means opening what `pikku scenario run` just produced,
295
+ // not hunting for one scenario's folder among many.
296
+ const captureRunId = randomUUID();
297
+ const capture = screenshots || video
298
+ ? { dir: captureDir, runId: captureRunId, video, compress: true }
299
+ : undefined;
288
300
  const browserLifecycle = scenarioBrowserLifecycle(needsBrowser
289
301
  ? await (async () => {
290
302
  const provider = await resolveScenarioBrowserProvider({
@@ -295,6 +307,7 @@ export const scenarioRun = pikkuSessionlessFunc({
295
307
  actors: scenarioActors,
296
308
  signInPath: env.signInPath,
297
309
  failureDir,
310
+ capture,
298
311
  browserScenarios: [...browserStepsByFlow.keys()],
299
312
  driver: config.scenarios?.browserDriver,
300
313
  });
@@ -353,10 +366,9 @@ export const scenarioRun = pikkuSessionlessFunc({
353
366
  * scenario body gets, the CLI's own singletons included, and its result is
354
367
  * discarded.
355
368
  *
356
- * The context is *feature*-scoped: `before` and `after` of one feature share
357
- * it, so setup can hand teardown the ids it created. It is deliberately not
358
- * the context the scenarios in the group see sharing one bag across a
359
- * group is the invisible coupling a Cucumber world had.
369
+ * Its context is *feature*-scoped shared by that feature's `before` and
370
+ * `after`, and deliberately not the context the group's scenarios see:
371
+ * one bag across a group is the invisible coupling a Cucumber world had.
360
372
  */
361
373
  const singletonServices = pikkuState(null, 'package', 'singletonServices');
362
374
  const runFeatureHook = async (hook, context) => {
@@ -371,6 +383,9 @@ export const scenarioRun = pikkuSessionlessFunc({
371
383
  // Before the scenario, not after it: the last scenario's window is left
372
384
  // open for headed debugging, while this one still starts clean.
373
385
  await browserLifecycle.reset();
386
+ // After the reset, which is what closes the previous scenario's context
387
+ // and finalises its video.
388
+ browserLifecycle.beginScenario(label);
374
389
  if (coverageActive) {
375
390
  const reset = await invokeCoverage('pikkuScenarioResetLiveCoverage');
376
391
  if (reset && reset.enabled === false) {
@@ -495,6 +510,12 @@ export const scenarioRun = pikkuSessionlessFunc({
495
510
  }
496
511
  }
497
512
  await browserLifecycle.close();
513
+ // Reported after the browser has closed, because video is only finalised
514
+ // when its context is. A capture nobody can find is a capture nobody
515
+ // looks at, and looking at them is the entire point of the flags.
516
+ if (capture) {
517
+ logger.info(`Captures → ${join(capture.dir, capture.runId)}`);
518
+ }
498
519
  if (coverage && Object.keys(scenarioCoverage).length > 0) {
499
520
  const coverageDir = join(resolve(config.rootDir, config.outDir), 'coverage');
500
521
  mkdirSync(coverageDir, { recursive: true });
@@ -1,10 +1,13 @@
1
1
  export declare const serve: import("#pikku").PikkuFunctionConfig<{
2
2
  port?: string;
3
3
  console?: boolean;
4
+ model?: string;
4
5
  }, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
5
6
  port?: string;
6
7
  console?: boolean;
8
+ model?: string;
7
9
  }, void, "rpc" | "session", import("#pikku").WiredServices, unknown> | import("#pikku").PikkuFunction<{
8
10
  port?: string;
9
11
  console?: boolean;
12
+ model?: string;
10
13
  }, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -4,19 +4,24 @@ import { ConsoleLogger, LocalEmailService, InMemoryQueueService, InMemoryWorkflo
4
4
  import { KyselyAIStorageService, KyselyAIRunStateService, KyselyAgentRunService, } from '@pikku/kysely';
5
5
  import { stopSingletonServices } from '@pikku/core';
6
6
  import { pikkuState } from '@pikku/core/ecosystem';
7
+ import { wireAIScorerQueueWorkers } from '@pikku/core/ai-scorer';
7
8
  import { LocalMetaService } from '@pikku/core/services/local-meta';
8
9
  import { LocalContent, } from '@pikku/core/services/local-content';
9
10
  import { InMemorySchedulerService } from '@pikku/schedule';
10
11
  import { resolveDb, createKysely, parseDatabaseUrl, } from '../db/local-db.js';
11
12
  import { loadUserBootstrap, loadUserModule } from './load-user-project.js';
13
+ import { registerScenarioInstrumentation } from '../wirings/scenarios/register-scenario-instrumentation.js';
14
+ import { resolveScaffoldFeature } from '../../utils/resolve-scaffold-feature.js';
12
15
  import { createDevAIAgentRunner } from './dev-ai-runner.js';
13
16
  import { resolveConsoleMount } from './serve-console.js';
14
17
  import { serverReadyLine } from '../../server/server-ready.js';
15
18
  import { createEphemeralContentSigningJWT } from '../../server/content-signing-jwt.js';
19
+ import { applyModelAliasOverride } from '../../utils/model-alias-override.js';
16
20
  export const serve = pikkuSessionlessFunc({
17
21
  remote: true,
18
- func: async ({ logger, config, getInspectorState, variables, devServerRunner }, { port, console: serveConsole }) => {
22
+ func: async ({ logger, config, getInspectorState, variables, devServerRunner }, { port, console: serveConsole, model }) => {
19
23
  process.env.PIKKU_DEV_QUICK_LOGIN ??= 'true';
24
+ applyModelAliasOverride(logger, model, config.models);
20
25
  const resolvedPort = parseInt(port || '3000', 10);
21
26
  const hostname = 'localhost';
22
27
  const bindHostname = '127.0.0.1';
@@ -28,6 +33,14 @@ export const serve = pikkuSessionlessFunc({
28
33
  return;
29
34
  }
30
35
  await loadUserBootstrap(pikkuDir);
36
+ // Scenario instrumentation exists only on a locally served project: the
37
+ // runner calls it over RPC to reset and snapshot coverage and stub calls.
38
+ // It is registered here, after the app bootstrap, rather than generated
39
+ // into the project — an app bootstrap is what a deployed bundle imports,
40
+ // and coverage endpoints have no business in one.
41
+ if (config.scaffold?.scenarios) {
42
+ registerScenarioInstrumentation(resolveScaffoldFeature('scenarios', config.scaffold.scenarios).auth);
43
+ }
31
44
  const workflowService = new InMemoryWorkflowService();
32
45
  const configModule = await loadUserModule(pikkuConfigFactory.file);
33
46
  const servicesModule = await loadUserModule(singletonServicesFactory.file);
@@ -115,6 +128,7 @@ export const serve = pikkuSessionlessFunc({
115
128
  };
116
129
  pikkuState(null, 'package', 'singletonServices', resolvedServices);
117
130
  resolvedServices.workflowService?.wireQueueWorkers?.();
131
+ wireAIScorerQueueWorkers();
118
132
  const { serverLifecycleFactory } = inspectorState.filesAndMethods;
119
133
  const loadLifecycle = async () => {
120
134
  if (!serverLifecycleFactory)
@@ -1,7 +1,12 @@
1
- import { renderWorkspaceValidate } from '../validate/workspace-validate.js';
2
- export declare const workspaceValidate: import("#pikku").PikkuFunctionConfig<Record<string, never>, {
1
+ import { renderValidate } from '../validate/validate.js';
2
+ export declare const validate: import("#pikku").PikkuFunctionConfig<Record<string, never>, {
3
3
  ok: boolean;
4
4
  root: string;
5
+ ran: {
6
+ checkId: string;
7
+ subject: string;
8
+ target: string;
9
+ }[];
5
10
  findings: {
6
11
  id: string;
7
12
  severity: "warn" | "error" | "info";
@@ -12,6 +17,11 @@ export declare const workspaceValidate: import("#pikku").PikkuFunctionConfig<Rec
12
17
  }, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<Record<string, never>, {
13
18
  ok: boolean;
14
19
  root: string;
20
+ ran: {
21
+ checkId: string;
22
+ subject: string;
23
+ target: string;
24
+ }[];
15
25
  findings: {
16
26
  id: string;
17
27
  severity: "warn" | "error" | "info";
@@ -22,6 +32,11 @@ export declare const workspaceValidate: import("#pikku").PikkuFunctionConfig<Rec
22
32
  }, "rpc" | "session", import("#pikku").WiredServices, unknown> | import("#pikku").PikkuFunction<Record<string, never>, {
23
33
  ok: boolean;
24
34
  root: string;
35
+ ran: {
36
+ checkId: string;
37
+ subject: string;
38
+ target: string;
39
+ }[];
25
40
  findings: {
26
41
  id: string;
27
42
  severity: "warn" | "error" | "info";
@@ -30,4 +45,4 @@ export declare const workspaceValidate: import("#pikku").PikkuFunctionConfig<Rec
30
45
  fixHint: string;
31
46
  }[];
32
47
  }, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
33
- export { renderWorkspaceValidate };
48
+ export { renderValidate };
@@ -0,0 +1,9 @@
1
+ import { pikkuSessionlessFunc } from '#pikku';
2
+ import { ValidateInput, ValidateOutput, renderValidate, runProjectValidate, } from '../validate/validate.js';
3
+ export const validate = pikkuSessionlessFunc({
4
+ description: 'Check this project against every Pikku check that applies to it — app structure, and the published file set of any addon it contains. Prints what was checked, with fix hints for anything wrong.',
5
+ input: ValidateInput,
6
+ output: ValidateOutput,
7
+ func: async () => runProjectValidate(),
8
+ });
9
+ export { renderValidate };
@@ -40,7 +40,7 @@ export interface ResolvedPostgresDb extends ResolvedDbBase {
40
40
  devSeedFile: string;
41
41
  /**
42
42
  * Postgres extensions the embedded PGlite databases must load, as declared by
43
- * `pgliteExtensions` in the project's config. See
43
+ * `db.pgliteExtensions` in the project's pikku.config.json. See
44
44
  * {@link loadPGliteExtensions}.
45
45
  *
46
46
  * Carried even in `url` mode: the shadow database the CLI migrates and
@@ -72,6 +72,7 @@ export declare function parseDatabaseUrl(url: string): Pick<UserConfigShape, 'sq
72
72
  export declare function resolveDb(userConfig: UserConfigShape, rootDir: string, outDir: string, runtimeDir?: string, dbConfig?: {
73
73
  schema?: string;
74
74
  defaultSchema?: string;
75
+ pgliteExtensions?: string[];
75
76
  } | string): ResolvedDb | null;
76
77
  /** @deprecated Use resolveDb(userConfig, ...) instead. */
77
78
  export declare function resolveLocalDb(sqliteDb: string | undefined, rootDir: string, outDir: string, runtimeDir?: string): ResolvedSqliteDb | null;
@@ -68,7 +68,7 @@ export function resolveDb(userConfig, rootDir, outDir, runtimeDir, dbConfig) {
68
68
  if (userConfig.postgresUrl && userConfig.sqliteDb) {
69
69
  throw new Error('Both postgresUrl and sqliteDb are set. Configure exactly one database dialect.');
70
70
  }
71
- const pgliteExtensions = userConfig.pgliteExtensions ?? [];
71
+ const pgliteExtensions = (typeof dbConfig === 'string' ? undefined : dbConfig?.pgliteExtensions) ?? [];
72
72
  if (userConfig.postgresUrl) {
73
73
  return {
74
74
  dialect: 'postgres',
@@ -268,7 +268,7 @@ function explainMissingExtension(error, declared) {
268
268
  return new Error(`The embedded PGlite database has no '${name}' extension. ` +
269
269
  `The CLI migrates a PGlite shadow database to type and diff your schema, ` +
270
270
  `so every extension your migrations use has to be declared as ` +
271
- `pgliteExtensions in createConfig — e.g. pgliteExtensions: ['${name}'] ` +
271
+ `db.pgliteExtensions in pikku.config.json — e.g. "db": { "pgliteExtensions": ["${name}"] } ` +
272
272
  `for a PGlite contrib extension, or the package that publishes it ` +
273
273
  `('@electric-sql/pglite-pgvector' for pgvector).` +
274
274
  (declared.length > 0
@@ -0,0 +1,14 @@
1
+ export type SurfaceKind = 'function' | 'class' | 'interface' | 'type' | 'const' | 'enum' | 'namespace';
2
+ export type SurfaceSymbol = {
3
+ name: string;
4
+ kind: SurfaceKind;
5
+ declaredAt: string;
6
+ deprecated: boolean;
7
+ };
8
+ export type SurfaceEntrypoint = {
9
+ subpath: string;
10
+ specifier: string;
11
+ entryFile: string;
12
+ symbols: SurfaceSymbol[];
13
+ };
14
+ export declare const collectSurface: (packageDir: string) => Promise<SurfaceEntrypoint[]>;
@@ -0,0 +1,215 @@
1
+ import { existsSync, readdirSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { join, relative, resolve } from 'node:path';
4
+ import ts from 'typescript';
5
+ const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts'];
6
+ const MODULE_EXTENSIONS = [...SOURCE_EXTENSIONS, '.js', '.jsx', '.mjs', '.cjs'];
7
+ const wildcardStem = (fileName) => {
8
+ if (fileName.endsWith('.map'))
9
+ return null;
10
+ if (/\.d\.(ts|mts|cts)$/.test(fileName))
11
+ return null;
12
+ const extension = MODULE_EXTENSIONS.find((each) => fileName.endsWith(each));
13
+ return extension ? fileName.slice(0, -extension.length) : null;
14
+ };
15
+ const subpathMap = (exports) => {
16
+ if (typeof exports === 'string')
17
+ return { '.': exports };
18
+ return Object.keys(exports).some((key) => key.startsWith('.'))
19
+ ? exports
20
+ : { '.': exports };
21
+ };
22
+ const publishesCode = (target) => !/\.(css|scss|json|svg|png|woff2?|txt|md)$/.test(target);
23
+ const sourceForTarget = (packageDir, target, outDir) => {
24
+ const withoutPrefix = target.replace(/^\.\//, '');
25
+ const isDeclaration = /\.d\.(ts|mts|cts)$/.test(withoutPrefix);
26
+ if (!isDeclaration &&
27
+ SOURCE_EXTENSIONS.some((extension) => withoutPrefix.endsWith(extension))) {
28
+ return existsSync(join(packageDir, withoutPrefix)) ? withoutPrefix : null;
29
+ }
30
+ const stripped = withoutPrefix.startsWith(`${outDir}/`)
31
+ ? withoutPrefix.slice(outDir.length + 1)
32
+ : withoutPrefix;
33
+ const base = stripped
34
+ .replace(/\.d\.(ts|mts|cts)$/, '')
35
+ .replace(/\.(js|jsx|mjs|cjs)$/, '');
36
+ const withoutSrc = base.startsWith('src/') ? base.slice(4) : base;
37
+ const candidates = [];
38
+ for (const extension of SOURCE_EXTENSIONS) {
39
+ candidates.push(join('src', `${base}${extension}`), `${base}${extension}`, join('src', `${withoutSrc}${extension}`), join('src', base, `index${extension}`), join(base, `index${extension}`));
40
+ }
41
+ for (const candidate of candidates) {
42
+ if (existsSync(join(packageDir, candidate)))
43
+ return candidate;
44
+ }
45
+ return null;
46
+ };
47
+ const expandWildcard = (packageDir, subpath, target) => {
48
+ const targetDir = target.replace(/^\.\//, '').split('*')[0] ?? '';
49
+ const suffix = target.slice(target.indexOf('*') + 1);
50
+ const absolute = join(packageDir, targetDir);
51
+ if (!existsSync(absolute))
52
+ return [];
53
+ const expanded = [];
54
+ const walk = (directory, prefix) => {
55
+ for (const entry of readdirSync(directory, { withFileTypes: true })) {
56
+ if (entry.isDirectory()) {
57
+ walk(join(directory, entry.name), `${prefix}${entry.name}/`);
58
+ continue;
59
+ }
60
+ if (!entry.isFile())
61
+ continue;
62
+ if (suffix && !entry.name.endsWith(suffix))
63
+ continue;
64
+ const stem = wildcardStem(entry.name);
65
+ if (stem === null)
66
+ continue;
67
+ expanded.push({
68
+ subpath: subpath.replace('*', `${prefix}${stem}`),
69
+ target: `${targetDir}${prefix}${entry.name}`,
70
+ });
71
+ }
72
+ };
73
+ walk(absolute, '');
74
+ return expanded;
75
+ };
76
+ const targetOf = (value) => {
77
+ if (typeof value === 'string')
78
+ return value;
79
+ if (!value || typeof value !== 'object')
80
+ return null;
81
+ const conditions = value;
82
+ for (const key of ['types', 'import', 'default', 'require']) {
83
+ const resolved = targetOf(conditions[key]);
84
+ if (resolved)
85
+ return resolved;
86
+ }
87
+ return null;
88
+ };
89
+ const readJson = async (path) => {
90
+ try {
91
+ return JSON.parse(await readFile(path, 'utf8'));
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ };
97
+ const readCompilerOptions = async (packageDir) => {
98
+ const configPath = join(packageDir, 'tsconfig.json');
99
+ if (!existsSync(configPath))
100
+ return { outDir: 'dist', paths: {} };
101
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
102
+ if (configFile.error)
103
+ return { outDir: 'dist', paths: {} };
104
+ const { options } = ts.parseJsonConfigFileContent(configFile.config, ts.sys, packageDir);
105
+ const { baseUrl, paths, pathsBasePath } = options;
106
+ return {
107
+ outDir: options.outDir ? relative(packageDir, options.outDir) : 'dist',
108
+ paths: {
109
+ ...(baseUrl !== undefined ? { baseUrl } : {}),
110
+ ...(paths !== undefined ? { paths } : {}),
111
+ ...(pathsBasePath !== undefined ? { pathsBasePath } : {}),
112
+ },
113
+ };
114
+ };
115
+ const KIND_BY_FLAG = [
116
+ [ts.SymbolFlags.Class, 'class'],
117
+ [ts.SymbolFlags.Interface, 'interface'],
118
+ [ts.SymbolFlags.RegularEnum | ts.SymbolFlags.ConstEnum, 'enum'],
119
+ [ts.SymbolFlags.Function, 'function'],
120
+ [ts.SymbolFlags.TypeAlias, 'type'],
121
+ [ts.SymbolFlags.Namespace, 'namespace'],
122
+ ];
123
+ const kindOf = (symbol, checker) => {
124
+ const target = symbol.flags & ts.SymbolFlags.Alias
125
+ ? checker.getAliasedSymbol(symbol)
126
+ : symbol;
127
+ for (const [flag, kind] of KIND_BY_FLAG) {
128
+ if (target.flags & flag)
129
+ return kind;
130
+ }
131
+ if (target.flags & ts.SymbolFlags.Variable) {
132
+ const declaration = target.declarations?.[0];
133
+ if (declaration) {
134
+ const type = checker.getTypeOfSymbolAtLocation(target, declaration);
135
+ if (type.getCallSignatures().length > 0)
136
+ return 'function';
137
+ }
138
+ return 'const';
139
+ }
140
+ return 'const';
141
+ };
142
+ const isDeprecated = (symbol) => symbol.getJsDocTags().some((tag) => tag.name === 'deprecated');
143
+ const declarationFileOf = (symbol, checker) => {
144
+ const target = symbol.flags & ts.SymbolFlags.Alias
145
+ ? checker.getAliasedSymbol(symbol)
146
+ : symbol;
147
+ const declaration = target.declarations?.[0] ?? symbol.declarations?.[0];
148
+ return declaration?.getSourceFile().fileName ?? null;
149
+ };
150
+ export const collectSurface = async (packageDir) => {
151
+ const root = resolve(packageDir);
152
+ const packageJson = await readJson(join(root, 'package.json'));
153
+ if (!packageJson?.exports)
154
+ return [];
155
+ const { outDir, paths } = await readCompilerOptions(root);
156
+ const packageName = packageJson.name ?? '';
157
+ const entries = [];
158
+ const seenEntryFiles = new Set();
159
+ for (const [subpath, value] of Object.entries(subpathMap(packageJson.exports))) {
160
+ if (!subpath.startsWith('.'))
161
+ continue;
162
+ const target = targetOf(value);
163
+ if (!target || !publishesCode(target))
164
+ continue;
165
+ const declared = target.includes('*')
166
+ ? expandWildcard(root, subpath, target)
167
+ : [{ subpath, target }];
168
+ for (const each of declared) {
169
+ const entryFile = sourceForTarget(root, each.target, outDir);
170
+ if (!entryFile || seenEntryFiles.has(entryFile))
171
+ continue;
172
+ seenEntryFiles.add(entryFile);
173
+ entries.push({
174
+ subpath: each.subpath,
175
+ specifier: each.subpath === '.'
176
+ ? packageName
177
+ : `${packageName}${each.subpath.slice(1)}`,
178
+ entryFile,
179
+ });
180
+ }
181
+ }
182
+ if (entries.length === 0)
183
+ return [];
184
+ const program = ts.createProgram(entries.map((entry) => join(root, entry.entryFile)), {
185
+ ...paths,
186
+ target: ts.ScriptTarget.ESNext,
187
+ module: ts.ModuleKind.Node16,
188
+ moduleResolution: ts.ModuleResolutionKind.Node16,
189
+ skipLibCheck: true,
190
+ skipDefaultLibCheck: true,
191
+ types: [],
192
+ allowJs: false,
193
+ checkJs: false,
194
+ });
195
+ const checker = program.getTypeChecker();
196
+ return entries.map((entry) => {
197
+ const sourceFile = program.getSourceFile(join(root, entry.entryFile));
198
+ const moduleSymbol = sourceFile
199
+ ? checker.getSymbolAtLocation(sourceFile)
200
+ : undefined;
201
+ const symbols = [];
202
+ for (const symbol of moduleSymbol
203
+ ? checker.getExportsOfModule(moduleSymbol)
204
+ : []) {
205
+ const file = declarationFileOf(symbol, checker);
206
+ symbols.push({
207
+ name: symbol.getName(),
208
+ kind: kindOf(symbol, checker),
209
+ declaredAt: file ? relative(root, file) : entry.entryFile,
210
+ deprecated: isDeprecated(symbol),
211
+ });
212
+ }
213
+ return { ...entry, symbols };
214
+ });
215
+ };