@zaip-ai/cli 2.2.0 → 2.6.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/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +23 -9
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +25 -9
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-discovery.d.ts +27 -0
- package/dist/services/agent-discovery.d.ts.map +1 -0
- package/dist/services/agent-discovery.js +73 -0
- package/dist/services/agent-discovery.js.map +1 -0
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +153 -24
- package/dist/services/codex-conversation-lifecycle-hook.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 +146 -72
- 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 +3 -3
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +117 -66
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +56 -6
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/logger.js +1 -1
- package/dist/services/logger.js.map +1 -1
- package/dist/services/logger.test.js +22 -1
- package/dist/services/logger.test.js.map +1 -1
- package/dist/services/runtime-template.test.js +129 -0
- package/dist/services/runtime-template.test.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +9 -3
- package/templates/.agents/README-ENG.md +30 -5
- package/templates/.agents/README.md +30 -7
- package/templates/.agents/architecture/software-architecture.md +1 -59
- package/templates/.agents/branding/brandbook.md +3 -0
- package/templates/.agents/config/agents/catalog.yaml +22 -10
- package/templates/.agents/config/agents/discovery.json +319 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +11 -8
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +2 -2
- package/templates/.agents/config/pricing/models.json +9 -5
- package/templates/.agents/config/project.yaml +12 -1
- package/templates/.agents/dashboard/.zaip-managed.json +375 -95
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-CGxeQak4.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DaSllaJp.js → DashboardHelpDialog-tzS7YxYB.js} +57 -33
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-DEbCi1gP.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-t1Om0Abw.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-TPUT2IUt.js → icons-vendor-DiGC-dsJ.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-Ct48XHGL.js → react-vendor-kPO6yNed.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +3 -1264
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +363 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +99 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +62 -6
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +7 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -7
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +151 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +28 -153
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-app-shell.tsx +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-retry.ts +17 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-setup-route.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +66 -0
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +3 -2
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +68 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.test.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +2 -5
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +30 -19
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +9 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +77 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +397 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +782 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-snapshot-notice.tsx +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperPanelSlot.tsx +16 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +459 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +27 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +62 -186
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorRunDialog.tsx +20 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-hides-calls-that-have-no-collected.test.ts +80 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +455 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +18 -525
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +32 -508
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-export-sources.ts +74 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-actions.ts +19 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +115 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test-fixtures.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTableBadges.tsx +34 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +8 -38
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +243 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +27 -275
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +70 -247
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +171 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewPanels.tsx +64 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +6 -2
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +6 -14
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +3 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +32 -0
- 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/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1458 -1458
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1425 -1425
- package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1458 -1459
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +53 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +79 -24
- package/templates/.agents/dashboard/packages/local-runtime/src/projection-refresh-diagnostics.ts +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +168 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +344 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-http-contracts.ts +31 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +345 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +461 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-route-context.ts +13 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -21
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-view-allowlist.test.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +64 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +2 -30
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +6 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -330
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +73 -1060
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-first-fold.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +561 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +600 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +269 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-context.ts +32 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +244 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +292 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +547 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +360 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +169 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +475 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +132 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-timing.ts +299 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +692 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +739 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-does-not-convert-delayed-historical-finalizer.test.ts +706 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +748 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +710 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-marks-token-cost-telemetry-unavailable-when.test.ts +618 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +755 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuilds-disposable-snapshot-serves-zaip-records.test.ts +276 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +193 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-types.ts +123 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1 -2805
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +17 -6930
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +385 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +412 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +4 -3
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +195 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.test.mjs +2 -7
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-navigation.mjs +114 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +90 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +89 -418
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +22 -12
- 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/playwright.config.ts +4 -1
- package/templates/.agents/design/.zaip-managed.json +5 -5
- package/templates/.agents/design/DESIGN.md +2 -186
- package/templates/.agents/design/README.md +12 -2
- 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/strategy.md +3 -0
- package/templates/.agents/marketing/strategy.md +3 -0
- package/templates/.agents/requirements/autonomous-assurance.md +2 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +13 -4
- 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 +4 -2
- 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 +3 -3
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/architecture.md +2 -0
- package/templates/.agents/rules/astra-diagnostic.md +1 -1
- package/templates/.agents/rules/autonomy-decision.md +3 -1
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +2 -0
- package/templates/.agents/rules/context.md +2 -1
- package/templates/.agents/rules/core.md +3 -3
- package/templates/.agents/rules/design-system-central-contract.md +17 -0
- package/templates/.agents/rules/evolution.md +3 -1
- package/templates/.agents/rules/frontend-lite.md +3 -1
- package/templates/.agents/rules/local-sqlite-storage.md +2 -2
- package/templates/.agents/rules/meta-mcp.md +3 -1
- package/templates/.agents/rules/model-orchestration.md +1 -1
- package/templates/.agents/rules/run-lifecycle-closure.md +6 -4
- package/templates/.agents/rules/security.md +3 -1
- package/templates/.agents/rules/specialist-routing.md +3 -1
- package/templates/.agents/rules/text-writing-utf8.md +1 -1
- package/templates/.agents/rules/workflow.md +7 -5
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +519 -247
- 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 +1 -1
- package/templates/.agents/sales/playbook.md +3 -0
- package/templates/.agents/skills/zaip-aios/SKILL.md +5 -3
- package/templates/.agents/skills/zaip-skill-adapt-stack/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-observability/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/references/signal-design.md +3 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/references/evidence-matrix.md +3 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/data-access-paths.md +9 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/worker-scenario.md +5 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/scripts/worker-contract.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-author-skills/references/engineering-skill-index.md +9 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +5 -3
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-backend/references/deployment-environments.md +75 -0
- package/templates/.agents/skills/zaip-skill-backend/references/supabase-migration-contract.md +23 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-cloud-engineering/SKILL.md +7 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/SKILL.md +37 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workers-static-assets.md +26 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workflow-templates.md +71 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/scripts/cloudflare-github-deploy-contract.test.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-config/SKILL.md +21 -11
- package/templates/.agents/skills/zaip-skill-config/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-container-runtime/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-container-runtime/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-context/SKILL.md +6 -1
- package/templates/.agents/skills/zaip-skill-context/references/prd-spec-task-handoff.md +10 -0
- package/templates/.agents/skills/zaip-skill-context/references/rule-selection.md +20 -0
- package/templates/.agents/skills/zaip-skill-cqrs/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/SKILL.md +18 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/references/audit-contract.md +94 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.mjs +185 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/manual-mode.md +15 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/promotion-example.md +5 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.mjs +145 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.test.mjs +178 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/references/runtime-shapes.md +3 -0
- package/templates/.agents/skills/zaip-skill-design-system/SKILL.md +20 -9
- package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/references/inventory-contract.md +7 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/scripts/inventory.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/references/recovery-scope.md +3 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +7 -0
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +1 -5
- package/templates/.agents/skills/zaip-skill-external-integrations/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-external-integrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/SKILL.md +44 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/SKILL.md +36 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md +33 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/github.md +63 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/hostinger-vps.md +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/npm.md +30 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/check-skill.mjs +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs +61 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs +128 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-ssh.integration.test.mjs +106 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +43 -76
- package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +131 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/github-release-workflow-template.md +31 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-gate-matrix.md +24 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +44 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-notes.md +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.mjs +389 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +25 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness-api.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.mjs +98 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.test.mjs +25 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.mjs +159 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.test.mjs +160 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +149 -12
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +64 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/release-notes-coverage.test.mjs +126 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.mjs +78 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.test.mjs +51 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.mjs +184 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.test.mjs +109 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +18 -10
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +3 -4
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/aws-cli-terraform.md +62 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/guia-iniciante-hostinger-vps.md +183 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/references/scaffold-contract.md +9 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/helpers.test.mjs +121 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/scaffold.mjs +169 -0
- package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-performance-engineering/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-performance-engineering/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +26 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +39 -13
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/SKILL.md +66 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/references/behavioral-dry-run.md +23 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +40 -1
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +98 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +19 -21
- package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-storage-uploads/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-storage-uploads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-task/SKILL.md +16 -7
- package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +25 -0
- package/templates/.agents/skills/zaip-skill-test-data/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-test-data/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-test-data/scripts/generate.mjs +72 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/references/example-map.md +3 -0
- package/templates/.agents/skills/zaip-skill-website-readiness/SKILL.md +8 -0
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +2 -1
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +5 -3
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +34 -0
- package/templates/template-manifest.json +955 -211
- package/templates/.agents/branding/.gitkeep +0 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-snUCQYTC.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-BPtVUGgs.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-GgzpZ_PY.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BCvZFMEf.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-_MEktQNM.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BDe4_Ubl.js +0 -1
- package/templates/.agents/growth/.gitkeep +0 -0
- package/templates/.agents/marketing/.gitkeep +0 -0
- package/templates/.agents/sales/.gitkeep +0 -0
|
@@ -1,27 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { serve } from "@hono/node-server";
|
|
5
5
|
import { serveStatic } from "@hono/node-server/serve-static";
|
|
6
|
-
import {
|
|
6
|
+
import { WorkspaceFileSystem, type WorkspaceLayout } from "@zaip-ai/core";
|
|
7
7
|
import { fxRateSchema, PricingRepository, pricingCatalogSchema } from "@zaip-ai/costs";
|
|
8
|
-
import {
|
|
9
|
-
buildCostSummaryProjection,
|
|
10
|
-
type CostSummarySource,
|
|
11
|
-
} from "@zaip-ai/dashboard-cost-monitor/server";
|
|
12
|
-
import type { OperationsProjection } from "@zaip-ai/dashboard-operations/contracts";
|
|
13
|
-
import {
|
|
14
|
-
buildOperationsProjection,
|
|
15
|
-
buildQuickOperationsProjection,
|
|
16
|
-
readPrdDetail,
|
|
17
|
-
readSpecDetail,
|
|
18
|
-
readTaskDetail,
|
|
19
|
-
} from "@zaip-ai/dashboard-operations/server";
|
|
20
|
-
import { buildTaskTrace } from "@zaip-ai/dashboard-traceability/server";
|
|
21
|
-
import { LifecycleManifestStore } from "@zaip-ai/lifecycle-manifests";
|
|
22
8
|
import { type Context, Hono } from "hono";
|
|
23
9
|
import { getCookie, setCookie } from "hono/cookie";
|
|
24
|
-
import
|
|
10
|
+
import { captureActiveCodexTelemetry } from "./active-codex-telemetry.js";
|
|
25
11
|
import { runAgentAdapterSync } from "./agent-adapter-sync.js";
|
|
26
12
|
import {
|
|
27
13
|
type AgentAdapterSyncResult,
|
|
@@ -34,47 +20,28 @@ import {
|
|
|
34
20
|
readProjectOverview,
|
|
35
21
|
readProjectSettings,
|
|
36
22
|
} from "./project-settings.js";
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
type BoardClassification,
|
|
40
|
-
boardFilters,
|
|
41
|
-
boardPage,
|
|
42
|
-
boardStage,
|
|
43
|
-
classificationPage,
|
|
44
|
-
} from "./server-board.js";
|
|
23
|
+
import { createProjectionRefreshDiagnostics } from "./projection-refresh-diagnostics.js";
|
|
24
|
+
import { agentPortraitFiles } from "./server-agent-assets.js";
|
|
45
25
|
import { registerBrowserLeaseRoute } from "./server-browser-lease.js";
|
|
46
|
-
import {
|
|
26
|
+
import { registerCostsRoutes } from "./server-costs-routes.js";
|
|
47
27
|
import {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
} from "./server-
|
|
53
|
-
import {
|
|
28
|
+
API_PREFIX,
|
|
29
|
+
headOrJson,
|
|
30
|
+
requireV2Layout,
|
|
31
|
+
V2WorkspaceRequiredError,
|
|
32
|
+
} from "./server-http-contracts.js";
|
|
33
|
+
import { registerOperationsRoutes } from "./server-operations-routes.js";
|
|
54
34
|
import { projectionPeriodFilter } from "./server-period.js";
|
|
55
|
-
import {
|
|
56
|
-
import {
|
|
57
|
-
buildCanonicalOperationsProjection,
|
|
58
|
-
buildCurrentCostProjection,
|
|
59
|
-
buildManifestCostRunPage,
|
|
60
|
-
buildManifestFirstCostProjection,
|
|
61
|
-
isUnfilteredCostRequest,
|
|
62
|
-
knownWorkIds,
|
|
63
|
-
normalizeWorkPriority,
|
|
64
|
-
readCurrentFxRate,
|
|
65
|
-
readWorkPriority,
|
|
66
|
-
} from "./server-projections.js";
|
|
35
|
+
import { buildFirstFoldQuickProjection, dashboardSnapshot } from "./server-read-projections.js";
|
|
67
36
|
import { isAllowedDashboardAuthority } from "./server-request-authority.js";
|
|
68
37
|
import { refreshSqliteSnapshotInWorker } from "./server-snapshot-refresh.js";
|
|
69
38
|
import { readCommittedSnapshotRevision } from "./server-snapshot-revision.js";
|
|
70
39
|
import { startSnapshotSynchronization } from "./server-snapshot-synchronization.js";
|
|
71
|
-
import { buildSqliteTaskTrace } from "./server-sqlite-task-trace.js";
|
|
72
40
|
import { writeReadModelStartup, writeStartupPhase } from "./server-startup.js";
|
|
73
|
-
import {
|
|
41
|
+
import { selectedCurrency } from "./server-summary-helpers.js";
|
|
42
|
+
import { registerTraceRoutes } from "./server-trace-routes.js";
|
|
74
43
|
import {
|
|
75
44
|
createWorkReconciliation,
|
|
76
|
-
reconciliationNeedsRefresh,
|
|
77
|
-
startHostTerminalReconciliation,
|
|
78
45
|
waitForWorkReconciliation,
|
|
79
46
|
} from "./server-work-reconciliation.js";
|
|
80
47
|
|
|
@@ -84,14 +51,9 @@ import {
|
|
|
84
51
|
dashboardIdentity,
|
|
85
52
|
dashboardWorkspaceKey,
|
|
86
53
|
ReconciliationCommandTimeoutError,
|
|
87
|
-
type ReconciliationResult,
|
|
88
54
|
reconcileOpenWork,
|
|
89
55
|
} from "./server-workspace.js";
|
|
90
|
-
import {
|
|
91
|
-
rebuildSqliteReadModel,
|
|
92
|
-
SqliteReadModelFileSystem,
|
|
93
|
-
sqliteViewMetadata,
|
|
94
|
-
} from "./sqlite-read-model.js";
|
|
56
|
+
import { rebuildSqliteReadModel, SqliteReadModelFileSystem } from "./sqlite-read-model.js";
|
|
95
57
|
|
|
96
58
|
export { manifestRun, mergeManifestRuns } from "./manifest-runs.js";
|
|
97
59
|
export { openWorkIds } from "./server-agent-assets.js";
|
|
@@ -110,15 +72,10 @@ export {
|
|
|
110
72
|
validateSqliteReadModelSchema,
|
|
111
73
|
} from "./sqlite-read-model.js";
|
|
112
74
|
|
|
113
|
-
type OverviewMacroMetrics = NonNullable<
|
|
114
|
-
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
115
|
-
>;
|
|
116
|
-
|
|
117
|
-
const API_PREFIX = "/api/v2";
|
|
118
75
|
const HOST = "127.0.0.1";
|
|
119
76
|
const RUNTIME_KIND = "zaip-dashboard-sqlite-runtime";
|
|
120
77
|
const SESSION_COOKIE = "zaip-dashboard-sqlite-session";
|
|
121
|
-
|
|
78
|
+
|
|
122
79
|
const SNAPSHOT_CACHE_TTL_MS = 5_000;
|
|
123
80
|
interface DashboardAppOptions {
|
|
124
81
|
syncAgentAdapters?: () => Promise<AgentAdapterSyncResult>;
|
|
@@ -137,10 +94,6 @@ interface DashboardAppOptions {
|
|
|
137
94
|
launcherOwned?: boolean;
|
|
138
95
|
}
|
|
139
96
|
|
|
140
|
-
class V2WorkspaceRequiredError extends Error {
|
|
141
|
-
override readonly name = "V2WorkspaceRequiredError";
|
|
142
|
-
}
|
|
143
|
-
|
|
144
97
|
function isAllowedOrigin(origin: string): boolean {
|
|
145
98
|
try {
|
|
146
99
|
const parsed = new URL(origin);
|
|
@@ -151,7 +104,6 @@ function isAllowedOrigin(origin: string): boolean {
|
|
|
151
104
|
return false;
|
|
152
105
|
}
|
|
153
106
|
}
|
|
154
|
-
|
|
155
107
|
function isSafeUiPath(pathname: string): boolean {
|
|
156
108
|
try {
|
|
157
109
|
const decoded = decodeURIComponent(pathname).replaceAll("\\", "/");
|
|
@@ -160,462 +112,29 @@ function isSafeUiPath(pathname: string): boolean {
|
|
|
160
112
|
return false;
|
|
161
113
|
}
|
|
162
114
|
}
|
|
163
|
-
|
|
164
115
|
function defaultSessionToken(): string {
|
|
165
116
|
return process.env.ZAIP_UI_TOKEN ?? randomBytes(24).toString("base64url");
|
|
166
117
|
}
|
|
167
|
-
|
|
168
118
|
function shouldBootstrapBrowserSession(context: Context): boolean {
|
|
169
119
|
if (context.req.method !== "GET" && context.req.method !== "HEAD") return false;
|
|
170
120
|
if (context.req.path !== "/" && context.req.path !== "/index.html") return false;
|
|
171
|
-
|
|
172
121
|
const origin = context.req.header("origin");
|
|
173
122
|
if (origin !== undefined && !isAllowedOrigin(origin)) return false;
|
|
174
123
|
return context.req.header("sec-fetch-site") !== "cross-site";
|
|
175
124
|
}
|
|
176
125
|
|
|
177
|
-
async function requireV2Layout(filesystem: WorkspaceFileSystem): Promise<WorkspaceLayout> {
|
|
178
|
-
const layout = await loadWorkspaceLayout(filesystem);
|
|
179
|
-
if (layout.version === 1) {
|
|
180
|
-
throw new V2WorkspaceRequiredError("Dashboard API requires a modern ZAIP-AIOS workspace");
|
|
181
|
-
}
|
|
182
|
-
return layout;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function headOrJson(
|
|
186
|
-
context: Context,
|
|
187
|
-
payload: unknown,
|
|
188
|
-
status: ContentfulStatusCode = 200,
|
|
189
|
-
cacheable = false,
|
|
190
|
-
): Response {
|
|
191
|
-
if (cacheable) {
|
|
192
|
-
const etag = `"${createHash("sha256").update(JSON.stringify(payload)).digest("base64url")}"`;
|
|
193
|
-
context.header("ETag", etag);
|
|
194
|
-
context.header("Cache-Control", "private, no-cache");
|
|
195
|
-
if (context.req.header("if-none-match") === etag) return context.body(null, 304);
|
|
196
|
-
}
|
|
197
|
-
if (context.req.method === "HEAD") return context.body(null, status);
|
|
198
|
-
return context.json(payload, status);
|
|
199
|
-
}
|
|
200
126
|
/**
|
|
201
127
|
* Keep the entity/macro details on the snapshot filesystem, while making the
|
|
202
128
|
* first-fold counters and token/cost facts come from SQL.
|
|
203
129
|
* Duration intentionally retains the shared hybrid legacy policy in the
|
|
204
130
|
* Operations module; its underlying daily rows are still SQLite-backed.
|
|
205
131
|
*/
|
|
206
|
-
async function buildFirstFoldQuickProjection(
|
|
207
|
-
filesystem: WorkspaceFileSystem,
|
|
208
|
-
layout: WorkspaceLayout,
|
|
209
|
-
filter: { from: string | null; to: string | null },
|
|
210
|
-
options: {
|
|
211
|
-
includeBoardTasks?: boolean;
|
|
212
|
-
includeExtended?: boolean;
|
|
213
|
-
includePeriods?: boolean;
|
|
214
|
-
includeTopTasks?: boolean;
|
|
215
|
-
} = {},
|
|
216
|
-
): Promise<OperationsProjection> {
|
|
217
|
-
// The comparison runtime deliberately has no lifecycle daily aggregates in
|
|
218
|
-
// its snapshot. Its immutable filesystem contains only canonical records,
|
|
219
|
-
// while the SQL views supply the first-fold facts. Never enter the legacy
|
|
220
|
-
// quick projection here: it requires lifecycle daily read models and would
|
|
221
|
-
// make an otherwise valid SQLite dashboard fail on first paint.
|
|
222
|
-
const projection =
|
|
223
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
224
|
-
? buildSqliteOperationsProjection(filesystem, layout, filter, options)
|
|
225
|
-
: await buildQuickOperationsProjection(filesystem, layout, filter, options);
|
|
226
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem)) return projection;
|
|
227
|
-
const cachedMonthlyQuick = filesystem.firstFoldMonthlyQuick(filter);
|
|
228
|
-
const aggregate =
|
|
229
|
-
filter.from === null && filter.to === null
|
|
230
|
-
? filesystem.firstFoldViewportAllTime().aggregate
|
|
231
|
-
: (cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter));
|
|
232
|
-
return {
|
|
233
|
-
...projection,
|
|
234
|
-
summary: {
|
|
235
|
-
...projection.summary,
|
|
236
|
-
run_count: aggregate.total_run_count,
|
|
237
|
-
overview_metrics: {
|
|
238
|
-
...projection.summary.overview_metrics,
|
|
239
|
-
duration_ms: aggregate.duration_ms,
|
|
240
|
-
tokens: aggregate.total_tokens,
|
|
241
|
-
cost_brl: aggregate.cost_brl,
|
|
242
|
-
execution_day_count: aggregate.execution_day_count,
|
|
243
|
-
data_source: "run_records",
|
|
244
|
-
},
|
|
245
|
-
},
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
132
|
|
|
249
133
|
/**
|
|
250
134
|
* SQLite's files snapshot intentionally excludes derived lifecycle manifests.
|
|
251
135
|
* Build the Operations first fold from its canonical SQL views instead of
|
|
252
136
|
* treating a missing manifest as a broken workspace.
|
|
253
137
|
*/
|
|
254
|
-
function buildSqliteOperationsProjection(
|
|
255
|
-
filesystem: SqliteReadModelFileSystem,
|
|
256
|
-
layout: WorkspaceLayout,
|
|
257
|
-
filter: { from: string | null; to: string | null },
|
|
258
|
-
options: {
|
|
259
|
-
includeBoardTasks?: boolean;
|
|
260
|
-
includeExtended?: boolean;
|
|
261
|
-
includePeriods?: boolean;
|
|
262
|
-
includeTopTasks?: boolean;
|
|
263
|
-
},
|
|
264
|
-
): OperationsProjection {
|
|
265
|
-
const cachedMonthlyQuick = filesystem.firstFoldMonthlyQuick(filter);
|
|
266
|
-
const fullAllTime =
|
|
267
|
-
filter.from === null && filter.to === null
|
|
268
|
-
? options.includeExtended === true
|
|
269
|
-
? filesystem.firstFoldAllTime()
|
|
270
|
-
: null
|
|
271
|
-
: null;
|
|
272
|
-
const allTime =
|
|
273
|
-
fullAllTime ??
|
|
274
|
-
(filter.from === null && filter.to === null ? filesystem.firstFoldViewportAllTime() : null);
|
|
275
|
-
const allTimeBoard =
|
|
276
|
-
filter.from === null && filter.to === null && options.includeBoardTasks === true
|
|
277
|
-
? filesystem.firstFoldBoardAllTime()
|
|
278
|
-
: null;
|
|
279
|
-
const page = <T extends "task" | "spec" | "prd">(kind: T) =>
|
|
280
|
-
cachedMonthlyQuick?.pages[kind] ??
|
|
281
|
-
allTimeBoard?.pages[kind] ??
|
|
282
|
-
filesystem.canonicalWorkPage(kind, filter, 0, 10_000).rows;
|
|
283
|
-
const includeEntities = allTime === null || options.includeBoardTasks === true;
|
|
284
|
-
const tasks = includeEntities ? page("task") : [];
|
|
285
|
-
const specs = includeEntities ? page("spec") : [];
|
|
286
|
-
const prds = includeEntities ? page("prd") : [];
|
|
287
|
-
const aggregate =
|
|
288
|
-
allTime?.aggregate ?? cachedMonthlyQuick?.aggregate ?? filesystem.firstFoldAggregate(filter);
|
|
289
|
-
const legacyDraftCount = allTime?.task_status_counts.draft ?? 0;
|
|
290
|
-
const taskCount =
|
|
291
|
-
allTime === null ? tasks.length : Math.max(0, allTime.aggregate.task_count - legacyDraftCount);
|
|
292
|
-
const allTimeTopTasks =
|
|
293
|
-
filter.from === null &&
|
|
294
|
-
filter.to === null &&
|
|
295
|
-
(fullAllTime !== null || options.includeTopTasks === true)
|
|
296
|
-
? (fullAllTime?.top_tasks ?? filesystem.firstFoldTopTasksAllTime())
|
|
297
|
-
: null;
|
|
298
|
-
const topTasks =
|
|
299
|
-
allTimeTopTasks === null
|
|
300
|
-
? (cachedMonthlyQuick?.top_tasks ?? filesystem.topTasks(filter)).map((task) => ({
|
|
301
|
-
task_id: task.task_id,
|
|
302
|
-
duration_ms: task.duration_ms,
|
|
303
|
-
total_tokens: task.total_tokens,
|
|
304
|
-
cost_brl: task.cost_brl,
|
|
305
|
-
run_count: task.run_count,
|
|
306
|
-
}))
|
|
307
|
-
: projectAllTimeTopTasks(allTimeTopTasks);
|
|
308
|
-
const macroMetrics =
|
|
309
|
-
fullAllTime === null
|
|
310
|
-
? ({
|
|
311
|
-
specs: periodMacroMetric(specs, "spec"),
|
|
312
|
-
prds: periodMacroMetric(prds, "prd"),
|
|
313
|
-
} satisfies OverviewMacroMetrics)
|
|
314
|
-
: (Object.fromEntries(
|
|
315
|
-
(["specs", "prds"] as const).map((kind) => {
|
|
316
|
-
const metric = fullAllTime.macro_metrics[kind];
|
|
317
|
-
return [
|
|
318
|
-
kind,
|
|
319
|
-
{
|
|
320
|
-
status_counts: metric.status_counts,
|
|
321
|
-
classification_counts: metric.classification_counts,
|
|
322
|
-
entity_count: metric.entity_count,
|
|
323
|
-
total_run_count: metric.total_run_count,
|
|
324
|
-
total_duration_ms: metric.total_duration_ms,
|
|
325
|
-
total_tokens: metric.total_tokens,
|
|
326
|
-
total_cost_usd: metric.total_cost_usd,
|
|
327
|
-
total_cost_brl: metric.total_cost_brl,
|
|
328
|
-
average_duration_ms: metric.average_duration_ms,
|
|
329
|
-
average_tokens: metric.average_tokens,
|
|
330
|
-
average_cost_usd: metric.average_cost_usd,
|
|
331
|
-
average_cost_brl: metric.average_cost_brl,
|
|
332
|
-
latest_created_at: metric.latest_created_at,
|
|
333
|
-
top_entities: metric.top_entities.map((entity) => ({
|
|
334
|
-
entity_id: entity.entity_id,
|
|
335
|
-
title: entity.title,
|
|
336
|
-
duration_ms: entity.total_duration_ms,
|
|
337
|
-
total_tokens: entity.total_tokens,
|
|
338
|
-
total_cost_usd: entity.total_cost_usd,
|
|
339
|
-
cost_brl: entity.total_cost_brl,
|
|
340
|
-
run_count: entity.total_run_count,
|
|
341
|
-
duration_share: entity.duration_share,
|
|
342
|
-
})),
|
|
343
|
-
},
|
|
344
|
-
];
|
|
345
|
-
}),
|
|
346
|
-
) as NonNullable<
|
|
347
|
-
NonNullable<OperationsProjection["summary"]["overview_metrics"]>["macro_metrics"]
|
|
348
|
-
>);
|
|
349
|
-
const statuses: Record<string, number> = Object.fromEntries(
|
|
350
|
-
Object.entries(allTime?.task_status_counts ?? {}).filter(([status]) => status !== "draft"),
|
|
351
|
-
);
|
|
352
|
-
const risks: Record<string, number> = allTime?.task_risk_counts ?? {};
|
|
353
|
-
if (allTime === null) {
|
|
354
|
-
for (const task of tasks) {
|
|
355
|
-
const status = typeof task.status === "string" ? task.status : "draft";
|
|
356
|
-
const risk = typeof task.risk === "string" ? task.risk : "standard";
|
|
357
|
-
statuses[status] = (statuses[status] ?? 0) + 1;
|
|
358
|
-
risks[risk] = (risks[risk] ?? 0) + 1;
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const latest =
|
|
362
|
-
allTime?.aggregate.latest_task_created_at ??
|
|
363
|
-
[...tasks, ...specs, ...prds]
|
|
364
|
-
.map((row) => (typeof row.occurred_at === "string" ? row.occurred_at : null))
|
|
365
|
-
.filter((value): value is string => value !== null)
|
|
366
|
-
.sort()
|
|
367
|
-
.at(-1) ??
|
|
368
|
-
null;
|
|
369
|
-
const unavailableUsage = {
|
|
370
|
-
events: 0,
|
|
371
|
-
tokens: { input: null, cached_input: null, output: null, reasoning: null, total: null },
|
|
372
|
-
cost: { usd: null, brl: null },
|
|
373
|
-
coverage: { events: 0, tokens: 0, usd: 0, brl: 0 },
|
|
374
|
-
};
|
|
375
|
-
const totalUsage = {
|
|
376
|
-
...unavailableUsage,
|
|
377
|
-
tokens: { ...unavailableUsage.tokens, total: aggregate.total_tokens },
|
|
378
|
-
cost: { ...unavailableUsage.cost, brl: aggregate.cost_brl },
|
|
379
|
-
};
|
|
380
|
-
const usage = {
|
|
381
|
-
conversation: unavailableUsage,
|
|
382
|
-
planning: unavailableUsage,
|
|
383
|
-
execution: unavailableUsage,
|
|
384
|
-
total: totalUsage,
|
|
385
|
-
new_work: unavailableUsage,
|
|
386
|
-
rework: unavailableUsage,
|
|
387
|
-
};
|
|
388
|
-
const dailyPeriods = options.includePeriods === true ? filesystem.dailyPeriods(filter) : {};
|
|
389
|
-
const hasUnknownUsage = Object.values(dailyPeriods).some(
|
|
390
|
-
(period) => period.usage.total_tokens.unknown > 0 || period.usage.cost.unknown > 0,
|
|
391
|
-
);
|
|
392
|
-
const canonicalSource = filesystem.canonicalSource();
|
|
393
|
-
const taskProjection = (row: Record<string, unknown>) => ({
|
|
394
|
-
schema_version: 2 as const,
|
|
395
|
-
id: String(row.id),
|
|
396
|
-
revision: 1,
|
|
397
|
-
change_id: typeof row.change_id === "string" ? row.change_id : "",
|
|
398
|
-
title: String(row.title ?? row.id),
|
|
399
|
-
short_name: String(row.title ?? row.id),
|
|
400
|
-
objective: "",
|
|
401
|
-
status: normalizeTaskStatus(row.status),
|
|
402
|
-
attempt_count: null,
|
|
403
|
-
risk: normalizeRisk(row.risk),
|
|
404
|
-
priority: "medium" as const,
|
|
405
|
-
owner: null,
|
|
406
|
-
requirement_ids: [],
|
|
407
|
-
acceptance_ids: [],
|
|
408
|
-
depends_on: [],
|
|
409
|
-
write_scopes: [],
|
|
410
|
-
created_at: String(row.occurred_at),
|
|
411
|
-
updated_at: String(row.occurred_at),
|
|
412
|
-
started_at: null,
|
|
413
|
-
finished_at: null,
|
|
414
|
-
result: null,
|
|
415
|
-
artifact_path: canonicalSource,
|
|
416
|
-
progress: 0,
|
|
417
|
-
spec_id: typeof row.spec_id === "string" ? row.spec_id : null,
|
|
418
|
-
origin: typeof row.origin === "string" ? row.origin : null,
|
|
419
|
-
execution_started: false,
|
|
420
|
-
telemetry: {
|
|
421
|
-
duration_ms: nullableMetric(row.total_duration),
|
|
422
|
-
tokens: nullableMetric(row.total_tokens),
|
|
423
|
-
cost_brl: nullableMetric(row.total_cost_brl),
|
|
424
|
-
},
|
|
425
|
-
});
|
|
426
|
-
const macroProjection = (row: Record<string, unknown>, kind: "prd" | "spec") => {
|
|
427
|
-
const entityUsage = {
|
|
428
|
-
...unavailableUsage,
|
|
429
|
-
tokens: { ...unavailableUsage.tokens, total: nullableMetric(row.total_tokens) },
|
|
430
|
-
cost: { ...unavailableUsage.cost, brl: nullableMetric(row.total_cost_brl) },
|
|
431
|
-
};
|
|
432
|
-
return {
|
|
433
|
-
id: String(row.id),
|
|
434
|
-
title: String(row.title ?? row.id),
|
|
435
|
-
created_at: String(row.occurred_at),
|
|
436
|
-
updated_at: String(row.occurred_at),
|
|
437
|
-
kind,
|
|
438
|
-
parent_id: null,
|
|
439
|
-
artifact_path: canonicalSource,
|
|
440
|
-
lifecycle_status: String(row.status ?? "draft"),
|
|
441
|
-
work_status: normalizeMacroStatus(row.status),
|
|
442
|
-
execution_ids: [],
|
|
443
|
-
task_ids: [],
|
|
444
|
-
planned_tasks: [],
|
|
445
|
-
canonical_run_ids: [],
|
|
446
|
-
run_ids: [],
|
|
447
|
-
root_execution_run_ids: [],
|
|
448
|
-
execution_count: 0,
|
|
449
|
-
task_count: 0,
|
|
450
|
-
run_count: nullableMetric(row.invocation_count) ?? 0,
|
|
451
|
-
duration_ms: nullableMetric(row.total_duration),
|
|
452
|
-
decisions: { human: 0, agent: 0 },
|
|
453
|
-
rework_run_count: 0,
|
|
454
|
-
quality: {
|
|
455
|
-
completed_tasks: 0,
|
|
456
|
-
task_completion_rate: 0,
|
|
457
|
-
terminal_runs: 0,
|
|
458
|
-
successful_runs: 0,
|
|
459
|
-
terminal_success_rate: 0,
|
|
460
|
-
rework_rate: 0,
|
|
461
|
-
},
|
|
462
|
-
usage: {
|
|
463
|
-
conversation: unavailableUsage,
|
|
464
|
-
planning: unavailableUsage,
|
|
465
|
-
execution: unavailableUsage,
|
|
466
|
-
total: entityUsage,
|
|
467
|
-
new_work: unavailableUsage,
|
|
468
|
-
rework: unavailableUsage,
|
|
469
|
-
},
|
|
470
|
-
};
|
|
471
|
-
};
|
|
472
|
-
return {
|
|
473
|
-
schema_version: 2,
|
|
474
|
-
layout_version: layout.version as 2 | 3,
|
|
475
|
-
readonly: true,
|
|
476
|
-
source: canonicalSource,
|
|
477
|
-
filters: filter,
|
|
478
|
-
summary: {
|
|
479
|
-
prd_count: allTime?.aggregate.prd_count ?? prds.length,
|
|
480
|
-
spec_count: allTime?.aggregate.spec_count ?? specs.length,
|
|
481
|
-
execution_count: 0,
|
|
482
|
-
task_count: taskCount,
|
|
483
|
-
run_count: aggregate.total_run_count,
|
|
484
|
-
overview_metrics: {
|
|
485
|
-
duration_ms: aggregate.duration_ms,
|
|
486
|
-
execution_day_count: aggregate.execution_day_count,
|
|
487
|
-
tokens: aggregate.total_tokens,
|
|
488
|
-
cost_brl: aggregate.cost_brl,
|
|
489
|
-
prd_count: allTime?.aggregate.prd_count ?? prds.length,
|
|
490
|
-
spec_count: allTime?.aggregate.spec_count ?? specs.length,
|
|
491
|
-
selected_counts: {
|
|
492
|
-
prds: allTime?.aggregate.prd_count ?? prds.length,
|
|
493
|
-
specs: allTime?.aggregate.spec_count ?? specs.length,
|
|
494
|
-
},
|
|
495
|
-
task_count: taskCount,
|
|
496
|
-
completed_prd_count:
|
|
497
|
-
allTime?.aggregate.completed_prd_count ??
|
|
498
|
-
prds.filter((row) => row.status === "completed").length,
|
|
499
|
-
completed_spec_count:
|
|
500
|
-
allTime?.aggregate.completed_spec_count ??
|
|
501
|
-
specs.filter((row) => row.status === "completed").length,
|
|
502
|
-
completed_task_count: allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0,
|
|
503
|
-
task_status_counts: statuses,
|
|
504
|
-
task_risk_counts: risks,
|
|
505
|
-
top_tasks: topTasks,
|
|
506
|
-
...(macroMetrics === undefined ? {} : { macro_metrics: macroMetrics }),
|
|
507
|
-
latest_task_created_at: latest,
|
|
508
|
-
coverage: { duration: 1, tokens: hasUnknownUsage ? 0 : 1, cost: hasUnknownUsage ? 0 : 1 },
|
|
509
|
-
data_source: "run_records",
|
|
510
|
-
partial: true,
|
|
511
|
-
},
|
|
512
|
-
decisions: { human: 0, agent: 0 },
|
|
513
|
-
source_latest_at: latest,
|
|
514
|
-
quality: {
|
|
515
|
-
completed_tasks: statuses.completed ?? 0,
|
|
516
|
-
task_completion_rate:
|
|
517
|
-
taskCount === 0
|
|
518
|
-
? 0
|
|
519
|
-
: (allTime?.aggregate.completed_task_count ?? statuses.completed ?? 0) / taskCount,
|
|
520
|
-
terminal_runs: 0,
|
|
521
|
-
successful_runs: 0,
|
|
522
|
-
terminal_success_rate: 0,
|
|
523
|
-
rework_rate: 0,
|
|
524
|
-
},
|
|
525
|
-
reconciliation: {
|
|
526
|
-
phase_tokens_match_total: true,
|
|
527
|
-
phase_usd_match_total: true,
|
|
528
|
-
phase_brl_match_total: true,
|
|
529
|
-
origin_tokens_match_total: true,
|
|
530
|
-
},
|
|
531
|
-
usage,
|
|
532
|
-
periods: { daily: options.includePeriods === true ? dailyPeriods : {} },
|
|
533
|
-
},
|
|
534
|
-
origins: { conversation: usage, task: usage, spec: usage, prd: usage },
|
|
535
|
-
prds: prds.map((row) => macroProjection(row, "prd")),
|
|
536
|
-
specs: specs.map((row) => macroProjection(row, "spec")),
|
|
537
|
-
tasks: options.includeBoardTasks ? tasks.map(taskProjection) : [],
|
|
538
|
-
changes: [],
|
|
539
|
-
executions: [],
|
|
540
|
-
runs: [],
|
|
541
|
-
decisions: [],
|
|
542
|
-
evidences: [],
|
|
543
|
-
validations: [],
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
function nullableMetric(value: unknown): number | null {
|
|
548
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
function normalizeTaskStatus(
|
|
552
|
-
value: unknown,
|
|
553
|
-
):
|
|
554
|
-
| "draft"
|
|
555
|
-
| "planned"
|
|
556
|
-
| "executing"
|
|
557
|
-
| "verifying"
|
|
558
|
-
| "completed"
|
|
559
|
-
| "failed"
|
|
560
|
-
| "blocked"
|
|
561
|
-
| "cancelled" {
|
|
562
|
-
return [
|
|
563
|
-
"draft",
|
|
564
|
-
"planned",
|
|
565
|
-
"executing",
|
|
566
|
-
"verifying",
|
|
567
|
-
"completed",
|
|
568
|
-
"failed",
|
|
569
|
-
"blocked",
|
|
570
|
-
"cancelled",
|
|
571
|
-
].includes(String(value))
|
|
572
|
-
? (String(value) as
|
|
573
|
-
| "draft"
|
|
574
|
-
| "planned"
|
|
575
|
-
| "executing"
|
|
576
|
-
| "verifying"
|
|
577
|
-
| "completed"
|
|
578
|
-
| "failed"
|
|
579
|
-
| "blocked"
|
|
580
|
-
| "cancelled")
|
|
581
|
-
: "draft";
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
function normalizeRisk(value: unknown): "lite" | "standard" | "critical" {
|
|
585
|
-
return ["lite", "standard", "critical"].includes(String(value))
|
|
586
|
-
? (String(value) as "lite" | "standard" | "critical")
|
|
587
|
-
: "standard";
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
function normalizeMacroStatus(
|
|
591
|
-
value: unknown,
|
|
592
|
-
): "planning" | "executing" | "verifying" | "completed" | "blocked" | "failed" | "cancelled" {
|
|
593
|
-
const status = String(value);
|
|
594
|
-
if (["executing", "verifying", "completed", "blocked", "failed", "cancelled"].includes(status))
|
|
595
|
-
return status as "executing" | "verifying" | "completed" | "blocked" | "failed" | "cancelled";
|
|
596
|
-
return "planning";
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
async function firstFoldCostSource(
|
|
600
|
-
filesystem: WorkspaceFileSystem,
|
|
601
|
-
filters: Parameters<SqliteReadModelFileSystem["invocationCostRows"]>[0] = {
|
|
602
|
-
from: null,
|
|
603
|
-
to: null,
|
|
604
|
-
},
|
|
605
|
-
): Promise<CostSummarySource> {
|
|
606
|
-
if (filesystem instanceof SqliteReadModelFileSystem) {
|
|
607
|
-
return filesystem.costMonitorSummaryAggregate(filters) as CostSummarySource;
|
|
608
|
-
}
|
|
609
|
-
const daily = await new LifecycleManifestStore(filesystem).readDailyReadModels("overview");
|
|
610
|
-
if (daily === null) throw new Error("Lifecycle daily overview is not initialized");
|
|
611
|
-
return {
|
|
612
|
-
periods: {
|
|
613
|
-
daily: Object.fromEntries(
|
|
614
|
-
Object.entries(daily.days).map(([day, model]) => [day, model.overview]),
|
|
615
|
-
),
|
|
616
|
-
},
|
|
617
|
-
} satisfies CostSummarySource;
|
|
618
|
-
}
|
|
619
138
|
|
|
620
139
|
export function createDashboardApp(
|
|
621
140
|
workspaceRoot = process.env.ZAIP_WORKSPACE ?? process.cwd(),
|
|
@@ -692,6 +211,7 @@ export function createDashboardApp(
|
|
|
692
211
|
aggregateInFlight.clear();
|
|
693
212
|
};
|
|
694
213
|
let observedSnapshotRevision: string | null = null;
|
|
214
|
+
const projectionRefreshDiagnostics = createProjectionRefreshDiagnostics();
|
|
695
215
|
let projectionRefreshInFlight: Promise<void> | null = null;
|
|
696
216
|
let projectionRefreshRequested = false;
|
|
697
217
|
const rebuildProjection = async () => {
|
|
@@ -701,15 +221,35 @@ export function createDashboardApp(
|
|
|
701
221
|
}
|
|
702
222
|
snapshotState = "updating";
|
|
703
223
|
projectionRefreshInFlight = (async () => {
|
|
224
|
+
let passes = 0;
|
|
704
225
|
do {
|
|
705
226
|
projectionRefreshRequested = false;
|
|
706
227
|
await refreshReadModel();
|
|
707
228
|
if (isSqliteSnapshot) sqliteLayout = requireV2Layout(filesystem);
|
|
708
229
|
clearSnapshotCache();
|
|
709
|
-
|
|
230
|
+
passes += 1;
|
|
231
|
+
// Publish a committed generation after a bounded catch-up pass. A
|
|
232
|
+
// busy watcher must not hold `/ready` in `updating` indefinitely.
|
|
233
|
+
} while (projectionRefreshRequested && passes < 2);
|
|
710
234
|
snapshotState = "current";
|
|
235
|
+
projectionRefreshDiagnostics.clear();
|
|
711
236
|
})().finally(() => {
|
|
712
237
|
projectionRefreshInFlight = null;
|
|
238
|
+
// Preserve a source change that arrived during the bounded catch-up.
|
|
239
|
+
// It starts after the committed generation becomes observable, rather
|
|
240
|
+
// than extending the current `updating` state without bound.
|
|
241
|
+
if (projectionRefreshRequested) {
|
|
242
|
+
projectionRefreshRequested = false;
|
|
243
|
+
// Yield a real event-loop turn with `current` exposed before starting
|
|
244
|
+
// another rebuild. `/ready` can then advertise the committed SQLite
|
|
245
|
+
// generation and open tabs can read it coherently.
|
|
246
|
+
const followUp = setTimeout(() => {
|
|
247
|
+
void rebuildProjection().catch((error: unknown) =>
|
|
248
|
+
projectionRefreshDiagnostics.record({ trigger: "source_change", error }),
|
|
249
|
+
);
|
|
250
|
+
}, 250);
|
|
251
|
+
followUp.unref();
|
|
252
|
+
}
|
|
713
253
|
});
|
|
714
254
|
return projectionRefreshInFlight;
|
|
715
255
|
};
|
|
@@ -718,6 +258,10 @@ export function createDashboardApp(
|
|
|
718
258
|
staleSeed: isSqliteSnapshot && snapshotState === "updating",
|
|
719
259
|
watchSources: isSqliteSnapshot && options.watchSources === true,
|
|
720
260
|
refresh: rebuildProjection,
|
|
261
|
+
...(isSqliteSnapshot && options.watchSources === true
|
|
262
|
+
? { captureActiveTelemetry: () => captureActiveCodexTelemetry(workspaceRoot) }
|
|
263
|
+
: {}),
|
|
264
|
+
onRefreshFailure: projectionRefreshDiagnostics.record,
|
|
721
265
|
});
|
|
722
266
|
const reconcileWork = createWorkReconciliation({
|
|
723
267
|
reconcile: (mode) =>
|
|
@@ -726,13 +270,9 @@ export function createDashboardApp(
|
|
|
726
270
|
}),
|
|
727
271
|
refresh: rebuildProjection,
|
|
728
272
|
});
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
process.env.ZAIP_DASHBOARD_WATCH_SOURCES !== "0"
|
|
733
|
-
) {
|
|
734
|
-
startHostTerminalReconciliation(() => reconcileWork("host-terminal"));
|
|
735
|
-
}
|
|
273
|
+
// Terminal usage is persisted by the host/CLI lifecycle boundary. The
|
|
274
|
+
// source synchronizer above projects those records, but the Dashboard must
|
|
275
|
+
// never run lifecycle reconciliation automatically on startup or a timer.
|
|
736
276
|
const readSnapshot = (context: Context) => {
|
|
737
277
|
const key = snapshotKey(context);
|
|
738
278
|
const cached = cachedSnapshots.get(key);
|
|
@@ -758,7 +298,6 @@ export function createDashboardApp(
|
|
|
758
298
|
snapshotInFlight.set(key, inFlight);
|
|
759
299
|
return inFlight;
|
|
760
300
|
};
|
|
761
|
-
|
|
762
301
|
app.use("*", async (context, next) => {
|
|
763
302
|
if (!isAllowedDashboardAuthority(context.req.url, context.req.header("host"))) {
|
|
764
303
|
return context.json({ error: "Host rejected" }, 403);
|
|
@@ -779,7 +318,6 @@ export function createDashboardApp(
|
|
|
779
318
|
}
|
|
780
319
|
return next();
|
|
781
320
|
});
|
|
782
|
-
|
|
783
321
|
app.use(`${API_PREFIX}/*`, async (context, next) => {
|
|
784
322
|
const settingsWrite =
|
|
785
323
|
context.req.method === "PUT" &&
|
|
@@ -824,7 +362,6 @@ export function createDashboardApp(
|
|
|
824
362
|
}
|
|
825
363
|
if (context.req.path === `${API_PREFIX}/health` || context.req.path === `${API_PREFIX}/ready`)
|
|
826
364
|
return next();
|
|
827
|
-
|
|
828
365
|
const origin = context.req.header("origin");
|
|
829
366
|
if (origin !== undefined && !isAllowedOrigin(origin)) {
|
|
830
367
|
return context.json({ error: "Origin rejected" }, 403);
|
|
@@ -853,7 +390,6 @@ export function createDashboardApp(
|
|
|
853
390
|
return next();
|
|
854
391
|
});
|
|
855
392
|
registerBrowserLeaseRoute(app, API_PREFIX, options.launcherOwned === true);
|
|
856
|
-
|
|
857
393
|
app.on(["GET", "HEAD"], `${API_PREFIX}/health`, async (context) => {
|
|
858
394
|
try {
|
|
859
395
|
const layout = await readLayout();
|
|
@@ -861,12 +397,13 @@ export function createDashboardApp(
|
|
|
861
397
|
kind: RUNTIME_KIND,
|
|
862
398
|
workspaceKey,
|
|
863
399
|
service: "zaip-aios-dashboard",
|
|
864
|
-
status:
|
|
400
|
+
status: projectionRefreshDiagnostics.healthStatus,
|
|
865
401
|
api_version: 2,
|
|
866
402
|
workspace_layout: layout.version,
|
|
867
403
|
read_only: true,
|
|
868
404
|
storage: isSqliteSnapshot ? filesystem.metadata() : { storage_mode: "filesystem" },
|
|
869
405
|
snapshot_state: snapshotState,
|
|
406
|
+
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
870
407
|
});
|
|
871
408
|
} catch (error) {
|
|
872
409
|
return headOrJson(
|
|
@@ -884,7 +421,6 @@ export function createDashboardApp(
|
|
|
884
421
|
);
|
|
885
422
|
}
|
|
886
423
|
});
|
|
887
|
-
|
|
888
424
|
// Launcher readiness proves a canonical projection can be read; health alone
|
|
889
425
|
// intentionally remains a lightweight process/layout probe.
|
|
890
426
|
app.on(["GET", "HEAD"], `${API_PREFIX}/ready`, async (context) => {
|
|
@@ -913,6 +449,7 @@ export function createDashboardApp(
|
|
|
913
449
|
// /ready must never start a competing projection in the background.
|
|
914
450
|
day_count: metadata.daily_aggregate_count,
|
|
915
451
|
snapshot_state: snapshotState,
|
|
452
|
+
projection_refresh_failure: projectionRefreshDiagnostics.failure,
|
|
916
453
|
snapshot_revision: revision,
|
|
917
454
|
});
|
|
918
455
|
}
|
|
@@ -939,321 +476,21 @@ export function createDashboardApp(
|
|
|
939
476
|
);
|
|
940
477
|
}
|
|
941
478
|
});
|
|
942
|
-
|
|
943
479
|
// Header identity is intentionally separate from Operations projections.
|
|
944
480
|
// The quick first fold omits it, and resolving this small configuration/git
|
|
945
481
|
// value must not read, refresh, or otherwise materialize a snapshot.
|
|
946
482
|
app.on(["GET", "HEAD"], `${API_PREFIX}/dashboard-identity`, async (context) =>
|
|
947
483
|
headOrJson(context, await dashboardIdentity(filesystem, workspaceRoot)),
|
|
948
484
|
);
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
scope !== "detail" &&
|
|
958
|
-
scope !== "board" &&
|
|
959
|
-
scope !== "classification"
|
|
960
|
-
)
|
|
961
|
-
return headOrJson(context, (await readSnapshot(context)).operations);
|
|
962
|
-
const layout = await readLayout();
|
|
963
|
-
const layoutMs = performance.now() - requestStartedAt;
|
|
964
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
965
|
-
if (scope === "board") {
|
|
966
|
-
const stage = boardStage(context.req.query("stage"));
|
|
967
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
968
|
-
const limit = Math.min(
|
|
969
|
-
50,
|
|
970
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "10", 10) || 10),
|
|
971
|
-
);
|
|
972
|
-
const board = await readAggregate(
|
|
973
|
-
`operations:board:${from ?? ""}:${to ?? ""}`,
|
|
974
|
-
async () => {
|
|
975
|
-
const projection = await buildFirstFoldQuickProjection(
|
|
976
|
-
filesystem,
|
|
977
|
-
layout,
|
|
978
|
-
{ from, to },
|
|
979
|
-
{ includeBoardTasks: true },
|
|
980
|
-
);
|
|
981
|
-
return {
|
|
982
|
-
projection,
|
|
983
|
-
priority: await readWorkPriority(canonicalFilesystem, knownWorkIds(projection)),
|
|
984
|
-
};
|
|
985
|
-
},
|
|
986
|
-
);
|
|
987
|
-
const filters = boardFilters(context);
|
|
988
|
-
const pageKey = JSON.stringify({ from, to, stage, offset, limit, ...filters });
|
|
989
|
-
const page = await readAggregate(`operations:board-page:${pageKey}`, async () =>
|
|
990
|
-
boardPage(board.projection, stage, offset, limit, board.priority.item_ids, filters),
|
|
991
|
-
);
|
|
992
|
-
return headOrJson(context, page, 200, true);
|
|
993
|
-
}
|
|
994
|
-
if (scope === "classification") {
|
|
995
|
-
const kind = context.req.query("kind");
|
|
996
|
-
const classification = context.req.query("classification");
|
|
997
|
-
if (kind !== "task" && kind !== "spec" && kind !== "prd")
|
|
998
|
-
return headOrJson(context, { error: "A valid work kind is required" }, 400);
|
|
999
|
-
if (
|
|
1000
|
-
!["lite", "standard", "critical", "empty", "structured", "rework"].includes(
|
|
1001
|
-
classification ?? "",
|
|
1002
|
-
)
|
|
1003
|
-
)
|
|
1004
|
-
return headOrJson(context, { error: "A valid classification is required" }, 400);
|
|
1005
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1006
|
-
const limit = Math.min(
|
|
1007
|
-
50,
|
|
1008
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "50", 10) || 50),
|
|
1009
|
-
);
|
|
1010
|
-
const projection = await readAggregate(
|
|
1011
|
-
`operations:classification:${from ?? ""}:${to ?? ""}`,
|
|
1012
|
-
() =>
|
|
1013
|
-
buildFirstFoldQuickProjection(
|
|
1014
|
-
filesystem,
|
|
1015
|
-
layout,
|
|
1016
|
-
{ from, to },
|
|
1017
|
-
{ includeBoardTasks: true },
|
|
1018
|
-
),
|
|
1019
|
-
);
|
|
1020
|
-
return headOrJson(
|
|
1021
|
-
context,
|
|
1022
|
-
classificationPage(
|
|
1023
|
-
projection,
|
|
1024
|
-
kind,
|
|
1025
|
-
classification as BoardClassification,
|
|
1026
|
-
offset,
|
|
1027
|
-
limit,
|
|
1028
|
-
),
|
|
1029
|
-
200,
|
|
1030
|
-
true,
|
|
1031
|
-
);
|
|
1032
|
-
}
|
|
1033
|
-
if (scope === "quick") {
|
|
1034
|
-
const projectionStartedAt = performance.now();
|
|
1035
|
-
const quick = await readAggregate(
|
|
1036
|
-
`operations:quick:${from ?? ""}:${to ?? ""}`,
|
|
1037
|
-
() =>
|
|
1038
|
-
buildFirstFoldQuickProjection(
|
|
1039
|
-
filesystem,
|
|
1040
|
-
layout,
|
|
1041
|
-
{ from, to },
|
|
1042
|
-
{
|
|
1043
|
-
includeTopTasks: from === null && to === null,
|
|
1044
|
-
includeExtended: from === null && to === null,
|
|
1045
|
-
},
|
|
1046
|
-
),
|
|
1047
|
-
context.req.query("fresh") === "1",
|
|
1048
|
-
);
|
|
1049
|
-
if (
|
|
1050
|
-
process.env.ZAIP_DASHBOARD_PROFILE_FIRST_FOLD === "1" &&
|
|
1051
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1052
|
-
) {
|
|
1053
|
-
const timings = filesystem.firstFoldViewportProfile();
|
|
1054
|
-
context.header(
|
|
1055
|
-
"Server-Timing",
|
|
1056
|
-
[
|
|
1057
|
-
`layout;dur=${Math.round(layoutMs * 10) / 10}`,
|
|
1058
|
-
`projection;dur=${Math.round((performance.now() - projectionStartedAt) * 10) / 10}`,
|
|
1059
|
-
...Object.entries(timings).map(([name, duration]) => `${name};dur=${duration}`),
|
|
1060
|
-
].join(", "),
|
|
1061
|
-
);
|
|
1062
|
-
}
|
|
1063
|
-
return headOrJson(context, quick, 200, true);
|
|
1064
|
-
}
|
|
1065
|
-
const projection =
|
|
1066
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1067
|
-
? await buildFirstFoldQuickProjection(
|
|
1068
|
-
filesystem,
|
|
1069
|
-
layout,
|
|
1070
|
-
{ from, to },
|
|
1071
|
-
{
|
|
1072
|
-
includeBoardTasks: scope === "detail",
|
|
1073
|
-
includeExtended: scope === "detail" || scope === "overview",
|
|
1074
|
-
includePeriods: scope === "detail" || scope === "overview",
|
|
1075
|
-
},
|
|
1076
|
-
)
|
|
1077
|
-
: await buildCanonicalOperationsProjection(
|
|
1078
|
-
filesystem,
|
|
1079
|
-
layout,
|
|
1080
|
-
{ from, to },
|
|
1081
|
-
scope === "overview",
|
|
1082
|
-
);
|
|
1083
|
-
return headOrJson(context, projection, 200, scope === "overview");
|
|
1084
|
-
} catch (error) {
|
|
1085
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1086
|
-
return headOrJson(
|
|
1087
|
-
context,
|
|
1088
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1089
|
-
400,
|
|
1090
|
-
);
|
|
1091
|
-
}
|
|
485
|
+
registerOperationsRoutes(app, {
|
|
486
|
+
filesystem,
|
|
487
|
+
canonicalFilesystem,
|
|
488
|
+
isSqliteSnapshot,
|
|
489
|
+
readLayout,
|
|
490
|
+
readSnapshot,
|
|
491
|
+
readAggregate,
|
|
492
|
+
clearSnapshotCache,
|
|
1092
493
|
});
|
|
1093
|
-
|
|
1094
|
-
registerOperationsRunsRoute(app, filesystem, readAggregate, headOrJson);
|
|
1095
|
-
|
|
1096
|
-
// Explicit SQL read-model API for the comparison dashboard. It never falls
|
|
1097
|
-
// back to filesystem pagination, making first-fold/entity query plans
|
|
1098
|
-
// inspectable while preserving the established Operations contracts.
|
|
1099
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/sqlite-read-models`, async (context) => {
|
|
1100
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1101
|
-
return headOrJson(context, { error: "SQLite read model is not active" }, 409);
|
|
1102
|
-
const kind = context.req.query("kind");
|
|
1103
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1104
|
-
const limit = Math.min(
|
|
1105
|
-
200,
|
|
1106
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "20", 10) || 20),
|
|
1107
|
-
);
|
|
1108
|
-
if (kind === "overview") {
|
|
1109
|
-
const period = context.req.query("period");
|
|
1110
|
-
if (period !== "day" && period !== "month" && period !== "year")
|
|
1111
|
-
return headOrJson(context, { error: "Unsupported SQLite overview period" }, 400);
|
|
1112
|
-
return headOrJson(context, filesystem.overviewPage(period, offset, limit), 200, true);
|
|
1113
|
-
}
|
|
1114
|
-
if (kind !== "task" && kind !== "spec" && kind !== "prd")
|
|
1115
|
-
return headOrJson(context, { error: "Unsupported SQLite read model" }, 400);
|
|
1116
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1117
|
-
const filters = operationsPageFilters(context);
|
|
1118
|
-
return headOrJson(
|
|
1119
|
-
context,
|
|
1120
|
-
filesystem.summaryPage(
|
|
1121
|
-
kind,
|
|
1122
|
-
{ from, to, ...filters },
|
|
1123
|
-
offset,
|
|
1124
|
-
limit,
|
|
1125
|
-
context.req.query("cursor") ?? null,
|
|
1126
|
-
),
|
|
1127
|
-
200,
|
|
1128
|
-
true,
|
|
1129
|
-
);
|
|
1130
|
-
});
|
|
1131
|
-
|
|
1132
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/sqlite-views`, async (context) => {
|
|
1133
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1134
|
-
return headOrJson(context, { error: "SQLite read model is not active" }, 409);
|
|
1135
|
-
const view = context.req.query("view");
|
|
1136
|
-
if (view === undefined || !(view in sqliteViewMetadata))
|
|
1137
|
-
return headOrJson(context, { error: "Unsupported SQLite view" }, 400);
|
|
1138
|
-
const parsed = Number.parseInt(context.req.query("limit") ?? "", 10);
|
|
1139
|
-
const defaultLimit = view.includes("agent_invocations")
|
|
1140
|
-
? 100
|
|
1141
|
-
: view === "first_fold_top_tasks"
|
|
1142
|
-
? 5
|
|
1143
|
-
: 50;
|
|
1144
|
-
const limit = Math.min(200, Math.max(1, Number.isFinite(parsed) ? parsed : defaultLimit));
|
|
1145
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1146
|
-
const optional = (name: string) => {
|
|
1147
|
-
const value = context.req.query(name);
|
|
1148
|
-
return value === undefined ? {} : { [name]: value };
|
|
1149
|
-
};
|
|
1150
|
-
const workListKind = context.req.query("kind");
|
|
1151
|
-
if (
|
|
1152
|
-
view === "operations_work_list" &&
|
|
1153
|
-
workListKind !== undefined &&
|
|
1154
|
-
!["all", "task", "standalone-task", "prd", "spec"].includes(workListKind)
|
|
1155
|
-
)
|
|
1156
|
-
return headOrJson(context, { error: "Unsupported Operations work-list kind" }, 400);
|
|
1157
|
-
return headOrJson(
|
|
1158
|
-
context,
|
|
1159
|
-
filesystem.viewPage(view as keyof typeof sqliteViewMetadata, {
|
|
1160
|
-
from,
|
|
1161
|
-
to,
|
|
1162
|
-
...optional("query"),
|
|
1163
|
-
...optional("status"),
|
|
1164
|
-
...optional("risk"),
|
|
1165
|
-
...optional("provider"),
|
|
1166
|
-
...optional("model"),
|
|
1167
|
-
...optional("agent"),
|
|
1168
|
-
...optional("phase"),
|
|
1169
|
-
...optional("origin"),
|
|
1170
|
-
...optional("workType"),
|
|
1171
|
-
...optional("priority"),
|
|
1172
|
-
...(workListKind === undefined
|
|
1173
|
-
? {}
|
|
1174
|
-
: { kind: workListKind as "all" | "task" | "standalone-task" | "prd" | "spec" }),
|
|
1175
|
-
offset: Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0),
|
|
1176
|
-
limit,
|
|
1177
|
-
}),
|
|
1178
|
-
200,
|
|
1179
|
-
true,
|
|
1180
|
-
);
|
|
1181
|
-
});
|
|
1182
|
-
|
|
1183
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/work-priority`, async (context) => {
|
|
1184
|
-
const layout = await requireV2Layout(canonicalFilesystem);
|
|
1185
|
-
const operations = await buildOperationsProjection(canonicalFilesystem, layout, {
|
|
1186
|
-
from: null,
|
|
1187
|
-
to: null,
|
|
1188
|
-
});
|
|
1189
|
-
return headOrJson(
|
|
1190
|
-
context,
|
|
1191
|
-
await readWorkPriority(canonicalFilesystem, knownWorkIds(operations)),
|
|
1192
|
-
);
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/operations/entities`, async (context) => {
|
|
1196
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1197
|
-
const limit = Math.min(
|
|
1198
|
-
500,
|
|
1199
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "100", 10) || 100),
|
|
1200
|
-
);
|
|
1201
|
-
const kind = context.req.query("kind");
|
|
1202
|
-
if (kind !== "changes" && kind !== "decisions")
|
|
1203
|
-
return headOrJson(context, { error: "Unsupported Operations entity page" }, 400);
|
|
1204
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1205
|
-
const pageFilters = operationsPageFilters(context);
|
|
1206
|
-
const payload = await readAggregate(
|
|
1207
|
-
`operations:entities:${kind}:${from ?? ""}:${to ?? ""}:${offset}:${limit}:${pageFilters.query}:${pageFilters.status}:${pageFilters.risk}`,
|
|
1208
|
-
async () => {
|
|
1209
|
-
const layout = await readLayout();
|
|
1210
|
-
const entities = await new LifecycleManifestStore(filesystem).readEntities(
|
|
1211
|
-
kind === "changes" ? "change" : "decision",
|
|
1212
|
-
);
|
|
1213
|
-
const entityRows =
|
|
1214
|
-
kind === "changes"
|
|
1215
|
-
? changeEntityPageRows(entities, layout, from, to)
|
|
1216
|
-
: decisionEntityPageRows(entities, layout, from, to);
|
|
1217
|
-
const rows = filterLifecyclePageRows(entityRows, pageFilters);
|
|
1218
|
-
return {
|
|
1219
|
-
data_source: "lifecycle_manifest_shards",
|
|
1220
|
-
kind,
|
|
1221
|
-
offset,
|
|
1222
|
-
limit,
|
|
1223
|
-
total: rows.length,
|
|
1224
|
-
rows: rows.slice(offset, offset + limit),
|
|
1225
|
-
};
|
|
1226
|
-
},
|
|
1227
|
-
);
|
|
1228
|
-
return headOrJson(context, payload, 200, true);
|
|
1229
|
-
});
|
|
1230
|
-
|
|
1231
|
-
registerDailyReadModelRoute(app, filesystem, readAggregate, headOrJson);
|
|
1232
|
-
app.put(`${API_PREFIX}/work-priority`, async (context) => {
|
|
1233
|
-
const candidate = normalizeWorkPriority(await context.req.json());
|
|
1234
|
-
// Priority is canonical queue configuration, never snapshot content.
|
|
1235
|
-
// Keep every other settings mutation blocked in snapshot-serving mode.
|
|
1236
|
-
await canonicalFilesystem.writeTextAtomic(
|
|
1237
|
-
WORK_PRIORITY_PATH,
|
|
1238
|
-
`${JSON.stringify(candidate, null, 2)}\n`,
|
|
1239
|
-
);
|
|
1240
|
-
clearSnapshotCache();
|
|
1241
|
-
return context.json(candidate);
|
|
1242
|
-
});
|
|
1243
|
-
|
|
1244
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/snapshot`, async (context) => {
|
|
1245
|
-
try {
|
|
1246
|
-
return headOrJson(context, await readSnapshot(context));
|
|
1247
|
-
} catch (error) {
|
|
1248
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1249
|
-
return headOrJson(
|
|
1250
|
-
context,
|
|
1251
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1252
|
-
400,
|
|
1253
|
-
);
|
|
1254
|
-
}
|
|
1255
|
-
});
|
|
1256
|
-
|
|
1257
494
|
app.post(`${API_PREFIX}/reconcile-open-work`, async (context) => {
|
|
1258
495
|
try {
|
|
1259
496
|
await readLayout();
|
|
@@ -1286,7 +523,6 @@ export function createDashboardApp(
|
|
|
1286
523
|
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1287
524
|
}
|
|
1288
525
|
});
|
|
1289
|
-
|
|
1290
526
|
app.post(`${API_PREFIX}/refresh-projection`, async (context) => {
|
|
1291
527
|
try {
|
|
1292
528
|
await readLayout();
|
|
@@ -1297,151 +533,15 @@ export function createDashboardApp(
|
|
|
1297
533
|
return context.json({ error: error instanceof Error ? error.message : String(error) }, 400);
|
|
1298
534
|
}
|
|
1299
535
|
});
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
const aggregateStartedAt = performance.now();
|
|
1309
|
-
const [source, rate] = await Promise.all([
|
|
1310
|
-
firstFoldCostSource(filesystem, {
|
|
1311
|
-
from,
|
|
1312
|
-
to,
|
|
1313
|
-
providers: queryValues(context, "provider"),
|
|
1314
|
-
models: queryValues(context, "model"),
|
|
1315
|
-
agents: queryValues(context, "agent"),
|
|
1316
|
-
phases: queryValues(context, "phase"),
|
|
1317
|
-
statuses: queryValues(context, "status"),
|
|
1318
|
-
tasks: queryValues(context, "task"),
|
|
1319
|
-
specs: queryValues(context, "spec"),
|
|
1320
|
-
prds: queryValues(context, "prd"),
|
|
1321
|
-
executions: queryValues(context, "execution"),
|
|
1322
|
-
changes: queryValues(context, "change"),
|
|
1323
|
-
}),
|
|
1324
|
-
currency === "BRL" ? readCurrentFxRate(filesystem) : Promise.resolve(null),
|
|
1325
|
-
]);
|
|
1326
|
-
// First fold receives only aggregate facts. Detailed Runs and entity
|
|
1327
|
-
// arrays remain on their explicit paginated endpoints.
|
|
1328
|
-
const aggregateMs = performance.now() - aggregateStartedAt;
|
|
1329
|
-
const costOperations = {
|
|
1330
|
-
schema_version: 1,
|
|
1331
|
-
layout_version: layout.version,
|
|
1332
|
-
readonly: true,
|
|
1333
|
-
source: ".agents/records",
|
|
1334
|
-
filters: { from, to },
|
|
1335
|
-
summary: { task_count: source.task_count ?? 0 },
|
|
1336
|
-
prds: [],
|
|
1337
|
-
specs: [],
|
|
1338
|
-
runs: [],
|
|
1339
|
-
} as unknown as OperationsProjection;
|
|
1340
|
-
const projectionStartedAt = performance.now();
|
|
1341
|
-
const payload = buildCostSummaryProjection(
|
|
1342
|
-
source,
|
|
1343
|
-
costOperations,
|
|
1344
|
-
currency,
|
|
1345
|
-
rate?.rate ?? null,
|
|
1346
|
-
);
|
|
1347
|
-
context.header(
|
|
1348
|
-
"Server-Timing",
|
|
1349
|
-
`cost_sql;dur=${aggregateMs.toFixed(1)},cost_projection;dur=${(performance.now() - projectionStartedAt).toFixed(1)}`,
|
|
1350
|
-
);
|
|
1351
|
-
return headOrJson(context, payload, 200, true);
|
|
1352
|
-
}
|
|
1353
|
-
if (scope === "runs") {
|
|
1354
|
-
const layout = await readLayout();
|
|
1355
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1356
|
-
const offset = Math.max(0, Number.parseInt(context.req.query("offset") ?? "0", 10) || 0);
|
|
1357
|
-
const limit = Math.min(
|
|
1358
|
-
500,
|
|
1359
|
-
Math.max(1, Number.parseInt(context.req.query("limit") ?? "100", 10) || 100),
|
|
1360
|
-
);
|
|
1361
|
-
return headOrJson(
|
|
1362
|
-
context,
|
|
1363
|
-
// The paged Cost adapter reads the lifecycle summary. That canonical
|
|
1364
|
-
// artifact is intentionally not copied into SQLite; use its current
|
|
1365
|
-
// filesystem alongside the immutable SQL facts rather than failing
|
|
1366
|
-
// a filtered page with a synthetic missing-file error.
|
|
1367
|
-
await buildManifestCostRunPage(
|
|
1368
|
-
isSqliteSnapshot ? canonicalFilesystem : filesystem,
|
|
1369
|
-
layout,
|
|
1370
|
-
context,
|
|
1371
|
-
{ from, to },
|
|
1372
|
-
offset,
|
|
1373
|
-
limit,
|
|
1374
|
-
),
|
|
1375
|
-
200,
|
|
1376
|
-
true,
|
|
1377
|
-
);
|
|
1378
|
-
}
|
|
1379
|
-
if (isUnfilteredCostRequest(context))
|
|
1380
|
-
return headOrJson(context, (await readSnapshot(context)).costs);
|
|
1381
|
-
const layout = await readLayout();
|
|
1382
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1383
|
-
// Cost and Operations must start from the same manifest-corrected Run
|
|
1384
|
-
// population; financial availability is represented on each row, never
|
|
1385
|
-
// by dropping lifecycle Runs before the Cost projection.
|
|
1386
|
-
const operations = await buildCanonicalOperationsProjection(filesystem, layout, { from, to });
|
|
1387
|
-
return headOrJson(
|
|
1388
|
-
context,
|
|
1389
|
-
await buildManifestFirstCostProjection(filesystem, operations, context),
|
|
1390
|
-
);
|
|
1391
|
-
} catch (error) {
|
|
1392
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1393
|
-
return headOrJson(
|
|
1394
|
-
context,
|
|
1395
|
-
{ error: error instanceof Error ? error.message : String(error) },
|
|
1396
|
-
400,
|
|
1397
|
-
);
|
|
1398
|
-
}
|
|
1399
|
-
});
|
|
1400
|
-
|
|
1401
|
-
/** Compact factual attribution view used by both Cost Monitor and Operations.
|
|
1402
|
-
* It is intentionally read-only and is available only from a coherent SQLite
|
|
1403
|
-
* generation, never by reopening mutable JSONL streams on a request. */
|
|
1404
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/developers`, async (context) => {
|
|
1405
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1406
|
-
return headOrJson(
|
|
1407
|
-
context,
|
|
1408
|
-
{ error: "Developer attribution requires the SQLite read model" },
|
|
1409
|
-
409,
|
|
1410
|
-
);
|
|
1411
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1412
|
-
return headOrJson(
|
|
1413
|
-
context,
|
|
1414
|
-
filesystem.developerCostAggregate({
|
|
1415
|
-
from,
|
|
1416
|
-
to,
|
|
1417
|
-
accountIds: queryValues(context, "account_id"),
|
|
1418
|
-
}),
|
|
1419
|
-
200,
|
|
1420
|
-
true,
|
|
1421
|
-
);
|
|
536
|
+
registerCostsRoutes(app, {
|
|
537
|
+
filesystem,
|
|
538
|
+
canonicalFilesystem,
|
|
539
|
+
isSqliteSnapshot,
|
|
540
|
+
readLayout,
|
|
541
|
+
readSnapshot,
|
|
542
|
+
readAggregate,
|
|
543
|
+
clearSnapshotCache,
|
|
1422
544
|
});
|
|
1423
|
-
|
|
1424
|
-
/** Operations keeps its developer facts separate from Cost Monitor columns. */
|
|
1425
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/operations/developers`, async (context) => {
|
|
1426
|
-
if (!(filesystem instanceof SqliteReadModelFileSystem))
|
|
1427
|
-
return headOrJson(
|
|
1428
|
-
context,
|
|
1429
|
-
{ error: "Developer attribution requires the SQLite read model" },
|
|
1430
|
-
409,
|
|
1431
|
-
);
|
|
1432
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1433
|
-
return headOrJson(
|
|
1434
|
-
context,
|
|
1435
|
-
filesystem.operationsDeveloperAggregate({
|
|
1436
|
-
from,
|
|
1437
|
-
to,
|
|
1438
|
-
accountIds: queryValues(context, "account_id"),
|
|
1439
|
-
}),
|
|
1440
|
-
200,
|
|
1441
|
-
true,
|
|
1442
|
-
);
|
|
1443
|
-
});
|
|
1444
|
-
|
|
1445
545
|
app.on(["GET", "HEAD"], `${API_PREFIX}/pricing`, async (context) =>
|
|
1446
546
|
headOrJson(
|
|
1447
547
|
context,
|
|
@@ -1450,7 +550,6 @@ export function createDashboardApp(
|
|
|
1450
550
|
),
|
|
1451
551
|
),
|
|
1452
552
|
);
|
|
1453
|
-
|
|
1454
553
|
app.put(`${API_PREFIX}/pricing`, async (context) => {
|
|
1455
554
|
const catalog = pricingCatalogSchema.parse({
|
|
1456
555
|
...(await context.req.json()),
|
|
@@ -1463,19 +562,16 @@ export function createDashboardApp(
|
|
|
1463
562
|
clearSnapshotCache();
|
|
1464
563
|
return context.json(catalog);
|
|
1465
564
|
});
|
|
1466
|
-
|
|
1467
565
|
app.on(["GET", "HEAD"], `${API_PREFIX}/fx-rate`, async (context) => {
|
|
1468
566
|
const rate = await new PricingRepository(filesystem).readLatestFxRate();
|
|
1469
567
|
return headOrJson(context, rate);
|
|
1470
568
|
});
|
|
1471
|
-
|
|
1472
569
|
app.put(`${API_PREFIX}/fx-rate`, async (context) => {
|
|
1473
570
|
const input = fxRateSchema.pick({ rate: true }).parse(await context.req.json());
|
|
1474
571
|
const rate = await new PricingRepository(filesystem).writeCurrentFxRate(input.rate);
|
|
1475
572
|
clearSnapshotCache();
|
|
1476
573
|
return context.json(rate);
|
|
1477
574
|
});
|
|
1478
|
-
|
|
1479
575
|
app.on(["GET", "HEAD"], `${API_PREFIX}/agent-catalog`, async (context) => {
|
|
1480
576
|
try {
|
|
1481
577
|
return headOrJson(context, await readAgentCatalogSettings(filesystem));
|
|
@@ -1487,7 +583,6 @@ export function createDashboardApp(
|
|
|
1487
583
|
);
|
|
1488
584
|
}
|
|
1489
585
|
});
|
|
1490
|
-
|
|
1491
586
|
app.get(`${API_PREFIX}/agent-catalog-assets/:agentId`, async (context) => {
|
|
1492
587
|
const portrait = agentPortraitFiles[context.req.param("agentId")];
|
|
1493
588
|
if (portrait === undefined) return context.json({ error: "Agent portrait not found" }, 404);
|
|
@@ -1504,7 +599,6 @@ export function createDashboardApp(
|
|
|
1504
599
|
return context.json({ error: "Agent portrait could not be read" }, 500);
|
|
1505
600
|
}
|
|
1506
601
|
});
|
|
1507
|
-
|
|
1508
602
|
app.put(`${API_PREFIX}/agent-catalog`, async (context) => {
|
|
1509
603
|
const update = async () => {
|
|
1510
604
|
try {
|
|
@@ -1529,7 +623,6 @@ export function createDashboardApp(
|
|
|
1529
623
|
);
|
|
1530
624
|
return result;
|
|
1531
625
|
});
|
|
1532
|
-
|
|
1533
626
|
app.on(["GET", "HEAD"], `${API_PREFIX}/project-settings`, async (context) => {
|
|
1534
627
|
try {
|
|
1535
628
|
return headOrJson(context, await readProjectSettings(canonicalFilesystem));
|
|
@@ -1541,11 +634,9 @@ export function createDashboardApp(
|
|
|
1541
634
|
);
|
|
1542
635
|
}
|
|
1543
636
|
});
|
|
1544
|
-
|
|
1545
637
|
app.on(["GET", "HEAD"], `${API_PREFIX}/project-settings/overview`, async (context) => {
|
|
1546
638
|
return headOrJson(context, await readProjectOverview(canonicalFilesystem));
|
|
1547
639
|
});
|
|
1548
|
-
|
|
1549
640
|
app.put(`${API_PREFIX}/project-settings`, async (context) => {
|
|
1550
641
|
try {
|
|
1551
642
|
const persisted = await persistProjectSettings(canonicalFilesystem, await context.req.json());
|
|
@@ -1558,53 +649,15 @@ export function createDashboardApp(
|
|
|
1558
649
|
);
|
|
1559
650
|
}
|
|
1560
651
|
});
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
}
|
|
1570
|
-
});
|
|
1571
|
-
|
|
1572
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/prds/:id`, async (context) => {
|
|
1573
|
-
try {
|
|
1574
|
-
const layout = await readLayout();
|
|
1575
|
-
return headOrJson(context, await readPrdDetail(filesystem, layout, context.req.param("id")));
|
|
1576
|
-
} catch (error) {
|
|
1577
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1578
|
-
return headOrJson(context, { error: "PRD not found" }, 404);
|
|
1579
|
-
}
|
|
1580
|
-
});
|
|
1581
|
-
|
|
1582
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/specs/:id`, async (context) => {
|
|
1583
|
-
try {
|
|
1584
|
-
const layout = await readLayout();
|
|
1585
|
-
return headOrJson(context, await readSpecDetail(filesystem, layout, context.req.param("id")));
|
|
1586
|
-
} catch (error) {
|
|
1587
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1588
|
-
return headOrJson(context, { error: "SPEC not found" }, 404);
|
|
1589
|
-
}
|
|
1590
|
-
});
|
|
1591
|
-
|
|
1592
|
-
app.on(["GET", "HEAD"], `${API_PREFIX}/tasks/:id/trace`, async (context) => {
|
|
1593
|
-
try {
|
|
1594
|
-
const layout = await readLayout();
|
|
1595
|
-
const taskId = context.req.param("id");
|
|
1596
|
-
return headOrJson(
|
|
1597
|
-
context,
|
|
1598
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1599
|
-
? buildSqliteTaskTrace(filesystem, layout, taskId)
|
|
1600
|
-
: await buildTaskTrace(filesystem, layout, taskId),
|
|
1601
|
-
);
|
|
1602
|
-
} catch (error) {
|
|
1603
|
-
if (error instanceof V2WorkspaceRequiredError) throw error;
|
|
1604
|
-
return headOrJson(context, { error: "Task trace not found" }, 404);
|
|
1605
|
-
}
|
|
652
|
+
registerTraceRoutes(app, {
|
|
653
|
+
filesystem,
|
|
654
|
+
canonicalFilesystem,
|
|
655
|
+
isSqliteSnapshot,
|
|
656
|
+
readLayout,
|
|
657
|
+
readSnapshot,
|
|
658
|
+
readAggregate,
|
|
659
|
+
clearSnapshotCache,
|
|
1606
660
|
});
|
|
1607
|
-
|
|
1608
661
|
app.onError((error, context) => {
|
|
1609
662
|
const status = error instanceof V2WorkspaceRequiredError ? 409 : 500;
|
|
1610
663
|
return headOrJson(
|
|
@@ -1613,9 +666,7 @@ export function createDashboardApp(
|
|
|
1613
666
|
status,
|
|
1614
667
|
);
|
|
1615
668
|
});
|
|
1616
|
-
|
|
1617
669
|
app.all(`${API_PREFIX}/*`, (context) => headOrJson(context, { error: "Not found" }, 404));
|
|
1618
|
-
|
|
1619
670
|
app.on(["GET", "HEAD"], "/", serveStatic({ path: `${uiRoot}/index.html` }));
|
|
1620
671
|
app.use("/*", async (context, next) => {
|
|
1621
672
|
if (!isSafeUiPath(context.req.path)) {
|
|
@@ -1628,45 +679,10 @@ export function createDashboardApp(
|
|
|
1628
679
|
return app;
|
|
1629
680
|
}
|
|
1630
681
|
|
|
1631
|
-
async function dashboardSnapshot(
|
|
1632
|
-
filesystem: WorkspaceFileSystem,
|
|
1633
|
-
workspaceRoot: string,
|
|
1634
|
-
context: Context,
|
|
1635
|
-
cachedLayout?: WorkspaceLayout,
|
|
1636
|
-
) {
|
|
1637
|
-
const layout = cachedLayout ?? (await requireV2Layout(filesystem));
|
|
1638
|
-
const { from, to } = projectionPeriodFilter(context);
|
|
1639
|
-
const currency = selectedCurrency(context);
|
|
1640
|
-
const operations =
|
|
1641
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1642
|
-
? await buildFirstFoldQuickProjection(filesystem, layout, { from, to })
|
|
1643
|
-
: await buildCanonicalOperationsProjection(filesystem, layout, { from, to });
|
|
1644
|
-
const costs =
|
|
1645
|
-
filesystem instanceof SqliteReadModelFileSystem
|
|
1646
|
-
? buildCostSummaryProjection(
|
|
1647
|
-
await firstFoldCostSource(filesystem, { from, to }),
|
|
1648
|
-
operations,
|
|
1649
|
-
currency,
|
|
1650
|
-
currency === "BRL" ? ((await readCurrentFxRate(filesystem))?.rate ?? null) : null,
|
|
1651
|
-
)
|
|
1652
|
-
: await buildCurrentCostProjection(filesystem, operations, currency);
|
|
1653
|
-
return {
|
|
1654
|
-
operations,
|
|
1655
|
-
costs,
|
|
1656
|
-
dashboard: await dashboardIdentity(filesystem, workspaceRoot),
|
|
1657
|
-
projection: {
|
|
1658
|
-
source_latest_at: operations.summary.source_latest_at,
|
|
1659
|
-
served_at: new Date().toISOString(),
|
|
1660
|
-
},
|
|
1661
|
-
};
|
|
1662
|
-
}
|
|
1663
|
-
|
|
1664
682
|
const moduleStartedAt = performance.now();
|
|
1665
683
|
const sessionToken = defaultSessionToken();
|
|
1666
684
|
const runtimeWorkspaceRoot = process.env.ZAIP_WORKSPACE ?? process.cwd();
|
|
1667
|
-
|
|
1668
685
|
let defaultApp: Hono | undefined;
|
|
1669
|
-
|
|
1670
686
|
/**
|
|
1671
687
|
* Compatibility export for direct module consumers. The executable must not
|
|
1672
688
|
* construct this filesystem-backed app: `main` creates the SQLite app after
|
|
@@ -1676,14 +692,12 @@ export function defaultDashboardApp(): Hono {
|
|
|
1676
692
|
defaultApp ??= createDashboardApp(runtimeWorkspaceRoot, sessionToken);
|
|
1677
693
|
return defaultApp;
|
|
1678
694
|
}
|
|
1679
|
-
|
|
1680
695
|
export const app = new Proxy({} as Hono, {
|
|
1681
696
|
get(_target, property) {
|
|
1682
697
|
const value = Reflect.get(defaultDashboardApp(), property);
|
|
1683
698
|
return typeof value === "function" ? value.bind(defaultDashboardApp()) : value;
|
|
1684
699
|
},
|
|
1685
700
|
});
|
|
1686
|
-
|
|
1687
701
|
async function main(): Promise<void> {
|
|
1688
702
|
const port = Number.parseInt(process.env.ZAIP_SERVER_PORT ?? "4317", 10);
|
|
1689
703
|
writeStartupPhase(moduleStartedAt, "main_entered");
|
|
@@ -1706,7 +720,6 @@ async function main(): Promise<void> {
|
|
|
1706
720
|
);
|
|
1707
721
|
});
|
|
1708
722
|
}
|
|
1709
|
-
|
|
1710
723
|
if (
|
|
1711
724
|
process.argv[1]?.endsWith("server.cjs") ||
|
|
1712
725
|
process.argv[1]?.endsWith("server.js") ||
|