@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,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal Dashboard Renderer Adapter
|
|
3
|
+
*
|
|
4
|
+
* Hexagonal Architecture - Infrastructure Layer
|
|
5
|
+
* Implements the DashboardRenderer port for terminal/CLI output.
|
|
6
|
+
*
|
|
7
|
+
* Follows Edward Tufte's data visualisation principles:
|
|
8
|
+
* - High data-ink ratio (minimal chartjunk)
|
|
9
|
+
* - Small multiples for comparison (agent metrics table)
|
|
10
|
+
* - 5-second scannable layout
|
|
11
|
+
* - Headline sentences for context
|
|
12
|
+
*
|
|
13
|
+
* Library-First Approach:
|
|
14
|
+
* - picocolors: Semantic ANSI colours (NOT raw escape codes)
|
|
15
|
+
* - cli-table3: ASCII table rendering
|
|
16
|
+
* - cli-progress: Progress bar rendering
|
|
17
|
+
*
|
|
18
|
+
* @module terminal-renderer.adapter
|
|
19
|
+
* @see {@link ../ports/dashboard-renderer.port.ts} - Port interface
|
|
20
|
+
* @see {@link ../domain/orchestration.types.ts} - Domain types
|
|
21
|
+
*/
|
|
22
|
+
import picocolors from 'picocolors';
|
|
23
|
+
import Table from 'cli-table3';
|
|
24
|
+
// Constants for rendering (no magic strings)
|
|
25
|
+
const SECTION_SEPARATOR = '\n' + '─'.repeat(80) + '\n';
|
|
26
|
+
const HEADER_PREFIX = '▸';
|
|
27
|
+
const BULLET = '•';
|
|
28
|
+
const CHECK_MARK = '✓';
|
|
29
|
+
const CROSS_MARK = '✗';
|
|
30
|
+
const PENDING_MARK = '○';
|
|
31
|
+
const PROGRESS_BAR_WIDTH = 30;
|
|
32
|
+
// Severity colour mapping
|
|
33
|
+
const SEVERITY_COLOURS = {
|
|
34
|
+
high: picocolors.red,
|
|
35
|
+
medium: picocolors.yellow,
|
|
36
|
+
low: picocolors.cyan,
|
|
37
|
+
};
|
|
38
|
+
// Agent result colour mapping
|
|
39
|
+
const RESULT_COLOURS = {
|
|
40
|
+
pass: picocolors.green,
|
|
41
|
+
fail: picocolors.red,
|
|
42
|
+
pending: picocolors.yellow,
|
|
43
|
+
skipped: picocolors.gray,
|
|
44
|
+
};
|
|
45
|
+
// Event severity colour mapping
|
|
46
|
+
const EVENT_SEVERITY_COLOURS = {
|
|
47
|
+
info: picocolors.cyan,
|
|
48
|
+
warning: picocolors.yellow,
|
|
49
|
+
error: picocolors.red,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Terminal Dashboard Renderer
|
|
53
|
+
*
|
|
54
|
+
* Renders orchestration dashboard data to terminal using ANSI colours and ASCII tables.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* const renderer = new TerminalDashboardRenderer();
|
|
58
|
+
* const data = await metricsCollector.collect();
|
|
59
|
+
* renderer.render(data);
|
|
60
|
+
*/
|
|
61
|
+
export class TerminalDashboardRenderer {
|
|
62
|
+
/**
|
|
63
|
+
* Render the complete dashboard with all 5 sections.
|
|
64
|
+
*
|
|
65
|
+
* Sections:
|
|
66
|
+
* 1. Global Status - High-level metrics
|
|
67
|
+
* 2. Agent Small Multiples - Per-agent comparison table
|
|
68
|
+
* 3. WU Progress - DoD progress bars with headlines
|
|
69
|
+
* 4. Timeline - Recent events
|
|
70
|
+
* 5. Alerts - Items requiring attention
|
|
71
|
+
*
|
|
72
|
+
* @param data - Complete dashboard data
|
|
73
|
+
*/
|
|
74
|
+
render(data) {
|
|
75
|
+
this.clear();
|
|
76
|
+
console.log(picocolors.bold(picocolors.cyan('\n🎯 Agent Orchestration Dashboard\n')));
|
|
77
|
+
// Section 1: Global Status
|
|
78
|
+
this.renderGlobalStatus(data.globalStatus);
|
|
79
|
+
// Section 2: Agent Small Multiples
|
|
80
|
+
this.renderAgentMetrics(data.agentMetrics);
|
|
81
|
+
// Section 3: WU Progress
|
|
82
|
+
this.renderWUProgress(data.wuProgress);
|
|
83
|
+
// Section 4: Timeline
|
|
84
|
+
this.renderTimeline(data.timeline);
|
|
85
|
+
// Section 5: Alerts
|
|
86
|
+
this.renderAlerts(data.alerts);
|
|
87
|
+
console.log('\n');
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Render prioritised suggestions.
|
|
91
|
+
*
|
|
92
|
+
* @param suggestions - Ordered suggestions (highest priority first)
|
|
93
|
+
*/
|
|
94
|
+
renderSuggestions(suggestions) {
|
|
95
|
+
console.log(SECTION_SEPARATOR);
|
|
96
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Suggestions\n`));
|
|
97
|
+
if (suggestions.length === 0) {
|
|
98
|
+
console.log(picocolors.gray('No suggestions at this time.\n'));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
for (const suggestion of suggestions) {
|
|
102
|
+
const priorityColour = SEVERITY_COLOURS[suggestion.priority];
|
|
103
|
+
const priorityLabel = suggestion.priority.toUpperCase().padEnd(6);
|
|
104
|
+
console.log(`${BULLET} ${priorityColour(priorityLabel)} ${picocolors.bold(suggestion.action)}`);
|
|
105
|
+
console.log(` ${picocolors.gray('Reason:')} ${suggestion.reason}`);
|
|
106
|
+
console.log(` ${picocolors.gray('Command:')} ${picocolors.cyan(suggestion.command)}\n`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Render execution plan and prompt for user approval.
|
|
111
|
+
*
|
|
112
|
+
* @param plan - Proposed execution plan
|
|
113
|
+
* @returns User's choice (approve/reject/edit)
|
|
114
|
+
*/
|
|
115
|
+
async renderPlan(plan) {
|
|
116
|
+
console.log(SECTION_SEPARATOR);
|
|
117
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Execution Plan\n`));
|
|
118
|
+
console.log(`${picocolors.gray('WU:')} ${picocolors.cyan(plan.wuId)}`);
|
|
119
|
+
console.log(`${picocolors.gray('Estimated Tokens:')} ${picocolors.yellow(plan.estimatedTokens.toString())}\n`);
|
|
120
|
+
console.log(picocolors.bold('Steps:'));
|
|
121
|
+
for (const step of plan.steps) {
|
|
122
|
+
const label = 'agent' in step
|
|
123
|
+
? `Run agent: ${step.agent}`
|
|
124
|
+
: 'action' in step
|
|
125
|
+
? `Run: ${step.action}`
|
|
126
|
+
: 'Unknown step';
|
|
127
|
+
const statusIcon = step.status === 'pending' ? PENDING_MARK : CHECK_MARK;
|
|
128
|
+
console.log(` ${statusIcon} ${label}`);
|
|
129
|
+
}
|
|
130
|
+
console.log('');
|
|
131
|
+
// Prompt user (mocked in tests via promptUser)
|
|
132
|
+
return this.promptUser();
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Clear terminal output.
|
|
136
|
+
*
|
|
137
|
+
* Uses ANSI escape sequence to clear screen.
|
|
138
|
+
*/
|
|
139
|
+
clear() {
|
|
140
|
+
// ANSI escape sequence: clear screen and move cursor to top-left
|
|
141
|
+
console.log('\x1Bc');
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Render global status section.
|
|
145
|
+
*
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
renderGlobalStatus(status) {
|
|
149
|
+
console.log(SECTION_SEPARATOR);
|
|
150
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Global Status\n`));
|
|
151
|
+
console.log(`${picocolors.gray('Active WUs:')} ${picocolors.cyan(status.activeWUs.toString())}`);
|
|
152
|
+
console.log(`${picocolors.gray('Completed (24h):')} ${picocolors.green(status.completed24h.toString())}`);
|
|
153
|
+
console.log(`${picocolors.gray('Blocked:')} ${status.blocked > 0 ? picocolors.yellow(status.blocked.toString()) : picocolors.gray(status.blocked.toString())}`);
|
|
154
|
+
console.log(`${picocolors.gray('Gates Failing:')} ${status.gatesFailing > 0 ? picocolors.red(status.gatesFailing.toString()) : picocolors.gray(status.gatesFailing.toString())}`);
|
|
155
|
+
if (status.longestRunning) {
|
|
156
|
+
const durationHours = Math.floor(status.longestRunning.durationMs / (1000 * 60 * 60));
|
|
157
|
+
const durationMinutes = Math.floor((status.longestRunning.durationMs % (1000 * 60 * 60)) / (1000 * 60));
|
|
158
|
+
console.log(`${picocolors.gray('Longest Running:')} ${picocolors.cyan(status.longestRunning.wuId)} ${picocolors.gray(`(${durationHours}h ${durationMinutes}m)`)}`);
|
|
159
|
+
}
|
|
160
|
+
if (status.pendingMandatory.length > 0) {
|
|
161
|
+
console.log(`\n${picocolors.yellow(BULLET)} ${picocolors.bold('Pending Mandatory Agents:')}`);
|
|
162
|
+
for (const pending of status.pendingMandatory) {
|
|
163
|
+
console.log(` ${picocolors.gray('-')} ${picocolors.cyan(pending.wuId)}: ${pending.agent}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// WU-1438: Display active agent session
|
|
167
|
+
if (status.activeSession) {
|
|
168
|
+
const session = status.activeSession;
|
|
169
|
+
const startTime = new Date(session.started);
|
|
170
|
+
const durationMs = Date.now() - startTime.getTime();
|
|
171
|
+
const durationMinutes = Math.floor(durationMs / (1000 * 60));
|
|
172
|
+
const durationSeconds = Math.floor((durationMs % (1000 * 60)) / 1000);
|
|
173
|
+
console.log(`\n${picocolors.green(BULLET)} ${picocolors.bold('Active Agent Session:')}`);
|
|
174
|
+
console.log(` ${picocolors.gray('Session ID:')} ${picocolors.cyan(session.sessionId.slice(0, 8))}...`);
|
|
175
|
+
console.log(` ${picocolors.gray('WU:')} ${picocolors.cyan(session.wuId)}`);
|
|
176
|
+
console.log(` ${picocolors.gray('Context Tier:')} ${session.contextTier}`);
|
|
177
|
+
console.log(` ${picocolors.gray('Duration:')} ${durationMinutes}m ${durationSeconds}s`);
|
|
178
|
+
console.log(` ${picocolors.gray('Incidents Logged:')} ${session.incidentsLogged}`);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
console.log(`\n${picocolors.gray(BULLET)} ${picocolors.gray('No active agent session')}`);
|
|
182
|
+
}
|
|
183
|
+
// WU-1748: Display worktrees with uncommitted changes
|
|
184
|
+
if (status.worktreesWithUncommittedChanges.length > 0) {
|
|
185
|
+
console.log(`\n${picocolors.yellow(BULLET)} ${picocolors.bold('Worktrees with Uncommitted Changes:')}`);
|
|
186
|
+
for (const wt of status.worktreesWithUncommittedChanges) {
|
|
187
|
+
const lastActivity = wt.lastActivityTimestamp
|
|
188
|
+
? new Date(wt.lastActivityTimestamp).toLocaleString('en-GB')
|
|
189
|
+
: 'Unknown';
|
|
190
|
+
console.log(` ${picocolors.gray('-')} ${picocolors.cyan(wt.wuId)}: ${picocolors.yellow(wt.uncommittedFileCount.toString())} uncommitted files`);
|
|
191
|
+
console.log(` ${picocolors.gray('Last activity:')} ${lastActivity}`);
|
|
192
|
+
console.log(` ${picocolors.gray('Path:')} ${wt.worktreePath}`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
console.log('');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Render agent metrics as small multiples table.
|
|
199
|
+
*
|
|
200
|
+
* @private
|
|
201
|
+
*/
|
|
202
|
+
renderAgentMetrics(metrics) {
|
|
203
|
+
console.log(SECTION_SEPARATOR);
|
|
204
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Agent Metrics\n`));
|
|
205
|
+
if (Object.keys(metrics).length === 0) {
|
|
206
|
+
console.log(picocolors.gray('No agent metrics available.\n'));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const table = new Table({
|
|
210
|
+
head: ['Agent', 'Invoked', 'Pass Rate', 'Avg Duration', 'Last Run'],
|
|
211
|
+
style: {
|
|
212
|
+
head: ['cyan'],
|
|
213
|
+
border: ['gray'],
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
for (const [agentName, metric] of Object.entries(metrics)) {
|
|
217
|
+
const passRateColour = metric.passRate >= 90
|
|
218
|
+
? picocolors.green
|
|
219
|
+
: metric.passRate >= 50
|
|
220
|
+
? picocolors.yellow
|
|
221
|
+
: picocolors.red;
|
|
222
|
+
const avgDurationMs = metric.avgDurationMs;
|
|
223
|
+
const avgDurationMinutes = Math.floor(avgDurationMs / (1000 * 60));
|
|
224
|
+
const avgDurationSeconds = Math.floor((avgDurationMs % (1000 * 60)) / 1000);
|
|
225
|
+
const lastRunResult = metric.lastRun
|
|
226
|
+
? RESULT_COLOURS[metric.lastRun.result](metric.lastRun.result)
|
|
227
|
+
: picocolors.gray('N/A');
|
|
228
|
+
table.push([
|
|
229
|
+
agentName,
|
|
230
|
+
metric.invoked.toString(),
|
|
231
|
+
passRateColour(`${metric.passRate}%`),
|
|
232
|
+
`${avgDurationMinutes}m ${avgDurationSeconds}s`,
|
|
233
|
+
lastRunResult,
|
|
234
|
+
]);
|
|
235
|
+
}
|
|
236
|
+
console.log(table.toString());
|
|
237
|
+
console.log('');
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Render WU progress with DoD bars and headlines.
|
|
241
|
+
*
|
|
242
|
+
* @private
|
|
243
|
+
*/
|
|
244
|
+
renderWUProgress(progress) {
|
|
245
|
+
console.log(SECTION_SEPARATOR);
|
|
246
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} WU Progress\n`));
|
|
247
|
+
if (progress.length === 0) {
|
|
248
|
+
console.log(picocolors.gray('No active WUs.\n'));
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
for (const wu of progress) {
|
|
252
|
+
// WU header
|
|
253
|
+
console.log(`${picocolors.bold(picocolors.cyan(wu.wuId))} ${picocolors.gray('-')} ${wu.title}`);
|
|
254
|
+
console.log(`${picocolors.gray('Lane:')} ${wu.lane}`);
|
|
255
|
+
// DoD progress bar
|
|
256
|
+
const percentage = (wu.dodProgress / wu.dodTotal) * 100;
|
|
257
|
+
const filledWidth = Math.floor((percentage / 100) * PROGRESS_BAR_WIDTH);
|
|
258
|
+
const emptyWidth = PROGRESS_BAR_WIDTH - filledWidth;
|
|
259
|
+
const progressBar = picocolors.green('█'.repeat(filledWidth)) + picocolors.gray('░'.repeat(emptyWidth));
|
|
260
|
+
console.log(`${picocolors.gray('DoD:')} [${progressBar}] ${picocolors.cyan(`${wu.dodProgress}/${wu.dodTotal}`)}`);
|
|
261
|
+
// Agent status
|
|
262
|
+
const agentStatuses = Object.entries(wu.agents)
|
|
263
|
+
.map(([agent, status]) => {
|
|
264
|
+
const statusIcon = status === 'pass'
|
|
265
|
+
? picocolors.green(CHECK_MARK)
|
|
266
|
+
: status === 'fail'
|
|
267
|
+
? picocolors.red(CROSS_MARK)
|
|
268
|
+
: status === 'skipped'
|
|
269
|
+
? picocolors.gray('-')
|
|
270
|
+
: picocolors.yellow(PENDING_MARK);
|
|
271
|
+
return `${statusIcon} ${agent}`;
|
|
272
|
+
})
|
|
273
|
+
.join(' ');
|
|
274
|
+
console.log(`${picocolors.gray('Agents:')} ${agentStatuses}`);
|
|
275
|
+
// Headline sentence (Tufte principle)
|
|
276
|
+
console.log(`${picocolors.italic(picocolors.gray(`"${wu.headline}"`))}\n`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Render timeline of recent events.
|
|
281
|
+
*
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
renderTimeline(timeline) {
|
|
285
|
+
console.log(SECTION_SEPARATOR);
|
|
286
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Timeline\n`));
|
|
287
|
+
if (timeline.length === 0) {
|
|
288
|
+
console.log(picocolors.gray('No recent events.\n'));
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
for (const event of timeline) {
|
|
292
|
+
const timestamp = new Date(event.timestamp).toLocaleTimeString('en-GB', {
|
|
293
|
+
hour: '2-digit',
|
|
294
|
+
minute: '2-digit',
|
|
295
|
+
});
|
|
296
|
+
const severityColour = EVENT_SEVERITY_COLOURS[event.severity];
|
|
297
|
+
console.log(`${picocolors.gray(timestamp)} ${severityColour(BULLET)} ${picocolors.cyan(event.wuId)} ${picocolors.gray('-')} ${event.detail}`);
|
|
298
|
+
}
|
|
299
|
+
console.log('');
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Render alerts requiring attention.
|
|
303
|
+
*
|
|
304
|
+
* @private
|
|
305
|
+
*/
|
|
306
|
+
renderAlerts(alerts) {
|
|
307
|
+
console.log(SECTION_SEPARATOR);
|
|
308
|
+
console.log(picocolors.bold(`${HEADER_PREFIX} Alerts\n`));
|
|
309
|
+
if (alerts.length === 0) {
|
|
310
|
+
console.log(picocolors.green(`${CHECK_MARK} No alerts - all clear.\n`));
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
for (const alert of alerts) {
|
|
314
|
+
const severityColour = SEVERITY_COLOURS[alert.severity];
|
|
315
|
+
const severityLabel = alert.severity.toUpperCase().padEnd(6);
|
|
316
|
+
console.log(`${severityColour(BULLET)} ${severityColour(severityLabel)} ${picocolors.bold(alert.message)}`);
|
|
317
|
+
console.log(` ${picocolors.gray('WU:')} ${picocolors.cyan(alert.wuId)}`);
|
|
318
|
+
console.log(` ${picocolors.gray('Action:')} ${alert.action}\n`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Prompt user for execution plan approval.
|
|
323
|
+
*
|
|
324
|
+
* This is a simplified implementation for testing.
|
|
325
|
+
* Production version would use @inquirer/prompts for interactive input.
|
|
326
|
+
*
|
|
327
|
+
* @private
|
|
328
|
+
*/
|
|
329
|
+
async promptUser() {
|
|
330
|
+
// Mock implementation for testing
|
|
331
|
+
// Production: use @inquirer/prompts select + input
|
|
332
|
+
return {
|
|
333
|
+
choice: 'approve',
|
|
334
|
+
modifications: undefined,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Predefined option configurations for WU management scripts.
|
|
3
|
+
* Each option has: name, flags, description, and optional default.
|
|
4
|
+
*
|
|
5
|
+
* Commander auto-converts kebab-case flags to camelCase in opts().
|
|
6
|
+
* Example: --branch-only becomes opts().branchOnly
|
|
7
|
+
*
|
|
8
|
+
* NOTE: Commander treats --no-* flags specially (negated booleans).
|
|
9
|
+
* --no-foo creates opts.foo = false (default true).
|
|
10
|
+
* We post-process to convert these to noFoo = true for backward compat.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* WU option definition structure
|
|
14
|
+
*/
|
|
15
|
+
interface WUOption {
|
|
16
|
+
name: string;
|
|
17
|
+
flags: string;
|
|
18
|
+
description: string;
|
|
19
|
+
default?: string | boolean | string[];
|
|
20
|
+
isNegated?: boolean;
|
|
21
|
+
isRepeatable?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare const WU_OPTIONS: Record<string, WUOption>;
|
|
24
|
+
/**
|
|
25
|
+
* Create a commander-based CLI parser for a WU script.
|
|
26
|
+
*
|
|
27
|
+
* @param {object} config - Parser configuration
|
|
28
|
+
* @param {string} config.name - Script name (e.g., 'wu-claim')
|
|
29
|
+
* @param {string} config.description - Script description for help text
|
|
30
|
+
* @param {Array<object>} config.options - Array of option objects from WU_OPTIONS
|
|
31
|
+
* @param {Array<string>} [config.required=[]] - Array of option names that are required
|
|
32
|
+
* @param {boolean} [config.allowPositionalId=false] - Allow first positional arg as WU ID
|
|
33
|
+
* @param {string} [config.version='1.0.0'] - Script version
|
|
34
|
+
* @returns {object} Parsed options object (camelCase keys)
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const opts = createWUParser({
|
|
38
|
+
* name: 'wu-claim',
|
|
39
|
+
* description: 'Claim a work unit for a lane',
|
|
40
|
+
* options: [WU_OPTIONS.id, WU_OPTIONS.lane, WU_OPTIONS.branchOnly],
|
|
41
|
+
* required: ['id', 'lane'],
|
|
42
|
+
* });
|
|
43
|
+
* console.log(opts.id); // 'WU-123'
|
|
44
|
+
* console.log(opts.branchOnly); // true
|
|
45
|
+
*/
|
|
46
|
+
export declare function createWUParser(config: any): import("commander").OptionValues;
|
|
47
|
+
/**
|
|
48
|
+
* Backward-compatible unified argument parser for WU management scripts.
|
|
49
|
+
* Uses commander internally but maintains the same return format.
|
|
50
|
+
*
|
|
51
|
+
* @deprecated Use createWUParser() for new scripts to get better help text.
|
|
52
|
+
*
|
|
53
|
+
* @param {string[]} argv - Process arguments (typically process.argv)
|
|
54
|
+
* @returns {object} Parsed arguments object (camelCase keys)
|
|
55
|
+
* @throws {Error} If unknown flag or missing required value
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const args = parseWUArgs(process.argv);
|
|
59
|
+
* console.log(args.id); // 'WU-123'
|
|
60
|
+
* console.log(args.branchOnly); // true
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseWUArgs(argv: any): import("commander").OptionValues;
|
|
63
|
+
export {};
|