@zaip-ai/cli 1.0.8 → 1.3.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 +1 -1
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.js +1 -1
- package/dist/services/agent-adapters.js +2 -2
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-adapters.test.js +5 -0
- package/dist/services/agent-adapters.test.js.map +1 -1
- package/dist/services/logger.test.js +2 -2
- package/dist/services/runtime-template.test.js +6 -6
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +5 -0
- package/dist/services/template-manifest.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/architecture/software-architecture.md +131 -0
- package/templates/.agents/branding/brandbook.docx +0 -0
- package/templates/.agents/branding/brandbook.md +60 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
- package/templates/.agents/dashboard/.tmp-run-list.json +254 -0
- package/templates/.agents/dashboard/.zaip-managed.json +252 -136
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-Z60df2r-.js → CostCalculationGuidePage-DxR_pgSV.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-4jZLTWE_.js +2156 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-Coc6pA-1.js → PricingSettingsDialog-CKcsqb-r.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BomxqCBU.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-DmmJD2Th.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DFBuc_qp.js → icons-vendor-C0fj2uU9.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-CCQOHdVI.js → react-vendor-BEsJ-FYH.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-pC2_0J8x.js → traceability-B6y6Gw12.js} +1 -1
- 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/App.tsx +204 -32
- package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +11 -11
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +14 -7
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +4 -2
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +14 -11
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +19 -4
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +24 -2
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +22 -1
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +36 -26
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +40 -6
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +39 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +89 -23
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +219 -29
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +61 -7
- package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +3 -6
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +3 -4
- package/templates/.agents/dashboard/apps/frontend/vite.config.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +89 -19
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +31 -16
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +43 -14
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +5 -5
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +67 -42
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +115 -39
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +188 -38
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +75 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +147 -58
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +5 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +2 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +2 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +18 -7
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +95 -9
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +29 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +0 -24
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +225 -424
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +24 -15
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +6 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-monitor-projection-agents.test.ts +31 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/source-size-cost-server/build-cost-summary-projection-duration.test.ts +414 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +26 -23
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +31 -11
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +3 -1
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +51 -21
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +47 -5
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +1 -4
- package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +32 -10
- package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +9 -3
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +13 -5
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +12 -4
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +1 -4
- package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +1 -2
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +385 -4
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +481 -61
- package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -1
- package/templates/.agents/dashboard/modules/operations/src/react/export/xlsx-runtime-e2e.test.ts +248 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +4 -4
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +6 -4
- package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +4 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +46 -6
- package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -4
- package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +82 -6
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +19 -7
- package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +4 -1
- package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +11 -5
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +152 -149
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +7333 -0
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +149 -146
- package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +15 -7
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +44 -13
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +5 -2
- package/templates/.agents/dashboard/packages/local-runtime/scripts/source-size-runtime-scripts/sqlite-read-model-fixture.mjs +397 -0
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +472 -145
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +15 -3
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +129 -31
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +153 -150
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +6 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +3 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +55 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +23 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +19 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +132 -9
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +126 -60
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +16 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1861 -350
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1218 -352
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +119 -42
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +45 -20
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +7 -5
- package/templates/.agents/design/.zaip-managed.json +3 -3
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/growth/estrategia-bootstrap-90-dias.md +169 -0
- package/templates/.agents/growth/strategy.md +27 -0
- package/templates/.agents/marketing/estrategia-marketing-zaip-90-dias.md +197 -0
- package/templates/.agents/marketing/strategy.md +29 -0
- package/templates/.agents/requirements/autonomous-assurance.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 +1 -1
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +30 -29
- 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/sales/playbook.md +32 -0
- package/templates/.agents/sales/roteiro-comercial-zaip.md +252 -0
- package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +9 -2
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +39 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +1 -1
- package/templates/.agents/skills/zaip-skill-enforce-architecture/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +39 -82
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +13 -8
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +44 -14
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +19 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +29 -5
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/source-size-telemetry/model-identity-reconciliation.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +28 -5
- package/templates/.agents/zaip-aios/INDEX.md +10 -0
- package/templates/.agents/zaip-aios/README.md +2 -1
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +76 -0
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +72 -0
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +330 -0
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +52 -0
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +69 -0
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +483 -0
- package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +85 -0
- package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +18 -0
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +44 -0
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +167 -0
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +144 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/lifecycles-task-spec-prd.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/prd-lifecycle.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/spec-lifecycle.png +0 -0
- package/templates/.agents/zaip-aios/guides/assets/diagrams/task-lifecycle.png +0 -0
- package/templates/template-manifest.json +313 -177
- package/templates/.agents/dashboard/apps/frontend/dist/assets/DashboardHelpDialog-Cs6dzDmW.js +0 -1505
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +0 -2
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
OperationsPageFilters,
|
|
35
35
|
PricingCatalog,
|
|
36
36
|
ReconciliationResult,
|
|
37
|
+
SqliteViewName,
|
|
37
38
|
WorkBoardStage,
|
|
38
39
|
} from "./dashboard-api.js";
|
|
39
40
|
import { DashboardApiClient } from "./dashboard-api.js";
|
|
@@ -52,19 +53,40 @@ import "./loading-feedback.css";
|
|
|
52
53
|
import "./period-transition-overlay.css";
|
|
53
54
|
|
|
54
55
|
type BoardStageState = { loading: boolean; error: string | null };
|
|
56
|
+
type OperationsExportView =
|
|
57
|
+
| "work-kanban"
|
|
58
|
+
| "work-list"
|
|
59
|
+
| "changes"
|
|
60
|
+
| "decisions"
|
|
61
|
+
| "executions"
|
|
62
|
+
| "runs"
|
|
63
|
+
| "conversations"
|
|
64
|
+
| "daily"
|
|
65
|
+
| "monthly"
|
|
66
|
+
| "yearly";
|
|
55
67
|
type OverviewStatusKind = "task" | "spec" | "prd";
|
|
56
68
|
type OverviewClassification = "lite" | "standard" | "critical" | "empty" | "structured" | "rework";
|
|
57
69
|
type OverviewStatusPage = {
|
|
58
|
-
items:
|
|
70
|
+
items:
|
|
71
|
+
| OperationsProjection["tasks"]
|
|
72
|
+
| OperationsProjection["specs"]
|
|
73
|
+
| OperationsProjection["prds"];
|
|
59
74
|
total: number;
|
|
60
75
|
loading: boolean;
|
|
61
76
|
error: string | null;
|
|
62
77
|
};
|
|
63
|
-
type OverviewStatusPages = Partial<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
`${
|
|
78
|
+
type OverviewStatusPages = Partial<
|
|
79
|
+
Record<`${WorkBoardStage}:${OverviewStatusKind}`, OverviewStatusPage>
|
|
80
|
+
>;
|
|
81
|
+
const overviewStatusPageKey = (stage: WorkBoardStage, kind: OverviewStatusKind) =>
|
|
82
|
+
`${stage}:${kind}` as const;
|
|
83
|
+
type OverviewClassificationPages = Partial<
|
|
84
|
+
Record<`${OverviewStatusKind}:${OverviewClassification}`, OverviewStatusPage>
|
|
85
|
+
>;
|
|
86
|
+
const overviewClassificationPageKey = (
|
|
87
|
+
kind: OverviewStatusKind,
|
|
88
|
+
classification: OverviewClassification,
|
|
89
|
+
) => `${kind}:${classification}` as const;
|
|
68
90
|
const initialWorkBoardStages: readonly WorkBoardStage[] = [
|
|
69
91
|
"definition",
|
|
70
92
|
"planning",
|
|
@@ -93,9 +115,75 @@ function dailyCostSeed(
|
|
|
93
115
|
currency: "BRL" | "USD",
|
|
94
116
|
filters: CostMonitorProjection["filters"],
|
|
95
117
|
): CostMonitorProjection {
|
|
96
|
-
const metric = {
|
|
97
|
-
|
|
98
|
-
|
|
118
|
+
const metric = {
|
|
119
|
+
events: 0,
|
|
120
|
+
tokens: { input: null, cached_input: null, output: null, reasoning: null, total: null },
|
|
121
|
+
cost: { usd: null, brl: null },
|
|
122
|
+
coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
|
|
123
|
+
};
|
|
124
|
+
const usage = {
|
|
125
|
+
conversation: metric,
|
|
126
|
+
planning: metric,
|
|
127
|
+
execution: metric,
|
|
128
|
+
total: metric,
|
|
129
|
+
new_work: metric,
|
|
130
|
+
rework: metric,
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
schema_version: 2,
|
|
134
|
+
layout_version: 2,
|
|
135
|
+
readonly: true,
|
|
136
|
+
source: ".agents/records",
|
|
137
|
+
aggregate_only: true,
|
|
138
|
+
data_source: "run_records",
|
|
139
|
+
legacy_effort_baseline: null,
|
|
140
|
+
currency,
|
|
141
|
+
pricing: { catalog_updated_at: null, fx_rate: null, conversion_applied: false },
|
|
142
|
+
filters,
|
|
143
|
+
overview: {
|
|
144
|
+
task_count: 0,
|
|
145
|
+
run_count: 0,
|
|
146
|
+
event_count: 0,
|
|
147
|
+
total_tokens: null,
|
|
148
|
+
estimated_usd: null,
|
|
149
|
+
estimated_brl: null,
|
|
150
|
+
recorded_usd: null,
|
|
151
|
+
recorded_brl: null,
|
|
152
|
+
average_run_cost_usd: null,
|
|
153
|
+
average_run_cost_brl: null,
|
|
154
|
+
average_run_duration_ms: null,
|
|
155
|
+
known_tokens_per_cycle: null,
|
|
156
|
+
top_10_token_share: null,
|
|
157
|
+
coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
|
|
158
|
+
},
|
|
159
|
+
filters_available: {
|
|
160
|
+
providers: [],
|
|
161
|
+
agents: [],
|
|
162
|
+
models: [],
|
|
163
|
+
statuses: [],
|
|
164
|
+
priorities: [],
|
|
165
|
+
risks: [],
|
|
166
|
+
phases: [],
|
|
167
|
+
origins: [],
|
|
168
|
+
work_types: [],
|
|
169
|
+
},
|
|
170
|
+
configured_agents: [],
|
|
171
|
+
usage,
|
|
172
|
+
origins: { conversation: usage, task: usage, spec: usage, prd: usage },
|
|
173
|
+
prds: [],
|
|
174
|
+
specs: [],
|
|
175
|
+
runs: [],
|
|
176
|
+
groups: {
|
|
177
|
+
conversations: [],
|
|
178
|
+
tasks: [],
|
|
179
|
+
providers: [],
|
|
180
|
+
agents: [],
|
|
181
|
+
models: [],
|
|
182
|
+
daily: [],
|
|
183
|
+
monthly: [],
|
|
184
|
+
annual: [],
|
|
185
|
+
},
|
|
186
|
+
};
|
|
99
187
|
}
|
|
100
188
|
|
|
101
189
|
export {
|
|
@@ -115,7 +203,8 @@ export function App() {
|
|
|
115
203
|
const [snapshotNoticeDelayElapsed, setSnapshotNoticeDelayElapsed] = useState(false);
|
|
116
204
|
const token = useMemo(readDashboardSessionToken, []);
|
|
117
205
|
const api = useMemo(() => new DashboardApiClient(token), [token]);
|
|
118
|
-
const { loadCostDetail, loadCostReadModelPage, loadCostRunPage, loadCostGroupPage } =
|
|
206
|
+
const { loadCostDetail, loadCostReadModelPage, loadCostRunPage, loadCostGroupPage } =
|
|
207
|
+
useAppCostLoaders(api);
|
|
119
208
|
const [dashboardView, setDashboardView] = useState<DashboardView | null>(() =>
|
|
120
209
|
initialDashboardView(window.location.pathname),
|
|
121
210
|
);
|
|
@@ -141,7 +230,8 @@ export function App() {
|
|
|
141
230
|
{},
|
|
142
231
|
);
|
|
143
232
|
const [overviewStatusPages, setOverviewStatusPages] = useState<OverviewStatusPages>({});
|
|
144
|
-
const [overviewClassificationPages, setOverviewClassificationPages] =
|
|
233
|
+
const [overviewClassificationPages, setOverviewClassificationPages] =
|
|
234
|
+
useState<OverviewClassificationPages>({});
|
|
145
235
|
const [costs, setCosts] = useState<CostMonitorProjection | null>(null);
|
|
146
236
|
const [displayedCosts, setDisplayedCosts] = useState<CostMonitorProjection | null>(null);
|
|
147
237
|
const [costLocale, setCostLocale] = useState<CostLocale>(savedLocale);
|
|
@@ -171,7 +261,10 @@ export function App() {
|
|
|
171
261
|
"choose" | "refreshing" | "reconciling" | null
|
|
172
262
|
>(null);
|
|
173
263
|
useEffect(() => {
|
|
174
|
-
void api
|
|
264
|
+
void api
|
|
265
|
+
.ready()
|
|
266
|
+
.then((ready) => setSnapshotUpdating(ready.snapshot_state === "updating"))
|
|
267
|
+
.catch(() => {});
|
|
175
268
|
}, [api]);
|
|
176
269
|
const [error, setError] = useState<string | null>(null);
|
|
177
270
|
const [reconciliationResult, setReconciliationResult] = useState<ReconciliationResult | null>(
|
|
@@ -238,7 +331,7 @@ export function App() {
|
|
|
238
331
|
// forcing a second full aggregate calculation.
|
|
239
332
|
const initialAggregateFreshRef = useRef(false);
|
|
240
333
|
const refresh = useCallback(
|
|
241
|
-
async (visible = true, reconcileOpenWork = false) => {
|
|
334
|
+
async (visible = true, reconcileOpenWork = false, refreshProjection = false) => {
|
|
242
335
|
operationsDetailCancelRef.current?.();
|
|
243
336
|
operationsDetailCancelRef.current = null;
|
|
244
337
|
operationsDetailAbortRef.current?.abort();
|
|
@@ -271,10 +364,20 @@ export function App() {
|
|
|
271
364
|
setError(null);
|
|
272
365
|
setFailedArea(null);
|
|
273
366
|
try {
|
|
274
|
-
if (reconcileOpenWork) {
|
|
275
|
-
|
|
367
|
+
if (reconcileOpenWork || refreshProjection) {
|
|
368
|
+
let snapshot: Awaited<ReturnType<typeof api.refreshProjection>>;
|
|
369
|
+
let reconciliation:
|
|
370
|
+
| Awaited<ReturnType<typeof api.reconcileOpenWork>>["reconciliation"]
|
|
371
|
+
| null = null;
|
|
372
|
+
if (reconcileOpenWork) {
|
|
373
|
+
const reconciledSnapshot = await api.reconcileOpenWork(currency, period);
|
|
374
|
+
reconciliation = reconciledSnapshot.reconciliation;
|
|
375
|
+
snapshot = reconciledSnapshot;
|
|
376
|
+
} else {
|
|
377
|
+
snapshot = await api.refreshProjection(currency, period);
|
|
378
|
+
}
|
|
276
379
|
if (!isCurrentRequest()) return;
|
|
277
|
-
setReconciliationResult(
|
|
380
|
+
if (reconciliation !== null) setReconciliationResult(reconciliation);
|
|
278
381
|
setOperations(snapshot.operations);
|
|
279
382
|
quickOverviewMetricsRef.current = snapshot.operations.summary.overview_metrics;
|
|
280
383
|
operationsDetailLoadedRef.current = true;
|
|
@@ -297,7 +400,9 @@ export function App() {
|
|
|
297
400
|
// An English first paint must have the factual USD summary
|
|
298
401
|
// before Operations formats currency. BRL retains the fast
|
|
299
402
|
// Operations-only path until the user opens Cost Monitor.
|
|
300
|
-
currency === "USD"
|
|
403
|
+
currency === "USD"
|
|
404
|
+
? api.costMonitor(currency, period, "summary")
|
|
405
|
+
: Promise.resolve(null),
|
|
301
406
|
]);
|
|
302
407
|
if (!isCurrentRequest()) return;
|
|
303
408
|
initialAggregateFreshRef.current = false;
|
|
@@ -497,7 +602,10 @@ export function App() {
|
|
|
497
602
|
const normalizedFilters = normalizeWorkListFilters(filters, workListFiltersRef.current);
|
|
498
603
|
workListFiltersRef.current = normalizedFilters;
|
|
499
604
|
const requestedKind = selectedWorkListKinds(normalizedFilters.kind);
|
|
500
|
-
const loadKindStage = async (
|
|
605
|
+
const loadKindStage = async (
|
|
606
|
+
stage: WorkBoardStage,
|
|
607
|
+
kind: "prd" | "spec" | "task" | "standalone-task",
|
|
608
|
+
) => {
|
|
501
609
|
return collectWorkListPages(async (offset) => {
|
|
502
610
|
const page = await api.operationsBoard(
|
|
503
611
|
period,
|
|
@@ -528,8 +636,9 @@ export function App() {
|
|
|
528
636
|
period.to !== requestPeriodForOperations(operationsPeriodRef.current).to
|
|
529
637
|
)
|
|
530
638
|
return;
|
|
531
|
-
const unique = <T extends { id: string }>(rows: readonly T[]) =>
|
|
532
|
-
|
|
639
|
+
const unique = <T extends { id: string }>(rows: readonly T[]) => [
|
|
640
|
+
...new Map(rows.map((row) => [row.id, row] as const)).values(),
|
|
641
|
+
];
|
|
533
642
|
setOperations((current) =>
|
|
534
643
|
current === null
|
|
535
644
|
? current
|
|
@@ -621,7 +730,8 @@ export function App() {
|
|
|
621
730
|
requestVersion !== boardRequestVersionRef.current ||
|
|
622
731
|
period.from !== requestPeriodForOperations(operationsPeriodRef.current).from ||
|
|
623
732
|
period.to !== requestPeriodForOperations(operationsPeriodRef.current).to
|
|
624
|
-
)
|
|
733
|
+
)
|
|
734
|
+
return;
|
|
625
735
|
const items = kind === "task" ? page.tasks : kind === "spec" ? page.specs : page.prds;
|
|
626
736
|
setOverviewClassificationPages((previous) => ({
|
|
627
737
|
...previous,
|
|
@@ -637,8 +747,10 @@ export function App() {
|
|
|
637
747
|
setOverviewClassificationPages((previous) => ({
|
|
638
748
|
...previous,
|
|
639
749
|
[key]: {
|
|
640
|
-
items: previous[key]?.items ?? [],
|
|
641
|
-
|
|
750
|
+
items: previous[key]?.items ?? [],
|
|
751
|
+
total: previous[key]?.total ?? 0,
|
|
752
|
+
loading: false,
|
|
753
|
+
error: cause instanceof Error ? cause.message : String(cause),
|
|
642
754
|
},
|
|
643
755
|
}));
|
|
644
756
|
} finally {
|
|
@@ -683,6 +795,55 @@ export function App() {
|
|
|
683
795
|
},
|
|
684
796
|
[api, operationsPeriod],
|
|
685
797
|
);
|
|
798
|
+
const detailExportSource = useCallback(
|
|
799
|
+
(
|
|
800
|
+
view: OperationsExportView,
|
|
801
|
+
filters: { query: string; status: string; risk: string; origin: string },
|
|
802
|
+
) => {
|
|
803
|
+
const period = requestPeriodForOperations(operationsPeriod);
|
|
804
|
+
if (view === "work-kanban") return undefined;
|
|
805
|
+
const sqliteView = {
|
|
806
|
+
"work-list": "operations_work_list",
|
|
807
|
+
changes: "operations_changes",
|
|
808
|
+
decisions: "operations_decisions",
|
|
809
|
+
executions: "operations_executions",
|
|
810
|
+
runs: "operations_agent_invocations",
|
|
811
|
+
conversations: "operations_conversations",
|
|
812
|
+
daily: "operations_daily",
|
|
813
|
+
monthly: "operations_monthly",
|
|
814
|
+
yearly: "operations_annual",
|
|
815
|
+
} as const satisfies Partial<Record<OperationsExportView, SqliteViewName>>;
|
|
816
|
+
const source = sqliteView[view];
|
|
817
|
+
if (source === undefined) return undefined;
|
|
818
|
+
const options = (offset: number) => ({
|
|
819
|
+
offset,
|
|
820
|
+
limit: 100,
|
|
821
|
+
...(filters.query ? { query: filters.query } : {}),
|
|
822
|
+
...(filters.status ? { status: filters.status } : {}),
|
|
823
|
+
...(filters.risk ? { risk: filters.risk } : {}),
|
|
824
|
+
...(filters.origin ? { origin: filters.origin } : {}),
|
|
825
|
+
});
|
|
826
|
+
return {
|
|
827
|
+
prepare: async () => {
|
|
828
|
+
const firstPage = await api.sqliteViewPage(source, period, options(0));
|
|
829
|
+
return {
|
|
830
|
+
totalRows: firstPage.total_count,
|
|
831
|
+
pages: async function* () {
|
|
832
|
+
let page = firstPage;
|
|
833
|
+
while (true) {
|
|
834
|
+
if (page.rows.length === 0) return;
|
|
835
|
+
yield page.rows;
|
|
836
|
+
const nextOffset = page.offset + page.rows.length;
|
|
837
|
+
if (nextOffset >= page.total_count) return;
|
|
838
|
+
page = await api.sqliteViewPage(source, period, options(nextOffset));
|
|
839
|
+
}
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
},
|
|
843
|
+
};
|
|
844
|
+
},
|
|
845
|
+
[api, operationsPeriod],
|
|
846
|
+
);
|
|
686
847
|
useEffect(() => {
|
|
687
848
|
if (dashboardView !== "operations" || operations === null) return;
|
|
688
849
|
let cancelled = false;
|
|
@@ -712,7 +873,7 @@ export function App() {
|
|
|
712
873
|
const refreshFromDialog = async (reconcileOpenWork: boolean) => {
|
|
713
874
|
if (reconcileOpenWork) setReconciliationResult(null);
|
|
714
875
|
setRefreshDialog(reconcileOpenWork ? "reconciling" : "refreshing");
|
|
715
|
-
await refresh(false, reconcileOpenWork);
|
|
876
|
+
await refresh(false, reconcileOpenWork, !reconcileOpenWork);
|
|
716
877
|
setRefreshDialog(null);
|
|
717
878
|
};
|
|
718
879
|
useAppEffects({
|
|
@@ -824,9 +985,9 @@ export function App() {
|
|
|
824
985
|
() =>
|
|
825
986
|
new Map(
|
|
826
987
|
(displayedCosts ?? costs)?.runs.map(
|
|
827
|
-
(run) =>
|
|
828
|
-
|
|
829
|
-
|
|
988
|
+
(run) =>
|
|
989
|
+
[run.run_id, currency === "USD" ? run.estimated_usd : run.estimated_brl] as const,
|
|
990
|
+
) ?? [],
|
|
830
991
|
),
|
|
831
992
|
[costs, currency, displayedCosts],
|
|
832
993
|
);
|
|
@@ -884,7 +1045,10 @@ export function App() {
|
|
|
884
1045
|
setSnapshotNoticeDelayElapsed(false);
|
|
885
1046
|
return undefined;
|
|
886
1047
|
}
|
|
887
|
-
const timeout = window.setTimeout(
|
|
1048
|
+
const timeout = window.setTimeout(
|
|
1049
|
+
() => setSnapshotNoticeDelayElapsed(true),
|
|
1050
|
+
snapshotNoticeDelayMs,
|
|
1051
|
+
);
|
|
888
1052
|
return () => window.clearTimeout(timeout);
|
|
889
1053
|
}, [initialDataPending, snapshotNoticeDismissed, snapshotUpdating]);
|
|
890
1054
|
const snapshotNoticeVisible = shouldShowSnapshotNotice({
|
|
@@ -895,9 +1059,16 @@ export function App() {
|
|
|
895
1059
|
});
|
|
896
1060
|
const snapshotNotice = snapshotNoticeVisible ? (
|
|
897
1061
|
<div aria-live="polite" className="app-notice app-snapshot-status" role="status">
|
|
898
|
-
<span>
|
|
1062
|
+
<span>
|
|
1063
|
+
Exibindo o último snapshot local validado. Os dados canônicos estão sendo atualizados em
|
|
1064
|
+
segundo plano e estarão atuais na próxima abertura.
|
|
1065
|
+
</span>
|
|
899
1066
|
<button
|
|
900
|
-
aria-label={
|
|
1067
|
+
aria-label={
|
|
1068
|
+
costLocale === "pt-BR"
|
|
1069
|
+
? "Fechar aviso de atualização do snapshot"
|
|
1070
|
+
: "Dismiss snapshot update notice"
|
|
1071
|
+
}
|
|
901
1072
|
onClick={() => setSnapshotNoticeDismissed(true)}
|
|
902
1073
|
type="button"
|
|
903
1074
|
>
|
|
@@ -971,6 +1142,7 @@ export function App() {
|
|
|
971
1142
|
boardTotals={boardTotals}
|
|
972
1143
|
boardKindTotals={boardKindTotals}
|
|
973
1144
|
boardExportSource={boardExportSource}
|
|
1145
|
+
detailExportSource={detailExportSource}
|
|
974
1146
|
boardStates={boardStates}
|
|
975
1147
|
data={renderedOperations}
|
|
976
1148
|
datePreset={operationsPeriod.preset}
|
|
@@ -995,8 +1167,8 @@ export function App() {
|
|
|
995
1167
|
: view === "executions"
|
|
996
1168
|
? "executions"
|
|
997
1169
|
: view === "runs"
|
|
998
|
-
|
|
999
|
-
|
|
1170
|
+
? "runs"
|
|
1171
|
+
: null;
|
|
1000
1172
|
if (kind !== null) void loadOperationsEntityPage(kind);
|
|
1001
1173
|
else if (view === "changes" || view === "decisions")
|
|
1002
1174
|
void loadOperationsLifecyclePage(view);
|
|
@@ -112,17 +112,17 @@ export function renderDashboardAlternateContent({
|
|
|
112
112
|
if (dashboardView === "traceability") {
|
|
113
113
|
return () => (
|
|
114
114
|
<Suspense fallback={<LoadingPanel area="operations" locale={costLocale} />}>
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
<TraceabilityWorkspace
|
|
116
|
+
loadingTaskId={traceLoadingTaskId}
|
|
117
|
+
locale={costLocale}
|
|
118
|
+
onOpenChange={onOpenTraceChange}
|
|
119
|
+
onOpenPrd={(prdId) => onOpenTraceMacro("PRD", prdId)}
|
|
120
|
+
onOpenSpec={(specId) => onOpenTraceMacro("SPEC", specId)}
|
|
121
|
+
onSelectTask={onSelectTraceTask}
|
|
122
|
+
selectedTaskId={selectedTraceTaskId}
|
|
123
|
+
tasks={traceTasks.length > 0 ? traceTasks : operations.tasks}
|
|
124
|
+
trace={trace}
|
|
125
|
+
/>
|
|
126
126
|
</Suspense>
|
|
127
127
|
);
|
|
128
128
|
}
|
|
@@ -4,16 +4,16 @@ import type {
|
|
|
4
4
|
ProjectConfigSettings,
|
|
5
5
|
ProjectOverview,
|
|
6
6
|
} from "./dashboard-api.js";
|
|
7
|
+
import { StackComponentEditor, StackVersions } from "./ProjectStackEditor.js";
|
|
7
8
|
import {
|
|
8
9
|
buildProjectSettingsPayload,
|
|
9
10
|
defaultAutonomousExecution,
|
|
10
11
|
lineList,
|
|
11
12
|
projectSettingsDraft,
|
|
12
|
-
shortFrameworkVersion,
|
|
13
13
|
type StackComponentsDraft,
|
|
14
|
+
shortFrameworkVersion,
|
|
14
15
|
withDetectedStackVersions,
|
|
15
16
|
} from "./project-settings-model.js";
|
|
16
|
-
import { StackComponentEditor, StackVersions } from "./ProjectStackEditor.js";
|
|
17
17
|
import "./project-settings-page.css";
|
|
18
18
|
|
|
19
19
|
type Locale = "pt-BR" | "en-US";
|
|
@@ -22,7 +22,7 @@ const copy = {
|
|
|
22
22
|
eyebrow: "Configurações",
|
|
23
23
|
title: "Configuração do projeto",
|
|
24
24
|
intro: "Edite o arquivo central do projeto com validação do schema antes da gravação.",
|
|
25
|
-
loading: "Carregando
|
|
25
|
+
loading: "Carregando…",
|
|
26
26
|
back: "Voltar ao dashboard",
|
|
27
27
|
save: "Salvar configurações",
|
|
28
28
|
saving: "Validando e salvando…",
|
|
@@ -190,10 +190,15 @@ export function ProjectSettingsPage({
|
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
if (config === null) {
|
|
193
|
+
const isLoading = error === null;
|
|
193
194
|
return (
|
|
194
|
-
<main className="project-settings-state">
|
|
195
|
-
<div
|
|
196
|
-
|
|
195
|
+
<main aria-busy={isLoading} className="project-settings-state">
|
|
196
|
+
<div
|
|
197
|
+
aria-live={isLoading ? "polite" : "assertive"}
|
|
198
|
+
className="project-settings-state-card"
|
|
199
|
+
role={isLoading ? "status" : "alert"}
|
|
200
|
+
>
|
|
201
|
+
{isLoading ? <span aria-hidden="true" className="project-settings-loader" /> : null}
|
|
197
202
|
<p>{text.eyebrow}</p>
|
|
198
203
|
<h1>{error ?? text.loading}</h1>
|
|
199
204
|
<button onClick={onClose} type="button">
|
|
@@ -229,7 +234,9 @@ export function ProjectSettingsPage({
|
|
|
229
234
|
<div>
|
|
230
235
|
<h2>
|
|
231
236
|
{text.framework}
|
|
232
|
-
{shortFrameworkVersion(overview?.framework_version)
|
|
237
|
+
{shortFrameworkVersion(overview?.framework_version)
|
|
238
|
+
? ` - ${shortFrameworkVersion(overview?.framework_version)}`
|
|
239
|
+
: ""}
|
|
233
240
|
</h2>
|
|
234
241
|
<p>{text.frameworkHint}</p>
|
|
235
242
|
</div>
|
|
@@ -131,8 +131,10 @@ export function StackVersions({
|
|
|
131
131
|
<div>
|
|
132
132
|
{components.map((component) => (
|
|
133
133
|
<article key={component.name}>
|
|
134
|
-
<
|
|
135
|
-
|
|
134
|
+
<div className="project-stack-version-identity">
|
|
135
|
+
<strong>{component.name}</strong>
|
|
136
|
+
<code>{component.version ?? text.versionUnavailable}</code>
|
|
137
|
+
</div>
|
|
136
138
|
<span className={`is-${component.verification}`}>
|
|
137
139
|
{component.verification === "exact"
|
|
138
140
|
? text.exact
|
|
@@ -9,7 +9,9 @@ describe("TraceabilityWorkspace task search", () => {
|
|
|
9
9
|
] as never[];
|
|
10
10
|
|
|
11
11
|
it("filters tasks by either title or ID", () => {
|
|
12
|
-
expect(filterTraceabilityTasks(tasks, "lançamento").map((task) => task.id)).toEqual([
|
|
12
|
+
expect(filterTraceabilityTasks(tasks, "lançamento").map((task) => task.id)).toEqual([
|
|
13
|
+
"TASK-ALPHA",
|
|
14
|
+
]);
|
|
13
15
|
expect(filterTraceabilityTasks(tasks, "beta").map((task) => task.id)).toEqual(["TASK-BETA"]);
|
|
14
16
|
expect(filterTraceabilityTasks(tasks, "missing")).toEqual([]);
|
|
15
17
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useEffect, useMemo, useState } from "react";
|
|
2
1
|
import type { OperationsProjection } from "@zaip-ai/dashboard-operations/contracts";
|
|
3
2
|
import type { TaskTrace } from "@zaip-ai/dashboard-traceability/contracts";
|
|
4
3
|
import { TaskTracePanel } from "@zaip-ai/dashboard-traceability/react";
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
5
|
import "./traceability-workspace.css";
|
|
6
6
|
|
|
7
7
|
type TraceabilityTask = OperationsProjection["tasks"][number];
|
|
@@ -62,11 +62,8 @@ export function TraceabilityWorkspace({
|
|
|
62
62
|
|
|
63
63
|
useEffect(() => {
|
|
64
64
|
setQuery(selectedTask?.title ?? selectedTaskId);
|
|
65
|
-
}, [selectedTask?.title, selectedTaskId]);
|
|
66
|
-
|
|
67
|
-
useEffect(() => {
|
|
68
65
|
setActiveIndex(0);
|
|
69
|
-
}, [
|
|
66
|
+
}, [selectedTask?.title, selectedTaskId]);
|
|
70
67
|
|
|
71
68
|
const selectTask = (task: TraceabilityTask) => {
|
|
72
69
|
setQuery(task.title);
|
|
@@ -109,6 +106,7 @@ export function TraceabilityWorkspace({
|
|
|
109
106
|
id={searchInputId}
|
|
110
107
|
onChange={(event) => {
|
|
111
108
|
setQuery(event.target.value);
|
|
109
|
+
setActiveIndex(0);
|
|
112
110
|
setIsListOpen(true);
|
|
113
111
|
}}
|
|
114
112
|
onFocus={() => setIsListOpen(true)}
|
|
@@ -118,10 +116,15 @@ export function TraceabilityWorkspace({
|
|
|
118
116
|
value={query}
|
|
119
117
|
/>
|
|
120
118
|
{isListOpen ? (
|
|
121
|
-
<
|
|
119
|
+
<div
|
|
120
|
+
aria-label={searchLabel}
|
|
121
|
+
className="traceability-task-results"
|
|
122
|
+
id={resultsId}
|
|
123
|
+
role="listbox"
|
|
124
|
+
>
|
|
122
125
|
{filteredTasks.length > 0 ? (
|
|
123
126
|
filteredTasks.map((task, index) => (
|
|
124
|
-
<
|
|
127
|
+
<div key={task.id} role="presentation">
|
|
125
128
|
<button
|
|
126
129
|
aria-selected={task.id === selectedTaskId}
|
|
127
130
|
className={index === activeIndex ? "is-active" : undefined}
|
|
@@ -133,14 +136,14 @@ export function TraceabilityWorkspace({
|
|
|
133
136
|
<strong>{task.title}</strong>
|
|
134
137
|
<small>{task.id}</small>
|
|
135
138
|
</button>
|
|
136
|
-
</
|
|
139
|
+
</div>
|
|
137
140
|
))
|
|
138
141
|
) : (
|
|
139
|
-
<
|
|
142
|
+
<div className="traceability-task-no-results" role="status">
|
|
140
143
|
{locale === "pt-BR" ? "Nenhuma task encontrada." : "No tasks found."}
|
|
141
|
-
</
|
|
144
|
+
</div>
|
|
142
145
|
)}
|
|
143
|
-
</
|
|
146
|
+
</div>
|
|
144
147
|
) : null}
|
|
145
148
|
</div>
|
|
146
149
|
<small>
|
|
@@ -22,12 +22,17 @@ describe("Cost period refresh", () => {
|
|
|
22
22
|
app.indexOf("const refresh = useCallback"),
|
|
23
23
|
app.indexOf("const loadOperationsDetails"),
|
|
24
24
|
);
|
|
25
|
+
const compactRefresh = refresh.replace(/\s+/g, " ");
|
|
25
26
|
|
|
26
27
|
expect(refresh).not.toContain("dailyCostSeed(currency, period)");
|
|
27
28
|
expect(refresh).toContain("initialAggregateFreshRef.current");
|
|
28
29
|
expect(refresh).not.toContain("loadAtomicCostSnapshot(() => api.snapshot(currency, period))");
|
|
29
|
-
expect(refresh).toContain(
|
|
30
|
-
|
|
30
|
+
expect(refresh).toContain(
|
|
31
|
+
'api.operations(period, "quick", undefined, initialAggregateFreshRef.current)',
|
|
32
|
+
);
|
|
33
|
+
expect(compactRefresh).toContain(
|
|
34
|
+
'currency === "USD" ? api.costMonitor(currency, period, "summary") : Promise.resolve(null)',
|
|
35
|
+
);
|
|
31
36
|
expect(refresh).toContain("setDisplayedCosts(null);");
|
|
32
37
|
expect(refresh).toContain("const activeDashboardView = dashboardViewRef.current");
|
|
33
38
|
expect(refresh).toContain("[api, currency, operationsPeriod]");
|
|
@@ -54,14 +59,24 @@ describe("Cost period refresh", () => {
|
|
|
54
59
|
const loaders = readFileSync(new URL("./use-app-cost-loaders.ts", import.meta.url), "utf8");
|
|
55
60
|
expect(app).toContain("useAppCostLoaders(api)");
|
|
56
61
|
expect(loaders).toContain("const loadCostRunPage = useCallback<LoadCostRunPage>");
|
|
57
|
-
expect(loaders).
|
|
62
|
+
expect(loaders).toMatch(/api\.sqliteViewPage\(\s*"cost_monitor_agent_invocations"/);
|
|
58
63
|
expect(loaders).toContain("const loadCostGroupPage = useCallback<LoadCostGroupPage>");
|
|
59
64
|
expect(loaders).toContain("task_count: nullableSqlNumber(row.task_count)");
|
|
60
65
|
expect(loaders).toContain("prd_count: Number(row.prd_count ?? 0)");
|
|
61
66
|
expect(loaders).toContain("spec_count: Number(row.spec_count ?? 0)");
|
|
62
67
|
expect(loaders).toContain("evidence_count: Number(row.evidence_count ?? 0)");
|
|
63
68
|
expect(loaders).toContain("test_count: Number(row.validation_count ?? 0)");
|
|
64
|
-
for (const dimension of [
|
|
69
|
+
for (const dimension of [
|
|
70
|
+
"provider",
|
|
71
|
+
"model",
|
|
72
|
+
"agent",
|
|
73
|
+
"phase",
|
|
74
|
+
"status",
|
|
75
|
+
"origin",
|
|
76
|
+
"workType",
|
|
77
|
+
"priority",
|
|
78
|
+
"risk",
|
|
79
|
+
])
|
|
65
80
|
expect(loaders).toContain(`filters.${dimension}`);
|
|
66
81
|
expect(app).toContain("loadRunPage={loadCostRunPage}");
|
|
67
82
|
expect(app).toContain("loadReadModelPage={loadCostReadModelPage}");
|
|
@@ -31,8 +31,14 @@ describe("DashboardApiClient reconciliation", () => {
|
|
|
31
31
|
|
|
32
32
|
it("posts to the exact canonical reconciliation path without a trailing slash", async () => {
|
|
33
33
|
vi.stubGlobal("window", globalThis);
|
|
34
|
-
const fetchMock = vi.fn(
|
|
35
|
-
|
|
34
|
+
const fetchMock = vi.fn(
|
|
35
|
+
async () =>
|
|
36
|
+
new Response(
|
|
37
|
+
JSON.stringify({
|
|
38
|
+
reconciliation: { reconciled_ids: [], blocked: [], not_reconciled: [] },
|
|
39
|
+
}),
|
|
40
|
+
{ status: 200 },
|
|
41
|
+
),
|
|
36
42
|
);
|
|
37
43
|
vi.stubGlobal("fetch", fetchMock);
|
|
38
44
|
|
|
@@ -46,6 +52,22 @@ describe("DashboardApiClient reconciliation", () => {
|
|
|
46
52
|
expect.objectContaining({ method: "POST", headers: { "x-zaip-session": "session" } }),
|
|
47
53
|
);
|
|
48
54
|
});
|
|
55
|
+
|
|
56
|
+
it("refreshes the disposable projection without calling the reconciliation route", async () => {
|
|
57
|
+
vi.stubGlobal("window", globalThis);
|
|
58
|
+
const fetchMock = vi.fn(async () => new Response(JSON.stringify({}), { status: 200 }));
|
|
59
|
+
vi.stubGlobal("fetch", fetchMock);
|
|
60
|
+
|
|
61
|
+
await new DashboardApiClient("session").refreshProjection("BRL", {
|
|
62
|
+
from: "2026-08-12",
|
|
63
|
+
to: "2026-08-12",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
expect(fetchMock).toHaveBeenCalledWith(
|
|
67
|
+
"/api/v2/refresh-projection?currency=BRL&from=2026-08-12&to=2026-08-12",
|
|
68
|
+
expect.objectContaining({ method: "POST", headers: { "x-zaip-session": "session" } }),
|
|
69
|
+
);
|
|
70
|
+
});
|
|
49
71
|
});
|
|
50
72
|
|
|
51
73
|
describe("DashboardApiClient cost monitor", () => {
|