mirror of
https://github.com/piabrota/mu.git
synced 2026-11-07 06:15:59 -10:00
The smoke can narrow the implementer's task (--brief-note, B-109) and names the go.work its build used (#71)
* The smoke can narrow the implementer's task with --brief-note and says whether its build used go.work (B-109, B-111) Co-Authored-By: Claude Sonnet 5.5 <[email protected]> * P4-note.md speaks of the implementer and names health as the one route without a session (B-109) Co-Authored-By: Claude Sonnet 5.5 <[email protected]> --------- Co-authored-by: Bruno Guilhermo de Barros Valério <[email protected]> Co-authored-by: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
4 files changed
+82
-7
No files matched your search
@@ -39,7 +39,7 @@ folder.
|
||||
| Any real-engine run (Podman, devcontainer, the sandbox): the engine, registry config and checks | `scripts/ygg-engine.sh check\|env\|run --folder DIR`. Never set `CONTAINER_HOST` by hand: the root socket is the wrong one |
|
||||
| The realms smoke runs (v0-H13, v0-H15) and their evidence | `scripts/ygg-smoke-realms.sh`, `scripts/ygg-smoke-loop.sh`, `scripts/ygg-evidence.sh` |
|
||||
| The grader smoke on a real engine (v0-H16), with the public sample suite | `scripts/ygg-smoke-grade.sh [--build]`. Never a hidden suite |
|
||||
| The real-agent smoke (v0-H17): costs money; `--dry-run` first; the cost from the ledger; a start from a planted-fault leaf; another implementer; the repair path from the ledger | `scripts/ygg-smoke-real.sh --dry-run`, then without it; `--from-leaf LEAF`, `--implementer AGENT:MODEL`; `scripts/ygg-cost.sh LEDGER`, `scripts/ygg-repair-path.sh LEDGER`. It never prints the credentials file |
|
||||
| The real-agent smoke (v0-H17): costs money; `--dry-run` first; the cost from the ledger; a start from a planted-fault leaf; another implementer; a note before the brief; the repair path from the ledger | `scripts/ygg-smoke-real.sh --dry-run`, then without it; `--from-leaf LEAF`, `--implementer AGENT:MODEL`, `--brief-note FILE` (narrows the implementer's task; the ygg line says if the build used go.work); `scripts/ygg-cost.sh LEDGER`, `scripts/ygg-repair-path.sh LEDGER`. It never prints the credentials file |
|
||||
| Compare reviewer models: costs money unless `--dry-run`; on the planted-fault leaves in `scripts/testdata/reviewer-bench`; runs the OpenCode version gleipnir pins (installed once with npm; `--opencode BIN`, `--any-opencode`) | `scripts/ygg-reviewer-bench.sh --model MODEL --leaf DIR --sessions N --dry-run`, then without it |
|
||||
| Build a plan from reference commits, or execute one task by task | `scripts/plan-*` (`plan-generate.py`, `plan-replay.py`, `plan-states.sh`, `plan-red.sh`, `plan-defences.py`; `plan-blocks.py`, `plan-task-start.sh`, `plan-task-done.sh`, `plan-task-land.sh`) |
|
||||
| Check that the repos have the required setup, and that the realms' shared files match | `scripts/as-bot.sh --read all scripts/check-repos.sh`; `--check shared` runs the realms check alone |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
The product below is already built to this spec. The implementer's task is only this: add `GET /api/health`, which answers 200 with `{"ok": true}`; it is the one route that needs no session. Change nothing else.
|
||||
@@ -54,6 +54,7 @@ printf '#!/usr/bin/env bash\nexit 0\n' >"$T/pathbin/ygg"
|
||||
cp "$T/pathbin/ygg" "$T/other/ygg-custom"
|
||||
cat >"$T/gobin/go" <<'EOF2'
|
||||
#!/usr/bin/env bash
|
||||
[ "$1" = env ] && [ "$2" = GOWORK ] && { printf '%s\n' "${GOWORK-}"; exit 0; }
|
||||
[ "$1" = build ] && [ "$2" = -o ] && { printf '#!/usr/bin/env bash\nexit 0\n' >"$3"; chmod +x "$3"; exit 0; }
|
||||
exit 1
|
||||
EOF2
|
||||
@@ -86,6 +87,16 @@ printf 'x\n' >"$O/untracked.txt"
|
||||
PATH="$T/gobin:$BASEPATH" run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "a dirty odin tree is said to be dirty" has "tree DIRTY"
|
||||
|
||||
# --- the go.work file of the build (B-111)
|
||||
PATH="$T/gobin:$BASEPATH" GOWORK="$T/ws/go.work" run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "a build with GOWORK set names the go.work file" has "go.work: $T/ws/go.work"
|
||||
PATH="$T/gobin:$BASEPATH" GOWORK=off run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "a build with GOWORK=off says no go.work" has "go.work: no go.work"
|
||||
PATH="$T/gobin:$BASEPATH" GOWORK='' run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "a build that finds no go.work says no go.work" has "go.work: no go.work"
|
||||
PATH="$T/pathbin:$BASEPATH" GOWORK="$T/ws/go.work" run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "a ygg that was not built says nothing about go.work" hasnt "go.work"
|
||||
|
||||
# The run's folder, from the line "smoke-real: made DIR".
|
||||
work() { sed -n 's/^smoke-real: made //p' "$T/out" | head -n 1; }
|
||||
export PATH="$T/pathbin:$BASEPATH"
|
||||
@@ -167,6 +178,39 @@ for bad in opencode qwen opencode: :sonnet scripted:x gemini:x opencode:qwen/qwe
|
||||
done
|
||||
check "a refusal says what is allowed" has "--implementer is AGENT:MODEL"
|
||||
|
||||
# --- --brief-note: the brief is the note, a blank line, then the task's instruction (B-109)
|
||||
printf 'Scope: only add the health route.\n' >"$T/note.md"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note "$T/note.md"
|
||||
W="$(work)"
|
||||
check "a dry run with a note exits 0" test "$rc" -eq 0
|
||||
check "ygg run gets the run's brief.md" has "--brief '$W/brief.md'"
|
||||
check "brief.md is the note, a blank line, the instruction" bash -c "[ \"\$(cat '$W/brief.md')\" = \"\$(printf 'Scope: only add the health route.\n\n# brief')\" ]"
|
||||
check "the real instruction file is not the brief" hasnt "--brief '$M/smoke-notes/instruction.md'"
|
||||
check "it says which note was used" has "smoke-real: the brief note: $T/note.md"
|
||||
printf 'Scope: no newline at the end' >"$T/note-nonl.md"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note "$T/note-nonl.md"
|
||||
check "a note without a final newline still has a blank line before the instruction" bash -c "[ \"\$(cat '$(work)/brief.md')\" = \"\$(printf 'Scope: no newline at the end\n\n# brief')\" ]"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}"
|
||||
check "without a note ygg run gets the instruction file" has "--brief '$M/smoke-notes/instruction.md'"
|
||||
check "and no brief.md is made" test ! -e "$(work)/brief.md"
|
||||
check "and no note is named" hasnt "the brief note"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note "$T/no-such-note.md"
|
||||
check "a missing note is refused" test "$rc" -eq 2
|
||||
check "and named" has "no brief note at $T/no-such-note.md"
|
||||
: >"$T/note-empty.md"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note "$T/note-empty.md"
|
||||
check "an empty note is refused" test "$rc" -eq 2
|
||||
printf ' \n\n' >"$T/note-blank.md"
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note "$T/note-blank.md"
|
||||
check "a note of blanks is refused" test "$rc" -eq 2
|
||||
run "$S/ygg-smoke-real.sh" "${rargs[@]}" --brief-note
|
||||
check "--brief-note without a file is a usage error" test "$rc" -eq 2
|
||||
|
||||
# The shipped note for P4 (the leaf whose fault is in the owner check of remove).
|
||||
check "P4-note.md exists" test -s "$S/testdata/reviewer-bench/P4-note.md"
|
||||
check "P4-note.md asks for GET /api/health" grep -q -F 'GET /api/health' "$S/testdata/reviewer-bench/P4-note.md"
|
||||
check "P4-note.md says nothing of deletion, owners or review" bash -c "! grep -q -i -E 'delet|remove|owner|review|fault|bug' '$S/testdata/reviewer-bench/P4-note.md'"
|
||||
|
||||
# --- the run's tail, without --dry-run: the repair path and --clip (B-109, B-111)
|
||||
# A non-dry run reaches the code after `ygg run`. run_real refuses unless every guard holds: YGG_CMD is an
|
||||
# executable under this test's temp folder, the engine check is off, and the folder and the credentials file are the
|
||||
@@ -233,6 +277,12 @@ check "run_real refuses a YGG_CMD outside the temp folder" grep -q -F "run_real
|
||||
(YGG_CMD="$FY" YGG_ENGINE_CHECK=1 run_real) >"$T/refusal"
|
||||
check "run_real refuses when the engine check is on" grep -q -F "run_real refused: YGG_ENGINE_CHECK is not 0" "$T/refusal"
|
||||
|
||||
PATH="$CLIPPATH" YGG_CMD="$FY" run_real --from-leaf "$L" --brief-note "$T/note.md"
|
||||
W="$(work)"
|
||||
check "a run with a note exits 0" test "$rc" -eq 0
|
||||
check "report.txt names the note" grep -q -F "smoke-real: the brief note: $T/note.md" "$W/report.txt"
|
||||
check "the note is printed in the terminal" has "smoke-real: the brief note: $T/note.md"
|
||||
|
||||
# --- the real odin files, when this checkout has them: the edits must match their lines
|
||||
R="${YGG_REAL_ODIN:-$S/../../yggdrasil/odin}"
|
||||
if [ -f "$R/testdata/smoke-grade/pack.yaml" ] && [ -f "$R/testdata/smoke-grade/factory.real.example.yaml" ]; then
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Run the real-agent smoke (v0-H17): the task smoke-notes built by the real Claude Code and the real OpenCode on
|
||||
# OpenRouter, then graded. IT COSTS MONEY: the caps are in odin/testdata/smoke-grade/factory.real.example.yaml.
|
||||
# ygg-smoke-real.sh [--dry-run] [--build] [--folder DIR] [--env FILE] [--tasks DIR] [--odin DIR] [--wall TIME] [--clip]
|
||||
# [--from-leaf LEAF] [--implementer AGENT:MODEL]
|
||||
# [--from-leaf LEAF] [--implementer AGENT:MODEL] [--brief-note FILE]
|
||||
# The suite is the PUBLIC sample suite of the task (no hidden suite of smoke-notes exists); the agents never mount
|
||||
# it. Needs DIR/factory.yaml (it names the engine; this script never writes it), the credentials file, the
|
||||
# devcontainer CLI 0.89.0, jq and python3, the engine up, the bind mount present, and a checkout of `mimir`. It
|
||||
@@ -19,7 +19,12 @@
|
||||
# execute bit, so the project's start.sh then runs the leaf's start.sh as a program when it is executable,
|
||||
# and with sh when it is not. The planted-fault leaves are in scripts/testdata/reviewer-bench (see
|
||||
# ygg-reviewer-bench.sh);
|
||||
# 4. prints which ygg runs (path, modified time; for a build from --odin, the odin commit and tree state), then
|
||||
# With --brief-note FILE, the run's brief is the text of FILE, a blank line, then the task's instruction.md,
|
||||
# written to DIR/smoke-real-<time>/brief.md (B-109). A note that narrows the implementer's task keeps the
|
||||
# work small, and the reviewer still gets the whole spec. The line "the brief note" says which file was used,
|
||||
# in the terminal and in report.txt. FILE must exist and have text. See scripts/testdata/reviewer-bench/P4-note.md;
|
||||
# 4. prints which ygg runs (path, modified time; for a build from --odin, the odin commit, the tree state and
|
||||
# the go.work file the build used, or "no go.work"; GOWORK=off turns go.work off), then
|
||||
# runs `ygg doctor` on that config. A config that doctor refuses stops the script before any money is spent;
|
||||
# 5. with --dry-run, stops here and prints what it would run, and what it would do after the run;
|
||||
# 6. otherwise runs `ygg run` under `timeout` (--wall, default 90m) with the credentials loaded in a subshell
|
||||
@@ -37,9 +42,9 @@
|
||||
set -euo pipefail
|
||||
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
dir="$HOME/ygg-it" envfile="$HOME/.config/ouroboric/factory.env" tasks="$HERE/../../mimir" wall=90m dry=0 build=0 clip=0
|
||||
leaf="" implementer=""
|
||||
leaf="" implementer="" note=""
|
||||
odin="${YGG_ODIN:-$HERE/../../yggdrasil/odin}"
|
||||
usage() { echo "usage: ygg-smoke-real.sh [--dry-run] [--build] [--folder DIR] [--env FILE] [--tasks DIR] [--odin DIR] [--wall TIME] [--clip] [--from-leaf LEAF] [--implementer AGENT:MODEL]" >&2; exit 2; }
|
||||
usage() { echo "usage: ygg-smoke-real.sh [--dry-run] [--build] [--folder DIR] [--env FILE] [--tasks DIR] [--odin DIR] [--wall TIME] [--clip] [--from-leaf LEAF] [--implementer AGENT:MODEL] [--brief-note FILE]" >&2; exit 2; }
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--dry-run) dry=1; shift ;;
|
||||
@@ -52,6 +57,7 @@ while [ $# -gt 0 ]; do
|
||||
--clip) clip=1; shift ;;
|
||||
--from-leaf) [ $# -ge 2 ] || usage; leaf="$2"; shift 2 ;;
|
||||
--implementer) [ $# -ge 2 ] || usage; implementer="$2"; shift 2 ;;
|
||||
--brief-note) [ $# -ge 2 ] || usage; note="$2"; shift 2 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
@@ -92,6 +98,13 @@ done
|
||||
suite="$(sed -n 's/^suite[[:space:]]*=[[:space:]]*"\([^"]*\)".*/\1/p' "$tasks/$task/task.toml" | head -n 1)"
|
||||
[ -n "$suite" ] || fail "$tasks/$task/task.toml has no metadata.suite"
|
||||
|
||||
# The brief note: a file with some text in it (not only blanks).
|
||||
if [ -n "$note" ]; then
|
||||
[ -f "$note" ] || fail "no brief note at $note (--brief-note)"
|
||||
grep -q '[^[:space:]]' "$note" || fail "the brief note $note is empty (--brief-note)"
|
||||
note="$(cd "$(dirname "$note")" && pwd)/$(basename "$note")"
|
||||
fi
|
||||
|
||||
# The leaf to start from: its files, without .git, each a plain name pack.yaml can list without quotes.
|
||||
if [ -n "$leaf" ]; then
|
||||
[ -d "$leaf" ] || fail "no leaf folder at $leaf (--from-leaf)"
|
||||
@@ -137,6 +150,13 @@ chmod +x "$project/start.sh"
|
||||
git -C "$project" add umbrella.yaml start.sh
|
||||
git -C "$project" -c user.name=ygg -c user.email=[email protected] commit -q -m "the real-agent smoke project"
|
||||
echo "smoke-real: made $work"
|
||||
brief="$tasks/$task/instruction.md" note_line=""
|
||||
if [ -n "$note" ]; then
|
||||
{ printf '%s\n\n' "$(<"$note")"; cat "$tasks/$task/instruction.md"; } >"$work/brief.md"
|
||||
brief="$work/brief.md"
|
||||
note_line="smoke-real: the brief note: $note (the brief is $brief: the note, a blank line, then the task's instruction.md)"
|
||||
echo "$note_line"
|
||||
fi
|
||||
echo "smoke-real: the suite is the PUBLIC sample suite $public/tests (suite $suite)"
|
||||
if [ -n "$leaf" ]; then
|
||||
# The run's own copy of the pack, with LEAF as the template of repos/notes. odin's pack is not changed.
|
||||
@@ -189,7 +209,10 @@ fi
|
||||
if [ "$built" -eq 1 ]; then
|
||||
sha="$(git -C "$odin" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
||||
if [ -n "$(git -C "$odin" status --porcelain 2>/dev/null)" ]; then tree="tree DIRTY"; else tree="tree clean"; fi
|
||||
ygg_line="$ygg_line, built from $odin at commit $sha, $tree"
|
||||
# The same environment as the build, so GOWORK=off is honoured. go prints a path, nothing, or "off".
|
||||
gw="$(cd "$odin" && go env GOWORK 2>/dev/null || true)"
|
||||
case "$gw" in ""|off) gw="no go.work" ;; esac
|
||||
ygg_line="$ygg_line, built from $odin at commit $sha, $tree, go.work: $gw"
|
||||
else
|
||||
ygg_line="$ygg_line, odin commit unknown (not built by this script)"
|
||||
fi
|
||||
@@ -209,7 +232,7 @@ after_run_notes() {
|
||||
fi
|
||||
}
|
||||
|
||||
run="$ygg run --project '$project' --config '$work/factory.yaml' --graph '$realm' --brief '$tasks/$task/instruction.md'"
|
||||
run="$ygg run --project '$project' --config '$work/factory.yaml' --graph '$realm' --brief '$brief'"
|
||||
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"
|
||||
@@ -237,6 +260,7 @@ echo "smoke-real: the run ended with exit code $rc (0 done, 1 a node failed, 3 s
|
||||
report="$work/report.txt"
|
||||
( { set +x; } 2>/dev/null # as above
|
||||
echo "$ygg_line"
|
||||
if [ -n "$note_line" ]; then echo "$note_line"; fi
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
. "$envfile"
|
||||
|
||||
Reference in new issue
Block a user