@zaip-ai/cli 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/services/agent-adapters.js +1 -1
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-adapters.test.js +2 -1
- package/dist/services/agent-adapters.test.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +89 -7
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-rules.d.ts +1 -1
- package/dist/services/codex-rules.d.ts.map +1 -1
- package/dist/services/codex-rules.js +7 -0
- package/dist/services/codex-rules.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +1 -0
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/runtime-template.test.js +31 -7
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +7 -3
- package/dist/services/template-manifest.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/config/agents/catalog.yaml +7 -7
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +8 -8
- package/templates/.agents/dashboard/.zaip-managed.json +373 -205
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DxR_pgSV.js → CostCalculationGuidePage-ovxurkIk.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-4jZLTWE_.js → DashboardHelpDialog-BgVgrfhQ.js} +240 -86
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CKcsqb-r.js → PricingSettingsDialog-vSvvOHQp.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-DmmJD2Th.js → ProjectSettingsPage-zH758vfs.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-DLn-Mz2M.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-CaKwQP43.css → TraceabilityWorkspace-DvvavDLY.css} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DKwP1stV.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-PoJA2PI1.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-C0fj2uU9.js → icons-vendor-B_lDDHn1.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-B31GMG5O.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-CZQlsLV9.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-BEsJ-FYH.js → react-vendor-B3TJrD4O.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-B6y6Gw12.js → traceability-7f1j5wx3.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +7 -7
- package/templates/.agents/dashboard/apps/frontend/playwright.dom.config.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +132 -245
- package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +0 -21
- package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +9 -0
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.dom.e2e.ts +56 -0
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +18 -1
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +75 -8
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +25 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -9
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +4 -4
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +7 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +20 -8
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.ts +21 -0
- package/templates/.agents/dashboard/apps/frontend/src/styles.css +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +6 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +31 -27
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.test.ts +163 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.ts +136 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-operations-detail-export.ts +76 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.test.ts +23 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.ts +27 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +38 -14
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionPanel.tsx +60 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +191 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.loading.test.ts +14 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts +18 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +18 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorLoadErrors.tsx +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +47 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +50 -58
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.test.ts +132 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.tsx +70 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +128 -138
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +17 -67
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +2 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +3 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-page-range.ts +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +16 -4
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +37 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +44 -8
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +6 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +20 -3
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.test.ts +54 -0
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +247 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +39 -13
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +107 -2
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.macro-metrics.test.ts +55 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +20 -28
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +162 -165
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +127 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +13 -46
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.test.tsx +43 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.tsx +181 -0
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +4 -2
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +13 -0
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.test.ts +18 -0
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.ts +30 -0
- package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +8 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -5
- 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 +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/operations-date-filters.css +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +21 -11
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.css +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +8 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/server/metric-coverage.ts +1 -0
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +527 -335
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +501 -309
- package/templates/.agents/dashboard/packages/local-runtime/gitignore.template +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +3 -3
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +25 -15
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +527 -335
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +34 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +15 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/server-classification-page.test.ts +87 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.test.ts +44 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.ts +125 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +66 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.test.ts +61 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-run-projections.test.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +97 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +91 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +36 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +98 -123
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +111 -135
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-artifact-counts.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +63 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +109 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +497 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-fast-page-parity.test-support.ts +65 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.test.ts +176 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.ts +119 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +41 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.test.ts +16 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.ts +29 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +355 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +121 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-timing.ts +27 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +15 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.test.ts +223 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +304 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +23 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +89 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +227 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +691 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +81 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +440 -863
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1120 -1086
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +129 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.test.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +116 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +146 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +165 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +140 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +188 -299
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +51 -70
- package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +5 -2
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-loading.spec.ts +142 -0
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-pagination.spec.ts +232 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +743 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +183 -210
- package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
- package/templates/.agents/requirements/autonomous-assurance.md +6 -6
- 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 +3 -3
- package/templates/.agents/requirements/kanban-dashboard.md +10 -2
- 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 +4 -4
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/dashboard-ui-consistency.md +14 -0
- package/templates/.agents/rules/frontend-lite.md +4 -4
- package/templates/.agents/rules/run-lifecycle-closure.md +4 -4
- package/templates/.agents/runtime/bin/zaip.mjs +1137 -1037
- package/templates/.agents/runtime/checksums.sha256 +2 -2
- package/templates/.agents/runtime/provenance.json +2 -2
- package/templates/.agents/skills/criar-pasta-obsidian/scripts/generate-obsidian-vault.test.mjs +20 -16
- package/templates/.agents/skills/zaip-skill-agent-catalog/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-agent-catalog/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +49 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/run-skill-tests.mjs +37 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +83 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -3
- package/templates/.agents/skills/zaip-skill-frontend/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +10 -10
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +27 -0
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +72 -22
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-explicit-recovery.mjs +223 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +42 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +53 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +5 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +22 -90
- package/templates/.agents/zaip-aios/INDEX.md +57 -32
- package/templates/.agents/zaip-aios/README.md +22 -12
- package/templates/.agents/zaip-aios/guides/02-requirements.md +5 -0
- package/templates/.agents/zaip-aios/guides/06-execucao.md +13 -4
- package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +7 -0
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +23 -0
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +6 -6
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +3 -0
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -3
- package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +5 -5
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +23 -0
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +44 -8
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +8 -14
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +5 -0
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +6 -6
- package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +8 -8
- package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +3 -2
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +77 -10
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +8 -3
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +5 -0
- package/templates/template-manifest.json +555 -170
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +0 -45
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +0 -7333
|
@@ -32,8 +32,6 @@ type DocumentDetail = {
|
|
|
32
32
|
export function AppOverlays({
|
|
33
33
|
costLocale,
|
|
34
34
|
documentDetail,
|
|
35
|
-
error,
|
|
36
|
-
failedArea,
|
|
37
35
|
helpOpen,
|
|
38
36
|
loadingArea,
|
|
39
37
|
operations,
|
|
@@ -46,7 +44,6 @@ export function AppOverlays({
|
|
|
46
44
|
closeDocument,
|
|
47
45
|
onCloseHelp,
|
|
48
46
|
onCloseTrace,
|
|
49
|
-
onDismissError,
|
|
50
47
|
onDismissReconciliation,
|
|
51
48
|
onOpenDocument,
|
|
52
49
|
onOpenTrace,
|
|
@@ -54,13 +51,10 @@ export function AppOverlays({
|
|
|
54
51
|
onOpenTraceMacro,
|
|
55
52
|
onRefreshCancel,
|
|
56
53
|
onRefreshFromDialog,
|
|
57
|
-
onRetry,
|
|
58
54
|
setTraceLink,
|
|
59
55
|
}: {
|
|
60
56
|
costLocale: CostLocale;
|
|
61
57
|
documentDetail: DocumentDetail | null;
|
|
62
|
-
error: string | null;
|
|
63
|
-
failedArea: LoadingArea | null;
|
|
64
58
|
helpOpen: boolean;
|
|
65
59
|
loadingArea: LoadingArea | null;
|
|
66
60
|
operations: OperationsProjection;
|
|
@@ -76,7 +70,6 @@ export function AppOverlays({
|
|
|
76
70
|
closeDocument: () => void;
|
|
77
71
|
onCloseHelp: () => void;
|
|
78
72
|
onCloseTrace: () => void;
|
|
79
|
-
onDismissError: () => void;
|
|
80
73
|
onDismissReconciliation: () => void;
|
|
81
74
|
onOpenDocument: (kind: "prd" | "spec", id: string) => void;
|
|
82
75
|
onOpenTrace: (taskId: string) => void;
|
|
@@ -84,24 +77,10 @@ export function AppOverlays({
|
|
|
84
77
|
onOpenTraceMacro: (label: "PRD" | "SPEC", id: string) => void;
|
|
85
78
|
onRefreshCancel: () => void;
|
|
86
79
|
onRefreshFromDialog: (reconcileOpenWork: boolean) => void;
|
|
87
|
-
onRetry: () => void;
|
|
88
80
|
setTraceLink: (value: null) => void;
|
|
89
81
|
}) {
|
|
90
82
|
return (
|
|
91
83
|
<>
|
|
92
|
-
{error ? (
|
|
93
|
-
<div aria-live="assertive" className="app-warning" role="alert">
|
|
94
|
-
<span>{error}</span>
|
|
95
|
-
{failedArea ? (
|
|
96
|
-
<button onClick={onRetry} type="button">
|
|
97
|
-
{costLocale === "pt-BR" ? "Tentar novamente" : "Try again"}
|
|
98
|
-
</button>
|
|
99
|
-
) : null}
|
|
100
|
-
<button onClick={onDismissError} type="button">
|
|
101
|
-
×
|
|
102
|
-
</button>
|
|
103
|
-
</div>
|
|
104
|
-
) : null}
|
|
105
84
|
{showTrace ? null : traceLoadingTaskId ? (
|
|
106
85
|
<TaskTraceLoadingPanel locale={costLocale} taskId={traceLoadingTaskId} />
|
|
107
86
|
) : trace ? (
|
|
@@ -35,6 +35,7 @@ type DashboardAlternateContentProps = {
|
|
|
35
35
|
onLoadingChange: (loading: boolean) => void;
|
|
36
36
|
onLocaleChange: (locale: CostLocale) => void;
|
|
37
37
|
onOpenTrace: (taskId: string) => void;
|
|
38
|
+
onLoadMoreTraceTasks: (loadAll?: boolean) => Promise<unknown>;
|
|
38
39
|
onRefresh: () => void;
|
|
39
40
|
onRetry: () => void;
|
|
40
41
|
onSelectTraceTask: (taskId: string) => void;
|
|
@@ -44,6 +45,8 @@ type DashboardAlternateContentProps = {
|
|
|
44
45
|
selectedTraceTaskId: string;
|
|
45
46
|
trace: TaskTrace | null;
|
|
46
47
|
traceLoadingTaskId: string | null;
|
|
48
|
+
traceTasksHasMore: boolean;
|
|
49
|
+
traceTasksLoading: boolean;
|
|
47
50
|
traceTasks: OperationsProjection["tasks"];
|
|
48
51
|
};
|
|
49
52
|
|
|
@@ -64,6 +67,7 @@ export function renderDashboardAlternateContent({
|
|
|
64
67
|
onLoadingChange,
|
|
65
68
|
onLocaleChange,
|
|
66
69
|
onOpenTrace,
|
|
70
|
+
onLoadMoreTraceTasks,
|
|
67
71
|
onRefresh,
|
|
68
72
|
onRetry,
|
|
69
73
|
onSelectTraceTask,
|
|
@@ -73,6 +77,8 @@ export function renderDashboardAlternateContent({
|
|
|
73
77
|
selectedTraceTaskId,
|
|
74
78
|
trace,
|
|
75
79
|
traceLoadingTaskId,
|
|
80
|
+
traceTasksHasMore,
|
|
81
|
+
traceTasksLoading,
|
|
76
82
|
traceTasks,
|
|
77
83
|
}: DashboardAlternateContentProps) {
|
|
78
84
|
if (dashboardView === "cost-monitor") {
|
|
@@ -118,9 +124,12 @@ export function renderDashboardAlternateContent({
|
|
|
118
124
|
onOpenChange={onOpenTraceChange}
|
|
119
125
|
onOpenPrd={(prdId) => onOpenTraceMacro("PRD", prdId)}
|
|
120
126
|
onOpenSpec={(specId) => onOpenTraceMacro("SPEC", specId)}
|
|
127
|
+
onLoadMoreTasks={onLoadMoreTraceTasks}
|
|
121
128
|
onSelectTask={onSelectTraceTask}
|
|
122
129
|
selectedTaskId={selectedTraceTaskId}
|
|
123
130
|
tasks={traceTasks.length > 0 ? traceTasks : operations.tasks}
|
|
131
|
+
hasMoreTasks={traceTasksHasMore}
|
|
132
|
+
isLoadingTasks={traceTasksLoading}
|
|
124
133
|
trace={trace}
|
|
125
134
|
/>
|
|
126
135
|
</Suspense>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { expect, test } from "@playwright/test";
|
|
2
|
+
|
|
3
|
+
test("opens every task from a preselected traceability combobox and preserves search and keyboard selection", async ({
|
|
4
|
+
page,
|
|
5
|
+
}) => {
|
|
6
|
+
const operations = page.waitForResponse(
|
|
7
|
+
(response) =>
|
|
8
|
+
response.status() === 200 &&
|
|
9
|
+
response.url().includes("/api/v2/operations") &&
|
|
10
|
+
response.url().includes("scope=quick"),
|
|
11
|
+
);
|
|
12
|
+
await page.goto("/?token=e2e-token");
|
|
13
|
+
await operations;
|
|
14
|
+
|
|
15
|
+
const traceabilityButton = page
|
|
16
|
+
.getByRole("navigation", { name: "Áreas do dashboard" })
|
|
17
|
+
.getByRole("button", { name: /Rastreabilidade/ });
|
|
18
|
+
await traceabilityButton.click();
|
|
19
|
+
await expect(traceabilityButton).toHaveAttribute("aria-current", "page");
|
|
20
|
+
|
|
21
|
+
const taskSelector = page.getByRole("combobox", { name: "Buscar task por nome ou ID" });
|
|
22
|
+
const taskOptions = page
|
|
23
|
+
.getByRole("listbox", { name: "Buscar task por nome ou ID" })
|
|
24
|
+
.getByRole("option");
|
|
25
|
+
const taskList = page.getByRole("listbox", { name: "Buscar task por nome ou ID" });
|
|
26
|
+
await expect(taskSelector).toBeVisible();
|
|
27
|
+
await expect(taskSelector).toHaveAttribute("aria-expanded", "false");
|
|
28
|
+
|
|
29
|
+
const selectedTitle = await taskSelector.inputValue();
|
|
30
|
+
await taskSelector.focus();
|
|
31
|
+
await expect(taskSelector).toHaveAttribute("aria-expanded", "true");
|
|
32
|
+
const initialTaskCount = await taskOptions.count();
|
|
33
|
+
expect(initialTaskCount).toBe(12);
|
|
34
|
+
await taskList.evaluate((element) => {
|
|
35
|
+
element.scrollTop = element.scrollHeight;
|
|
36
|
+
element.dispatchEvent(new Event("scroll", { bubbles: true }));
|
|
37
|
+
});
|
|
38
|
+
await expect.poll(() => taskOptions.count()).toBeGreaterThan(initialTaskCount);
|
|
39
|
+
|
|
40
|
+
await taskSelector.fill(selectedTitle);
|
|
41
|
+
await expect(taskOptions).toHaveCount(1);
|
|
42
|
+
|
|
43
|
+
await taskSelector.click();
|
|
44
|
+
await expect(taskOptions).toHaveCount(initialTaskCount);
|
|
45
|
+
const thirdOptionId = await taskOptions.nth(2).getAttribute("id");
|
|
46
|
+
await taskSelector.press("ArrowDown");
|
|
47
|
+
await taskSelector.press("ArrowDown");
|
|
48
|
+
const activeOptionId = await taskSelector.getAttribute("aria-activedescendant");
|
|
49
|
+
expect(activeOptionId).toBe(thirdOptionId);
|
|
50
|
+
const activeOption = page.locator(`[id="${activeOptionId}"]`);
|
|
51
|
+
const activeTitle = await activeOption.locator("strong").innerText();
|
|
52
|
+
|
|
53
|
+
await taskSelector.press("Enter");
|
|
54
|
+
await expect(taskSelector).toHaveAttribute("aria-expanded", "false");
|
|
55
|
+
await expect(taskSelector).toHaveValue(activeTitle);
|
|
56
|
+
});
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
filterTraceabilityTasks,
|
|
5
|
+
traceabilityTaskOptionId,
|
|
6
|
+
visibleTraceabilityTasks,
|
|
7
|
+
} from "./TraceabilityWorkspace.js";
|
|
4
8
|
|
|
5
9
|
describe("TraceabilityWorkspace task search", () => {
|
|
6
10
|
const tasks = [
|
|
@@ -16,6 +20,15 @@ describe("TraceabilityWorkspace task search", () => {
|
|
|
16
20
|
expect(filterTraceabilityTasks(tasks, "missing")).toEqual([]);
|
|
17
21
|
});
|
|
18
22
|
|
|
23
|
+
it("shows every task when the selected combobox is opened", () => {
|
|
24
|
+
expect(
|
|
25
|
+
visibleTraceabilityTasks(tasks, "Preparar lançamento", true).map((task) => task.id),
|
|
26
|
+
).toEqual(["TASK-ALPHA", "TASK-BETA"]);
|
|
27
|
+
expect(
|
|
28
|
+
visibleTraceabilityTasks(tasks, "Preparar lançamento", false).map((task) => task.id),
|
|
29
|
+
).toEqual(["TASK-ALPHA"]);
|
|
30
|
+
});
|
|
31
|
+
|
|
19
32
|
it("keeps selection and keyboard interaction accessible", () => {
|
|
20
33
|
const source = readFileSync(new URL("TraceabilityWorkspace.tsx", import.meta.url), "utf8");
|
|
21
34
|
|
|
@@ -26,6 +39,10 @@ describe("TraceabilityWorkspace task search", () => {
|
|
|
26
39
|
expect(source).toContain('event.key === "Enter"');
|
|
27
40
|
expect(source).toContain('event.key === "ArrowDown"');
|
|
28
41
|
expect(source).toContain("setActiveIndex");
|
|
42
|
+
expect(source).toContain("onClick={() => openAllTasks()}");
|
|
43
|
+
expect(source).toContain("onFocus={() => openAllTasks()}");
|
|
44
|
+
expect(source).toContain("openAllTasks(false)");
|
|
45
|
+
expect(source).toContain("setShowAllTasks(true)");
|
|
29
46
|
expect(source).toContain("aria-activedescendant");
|
|
30
47
|
expect(source).toContain("traceabilityTaskOptionId(activeTaskId)");
|
|
31
48
|
expect(source).toContain('role="status"');
|
|
@@ -2,9 +2,11 @@ import type { OperationsProjection } from "@zaip-ai/dashboard-operations/contrac
|
|
|
2
2
|
import type { TaskTrace } from "@zaip-ai/dashboard-traceability/contracts";
|
|
3
3
|
import { TaskTracePanel } from "@zaip-ai/dashboard-traceability/react";
|
|
4
4
|
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
import { nextTraceabilityVisibleCount } from "./traceability-task-pagination.js";
|
|
5
6
|
import "./traceability-workspace.css";
|
|
6
7
|
|
|
7
8
|
type TraceabilityTask = OperationsProjection["tasks"][number];
|
|
9
|
+
export const traceabilityTaskInitialBatchSize = 12;
|
|
8
10
|
|
|
9
11
|
export function filterTraceabilityTasks(
|
|
10
12
|
tasks: readonly TraceabilityTask[],
|
|
@@ -17,6 +19,14 @@ export function filterTraceabilityTasks(
|
|
|
17
19
|
);
|
|
18
20
|
}
|
|
19
21
|
|
|
22
|
+
export function visibleTraceabilityTasks(
|
|
23
|
+
tasks: readonly TraceabilityTask[],
|
|
24
|
+
query: string,
|
|
25
|
+
showAllTasks: boolean,
|
|
26
|
+
): TraceabilityTask[] {
|
|
27
|
+
return showAllTasks ? [...tasks] : filterTraceabilityTasks(tasks, query);
|
|
28
|
+
}
|
|
29
|
+
|
|
20
30
|
export function traceabilityTaskOptionId(taskId: string): string {
|
|
21
31
|
return `traceability-task-option-${taskId}`;
|
|
22
32
|
}
|
|
@@ -24,6 +34,9 @@ export function traceabilityTaskOptionId(taskId: string): string {
|
|
|
24
34
|
export function TraceabilityWorkspace({
|
|
25
35
|
locale,
|
|
26
36
|
loadingTaskId,
|
|
37
|
+
hasMoreTasks,
|
|
38
|
+
isLoadingTasks,
|
|
39
|
+
onLoadMoreTasks,
|
|
27
40
|
onSelectTask,
|
|
28
41
|
onOpenChange,
|
|
29
42
|
onOpenPrd,
|
|
@@ -34,6 +47,9 @@ export function TraceabilityWorkspace({
|
|
|
34
47
|
}: {
|
|
35
48
|
locale: "pt-BR" | "en-US";
|
|
36
49
|
loadingTaskId: string | null;
|
|
50
|
+
hasMoreTasks: boolean;
|
|
51
|
+
isLoadingTasks: boolean;
|
|
52
|
+
onLoadMoreTasks: (loadAll?: boolean) => Promise<unknown>;
|
|
37
53
|
onSelectTask: (taskId: string) => void;
|
|
38
54
|
onOpenChange: (changeId: string) => void;
|
|
39
55
|
onOpenPrd: (prdId: string) => void;
|
|
@@ -48,11 +64,15 @@ export function TraceabilityWorkspace({
|
|
|
48
64
|
const selectedTask = sortedTasks.find((task) => task.id === selectedTaskId);
|
|
49
65
|
const [query, setQuery] = useState(() => selectedTask?.title ?? selectedTaskId);
|
|
50
66
|
const [isListOpen, setIsListOpen] = useState(false);
|
|
67
|
+
const [showAllTasks, setShowAllTasks] = useState(false);
|
|
51
68
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
69
|
+
const [visibleCount, setVisibleCount] = useState(traceabilityTaskInitialBatchSize);
|
|
52
70
|
const filteredTasks = useMemo(
|
|
53
|
-
() =>
|
|
54
|
-
[query, sortedTasks],
|
|
71
|
+
() => visibleTraceabilityTasks(sortedTasks, query, showAllTasks),
|
|
72
|
+
[query, showAllTasks, sortedTasks],
|
|
55
73
|
);
|
|
74
|
+
const visibleTasks = filteredTasks.slice(0, visibleCount);
|
|
75
|
+
const hasMoreVisibleTasks = visibleTasks.length < filteredTasks.length;
|
|
56
76
|
const searchInputId = "traceability-task-search";
|
|
57
77
|
const resultsId = "traceability-task-results";
|
|
58
78
|
const taskLabel = locale === "pt-BR" ? "Task selecionada" : "Selected task";
|
|
@@ -68,17 +88,42 @@ export function TraceabilityWorkspace({
|
|
|
68
88
|
const selectTask = (task: TraceabilityTask) => {
|
|
69
89
|
setQuery(task.title);
|
|
70
90
|
setIsListOpen(false);
|
|
91
|
+
setShowAllTasks(false);
|
|
71
92
|
onSelectTask(task.id);
|
|
72
93
|
};
|
|
73
94
|
|
|
95
|
+
const openAllTasks = (resetList = true) => {
|
|
96
|
+
setIsListOpen(true);
|
|
97
|
+
setShowAllTasks(true);
|
|
98
|
+
if (resetList) {
|
|
99
|
+
setActiveIndex(0);
|
|
100
|
+
setVisibleCount(traceabilityTaskInitialBatchSize);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const loadMoreTasks = (event: React.UIEvent<HTMLDivElement>) => {
|
|
105
|
+
const { clientHeight, scrollHeight, scrollTop } = event.currentTarget;
|
|
106
|
+
if (scrollTop + clientHeight < scrollHeight - 32) return;
|
|
107
|
+
if (hasMoreTasks) void onLoadMoreTasks();
|
|
108
|
+
if (visibleTasks.length < filteredTasks.length) {
|
|
109
|
+
setVisibleCount((current) =>
|
|
110
|
+
nextTraceabilityVisibleCount(
|
|
111
|
+
current,
|
|
112
|
+
filteredTasks.length,
|
|
113
|
+
traceabilityTaskInitialBatchSize,
|
|
114
|
+
),
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
74
119
|
const onSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
75
120
|
if (event.key === "ArrowDown") {
|
|
76
121
|
event.preventDefault();
|
|
77
|
-
|
|
78
|
-
setActiveIndex((index) => Math.min(index + 1, Math.max(0,
|
|
122
|
+
openAllTasks(false);
|
|
123
|
+
setActiveIndex((index) => Math.min(index + 1, Math.max(0, sortedTasks.length - 1)));
|
|
79
124
|
} else if (event.key === "ArrowUp") {
|
|
80
125
|
event.preventDefault();
|
|
81
|
-
|
|
126
|
+
openAllTasks(false);
|
|
82
127
|
setActiveIndex((index) => Math.max(0, index - 1));
|
|
83
128
|
} else if (event.key === "Enter" && isListOpen) {
|
|
84
129
|
const task = filteredTasks[activeIndex];
|
|
@@ -107,9 +152,16 @@ export function TraceabilityWorkspace({
|
|
|
107
152
|
onChange={(event) => {
|
|
108
153
|
setQuery(event.target.value);
|
|
109
154
|
setActiveIndex(0);
|
|
155
|
+
setShowAllTasks(false);
|
|
156
|
+
setVisibleCount(traceabilityTaskInitialBatchSize);
|
|
110
157
|
setIsListOpen(true);
|
|
158
|
+
// Do not turn a keystroke into a full repository walk. More
|
|
159
|
+
// candidates are acquired only by explicit list scrolling; a
|
|
160
|
+
// server-side search can be wired here when its bounded query
|
|
161
|
+
// contract is available.
|
|
111
162
|
}}
|
|
112
|
-
|
|
163
|
+
onClick={() => openAllTasks()}
|
|
164
|
+
onFocus={() => openAllTasks()}
|
|
113
165
|
onKeyDown={onSearchKeyDown}
|
|
114
166
|
role="combobox"
|
|
115
167
|
type="search"
|
|
@@ -120,10 +172,11 @@ export function TraceabilityWorkspace({
|
|
|
120
172
|
aria-label={searchLabel}
|
|
121
173
|
className="traceability-task-results"
|
|
122
174
|
id={resultsId}
|
|
175
|
+
onScroll={loadMoreTasks}
|
|
123
176
|
role="listbox"
|
|
124
177
|
>
|
|
125
178
|
{filteredTasks.length > 0 ? (
|
|
126
|
-
|
|
179
|
+
visibleTasks.map((task, index) => (
|
|
127
180
|
<div key={task.id} role="presentation">
|
|
128
181
|
<button
|
|
129
182
|
aria-selected={task.id === selectedTaskId}
|
|
@@ -134,7 +187,6 @@ export function TraceabilityWorkspace({
|
|
|
134
187
|
type="button"
|
|
135
188
|
>
|
|
136
189
|
<strong>{task.title}</strong>
|
|
137
|
-
<small>{task.id}</small>
|
|
138
190
|
</button>
|
|
139
191
|
</div>
|
|
140
192
|
))
|
|
@@ -145,6 +197,21 @@ export function TraceabilityWorkspace({
|
|
|
145
197
|
)}
|
|
146
198
|
</div>
|
|
147
199
|
) : null}
|
|
200
|
+
{isListOpen && filteredTasks.length > 0 ? (
|
|
201
|
+
<p aria-live="polite" className="traceability-task-pagination-status" role="status">
|
|
202
|
+
{isLoadingTasks
|
|
203
|
+
? locale === "pt-BR"
|
|
204
|
+
? "Carregando mais tasks…"
|
|
205
|
+
: "Loading more tasks…"
|
|
206
|
+
: hasMoreVisibleTasks || hasMoreTasks
|
|
207
|
+
? locale === "pt-BR"
|
|
208
|
+
? `${visibleTasks.length} de ${filteredTasks.length} tasks exibidas. Role para carregar mais.`
|
|
209
|
+
: `${visibleTasks.length} of ${filteredTasks.length} tasks shown. Scroll to load more.`
|
|
210
|
+
: locale === "pt-BR"
|
|
211
|
+
? `${filteredTasks.length} tasks exibidas. Fim da lista.`
|
|
212
|
+
: `${filteredTasks.length} tasks shown. End of list.`}
|
|
213
|
+
</p>
|
|
214
|
+
) : null}
|
|
148
215
|
</div>
|
|
149
216
|
<small>
|
|
150
217
|
{locale === "pt-BR"
|
|
@@ -21,7 +21,7 @@ describe("DashboardApiClient reconciliation", () => {
|
|
|
21
21
|
vi.stubGlobal("fetch", fetchMock);
|
|
22
22
|
|
|
23
23
|
const pending = new DashboardApiClient("session").reconcileOpenWork();
|
|
24
|
-
const rejection = expect(pending).rejects.toThrow("
|
|
24
|
+
const rejection = expect(pending).rejects.toThrow("180 segundos");
|
|
25
25
|
await vi.advanceTimersByTimeAsync(30_000);
|
|
26
26
|
expect(fetchMock.mock.calls[0]?.[1].signal?.aborted).toBe(false);
|
|
27
27
|
|
|
@@ -116,6 +116,30 @@ describe("DashboardApiClient cost monitor", () => {
|
|
|
116
116
|
expect(requestPath).not.toContain("run_kind=");
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
+
it("sends the Work List stage through the canonical status query parameter", async () => {
|
|
120
|
+
vi.stubGlobal("window", globalThis);
|
|
121
|
+
const fetchMock = vi.fn((_path: string) =>
|
|
122
|
+
Promise.resolve(
|
|
123
|
+
new Response(JSON.stringify({ rows: [] }), {
|
|
124
|
+
headers: { "content-type": "application/json" },
|
|
125
|
+
status: 200,
|
|
126
|
+
}),
|
|
127
|
+
),
|
|
128
|
+
);
|
|
129
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
130
|
+
|
|
131
|
+
await new DashboardApiClient("session").sqliteViewPage("operations_work_list", undefined, {
|
|
132
|
+
limit: 10,
|
|
133
|
+
origin: "standalone",
|
|
134
|
+
status: "executing",
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const requestPath = String(fetchMock.mock.calls[0]?.[0]);
|
|
138
|
+
expect(requestPath).toContain("status=executing");
|
|
139
|
+
expect(requestPath).toContain("origin=standalone");
|
|
140
|
+
expect(requestPath).not.toContain("stage=executing");
|
|
141
|
+
});
|
|
142
|
+
|
|
119
143
|
it("adds fresh only to an explicit bootstrap aggregate read", async () => {
|
|
120
144
|
vi.stubGlobal("window", globalThis);
|
|
121
145
|
const fetchMock = vi.fn((_path: string | URL | Request) =>
|
|
@@ -10,7 +10,6 @@ import type {
|
|
|
10
10
|
TaskDetailProjection,
|
|
11
11
|
} from "@zaip-ai/dashboard-operations/contracts";
|
|
12
12
|
import type { TaskTrace } from "@zaip-ai/dashboard-traceability/contracts";
|
|
13
|
-
|
|
14
13
|
export interface ReconciliationBlockedItem {
|
|
15
14
|
id: string;
|
|
16
15
|
reason: string | null;
|
|
@@ -56,7 +55,6 @@ export interface SqliteViewPage {
|
|
|
56
55
|
totals?: Record<string, unknown>;
|
|
57
56
|
rows: Array<Record<string, unknown>>;
|
|
58
57
|
}
|
|
59
|
-
|
|
60
58
|
export type OperationsScope = "quick" | "overview" | "detail";
|
|
61
59
|
export type WorkBoardStage =
|
|
62
60
|
| "definition"
|
|
@@ -252,6 +250,7 @@ export class DashboardApiClient {
|
|
|
252
250
|
origin?: string;
|
|
253
251
|
workType?: string;
|
|
254
252
|
priority?: string;
|
|
253
|
+
kind?: string;
|
|
255
254
|
} = {},
|
|
256
255
|
signal?: AbortSignal,
|
|
257
256
|
): Promise<SqliteViewPage> {
|
|
@@ -267,6 +266,7 @@ export class DashboardApiClient {
|
|
|
267
266
|
if (options.origin) query.set("origin", options.origin);
|
|
268
267
|
if (options.workType) query.set("workType", options.workType);
|
|
269
268
|
if (options.priority) query.set("priority", options.priority);
|
|
269
|
+
if (options.kind) query.set("kind", options.kind);
|
|
270
270
|
return this.get(withPeriod(`/api/v2/sqlite-views?${query.toString()}`, period), signal);
|
|
271
271
|
}
|
|
272
272
|
|
|
@@ -455,11 +455,9 @@ export class DashboardApiClient {
|
|
|
455
455
|
spec(specId: string): Promise<SpecDetailProjection> {
|
|
456
456
|
return this.get(dashboardApiPaths.spec(specId));
|
|
457
457
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
return this.get(dashboardApiPaths.taskTrace(taskId));
|
|
458
|
+
taskTrace(taskId: string, signal?: AbortSignal): Promise<TaskTrace> {
|
|
459
|
+
return this.get(dashboardApiPaths.taskTrace(taskId), signal);
|
|
461
460
|
}
|
|
462
|
-
|
|
463
461
|
pricing(): Promise<PricingCatalog> {
|
|
464
462
|
return this.get("/api/v2/pricing");
|
|
465
463
|
}
|
|
@@ -593,9 +591,9 @@ function operationsPageParams(
|
|
|
593
591
|
}
|
|
594
592
|
|
|
595
593
|
export const dashboardRequestTimeoutMs = 60_000;
|
|
596
|
-
// The
|
|
597
|
-
// transport margin
|
|
598
|
-
export const reconciliationRequestTimeoutMs =
|
|
594
|
+
// The command may use two minutes plus a projection rebuild; keep enough
|
|
595
|
+
// transport margin to avoid false browser failures after healthy reconciliation.
|
|
596
|
+
export const reconciliationRequestTimeoutMs = 180_000;
|
|
599
597
|
|
|
600
598
|
export async function fetchWithTimeout(
|
|
601
599
|
path: string,
|
|
@@ -94,12 +94,12 @@ describe("App-owned Operations period render", () => {
|
|
|
94
94
|
expect(css).toContain("prefers-reduced-motion: reduce");
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
it("
|
|
97
|
+
it("reserves the global gate for a period replacement, not secondary pages", () => {
|
|
98
98
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
99
99
|
expect(app).toContain("const globalLoadingPending =");
|
|
100
|
-
expect(app).toContain("
|
|
101
|
-
expect(app).toContain("entityPage.loading");
|
|
102
|
-
expect(app).toContain("Object.values(boardStates).some((state) => state.loading)");
|
|
100
|
+
expect(app).toContain("periodTransitionPending ||");
|
|
101
|
+
expect(app).not.toContain("entityPage.loading ||");
|
|
102
|
+
expect(app).not.toContain("Object.values(boardStates).some((state) => state.loading)");
|
|
103
103
|
expect(app).toContain("<PeriodTransitionShell pending={globalLoadingPending}>");
|
|
104
104
|
});
|
|
105
105
|
});
|
|
@@ -6,7 +6,7 @@ const source = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
|
6
6
|
describe("overview status page loading", () => {
|
|
7
7
|
it("requests a dedicated stage and kind page instead of reusing the mixed board page", () => {
|
|
8
8
|
expect(source).toContain("const loadOverviewStatusPage");
|
|
9
|
-
expect(source).toContain("
|
|
9
|
+
expect(source).toContain('kind: kind === "task" ? "all-tasks" : kind');
|
|
10
10
|
expect(source).toContain(
|
|
11
11
|
'kind === "task" ? page.tasks : kind === "spec" ? page.specs : page.prds',
|
|
12
12
|
);
|
|
@@ -44,6 +44,7 @@ describe("snapshot update banner semantics", () => {
|
|
|
44
44
|
it("presents a stale local snapshot as neutral status and reserves alert red for errors", () => {
|
|
45
45
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
46
46
|
const boundary = readFileSync(new URL("./AppLoadingBoundary.tsx", import.meta.url), "utf8");
|
|
47
|
+
const overlays = readFileSync(new URL("./AppOverlays.tsx", import.meta.url), "utf8");
|
|
47
48
|
const styles = readFileSync(new URL("./styles.css", import.meta.url), "utf8");
|
|
48
49
|
const snapshot = app.slice(
|
|
49
50
|
app.indexOf("const initialDataPending"),
|
|
@@ -70,7 +71,13 @@ describe("snapshot update banner semantics", () => {
|
|
|
70
71
|
expect(error).toContain('aria-live="assertive"');
|
|
71
72
|
expect(error).toContain('"Fechar erro"');
|
|
72
73
|
expect(error).toContain('"Dismiss error"');
|
|
74
|
+
expect(overlays).not.toContain('role="alert"');
|
|
75
|
+
expect(overlays).not.toContain('className="app-warning"');
|
|
76
|
+
expect(overlays).not.toContain("startupReconciliation");
|
|
77
|
+
expect(overlays).not.toContain('"Fechar aviso de reconciliação"');
|
|
78
|
+
expect(overlays).not.toContain('"Dismiss reconciliation notice"');
|
|
73
79
|
expect(styles).toContain(".app-snapshot-status {");
|
|
80
|
+
expect(styles).toContain(".app-refresh-status-close {");
|
|
74
81
|
expect(styles).toContain("background: rgba(8, 47, 73, 0.96);");
|
|
75
82
|
expect(styles).toContain(".app-warning.app-error {");
|
|
76
83
|
expect(styles).toContain("background: rgba(69, 16, 16, 0.96);");
|
|
@@ -48,15 +48,18 @@ describe("atomic Cost snapshot loading", () => {
|
|
|
48
48
|
expect(costSelection).not.toContain("loadOperationsDetails");
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
it("
|
|
51
|
+
it("never blocks the dashboard or starts a full snapshot for a paged Cost request", () => {
|
|
52
52
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
53
53
|
const globalGate = app.slice(
|
|
54
54
|
app.indexOf("const globalLoadingPending"),
|
|
55
55
|
app.indexOf("const renderedOperations"),
|
|
56
56
|
);
|
|
57
|
-
expect(app).toContain("const [
|
|
58
|
-
expect(globalGate).toContain("costSurfaceLoading");
|
|
59
|
-
expect(globalGate).toContain(
|
|
57
|
+
expect(app).toContain("const [, setCostSurfaceLoading] = useState(false);");
|
|
58
|
+
expect(globalGate).not.toContain("costSurfaceLoading");
|
|
59
|
+
expect(globalGate).not.toContain("operationsSurfaceLoading");
|
|
60
|
+
expect(globalGate).not.toContain("entityPage.loading");
|
|
61
|
+
expect(app).not.toContain("api.snapshot(currency, period)");
|
|
62
|
+
expect(app).not.toContain("useIdleCostPrefetch");
|
|
60
63
|
});
|
|
61
64
|
|
|
62
65
|
it("does not request Cost Monitor while the initial route is Operations", () => {
|
|
@@ -132,6 +135,12 @@ describe("atomic Cost snapshot loading", () => {
|
|
|
132
135
|
expect(effects).toContain("void refresh(false, false, true)");
|
|
133
136
|
});
|
|
134
137
|
|
|
138
|
+
it("does not reconcile open work automatically", () => {
|
|
139
|
+
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
140
|
+
expect(app).not.toContain("startupReconciliation");
|
|
141
|
+
expect(app).toContain("await refresh(false, reconcileOpenWork, !reconcileOpenWork)");
|
|
142
|
+
});
|
|
143
|
+
|
|
135
144
|
it("removes the global Cost detail request and keeps stale request guards", () => {
|
|
136
145
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
137
146
|
const costPage = readFileSync(
|
|
@@ -231,13 +240,16 @@ describe("atomic Cost snapshot loading", () => {
|
|
|
231
240
|
app.indexOf("const loadCostDetails"),
|
|
232
241
|
);
|
|
233
242
|
|
|
234
|
-
expect(boardHydration).toContain("
|
|
235
|
-
expect(boardHydration).toContain(
|
|
236
|
-
|
|
243
|
+
expect(boardHydration).toContain("offset += 3");
|
|
244
|
+
expect(boardHydration).toContain(
|
|
245
|
+
"await Promise.all(batch.map((stage) => loadMoreBoard(stage)))",
|
|
246
|
+
);
|
|
247
|
+
expect(boardHydration).toContain("window.requestIdleCallback(() => void hydrateBoard())");
|
|
248
|
+
expect(boardHydration).toContain("window.setTimeout(() => void hydrateBoard(), 0)");
|
|
237
249
|
expect(boardHydration).toContain("!boardInitialPageRef.current.has(stage)");
|
|
238
250
|
expect(boardHydration).toContain("boardInitialPageRef.current.add(stage)");
|
|
239
251
|
expect(boardHydration).toContain("!boardInFlightRef.current.has(stage)");
|
|
240
|
-
expect(boardHydration).toContain("
|
|
252
|
+
expect(boardHydration).toContain("boardInitialPageRef.current.add(stage)");
|
|
241
253
|
});
|
|
242
254
|
|
|
243
255
|
it("merges concurrent board pages without replacing rows from another stage", () => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { allSqliteExportPages } from "./sqlite-page-export.js";
|
|
3
|
+
|
|
4
|
+
describe("complete SQLite export", () => {
|
|
5
|
+
it("exports every filtered page, even when the visual page contains only ten rows", async () => {
|
|
6
|
+
const second = vi.fn().mockResolvedValue({
|
|
7
|
+
offset: 100,
|
|
8
|
+
total_count: 145,
|
|
9
|
+
has_more: false,
|
|
10
|
+
rows: Array.from({ length: 45 }, (_, id) => ({ id: `standalone-${id}` })),
|
|
11
|
+
});
|
|
12
|
+
const first = {
|
|
13
|
+
offset: 0,
|
|
14
|
+
total_count: 145,
|
|
15
|
+
has_more: true,
|
|
16
|
+
rows: Array.from({ length: 100 }, (_, id) => ({ id: `standalone-${id}` })),
|
|
17
|
+
};
|
|
18
|
+
const pages = [] as Array<readonly { id: string }[]>;
|
|
19
|
+
for await (const page of allSqliteExportPages(first, second)) pages.push(page);
|
|
20
|
+
|
|
21
|
+
expect(pages.flat()).toHaveLength(145);
|
|
22
|
+
expect(second).toHaveBeenCalledWith(100);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("keeps the active PRD or standalone-task kind in the export source", async () => {
|
|
26
|
+
const source = await import("node:fs/promises").then(({ readFile }) =>
|
|
27
|
+
readFile(new URL("./use-operations-detail-export.ts", import.meta.url), "utf8"),
|
|
28
|
+
);
|
|
29
|
+
expect(source).toContain('source === "operations_work_list" && filters.kind');
|
|
30
|
+
expect(source).toContain("limit: 100");
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type SqliteExportPage<Row extends Record<string, unknown>> = {
|
|
2
|
+
offset: number;
|
|
3
|
+
total_count: number;
|
|
4
|
+
has_more: boolean;
|
|
5
|
+
rows: readonly Row[];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/** Export transport deliberately follows every server page, unlike the UI. */
|
|
9
|
+
export async function* allSqliteExportPages<Row extends Record<string, unknown>>(
|
|
10
|
+
firstPage: SqliteExportPage<Row>,
|
|
11
|
+
loadPage: (offset: number) => Promise<SqliteExportPage<Row>>,
|
|
12
|
+
): AsyncGenerator<readonly Row[]> {
|
|
13
|
+
let page = firstPage;
|
|
14
|
+
while (true) {
|
|
15
|
+
if (page.rows.length === 0) return;
|
|
16
|
+
yield page.rows;
|
|
17
|
+
const nextOffset = page.offset + page.rows.length;
|
|
18
|
+
if (!page.has_more || nextOffset >= page.total_count) return;
|
|
19
|
+
page = await loadPage(nextOffset);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -438,6 +438,25 @@ select:focus-visible {
|
|
|
438
438
|
font-size: 0.78rem;
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
+
.app-refresh-status-close {
|
|
442
|
+
flex: 0 0 auto;
|
|
443
|
+
align-self: flex-start;
|
|
444
|
+
border: 0;
|
|
445
|
+
border-radius: 6px;
|
|
446
|
+
padding: 0 5px;
|
|
447
|
+
color: #cbd5e1;
|
|
448
|
+
background: transparent;
|
|
449
|
+
cursor: pointer;
|
|
450
|
+
font-size: 1.25rem;
|
|
451
|
+
line-height: 1;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.app-refresh-status-close:hover,
|
|
455
|
+
.app-refresh-status-close:focus-visible {
|
|
456
|
+
color: #f8fafc;
|
|
457
|
+
background: rgba(148, 163, 184, 0.16);
|
|
458
|
+
}
|
|
459
|
+
|
|
441
460
|
.app-reconciliation-result {
|
|
442
461
|
position: fixed;
|
|
443
462
|
z-index: 80;
|