monty runs python3 in-process (fast,
stdlib-only) and docker runs it in your container (your packages, an
exec round-trip):
policy.py
python3 /jobs/train.py runs in the container; cat data.csv | python3 -c ... stays on monty.
Input: the line’s context
The script reads one global,ctx:
commands has one entry per pipeline stage; command and builtin
mirror the first. It round-trips through JSON (RouteContext.from_dict)
for tests.
Output: the verdict
In code the typed forms are
RouteResult and DenyResult:
script: answers a yes or no: will it serve this
line? With no placement, the first willing capturer wins. A runtime a
policy places the line on must also say yes, or the line is refused with
runtimes.<name> as the refusal’s policy. The caller’s runtime=
argument skips the scripts.
Admit, then route
The route policy is the built-in answer to the policy’spre_execute hook, asked before
any coded policy. A coded policy places a line the same way:
$( ),
eval, source, xargs) keep the outer line’s placement.
ws.explain(line) shows each placement answer and each command’s
runtime.
What runs the scripts
A script runs on an evaluator runtime from theruntimes list: a
.py script on the first Python evaluator (monty, or pyodide in
TypeScript), a .js one on the first JavaScript evaluator (quickjs).
With no evaluator the first decision fails. A script that runs past 10
seconds fails the line.
In code, route_policy= also takes a plain function, sync or async,
called directly; a runtime’s script= takes (ctx) -> bool:
Bring your own
InheritEvaluatorMixin (Python) or implement Evaluator with the
EVALUATOR brand (TypeScript) on your runtime, and it can evaluate
scripts: eval(code, inputs=...) returns the last expression’s value.
The docker examples do it by piping a harness to python3 -:
python,
typescript.