SWE-Lego-Live

Reference

config.yaml schema

The fixed schema every block's config.yaml follows

Every block in the tree — root or subblock — has a config.yaml with the same top-level shape. Live state is not stored here; that lives in artifacts/index.yaml. The schema is machine-enforced by scripts/validate_config.py (run by every block's dryrun.sh, the CI schema tests, and the :check skills).

Top-level structure

meta_info:
  name:                 # short identifier; must equal the block's directory name
  label:                # human-friendly title
  description:          # one-sentence purpose
  parent:               # parent block's `name`, or null for the root
  subblocks:            # parent blocks only: children with a role one-liner — NO wiring
    <child_name>: {role: "<one phrase>"}
  dependencies:         # this block's OWN upstream hand-offs — see "Wiring rule"
    <input.dot.path>: <source_block>.output.<key>
  repos: {}             # name → {commit_id, role}; pinned vendored deps under repos/
  resources:
    ip:                 # 'local' (default) or null = current host; remote IP = SSH+tmux
    directory:          # working directory on the remote node (when ip is remote)

runtime_info:
  input: {}             # ONLY values originating outside the block tree
  output: {}            # values produced for downstream blocks

These are the only two top-level sections. Legacy status: and evolving: sections and a top-level environment: are validation failures (schema:legacy-status, schema:legacy-evolving, schema:unknown-toplevel); per-run env vars live in runtime_info.input.env_extra.

Wiring rule

This is the rule the whole pipeline depends on:

Each consumer block declares its upstream hand-offs in its own flat meta_info.dependencies. The key is a dot-path into that block's runtime_info.input naming the input that receives the value; the value references the producer's output. A block with no upstream declares an explicit dependencies: {}. The root's subblocks entries carry roles only — never wiring.

Two value forms:

# string form — required dependency
task_source.dataset_name: curator.output.swe_tasks_dir

# mapping form — conditional and/or optional
source.job_dir:
  from: tracer.output.raw_trajectories_dir
  when: {source.type: harbor_job}   # enforced only while these inputs hold these values
  required: false                   # null producer output → warning, not failure

Resolution reads the producer's runtime_info.output.<key>: a non-null value first, else path. A dangling reference (missing producer block or output key) always fails validation, even when the dependency is inactive or optional. The validator also warns (dep:path-mismatch) when a consumer's configured path does not lie under the producer's declared output path — catching stale paths after renames.

Fill markers in runtime_info.input

MarkerMeaningValidator
humanUser must replace before a runinput:unfilled (fail)
""Auto-derived or env/file-supplied; never edit to run
nullSemantic unset / default / all
anything elseReal working default
<...>, REPLACE_ME, YOUR_API_KEY, changemeRetired legacy placeholdersinput:placeholder (fail)

runtime_info.output shape

Each output key is a mapping with path: (a static location fixed at authoring time, block-relative) and/or value: (run-produced — null until the block's run script writes it back, as trainer's train.sh does after training). Consumers resolve value first, then path.

resources.ip

  • local or null → run on the current host (default; no SSH).
  • Real remote IP → the agent must SSH into that node and run inside a tmux session, with meta_info.resources.directory as the working directory.

Do not "restore" an old remote IP from git history. The local default is intentional.

Validation

python3 scripts/validate_config.py --root .                  # whole tree + cross-block deps
python3 scripts/validate_config.py --block subblock/tracer   # one block
python3 scripts/validate_config.py --block subblock/tracer --config tests/smoke/config.yaml

Findings are printed as [OK]/[WARN]/[FAIL] lines with stable labels (schema:*, dep:*, input:*, output:shape, tree:*); the exit code is non-zero iff any [FAIL] was reported.

Where to read more

  • The canonical contract: .claude/plugins/root-plugin/resources/BLOCK_DEFINITION.md.
  • The schema template: .claude/plugins/root-plugin/resources/config.template.yaml.
  • A worked example scaffold: .claude/plugins/root-plugin/resources/example_block/.

On this page