@zaip-ai/cli 2.6.0 → 3.1.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/README.md +36 -13
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +5 -2
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +12 -9
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +32 -21
- package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
- package/dist/services/install-agents-template.js +9 -1
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/runtime-template.test.js +25 -2
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/services/transactional-files.d.ts.map +1 -1
- package/dist/services/transactional-files.js +59 -14
- package/dist/services/transactional-files.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/README-ENG.md +75 -10
- package/templates/.agents/README.md +76 -10
- package/templates/.agents/config/agents/catalog.yaml +3 -0
- package/templates/.agents/config/agents/discovery.json +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +13 -10
- package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -1
- package/templates/.agents/config/project.yaml +10 -1
- package/templates/.agents/dashboard/.zaip-managed.json +274 -138
- package/templates/.agents/dashboard/README.md +16 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-CGxeQak4.js → CostCalculationGuidePage-CEDZjl4V.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-tzS7YxYB.js → DashboardHelpDialog-DIWDmvAS.js} +930 -550
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-DEbCi1gP.js → PricingSettingsDialog-BBRBKaHa.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-B9GWkEyN.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BAvLPAee.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-t1Om0Abw.js → TraceabilityWorkspace-C9dDhj34.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-06__WZco.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-CoAVMZN6.js +828 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DiGC-dsJ.js → icons-vendor-DEmo6Tn2.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-BVzw_Wux.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-kPO6yNed.js → react-vendor-CadYsm83.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BzKK8kK3.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +5 -5
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +10 -5
- package/templates/.agents/dashboard/apps/frontend/src/AutonomySettings.tsx +82 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +38 -7
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +164 -171
- package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +6 -1
- package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +149 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +2 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +22 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.test.ts +54 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +20 -2
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +37 -43
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +9 -251
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +34 -7
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.test.ts +51 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +35 -0
- package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +19 -4
- package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +5 -3
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +112 -23
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +49 -12
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-copy.ts +181 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +11 -1
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +34 -51
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-state.css +55 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +12 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +1 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +6 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +2 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +4 -15
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +2 -2
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/complete-cost-average.test.ts +73 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +9 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/period-averages.ts +60 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -22
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +2 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +32 -8
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +3 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +1 -42
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +2 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +3 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +8 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +66 -3
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +71 -1
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +36 -30
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +5 -14
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +46 -0
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +28 -1
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +11 -4
- package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +2 -2
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +28 -8
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +19 -2
- package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +89 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +3 -3
- package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +2 -1
- 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/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 +279 -245
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +247 -215
- package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -2
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +15 -25
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +279 -245
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.test.ts +142 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/project-installation-summary.ts +190 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +65 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +67 -66
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.test.ts +91 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +24 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/server-hono-security.test.ts +17 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +21 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +94 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +62 -12
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +4 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.test.ts +97 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +10 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +2 -10
- package/templates/.agents/dashboard/packages/local-runtime/src/server-traceability-index.test.ts +84 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +15 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-calendar.ts +17 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cold-parse.test.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-dimension-facts.test.ts +12 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.test.ts +94 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +5 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-duration-lookup.test.ts +59 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-entity-label-views.test.ts +72 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-file-index.test.ts +69 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +9 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +4 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-period-averages.ts +46 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-provider-alias-parity.test.ts +50 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.test.ts +171 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +36 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +13 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +25 -7
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical-parsing.ts +7 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +5 -15
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +34 -10
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +17 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +11 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +5 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +54 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +4 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-risk-population.test.ts +98 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +29 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +2 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/verify-project-settings.mjs +57 -0
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/scripts/qualify-observability.mjs +130 -0
- package/templates/.agents/dashboard/scripts/verify-autonomy-settings.mjs +175 -0
- package/templates/.agents/dashboard/scripts/verify-observability.mjs +254 -0
- package/templates/.agents/dashboard/scripts/verify-project-setup.mjs +64 -0
- package/templates/.agents/dashboard/tests/e2e/lease-global-setup.ts +37 -0
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +5 -3
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-period-transition.spec.ts +22 -1
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +17 -8
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +47 -6
- package/templates/.agents/dashboard/tests/e2e/specs/lease-lifetime.spec.ts +14 -0
- package/templates/.agents/dashboard/tests/observability-fixture.mjs +200 -0
- package/templates/.agents/design/.zaip-managed.json +84 -40
- package/templates/.agents/design/apps/catalog/dist/assets/index-BJV597iq.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-BOjCcUaU.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-B_WhrCZe.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-CqtYXZfV.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-D_lfqoyx.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/assets/index-i_PO2k9R.js +9 -0
- package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-Cstn1UwA.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{Color-6AOWCN3U-B-kAgAjB.js → Color-6AOWCN3U-Cm-yJJz_.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-D1WopB2L.js +137 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DQ9PJ3N3.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{DocsRenderer-JROSPFPF-BVN7xHtv.js → DocsRenderer-JROSPFPF-Belk4jRr.js} +4 -4
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{WithTooltip-7X4HQR7L-CDHtKYkz.js → WithTooltip-7X4HQR7L-DoPvjkS1.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-DRQKCCAG-D6AsDkMK.js → chunk-DRQKCCAG-B1itKXEN.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{chunk-W22LQPXL-B4m5uloN.js → chunk-W22LQPXL-C-Eb5SPY.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{components-CN8YyTUg.js → components-DnyKLwhj.js} +5 -5
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-D0OSgxWz.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{iframe-9yZfIsdT.js → iframe-DcXBsFPz.js} +3 -3
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{react-18-BoCSnq6H.js → react-18-CRM89QRf.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-C3tkVMIp.js +1 -0
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{syntaxhighlighter-YFXUGROL-Bnn_nMwJ.js → syntaxhighlighter-YFXUGROL-B03jQGTF.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/{theming-DS_ue2sb.js → theming-4ZyufAga.js} +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/iframe.html +1 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/index.json +1 -1
- package/templates/.agents/design/apps/catalog/package.json +2 -2
- package/templates/.agents/design/apps/catalog/src/components/AutonomySpecimen.tsx +15 -0
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +19 -0
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +45 -0
- package/templates/.agents/design/apps/catalog/src/components/EstimatedCostSpecimen.tsx +48 -0
- package/templates/.agents/design/apps/catalog/src/components/ProjectStatusSpecimen.tsx +169 -0
- package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +55 -0
- package/templates/.agents/design/apps/catalog/src/stories/Components.stories.tsx +60 -0
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/requirements/autonomous-assurance.md +1 -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 +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 +5 -5
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/astra-diagnostic.md +3 -1
- package/templates/.agents/rules/autonomy-decision.md +10 -2
- package/templates/.agents/rules/core.md +12 -1
- package/templates/.agents/rules/run-lifecycle-closure.md +8 -6
- package/templates/.agents/rules/workflow.md +2 -2
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +383 -350
- 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 +3 -3
- package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +28 -5
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +17 -3
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +8 -9
- package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +10 -6
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +17 -12
- package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +21 -23
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +37 -13
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +2 -0
- package/templates/.agents/zaip-aios/INDEX.md +9 -1
- package/templates/.agents/zaip-aios/README.md +24 -2
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +5 -1
- package/templates/.agents/zaip-aios/guides/03-tasks.md +15 -2
- package/templates/.agents/zaip-aios/guides/04-specs.md +13 -0
- package/templates/.agents/zaip-aios/guides/05-prds.md +13 -0
- package/templates/.agents/zaip-aios/guides/06-execucao.md +19 -4
- package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +14 -0
- package/templates/.agents/zaip-aios/guides/08-contexto-e-tokens.md +4 -3
- package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +17 -9
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +9 -0
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +69 -0
- package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +9 -4
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +7 -1
- package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +18 -0
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +54 -3
- package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +10 -2
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +186 -5
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +21 -15
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +18 -2
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +14 -2
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +190 -489
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +72 -13
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +18 -0
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +18 -1
- package/templates/template-manifest.json +454 -274
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/dashboard-localization-CLJ0lT9v.js +0 -231
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/CatalogShell-BWY-80s4.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/Components.stories-Be2mDUQj.js +0 -27
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/DesignSystem.stories-DRx9blDs.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/formatter-L2YTDE3Q-EwuTh8Zk.js +0 -1
- package/templates/.agents/design/apps/catalog/dist/storybook/assets/react-DyL61NPT.js +0 -1
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.test.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { DatabaseSync } from "node:sqlite";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import type { SqliteViewInput } from "./sqlite-query-context.js";
|
|
4
|
+
import { readEntityGroup } from "./sqlite-query-entity-group.js";
|
|
5
|
+
|
|
6
|
+
const databases: DatabaseSync[] = [];
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
vi.restoreAllMocks();
|
|
9
|
+
for (const database of databases.splice(0)) database.close();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
function fixture(kind: "spec" | "prd") {
|
|
13
|
+
const database = new DatabaseSync(":memory:");
|
|
14
|
+
databases.push(database);
|
|
15
|
+
database.exec(`
|
|
16
|
+
CREATE TABLE ${kind}s (id TEXT PRIMARY KEY, title TEXT, status TEXT, risk TEXT,
|
|
17
|
+
occurred_at TEXT, occurred_day_sp TEXT);
|
|
18
|
+
CREATE TABLE invocations (agent_invocation_id TEXT PRIMARY KEY, ${kind}_id TEXT,
|
|
19
|
+
occurred_at TEXT, occurred_day_sp TEXT, llm_call_count INTEGER, duration_ms REAL,
|
|
20
|
+
input_tokens REAL, cached_input_tokens REAL, output_tokens REAL, reasoning_tokens REAL,
|
|
21
|
+
total_tokens REAL, cost_usd REAL, cost_brl REAL);
|
|
22
|
+
`);
|
|
23
|
+
const entity = (id: string, day = "2026-09-10", status = "completed", risk = "standard") =>
|
|
24
|
+
database
|
|
25
|
+
.prepare(`INSERT INTO ${kind}s VALUES (?, ?, ?, ?, ?, ?)`)
|
|
26
|
+
.run(id, `Title ${id}`, status, risk, `${day}T12:00:00Z`, day);
|
|
27
|
+
const invocation = (id: string, parent: string, day: string, cost: number | null) =>
|
|
28
|
+
database
|
|
29
|
+
.prepare("INSERT INTO invocations VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
|
|
30
|
+
.run(
|
|
31
|
+
id,
|
|
32
|
+
parent,
|
|
33
|
+
`${day}T13:00:00Z`,
|
|
34
|
+
day,
|
|
35
|
+
cost === null ? null : 1,
|
|
36
|
+
cost,
|
|
37
|
+
cost,
|
|
38
|
+
cost,
|
|
39
|
+
cost,
|
|
40
|
+
cost,
|
|
41
|
+
cost,
|
|
42
|
+
cost,
|
|
43
|
+
cost,
|
|
44
|
+
);
|
|
45
|
+
const read = (input: SqliteViewInput = {}) =>
|
|
46
|
+
readEntityGroup(
|
|
47
|
+
{ database },
|
|
48
|
+
kind === "spec" ? "cost_monitor_specs" : "cost_monitor_prds",
|
|
49
|
+
input,
|
|
50
|
+
kind,
|
|
51
|
+
);
|
|
52
|
+
return { database, entity, invocation, read };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
describe.each(["spec", "prd"] as const)("canonical %s single grouped query", (kind) => {
|
|
56
|
+
it("computes full totals and deterministic pages with one SQL statement", () => {
|
|
57
|
+
const { database, entity, invocation, read } = fixture(kind);
|
|
58
|
+
for (let i = 0; i < 12; i++) {
|
|
59
|
+
const id = `E${String(i).padStart(2, "0")}`;
|
|
60
|
+
entity(id);
|
|
61
|
+
invocation(`I${i}`, id, "2026-09-10", 0.12345678901234566);
|
|
62
|
+
}
|
|
63
|
+
const prepare = vi.spyOn(database, "prepare");
|
|
64
|
+
const first = read({ limit: 10 });
|
|
65
|
+
expect(prepare).toHaveBeenCalledTimes(1);
|
|
66
|
+
prepare.mockClear();
|
|
67
|
+
const second = read({ limit: 10, offset: 10 });
|
|
68
|
+
expect(prepare).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(first.total_count).toBe(12);
|
|
70
|
+
expect(first.has_more).toBe(true);
|
|
71
|
+
expect(second.has_more).toBe(false);
|
|
72
|
+
expect(second.rows.map((row) => row.id)).toEqual(["E10", "E11"]);
|
|
73
|
+
expect(first.totals).toEqual(second.totals);
|
|
74
|
+
expect(first.totals).toMatchObject({
|
|
75
|
+
entity_count: 12,
|
|
76
|
+
invocation_count: 12,
|
|
77
|
+
total_duration: 1,
|
|
78
|
+
});
|
|
79
|
+
expect(first.rows[0]).toMatchObject({
|
|
80
|
+
id: "E00",
|
|
81
|
+
key: "E00",
|
|
82
|
+
total_cost_brl: 0.12345678901234566,
|
|
83
|
+
});
|
|
84
|
+
expect(Object.keys(first.rows[0] ?? {}).some((key) => key.startsWith("__"))).toBe(false);
|
|
85
|
+
const beyond = read({ limit: 10, offset: 99 });
|
|
86
|
+
expect(beyond).toMatchObject({
|
|
87
|
+
total_count: 12,
|
|
88
|
+
rows: [],
|
|
89
|
+
totals: first.totals,
|
|
90
|
+
has_more: false,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("retains canonical entity dates, no-run unknowns and observed zero with filters", () => {
|
|
95
|
+
const { entity, invocation, read } = fixture(kind);
|
|
96
|
+
entity("CURRENT");
|
|
97
|
+
invocation("old-run", "CURRENT", "2026-08-01", 100);
|
|
98
|
+
entity("ZERO");
|
|
99
|
+
invocation("zero", "ZERO", "2026-09-10", 0);
|
|
100
|
+
entity("UNKNOWN");
|
|
101
|
+
invocation("unknown", "UNKNOWN", "2026-09-10", null);
|
|
102
|
+
entity("NO-RUN");
|
|
103
|
+
entity("OLD", "2026-08-01");
|
|
104
|
+
invocation("new-run", "OLD", "2026-09-10", 999);
|
|
105
|
+
entity("BLOCKED", "2026-09-10", "blocked", "critical");
|
|
106
|
+
const page = read({
|
|
107
|
+
from: "2026-09-01",
|
|
108
|
+
to: "2026-09-30",
|
|
109
|
+
status: "completed",
|
|
110
|
+
risk: "standard",
|
|
111
|
+
});
|
|
112
|
+
expect(page.total_count).toBe(4);
|
|
113
|
+
expect(page.totals).toEqual({
|
|
114
|
+
entity_count: 4,
|
|
115
|
+
invocation_count: 2,
|
|
116
|
+
total_duration: 0,
|
|
117
|
+
total_tokens: 0,
|
|
118
|
+
total_cost_usd: 0,
|
|
119
|
+
total_cost_brl: 0,
|
|
120
|
+
});
|
|
121
|
+
expect(page.rows.find((row) => row.id === "CURRENT")).toMatchObject({
|
|
122
|
+
invocation_count: 0,
|
|
123
|
+
total_cost_brl: null,
|
|
124
|
+
first_day: "2026-09-10",
|
|
125
|
+
occurred_at: "2026-09-10T12:00:00Z",
|
|
126
|
+
});
|
|
127
|
+
expect(page.rows.find((row) => row.id === "ZERO")).toMatchObject({
|
|
128
|
+
total_cost_brl: 0,
|
|
129
|
+
invocation_count: 1,
|
|
130
|
+
});
|
|
131
|
+
expect(page.rows.find((row) => row.id === "UNKNOWN")).toMatchObject({
|
|
132
|
+
total_cost_brl: null,
|
|
133
|
+
invocation_count: 1,
|
|
134
|
+
});
|
|
135
|
+
expect(page.rows.find((row) => row.id === "NO-RUN")).toMatchObject({
|
|
136
|
+
total_cost_brl: null,
|
|
137
|
+
invocation_count: 0,
|
|
138
|
+
});
|
|
139
|
+
expect(read({ query: "Title BLOCKED", risk: "critical" }).rows.map((row) => row.id)).toEqual([
|
|
140
|
+
"BLOCKED",
|
|
141
|
+
]);
|
|
142
|
+
expect(read({ query: "CURRENT" }).totals.total_cost_brl).toBe(100);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("returns nullable empty totals and clamps page boundaries without losing counts", () => {
|
|
146
|
+
const { entity, read } = fixture(kind);
|
|
147
|
+
expect(read({ limit: 0, offset: -2 })).toMatchObject({
|
|
148
|
+
rows: [],
|
|
149
|
+
total_count: 0,
|
|
150
|
+
limit: 1,
|
|
151
|
+
offset: 0,
|
|
152
|
+
has_more: false,
|
|
153
|
+
totals: {
|
|
154
|
+
entity_count: 0,
|
|
155
|
+
invocation_count: 0,
|
|
156
|
+
total_duration: null,
|
|
157
|
+
total_tokens: null,
|
|
158
|
+
total_cost_usd: null,
|
|
159
|
+
total_cost_brl: null,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
entity("ONLY");
|
|
163
|
+
expect(read({ limit: 1000, offset: 1 })).toMatchObject({
|
|
164
|
+
rows: [],
|
|
165
|
+
total_count: 1,
|
|
166
|
+
limit: 200,
|
|
167
|
+
has_more: false,
|
|
168
|
+
totals: { entity_count: 1, invocation_count: 0, total_cost_brl: null },
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
});
|
|
@@ -2,7 +2,7 @@ import { type CostGroupKind, readCostGroupPage } from "./sqlite-cost-group-page.
|
|
|
2
2
|
import type { SqliteQueryContext, SqliteViewInput } from "./sqlite-query-context.js";
|
|
3
3
|
import type { SqliteViewName } from "./sqlite-read-model-types.js";
|
|
4
4
|
export function readEntityGroup(
|
|
5
|
-
context: SqliteQueryContext,
|
|
5
|
+
context: Pick<SqliteQueryContext, "database">,
|
|
6
6
|
view: SqliteViewName,
|
|
7
7
|
input: SqliteViewInput,
|
|
8
8
|
groupKind: string,
|
|
@@ -55,7 +55,7 @@ export function readEntityGroup(
|
|
|
55
55
|
const entityWhere = entityClauses.length === 0 ? "1" : entityClauses.join(" AND ");
|
|
56
56
|
const invocationJoin =
|
|
57
57
|
invocationClauses.length === 0 ? "" : ` AND ${invocationClauses.join(" AND ")}`;
|
|
58
|
-
const ctes = `WITH grouped AS (
|
|
58
|
+
const ctes = `WITH grouped AS MATERIALIZED (
|
|
59
59
|
SELECT entity.id AS group_value, entity.title, entity.status, entity.risk,
|
|
60
60
|
COALESCE(MIN(i.occurred_day_sp), entity.occurred_day_sp) AS first_day,
|
|
61
61
|
COALESCE(MAX(i.occurred_day_sp), entity.occurred_day_sp) AS last_day,
|
|
@@ -76,23 +76,43 @@ export function readEntityGroup(
|
|
|
76
76
|
const limit = Math.min(200, Math.max(1, input.limit ?? 50));
|
|
77
77
|
const offset = Math.max(0, input.offset ?? 0);
|
|
78
78
|
const values = [...invocationValues, ...entityValues];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
.prepare(`${ctes} SELECT COUNT(*) AS count FROM grouped`)
|
|
83
|
-
.get(...values) as { count: number }
|
|
84
|
-
).count,
|
|
85
|
-
);
|
|
86
|
-
const totals = context.database
|
|
79
|
+
// Materialize this population once for count, totals and the requested page.
|
|
80
|
+
// A totals-first LEFT JOIN retains totals even for an empty/out-of-range page.
|
|
81
|
+
const result = context.database
|
|
87
82
|
.prepare(
|
|
88
|
-
`${ctes}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
83
|
+
`${ctes}, totals AS (
|
|
84
|
+
SELECT COUNT(*) AS __entity_count,
|
|
85
|
+
COALESCE(SUM(invocation_count), 0) AS __invocation_count,
|
|
86
|
+
ROUND(SUM(total_duration)) AS __total_duration,
|
|
87
|
+
SUM(total_tokens) AS __total_tokens,
|
|
88
|
+
SUM(total_cost_usd) AS __total_cost_usd,
|
|
89
|
+
SUM(total_cost_brl) AS __total_cost_brl FROM grouped
|
|
90
|
+
), paged AS (
|
|
91
|
+
SELECT 1 AS __row_present, group_value AS id, group_value AS key,
|
|
92
|
+
title, status, risk, first_day, last_day, occurred_at, invocation_count,
|
|
93
|
+
llm_call_count, total_duration, total_input_tokens, total_cached_input_tokens,
|
|
94
|
+
total_output_tokens, total_reasoning_tokens, total_tokens, total_cost_usd,
|
|
95
|
+
total_cost_brl FROM grouped ORDER BY total_cost_brl DESC, group_value LIMIT ? OFFSET ?
|
|
96
|
+
) SELECT totals.*, paged.* FROM totals LEFT JOIN paged ON 1
|
|
97
|
+
ORDER BY paged.total_cost_brl DESC, paged.id`,
|
|
94
98
|
)
|
|
95
99
|
.all(...values, limit, offset) as Array<Record<string, unknown>>;
|
|
100
|
+
const aggregate = result[0];
|
|
101
|
+
if (!aggregate) throw new Error("Canonical macro query did not return its aggregate row.");
|
|
102
|
+
const total_count = Number(aggregate.__entity_count);
|
|
103
|
+
const totals = {
|
|
104
|
+
entity_count: aggregate.__entity_count,
|
|
105
|
+
invocation_count: aggregate.__invocation_count,
|
|
106
|
+
total_duration: aggregate.__total_duration,
|
|
107
|
+
total_tokens: aggregate.__total_tokens,
|
|
108
|
+
total_cost_usd: aggregate.__total_cost_usd,
|
|
109
|
+
total_cost_brl: aggregate.__total_cost_brl,
|
|
110
|
+
};
|
|
111
|
+
const rows = result
|
|
112
|
+
.filter((row) => row.__row_present === 1)
|
|
113
|
+
.map((row) =>
|
|
114
|
+
Object.fromEntries(Object.entries(row).filter(([key]) => !key.startsWith("__"))),
|
|
115
|
+
);
|
|
96
116
|
return {
|
|
97
117
|
data_source: "sqlite_read_model" as const,
|
|
98
118
|
view,
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sqlitePeriodAverages, sqlitePeriodTotals } from "./sqlite-period-averages.js";
|
|
1
2
|
import type { SqliteQueryContext, SqliteViewInput } from "./sqlite-query-context.js";
|
|
2
3
|
import { costMonitorFilterDay } from "./sqlite-read-model-canonical.js";
|
|
3
4
|
import type { SqliteViewName } from "./sqlite-read-model-types.js";
|
|
@@ -9,6 +10,8 @@ export function readFilteredDimension(
|
|
|
9
10
|
) {
|
|
10
11
|
const temporalCostGroup =
|
|
11
12
|
filteredCostGroup === "day" || filteredCostGroup === "month" || filteredCostGroup === "year";
|
|
13
|
+
let periodAverages: ReturnType<typeof sqlitePeriodAverages> | undefined;
|
|
14
|
+
let periodTotals: ReturnType<typeof sqlitePeriodTotals> | undefined;
|
|
12
15
|
|
|
13
16
|
if (temporalCostGroup && input.workType) {
|
|
14
17
|
// No canonical work_type exists at invocation grain, including for
|
|
@@ -20,6 +23,8 @@ export function readFilteredDimension(
|
|
|
20
23
|
limit: Math.min(200, Math.max(1, input.limit ?? 50)),
|
|
21
24
|
total_count: 0,
|
|
22
25
|
has_more: false,
|
|
26
|
+
period_averages: sqlitePeriodAverages([]),
|
|
27
|
+
totals: sqlitePeriodTotals([]),
|
|
23
28
|
rows: [],
|
|
24
29
|
};
|
|
25
30
|
}
|
|
@@ -152,9 +157,11 @@ export function readFilteredDimension(
|
|
|
152
157
|
: "total_cost_brl DESC, key";
|
|
153
158
|
let rows = context.database
|
|
154
159
|
.prepare(
|
|
155
|
-
`${facts} SELECT ${groupExpression} AS key, ${groupExpression} AS label, ${groupExpression} AS period_key, MIN(date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours')) AS start_day, MAX(date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours')) AS end_day, COUNT(*) AS invocation_count, SUM(i.llm_call_count) AS llm_call_count, SUM(i.source_event_count) AS source_event_count, NULL AS total_duration, SUM(i.input_tokens) AS total_input_tokens, SUM(i.cached_input_tokens) AS total_cached_input_tokens, SUM(i.output_tokens) AS total_output_tokens, SUM(i.reasoning_tokens) AS total_reasoning_tokens, SUM(i.total_tokens) AS total_tokens, SUM(i.cost_usd) AS total_cost_usd, SUM(i.cost_brl) AS total_cost_brl FROM facts i WHERE ${where} GROUP BY ${groupExpression} ORDER BY ${order} LIMIT ? OFFSET
|
|
160
|
+
`${facts} SELECT ${groupExpression} AS key, ${groupExpression} AS label, ${groupExpression} AS period_key, MIN(date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours')) AS start_day, MAX(date(COALESCE(i.source_started_at, i.source_occurred_at, i.occurred_at), '-3 hours')) AS end_day, COUNT(*) AS invocation_count, SUM(i.llm_call_count) AS llm_call_count, SUM(i.source_event_count) AS source_event_count, NULL AS total_duration, SUM(i.input_tokens) AS total_input_tokens, SUM(i.cached_input_tokens) AS total_cached_input_tokens, SUM(i.output_tokens) AS total_output_tokens, SUM(i.reasoning_tokens) AS total_reasoning_tokens, SUM(i.total_tokens) AS total_tokens, SUM(i.cost_usd) AS total_cost_usd, SUM(i.cost_brl) AS total_cost_brl FROM facts i WHERE ${where} GROUP BY ${groupExpression} ORDER BY ${order}${temporalCostGroup ? "" : " LIMIT ? OFFSET ?"}`,
|
|
156
161
|
)
|
|
157
|
-
.all(...values, limit, offset) as Array<
|
|
162
|
+
.all(...values, ...(temporalCostGroup ? [] : [limit, offset])) as Array<
|
|
163
|
+
Record<string, unknown>
|
|
164
|
+
>;
|
|
158
165
|
if (temporalCostGroup) {
|
|
159
166
|
const canonicalFilter = {
|
|
160
167
|
from: input.from ?? null,
|
|
@@ -268,6 +275,8 @@ export function readFilteredDimension(
|
|
|
268
275
|
};
|
|
269
276
|
});
|
|
270
277
|
total_count = allRows.length;
|
|
278
|
+
periodAverages = sqlitePeriodAverages(allRows);
|
|
279
|
+
periodTotals = sqlitePeriodTotals(allRows);
|
|
271
280
|
rows = allRows.slice(offset, offset + limit);
|
|
272
281
|
for (const row of rows) {
|
|
273
282
|
const key = String(row.period_key);
|
|
@@ -287,6 +296,8 @@ export function readFilteredDimension(
|
|
|
287
296
|
limit,
|
|
288
297
|
total_count,
|
|
289
298
|
has_more: offset + rows.length < total_count,
|
|
299
|
+
...(periodAverages === undefined ? {} : { period_averages: periodAverages }),
|
|
300
|
+
...(periodTotals === undefined ? {} : { totals: periodTotals }),
|
|
290
301
|
rows,
|
|
291
302
|
};
|
|
292
303
|
}
|
|
@@ -79,7 +79,8 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
79
79
|
const sourceDay =
|
|
80
80
|
"date(COALESCE(a.source_started_at, a.source_occurred_at, a.occurred_at), '-3 hours')";
|
|
81
81
|
const clauses = [
|
|
82
|
-
|
|
82
|
+
// Availability affects coverage, not membership. Excluding unknown Runs
|
|
83
|
+
// silently inflated coverage and made Cost Monitor disagree with Operations.
|
|
83
84
|
`(? IS NULL OR ${sourceDay} >= ?)`,
|
|
84
85
|
`(? IS NULL OR ${sourceDay} <= ?)`,
|
|
85
86
|
];
|
|
@@ -131,7 +132,7 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
131
132
|
SELECT ${sourceDay} AS day,
|
|
132
133
|
CASE WHEN a.phase='conversation' THEN 'conversation'
|
|
133
134
|
WHEN a.phase='planning' THEN 'planning' ELSE 'execution' END AS phase_key,
|
|
134
|
-
a.task_id, a.model, a.agent_run_id, a.activity_source_kind,
|
|
135
|
+
a.task_id, a.model, a.agent_run_id, a.activity_source_kind, a.work_type AS work_key,
|
|
135
136
|
a.source_event_count AS event_count,
|
|
136
137
|
a.attributed_token_active_ms AS duration_ms,
|
|
137
138
|
a.input_tokens, a.cached_input_tokens, a.output_tokens, a.reasoning_tokens,
|
|
@@ -158,8 +159,8 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
158
159
|
// population is evaluated once rather than once per dashboard widget.
|
|
159
160
|
const factRows = context.database
|
|
160
161
|
.prepare(`${selected}
|
|
161
|
-
SELECT day, phase_key, ${aggregateColumns}
|
|
162
|
-
FROM selected GROUP BY day, phase_key ORDER BY day, phase_key`)
|
|
162
|
+
SELECT day, phase_key, work_key, ${aggregateColumns}
|
|
163
|
+
FROM selected GROUP BY day, phase_key, work_key ORDER BY day, phase_key, work_key`)
|
|
163
164
|
.all(...values) as Array<Record<string, unknown>>;
|
|
164
165
|
const nullableColumns = [
|
|
165
166
|
"duration_ms",
|
|
@@ -219,11 +220,13 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
219
220
|
SELECT entity_kind AS kind, id FROM canonical_work_items
|
|
220
221
|
), work_item_days AS (
|
|
221
222
|
SELECT entity_kind AS kind, id, occurred_day_sp AS day FROM canonical_work_items
|
|
223
|
+
WHERE entity_kind <> 'task' OR COALESCE(status, 'draft') <> 'draft'
|
|
222
224
|
UNION ALL
|
|
223
225
|
SELECT 'task', a.task_id, MIN(a.occurred_day_sp) FROM activities a
|
|
224
226
|
LEFT JOIN canonical_ids c ON c.kind='task' AND c.id=a.task_id
|
|
225
227
|
WHERE a.task_id IS NOT NULL AND c.id IS NULL
|
|
226
228
|
GROUP BY a.task_id
|
|
229
|
+
HAVING COALESCE(MAX(a.work_item_status), 'draft') <> 'draft'
|
|
227
230
|
UNION ALL
|
|
228
231
|
SELECT 'spec', a.spec_id, MIN(a.occurred_day_sp) FROM activities a
|
|
229
232
|
LEFT JOIN canonical_ids c ON c.kind='spec' AND c.id=a.spec_id
|
|
@@ -301,7 +304,22 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
301
304
|
const planning = stripDurationPopulation(metric(byKey.get("planning")));
|
|
302
305
|
const execution = stripDurationPopulation(metric(byKey.get("execution")));
|
|
303
306
|
const total = stripDurationPopulation(metric(byKey.get("total")));
|
|
304
|
-
const
|
|
307
|
+
const newWork = stripDurationPopulation(
|
|
308
|
+
metric(
|
|
309
|
+
rollup(
|
|
310
|
+
"new",
|
|
311
|
+
factRows.filter((row) => row.work_key === "new"),
|
|
312
|
+
),
|
|
313
|
+
),
|
|
314
|
+
);
|
|
315
|
+
const rework = stripDurationPopulation(
|
|
316
|
+
metric(
|
|
317
|
+
rollup(
|
|
318
|
+
"rework",
|
|
319
|
+
factRows.filter((row) => row.work_key === "rework"),
|
|
320
|
+
),
|
|
321
|
+
),
|
|
322
|
+
);
|
|
305
323
|
const financialByDay = new Map(dailyRows.map((row) => [String(row.key), row]));
|
|
306
324
|
const structuralByDay = new Map(structuralRows.map((row) => [String(row.day), row]));
|
|
307
325
|
const days = [...new Set([...financialByDay.keys(), ...structuralByDay.keys()])].sort();
|
|
@@ -464,8 +482,8 @@ export function queryCostMonitorSummaryAggregate(
|
|
|
464
482
|
planning,
|
|
465
483
|
execution,
|
|
466
484
|
total,
|
|
467
|
-
new_work:
|
|
468
|
-
rework
|
|
485
|
+
new_work: newWork,
|
|
486
|
+
rework,
|
|
469
487
|
},
|
|
470
488
|
task_count: number(totalRow?.task_count),
|
|
471
489
|
model_groups,
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sqlitePeriodAverages } from "./sqlite-period-averages.js";
|
|
1
2
|
import type { SqliteQueryContext, SqliteViewInput } from "./sqlite-query-context.js";
|
|
2
3
|
import { costMonitorFilterDay } from "./sqlite-read-model-canonical.js";
|
|
3
4
|
import type { SqliteViewName } from "./sqlite-read-model-types.js";
|
|
@@ -127,6 +128,7 @@ export function readTemporalDimension(
|
|
|
127
128
|
total_count: allRows.length,
|
|
128
129
|
has_more: offset + rows.length < allRows.length,
|
|
129
130
|
totals,
|
|
131
|
+
period_averages: sqlitePeriodAverages(allRows),
|
|
130
132
|
rows,
|
|
131
133
|
};
|
|
132
134
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { parseYaml } from "@zaip-ai/core";
|
|
2
2
|
|
|
3
|
+
/** Same accepted lifecycle paths as the parser, before any YAML or cache work. */
|
|
4
|
+
export function isCanonicalLifecyclePath(path: string): boolean {
|
|
5
|
+
return /^\.agents\/(?:data|records)\/(?:executions\/.*\/execution\.md|changes\/.*\/change\.md|(?:changes|executions)\/.*\/decisions\/.*\.md)$/.test(
|
|
6
|
+
path,
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
export function frontMatterRecord(content: string): Record<string, unknown> | null {
|
|
4
11
|
const source = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(content)?.[1];
|
|
5
12
|
if (source === undefined) return null;
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
consolidatedValue,
|
|
3
3
|
frontMatterRecord,
|
|
4
|
+
isCanonicalLifecyclePath,
|
|
4
5
|
recordValue,
|
|
5
6
|
stringValue,
|
|
6
7
|
stringValues,
|
|
@@ -23,6 +24,9 @@ import {
|
|
|
23
24
|
type PricingCatalog,
|
|
24
25
|
} from "@zaip-ai/costs";
|
|
25
26
|
import type { RunV2Fold, UsageRecordedV2 } from "../../../../../packages/decisions/src/index.js";
|
|
27
|
+
import { saoPauloDay } from "./sqlite-calendar.js";
|
|
28
|
+
|
|
29
|
+
export { saoPauloDay } from "./sqlite-calendar.js";
|
|
26
30
|
|
|
27
31
|
const MAX_RECONCILED_RUN_INTERVAL_MS = 2 * 3_600_000;
|
|
28
32
|
|
|
@@ -112,6 +116,7 @@ export function readCanonicalLifecycleRecords(rows: Array<{ path: string; conten
|
|
|
112
116
|
const changes: CanonicalChange[] = [];
|
|
113
117
|
const decisions: CanonicalDecision[] = [];
|
|
114
118
|
for (const row of rows) {
|
|
119
|
+
if (!isCanonicalLifecyclePath(row.path)) continue;
|
|
115
120
|
const metadata = frontMatterRecord(row.content);
|
|
116
121
|
if (metadata === null) continue;
|
|
117
122
|
const id = stringValue(metadata.id);
|
|
@@ -689,21 +694,6 @@ export function usagePricingAudit(
|
|
|
689
694
|
};
|
|
690
695
|
}
|
|
691
696
|
|
|
692
|
-
export function saoPauloDay(timestamp: string): string {
|
|
693
|
-
const values = Object.fromEntries(
|
|
694
|
-
new Intl.DateTimeFormat("en", {
|
|
695
|
-
timeZone: "America/Sao_Paulo",
|
|
696
|
-
year: "numeric",
|
|
697
|
-
month: "2-digit",
|
|
698
|
-
day: "2-digit",
|
|
699
|
-
})
|
|
700
|
-
.formatToParts(new Date(timestamp))
|
|
701
|
-
.filter((part) => part.type !== "literal")
|
|
702
|
-
.map((part) => [part.type, part.value]),
|
|
703
|
-
) as { year: string; month: string; day: string };
|
|
704
|
-
return `${values.year}-${values.month}-${values.day}`;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
697
|
export type TemporalInterval = { activityRowId: string; startMs: number; endMs: number };
|
|
708
698
|
|
|
709
699
|
/**
|
|
@@ -6,6 +6,7 @@ import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read
|
|
|
6
6
|
import { expectPersistedFirstFoldCaches } from "./sqlite-read-model-cache.test-support.js";
|
|
7
7
|
|
|
8
8
|
const roots: string[] = [];
|
|
9
|
+
const readers = new Set<SqliteReadModelFileSystem>();
|
|
9
10
|
const sqliteTestTempRoot = join(
|
|
10
11
|
resolve(import.meta.dirname, "../../../../../.."),
|
|
11
12
|
".tmp",
|
|
@@ -16,6 +17,8 @@ async function createSqliteTestRoot(): Promise<string> {
|
|
|
16
17
|
return mkdtemp(join(sqliteTestTempRoot, "fixture-"));
|
|
17
18
|
}
|
|
18
19
|
afterEach(async () => {
|
|
20
|
+
for (const reader of readers) reader.close();
|
|
21
|
+
readers.clear();
|
|
19
22
|
vi.useRealTimers();
|
|
20
23
|
vi.restoreAllMocks();
|
|
21
24
|
await Promise.all(
|
|
@@ -216,6 +219,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
216
219
|
);
|
|
217
220
|
await rebuildSqliteReadModel(root);
|
|
218
221
|
const filesystem = new SqliteReadModelFileSystem(root);
|
|
222
|
+
readers.add(filesystem);
|
|
219
223
|
expect(filesystem.firstFoldAggregate({ from: null, to: null }).execution_day_count).toBe(2);
|
|
220
224
|
expect(filesystem.firstFoldAggregate({ from: null, to: null }).duration_ms).toBe(2_400_000);
|
|
221
225
|
expect(filesystem.topTasks({ from: null, to: null })).toMatchObject([
|
|
@@ -386,7 +390,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
386
390
|
expect(operationDays["2026-08-02"]).toMatchObject({
|
|
387
391
|
runs: 2,
|
|
388
392
|
specs: 1,
|
|
389
|
-
tasks:
|
|
393
|
+
tasks: 0,
|
|
390
394
|
validations: 1,
|
|
391
395
|
evidences: 0,
|
|
392
396
|
usage: {
|
|
@@ -398,7 +402,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
398
402
|
expect(filesystem.viewPage("operations_daily", { limit: 50 }).rows).toContainEqual(
|
|
399
403
|
expect.objectContaining({
|
|
400
404
|
day: "2026-08-02",
|
|
401
|
-
task_count:
|
|
405
|
+
task_count: 0,
|
|
402
406
|
spec_count: 1,
|
|
403
407
|
validation_count: 1,
|
|
404
408
|
evidence_count: 0,
|
|
@@ -417,7 +421,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
417
421
|
period_key: key,
|
|
418
422
|
prd_count: 2,
|
|
419
423
|
spec_count: 3,
|
|
420
|
-
task_count:
|
|
424
|
+
task_count: 0, // All three Tasks in this fixture are draft, unlike their observed Runs.
|
|
421
425
|
validation_count: 1,
|
|
422
426
|
evidence_count: 1,
|
|
423
427
|
total_run_count: 3,
|
|
@@ -451,17 +455,17 @@ describe("SQLite dashboard read model", () => {
|
|
|
451
455
|
[
|
|
452
456
|
"cost_monitor_daily",
|
|
453
457
|
"2026-08-02",
|
|
454
|
-
{ prd_count: 0, spec_count: 1, task_count:
|
|
458
|
+
{ prd_count: 0, spec_count: 1, task_count: 0, validation_count: 1, evidence_count: 0 },
|
|
455
459
|
],
|
|
456
460
|
[
|
|
457
461
|
"cost_monitor_monthly",
|
|
458
462
|
"2026-08",
|
|
459
|
-
{ prd_count: 2, spec_count: 3, task_count:
|
|
463
|
+
{ prd_count: 2, spec_count: 3, task_count: 0, validation_count: 1, evidence_count: 1 },
|
|
460
464
|
],
|
|
461
465
|
[
|
|
462
466
|
"cost_monitor_annual",
|
|
463
467
|
"2026",
|
|
464
|
-
{ prd_count: 2, spec_count: 3, task_count:
|
|
468
|
+
{ prd_count: 2, spec_count: 3, task_count: 0, validation_count: 1, evidence_count: 1 },
|
|
465
469
|
],
|
|
466
470
|
] as const) {
|
|
467
471
|
expect(filesystem.viewPage(view, { limit: 50 }).rows).toContainEqual(
|
|
@@ -469,13 +473,13 @@ describe("SQLite dashboard read model", () => {
|
|
|
469
473
|
);
|
|
470
474
|
}
|
|
471
475
|
expect(filesystem.viewPage("cost_monitor_daily", { limit: 50 }).rows).toContainEqual(
|
|
472
|
-
expect.objectContaining({ key: "2026-08-03", prd_count: 1, spec_count: 1, task_count:
|
|
476
|
+
expect.objectContaining({ key: "2026-08-03", prd_count: 1, spec_count: 1, task_count: 0 }),
|
|
473
477
|
);
|
|
474
478
|
expect(filesystem.viewPage("cost_monitor_monthly", { limit: 50 }).rows).toContainEqual(
|
|
475
|
-
expect.objectContaining({ key: "2026-08", prd_count: 2, spec_count: 3, task_count:
|
|
479
|
+
expect.objectContaining({ key: "2026-08", prd_count: 2, spec_count: 3, task_count: 0 }),
|
|
476
480
|
);
|
|
477
481
|
expect(filesystem.viewPage("cost_monitor_annual", { limit: 50 }).rows).toContainEqual(
|
|
478
|
-
expect.objectContaining({ key: "2026", prd_count: 2, spec_count: 3, task_count:
|
|
482
|
+
expect.objectContaining({ key: "2026", prd_count: 2, spec_count: 3, task_count: 0 }),
|
|
479
483
|
);
|
|
480
484
|
const annualCostPage = filesystem.viewPage("cost_monitor_annual", { limit: 50 });
|
|
481
485
|
const dailyCostRows = filesystem.viewPage("cost_monitor_daily", { limit: 50 }).rows;
|
|
@@ -515,6 +519,21 @@ describe("SQLite dashboard read model", () => {
|
|
|
515
519
|
observed.length === 0 ? null : observed.reduce((sum, value) => sum + value, 0),
|
|
516
520
|
);
|
|
517
521
|
}
|
|
522
|
+
const filteredFirst = filesystem.viewPage("cost_monitor_daily", {
|
|
523
|
+
limit: 1,
|
|
524
|
+
provider: "openai",
|
|
525
|
+
});
|
|
526
|
+
const filteredNext = filesystem.viewPage("cost_monitor_daily", {
|
|
527
|
+
limit: 1,
|
|
528
|
+
offset: 1,
|
|
529
|
+
provider: "openai",
|
|
530
|
+
});
|
|
531
|
+
expect(filteredFirst.totals).toEqual(filteredNext.totals);
|
|
532
|
+
expect(filteredFirst.period_averages).toEqual(filteredNext.period_averages);
|
|
533
|
+
expect(filteredFirst).toMatchObject({
|
|
534
|
+
totals: { task_count: 0, total_cost_brl: 15 },
|
|
535
|
+
period_averages: { BRL: { tasks: 0, tokens: 3, cost: 7.5 } },
|
|
536
|
+
});
|
|
518
537
|
expect(
|
|
519
538
|
filesystem.viewPage("cost_monitor_daily", { limit: 50, provider: "openai" }).rows,
|
|
520
539
|
).toContainEqual(
|
|
@@ -522,7 +541,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
522
541
|
key: "2026-08-02",
|
|
523
542
|
prd_count: 0,
|
|
524
543
|
spec_count: 1,
|
|
525
|
-
task_count:
|
|
544
|
+
task_count: 0,
|
|
526
545
|
validation_count: 1,
|
|
527
546
|
evidence_count: 0,
|
|
528
547
|
}),
|
|
@@ -635,6 +654,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
635
654
|
});
|
|
636
655
|
expect(filesystem.firstFoldAllTime()).toBe(allTime);
|
|
637
656
|
filesystem.close();
|
|
657
|
+
readers.delete(filesystem);
|
|
638
658
|
|
|
639
659
|
// Period membership follows the canonical macro day, not an invocation
|
|
640
660
|
// that happened on another day. Search accepts either the macro ID or
|
|
@@ -674,6 +694,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
674
694
|
);
|
|
675
695
|
await rebuildSqliteReadModel(root);
|
|
676
696
|
const canonicalDayFilesystem = new SqliteReadModelFileSystem(root);
|
|
697
|
+
readers.add(canonicalDayFilesystem);
|
|
677
698
|
expect(
|
|
678
699
|
canonicalDayFilesystem.viewPage("cost_monitor_specs", {
|
|
679
700
|
from: "2026-08-03",
|
|
@@ -702,6 +723,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
702
723
|
}),
|
|
703
724
|
).toMatchObject({ total_count: 0, rows: [] });
|
|
704
725
|
canonicalDayFilesystem.close();
|
|
726
|
+
readers.delete(canonicalDayFilesystem);
|
|
705
727
|
|
|
706
728
|
// A large result set keeps its subtotal for all 270 matching Tasks while
|
|
707
729
|
// the page transports only 50 records.
|
|
@@ -717,6 +739,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
717
739
|
}
|
|
718
740
|
await rebuildSqliteReadModel(root);
|
|
719
741
|
const pageFilesystem = new SqliteReadModelFileSystem(root);
|
|
742
|
+
readers.add(pageFilesystem);
|
|
720
743
|
const paged = pageFilesystem.viewPage("cost_monitor_tasks", {
|
|
721
744
|
from: "2026-08-04",
|
|
722
745
|
to: "2026-08-04",
|
|
@@ -735,5 +758,6 @@ describe("SQLite dashboard read model", () => {
|
|
|
735
758
|
total_cost_brl: 1_350,
|
|
736
759
|
});
|
|
737
760
|
pageFilesystem.close();
|
|
761
|
+
readers.delete(pageFilesystem);
|
|
738
762
|
});
|
|
739
763
|
});
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts
CHANGED
|
@@ -344,14 +344,28 @@ export class SqliteReadModelFileSystem extends WorkspaceFileSystem {
|
|
|
344
344
|
return queryTopTasks(this.queryContext(), filter, limit);
|
|
345
345
|
}
|
|
346
346
|
|
|
347
|
-
canonicalTraceFiles(
|
|
347
|
+
canonicalTraceFiles(
|
|
348
|
+
markers: readonly string[],
|
|
349
|
+
maxContentLength?: number,
|
|
350
|
+
): Array<{ path: string; content: string }> {
|
|
348
351
|
const selected = [...new Set(markers.filter(Boolean))];
|
|
349
352
|
if (selected.length === 0) return [];
|
|
353
|
+
if (
|
|
354
|
+
maxContentLength !== undefined &&
|
|
355
|
+
(!Number.isSafeInteger(maxContentLength) || maxContentLength < 0)
|
|
356
|
+
)
|
|
357
|
+
throw new Error("Invalid trace content bound");
|
|
350
358
|
const clauses = selected.map(() => "content LIKE ?").join(" OR ");
|
|
359
|
+
// SQL counts code points while the caller retains its UTF-16 length check.
|
|
360
|
+
// This conservative prefilter never excludes an otherwise admissible file.
|
|
361
|
+
const bound = maxContentLength === undefined ? "" : " AND length(content) <= ?";
|
|
351
362
|
return this.database
|
|
352
363
|
.prepare(`SELECT path, content FROM files
|
|
353
|
-
WHERE (path LIKE '.agents/data/%' OR path LIKE '.agents/records/%') AND (${clauses}) ORDER BY path`)
|
|
354
|
-
.all(
|
|
364
|
+
WHERE (path LIKE '.agents/data/%' OR path LIKE '.agents/records/%')${bound} AND (${clauses}) ORDER BY path`)
|
|
365
|
+
.all(
|
|
366
|
+
...(maxContentLength === undefined ? [] : [maxContentLength]),
|
|
367
|
+
...selected.map((marker) => `%${marker}%`),
|
|
368
|
+
) as Array<{
|
|
355
369
|
path: string;
|
|
356
370
|
content: string;
|
|
357
371
|
}>;
|
|
@@ -210,7 +210,7 @@ describe("SQLite dashboard read model", () => {
|
|
|
210
210
|
snapshot
|
|
211
211
|
.prepare("SELECT value FROM zaip_vw_read_model_metadata WHERE key='schema_version'")
|
|
212
212
|
.get(),
|
|
213
|
-
).toEqual({ value: "
|
|
213
|
+
).toEqual({ value: "79" });
|
|
214
214
|
} finally {
|
|
215
215
|
snapshot.close();
|
|
216
216
|
}
|