@zaip-ai/cli 2.2.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +23 -9
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +25 -9
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-discovery.d.ts +27 -0
- package/dist/services/agent-discovery.d.ts.map +1 -0
- package/dist/services/agent-discovery.js +73 -0
- package/dist/services/agent-discovery.js.map +1 -0
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +153 -24
- package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +146 -72
- package/dist/services/codex-pre-tool-hook-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 +3 -3
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +117 -66
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +56 -6
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/logger.js +1 -1
- package/dist/services/logger.js.map +1 -1
- package/dist/services/logger.test.js +22 -1
- package/dist/services/logger.test.js.map +1 -1
- package/dist/services/runtime-template.test.js +129 -0
- package/dist/services/runtime-template.test.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +9 -3
- package/templates/.agents/README-ENG.md +30 -5
- package/templates/.agents/README.md +30 -7
- package/templates/.agents/architecture/software-architecture.md +1 -59
- package/templates/.agents/branding/brandbook.md +3 -0
- package/templates/.agents/config/agents/catalog.yaml +22 -10
- package/templates/.agents/config/agents/discovery.json +319 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +11 -8
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +2 -2
- package/templates/.agents/config/pricing/models.json +9 -5
- package/templates/.agents/config/project.yaml +12 -1
- package/templates/.agents/dashboard/.zaip-managed.json +375 -95
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-CGxeQak4.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DaSllaJp.js → DashboardHelpDialog-tzS7YxYB.js} +57 -33
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-DEbCi1gP.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-t1Om0Abw.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-TPUT2IUt.js → icons-vendor-DiGC-dsJ.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-Ct48XHGL.js → react-vendor-kPO6yNed.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +3 -1264
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +363 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +99 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +62 -6
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +7 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -7
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +151 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +28 -153
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-app-shell.tsx +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-retry.ts +17 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-setup-route.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +66 -0
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +3 -2
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +68 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.test.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +2 -5
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +30 -19
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +9 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +77 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +397 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +782 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-snapshot-notice.tsx +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperPanelSlot.tsx +16 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +459 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +27 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +62 -186
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorRunDialog.tsx +20 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-hides-calls-that-have-no-collected.test.ts +80 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +455 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +18 -525
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +32 -508
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-export-sources.ts +74 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-actions.ts +19 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +115 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test-fixtures.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTableBadges.tsx +34 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +8 -38
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +243 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +27 -275
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +70 -247
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +171 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewPanels.tsx +64 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +6 -2
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +6 -14
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +3 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +32 -0
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1458 -1458
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1425 -1425
- package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1458 -1459
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +53 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +79 -24
- package/templates/.agents/dashboard/packages/local-runtime/src/projection-refresh-diagnostics.ts +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +168 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +344 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-http-contracts.ts +31 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +345 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +461 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-route-context.ts +13 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -21
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-view-allowlist.test.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +64 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +2 -30
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +6 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -330
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +73 -1060
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-first-fold.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +561 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +600 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +269 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-context.ts +32 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +244 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +292 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +547 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +360 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +169 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +475 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +132 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-timing.ts +299 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +692 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +739 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-does-not-convert-delayed-historical-finalizer.test.ts +706 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +748 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +710 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-marks-token-cost-telemetry-unavailable-when.test.ts +618 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +755 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuilds-disposable-snapshot-serves-zaip-records.test.ts +276 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +193 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-types.ts +123 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1 -2805
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +17 -6930
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +385 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +412 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +4 -3
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +195 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.test.mjs +2 -7
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-navigation.mjs +114 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +90 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +89 -418
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +22 -12
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
- package/templates/.agents/design/.zaip-managed.json +5 -5
- package/templates/.agents/design/DESIGN.md +2 -186
- package/templates/.agents/design/README.md +12 -2
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/growth/strategy.md +3 -0
- package/templates/.agents/marketing/strategy.md +3 -0
- package/templates/.agents/requirements/autonomous-assurance.md +2 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- 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 +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +13 -4
- 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 +4 -2
- 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 +3 -3
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/architecture.md +2 -0
- package/templates/.agents/rules/astra-diagnostic.md +1 -1
- package/templates/.agents/rules/autonomy-decision.md +3 -1
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +2 -0
- package/templates/.agents/rules/context.md +2 -1
- package/templates/.agents/rules/core.md +3 -3
- package/templates/.agents/rules/design-system-central-contract.md +17 -0
- package/templates/.agents/rules/evolution.md +3 -1
- package/templates/.agents/rules/frontend-lite.md +3 -1
- package/templates/.agents/rules/local-sqlite-storage.md +2 -2
- package/templates/.agents/rules/meta-mcp.md +3 -1
- package/templates/.agents/rules/model-orchestration.md +1 -1
- package/templates/.agents/rules/run-lifecycle-closure.md +6 -4
- package/templates/.agents/rules/security.md +3 -1
- package/templates/.agents/rules/specialist-routing.md +3 -1
- package/templates/.agents/rules/text-writing-utf8.md +1 -1
- package/templates/.agents/rules/workflow.md +7 -5
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +519 -247
- package/templates/.agents/runtime/checksums.sha256 +6 -6
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
- package/templates/.agents/runtime/provenance.json +5 -5
- package/templates/.agents/runtime/sbom.cdx.json +1 -1
- package/templates/.agents/sales/playbook.md +3 -0
- package/templates/.agents/skills/zaip-aios/SKILL.md +5 -3
- package/templates/.agents/skills/zaip-skill-adapt-stack/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-observability/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/references/signal-design.md +3 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/references/evidence-matrix.md +3 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/data-access-paths.md +9 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/worker-scenario.md +5 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/scripts/worker-contract.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-author-skills/references/engineering-skill-index.md +9 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +5 -3
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-backend/references/deployment-environments.md +75 -0
- package/templates/.agents/skills/zaip-skill-backend/references/supabase-migration-contract.md +23 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-cloud-engineering/SKILL.md +7 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/SKILL.md +37 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workers-static-assets.md +26 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workflow-templates.md +71 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/scripts/cloudflare-github-deploy-contract.test.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-config/SKILL.md +21 -11
- package/templates/.agents/skills/zaip-skill-config/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-container-runtime/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-container-runtime/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-context/SKILL.md +6 -1
- package/templates/.agents/skills/zaip-skill-context/references/prd-spec-task-handoff.md +10 -0
- package/templates/.agents/skills/zaip-skill-context/references/rule-selection.md +20 -0
- package/templates/.agents/skills/zaip-skill-cqrs/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/SKILL.md +18 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/references/audit-contract.md +94 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.mjs +185 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/manual-mode.md +15 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/promotion-example.md +5 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.mjs +145 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.test.mjs +178 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/references/runtime-shapes.md +3 -0
- package/templates/.agents/skills/zaip-skill-design-system/SKILL.md +20 -9
- package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/references/inventory-contract.md +7 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/scripts/inventory.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/references/recovery-scope.md +3 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +7 -0
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +1 -5
- package/templates/.agents/skills/zaip-skill-external-integrations/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-external-integrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/SKILL.md +44 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/SKILL.md +36 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md +33 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/github.md +63 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/hostinger-vps.md +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/npm.md +30 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/check-skill.mjs +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs +61 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs +128 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-ssh.integration.test.mjs +106 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +43 -76
- package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +131 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/github-release-workflow-template.md +31 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-gate-matrix.md +24 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +44 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-notes.md +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.mjs +389 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +25 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness-api.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.mjs +98 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.test.mjs +25 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.mjs +159 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.test.mjs +160 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +149 -12
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +64 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/release-notes-coverage.test.mjs +126 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.mjs +78 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.test.mjs +51 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.mjs +184 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.test.mjs +109 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +18 -10
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +3 -4
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/aws-cli-terraform.md +62 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/guia-iniciante-hostinger-vps.md +183 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/references/scaffold-contract.md +9 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/helpers.test.mjs +121 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/scaffold.mjs +169 -0
- package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-performance-engineering/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-performance-engineering/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +26 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +39 -13
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/SKILL.md +66 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/references/behavioral-dry-run.md +23 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +40 -1
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +98 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +19 -21
- package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-storage-uploads/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-storage-uploads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-task/SKILL.md +16 -7
- package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +25 -0
- package/templates/.agents/skills/zaip-skill-test-data/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-test-data/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-test-data/scripts/generate.mjs +72 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/references/example-map.md +3 -0
- package/templates/.agents/skills/zaip-skill-website-readiness/SKILL.md +8 -0
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +2 -1
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +5 -3
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +34 -0
- package/templates/template-manifest.json +955 -211
- package/templates/.agents/branding/.gitkeep +0 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-snUCQYTC.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-BPtVUGgs.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-GgzpZ_PY.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BCvZFMEf.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-_MEktQNM.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BDe4_Ubl.js +0 -1
- package/templates/.agents/growth/.gitkeep +0 -0
- package/templates/.agents/marketing/.gitkeep +0 -0
- package/templates/.agents/sales/.gitkeep +0 -0
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts
ADDED
|
@@ -0,0 +1,748 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { WorkspaceFileSystem } from "@zaip-ai/core";
|
|
3
|
+
import type { CostSummarySource } from "@zaip-ai/dashboard-cost-monitor/server";
|
|
4
|
+
import { attachAgentProductivity } from "./sqlite-agent-productivity.js";
|
|
5
|
+
import {
|
|
6
|
+
readFirstFoldAllTime,
|
|
7
|
+
readFirstFoldBoardAllTime,
|
|
8
|
+
readFirstFoldMonthlyQuick,
|
|
9
|
+
readFirstFoldTopTasksAllTime,
|
|
10
|
+
readFirstFoldViewport,
|
|
11
|
+
} from "./sqlite-first-fold-cache.js";
|
|
12
|
+
import { operationsWorkListSqlRows } from "./sqlite-operations-work-list.js";
|
|
13
|
+
import type { SqliteQueryContext } from "./sqlite-query-context.js";
|
|
14
|
+
import {
|
|
15
|
+
queryActivityCostRows,
|
|
16
|
+
queryCostMonitorFactualDurationByDay,
|
|
17
|
+
queryCostMonitorFinancialActivityRows,
|
|
18
|
+
queryDeveloperCostAggregate,
|
|
19
|
+
queryInvocationCostRows,
|
|
20
|
+
queryInvocationTotals,
|
|
21
|
+
queryOperationsDeveloperAggregate,
|
|
22
|
+
} from "./sqlite-query-financial.js";
|
|
23
|
+
import { queryCostMonitorSummaryAggregate } from "./sqlite-query-summary.js";
|
|
24
|
+
import {
|
|
25
|
+
queryCanonicalRunCountByDay,
|
|
26
|
+
queryDailyPeriods,
|
|
27
|
+
queryExecutionDurationByDay,
|
|
28
|
+
queryFirstFoldAggregate,
|
|
29
|
+
queryOverviewPage,
|
|
30
|
+
queryTopTasks,
|
|
31
|
+
} from "./sqlite-query-timing.js";
|
|
32
|
+
import { queryUncachedViewPage } from "./sqlite-query-view-page.js";
|
|
33
|
+
import type {
|
|
34
|
+
SqliteFirstFoldAllTime,
|
|
35
|
+
SqliteFirstFoldAllTimeBoard,
|
|
36
|
+
SqliteFirstFoldMonthlyQuick,
|
|
37
|
+
} from "./sqlite-read-model-first-fold-types.js";
|
|
38
|
+
import { dbRelativePath, sqliteReadModelPath } from "./sqlite-read-model-schema.js";
|
|
39
|
+
import {
|
|
40
|
+
type SqliteFirstFoldAggregate,
|
|
41
|
+
type SqliteFirstFoldViewport,
|
|
42
|
+
type SqliteSummaryKind,
|
|
43
|
+
type SqliteSummaryPage,
|
|
44
|
+
type SqliteViewName,
|
|
45
|
+
sqliteViewMetadata,
|
|
46
|
+
} from "./sqlite-read-model-types.js";
|
|
47
|
+
import { installLegacyViewAliases } from "./sqlite-snapshot-cache.js";
|
|
48
|
+
export class SqliteReadModelFileSystem extends WorkspaceFileSystem {
|
|
49
|
+
private readonly executionDurationCache = new Map<string, Map<string, number>>();
|
|
50
|
+
private dailyAggregateRowsCache: Array<Record<string, number | string | null>> | null = null;
|
|
51
|
+
private firstFoldAllTimeCache: SqliteFirstFoldAllTime | null = null;
|
|
52
|
+
private firstFoldAllTimeBoardCache: SqliteFirstFoldAllTimeBoard | null = null;
|
|
53
|
+
private firstFoldTopTasksAllTimeCache: SqliteFirstFoldAllTime["top_tasks"] | null = null;
|
|
54
|
+
private firstFoldViewportCache: SqliteFirstFoldViewport | null = null;
|
|
55
|
+
private firstFoldMonthlyQuickCache: SqliteFirstFoldMonthlyQuick | null | undefined = undefined;
|
|
56
|
+
private firstFoldViewportTimings: Record<string, number> = {};
|
|
57
|
+
private metadataValues: Map<string, string> | null = null;
|
|
58
|
+
private readonly unfilteredViewPageCache = new Map<string, Array<Record<string, unknown>>>();
|
|
59
|
+
private readonly technicalPayloadRowsCache = new Map<string, Array<Record<string, unknown>>>();
|
|
60
|
+
private readonly viewPageResultCache = new Map<string, Record<string, unknown>>();
|
|
61
|
+
// Summary cards and temporal Cost tables consume the same aggregate. Keep
|
|
62
|
+
// exact filter results inside the immutable generation so a tab switch does
|
|
63
|
+
// not repeat its multi-second SQL scan.
|
|
64
|
+
private readonly costMonitorSummaryCache = new Map<string, CostSummarySource>();
|
|
65
|
+
|
|
66
|
+
canonicalSource(): ".agents/data" | ".agents/records" {
|
|
67
|
+
const current = this.database
|
|
68
|
+
.prepare("SELECT 1 FROM files WHERE path LIKE '.agents/data/%' LIMIT 1")
|
|
69
|
+
.get();
|
|
70
|
+
return current === undefined ? ".agents/records" : ".agents/data";
|
|
71
|
+
}
|
|
72
|
+
private dailyAggregateRows(): Array<Record<string, number | string | null>> {
|
|
73
|
+
if (this.dailyAggregateRowsCache === null) {
|
|
74
|
+
this.dailyAggregateRowsCache = this.database
|
|
75
|
+
.prepare("SELECT * FROM daily_aggregate_cache ORDER BY day")
|
|
76
|
+
.all() as Array<Record<string, number | string | null>>;
|
|
77
|
+
}
|
|
78
|
+
return this.dailyAggregateRowsCache;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private unfilteredViewRows(view: SqliteViewName): Array<Record<string, unknown>> {
|
|
82
|
+
const cached = this.unfilteredViewPageCache.get(view);
|
|
83
|
+
if (cached !== undefined) return cached;
|
|
84
|
+
const order = sqliteViewMetadata[view].order;
|
|
85
|
+
const rows = this.database.prepare(`SELECT * FROM ${view} ORDER BY ${order}`).all() as Array<
|
|
86
|
+
Record<string, unknown>
|
|
87
|
+
>;
|
|
88
|
+
this.unfilteredViewPageCache.set(view, rows);
|
|
89
|
+
return rows;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private technicalPayloadRows(payloadType: string): Array<Record<string, unknown>> {
|
|
93
|
+
const cached = this.technicalPayloadRowsCache.get(payloadType);
|
|
94
|
+
if (cached !== undefined) return cached;
|
|
95
|
+
const rows = (
|
|
96
|
+
this.database
|
|
97
|
+
.prepare("SELECT payload_json FROM zaip_aios_activities WHERE payload_type=?")
|
|
98
|
+
.all(payloadType) as Array<{ payload_json: string }>
|
|
99
|
+
).flatMap(({ payload_json }) => {
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(payload_json) as unknown;
|
|
102
|
+
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
|
|
103
|
+
? [parsed as Record<string, unknown>]
|
|
104
|
+
: [];
|
|
105
|
+
} catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
this.technicalPayloadRowsCache.set(payloadType, rows);
|
|
110
|
+
return rows;
|
|
111
|
+
}
|
|
112
|
+
private database: DatabaseSync;
|
|
113
|
+
private readonly ownsDatabase: boolean;
|
|
114
|
+
|
|
115
|
+
constructor(root: string, database?: DatabaseSync) {
|
|
116
|
+
super(root);
|
|
117
|
+
this.ownsDatabase = database === undefined;
|
|
118
|
+
this.database = database ?? new DatabaseSync(sqliteReadModelPath(root), { readOnly: true });
|
|
119
|
+
// The aliases are TEMP views on this connection. The rebuilding writer
|
|
120
|
+
// needs them too because first-fold readers deliberately query through
|
|
121
|
+
// the same uncommitted transaction.
|
|
122
|
+
installLegacyViewAliases(this.database);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
override async exists(path: string): Promise<boolean> {
|
|
126
|
+
const exact = this.database.prepare("SELECT 1 FROM files WHERE path = ? LIMIT 1").get(path);
|
|
127
|
+
const child = this.database
|
|
128
|
+
.prepare("SELECT 1 FROM files WHERE path LIKE ? LIMIT 1")
|
|
129
|
+
.get(`${path.replace(/\/$/, "")}/%`);
|
|
130
|
+
return exact !== undefined || child !== undefined;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override async readText(path: string): Promise<string> {
|
|
134
|
+
const row = this.database.prepare("SELECT content FROM files WHERE path = ?").get(path) as
|
|
135
|
+
| { content?: string }
|
|
136
|
+
| undefined;
|
|
137
|
+
if (row?.content === undefined)
|
|
138
|
+
throw Object.assign(new Error(`SQLite read model is missing ${path}`), { code: "ENOENT" });
|
|
139
|
+
return row.content;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
override async readBytes(path: string): Promise<Buffer> {
|
|
143
|
+
return Buffer.from(await this.readText(path), "utf8");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override async readTextFrom(
|
|
147
|
+
path: string,
|
|
148
|
+
offset: number,
|
|
149
|
+
): Promise<{ content: string; nextOffset: number }> {
|
|
150
|
+
const content = await this.readText(path);
|
|
151
|
+
const bytes = Buffer.from(content, "utf8");
|
|
152
|
+
return {
|
|
153
|
+
content: bytes.subarray(Math.min(offset, bytes.byteLength)).toString("utf8"),
|
|
154
|
+
nextOffset: bytes.byteLength,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
override async listFiles(path: string, suffix = ""): Promise<readonly string[]> {
|
|
159
|
+
const prefix = `${path.replace(/\/$/, "")}/%`;
|
|
160
|
+
const rows = this.database
|
|
161
|
+
.prepare("SELECT path FROM files WHERE path LIKE ? ORDER BY path")
|
|
162
|
+
.all(prefix) as Array<{ path: string }>;
|
|
163
|
+
return rows.map((row) => row.path).filter((candidate) => candidate.endsWith(suffix));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
override async listDirectories(path: string): Promise<readonly string[]> {
|
|
167
|
+
const prefix = `${path.replace(/\/$/, "")}/`;
|
|
168
|
+
const rows = this.database
|
|
169
|
+
.prepare("SELECT path FROM files WHERE path LIKE ?")
|
|
170
|
+
.all(`${prefix}%`) as Array<{ path: string }>;
|
|
171
|
+
return [
|
|
172
|
+
...new Set(
|
|
173
|
+
rows
|
|
174
|
+
.map((row) => row.path.slice(prefix.length).split("/")[0])
|
|
175
|
+
.filter(Boolean)
|
|
176
|
+
.map((name) => `${path.replace(/\/$/, "")}/${name}`),
|
|
177
|
+
),
|
|
178
|
+
].sort();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
close(): void {
|
|
182
|
+
if (this.ownsDatabase) this.database.close();
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private reopen(): void {
|
|
186
|
+
this.database = new DatabaseSync(sqliteReadModelPath(this.root), { readOnly: true });
|
|
187
|
+
installLegacyViewAliases(this.database);
|
|
188
|
+
this.executionDurationCache.clear();
|
|
189
|
+
this.dailyAggregateRowsCache = null;
|
|
190
|
+
this.firstFoldAllTimeCache = null;
|
|
191
|
+
this.firstFoldAllTimeBoardCache = null;
|
|
192
|
+
this.firstFoldTopTasksAllTimeCache = null;
|
|
193
|
+
this.firstFoldViewportCache = null;
|
|
194
|
+
this.firstFoldMonthlyQuickCache = undefined;
|
|
195
|
+
this.firstFoldViewportTimings = {};
|
|
196
|
+
this.metadataValues = null;
|
|
197
|
+
// Public pages belong to the opened immutable SQLite generation. Never
|
|
198
|
+
// carry them across refresh/rebuild, even when this filesystem instance is
|
|
199
|
+
// reused by the launcher.
|
|
200
|
+
this.unfilteredViewPageCache.clear();
|
|
201
|
+
this.technicalPayloadRowsCache.clear();
|
|
202
|
+
this.costMonitorSummaryCache.clear();
|
|
203
|
+
this.viewPageResultCache.clear();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Reopen after an external atomic canonical read-model rebuild. */
|
|
207
|
+
refresh(): void {
|
|
208
|
+
this.database.close();
|
|
209
|
+
this.reopen();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Release the Windows read-only handle before replacing the generation.
|
|
214
|
+
* The prior snapshot is reopened when rebuilding fails, preserving a usable
|
|
215
|
+
* read model and surfacing the original rebuild error to the caller.
|
|
216
|
+
*/
|
|
217
|
+
async rebuildAndRefresh(rebuild: () => Promise<unknown>): Promise<void> {
|
|
218
|
+
this.database.close();
|
|
219
|
+
try {
|
|
220
|
+
await rebuild();
|
|
221
|
+
} finally {
|
|
222
|
+
this.reopen();
|
|
223
|
+
}
|
|
224
|
+
// A successful refresh must leave the precise public Cost Monitor view
|
|
225
|
+
// usable before the server builds its response snapshot.
|
|
226
|
+
this.viewPage("cost_monitor_daily", { limit: 1, offset: 0 });
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Wall-clock execution duration by Sao Paulo day. Root Runs define the
|
|
231
|
+
* execution envelope; child Runs are intentionally excluded because their
|
|
232
|
+
* time is already contained by the root. Concurrent roots are merged so the
|
|
233
|
+
* same clock interval is never counted twice.
|
|
234
|
+
*/
|
|
235
|
+
executionDurationByDay(
|
|
236
|
+
filter: {
|
|
237
|
+
from: string | null;
|
|
238
|
+
to: string | null;
|
|
239
|
+
providers?: readonly string[];
|
|
240
|
+
models?: readonly string[];
|
|
241
|
+
agents?: readonly string[];
|
|
242
|
+
phases?: readonly string[];
|
|
243
|
+
statuses?: readonly string[];
|
|
244
|
+
},
|
|
245
|
+
taskId: string | null = null,
|
|
246
|
+
): Map<string, number> {
|
|
247
|
+
return queryExecutionDurationByDay(this.queryContext(), filter, taskId);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
canonicalRunCountByDay(filter: {
|
|
251
|
+
from: string | null;
|
|
252
|
+
to: string | null;
|
|
253
|
+
providers?: readonly string[];
|
|
254
|
+
models?: readonly string[];
|
|
255
|
+
agents?: readonly string[];
|
|
256
|
+
phases?: readonly string[];
|
|
257
|
+
statuses?: readonly string[];
|
|
258
|
+
}): Map<string, number> {
|
|
259
|
+
return queryCanonicalRunCountByDay(this.queryContext(), filter);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
dailyPeriods(filter: { from: string | null; to: string | null }) {
|
|
263
|
+
return queryDailyPeriods(this.queryContext(), filter);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** SQL-backed first-fold aggregate. SQLite SUM excludes unknown null facts. */
|
|
267
|
+
firstFoldAggregate(filter: { from: string | null; to: string | null }): SqliteFirstFoldAggregate {
|
|
268
|
+
return queryFirstFoldAggregate(this.queryContext(), filter);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Returns the materialized default-month inputs when they remain complete.
|
|
273
|
+
* A later month with no facts in this immutable generation is also an exact
|
|
274
|
+
* empty result; every month that may contain a fact continues through SQL.
|
|
275
|
+
*/
|
|
276
|
+
firstFoldMonthlyQuick(filter: {
|
|
277
|
+
from: string | null;
|
|
278
|
+
to: string | null;
|
|
279
|
+
}): SqliteFirstFoldMonthlyQuick | null {
|
|
280
|
+
const read = readFirstFoldMonthlyQuick(this.database, this.firstFoldMonthlyQuickCache, filter);
|
|
281
|
+
this.firstFoldMonthlyQuickCache = read.cache;
|
|
282
|
+
return read.result;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
firstFoldRelevantLatestDay(): string | null {
|
|
286
|
+
const row = this.database
|
|
287
|
+
.prepare(`SELECT MAX(day) AS day FROM (
|
|
288
|
+
SELECT occurred_day_sp AS day FROM activities
|
|
289
|
+
UNION ALL SELECT occurred_day_sp AS day FROM canonical_work_items
|
|
290
|
+
UNION ALL SELECT occurred_day_sp AS day FROM canonical_artifacts
|
|
291
|
+
UNION ALL SELECT occurred_day_sp AS day FROM canonical_run_index
|
|
292
|
+
UNION ALL SELECT occurred_day_sp AS day FROM attributed_token_active_facts
|
|
293
|
+
)`)
|
|
294
|
+
.get() as { day?: string | null };
|
|
295
|
+
return typeof row.day === "string" ? row.day : null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
firstFoldAllTime(): SqliteFirstFoldAllTime {
|
|
299
|
+
if (this.firstFoldAllTimeCache !== null) return this.firstFoldAllTimeCache;
|
|
300
|
+
this.firstFoldAllTimeCache = readFirstFoldAllTime(
|
|
301
|
+
this.database,
|
|
302
|
+
() => this.dailyAggregateRows().length,
|
|
303
|
+
this.firstFoldViewportAllTime(),
|
|
304
|
+
);
|
|
305
|
+
return this.firstFoldAllTimeCache;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
firstFoldBoardAllTime(): SqliteFirstFoldAllTimeBoard {
|
|
309
|
+
if (this.firstFoldAllTimeBoardCache !== null) return this.firstFoldAllTimeBoardCache;
|
|
310
|
+
this.firstFoldAllTimeBoardCache = readFirstFoldBoardAllTime(this.database, () => {
|
|
311
|
+
const rows = operationsWorkListSqlRows(this.database);
|
|
312
|
+
return {
|
|
313
|
+
pages: {
|
|
314
|
+
task: rows.filter((row) => row.kind === "task" || row.kind === "standalone-task"),
|
|
315
|
+
spec: rows.filter((row) => row.kind === "spec"),
|
|
316
|
+
prd: rows.filter((row) => row.kind === "prd"),
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
return this.firstFoldAllTimeBoardCache;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
firstFoldTopTasksAllTime(): SqliteFirstFoldAllTime["top_tasks"] {
|
|
324
|
+
if (this.firstFoldTopTasksAllTimeCache !== null) return this.firstFoldTopTasksAllTimeCache;
|
|
325
|
+
this.firstFoldTopTasksAllTimeCache = readFirstFoldTopTasksAllTime(this.database);
|
|
326
|
+
return this.firstFoldTopTasksAllTimeCache;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
firstFoldViewportAllTime(): SqliteFirstFoldViewport {
|
|
330
|
+
if (this.firstFoldViewportCache !== null) return this.firstFoldViewportCache;
|
|
331
|
+
this.firstFoldViewportCache = readFirstFoldViewport(
|
|
332
|
+
this.database,
|
|
333
|
+
this.firstFoldViewportTimings,
|
|
334
|
+
);
|
|
335
|
+
return this.firstFoldViewportCache;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
firstFoldViewportProfile(): Readonly<Record<string, number>> {
|
|
339
|
+
return this.firstFoldViewportTimings;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Top tasks from canonical activities, limited by the caller for first paint. */
|
|
343
|
+
topTasks(filter: { from: string | null; to: string | null }, limit = 5) {
|
|
344
|
+
return queryTopTasks(this.queryContext(), filter, limit);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
canonicalTraceFiles(markers: readonly string[]): Array<{ path: string; content: string }> {
|
|
348
|
+
const selected = [...new Set(markers.filter(Boolean))];
|
|
349
|
+
if (selected.length === 0) return [];
|
|
350
|
+
const clauses = selected.map(() => "content LIKE ?").join(" OR ");
|
|
351
|
+
return this.database
|
|
352
|
+
.prepare(`SELECT path, content FROM files
|
|
353
|
+
WHERE (path LIKE '.agents/data/%' OR path LIKE '.agents/records/%') AND (${clauses}) ORDER BY path`)
|
|
354
|
+
.all(...selected.map((marker) => `%${marker}%`)) as Array<{
|
|
355
|
+
path: string;
|
|
356
|
+
content: string;
|
|
357
|
+
}>;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
taskTraceUsage(taskId: string) {
|
|
361
|
+
const runs = this.database
|
|
362
|
+
.prepare(`SELECT run_id, run_role, phase, duration_ms FROM canonical_run_index
|
|
363
|
+
WHERE task_id = ?`)
|
|
364
|
+
.all(taskId) as Array<{
|
|
365
|
+
run_id: string;
|
|
366
|
+
run_role: string;
|
|
367
|
+
phase: string | null;
|
|
368
|
+
duration_ms: number | null;
|
|
369
|
+
}>;
|
|
370
|
+
const financial = this.database
|
|
371
|
+
.prepare(`SELECT run_id, total_tokens, cost_brl FROM activities WHERE task_id = ?`)
|
|
372
|
+
.all(taskId) as Array<{
|
|
373
|
+
run_id: string;
|
|
374
|
+
total_tokens: number | null;
|
|
375
|
+
cost_brl: number | null;
|
|
376
|
+
}>;
|
|
377
|
+
const knownDurationRuns = runs.filter(
|
|
378
|
+
(run) =>
|
|
379
|
+
run.run_role === "root" && run.phase === "execution" && typeof run.duration_ms === "number",
|
|
380
|
+
).length;
|
|
381
|
+
const durationByDay = this.executionDurationByDay({ from: null, to: null }, taskId);
|
|
382
|
+
const duration =
|
|
383
|
+
durationByDay.size === 0
|
|
384
|
+
? null
|
|
385
|
+
: [...durationByDay.values()].reduce((sum, value) => sum + value, 0);
|
|
386
|
+
const knownTokens = financial.filter((row) => typeof row.total_tokens === "number");
|
|
387
|
+
const knownCosts = financial.filter((row) => typeof row.cost_brl === "number");
|
|
388
|
+
const metric = (value: number | null, known: number) => ({
|
|
389
|
+
value,
|
|
390
|
+
known_runs: known,
|
|
391
|
+
unknown_runs: Math.max(0, runs.length - known),
|
|
392
|
+
coverage_ratio: runs.length === 0 ? 1 : known / runs.length,
|
|
393
|
+
});
|
|
394
|
+
return {
|
|
395
|
+
run_count: runs.length,
|
|
396
|
+
duration_ms: metric(duration, knownDurationRuns),
|
|
397
|
+
total_tokens: metric(
|
|
398
|
+
knownTokens.length === 0
|
|
399
|
+
? null
|
|
400
|
+
: knownTokens.reduce((sum, row) => sum + Number(row.total_tokens), 0),
|
|
401
|
+
knownTokens.length,
|
|
402
|
+
),
|
|
403
|
+
cost: {
|
|
404
|
+
...metric(
|
|
405
|
+
knownCosts.length === 0
|
|
406
|
+
? null
|
|
407
|
+
: knownCosts.reduce((sum, row) => sum + Number(row.cost_brl), 0),
|
|
408
|
+
knownCosts.length,
|
|
409
|
+
),
|
|
410
|
+
currency: knownCosts.length === 0 ? null : ("BRL" as const),
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Cost Monitor agent population: canonical Agent Runs filtered by São Paulo calendar day. */
|
|
416
|
+
invocationTotals(filter: { from: string | null; to: string | null }): {
|
|
417
|
+
invocation_count: number;
|
|
418
|
+
llm_call_count: number | null;
|
|
419
|
+
total_tokens: number | null;
|
|
420
|
+
cost_usd: number | null;
|
|
421
|
+
cost_brl: number | null;
|
|
422
|
+
} {
|
|
423
|
+
return queryInvocationTotals(this.queryContext(), filter);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
invocationCostRows(filter: {
|
|
427
|
+
from: string | null;
|
|
428
|
+
to: string | null;
|
|
429
|
+
providers?: readonly string[];
|
|
430
|
+
models?: readonly string[];
|
|
431
|
+
agents?: readonly string[];
|
|
432
|
+
phases?: readonly string[];
|
|
433
|
+
statuses?: readonly string[];
|
|
434
|
+
tasks?: readonly string[];
|
|
435
|
+
specs?: readonly string[];
|
|
436
|
+
prds?: readonly string[];
|
|
437
|
+
executions?: readonly string[];
|
|
438
|
+
changes?: readonly string[];
|
|
439
|
+
}) {
|
|
440
|
+
return queryInvocationCostRows(this.queryContext(), filter);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Attributed active-time facts for exactly the Cost Monitor financial
|
|
445
|
+
* population. This deliberately reads the same activity x Sao Paulo day
|
|
446
|
+
* fact used by Operations: recomputing a union from raw source intervals
|
|
447
|
+
* made the two surfaces disagree whenever sessions overlapped.
|
|
448
|
+
*/
|
|
449
|
+
costMonitorFactualDurationByDay(
|
|
450
|
+
filter: Parameters<SqliteReadModelFileSystem["invocationCostRows"]>[0],
|
|
451
|
+
financialRows: readonly Record<string, unknown>[] = this.costMonitorFinancialActivityRows(
|
|
452
|
+
filter,
|
|
453
|
+
),
|
|
454
|
+
): Map<string, { known_sum: number; eligible_runs: number; known_runs: number }> {
|
|
455
|
+
return queryCostMonitorFactualDurationByDay(this.queryContext(), filter, financialRows);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** Complete canonical Run population for global Cost Monitor aggregates. */
|
|
459
|
+
activityCostRows(filter: {
|
|
460
|
+
from: string | null;
|
|
461
|
+
to: string | null;
|
|
462
|
+
providers?: readonly string[];
|
|
463
|
+
models?: readonly string[];
|
|
464
|
+
agents?: readonly string[];
|
|
465
|
+
phases?: readonly string[];
|
|
466
|
+
statuses?: readonly string[];
|
|
467
|
+
tasks?: readonly string[];
|
|
468
|
+
specs?: readonly string[];
|
|
469
|
+
prds?: readonly string[];
|
|
470
|
+
executions?: readonly string[];
|
|
471
|
+
changes?: readonly string[];
|
|
472
|
+
}) {
|
|
473
|
+
return queryActivityCostRows(this.queryContext(), filter);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/** Cost Monitor's historical financial population, independent of Agent-only views. */
|
|
477
|
+
costMonitorFinancialActivityRows(
|
|
478
|
+
filter: Parameters<SqliteReadModelFileSystem["activityCostRows"]>[0],
|
|
479
|
+
) {
|
|
480
|
+
return queryCostMonitorFinancialActivityRows(this.queryContext(), filter);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
/**
|
|
484
|
+
* Aggregate-only Cost Monitor source. The SQL result is bounded to one row
|
|
485
|
+
* per selected day plus conversation/planning/execution and total rows; no
|
|
486
|
+
* activity-shaped record is returned to the server or serialized to HTTP.
|
|
487
|
+
*/
|
|
488
|
+
developerCostAggregate(filter: {
|
|
489
|
+
from: string | null;
|
|
490
|
+
to: string | null;
|
|
491
|
+
accountIds?: readonly string[];
|
|
492
|
+
}) {
|
|
493
|
+
return queryDeveloperCostAggregate(this.queryContext(), filter);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Operations-only developer projection. It deliberately keeps the Cost
|
|
498
|
+
* Monitor aggregate unchanged: status, kind and risk are derived solely
|
|
499
|
+
* from canonical Task records linked to the developer's observed Task ids.
|
|
500
|
+
*/
|
|
501
|
+
operationsDeveloperAggregate(filter: {
|
|
502
|
+
from: string | null;
|
|
503
|
+
to: string | null;
|
|
504
|
+
accountIds?: readonly string[];
|
|
505
|
+
}) {
|
|
506
|
+
return queryOperationsDeveloperAggregate(this.queryContext(), filter);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
costMonitorSummaryAggregate(
|
|
510
|
+
filter: Parameters<SqliteReadModelFileSystem["activityCostRows"]>[0],
|
|
511
|
+
): CostSummarySource {
|
|
512
|
+
return queryCostMonitorSummaryAggregate(this.queryContext(), filter);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** Keyset cursor or LIMIT/OFFSET pagination for materialized work summaries. */
|
|
516
|
+
summaryPage(
|
|
517
|
+
kind: SqliteSummaryKind,
|
|
518
|
+
filter: {
|
|
519
|
+
from: string | null;
|
|
520
|
+
to: string | null;
|
|
521
|
+
status?: string;
|
|
522
|
+
risk?: string;
|
|
523
|
+
query?: string;
|
|
524
|
+
},
|
|
525
|
+
offset: number,
|
|
526
|
+
limit: number,
|
|
527
|
+
cursor: string | null = null,
|
|
528
|
+
): SqliteSummaryPage {
|
|
529
|
+
// Entity summaries retain activity-derived historical coverage. Kanban is
|
|
530
|
+
// deliberately stricter and lists only canonical lifecycle records.
|
|
531
|
+
const table = "operations_work_summary";
|
|
532
|
+
const from = filter.from?.slice(0, 10) ?? null;
|
|
533
|
+
const to = filter.to?.slice(0, 10) ?? null;
|
|
534
|
+
const cursorValue = parseSummaryCursor(cursor);
|
|
535
|
+
const clauses = [
|
|
536
|
+
"entity_kind = ?",
|
|
537
|
+
"(? IS NULL OR occurred_day_sp >= ?)",
|
|
538
|
+
"(? IS NULL OR occurred_day_sp <= ?)",
|
|
539
|
+
];
|
|
540
|
+
const values: Array<string | number | null> = [kind, from, from, to, to];
|
|
541
|
+
if (filter.status) {
|
|
542
|
+
clauses.push("status = ?");
|
|
543
|
+
values.push(filter.status);
|
|
544
|
+
}
|
|
545
|
+
if (filter.risk) {
|
|
546
|
+
clauses.push("risk = ?");
|
|
547
|
+
values.push(filter.risk);
|
|
548
|
+
}
|
|
549
|
+
if (filter.query) {
|
|
550
|
+
clauses.push("(id LIKE ? OR title LIKE ?)");
|
|
551
|
+
values.push(`%${filter.query}%`, `%${filter.query}%`);
|
|
552
|
+
}
|
|
553
|
+
const baseWhere = clauses.join(" AND ");
|
|
554
|
+
const baseValues = [...values];
|
|
555
|
+
if (cursorValue !== null) {
|
|
556
|
+
clauses.push("(occurred_at < ? OR (occurred_at = ? AND id < ?))");
|
|
557
|
+
values.push(cursorValue[0], cursorValue[0], cursorValue[1]);
|
|
558
|
+
}
|
|
559
|
+
const where = clauses.join(" AND ");
|
|
560
|
+
const total = Number(
|
|
561
|
+
(
|
|
562
|
+
this.database
|
|
563
|
+
.prepare(`SELECT COUNT(*) AS count FROM ${table} WHERE ${baseWhere}`)
|
|
564
|
+
.get(...baseValues) as { count: number }
|
|
565
|
+
).count,
|
|
566
|
+
);
|
|
567
|
+
const pageOffset = cursorValue === null ? offset : 0;
|
|
568
|
+
const rows = this.database
|
|
569
|
+
.prepare(
|
|
570
|
+
`SELECT id, title, status, risk, occurred_at, occurred_day_sp,
|
|
571
|
+
invocation_count, llm_call_count, total_duration, total_tokens, total_cost_usd, total_cost_brl
|
|
572
|
+
FROM ${table} WHERE ${where} ORDER BY occurred_at DESC, id DESC LIMIT ? OFFSET ?`,
|
|
573
|
+
)
|
|
574
|
+
.all(...values, limit, pageOffset) as Array<Record<string, unknown>>;
|
|
575
|
+
const last = rows.at(-1);
|
|
576
|
+
return {
|
|
577
|
+
data_source: "sqlite_read_model",
|
|
578
|
+
kind,
|
|
579
|
+
offset: pageOffset,
|
|
580
|
+
limit,
|
|
581
|
+
total,
|
|
582
|
+
has_more: rows.length === limit && (cursorValue !== null || pageOffset + rows.length < total),
|
|
583
|
+
next_cursor:
|
|
584
|
+
last === undefined || rows.length < limit
|
|
585
|
+
? null
|
|
586
|
+
: encodeSummaryCursor(String(last.occurred_at), String(last.id)),
|
|
587
|
+
rows,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/** Canonical page for the Board: keeps telemetry-only historical rows out. */
|
|
592
|
+
canonicalWorkPage(
|
|
593
|
+
kind: SqliteSummaryKind,
|
|
594
|
+
filter: { from: string | null; to: string | null },
|
|
595
|
+
offset: number,
|
|
596
|
+
limit: number,
|
|
597
|
+
) {
|
|
598
|
+
return this.viewPage("operations_work_list", {
|
|
599
|
+
...filter,
|
|
600
|
+
kind: kind === "task" ? "all-tasks" : kind,
|
|
601
|
+
offset,
|
|
602
|
+
limit,
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
overviewPage(period: "day" | "month" | "year", offset: number, limit: number) {
|
|
607
|
+
return queryOverviewPage(this.queryContext(), period, offset, limit);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
viewPage(
|
|
611
|
+
view: SqliteViewName,
|
|
612
|
+
input: {
|
|
613
|
+
from?: string | null;
|
|
614
|
+
to?: string | null;
|
|
615
|
+
query?: string;
|
|
616
|
+
status?: string;
|
|
617
|
+
risk?: string;
|
|
618
|
+
provider?: string;
|
|
619
|
+
model?: string;
|
|
620
|
+
agent?: string;
|
|
621
|
+
phase?: string;
|
|
622
|
+
origin?: string;
|
|
623
|
+
workType?: string;
|
|
624
|
+
priority?: string;
|
|
625
|
+
kind?: "all" | "all-tasks" | "task" | "standalone-task" | "prd" | "spec";
|
|
626
|
+
offset?: number;
|
|
627
|
+
limit?: number;
|
|
628
|
+
},
|
|
629
|
+
): ReturnType<SqliteReadModelFileSystem["uncachedViewPage"]> {
|
|
630
|
+
const key = `${view}:${JSON.stringify(input)}`;
|
|
631
|
+
const cached = this.viewPageResultCache.get(key);
|
|
632
|
+
if (cached !== undefined)
|
|
633
|
+
return structuredClone(cached) as ReturnType<SqliteReadModelFileSystem["uncachedViewPage"]>;
|
|
634
|
+
const result = this.uncachedViewPage(view, input);
|
|
635
|
+
if (view === "cost_monitor_zaip_agents") attachAgentProductivity(this.database, input, result);
|
|
636
|
+
if (this.viewPageResultCache.size >= 256) {
|
|
637
|
+
const oldest = this.viewPageResultCache.keys().next().value as string | undefined;
|
|
638
|
+
if (oldest !== undefined) this.viewPageResultCache.delete(oldest);
|
|
639
|
+
}
|
|
640
|
+
this.viewPageResultCache.set(key, structuredClone(result) as Record<string, unknown>);
|
|
641
|
+
return result;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/** Paginated allowlisted SQL view reader. Views are never interpolated from user input. */
|
|
645
|
+
private uncachedViewPage(
|
|
646
|
+
view: SqliteViewName,
|
|
647
|
+
input: {
|
|
648
|
+
from?: string | null;
|
|
649
|
+
to?: string | null;
|
|
650
|
+
query?: string;
|
|
651
|
+
status?: string;
|
|
652
|
+
risk?: string;
|
|
653
|
+
provider?: string;
|
|
654
|
+
model?: string;
|
|
655
|
+
agent?: string;
|
|
656
|
+
phase?: string;
|
|
657
|
+
origin?: string;
|
|
658
|
+
workType?: string;
|
|
659
|
+
priority?: string;
|
|
660
|
+
kind?: "all" | "all-tasks" | "task" | "standalone-task" | "prd" | "spec";
|
|
661
|
+
offset?: number;
|
|
662
|
+
limit?: number;
|
|
663
|
+
},
|
|
664
|
+
) {
|
|
665
|
+
return queryUncachedViewPage(this.queryContext(), view, input);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
metadata(): {
|
|
669
|
+
storage_mode: "sqlite_read_model";
|
|
670
|
+
db_path: string;
|
|
671
|
+
source_file_count: number;
|
|
672
|
+
excluded_source_count: number;
|
|
673
|
+
daily_aggregate_count: number;
|
|
674
|
+
activity_count: number;
|
|
675
|
+
canonical_run_count: number;
|
|
676
|
+
agent_run_count: number;
|
|
677
|
+
telemetry_summary_count: number;
|
|
678
|
+
unassisted_activity_count: number;
|
|
679
|
+
} {
|
|
680
|
+
if (this.metadataValues === null) {
|
|
681
|
+
this.metadataValues = new Map(
|
|
682
|
+
(
|
|
683
|
+
this.database.prepare("SELECT key, value FROM read_model_metadata").all() as Array<{
|
|
684
|
+
key: string;
|
|
685
|
+
value: string;
|
|
686
|
+
}>
|
|
687
|
+
).map((row) => [row.key, row.value]),
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
const value = (key: string) => Number(this.metadataValues?.get(key) ?? 0);
|
|
691
|
+
return {
|
|
692
|
+
storage_mode: "sqlite_read_model",
|
|
693
|
+
db_path: process.env.ZAIP_SQLITE_DB_PATH ? "session-specific" : dbRelativePath,
|
|
694
|
+
source_file_count: value("source_file_count"),
|
|
695
|
+
excluded_source_count: value("excluded_source_count"),
|
|
696
|
+
daily_aggregate_count: value("daily_aggregate_count"),
|
|
697
|
+
activity_count: value("activity_count"),
|
|
698
|
+
canonical_run_count: value("canonical_run_count"),
|
|
699
|
+
agent_run_count: value("agent_run_count"),
|
|
700
|
+
telemetry_summary_count: value("telemetry_summary_count"),
|
|
701
|
+
unassisted_activity_count: value("unassisted_activity_count"),
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
projectionUpdatedAt(): string | null {
|
|
706
|
+
if (this.metadataValues === null) this.metadata();
|
|
707
|
+
const value = this.metadataValues?.get("snapshot_updated_at") ?? null;
|
|
708
|
+
return value !== null && Number.isFinite(Date.parse(value)) ? value : null;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
latestTokenCollectedAt(): string | null {
|
|
712
|
+
if (this.metadataValues === null) this.metadata();
|
|
713
|
+
const value = this.metadataValues?.get("latest_token_collected_at") ?? null;
|
|
714
|
+
return value !== null && Number.isFinite(Date.parse(value)) ? value : null;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
private queryContext(): SqliteQueryContext {
|
|
718
|
+
return {
|
|
719
|
+
database: this.database,
|
|
720
|
+
executionDurationCache: this.executionDurationCache,
|
|
721
|
+
costMonitorSummaryCache: this.costMonitorSummaryCache,
|
|
722
|
+
executionDurationByDay: this.executionDurationByDay.bind(this),
|
|
723
|
+
costMonitorFinancialActivityRows: this.costMonitorFinancialActivityRows.bind(this),
|
|
724
|
+
costMonitorFactualDurationByDay: this.costMonitorFactualDurationByDay.bind(this),
|
|
725
|
+
costMonitorSummaryAggregate: this.costMonitorSummaryAggregate.bind(this),
|
|
726
|
+
firstFoldMonthlyQuick: this.firstFoldMonthlyQuick.bind(this),
|
|
727
|
+
dailyAggregateRows: this.dailyAggregateRows.bind(this),
|
|
728
|
+
technicalPayloadRows: this.technicalPayloadRows.bind(this),
|
|
729
|
+
unfilteredViewRows: this.unfilteredViewRows.bind(this),
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
function encodeSummaryCursor(occurredAt: string, id: string): string {
|
|
735
|
+
return encodeURIComponent(JSON.stringify([occurredAt, id]));
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function parseSummaryCursor(cursor: string | null): [string, string] | null {
|
|
739
|
+
if (cursor === null) return null;
|
|
740
|
+
try {
|
|
741
|
+
const parsed = JSON.parse(decodeURIComponent(cursor));
|
|
742
|
+
return Array.isArray(parsed) && typeof parsed[0] === "string" && typeof parsed[1] === "string"
|
|
743
|
+
? [parsed[0], parsed[1]]
|
|
744
|
+
: null;
|
|
745
|
+
} catch {
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
}
|