Skip to content

feat: CLI output UX overhaul with @clack/prompts#65

Open
dean0x wants to merge 1 commit intomainfrom
feat/cli-ux-overhaul
Open

feat: CLI output UX overhaul with @clack/prompts#65
dean0x wants to merge 1 commit intomainfrom
feat/cli-ux-overhaul

Conversation

@dean0x
Copy link
Owner

@dean0x dean0x commented Feb 27, 2026

Summary

  • Split monolithic src/cli.ts (1,500 lines) into 11 focused command modules under src/cli/commands/ plus a display abstraction layer (src/cli/ui.ts)
  • Add structured CLI output via @clack/prompts — spinners during async ops, color-coded status, clean visual hierarchy
  • All display output routed to process.stderr (stdout reserved for MCP protocol); TTY-aware with plain-text non-TTY fallback

Changes

File Description
src/cli.ts Slimmed from ~1,500 to ~260 lines (thin arg-parsing router)
src/cli/ui.ts New display abstraction — TTY: @Clack styled; non-TTY: plain text
src/cli/services.ts Shared withServices() bootstrap + errorMessage() helper
src/cli/commands/*.ts 11 command modules (delegate, status, logs, cancel, retry, resume, schedule, pipeline, config, mcp, help)
package.json Added @clack/prompts dependency

Design decisions

  • stderr-only display: All @clack/prompts calls pass { output: process.stderr } — stdout is reserved for MCP protocol and machine-readable output (--version, config path)
  • TTY-aware fallback: Interactive terminals get spinners and styled output; pipes/CI get plain text with no ANSI codes
  • Detach-mode contract preserved: Non-TTY error() emits prefix (regex /^❌/m) and Task ID: pattern preserved for background process polling
  • Zero decorative emojis: @Clack symbols (◆, │, ─) provide visual structure in TTY mode

Test plan

  • npm run build — clean compile
  • npm run test:cli — 115 CLI tests pass
  • npm run test:core — 331 tests pass
  • npm run test:handlers — 84 tests pass
  • npm run test:services — 131 tests pass
  • npm run test:repositories — 109 tests pass
  • npm run test:adapters — 37 tests pass
  • npm run test:implementations — 257 tests pass
  • npm run test:integration — 54 tests pass
  • Manual: delegate help — clean structured output
  • Manual: delegate help | cat — no ANSI codes in piped output
  • Manual: delegate config show — grouped sections
  • Manual: delegate boguscommand — error with exit 1
  • Manual: detach-mode end-to-end (delegate a task, verify polling picks up Task ID)
  • CI green

@qodo-free-for-open-source-projects

Review Summary by Qodo

CLI output UX overhaul with modular command structure and @clack/prompts integration

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Refactored monolithic src/cli.ts (1,500 lines) into 11 focused command modules under
  src/cli/commands/ with a display abstraction layer (src/cli/ui.ts)
• Implemented structured CLI output via @clack/prompts with spinners, color-coded status messages,
  and clean visual hierarchy
• All display output routed to process.stderr (stdout reserved for MCP protocol); TTY-aware with
  plain-text non-TTY fallback
• Created shared service bootstrap module (src/cli/services.ts) to eliminate boilerplate across
  command handlers
• Extracted 11 command handlers: delegate, status, logs, cancel, retry, resume,
  schedule, pipeline, config, mcp, and help
• Preserved detach-mode contract with  prefix in non-TTY error output for background process
  polling
• Added @clack/prompts dependency for enhanced CLI UX
Diagram
flowchart LR
  A["src/cli.ts<br/>1500 lines"] -->|refactored| B["src/cli.ts<br/>260 lines<br/>thin router"]
  A -->|extracted| C["src/cli/ui.ts<br/>TTY-aware display<br/>@clack/prompts"]
  A -->|extracted| D["src/cli/services.ts<br/>Service bootstrap<br/>Error handling"]
  A -->|extracted| E["src/cli/commands/<br/>11 modules<br/>delegate, status,<br/>logs, schedule, etc."]
  B -->|uses| C
  B -->|uses| D
  B -->|delegates to| E
  E -->|uses| C
  E -->|uses| D
  F["@clack/prompts<br/>dependency"] -->|powers| C
Loading

Grey Divider

File Changes

1. src/cli.ts ✨ Enhancement +62/-1306

Monolithic CLI refactored into modular command structure

• Refactored monolithic CLI file from ~1,500 lines to ~260 lines by extracting command logic into
 dedicated modules
• Replaced direct console.log/error calls with ui.* abstraction layer for structured output
• Imported 11 command handlers from src/cli/commands/ directory
• Simplified main command routing to delegate to specialized command modules

src/cli.ts


2. src/cli/ui.ts ✨ Enhancement +173/-0

TTY-aware display abstraction with @clack/prompts integration

• New display abstraction layer routing all output to process.stderr (stdout reserved for MCP
 protocol)
• TTY-aware implementation: uses @clack/prompts styled output in interactive terminals, plain text
 fallback in pipes/CI
• Provides structured logging functions (success, error, warn, info, step, note) with
 color support
• Includes formatting helpers (formatMs, formatBytes, formatDuration) and text styling
 (bold, dim, cyan)
• Critical contract: error() emits  prefix in non-TTY mode for detach-mode error detection

src/cli/ui.ts


3. src/cli/services.ts ✨ Enhancement +50/-0

Centralized service initialization and error handling

 Shared service bootstrap and error handling utilities

src/cli/services.ts


View more (12)
4. src/cli/commands/delegate.ts ✨ Enhancement +299/-0

Task delegation with detach-mode and foreground execution

• Extracted task delegation logic including delegateTask() and handleDetachMode() functions
• Implements detach-mode background process spawning with log file polling for task ID extraction
• Provides waitForTaskCompletion() for real-time event streaming and exit code handling
• Uses ui.* for structured output and spinner feedback during initialization and execution

src/cli/commands/delegate.ts


5. src/cli/commands/schedule.ts ✨ Enhancement +326/-0

Schedule management commands with cron and one-time support

• Extracted schedule command handler and all schedule subcommands (create, list, get,
 cancel, pause, resume)
• Implements argument parsing for cron expressions, one-time schedules, timezone, and missed-run
 policies
• Uses ui.* for structured output with colored status display and formatted schedule details
• Provides comprehensive schedule lifecycle management

src/cli/commands/schedule.ts


6. src/cli/commands/status.ts ✨ Enhancement +74/-0

Task status query and dependency visualization

• Extracted task status retrieval logic supporting single task and all-tasks listing
• Displays task details including dependencies, dependents, duration, and exit codes
• Uses ui.* for colored status output and formatted task information
• Integrates with withServices() for service initialization

src/cli/commands/status.ts


7. src/cli/commands/logs.ts ✨ Enhancement +56/-0

Task output log retrieval with tail support

• Extracted task log retrieval with optional tail limit support
• Separates stdout and stderr output with clear section headers
• Uses ui.* for spinner feedback and structured output
• Integrates with withServices() for service initialization

src/cli/commands/logs.ts


8. src/cli/commands/cancel.ts ✨ Enhancement +26/-0

Task cancellation with reason tracking

• Extracted task cancellation logic with optional reason parameter
• Uses ui.* for spinner feedback and success/error messaging
• Integrates with withServices() for service initialization

src/cli/commands/cancel.ts


9. src/cli/commands/retry.ts ✨ Enhancement +28/-0

Task retry creation and status display

• Extracted task retry logic creating new task from failed/completed task
• Displays new task ID and retry count information
• Uses ui.* for spinner feedback and structured output
• Integrates with withServices() for service initialization

src/cli/commands/retry.ts


10. src/cli/commands/resume.ts ✨ Enhancement +34/-0

Task resumption with checkpoint context support

• Extracted task resume logic with optional additional context parameter
• Displays new task ID, status, retry count, and parent task information
• Uses ui.* for spinner feedback and structured output
• Integrates with withServices() for service initialization

src/cli/commands/resume.ts


11. src/cli/commands/config.ts ✨ Enhancement +94/-0

Configuration display and modification commands

• Extracted configuration management commands (show, set, reset, path)
• Displays resolved configuration with formatted time and byte values
• Uses ui.* for structured output with bold headers and dimmed raw values
• Provides configuration file path output to stdout for scripting

src/cli/commands/config.ts


12. src/cli/commands/mcp.ts ✨ Enhancement +114/-0

MCP server lifecycle and configuration management

• Extracted MCP server commands (start, test, config)
• Implements server startup via dynamic import and test validation with process spawning
• Uses ui.* for spinner feedback and structured output
• Provides MCP configuration display with multiple installation examples

src/cli/commands/mcp.ts


13. src/cli/commands/help.ts ✨ Enhancement +95/-0

Help text generation with styled command reference

• Extracted help text generation with version display from package.json
• Uses ui.* text styling (bold, cyan) for visual hierarchy
• Outputs to stdout via ui.stdout() for machine-readable compatibility
• Provides comprehensive command reference with examples

src/cli/commands/help.ts


14. src/cli/commands/pipeline.ts ✨ Enhancement +68/-0

Sequential pipeline creation with visual representation

• Extracted pipeline command creating chained one-time schedules
• Implements sequential task dependency setup with visual step representation
• Uses ui.* for spinner feedback and formatted pipeline visualization
• Integrates with withServices() for service initialization

src/cli/commands/pipeline.ts


15. package.json Dependencies +1/-0

Added @clack/prompts dependency for CLI UX

• Added @clack/prompts dependency (^1.0.1) for structured CLI output with spinners and styled
 logging

package.json


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link

qodo-free-for-open-source-projects bot commented Feb 27, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Help ANSI leaks to pipes 🐞 Bug ✓ Correctness
Description
delegate help builds ANSI-styled strings using process.stderr.isTTY, but then prints them to
stdout via ui.stdout(). If stdout is piped while stderr remains a TTY (common), help output will
contain ANSI codes in the pipe, contradicting the intended non-TTY/plain-text behavior and the UI
contract that display output routes to stderr.
Code

src/cli/commands/help.ts[R3-10]

+import { bold, cyan, stdout } from '../ui.js';
+
+export function showHelp(dirname: string) {
+  const pkg = JSON.parse(readFileSync(path.join(dirname, '..', 'package.json'), 'utf-8'));
+  const v = pkg.version ?? '0.0.0';
+
+  stdout(`${bold(`Delegate v${v}`)} ${cyan('Task Delegation MCP Server')}
+
Evidence
Help uses stdout() (writes to process.stdout) while styling helpers (bold/cyan) decide whether
to emit ANSI based on isTTY = process.stderr.isTTY. Therefore, when stdout is piped but stderr is
still a TTY, styled strings (ANSI) are emitted into the pipe. This also conflicts with the UI module
header stating display output should go to stderr.

src/cli/commands/help.ts[1-13]
src/cli/ui.ts[1-17]
src/cli/ui.ts[155-173]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`delegate help` prints to stdout but applies styling based on `process.stderr.isTTY`, so `delegate help | cat` can receive ANSI codes even though stdout is non-TTY.

### Issue Context
- UI module states display output should go to stderr; stdout reserved for MCP/machine output.
- Help currently uses `ui.stdout()` but includes styled segments via `bold/cyan` that are based on stderr TTY state.

### Fix Focus Areas
- src/cli/commands/help.ts[1-15]
- src/cli/ui.ts[15-17]
- src/cli/ui.ts[155-173]

### Implementation directions
Pick one:
1) **Stderr-only help (align with UI contract):** replace `stdout(...)` with `process.stderr.write(...)` or `ui.note(...)`/`ui.info(...)`, and ensure no stdout writes for help.
2) **Pipe-friendly stdout help:** keep stdout output but add stdout-based TTY checks for styling (e.g., add `boldStdout/cyanStdout` or allow `bold/cyan` to accept a `stream` and use `stream.isTTY`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. show-deps flag is noop 🐞 Bug ✓ Correctness
Description
--show-dependencies is parsed and passed into the status command, but the status implementation
explicitly ignores it (_showDependencies). This makes the flag misleading (and help text still
claims it shows a dependency graph).
Code

src/cli/commands/status.ts[6]

+export async function getTaskStatus(taskId?: string, _showDependencies?: boolean) {
Evidence
The CLI router parses --show-dependencies and passes it into `getTaskStatus(taskId,
showDependencies), but getTaskStatus names the parameter _showDependencies` and never branches
on it, making the flag a no-op despite being advertised in help output.

src/cli.ts[166-179]
src/cli/commands/status.ts[1-10]
src/cli/commands/help.ts[30-33]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The `--show-dependencies` flag is accepted by the CLI but ignored by the status implementation, making it misleading.

### Issue Context
- Router parses `--show-dependencies` and passes it to `getTaskStatus`.
- `getTaskStatus` explicitly ignores the parameter (`_showDependencies`).
- Help text advertises a dependency graph.

### Fix Focus Areas
- src/cli.ts[166-179]
- src/cli/commands/status.ts[1-74]
- src/cli/commands/help.ts[30-33]

### Implementation directions
Choose one:
1) Implement the flag in `getTaskStatus` (only show dependency/dependent sections or a richer graph when true).
2) Remove the flag from parsing and help output if it’s not supported.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Detach error false positive 🐞 Bug ⛯ Reliability
Description
Detach-mode polling treats any  line in the background log as a CLI error before checking for
Task ID:. Because the background process streams unmodified task stdout/stderr into the same log,
a task that outputs a line starting with  can cause the poller to incorrectly fail even if
delegation succeeded.
Code

src/cli/commands/delegate.ts[R147-179]

+    const taskIdPattern = /Task ID:\s+(task-\S+)/;
+    const errorPattern = /^❌/m;
+
+    const s = ui.createSpinner();
+    s.start('Waiting for task ID...');
+
+    const pollInterval = setInterval(() => {
+      attempt++;
+      try {
+        const content = readFileSync(logFile, 'utf-8');
+
+        // Check for error patterns first
+        if (errorPattern.test(content)) {
+          clearInterval(pollInterval);
+          s.stop('Background process error');
+          const lines = content.split('\n').filter((l) => l.trim().length > 0);
+          const lastLines = lines.slice(-5);
+          ui.error('Background process encountered an error:');
+          for (const line of lastLines) {
+            process.stderr.write(`  ${line}\n`);
+          }
+          process.exit(1);
+        }
+
+        // Check for task ID
+        const match = content.match(taskIdPattern);
+        if (match) {
+          clearInterval(pollInterval);
+          const taskId = match[1];
+          s.stop(`Task delegated: ${taskId}`);
+          ui.info(`Check status: delegate status ${taskId}`);
+          ui.info(`View logs:    delegate logs ${taskId}`);
+          process.exit(0);
Evidence
The polling loop reads the entire log file and checks /^❌/m first. Separately, the background
process writes task output directly to stdout/stderr (which are redirected into the same log file).
Therefore, any task output line beginning with  can trigger the poller’s “background process
error” path before it ever checks for Task ID:.

src/cli/commands/delegate.ts[144-179]
src/cli/commands/delegate.ts[20-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Detach-mode foreground polling can misclassify task output as a CLI error because it scans the full background log for `/^❌/m` before checking for the Task ID.

### Issue Context
- Background process writes both CLI messages and streamed task output into the same log file (stdio redirected).
- Poller uses a broad error regex that can match task output.

### Fix Focus Areas
- src/cli/commands/delegate.ts[144-191]
- src/cli/commands/delegate.ts[20-56]

### Implementation directions
- Reorder checks: **look for `Task ID:` first**, then only treat errors as fatal if no task ID exists yet.
- Consider narrowing the error pattern to a CLI-only prefix (e.g., standardize CLI errors as `❌ delegate:`) and match that exact prefix.
- If feasible, separate CLI bootstrap/delegation logs from task output (two different log files or structured marker lines).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +3 to +10
import { bold, cyan, stdout } from '../ui.js';

export function showHelp(dirname: string) {
const pkg = JSON.parse(readFileSync(path.join(dirname, '..', 'package.json'), 'utf-8'));
const v = pkg.version ?? '0.0.0';

stdout(`${bold(`Delegate v${v}`)} ${cyan('Task Delegation MCP Server')}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Help ansi leaks to pipes 🐞 Bug ✓ Correctness

delegate help builds ANSI-styled strings using process.stderr.isTTY, but then prints them to
stdout via ui.stdout(). If stdout is piped while stderr remains a TTY (common), help output will
contain ANSI codes in the pipe, contradicting the intended non-TTY/plain-text behavior and the UI
contract that display output routes to stderr.
Agent Prompt
### Issue description
`delegate help` prints to stdout but applies styling based on `process.stderr.isTTY`, so `delegate help | cat` can receive ANSI codes even though stdout is non-TTY.

### Issue Context
- UI module states display output should go to stderr; stdout reserved for MCP/machine output.
- Help currently uses `ui.stdout()` but includes styled segments via `bold/cyan` that are based on stderr TTY state.

### Fix Focus Areas
- src/cli/commands/help.ts[1-15]
- src/cli/ui.ts[15-17]
- src/cli/ui.ts[155-173]

### Implementation directions
Pick one:
1) **Stderr-only help (align with UI contract):** replace `stdout(...)` with `process.stderr.write(...)` or `ui.note(...)`/`ui.info(...)`, and ensure no stdout writes for help.
2) **Pipe-friendly stdout help:** keep stdout output but add stdout-based TTY checks for styling (e.g., add `boldStdout/cyanStdout` or allow `bold/cyan` to accept a `stream` and use `stream.isTTY`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Split monolithic cli.ts (1,500 lines) into thin router (~260 lines) +
11 focused command modules + shared ui.ts display layer + services.ts.

Key changes:
- All output routed through ui.ts abstraction (TTY-aware)
- TTY mode: @clack/prompts spinners, colored status, boxed notes
- Non-TTY mode: plain text fallback with critical error prefix preservation
- stdout reserved for MCP protocol; all UI output goes to stderr
- Dependency state shows human-readable explanations
- Logs usage error includes examples
@dean0x dean0x force-pushed the feat/cli-ux-overhaul branch from 98a6b58 to 2ca6448 Compare February 27, 2026 23:56
@qodo-free-for-open-source-projects

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: test (20.x)

Failed stage: Run tests [❌]

Failed test name: RecoveryManager > Edge cases > should handle task at exactly 30 minute boundary as not stale

Failure summary:

The action failed during npm run test:services because a Vitest unit test assertion failed in
tests/unit/services/recovery-manager.test.ts.
- Failed test: RecoveryManager > Edge cases > should
handle task at exactly 30 minute boundary as not stale
- Failure details: the test expected
queue.enqueue (a vi.fn()) to be called with the boundary task, but it was never called (Number of
calls: 0), indicating the recovery logic did not re-queue the task at the 30-minute boundary as the
test expects.
- Location: tests/unit/services/recovery-manager.test.ts:569:29
The test failure
caused the process to exit with code 1, failing the GitHub Action.

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

156:  ##[group]Run npm run build
157:  �[36;1mnpm run build�[0m
158:  shell: /usr/bin/bash -e {0}
159:  ##[endgroup]
160:  > @dean0x/delegate@0.4.0 prebuild
161:  > npm run clean
162:  > @dean0x/delegate@0.4.0 clean
163:  > rm -rf dist logs test-logs test-db tsconfig.tsbuildinfo
164:  > @dean0x/delegate@0.4.0 build
165:  > tsc
166:  ##[group]Run npm run test:all
167:  �[36;1mnpm run test:all�[0m
168:  shell: /usr/bin/bash -e {0}
169:  ##[endgroup]
170:  > @dean0x/delegate@0.4.0 test:all
171:  > npm run test:core && npm run test:handlers && npm run test:services && npm run test:repositories && npm run test:adapters && npm run test:implementations && npm run test:cli && npm run test:scheduling && npm run test:checkpoints && npm run test:error-scenarios && npm run test:integration
172:  > @dean0x/delegate@0.4.0 test:core
173:  > NODE_OPTIONS='--max-old-space-size=2048' vitest run tests/unit/core --no-file-parallelism
174:  �[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/home/runner/work/delegate/delegate�[39m
175:  �[32m✓�[39m tests/unit/core/dependency-graph.test.ts �[2m(�[22m�[2m72 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
176:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mEnvironment variable loading�[2m > �[22m�[2mshould handle invalid number parsing
177:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
178:  - timeout: Number must be greater than or equal to 1000
179:  - maxOutputBuffer: Number must be greater than or equal to 1024
180:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mValidation fallback�[2m > �[22m�[2mshould fallback to defaults on invalid timeout
181:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
182:  - timeout: Number must be greater than or equal to 1000
183:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mValidation fallback�[2m > �[22m�[2mshould fallback to defaults on invalid CPU threshold
184:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
185:  - cpuCoresReserved: Number must be less than or equal to 32
186:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mValidation fallback�[2m > �[22m�[2mshould fallback to defaults on invalid memory reserve
187:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
188:  - memoryReserve: Number must be greater than or equal to 0
189:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mValidation fallback�[2m > �[22m�[2mshould fallback to all defaults on any validation failure
190:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
191:  - memoryReserve: Number must be greater than or equal to 0
192:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mEdge cases�[2m > �[22m�[2mshould handle very large numbers
193:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
194:  - memoryReserve: Number must be less than or equal to 68719476736
195:  �[90mstderr�[2m | tests/unit/core/configuration.test.ts�[2m > �[22m�[2mloadConfiguration - REAL Configuration Loading�[2m > �[22m�[2mConfiguration consistency�[2m > �[22m�[2mshould always return valid configuration
196:  �[22m�[39m[Delegate] Configuration file validation failed, falling back to environment variables and defaults:
197:  - timeout: Number must be greater than or equal to 1000
198:  - cpuCoresReserved: Number must be less than or equal to 32
199:  [Delegate] Configuration file validation failed, falling back to environment variables and defaults:
200:  - maxOutputBuffer: Number must be greater than or equal to 1024
201:  - memoryReserve: Number must be greater than or equal to 0
202:  [Delegate] Configuration file validation failed, falling back to environment variables and defaults:
203:  - timeout: Number must be greater than or equal to 1000
204:  [Delegate] Configuration file validation failed, falling back to environment variables and defaults:
205:  - cpuCoresReserved: Number must be greater than or equal to 1
206:  �[32m✓�[39m tests/unit/core/configuration.test.ts �[2m(�[22m�[2m52 tests�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
207:  �[32m✓�[39m tests/unit/core/container.test.ts �[2m(�[22m�[2m42 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
208:  �[32m✓�[39m tests/unit/core/events/event-bus.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
209:  �[32m✓�[39m tests/unit/core/result.test.ts �[2m(�[22m�[2m37 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
210:  �[32m✓�[39m tests/unit/core/domain.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
211:  �[32m✓�[39m tests/unit/core/errors.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 47�[2mms�[22m�[39m
212:  �[32m✓�[39m tests/unit/core/events/event-bus-request.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[33m 870�[2mms�[22m�[39m
...

220:  �[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/home/runner/work/delegate/delegate�[39m
221:  �[32m✓�[39m tests/unit/services/handlers/dependency-handler.test.ts �[2m(�[22m�[2m34 tests�[22m�[2m)�[22m�[33m 5359�[2mms�[22m�[39m
222:  �[33m�[2m✓�[22m�[39m should proceed without enrichment when checkpoint is not available �[33m 5025�[2mms�[22m�[39m
223:  �[32m✓�[39m tests/unit/services/handlers/schedule-handler.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 116�[2mms�[22m�[39m
224:  �[32m✓�[39m tests/unit/services/handlers/checkpoint-handler.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 46�[2mms�[22m�[39m
225:  �[32m✓�[39m tests/unit/services/handlers/query-handler.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 136�[2mms�[22m�[39m
226:  �[2m Test Files �[22m �[1m�[32m4 passed�[39m�[22m�[90m (4)�[39m
227:  �[2m      Tests �[22m �[1m�[32m84 passed�[39m�[22m�[90m (84)�[39m
228:  �[2m   Start at �[22m 23:57:13
229:  �[2m   Duration �[22m 6.21s�[2m (transform 311ms, setup 43ms, import 358ms, tests 5.66s, environment 0ms)�[22m
230:  > @dean0x/delegate@0.4.0 test:services
231:  > NODE_OPTIONS='--max-old-space-size=2048' vitest run tests/unit/services/task-manager.test.ts tests/unit/services/recovery-manager.test.ts tests/unit/services/autoscaling-manager.test.ts --no-file-parallelism
232:  �[1m�[46m RUN �[49m�[22m �[36mv4.0.18 �[39m�[90m/home/runner/work/delegate/delegate�[39m
233:  �[32m✓�[39m tests/unit/services/task-manager.test.ts �[2m(�[22m�[2m46 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
234:  �[32m✓�[39m tests/unit/services/autoscaling-manager.test.ts �[2m(�[22m�[2m54 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
235:  �[31m❯�[39m tests/unit/services/recovery-manager.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m | �[22m�[31m1 failed�[39m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
236:  �[32m✓�[39m should emit RecoveryStarted event at the beginning�[32m 1�[2mms�[22m�[39m
237:  �[32m✓�[39m should emit RecoveryCompleted event with correct counts when no tasks exist�[32m 1�[2mms�[22m�[39m
238:  �[32m✓�[39m should succeed with no operations when no queued or running tasks exist�[32m 0�[2mms�[22m�[39m
239:  �[32m✓�[39m should call cleanupOldTasks with 7-day threshold in milliseconds�[32m 0�[2mms�[22m�[39m
240:  �[32m✓�[39m should log cleanup count when tasks are cleaned up�[32m 1�[2mms�[22m�[39m
241:  �[32m✓�[39m should not log cleanup when zero tasks are cleaned�[32m 1�[2mms�[22m�[39m
242:  �[32m✓�[39m should re-queue QUEUED tasks and emit TaskQueued events�[32m 1�[2mms�[22m�[39m
243:  �[32m✓�[39m should skip QUEUED tasks that are already in the queue�[32m 1�[2mms�[22m�[39m
244:  �[32m✓�[39m should log enqueue failures but continue recovery�[32m 1�[2mms�[22m�[39m
245:  �[32m✓�[39m should include re-queued QUEUED tasks in RecoveryCompleted count�[32m 1�[2mms�[22m�[39m
246:  �[32m✓�[39m should mark stale RUNNING tasks (>=30 min) as FAILED with exitCode -1�[32m 1�[2mms�[22m�[39m
247:  �[32m✓�[39m should not re-queue stale RUNNING tasks�[32m 0�[2mms�[22m�[39m
248:  �[32m✓�[39m should use startedAt for age calculation when available�[32m 1�[2mms�[22m�[39m
249:  �[32m✓�[39m should fall back to createdAt when startedAt is undefined�[32m 1�[2mms�[22m�[39m
250:  �[32m✓�[39m should include stale tasks in RecoveryCompleted markedFailed count�[32m 0�[2mms�[22m�[39m
251:  �[32m✓�[39m should log stale task failure with age in minutes�[32m 3�[2mms�[22m�[39m
252:  �[32m✓�[39m should log error when update fails for stale task�[32m 0�[2mms�[22m�[39m
253:  �[32m✓�[39m should re-queue recent RUNNING tasks (<30 min) and emit TaskQueued events�[32m 0�[2mms�[22m�[39m
254:  �[32m✓�[39m should skip recent RUNNING tasks already in the queue�[32m 1�[2mms�[22m�[39m
255:  �[32m✓�[39m should include re-queued recent tasks in RecoveryCompleted tasksRecovered count�[32m 0�[2mms�[22m�[39m
256:  �[32m✓�[39m should log enqueue failure for recent running task but continue�[32m 0�[2mms�[22m�[39m
257:  �[32m✓�[39m should return error when findByStatus for QUEUED tasks fails�[32m 0�[2mms�[22m�[39m
258:  �[32m✓�[39m should return error when findByStatus for RUNNING tasks fails�[32m 0�[2mms�[22m�[39m
259:  �[32m✓�[39m should log error when RecoveryStarted emit fails but continue recovery�[32m 0�[2mms�[22m�[39m
260:  �[32m✓�[39m should log error when RecoveryCompleted emit fails�[32m 0�[2mms�[22m�[39m
261:  �[32m✓�[39m should handle a mix of queued, stale running, and recent running tasks�[32m 1�[2mms�[22m�[39m
262:  �[32m✓�[39m should handle multiple queued and multiple running tasks�[32m 0�[2mms�[22m�[39m
263:  �[32m✓�[39m should log TaskQueued event emit failure but still count task as recovered�[32m 0�[2mms�[22m�[39m
264:  �[31m       �[31m�[31m should handle task at exactly 30 minute boundary as not stale�[39m�[32m 6�[2mms�[22m�[39m
265:  �[32m✓�[39m should call findByStatus with correct status values�[32m 1�[2mms�[22m�[39m
266:  �[32m✓�[39m should return ok result on successful recovery�[32m 0�[2mms�[22m�[39m
267:  �[31m⎯⎯⎯⎯⎯⎯⎯�[39m�[1m�[41m Failed Tests 1 �[49m�[22m�[31m⎯⎯⎯⎯⎯⎯⎯�[39m
268:  �[41m�[1m FAIL �[22m�[49m tests/unit/services/recovery-manager.test.ts�[2m > �[22mRecoveryManager�[2m > �[22mEdge cases�[2m > �[22mshould handle task at exactly 30 minute boundary as not stale
269:  �[31m�[1mAssertionError�[22m: expected "vi.fn()" to be called with arguments: [ { id: 'boundary-task', …(16) } ]�[90m
270:  Number of calls: �[1m0�[22m
271:  �[31m�[39m
272:  �[36m �[2m❯�[22m tests/unit/services/recovery-manager.test.ts:�[2m569:29�[22m�[39m
273:  �[90m567| �[39m      // At exactly 30 min, taskAge === threshold, so isStale = false …
274:  �[90m568| �[39m      �[90m// The task should be re-queued, not marked failed�[39m
275:  �[90m569| �[39m      �[34mexpect�[39m(queue�[33m.�[39menqueue)�[33m.�[39m�[34mtoHaveBeenCalledWith�[39m(task)�[33m;�[39m
276:  �[90m   | �[39m                            �[31m^�[39m
277:  �[90m570| �[39m      �[34mexpect�[39m(repo�[33m.�[39mupdate)�[33m.�[39mnot�[33m.�[39m�[34mtoHaveBeenCalled�[39m()�[33m;�[39m
278:  �[90m571| �[39m    })�[33m;�[39m
279:  �[31m�[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯�[22m�[39m
280:  �[2m Test Files �[22m �[1m�[31m1 failed�[39m�[22m�[2m | �[22m�[1m�[32m2 passed�[39m�[22m�[90m (3)�[39m
281:  �[2m      Tests �[22m �[1m�[31m1 failed�[39m�[22m�[2m | �[22m�[1m�[32m130 passed�[39m�[22m�[90m (131)�[39m
282:  �[2m   Start at �[22m 23:57:20
283:  �[2m   Duration �[22m 477ms�[2m (transform 183ms, setup 44ms, import 185ms, tests 82ms, environment 0ms)�[22m
284:  ##[error]AssertionError: expected "vi.fn()" to be called with arguments: [ { id: 'boundary-task', …(16) } ]
285:  
286:  Number of calls: 0
287:  
288:   ❯ tests/unit/services/recovery-manager.test.ts:569:29
289:  
290:  
291:  ##[error]Process completed with exit code 1.
292:  Post job cleanup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant