Stacked on #864, which adds the executor. This branch adds the `script:`
step
itself: the YAML directive, the runner integration, the CLI and MCP
rendering,
and the authoring reference.
```yaml
- script: { path: ../../scripts/seed-order.mjs }
- script: { path: ../../scripts/seed-order.mjs, timeout: 60000 }
```
A `script:` step runs an external `.mjs` file from the project, in a
fresh Node
process. What the script does is its own business — seeding an order,
creating
a test account, cleaning up what a run left behind are the reasons flows
have
wanted one. It drives no device, so a flow of nothing but scripts runs
with
nothing booted.
## What it adds
- **The directive.** The value is always a map; `path` is required and
obeys
the same name rules a `run:` target does, spelled for `.mjs`. It
resolves
against the directory of the flow file containing the step, so a
fragment
reaches the same script whichever flow composed it. A mis-cased path is
refused rather than run, because macOS and Windows would open it and
Linux CI
would not.
- **The report.** The script's stdout and stderr come back on the step
and
print under the step line, on a pass as well as a failure — it is the
only
record of what the step did to the backend. Both renderers (CLI, MCP)
carry
it, live and buffered.
- **The fail/error split.** A `fail` is the script's own answer; an
`error` is
the host's. That is what lets CI tell a regression from the machine it
ran
on.
- **Two boundaries.** An uploaded flow carrying a `script:` step is
refused
before anything runs — its `.mjs` never left the client. A flow whose
script
step sits beside a `run:` step still resolves a device.
## Review follow-ups
The last three commits answer a review of the three above them.
- A launch behind a leading `script:` was not read as the flow's leading
launch, so a Chromium flow that seeded a backend first hoisted no boot,
bound
to whatever browser happened to be up, and passed a launch it never
performed. The same lead-in walked a fragment past the
`executionPrerequisite` refusal its `echo:`-led twin is given. Both
readers
now share one exhaustively-switched predicate.
- Coverage: the whole failure-kind table, the mis-cased arm CI never
ran, the
two unreached `scriptFileProblem` arms, symlink resolution for a script
path,
and the CLI live-progress closure that no test had executed.
- Docs: the reference claimed the log was secret-redacted (it is not),
never
mentioned the environment allowlist, the working directory, the
time-limit
ceiling or the log caps, stated a fail/error rule that was not the
code's,
and was missing from its own table of contents. The skills stated a
closed
list of legal unrecorded insertions that excluded the only way this step
can
ever be written.
## Verification
`npm run build`, `npx eslint . --max-warnings 0`, `npx prettier --check
.`,
`npm run knip`, `npm run typecheck:scripts` and `npm run test:scripts`
are
green, as are the three `tsconfig.test.json` typechecks. Suites:
tool-server
357 files / 4552 passed, `@argent/cli` 469, `@argent/mcp` 83,
`@argent/registry` 90.
Reproduced end to end against a real tool server and a real Electron
app, not
only in tests: a flow of `script:` then `launch:` now boots its own
Chromium
instance and reports it, where before it attached to a stray browser and
reported a green launch for an app path that did not exist.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added support for local `.mjs` scripts as flow steps, including
configurable timeouts, validation, cancellation, and device-free
execution.
- Script output is displayed in CLI runs and included in MCP flow
results, with indentation and truncation notices.
- Script failures now provide clearer diagnostics and verdicts.
- Flow authoring tools recognize and guide creation of script steps.
- **Documentation**
- Added guidance for script syntax, execution limits, output handling,
classification, and remote-run restrictions.
- Updated flow creation and QA guidance to include script steps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Hubert Gancarczyk <claude-hubert.gancarczyk@swmansion.com>