@kindgi/cli 0.1.11-rc.0 → 0.2.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +77 -33
  2. package/dist/build/containerfile.d.ts +2 -0
  3. package/dist/build/containerfile.d.ts.map +1 -1
  4. package/dist/build/containerfile.js +14 -3
  5. package/dist/build/containerfile.js.map +1 -1
  6. package/dist/build/defaults.d.ts +2 -0
  7. package/dist/build/defaults.d.ts.map +1 -1
  8. package/dist/build/defaults.js +8 -0
  9. package/dist/build/defaults.js.map +1 -1
  10. package/dist/build/hosted.d.ts +2 -9
  11. package/dist/build/hosted.d.ts.map +1 -1
  12. package/dist/build/hosted.js +4 -2
  13. package/dist/build/hosted.js.map +1 -1
  14. package/dist/build/pack-blocks.d.ts +51 -0
  15. package/dist/build/pack-blocks.d.ts.map +1 -0
  16. package/dist/build/pack-blocks.js +98 -0
  17. package/dist/build/pack-blocks.js.map +1 -0
  18. package/dist/build/runners.d.ts +5 -1
  19. package/dist/build/runners.d.ts.map +1 -1
  20. package/dist/cli.js +4 -0
  21. package/dist/cli.js.map +1 -1
  22. package/dist/commands/adapters.d.ts.map +1 -1
  23. package/dist/commands/adapters.js +12 -6
  24. package/dist/commands/adapters.js.map +1 -1
  25. package/dist/commands/agents.js +8 -8
  26. package/dist/commands/agents.js.map +1 -1
  27. package/dist/commands/auth.d.ts.map +1 -1
  28. package/dist/commands/auth.js +155 -39
  29. package/dist/commands/auth.js.map +1 -1
  30. package/dist/commands/blocks.d.ts.map +1 -1
  31. package/dist/commands/blocks.js +1 -1
  32. package/dist/commands/blocks.js.map +1 -1
  33. package/dist/commands/build.d.ts +17 -6
  34. package/dist/commands/build.d.ts.map +1 -1
  35. package/dist/commands/build.js +136 -89
  36. package/dist/commands/build.js.map +1 -1
  37. package/dist/commands/connection-apps.d.ts +3 -0
  38. package/dist/commands/connection-apps.d.ts.map +1 -0
  39. package/dist/commands/connection-apps.js +239 -0
  40. package/dist/commands/connection-apps.js.map +1 -0
  41. package/dist/commands/connections.d.ts +44 -0
  42. package/dist/commands/connections.d.ts.map +1 -0
  43. package/dist/commands/connections.js +385 -0
  44. package/dist/commands/connections.js.map +1 -0
  45. package/dist/commands/conversations.js +1 -1
  46. package/dist/commands/conversations.js.map +1 -1
  47. package/dist/commands/deploy.d.ts.map +1 -1
  48. package/dist/commands/deploy.js +178 -97
  49. package/dist/commands/deploy.js.map +1 -1
  50. package/dist/commands/dev.d.ts +10 -0
  51. package/dist/commands/dev.d.ts.map +1 -1
  52. package/dist/commands/dev.js +177 -87
  53. package/dist/commands/dev.js.map +1 -1
  54. package/dist/commands/doctor.js +7 -7
  55. package/dist/commands/doctor.js.map +1 -1
  56. package/dist/commands/env-scoped.d.ts.map +1 -1
  57. package/dist/commands/env-scoped.js +37 -22
  58. package/dist/commands/env-scoped.js.map +1 -1
  59. package/dist/commands/env.d.ts.map +1 -1
  60. package/dist/commands/env.js +35 -22
  61. package/dist/commands/env.js.map +1 -1
  62. package/dist/commands/eval-runs.js +6 -6
  63. package/dist/commands/eval-runs.js.map +1 -1
  64. package/dist/commands/eval-suites.js +9 -9
  65. package/dist/commands/eval-suites.js.map +1 -1
  66. package/dist/commands/exports.d.ts.map +1 -1
  67. package/dist/commands/exports.js +35 -9
  68. package/dist/commands/exports.js.map +1 -1
  69. package/dist/commands/feedback.d.ts.map +1 -1
  70. package/dist/commands/feedback.js +4 -3
  71. package/dist/commands/feedback.js.map +1 -1
  72. package/dist/commands/gate-policies.d.ts.map +1 -1
  73. package/dist/commands/gate-policies.js +7 -7
  74. package/dist/commands/gate-policies.js.map +1 -1
  75. package/dist/commands/helpers.d.ts +9 -0
  76. package/dist/commands/helpers.d.ts.map +1 -1
  77. package/dist/commands/helpers.js +20 -0
  78. package/dist/commands/helpers.js.map +1 -1
  79. package/dist/commands/index.d.ts.map +1 -1
  80. package/dist/commands/index.js +8 -0
  81. package/dist/commands/index.js.map +1 -1
  82. package/dist/commands/init.d.ts +1 -1
  83. package/dist/commands/init.d.ts.map +1 -1
  84. package/dist/commands/init.js +57 -45
  85. package/dist/commands/init.js.map +1 -1
  86. package/dist/commands/judge-classes.js +4 -4
  87. package/dist/commands/judge-classes.js.map +1 -1
  88. package/dist/commands/judging-queue.d.ts +3 -0
  89. package/dist/commands/judging-queue.d.ts.map +1 -0
  90. package/dist/commands/judging-queue.js +105 -0
  91. package/dist/commands/judging-queue.js.map +1 -0
  92. package/dist/commands/judging-rules.d.ts +3 -0
  93. package/dist/commands/judging-rules.d.ts.map +1 -0
  94. package/dist/commands/judging-rules.js +351 -0
  95. package/dist/commands/judging-rules.js.map +1 -0
  96. package/dist/commands/judgments.d.ts.map +1 -1
  97. package/dist/commands/judgments.js +78 -36
  98. package/dist/commands/judgments.js.map +1 -1
  99. package/dist/commands/key.d.ts.map +1 -1
  100. package/dist/commands/key.js +107 -9
  101. package/dist/commands/key.js.map +1 -1
  102. package/dist/commands/license.d.ts.map +1 -1
  103. package/dist/commands/license.js +67 -15
  104. package/dist/commands/license.js.map +1 -1
  105. package/dist/commands/mcp.d.ts.map +1 -1
  106. package/dist/commands/mcp.js +4 -4
  107. package/dist/commands/mcp.js.map +1 -1
  108. package/dist/commands/people.js +8 -14
  109. package/dist/commands/people.js.map +1 -1
  110. package/dist/commands/promote.js +1 -1
  111. package/dist/commands/promote.js.map +1 -1
  112. package/dist/commands/proposals.d.ts.map +1 -1
  113. package/dist/commands/proposals.js +83 -30
  114. package/dist/commands/proposals.js.map +1 -1
  115. package/dist/commands/run-waits.d.ts +68 -19
  116. package/dist/commands/run-waits.d.ts.map +1 -1
  117. package/dist/commands/run-waits.js +82 -8
  118. package/dist/commands/run-waits.js.map +1 -1
  119. package/dist/commands/runs.d.ts.map +1 -1
  120. package/dist/commands/runs.js +70 -30
  121. package/dist/commands/runs.js.map +1 -1
  122. package/dist/commands/schedules.d.ts.map +1 -1
  123. package/dist/commands/schedules.js +35 -12
  124. package/dist/commands/schedules.js.map +1 -1
  125. package/dist/commands/secrets-copy.d.ts.map +1 -1
  126. package/dist/commands/secrets-copy.js +20 -12
  127. package/dist/commands/secrets-copy.js.map +1 -1
  128. package/dist/commands/secrets.d.ts.map +1 -1
  129. package/dist/commands/secrets.js +13 -8
  130. package/dist/commands/secrets.js.map +1 -1
  131. package/dist/commands/sign-in.js +2 -2
  132. package/dist/commands/sign-in.js.map +1 -1
  133. package/dist/commands/sites.d.ts.map +1 -1
  134. package/dist/commands/sites.js +13 -6
  135. package/dist/commands/sites.js.map +1 -1
  136. package/dist/commands/skills.d.ts +54 -3
  137. package/dist/commands/skills.d.ts.map +1 -1
  138. package/dist/commands/skills.js +169 -38
  139. package/dist/commands/skills.js.map +1 -1
  140. package/dist/commands/tokens.d.ts.map +1 -1
  141. package/dist/commands/tokens.js +9 -1
  142. package/dist/commands/tokens.js.map +1 -1
  143. package/dist/commands/upgrade.d.ts.map +1 -1
  144. package/dist/commands/upgrade.js +9 -8
  145. package/dist/commands/upgrade.js.map +1 -1
  146. package/dist/commands/webhooks.d.ts.map +1 -1
  147. package/dist/commands/webhooks.js +62 -24
  148. package/dist/commands/webhooks.js.map +1 -1
  149. package/dist/config.d.ts +6 -0
  150. package/dist/config.d.ts.map +1 -1
  151. package/dist/config.js +18 -3
  152. package/dist/config.js.map +1 -1
  153. package/dist/context.d.ts +12 -0
  154. package/dist/context.d.ts.map +1 -1
  155. package/dist/context.js +2 -0
  156. package/dist/context.js.map +1 -1
  157. package/dist/deploy/pack-blocks-gate.d.ts +12 -0
  158. package/dist/deploy/pack-blocks-gate.d.ts.map +1 -0
  159. package/dist/deploy/pack-blocks-gate.js +34 -0
  160. package/dist/deploy/pack-blocks-gate.js.map +1 -0
  161. package/dist/deploy/post.d.ts +9 -0
  162. package/dist/deploy/post.d.ts.map +1 -1
  163. package/dist/deploy/post.js +20 -3
  164. package/dist/deploy/post.js.map +1 -1
  165. package/dist/dev/defaults.d.ts.map +1 -1
  166. package/dist/dev/defaults.js +8 -1
  167. package/dist/dev/defaults.js.map +1 -1
  168. package/dist/dev/dev-only-imports.d.ts +7 -4
  169. package/dist/dev/dev-only-imports.d.ts.map +1 -1
  170. package/dist/dev/dev-only-imports.js +5 -5
  171. package/dist/dev/dev-only-imports.js.map +1 -1
  172. package/dist/dev/log-view.d.ts +4 -4
  173. package/dist/dev/log-view.d.ts.map +1 -1
  174. package/dist/dev/log-view.js +4 -4
  175. package/dist/dev/log-view.js.map +1 -1
  176. package/dist/dev/pack-service.d.ts +7 -1
  177. package/dist/dev/pack-service.d.ts.map +1 -1
  178. package/dist/dev/pack-service.js +36 -3
  179. package/dist/dev/pack-service.js.map +1 -1
  180. package/dist/dev/preview-expiry.d.ts +6 -7
  181. package/dist/dev/preview-expiry.d.ts.map +1 -1
  182. package/dist/dev/preview-expiry.js +7 -8
  183. package/dist/dev/preview-expiry.js.map +1 -1
  184. package/dist/dev/providers.d.ts +2 -1
  185. package/dist/dev/providers.d.ts.map +1 -1
  186. package/dist/dev/providers.js +28 -12
  187. package/dist/dev/providers.js.map +1 -1
  188. package/dist/dev/runners.d.ts +19 -0
  189. package/dist/dev/runners.d.ts.map +1 -1
  190. package/dist/dev/runtime-container.d.ts.map +1 -1
  191. package/dist/dev/runtime-container.js +2 -2
  192. package/dist/dev/runtime-container.js.map +1 -1
  193. package/dist/dev/runtime-env.d.ts +2 -1
  194. package/dist/dev/runtime-env.d.ts.map +1 -1
  195. package/dist/dev/runtime-env.js +5 -5
  196. package/dist/dev/runtime-env.js.map +1 -1
  197. package/dist/dev/runtime-image.d.ts +2 -2
  198. package/dist/dev/runtime-image.d.ts.map +1 -1
  199. package/dist/dev/runtime-image.js +2 -2
  200. package/dist/dev/runtime-image.js.map +1 -1
  201. package/dist/dev/runtime-registry.d.ts +8 -10
  202. package/dist/dev/runtime-registry.d.ts.map +1 -1
  203. package/dist/dev/runtime-registry.js +27 -27
  204. package/dist/dev/runtime-registry.js.map +1 -1
  205. package/dist/dev/sandbox/index.js +1 -1
  206. package/dist/dev/sandbox/notices.d.ts +2 -0
  207. package/dist/dev/sandbox/notices.d.ts.map +1 -1
  208. package/dist/dev/sandbox/notices.js +5 -2
  209. package/dist/dev/sandbox/notices.js.map +1 -1
  210. package/dist/env/defaults.d.ts.map +1 -1
  211. package/dist/env/defaults.js +3 -1
  212. package/dist/env/defaults.js.map +1 -1
  213. package/dist/env/pack-env-plan.d.ts +4 -0
  214. package/dist/env/pack-env-plan.d.ts.map +1 -1
  215. package/dist/env/pack-env-plan.js +8 -2
  216. package/dist/env/pack-env-plan.js.map +1 -1
  217. package/dist/exports/create.d.ts +2 -0
  218. package/dist/exports/create.d.ts.map +1 -1
  219. package/dist/exports/create.js +10 -2
  220. package/dist/exports/create.js.map +1 -1
  221. package/dist/exports/plan.d.ts.map +1 -1
  222. package/dist/exports/plan.js +20 -0
  223. package/dist/exports/plan.js.map +1 -1
  224. package/dist/feedback/store.d.ts.map +1 -1
  225. package/dist/feedback/store.js +8 -19
  226. package/dist/feedback/store.js.map +1 -1
  227. package/dist/help.d.ts +6 -0
  228. package/dist/help.d.ts.map +1 -1
  229. package/dist/help.js +35 -1
  230. package/dist/help.js.map +1 -1
  231. package/dist/init/agent-access.d.ts +3 -2
  232. package/dist/init/agent-access.d.ts.map +1 -1
  233. package/dist/init/agent-access.js +5 -1
  234. package/dist/init/agent-access.js.map +1 -1
  235. package/dist/init/augment-scaffolder.d.ts +7 -0
  236. package/dist/init/augment-scaffolder.d.ts.map +1 -1
  237. package/dist/init/augment-scaffolder.js +15 -14
  238. package/dist/init/augment-scaffolder.js.map +1 -1
  239. package/dist/init/dependency-specs.d.ts +1 -0
  240. package/dist/init/dependency-specs.d.ts.map +1 -1
  241. package/dist/init/dependency-specs.js +27 -7
  242. package/dist/init/dependency-specs.js.map +1 -1
  243. package/dist/init/java-augment.d.ts +3 -0
  244. package/dist/init/java-augment.d.ts.map +1 -1
  245. package/dist/init/java-augment.js +16 -15
  246. package/dist/init/java-augment.js.map +1 -1
  247. package/dist/init/python-augment.d.ts +3 -0
  248. package/dist/init/python-augment.d.ts.map +1 -1
  249. package/dist/init/python-augment.js +15 -14
  250. package/dist/init/python-augment.js.map +1 -1
  251. package/dist/init/scala-augment.d.ts +8 -1
  252. package/dist/init/scala-augment.d.ts.map +1 -1
  253. package/dist/init/scala-augment.js +32 -17
  254. package/dist/init/scala-augment.js.map +1 -1
  255. package/dist/key/defaults.d.ts.map +1 -1
  256. package/dist/key/defaults.js +6 -1
  257. package/dist/key/defaults.js.map +1 -1
  258. package/dist/key/runners.d.ts +4 -1
  259. package/dist/key/runners.d.ts.map +1 -1
  260. package/dist/license/renew.d.ts +6 -0
  261. package/dist/license/renew.d.ts.map +1 -1
  262. package/dist/license/renew.js +8 -5
  263. package/dist/license/renew.js.map +1 -1
  264. package/dist/main.d.ts +10 -0
  265. package/dist/main.d.ts.map +1 -1
  266. package/dist/main.js +19 -5
  267. package/dist/main.js.map +1 -1
  268. package/dist/output.d.ts +6 -0
  269. package/dist/output.d.ts.map +1 -1
  270. package/dist/output.js +8 -0
  271. package/dist/output.js.map +1 -1
  272. package/dist/parse.d.ts +1 -1
  273. package/dist/parse.d.ts.map +1 -1
  274. package/dist/parse.js +1 -1
  275. package/dist/parse.js.map +1 -1
  276. package/dist/private-file.d.ts +23 -0
  277. package/dist/private-file.d.ts.map +1 -0
  278. package/dist/private-file.js +65 -0
  279. package/dist/private-file.js.map +1 -0
  280. package/dist/progress-head.d.ts +13 -0
  281. package/dist/progress-head.d.ts.map +1 -0
  282. package/dist/progress-head.js +30 -0
  283. package/dist/progress-head.js.map +1 -0
  284. package/dist/progress-lines.d.ts +29 -0
  285. package/dist/progress-lines.d.ts.map +1 -0
  286. package/dist/progress-lines.js +35 -0
  287. package/dist/progress-lines.js.map +1 -0
  288. package/dist/sdk-skills/kindgi-authoring-agents/SKILL.md +6 -6
  289. package/dist/sdk-skills/kindgi-authoring-flows/SKILL.md +1 -1
  290. package/dist/sdk-skills/kindgi-authoring-guardrails/SKILL.md +2 -2
  291. package/dist/sdk-skills/kindgi-authoring-mcp-servers/SKILL.md +1 -1
  292. package/dist/sdk-skills/kindgi-authoring-providers/SKILL.md +3 -3
  293. package/dist/sdk-skills/kindgi-authoring-tools/SKILL.md +39 -6
  294. package/dist/sdk-skills/kindgi-fix-corrections/SKILL.md +262 -0
  295. package/dist/sdk-skills/kindgi-framework-feedback/SKILL.md +1 -1
  296. package/dist/sdk-skills/kindgi-getting-started/SKILL.md +43 -9
  297. package/dist/sdk-skills/kindgi-java-authoring-agents/SKILL.md +5 -5
  298. package/dist/sdk-skills/kindgi-java-authoring-flows/SKILL.md +1 -1
  299. package/dist/sdk-skills/kindgi-java-authoring-guardrails/SKILL.md +1 -1
  300. package/dist/sdk-skills/kindgi-java-authoring-tools/SKILL.md +91 -9
  301. package/dist/sdk-skills/kindgi-java-getting-started/SKILL.md +38 -9
  302. package/dist/sdk-skills/kindgi-python-authoring-agents/SKILL.md +4 -4
  303. package/dist/sdk-skills/kindgi-python-authoring-flows/SKILL.md +1 -1
  304. package/dist/sdk-skills/kindgi-python-authoring-guardrails/SKILL.md +1 -1
  305. package/dist/sdk-skills/kindgi-python-authoring-tools/SKILL.md +43 -8
  306. package/dist/sdk-skills/kindgi-python-getting-started/SKILL.md +39 -11
  307. package/dist/sdk-skills/kindgi-scala-authoring-agents/SKILL.md +5 -5
  308. package/dist/sdk-skills/kindgi-scala-authoring-flows/SKILL.md +1 -1
  309. package/dist/sdk-skills/kindgi-scala-authoring-guardrails/SKILL.md +1 -1
  310. package/dist/sdk-skills/kindgi-scala-authoring-tools/SKILL.md +82 -7
  311. package/dist/sdk-skills/kindgi-scala-getting-started/SKILL.md +38 -9
  312. package/dist/sdk-skills/kindgi-using/SKILL.md +50 -21
  313. package/dist/templates/drupal/AGENTS.md +2 -1
  314. package/dist/templates/follow-up/.nvmrc +1 -0
  315. package/dist/templates/follow-up/AGENTS.md +83 -0
  316. package/dist/templates/follow-up/README.md.tmpl +111 -0
  317. package/dist/templates/follow-up/agents/follow-up/index.test.ts.tmpl +26 -0
  318. package/dist/templates/follow-up/agents/follow-up/index.ts.tmpl +53 -0
  319. package/dist/templates/follow-up/gitignore +8 -0
  320. package/dist/templates/follow-up/kindgi.config.ts.tmpl +45 -0
  321. package/dist/templates/follow-up/package.json.tmpl +30 -0
  322. package/dist/templates/follow-up/pnpm-workspace.yaml +9 -0
  323. package/dist/templates/follow-up/tools/gmail-send/index.test.ts.tmpl +60 -0
  324. package/dist/templates/follow-up/tools/gmail-send/index.ts.tmpl +14 -0
  325. package/dist/templates/follow-up/tsconfig.json.tmpl +27 -0
  326. package/dist/templates/follow-up/vitest.config.ts.tmpl +14 -0
  327. package/dist/templates/java/AGENTS.md +2 -1
  328. package/dist/templates/minimal/AGENTS.md +2 -1
  329. package/dist/templates/python/AGENTS.md +2 -1
  330. package/dist/templates/sample/AGENTS.md +2 -1
  331. package/dist/templates/scala/AGENTS.md +2 -1
  332. package/dist/templates/woocommerce/AGENTS.md +12 -3
  333. package/dist/templates/woocommerce/README.md.tmpl +29 -5
  334. package/dist/templates/woocommerce/agents/store-agent/index.test.ts.tmpl +38 -7
  335. package/dist/templates/woocommerce/agents/store-agent/index.ts.tmpl +7 -12
  336. package/dist/templates/woocommerce/blocks/store-agent-prompt.json.tmpl +10 -0
  337. package/dist/templates/woocommerce/blocks/store-agent-prompt.liquid.tmpl +7 -0
  338. package/dist/templates/woocommerce/kindgi.config.ts.tmpl +1 -0
  339. package/dist/value-target.d.ts +4 -2
  340. package/dist/value-target.d.ts.map +1 -1
  341. package/dist/value-target.js +8 -5
  342. package/dist/value-target.js.map +1 -1
  343. package/package.json +13 -13
