Recommended Gate Resources
LumenFlow’s gates layer accepts a vendor-agnostic resource registry under
software_delivery.gates.resources. The registry has two opt-in sub-fields:
env— environment variables to inject into every gate subprocess (caller env wins on collision).runners— flag-injection rules keyed by runner name. Each rule says: “if the gate command containsmatchas a substring AND does not already specifyflag, splice<flag>=<value>into the command before any shell operator (|,>,&&, …).”
The runtime mechanism is opt-in — gate execution passes the configured
command through without choosing a runner. During lumenflow init and
lumenflow:upgrade, LumenFlow can project a safe scoped default when the
project already provides explicit runner evidence. This page also lists
snippets you can adjust for repository-specific needs.
Choosing a test runner
Section titled “Choosing a test runner”Choose the command your project already uses and wire that command into
software_delivery.gates.commands. Runtime gates store and execute that
consumer command verbatim. Initialisation and upgrade may infer Vitest, Jest,
Nx, or Turbo only from package.json, a runner configuration file, or an
explicit changed-test script; a language preset alone is never treated as
runner evidence.
Vitest
Section titled “Vitest”Use resources.runners when your CI or local machines need bounded workers.
If the command already includes --maxWorkers, LumenFlow leaves that explicit
choice untouched. CLI flags in gates.commands take precedence over the
resource rule, so LumenFlow emits a non-blocking warning naming the command
and flag when it detects that override.
Command flags take precedence
Section titled “Command flags take precedence”gates.commands is the source of truth for a particular gate invocation. A
flag hardcoded in a command, such as --maxWorkers=4, overrides the matching
resources.runners value, such as --maxWorkers=1. LumenFlow preserves the
command and continues execution; the warning is advisory and emitted once per
process for each distinct command/flag combination.
The same advisory also covers common worker, reporter, and timeout flags even when no resource injection rule exists. This helps surface command-level settings that may be taking precedence over a runner configuration file.
To centralize a setting, remove the flag from gates.commands and add the
corresponding resources.runners rule. Keep the command flag when a specific
gate intentionally needs different behavior; its explicit CLI value wins.
For Jest, keep the command semantics in your package scripts or gate command.
LumenFlow only injects a configured resource flag when the command token
matches match and the flag is absent.
Mocha does not define a universal changed-test mode. Leave
test_incremental unset unless your repository has a package script that maps
changed files to Mocha arguments. An unset or full-equivalent incremental
command safely falls back to test_full.
bun:test
Section titled “bun:test”test_runner is a label for your workspace. It can name bun:test while the
resource rule matches the actual binary token in the shell command. Add
test_incremental only when the project owns a genuinely scoped Bun command.
For small runners such as uvu, keep the full gate command close to the command you would run by hand. Add a changed-test script only when the project can map changed code to the correct test files.
Automatic defaults on init and upgrade
Section titled “Automatic defaults on init and upgrade”LumenFlow chooses a generated test_incremental command in this order:
- A project-owned
test:changed,test:incremental, ortest:affectedpackage script. - File-level impact analysis from evidenced Vitest or Jest tooling.
- Nx affected projects.
- Turbo affected packages as a last resort.
The generated command uses the configured integration remote and branch
instead of assuming origin/main. Turbo is intentionally last: --affected
works at package level, so a change to a shared core package can select most
reverse dependants. Vitest or Jest changed-test analysis is usually more
precise for repositories that expose those runners directly.
For unsupported ecosystems, init leaves test_incremental empty and gates
fall back to test_full. Upgrade repairs only a missing/blank value or a
legacy value equal to test_full, and only when a full fallback is already
configured; it preserves custom commands and YAML comments.
Recommended snippet (Vitest + Playwright)
Section titled “Recommended snippet (Vitest + Playwright)”Each rule is conditional:
- A rule only fires when the resolved gate command contains its
matchsubstring. So avitest-workersrule is a no-op when the active command invokes a non-Vitest runner. - A rule never overwrites a flag the user has already specified. If your
test_incrementalreadsvitest --changed --maxWorkers=4, thevitest-workersrule sees--maxWorkersis already present and leaves the command alone. The command-level value takes precedence and produces a non-blocking advisory. Same for the paired--flag valueform. - Flag injection is spliced before the first shell operator, so chained redirection / pipelines remain attached to the correct process.
Why this is opt-in
Section titled “Why this is opt-in”Prior to v5.8 LumenFlow auto-injected --maxWorkers=1 and
--teardownTimeout=30000 whenever it detected a vitest --changed
command. That coupling lived in the software-delivery pack’s
buildVitestChangedArgs helper and the
augmentVitestIncrementalCommand follow-up (which fixed a bug where
the original helper overwrote user-supplied flags).
A later release removed both helpers from runtime gate execution as part of LumenFlow’s vendor-neutral execution boundary. Hardening defaults still live in consumer config and remain opt-in. Init and upgrade runner detection is a separate configuration-projection step and does not rewrite commands at run time.
Migration note
Section titled “Migration note”If your project relied on the implicit Vitest hardening before v5.8:
- Paste the snippet above into your
workspace.yaml. - Run
pnpm gatesand confirm that the incremental test command logs the expected--maxWorkers=1 --teardownTimeout=30000suffix (or your repo-specific overrides if you set them explicitly). - No change is required to your
gates.commands.test_incrementalvalue itself — the resources mechanism augments it at run() time.
If you do not configure test_incremental, or it is equal to
test_full, LumenFlow falls back to the configured full command. Runtime
execution never invents a runner-specific command.
Schema reference
Section titled “Schema reference”The resources block is validated by GateResourcesSchema in
@hellmai/lumenflow-packs-software-delivery/config/lumenflow-config-schema. Each runner entry has shape:
Invalid blocks log a warning and are ignored; they do not break gate execution.
See also
Section titled “See also”- The release that introduced
applyGateResourcesand the schema. - The original “preserve configured flags” bug fix that this page supersedes.
- The change that deleted the runner-specific hardening helpers and routed hardening through this page’s snippet.