@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
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
applyExplicitTurnRecovery,
|
|
5
|
+
normalizeExplicitTurnRecoverySchema,
|
|
6
|
+
parseExplicitTurnMappings,
|
|
7
|
+
planExplicitTurnRecovery,
|
|
8
|
+
} from "./reconcile-telemetry-explicit-recovery.mjs";
|
|
3
9
|
import {
|
|
4
10
|
aggregate,
|
|
5
11
|
duplicateUsageAssignments,
|
|
@@ -32,6 +38,7 @@ const reprice = process.argv.includes("--reprice");
|
|
|
32
38
|
const deduplicate = process.argv.includes("--deduplicate");
|
|
33
39
|
const remeasure = process.argv.includes("--remeasure");
|
|
34
40
|
const timingOnly = process.argv.includes("--timing-only");
|
|
41
|
+
const explicitRecovery = process.argv.includes("--explicit-turn-recovery");
|
|
35
42
|
if (timingOnly && !remeasure) {
|
|
36
43
|
throw new Error("--timing-only requires --remeasure");
|
|
37
44
|
}
|
|
@@ -55,13 +62,19 @@ const selectedSessionFiles = process.argv
|
|
|
55
62
|
: [],
|
|
56
63
|
)
|
|
57
64
|
.filter(Boolean);
|
|
65
|
+
const explicitMappings = parseExplicitTurnMappings(
|
|
66
|
+
process.argv,
|
|
67
|
+
explicitRecovery,
|
|
68
|
+
selectedRunIds,
|
|
69
|
+
selectedSessionFiles,
|
|
70
|
+
);
|
|
58
71
|
if (remeasure && selectedRunIds.size === 0) {
|
|
59
72
|
throw new Error("--remeasure requires at least one explicit --run <RUN-ID>");
|
|
60
73
|
}
|
|
61
74
|
if (apply && deduplicate && selectedRunIds.size === 0) {
|
|
62
75
|
throw new Error("--apply --deduplicate requires at least one explicit --run <RUN-ID>");
|
|
63
76
|
}
|
|
64
|
-
const applyBackfill = apply && !deduplicate && !remeasure;
|
|
77
|
+
const applyBackfill = apply && !deduplicate && !remeasure && !explicitRecovery;
|
|
65
78
|
|
|
66
79
|
const runFiles = await filesUnder(join(workspace, ".agents", "records", "runs"), ".jsonl");
|
|
67
80
|
const runs = [];
|
|
@@ -192,9 +205,38 @@ const allSegments = await loadSegments(
|
|
|
192
205
|
workspace,
|
|
193
206
|
selectedSessionFiles.length === 0 ? null : selectedSessionFiles,
|
|
194
207
|
);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
208
|
+
let explicitSchemaNormalized = false;
|
|
209
|
+
if (apply && explicitRecovery) {
|
|
210
|
+
const run = runs.find((candidate) => candidate.started.run_id === [...selectedRunIds][0]);
|
|
211
|
+
if (run) {
|
|
212
|
+
const normalized = await normalizeExplicitTurnRecoverySchema(
|
|
213
|
+
run.file,
|
|
214
|
+
run.records,
|
|
215
|
+
explicitMappings,
|
|
216
|
+
);
|
|
217
|
+
if (normalized !== run.records) {
|
|
218
|
+
run.records = normalized;
|
|
219
|
+
run.usage = normalized
|
|
220
|
+
.filter((record) => recordType(record) === "usage.recorded")
|
|
221
|
+
.map(usageView);
|
|
222
|
+
explicitSchemaNormalized = true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
const explicitRecoveryPlan = explicitRecovery
|
|
227
|
+
? (() => {
|
|
228
|
+
const runId = [...selectedRunIds][0];
|
|
229
|
+
const run = runs.find((candidate) => candidate.started.run_id === runId);
|
|
230
|
+
return run
|
|
231
|
+
? planExplicitTurnRecovery({ run, segments: allSegments, mappings: explicitMappings })
|
|
232
|
+
: { run_id: runId, eligible: false, reasons: ["run-not-found"], turns: [], recovered: [] };
|
|
233
|
+
})()
|
|
234
|
+
: null;
|
|
235
|
+
if (apply && explicitRecovery && explicitRecoveryPlan.eligible) {
|
|
236
|
+
const run = runs.find((candidate) => candidate.started.run_id === explicitRecoveryPlan.run_id);
|
|
237
|
+
await applyExplicitTurnRecovery({ run, plan: explicitRecoveryPlan });
|
|
238
|
+
explicitRecoveryPlan.applied = true;
|
|
239
|
+
}
|
|
198
240
|
const timingRunIds = timingEnrichmentRunIds({
|
|
199
241
|
remeasure,
|
|
200
242
|
applyBackfill,
|
|
@@ -208,8 +250,6 @@ const remeasurement =
|
|
|
208
250
|
allSegments,
|
|
209
251
|
runs,
|
|
210
252
|
selectedRunIds: timingRunIds,
|
|
211
|
-
// Automatic backfill is intentionally timing-only. Explicit remeasurement
|
|
212
|
-
// retains its existing token/cost correction behavior unless requested.
|
|
213
253
|
timingOnly: remeasure ? timingOnly : true,
|
|
214
254
|
workspace,
|
|
215
255
|
})
|
|
@@ -598,8 +638,6 @@ const eligible = candidates.filter(
|
|
|
598
638
|
|
|
599
639
|
if (applyBackfill) {
|
|
600
640
|
for (const { run, segment, confidence } of eligible) {
|
|
601
|
-
// Re-read each Run under the serial apply loop: a preceding timing repair may
|
|
602
|
-
// have reordered or appended a correction after the initial scan.
|
|
603
641
|
const persistedRecords = jsonLines(await readFile(run.file, "utf8"));
|
|
604
642
|
const finishIndex = persistedRecords.findIndex(
|
|
605
643
|
(record) => recordType(record) === "run.finished",
|
|
@@ -676,23 +714,35 @@ console.log(
|
|
|
676
714
|
? apply
|
|
677
715
|
? "apply-deduplicate"
|
|
678
716
|
: "dry-run-deduplicate"
|
|
679
|
-
:
|
|
717
|
+
: explicitRecovery
|
|
680
718
|
? apply
|
|
681
|
-
? "apply-
|
|
682
|
-
: "dry-run-
|
|
683
|
-
:
|
|
684
|
-
?
|
|
685
|
-
? "apply-
|
|
686
|
-
:
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
719
|
+
? "apply-explicit-turn-recovery"
|
|
720
|
+
: "dry-run-explicit-turn-recovery"
|
|
721
|
+
: remeasure
|
|
722
|
+
? apply
|
|
723
|
+
? "apply-remeasure"
|
|
724
|
+
: "dry-run-remeasure"
|
|
725
|
+
: apply
|
|
726
|
+
? reprice
|
|
727
|
+
? "apply-reprice"
|
|
728
|
+
: approximate
|
|
729
|
+
? "apply-approximate"
|
|
730
|
+
: "apply"
|
|
731
|
+
: reprice
|
|
732
|
+
? "dry-run-reprice"
|
|
733
|
+
: approximate
|
|
734
|
+
? "dry-run-approximate"
|
|
735
|
+
: "dry-run",
|
|
694
736
|
run_files: runs.length,
|
|
695
737
|
remeasurement,
|
|
738
|
+
explicit_turn_recovery: explicitRecoveryPlan && {
|
|
739
|
+
run_id: explicitRecoveryPlan.run_id,
|
|
740
|
+
eligible: explicitRecoveryPlan.eligible,
|
|
741
|
+
applied: explicitRecoveryPlan.applied === true,
|
|
742
|
+
reasons: explicitRecoveryPlan.reasons,
|
|
743
|
+
turns: explicitRecoveryPlan.turns,
|
|
744
|
+
schema_normalized: explicitSchemaNormalized,
|
|
745
|
+
},
|
|
696
746
|
local_session_files: new Set(segments.map((segment) => segment.file)).size,
|
|
697
747
|
local_segments_available: segments.length,
|
|
698
748
|
already_measured: runs.filter((run) => run.measured).length,
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { open, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import {
|
|
3
|
+
aggregate,
|
|
4
|
+
jsonLines,
|
|
5
|
+
recordPhase,
|
|
6
|
+
recordType,
|
|
7
|
+
usageStatus,
|
|
8
|
+
usageView,
|
|
9
|
+
withSequence,
|
|
10
|
+
} from "./reconcile-telemetry-lib.mjs";
|
|
11
|
+
|
|
12
|
+
export function parseExplicitTurnMappings(args, enabled, runIds, sessionFiles) {
|
|
13
|
+
const mappings = args.flatMap((argument, index, values) => {
|
|
14
|
+
if (argument !== "--explicit-turn") return [];
|
|
15
|
+
const [spec_id, turn_id, total, usd, brl] = String(values[index + 1] ?? "").split("|");
|
|
16
|
+
return [{ spec_id, turn_id, total: Number(total), usd: Number(usd), brl: Number(brl) }];
|
|
17
|
+
});
|
|
18
|
+
if (enabled && (runIds.size !== 1 || sessionFiles.length !== 1))
|
|
19
|
+
throw new Error("--explicit-turn-recovery requires exactly one --run and one --session-file");
|
|
20
|
+
if (enabled && mappings.length === 0)
|
|
21
|
+
throw new Error(
|
|
22
|
+
"--explicit-turn-recovery requires one or more --explicit-turn SPEC|TURN|TOTAL|USD|BRL",
|
|
23
|
+
);
|
|
24
|
+
return mappings;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// This deliberately accepts no temporal heuristic. A recovery is useful only
|
|
28
|
+
// when a human supplies the expected SPEC-to-turn mapping and every identity
|
|
29
|
+
// boundary independently agrees with the persisted Run.
|
|
30
|
+
export function planExplicitTurnRecovery({ run, segments, mappings }) {
|
|
31
|
+
const runId = run?.started?.run_id;
|
|
32
|
+
const finished = run?.records?.find((record) => recordType(record) === "run.finished");
|
|
33
|
+
const usedKeys = new Set(
|
|
34
|
+
run.usage.filter((usage) => usage.source_segment_key).map((usage) => usage.source_segment_key),
|
|
35
|
+
);
|
|
36
|
+
const problems = [];
|
|
37
|
+
if (!runId || !finished) problems.push("run-not-finished");
|
|
38
|
+
if (!run?.started?.client_thread_id) problems.push("run-client-thread-unavailable");
|
|
39
|
+
if (!Array.isArray(mappings) || mappings.length === 0) problems.push("explicit-mapping-required");
|
|
40
|
+
const turnIds = new Set();
|
|
41
|
+
const recovered = [];
|
|
42
|
+
for (const mapping of mappings ?? []) {
|
|
43
|
+
if (!mapping.spec_id || !mapping.turn_id) {
|
|
44
|
+
problems.push("mapping-spec-and-turn-required");
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (turnIds.has(mapping.turn_id)) {
|
|
48
|
+
problems.push("duplicate-explicit-turn");
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
turnIds.add(mapping.turn_id);
|
|
52
|
+
const matches = segments.filter(
|
|
53
|
+
(segment) =>
|
|
54
|
+
segment.internal_turn_ids?.includes(mapping.turn_id) || segment.turn_id === mapping.turn_id,
|
|
55
|
+
);
|
|
56
|
+
if (matches.length !== 1) {
|
|
57
|
+
problems.push(
|
|
58
|
+
matches.length === 0
|
|
59
|
+
? `turn-not-found:${mapping.turn_id}`
|
|
60
|
+
: `turn-ambiguous:${mapping.turn_id}`,
|
|
61
|
+
);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const segment = matches[0];
|
|
65
|
+
if (segment.session_agent_path !== run.started.client_thread_id)
|
|
66
|
+
problems.push(`session-agent-path-mismatch:${mapping.turn_id}`);
|
|
67
|
+
if (segment.model !== run.started.model || segment.effort !== run.started.reasoning_effort)
|
|
68
|
+
problems.push(`model-effort-mismatch:${mapping.turn_id}`);
|
|
69
|
+
if (usedKeys.has(segment.key)) problems.push(`turn-already-used:${mapping.turn_id}`);
|
|
70
|
+
if (!segment.finished_at) problems.push(`turn-not-finished:${mapping.turn_id}`);
|
|
71
|
+
if (!segment.raw?.includes(mapping.spec_id))
|
|
72
|
+
problems.push(`spec-evidence-missing:${mapping.turn_id}`);
|
|
73
|
+
const tokens = aggregate(segment);
|
|
74
|
+
if (mapping.total !== undefined && tokens.total !== mapping.total)
|
|
75
|
+
problems.push(`token-total-mismatch:${mapping.turn_id}`);
|
|
76
|
+
recovered.push({ mapping, segment, tokens });
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
run_id: runId,
|
|
80
|
+
eligible: problems.length === 0 && recovered.length === mappings.length,
|
|
81
|
+
reasons: problems,
|
|
82
|
+
turns: recovered.map(({ mapping, segment, tokens }) => ({
|
|
83
|
+
spec_id: mapping.spec_id,
|
|
84
|
+
turn_id: mapping.turn_id,
|
|
85
|
+
source_segment_key: segment.key,
|
|
86
|
+
source_started_at: segment.started_at,
|
|
87
|
+
source_finished_at: segment.finished_at,
|
|
88
|
+
tokens,
|
|
89
|
+
})),
|
|
90
|
+
recovered,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function applyExplicitTurnRecovery({ run, plan }) {
|
|
95
|
+
if (!plan.eligible)
|
|
96
|
+
throw new Error(`Explicit recovery is not eligible: ${plan.reasons.join(", ")}`);
|
|
97
|
+
const finished = run.records.find((record) => recordType(record) === "run.finished");
|
|
98
|
+
const superseded = usageStatus(run.usage).effective.at(-1);
|
|
99
|
+
if (!superseded) throw new Error("Explicit recovery needs a supersedable effective usage event");
|
|
100
|
+
const sequence = run.records.length + 1;
|
|
101
|
+
const events = plan.recovered.map(({ mapping, segment, tokens }, index) => ({
|
|
102
|
+
schema_version: 2,
|
|
103
|
+
event_id: `${run.started.run_id}:explicit-turn-recovery:${String(sequence + index).padStart(6, "0")}`,
|
|
104
|
+
run_id: run.started.run_id,
|
|
105
|
+
sequence: sequence + index,
|
|
106
|
+
occurred_at: segment.finished_at,
|
|
107
|
+
type: "usage.recorded",
|
|
108
|
+
phase: recordPhase(finished),
|
|
109
|
+
activity_kind: "retrospective_explicit_turn_recovery",
|
|
110
|
+
classification_source: "explicit",
|
|
111
|
+
tokens: { ...tokens, source: "provider_reported" },
|
|
112
|
+
cost: { usd: mapping.usd, brl: mapping.brl },
|
|
113
|
+
provider: run.started.provider ?? "openai",
|
|
114
|
+
model: segment.model,
|
|
115
|
+
source_segment_key: segment.key,
|
|
116
|
+
attributed_spec_id: mapping.spec_id,
|
|
117
|
+
supersedes_event_id: index === 0 ? superseded.event_id : null,
|
|
118
|
+
retrospective_correction: true,
|
|
119
|
+
source_occurred_at: segment.finished_at,
|
|
120
|
+
source_started_at: segment.started_at,
|
|
121
|
+
source_finished_at: segment.finished_at,
|
|
122
|
+
runtime: { reasoning_effort: segment.effort, service_tier: segment.service_tier },
|
|
123
|
+
}));
|
|
124
|
+
await appendExplicitTurnRecovery(run.file, run.records, events);
|
|
125
|
+
return events;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Kept separate from the general reconcile path: it only normalizes fields
|
|
129
|
+
// emitted by this explicit recovery writer, and only when the same scoped
|
|
130
|
+
// command is being resumed after an interrupted projection check.
|
|
131
|
+
export async function normalizeExplicitTurnRecoverySchema(file, expectedRecords, mappings = []) {
|
|
132
|
+
const specByTurn = new Map(mappings.map((mapping) => [mapping.turn_id, mapping.spec_id]));
|
|
133
|
+
const changed = expectedRecords.some((record) => {
|
|
134
|
+
const usage = usageView(record);
|
|
135
|
+
return (
|
|
136
|
+
usage?.activity_kind === "retrospective_explicit_turn_recovery" &&
|
|
137
|
+
(usage.classification_source !== "explicit" ||
|
|
138
|
+
"explicit_turn_recovery" in usage ||
|
|
139
|
+
"explicit_spec_id" in usage ||
|
|
140
|
+
usage.attributed_spec_id === undefined)
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
if (!changed) return expectedRecords;
|
|
144
|
+
const lockPath = `${file}.lock`;
|
|
145
|
+
const handle = await open(lockPath, "wx");
|
|
146
|
+
await handle.close();
|
|
147
|
+
try {
|
|
148
|
+
const persisted = jsonLines(await readFile(file, "utf8"));
|
|
149
|
+
const ids = (records) => records.map((record) => record?.event_id ?? record?.[2]);
|
|
150
|
+
if (
|
|
151
|
+
persisted.length !== expectedRecords.length ||
|
|
152
|
+
ids(persisted).some((id, index) => id !== ids(expectedRecords)[index])
|
|
153
|
+
)
|
|
154
|
+
throw new Error("Run history changed before explicit recovery schema normalization");
|
|
155
|
+
let recoveryIndex = 0;
|
|
156
|
+
const normalized = persisted.map((record) => {
|
|
157
|
+
const usage = usageView(record);
|
|
158
|
+
if (usage?.activity_kind !== "retrospective_explicit_turn_recovery") return record;
|
|
159
|
+
const { explicit_turn_recovery, explicit_spec_id, ...rest } = usage;
|
|
160
|
+
const recoveredTurn = [...specByTurn.keys()].find((turn) =>
|
|
161
|
+
rest.source_segment_key?.includes(turn),
|
|
162
|
+
);
|
|
163
|
+
const mappedSpecId = mappings[recoveryIndex++]?.spec_id;
|
|
164
|
+
return {
|
|
165
|
+
...rest,
|
|
166
|
+
classification_source: "explicit",
|
|
167
|
+
...(typeof rest.attributed_spec_id === "string"
|
|
168
|
+
? {}
|
|
169
|
+
: typeof explicit_spec_id === "string"
|
|
170
|
+
? { attributed_spec_id: explicit_spec_id }
|
|
171
|
+
: recoveredTurn
|
|
172
|
+
? { attributed_spec_id: specByTurn.get(recoveredTurn) }
|
|
173
|
+
: typeof mappedSpecId === "string"
|
|
174
|
+
? { attributed_spec_id: mappedSpecId }
|
|
175
|
+
: {}),
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
const temporary = `${file}.explicit-recovery-schema.tmp`;
|
|
179
|
+
await writeFile(
|
|
180
|
+
temporary,
|
|
181
|
+
`${normalized.map((record) => JSON.stringify(record)).join("\n")}\n`,
|
|
182
|
+
"utf8",
|
|
183
|
+
);
|
|
184
|
+
await rename(temporary, file);
|
|
185
|
+
return normalized;
|
|
186
|
+
} finally {
|
|
187
|
+
await rm(lockPath, { force: true });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export async function appendExplicitTurnRecovery(file, expectedRecords, events) {
|
|
192
|
+
if (!Array.isArray(events) || events.length === 0)
|
|
193
|
+
throw new Error("Explicit recovery events required");
|
|
194
|
+
const lockPath = `${file}.lock`;
|
|
195
|
+
const handle = await open(lockPath, "wx");
|
|
196
|
+
await handle.close();
|
|
197
|
+
try {
|
|
198
|
+
const persisted = jsonLines(await readFile(file, "utf8"));
|
|
199
|
+
const ids = (records) => records.map((record) => record?.event_id ?? record?.[2]);
|
|
200
|
+
if (
|
|
201
|
+
persisted.length !== expectedRecords.length ||
|
|
202
|
+
ids(persisted).some((id, index) => id !== ids(expectedRecords)[index])
|
|
203
|
+
)
|
|
204
|
+
throw new Error("Run history changed before explicit recovery");
|
|
205
|
+
const finishIndex = persisted.findIndex((record) => recordType(record) === "run.finished");
|
|
206
|
+
if (finishIndex < 0) throw new Error("Explicit recovery requires run.finished");
|
|
207
|
+
const before = persisted.slice(0, finishIndex);
|
|
208
|
+
const finish = persisted[finishIndex];
|
|
209
|
+
const after = persisted.slice(finishIndex + 1);
|
|
210
|
+
const updated = [...before, ...after, ...events, finish].map((record, index) =>
|
|
211
|
+
withSequence(record, index + 1),
|
|
212
|
+
);
|
|
213
|
+
const temporary = `${file}.explicit-recovery.tmp`;
|
|
214
|
+
await writeFile(
|
|
215
|
+
temporary,
|
|
216
|
+
`${updated.map((record) => JSON.stringify(record)).join("\n")}\n`,
|
|
217
|
+
"utf8",
|
|
218
|
+
);
|
|
219
|
+
await rename(temporary, file);
|
|
220
|
+
} finally {
|
|
221
|
+
await rm(lockPath, { force: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs
CHANGED
|
@@ -243,7 +243,20 @@ export function exactCompletedSegment(started, segments) {
|
|
|
243
243
|
if (!started?.client_turn_id) return { segment: null, ambiguous: false };
|
|
244
244
|
const runStartedAt = Date.parse(started.occurred_at ?? "");
|
|
245
245
|
const matches = segments.filter((segment) => {
|
|
246
|
-
|
|
246
|
+
// Older Codex sub-runs can persist the internal turn id exposed in a
|
|
247
|
+
// response item's metadata instead of the enclosing task_started id. It
|
|
248
|
+
// is an observed identity for this exact local interval, never a token
|
|
249
|
+
// matching heuristic.
|
|
250
|
+
const observedInternalTurnIds = Array.isArray(segment.internal_turn_ids)
|
|
251
|
+
? segment.internal_turn_ids
|
|
252
|
+
: [];
|
|
253
|
+
if (
|
|
254
|
+
(segment.turn_id !== started.client_turn_id &&
|
|
255
|
+
!observedInternalTurnIds.includes(started.client_turn_id)) ||
|
|
256
|
+
!segment.finished_at
|
|
257
|
+
) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
247
260
|
const segmentFinishedAt = Date.parse(segment.finished_at);
|
|
248
261
|
return (
|
|
249
262
|
Number.isFinite(runStartedAt) &&
|
|
@@ -330,6 +343,7 @@ export async function loadSegments(workspace, sessionFiles = null) {
|
|
|
330
343
|
let canonicalSessionMetaSeen = false;
|
|
331
344
|
let workspaceMatches = false;
|
|
332
345
|
let sessionId = null;
|
|
346
|
+
let sessionAgentPath = null;
|
|
333
347
|
let current = null;
|
|
334
348
|
let index = 0;
|
|
335
349
|
let model = null;
|
|
@@ -365,6 +379,16 @@ export async function loadSegments(workspace, sessionFiles = null) {
|
|
|
365
379
|
canonicalSessionMetaSeen = true;
|
|
366
380
|
workspaceMatches = normalized(payload.cwd) === normalized(workspace);
|
|
367
381
|
sessionId = nextSessionId;
|
|
382
|
+
const declaredAgentPath =
|
|
383
|
+
typeof payload.agent_path === "string"
|
|
384
|
+
? payload.agent_path
|
|
385
|
+
: typeof payload?.source?.subagent?.thread_spawn?.agent_path === "string"
|
|
386
|
+
? payload.source.subagent.thread_spawn.agent_path
|
|
387
|
+
: null;
|
|
388
|
+
// A child rollout may embed its parent session metadata immediately
|
|
389
|
+
// after its own. Retain the child identity rather than downgrading to
|
|
390
|
+
// the parent metadata that cannot identify the subagent.
|
|
391
|
+
sessionAgentPath = declaredAgentPath ?? sessionAgentPath;
|
|
368
392
|
}
|
|
369
393
|
if (!workspaceMatches) continue;
|
|
370
394
|
const settings = payload?.type === "thread_settings_applied" ? payload.thread_settings : null;
|
|
@@ -393,12 +417,14 @@ export async function loadSegments(workspace, sessionFiles = null) {
|
|
|
393
417
|
key: `${normalized(file)}#${index}`,
|
|
394
418
|
file,
|
|
395
419
|
session_id: sessionId,
|
|
420
|
+
session_agent_path: sessionAgentPath,
|
|
396
421
|
turn_id: typeof payload.turn_id === "string" ? payload.turn_id : null,
|
|
397
422
|
started_at: record.timestamp ?? null,
|
|
398
423
|
finished_at: null,
|
|
399
424
|
model,
|
|
400
425
|
effort,
|
|
401
426
|
service_tier: serviceTier,
|
|
427
|
+
internal_turn_ids: [],
|
|
402
428
|
usage: [],
|
|
403
429
|
raw: [],
|
|
404
430
|
};
|
|
@@ -422,12 +448,27 @@ export async function loadSegments(workspace, sessionFiles = null) {
|
|
|
422
448
|
}
|
|
423
449
|
}
|
|
424
450
|
if (!current) continue;
|
|
451
|
+
const internalTurnId = payload?.internal_chat_message_metadata_passthrough?.turn_id;
|
|
452
|
+
if (
|
|
453
|
+
typeof internalTurnId === "string" &&
|
|
454
|
+
!current.internal_turn_ids.includes(internalTurnId)
|
|
455
|
+
) {
|
|
456
|
+
current.internal_turn_ids.push(internalTurnId);
|
|
457
|
+
}
|
|
425
458
|
if (line.includes("RUN-") || line.includes("TASK-")) current.raw.push(line);
|
|
426
459
|
if (payload?.type === "task_complete") {
|
|
427
460
|
current.finished_at = record.timestamp ?? null;
|
|
428
461
|
if (current.usage.length) segments.push(current);
|
|
429
462
|
current = null;
|
|
430
463
|
}
|
|
464
|
+
if (current && payload?.type === "turn_aborted" && payload.turn_id === current.turn_id) {
|
|
465
|
+
// An interrupted Codex turn is still an observed terminal boundary.
|
|
466
|
+
// Preserve its collected token snapshots, but never fabricate a later
|
|
467
|
+
// finish from the Run history or wall clock.
|
|
468
|
+
current.finished_at = record.timestamp ?? null;
|
|
469
|
+
if (current.usage.length) segments.push(current);
|
|
470
|
+
current = null;
|
|
471
|
+
}
|
|
431
472
|
}
|
|
432
473
|
if (current?.usage.length) segments.push(current);
|
|
433
474
|
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
exactRemeasurementSegment,
|
|
14
14
|
isExactDuplicateUsageGroup,
|
|
15
15
|
jsonLines,
|
|
16
|
+
loadSegments,
|
|
16
17
|
pricingFor,
|
|
17
18
|
recordSequence,
|
|
18
19
|
recordType,
|
|
@@ -209,6 +210,106 @@ test("selects only one completed local segment for an exact Run turn", () => {
|
|
|
209
210
|
);
|
|
210
211
|
});
|
|
211
212
|
|
|
213
|
+
test("matches an observed internal Codex subturn to its enclosing local interval", async () => {
|
|
214
|
+
const root = await mkdtemp(join(tmpdir(), "zaip-reconcile-internal-turn-"));
|
|
215
|
+
roots.push(root);
|
|
216
|
+
const sessionFile = join(root, "internal-subturn.jsonl");
|
|
217
|
+
await writeFile(
|
|
218
|
+
sessionFile,
|
|
219
|
+
[
|
|
220
|
+
{
|
|
221
|
+
timestamp: "2026-08-12T04:30:25.797Z",
|
|
222
|
+
type: "session_meta",
|
|
223
|
+
payload: { id: "session-1", cwd: root },
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
timestamp: "2026-08-12T04:30:26.435Z",
|
|
227
|
+
type: "event_msg",
|
|
228
|
+
payload: { type: "task_started", turn_id: "outer-turn" },
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
timestamp: "2026-08-12T04:31:00.000Z",
|
|
232
|
+
type: "response_item",
|
|
233
|
+
payload: {
|
|
234
|
+
type: "reasoning",
|
|
235
|
+
internal_chat_message_metadata_passthrough: { turn_id: "internal-subturn" },
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
timestamp: "2026-08-12T04:32:00.000Z",
|
|
240
|
+
type: "event_msg",
|
|
241
|
+
payload: {
|
|
242
|
+
type: "token_count",
|
|
243
|
+
info: {
|
|
244
|
+
last_token_usage: {
|
|
245
|
+
input_tokens: 10,
|
|
246
|
+
cached_input_tokens: 0,
|
|
247
|
+
output_tokens: 2,
|
|
248
|
+
reasoning_output_tokens: 0,
|
|
249
|
+
total_tokens: 12,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
timestamp: "2026-08-12T04:33:00.000Z",
|
|
256
|
+
type: "event_msg",
|
|
257
|
+
payload: { type: "task_complete", turn_id: "outer-turn" },
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
timestamp: "2026-08-12T04:35:46.804Z",
|
|
261
|
+
type: "event_msg",
|
|
262
|
+
payload: { type: "task_started", turn_id: "enclosing-turn" },
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
timestamp: "2026-08-12T04:36:00.000Z",
|
|
266
|
+
type: "response_item",
|
|
267
|
+
payload: {
|
|
268
|
+
type: "reasoning",
|
|
269
|
+
internal_chat_message_metadata_passthrough: { turn_id: "internal-subturn" },
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
timestamp: "2026-08-12T04:37:00.000Z",
|
|
274
|
+
type: "event_msg",
|
|
275
|
+
payload: {
|
|
276
|
+
type: "token_count",
|
|
277
|
+
info: {
|
|
278
|
+
last_token_usage: {
|
|
279
|
+
input_tokens: 20,
|
|
280
|
+
cached_input_tokens: 0,
|
|
281
|
+
output_tokens: 4,
|
|
282
|
+
reasoning_output_tokens: 0,
|
|
283
|
+
total_tokens: 24,
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
timestamp: "2026-08-12T04:39:10.716Z",
|
|
290
|
+
type: "event_msg",
|
|
291
|
+
payload: { type: "turn_aborted", turn_id: "enclosing-turn", completed_at: 1786509550 },
|
|
292
|
+
},
|
|
293
|
+
]
|
|
294
|
+
.map((record) => JSON.stringify(record))
|
|
295
|
+
.join("\n") + "\n",
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
const [outerSegment, segment] = await loadSegments(root, [sessionFile]);
|
|
299
|
+
assert.deepEqual(outerSegment.internal_turn_ids, ["internal-subturn"]);
|
|
300
|
+
assert.deepEqual(segment.internal_turn_ids, ["internal-subturn"]);
|
|
301
|
+
assert.equal(outerSegment.finished_at, "2026-08-12T04:33:00.000Z");
|
|
302
|
+
assert.equal(segment.started_at, "2026-08-12T04:35:46.804Z");
|
|
303
|
+
assert.equal(segment.finished_at, "2026-08-12T04:39:10.716Z");
|
|
304
|
+
assert.deepEqual(
|
|
305
|
+
exactCompletedSegment(
|
|
306
|
+
{ client_turn_id: "internal-subturn", occurred_at: "2026-08-12T04:39:07.934Z" },
|
|
307
|
+
[outerSegment, segment],
|
|
308
|
+
),
|
|
309
|
+
{ segment, ambiguous: false },
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
|
|
212
313
|
test("remeasurement falls back only to the exact persisted source segment key", () => {
|
|
213
314
|
const target = {
|
|
214
315
|
key: "c:/users/test/.codex/sessions/2026/07/25/child.jsonl#1",
|
|
@@ -3,6 +3,7 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { after, test } from "node:test";
|
|
6
|
+
import { planExplicitTurnRecovery } from "./reconcile-telemetry-explicit-recovery.mjs";
|
|
6
7
|
import { jsonLines, usageStatus, usageView } from "./reconcile-telemetry-lib.mjs";
|
|
7
8
|
import {
|
|
8
9
|
appendRetrospectiveUsage,
|
|
@@ -36,6 +37,58 @@ test("selects completed native Runs for default timing-only backfill", () => {
|
|
|
36
37
|
assert.deepEqual([...selected], ["RUN-NATIVE"]);
|
|
37
38
|
});
|
|
38
39
|
|
|
40
|
+
test("explicit recovery requires exact session identity, unused turns, model/effort, and SPEC text", () => {
|
|
41
|
+
const run = {
|
|
42
|
+
started: {
|
|
43
|
+
run_id: "RUN-EXPLICIT",
|
|
44
|
+
client_thread_id: "/root/agent",
|
|
45
|
+
model: "gpt-test",
|
|
46
|
+
reasoning_effort: "medium",
|
|
47
|
+
},
|
|
48
|
+
records: [
|
|
49
|
+
{ type: "run.started" },
|
|
50
|
+
{ type: "usage.recorded", event_id: "RUN-EXPLICIT:old", source_segment_key: "old" },
|
|
51
|
+
{ type: "run.finished" },
|
|
52
|
+
],
|
|
53
|
+
usage: [{ event_id: "RUN-EXPLICIT:old", source_segment_key: "old", tokens: { total: 1 } }],
|
|
54
|
+
};
|
|
55
|
+
const segment = {
|
|
56
|
+
key: "session#5",
|
|
57
|
+
turn_id: "turn-r7qk",
|
|
58
|
+
internal_turn_ids: ["turn-r7qk"],
|
|
59
|
+
session_agent_path: "/root/agent",
|
|
60
|
+
model: "gpt-test",
|
|
61
|
+
effort: "medium",
|
|
62
|
+
started_at: "2026-08-22T22:56:58.553Z",
|
|
63
|
+
finished_at: "2026-08-22T23:05:26.121Z",
|
|
64
|
+
raw: "SPEC-R7QK observed",
|
|
65
|
+
usage: [
|
|
66
|
+
{
|
|
67
|
+
input_tokens: 8,
|
|
68
|
+
cached_input_tokens: 3,
|
|
69
|
+
output_tokens: 2,
|
|
70
|
+
reasoning_output_tokens: 1,
|
|
71
|
+
total_tokens: 10,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
const plan = planExplicitTurnRecovery({
|
|
76
|
+
run,
|
|
77
|
+
segments: [segment],
|
|
78
|
+
mappings: [{ spec_id: "SPEC-R7QK", turn_id: "turn-r7qk", total: 10, usd: 1, brl: 5 }],
|
|
79
|
+
});
|
|
80
|
+
assert.equal(plan.eligible, true);
|
|
81
|
+
assert.equal(plan.turns[0].tokens.total, 10);
|
|
82
|
+
assert.equal(
|
|
83
|
+
planExplicitTurnRecovery({
|
|
84
|
+
run,
|
|
85
|
+
segments: [{ ...segment, session_agent_path: "/root/root", key: "old" }],
|
|
86
|
+
mappings: [{ spec_id: "SPEC-R7QK", turn_id: "turn-r7qk", total: 10, usd: 1, brl: 5 }],
|
|
87
|
+
}).eligible,
|
|
88
|
+
false,
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
39
92
|
test("inserts a correction before the terminal event under an exclusive lock", async () => {
|
|
40
93
|
const root = await mkdtemp(join(tmpdir(), "zaip-remeasure-append-"));
|
|
41
94
|
roots.push(root);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zaip-skill-release-qualification
|
|
3
|
+
description: Qualify an exact ZAIP release candidate through source-template-package parity, cleanroom, smoke, and candidate-specific evidence; use before a release or publication decision.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Qualify a release candidate
|
|
7
|
+
|
|
8
|
+
Use before deciding whether a concrete candidate is ready. It does not publish.
|
|
9
|
+
|
|
10
|
+
1. Identify the exact candidate revision, version, and intended distribution surface.
|
|
11
|
+
Do not substitute current working-tree checks for candidate evidence.
|
|
12
|
+
2. Validate framework lock, source-to-public-template parity, generated artifacts,
|
|
13
|
+
package contents, and version alignment. Treat any source/template/package drift as
|
|
14
|
+
a failed candidate.
|
|
15
|
+
3. Run the relevant smoke and cleanroom checks against that candidate and preserve the
|
|
16
|
+
commands, revision, outcomes, and unresolved limits as evidence.
|
|
17
|
+
4. Separate local qualification, remote GitHub CI, registry publication, and formal
|
|
18
|
+
lifecycle closure. A matching SHA or passing local gate does not prove terminal CI.
|
|
19
|
+
5. Route an explicit push, deploy, or GitHub publication request to
|
|
20
|
+
`$zaip-skill-github-deploy`; never publish as part of qualification.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "ZAIP Release Qualification"
|
|
3
|
+
short_description: "Qualify an exact release candidate without publishing it."
|
|
4
|
+
default_prompt: "Use $zaip-skill-release-qualification to qualify this exact ZAIP release candidate for source-template-package parity, smoke, and cleanroom evidence."
|
|
@@ -16,3 +16,8 @@ Esta skill é read-only. Um pedido de revisão não autoriza corrigir, concluir
|
|
|
16
16
|
7. Correções aprovadas exigem autorização separada e começam uma nova Task. Inicie seu Run com `--work-type rework`, relacione somente IDs já conhecidos e deixe ancestral desconhecido como `null`; nunca leia todo o histórico para adivinhar vínculos. A revisão original permanece imutável.
|
|
17
17
|
8. Valide o perfil quantitativo e semântico por mínimos, sem quotas máximas: `lite` exige pelo menos uma validação e uma Evidence, normalmente uma de cada, mas aceita extras legítimos; `standard` exige pelo menos duas validações no perfil base ou três no elevado e ao menos uma Evidence consolidada; `critical` exige três ou mais validações, quality review independente e somente os controles acionados pelos sinais persistidos; SPEC/PRD exigem três ou mais validações e Evidences parentais, matriz, integração e review independente.
|
|
18
18
|
9. Para cleanroom, ambiente representativo ou produção, confira hash do candidato, identidade do ambiente, reviewer independente e Run observado; teste local não promove esses estados.
|
|
19
|
+
10. Leia [o contrato de prova observável](../zaip-skill-change/references/observable-evidence.md) e confronte cenário, expectativa e observação por AC. Diferencie prova confirmada, limitada, pendente, reprovada e modalidade não aplicável; observações não substituem Validation/Evidence aprovadas. Não transfira aprovação entre Runs nem conte uma limitação como prova suficiente.
|
|
20
|
+
|
|
21
|
+
# Revisão visual condicional
|
|
22
|
+
|
|
23
|
+
Não aprove UI visual apenas por source ou typecheck: exija render de cada consumidor e bundle servido quando aplicável, além de screenshot real examinado do estado pedido. Após o fallback finito, browser indisponível deixa browser proof como unknown e o AC visual pendente, sem bloquear prova técnica ou trabalho independente. Ausência de impacto visual admite N/A justificado, não ausência de ferramenta.
|