From 605e3070c7e34292c773884f51400913daa15b40 Mon Sep 17 00:00:00 2001 From: Alfonso Sastre Date: Wed, 9 Sep 2026 04:24:59 +0200 Subject: [PATCH] bin: add lex-code-bootstrap wrapper; document --max-steps in the README bin/lex-code already solves this for the TUI: the VM's default step budget (10,000,000, a DoS guard for untrusted sandboxed snippets) kills a long agentic session with a step-limit-exceeded panic once enough turns or verbose-enough model output accumulate. bootstrap/run.lex -- build/test/verify pipelines against a real task -- is exactly the same "trusted, long-running orchestration" case, but had no wrapper of its own, so the flag had to be remembered by hand every time `lex run` was typed directly against it. Reproduced live, repeatedly: real multi-module builds running 10-20+ minutes across dozens of agent turns hit the panic with the flag omitted, discarding that whole run's output (bootstrap/run.lex only prints per-step output after the graph run returns, so a mid-run panic loses everything, not just the final result). Added bin/lex-code-bootstrap, mirroring bin/lex-code's own defaults and env-var overrides (LEX_CODE_EFFECTS, LEX_CODE_MAX_STEPS). Simpler than bin/lex-code: bootstrap/run.lex's main takes no positional args (every input is env-driven -- LEX_TASK/LEX_TASK_SPEC/LEX_PIPELINE/LEX_PROVIDER -- by the file's own design, so there's no `main --` separator or "$@" forwarding to get right). Also fixed the three `bootstrap/run.lex` invocation examples in the README's own "Bootstrap Script" section, which was missing --max-steps even though the Quickstart and semantic-search sections both already document it for their own entry points -- the exact gap that led to this session hitting the crash three times before finding the root cause. Verified live: ran the wrapper against the repo's own zip demo task (LEX_PIPELINE=build) in a throwaway worktree, produced a correct, lex-check-clean src/list.lex. Co-Authored-By: Claude Sonnet 5 --- README.md | 17 ++++++++++++++--- bin/lex-code-bootstrap | 29 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100755 bin/lex-code-bootstrap diff --git a/README.md b/README.md index a8de937..ceec2f5 100644 --- a/README.md +++ b/README.md @@ -669,15 +669,26 @@ let test_steps := conc.ask(test_actor, Execute(test_task)) used to hardcode one — implement `list.zip`, in four fixed phases, with its own sequential runner — and now drives the same agent graph the TUI does. +This entry point needs the same `--max-steps` override the Quickstart's +`bin/lex-code` wrapper supplies for the TUI, and for the same reason: it's +trusted, long-running orchestration code, not the untrusted-sandboxed-snippet +case the VM's 10,000,000-step default guards against. There's no wrapper +script for this entry point, so it has to be typed by hand every time — +reproduced live: a real multi-module build ran for 17+ minutes across dozens +of agent turns and hit `step limit exceeded` with the flag omitted, discarding +that whole run's output (`bootstrap/run.lex`'s own step-by-step printing only +happens after the graph run returns, so a mid-run panic here loses everything, +not just the final result). + ```sh # the original demo, unchanged -lex run --allow-effects … src/bootstrap/run.lex main +lex run --max-steps 20000000000 --allow-effects … src/bootstrap/run.lex main # a real task, phases of your choosing LEX_TASK="add a retry wrapper to src/http.lex" \ LEX_PIPELINE=build,test \ LEX_PROVIDER=litellm \ - lex run --allow-effects … src/bootstrap/run.lex main + lex run --max-steps 20000000000 --allow-effects … src/bootstrap/run.lex main ``` | Variable | Default | Meaning | @@ -706,7 +717,7 @@ verified_on = [] # ":" — a pass on that path ```sh LEX_TASK_SPEC=examples/tasks/zip.task \ - lex run --allow-effects … src/bootstrap/run.lex main + lex run --max-steps 20000000000 --allow-effects … src/bootstrap/run.lex main ``` The spec's `goal` becomes the task the agents are told, so the words they act diff --git a/bin/lex-code-bootstrap b/bin/lex-code-bootstrap new file mode 100755 index 0000000..3f259bb --- /dev/null +++ b/bin/lex-code-bootstrap @@ -0,0 +1,29 @@ +#!/usr/bin/env sh +# Wrapper for `src/bootstrap/run.lex main` — requires `lex` CLI on PATH. +# +# Same reason `bin/lex-code` exists for the TUI: the VM's default step +# budget (10,000,000, a DoS guard for *untrusted* sandboxed snippets per +# `lex run --help`) kills a long agentic session outright with a +# step-limit-exceeded panic once enough turns or verbose-enough model +# output accumulate. bootstrap/run.lex's own build/test/verify pipeline +# is exactly this case — trusted, long-running orchestration code, not +# an untrusted snippet — and it has no wrapper of its own, so the flag +# has to be remembered by hand every time `lex run` is typed directly. +# Reproduced live, repeatedly: real multi-module builds running 10-20+ +# minutes across dozens of agent turns hit `step limit exceeded` with +# the flag omitted, discarding that whole run's output (bootstrap/run.lex +# only prints per-step output after the graph run returns, so a mid-run +# panic here loses everything, not just the final result — see the +# README's "Bootstrap Script" section for the full story). +# +# bootstrap/run.lex's `main` takes no positional args (LEX_TASK, +# LEX_TASK_SPEC, LEX_PIPELINE, LEX_PROVIDER are all read from the +# environment, not argv — see its own header comment for why), so unlike +# bin/lex-code there is no `main --` separator or "$@" forwarding to get +# right here; just the effect grant and the step-limit override. +set -e +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +LEX_CODE_EFFECTS="${LEX_CODE_EFFECTS:-approval,concurrent,crypto,env,fs_read,fs_walk,fs_write,io,llm,net,proc,random,sql,stream,time}" +LEX_CODE_MAX_STEPS="${LEX_CODE_MAX_STEPS:-20000000000}" +exec lex run --max-steps "$LEX_CODE_MAX_STEPS" --allow-effects "$LEX_CODE_EFFECTS" \ + "$SCRIPT_DIR/../src/bootstrap/run.lex" main