@zaip-ai/cli 1.3.8 → 1.4.2

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 (317) hide show
  1. package/README.md +58 -3
  2. package/dist/commands/init.d.ts +1 -0
  3. package/dist/commands/init.d.ts.map +1 -1
  4. package/dist/commands/init.js +17 -6
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -1
  10. package/dist/services/adapters.js +4 -4
  11. package/dist/services/adapters.js.map +1 -1
  12. package/dist/services/codex-config-template.d.ts +2 -2
  13. package/dist/services/codex-config-template.d.ts.map +1 -1
  14. package/dist/services/codex-config-template.js +3 -3
  15. package/dist/services/codex-config-template.js.map +1 -1
  16. package/dist/services/codex-rules.d.ts +1 -1
  17. package/dist/services/codex-rules.d.ts.map +1 -1
  18. package/dist/services/codex-rules.js +9 -24
  19. package/dist/services/codex-rules.js.map +1 -1
  20. package/dist/services/delivery-git-preflight.d.ts +23 -0
  21. package/dist/services/delivery-git-preflight.d.ts.map +1 -0
  22. package/dist/services/delivery-git-preflight.js +69 -0
  23. package/dist/services/delivery-git-preflight.js.map +1 -0
  24. package/dist/services/doctor.d.ts.map +1 -1
  25. package/dist/services/doctor.js +13 -1
  26. package/dist/services/doctor.js.map +1 -1
  27. package/dist/services/install-agents-template.d.ts.map +1 -1
  28. package/dist/services/install-agents-template.js +22 -28
  29. package/dist/services/install-agents-template.js.map +1 -1
  30. package/dist/services/install-profile.d.ts +8 -0
  31. package/dist/services/install-profile.d.ts.map +1 -0
  32. package/dist/services/install-profile.js +56 -0
  33. package/dist/services/install-profile.js.map +1 -0
  34. package/dist/services/logger.d.ts.map +1 -1
  35. package/dist/services/logger.js +6 -5
  36. package/dist/services/logger.js.map +1 -1
  37. package/dist/services/stack-git.d.ts +9 -0
  38. package/dist/services/stack-git.d.ts.map +1 -0
  39. package/dist/services/stack-git.js +188 -0
  40. package/dist/services/stack-git.js.map +1 -0
  41. package/dist/services/stack-plan.d.ts +3 -1
  42. package/dist/services/stack-plan.d.ts.map +1 -1
  43. package/dist/services/stack-plan.js +15 -1
  44. package/dist/services/stack-plan.js.map +1 -1
  45. package/dist/services/stack-terraform.d.ts +13 -0
  46. package/dist/services/stack-terraform.d.ts.map +1 -0
  47. package/dist/services/stack-terraform.js +274 -0
  48. package/dist/services/stack-terraform.js.map +1 -0
  49. package/dist/services/template-manifest.d.ts.map +1 -1
  50. package/dist/services/template-manifest.js +14 -1
  51. package/dist/services/template-manifest.js.map +1 -1
  52. package/dist/types.d.ts +1 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/package.json +1 -1
  55. package/templates/.agents/.env.example +34 -0
  56. package/templates/{README.md → .agents/README.md} +124 -60
  57. package/templates/.agents/config/agents/catalog.yaml +23 -23
  58. package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -0
  59. package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -0
  60. package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +5 -4
  61. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -0
  62. package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -0
  63. package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +10 -7
  64. package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -0
  65. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -0
  66. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -0
  67. package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +5 -4
  68. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -0
  69. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -0
  70. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -0
  71. package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -0
  72. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +5 -4
  73. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -0
  74. package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -0
  75. package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -0
  76. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -0
  77. package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -0
  78. package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -0
  79. package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +5 -4
  80. package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -0
  81. package/templates/.agents/config/pricing/models.json +25 -1
  82. package/templates/.agents/config/project.yaml +2 -0
  83. package/templates/.agents/dashboard/.zaip-managed.json +208 -88
  84. package/templates/.agents/dashboard/DATA-DICTIONARY.md +1 -1
  85. package/templates/.agents/dashboard/README.md +58 -19
  86. package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DwVZOmMV.js → CostCalculationGuidePage-snUCQYTC.js} +1 -1
  87. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-VcLx9iOO.js → DashboardHelpDialog-oZVlf-l5.js} +72 -8
  88. package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CyjMXkm8.js → PricingSettingsDialog-BPtVUGgs.js} +1 -1
  89. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +3 -0
  90. package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-DFZwIXSC.js → TraceabilityWorkspace-BYjVOHI_.js} +1 -1
  91. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +68 -0
  92. package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DXBOtWNI.js → icons-vendor-TPUT2IUt.js} +1 -1
  93. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cmlx8OYH.css +1 -0
  94. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-ZJFXmK7m.js +2 -0
  95. package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-DaNXQPyk.js → react-vendor-Ct48XHGL.js} +1 -1
  96. package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-I4AKqVDX.js → traceability-BDe4_Ubl.js} +1 -1
  97. package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
  98. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +73 -67
  99. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +35 -7
  100. package/templates/.agents/dashboard/apps/frontend/src/AppWorkBoard.ts +55 -0
  101. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +11 -0
  102. package/templates/.agents/dashboard/apps/frontend/src/app-loading-boundary.css +98 -0
  103. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +5 -5
  104. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-reconciliation.ts +33 -0
  105. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +75 -0
  106. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -8
  107. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +14 -2
  108. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +35 -0
  109. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +78 -2
  110. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +28 -0
  111. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +8 -5
  112. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +180 -1
  113. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +7 -4
  114. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +13 -7
  115. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +14 -0
  116. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +211 -0
  117. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +152 -157
  118. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +155 -142
  119. package/templates/.agents/dashboard/modules/cost-monitor/src/react/InvocationManifestQuery.test.ts +145 -0
  120. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +7 -5
  121. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +4 -1
  122. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +4 -1
  123. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +4 -1
  124. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +4 -4
  125. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +79 -1
  126. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +105 -11
  127. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +482 -332
  128. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +430 -285
  129. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +14 -2
  130. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +6 -26
  131. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +1 -1
  132. package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-persistent-launch.mjs +268 -0
  133. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +482 -332
  134. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +90 -1
  135. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +112 -22
  136. package/templates/.agents/dashboard/packages/local-runtime/src/server-agent-assets.ts +39 -0
  137. package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +33 -0
  138. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +148 -11
  139. package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-result.test.ts +68 -0
  140. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +19 -0
  141. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +39 -43
  142. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.test.ts +42 -0
  143. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.ts +26 -0
  144. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +34 -0
  145. package/templates/.agents/dashboard/packages/local-runtime/src/server-startup.ts +30 -0
  146. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +89 -0
  147. package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +88 -0
  148. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +68 -7
  149. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +11 -5
  150. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +129 -99
  151. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.test.ts +111 -0
  152. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.ts +140 -0
  153. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +127 -4
  154. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +145 -5
  155. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +156 -23
  156. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +18 -9
  157. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-projection.ts +52 -0
  158. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +35 -13
  159. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +56 -0
  160. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.test.ts +29 -0
  161. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.ts +136 -0
  162. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +251 -0
  163. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +22 -7
  164. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +1 -1
  165. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical-parsing.ts +42 -0
  166. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +793 -0
  167. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-duration.test.ts +270 -0
  168. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +3 -2
  169. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +18 -4
  170. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +87 -0
  171. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +105 -16
  172. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +131 -59
  173. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1000 -1115
  174. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +13 -92
  175. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-claims.test.mjs +79 -0
  176. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +27 -0
  177. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.mjs +6 -6
  178. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-prerequisites.mjs +1 -1
  179. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +2 -10
  180. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-runtime-selection.mjs +36 -0
  181. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-runtime-selection.test.mjs +63 -0
  182. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-server.mjs +142 -0
  183. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +262 -267
  184. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +18 -29
  185. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +6 -0
  186. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  187. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  188. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +47 -0
  189. package/templates/.agents/requirements/comparative-audit.md +1 -1
  190. package/templates/.agents/requirements/context-engine.md +1 -1
  191. package/templates/.agents/requirements/cost-observability.md +1 -1
  192. package/templates/.agents/requirements/dashboard-launch.md +2 -2
  193. package/templates/.agents/requirements/data-export.md +1 -1
  194. package/templates/.agents/requirements/design-system.md +1 -1
  195. package/templates/.agents/requirements/execution-engine.md +1 -1
  196. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  197. package/templates/.agents/requirements/model-orchestration.md +1 -1
  198. package/templates/.agents/requirements/public-distribution.md +1 -1
  199. package/templates/.agents/requirements/software-architecture.md +1 -1
  200. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  201. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  202. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  203. package/templates/.agents/rules/autonomy-decision.md +1 -1
  204. package/templates/.agents/rules/cloud-hostinger-autonomy.md +21 -0
  205. package/templates/.agents/rules/core.md +5 -4
  206. package/templates/.agents/rules/local-sqlite-storage.md +18 -0
  207. package/templates/.agents/rules/meta-mcp.md +21 -0
  208. package/templates/.agents/rules/workflow.md +1 -0
  209. package/templates/.agents/runtime/bin/zaip.mjs +305 -137
  210. package/templates/.agents/runtime/checksums.sha256 +2 -2
  211. package/templates/.agents/runtime/provenance.json +2 -2
  212. package/templates/.agents/skills/zaip-skill-api-to-mcp/SKILL.md +4 -0
  213. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +25 -9
  214. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +2 -2
  215. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +2 -2
  216. package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +15 -0
  217. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +13 -5
  218. package/templates/.agents/skills/zaip-skill-data-analyst/SKILL.md +10 -5
  219. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +5 -4
  220. package/templates/.agents/skills/zaip-skill-frontend-launcher/SKILL.md +4 -3
  221. package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +5 -3
  222. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -5
  223. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +78 -13
  224. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +59 -0
  225. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/yaml-parser.mjs +157 -0
  226. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +11 -6
  227. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +17 -0
  228. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +7 -0
  229. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-cloud-inputs.example.json +41 -0
  230. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-runner.md +84 -0
  231. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/operational-contract.md +19 -0
  232. package/templates/.agents/skills/zaip-skill-local-credentials/SKILL.md +43 -0
  233. package/templates/.agents/skills/zaip-skill-local-credentials/agents/openai.yaml +6 -0
  234. package/templates/.agents/skills/zaip-skill-local-credentials/references/dotenv-resolution.md +47 -0
  235. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +8 -3
  236. package/templates/.agents/skills/zaip-skill-meta-ads/SKILL.md +16 -0
  237. package/templates/.agents/skills/zaip-skill-meta-ads/agents/openai.yaml +4 -0
  238. package/templates/.agents/skills/zaip-skill-meta-ads/references/setup.md +3 -0
  239. package/templates/.agents/skills/zaip-skill-meta-ads-setup/SKILL.md +24 -0
  240. package/templates/.agents/skills/zaip-skill-meta-ads-setup/agents/openai.yaml +4 -0
  241. package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/diagnostics.md +13 -0
  242. package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/official-sources.md +10 -0
  243. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/SKILL.md +12 -0
  244. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/agents/openai.yaml +4 -0
  245. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/LICENSE +21 -0
  246. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/upstream.md +77 -0
  247. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/SKILL.md +12 -0
  248. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/agents/openai.yaml +4 -0
  249. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/LICENSE +21 -0
  250. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/upstream.md +126 -0
  251. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/SKILL.md +12 -0
  252. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/agents/openai.yaml +4 -0
  253. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/LICENSE +21 -0
  254. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/upstream.md +67 -0
  255. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/SKILL.md +12 -0
  256. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/agents/openai.yaml +4 -0
  257. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/LICENSE +21 -0
  258. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/upstream.md +69 -0
  259. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/SKILL.md +12 -0
  260. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/agents/openai.yaml +4 -0
  261. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/LICENSE +21 -0
  262. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/upstream.md +79 -0
  263. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/SKILL.md +14 -0
  264. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/agents/openai.yaml +4 -0
  265. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/LICENSE +21 -0
  266. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/upstream.md +144 -0
  267. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/SKILL.md +12 -0
  268. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/agents/openai.yaml +4 -0
  269. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/LICENSE +21 -0
  270. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/upstream.md +83 -0
  271. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/SKILL.md +10 -0
  272. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/agents/openai.yaml +4 -0
  273. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/LICENSE +21 -0
  274. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/setup.md +11 -0
  275. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/upstream.md +55 -0
  276. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/SKILL.md +12 -0
  277. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/agents/openai.yaml +4 -0
  278. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/LICENSE +21 -0
  279. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/upstream.md +56 -0
  280. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +12 -7
  281. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +11 -4
  282. package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +6 -4
  283. package/templates/.agents/skills/zaip-skill-tool-setup/references/codex-config.md +4 -2
  284. package/templates/.agents/skills/zaip-skill-tool-setup/references/secrets.md +1 -0
  285. package/templates/.agents/tools/catalog.yaml +6 -0
  286. package/templates/.agents/tools/cloud-runner-dns.mjs +28 -0
  287. package/templates/.agents/tools/cloud-runner-terraform.mjs +212 -0
  288. package/templates/.agents/tools/cloud-runner.integration.test.mjs +239 -0
  289. package/templates/.agents/tools/cloud-runner.mjs +786 -0
  290. package/templates/.agents/tools/cloud-runner.test.mjs +534 -0
  291. package/templates/.agents/tools/cloud-terraform-plan-policy.mjs +262 -0
  292. package/templates/.agents/tools/mcp/development/meta-devtools/README.md +14 -0
  293. package/templates/.agents/tools/mcp/development/meta-devtools/manifest.yaml +28 -0
  294. package/templates/.agents/tools/mcp/infra/cloudflare/manifest.yaml +2 -3
  295. package/templates/.agents/tools/mcp/infra/hostinger/manifest.yaml +1 -3
  296. package/templates/.agents/tools/mcp/marketing/meta-ads/README.md +15 -13
  297. package/templates/.agents/tools/mcp/marketing/meta-ads/manifest.yaml +15 -10
  298. package/templates/.agents/tools/profiles/development.yaml +3 -0
  299. package/templates/infra/terraform/.terraform.lock.hcl +42 -0
  300. package/templates/infra/terraform/README.md +31 -0
  301. package/templates/infra/terraform/backend.tf.json +13 -0
  302. package/templates/infra/terraform/deployment-inputs.example.yaml +22 -0
  303. package/templates/infra/terraform/fixtures/approved-targets.json +32 -0
  304. package/templates/infra/terraform/fixtures/plan-approved.json +67 -0
  305. package/templates/infra/terraform/main.tf +77 -0
  306. package/templates/infra/terraform/outputs.tf +20 -0
  307. package/templates/infra/terraform/terraform.tfvars.example +26 -0
  308. package/templates/infra/terraform/variables.tf +91 -0
  309. package/templates/infra/terraform/versions.tf +18 -0
  310. package/templates/scripts/validate-cloud-hostinger-contract.mjs +89 -0
  311. package/templates/scripts/validate-cloud-terraform-plan.mjs +1 -0
  312. package/templates/template-manifest.json +607 -167
  313. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BwnJpl02.js +0 -3
  314. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-C09KmlSw.js +0 -68
  315. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dyo_wpL4.js +0 -2
  316. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-hPPfVGQv.css +0 -1
  317. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-stale-seed.ts +0 -50
