@lumenflow/core 1.0.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/LICENSE +190 -0
- package/README.md +119 -0
- package/dist/active-wu-detector.d.ts +33 -0
- package/dist/active-wu-detector.js +106 -0
- package/dist/adapters/filesystem-metrics.adapter.d.ts +108 -0
- package/dist/adapters/filesystem-metrics.adapter.js +519 -0
- package/dist/adapters/terminal-renderer.adapter.d.ts +106 -0
- package/dist/adapters/terminal-renderer.adapter.js +337 -0
- package/dist/arg-parser.d.ts +63 -0
- package/dist/arg-parser.js +560 -0
- package/dist/backlog-editor.d.ts +98 -0
- package/dist/backlog-editor.js +179 -0
- package/dist/backlog-generator.d.ts +111 -0
- package/dist/backlog-generator.js +381 -0
- package/dist/backlog-parser.d.ts +45 -0
- package/dist/backlog-parser.js +102 -0
- package/dist/backlog-sync-validator.d.ts +78 -0
- package/dist/backlog-sync-validator.js +294 -0
- package/dist/branch-drift.d.ts +34 -0
- package/dist/branch-drift.js +51 -0
- package/dist/cleanup-install-config.d.ts +33 -0
- package/dist/cleanup-install-config.js +37 -0
- package/dist/cleanup-lock.d.ts +139 -0
- package/dist/cleanup-lock.js +313 -0
- package/dist/code-path-validator.d.ts +146 -0
- package/dist/code-path-validator.js +537 -0
- package/dist/code-paths-overlap.d.ts +55 -0
- package/dist/code-paths-overlap.js +245 -0
- package/dist/commands-logger.d.ts +77 -0
- package/dist/commands-logger.js +254 -0
- package/dist/commit-message-utils.d.ts +25 -0
- package/dist/commit-message-utils.js +41 -0
- package/dist/compliance-parser.d.ts +150 -0
- package/dist/compliance-parser.js +507 -0
- package/dist/constants/backlog-patterns.d.ts +20 -0
- package/dist/constants/backlog-patterns.js +23 -0
- package/dist/constants/dora-constants.d.ts +49 -0
- package/dist/constants/dora-constants.js +53 -0
- package/dist/constants/gate-constants.d.ts +15 -0
- package/dist/constants/gate-constants.js +15 -0
- package/dist/constants/linter-constants.d.ts +16 -0
- package/dist/constants/linter-constants.js +16 -0
- package/dist/constants/tokenizer-constants.d.ts +15 -0
- package/dist/constants/tokenizer-constants.js +15 -0
- package/dist/core/scope-checker.d.ts +97 -0
- package/dist/core/scope-checker.js +163 -0
- package/dist/core/tool-runner.d.ts +161 -0
- package/dist/core/tool-runner.js +393 -0
- package/dist/core/tool.constants.d.ts +105 -0
- package/dist/core/tool.constants.js +101 -0
- package/dist/core/tool.schemas.d.ts +226 -0
- package/dist/core/tool.schemas.js +226 -0
- package/dist/core/worktree-guard.d.ts +130 -0
- package/dist/core/worktree-guard.js +242 -0
- package/dist/coverage-gate.d.ts +108 -0
- package/dist/coverage-gate.js +196 -0
- package/dist/date-utils.d.ts +75 -0
- package/dist/date-utils.js +140 -0
- package/dist/dependency-graph.d.ts +142 -0
- package/dist/dependency-graph.js +550 -0
- package/dist/dependency-guard.d.ts +54 -0
- package/dist/dependency-guard.js +142 -0
- package/dist/dependency-validator.d.ts +105 -0
- package/dist/dependency-validator.js +154 -0
- package/dist/docs-path-validator.d.ts +36 -0
- package/dist/docs-path-validator.js +95 -0
- package/dist/domain/orchestration.constants.d.ts +99 -0
- package/dist/domain/orchestration.constants.js +97 -0
- package/dist/domain/orchestration.schemas.d.ts +280 -0
- package/dist/domain/orchestration.schemas.js +211 -0
- package/dist/domain/orchestration.types.d.ts +133 -0
- package/dist/domain/orchestration.types.js +12 -0
- package/dist/error-handler.d.ts +116 -0
- package/dist/error-handler.js +136 -0
- package/dist/file-classifiers.d.ts +62 -0
- package/dist/file-classifiers.js +108 -0
- package/dist/gates-agent-mode.d.ts +81 -0
- package/dist/gates-agent-mode.js +94 -0
- package/dist/generate-traceability.d.ts +107 -0
- package/dist/generate-traceability.js +411 -0
- package/dist/git-adapter.d.ts +395 -0
- package/dist/git-adapter.js +649 -0
- package/dist/git-staged-validator.d.ts +32 -0
- package/dist/git-staged-validator.js +48 -0
- package/dist/hardcoded-strings.d.ts +61 -0
- package/dist/hardcoded-strings.js +270 -0
- package/dist/incremental-lint.d.ts +78 -0
- package/dist/incremental-lint.js +129 -0
- package/dist/incremental-test.d.ts +39 -0
- package/dist/incremental-test.js +61 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +61 -0
- package/dist/invariants/check-automated-tests.d.ts +50 -0
- package/dist/invariants/check-automated-tests.js +166 -0
- package/dist/invariants-runner.d.ts +103 -0
- package/dist/invariants-runner.js +527 -0
- package/dist/lane-checker.d.ts +50 -0
- package/dist/lane-checker.js +319 -0
- package/dist/lane-inference.d.ts +39 -0
- package/dist/lane-inference.js +195 -0
- package/dist/lane-lock.d.ts +211 -0
- package/dist/lane-lock.js +474 -0
- package/dist/lane-validator.d.ts +48 -0
- package/dist/lane-validator.js +114 -0
- package/dist/logs-lib.d.ts +104 -0
- package/dist/logs-lib.js +207 -0
- package/dist/lumenflow-config-schema.d.ts +272 -0
- package/dist/lumenflow-config-schema.js +207 -0
- package/dist/lumenflow-config.d.ts +95 -0
- package/dist/lumenflow-config.js +236 -0
- package/dist/manual-test-validator.d.ts +80 -0
- package/dist/manual-test-validator.js +200 -0
- package/dist/merge-lock.d.ts +115 -0
- package/dist/merge-lock.js +251 -0
- package/dist/micro-worktree.d.ts +159 -0
- package/dist/micro-worktree.js +427 -0
- package/dist/migration-deployer.d.ts +69 -0
- package/dist/migration-deployer.js +151 -0
- package/dist/orchestration-advisory-loader.d.ts +28 -0
- package/dist/orchestration-advisory-loader.js +87 -0
- package/dist/orchestration-advisory.d.ts +58 -0
- package/dist/orchestration-advisory.js +94 -0
- package/dist/orchestration-di.d.ts +48 -0
- package/dist/orchestration-di.js +57 -0
- package/dist/orchestration-rules.d.ts +57 -0
- package/dist/orchestration-rules.js +201 -0
- package/dist/orphan-detector.d.ts +131 -0
- package/dist/orphan-detector.js +226 -0
- package/dist/path-classifiers.d.ts +57 -0
- package/dist/path-classifiers.js +93 -0
- package/dist/piped-command-detector.d.ts +34 -0
- package/dist/piped-command-detector.js +64 -0
- package/dist/ports/dashboard-renderer.port.d.ts +112 -0
- package/dist/ports/dashboard-renderer.port.js +25 -0
- package/dist/ports/metrics-collector.port.d.ts +132 -0
- package/dist/ports/metrics-collector.port.js +26 -0
- package/dist/process-detector.d.ts +84 -0
- package/dist/process-detector.js +172 -0
- package/dist/prompt-linter.d.ts +72 -0
- package/dist/prompt-linter.js +312 -0
- package/dist/prompt-monitor.d.ts +15 -0
- package/dist/prompt-monitor.js +205 -0
- package/dist/rebase-artifact-cleanup.d.ts +145 -0
- package/dist/rebase-artifact-cleanup.js +433 -0
- package/dist/retry-strategy.d.ts +189 -0
- package/dist/retry-strategy.js +283 -0
- package/dist/risk-detector.d.ts +108 -0
- package/dist/risk-detector.js +252 -0
- package/dist/rollback-utils.d.ts +76 -0
- package/dist/rollback-utils.js +104 -0
- package/dist/section-headings.d.ts +43 -0
- package/dist/section-headings.js +49 -0
- package/dist/spawn-escalation.d.ts +90 -0
- package/dist/spawn-escalation.js +253 -0
- package/dist/spawn-monitor.d.ts +229 -0
- package/dist/spawn-monitor.js +672 -0
- package/dist/spawn-recovery.d.ts +82 -0
- package/dist/spawn-recovery.js +298 -0
- package/dist/spawn-registry-schema.d.ts +98 -0
- package/dist/spawn-registry-schema.js +108 -0
- package/dist/spawn-registry-store.d.ts +146 -0
- package/dist/spawn-registry-store.js +273 -0
- package/dist/spawn-tree.d.ts +121 -0
- package/dist/spawn-tree.js +285 -0
- package/dist/stamp-status-validator.d.ts +84 -0
- package/dist/stamp-status-validator.js +134 -0
- package/dist/stamp-utils.d.ts +100 -0
- package/dist/stamp-utils.js +229 -0
- package/dist/state-machine.d.ts +26 -0
- package/dist/state-machine.js +83 -0
- package/dist/system-map-validator.d.ts +80 -0
- package/dist/system-map-validator.js +272 -0
- package/dist/telemetry.d.ts +80 -0
- package/dist/telemetry.js +213 -0
- package/dist/token-counter.d.ts +51 -0
- package/dist/token-counter.js +145 -0
- package/dist/usecases/get-dashboard-data.usecase.d.ts +52 -0
- package/dist/usecases/get-dashboard-data.usecase.js +61 -0
- package/dist/usecases/get-suggestions.usecase.d.ts +100 -0
- package/dist/usecases/get-suggestions.usecase.js +153 -0
- package/dist/user-normalizer.d.ts +41 -0
- package/dist/user-normalizer.js +141 -0
- package/dist/validators/phi-constants.d.ts +97 -0
- package/dist/validators/phi-constants.js +152 -0
- package/dist/validators/phi-scanner.d.ts +58 -0
- package/dist/validators/phi-scanner.js +215 -0
- package/dist/worktree-ownership.d.ts +50 -0
- package/dist/worktree-ownership.js +74 -0
- package/dist/worktree-scanner.d.ts +103 -0
- package/dist/worktree-scanner.js +168 -0
- package/dist/worktree-symlink.d.ts +99 -0
- package/dist/worktree-symlink.js +359 -0
- package/dist/wu-backlog-updater.d.ts +17 -0
- package/dist/wu-backlog-updater.js +37 -0
- package/dist/wu-checkpoint.d.ts +124 -0
- package/dist/wu-checkpoint.js +233 -0
- package/dist/wu-claim-helpers.d.ts +26 -0
- package/dist/wu-claim-helpers.js +63 -0
- package/dist/wu-claim-resume.d.ts +106 -0
- package/dist/wu-claim-resume.js +276 -0
- package/dist/wu-consistency-checker.d.ts +95 -0
- package/dist/wu-consistency-checker.js +567 -0
- package/dist/wu-constants.d.ts +1275 -0
- package/dist/wu-constants.js +1382 -0
- package/dist/wu-create-validators.d.ts +42 -0
- package/dist/wu-create-validators.js +93 -0
- package/dist/wu-done-branch-only.d.ts +63 -0
- package/dist/wu-done-branch-only.js +191 -0
- package/dist/wu-done-messages.d.ts +119 -0
- package/dist/wu-done-messages.js +185 -0
- package/dist/wu-done-pr.d.ts +72 -0
- package/dist/wu-done-pr.js +174 -0
- package/dist/wu-done-retry-helpers.d.ts +85 -0
- package/dist/wu-done-retry-helpers.js +172 -0
- package/dist/wu-done-ui.d.ts +37 -0
- package/dist/wu-done-ui.js +69 -0
- package/dist/wu-done-validators.d.ts +411 -0
- package/dist/wu-done-validators.js +1229 -0
- package/dist/wu-done-worktree.d.ts +182 -0
- package/dist/wu-done-worktree.js +1097 -0
- package/dist/wu-helpers.d.ts +128 -0
- package/dist/wu-helpers.js +248 -0
- package/dist/wu-lint.d.ts +70 -0
- package/dist/wu-lint.js +234 -0
- package/dist/wu-paths.d.ts +171 -0
- package/dist/wu-paths.js +178 -0
- package/dist/wu-preflight-validators.d.ts +86 -0
- package/dist/wu-preflight-validators.js +251 -0
- package/dist/wu-recovery.d.ts +138 -0
- package/dist/wu-recovery.js +341 -0
- package/dist/wu-repair-core.d.ts +131 -0
- package/dist/wu-repair-core.js +669 -0
- package/dist/wu-schema-normalization.d.ts +17 -0
- package/dist/wu-schema-normalization.js +82 -0
- package/dist/wu-schema.d.ts +793 -0
- package/dist/wu-schema.js +881 -0
- package/dist/wu-spawn-helpers.d.ts +121 -0
- package/dist/wu-spawn-helpers.js +271 -0
- package/dist/wu-spawn.d.ts +158 -0
- package/dist/wu-spawn.js +1306 -0
- package/dist/wu-state-schema.d.ts +213 -0
- package/dist/wu-state-schema.js +156 -0
- package/dist/wu-state-store.d.ts +264 -0
- package/dist/wu-state-store.js +691 -0
- package/dist/wu-status-transition.d.ts +63 -0
- package/dist/wu-status-transition.js +382 -0
- package/dist/wu-status-updater.d.ts +25 -0
- package/dist/wu-status-updater.js +116 -0
- package/dist/wu-transaction-collectors.d.ts +116 -0
- package/dist/wu-transaction-collectors.js +272 -0
- package/dist/wu-transaction.d.ts +170 -0
- package/dist/wu-transaction.js +273 -0
- package/dist/wu-validation-constants.d.ts +60 -0
- package/dist/wu-validation-constants.js +66 -0
- package/dist/wu-validation.d.ts +118 -0
- package/dist/wu-validation.js +243 -0
- package/dist/wu-validator.d.ts +62 -0
- package/dist/wu-validator.js +325 -0
- package/dist/wu-yaml-fixer.d.ts +97 -0
- package/dist/wu-yaml-fixer.js +264 -0
- package/dist/wu-yaml.d.ts +86 -0
- package/dist/wu-yaml.js +222 -0
- package/package.json +114 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Telemetry Module - DORA/SPACE Metrics Emission
|
|
4
|
+
*
|
|
5
|
+
* Emits structured NDJSON telemetry for gates execution and WU flow metrics.
|
|
6
|
+
* Used by gates-local.mjs and flow-report.mjs.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Emit a telemetry event as NDJSON
|
|
10
|
+
* @param {string} filePath - Path to NDJSON file
|
|
11
|
+
* @param {object} event - Event data to emit
|
|
12
|
+
*/
|
|
13
|
+
export declare function emit(filePath: any, event: any): void;
|
|
14
|
+
/**
|
|
15
|
+
* Emit a gates execution event
|
|
16
|
+
* @param {object} data - Gates event data
|
|
17
|
+
* @param {string} data.wu_id - Work Unit ID (e.g., 'WU-402')
|
|
18
|
+
* @param {string} data.lane - Lane name (e.g., 'Operations')
|
|
19
|
+
* @param {string} data.gate_name - Gate name (e.g., 'format:check')
|
|
20
|
+
* @param {boolean} data.passed - Whether gate passed
|
|
21
|
+
* @param {number} data.duration_ms - Execution duration in milliseconds
|
|
22
|
+
*/
|
|
23
|
+
export declare function emitGateEvent(data: any): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get current WU ID from git branch or environment
|
|
26
|
+
* @returns {string|null} WU ID or null
|
|
27
|
+
*/
|
|
28
|
+
export declare function getCurrentWU(): string;
|
|
29
|
+
/**
|
|
30
|
+
* Get lane from git branch or environment
|
|
31
|
+
* @returns {string|null} Lane name or null
|
|
32
|
+
*/
|
|
33
|
+
export declare function getCurrentLane(): string;
|
|
34
|
+
/**
|
|
35
|
+
* Emit LLM classification start event
|
|
36
|
+
* @param {object} data - Classification start data
|
|
37
|
+
* @param {string} data.classification_type - Type of classification (e.g., 'mode_detection', 'red_flag', 'phi_detection')
|
|
38
|
+
* @param {boolean} [data.has_context] - Whether conversation context was provided
|
|
39
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
40
|
+
* @param {string} [data.lane] - Lane name
|
|
41
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
42
|
+
*/
|
|
43
|
+
export declare function emitLLMClassificationStart(data: any, logPath?: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Emit LLM classification complete event
|
|
46
|
+
* @param {object} data - Classification completion data
|
|
47
|
+
* @param {string} data.classification_type - Type of classification
|
|
48
|
+
* @param {number} data.duration_ms - Processing duration in milliseconds
|
|
49
|
+
* @param {number} data.tokens_used - Total tokens consumed
|
|
50
|
+
* @param {number} data.estimated_cost_usd - Estimated cost in USD
|
|
51
|
+
* @param {number} data.confidence - Classification confidence score (0-1)
|
|
52
|
+
* @param {boolean} data.fallback_used - Whether fallback (regex) was used
|
|
53
|
+
* @param {string} [data.fallback_reason] - Reason fallback was triggered
|
|
54
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
55
|
+
* @param {string} [data.lane] - Lane name
|
|
56
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
57
|
+
*/
|
|
58
|
+
export declare function emitLLMClassificationComplete(data: any, logPath?: string): void;
|
|
59
|
+
/**
|
|
60
|
+
* Emit LLM classification error event
|
|
61
|
+
* @param {object} data - Classification error data
|
|
62
|
+
* @param {string} data.classification_type - Type of classification
|
|
63
|
+
* @param {string} data.error_type - Error type (e.g., 'timeout', 'rate_limit', 'validation')
|
|
64
|
+
* @param {string} data.error_message - Error message (must be PII-free)
|
|
65
|
+
* @param {number} [data.duration_ms] - Duration before error occurred
|
|
66
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
67
|
+
* @param {string} [data.lane] - Lane name
|
|
68
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
69
|
+
*/
|
|
70
|
+
export declare function emitLLMClassificationError(data: any, logPath?: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Emit WU flow telemetry event to .beacon/flow.log
|
|
73
|
+
*
|
|
74
|
+
* Used by wu-claim, wu-done, wu-unblock for workflow tracking.
|
|
75
|
+
* Centralized from duplicated emitTelemetry() functions (WU-1256).
|
|
76
|
+
*
|
|
77
|
+
* @param {object} event - Event data (script, wu_id, lane, step, etc.)
|
|
78
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
79
|
+
*/
|
|
80
|
+
export declare function emitWUFlowEvent(event: any, logPath?: string): void;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Telemetry Module - DORA/SPACE Metrics Emission
|
|
4
|
+
*
|
|
5
|
+
* Emits structured NDJSON telemetry for gates execution and WU flow metrics.
|
|
6
|
+
* Used by gates-local.mjs and flow-report.mjs.
|
|
7
|
+
*/
|
|
8
|
+
import { appendFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { BEACON_PATHS, FILE_EXTENSIONS, STDIO, STRING_LITERALS, } from './wu-constants.js';
|
|
12
|
+
const TELEMETRY_DIR = BEACON_PATHS.TELEMETRY;
|
|
13
|
+
const GATES_LOG = `${TELEMETRY_DIR}/gates${FILE_EXTENSIONS.NDJSON}`;
|
|
14
|
+
const LLM_CLASSIFICATION_LOG = `${TELEMETRY_DIR}/llm-classification${FILE_EXTENSIONS.NDJSON}`;
|
|
15
|
+
const FLOW_LOG = BEACON_PATHS.FLOW_LOG;
|
|
16
|
+
/**
|
|
17
|
+
* Ensure telemetry directory exists
|
|
18
|
+
*/
|
|
19
|
+
function ensureTelemetryDir() {
|
|
20
|
+
try {
|
|
21
|
+
mkdirSync(TELEMETRY_DIR, { recursive: true });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Directory may already exist, ignore
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Emit a telemetry event as NDJSON
|
|
29
|
+
* @param {string} filePath - Path to NDJSON file
|
|
30
|
+
* @param {object} event - Event data to emit
|
|
31
|
+
*/
|
|
32
|
+
export function emit(filePath, event) {
|
|
33
|
+
ensureTelemetryDir();
|
|
34
|
+
const line = `${JSON.stringify(event)}${STRING_LITERALS.NEWLINE}`;
|
|
35
|
+
try {
|
|
36
|
+
appendFileSync(filePath, line, { encoding: 'utf-8' });
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
40
|
+
console.error(`[telemetry] Failed to emit to ${filePath}:`, message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Emit a gates execution event
|
|
45
|
+
* @param {object} data - Gates event data
|
|
46
|
+
* @param {string} data.wu_id - Work Unit ID (e.g., 'WU-402')
|
|
47
|
+
* @param {string} data.lane - Lane name (e.g., 'Operations')
|
|
48
|
+
* @param {string} data.gate_name - Gate name (e.g., 'format:check')
|
|
49
|
+
* @param {boolean} data.passed - Whether gate passed
|
|
50
|
+
* @param {number} data.duration_ms - Execution duration in milliseconds
|
|
51
|
+
*/
|
|
52
|
+
export function emitGateEvent(data) {
|
|
53
|
+
const event = {
|
|
54
|
+
timestamp: new Date().toISOString(),
|
|
55
|
+
wu_id: data.wu_id || null,
|
|
56
|
+
lane: data.lane || null,
|
|
57
|
+
gate_name: data.gate_name,
|
|
58
|
+
passed: data.passed,
|
|
59
|
+
duration_ms: data.duration_ms,
|
|
60
|
+
};
|
|
61
|
+
emit(GATES_LOG, event);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get current WU ID from git branch or environment
|
|
65
|
+
* @returns {string|null} WU ID or null
|
|
66
|
+
*/
|
|
67
|
+
export function getCurrentWU() {
|
|
68
|
+
try {
|
|
69
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
70
|
+
encoding: 'utf-8',
|
|
71
|
+
stdio: [STDIO.PIPE, STDIO.PIPE, STDIO.IGNORE],
|
|
72
|
+
}).trim();
|
|
73
|
+
// Extract WU ID from branch name (e.g., lane/operations/wu-402 -> WU-402)
|
|
74
|
+
const match = branch.match(/wu-(\d+)/i);
|
|
75
|
+
if (match) {
|
|
76
|
+
return `WU-${match[1]}`.toUpperCase();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Not in a git repo or command failed
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get lane from git branch or environment
|
|
86
|
+
* @returns {string|null} Lane name or null
|
|
87
|
+
*/
|
|
88
|
+
export function getCurrentLane() {
|
|
89
|
+
try {
|
|
90
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD', {
|
|
91
|
+
encoding: 'utf-8',
|
|
92
|
+
stdio: [STDIO.PIPE, STDIO.PIPE, STDIO.IGNORE],
|
|
93
|
+
}).trim();
|
|
94
|
+
// Extract lane from branch name (e.g., lane/operations/wu-402 -> Operations)
|
|
95
|
+
const match = branch.match(/^lane\/([^/]+)\//i);
|
|
96
|
+
if (match) {
|
|
97
|
+
return match[1].charAt(0).toUpperCase() + match[1].slice(1).toLowerCase();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Not in a git repo or command failed
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Emit LLM classification start event
|
|
107
|
+
* @param {object} data - Classification start data
|
|
108
|
+
* @param {string} data.classification_type - Type of classification (e.g., 'mode_detection', 'red_flag', 'phi_detection')
|
|
109
|
+
* @param {boolean} [data.has_context] - Whether conversation context was provided
|
|
110
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
111
|
+
* @param {string} [data.lane] - Lane name
|
|
112
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
113
|
+
*/
|
|
114
|
+
export function emitLLMClassificationStart(data, logPath = LLM_CLASSIFICATION_LOG) {
|
|
115
|
+
const event = {
|
|
116
|
+
timestamp: new Date().toISOString(),
|
|
117
|
+
event_type: 'llm.classification.start',
|
|
118
|
+
classification_type: data.classification_type,
|
|
119
|
+
has_context: data.has_context ?? false,
|
|
120
|
+
wu_id: data.wu_id || getCurrentWU(),
|
|
121
|
+
lane: data.lane || getCurrentLane(),
|
|
122
|
+
};
|
|
123
|
+
emit(logPath, event);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Emit LLM classification complete event
|
|
127
|
+
* @param {object} data - Classification completion data
|
|
128
|
+
* @param {string} data.classification_type - Type of classification
|
|
129
|
+
* @param {number} data.duration_ms - Processing duration in milliseconds
|
|
130
|
+
* @param {number} data.tokens_used - Total tokens consumed
|
|
131
|
+
* @param {number} data.estimated_cost_usd - Estimated cost in USD
|
|
132
|
+
* @param {number} data.confidence - Classification confidence score (0-1)
|
|
133
|
+
* @param {boolean} data.fallback_used - Whether fallback (regex) was used
|
|
134
|
+
* @param {string} [data.fallback_reason] - Reason fallback was triggered
|
|
135
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
136
|
+
* @param {string} [data.lane] - Lane name
|
|
137
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
138
|
+
*/
|
|
139
|
+
export function emitLLMClassificationComplete(data, logPath = LLM_CLASSIFICATION_LOG) {
|
|
140
|
+
// PII Protection: Explicitly exclude any user input fields
|
|
141
|
+
const event = {
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
event_type: 'llm.classification.complete',
|
|
144
|
+
classification_type: data.classification_type,
|
|
145
|
+
duration_ms: data.duration_ms,
|
|
146
|
+
tokens_used: data.tokens_used,
|
|
147
|
+
estimated_cost_usd: data.estimated_cost_usd,
|
|
148
|
+
confidence: data.confidence,
|
|
149
|
+
fallback_used: data.fallback_used,
|
|
150
|
+
wu_id: data.wu_id || getCurrentWU(),
|
|
151
|
+
lane: data.lane || getCurrentLane(),
|
|
152
|
+
};
|
|
153
|
+
// Add fallback_reason only if fallback was used
|
|
154
|
+
if (data.fallback_used && data.fallback_reason) {
|
|
155
|
+
event.fallback_reason = data.fallback_reason;
|
|
156
|
+
}
|
|
157
|
+
emit(logPath, event);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Emit LLM classification error event
|
|
161
|
+
* @param {object} data - Classification error data
|
|
162
|
+
* @param {string} data.classification_type - Type of classification
|
|
163
|
+
* @param {string} data.error_type - Error type (e.g., 'timeout', 'rate_limit', 'validation')
|
|
164
|
+
* @param {string} data.error_message - Error message (must be PII-free)
|
|
165
|
+
* @param {number} [data.duration_ms] - Duration before error occurred
|
|
166
|
+
* @param {string} [data.wu_id] - Work Unit ID
|
|
167
|
+
* @param {string} [data.lane] - Lane name
|
|
168
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
169
|
+
*/
|
|
170
|
+
export function emitLLMClassificationError(data, logPath = LLM_CLASSIFICATION_LOG) {
|
|
171
|
+
// PII Protection: Never log user input or sensitive data
|
|
172
|
+
const event = {
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
event_type: 'llm.classification.error',
|
|
175
|
+
classification_type: data.classification_type,
|
|
176
|
+
error_type: data.error_type,
|
|
177
|
+
error_message: data.error_message, // Caller must ensure this is PII-free
|
|
178
|
+
wu_id: data.wu_id || getCurrentWU(),
|
|
179
|
+
lane: data.lane || getCurrentLane(),
|
|
180
|
+
};
|
|
181
|
+
if (data.duration_ms !== undefined) {
|
|
182
|
+
event.duration_ms = data.duration_ms;
|
|
183
|
+
}
|
|
184
|
+
// Explicitly redact any input_text_preview to prevent PII leakage
|
|
185
|
+
if (data.input_text_preview) {
|
|
186
|
+
event.input_text_preview = '[REDACTED]';
|
|
187
|
+
}
|
|
188
|
+
emit(logPath, event);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Emit WU flow telemetry event to .beacon/flow.log
|
|
192
|
+
*
|
|
193
|
+
* Used by wu-claim, wu-done, wu-unblock for workflow tracking.
|
|
194
|
+
* Centralized from duplicated emitTelemetry() functions (WU-1256).
|
|
195
|
+
*
|
|
196
|
+
* @param {object} event - Event data (script, wu_id, lane, step, etc.)
|
|
197
|
+
* @param {string} [logPath] - Optional log path override (for testing)
|
|
198
|
+
*/
|
|
199
|
+
export function emitWUFlowEvent(event, logPath = FLOW_LOG) {
|
|
200
|
+
const logDir = path.dirname(logPath);
|
|
201
|
+
if (!existsSync(logDir)) {
|
|
202
|
+
mkdirSync(logDir, { recursive: true });
|
|
203
|
+
}
|
|
204
|
+
const line = JSON.stringify({ timestamp: new Date().toISOString(), ...event });
|
|
205
|
+
try {
|
|
206
|
+
appendFileSync(logPath, `${line}${STRING_LITERALS.NEWLINE}`, { encoding: 'utf-8' });
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
// Silently fail - telemetry should not block workflow
|
|
210
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
211
|
+
console.error(`[telemetry] Failed to emit flow event: ${message}`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Counter Utility
|
|
3
|
+
*
|
|
4
|
+
* Wraps tiktoken for counting tokens in prompts using the o200k_base encoding
|
|
5
|
+
* (used by gpt-5-nano). Provides caching and hash computation for stability checks.
|
|
6
|
+
*
|
|
7
|
+
* Part of WU-676: Single-Call LLM Orchestrator token budget enforcement.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Count tokens in text using gpt-5-nano tokenizer
|
|
11
|
+
* @param {string} text - Text to tokenize
|
|
12
|
+
* @returns {number} Token count
|
|
13
|
+
*/
|
|
14
|
+
export declare function countTokens(text: any): any;
|
|
15
|
+
/**
|
|
16
|
+
* Compute SHA256 hash of text (for stability checks)
|
|
17
|
+
* @param {string} text - Text to hash
|
|
18
|
+
* @returns {string} Hex hash
|
|
19
|
+
*/
|
|
20
|
+
export declare function computeHash(text: any): string;
|
|
21
|
+
/**
|
|
22
|
+
* Load and render a prompt file (resolves includes, strips comments)
|
|
23
|
+
* @param {string} promptPath - Absolute path to prompt YAML file
|
|
24
|
+
* @returns {{text: string, raw: string}} Rendered text and raw YAML
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadPrompt(promptPath: any): {
|
|
27
|
+
text: any;
|
|
28
|
+
raw: string;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Analyze a prompt file (count tokens, compute hash, extract metadata)
|
|
32
|
+
* @param {string} promptPath - Absolute path to prompt YAML file
|
|
33
|
+
* @returns {{tokenCount: number, hash: string, text: string, raw: string}}
|
|
34
|
+
*/
|
|
35
|
+
export declare function analyzePrompt(promptPath: any): {
|
|
36
|
+
tokenCount: any;
|
|
37
|
+
hash: string;
|
|
38
|
+
text: any;
|
|
39
|
+
raw: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get top N longest lines from text (for cleanup targeting)
|
|
43
|
+
* @param {string} text - Text to analyze
|
|
44
|
+
* @param {number} n - Number of lines to return
|
|
45
|
+
* @returns {Array<{line: string, length: number, number: number}>} Longest lines
|
|
46
|
+
*/
|
|
47
|
+
export declare function getLongestLines(text: any, n?: number): any;
|
|
48
|
+
/**
|
|
49
|
+
* Cleanup function (call on process exit to free tokenizer)
|
|
50
|
+
*/
|
|
51
|
+
export declare function cleanup(): void;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Counter Utility
|
|
3
|
+
*
|
|
4
|
+
* Wraps tiktoken for counting tokens in prompts using the o200k_base encoding
|
|
5
|
+
* (used by gpt-5-nano). Provides caching and hash computation for stability checks.
|
|
6
|
+
*
|
|
7
|
+
* Part of WU-676: Single-Call LLM Orchestrator token budget enforcement.
|
|
8
|
+
*/
|
|
9
|
+
import { get_encoding } from 'tiktoken';
|
|
10
|
+
import { readFileSync } from 'fs';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { load as loadYAML } from 'js-yaml';
|
|
13
|
+
import { createError, ErrorCodes } from './error-handler.js';
|
|
14
|
+
import { EXIT_CODES, STRING_LITERALS } from './wu-constants.js';
|
|
15
|
+
// Cache tokenizer instance (expensive to create)
|
|
16
|
+
let tokenizerCache = null;
|
|
17
|
+
/**
|
|
18
|
+
* Get or create tiktoken instance with o200k_base encoding (gpt-5-nano)
|
|
19
|
+
* @returns {Tiktoken} Tokenizer instance
|
|
20
|
+
*/
|
|
21
|
+
function getTokenizer() {
|
|
22
|
+
if (!tokenizerCache) {
|
|
23
|
+
tokenizerCache = get_encoding('o200k_base');
|
|
24
|
+
}
|
|
25
|
+
return tokenizerCache;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Count tokens in text using gpt-5-nano tokenizer
|
|
29
|
+
* @param {string} text - Text to tokenize
|
|
30
|
+
* @returns {number} Token count
|
|
31
|
+
*/
|
|
32
|
+
export function countTokens(text) {
|
|
33
|
+
if (!text || typeof text !== 'string') {
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
const tokenizer = getTokenizer();
|
|
37
|
+
const tokens = tokenizer.encode(text);
|
|
38
|
+
return tokens.length;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Compute SHA256 hash of text (for stability checks)
|
|
42
|
+
* @param {string} text - Text to hash
|
|
43
|
+
* @returns {string} Hex hash
|
|
44
|
+
*/
|
|
45
|
+
export function computeHash(text) {
|
|
46
|
+
return createHash('sha256').update(text).digest('hex').slice(0, 16);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Strip YAML comments from prompt text
|
|
50
|
+
* @param {string} text - YAML text
|
|
51
|
+
* @returns {string} Text with comments removed
|
|
52
|
+
*/
|
|
53
|
+
function stripYAMLComments(text) {
|
|
54
|
+
return text
|
|
55
|
+
.split(STRING_LITERALS.NEWLINE)
|
|
56
|
+
.filter((line) => !line.trim().startsWith('#'))
|
|
57
|
+
.join(STRING_LITERALS.NEWLINE);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Load and render a prompt file (resolves includes, strips comments)
|
|
61
|
+
* @param {string} promptPath - Absolute path to prompt YAML file
|
|
62
|
+
* @returns {{text: string, raw: string}} Rendered text and raw YAML
|
|
63
|
+
*/
|
|
64
|
+
export function loadPrompt(promptPath) {
|
|
65
|
+
try {
|
|
66
|
+
const raw = readFileSync(promptPath, { encoding: 'utf-8' });
|
|
67
|
+
// Parse YAML to access prompt structure
|
|
68
|
+
const parsed = loadYAML(raw);
|
|
69
|
+
// Extract prompt text (handle different YAML structures)
|
|
70
|
+
let promptText = '';
|
|
71
|
+
if (typeof parsed === 'string') {
|
|
72
|
+
promptText = parsed;
|
|
73
|
+
}
|
|
74
|
+
else if (parsed && parsed.prompt) {
|
|
75
|
+
promptText = parsed.prompt;
|
|
76
|
+
}
|
|
77
|
+
else if (parsed && parsed.system) {
|
|
78
|
+
promptText = parsed.system;
|
|
79
|
+
}
|
|
80
|
+
else if (parsed && parsed.content) {
|
|
81
|
+
promptText = parsed.content;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
// Fallback: use entire YAML stringified (for complex structures)
|
|
85
|
+
promptText = JSON.stringify(parsed, null, 2);
|
|
86
|
+
}
|
|
87
|
+
// Strip comments from rendered text
|
|
88
|
+
const renderedText = stripYAMLComments(promptText);
|
|
89
|
+
return { text: renderedText, raw };
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
93
|
+
throw createError(ErrorCodes.FILE_NOT_FOUND, `Failed to load prompt from ${promptPath}: ${message}`, { path: promptPath, originalError: message });
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Analyze a prompt file (count tokens, compute hash, extract metadata)
|
|
98
|
+
* @param {string} promptPath - Absolute path to prompt YAML file
|
|
99
|
+
* @returns {{tokenCount: number, hash: string, text: string, raw: string}}
|
|
100
|
+
*/
|
|
101
|
+
export function analyzePrompt(promptPath) {
|
|
102
|
+
const { text, raw } = loadPrompt(promptPath);
|
|
103
|
+
const tokenCount = countTokens(text);
|
|
104
|
+
const hash = computeHash(text);
|
|
105
|
+
return {
|
|
106
|
+
tokenCount,
|
|
107
|
+
hash,
|
|
108
|
+
text,
|
|
109
|
+
raw,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get top N longest lines from text (for cleanup targeting)
|
|
114
|
+
* @param {string} text - Text to analyze
|
|
115
|
+
* @param {number} n - Number of lines to return
|
|
116
|
+
* @returns {Array<{line: string, length: number, number: number}>} Longest lines
|
|
117
|
+
*/
|
|
118
|
+
export function getLongestLines(text, n = 3) {
|
|
119
|
+
const lines = text.split(STRING_LITERALS.NEWLINE);
|
|
120
|
+
const linesWithMetadata = lines.map((line, index) => ({
|
|
121
|
+
line: line.trim(),
|
|
122
|
+
length: line.length,
|
|
123
|
+
number: index + 1,
|
|
124
|
+
}));
|
|
125
|
+
// Sort by length descending, take top N
|
|
126
|
+
return linesWithMetadata
|
|
127
|
+
.filter((l) => l.line.length > 0)
|
|
128
|
+
.sort((a, b) => b.length - a.length)
|
|
129
|
+
.slice(0, n);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Cleanup function (call on process exit to free tokenizer)
|
|
133
|
+
*/
|
|
134
|
+
export function cleanup() {
|
|
135
|
+
if (tokenizerCache) {
|
|
136
|
+
tokenizerCache.free();
|
|
137
|
+
tokenizerCache = null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Auto-cleanup on process exit
|
|
141
|
+
process.on('exit', cleanup);
|
|
142
|
+
process.on('SIGINT', () => {
|
|
143
|
+
cleanup();
|
|
144
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
145
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GetDashboardData Use Case
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the collection of all dashboard metrics from the metrics collector.
|
|
5
|
+
* Follows hexagonal architecture - depends on port interface, not concrete implementation.
|
|
6
|
+
*
|
|
7
|
+
* @module get-dashboard-data.usecase
|
|
8
|
+
* @see {@link ../ports/metrics-collector.port.ts} - Port interface
|
|
9
|
+
* @see {@link ../domain/orchestration.types.ts} - Domain types
|
|
10
|
+
*/
|
|
11
|
+
import type { IMetricsCollector } from '../ports/metrics-collector.port.js';
|
|
12
|
+
import type { DashboardData } from '../domain/orchestration.types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Options for the GetDashboardData use case.
|
|
15
|
+
*/
|
|
16
|
+
export interface GetDashboardDataOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Number of hours to include in the timeline.
|
|
19
|
+
* @default TIMELINE_WINDOW_HOURS (24)
|
|
20
|
+
*/
|
|
21
|
+
timelineHours?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Use case for collecting all dashboard data.
|
|
25
|
+
*
|
|
26
|
+
* Orchestrates parallel calls to the metrics collector to gather:
|
|
27
|
+
* - Global status (active WUs, completed, blocked, etc.)
|
|
28
|
+
* - Agent metrics (invocation counts, pass rates, timing)
|
|
29
|
+
* - WU progress (DoD progress, agent statuses)
|
|
30
|
+
* - Timeline events (recent activity)
|
|
31
|
+
* - Alerts (items requiring attention)
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* const collector = new FileSystemMetricsCollector(basePath);
|
|
35
|
+
* const useCase = new GetDashboardDataUseCase(collector);
|
|
36
|
+
* const data = await useCase.execute();
|
|
37
|
+
* console.log(data.globalStatus.activeWUs);
|
|
38
|
+
*/
|
|
39
|
+
export declare class GetDashboardDataUseCase {
|
|
40
|
+
private readonly metricsCollector;
|
|
41
|
+
constructor(metricsCollector: IMetricsCollector);
|
|
42
|
+
/**
|
|
43
|
+
* Execute the use case to collect all dashboard data.
|
|
44
|
+
*
|
|
45
|
+
* Calls all collector methods in parallel for optimal performance.
|
|
46
|
+
*
|
|
47
|
+
* @param options - Optional configuration
|
|
48
|
+
* @returns Promise resolving to complete dashboard data
|
|
49
|
+
* @throws Error if any collector method fails
|
|
50
|
+
*/
|
|
51
|
+
execute(options?: GetDashboardDataOptions): Promise<DashboardData>;
|
|
52
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GetDashboardData Use Case
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the collection of all dashboard metrics from the metrics collector.
|
|
5
|
+
* Follows hexagonal architecture - depends on port interface, not concrete implementation.
|
|
6
|
+
*
|
|
7
|
+
* @module get-dashboard-data.usecase
|
|
8
|
+
* @see {@link ../ports/metrics-collector.port.ts} - Port interface
|
|
9
|
+
* @see {@link ../domain/orchestration.types.ts} - Domain types
|
|
10
|
+
*/
|
|
11
|
+
import { TIMELINE_WINDOW_HOURS } from '../domain/orchestration.constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* Use case for collecting all dashboard data.
|
|
14
|
+
*
|
|
15
|
+
* Orchestrates parallel calls to the metrics collector to gather:
|
|
16
|
+
* - Global status (active WUs, completed, blocked, etc.)
|
|
17
|
+
* - Agent metrics (invocation counts, pass rates, timing)
|
|
18
|
+
* - WU progress (DoD progress, agent statuses)
|
|
19
|
+
* - Timeline events (recent activity)
|
|
20
|
+
* - Alerts (items requiring attention)
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const collector = new FileSystemMetricsCollector(basePath);
|
|
24
|
+
* const useCase = new GetDashboardDataUseCase(collector);
|
|
25
|
+
* const data = await useCase.execute();
|
|
26
|
+
* console.log(data.globalStatus.activeWUs);
|
|
27
|
+
*/
|
|
28
|
+
export class GetDashboardDataUseCase {
|
|
29
|
+
metricsCollector;
|
|
30
|
+
constructor(metricsCollector) {
|
|
31
|
+
this.metricsCollector = metricsCollector;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Execute the use case to collect all dashboard data.
|
|
35
|
+
*
|
|
36
|
+
* Calls all collector methods in parallel for optimal performance.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Optional configuration
|
|
39
|
+
* @returns Promise resolving to complete dashboard data
|
|
40
|
+
* @throws Error if any collector method fails
|
|
41
|
+
*/
|
|
42
|
+
async execute(options = {}) {
|
|
43
|
+
const { timelineHours = TIMELINE_WINDOW_HOURS } = options;
|
|
44
|
+
const timelineSince = new Date();
|
|
45
|
+
timelineSince.setHours(timelineSince.getHours() - timelineHours);
|
|
46
|
+
const [globalStatus, agentMetrics, wuProgress, timeline, alerts] = await Promise.all([
|
|
47
|
+
this.metricsCollector.getGlobalStatus(),
|
|
48
|
+
this.metricsCollector.getAgentMetrics(),
|
|
49
|
+
this.metricsCollector.getWUProgress(),
|
|
50
|
+
this.metricsCollector.getTimeline(timelineSince),
|
|
51
|
+
this.metricsCollector.getAlerts(),
|
|
52
|
+
]);
|
|
53
|
+
return {
|
|
54
|
+
globalStatus,
|
|
55
|
+
agentMetrics,
|
|
56
|
+
wuProgress,
|
|
57
|
+
timeline,
|
|
58
|
+
alerts,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|