Running Cascaded Blocks
Cascaded mode is the root plugin coordinating child blocks in dependency and declaration order. Use it after running the blocks individually at least once, when their inputs, outputs, and approval gates are already familiar.
The operating pattern is three skills and one experiment brief: prepare the tree, validate it, then ask the root plugin to dispatch the work. The brief describes the target and constraints; it does not override block configuration or make undeclared handoffs automatic.
Step 1: Prepare the tree
/root:setupThis checks shared tooling and ensures the root config.yaml exists. It can
offer to invoke each child's setup, but recursion is optional and confirmed one
block at a time. Setup can create environments, synchronize pinned repositories,
and fill approved inputs; it does not launch workloads.
Keep secrets such as LLM API keys and GITHUB_TOKENS in environment variables
or ignored private files. Non-secret decisions such as model names, languages,
benchmarks, and endpoint locations belong in the relevant block's
runtime_info.input.
Step 2: Check the tree
/root:checkThis is operationally read-only: it validates configs, both ends of declared dependencies, repository pins, environments, per-block dry runs, and live model endpoints without launching workloads. It cannot infer a dependency that has not been declared, so a missing edge is still a design decision to resolve.
Fix every required failure before continuing. Optional Cloudflare credentials only affect dashboard publishing and do not block the pipeline.
Collect pull requests before the root run
Root orchestration consumes Curator's existing collection under
blocks/curator/artifacts/collected_prs/. Run /curator:collect-prs first and
wait for it to finish.
Step 3: Run the tree
/root:run start the data pipelineThe root skill repeats preflight, presents the resolved configuration, and waits for explicit approval before expensive work. Natural-language instructions may lead the skills to propose concrete config changes, but those inputs remain user-owned and every change requires confirmation.
What each stage should produce, and what to hold it to:
| Stage | Target | The condition that matters |
|---|---|---|
| Curator | Verified Python tasks | Only tasks that pass NOP and Oracle validation reach the manifest. |
| Tracer | Solved rollouts | Preserve the raw trajectory and verified reward; adapt concurrency to endpoint health rather than dropping tasks silently. |
| Selection and conversion | A frozen training set | This is a data-preparation operation, not a registered block. Deduplicate, remove malformed and shallow examples, and freeze an ordered set. |
| Trainer | One checkpoint | Derive the training configuration from the model and GPU topology; preserve the resolved config, logs, and curves. |
| Evaluator | One completed benchmark run | Keep one agent, serving, and verifier configuration; resume infrastructure failures without changing evaluation conditions. |
Current handoff boundaries
The shipped configuration has an active Curator merged_tasks_dir -> Tracer
task_source.dataset_name edge. Tracer raw_trajectories_dir -> Trainer
source.job_dir is conditional on Trainer using source.type: harbor_job; the
default hf_lf profile leaves it inactive, and Tracer's sft_data_dir has no
declared Trainer consumer. Trainer checkpoint -> Evaluator is not declared, so
checkpoint serving and Evaluator endpoint configuration remain explicit steps.
The root script is not cascaded mode
The parent-plugin contract for /root:run dispatches child run skills. Do not
substitute root scripts/start.sh: that separate launcher starts only the
Python Curator worker and Tracer in detached sessions, does not wait for
Curator, and skips Trainer and Evaluator.
For a partial workflow, invoke the relevant child skills individually. Current root target resolution treats multiple named blocks as ambiguous rather than as a requested slice.
While it runs
Read each block's outputs, logs, dashboard, and latest artifacts/index.yaml
entry. A normal leaf run automatically records metadata, a config snapshot, a
copy of its scripts, and repository HEAD SHAs, then appends a block-local index
entry. Generated trajectories, logs, checkpoints, and curves remain ordinary
artifacts unless they are explicitly captured.
When a failure or quality regression appears, use the same loop throughout: read the evidence, form a hypothesis, change the smallest responsible thing, rerun only the affected downstream stages, and retain both failed and improved attempts.
Case study: recovery and improvement
One agent used this workflow to operate Curator, Tracer, Trainer, and Evaluator
across a Python-only experiment. Curator produced 4,166 verified tasks, and a
GLM-5.2 teacher solved 915 rollouts. Training used
Qwen3.5-35B-A3B-Base on one host with 8× H800 80GB GPUs, and evaluation used
all 500 SWE-bench Verified tasks.
What the agent recovered from
| Evidence | Smallest responsible change |
|---|---|
| Inference endpoints returned HTTP 502 responses and timed out. | Route new requests through healthy endpoints and record the routing change. |
| Some converted trajectories contained tool calls the downstream harness could not parse. | Normalize the tool-call format during conversion rather than patching Trainer or Evaluator. |
Host memory, not GPU memory, was exhausted at 128k context with use_unsloth_gc. | Switch to standard gradient checkpointing and keep the full context. |
NCCL selected eth0 on a single multi-GPU host and failed to synchronize. | Bind distributed communication to loopback (lo) for that topology. |
Training completed three epochs and 24 optimizer steps; per-step loss declined from 0.524 to a minimum of 0.229, while the reported summary training loss was 0.369.

Figure 1. Full-parameter SFT loss for the depth-first run.
The second selection favored reasoning substance over reasoning frequency. The comparison is consistent with that hypothesis, but it is not proof that selection was the only changed variable.
| Metric | Coverage-first attempt | Depth-first attempt | Difference |
|---|---|---|---|
| Trajectories | 500 | 512 | about the same |
| Reasoning coverage | 80.7% | 30.7% | -50 points |
| Reported reasoning depth | 140 char/block | 959 char/turn | different denominators |
| SWE-bench Verified solve rate | 56.1% | 64.4% | +8.3 points |
The untrained base model scored 7.6%, so the depth-first result was 56.8 points higher under the reported evaluation.

Figure 2. The base model and the two SFT attempts.
Why LegoFlow enabled it
- Declared boundaries localize change. Each declared producer and consumer names the same handoff, so a format mismatch can be traced upstream. The validator checks declared edges; it does not invent missing ones.
- Per-block evidence supports reruns. Config and script snapshots, repository SHAs, block-local indexes, and retained runtime artifacts let the operator compare attempts without relying on memory.
- A uniform lifecycle reduces operational variation. Setup, check, run, archive, and dashboard surfaces give each block a familiar control plane, while the input/output contract keeps internal fixes behind a stable boundary.
Reproducibility warning
Exact tasks, trajectories, corrections, and scores will not repeat bit for bit. Live GitHub state, model sampling, provider revisions, endpoint health, retries, container dependencies, GPU kernels, and scheduling all move underneath a run. An agent's self-corrections depend on the failures it happens to see, so another run may take a different corrective path.