@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
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
readProjectOverview,
|
|
35
35
|
readProjectSettings,
|
|
36
36
|
} from "./project-settings.js";
|
|
37
|
+
import { agentPortraitFiles, openWorkIds } from "./server-agent-assets.js";
|
|
37
38
|
import {
|
|
38
39
|
type BoardClassification,
|
|
39
40
|
boardFilters,
|
|
@@ -41,6 +42,7 @@ import {
|
|
|
41
42
|
boardStage,
|
|
42
43
|
classificationPage,
|
|
43
44
|
} from "./server-board.js";
|
|
45
|
+
import { registerBrowserLeaseRoute } from "./server-browser-lease.js";
|
|
44
46
|
import { registerDailyReadModelRoute } from "./server-daily-read-models-route.js";
|
|
45
47
|
import {
|
|
46
48
|
changeEntityPageRows,
|
|
@@ -64,11 +66,24 @@ import {
|
|
|
64
66
|
} from "./server-projections.js";
|
|
65
67
|
import { isAllowedDashboardAuthority } from "./server-request-authority.js";
|
|
66
68
|
import { refreshSqliteSnapshotInWorker } from "./server-snapshot-refresh.js";
|
|
69
|
+
import { readCommittedSnapshotRevision } from "./server-snapshot-revision.js";
|
|
70
|
+
import { startSnapshotSynchronization } from "./server-snapshot-synchronization.js";
|
|
67
71
|
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
72
|
+
import { writeReadModelStartup, writeStartupPhase } from "./server-startup.js";
|
|
68
73
|
import { queryValues, selectedCurrency } from "./server-summary-helpers.js";
|
|
74
|
+
import {
|
|
75
|
+
createWorkReconciliation,
|
|
76
|
+
reconciliationNeedsRefresh,
|
|
77
|
+
startHostTerminalReconciliation,
|
|
78
|
+
waitForWorkReconciliation,
|
|
79
|
+
} from "./server-work-reconciliation.js";
|
|
80
|
+
|
|
81
|
+
export { reconciliationNeedsRefresh } from "./server-work-reconciliation.js";
|
|
82
|
+
|
|
69
83
|
import {
|
|
70
84
|
dashboardIdentity,
|
|
71
85
|
dashboardWorkspaceKey,
|
|
86
|
+
ReconciliationCommandTimeoutError,
|
|
72
87
|
type ReconciliationResult,
|
|
73
88
|
reconcileOpenWork,
|
|
74
89
|
} from "./server-workspace.js";
|
|
@@ -79,6 +94,7 @@ import {
|
|
|
79
94
|
} from "./sqlite-read-model.js";
|
|
80
95
|
|
|
81
96
|
export { manifestRun, mergeManifestRuns } from "./manifest-runs.js";
|
|
97
|
+
export { openWorkIds } from "./server-agent-assets.js";
|
|
82
98
|
export { projectionPeriodFilter } from "./server-period.js";
|
|
83
99
|
export { projectAllTimeTopTasks } from "./server-period-macro-metric.js";
|
|
84
100
|
export {
|
|
@@ -94,10 +110,6 @@ export {
|
|
|
94
110
|
validateSqliteReadModelSchema,
|
|
95
111
|
} from "./sqlite-read-model.js";
|
|
96
112
|
|
|
97
|
-
export function reconciliationNeedsRefresh(result: ReconciliationResult): boolean {
|
|
98
|
-
return result.reconciled_ids.length > 0 || result.blocked.length > 0;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
113
|
type OverviewMacroMetrics = NonNullable<
|
|
102
114
|
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
103
115
|
>;
|
|
@@ -108,47 +120,6 @@ const RUNTIME_KIND = "zaip-dashboard-sqlite-runtime";
|
|
|
108
120
|
const SESSION_COOKIE = "zaip-dashboard-sqlite-session";
|
|
109
121
|
const WORK_PRIORITY_PATH = ".agents/dashboard/work-priority.json";
|
|
110
122
|
const SNAPSHOT_CACHE_TTL_MS = 5_000;
|
|
111
|
-
const agentPortraitFiles: Record<string, string> = {
|
|
112
|
-
"agent-orchestrator": "1 - Dave - Product Owner.png",
|
|
113
|
-
"agent-builder": "2 - Rafa - Tech Lead.png",
|
|
114
|
-
"agent-task-executor": "3 - Leo - Software Engineer.png",
|
|
115
|
-
"agent-analyst": "4 - Bia - Product Manager.png",
|
|
116
|
-
"agent-finalizer": "5 - Gui - Quality Assurance Lead.png",
|
|
117
|
-
"agent-reviewer": "6 - Nanda - Principal Engineer.png",
|
|
118
|
-
"agent-integrator": "7 - Dani - Integration Engineer.png",
|
|
119
|
-
"agent-auditor": "8 - Ana - Quality Auditor.png",
|
|
120
|
-
"agent-text-summarizer": "9 - Lia - Technical Writer.png",
|
|
121
|
-
"agent-data-analyst": "10 - Gabi - Data Analyst.png",
|
|
122
|
-
"agent-refactoring-specialist": "11 - Tati - Refactoring Specialist.png",
|
|
123
|
-
"agent-frontend": "12 - Doug - Frontend Developer.png",
|
|
124
|
-
"agent-backend": "13 - Will - Backend Developer.png",
|
|
125
|
-
"agent-website-developer": "14 - Jonny - Website Developer.png",
|
|
126
|
-
"agent-designer": "15 - Manu - Product Designer.png",
|
|
127
|
-
"agent-cloud-engineer": "16 - Dan - Cloud Engineer.png",
|
|
128
|
-
"agent-security-auditor": "17 - Luis - Security Auditor.png",
|
|
129
|
-
"agent-marketing-analyst": "18 - Lucia - Marketing Analyst.png",
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
interface ActiveWorkItem {
|
|
133
|
-
kind: string;
|
|
134
|
-
id: string;
|
|
135
|
-
status: string | null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** Pure lifecycle helper retained for callers; it never reads a runtime projection. */
|
|
139
|
-
export function openWorkIds(items: readonly ActiveWorkItem[]): string[] {
|
|
140
|
-
const kinds = new Set(["prd", "spec", "change", "task", "execution"]);
|
|
141
|
-
const statuses = new Set(["active", "executing", "verifying", "running", "paused"]);
|
|
142
|
-
return items
|
|
143
|
-
.filter(
|
|
144
|
-
(item) =>
|
|
145
|
-
kinds.has(item.kind) &&
|
|
146
|
-
(statuses.has(item.status ?? "") || (item.kind === "task" && item.status === "planned")),
|
|
147
|
-
)
|
|
148
|
-
.map((item) => item.id)
|
|
149
|
-
.sort();
|
|
150
|
-
}
|
|
151
|
-
|
|
152
123
|
interface DashboardAppOptions {
|
|
153
124
|
syncAgentAdapters?: () => Promise<AgentAdapterSyncResult>;
|
|
154
125
|
filesystem?: WorkspaceFileSystem;
|
|
@@ -158,8 +129,12 @@ interface DashboardAppOptions {
|
|
|
158
129
|
reconcileOpenWork?: typeof reconcileOpenWork;
|
|
159
130
|
refreshReadModel?: () => Promise<void>;
|
|
160
131
|
snapshotState?: "current" | "updating";
|
|
132
|
+
/** Enable filesystem and day rollover synchronization for the serving process. */
|
|
133
|
+
watchSources?: boolean;
|
|
161
134
|
/** Test seam: health and reconciliation only require the asserted V2 layout. */
|
|
162
135
|
layout?: WorkspaceLayout;
|
|
136
|
+
/** Only the spawned local runtime may self-terminate for a missing browser lease. */
|
|
137
|
+
launcherOwned?: boolean;
|
|
163
138
|
}
|
|
164
139
|
|
|
165
140
|
class V2WorkspaceRequiredError extends Error {
|
|
@@ -650,14 +625,15 @@ export function createDashboardApp(
|
|
|
650
625
|
const app = new Hono();
|
|
651
626
|
const filesystem = options.filesystem ?? new WorkspaceFileSystem(workspaceRoot);
|
|
652
627
|
const isSqliteSnapshot = filesystem instanceof SqliteReadModelFileSystem;
|
|
653
|
-
//
|
|
654
|
-
|
|
655
|
-
// canonical filesystems remain deliberately uncached.
|
|
656
|
-
const sqliteLayout = isSqliteSnapshot ? requireV2Layout(filesystem) : null;
|
|
628
|
+
// Cache layout within a committed revision and reload after synchronization.
|
|
629
|
+
let sqliteLayout = isSqliteSnapshot ? requireV2Layout(filesystem) : null;
|
|
657
630
|
const readLayout = async () =>
|
|
658
631
|
options.layout ?? sqliteLayout ?? (await requireV2Layout(filesystem));
|
|
659
632
|
const snapshotReadOnly = options.snapshotReadOnly ?? isSqliteSnapshot;
|
|
660
|
-
|
|
633
|
+
// A stale seed is safe to serve only until this process promotes its own
|
|
634
|
+
// replacement. Keep the state mutable so health/ready stop advertising an
|
|
635
|
+
// update after the atomic handoff succeeds.
|
|
636
|
+
let snapshotState = options.snapshotState ?? "current";
|
|
661
637
|
const canonicalFilesystem = options.canonicalFilesystem ?? new WorkspaceFileSystem(workspaceRoot);
|
|
662
638
|
const reconcileOpen = options.reconcileOpenWork ?? reconcileOpenWork;
|
|
663
639
|
const refreshReadModel =
|
|
@@ -714,16 +690,48 @@ export function createDashboardApp(
|
|
|
714
690
|
aggregatePayloads.clear();
|
|
715
691
|
aggregateInFlight.clear();
|
|
716
692
|
};
|
|
693
|
+
let observedSnapshotRevision: string | null = null;
|
|
717
694
|
let projectionRefreshInFlight: Promise<void> | null = null;
|
|
695
|
+
let projectionRefreshRequested = false;
|
|
718
696
|
const rebuildProjection = async () => {
|
|
719
|
-
if (projectionRefreshInFlight !== null)
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
697
|
+
if (projectionRefreshInFlight !== null) {
|
|
698
|
+
projectionRefreshRequested = true;
|
|
699
|
+
return projectionRefreshInFlight;
|
|
700
|
+
}
|
|
701
|
+
snapshotState = "updating";
|
|
702
|
+
projectionRefreshInFlight = (async () => {
|
|
703
|
+
do {
|
|
704
|
+
projectionRefreshRequested = false;
|
|
705
|
+
await refreshReadModel();
|
|
706
|
+
if (isSqliteSnapshot) sqliteLayout = requireV2Layout(filesystem);
|
|
707
|
+
clearSnapshotCache();
|
|
708
|
+
} while (projectionRefreshRequested);
|
|
709
|
+
snapshotState = "current";
|
|
710
|
+
})().finally(() => {
|
|
711
|
+
projectionRefreshInFlight = null;
|
|
712
|
+
});
|
|
725
713
|
return projectionRefreshInFlight;
|
|
726
714
|
};
|
|
715
|
+
startSnapshotSynchronization({
|
|
716
|
+
workspaceRoot,
|
|
717
|
+
staleSeed: isSqliteSnapshot && snapshotState === "updating",
|
|
718
|
+
watchSources: isSqliteSnapshot && options.watchSources === true,
|
|
719
|
+
refresh: rebuildProjection,
|
|
720
|
+
});
|
|
721
|
+
const reconcileWork = createWorkReconciliation({
|
|
722
|
+
reconcile: (mode) =>
|
|
723
|
+
reconcileOpen(canonicalFilesystem, workspaceRoot, {
|
|
724
|
+
hostTerminalOnly: mode === "host-terminal",
|
|
725
|
+
}),
|
|
726
|
+
refresh: rebuildProjection,
|
|
727
|
+
});
|
|
728
|
+
if (
|
|
729
|
+
isSqliteSnapshot &&
|
|
730
|
+
options.watchSources === true &&
|
|
731
|
+
process.env.ZAIP_DASHBOARD_WATCH_SOURCES !== "0"
|
|
732
|
+
) {
|
|
733
|
+
startHostTerminalReconciliation(() => reconcileWork("host-terminal"));
|
|
734
|
+
}
|
|
727
735
|
const readSnapshot = (context: Context) => {
|
|
728
736
|
const key = snapshotKey(context);
|
|
729
737
|
const cached = cachedSnapshots.get(key);
|
|
@@ -785,6 +793,8 @@ export function createDashboardApp(
|
|
|
785
793
|
// available while the dashboard serves a read-only snapshot.
|
|
786
794
|
const reconcileWrite =
|
|
787
795
|
context.req.method === "POST" && context.req.path === `${API_PREFIX}/reconcile-open-work`;
|
|
796
|
+
const browserLeaseWrite =
|
|
797
|
+
context.req.method === "GET" && context.req.path === `${API_PREFIX}/browser-lease`;
|
|
788
798
|
const projectionRefreshWrite =
|
|
789
799
|
context.req.method === "POST" && context.req.path === `${API_PREFIX}/refresh-projection`;
|
|
790
800
|
if (
|
|
@@ -792,7 +802,8 @@ export function createDashboardApp(
|
|
|
792
802
|
context.req.method !== "HEAD" &&
|
|
793
803
|
!settingsWrite &&
|
|
794
804
|
!reconcileWrite &&
|
|
795
|
-
!projectionRefreshWrite
|
|
805
|
+
!projectionRefreshWrite &&
|
|
806
|
+
!browserLeaseWrite
|
|
796
807
|
) {
|
|
797
808
|
context.header(
|
|
798
809
|
"Allow",
|
|
@@ -824,15 +835,23 @@ export function createDashboardApp(
|
|
|
824
835
|
context.req.path.startsWith(`${API_PREFIX}/agent-catalog-assets/`)
|
|
825
836
|
? context.req.query("token")
|
|
826
837
|
: undefined;
|
|
838
|
+
const leaseToken = browserLeaseWrite ? context.req.query("token") : undefined;
|
|
839
|
+
// EventSource cannot carry the session header and localhost cookies span
|
|
840
|
+
// ports. Its query capability is therefore intentionally stricter than
|
|
841
|
+
// ordinary dashboard requests: an old tab must never lease a new runtime.
|
|
842
|
+
if (browserLeaseWrite && leaseToken !== sessionToken)
|
|
843
|
+
return context.json({ error: "Invalid local session" }, 401);
|
|
827
844
|
if (
|
|
828
845
|
headerSession !== sessionToken &&
|
|
829
846
|
cookieSession !== sessionToken &&
|
|
830
|
-
portraitToken !== sessionToken
|
|
847
|
+
portraitToken !== sessionToken &&
|
|
848
|
+
leaseToken !== sessionToken
|
|
831
849
|
) {
|
|
832
850
|
return context.json({ error: "Invalid local session" }, 401);
|
|
833
851
|
}
|
|
834
852
|
return next();
|
|
835
853
|
});
|
|
854
|
+
registerBrowserLeaseRoute(app, API_PREFIX, options.launcherOwned === true);
|
|
836
855
|
|
|
837
856
|
app.on(["GET", "HEAD"], `${API_PREFIX}/health`, async (context) => {
|
|
838
857
|
try {
|
|
@@ -871,6 +890,15 @@ export function createDashboardApp(
|
|
|
871
890
|
try {
|
|
872
891
|
const layout = await readLayout();
|
|
873
892
|
if (isSqliteSnapshot) {
|
|
893
|
+
const revision = readCommittedSnapshotRevision(workspaceRoot);
|
|
894
|
+
if (observedSnapshotRevision !== null && observedSnapshotRevision !== revision) {
|
|
895
|
+
// A worker may commit before its completion callback runs. Refresh
|
|
896
|
+
// the reader and its caches before advertising the new revision.
|
|
897
|
+
filesystem.refresh();
|
|
898
|
+
clearSnapshotCache();
|
|
899
|
+
sqliteLayout = requireV2Layout(filesystem);
|
|
900
|
+
}
|
|
901
|
+
observedSnapshotRevision = revision;
|
|
874
902
|
const metadata = filesystem.metadata();
|
|
875
903
|
return headOrJson(context, {
|
|
876
904
|
kind: RUNTIME_KIND,
|
|
@@ -884,6 +912,7 @@ export function createDashboardApp(
|
|
|
884
912
|
// /ready must never start a competing projection in the background.
|
|
885
913
|
day_count: metadata.daily_aggregate_count,
|
|
886
914
|
snapshot_state: snapshotState,
|
|
915
|
+
snapshot_revision: revision,
|
|
887
916
|
});
|
|
888
917
|
}
|
|
889
918
|
const projection = await buildFirstFoldQuickProjection(filesystem, layout, {
|
|
@@ -1220,23 +1249,32 @@ export function createDashboardApp(
|
|
|
1220
1249
|
app.post(`${API_PREFIX}/reconcile-open-work`, async (context) => {
|
|
1221
1250
|
try {
|
|
1222
1251
|
await readLayout();
|
|
1223
|
-
//
|
|
1224
|
-
//
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
// canonical data, so rebuilding the immutable SQLite snapshot only adds
|
|
1229
|
-
// seconds of redundant work before the dashboard can settle.
|
|
1230
|
-
if (reconciliationNeedsRefresh(reconciledIds)) {
|
|
1231
|
-
await rebuildProjection();
|
|
1232
|
-
}
|
|
1252
|
+
// Share the canonical mutation queue with missed host-stop recovery.
|
|
1253
|
+
// Projection rebuilds run in the background and publish their revision.
|
|
1254
|
+
const reconciledIds = await waitForWorkReconciliation(reconcileWork("manual"), () => {
|
|
1255
|
+
void rebuildProjection().catch(() => undefined);
|
|
1256
|
+
});
|
|
1233
1257
|
return context.json({
|
|
1234
|
-
...(await readSnapshot(context)),
|
|
1235
1258
|
reconciliation: reconciledIds,
|
|
1236
|
-
|
|
1259
|
+
snapshot_state: snapshotState,
|
|
1260
|
+
projection_refresh_completed:
|
|
1261
|
+
snapshotState === "current" && projectionRefreshInFlight === null,
|
|
1237
1262
|
});
|
|
1238
1263
|
} catch (error) {
|
|
1239
1264
|
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1265
|
+
if (error instanceof ReconciliationCommandTimeoutError) {
|
|
1266
|
+
// SIGTERM can occur after the CLI persisted some records. Start an
|
|
1267
|
+
// atomic refresh without extending the request past the client's
|
|
1268
|
+
// deadline, and make that uncertainty explicit to the caller.
|
|
1269
|
+
return context.json(
|
|
1270
|
+
{
|
|
1271
|
+
error: error.message,
|
|
1272
|
+
reconciliation_may_be_partial: true,
|
|
1273
|
+
projection_refresh_started: true,
|
|
1274
|
+
},
|
|
1275
|
+
408,
|
|
1276
|
+
);
|
|
1277
|
+
}
|
|
1240
1278
|
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1241
1279
|
}
|
|
1242
1280
|
});
|
|
@@ -1314,7 +1352,18 @@ export function createDashboardApp(
|
|
|
1314
1352
|
);
|
|
1315
1353
|
return headOrJson(
|
|
1316
1354
|
context,
|
|
1317
|
-
|
|
1355
|
+
// The paged Cost adapter reads the lifecycle summary. That canonical
|
|
1356
|
+
// artifact is intentionally not copied into SQLite; use its current
|
|
1357
|
+
// filesystem alongside the immutable SQL facts rather than failing
|
|
1358
|
+
// a filtered page with a synthetic missing-file error.
|
|
1359
|
+
await buildManifestCostRunPage(
|
|
1360
|
+
isSqliteSnapshot ? canonicalFilesystem : filesystem,
|
|
1361
|
+
layout,
|
|
1362
|
+
context,
|
|
1363
|
+
{ from, to },
|
|
1364
|
+
offset,
|
|
1365
|
+
limit,
|
|
1366
|
+
),
|
|
1318
1367
|
200,
|
|
1319
1368
|
true,
|
|
1320
1369
|
);
|
|
@@ -1627,42 +1676,23 @@ export const app = new Proxy({} as Hono, {
|
|
|
1627
1676
|
},
|
|
1628
1677
|
});
|
|
1629
1678
|
|
|
1630
|
-
function startupPhase(phase: string): void {
|
|
1631
|
-
process.stderr.write(
|
|
1632
|
-
`${JSON.stringify({
|
|
1633
|
-
event: "dashboard_sqlite_startup_phase",
|
|
1634
|
-
phase,
|
|
1635
|
-
elapsed_ms: Math.round(performance.now() - moduleStartedAt),
|
|
1636
|
-
})}\n`,
|
|
1637
|
-
);
|
|
1638
|
-
}
|
|
1639
|
-
|
|
1640
1679
|
async function main(): Promise<void> {
|
|
1641
1680
|
const port = Number.parseInt(process.env.ZAIP_SERVER_PORT ?? "4317", 10);
|
|
1642
|
-
|
|
1681
|
+
writeStartupPhase(moduleStartedAt, "main_entered");
|
|
1643
1682
|
const startedAt = performance.now();
|
|
1644
|
-
const
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
process.stderr.write(
|
|
1649
|
-
`${JSON.stringify({
|
|
1650
|
-
event: "dashboard_sqlite_read_model",
|
|
1651
|
-
elapsed_ms: Math.round(performance.now() - startedAt),
|
|
1652
|
-
cache: readModel.cache,
|
|
1653
|
-
fingerprint_ms: readModel.fingerprint_ms,
|
|
1654
|
-
materialize_ms: readModel.materialize_ms,
|
|
1655
|
-
source_files: readModel.files,
|
|
1656
|
-
})}\n`,
|
|
1657
|
-
);
|
|
1658
|
-
startupPhase("read_model_ready");
|
|
1683
|
+
const startupOptions = { forceCanonical: false, preferExisting: true };
|
|
1684
|
+
const readModel = await rebuildSqliteReadModel(runtimeWorkspaceRoot, startupOptions);
|
|
1685
|
+
writeReadModelStartup(startedAt, readModel);
|
|
1686
|
+
writeStartupPhase(moduleStartedAt, "read_model_ready");
|
|
1659
1687
|
const runtimeApp = createDashboardApp(runtimeWorkspaceRoot, sessionToken, undefined, {
|
|
1660
1688
|
filesystem: new SqliteReadModelFileSystem(runtimeWorkspaceRoot),
|
|
1661
1689
|
snapshotState: readModel.cache === "stale_seed" ? "updating" : "current",
|
|
1690
|
+
watchSources: true,
|
|
1691
|
+
launcherOwned: true,
|
|
1662
1692
|
});
|
|
1663
|
-
|
|
1693
|
+
writeStartupPhase(moduleStartedAt, "runtime_app_ready");
|
|
1664
1694
|
serve({ fetch: runtimeApp.fetch, hostname: HOST, port }, ({ port: boundPort }) => {
|
|
1665
|
-
|
|
1695
|
+
writeStartupPhase(moduleStartedAt, "listening");
|
|
1666
1696
|
process.stdout.write(
|
|
1667
1697
|
`ZAIP-AIOS dashboard API: http://${HOST}:${boundPort}${API_PREFIX}/health\n`,
|
|
1668
1698
|
);
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.test.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { agentProductivity, attachAgentProductivity } from "./sqlite-agent-productivity.js";
|
|
4
|
+
|
|
5
|
+
function fixture() {
|
|
6
|
+
const db = new DatabaseSync(":memory:");
|
|
7
|
+
db.exec(`CREATE TABLE zaip_aios_activities (payload_type TEXT,payload_json TEXT,run_id TEXT,zaip_agent TEXT,occurred_day_sp TEXT,phase TEXT,status TEXT,task_id TEXT,agent_invocation_id TEXT,zaip_agent_persona TEXT,zaip_agent_job TEXT);
|
|
8
|
+
INSERT INTO zaip_aios_activities(run_id,zaip_agent,occurred_day_sp) VALUES ('CREATE','dave','2026-09-01'),('CREATE','dave','2026-09-01'),('LATER','leo','2026-09-02'); UPDATE zaip_aios_activities SET task_id='T1' WHERE payload_type IS NULL;`);
|
|
9
|
+
const put = (type: string, value: object) =>
|
|
10
|
+
db
|
|
11
|
+
.prepare("INSERT INTO zaip_aios_activities(payload_type,payload_json) VALUES (?,?)")
|
|
12
|
+
.run(type, JSON.stringify(value));
|
|
13
|
+
put("work_item", {
|
|
14
|
+
entity_kind: "task",
|
|
15
|
+
id: "T1",
|
|
16
|
+
creation_run_id: "CREATE",
|
|
17
|
+
occurred_day_sp: "2026-09-01",
|
|
18
|
+
});
|
|
19
|
+
put("work_item", {
|
|
20
|
+
entity_kind: "prd",
|
|
21
|
+
id: "P1",
|
|
22
|
+
creation_run_id: "CREATE",
|
|
23
|
+
occurred_day_sp: "2026-09-01",
|
|
24
|
+
});
|
|
25
|
+
put("work_item", {
|
|
26
|
+
entity_kind: "spec",
|
|
27
|
+
id: "S1",
|
|
28
|
+
creation_run_id: "CREATE",
|
|
29
|
+
occurred_day_sp: "2026-09-01",
|
|
30
|
+
});
|
|
31
|
+
for (const path of ["a/artifacts/tests/one.md", "b/artifacts/tests/duplicate.md"])
|
|
32
|
+
put("file", {
|
|
33
|
+
path,
|
|
34
|
+
artifact_kind: "validation",
|
|
35
|
+
artifact_id: "TEST1",
|
|
36
|
+
artifact_run_id: "LATER",
|
|
37
|
+
artifact_occurred_day_sp: "2026-09-02",
|
|
38
|
+
});
|
|
39
|
+
put("file", {
|
|
40
|
+
path: "a/artifacts/validations/review.md",
|
|
41
|
+
artifact_kind: "validation",
|
|
42
|
+
artifact_id: "REVIEW",
|
|
43
|
+
artifact_run_id: "LATER",
|
|
44
|
+
artifact_occurred_day_sp: "2026-09-02",
|
|
45
|
+
});
|
|
46
|
+
put("file", {
|
|
47
|
+
path: "a/artifacts/evidences/e.md",
|
|
48
|
+
artifact_kind: "evidence",
|
|
49
|
+
artifact_id: "E1",
|
|
50
|
+
artifact_run_id: "LATER",
|
|
51
|
+
artifact_occurred_day_sp: "2026-09-02",
|
|
52
|
+
});
|
|
53
|
+
return db;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
describe("agent productivity", () => {
|
|
57
|
+
it("counts a shared Task for each agent without duplicating repeated Runs by that agent", () => {
|
|
58
|
+
const db = fixture();
|
|
59
|
+
try {
|
|
60
|
+
const result = agentProductivity(db, {});
|
|
61
|
+
expect(result.get("dave")).toEqual({
|
|
62
|
+
prd_count: 1,
|
|
63
|
+
spec_count: 1,
|
|
64
|
+
task_count: 1,
|
|
65
|
+
test_count: 0,
|
|
66
|
+
evidence_count: 0,
|
|
67
|
+
});
|
|
68
|
+
expect(result.get("leo")).toEqual({
|
|
69
|
+
prd_count: 0,
|
|
70
|
+
spec_count: 0,
|
|
71
|
+
task_count: 1,
|
|
72
|
+
test_count: 1,
|
|
73
|
+
evidence_count: 1,
|
|
74
|
+
});
|
|
75
|
+
expect(agentProductivity(db, { from: "2026-09-02", to: "2026-09-02" }).has("dave")).toBe(
|
|
76
|
+
false,
|
|
77
|
+
);
|
|
78
|
+
expect(agentProductivity(db, { agent: "leo" }).get("leo")?.task_count).toBe(1);
|
|
79
|
+
} finally {
|
|
80
|
+
db.close();
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
it("counts participation without creation metadata and sums memberships in the full-population footer", () => {
|
|
84
|
+
const db = fixture();
|
|
85
|
+
try {
|
|
86
|
+
db.exec(
|
|
87
|
+
`UPDATE zaip_aios_activities SET payload_json=json_remove(payload_json,'$.creation_run_id') WHERE payload_type='work_item' AND json_extract(payload_json,'$.entity_kind')='task'`,
|
|
88
|
+
);
|
|
89
|
+
const page = {
|
|
90
|
+
rows: [{ key: "dave", task_count: 50, total_tokens: 12 }],
|
|
91
|
+
totals: { task_count: 50, total_tokens: 100 },
|
|
92
|
+
};
|
|
93
|
+
attachAgentProductivity(db, {}, page);
|
|
94
|
+
expect(page.rows[0]).toMatchObject({
|
|
95
|
+
task_count: 1,
|
|
96
|
+
tasks_active: 50,
|
|
97
|
+
prd_count: 1,
|
|
98
|
+
total_tokens: 12,
|
|
99
|
+
});
|
|
100
|
+
expect(page.totals).toMatchObject({
|
|
101
|
+
task_count: 2,
|
|
102
|
+
prd_count: 1,
|
|
103
|
+
test_count: 1,
|
|
104
|
+
evidence_count: 1,
|
|
105
|
+
total_tokens: 100,
|
|
106
|
+
});
|
|
107
|
+
} finally {
|
|
108
|
+
db.close();
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import type { DateOnlyCostPageInput } from "./sqlite-cost-agent-page.js";
|
|
3
|
+
|
|
4
|
+
const fields = ["prd_count", "spec_count", "task_count", "test_count", "evidence_count"] as const;
|
|
5
|
+
type Counts = Record<(typeof fields)[number], number | null>;
|
|
6
|
+
const empty = (): Counts => ({
|
|
7
|
+
prd_count: 0,
|
|
8
|
+
spec_count: 0,
|
|
9
|
+
task_count: 0,
|
|
10
|
+
test_count: 0,
|
|
11
|
+
evidence_count: 0,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
/** Tasks count participation per agent; macro creation and artifacts keep their Run attribution. */
|
|
15
|
+
export function agentProductivity(database: DatabaseSync, input: DateOnlyCostPageInput) {
|
|
16
|
+
const clauses = ["a.payload_type IS NULL", "a.run_id IS NOT NULL", "a.zaip_agent IS NOT NULL"];
|
|
17
|
+
const values: string[] = [];
|
|
18
|
+
for (const bound of ["from", "to"] as const) {
|
|
19
|
+
if (!input[bound]) continue;
|
|
20
|
+
clauses.push(`a.occurred_day_sp ${bound === "from" ? ">=" : "<="} ?`);
|
|
21
|
+
values.push(input[bound].slice(0, 10));
|
|
22
|
+
}
|
|
23
|
+
for (const field of ["agent", "phase", "status"] as const) {
|
|
24
|
+
if (!input[field]) continue;
|
|
25
|
+
clauses.push(`a.${field === "agent" ? "zaip_agent" : field}=?`);
|
|
26
|
+
values.push(input[field]);
|
|
27
|
+
}
|
|
28
|
+
if (input.risk) {
|
|
29
|
+
clauses.push(
|
|
30
|
+
"EXISTS (SELECT 1 FROM zaip_aios_activities t WHERE t.payload_type='work_item' AND json_extract(t.payload_json,'$.entity_kind')='task' AND json_extract(t.payload_json,'$.id')=a.task_id AND json_extract(t.payload_json,'$.risk')=?)",
|
|
31
|
+
);
|
|
32
|
+
values.push(input.risk);
|
|
33
|
+
}
|
|
34
|
+
if (input.priority || input.workType) clauses.push("0");
|
|
35
|
+
if (input.origin)
|
|
36
|
+
clauses.push(
|
|
37
|
+
input.origin === "prd"
|
|
38
|
+
? "a.prd_id IS NOT NULL"
|
|
39
|
+
: input.origin === "spec"
|
|
40
|
+
? "a.prd_id IS NULL AND a.spec_id IS NOT NULL"
|
|
41
|
+
: input.origin === "task"
|
|
42
|
+
? "a.prd_id IS NULL AND a.spec_id IS NULL AND a.task_id IS NOT NULL"
|
|
43
|
+
: "a.prd_id IS NULL AND a.spec_id IS NULL AND a.task_id IS NULL",
|
|
44
|
+
);
|
|
45
|
+
const usage: string[] = [];
|
|
46
|
+
for (const field of ["provider", "model"] as const) {
|
|
47
|
+
if (!input[field]) continue;
|
|
48
|
+
usage.push(`COALESCE(u.${field},'unavailable')=?`);
|
|
49
|
+
values.push(input[field]);
|
|
50
|
+
}
|
|
51
|
+
if (usage.length)
|
|
52
|
+
clauses.push(
|
|
53
|
+
`EXISTS (SELECT 1 FROM invocation_usage u WHERE u.agent_invocation_id=a.agent_invocation_id AND ${usage.join(" AND ")})`,
|
|
54
|
+
);
|
|
55
|
+
if (input.query) {
|
|
56
|
+
clauses.push("(a.zaip_agent LIKE ? OR a.zaip_agent_persona LIKE ? OR a.zaip_agent_job LIKE ?)");
|
|
57
|
+
values.push(...Array<string>(3).fill(`%${input.query}%`));
|
|
58
|
+
}
|
|
59
|
+
const owners = database
|
|
60
|
+
.prepare(
|
|
61
|
+
`SELECT a.run_id, MIN(a.zaip_agent) AS agent FROM zaip_aios_activities a WHERE ${clauses.join(" AND ")} GROUP BY a.run_id HAVING COUNT(DISTINCT a.zaip_agent)=1`,
|
|
62
|
+
)
|
|
63
|
+
.all(...values) as Array<{ run_id: string; agent: string }>;
|
|
64
|
+
const agentByRun = new Map(owners.map((row) => [row.run_id, row.agent]));
|
|
65
|
+
const counts = new Map<string, Counts>();
|
|
66
|
+
const seen = new Set<string>();
|
|
67
|
+
const from = input.from?.slice(0, 10) ?? "0000-01-01";
|
|
68
|
+
const to = input.to?.slice(0, 10) ?? "9999-12-31";
|
|
69
|
+
const facts = database
|
|
70
|
+
.prepare(`WITH files AS (
|
|
71
|
+
SELECT json_extract(payload_json,'$.path') path,
|
|
72
|
+
json_extract(payload_json,'$.artifact_kind') artifact_kind,
|
|
73
|
+
json_extract(payload_json,'$.artifact_id') artifact_id,
|
|
74
|
+
json_extract(payload_json,'$.artifact_run_id') artifact_run_id,
|
|
75
|
+
json_extract(payload_json,'$.artifact_occurred_day_sp') artifact_occurred_day_sp
|
|
76
|
+
FROM zaip_aios_activities WHERE payload_type='file'
|
|
77
|
+
)
|
|
78
|
+
SELECT json_extract(payload_json,'$.entity_kind') AS kind,
|
|
79
|
+
json_extract(payload_json,'$.id') id, json_extract(payload_json,'$.creation_run_id') AS run_id,
|
|
80
|
+
json_extract(payload_json,'$.occurred_day_sp') AS day
|
|
81
|
+
FROM zaip_aios_activities WHERE payload_type='work_item'
|
|
82
|
+
AND json_extract(payload_json,'$.entity_kind') IN ('prd','spec')
|
|
83
|
+
AND json_extract(payload_json,'$.creation_run_id') IS NOT NULL
|
|
84
|
+
UNION ALL
|
|
85
|
+
SELECT CASE WHEN artifact_kind='validation' THEN 'test' ELSE 'evidence' END,
|
|
86
|
+
COALESCE(artifact_id,path), artifact_run_id, artifact_occurred_day_sp
|
|
87
|
+
FROM files WHERE artifact_run_id IS NOT NULL AND
|
|
88
|
+
(artifact_kind='evidence' OR (artifact_kind='validation' AND path LIKE '%/artifacts/tests/%'))
|
|
89
|
+
`)
|
|
90
|
+
.all() as Array<{ kind: string; id: string; run_id: string; day: string }>;
|
|
91
|
+
for (const fact of facts) {
|
|
92
|
+
if (!fact.day || fact.day < from || fact.day > to) continue;
|
|
93
|
+
const owner = agentByRun.get(fact.run_id);
|
|
94
|
+
if (!owner) continue;
|
|
95
|
+
const key = `${fact.kind}:${fact.id}`;
|
|
96
|
+
if (seen.has(key)) continue;
|
|
97
|
+
seen.add(key);
|
|
98
|
+
const row = counts.get(owner) ?? empty();
|
|
99
|
+
const field = `${fact.kind}_count` as keyof Counts;
|
|
100
|
+
row[field] = (row[field] ?? 0) + 1;
|
|
101
|
+
counts.set(owner, row);
|
|
102
|
+
}
|
|
103
|
+
// Repeated Runs by one agent do not create extra Tasks. The same Task is
|
|
104
|
+
// counted once for EACH participating agent, so the footer sums memberships.
|
|
105
|
+
const taskCounts = database
|
|
106
|
+
.prepare(`SELECT a.zaip_agent AS agent,
|
|
107
|
+
COUNT(DISTINCT NULLIF(trim(a.task_id),'')) AS task_count
|
|
108
|
+
FROM zaip_aios_activities a WHERE ${clauses.join(" AND ")}
|
|
109
|
+
GROUP BY a.zaip_agent`)
|
|
110
|
+
.all(...values) as Array<{ agent: string; task_count: number }>;
|
|
111
|
+
for (const participation of taskCounts) {
|
|
112
|
+
const row = counts.get(participation.agent) ?? empty();
|
|
113
|
+
row.task_count = participation.task_count;
|
|
114
|
+
counts.set(participation.agent, row);
|
|
115
|
+
}
|
|
116
|
+
return counts;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function attachAgentProductivity(
|
|
120
|
+
database: DatabaseSync,
|
|
121
|
+
input: DateOnlyCostPageInput,
|
|
122
|
+
page: { rows: Array<Record<string, unknown>>; totals?: Record<string, unknown> },
|
|
123
|
+
) {
|
|
124
|
+
const counts = agentProductivity(database, input);
|
|
125
|
+
for (const row of page.rows) {
|
|
126
|
+
row.tasks_active = row.task_count;
|
|
127
|
+
Object.assign(row, counts.get(String(row.key)) ?? empty());
|
|
128
|
+
row.validation_count = row.test_count;
|
|
129
|
+
}
|
|
130
|
+
if (page.totals) {
|
|
131
|
+
const totals = empty();
|
|
132
|
+
for (const row of counts.values())
|
|
133
|
+
for (const field of fields)
|
|
134
|
+
totals[field] =
|
|
135
|
+
totals[field] === null || row[field] === null ? null : totals[field] + row[field];
|
|
136
|
+
Object.assign(page.totals, totals, {
|
|
137
|
+
validation_count: totals.test_count,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|