diff --git a/scripts/tests/ygg-engine.test.sh b/scripts/tests/ygg-engine.test.sh index 710d70f..9f5dc95 100755 --- a/scripts/tests/ygg-engine.test.sh +++ b/scripts/tests/ygg-engine.test.sh @@ -37,7 +37,13 @@ cat > "$T/bin/devcontainer" <<'EOF2' #!/usr/bin/env bash echo "${FAKE_CLI:-0.89.0}" EOF2 -chmod +x "$T/bin/podman" "$T/bin/devcontainer" +# mountpoint -q DIR succeeds only for a folder that holds a .fake-mounted file (nothing is really mounted here). +cat > "$T/bin/mountpoint" <<'EOF2' +#!/usr/bin/env bash +[ -e "${2:?}/.fake-mounted" ] +EOF2 +chmod +x "$T/bin/podman" "$T/bin/devcontainer" "$T/bin/mountpoint" +touch "$T/bind/.fake-mounted" export PATH="$T/bin:$PATH" YGG_BIND="$T/bind" YGG_ENGINE_TIMEOUT=2 run bash "$S/ygg-engine.sh" check --folder "$D" @@ -69,6 +75,10 @@ check "check refuses another devcontainer CLI version" bash -c "[ $rc = 2 ]" && YGG_BIND="$T/nowhere" run bash "$S/ygg-engine.sh" check --folder "$D" check "check refuses a missing bind mount" bash -c "[ $rc = 2 ]" && has "bind mount" +mkdir -p "$T/plain" +YGG_BIND="$T/plain" run bash "$S/ygg-engine.sh" check --folder "$D" +check "check refuses a folder that exists but has nothing mounted on it" bash -c "[ $rc = 2 ] && grep -q 'nothing mounted' '$T/out' && grep -q 'sudo mount --bind' '$T/out'" + D2="$T/other"; mkdir -p "$D2"; printf 'sandbox:\n engine: unix://%s/gone.sock\n' "$T" > "$D2/factory.yaml" run bash "$S/ygg-engine.sh" check --folder "$D2" check "check names a socket that is not there" bash -c "[ $rc = 2 ]" && has "gone.sock is not there" diff --git a/scripts/tests/ygg-evidence.test.sh b/scripts/tests/ygg-evidence.test.sh index 71a572a..8a43ae2 100755 --- a/scripts/tests/ygg-evidence.test.sh +++ b/scripts/tests/ygg-evidence.test.sh @@ -45,7 +45,12 @@ esac EOF # shellcheck disable=SC2016 # the printf format holds a literal ${...}, not an expansion printf '#!/usr/bin/env bash\necho "${FAKE_CLI_VERSION:-0.89.0}"\n' > "$T/bin/devcontainer" -chmod +x "$T/bin/ygg" "$T/bin/devcontainer" +# mountpoint -q DIR succeeds only for a folder that holds a .fake-mounted file (nothing is really mounted here). +cat > "$T/bin/mountpoint" <<'EOF' +#!/usr/bin/env bash +[ -e "${2:?}/.fake-mounted" ] +EOF +chmod +x "$T/bin/ygg" "$T/bin/devcontainer" "$T/bin/mountpoint" export PATH="$T/bin:$PATH" # --- ygg-evidence.sh on a project with a ledger. @@ -91,9 +96,10 @@ unset SOME_API_KEY # --- ygg-smoke-loop.sh. D="$T/ygg-it"; mkdir -p "$D" printf 'CLAUDE_CODE_OAUTH_TOKEN=%s\n' "$SECRET" > "$T/factory.env" -mkdir -p "$T/bind" +mkdir -p "$T/bind" "$T/plain" +touch "$T/bind/.fake-mounted" export YGG_BIND="$T/bind" YGG_ODIN="$T/odin" YGG_CMD="$T/bin/ygg" -args=(--folder "$D" --env "$T/factory.env" --realm "$T/realm") +args=(--folder "$D" --env "$T/factory.env" --graph "$T/realm") run "$S/ygg-smoke-loop.sh" "${args[@]}" check "a missing factory.yaml is refused" test "$rc" -eq 2 touch "$D/factory.yaml" @@ -101,6 +107,8 @@ FAKE_CLI_VERSION=0.88.0 run "$S/ygg-smoke-loop.sh" "${args[@]}" check "a wrong devcontainer version is refused" test "$rc" -eq 2 YGG_BIND="$T/missing" run "$S/ygg-smoke-loop.sh" "${args[@]}" check "a missing bind mount is refused" test "$rc" -eq 2 +YGG_BIND="$T/plain" run "$S/ygg-smoke-loop.sh" "${args[@]}" +check "a bind folder with nothing mounted on it is refused (loop)" bash -c "[ $rc = 2 ] && grep -q 'nothing mounted' '$T/out' && grep -q 'sudo mount --bind' '$T/out'" FAKE_RUN_RC=4 run "$S/ygg-smoke-loop.sh" --build "${args[@]}" check "the exit code of the run is the script's" test "$rc" -eq 4 check "the project is made" test -f "$D/smoke-loop/umbrella.yaml" @@ -133,11 +141,13 @@ printf 'mode: unattended\n' > "$R/factory.yaml" run "$S/ygg-smoke-realms.sh" "${rargs[@]}" check "a config with no realms section is refused" test "$rc" -eq 2 check "and the refusal says why" has "no realms section" -printf 'mode: unattended\nrealms:\n dir: /somewhere\n' > "$R/factory.yaml" +printf 'mode: unattended\nrealms:\n dir: /somewhere\ngraphs:\n dir: /somewhere\n' > "$R/factory.yaml" FAKE_CLI_VERSION=0.88.0 run "$S/ygg-smoke-realms.sh" "${rargs[@]}" check "a wrong devcontainer version is refused (realms)" test "$rc" -eq 2 YGG_BIND="$T/missing" run "$S/ygg-smoke-realms.sh" "${rargs[@]}" check "a missing bind mount is refused (realms)" test "$rc" -eq 2 +YGG_BIND="$T/plain" run "$S/ygg-smoke-realms.sh" "${rargs[@]}" +check "a bind folder with nothing mounted on it is refused (realms)" bash -c "[ $rc = 2 ] && grep -q 'nothing mounted' '$T/out' && grep -q 'sudo mount --bind' '$T/out'" FAKE_RUN_RC=5 run "$S/ygg-smoke-realms.sh" --build "${rargs[@]}" check "the exit code of the run is the script's (realms)" test "$rc" -eq 5 projects=("$R"/smoke-realms-*/) @@ -150,16 +160,27 @@ FAKE_RUN_RC=0 run "$S/ygg-smoke-realms.sh" "${rargs[@]}" projects=("$R"/smoke-realms-*/) check "each run gets a project of its own" test "${#projects[@]}" -eq 2 -# The same script runs the content smoke run: another lead realm, a brief, and a tag for its files. +# The same script runs the content smoke run: another graph, a brief, and a tag for its files. printf 'a brief\n' > "$T/brief.md" sleep 1 # a project is named by the second it is made in -FAKE_ARGS_LOG="$T/args.log" FAKE_RUN_RC=0 run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --realm midgard-react --brief "$T/brief.md" --tag h15 -check "the lead realm and the brief are given to the run" grep -q -- "--realm midgard-react --brief $T/brief.md" "$T/args.log" +FAKE_ARGS_LOG="$T/args.log" FAKE_RUN_RC=0 run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --graph software --brief "$T/brief.md" --tag h15 +check "the graph and the brief are given to the run" grep -q -- "--graph software --brief $T/brief.md" "$T/args.log" +check "no run argument holds --realm" bash -c "! grep -q -- '--realm' '$T/args.log'" check "the files of the run carry the tag" test -f "$R/h15-run.txt" -a -f "$R/h15-report.txt" run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --brief "$T/nope.md" check "a brief that is not there is refused" test "$rc" -eq 2 sleep 1 FAKE_ARGS_LOG="$T/args2.log" run "$S/ygg-smoke-realms.sh" "${rargs[@]}" -check "without options the run is the smoke-lead realm with no brief, as before" bash -c "grep -q -- '--realm smoke-lead' '$T/args2.log' && ! grep -q -- '--brief' '$T/args2.log'" +check "without options the run is the smoke-lead graph folder of odin with no brief" bash -c "grep -q -- '--graph $T/odin/testdata/smoke-realms/smoke-lead' '$T/args2.log' && ! grep -q -- '--brief' '$T/args2.log' && ! grep -q -- '--realm' '$T/args2.log'" +printf 'mode: unattended\nrealms:\n dir: /somewhere\n' > "$R/factory.yaml" +run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --graph software +check "a graph given by name needs a config with a graphs section" test "$rc" -eq 2 +check "and the refusal says why" has "no graphs section" +printf 'mode: unattended\nrealms:\n dir: /somewhere\n# graphs:\n# dir: /somewhere\n' > "$R/factory.yaml" +run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --graph software +check "a commented-out graphs section does not count" bash -c "[ $rc = 2 ] && grep -q 'no graphs section' '$T/out'" +printf 'mode: unattended\nrealms:\n dir: /somewhere\n graphs:\n dir: /somewhere\n' > "$R/factory.yaml" +run "$S/ygg-smoke-realms.sh" "${rargs[@]}" --graph software +check "a graphs key indented under another key does not count" bash -c "[ $rc = 2 ] && grep -q 'no graphs section' '$T/out'" exit "$fail" diff --git a/scripts/tests/ygg-smoke-grade.test.sh b/scripts/tests/ygg-smoke-grade.test.sh index 1d5e149..40f3a95 100755 --- a/scripts/tests/ygg-smoke-grade.test.sh +++ b/scripts/tests/ygg-smoke-grade.test.sh @@ -165,8 +165,10 @@ check "a missing factory.yaml is refused" test "$rc" -eq 2 printf 'sandbox:\n engine: unix:///run/ygg-test.sock\n' >"$D/factory.yaml" run "$S/ygg-smoke-grade.sh" --folder "$D" --tasks "$T/nowhere" --odin "$T/odin" check "a missing task folder is refused" test "$rc" -eq 2 -run "$S/ygg-smoke-grade.sh" "${gargs[@]}" +FAKE_ARGS_LOG="$T/gargs.log" run "$S/ygg-smoke-grade.sh" "${gargs[@]}" --build check "a good run passes every check and exits 0" test "$rc" -eq 0 +check "ygg run is given --graph and never --realm (grade)" bash -c "grep -q '^run .*--graph $T/odin/testdata/smoke-grade' '$T/gargs.log' && ! grep '^run ' '$T/gargs.log' | grep -q -- '--realm'" +check "ygg sandbox build keeps --realm (grade)" bash -c "grep '^sandbox build ' '$T/gargs.log' | grep -q -- '--realm $T/odin/testdata/smoke-grade'" check "the reference case grades 1" has "smoke-grade: reference reward 1" check "the empty case grades 0" has "smoke-grade: empty reward 0" check "no check failed" hasnt "FAIL" @@ -238,6 +240,8 @@ FAKE_ARGS_LOG="$T/args.log" run "$S/ygg-smoke-real.sh" "${rargs[@]}" --dry-run check "a dry run exits 0" test "$rc" -eq 0 check "a dry run says what it would run, under a wall clock" has "would run: timeout --signal=INT --kill-after=2m 90m" check "a dry run runs the doctor" grep -q '^doctor ' "$T/args.log" +check "a dry run prints a run with --graph" has "--graph '$T/odin/testdata/smoke-grade'" +check "and the printed run holds no --realm" bash -c "! grep 'would run: timeout' '$T/out' | grep -q -- '--realm'" check "a dry run does not start the run" test -z "$(grep '^run ' "$T/args.log")" check "a dry run does not load the credentials, not even for the doctor" test -z "$(grep '^loaded:' "$T/args.log")" check "a dry run prints the caps" has "per_run: { tokens: 400000, turns: 100, usd: 3 }" @@ -258,6 +262,8 @@ check "the credentials were loaded for the run" grep -q '^loaded:run$' "$T/args3 check "and not for the first doctor, which comes before the run" test "$(head -n 1 "$T/args3.log" | cut -d' ' -f1)" = doctor check "no credential value is printed" hasnt "$MARK_A" check "nor the second" hasnt "$MARK_B" +check "ygg run is given --graph and never --realm (real)" bash -c "grep -q '^run .*--graph $T/odin/testdata/smoke-grade' '$T/args3.log' && ! grep '^run ' '$T/args3.log' | grep -q -- '--realm'" +check "ygg sandbox build keeps --realm (real)" bash -c "grep '^sandbox build ' '$T/args3.log' | grep -q -- '--realm $T/odin/testdata/smoke-grade'" check "the score is printed" has "reward 0, fail-to-pass 6/6" check "the cost is printed from the ledger" has 'cost $0.3750' check "and the cap beside it" has 'per_run cap is $3' diff --git a/scripts/ygg-engine.sh b/scripts/ygg-engine.sh index f6b273a..8140864 100755 --- a/scripts/ygg-engine.sh +++ b/scripts/ygg-engine.sh @@ -51,6 +51,7 @@ fi got="$(devcontainer --version 2>/dev/null | head -n 1 || true)" [ "$got" = "$want" ] || fail "the devcontainer CLI is '${got:-missing}', want $want; install it in $dir/dc (npm install --prefix $dir/dc @devcontainers/cli@$want)" [ -d "$bind" ] || fail "the bind mount $bind is missing; a WSL restart removes it" +mountpoint -q "$bind" || fail "the bind mount $bind is a folder with nothing mounted on it; run: sudo mount --bind $bind (a WSL restart removes it, see Phase 3 v0-H07)" case "$mode" in check) diff --git a/scripts/ygg-smoke-grade.sh b/scripts/ygg-smoke-grade.sh index 0b41db8..9930d4a 100755 --- a/scripts/ygg-smoke-grade.sh +++ b/scripts/ygg-smoke-grade.sh @@ -178,7 +178,7 @@ oneCase() { # oneCase CASE: build the project, run it to its end, grade it again # An interrupt or an early exit must not leave the poller running. trap 'touch "$watchlog.stop"; kill "$watcher" 2>/dev/null || true' EXIT set +e - eval "$ygg run --project '$project' --config '$v/factory.yaml' --realm '$realm' --brief '$tasks/$task/instruction.md'" 2>&1 | tee "$v/run.txt" + eval "$ygg run --project '$project' --config '$v/factory.yaml' --graph '$realm' --brief '$tasks/$task/instruction.md'" 2>&1 | tee "$v/run.txt" rc="${PIPESTATUS[0]}" set -e id="$(find "$project/.factory/runs" -mindepth 1 -maxdepth 1 -type d -printf '%f\n' 2>/dev/null | sort | tail -n 1 || true)" diff --git a/scripts/ygg-smoke-loop.sh b/scripts/ygg-smoke-loop.sh index 1cd3208..2c36fac 100755 --- a/scripts/ygg-smoke-loop.sh +++ b/scripts/ygg-smoke-loop.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Run the loop smoke realm (v0-H11) with its checks, then print the evidence report. -# ygg-smoke-loop.sh [--build] [--folder DIR] [--env FILE] [--realm DIR] [--clip] +# ygg-smoke-loop.sh [--build] [--folder DIR] [--env FILE] [--graph DIR] [--clip] # Needs: DIR/factory.yaml (the operator's config; this script never writes it), the devcontainer CLI 0.89.0 # first on PATH (or in DIR/dc/node_modules/.bin), the engine up and the bind mount present. It # 1. checks the devcontainer CLI version and the bind mount, and stops with a reason if one is wrong; @@ -12,7 +12,7 @@ # 5. runs the realm and keeps its raw output in DIR/h11-run.txt (shown live as ygg prints it: do not paste # that file, paste the report); # 6. prints the report of ygg-evidence.sh, with the credentials removed (also in DIR/h11-report.txt): paste it. -# Defaults: DIR=$HOME/ygg-it, FILE=$HOME/.config/ouroboric/factory.env, realm=testdata/smoke-loop of the +# Defaults: DIR=$HOME/ygg-it, FILE=$HOME/.config/ouroboric/factory.env, graph=testdata/smoke-loop of the # odin folder. For tests and other machines: YGG_CMD (how ygg runs), YGG_ODIN (the odin folder), # YGG_BIND (the bind mount, default /mnt/wsl/ygg-bind) and YGG_CLI_VERSION (default 0.89.0). set -euo pipefail @@ -23,9 +23,9 @@ while [ $# -gt 0 ]; do --build) build=1; shift ;; --folder) dir="${2:?--folder needs a folder}"; shift 2 ;; --env) envfile="${2:?--env needs a file}"; shift 2 ;; - --realm) realm="${2:?--realm needs a folder}"; shift 2 ;; + --graph) realm="${2:?--graph needs a folder}"; shift 2 ;; --clip) clip=(--clip); shift ;; - *) echo "usage: ygg-smoke-loop.sh [--build] [--folder DIR] [--env FILE] [--realm DIR] [--clip]" >&2; exit 2 ;; + *) echo "usage: ygg-smoke-loop.sh [--build] [--folder DIR] [--env FILE] [--graph DIR] [--clip]" >&2; exit 2 ;; esac done odin="${YGG_ODIN:-$HERE/../../yggdrasil/odin}" @@ -37,6 +37,7 @@ export PATH="$dir/dc/node_modules/.bin:$PATH" got="$(devcontainer --version 2>/dev/null | head -n 1 || true)" [ "$got" = "$want" ] || { echo "smoke-loop: devcontainer CLI is '${got:-missing}', want $want; put the right one first on PATH" >&2; exit 2; } [ -d "$bind" ] || { echo "smoke-loop: the bind mount $bind is missing; a WSL restart removes it (see Phase 3 v0-H07)" >&2; exit 2; } +mountpoint -q "$bind" || { echo "smoke-loop: the bind mount $bind is a folder with nothing mounted on it; run: sudo mount --bind $bind (a WSL restart removes it, see Phase 3 v0-H07)" >&2; exit 2; } project="$dir/smoke-loop" if [ ! -d "$project" ]; then @@ -70,7 +71,7 @@ set +e . "$envfile" set +a if [ "$build" -eq 1 ]; then eval "$ygg sandbox build --config '$dir/factory.yaml' --realm '$realm'"; fi - eval "$ygg run --project '$project' --config '$dir/factory.yaml' --realm '$realm'" + eval "$ygg run --project '$project' --config '$dir/factory.yaml' --graph '$realm'" ) 2>&1 | tee "$out" rc="${PIPESTATUS[0]}" set -e diff --git a/scripts/ygg-smoke-real.sh b/scripts/ygg-smoke-real.sh index 9074ef4..14f3b67 100755 --- a/scripts/ygg-smoke-real.sh +++ b/scripts/ygg-smoke-real.sh @@ -113,7 +113,7 @@ echo "smoke-real: the caps in $work/factory.yaml:" echo "smoke-real: ygg doctor on that config" if ! eval "$ygg doctor --project '$project' --config '$work/factory.yaml'"; then fail "ygg doctor refused the config; nothing was spent"; fi -run="$ygg run --project '$project' --config '$work/factory.yaml' --realm '$realm' --brief '$tasks/$task/instruction.md'" +run="$ygg run --project '$project' --config '$work/factory.yaml' --graph '$realm' --brief '$tasks/$task/instruction.md'" if [ "$dry" -eq 1 ]; then [ "$build" -eq 0 ] || echo "smoke-real: would run: $ygg sandbox build --config '$work/factory.yaml' --realm '$realm'" echo "smoke-real: would run: timeout --signal=INT --kill-after=2m $wall $run" diff --git a/scripts/ygg-smoke-realms.sh b/scripts/ygg-smoke-realms.sh index 9a030ca..f5b280b 100755 --- a/scripts/ygg-smoke-realms.sh +++ b/scripts/ygg-smoke-realms.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Run the realms smoke run (v0-H13) with real agents, then print the evidence report. -# ygg-smoke-realms.sh [--build] [--folder DIR] [--env FILE] [--clip] [--realm NAME] [--brief FILE] [--tag TAG] +# ygg-smoke-realms.sh [--build] [--folder DIR] [--env FILE] [--clip] [--graph NAME|DIR] [--brief FILE] [--tag TAG] # The run builds a tiny product from two realm leaves (smoke-lead and smoke-api, in odin/testdata/smoke-realms): # real planners write the leaves file and the plan in scratch workspaces in sandboxes, Odin publishes them, # creates the leaves from their realms' templates, and a real implementer builds one task in each leaf. @@ -14,27 +14,30 @@ # 5. runs the realm and keeps its raw output in DIR/h13-run.txt (shown live as ygg prints it: do not paste # that file, paste the report); # 6. prints the report of ygg-evidence.sh, with the credentials removed (also in DIR/h13-report.txt): paste it. -# The same script runs the content smoke run (v0-H15) with --realm midgard-react --brief BRIEF --tag h15: the real -# realms, scripted agents, the real check ladder. --realm is the lead realm (default smoke-lead), --brief the +# The same script runs the content smoke run (v0-H15) with --graph software --brief BRIEF --tag h15: the real +# realms, scripted agents, the real check ladder. --graph is the graph pack, a name or a folder (default: the +# smoke-lead folder of odin/testdata/smoke-realms; a name needs a graphs section in factory.yaml), --brief the # brief the run is given, and --tag names the files of the run and its report in DIR (h13 by default). # Defaults: DIR=$HOME/ygg-it, FILE=$HOME/.config/ouroboric/factory.env. For tests and other machines: YGG_CMD # (how ygg runs), YGG_ODIN (the odin folder), YGG_BIND (the bind mount, default /mnt/wsl/ygg-bind) and # YGG_CLI_VERSION (default 0.89.0). The engine environment comes from ygg-engine.sh (YGG_ENGINE_CHECK=0 skips it). set -euo pipefail HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -dir="$HOME/ygg-it" envfile="$HOME/.config/ouroboric/factory.env" build=0 clip=() realm=smoke-lead brief="" tag=h13 +dir="$HOME/ygg-it" envfile="$HOME/.config/ouroboric/factory.env" build=0 clip=() graph="" brief="" tag=h13 while [ $# -gt 0 ]; do case "$1" in --build) build=1; shift ;; --folder) dir="${2:?--folder needs a folder}"; shift 2 ;; --env) envfile="${2:?--env needs a file}"; shift 2 ;; --clip) clip=(--clip); shift ;; - --realm) realm="${2:?--realm needs a realm name}"; shift 2 ;; + --graph) graph="${2:?--graph needs a name or a folder}"; shift 2 ;; --brief) brief="${2:?--brief needs a file}"; shift 2 ;; --tag) tag="${2:?--tag needs a name}"; shift 2 ;; - *) echo "usage: ygg-smoke-realms.sh [--build] [--folder DIR] [--env FILE] [--clip] [--realm NAME] [--brief FILE] [--tag TAG]" >&2; exit 2 ;; + *) echo "usage: ygg-smoke-realms.sh [--build] [--folder DIR] [--env FILE] [--clip] [--graph NAME|DIR] [--brief FILE] [--tag TAG]" >&2; exit 2 ;; esac done +odin="${YGG_ODIN:-$HERE/../../yggdrasil/odin}" +[ -n "$graph" ] || graph="$odin/testdata/smoke-realms/smoke-lead" want="${YGG_CLI_VERSION:-0.89.0}" bind="${YGG_BIND:-/mnt/wsl/ygg-bind}" export PATH="$dir/dc/node_modules/.bin:$PATH" # The engine environment is ygg-engine.sh's: the engine of DIR/factory.yaml (never the shell's CONTAINER_HOST), @@ -45,11 +48,13 @@ if [ "${YGG_ENGINE_CHECK:-1}" = 1 ]; then fi [ -f "$dir/factory.yaml" ] || { echo "smoke-realms: $dir/factory.yaml is missing; copy odin/testdata/smoke-realms/factory.example.yaml there and set the engine, the mount and realms.dir" >&2; exit 2; } [ -f "$envfile" ] || { echo "smoke-realms: the credentials file $envfile is missing" >&2; exit 2; } -grep -q '^realms:' "$dir/factory.yaml" || { echo "smoke-realms: $dir/factory.yaml has no realms section: the run is given a realm by name ($realm), and realms.dir says where it is" >&2; exit 2; } +grep -q '^realms:' "$dir/factory.yaml" || { echo "smoke-realms: $dir/factory.yaml has no realms section: realms.dir says where the leaf realms are" >&2; exit 2; } +case "$graph" in */*) ;; *) grep -q '^graphs:' "$dir/factory.yaml" || { echo "smoke-realms: $dir/factory.yaml has no graphs section: the run is given a graph by name ($graph), and graphs.dir says where it is" >&2; exit 2; } ;; esac [ -z "$brief" ] || [ -f "$brief" ] || { echo "smoke-realms: the brief $brief is missing" >&2; exit 2; } got="$(devcontainer --version 2>/dev/null | head -n 1 || true)" [ "$got" = "$want" ] || { echo "smoke-realms: devcontainer CLI is '${got:-missing}', want $want; put the right one first on PATH" >&2; exit 2; } [ -d "$bind" ] || { echo "smoke-realms: the bind mount $bind is missing; a WSL restart removes it (see Phase 3 v0-H07)" >&2; exit 2; } +mountpoint -q "$bind" || { echo "smoke-realms: the bind mount $bind is a folder with nothing mounted on it; run: sudo mount --bind $bind (a WSL restart removes it, see Phase 3 v0-H07)" >&2; exit 2; } project="$dir/smoke-realms-$(date +%Y%m%d-%H%M%S)" mkdir -p "$project" @@ -61,7 +66,6 @@ echo "smoke-realms: made $project" ygg="${YGG_CMD:-}" if [ -z "$ygg" ]; then - odin="${YGG_ODIN:-$HERE/../../yggdrasil/odin}" if command -v ygg >/dev/null 2>&1; then ygg=ygg; else ygg="cd '$odin' && go run ./cmd/ygg"; fi fi out="$dir/$tag-run.txt" @@ -73,7 +77,7 @@ set +e . "$envfile" set +a if [ "$build" -eq 1 ]; then eval "$ygg sandbox build --config '$dir/factory.yaml' --all"; fi - eval "$ygg run --project '$project' --config '$dir/factory.yaml' --realm '$realm' ${brief:+--brief '$brief'}" + eval "$ygg run --project '$project' --config '$dir/factory.yaml' --graph '$graph' ${brief:+--brief '$brief'}" ) 2>&1 | tee "$out" rc="${PIPESTATUS[0]}" set -e