@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
|
@@ -7,9 +7,26 @@ import {
|
|
|
7
7
|
parseAgentCatalog,
|
|
8
8
|
parseProjectConfig,
|
|
9
9
|
parseYaml,
|
|
10
|
+
resolveAutonomy,
|
|
10
11
|
serializeYaml,
|
|
11
12
|
type WorkspaceFileSystem,
|
|
12
13
|
} from "@zaip-ai/core";
|
|
14
|
+
import {
|
|
15
|
+
installationProfile,
|
|
16
|
+
type PROJECT_INSTALLATION_TOTAL,
|
|
17
|
+
type ProjectStatusSummary,
|
|
18
|
+
readDocumentAvailability,
|
|
19
|
+
summarizeProjectInstallation,
|
|
20
|
+
summarizeProjectStatus,
|
|
21
|
+
} from "./project-installation-summary.js";
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
PROJECT_INSTALLATION_AREA_REQUIREMENTS,
|
|
25
|
+
PROJECT_INSTALLATION_STACK_REQUIREMENTS,
|
|
26
|
+
PROJECT_INSTALLATION_TOTAL,
|
|
27
|
+
summarizeProjectInstallation,
|
|
28
|
+
summarizeProjectStatus,
|
|
29
|
+
} from "./project-installation-summary.js";
|
|
13
30
|
|
|
14
31
|
const AGENT_CATALOG_PATH = ".agents/config/agents/catalog.yaml";
|
|
15
32
|
const CODEX_CONFIG_PATH = ".codex/config.toml";
|
|
@@ -17,30 +34,7 @@ const FRAMEWORK_LOCK_PATH = ".agents/config/framework.lock.yaml";
|
|
|
17
34
|
const DASHBOARD_STACK_DEPENDENCIES_PATH = ".agents/dashboard/stack-dependencies.json";
|
|
18
35
|
const exec = promisify(execFile);
|
|
19
36
|
export const SOFTWARE_ARCHITECTURE_PATH = ".agents/architecture/software-architecture.md";
|
|
20
|
-
export
|
|
21
|
-
"Node.js",
|
|
22
|
-
"TypeScript",
|
|
23
|
-
"Vite",
|
|
24
|
-
"Astro",
|
|
25
|
-
"Redis",
|
|
26
|
-
"BullMQ",
|
|
27
|
-
"Hono",
|
|
28
|
-
"React",
|
|
29
|
-
"Git",
|
|
30
|
-
"Terraform",
|
|
31
|
-
] as const;
|
|
32
|
-
export const PROJECT_INSTALLATION_AREA_REQUIREMENTS = [
|
|
33
|
-
"software_architecture",
|
|
34
|
-
"design_system",
|
|
35
|
-
"brandbook",
|
|
36
|
-
"marketing_strategy",
|
|
37
|
-
"sales_playbook",
|
|
38
|
-
"growth_strategy",
|
|
39
|
-
] as const;
|
|
40
|
-
export const PROJECT_INSTALLATION_TOTAL =
|
|
41
|
-
PROJECT_INSTALLATION_STACK_REQUIREMENTS.length + PROJECT_INSTALLATION_AREA_REQUIREMENTS.length;
|
|
42
|
-
|
|
43
|
-
export type ProjectOverview = {
|
|
37
|
+
export type ProjectOverview = ProjectStatusSummary & {
|
|
44
38
|
framework_version: string | null;
|
|
45
39
|
installation: {
|
|
46
40
|
completed: number;
|
|
@@ -60,6 +54,7 @@ export type ProjectOverview = {
|
|
|
60
54
|
source: string | null;
|
|
61
55
|
verification: "exact" | "constraint" | "unavailable";
|
|
62
56
|
installation: "runtime" | "installed" | "missing" | "bundled";
|
|
57
|
+
probe?: "verified" | "missing" | "unknown";
|
|
63
58
|
}>;
|
|
64
59
|
areas: Array<{
|
|
65
60
|
id:
|
|
@@ -71,7 +66,7 @@ export type ProjectOverview = {
|
|
|
71
66
|
| "sales_playbook";
|
|
72
67
|
label: string;
|
|
73
68
|
artifact: string;
|
|
74
|
-
available: boolean;
|
|
69
|
+
available: boolean | null;
|
|
75
70
|
}>;
|
|
76
71
|
};
|
|
77
72
|
|
|
@@ -107,19 +102,27 @@ export async function readProjectOverview(
|
|
|
107
102
|
countDirectMarkdownFiles(filesystem, ".agents/rules"),
|
|
108
103
|
countCodexHookEvents(filesystem),
|
|
109
104
|
]);
|
|
110
|
-
const [stack_components, areas] = await Promise.all([
|
|
105
|
+
const [project, stack_components, areas] = await Promise.all([
|
|
106
|
+
readProjectSettings(filesystem),
|
|
111
107
|
readVerifiedStackComponents(filesystem),
|
|
112
108
|
Promise.all(
|
|
113
109
|
projectOverviewArtifacts.map(async (area) => ({
|
|
114
110
|
...area,
|
|
115
|
-
available: await
|
|
111
|
+
available: await readDocumentAvailability(filesystem, area.artifact),
|
|
116
112
|
})),
|
|
117
113
|
),
|
|
118
114
|
]);
|
|
119
115
|
const installation = summarizeProjectInstallation(stack_components, areas);
|
|
116
|
+
const status = summarizeProjectStatus(
|
|
117
|
+
installationProfile(project),
|
|
118
|
+
stack_components,
|
|
119
|
+
areas,
|
|
120
|
+
"healthy",
|
|
121
|
+
);
|
|
120
122
|
return {
|
|
121
123
|
framework_version: frameworkVersion,
|
|
122
124
|
installation,
|
|
125
|
+
...status,
|
|
123
126
|
metrics: [
|
|
124
127
|
{ id: "agents", label: "Agentes", value: catalog.agents.length },
|
|
125
128
|
{ id: "squads", label: "Squads", value: catalog.squads.length },
|
|
@@ -132,36 +135,6 @@ export async function readProjectOverview(
|
|
|
132
135
|
};
|
|
133
136
|
}
|
|
134
137
|
|
|
135
|
-
export function summarizeProjectInstallation(
|
|
136
|
-
stackComponents: ProjectOverview["stack_components"],
|
|
137
|
-
areas: ProjectOverview["areas"],
|
|
138
|
-
): ProjectOverview["installation"] {
|
|
139
|
-
const completed =
|
|
140
|
-
PROJECT_INSTALLATION_STACK_REQUIREMENTS.filter((name) =>
|
|
141
|
-
stackComponents.some(
|
|
142
|
-
(component) => component.name === name && isInstalledLocalRequirement(component),
|
|
143
|
-
),
|
|
144
|
-
).length +
|
|
145
|
-
PROJECT_INSTALLATION_AREA_REQUIREMENTS.filter((id) =>
|
|
146
|
-
areas.some((area) => area.id === id && area.available),
|
|
147
|
-
).length;
|
|
148
|
-
return {
|
|
149
|
-
completed,
|
|
150
|
-
total: PROJECT_INSTALLATION_TOTAL,
|
|
151
|
-
percent: (completed / PROJECT_INSTALLATION_TOTAL) * 100,
|
|
152
|
-
state: completed === PROJECT_INSTALLATION_TOTAL ? "complete" : "incomplete",
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function isInstalledLocalRequirement(
|
|
157
|
-
component: ProjectOverview["stack_components"][number],
|
|
158
|
-
): boolean {
|
|
159
|
-
return (
|
|
160
|
-
component.verification === "exact" &&
|
|
161
|
-
(component.installation === "runtime" || component.installation === "installed")
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
138
|
async function readFrameworkVersion(filesystem: WorkspaceFileSystem): Promise<string | null> {
|
|
166
139
|
try {
|
|
167
140
|
const lock = recordValue(parseYaml(await filesystem.readText(FRAMEWORK_LOCK_PATH)));
|
|
@@ -246,13 +219,19 @@ async function readVerifiedStackComponents(
|
|
|
246
219
|
];
|
|
247
220
|
}
|
|
248
221
|
|
|
249
|
-
type InstalledPackage = {
|
|
222
|
+
type InstalledPackage = {
|
|
223
|
+
name: string;
|
|
224
|
+
version: string | null;
|
|
225
|
+
source: string | null;
|
|
226
|
+
probe: "verified" | "missing" | "unknown";
|
|
227
|
+
};
|
|
250
228
|
type DashboardStackDependencies = { node: string | null; packages: Map<string, string> };
|
|
251
229
|
|
|
252
230
|
async function readInstalledPackageVersion(
|
|
253
231
|
filesystem: WorkspaceFileSystem,
|
|
254
232
|
name: string,
|
|
255
233
|
): Promise<InstalledPackage> {
|
|
234
|
+
let uncertain = false;
|
|
256
235
|
const roots = ["node_modules"];
|
|
257
236
|
if (name === "hono") roots.push(".agents/dashboard/packages/local-runtime/node_modules");
|
|
258
237
|
if (name === "react") roots.push(".agents/dashboard/apps/frontend/node_modules");
|
|
@@ -267,15 +246,18 @@ async function readInstalledPackageVersion(
|
|
|
267
246
|
version === null ||
|
|
268
247
|
!/^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(version) ||
|
|
269
248
|
entrypoint === null
|
|
270
|
-
)
|
|
249
|
+
) {
|
|
250
|
+
uncertain = true;
|
|
271
251
|
continue;
|
|
252
|
+
}
|
|
272
253
|
await filesystem.readText(`${root}/${name}/${entrypoint}`);
|
|
273
|
-
return { name, version, source };
|
|
274
|
-
} catch {
|
|
275
|
-
//
|
|
254
|
+
return { name, version, source, probe: "verified" };
|
|
255
|
+
} catch (error) {
|
|
256
|
+
// Absence is known only for ENOENT; invalid JSON and denied reads are unknown.
|
|
257
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") uncertain = true;
|
|
276
258
|
}
|
|
277
259
|
}
|
|
278
|
-
return { name, version: null, source: null };
|
|
260
|
+
return { name, version: null, source: null, probe: uncertain ? "unknown" : "missing" };
|
|
279
261
|
}
|
|
280
262
|
|
|
281
263
|
async function readDashboardStackDependencies(
|
|
@@ -374,6 +356,7 @@ async function executableComponent(
|
|
|
374
356
|
source: executable === command ? `Comando do workspace: ${command}` : local,
|
|
375
357
|
verification: "exact",
|
|
376
358
|
installation: executable === command ? "runtime" : "installed",
|
|
359
|
+
probe: "verified",
|
|
377
360
|
};
|
|
378
361
|
} catch {
|
|
379
362
|
return {
|
|
@@ -383,6 +366,7 @@ async function executableComponent(
|
|
|
383
366
|
source: null,
|
|
384
367
|
verification: "unavailable",
|
|
385
368
|
installation: "missing",
|
|
369
|
+
probe: "unknown",
|
|
386
370
|
};
|
|
387
371
|
}
|
|
388
372
|
}
|
|
@@ -399,6 +383,7 @@ function runtimeComponent(
|
|
|
399
383
|
source: `Runtime do Dashboard: ${process.execPath}`,
|
|
400
384
|
verification: "exact",
|
|
401
385
|
installation: "runtime",
|
|
386
|
+
probe: "verified",
|
|
402
387
|
};
|
|
403
388
|
}
|
|
404
389
|
|
|
@@ -418,6 +403,7 @@ function packageComponent(
|
|
|
418
403
|
source: installed.get(packageName)?.source ?? null,
|
|
419
404
|
verification: "exact",
|
|
420
405
|
installation: "installed",
|
|
406
|
+
probe: "verified",
|
|
421
407
|
};
|
|
422
408
|
if (bundled)
|
|
423
409
|
return {
|
|
@@ -430,6 +416,7 @@ function packageComponent(
|
|
|
430
416
|
: ".agents/dashboard/apps/frontend/dist",
|
|
431
417
|
verification: "unavailable",
|
|
432
418
|
installation: "bundled",
|
|
419
|
+
probe: "unknown",
|
|
433
420
|
};
|
|
434
421
|
return {
|
|
435
422
|
name,
|
|
@@ -438,6 +425,7 @@ function packageComponent(
|
|
|
438
425
|
source: null,
|
|
439
426
|
verification: "unavailable",
|
|
440
427
|
installation: "missing",
|
|
428
|
+
probe: installed.get(packageName)?.probe ?? "missing",
|
|
441
429
|
};
|
|
442
430
|
}
|
|
443
431
|
|
|
@@ -535,6 +523,7 @@ const architectureLabels: Record<string, string> = {
|
|
|
535
523
|
};
|
|
536
524
|
|
|
537
525
|
export function renderSoftwareArchitecture(config: ProjectConfig): string {
|
|
526
|
+
const autonomy = resolveAutonomy(config.autonomy);
|
|
538
527
|
const overrides = recordValue(config.stack.overrides);
|
|
539
528
|
const components = recordValue(overrides.components);
|
|
540
529
|
const languages = recordValue(overrides.languages);
|
|
@@ -556,14 +545,14 @@ export function renderSoftwareArchitecture(config: ProjectConfig): string {
|
|
|
556
545
|
"",
|
|
557
546
|
]);
|
|
558
547
|
const executionDetails =
|
|
559
|
-
config.execution
|
|
548
|
+
config.execution && config.execution.runtime !== "manual"
|
|
560
549
|
? [
|
|
561
|
-
|
|
550
|
+
`- **Runtime:** ${config.execution.runtime}`,
|
|
562
551
|
`- **Provider:** ${markdownCell(config.execution.autonomous.provider)}`,
|
|
563
552
|
`- **Modelo-base:** ${markdownCell(config.execution.autonomous.model)}`,
|
|
564
553
|
`- **Paralelismo máximo:** ${config.execution.autonomous.max_parallelism}`,
|
|
565
554
|
`- **Lease configurado:** ${config.execution.autonomous.lease_ms} ms`,
|
|
566
|
-
`- **Limite total de invocações:** ${config.execution.autonomous.max_total_invocations ?? "Não definido"}`,
|
|
555
|
+
`- **Limite total de invocações:** ${config.autonomy ? "Por Task; sem teto agregado de SPEC/PRD" : (config.execution.autonomous.max_total_invocations ?? "Não definido")}`,
|
|
567
556
|
]
|
|
568
557
|
: [`- **Runtime:** ${config.execution?.runtime ?? "manual (padrão implícito)"}`];
|
|
569
558
|
const assuranceDetails =
|
|
@@ -602,6 +591,18 @@ export function renderSoftwareArchitecture(config: ProjectConfig): string {
|
|
|
602
591
|
"## Execução",
|
|
603
592
|
"",
|
|
604
593
|
...executionDetails,
|
|
594
|
+
...(config.autonomy
|
|
595
|
+
? [
|
|
596
|
+
"",
|
|
597
|
+
"### Autonomia",
|
|
598
|
+
"",
|
|
599
|
+
`- **Perfil:** ${autonomy.label}`,
|
|
600
|
+
`- **Execuções por Task:** ${autonomy.attempts ?? "Ilimitadas"}`,
|
|
601
|
+
`- **Replanejamentos por Task:** ${autonomy.replans ?? "Ilimitados"}`,
|
|
602
|
+
"- Sem abandono por tempo. Tasks iniciadas preservam o perfil e os contadores.",
|
|
603
|
+
"- Subagentes podem ter modelo/esforço diferentes do principal, com aviso explícito.",
|
|
604
|
+
]
|
|
605
|
+
: []),
|
|
605
606
|
"",
|
|
606
607
|
"## Assurance",
|
|
607
608
|
"",
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
3
|
+
import { registerBrowserLeaseRoute } from "./server-browser-lease.js";
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
vi.useRealTimers();
|
|
7
|
+
vi.restoreAllMocks();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
async function openLease(app: Hono) {
|
|
11
|
+
const response = await app.request("/api/v2/browser-lease");
|
|
12
|
+
if (response.body === null) throw new Error("Missing SSE body");
|
|
13
|
+
const reader = response.body.getReader();
|
|
14
|
+
const chunks: string[] = [];
|
|
15
|
+
const drained = (async () => {
|
|
16
|
+
for (;;) {
|
|
17
|
+
const chunk = await reader.read();
|
|
18
|
+
if (chunk.done) return;
|
|
19
|
+
chunks.push(new TextDecoder().decode(chunk.value));
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
22
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
23
|
+
expect(response.headers.get("content-type")).toContain("text/event-stream");
|
|
24
|
+
expect(chunks[0]).toContain("event: lease\ndata: active");
|
|
25
|
+
return {
|
|
26
|
+
chunks,
|
|
27
|
+
close: async () => {
|
|
28
|
+
await reader.cancel();
|
|
29
|
+
await drained;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("browser lease lifecycle", () => {
|
|
35
|
+
it("keeps the real SSE body active past a five-minute idle timeout", async () => {
|
|
36
|
+
vi.useFakeTimers();
|
|
37
|
+
const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
|
|
38
|
+
const app = new Hono();
|
|
39
|
+
registerBrowserLeaseRoute(app, "/api/v2", true);
|
|
40
|
+
const lease = await openLease(app);
|
|
41
|
+
try {
|
|
42
|
+
for (let interval = 0; interval < 31; interval++) {
|
|
43
|
+
const before = lease.chunks.length;
|
|
44
|
+
await vi.advanceTimersByTimeAsync(10_000);
|
|
45
|
+
expect(lease.chunks.length).toBeGreaterThan(before);
|
|
46
|
+
expect(lease.chunks.at(-1)).toContain(": keep-alive\n\n");
|
|
47
|
+
expect(exit).not.toHaveBeenCalled();
|
|
48
|
+
}
|
|
49
|
+
} finally {
|
|
50
|
+
await lease.close();
|
|
51
|
+
}
|
|
52
|
+
expect(vi.getTimerCount()).toBe(1);
|
|
53
|
+
await vi.advanceTimersByTimeAsync(11_999);
|
|
54
|
+
expect(exit).not.toHaveBeenCalled();
|
|
55
|
+
await vi.advanceTimersByTimeAsync(1);
|
|
56
|
+
expect(exit).toHaveBeenCalledExactlyOnceWith(0);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("expires only after the last client closes and a replacement cancels expiry", async () => {
|
|
60
|
+
vi.useFakeTimers();
|
|
61
|
+
const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
|
|
62
|
+
const app = new Hono();
|
|
63
|
+
registerBrowserLeaseRoute(app, "/api/v2", true);
|
|
64
|
+
const first = await openLease(app);
|
|
65
|
+
const second = await openLease(app);
|
|
66
|
+
await first.close();
|
|
67
|
+
await vi.advanceTimersByTimeAsync(13_000);
|
|
68
|
+
expect(exit).not.toHaveBeenCalled();
|
|
69
|
+
await second.close();
|
|
70
|
+
await vi.advanceTimersByTimeAsync(11_000);
|
|
71
|
+
const replacement = await openLease(app);
|
|
72
|
+
await vi.advanceTimersByTimeAsync(13_000);
|
|
73
|
+
expect(exit).not.toHaveBeenCalled();
|
|
74
|
+
await replacement.close();
|
|
75
|
+
await vi.advanceTimersByTimeAsync(12_000);
|
|
76
|
+
expect(exit).toHaveBeenCalledExactlyOnceWith(0);
|
|
77
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("does not terminate an unmanaged server or retain a heartbeat after cancellation", async () => {
|
|
81
|
+
vi.useFakeTimers();
|
|
82
|
+
const exit = vi.spyOn(process, "exit").mockImplementation(() => undefined as never);
|
|
83
|
+
const app = new Hono();
|
|
84
|
+
registerBrowserLeaseRoute(app, "/api/v2");
|
|
85
|
+
const lease = await openLease(app);
|
|
86
|
+
await lease.close();
|
|
87
|
+
await vi.advanceTimersByTimeAsync(60_000);
|
|
88
|
+
expect(exit).not.toHaveBeenCalled();
|
|
89
|
+
expect(vi.getTimerCount()).toBe(0);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -13,7 +13,7 @@ export function registerBrowserLeaseRoute(
|
|
|
13
13
|
browserLeaseDeadline.unref();
|
|
14
14
|
}
|
|
15
15
|
const releaseBrowserLease = (lease: object) => {
|
|
16
|
-
browserLeases.delete(lease);
|
|
16
|
+
if (!browserLeases.delete(lease)) return;
|
|
17
17
|
if (!launcherOwned || browserLeases.size !== 0) return;
|
|
18
18
|
if (browserLeaseDeadline !== undefined) clearTimeout(browserLeaseDeadline);
|
|
19
19
|
browserLeaseDeadline = setTimeout(() => process.exit(0), 12_000);
|
|
@@ -25,9 +25,29 @@ export function registerBrowserLeaseRoute(
|
|
|
25
25
|
browserLeaseDeadline = undefined;
|
|
26
26
|
browserLeases.add(lease);
|
|
27
27
|
return streamSSE(context, async (stream) => {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
let heartbeat: NodeJS.Timeout | undefined;
|
|
29
|
+
let wake: (() => void) | undefined;
|
|
30
|
+
stream.onAbort(() => {
|
|
31
|
+
if (heartbeat !== undefined) clearTimeout(heartbeat);
|
|
32
|
+
wake?.();
|
|
33
|
+
releaseBrowserLease(lease);
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
await stream.writeSSE({ event: "lease", data: "active" });
|
|
37
|
+
while (!stream.aborted) {
|
|
38
|
+
await new Promise<void>((resolve) => {
|
|
39
|
+
wake = resolve;
|
|
40
|
+
heartbeat = setTimeout(resolve, 10_000);
|
|
41
|
+
heartbeat.unref();
|
|
42
|
+
});
|
|
43
|
+
// SSE comments keep idle HTTP clients alive without changing the
|
|
44
|
+
// browser's lease event contract or accumulating overlapping writes.
|
|
45
|
+
if (!stream.aborted) await stream.write(": keep-alive\n\n");
|
|
46
|
+
}
|
|
47
|
+
} finally {
|
|
48
|
+
if (heartbeat !== undefined) clearTimeout(heartbeat);
|
|
49
|
+
releaseBrowserLease(lease);
|
|
50
|
+
}
|
|
31
51
|
});
|
|
32
52
|
});
|
|
33
53
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe("Dashboard HTTP query security", () => {
|
|
5
|
+
const app = new Hono().get("/", (context) => context.json(context.req.query()));
|
|
6
|
+
|
|
7
|
+
it("does not interpret a question mark inside a URL fragment as a query", async () => {
|
|
8
|
+
const response = await app.request("http://localhost/#?admin=true");
|
|
9
|
+
expect(response.status).toBe(200);
|
|
10
|
+
expect(await response.json()).toEqual({});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("preserves real query parameters but excludes fragment parameters", async () => {
|
|
14
|
+
const response = await app.request("http://localhost/?currency=BRL#?admin=true");
|
|
15
|
+
expect(await response.json()).toEqual({ currency: "BRL" });
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -52,14 +52,14 @@ export function registerOperationsRoutes(app: Hono, dependencies: DashboardRoute
|
|
|
52
52
|
scope !== "quick" &&
|
|
53
53
|
scope !== "detail" &&
|
|
54
54
|
scope !== "board" &&
|
|
55
|
+
scope !== "traceability" &&
|
|
55
56
|
scope !== "classification"
|
|
56
57
|
)
|
|
57
58
|
return headOrJson(context, (await readSnapshot(context)).operations);
|
|
58
59
|
const layout = await readLayout();
|
|
59
60
|
const layoutMs = performance.now() - requestStartedAt;
|
|
60
61
|
const { from, to } = projectionPeriodFilter(context);
|
|
61
|
-
if (scope === "board") {
|
|
62
|
-
const stage = boardStage(context.req.query("stage"));
|
|
62
|
+
if (scope === "board" || scope === "traceability") {
|
|
63
63
|
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
64
64
|
const limit = Math.min(
|
|
65
65
|
50,
|
|
@@ -80,6 +80,25 @@ export function registerOperationsRoutes(app: Hono, dependencies: DashboardRoute
|
|
|
80
80
|
};
|
|
81
81
|
},
|
|
82
82
|
);
|
|
83
|
+
// Traceability is an identity index, not an executable Kanban column.
|
|
84
|
+
// Drafts remain discoverable without changing their canonical state.
|
|
85
|
+
if (scope === "traceability") {
|
|
86
|
+
const tasks = board.projection.tasks.toSorted(
|
|
87
|
+
(a, b) => b.created_at.localeCompare(a.created_at) || b.id.localeCompare(a.id),
|
|
88
|
+
);
|
|
89
|
+
return headOrJson(
|
|
90
|
+
context,
|
|
91
|
+
{
|
|
92
|
+
tasks: tasks.slice(offset, offset + limit),
|
|
93
|
+
total: tasks.length,
|
|
94
|
+
offset,
|
|
95
|
+
limit,
|
|
96
|
+
},
|
|
97
|
+
200,
|
|
98
|
+
true,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const stage = boardStage(context.req.query("stage"));
|
|
83
102
|
const filters = boardFilters(context);
|
|
84
103
|
const pageKey = JSON.stringify({ from, to, stage, offset, limit, ...filters });
|
|
85
104
|
const page = await readAggregate(`operations:board-page:${pageKey}`, async () =>
|
package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { DatabaseSync } from "node:sqlite";
|
|
6
|
+
import { describe, expect, it, vi } from "vitest";
|
|
7
|
+
import {
|
|
8
|
+
attachRefreshWorkerCleanup,
|
|
9
|
+
refreshSqliteSnapshotInWorker,
|
|
10
|
+
validateSnapshotWorkerReceipt,
|
|
11
|
+
} from "./server-snapshot-refresh.js";
|
|
12
|
+
import { SqliteReadModelFileSystem } from "./sqlite-read-model-filesystem.js";
|
|
13
|
+
import {
|
|
14
|
+
readModelSchemaVersion,
|
|
15
|
+
requiredIndexes,
|
|
16
|
+
requiredPersistedTables,
|
|
17
|
+
requiredViews,
|
|
18
|
+
} from "./sqlite-read-model-schema.js";
|
|
4
19
|
|
|
5
20
|
describe("snapshot refresh shutdown", () => {
|
|
6
21
|
it("terminates an active refresh worker on runtime shutdown and removes its listener on completion", () => {
|
|
@@ -17,3 +32,80 @@ describe("snapshot refresh shutdown", () => {
|
|
|
17
32
|
expect(calls).toEqual(["SIGTERM"]);
|
|
18
33
|
});
|
|
19
34
|
});
|
|
35
|
+
|
|
36
|
+
describe("snapshot worker process boundary", () => {
|
|
37
|
+
it.each([
|
|
38
|
+
"valid",
|
|
39
|
+
"empty",
|
|
40
|
+
"wrong-path",
|
|
41
|
+
"nonzero",
|
|
42
|
+
"oversized",
|
|
43
|
+
] as const)("reopens only after valid receipt and successful process close: %s", async (mode) => {
|
|
44
|
+
const root = await mkdtemp(join(tmpdir(), "zaip-refresh-receipt-"));
|
|
45
|
+
const db = new DatabaseSync(":memory:");
|
|
46
|
+
const filesystem = new SqliteReadModelFileSystem(root, db);
|
|
47
|
+
const refresh = vi.spyOn(filesystem, "refresh").mockImplementation(() => undefined);
|
|
48
|
+
try {
|
|
49
|
+
const scripts = join(root, ".agents/dashboard/packages/local-runtime/scripts");
|
|
50
|
+
await mkdir(scripts, { recursive: true });
|
|
51
|
+
// This fixture tests native transport/failure handling, not DB integrity.
|
|
52
|
+
// The shipped rebuild script performs the real schema/integrity validation.
|
|
53
|
+
await writeFile(
|
|
54
|
+
join(scripts, "rebuild-sqlite-read-model.mjs"),
|
|
55
|
+
`
|
|
56
|
+
const receipt = {storage_mode:'sqlite_read_model',
|
|
57
|
+
path: ${JSON.stringify(mode)} === 'wrong-path' ? 'other.sqlite' : process.env.ZAIP_SQLITE_DB_PATH,
|
|
58
|
+
schema: ${JSON.stringify({ schemaVersion: readModelSchemaVersion, tableCount: requiredPersistedTables.length, viewCount: requiredViews.length, indexCount: requiredIndexes.length })}};
|
|
59
|
+
if (${JSON.stringify(mode)} !== 'empty') {
|
|
60
|
+
if (${JSON.stringify(mode)} === 'oversized') process.stdout.write(' '.repeat(64001));
|
|
61
|
+
const output = JSON.stringify(receipt);
|
|
62
|
+
process.stdout.write(output.slice(0, 20));
|
|
63
|
+
setTimeout(() => process.stdout.write(output.slice(20)), 5);
|
|
64
|
+
}
|
|
65
|
+
process.exitCode = ${mode === "nonzero" ? 1 : 0};
|
|
66
|
+
`,
|
|
67
|
+
);
|
|
68
|
+
if (mode === "valid") {
|
|
69
|
+
await expect(refreshSqliteSnapshotInWorker(root, filesystem)).resolves.toBeUndefined();
|
|
70
|
+
expect(refresh).toHaveBeenCalledTimes(1);
|
|
71
|
+
} else {
|
|
72
|
+
await expect(refreshSqliteSnapshotInWorker(root, filesystem)).rejects.toThrow();
|
|
73
|
+
expect(refresh).not.toHaveBeenCalled();
|
|
74
|
+
}
|
|
75
|
+
} finally {
|
|
76
|
+
refresh.mockRestore();
|
|
77
|
+
db.close();
|
|
78
|
+
await rm(root, { recursive: true, force: true });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("validated worker receipt", () => {
|
|
84
|
+
const destination = "snapshot.sqlite";
|
|
85
|
+
const receipt = {
|
|
86
|
+
storage_mode: "sqlite_read_model",
|
|
87
|
+
path: destination,
|
|
88
|
+
schema: {
|
|
89
|
+
schemaVersion: readModelSchemaVersion,
|
|
90
|
+
tableCount: requiredPersistedTables.length,
|
|
91
|
+
viewCount: requiredViews.length,
|
|
92
|
+
indexCount: requiredIndexes.length,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
it("accepts the exact schema-validated destination without scanning it on the HTTP thread", () => {
|
|
96
|
+
// The path need not exist in this process: only the worker does the heavy check.
|
|
97
|
+
expect(() => validateSnapshotWorkerReceipt(JSON.stringify(receipt), destination)).not.toThrow();
|
|
98
|
+
});
|
|
99
|
+
it.each([
|
|
100
|
+
"",
|
|
101
|
+
"null",
|
|
102
|
+
"{}",
|
|
103
|
+
JSON.stringify({ ...receipt, path: "other.sqlite" }),
|
|
104
|
+
JSON.stringify({ ...receipt, schema: { ...receipt.schema, schemaVersion: "old" } }),
|
|
105
|
+
JSON.stringify({ ...receipt, schema: { ...receipt.schema, indexCount: 0 } }),
|
|
106
|
+
JSON.stringify({ ...receipt, schema: { ...receipt.schema, tableCount: 0 } }),
|
|
107
|
+
JSON.stringify({ ...receipt, schema: { ...receipt.schema, viewCount: null } }),
|
|
108
|
+
])("rejects absent, stale or unrelated validation: %s", (value) => {
|
|
109
|
+
expect(() => validateSnapshotWorkerReceipt(value, destination)).toThrow();
|
|
110
|
+
});
|
|
111
|
+
});
|