@@ -0,0 +1,28 @@
1
+ const fields = ["name", "type", "content", "proxied", "ttl", "comment"];
2
+
3
+ export function dnsInventory(scope) {
4
+ return new Set(
5
+ Array.isArray(scope.dns_records) ? scope.dns_records : Object.keys(scope.dns_records ?? {}),
6
+ );
7
+ }
8
+
9
+ export function dnsBody(record, fail) {
10
+ if (!record || typeof record !== "object") fail("invalid_contract");
11
+ const body = {};
12
+ for (const key of fields) if (record[key] !== undefined) body[key] = record[key];
13
+ if (
14
+ typeof body.name !== "string" ||
15
+ typeof body.type !== "string" ||
16
+ typeof body.content !== "string"
17
+ )
18
+ fail("invalid_contract");
19
+ return body;
20
+ }
21
+
22
+ export function sameDns(actual, expected) {
23
+ return fields.every((key) => expected[key] === undefined || actual[key] === expected[key]);
24
+ }
25
+
26
+ export function authHeaders(token) {
27
+ return { Authorization: `Bearer ${token}`, "Content-Type": "application/json" };
28
+ }
@@ -0,0 +1,212 @@
1
+ /** Executes the contract-bound Terraform operations used by cloud-runner. */
2
+ export async function runTerraform(args, contract, credentials, toolkit) {
3
+ const { deps, root, dirname, exact, fail, insideRoot, nonempty, requireString, result, sha256 } =
4
+ toolkit;
5
+ const scope = contract.terraform;
6
+ if (
7
+ !scope ||
8
+ !new Set(["terraform:plan", "terraform:apply", "terraform:import"]).has(args.operation) ||
9
+ !scope.allowed_operations?.includes(args.operation)
10
+ )
11
+ fail("operation_not_allowed");
12
+ exact(
13
+ args,
14
+ args.operation === "terraform:plan"
15
+ ? ["contract", "operation", "credentials-source", "terraform-directory"]
16
+ : args.operation === "terraform:apply"
17
+ ? [
18
+ "contract",
19
+ "operation",
20
+ "credentials-source",
21
+ "plan-path",
22
+ "plan-sha256",
23
+ "policy-result-sha256",
24
+ ]
25
+ : ["contract", "operation", "credentials-source", "resource-address", "resource-id"],
26
+ );
27
+ if (
28
+ !credentials.cloudflare ||
29
+ !credentials.hostinger ||
30
+ scope.working_directory !== "infra/terraform"
31
+ )
32
+ fail("credential_unavailable");
33
+ const cwd = insideRoot(scope.working_directory);
34
+ const env = terraformEnvironment(credentials.values, { nonempty, fail });
35
+ const binary = insideRoot(requireString(scope, "binary_path"));
36
+ if (sha256(await deps.readFile(binary)) !== scope.binary_sha256)
37
+ fail("terraform_binary_mismatch");
38
+ await toolkit.preflight(contract, credentials, deps);
39
+ const plan = toolkit.validPlan(scope.plan, contract.cloudflare.account_id);
40
+ await toolkit.verifyPolicyTargets(contract, deps);
41
+ await toolkit.verifyBackendSource(plan, cwd, deps);
42
+ const execOptions = { cwd, env, timeout: 900_000, maxOutput: 32_000_000 };
43
+ if (
44
+ (await deps.exec(binary, ["init", "-input=false", "-lockfile=readonly"], execOptions)).code !==
45
+ 0
46
+ )
47
+ fail("terraform_init_failed");
48
+ await toolkit.verifyBackend(plan, cwd, deps);
49
+ if (args.operation === "terraform:plan")
50
+ return planTerraform(args, contract, plan, binary, execOptions, {
51
+ deps,
52
+ root,
53
+ dirname,
54
+ fail,
55
+ insideRoot,
56
+ result,
57
+ sha256,
58
+ receipt: toolkit.receipt,
59
+ });
60
+ if (args.operation === "terraform:apply")
61
+ return applyTerraform(args, contract, credentials, plan, binary, cwd, execOptions, toolkit);
62
+ exact(args, ["contract", "operation", "credentials-source", "resource-address", "resource-id"]);
63
+ if (scope.import_targets?.[args.resourceAddress] !== args.resourceId) fail("target_mismatch");
64
+ if (
65
+ (
66
+ await deps.exec(
67
+ binary,
68
+ ["import", "-input=false", args.resourceAddress, args.resourceId],
69
+ execOptions,
70
+ )
71
+ ).code !== 0
72
+ )
73
+ fail("remote_result_requires_reconciliation");
74
+ return result(args.operation, "terraform", [args.resourceAddress, args.resourceId]);
75
+ }
76
+
77
+ async function planTerraform(args, contract, plan, binary, execOptions, toolkit) {
78
+ const { deps, root, dirname, fail, insideRoot, result, sha256, receipt } = toolkit;
79
+ if (args.terraformDirectory !== "infra/terraform") fail("target_mismatch");
80
+ const planPath = insideRoot(plan.path),
81
+ policyPath = insideRoot(plan.policy_json_path);
82
+ await deps.mkdir(dirname(planPath), { recursive: true });
83
+ for (const argv of [
84
+ ["fmt", "-check"],
85
+ ["validate"],
86
+ ["plan", "-input=false", "-out", planPath],
87
+ ["show", "-json", planPath],
88
+ ]) {
89
+ const response = await deps.exec(binary, argv, execOptions);
90
+ if (response.code !== 0) fail("terraform_failed");
91
+ if (argv[0] === "show") await deps.writeFile(policyPath, response.stdout ?? "");
92
+ }
93
+ const policy = await policyCheck(plan, root, deps);
94
+ if (policy.code !== 0) fail("terraform_policy_failed");
95
+ return {
96
+ ...result(args.operation, "terraform", plan.targets ?? []),
97
+ plan_sha256: sha256(await deps.readFile(planPath)),
98
+ policy_result_sha256: await receipt(contract, policy.stdout ?? "", deps),
99
+ };
100
+ }
101
+
102
+ async function applyTerraform(
103
+ args,
104
+ contract,
105
+ credentials,
106
+ plan,
107
+ binary,
108
+ cwd,
109
+ execOptions,
110
+ toolkit,
111
+ ) {
112
+ const {
113
+ deps,
114
+ root,
115
+ fail,
116
+ exact,
117
+ insideRoot,
118
+ result,
119
+ sha256,
120
+ receipt,
121
+ verifyBackend,
122
+ observeState,
123
+ } = toolkit;
124
+ exact(args, [
125
+ "contract",
126
+ "operation",
127
+ "credentials-source",
128
+ "plan-path",
129
+ "plan-sha256",
130
+ "policy-result-sha256",
131
+ ]);
132
+ const planPath = insideRoot(plan.path);
133
+ if (
134
+ args.planPath !== plan.path ||
135
+ args.planSha256 !== plan.sha256 ||
136
+ args.policyResultSha256 !== plan.policy_result_sha256 ||
137
+ sha256(await deps.readFile(planPath)) !== args.planSha256
138
+ )
139
+ fail("target_mismatch");
140
+ const show = await deps.exec(binary, ["show", "-json", planPath], execOptions);
141
+ if (show.code !== 0) fail("terraform_failed");
142
+ await deps.writeFile(insideRoot(plan.policy_json_path), show.stdout ?? "");
143
+ const policy = await policyCheck(plan, root, deps);
144
+ if (
145
+ policy.code !== 0 ||
146
+ (await receipt(contract, policy.stdout ?? "", deps)) !== args.policyResultSha256
147
+ )
148
+ fail("terraform_policy_failed");
149
+ if ((await deps.exec(binary, ["apply", "-input=false", planPath], execOptions)).code !== 0)
150
+ fail("remote_result_requires_reconciliation");
151
+ await verifyBackend(plan, cwd, deps);
152
+ const state = await deps.exec(binary, ["show", "-json"], execOptions);
153
+ if (state.code !== 0) fail("read_after_write_failed");
154
+ const observed = await observeState(JSON.parse(state.stdout), contract, credentials, deps);
155
+ if (observed.bindings.length) {
156
+ for (const binding of observed.bindings)
157
+ Object.assign(contract.hostinger.vps[binding.role], {
158
+ id: binding.id,
159
+ ssh_host: binding.ipv4,
160
+ });
161
+ delete contract.terraform.plan.sha256;
162
+ delete contract.terraform.plan.policy_result_sha256;
163
+ await deps.writeFile(insideRoot(args.contract), `${JSON.stringify(contract, null, 2)}\n`, {
164
+ mode: 0o600,
165
+ });
166
+ }
167
+ return {
168
+ ...result(args.operation, "terraform", observed.targets),
169
+ bindings: observed.bindings,
170
+ validation: "provider-read-after-write; application health requires separate checks",
171
+ plan_sha256: args.planSha256,
172
+ policy_result_sha256: args.policyResultSha256,
173
+ };
174
+ }
175
+
176
+ function terraformEnvironment(values, { nonempty, fail }) {
177
+ if (!nonempty(values.AWS_ACCESS_KEY_ID) || !nonempty(values.AWS_SECRET_ACCESS_KEY))
178
+ fail("backend_credential_unavailable");
179
+ const allowed = [
180
+ "CLOUDFLARE_API_TOKEN",
181
+ "HOSTINGER_API_TOKEN",
182
+ "TF_VAR_cloudflare_account_id",
183
+ "TF_VAR_cloudflare_zone_id",
184
+ "TF_VAR_cloudflare_zone_name",
185
+ "TF_VAR_edge_vps_ipv4",
186
+ "TF_VAR_application_vps_ipv4",
187
+ "AWS_ACCESS_KEY_ID",
188
+ "AWS_SECRET_ACCESS_KEY",
189
+ "AWS_SESSION_TOKEN",
190
+ "AWS_REGION",
191
+ ];
192
+ return {
193
+ ...Object.fromEntries(
194
+ allowed.filter((key) => nonempty(values[key])).map((key) => [key, values[key]]),
195
+ ),
196
+ AWS_EC2_METADATA_DISABLED: "true",
197
+ };
198
+ }
199
+
200
+ function policyCheck(plan, root, deps) {
201
+ return deps.exec(
202
+ process.execPath,
203
+ [
204
+ ".agents/tools/cloud-terraform-plan-policy.mjs",
205
+ "--plan",
206
+ plan.policy_json_path,
207
+ "--contract",
208
+ plan.policy_contract_path,
209
+ ],
210
+ { cwd: root, env: {} },
211
+ );
212
+ }
@@ -0,0 +1,239 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHash } from "node:crypto";
3
+ import {
4
+ copyFile,
5
+ link,
6
+ mkdir,
7
+ mkdtemp,
8
+ readFile,
9
+ realpath,
10
+ rm,
11
+ writeFile,
12
+ } from "node:fs/promises";
13
+ import { createServer } from "node:http";
14
+ import { tmpdir } from "node:os";
15
+ import { basename, dirname, join, resolve } from "node:path";
16
+ import test from "node:test";
17
+ import { pathToFileURL } from "node:url";
18
+
19
+ test("real filesystem, local HTTP providers and stateful child CLI complete plan/apply without real accounts", async (t) => {
20
+ const temporaryRoot = await realpath(tmpdir());
21
+ const workspace = await mkdtemp(join(temporaryRoot, "zaip-cloud-e2e-"));
22
+ t.after(async () => {
23
+ assert.equal(dirname(await realpath(workspace)), temporaryRoot);
24
+ assert.ok(basename(workspace).startsWith("zaip-cloud-e2e-"));
25
+ await rm(workspace, { recursive: true, force: true });
26
+ });
27
+ const put = async (name, content) => {
28
+ const path = join(workspace, name);
29
+ await mkdir(dirname(path), { recursive: true });
30
+ await writeFile(path, typeof content === "string" ? content : JSON.stringify(content));
31
+ };
32
+ await put(".agents/tools/.keep", "");
33
+ await copyFile(
34
+ resolve(import.meta.dirname, "cloud-runner.mjs"),
35
+ join(workspace, ".agents/tools/cloud-runner.mjs"),
36
+ );
37
+ await copyFile(
38
+ resolve(import.meta.dirname, "cloud-terraform-plan-policy.mjs"),
39
+ join(workspace, ".agents/tools/cloud-terraform-plan-policy.mjs"),
40
+ );
41
+ await put("scripts/.keep", "");
42
+ await copyFile(
43
+ resolve(import.meta.dirname, "../../scripts/validate-cloud-terraform-plan.mjs"),
44
+ join(workspace, "scripts/validate-cloud-terraform-plan.mjs"),
45
+ );
46
+ await mkdir(join(workspace, ".local"), { recursive: true });
47
+ const binary = join(
48
+ workspace,
49
+ ".local",
50
+ process.platform === "win32" ? "terraform.exe" : "terraform",
51
+ );
52
+ try {
53
+ await link(process.execPath, binary);
54
+ } catch {
55
+ await copyFile(process.execPath, binary);
56
+ }
57
+ const hash = createHash("sha256")
58
+ .update(await readFile(binary))
59
+ .digest("hex");
60
+ const config = {
61
+ bucket: "approved-state",
62
+ key: "test/state",
63
+ region: "us-east-1",
64
+ encrypt: true,
65
+ use_lockfile: true,
66
+ };
67
+ const policy = {
68
+ cloudflare: {
69
+ account_id: "cf",
70
+ zone_id: "zone",
71
+ zone_name: "example.com",
72
+ edge_ipv4: "198.51.100.7",
73
+ dns_records: {},
74
+ },
75
+ hostinger: {
76
+ edge: {
77
+ id: "101",
78
+ plan: "sku",
79
+ data_center_id: 1,
80
+ template_id: 2,
81
+ hostname: "edge",
82
+ ssh_key_ids: [],
83
+ },
84
+ application: {
85
+ id: "102",
86
+ plan: "sku",
87
+ data_center_id: 1,
88
+ template_id: 2,
89
+ hostname: "app",
90
+ ssh_key_ids: [],
91
+ ipv4: "198.51.100.8",
92
+ },
93
+ },
94
+ };
95
+ const contract = {
96
+ version: 1,
97
+ profile: "autonomous-cloud",
98
+ authorization: { standing: true, reference: "TASK-TEST" },
99
+ cloudflare: { account_id: "cf", zone_id: "zone", zone_name: "example.com", dns_records: [] },
100
+ hostinger: {
101
+ account_id: "hs",
102
+ vps: {
103
+ edge: { id: "101", ssh_host: "198.51.100.7" },
104
+ application: { id: "102", ssh_host: "198.51.100.8" },
105
+ },
106
+ },
107
+ terraform: {
108
+ binary_path: ".local/" + basename(binary),
109
+ binary_sha256: hash,
110
+ working_directory: "infra/terraform",
111
+ allowed_operations: ["terraform:plan", "terraform:apply"],
112
+ plan: {
113
+ backend: { type: "s3", config },
114
+ path: ".local/cloud/plans/approved.tfplan",
115
+ policy_json_path: ".local/cloud/plans/approved.json",
116
+ policy_contract_path: ".agents/config/policy.json",
117
+ },
118
+ },
119
+ };
120
+ const contractPath = ".agents/config/autonomous-cloud-contract.json";
121
+ await put(contractPath, contract);
122
+ await put(".agents/config/policy.json", policy);
123
+ await put(
124
+ ".env",
125
+ "CLOUDFLARE_API_TOKEN=fake-cf\nHOSTINGER_API_TOKEN=fake-hs\nAWS_ACCESS_KEY_ID=fake-state-key\nAWS_SECRET_ACCESS_KEY=fake-state-secret\nUNRELATED_SECRET=never-forward\n",
126
+ );
127
+ await put("infra/terraform/backend.tf.json", { terraform: { backend: { s3: config } } });
128
+ await put("infra/terraform/.terraform.lock.hcl", "fixture-provider-lock");
129
+ const values = ["edge", "application"].map((role) => ({
130
+ address: `hostinger_vps.${role}[0]`,
131
+ type: "hostinger_vps",
132
+ mode: "managed",
133
+ values: { ...policy.hostinger[role], ipv4_address: contract.hostinger.vps[role].ssh_host },
134
+ }));
135
+ for (const resource of values) delete resource.values.ipv4;
136
+ await put("infra/terraform/expected-plan.json", {
137
+ resource_changes: values.map((resource) => ({
138
+ address: resource.address,
139
+ type: resource.type,
140
+ change: { actions: ["no-op"], before: resource.values, after: resource.values },
141
+ })),
142
+ });
143
+ await put("infra/terraform/expected-state.json", {
144
+ values: { root_module: { resources: values } },
145
+ });
146
+ await put(
147
+ "infra/terraform/fake.cjs",
148
+ `const fs=require('node:fs');const assert=require('node:assert/strict');module.exports=(op)=>{
149
+ assert.equal(process.env.UNRELATED_SECRET,undefined);assert.equal(process.env.AWS_EC2_METADATA_DISABLED,'true');
150
+ let state=fs.existsSync('.fake-state.json')?JSON.parse(fs.readFileSync('.fake-state.json')):{};
151
+ if(op==='init'){state.initialized=true;fs.mkdirSync('.terraform',{recursive:true});const b=JSON.parse(fs.readFileSync('backend.tf.json')).terraform.backend.s3;fs.writeFileSync('.terraform/terraform.tfstate',JSON.stringify({backend:{type:'s3',config:b}}));}
152
+ else {assert.ok(state.initialized);if(op==='plan'){state.planned=true;fs.writeFileSync(process.argv[process.argv.indexOf('-out')+1],'reviewed-plan');}
153
+ if(op==='show'){assert.ok(state.planned);const saved=process.argv.length>3;if(!saved)assert.ok(state.applied);process.stdout.write(fs.readFileSync(saved?'expected-plan.json':'expected-state.json'));}
154
+ if(op==='apply'){assert.ok(state.planned);assert.equal(fs.readFileSync(process.argv.at(-1),'utf8'),'reviewed-plan');state.applied=true;}}
155
+ state.calls=[...(state.calls||[]),op];fs.writeFileSync('.fake-state.json',JSON.stringify(state));};`,
156
+ );
157
+ for (const op of ["init", "fmt", "validate", "plan", "show", "apply"])
158
+ await put(`infra/terraform/${op}`, `require('./fake.cjs')('${op}');`);
159
+ const requests = [];
160
+ const server = createServer((req, res) => {
161
+ requests.push(req.url);
162
+ res.setHeader("Content-Type", "application/json");
163
+ if (req.method !== "GET") {
164
+ res.statusCode = 405;
165
+ return res.end("{}");
166
+ }
167
+ if (req.url === "/client/v4/zones/zone")
168
+ return res.end(
169
+ JSON.stringify({
170
+ success: true,
171
+ result: { id: "zone", name: "example.com", account: { id: "cf" } },
172
+ }),
173
+ );
174
+ const id = /virtual-machines\/(101|102)$/.exec(req.url)?.[1];
175
+ if (id)
176
+ return res.end(
177
+ JSON.stringify({
178
+ id: Number(id),
179
+ ipv4: [{ address: id === "101" ? "198.51.100.7" : "198.51.100.8" }],
180
+ }),
181
+ );
182
+ res.statusCode = 404;
183
+ res.end("{}");
184
+ });
185
+ await new Promise((done) => server.listen(0, "127.0.0.1", done));
186
+ t.after(() => new Promise((done) => server.close(done)));
187
+ const endpoint = `http://127.0.0.1:${server.address().port}`;
188
+ const deps = { http: (url, options) => fetch(endpoint + new URL(url).pathname, options) };
189
+ const { run } = await import(
190
+ pathToFileURL(join(workspace, ".agents/tools/cloud-runner.mjs")).href
191
+ );
192
+ const planned = await run(
193
+ {
194
+ contract: contractPath,
195
+ operation: "terraform:plan",
196
+ credentialsSource: "root",
197
+ terraformDirectory: "infra/terraform",
198
+ },
199
+ deps,
200
+ );
201
+ Object.assign(contract.terraform.plan, {
202
+ sha256: planned.plan_sha256,
203
+ policy_result_sha256: planned.policy_result_sha256,
204
+ });
205
+ await put(contractPath, contract);
206
+ const args = {
207
+ contract: contractPath,
208
+ operation: "terraform:apply",
209
+ credentialsSource: "root",
210
+ planPath: contract.terraform.plan.path,
211
+ planSha256: planned.plan_sha256,
212
+ policyResultSha256: planned.policy_result_sha256,
213
+ };
214
+ const result = await run(args, deps);
215
+ assert.deepEqual(result.targets, ["101", "102"]);
216
+ const recorded = JSON.parse(
217
+ await readFile(join(workspace, "infra/terraform/.fake-state.json"), "utf8"),
218
+ );
219
+ assert.deepEqual(recorded.calls, [
220
+ "init",
221
+ "fmt",
222
+ "validate",
223
+ "plan",
224
+ "show",
225
+ "init",
226
+ "show",
227
+ "apply",
228
+ "show",
229
+ ]);
230
+ assert.equal(requests.length, 8);
231
+ await put(contract.terraform.plan.path, "tampered");
232
+ await assert.rejects(run(args, deps), /target_mismatch/);
233
+ assert.equal(
234
+ JSON.parse(
235
+ await readFile(join(workspace, "infra/terraform/.fake-state.json"), "utf8"),
236
+ ).calls.filter((op) => op === "apply").length,
237
+ 1,
238
+ );
239
+ });