Skip to content

Output

Source files: src/output/progress.ts, src/output/terminal.ts

The output module provides real-time terminal feedback while tests are running. LLM invocations can take anywhere from seconds to minutes per test file, so without live feedback the tool would appear frozen. The spinner system animates Unicode Braille characters at 80ms intervals, showing which test is currently running and progress through the suite. When a test completes, the spinner is replaced with a result line showing pass/fail counts.

The colour system uses raw ANSI escape codes rather than a library like chalk. It detects whether stdout is a TTY — in a terminal, it shows animated spinners and coloured output. In piped or CI output (where escape codes and line overwriting would produce garbage), it falls back to static, unadorned lines.

createProgress(total) returns a Progress object with three methods:

Starts an animated spinner (TTY) or prints a static line (non-TTY):

⠹ [1/5] Running auth-middleware.spec.md...

Uses Unicode Braille frames (⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏) cycling at 80ms intervals.

Replaces the spinner with a retry indicator:

⟳ [1/3] Retrying auth-middleware.spec.md...

Shows the current repeat iteration when --repeat is greater than 1:

⟳ [1/5] auth-middleware.spec.md (run 2/3)...

result(testName, results, index, verbose?)

Section titled “result(testName, results, index, verbose?)”

Stops the spinner and prints the final result with an icon:

✔ [1/5] auth-middleware.spec.md · 2 passed
✗ [2/5] api-routes.spec.md · 1 failed
⚠ [3/5] broken-test.spec.md · 1 errored

Results from a single test file may contain multiple scenarios (e.g. “2 passed, 1 failed”).

Verbose output appears in two places:

  1. Progress results — The result() method prints per-scenario lines below each test result, showing the individual test ID and status icon.
  2. Terminal summaryprintSummary() prints a grouped breakdown of all results. For failures, it includes the expectation, observed behaviour, location, and suggested resolution.

This is useful during development when you want to see exactly what the LLM reported without opening the full Markdown report.

The colors object is exported for use across the output layer:

FunctionANSI codeUsage
green\x1b[32mPassed counts
red\x1b[31mFailed counts
yellow\x1b[33mErrored counts, warnings
cyan\x1b[36mSpinner frames
dim\x1b[2mIndex tags, separators
bold\x1b[1mEmphasis
greenBold\x1b[1;32mFinal “PASSED” verdict
redBold\x1b[1;31mFinal “FAILED” verdict
yellowBold\x1b[1;33mEmphasis warnings

Colour is disabled when NO_COLOR is set or FORCE_COLOR=0, following the no-color standard.

printSummary() in terminal.ts prints the final output after all tests complete:

Semantic tests completed
Report: semtest-results/latest.md
CI Output: semtest-results/ci-results.json
JUnit: semtest-results/junit-results.xml
Debug: semtest-results/debug/
Passed: 10
Failed: 2
Errored: 1
Validation Issues:
- [duplicate-id] Duplicate test ID "auth-check" found in: auth.spec.md, session.spec.md
FAILED
LineColourCondition
Report pathAlways
CI Output pathAlways
JUnit pathOnly if --junit enabled
Debug pathOnly if --debug enabled
Passed countGreenAlways
Failed countRedAlways
Errored countYellowOnly if > 0
Skipped countDimOnly if > 0
Invalid countDimOnly if > 0
Validation issuesYellow headerOnly if validation ran and has issues
Final verdictGreen bold / Red bold”PASSED” or “FAILED”