@@ -18,7 +18,8 @@
18
18
  * `buildLogsUrl`).
19
19
  * 5. Compute `Idempotency-Key: sha256(canonicalBody)` (or `--idempotency-key`).
20
20
  * 6. If `--dry-run`: print the curl-equivalent + body + headers to
21
- * stderr, exit 0.
21
+ * stderr, exit 0. An unsigned envelope shows the body less the
22
+ * signature's fields, and no derived key.
22
23
  * 7. Otherwise POST via `ctx.fetch`, waiting out the server's rate
23
24
  * limits (`429` with `Retry-After`) for up to 10 minutes in all.
24
25
  * 8. Handle response (201 / 200 / 4xx / 5xx / transport).
@@ -26,22 +27,27 @@
26
27
  */
27
28
  import { stat } from 'node:fs/promises';
28
29
  import { isAbsolute, join, resolve } from 'node:path';
30
+ import { readPackBlocks, resolveDiscovery } from '@kindgi/handler-runtime';
29
31
  import { LOCAL_ENV_NAME, packValues, readPackEnv } from '@kindgi/secrets-dotenv';
30
32
  import { deployApiAddress, hostedApiAddress } from '../api-address.js';
33
+ import { describeFiles } from '../build/pack-blocks.js';
31
34
  import { isEnvelopeSigned } from '../deploy/envelope-loader.js';
35
+ import { packBlocksRefusal } from '../deploy/pack-blocks-gate.js';
32
36
  import { packServiceProblemText, packServiceRetiredText } from '../deploy/pack-service-text.js';
33
- import { buildPostBody, deriveIdempotencyKey, deriveSyncSecretsIdempotencyKey, } from '../deploy/post.js';
37
+ import { buildPostBody, deriveIdempotencyKey, deriveSyncSecretsIdempotencyKey, unsignedPostBody, } from '../deploy/post.js';
34
38
  import { promotionPath } from '../deploy/promotion-path.js';
35
39
  import { renderResponse } from '../deploy/response.js';
36
40
  import { envProjectRefs } from '../env-projects.js';
37
41
  import { packEnvProblemLines, packEnvSecretSetCommand, packEnvSetCommand, } from '../env/pack-env-hint.js';
38
- import { describePackEnvPlan, plainSecretReason, planPackEnv, } from '../env/pack-env-plan.js';
42
+ import { describePackEnvPlan, packEnvPlanLines, packEnvPlanWarnings, plainSecretReason, planPackEnv, } from '../env/pack-env-plan.js';
39
43
  import { renderJson } from '../output.js';
40
44
  import { loadPackConfig } from '../pack-config.js';
45
+ import { progressLines } from '../progress-lines.js';
41
46
  import { PROJECT_ID_RE } from '../project-ref.js';
42
47
  import { isWait, sendWaitingOutRateLimits } from '../rate-limit-wait.js';
43
48
  import { SLUG } from '../slug.js';
44
49
  import { environmentsOf, resolveValueTarget } from '../value-target.js';
50
+ import { CLI_VERSION } from '../version-info.js';
45
51
  import { runBuild } from './build.js';
46
52
  /** Default relative path to look for a pre-built envelope. */
47
53
  export const DEFAULT_ENVELOPE_RELATIVE_PATH = '.kindgi/build/deploy-envelope.json';
@@ -160,10 +166,19 @@ export async function runDeploy(ctx) {
160
166
  if (parsed.kind === 'error')
161
167
  return parsed;
162
168
  const args = parsed.args;
163
- const banner = [];
164
- const line = (s) => {
165
- banner.push(s);
166
- };
169
+ // Deploy's lines, its inline build's among them: each to stderr as it
170
+ // comes when the CLI streams them, else kept for the result. A failure's
171
+ // error comes after them either way. `--quiet` keeps errors and warnings
172
+ // only, as `kindgi dev` does: a refusal, a secret sync that failed, and
173
+ // its warnings.
174
+ const out = progressLines(ctx.progress, ctx.globals.format === 'quiet');
175
+ const result = await deployWith(ctx, runners, args, out);
176
+ if (result.kind === 'error')
177
+ return { ...result, stderr: `${out.kept()}${result.stderr}` };
178
+ return { ...result, rendered: { ...result.rendered, stderr: out.kept() } };
179
+ }
180
+ async function deployWith(ctx, runners, args, out) {
181
+ const { line } = out;
167
182
  line('');
168
183
  line(` Environment: ${args.envName}`);
169
184
  line(` API: ${args.endpoint}`);
@@ -175,7 +190,7 @@ export async function runDeploy(ctx) {
175
190
  // Every name the pack declares in env.required needs a value or a
176
191
  // Secret Manager reference for this environment; a secret given in
177
192
  // the clear is refused. Checked before anything is built or sent.
178
- const envRefusal = checkPackEnv(args, line);
193
+ const envRefusal = checkPackEnv(args, out);
179
194
  if (envRefusal !== undefined)
180
195
  return envRefusal;
181
196
  // On a runtime that keeps its values under one env, a pack environment
@@ -221,8 +236,33 @@ export async function runDeploy(ctx) {
221
236
  const hostedEnvRefusal = refuseHostedConfigEnv(args, project.id);
222
237
  if (hostedEnvRefusal !== undefined)
223
238
  return hostedEnvRefusal;
239
+ // A pack with blocks deploys only to a runtime that publishes them
240
+ // (`deploy/pack-blocks-gate.ts`): read before a build or an upload, from
241
+ // the pack's block files when the envelope is still to be built, and
242
+ // from the envelope's index (step 3) otherwise. Not on --dry-run, which
243
+ // sends nothing.
244
+ let blocksChecked = false;
245
+ const refuseBlocks = async (brought) => {
246
+ if (args.dryRun || blocksChecked)
247
+ return undefined;
248
+ blocksChecked = true;
249
+ return packBlocksRefusal({
250
+ endpoint: args.endpoint,
251
+ fetchImpl: ctx.fetch,
252
+ ...(ctx.stopSignal !== undefined && { signal: ctx.stopSignal }),
253
+ brought,
254
+ release: CLI_VERSION,
255
+ });
256
+ };
257
+ if (!args.explicitEnvelope && !(await pathExists(args.envelopePath))) {
258
+ const read = await readPackBlocks(args.packDir, args.blocksPattern);
259
+ const found = new Set([...read.files, ...read.errors.map((e) => e.filePath)]).size;
260
+ const refused = found > 0 ? await refuseBlocks(describeFiles(args.blocksPattern, found)) : undefined;
261
+ if (refused !== undefined)
262
+ return failure(refused);
263
+ }
224
264
  // ---- 2. Ensure envelope on disk -------------------------------------
225
- const envelopeReady = await ensureEnvelopeExists(ctx, args, runners, line, project.id);
265
+ const envelopeReady = await ensureEnvelopeExists(ctx, args, runners, out, project.id);
226
266
  if (envelopeReady.kind === 'error')
227
267
  return envelopeReady;
228
268
  // ---- 3. Load + validate envelope ------------------------------------
@@ -233,34 +273,34 @@ export async function runDeploy(ctx) {
233
273
  `Regenerate with \`kindgi build --env=${args.envName}\` or point --from-envelope at a valid file.\n`);
234
274
  }
235
275
  const envelope = loaded.envelope;
276
+ const indexBlocks = Array.isArray(envelope.index.blocks) ? envelope.index.blocks.length : 0;
277
+ if (indexBlocks > 0) {
278
+ const refused = await refuseBlocks(`${indexBlocks} ${indexBlocks === 1 ? 'block' : 'blocks'} in its index`);
279
+ if (refused !== undefined)
280
+ return failure(refused);
281
+ }
236
282
  // ---- 4. Signed-envelope gate ----------------------------------------
237
283
  if (!isEnvelopeSigned(envelope)) {
238
- if (!args.dryRun) {
239
- return failure('deploy-envelope.json is unsigned. The server will refuse the deployment.\n' +
240
- 'Re-run `kindgi build` without --skip-sign, or pass --dry-run to inspect ' +
241
- 'what would be POSTed.\n');
242
- }
243
- line(' ⚠ Envelope is unsigned — --dry-run is proceeding for inspection only.');
244
- line('');
284
+ if (!args.dryRun)
285
+ return failure(UNSIGNED_REFUSAL);
286
+ out.problem(' ⚠ Envelope is unsigned — --dry-run is proceeding for inspection only.');
287
+ out.problem('');
245
288
  }
246
289
  // ---- 5. Consistency check: envelope.tenantId vs --tenant override ---
247
290
  if (args.explicitTenantId !== undefined && args.explicitTenantId !== envelope.tenantId) {
248
291
  return failure(`--tenant mismatch: envelope was signed against tenantId="${envelope.tenantId}", but --tenant was passed as "${args.explicitTenantId}". The server re-canonicalises using the token's tenantId + verifies the signature — a mismatch would fail with signature-invalid. Either drop --tenant or re-run \`kindgi build --tenant=${args.explicitTenantId}\`.\n`);
249
292
  }
250
293
  // ---- 6. Build POST body + Idempotency-Key ---------------------------
251
- let postBody;
252
- try {
253
- postBody = {
254
- ...buildPostBody(envelope),
255
- ...(project.id !== undefined && { projectId: project.id }),
256
- };
257
- }
258
- catch (err) {
259
- return failure(`Internal error building POST body: ${err.message}\n`);
260
- }
261
- const idempotencyKey = args.idempotencyKeyOverride !== undefined
262
- ? args.idempotencyKeyOverride
263
- : deriveIdempotencyKey(postBody);
294
+ //
295
+ // An unsigned envelope comes this far only under --dry-run (step 4). It
296
+ // has no POST body: the dry run shows the body less the signature's
297
+ // fields, and no derived Idempotency-Key, which hashes the signed body.
298
+ const projectField = project.id !== undefined ? { projectId: project.id } : {};
299
+ const postBody = isEnvelopeSigned(envelope)
300
+ ? { ...buildPostBody(envelope), ...projectField }
301
+ : undefined;
302
+ const idempotencyKey = args.idempotencyKeyOverride ??
303
+ (postBody !== undefined ? deriveIdempotencyKey(postBody) : undefined);
264
304
  // ---- 7. Secrets sync detection + warning ---------------------------
265
305
  //
266
306
  // `POST /v1/deployments/:id/secrets` lands after a successful
@@ -285,34 +325,12 @@ export async function runDeploy(ctx) {
285
325
  }
286
326
  // ---- 8. Dry-run ------------------------------------------------------
287
327
  if (args.dryRun) {
288
- line(' Dry run — would POST the following:');
289
- line('');
290
- line(` curl -X POST ${args.endpoint.replace(/\/+$/, '')}/v1/deployments \\`);
291
- line(' -H "Authorization: Bearer <redacted>" \\');
292
- line(' -H "Content-Type: application/json" \\');
293
- line(` -H "Idempotency-Key: ${idempotencyKey}" \\`);
294
- line(" -d @- <<'JSON'");
295
- for (const bodyLine of JSON.stringify(postBody, null, 2).split('\n')) {
296
- line(` ${bodyLine}`);
297
- }
298
- line(' JSON');
299
- line('');
300
- line(' --dry-run set. No request sent. Exiting 0.');
301
- line('');
302
- const summary = {
303
- envName: args.envName,
304
- endpoint: args.endpoint,
305
- envelopePath: args.envelopePath,
306
- idempotencyKey,
307
- dryRun: true,
308
- wouldPost: postBody,
309
- };
310
- const rendered = renderJson(summary, ctx.globals.format);
311
- return {
312
- kind: 'ok',
313
- rendered: { stdout: rendered.stdout, stderr: `${banner.join('\n')}\n` },
314
- };
328
+ const shown = postBody ?? { ...unsignedPostBody(envelope), ...projectField };
329
+ return dryRunResult(ctx, args, line, shown, idempotencyKey);
315
330
  }
331
+ // Step 4 refused an unsigned envelope without --dry-run; this tells the types.
332
+ if (postBody === undefined || idempotencyKey === undefined)
333
+ return failure(UNSIGNED_REFUSAL);
316
334
  // ---- 9. POST ---------------------------------------------------------
317
335
  //
318
336
  // A `429 rate-limit-exceeded` with `Retry-After` is waited out and the
@@ -340,15 +358,16 @@ export async function runDeploy(ctx) {
340
358
  idempotencyKey,
341
359
  promotionPath,
342
360
  });
343
- for (const l of rendered.banner)
344
- line(l);
361
+ // A refused deployment's banner is its error: said under `--quiet` too.
345
362
  if (rendered.exitCode !== 0) {
346
363
  return {
347
364
  kind: 'error',
348
- stderr: `${banner.join('\n')}\n`,
365
+ stderr: rendered.banner.map((l) => `${l}\n`).join(''),
349
366
  exitCode: rendered.exitCode,
350
367
  };
351
368
  }
369
+ for (const l of rendered.banner)
370
+ line(l);
352
371
  // ---- 11. Post-deploy secrets sync ----------------------------------
353
372
  //
354
373
  // Runs iff `--sync-secrets` is passed AND the deploy landed OK AND
@@ -361,7 +380,7 @@ export async function runDeploy(ctx) {
361
380
  const syncSummary = { performed: false };
362
381
  const deployedRecord = result.kind === 'created' || result.kind === 'replayed' ? result.record : null;
363
382
  if (args.syncSecrets && deployedRecord !== null) {
364
- const syncOutcome = await runSecretsSync(ctx, args, syncEnvName, runners, deployedRecord.deploymentId, line);
383
+ const syncOutcome = await runSecretsSync(ctx, args, syncEnvName, runners, deployedRecord.deploymentId, out);
365
384
  Object.assign(syncSummary, syncOutcome);
366
385
  }
367
386
  // ---- 12. Hosted: wait for the deployment's pack service --------------
@@ -372,7 +391,7 @@ export async function runDeploy(ctx) {
372
391
  if (args.hosted && deployedRecord !== null && deployedRecord.endpoint !== undefined) {
373
392
  const waited = await waitForPackService(ctx, args, runners, deployedRecord, line, project.id);
374
393
  if (waited.kind === 'error') {
375
- return { kind: 'error', stderr: `${banner.join('\n')}\n${waited.message}`, exitCode: 1 };
394
+ return { kind: 'error', stderr: waited.message, exitCode: 1 };
376
395
  }
377
396
  packService = waited.endpoint;
378
397
  }
@@ -383,7 +402,7 @@ export async function runDeploy(ctx) {
383
402
  }, ctx.globals.format);
384
403
  return {
385
404
  kind: 'ok',
386
- rendered: { stdout: jsonOut.stdout, stderr: `${banner.join('\n')}\n` },
405
+ rendered: { stdout: jsonOut.stdout, stderr: '' },
387
406
  };
388
407
  }
389
408
  /**
@@ -415,7 +434,8 @@ function deployRefusal(result) {
415
434
  */
416
435
  async function runSecretsSync(ctx, args,
417
436
  /** The env the values go under: `--env`, or the one a runtime that keeps its values under one serves. */
418
- envName, runners, deploymentId, line) {
437
+ envName, runners, deploymentId, out) {
438
+ const { line, problem } = out;
419
439
  const file = await detectSecretsFile(args, '');
420
440
  if (file === null || file.entries.length === 0) {
421
441
  line(' --sync-secrets set, but no `.env.<envName>` entries to sync. Skipping.');
@@ -428,10 +448,10 @@ envName, runners, deploymentId, line) {
428
448
  // impossible to miss.
429
449
  const shaped = file.entries.filter((e) => plainSecretReason(e.name, e.value) !== undefined);
430
450
  if (shaped.length > 0) {
431
- line(` ! secret-shaped keys detected in .env.${args.envName}: ${shaped.map((e) => e.name).join(', ')}`);
432
- line(' Keep secrets out of .env files: store them with `kindgi secrets`.');
433
- line(` Consider: kindgi secrets set --env=${args.envName} <name> <value>`);
434
- line('');
451
+ problem(` ! secret-shaped keys detected in .env.${args.envName}: ${shaped.map((e) => e.name).join(', ')}`);
452
+ problem(' Keep secrets out of .env files: store them with `kindgi secrets`.');
453
+ problem(` Consider: kindgi secrets set --env=${args.envName} <name> <value>`);
454
+ problem('');
435
455
  }
436
456
  const syncBody = {
437
457
  envName,
@@ -466,22 +486,27 @@ envName, runners, deploymentId, line) {
466
486
  };
467
487
  }
468
488
  if (result.kind === 'wire-error') {
469
- line(` ✗ ${result.status} ${result.error.code}: ${result.error.message}`);
470
- line(' The deployment landed OK; only the secret sync failed. Retry with');
471
- line(' `kindgi deploy --sync-secrets` (idempotent).');
472
- line('');
489
+ // Errors: said under `--quiet` too, though the exit code stays 0.
490
+ problem(` ✗ ${result.status} ${result.error.code}: ${result.error.message}`);
491
+ syncFailedHint(problem);
473
492
  return { performed: false, error: { code: result.error.code, message: result.error.message } };
474
493
  }
475
- line(` ✗ transport error: ${result.message}`);
476
- line('');
494
+ problem(` ✗ transport error: ${result.message}`);
495
+ syncFailedHint(problem);
477
496
  return { performed: false, error: { code: 'transport-error', message: result.message } };
478
497
  }
498
+ /** After a secret sync that failed: the deployment is in place; how to sync again. */
499
+ function syncFailedHint(problem) {
500
+ problem(' The deployment landed OK; only the secret sync failed. Retry with');
501
+ problem(' `kindgi deploy --sync-secrets` (idempotent).');
502
+ problem('');
503
+ }
479
504
  /**
480
505
  * The deploy preflight for the pack service's env (R4): the plan's lines
481
506
  * when the pack declares any, and the refusal when a required name has no
482
507
  * value (unless `--allow-missing-env`) or a secret is given in the clear.
483
508
  */
484
- function checkPackEnv(args, line) {
509
+ function checkPackEnv(args, out) {
485
510
  // A hosted pack service gets the values set in the workspace, not these:
486
511
  // `refuseHostedConfigEnv`, once the project is known.
487
512
  if (args.hosted)
@@ -490,18 +515,33 @@ function checkPackEnv(args, line) {
490
515
  if (plan.entries.length === 0 && plan.problems.length === 0 && plan.warnings.length === 0) {
491
516
  return undefined;
492
517
  }
493
- for (const l of describePackEnvPlan(plan))
494
- line(l);
495
- line('');
518
+ const refusal = packEnvRefusal(args, plan);
519
+ if (refusal !== undefined) {
520
+ // A refusal's reason is the plan: said under `--quiet` too.
521
+ for (const l of describePackEnvPlan(plan))
522
+ out.problem(l);
523
+ out.problem('');
524
+ return failure(refusal);
525
+ }
526
+ // A plan that deploys: under `--quiet`, its warnings alone.
527
+ for (const l of packEnvPlanLines(plan))
528
+ out.line(l);
529
+ for (const l of packEnvPlanWarnings(plan))
530
+ out.problem(l);
531
+ (plan.warnings.length > 0 ? out.problem : out.line)('');
532
+ if (plan.missing.length > 0) {
533
+ out.problem(` ⚠ --allow-missing-env: deploying without ${plan.missing.join(', ')}`);
534
+ out.problem('');
535
+ }
536
+ return undefined;
537
+ }
538
+ /** Why the pack service's env refuses the deploy (`checkPackEnv`), when it does. */
539
+ function packEnvRefusal(args, plan) {
496
540
  if (plan.problems.length > 0) {
497
- return failure(`kindgi deploy: the pack service's env for ${args.envName} gives a secret in the clear or is malformed (above). Fix environments.${args.envName}.env in kindgi.config and deploy again.\n`);
541
+ return `kindgi deploy: the pack service's env for ${args.envName} gives a secret in the clear or is malformed (above). Fix environments.${args.envName}.env in kindgi.config and deploy again.\n`;
498
542
  }
499
543
  if (plan.missing.length > 0 && !args.allowMissingEnv) {
500
- return failure(`kindgi deploy: ${plan.missing.join(', ')} ${plan.missing.length === 1 ? 'is' : 'are'} required by the pack and ${plan.missing.length === 1 ? 'has' : 'have'} no value in environments.${args.envName}.env, so the pack service wouldn't be ready. Add ${plan.missing.length === 1 ? 'it' : 'them'}, or deploy anyway with --allow-missing-env.\n`);
501
- }
502
- if (plan.missing.length > 0) {
503
- line(` ⚠ --allow-missing-env: deploying without ${plan.missing.join(', ')}`);
504
- line('');
544
+ return `kindgi deploy: ${plan.missing.join(', ')} ${plan.missing.length === 1 ? 'is' : 'are'} required by the pack and ${plan.missing.length === 1 ? 'has' : 'have'} no value in environments.${args.envName}.env, so the pack service wouldn't be ready. Add ${plan.missing.length === 1 ? 'it' : 'them'}, or deploy anyway with --allow-missing-env.\n`;
505
545
  }
506
546
  return undefined;
507
547
  }
@@ -529,7 +569,8 @@ function refuseHostedConfigEnv(args, projectId) {
529
569
  // ---------------------------------------------------------------------
530
570
  // Envelope existence — either read from disk or inline-build
531
571
  // ---------------------------------------------------------------------
532
- async function ensureEnvelopeExists(ctx, args, runners, line, projectId) {
572
+ async function ensureEnvelopeExists(ctx, args, runners, out, projectId) {
573
+ const { line } = out;
533
574
  const exists = await pathExists(args.envelopePath);
534
575
  if (exists)
535
576
  return { kind: 'ok' };
@@ -538,8 +579,8 @@ async function ensureEnvelopeExists(ctx, args, runners, line, projectId) {
538
579
  }
539
580
  // Auto-detect path is missing → run build inline.
540
581
  line(` Envelope missing — running \`kindgi build --env=${args.envName}\` inline...`);
541
- line('');
542
582
  if (runners.runBuild !== undefined) {
583
+ line('');
543
584
  const buildArgv = buildInlineArgv(ctx, args, projectId);
544
585
  const outcome = await runners.runBuild({
545
586
  buildArgv,
@@ -569,13 +610,9 @@ async function ensureEnvelopeExists(ctx, args, runners, line, projectId) {
569
610
  // No inline runner available — invoke the same-package `runBuild`
570
611
  // directly. This is the production path when
571
612
  // `deployRunners.runBuild` is omitted (see `deploy/defaults.ts`).
572
- const built = await runInlineBuild(ctx, args, projectId);
613
+ const built = await runInlineBuild(ctx, args, projectId, out);
573
614
  if (built.kind === 'error')
574
615
  return built;
575
- if (built.banner.length > 0) {
576
- line(built.banner);
577
- line('');
578
- }
579
616
  return { kind: 'ok' };
580
617
  }
581
618
  /**
@@ -583,14 +620,17 @@ async function ensureEnvelopeExists(ctx, args, runners, line, projectId) {
583
620
  * `CommandContext` (buildRunners, buildConfigLoader, env, cwd, etc.)
584
621
  * but with an argument set derived from the deploy invocation. We
585
622
  * clone the context with `options` replaced so the build command sees
586
- * only build-relevant flags.
623
+ * only build-relevant flags. Its lines go out with deploy's (`out`), in
624
+ * order.
587
625
  */
588
- async function runInlineBuild(ctx, args, projectId) {
626
+ async function runInlineBuild(ctx, args, projectId, out) {
589
627
  const buildOptions = buildInlineOptions(ctx, args, projectId);
590
628
  // A hosted build runs at the API this deploy goes to: the build resolves
591
629
  // the same address, with the same key, from the same config.
592
630
  const buildCtx = { ...ctx, options: buildOptions };
593
- const result = await runBuild(buildCtx);
631
+ // Through deploy's own `out`, `--quiet` and all. None are kept here:
632
+ // deploy's `out` streams or keeps them.
633
+ const result = await runBuild(buildCtx, { ...out, kept: () => '' });
594
634
  if (result.kind === 'error') {
595
635
  return {
596
636
  kind: 'error',
@@ -607,10 +647,7 @@ async function runInlineBuild(ctx, args, projectId) {
607
647
  exitCode: 1,
608
648
  };
609
649
  }
610
- return {
611
- kind: 'ok',
612
- banner: result.rendered.stderr.trim(),
613
- };
650
+ return { kind: 'ok' };
614
651
  }
615
652
  function buildInlineOptions(ctx, args, projectId) {
616
653
  const opts = {};
@@ -1023,6 +1060,7 @@ async function resolveDeployArgs(ctx) {
1023
1060
  environments: environmentsOf(cfg),
1024
1061
  packEnv: packEnv.plan,
1025
1062
  allowMissingEnv: ctx.options['allow-missing-env'] === true,
1063
+ blocksPattern: resolveDiscovery(cfg.discovery).blocks,
1026
1064
  },
1027
1065
  };
1028
1066
  }
@@ -1088,9 +1126,52 @@ async function pathExists(path) {
1088
1126
  return false;
1089
1127
  }
1090
1128
  }
1129
+ /**
1130
+ * `--dry-run`'s answer: the curl-equivalent and body as progress, the
1131
+ * summary on stdout. An unsigned envelope's body lacks the signature's
1132
+ * fields, and has no derived Idempotency-Key, which hashes the signed body.
1133
+ */
1134
+ function dryRunResult(ctx, args, line, body, idempotencyKey) {
1135
+ const missing = idempotencyKey === undefined
1136
+ ? 'signerKeyId, signerPublicKey and signature a signed build adds, and the Idempotency-Key, which hashes that body'
1137
+ : 'signerKeyId, signerPublicKey and signature a signed build adds';
1138
+ line('signature' in body
1139
+ ? ' Dry run — would POST the following:'
1140
+ : ` Dry run — would POST the following, plus the ${missing}:`);
1141
+ line('');
1142
+ line(` curl -X POST ${args.endpoint.replace(/\/+$/, '')}/v1/deployments \\`);
1143
+ line(' -H "Authorization: Bearer <redacted>" \\');
1144
+ line(' -H "Content-Type: application/json" \\');
1145
+ if (idempotencyKey !== undefined)
1146
+ line(` -H "Idempotency-Key: ${idempotencyKey}" \\`);
1147
+ line(" -d @- <<'JSON'");
1148
+ for (const bodyLine of JSON.stringify(body, null, 2).split('\n')) {
1149
+ line(` ${bodyLine}`);
1150
+ }
1151
+ line(' JSON');
1152
+ line('');
1153
+ line(' --dry-run set. No request sent. Exiting 0.');
1154
+ line('');
1155
+ const summary = {
1156
+ envName: args.envName,
1157
+ endpoint: args.endpoint,
1158
+ envelopePath: args.envelopePath,
1159
+ ...(idempotencyKey !== undefined && { idempotencyKey }),
1160
+ dryRun: true,
1161
+ wouldPost: body,
1162
+ };
1163
+ const rendered = renderJson(summary, ctx.globals.format);
1164
+ return {
1165
+ kind: 'ok',
1166
+ rendered: { stdout: rendered.stdout, stderr: '' },
1167
+ };
1168
+ }
1091
1169
  function failure(stderr) {
1092
1170
  return { kind: 'error', stderr, exitCode: 1 };
1093
1171
  }
1172
+ const UNSIGNED_REFUSAL = 'deploy-envelope.json is unsigned. The server will refuse the deployment.\n' +
1173
+ 'Re-run `kindgi build` without --skip-sign, or pass --dry-run to inspect ' +
1174
+ 'what would be POSTed.\n';
1094
1175
  function countIndexPrimitives(index) {
1095
1176
  const asArrLen = (v) => (Array.isArray(v) ? v.length : 0);
1096
1177
  return {