What it does for you
Release checks and agent workflows need a local runner that finishes predictably and leaves a short report. Workflow Harness Lite reads a JSON list of named commands, runs them in parallel, stops any that run past a timeout, redacts secret-shaped text from the output previews, and exits non-zero if anything failed. It can also write a receipt that records hashes of each command and its output, with no raw text in it.
- Parallel by defaultIndependent tasks run at once;
--no-parallelruns them in order. - Guaranteed to endEvery task has a timeout, so a hung command cannot hold the run open.
- Redacted previewsOutput previews are capped in length and secret-shaped values are replaced.
- A receipt without the textCommands and output appear as SHA-256 hashes, and the privacy fields say so.
Source: README.md at 5886706 (version 0.2.0)
Watch
No concept film fits this tool closely yet. The walkthrough below covers it in text, with real commands and output.
Video walkthrough: coming with the next release.
How it works, one step at a time
Scroll, or use the step buttons. The panel runs a four-task config written for this page: two commands that pass, one that prints a token-shaped line and fails, and one that hangs. Every line is output from workflow-harness-lite at commit 5886706 under Node 25.
- 01
A config of named commands
A workflow is a name and a list of tasks, each a name and a command. This one checks the Node version, runs a stand-in lint, runs a flaky step that prints a token to stderr and exits 2, and runs a step that waits a minute.
Source: README.md, "Usage"
- 02
Run them, all at once
The harness starts the four tasks in parallel and prints one line per task. Two pass and two fail, and the run exits 1.
Source: src/workflow_harness_lite.js,
runWorkflow - 03
A hung task is stopped
The hang task would wait 60 seconds. Every task has a timeout: 15 seconds by default, and here
--timeout 2000sets 2. The task is killed at about 2,018 ms and recorded as a failure, so the run ends.The receipt records the bound it ran under: guaranteed termination, the per-task timeout and a maximum of four iterations for four tasks.
Source: src/workflow_harness_lite.js,
runTask - 04
Secrets out of the preview
The flaky task printed a
token=line. The JSON report keeps a short preview of each task's output, and the preview shows the token replaced. Previews are capped at 4,000 characters by default.Source: src/workflow_harness_lite.js,
sanitizeOutput - 05
A receipt with no commands and no output
--telos-receiptwrites a bounded-run receipt. Each task appears by name, index, command hash, status, exit code, duration and output hashes. The privacy fields state that no raw command, raw output or absolute working directory is included, and the receipt carries its own hash.Source: src/telos_receipt.js,
buildTelosReceipt
Walkthrough
Install it, run it once, then use the main feature. Each command below is real, and so is its output.
Get it
Clone it. Node 18 or newer, no dependencies.
$ git clone https://github.com/HarperZ9/workflow-harness-lite && cd workflow-harness-lite $ npm testFirst run: the demo
Run a two-step workflow and build its receipt.
$ node examples/demo.mjs runWorkflow -> status=pass total=2 passed=2 failed=0 skipped=0 buildTelosReceipt -> project-telos.bounded-run-receipt/v1 okRun your own workflow
A step that fails makes the run fail.
$ workflow-harness-lite --config wf.json workflow=local-checks status=fail passed=2 failed=2 PASS node-version PASS lint FAIL flaky FAIL hangWrite a receipt
Record the bounded run as a receipt.
$ workflow-harness-lite --config wf.json --telos-receipt receipt.json schema project-telos.bounded-run-receipt/v1 terminal_status error counts total 4, passed 2, failed 2 flaky command_hash sha256:8b0faa47b894b99e... status fail code 2 stderr_hash sha256:5e7b8623d7048b91... raw_output_included false privacy raw_commands_included false, raw_output_included false, absolute_cwd_included false receipt_hash sha256:2ca9c5963543c0cc...
Output from workflow-harness-lite at 5886706 on Windows with Node 25. Hashes in a receipt depend on the commands and their output, so yours will differ.
What it does not do
- It runs local commands only. It is not a CI system and does not sandbox what the commands do.
- Redaction of previews is by shape. Output that holds a secret in another form is not caught.
- The timeout is one value for the whole run, set with
--timeout. A task cannot carry its own. - Every task's side-effect class is recorded as unknown. The harness does not inspect what a command changes.
Source: README.md at 5886706, "Current status" and "Report"; the receipt written for this page
Check what stuck
Answer each one in your head before you open it.
What stops the hang task?
The per-task timeout. The task is killed and recorded as a failure, so the run ends.
What does the JSON report show for the flaky task's stderr?
token=
What does the receipt keep about each command?
Its hash, status, exit code, duration and output hashes, with no raw command or output.