@zaip-ai/cli 1.3.8 → 1.4.1

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 (315) 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 +200 -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-server.mjs +142 -0
  181. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +231 -239
  182. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +18 -29
  183. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +6 -0
  184. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  185. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  186. package/templates/.agents/requirements/cloud-hostinger-autonomy.md +47 -0
  187. package/templates/.agents/requirements/comparative-audit.md +1 -1
  188. package/templates/.agents/requirements/context-engine.md +1 -1
  189. package/templates/.agents/requirements/cost-observability.md +1 -1
  190. package/templates/.agents/requirements/dashboard-launch.md +2 -2
  191. package/templates/.agents/requirements/data-export.md +1 -1
  192. package/templates/.agents/requirements/design-system.md +1 -1
  193. package/templates/.agents/requirements/execution-engine.md +1 -1
  194. package/templates/.agents/requirements/kanban-dashboard.md +1 -1
  195. package/templates/.agents/requirements/model-orchestration.md +1 -1
  196. package/templates/.agents/requirements/public-distribution.md +1 -1
  197. package/templates/.agents/requirements/software-architecture.md +1 -1
  198. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  199. package/templates/.agents/requirements/work-lifecycle.md +1 -1
  200. package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
  201. package/templates/.agents/rules/autonomy-decision.md +1 -1
  202. package/templates/.agents/rules/cloud-hostinger-autonomy.md +21 -0
  203. package/templates/.agents/rules/core.md +5 -4
  204. package/templates/.agents/rules/local-sqlite-storage.md +18 -0
  205. package/templates/.agents/rules/meta-mcp.md +21 -0
  206. package/templates/.agents/rules/workflow.md +1 -0
  207. package/templates/.agents/runtime/bin/zaip.mjs +305 -137
  208. package/templates/.agents/runtime/checksums.sha256 +2 -2
  209. package/templates/.agents/runtime/provenance.json +2 -2
  210. package/templates/.agents/skills/zaip-skill-api-to-mcp/SKILL.md +4 -0
  211. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +25 -9
  212. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +2 -2
  213. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +2 -2
  214. package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +15 -0
  215. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +13 -5
  216. package/templates/.agents/skills/zaip-skill-data-analyst/SKILL.md +10 -5
  217. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +5 -4
  218. package/templates/.agents/skills/zaip-skill-frontend-launcher/SKILL.md +4 -3
  219. package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +5 -3
  220. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -5
  221. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +78 -13
  222. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +59 -0
  223. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/yaml-parser.mjs +157 -0
  224. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +11 -6
  225. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +17 -0
  226. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +7 -0
  227. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-cloud-inputs.example.json +41 -0
  228. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-runner.md +84 -0
  229. package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/operational-contract.md +19 -0
  230. package/templates/.agents/skills/zaip-skill-local-credentials/SKILL.md +43 -0
  231. package/templates/.agents/skills/zaip-skill-local-credentials/agents/openai.yaml +6 -0
  232. package/templates/.agents/skills/zaip-skill-local-credentials/references/dotenv-resolution.md +47 -0
  233. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +8 -3
  234. package/templates/.agents/skills/zaip-skill-meta-ads/SKILL.md +16 -0
  235. package/templates/.agents/skills/zaip-skill-meta-ads/agents/openai.yaml +4 -0
  236. package/templates/.agents/skills/zaip-skill-meta-ads/references/setup.md +3 -0
  237. package/templates/.agents/skills/zaip-skill-meta-ads-setup/SKILL.md +24 -0
  238. package/templates/.agents/skills/zaip-skill-meta-ads-setup/agents/openai.yaml +4 -0
  239. package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/diagnostics.md +13 -0
  240. package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/official-sources.md +10 -0
  241. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/SKILL.md +12 -0
  242. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/agents/openai.yaml +4 -0
  243. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/LICENSE +21 -0
  244. package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/upstream.md +77 -0
  245. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/SKILL.md +12 -0
  246. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/agents/openai.yaml +4 -0
  247. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/LICENSE +21 -0
  248. package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/upstream.md +126 -0
  249. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/SKILL.md +12 -0
  250. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/agents/openai.yaml +4 -0
  251. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/LICENSE +21 -0
  252. package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/upstream.md +67 -0
  253. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/SKILL.md +12 -0
  254. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/agents/openai.yaml +4 -0
  255. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/LICENSE +21 -0
  256. package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/upstream.md +69 -0
  257. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/SKILL.md +12 -0
  258. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/agents/openai.yaml +4 -0
  259. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/LICENSE +21 -0
  260. package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/upstream.md +79 -0
  261. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/SKILL.md +14 -0
  262. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/agents/openai.yaml +4 -0
  263. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/LICENSE +21 -0
  264. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/upstream.md +144 -0
  265. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/SKILL.md +12 -0
  266. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/agents/openai.yaml +4 -0
  267. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/LICENSE +21 -0
  268. package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/upstream.md +83 -0
  269. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/SKILL.md +10 -0
  270. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/agents/openai.yaml +4 -0
  271. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/LICENSE +21 -0
  272. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/setup.md +11 -0
  273. package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/upstream.md +55 -0
  274. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/SKILL.md +12 -0
  275. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/agents/openai.yaml +4 -0
  276. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/LICENSE +21 -0
  277. package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/upstream.md +56 -0
  278. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +12 -7
  279. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +11 -4
  280. package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +6 -4
  281. package/templates/.agents/skills/zaip-skill-tool-setup/references/codex-config.md +4 -2
  282. package/templates/.agents/skills/zaip-skill-tool-setup/references/secrets.md +1 -0
  283. package/templates/.agents/tools/catalog.yaml +6 -0
  284. package/templates/.agents/tools/cloud-runner-dns.mjs +28 -0
  285. package/templates/.agents/tools/cloud-runner-terraform.mjs +212 -0
  286. package/templates/.agents/tools/cloud-runner.integration.test.mjs +239 -0
  287. package/templates/.agents/tools/cloud-runner.mjs +786 -0
  288. package/templates/.agents/tools/cloud-runner.test.mjs +534 -0
  289. package/templates/.agents/tools/cloud-terraform-plan-policy.mjs +262 -0
  290. package/templates/.agents/tools/mcp/development/meta-devtools/README.md +14 -0
  291. package/templates/.agents/tools/mcp/development/meta-devtools/manifest.yaml +28 -0
  292. package/templates/.agents/tools/mcp/infra/cloudflare/manifest.yaml +2 -3
  293. package/templates/.agents/tools/mcp/infra/hostinger/manifest.yaml +1 -3
  294. package/templates/.agents/tools/mcp/marketing/meta-ads/README.md +15 -13
  295. package/templates/.agents/tools/mcp/marketing/meta-ads/manifest.yaml +15 -10
  296. package/templates/.agents/tools/profiles/development.yaml +3 -0
  297. package/templates/infra/terraform/.terraform.lock.hcl +42 -0
  298. package/templates/infra/terraform/README.md +31 -0
  299. package/templates/infra/terraform/backend.tf.json +13 -0
  300. package/templates/infra/terraform/deployment-inputs.example.yaml +22 -0
  301. package/templates/infra/terraform/fixtures/approved-targets.json +32 -0
  302. package/templates/infra/terraform/fixtures/plan-approved.json +67 -0
  303. package/templates/infra/terraform/main.tf +77 -0
  304. package/templates/infra/terraform/outputs.tf +20 -0
  305. package/templates/infra/terraform/terraform.tfvars.example +26 -0
  306. package/templates/infra/terraform/variables.tf +91 -0
  307. package/templates/infra/terraform/versions.tf +18 -0
  308. package/templates/scripts/validate-cloud-hostinger-contract.mjs +89 -0
  309. package/templates/scripts/validate-cloud-terraform-plan.mjs +1 -0
  310. package/templates/template-manifest.json +599 -167
  311. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BwnJpl02.js +0 -3
  312. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-C09KmlSw.js +0 -68
  313. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dyo_wpL4.js +0 -2
  314. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-hPPfVGQv.css +0 -1
  315. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-stale-seed.ts +0 -50
