@zaip-ai/cli 2.6.0 → 3.0.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 +71 -10
- package/templates/.agents/README.md +72 -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 +246 -134
- 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-TnrL1ZyZ.js} +915 -550
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-DEbCi1gP.js → PricingSettingsDialog-DjQpBqGU.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-BQZXUnQu.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-Basaw1NR.js +824 -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-BQe3zTvL.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 +238 -226
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +205 -195
- 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 +238 -226
- 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-cost-dimension-facts.test.ts +12 -1
- 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 +1 -1
- 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-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-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 +9 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +4 -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 +7 -2
- 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-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 +23 -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 +61 -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 +425 -269
- 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
|
@@ -1,11 +1,44 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
|
+
import { type SqliteReadModelFileSystem, sqliteReadModelPath } from "./sqlite-read-model.js";
|
|
4
5
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
readModelSchemaVersion,
|
|
7
|
+
requiredIndexes,
|
|
8
|
+
requiredPersistedTables,
|
|
9
|
+
requiredViews,
|
|
10
|
+
} from "./sqlite-read-model-schema.js";
|
|
11
|
+
|
|
12
|
+
/** The worker validates integrity and schema before emitting this receipt. */
|
|
13
|
+
export function validateSnapshotWorkerReceipt(stdout: string, destination: string): void {
|
|
14
|
+
const result = JSON.parse(stdout) as {
|
|
15
|
+
storage_mode?: unknown;
|
|
16
|
+
path?: unknown;
|
|
17
|
+
schema?: {
|
|
18
|
+
schemaVersion?: unknown;
|
|
19
|
+
tableCount?: unknown;
|
|
20
|
+
viewCount?: unknown;
|
|
21
|
+
indexCount?: unknown;
|
|
22
|
+
};
|
|
23
|
+
} | null;
|
|
24
|
+
const schema = result?.schema;
|
|
25
|
+
if (
|
|
26
|
+
result?.storage_mode !== "sqlite_read_model" ||
|
|
27
|
+
typeof result.path !== "string" ||
|
|
28
|
+
resolve(result.path) !== resolve(destination) ||
|
|
29
|
+
schema?.schemaVersion !== readModelSchemaVersion ||
|
|
30
|
+
schema.tableCount !== requiredPersistedTables.length ||
|
|
31
|
+
typeof schema.viewCount !== "number" ||
|
|
32
|
+
!Number.isSafeInteger(schema.viewCount) ||
|
|
33
|
+
schema.viewCount < requiredViews.length ||
|
|
34
|
+
typeof schema.indexCount !== "number" ||
|
|
35
|
+
!Number.isSafeInteger(schema.indexCount) ||
|
|
36
|
+
schema.indexCount < requiredIndexes.length
|
|
37
|
+
)
|
|
38
|
+
throw new Error(
|
|
39
|
+
"SQLite refresh worker did not return a valid schema receipt for this destination",
|
|
40
|
+
);
|
|
41
|
+
}
|
|
9
42
|
|
|
10
43
|
async function rebuildPersistentDatabaseInWorker(workspaceRoot: string, destination: string) {
|
|
11
44
|
const scriptCandidates = [
|
|
@@ -24,6 +57,8 @@ async function rebuildPersistentDatabaseInWorker(workspaceRoot: string, destinat
|
|
|
24
57
|
throw new Error("SQLite refresh worker script is unavailable from this runtime checkout");
|
|
25
58
|
await new Promise<void>((resolveWorker, rejectWorker) => {
|
|
26
59
|
let stderr = "";
|
|
60
|
+
let stdout = "";
|
|
61
|
+
let oversizedReceipt = false;
|
|
27
62
|
const worker = spawn(process.execPath, [script], {
|
|
28
63
|
cwd: workspaceRoot,
|
|
29
64
|
env: {
|
|
@@ -33,13 +68,18 @@ async function rebuildPersistentDatabaseInWorker(workspaceRoot: string, destinat
|
|
|
33
68
|
ZAIP_SQLITE_PREFER_LAST_VALID_SEED: "0",
|
|
34
69
|
ZAIP_DASHBOARD_LAUNCH_PROGRESS: "0",
|
|
35
70
|
},
|
|
36
|
-
stdio: ["ignore", "
|
|
71
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
37
72
|
windowsHide: true,
|
|
38
73
|
});
|
|
39
74
|
// Lease shutdown may end the serving parent while a slow snapshot rebuild
|
|
40
75
|
// is still writing. Terminate the direct child synchronously during parent
|
|
41
76
|
// exit so the next launcher cannot overlap the persistent SQLite writer.
|
|
42
77
|
const cleanupWorker = attachRefreshWorkerCleanup(worker);
|
|
78
|
+
worker.stdout?.setEncoding("utf8");
|
|
79
|
+
worker.stdout?.on("data", (chunk: string) => {
|
|
80
|
+
if (stdout.length + chunk.length > 64_000) oversizedReceipt = true;
|
|
81
|
+
if (!oversizedReceipt) stdout += chunk;
|
|
82
|
+
});
|
|
43
83
|
worker.stderr?.setEncoding("utf8");
|
|
44
84
|
worker.stderr?.on("data", (chunk: string) => {
|
|
45
85
|
stderr = `${stderr}${chunk}`.slice(-8_000);
|
|
@@ -48,13 +88,22 @@ async function rebuildPersistentDatabaseInWorker(workspaceRoot: string, destinat
|
|
|
48
88
|
cleanupWorker();
|
|
49
89
|
rejectWorker(error);
|
|
50
90
|
});
|
|
51
|
-
|
|
91
|
+
// close follows stdout drain; exit alone may precede the receipt bytes.
|
|
92
|
+
worker.once("close", (code) => {
|
|
52
93
|
cleanupWorker();
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
94
|
+
if (code !== 0) {
|
|
95
|
+
rejectWorker(
|
|
96
|
+
new Error(`SQLite refresh worker failed (${code}): ${stderr.trim() || "no stderr"}`),
|
|
97
|
+
);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
if (oversizedReceipt) throw new Error("SQLite refresh worker receipt exceeds size limit");
|
|
102
|
+
validateSnapshotWorkerReceipt(stdout, destination);
|
|
103
|
+
resolveWorker();
|
|
104
|
+
} catch (error) {
|
|
105
|
+
rejectWorker(error);
|
|
106
|
+
}
|
|
58
107
|
});
|
|
59
108
|
});
|
|
60
109
|
}
|
|
@@ -88,6 +137,7 @@ export async function refreshSqliteSnapshotInWorker(
|
|
|
88
137
|
) {
|
|
89
138
|
const destination = sqliteReadModelPath(workspaceRoot);
|
|
90
139
|
await rebuildPersistentDatabaseInWorker(workspaceRoot, destination);
|
|
91
|
-
|
|
140
|
+
// Integrity/schema checking belongs to the worker, not the HTTP event loop.
|
|
141
|
+
// Zero exit alone is insufficient: its exact-destination receipt is mandatory.
|
|
92
142
|
filesystem.refresh();
|
|
93
143
|
}
|
|
@@ -19,6 +19,32 @@ afterEach(() => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
describe("snapshot source synchronization", () => {
|
|
22
|
+
it("reports capture failure separately while refreshing canonical data", async () => {
|
|
23
|
+
vi.useFakeTimers();
|
|
24
|
+
const error = new Error("capture timed out");
|
|
25
|
+
const onCaptureFailure = vi.fn();
|
|
26
|
+
const onRefreshFailure = vi.fn();
|
|
27
|
+
const onCaptureSuccess = vi.fn();
|
|
28
|
+
const capture = vi.fn().mockRejectedValueOnce(error).mockResolvedValue(undefined);
|
|
29
|
+
const refresh = vi.fn(async () => undefined);
|
|
30
|
+
startSnapshotSynchronization({
|
|
31
|
+
workspaceRoot: "C:/workspace",
|
|
32
|
+
staleSeed: false,
|
|
33
|
+
watchSources: true,
|
|
34
|
+
refresh,
|
|
35
|
+
captureActiveTelemetry: capture,
|
|
36
|
+
onCaptureFailure,
|
|
37
|
+
onCaptureSuccess,
|
|
38
|
+
onRefreshFailure,
|
|
39
|
+
});
|
|
40
|
+
await vi.advanceTimersByTimeAsync(301);
|
|
41
|
+
expect(onCaptureFailure).toHaveBeenCalledWith(error);
|
|
42
|
+
expect(onRefreshFailure).not.toHaveBeenCalled();
|
|
43
|
+
expect(refresh).toHaveBeenCalledTimes(1);
|
|
44
|
+
await vi.advanceTimersByTimeAsync(60_000);
|
|
45
|
+
expect(onCaptureSuccess).toHaveBeenCalledTimes(1);
|
|
46
|
+
expect(refresh).toHaveBeenCalledTimes(2);
|
|
47
|
+
});
|
|
22
48
|
it("watches current data for both creation and alteration refreshes", async () => {
|
|
23
49
|
vi.useFakeTimers();
|
|
24
50
|
const refresh = vi.fn(async () => undefined);
|
package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts
CHANGED
|
@@ -8,6 +8,8 @@ export function startSnapshotSynchronization(input: {
|
|
|
8
8
|
refresh: () => Promise<void>;
|
|
9
9
|
/** Exact active-Codex collection, separate from projection and lifecycle repair. */
|
|
10
10
|
captureActiveTelemetry?: () => Promise<void>;
|
|
11
|
+
onCaptureFailure?: (error: unknown) => void;
|
|
12
|
+
onCaptureSuccess?: () => void;
|
|
11
13
|
/** Report failed asynchronous refreshes; a stale snapshot must never look healthy. */
|
|
12
14
|
onRefreshFailure?: (input: { trigger: "stale_seed" | "source_change"; error: unknown }) => void;
|
|
13
15
|
}): void {
|
|
@@ -40,7 +42,8 @@ export function startSnapshotSynchronization(input: {
|
|
|
40
42
|
if (input.captureActiveTelemetry === undefined) return scheduleRefresh();
|
|
41
43
|
void input
|
|
42
44
|
.captureActiveTelemetry()
|
|
43
|
-
.
|
|
45
|
+
.then(() => input.onCaptureSuccess?.())
|
|
46
|
+
.catch((error: unknown) => input.onCaptureFailure?.(error))
|
|
44
47
|
.finally(scheduleRefresh);
|
|
45
48
|
};
|
|
46
49
|
// Run at most once a minute. File watchers only project canonical changes;
|
package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.test.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { createV2WorkspaceLayout } from "@zaip-ai/core";
|
|
5
|
+
import { afterEach, expect, it, vi } from "vitest";
|
|
6
|
+
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
7
|
+
import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
8
|
+
import { prepareMultiProviderFixture } from "./sqlite-read-model-multi-provider-fixture.js";
|
|
9
|
+
|
|
10
|
+
const roots: string[] = [];
|
|
11
|
+
const readers: SqliteReadModelFileSystem[] = [];
|
|
12
|
+
afterEach(async () => {
|
|
13
|
+
vi.restoreAllMocks();
|
|
14
|
+
for (const reader of readers.splice(0)) reader.close();
|
|
15
|
+
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
16
|
+
});
|
|
17
|
+
const taskId = "TASK-2026-09-10-12-00-TRACE-AAAA";
|
|
18
|
+
const layout = createV2WorkspaceLayout(
|
|
19
|
+
{
|
|
20
|
+
schema_version: 1,
|
|
21
|
+
project: { id: "trace", name: "Trace", timezone: "America/Sao_Paulo" },
|
|
22
|
+
stack: { id: "zaip-aios-stack", overrides: {} },
|
|
23
|
+
clients: { codex: true, claude: false },
|
|
24
|
+
tracking: { enabled: true, currency: "BRL", storage_mode: "tracked_sanitized" },
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
lock_version: 2,
|
|
28
|
+
framework: { version: "3.0.0", distribution_sha256: null },
|
|
29
|
+
layout: { version: 3 },
|
|
30
|
+
resolved_profile: { id: null, sha256: null },
|
|
31
|
+
managed_files: {},
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
const taskContent = (id: string, title: string) =>
|
|
35
|
+
`---\nid: ${id}\ntitle: ${title}\nstatus: completed\nrisk: standard\ncreated_at: 2026-09-10T15:00:00.000Z\n---\n# ${title}\n`;
|
|
36
|
+
async function fixture(files: Record<string, string>) {
|
|
37
|
+
const root = await mkdtemp(join(tmpdir(), "zaip-trace-bounded-"));
|
|
38
|
+
roots.push(root);
|
|
39
|
+
await prepareMultiProviderFixture(root);
|
|
40
|
+
for (const [path, content] of Object.entries(files)) {
|
|
41
|
+
const target = join(root, path);
|
|
42
|
+
await mkdir(dirname(target), { recursive: true });
|
|
43
|
+
await writeFile(target, content);
|
|
44
|
+
}
|
|
45
|
+
await rebuildSqliteReadModel(root);
|
|
46
|
+
const filesystem = new SqliteReadModelFileSystem(root);
|
|
47
|
+
readers.push(filesystem);
|
|
48
|
+
return filesystem;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
it("resolves the exact Task and filters oversized history before transport without losing documents", async () => {
|
|
52
|
+
const path = layout.activePath("task", taskId);
|
|
53
|
+
const small = ".agents/records/changes/trace/artifacts/tests/notes.md";
|
|
54
|
+
const large = ".agents/records/changes/trace/artifacts/tests/oversized.md";
|
|
55
|
+
const astral = ".agents/records/changes/trace/artifacts/tests/astral.md";
|
|
56
|
+
const shadowId = "TASK-2026-09-10-11-00-SHADOW-AAAA";
|
|
57
|
+
const filesystem = await fixture({
|
|
58
|
+
[path]: taskContent(taskId, "Requested Task"),
|
|
59
|
+
[layout.activePath("task", shadowId)]: taskContent(shadowId, `References ${taskId}`),
|
|
60
|
+
[small]: `# ${taskId}\n${"x".repeat(250_000 - taskId.length - 3)}`,
|
|
61
|
+
[large]: `${taskId}\n${"x".repeat(250_001)}`,
|
|
62
|
+
[astral]: `${taskId}\n${"😀".repeat(130_000)}`,
|
|
63
|
+
});
|
|
64
|
+
const expected = filesystem
|
|
65
|
+
.canonicalTraceFiles([taskId])
|
|
66
|
+
.filter((row) => row.content.length <= 250_000)
|
|
67
|
+
.map((row) => row.path);
|
|
68
|
+
expect(expected).toContain(small);
|
|
69
|
+
expect(expected).not.toContain(large);
|
|
70
|
+
expect(expected).not.toContain(astral);
|
|
71
|
+
const scan = vi.spyOn(filesystem, "canonicalTraceFiles");
|
|
72
|
+
const trace = await buildSqliteTaskTrace(filesystem, layout, taskId);
|
|
73
|
+
expect(trace.task_title).toBe("Requested Task");
|
|
74
|
+
expect(trace.task_id).toBe(taskId);
|
|
75
|
+
expect(trace.documents.map((row) => row.path)).toEqual(expected);
|
|
76
|
+
expect(scan).toHaveBeenCalledOnce();
|
|
77
|
+
expect(scan.mock.calls[0]?.[1]).toBe(250_000);
|
|
78
|
+
expect(scan.mock.results[0]?.value.map((row: { path: string }) => row.path)).not.toContain(large);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("rejects a mismatched Task identity instead of tracing a document that mentions it", async () => {
|
|
82
|
+
const filesystem = await fixture({
|
|
83
|
+
[layout.activePath("task", taskId)]: taskContent("TASK-2026-09-10-11-00-WRONG-AAAA", taskId),
|
|
84
|
+
});
|
|
85
|
+
await expect(buildSqliteTaskTrace(filesystem, layout, taskId)).rejects.toThrow(
|
|
86
|
+
/identity mismatch/,
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("retains the canonical divergent-layout guard and rejects invalid bounds", async () => {
|
|
91
|
+
const filesystem = await fixture({
|
|
92
|
+
[layout.activePath("task", taskId)]: taskContent(taskId, "Active"),
|
|
93
|
+
[`.agents/data/tasks/2026/09/10/${taskId}.md`]: taskContent(taskId, "Divergent"),
|
|
94
|
+
});
|
|
95
|
+
await expect(buildSqliteTaskTrace(filesystem, layout, taskId)).rejects.toThrow(/Divergent/);
|
|
96
|
+
expect(() => filesystem.canonicalTraceFiles([taskId], -1)).toThrow(/Invalid trace content bound/);
|
|
97
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import type
|
|
2
|
+
import { resolveArtifactReadPath, type WorkspaceLayout } from "@zaip-ai/core";
|
|
3
3
|
import type { TaskTrace, TraceDocument } from "@zaip-ai/dashboard-traceability/contracts";
|
|
4
4
|
import {
|
|
5
5
|
buildTraceStageRecords,
|
|
@@ -8,26 +8,23 @@ import {
|
|
|
8
8
|
} from "@zaip-ai/dashboard-traceability/server";
|
|
9
9
|
import type { SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
10
10
|
|
|
11
|
-
export function buildSqliteTaskTrace(
|
|
11
|
+
export async function buildSqliteTaskTrace(
|
|
12
12
|
filesystem: SqliteReadModelFileSystem,
|
|
13
13
|
layout: WorkspaceLayout,
|
|
14
14
|
taskId: string,
|
|
15
|
-
): TaskTrace {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
row.path.includes("/.agents/records/tasks/") ||
|
|
22
|
-
row.path.includes(".agents/records/tasks/"),
|
|
23
|
-
);
|
|
24
|
-
if (taskFile === undefined) throw new Error(`Canonical Task ${taskId} was not found`);
|
|
15
|
+
): Promise<TaskTrace> {
|
|
16
|
+
// Resolve the exact canonical identity, not the first Task mentioning it.
|
|
17
|
+
// This also avoids scanning all historical contents just to locate one Task.
|
|
18
|
+
const taskPath = await resolveArtifactReadPath(filesystem, layout, "task", taskId);
|
|
19
|
+
if (taskPath === null) throw new Error(`Canonical Task ${taskId} was not found`);
|
|
20
|
+
const taskFile = { path: taskPath, content: await filesystem.readText(taskPath) };
|
|
25
21
|
const scalar = (key: string): string | null => {
|
|
26
22
|
const frontMatter = /^---\r?\n([\s\S]*?)\r?\n---/.exec(taskFile.content)?.[1] ?? "";
|
|
27
23
|
const value = new RegExp(`^${key}:\\s*(.+?)\\s*$`, "m").exec(frontMatter)?.[1]?.trim();
|
|
28
24
|
if (value === undefined || value === "null") return null;
|
|
29
25
|
return value.replace(/^['"]|['"]$/g, "");
|
|
30
26
|
};
|
|
27
|
+
if (scalar("id") !== taskId) throw new Error(`Canonical Task identity mismatch: ${taskId}`);
|
|
31
28
|
const relatedId = (key: string, prefix: string): string | null =>
|
|
32
29
|
scalar(key) ?? new RegExp(`\\b${prefix}[A-Z0-9-]+`).exec(taskFile.content)?.[0] ?? null;
|
|
33
30
|
const changeId = relatedId("change_id", "CHG-") ?? taskId;
|
|
@@ -37,7 +34,7 @@ export function buildSqliteTaskTrace(
|
|
|
37
34
|
(value): value is string => value !== null,
|
|
38
35
|
);
|
|
39
36
|
const documents = filesystem
|
|
40
|
-
.canonicalTraceFiles(markers)
|
|
37
|
+
.canonicalTraceFiles(markers, 250_000)
|
|
41
38
|
.filter(
|
|
42
39
|
(row) => /\.(?:md|json|jsonl|txt|log)$/i.test(row.path) && row.content.length <= 250_000,
|
|
43
40
|
)
|
|
@@ -10,15 +10,7 @@ import type { DashboardRouteContext } from "./server-route-context.js";
|
|
|
10
10
|
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
11
11
|
import { SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
12
12
|
export function registerTraceRoutes(app: Hono, dependencies: DashboardRouteContext) {
|
|
13
|
-
const {
|
|
14
|
-
filesystem,
|
|
15
|
-
canonicalFilesystem,
|
|
16
|
-
isSqliteSnapshot,
|
|
17
|
-
readLayout,
|
|
18
|
-
readSnapshot,
|
|
19
|
-
readAggregate,
|
|
20
|
-
clearSnapshotCache,
|
|
21
|
-
} = dependencies;
|
|
13
|
+
const { filesystem, readLayout } = dependencies;
|
|
22
14
|
app.on(["GET", "HEAD"], `${API_PREFIX}/tasks/:id`, async (context) => {
|
|
23
15
|
try {
|
|
24
16
|
const layout = await readLayout();
|
|
@@ -53,7 +45,7 @@ export function registerTraceRoutes(app: Hono, dependencies: DashboardRouteConte
|
|
|
53
45
|
return headOrJson(
|
|
54
46
|
context,
|
|
55
47
|
filesystem instanceof SqliteReadModelFileSystem
|
|
56
|
-
? buildSqliteTaskTrace(filesystem, layout, taskId)
|
|
48
|
+
? await buildSqliteTaskTrace(filesystem, layout, taskId)
|
|
57
49
|
: await buildTaskTrace(filesystem, layout, taskId),
|
|
58
50
|
);
|
|
59
51
|
} catch (error) {
|
package/templates/.agents/dashboard/packages/local-runtime/src/server-traceability-index.test.ts
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { serializeMarkdown, WorkspaceFileSystem } from "@zaip-ai/core";
|
|
2
|
+
import { expect, it } from "vitest";
|
|
3
|
+
import { createDashboardApp } from "./server.js";
|
|
4
|
+
import { withSqliteReadModelFixture } from "./server.test-fixtures.js";
|
|
5
|
+
import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
6
|
+
|
|
7
|
+
it("indexes draft and terminal Tasks in SQLite without adding drafts to Kanban", async () => {
|
|
8
|
+
await withSqliteReadModelFixture("trace-index", async ({ root }) => {
|
|
9
|
+
const at = "2026-09-11T10:00:00.000Z";
|
|
10
|
+
const canonical = new WorkspaceFileSystem(root);
|
|
11
|
+
for (const [i, status] of ["draft", "cancelled", "blocked"].entries()) {
|
|
12
|
+
await canonical.writeTextAtomic(
|
|
13
|
+
`.agents/records/tasks/2026/09/task-${i}.md`,
|
|
14
|
+
serializeMarkdown({
|
|
15
|
+
metadata: {
|
|
16
|
+
schema_version: 2,
|
|
17
|
+
id: `TASK-INDEX-${i}`,
|
|
18
|
+
title: `Task ${status}`,
|
|
19
|
+
status,
|
|
20
|
+
revision: 1,
|
|
21
|
+
change_id: `CHG-INDEX-${i}`,
|
|
22
|
+
short_name: `index-${i}`,
|
|
23
|
+
objective: "Identity fixture",
|
|
24
|
+
risk: "standard",
|
|
25
|
+
priority: "medium",
|
|
26
|
+
owner: null,
|
|
27
|
+
requirement_ids: ["REQ-WORK-001"],
|
|
28
|
+
acceptance_ids: ["AC-WORK-001-09"],
|
|
29
|
+
depends_on: [],
|
|
30
|
+
write_scopes: ["proof"],
|
|
31
|
+
plan_revision: null,
|
|
32
|
+
plan_hash: null,
|
|
33
|
+
created_at: at,
|
|
34
|
+
updated_at: at,
|
|
35
|
+
started_at: null,
|
|
36
|
+
finished_at: null,
|
|
37
|
+
result: null,
|
|
38
|
+
},
|
|
39
|
+
body: "# Identity fixture\n",
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
await rebuildSqliteReadModel(root);
|
|
44
|
+
const sqlite = new SqliteReadModelFileSystem(root);
|
|
45
|
+
try {
|
|
46
|
+
const app = createDashboardApp(root, "fixture", undefined, { filesystem: sqlite });
|
|
47
|
+
const request = async (query: string) => {
|
|
48
|
+
const response = await app.request(`/api/v2/operations?${query}`, {
|
|
49
|
+
headers: { "x-zaip-session": "fixture" },
|
|
50
|
+
});
|
|
51
|
+
expect(response.status).toBe(200);
|
|
52
|
+
return response.json() as Promise<{
|
|
53
|
+
total: number;
|
|
54
|
+
tasks: { id: string; status: string }[];
|
|
55
|
+
}>;
|
|
56
|
+
};
|
|
57
|
+
const first = await request("scope=traceability&offset=0&limit=2");
|
|
58
|
+
const second = await request("scope=traceability&offset=2&limit=2");
|
|
59
|
+
expect(first.total).toBe(3);
|
|
60
|
+
expect(first.tasks).toHaveLength(2);
|
|
61
|
+
expect(second.tasks).toHaveLength(1);
|
|
62
|
+
expect([...first.tasks, ...second.tasks].map((task) => task.id)).toEqual([
|
|
63
|
+
"TASK-INDEX-2",
|
|
64
|
+
"TASK-INDEX-1",
|
|
65
|
+
"TASK-INDEX-0",
|
|
66
|
+
]);
|
|
67
|
+
expect(second.tasks[0]?.status).toBe("draft");
|
|
68
|
+
for (const stage of [
|
|
69
|
+
"definition",
|
|
70
|
+
"planning",
|
|
71
|
+
"ready",
|
|
72
|
+
"executing",
|
|
73
|
+
"completed",
|
|
74
|
+
"blocked",
|
|
75
|
+
]) {
|
|
76
|
+
const board = await request(`scope=board&stage=${stage}&kind=all-tasks`);
|
|
77
|
+
expect(board.tasks.map((task: { id: string }) => task.id)).not.toContain("TASK-INDEX-0");
|
|
78
|
+
}
|
|
79
|
+
expect((await request("scope=traceability&offset=3&limit=2")).tasks).toEqual([]);
|
|
80
|
+
} finally {
|
|
81
|
+
sqlite.close();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -212,6 +212,7 @@ export function createDashboardApp(
|
|
|
212
212
|
};
|
|
213
213
|
let observedSnapshotRevision: string | null = null;
|
|
214
214
|
const projectionRefreshDiagnostics = createProjectionRefreshDiagnostics();
|
|
215
|
+
let activeCaptureFailure: { code: string; occurred_at: string; cause: string } | null = null;
|
|
215
216
|
let projectionRefreshInFlight: Promise<void> | null = null;
|
|
216
217
|
let projectionRefreshRequested = false;
|
|
217
218
|
const rebuildProjection = async () => {
|
|
@@ -262,6 +263,16 @@ export function createDashboardApp(
|
|
|
262
263
|
? { captureActiveTelemetry: () => captureActiveCodexTelemetry(workspaceRoot) }
|
|
263
264
|
: {}),
|
|
264
265
|
onRefreshFailure: projectionRefreshDiagnostics.record,
|
|
266
|
+
onCaptureSuccess: () => {
|
|
267
|
+
activeCaptureFailure = null;
|
|
268
|
+
},
|
|
269
|
+
onCaptureFailure: (error) => {
|
|
270
|
+
activeCaptureFailure = {
|
|
271
|
+
code: "active_telemetry_capture_failed",
|
|
272
|
+
occurred_at: new Date().toISOString(),
|
|
273
|
+
cause: error instanceof Error ? error.name : "unknown_error",
|
|
274
|
+
};
|
|
275
|
+
},
|
|
265
276
|
});
|
|
266
277
|
const reconcileWork = createWorkReconciliation({
|
|
267
278
|
reconcile: (mode) =>
|
|
@@ -397,13 +408,15 @@ export function createDashboardApp(
|
|
|
397
408
|
kind: RUNTIME_KIND,
|
|
398
409
|
workspaceKey,
|
|
399
410
|
service: "zaip-aios-dashboard",
|
|
400
|
-
status:
|
|
411
|
+
status:
|
|
412
|
+
activeCaptureFailure === null ? projectionRefreshDiagnostics.healthStatus : "degraded",
|
|
401
413
|
api_version: 2,
|
|
402
414
|
workspace_layout: layout.version,
|
|
403
415
|
read_only: true,
|
|
404
416
|
storage: isSqliteSnapshot ? filesystem.metadata() : { storage_mode: "filesystem" },
|
|
405
417
|
snapshot_state: snapshotState,
|
|
406
418
|
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
419
|
+
active_capture_failure: activeCaptureFailure,
|
|
407
420
|
});
|
|
408
421
|
} catch (error) {
|
|
409
422
|
return headOrJson(
|
|
@@ -450,6 +463,7 @@ export function createDashboardApp(
|
|
|
450
463
|
day_count: metadata.daily_aggregate_count,
|
|
451
464
|
snapshot_state: snapshotState,
|
|
452
465
|
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
466
|
+
active_capture_failure: activeCaptureFailure,
|
|
453
467
|
snapshot_revision: revision,
|
|
454
468
|
});
|
|
455
469
|
}
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-dimension-facts.test.ts
CHANGED
|
@@ -258,8 +258,19 @@ describe("cost invocation dimension rebuild", () => {
|
|
|
258
258
|
expect(factRows(database, "cost_invocation_dimension_facts")).toEqual(
|
|
259
259
|
factRows(database, "legacy_cost_invocation_dimension_facts"),
|
|
260
260
|
);
|
|
261
|
+
// SQLite versions bundled with supported Node runtimes may serialize REALs
|
|
262
|
+
// with different precision. The contract is exact legacy JSON parity on
|
|
263
|
+
// that engine, not a hard-coded decimal spelling from SQLite 3.49.
|
|
264
|
+
const expectedCosts = database
|
|
265
|
+
.prepare(`
|
|
266
|
+
SELECT json_extract(payload, '$.cost_usd') AS cost_usd,
|
|
267
|
+
json_extract(payload, '$.cost_brl') AS cost_brl
|
|
268
|
+
FROM (SELECT json_object('cost_usd', ?, 'cost_brl', ?) AS payload)
|
|
269
|
+
`)
|
|
270
|
+
.get(0.1 + 0.2, 1234567.8912345679);
|
|
271
|
+
expect(expectedCosts).toEqual({ cost_usd: expect.any(Number), cost_brl: expect.any(Number) });
|
|
261
272
|
expect(factRows(database, "cost_invocation_dimension_facts")).toContainEqual(
|
|
262
|
-
expect.objectContaining({ residual: 0,
|
|
273
|
+
expect.objectContaining({ residual: 0, ...expectedCosts }),
|
|
263
274
|
);
|
|
264
275
|
});
|
|
265
276
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { DatabaseSync } from "node:sqlite";
|
|
5
|
+
import { expect, it } from "vitest";
|
|
6
|
+
import { rebuildSqliteReadModel, validateSqliteReadModelSchema } from "./sqlite-read-model.js";
|
|
7
|
+
import { prepareMultiProviderFixture } from "./sqlite-read-model-multi-provider-fixture.js";
|
|
8
|
+
|
|
9
|
+
it("indexes exact and LIKE file lookups without changing case or prefix membership", async () => {
|
|
10
|
+
const root = await mkdtemp(join(tmpdir(), "zaip-file-index-"));
|
|
11
|
+
let database: DatabaseSync | undefined;
|
|
12
|
+
try {
|
|
13
|
+
await prepareMultiProviderFixture(root);
|
|
14
|
+
await rebuildSqliteReadModel(root);
|
|
15
|
+
const path = join(root, ".local/sqlite/zaip-aios-dashboard.sqlite");
|
|
16
|
+
database = new DatabaseSync(path);
|
|
17
|
+
const reader = database;
|
|
18
|
+
const queries = [
|
|
19
|
+
{
|
|
20
|
+
sql: "SELECT path, content FROM zaip_vw_files WHERE path = ?",
|
|
21
|
+
arg: ".agents/config/project.yaml",
|
|
22
|
+
index: "zaip_activities_file_path",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
sql: "SELECT path FROM zaip_vw_files WHERE path LIKE ? ORDER BY path",
|
|
26
|
+
arg: ".agents/%",
|
|
27
|
+
index: "zaip_activities_file_path",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
sql: "SELECT path FROM zaip_vw_files WHERE path LIKE ? ORDER BY path",
|
|
31
|
+
arg: ".AGENTS/%",
|
|
32
|
+
index: "zaip_activities_file_path",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
sql: "SELECT path FROM zaip_vw_files WHERE path LIKE ? ORDER BY path",
|
|
36
|
+
arg: ".agents/missing/%",
|
|
37
|
+
index: "zaip_activities_file_path",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
sql: "SELECT path FROM zaip_vw_files WHERE path = ?",
|
|
41
|
+
arg: ".AGENTS/config/project.yaml",
|
|
42
|
+
index: "zaip_activities_file_path",
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
const indexed = queries.map(({ sql, arg, index }) => {
|
|
46
|
+
const plan = reader.prepare(`EXPLAIN QUERY PLAN ${sql}`).all(arg);
|
|
47
|
+
expect(JSON.stringify(plan)).toContain(`USING INDEX ${index}`);
|
|
48
|
+
return reader.prepare(sql).all(arg);
|
|
49
|
+
});
|
|
50
|
+
expect(indexed[0]).toHaveLength(1);
|
|
51
|
+
expect(indexed[1]?.length).toBeGreaterThan(1);
|
|
52
|
+
expect(indexed[2]).toEqual(indexed[1]);
|
|
53
|
+
expect(indexed[3]).toEqual([]);
|
|
54
|
+
expect(indexed[4]).toEqual([]);
|
|
55
|
+
const view = database
|
|
56
|
+
.prepare("SELECT sql FROM sqlite_master WHERE name='zaip_vw_files'")
|
|
57
|
+
.get() as { sql: string };
|
|
58
|
+
database.exec("DROP VIEW zaip_vw_files;");
|
|
59
|
+
database.exec(view.sql.replace(" INDEXED BY zaip_activities_file_path", ""));
|
|
60
|
+
database.exec("DROP INDEX zaip_activities_file_path;");
|
|
61
|
+
expect(() => validateSqliteReadModelSchema(path)).toThrow(/missing required indexes/);
|
|
62
|
+
for (const [position, { sql, arg }] of queries.entries()) {
|
|
63
|
+
expect(database.prepare(sql).all(arg)).toEqual(indexed[position]);
|
|
64
|
+
}
|
|
65
|
+
} finally {
|
|
66
|
+
database?.close();
|
|
67
|
+
await rm(root, { recursive: true, force: true });
|
|
68
|
+
}
|
|
69
|
+
});
|
|
@@ -231,7 +231,9 @@ export function readFirstFoldViewport(
|
|
|
231
231
|
SELECT COALESCE(status, 'draft') AS status, COUNT(*) AS task_count FROM items WHERE entity_kind='task' GROUP BY COALESCE(status, 'draft'))
|
|
232
232
|
), task_risk AS (
|
|
233
233
|
SELECT json_group_object(risk, task_count) AS task_risk_json FROM (
|
|
234
|
-
SELECT COALESCE(risk, 'standard') AS risk, COUNT(*) AS task_count FROM items
|
|
234
|
+
SELECT COALESCE(risk, 'standard') AS risk, COUNT(*) AS task_count FROM items
|
|
235
|
+
WHERE entity_kind='task' AND COALESCE(status, 'draft') <> 'draft'
|
|
236
|
+
GROUP BY COALESCE(risk, 'standard'))
|
|
235
237
|
)
|
|
236
238
|
SELECT totals.*, run_totals.*, duration_totals.*, bounds.*, item_totals.*, task_status.*, task_risk.*
|
|
237
239
|
FROM totals CROSS JOIN run_totals CROSS JOIN duration_totals CROSS JOIN bounds
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
3
|
import { DatabaseSync } from "node:sqlite";
|
|
4
|
-
import { afterEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
5
|
import { rebuildSqliteReadModel } from "./sqlite-read-model.js";
|
|
6
6
|
|
|
7
7
|
const roots: string[] = [];
|
|
@@ -17,12 +17,14 @@ async function fixture(): Promise<string> {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
afterEach(async () => {
|
|
20
|
+
vi.restoreAllMocks();
|
|
20
21
|
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
describe("forceCanonical SQLite refresh", () => {
|
|
24
25
|
it("bypasses a healthy generation and verifies canonical sources again", async () => {
|
|
25
26
|
const root = await fixture();
|
|
27
|
+
vi.spyOn(Date, "now").mockReturnValue(Date.now() + 5_000);
|
|
26
28
|
const initial = await rebuildSqliteReadModel(root);
|
|
27
29
|
await expect(rebuildSqliteReadModel(root)).resolves.toMatchObject({
|
|
28
30
|
cache: "generation",
|
package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts
CHANGED
|
@@ -173,6 +173,8 @@ describe("incremental refresh preserves historical facts", () => {
|
|
|
173
173
|
it("updates and removes changed sources in place with full-build query parity and untouched historical payloads", async () => {
|
|
174
174
|
const root = await fixture();
|
|
175
175
|
const { started, usage, finished } = await prepareMultiProviderFixture(root);
|
|
176
|
+
// This scenario exercises settled historical checkpoints, not rapid writes.
|
|
177
|
+
vi.spyOn(Date, "now").mockReturnValue(Date.now() + 5_000);
|
|
176
178
|
const first = await rebuildSqliteReadModel(root);
|
|
177
179
|
const history = inspect(first.path, historySql);
|
|
178
180
|
expect(history).toHaveLength(2);
|