@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.
- package/README.md +58 -3
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +17 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/services/adapters.js +4 -4
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/codex-config-template.d.ts +2 -2
- package/dist/services/codex-config-template.d.ts.map +1 -1
- package/dist/services/codex-config-template.js +3 -3
- package/dist/services/codex-config-template.js.map +1 -1
- package/dist/services/codex-rules.d.ts +1 -1
- package/dist/services/codex-rules.d.ts.map +1 -1
- package/dist/services/codex-rules.js +9 -24
- package/dist/services/codex-rules.js.map +1 -1
- package/dist/services/delivery-git-preflight.d.ts +23 -0
- package/dist/services/delivery-git-preflight.d.ts.map +1 -0
- package/dist/services/delivery-git-preflight.js +69 -0
- package/dist/services/delivery-git-preflight.js.map +1 -0
- package/dist/services/doctor.d.ts.map +1 -1
- package/dist/services/doctor.js +13 -1
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +22 -28
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/install-profile.d.ts +8 -0
- package/dist/services/install-profile.d.ts.map +1 -0
- package/dist/services/install-profile.js +56 -0
- package/dist/services/install-profile.js.map +1 -0
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +6 -5
- package/dist/services/logger.js.map +1 -1
- package/dist/services/stack-git.d.ts +9 -0
- package/dist/services/stack-git.d.ts.map +1 -0
- package/dist/services/stack-git.js +188 -0
- package/dist/services/stack-git.js.map +1 -0
- package/dist/services/stack-plan.d.ts +3 -1
- package/dist/services/stack-plan.d.ts.map +1 -1
- package/dist/services/stack-plan.js +15 -1
- package/dist/services/stack-plan.js.map +1 -1
- package/dist/services/stack-terraform.d.ts +13 -0
- package/dist/services/stack-terraform.d.ts.map +1 -0
- package/dist/services/stack-terraform.js +274 -0
- package/dist/services/stack-terraform.js.map +1 -0
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +14 -1
- package/dist/services/template-manifest.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +34 -0
- package/templates/{README.md → .agents/README.md} +124 -60
- package/templates/.agents/config/agents/catalog.yaml +23 -23
- package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +10 -7
- package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -0
- package/templates/.agents/config/pricing/models.json +25 -1
- package/templates/.agents/config/project.yaml +2 -0
- package/templates/.agents/dashboard/.zaip-managed.json +200 -88
- package/templates/.agents/dashboard/DATA-DICTIONARY.md +1 -1
- package/templates/.agents/dashboard/README.md +58 -19
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DwVZOmMV.js → CostCalculationGuidePage-snUCQYTC.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-VcLx9iOO.js → DashboardHelpDialog-oZVlf-l5.js} +72 -8
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CyjMXkm8.js → PricingSettingsDialog-BPtVUGgs.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-DFZwIXSC.js → TraceabilityWorkspace-BYjVOHI_.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DXBOtWNI.js → icons-vendor-TPUT2IUt.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cmlx8OYH.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-ZJFXmK7m.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-DaNXQPyk.js → react-vendor-Ct48XHGL.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-I4AKqVDX.js → traceability-BDe4_Ubl.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +73 -67
- package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +35 -7
- package/templates/.agents/dashboard/apps/frontend/src/AppWorkBoard.ts +55 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +11 -0
- package/templates/.agents/dashboard/apps/frontend/src/app-loading-boundary.css +98 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +5 -5
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-reconciliation.ts +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +75 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -8
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +14 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +35 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +78 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +28 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +8 -5
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +180 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +7 -4
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +13 -7
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +14 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +211 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +152 -157
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +155 -142
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/InvocationManifestQuery.test.ts +145 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +7 -5
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +4 -4
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +79 -1
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +105 -11
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +482 -332
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +430 -285
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +14 -2
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +6 -26
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-persistent-launch.mjs +268 -0
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +482 -332
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +90 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +112 -22
- package/templates/.agents/dashboard/packages/local-runtime/src/server-agent-assets.ts +39 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +33 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +148 -11
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-result.test.ts +68 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +19 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +39 -43
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.test.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +34 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-startup.ts +30 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +89 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +88 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +68 -7
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +11 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +129 -99
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.test.ts +111 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.ts +140 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +127 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +145 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +156 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +18 -9
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-projection.ts +52 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +35 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +56 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.test.ts +29 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.ts +136 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +251 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +22 -7
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical-parsing.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +793 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-duration.test.ts +270 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +3 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +18 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +87 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +105 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +131 -59
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1000 -1115
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +13 -92
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-claims.test.mjs +79 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +27 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.mjs +6 -6
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-prerequisites.mjs +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +2 -10
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-server.mjs +142 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +231 -239
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +18 -29
- package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +6 -0
- package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
- package/templates/.agents/requirements/autonomous-assurance.md +1 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +47 -0
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +2 -2
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +1 -1
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +1 -1
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +1 -1
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/autonomy-decision.md +1 -1
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +21 -0
- package/templates/.agents/rules/core.md +5 -4
- package/templates/.agents/rules/local-sqlite-storage.md +18 -0
- package/templates/.agents/rules/meta-mcp.md +21 -0
- package/templates/.agents/rules/workflow.md +1 -0
- package/templates/.agents/runtime/bin/zaip.mjs +305 -137
- package/templates/.agents/runtime/checksums.sha256 +2 -2
- package/templates/.agents/runtime/provenance.json +2 -2
- package/templates/.agents/skills/zaip-skill-api-to-mcp/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +25 -9
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +2 -2
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +2 -2
- package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +15 -0
- package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +13 -5
- package/templates/.agents/skills/zaip-skill-data-analyst/SKILL.md +10 -5
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +5 -4
- package/templates/.agents/skills/zaip-skill-frontend-launcher/SKILL.md +4 -3
- package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +5 -3
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +78 -13
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +59 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/yaml-parser.mjs +157 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +11 -6
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +17 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +7 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-cloud-inputs.example.json +41 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-runner.md +84 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/operational-contract.md +19 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/SKILL.md +43 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/references/dotenv-resolution.md +47 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +8 -3
- package/templates/.agents/skills/zaip-skill-meta-ads/SKILL.md +16 -0
- package/templates/.agents/skills/zaip-skill-meta-ads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-ads/references/setup.md +3 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/SKILL.md +24 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/diagnostics.md +13 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/official-sources.md +10 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/upstream.md +77 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/upstream.md +126 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/upstream.md +67 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/upstream.md +69 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/upstream.md +79 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/upstream.md +144 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/upstream.md +83 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/SKILL.md +10 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/setup.md +11 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/upstream.md +55 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/upstream.md +56 -0
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +12 -7
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +11 -4
- package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +6 -4
- package/templates/.agents/skills/zaip-skill-tool-setup/references/codex-config.md +4 -2
- package/templates/.agents/skills/zaip-skill-tool-setup/references/secrets.md +1 -0
- package/templates/.agents/tools/catalog.yaml +6 -0
- package/templates/.agents/tools/cloud-runner-dns.mjs +28 -0
- package/templates/.agents/tools/cloud-runner-terraform.mjs +212 -0
- package/templates/.agents/tools/cloud-runner.integration.test.mjs +239 -0
- package/templates/.agents/tools/cloud-runner.mjs +786 -0
- package/templates/.agents/tools/cloud-runner.test.mjs +534 -0
- package/templates/.agents/tools/cloud-terraform-plan-policy.mjs +262 -0
- package/templates/.agents/tools/mcp/development/meta-devtools/README.md +14 -0
- package/templates/.agents/tools/mcp/development/meta-devtools/manifest.yaml +28 -0
- package/templates/.agents/tools/mcp/infra/cloudflare/manifest.yaml +2 -3
- package/templates/.agents/tools/mcp/infra/hostinger/manifest.yaml +1 -3
- package/templates/.agents/tools/mcp/marketing/meta-ads/README.md +15 -13
- package/templates/.agents/tools/mcp/marketing/meta-ads/manifest.yaml +15 -10
- package/templates/.agents/tools/profiles/development.yaml +3 -0
- package/templates/infra/terraform/.terraform.lock.hcl +42 -0
- package/templates/infra/terraform/README.md +31 -0
- package/templates/infra/terraform/backend.tf.json +13 -0
- package/templates/infra/terraform/deployment-inputs.example.yaml +22 -0
- package/templates/infra/terraform/fixtures/approved-targets.json +32 -0
- package/templates/infra/terraform/fixtures/plan-approved.json +67 -0
- package/templates/infra/terraform/main.tf +77 -0
- package/templates/infra/terraform/outputs.tf +20 -0
- package/templates/infra/terraform/terraform.tfvars.example +26 -0
- package/templates/infra/terraform/variables.tf +91 -0
- package/templates/infra/terraform/versions.tf +18 -0
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +89 -0
- package/templates/scripts/validate-cloud-terraform-plan.mjs +1 -0
- package/templates/template-manifest.json +599 -167
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BwnJpl02.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-C09KmlSw.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dyo_wpL4.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-hPPfVGQv.css +0 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-stale-seed.ts +0 -50
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-projection.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
|
|
3
|
+
// Expand the persisted usage payloads once so the join can use an automatic
|
|
4
|
+
// index instead of decoding every historical segment for each invocation.
|
|
5
|
+
export const costInvocationProjectionSelect = `WITH usage AS MATERIALIZED (SELECT * FROM invocation_usage)
|
|
6
|
+
SELECT i.*,
|
|
7
|
+
COUNT(u.usage_index) AS pricing_segment_count,
|
|
8
|
+
CASE WHEN COUNT(DISTINCT COALESCE(u.provider, '') || '|' || COALESCE(u.model, '') || '|' || COALESCE(u.service_tier, 'default') || '|' || COALESCE(CAST(u.context_input_multiplier AS TEXT), '') || '|' || COALESCE(CAST(u.context_output_multiplier AS TEXT), '')) > 1 THEN 1 ELSE 0 END AS pricing_mixed,
|
|
9
|
+
SUM(u.uncached_input_tokens) AS uncached_input_tokens,
|
|
10
|
+
SUM(u.visible_output_tokens) AS visible_output_tokens,
|
|
11
|
+
CASE COUNT(DISTINCT u.input_rate_usd_per_million) WHEN 1 THEN MIN(u.input_rate_usd_per_million) ELSE NULL END AS input_rate_usd_per_million,
|
|
12
|
+
CASE COUNT(DISTINCT u.cached_input_rate_usd_per_million) WHEN 1 THEN MIN(u.cached_input_rate_usd_per_million) ELSE NULL END AS cached_input_rate_usd_per_million,
|
|
13
|
+
CASE COUNT(DISTINCT u.output_rate_usd_per_million) WHEN 1 THEN MIN(u.output_rate_usd_per_million) ELSE NULL END AS output_rate_usd_per_million,
|
|
14
|
+
CASE COUNT(DISTINCT u.reasoning_rate_usd_per_million) WHEN 1 THEN MIN(u.reasoning_rate_usd_per_million) ELSE NULL END AS reasoning_rate_usd_per_million,
|
|
15
|
+
CASE COUNT(DISTINCT u.context_input_multiplier) WHEN 1 THEN MIN(u.context_input_multiplier) ELSE NULL END AS context_input_multiplier,
|
|
16
|
+
CASE COUNT(DISTINCT u.context_output_multiplier) WHEN 1 THEN MIN(u.context_output_multiplier) ELSE NULL END AS context_output_multiplier,
|
|
17
|
+
CASE COUNT(DISTINCT u.speed_cost_multiplier) WHEN 1 THEN MIN(u.speed_cost_multiplier) ELSE NULL END AS speed_cost_multiplier,
|
|
18
|
+
CASE COUNT(DISTINCT u.pricing_scenario) WHEN 1 THEN MIN(u.pricing_scenario) ELSE 'mixed' END AS pricing_scenario,
|
|
19
|
+
SUM(u.standard_cost_usd) AS standard_cost_usd,
|
|
20
|
+
SUM(u.speed_uplift_usd) AS speed_uplift_usd,
|
|
21
|
+
SUM(u.input_cost_usd) AS input_cost_usd,
|
|
22
|
+
SUM(u.cached_input_cost_usd) AS cached_input_cost_usd,
|
|
23
|
+
SUM(u.output_cost_usd) AS output_cost_usd,
|
|
24
|
+
SUM(u.reasoning_cost_usd) AS reasoning_cost_usd,
|
|
25
|
+
SUM(u.calculated_cost_usd) AS calculated_cost_usd,
|
|
26
|
+
SUM(u.recorded_cost_usd) AS recorded_cost_usd,
|
|
27
|
+
CASE COUNT(DISTINCT CASE WHEN u.recorded_cost_usd IS NOT NULL THEN u.fx_rate END)
|
|
28
|
+
WHEN 1 THEN MIN(CASE WHEN u.recorded_cost_usd IS NOT NULL THEN u.fx_rate END)
|
|
29
|
+
ELSE NULL
|
|
30
|
+
END AS recorded_fx_rate,
|
|
31
|
+
SUM(CASE WHEN u.recorded_cost_usd IS NOT NULL THEN u.cost_brl END) AS recorded_brl,
|
|
32
|
+
(SELECT json_extract(fx.content, '$.rate')
|
|
33
|
+
FROM files fx
|
|
34
|
+
WHERE fx.path LIKE '.agents/config/pricing/fx/%.json'
|
|
35
|
+
ORDER BY CASE WHEN fx.path LIKE '%/current-usd-brl.json' THEN 0 ELSE 1 END,
|
|
36
|
+
json_extract(fx.content, '$.as_of') DESC
|
|
37
|
+
LIMIT 1) AS current_fx_rate,
|
|
38
|
+
SUM(u.cost_variance_usd) AS cost_variance_usd,
|
|
39
|
+
CASE COUNT(DISTINCT u.pricing_model) WHEN 1 THEN MIN(u.pricing_model) ELSE NULL END AS audit_pricing_model,
|
|
40
|
+
CASE COUNT(DISTINCT u.pricing_source) WHEN 1 THEN MIN(u.pricing_source) ELSE NULL END AS audit_pricing_source
|
|
41
|
+
FROM invocations i LEFT JOIN usage u USING(agent_invocation_id)
|
|
42
|
+
GROUP BY i.agent_invocation_id`;
|
|
43
|
+
|
|
44
|
+
export function readCostInvocationProjection(
|
|
45
|
+
database: DatabaseSync,
|
|
46
|
+
): Array<Record<string, unknown>> {
|
|
47
|
+
const sql = costInvocationProjectionSelect
|
|
48
|
+
.replaceAll(/\binvocation_usage\b/g, "zaip_vw_invocation_usage")
|
|
49
|
+
.replaceAll(/\binvocations\b/g, "zaip_vw_invocations")
|
|
50
|
+
.replaceAll(/\bfiles\b/g, "zaip_vw_files");
|
|
51
|
+
return database.prepare(sql).all() as Array<Record<string, unknown>>;
|
|
52
|
+
}
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts
CHANGED
|
@@ -96,20 +96,8 @@ export function persistFirstFoldPayloads(
|
|
|
96
96
|
for (const path of paths) {
|
|
97
97
|
const database = new DatabaseSync(path);
|
|
98
98
|
try {
|
|
99
|
-
const insert = database.prepare(`INSERT INTO zaip_aios_activities(
|
|
100
|
-
activity_row_id, activity_source_kind, activity_key, source_path, source_hash,
|
|
101
|
-
recorded_at, run_role, root_run_id, payload_type, payload_json
|
|
102
|
-
) VALUES (?, 'technical_payload', ?, ?, '', datetime('now'), 'technical', 'technical', ?, ?)`);
|
|
103
99
|
database.exec("BEGIN;");
|
|
104
|
-
|
|
105
|
-
insert.run(
|
|
106
|
-
`TECH-${randomUUID().toLowerCase()}`,
|
|
107
|
-
key,
|
|
108
|
-
`sqlite://${payloadType}/${key.split(":")[1]}`,
|
|
109
|
-
payloadType,
|
|
110
|
-
payloads[payloadType],
|
|
111
|
-
);
|
|
112
|
-
}
|
|
100
|
+
persistFirstFoldPayloadsInDatabase(database, payloads);
|
|
113
101
|
database.exec("COMMIT;");
|
|
114
102
|
} catch (error) {
|
|
115
103
|
database.exec("ROLLBACK;");
|
|
@@ -119,3 +107,37 @@ export function persistFirstFoldPayloads(
|
|
|
119
107
|
}
|
|
120
108
|
}
|
|
121
109
|
}
|
|
110
|
+
|
|
111
|
+
/** Adds first-fold payloads to the caller's current transaction. */
|
|
112
|
+
export function persistFirstFoldPayloadsInDatabase(
|
|
113
|
+
database: DatabaseSync,
|
|
114
|
+
payloads: FirstFoldPayloads,
|
|
115
|
+
): void {
|
|
116
|
+
const insert = database.prepare(`INSERT INTO zaip_aios_activities(
|
|
117
|
+
activity_row_id, activity_source_kind, activity_key, source_path, source_hash,
|
|
118
|
+
recorded_at, run_role, root_run_id, payload_type, payload_json
|
|
119
|
+
) VALUES (?, 'technical_payload', ?, ?, '', datetime('now'), 'technical', 'technical', ?, ?)`);
|
|
120
|
+
for (const [payloadType, key] of technicalPayloads) {
|
|
121
|
+
const existing = database
|
|
122
|
+
.prepare(
|
|
123
|
+
"SELECT activity_row_id,payload_json FROM zaip_aios_activities WHERE payload_type=? AND activity_key=?",
|
|
124
|
+
)
|
|
125
|
+
.get(payloadType, key) as { activity_row_id: string; payload_json: string } | undefined;
|
|
126
|
+
if (existing) {
|
|
127
|
+
if (existing.payload_json !== payloads[payloadType])
|
|
128
|
+
database
|
|
129
|
+
.prepare(
|
|
130
|
+
"UPDATE zaip_aios_activities SET payload_json=?,recorded_at=datetime('now') WHERE activity_row_id=?",
|
|
131
|
+
)
|
|
132
|
+
.run(payloads[payloadType], existing.activity_row_id);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
insert.run(
|
|
136
|
+
`TECH-${randomUUID().toLowerCase()}`,
|
|
137
|
+
key,
|
|
138
|
+
`sqlite://${payloadType}/${key.split(":")[1]}`,
|
|
139
|
+
payloadType,
|
|
140
|
+
payloads[payloadType],
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { DatabaseSync } from "node:sqlite";
|
|
4
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { rebuildSqliteReadModel } from "./sqlite-read-model.js";
|
|
6
|
+
|
|
7
|
+
const roots: string[] = [];
|
|
8
|
+
|
|
9
|
+
async function fixture(): Promise<string> {
|
|
10
|
+
const directory = resolve(import.meta.dirname, "../../../../..", ".local/sqlite/tests");
|
|
11
|
+
await mkdir(directory, { recursive: true });
|
|
12
|
+
const root = await mkdtemp(join(directory, "force-canonical-"));
|
|
13
|
+
roots.push(root);
|
|
14
|
+
await mkdir(join(root, ".agents/config"), { recursive: true });
|
|
15
|
+
await writeFile(join(root, ".agents/config/project.yaml"), "zaip:\n enabled: true\n");
|
|
16
|
+
return root;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
afterEach(async () => {
|
|
20
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("forceCanonical SQLite refresh", () => {
|
|
24
|
+
it("bypasses a healthy generation and verifies canonical sources again", async () => {
|
|
25
|
+
const root = await fixture();
|
|
26
|
+
const initial = await rebuildSqliteReadModel(root);
|
|
27
|
+
await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({
|
|
28
|
+
cache: "generation",
|
|
29
|
+
refresh: { processed_sources: 0 },
|
|
30
|
+
});
|
|
31
|
+
await expect(rebuildSqliteReadModel(root, { forceCanonical: true })).resolves.toMatchObject({
|
|
32
|
+
cache: "rebuilt",
|
|
33
|
+
path: initial.path,
|
|
34
|
+
refresh: { processed_sources: 1 },
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("rebuilds a generation whose persisted schema marker is incompatible", async () => {
|
|
39
|
+
const root = await fixture();
|
|
40
|
+
const initial = await rebuildSqliteReadModel(root);
|
|
41
|
+
const database = new DatabaseSync(initial.path);
|
|
42
|
+
try {
|
|
43
|
+
database
|
|
44
|
+
.prepare(
|
|
45
|
+
"UPDATE zaip_aios_activities SET payload_json=json_set(payload_json, '$.value', 'invalid') WHERE payload_type='metadata' AND activity_key='metadata:schema_version'",
|
|
46
|
+
)
|
|
47
|
+
.run();
|
|
48
|
+
} finally {
|
|
49
|
+
database.close();
|
|
50
|
+
}
|
|
51
|
+
await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({
|
|
52
|
+
cache: "rebuilt",
|
|
53
|
+
path: initial.path,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.test.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { affectedTemporalIntervals } from "./sqlite-incremental-cache.js";
|
|
3
|
+
|
|
4
|
+
describe("temporal delta dependencies", () => {
|
|
5
|
+
it("includes old overlap neighbors after removal while excluding disjoint history", () => {
|
|
6
|
+
const old = [
|
|
7
|
+
{ activityRowId: "removed", startMs: 10, endMs: 20 },
|
|
8
|
+
{ activityRowId: "neighbor", startMs: 18, endMs: 30 },
|
|
9
|
+
{ activityRowId: "chain", startMs: 29, endMs: 40 },
|
|
10
|
+
{ activityRowId: "untouched", startMs: 100, endMs: 120 },
|
|
11
|
+
];
|
|
12
|
+
const result = affectedTemporalIntervals(old, old.slice(1), new Set(["removed"]));
|
|
13
|
+
expect([...result.ids].sort()).toEqual(["chain", "neighbor", "removed"]);
|
|
14
|
+
expect(result.intervals.map((row) => row.activityRowId)).toEqual(["neighbor", "chain"]);
|
|
15
|
+
});
|
|
16
|
+
it("covers both old and new components of a moved interval without crossing a gap", () => {
|
|
17
|
+
const history = [
|
|
18
|
+
{ activityRowId: "old-neighbor", startMs: 0, endMs: 10 },
|
|
19
|
+
{ activityRowId: "gap", startMs: 30, endMs: 40 },
|
|
20
|
+
{ activityRowId: "new-neighbor", startMs: 100, endMs: 110 },
|
|
21
|
+
];
|
|
22
|
+
const result = affectedTemporalIntervals(
|
|
23
|
+
[...history, { activityRowId: "moved", startMs: 5, endMs: 15 }],
|
|
24
|
+
[...history, { activityRowId: "moved", startMs: 105, endMs: 115 }],
|
|
25
|
+
new Set(["moved"]),
|
|
26
|
+
);
|
|
27
|
+
expect([...result.ids].sort()).toEqual(["moved", "new-neighbor", "old-neighbor"]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
3
|
+
|
|
4
|
+
/** Parsed canonical records survive worker restarts in the same transaction as their facts. */
|
|
5
|
+
export class SqliteParsedSourceCache {
|
|
6
|
+
constructor(private readonly database: DatabaseSync) {}
|
|
7
|
+
|
|
8
|
+
read<T>(kind: string, path: string, hash: string, parse: () => T): T {
|
|
9
|
+
const key = `parsed_source:${kind}:${path}`;
|
|
10
|
+
const cached = this.database
|
|
11
|
+
.prepare(
|
|
12
|
+
"SELECT source_hash, payload_json FROM zaip_aios_activities WHERE payload_type='parsed_source' AND activity_key=?",
|
|
13
|
+
)
|
|
14
|
+
.get(key) as { source_hash: string; payload_json: string } | undefined;
|
|
15
|
+
if (cached?.source_hash === hash) {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.parse(cached.payload_json) as T;
|
|
18
|
+
} catch {
|
|
19
|
+
/* A damaged derived cache is repaired from this source only. */
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const value = parse();
|
|
23
|
+
this.database
|
|
24
|
+
.prepare(
|
|
25
|
+
"DELETE FROM zaip_aios_activities WHERE payload_type='parsed_source' AND activity_key=?",
|
|
26
|
+
)
|
|
27
|
+
.run(key);
|
|
28
|
+
this.database
|
|
29
|
+
.prepare(`INSERT INTO zaip_aios_activities(
|
|
30
|
+
activity_row_id, activity_source_kind, activity_key, source_path, source_hash,
|
|
31
|
+
recorded_at, run_role, root_run_id, payload_type, payload_json
|
|
32
|
+
) VALUES (?, 'technical_payload', ?, ?, ?, ?, 'technical', 'technical', 'parsed_source', ?)`)
|
|
33
|
+
.run(
|
|
34
|
+
`TECH-${randomUUID()}`,
|
|
35
|
+
key,
|
|
36
|
+
path,
|
|
37
|
+
hash,
|
|
38
|
+
new Date().toISOString(),
|
|
39
|
+
JSON.stringify(value),
|
|
40
|
+
);
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export type CachedTemporalInterval = { activityRowId: string; startMs: number; endMs: number };
|
|
46
|
+
|
|
47
|
+
/** Upserts changed derived rows while keeping untouched row identities and processing timestamps. */
|
|
48
|
+
export type IncrementalPayloadRow = {
|
|
49
|
+
row_key: string;
|
|
50
|
+
payload_json: string;
|
|
51
|
+
occurred_day_sp?: string | null;
|
|
52
|
+
};
|
|
53
|
+
export function synchronizePayloadRows(
|
|
54
|
+
database: DatabaseSync,
|
|
55
|
+
type: string,
|
|
56
|
+
select: string | readonly IncrementalPayloadRow[],
|
|
57
|
+
): void {
|
|
58
|
+
const previous = new Map(
|
|
59
|
+
(
|
|
60
|
+
database
|
|
61
|
+
.prepare(
|
|
62
|
+
"SELECT activity_row_id,activity_key,payload_json FROM zaip_aios_activities WHERE payload_type=?",
|
|
63
|
+
)
|
|
64
|
+
.all(type) as Array<{ activity_row_id: string; activity_key: string; payload_json: string }>
|
|
65
|
+
).map((row) => [row.activity_key, row]),
|
|
66
|
+
);
|
|
67
|
+
const insert = database.prepare(`INSERT INTO zaip_aios_activities(
|
|
68
|
+
activity_row_id,activity_source_kind,activity_key,source_path,source_hash,recorded_at,run_role,root_run_id,payload_type,payload_json,occurred_day_sp
|
|
69
|
+
) VALUES (?,'technical_payload',?,?,'',?,'technical','technical',?,?,?)`);
|
|
70
|
+
const update = database.prepare(
|
|
71
|
+
"UPDATE zaip_aios_activities SET payload_json=?,recorded_at=?,occurred_day_sp=? WHERE activity_row_id=?",
|
|
72
|
+
);
|
|
73
|
+
const remove = database.prepare("DELETE FROM zaip_aios_activities WHERE activity_row_id=?");
|
|
74
|
+
const rows =
|
|
75
|
+
typeof select === "string"
|
|
76
|
+
? (database.prepare(select).all() as IncrementalPayloadRow[])
|
|
77
|
+
: select;
|
|
78
|
+
for (const row of rows) {
|
|
79
|
+
const key = `${type}:${row.row_key}`;
|
|
80
|
+
const old = previous.get(key);
|
|
81
|
+
let payload = row.payload_json;
|
|
82
|
+
if (type === "source_state" && old) {
|
|
83
|
+
const value = JSON.parse(payload);
|
|
84
|
+
const original = JSON.parse(old.payload_json);
|
|
85
|
+
if (value.source_hash === original.source_hash)
|
|
86
|
+
value.last_processed_at = original.last_processed_at;
|
|
87
|
+
payload = JSON.stringify(value);
|
|
88
|
+
}
|
|
89
|
+
if (!old)
|
|
90
|
+
insert.run(
|
|
91
|
+
`TECH-${randomUUID()}`,
|
|
92
|
+
key,
|
|
93
|
+
`sqlite://${type}`,
|
|
94
|
+
new Date().toISOString(),
|
|
95
|
+
type,
|
|
96
|
+
payload,
|
|
97
|
+
row.occurred_day_sp ?? null,
|
|
98
|
+
);
|
|
99
|
+
else if (payload !== old.payload_json)
|
|
100
|
+
update.run(
|
|
101
|
+
payload,
|
|
102
|
+
new Date().toISOString(),
|
|
103
|
+
row.occurred_day_sp ?? null,
|
|
104
|
+
old.activity_row_id,
|
|
105
|
+
);
|
|
106
|
+
previous.delete(key);
|
|
107
|
+
}
|
|
108
|
+
for (const row of previous.values()) remove.run(row.activity_row_id);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Include the connected old/new overlap component so neighbors are recalculated consistently. */
|
|
112
|
+
export function affectedTemporalIntervals(
|
|
113
|
+
oldIntervals: readonly CachedTemporalInterval[],
|
|
114
|
+
newIntervals: readonly CachedTemporalInterval[],
|
|
115
|
+
dirtyIds: ReadonlySet<string>,
|
|
116
|
+
): { ids: Set<string>; intervals: CachedTemporalInterval[] } {
|
|
117
|
+
const ids = new Set(dirtyIds);
|
|
118
|
+
const ranges = [...oldIntervals, ...newIntervals].filter((interval) =>
|
|
119
|
+
ids.has(interval.activityRowId),
|
|
120
|
+
);
|
|
121
|
+
let changed = true;
|
|
122
|
+
while (changed) {
|
|
123
|
+
changed = false;
|
|
124
|
+
for (const interval of newIntervals) {
|
|
125
|
+
if (ids.has(interval.activityRowId)) continue;
|
|
126
|
+
if (
|
|
127
|
+
ranges.some((range) => interval.startMs < range.endMs && interval.endMs > range.startMs)
|
|
128
|
+
) {
|
|
129
|
+
ids.add(interval.activityRowId);
|
|
130
|
+
ranges.push(interval);
|
|
131
|
+
changed = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return { ids, intervals: newIntervals.filter((interval) => ids.has(interval.activityRowId)) };
|
|
136
|
+
}
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { DatabaseSync } from "node:sqlite";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import * as decisions from "../../../../../packages/decisions/src/index.js";
|
|
6
|
+
import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
7
|
+
import { prepareMultiProviderFixture } from "./sqlite-read-model-multi-provider-fixture.js";
|
|
8
|
+
|
|
9
|
+
const roots: string[] = [];
|
|
10
|
+
async function fixture() {
|
|
11
|
+
const directory = resolve(import.meta.dirname, "../../../../..", ".local/sqlite/tests");
|
|
12
|
+
await mkdir(directory, { recursive: true });
|
|
13
|
+
const root = await mkdtemp(join(directory, "incremental-"));
|
|
14
|
+
roots.push(root);
|
|
15
|
+
return root;
|
|
16
|
+
}
|
|
17
|
+
function inspect(path: string, sql: string) {
|
|
18
|
+
const database = new DatabaseSync(path, { readOnly: true });
|
|
19
|
+
try {
|
|
20
|
+
return database.prepare(sql).all();
|
|
21
|
+
} finally {
|
|
22
|
+
database.close();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const historySql = `SELECT activity_row_id, activity_key, payload_json FROM zaip_aios_activities
|
|
26
|
+
WHERE activity_key IN ('file:.agents/records/runs/2026/08/RUN-UNASSISTED.jsonl',
|
|
27
|
+
'source_state:.agents/records/runs/2026/08/RUN-UNASSISTED.jsonl') ORDER BY activity_key`;
|
|
28
|
+
|
|
29
|
+
async function expectFullParity(root: string) {
|
|
30
|
+
const baseline = await fixture();
|
|
31
|
+
await cp(join(root, ".agents"), join(baseline, ".agents"), { recursive: true });
|
|
32
|
+
const baselineBuild = await rebuildSqliteReadModel(baseline, { forceCanonical: true });
|
|
33
|
+
const incremental = new SqliteReadModelFileSystem(root);
|
|
34
|
+
const complete = new SqliteReadModelFileSystem(baseline);
|
|
35
|
+
try {
|
|
36
|
+
for (const view of [
|
|
37
|
+
"cost_monitor_daily",
|
|
38
|
+
"cost_monitor_models",
|
|
39
|
+
"cost_monitor_providers",
|
|
40
|
+
"cost_monitor_tasks",
|
|
41
|
+
"cost_monitor_specs",
|
|
42
|
+
"cost_monitor_prds",
|
|
43
|
+
"operations_work_list",
|
|
44
|
+
] as const) {
|
|
45
|
+
expect(incremental.viewPage(view, { limit: 100 }), view).toEqual(
|
|
46
|
+
complete.viewPage(view, { limit: 100 }),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const databasePath = join(root, ".local/sqlite/zaip-aios-dashboard.sqlite");
|
|
50
|
+
expect(
|
|
51
|
+
inspect(databasePath, "SELECT * FROM developer_cost_projection ORDER BY account_id"),
|
|
52
|
+
).toEqual(
|
|
53
|
+
inspect(baselineBuild.path, "SELECT * FROM developer_cost_projection ORDER BY account_id"),
|
|
54
|
+
);
|
|
55
|
+
const facts =
|
|
56
|
+
"SELECT run_id,root_run_id,parent_run_id,activity_key,work_item_kind,title,work_item_status,work_stage,risk,duration_ms,cost_usd,cost_brl,total_tokens FROM zaip_aios_activities WHERE payload_type IS NULL OR payload_type='shared_creation_allocation' ORDER BY activity_key";
|
|
57
|
+
expect(inspect(databasePath, facts)).toEqual(inspect(baselineBuild.path, facts));
|
|
58
|
+
} finally {
|
|
59
|
+
incremental.close();
|
|
60
|
+
complete.close();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
afterEach(async () => {
|
|
65
|
+
vi.useRealTimers();
|
|
66
|
+
vi.restoreAllMocks();
|
|
67
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe("incremental refresh preserves historical facts", () => {
|
|
71
|
+
it("refreshes developer delivery and shared SPEC allocation from cached Run facts", async () => {
|
|
72
|
+
const root = await fixture();
|
|
73
|
+
await prepareMultiProviderFixture(root);
|
|
74
|
+
const runPath = join(root, ".agents/records/runs/2026/08/RUN-MULTI.jsonl");
|
|
75
|
+
const records = (await readFile(runPath, "utf8"))
|
|
76
|
+
.trim()
|
|
77
|
+
.split("\n")
|
|
78
|
+
.map((line) => JSON.parse(line));
|
|
79
|
+
records[0].developer_identity = {
|
|
80
|
+
schema_version: 1,
|
|
81
|
+
provider: "github",
|
|
82
|
+
account_id: "42",
|
|
83
|
+
login_snapshot: "dev-fixture",
|
|
84
|
+
verified_at: "2026-08-04T12:00:00.000Z",
|
|
85
|
+
attribution_source: "verified_local_account",
|
|
86
|
+
};
|
|
87
|
+
await writeFile(runPath, records.map((row) => JSON.stringify(row)).join("\n") + "\n");
|
|
88
|
+
await rebuildSqliteReadModel(root);
|
|
89
|
+
await mkdir(join(root, ".agents/records/tasks"), { recursive: true });
|
|
90
|
+
await mkdir(join(root, ".agents/records/specs"), { recursive: true });
|
|
91
|
+
const task = join(root, ".agents/records/tasks/TASK-MULTI.md");
|
|
92
|
+
const spec = (id: string) =>
|
|
93
|
+
`---\nid: ${id}\ntitle: ${id}\nstatus: completed\ncreation_run_id: RUN-MULTI\ncreated_at: 2026-08-04T12:00:00.000Z\n---\n`;
|
|
94
|
+
await writeFile(
|
|
95
|
+
task,
|
|
96
|
+
"---\nid: TASK-MULTI\ntitle: Delivered task\nstatus: completed\ncompleted_run_id: RUN-MULTI\ncreated_at: 2026-08-04T12:00:00.000Z\n---\n",
|
|
97
|
+
);
|
|
98
|
+
const a = join(root, ".agents/records/specs/SPEC-A.md");
|
|
99
|
+
const b = join(root, ".agents/records/specs/SPEC-B.md");
|
|
100
|
+
await writeFile(a, spec("SPEC-A"));
|
|
101
|
+
const spy = vi.spyOn(decisions, "foldRunV2Records");
|
|
102
|
+
await rebuildSqliteReadModel(root);
|
|
103
|
+
expect(spy.mock.calls.length).toBe(0);
|
|
104
|
+
await expectFullParity(root);
|
|
105
|
+
spy.mockClear();
|
|
106
|
+
await writeFile(b, spec("SPEC-B"));
|
|
107
|
+
await rebuildSqliteReadModel(root);
|
|
108
|
+
expect(spy.mock.calls.length).toBe(0);
|
|
109
|
+
await expectFullParity(root);
|
|
110
|
+
spy.mockClear();
|
|
111
|
+
await rm(a);
|
|
112
|
+
await rm(task);
|
|
113
|
+
await rebuildSqliteReadModel(root);
|
|
114
|
+
expect(spy.mock.calls.length).toBe(0);
|
|
115
|
+
await expectFullParity(root);
|
|
116
|
+
}, 120_000);
|
|
117
|
+
|
|
118
|
+
it("updates and removes changed sources in place with full-build query parity and untouched historical payloads", async () => {
|
|
119
|
+
const root = await fixture();
|
|
120
|
+
const { started, usage, finished } = await prepareMultiProviderFixture(root);
|
|
121
|
+
const first = await rebuildSqliteReadModel(root);
|
|
122
|
+
const history = inspect(first.path, historySql);
|
|
123
|
+
expect(history).toHaveLength(2);
|
|
124
|
+
const schema = inspect(first.path, "PRAGMA schema_version");
|
|
125
|
+
const fold = vi.spyOn(decisions, "foldRunV2Records");
|
|
126
|
+
const exec = DatabaseSync.prototype.exec;
|
|
127
|
+
vi.spyOn(DatabaseSync.prototype, "exec").mockImplementation(function (
|
|
128
|
+
this: DatabaseSync,
|
|
129
|
+
sql: string,
|
|
130
|
+
) {
|
|
131
|
+
const result = exec.call(this, sql);
|
|
132
|
+
if (
|
|
133
|
+
sql.includes("BEGIN IMMEDIATE") &&
|
|
134
|
+
this.prepare("SELECT 1 FROM sqlite_master WHERE name='zaip_aios_activities'").get()
|
|
135
|
+
) {
|
|
136
|
+
// A historical activity outside the changed interval must not be
|
|
137
|
+
// deleted/reinserted or updated just because a different source changed.
|
|
138
|
+
for (const action of ["DELETE", "UPDATE"])
|
|
139
|
+
exec.call(
|
|
140
|
+
this,
|
|
141
|
+
`
|
|
142
|
+
CREATE TEMP TRIGGER protect_history_${action} BEFORE ${action} ON main.zaip_aios_activities
|
|
143
|
+
WHEN OLD.payload_type IS NULL AND OLD.run_id='RUN-UNAVAILABLE'
|
|
144
|
+
BEGIN SELECT RAISE(ABORT, 'unaffected historical activity was rewritten'); END;
|
|
145
|
+
`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
});
|
|
150
|
+
const unchanged = await rebuildSqliteReadModel(root);
|
|
151
|
+
expect(unchanged).toMatchObject({
|
|
152
|
+
cache: "generation",
|
|
153
|
+
refresh: { processed_sources: 0, canonical_runs_refolded: 0 },
|
|
154
|
+
});
|
|
155
|
+
expect(fold.mock.calls.length).toBe(0);
|
|
156
|
+
const task = join(root, ".agents/records/tasks/TASK-MULTI.md");
|
|
157
|
+
await mkdir(join(root, ".agents/records/tasks"), { recursive: true });
|
|
158
|
+
await writeFile(
|
|
159
|
+
task,
|
|
160
|
+
"---\nid: TASK-MULTI\ntitle: Incremental task\nstatus: completed\ncreated_at: 2026-08-04T12:00:00.000Z\n---\n",
|
|
161
|
+
);
|
|
162
|
+
await rebuildSqliteReadModel(root);
|
|
163
|
+
expect(fold.mock.calls.length).toBe(0);
|
|
164
|
+
expect(inspect(first.path, "PRAGMA schema_version")).toEqual(schema);
|
|
165
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
166
|
+
await expectFullParity(root);
|
|
167
|
+
fold.mockClear();
|
|
168
|
+
|
|
169
|
+
// This new Run overlaps an existing interval. Both activities' allocated
|
|
170
|
+
// duration must agree with a fresh calculation without rereading other Runs.
|
|
171
|
+
const newRun = join(root, ".agents/records/runs/2026/08/RUN-NEW.jsonl");
|
|
172
|
+
const rows = [started, usage(2, "openai", "gpt-a", 100, 50), { ...finished, sequence: 3 }].map(
|
|
173
|
+
(row, index) => ({
|
|
174
|
+
...row,
|
|
175
|
+
run_id: "RUN-NEW",
|
|
176
|
+
event_id: `RUN-NEW:${index + 1}`,
|
|
177
|
+
...(index === 0
|
|
178
|
+
? { agent_invocation_id: "AINV-NEW", root_agent_invocation_id: "AINV-NEW" }
|
|
179
|
+
: {}),
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
182
|
+
await writeFile(newRun, `${rows.map((row) => JSON.stringify(row)).join("\n")}\n`);
|
|
183
|
+
await rebuildSqliteReadModel(root);
|
|
184
|
+
expect(fold.mock.calls.length).toBe(1);
|
|
185
|
+
expect(inspect(first.path, "PRAGMA schema_version")).toEqual(schema);
|
|
186
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
187
|
+
await expectFullParity(root);
|
|
188
|
+
fold.mockClear();
|
|
189
|
+
const editedRun = join(root, ".agents/records/runs/2026/08/RUN-MULTI.jsonl");
|
|
190
|
+
const editedRows = (await readFile(editedRun, "utf8"))
|
|
191
|
+
.trim()
|
|
192
|
+
.split("\n")
|
|
193
|
+
.map((line) => JSON.parse(line));
|
|
194
|
+
editedRows[1].tokens.input += 10;
|
|
195
|
+
editedRows[1].tokens.total += 10;
|
|
196
|
+
await writeFile(editedRun, `${editedRows.map((row) => JSON.stringify(row)).join("\n")}\n`);
|
|
197
|
+
await rebuildSqliteReadModel(root);
|
|
198
|
+
expect(fold.mock.calls.length).toBe(1);
|
|
199
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
200
|
+
await expectFullParity(root);
|
|
201
|
+
fold.mockClear();
|
|
202
|
+
await rm(newRun);
|
|
203
|
+
await rm(task);
|
|
204
|
+
await rebuildSqliteReadModel(root);
|
|
205
|
+
expect(fold.mock.calls.length).toBe(0);
|
|
206
|
+
expect(inspect(first.path, "PRAGMA schema_version")).toEqual(schema);
|
|
207
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
208
|
+
await expectFullParity(root);
|
|
209
|
+
}, 120_000);
|
|
210
|
+
|
|
211
|
+
it("preserves historical checkpoints on the day boundary and rolls back failed delta publication", async () => {
|
|
212
|
+
const root = await fixture();
|
|
213
|
+
await prepareMultiProviderFixture(root);
|
|
214
|
+
vi.useFakeTimers({ toFake: ["Date"] });
|
|
215
|
+
vi.setSystemTime(new Date("2026-09-05T02:59:00Z"));
|
|
216
|
+
const first = await rebuildSqliteReadModel(root);
|
|
217
|
+
const history = inspect(first.path, historySql);
|
|
218
|
+
const schema = inspect(first.path, "PRAGMA schema_version");
|
|
219
|
+
vi.setSystemTime(new Date("2026-09-05T03:01:00Z"));
|
|
220
|
+
await rebuildSqliteReadModel(root);
|
|
221
|
+
expect(inspect(first.path, "PRAGMA schema_version")).toEqual(schema);
|
|
222
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
223
|
+
const path = join(root, ".agents/records/runs/2026/08/RUN-MULTI.jsonl");
|
|
224
|
+
const content = await readFile(path, "utf8");
|
|
225
|
+
await writeFile(path, content.replace('"brl":5,', '"brl":8,'));
|
|
226
|
+
const exec = DatabaseSync.prototype.exec;
|
|
227
|
+
vi.spyOn(DatabaseSync.prototype, "exec").mockImplementation(function (
|
|
228
|
+
this: DatabaseSync,
|
|
229
|
+
sql: string,
|
|
230
|
+
) {
|
|
231
|
+
if (sql.trim() === "COMMIT;") throw new Error("injected delta publication failure");
|
|
232
|
+
return exec.call(this, sql);
|
|
233
|
+
});
|
|
234
|
+
await expect(rebuildSqliteReadModel(root)).rejects.toThrow(
|
|
235
|
+
"injected delta publication failure",
|
|
236
|
+
);
|
|
237
|
+
vi.restoreAllMocks();
|
|
238
|
+
expect(inspect(first.path, "PRAGMA schema_version")).toEqual(schema);
|
|
239
|
+
expect(inspect(first.path, historySql)).toEqual(history);
|
|
240
|
+
const filesystem = new SqliteReadModelFileSystem(root);
|
|
241
|
+
try {
|
|
242
|
+
expect(await filesystem.readText(".agents/records/runs/2026/08/RUN-MULTI.jsonl")).toBe(
|
|
243
|
+
content,
|
|
244
|
+
);
|
|
245
|
+
} finally {
|
|
246
|
+
filesystem.close();
|
|
247
|
+
}
|
|
248
|
+
await rebuildSqliteReadModel(root);
|
|
249
|
+
await expectFullParity(root);
|
|
250
|
+
}, 120_000);
|
|
251
|
+
});
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts
CHANGED
|
@@ -2,14 +2,29 @@ import type { DatabaseSync } from "node:sqlite";
|
|
|
2
2
|
|
|
3
3
|
/** Persists the exact canonical Board summary so runtime pages never re-expand its lineage CTE. */
|
|
4
4
|
export function materializeOperationsWorkProjection(database: DatabaseSync): void {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const select = `
|
|
6
|
+
WITH changes AS MATERIALIZED (SELECT * FROM zaip_vw_canonical_changes),
|
|
7
|
+
work_items AS MATERIALIZED (SELECT * FROM zaip_vw_canonical_work_items),
|
|
8
|
+
fallback_changes AS MATERIALIZED (
|
|
9
|
+
SELECT task.value AS task_id, change.id,
|
|
10
|
+
ROW_NUMBER() OVER (PARTITION BY task.value ORDER BY change.created_at DESC, change.id DESC) AS preference
|
|
11
|
+
FROM changes change, json_each(change.task_ids_json) task
|
|
12
|
+
),
|
|
13
|
+
resolved AS MATERIALIZED (
|
|
14
|
+
SELECT canonical.*, COALESCE(canonical.change_id, fallback.id) AS resolved_change_id
|
|
15
|
+
FROM work_items canonical
|
|
16
|
+
LEFT JOIN fallback_changes fallback ON fallback.task_id=canonical.id AND fallback.preference=1
|
|
17
|
+
)
|
|
7
18
|
SELECT summary.*, canonical.stage, canonical.spec_id,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
CASE WHEN canonical.entity_kind='task' THEN CASE WHEN canonical.spec_id IS NOT NULL OR COALESCE((SELECT change.source_type FROM canonical_changes change WHERE change.id=COALESCE(canonical.change_id, (SELECT fallback.id FROM canonical_changes fallback, json_each(fallback.task_ids_json) task WHERE task.value=canonical.id ORDER BY fallback.created_at DESC, fallback.id DESC LIMIT 1))) IN ('spec','prd'), 0) THEN 'task' ELSE 'standalone-task' END ELSE canonical.entity_kind END AS kind
|
|
19
|
+
canonical.resolved_change_id AS change_id, change.source_type AS origin,
|
|
20
|
+
CASE WHEN canonical.entity_kind='task' THEN CASE WHEN canonical.spec_id IS NOT NULL OR COALESCE(change.source_type IN ('spec','prd'), 0) THEN 'task' ELSE 'standalone-task' END ELSE canonical.entity_kind END AS kind
|
|
11
21
|
FROM zaip_vw_operations_work_kanban summary
|
|
12
|
-
JOIN
|
|
13
|
-
|
|
22
|
+
JOIN resolved canonical ON canonical.entity_kind=summary.entity_kind AND canonical.id=summary.id
|
|
23
|
+
LEFT JOIN changes change ON change.id=canonical.resolved_change_id`;
|
|
24
|
+
database.exec(`
|
|
25
|
+
CREATE TABLE IF NOT EXISTS operations_work_projection AS ${select} LIMIT 0;
|
|
26
|
+
DELETE FROM operations_work_projection;
|
|
27
|
+
INSERT INTO operations_work_projection ${select};
|
|
28
|
+
CREATE INDEX IF NOT EXISTS operations_work_projection_order ON operations_work_projection(occurred_at DESC, id DESC);
|
|
14
29
|
`);
|
|
15
30
|
}
|
|
@@ -3,7 +3,7 @@ import { DatabaseSync } from "node:sqlite";
|
|
|
3
3
|
import { expect } from "vitest";
|
|
4
4
|
|
|
5
5
|
export function expectPersistedFirstFoldCaches(root: string, allTime: unknown, board: unknown) {
|
|
6
|
-
const database = new DatabaseSync(resolve(root, ".local/
|
|
6
|
+
const database = new DatabaseSync(resolve(root, ".local/sqlite/zaip-aios-dashboard.sqlite"), {
|
|
7
7
|
readOnly: true,
|
|
8
8
|
});
|
|
9
9
|
try {
|