@@ -1,45 +1,18 @@
1
- import { randomUUID } from "node:crypto";
2
- import { copyFile, mkdir, readdir, rename, rm, stat } from "node:fs/promises";
3
- import { dirname, join, resolve } from "node:path";
4
1
  import { DatabaseSync } from "node:sqlite";
5
2
 
6
- export async function pruneSnapshotCache(directory: string, activePath: string): Promise<void> {
7
- const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
8
- const stale = await Promise.all(
9
- entries
10
- .filter(
11
- (entry) =>
12
- entry.isFile() &&
13
- entry.name.endsWith(".sqlite") &&
14
- resolve(directory, entry.name) !== activePath,
15
- )
16
- .map(async (entry) => ({
17
- path: resolve(directory, entry.name),
18
- mtime: (await stat(resolve(directory, entry.name))).mtimeMs,
19
- })),
20
- );
21
- for (const entry of stale.sort((a, b) => b.mtime - a.mtime).slice(1))
22
- await rm(entry.path, { force: true }).catch(() => {});
23
- for (const entry of entries) {
24
- if (!entry.isFile() || !entry.name.includes(".sqlite.") || !entry.name.includes(".tmp"))
25
- continue;
26
- const candidate = resolve(directory, entry.name);
27
- if (Date.now() - (await stat(candidate)).mtimeMs > 60_000)
28
- await rm(candidate, { force: true }).catch(() => {});
29
- }
30
- }
31
-
32
3
  export function readSnapshotFileCount(
33
4
  path: string,
34
5
  fingerprint: string,
35
6
  schemaVersion: string,
36
7
  hasRequiredPayloads: (database: DatabaseSync) => boolean,
37
8
  ): number | null {
9
+ let database: DatabaseSync | undefined;
38
10
  try {
39
- const database = new DatabaseSync(path, { readOnly: true });
11
+ database = new DatabaseSync(path, { readOnly: true });
12
+ const reader = database;
40
13
  const value = (key: string) =>
41
14
  (
42
- database.prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key = ?").get(key) as
15
+ reader.prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key = ?").get(key) as
43
16
  | { value?: string }
44
17
  | undefined
45
18
  )?.value;
@@ -50,58 +23,11 @@ export function readSnapshotFileCount(
50
23
  hasRequiredPayloads(database)
51
24
  ? files
52
25
  : null;
53
- database.close();
54
- return result;
55
- } catch {
56
- return null;
57
- }
58
- }
59
-
60
- export async function mostRecentCompatibleSnapshot(
61
- directory: string,
62
- schemaVersion: string,
63
- hasRequiredPayloads: (database: DatabaseSync) => boolean,
64
- ): Promise<{ path: string; files: number } | null> {
65
- const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
66
- const candidates = await Promise.all(
67
- entries
68
- .filter((entry) => entry.isFile() && entry.name.endsWith(".sqlite"))
69
- .map(async (entry) => ({
70
- path: join(directory, entry.name),
71
- mtime: (await stat(join(directory, entry.name))).mtimeMs,
72
- })),
73
- );
74
- for (const candidate of candidates.sort((left, right) => right.mtime - left.mtime)) {
75
- const files = readCompatibleSnapshotFileCount(
76
- candidate.path,
77
- schemaVersion,
78
- hasRequiredPayloads,
79
- );
80
- if (files !== null) return { path: candidate.path, files };
81
- }
82
- return null;
83
- }
84
-
85
- function readCompatibleSnapshotFileCount(
86
- path: string,
87
- schemaVersion: string,
88
- hasRequiredPayloads: (database: DatabaseSync) => boolean,
89
- ): number | null {
90
- try {
91
- const database = new DatabaseSync(path, { readOnly: true });
92
- const value = (key: string) =>
93
- (
94
- database.prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key = ?").get(key) as
95
- | { value?: string }
96
- | undefined
97
- )?.value;
98
- const files = Number(value("source_file_count") ?? 0);
99
- const result =
100
- value("schema_version") === schemaVersion && hasRequiredPayloads(database) ? files : null;
101
- database.close();
102
26
  return result;
103
27
  } catch {
104
28
  return null;
29
+ } finally {
30
+ database?.close();
105
31
  }
106
32
  }
107
33
 
@@ -112,18 +38,13 @@ export function installLegacyViewAliases(database: DatabaseSync): void {
112
38
  for (const { name } of views) {
113
39
  const alias = name.slice("zaip_vw_".length);
114
40
  const quoted = (identifier: string) => `"${identifier.replaceAll('"', '""')}"`;
41
+ // A transaction may still have a staging table with a legacy public name.
42
+ // The table is already the intended source in that connection, so a TEMP
43
+ // alias would collide and make the complete transaction impossible.
44
+ const existing = database
45
+ .prepare("SELECT 1 FROM sqlite_temp_master WHERE name=? LIMIT 1")
46
+ .get(alias);
47
+ if (existing !== undefined) continue;
115
48
  database.exec(`CREATE TEMP VIEW ${quoted(alias)} AS SELECT * FROM main.${quoted(name)}`);
116
49
  }
117
50
  }
118
-
119
- export async function materializeSnapshot(source: string, destination: string): Promise<void> {
120
- await mkdir(dirname(destination), { recursive: true });
121
- const temporaryPath = `${destination}.${process.pid}.${randomUUID()}.tmp`;
122
- await copyFile(source, temporaryPath);
123
- try {
124
- await rename(temporaryPath, destination);
125
- } catch (error) {
126
- await rm(temporaryPath, { force: true });
127
- throw error;
128
- }
129
- }
@@ -0,0 +1,79 @@
1
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import {
6
+ claimDashboardLaunch,
7
+ host,
8
+ requestBackgroundProjectionRefresh,
9
+ workspaceKey,
10
+ } from "./start-dashboard.mjs";
11
+
12
+ const temporaryDirectories = [];
13
+
14
+ afterEach(async () => {
15
+ await Promise.all(
16
+ temporaryDirectories.splice(0).map((path) => rm(path, { recursive: true, force: true })),
17
+ );
18
+ });
19
+
20
+ describe("dashboard launch claims", () => {
21
+ it("blocks the new launch before SQLite when the superseded launcher will not exit", async () => {
22
+ const directory = await temporaryDirectory();
23
+ const path = join(directory, "dashboard-launch.json");
24
+ await writeFile(
25
+ path,
26
+ JSON.stringify({ kind: "zaip-dashboard-sqlite-launch", workspaceKey, launcherPid: 1234 }),
27
+ );
28
+ const stops = [];
29
+ await expect(
30
+ claimDashboardLaunch(
31
+ { launchPort: 4317, token: "newest-token" },
32
+ {
33
+ path,
34
+ stopProcessTreeImpl: async (pid) => stops.push(pid),
35
+ isKnownDashboardLauncherImpl: async () => true,
36
+ isProcessAliveImpl: async () => true,
37
+ delayImpl: async () => {},
38
+ },
39
+ ),
40
+ ).rejects.toThrow("Could not stop the superseded dashboard launcher");
41
+ expect(stops).toEqual([1234]);
42
+ });
43
+
44
+ it("recovers a recent claim lock immediately when its owner PID is dead", async () => {
45
+ const directory = await temporaryDirectory();
46
+ const path = join(directory, "launch.json");
47
+ const lockPath = join(directory, "claim.lock");
48
+ await mkdir(lockPath);
49
+ await writeFile(join(lockPath, "owner"), "999999", "utf8");
50
+ await claimDashboardLaunch(
51
+ { launchPort: 4317, token: "new-token" },
52
+ { path, lockPath, isProcessAliveImpl: async () => false },
53
+ );
54
+ await expect(readFile(path, "utf8")).resolves.toContain('"launchPort": 4317');
55
+ });
56
+
57
+ it("requests a coalesced projection refresh after reusing a warm session", async () => {
58
+ const calls = [];
59
+ await requestBackgroundProjectionRefresh(
60
+ { port: 4417, token: "warm-token" },
61
+ async (url, init) => calls.push({ url, init }),
62
+ );
63
+ expect(calls).toEqual([
64
+ {
65
+ url: `http://${host}:4417/api/v2/refresh-projection`,
66
+ init: expect.objectContaining({
67
+ method: "POST",
68
+ headers: { "x-zaip-session": "warm-token" },
69
+ }),
70
+ },
71
+ ]);
72
+ });
73
+ });
74
+
75
+ async function temporaryDirectory() {
76
+ const path = await mkdtemp(join(tmpdir(), "zaip-dashboard-launch-claims-"));
77
+ temporaryDirectories.push(path);
78
+ return path;
79
+ }
@@ -9,6 +9,18 @@ export async function createDashboardLaunchPage({ port, host, runtimeKind, healt
9
9
  detail: "Abrindo a página de preparação.",
10
10
  };
11
11
  let progressSteps = [{ phase: progress.phase, detail: progress.detail }];
12
+ const browserLeases = new Set();
13
+ let resolveBrowserDeparture;
14
+ const browserDeparture = new Promise((resolve) => {
15
+ resolveBrowserDeparture = resolve;
16
+ });
17
+ const browserLeaseGraceMs = 12_000;
18
+ let browserDepartureTimer = null;
19
+ const scheduleBrowserDeparture = () => {
20
+ if (browserLeases.size > 0 || browserDepartureTimer !== null) return;
21
+ browserDepartureTimer = setTimeout(() => resolveBrowserDeparture(), browserLeaseGraceMs);
22
+ browserDepartureTimer.unref?.();
23
+ };
12
24
  progress = { ...progress, steps: progressSteps };
13
25
  const connections = new Set();
14
26
  let resolveRedirectObserved;
@@ -36,6 +48,18 @@ export async function createDashboardLaunchPage({ port, host, runtimeKind, healt
36
48
  response.end(JSON.stringify({ ...progress, failure }));
37
49
  return;
38
50
  }
51
+ if (request.url?.startsWith("/api/v2/browser-lease")) {
52
+ if (browserDepartureTimer !== null) clearTimeout(browserDepartureTimer);
53
+ browserDepartureTimer = null;
54
+ browserLeases.add(response);
55
+ response.writeHead(200, { "Content-Type": "text/event-stream", "Cache-Control": "no-store" });
56
+ response.write("event: lease\ndata: active\n\n");
57
+ response.once("close", () => {
58
+ browserLeases.delete(response);
59
+ scheduleBrowserDeparture();
60
+ });
61
+ return;
62
+ }
39
63
  if (request.url?.startsWith(healthPath)) {
40
64
  response.writeHead(503, { "Content-Type": "application/json; charset=utf-8" });
41
65
  response.end(JSON.stringify({ kind: "zaip-dashboard-launcher", status: "starting" }));
@@ -70,6 +94,7 @@ export async function createDashboardLaunchPage({ port, host, runtimeKind, healt
70
94
  function setProgressBar(percent,phase){lastProgressPercent=percent;document.getElementById("bar").style.width=percent+"%";document.getElementById("track").setAttribute("aria-valuenow",String(percent));document.getElementById("track").setAttribute("aria-valuetext",phase)}
71
95
  function showHandoff(target){handoffTarget=target;stopCompilationTicker();setProgressBar(100,"Dashboard pronto");document.querySelector(".launch-overlay").setAttribute("aria-busy","false");document.getElementById("handoff").style.display="block";document.getElementById("phase").textContent="Dashboard pronto";document.getElementById("detail").textContent="Concluindo a abertura da tela principal.";document.getElementById("activity").textContent="Preparação concluída."}
72
96
  function showFailure(next,percent=lastProgressPercent){terminalFailure=true;clearInterval(progressPoll);stopCompilationTicker();document.querySelector(".launch-overlay").setAttribute("aria-busy","false");document.getElementById("phase").textContent=next.phase;document.getElementById("detail").textContent="A preparação não foi concluída. Consulte a mensagem abaixo para agir.";setProgressBar(percent,next.phase);document.getElementById("handoff").style.display="none";document.getElementById("failure").textContent=next.detail;document.getElementById("failure").style.display="block";document.querySelector(".progress").classList.add("terminal-failure")}
97
+ const browserLease=new EventSource("/api/v2/browser-lease");
73
98
  async function updateProgress(){if(progressRequestInFlight||terminalFailure)return terminalFailure;progressRequestInFlight=true;try{const r=await fetch("/api/v2/progress",{cache:"no-store",signal:AbortSignal.timeout(1000)});const p=await r.json();if(terminalFailure)return true;const percent=Math.max(4,Math.min(100,Number(p.percent)||4));if(p.failure){showFailure(p.failure,percent);return true}if(!handoffTarget){for(const step of Array.isArray(p.steps)?p.steps:[p])recordStep(step);const nextStepKey=p.phase+"\\u0000"+(p.detail??"");if(nextStepKey!==activeStepKey){activeStepKey=nextStepKey;activeStepStartedAt=Date.now()}document.getElementById("phase").textContent=p.phase;const compiling=p.phase.startsWith("Atualizando ");if(compiling){if(compilationStartedAt===null){compilationStartedAt=Date.now();compilationDetail=p.detail;if(!reducedMotion)compilationTicker=setInterval(renderCompilationElapsed,1000)}renderCompilationElapsed()}else{stopCompilationTicker();document.getElementById("detail").textContent=p.detail}renderActivityElapsed()}if(!terminalFailure&&!handoffTarget)setProgressBar(percent,p.phase)}catch{}finally{progressRequestInFlight=false}return terminalFailure}
74
99
  const progressPoll=setInterval(updateProgress,250);
75
100
  async function waitForDashboard(){try{if(await updateProgress())return;const ready=await fetch("/api/v2/ready",{cache:"no-store",signal:AbortSignal.timeout(1000)});const next=await ready.json();if(next.failure){showFailure(next.failure);return}if(next.target){showHandoff(next.target);clearInterval(progressPoll);setTimeout(()=>location.replace(next.target),0);return}const response=await fetch("${healthPath}",{cache:"no-store",signal:AbortSignal.timeout(1000)});const payload=await response.json();if(response.ok&&payload.kind==="${runtimeKind}"){clearInterval(progressPoll);location.reload();return}}catch{}setTimeout(waitForDashboard,250)}
@@ -120,6 +145,7 @@ export async function createDashboardLaunchPage({ port, host, runtimeKind, healt
120
145
  },
121
146
  waitForRedirect: async (timeoutMs = 1_500) =>
122
147
  Promise.race([redirectObserved, delay(timeoutMs).then(() => false)]),
148
+ waitForBrowserDeparture: () => browserDeparture,
123
149
  closeAfterHandoffGrace: (graceMs = 12_000) => {
124
150
  const timer = setTimeout(() => {
125
151
  void server.close();
@@ -153,6 +179,7 @@ export async function createDashboardLaunchPage({ port, host, runtimeKind, healt
153
179
  if (error) rejectClose(error);
154
180
  else resolveClose();
155
181
  };
182
+ if (browserDepartureTimer !== null) clearTimeout(browserDepartureTimer);
156
183
  server.close(finish);
157
184
  forceTimer = setTimeout(() => {
158
185
  server.closeAllConnections?.();
@@ -39,20 +39,20 @@ export async function awaitOwnedDashboardExit({
39
39
  currentSession,
40
40
  clearOwnedDashboardSession,
41
41
  recordPortStatus,
42
- removeGeneratedReadModel,
43
42
  processRef = process,
44
43
  }) {
45
44
  for (const signal of ["SIGINT", "SIGTERM"]) {
46
45
  processRef.once(signal, () => child.kill(signal));
47
46
  }
48
- const exitCode = await new Promise((resolveExit, rejectExit) => {
49
- child.once("error", rejectExit);
50
- child.once("exit", (code) => resolveExit(code ?? 0));
51
- });
47
+ const exitCode =
48
+ child.exitCode ??
49
+ (await new Promise((resolveExit, rejectExit) => {
50
+ child.once("error", rejectExit);
51
+ child.once("exit", (code) => resolveExit(code ?? 0));
52
+ }));
52
53
  await clearOwnedDashboardSession();
53
54
  if (currentSession !== null) {
54
55
  await recordPortStatus(currentSession, "closed");
55
- await removeGeneratedReadModel(currentSession.dbPath);
56
56
  }
57
57
  return exitCode;
58
58
  }
@@ -2,7 +2,7 @@ import { access, mkdir } from "node:fs/promises";
2
2
  import { relative, resolve } from "node:path";
3
3
  import process from "node:process";
4
4
 
5
- async function exists(path) {
5
+ export async function exists(path) {
6
6
  return access(path).then(
7
7
  () => true,
8
8
  () => false,
@@ -40,12 +40,10 @@ async function acquireRefreshLock(lockPath, isProcessAlive) {
40
40
  export async function startSeedRefresh(options) {
41
41
  const {
42
42
  appendLog,
43
- cacheDirectory,
44
43
  isRunning,
45
44
  isProcessAlive,
46
45
  lockPath,
47
46
  packageRoot,
48
- randomBytes,
49
47
  refreshLogPath,
50
48
  refreshStatusPath,
51
49
  sqliteDirectory,
@@ -62,10 +60,7 @@ export async function startSeedRefresh(options) {
62
60
  appendLog("Skipped duplicate background SQLite seed refresh; a worker is already running.");
63
61
  return;
64
62
  }
65
- const refreshPath = resolve(
66
- sqliteDirectory,
67
- `refresh-${process.pid}-${randomBytes(4).toString("hex")}.sqlite`,
68
- );
63
+ const refreshPath = resolve(sqliteDirectory, "zaip-aios-dashboard.sqlite");
69
64
  mkdirSync(dirname(refreshStatusPath), { recursive: true });
70
65
  const descriptor = openSync(refreshLogPath, "a");
71
66
  let worker;
@@ -81,8 +76,6 @@ export async function startSeedRefresh(options) {
81
76
  ZAIP_SQLITE_DB_PATH: refreshPath,
82
77
  ZAIP_SQLITE_PREFER_LAST_VALID_SEED: "0",
83
78
  ZAIP_DASHBOARD_LAUNCH_PROGRESS: "0",
84
- ZAIP_SQLITE_REFRESH_CLEANUP: "1",
85
- ZAIP_SQLITE_CACHE_DIR: cacheDirectory,
86
79
  },
87
80
  stdio: ["ignore", descriptor, descriptor],
88
81
  detached: true,
@@ -101,7 +94,6 @@ export async function startSeedRefresh(options) {
101
94
  status: "running",
102
95
  pid: worker.pid,
103
96
  path: refreshPath,
104
- cacheDirectory,
105
97
  startedAt: new Date().toISOString(),
106
98
  });
107
99
  } catch (error) {
@@ -130,7 +122,7 @@ export async function startSeedRefresh(options) {
130
122
  });
131
123
  worker.unref();
132
124
  appendLog(
133
- `Started background SQLite seed refresh at ${refreshPath}; cache ${cacheDirectory}; worker log ${refreshLogPath}.`,
125
+ `Started transactional refresh of the persistent SQLite database at ${refreshPath}; worker log ${refreshLogPath}.`,
134
126
  );
135
127
  } finally {
136
128
  try {
@@ -0,0 +1,142 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createServer } from "node:net";
3
+ import process from "node:process";
4
+
5
+ export function isPortFree(host, port) {
6
+ return new Promise((resolvePort) => {
7
+ const server = createServer();
8
+ server.unref();
9
+ server.once("error", () => resolvePort(false));
10
+ server.listen({ host, port }, () => server.close(() => resolvePort(true)));
11
+ });
12
+ }
13
+
14
+ export async function startDashboardServer({
15
+ serverPath,
16
+ token,
17
+ excludedPorts,
18
+ initialPort = null,
19
+ onProgress = () => {},
20
+ onChildStarted = () => {},
21
+ maxAttempts,
22
+ dbPath,
23
+ packageRoot,
24
+ workspaceRoot,
25
+ frontendRoot,
26
+ compileCacheDirectory,
27
+ findPort,
28
+ waitForDashboard,
29
+ stopProcessTree,
30
+ sanitize,
31
+ formatError,
32
+ appendLog,
33
+ }) {
34
+ const failures = [];
35
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
36
+ const port =
37
+ attempt === 1 && Number.isInteger(initialPort)
38
+ ? initialPort
39
+ : await findPort({ excludedPorts: [...excludedPorts] });
40
+ excludedPorts.add(port);
41
+ let stderr = "";
42
+ let startupTelemetryBuffer = "";
43
+ let snapshotCache = null;
44
+ const child = spawn(process.execPath, [serverPath], {
45
+ cwd: packageRoot,
46
+ env: {
47
+ ...process.env,
48
+ ZAIP_WORKSPACE: workspaceRoot,
49
+ ZAIP_UI_ROOT: frontendRoot,
50
+ ZAIP_UI_TOKEN: token,
51
+ ZAIP_SERVER_PORT: String(port),
52
+ NODE_COMPILE_CACHE: compileCacheDirectory,
53
+ NODE_NO_WARNINGS: "1",
54
+ ZAIP_DASHBOARD_LAUNCH_PROGRESS: "1",
55
+ ZAIP_SQLITE_PREFER_LAST_VALID_SEED: "0",
56
+ ZAIP_SQLITE_DB_PATH: dbPath,
57
+ },
58
+ stdio: ["ignore", "ignore", "pipe"],
59
+ windowsHide: true,
60
+ });
61
+ onChildStarted(child);
62
+ child.stderr?.setEncoding("utf8");
63
+ child.stderr?.on("data", (chunk) => {
64
+ stderr = `${stderr}${chunk}`.slice(-4_000);
65
+ startupTelemetryBuffer = `${startupTelemetryBuffer}${String(chunk)}`;
66
+ const lines = startupTelemetryBuffer.split("\n");
67
+ startupTelemetryBuffer = lines.pop() ?? "";
68
+ for (const line of lines)
69
+ reportStartupProgress(line, onProgress, (value) => {
70
+ snapshotCache = value;
71
+ });
72
+ });
73
+ try {
74
+ await waitForDashboard(port, child);
75
+ for (const timing of sanitize(stderr)
76
+ .split("\n")
77
+ .filter(
78
+ (line) =>
79
+ line.includes('"event":"dashboard_sqlite_read_model"') ||
80
+ line.includes('"event":"dashboard_sqlite_startup_phase"'),
81
+ ))
82
+ appendLog(timing);
83
+ return { child, port, dbPath, snapshotCache };
84
+ } catch (error) {
85
+ await stopProcessTree(child.pid);
86
+ const detail = sanitize(stderr)
87
+ .split("\n")
88
+ .filter(
89
+ (line) =>
90
+ !line.includes("ExperimentalWarning") && !line.includes("node --trace-warnings"),
91
+ )
92
+ .join("\n")
93
+ .trim();
94
+ failures.push(
95
+ `porta ${port}: ${error.message}${detail ? ` — ${formatError(detail, 600)}` : ""}`,
96
+ );
97
+ appendLog(`Dashboard start attempt ${attempt} failed on port ${port}: ${error.message}`);
98
+ if (error.retryable === false) break;
99
+ }
100
+ }
101
+ throw new Error(
102
+ `Não foi possível iniciar o dashboard após os fallbacks. ${failures.join(" | ")}`,
103
+ );
104
+ }
105
+
106
+ function reportStartupProgress(line, onProgress, setSnapshotCache) {
107
+ try {
108
+ const event = JSON.parse(line);
109
+ if (event?.event === "dashboard_sqlite_rebuild_progress")
110
+ onProgress({
111
+ percent: event.percent,
112
+ phase: "Configurando o banco SQLite local",
113
+ detail:
114
+ "Esta é a instalação/atualização da cópia local descartável; nenhum servidor externo é instalado.",
115
+ });
116
+ if (event?.event === "dashboard_sqlite_startup_phase" && event.phase === "main_entered")
117
+ onProgress({
118
+ percent: 50,
119
+ phase: "Lendo os registros do projeto",
120
+ detail: "Preparando o read model SQLite local.",
121
+ });
122
+ if (event?.event === "dashboard_sqlite_read_model") {
123
+ setSnapshotCache(event.cache);
124
+ onProgress({
125
+ percent: 82,
126
+ phase: "Banco local pronto",
127
+ detail:
128
+ event.cache === "rebuilt"
129
+ ? "O read model SQLite foi reconstruído para os dados atuais."
130
+ : "Uma cópia local do read model foi preparada.",
131
+ });
132
+ }
133
+ if (event?.event === "dashboard_sqlite_startup_phase" && event.phase === "listening")
134
+ onProgress({
135
+ percent: 88,
136
+ phase: "Iniciando a interface",
137
+ detail: "Verificando saúde e disponibilidade dos dados.",
138
+ });
139
+ } catch {
140
+ // Only structured startup telemetry affects user-facing progress.
141
+ }
142
+ }