From 11f4e08a21efac9b1ca27bd4b26cb18758411f82 Mon Sep 17 00:00:00 2001 From: Eureka Date: Wed, 11 Nov 2026 16:22:11 +0000 Subject: [PATCH] ygg-verify: local mode for the Yggdrasil seat; executable modes One code path with a transport switch: on a host named yggdrasil[-*] (or YGG_VERIFY_LOCAL=1) the remote half runs through local bash with cp and a local git push instead of ssh/scp; the ssh path is unchanged. Scripts meant to be run directly are committed 100755, and the scripts that call ygg-verify.sh do so through bash (noexec skill mount). test-tools.sh covers the local branch and, under a mock ssh, the remote branch and the detection rule. Co-Authored-By: Claude Sonnet 5.5 --- references/changelog.md | 8 +++++ tools/INDEX.md | 18 +++++++----- tools/cargo-mutants.sh | 2 +- tools/context-pack.py | 0 tools/mutation-table.sh | 2 +- tools/stopgap/ygg-verify.sh | 54 ++++++++++++++++++++++++++++------ tools/test-tools.sh | 58 ++++++++++++++++++++++++++++++++++++- 7 files changed, 123 insertions(+), 19 deletions(-) mode change 100644 => 100755 tools/cargo-mutants.sh mode change 100644 => 100755 tools/context-pack.py mode change 100644 => 100755 tools/mutation-table.sh mode change 100644 => 100755 tools/stopgap/ygg-verify.sh mode change 100644 => 100755 tools/test-tools.sh diff --git a/references/changelog.md b/references/changelog.md index c6949f1..2558d11 100644 --- a/references/changelog.md +++ b/references/changelog.md @@ -2,6 +2,14 @@ Record each change to the skill together with the evidence that motivated it. +## 2026-11-11: ygg-verify.sh runs on the Yggdrasil seat + +Hands, follow-up `eureka-substrate:follow_up:chat-mind-20261111T150417226Z-t35`. + +Evidence. A Self seat on Yggdrasil could not launch `tools/stopgap/ygg-verify.sh` (git mode 644, and the skill mount is `noexec`) and, through `bash`, stopped at `ssh: Could not resolve hostname ygg`, although the seat is the host `ygg` names and `sudo -n docker` works there. + +What changed. One code path with a transport switch: local mode (`hostname` `yggdrasil`/`yggdrasil-*`/`yggdrasil.*` with `YGG_HOST` unset, or `YGG_VERIFY_LOCAL=1`; `=0` forces ssh) runs the same remote half through local `bash -s`, with `cp` and a local `git push` in place of `scp` and the ssh push, under `$YGG_VERIFY_ROOT` (default `$HOME/eureka-verify`). The remote half takes the root as an optional 14th argument, empty over ssh, so the ssh path is unchanged. The SUMMARY re-exec and the two runners' call of `ygg-verify.sh` go through `bash`, which a `noexec` mount needs. `ygg-verify.sh`, `cargo-mutants.sh`, `mutation-table.sh`, `context-pack.py` and `test-tools.sh` are committed 100755. `tools/test-tools.sh` covers the local branch and, under a mock ssh, the remote branch and the detection rule; it also now passes the cargo-mutants cases that failed with `Permission denied` on Linux. + ## 2026-11-07: Eureka tools stop reaching the mind Hands, cut `eureka-substrate:cut_spec:cut-skill-tools-off-mcp.r2`, base `54b3cfd` (the spec named `6485496`; main moved by `dotnet-self-env.sh` only). diff --git a/tools/INDEX.md b/tools/INDEX.md index faf35bd..27d90ce 100644 --- a/tools/INDEX.md +++ b/tools/INDEX.md @@ -8,7 +8,7 @@ gets a Soul pass before merge. | script | purpose | consumer | named by | |---|---|---|---| -| `tools/stopgap/ygg-verify.sh` | Pushes an exact revision to a mirror on Yggdrasil and runs one command in a capped, niced container (`RUN_ON_HOST=1`: run a host-side command in the same slot, clone and watchdog instead; the watchdog kills every container carrying the job label). `SUMMARY=` keeps the full log and prints a bounded summary (verdict, counts, ZERO TESTS RAN, failing tests); `wait ` blocks at most 270 s and returns the summary once; call it with a Bash tool `timeout` of at least 280000 ms. Dies with the stopgap when Idunn's verify transaction lands. | Hands, Soul, Imagination probes | `references/briefs.md` (Hands long jobs and verification, Soul long jobs), `SKILL.md` (Yggdrasil) | +| `tools/stopgap/ygg-verify.sh` | Pushes an exact revision to a mirror on Yggdrasil and runs one command in a capped, niced container (`RUN_ON_HOST=1`: run a host-side command in the same slot, clone and watchdog instead; the watchdog kills every container carrying the job label). `SUMMARY=` keeps the full log and prints a bounded summary (verdict, counts, ZERO TESTS RAN, failing tests); `wait ` blocks at most 270 s and returns the summary once; call it with a Bash tool `timeout` of at least 280000 ms. On the Yggdrasil seat itself (`hostname` is `yggdrasil` or `yggdrasil-*`, no `YGG_HOST`; `YGG_VERIFY_LOCAL=1` forces, `=0` forces ssh) it runs local: same code, local `sudo -n docker`, state under `$YGG_VERIFY_ROOT` (default `$HOME/eureka-verify`). Dies with the stopgap when Idunn's verify transaction lands. | Hands, Soul, Imagination probes | `references/briefs.md` (Hands long jobs and verification, Soul long jobs), `SKILL.md` (Yggdrasil) | | `tools/wait-on.sh` | One general waiter for anything that is not a Yggdrasil job: `pid []`, `log ` (with `WAIT_PID=` a dead process with no match is exit 98; an invalid ERE is exit 3), `file `. The `pid` form prints `GONE (no completion evidence)`: prefer `log` whenever the job writes a done line. Same contract as `ygg-verify.sh wait`: blocks at most 270 s, exit 0 done with a tail of at most 60 log lines, `RUNNING s` exit 99, exit 98 gone with no completion evidence; call it with a Bash tool `timeout` of at least 280000 ms. Replaces hand-rolled poll loops and idle `true`/`echo`/`sleep` calls. | Hands, Soul, Imagination probes | `references/briefs.md` (Hands long jobs, Soul long jobs, detached scripts) | | `tools/mutation-table.sh` | One verify job that runs a list of hand mutants (file, before, after, test) against a revision and returns a kill table: CAUGHT with the killing test, SURVIVED, UNVIABLE, TIMEOUT, NOAPPLY, ERROR. Refuses a red or zero-test baseline and a red BUILD; rows print live. Isolation is Docker's: the baselines run once in a container that holds the revision, that container is committed to a throwaway image, and every mutant runs in a fresh `--rm` container from it, so nothing a run writes (tracked, untracked or ignored, such as `target/`) reaches the next mutant; the image is removed when the job ends, killed or not. The shared registry and sccache volumes and the network are not isolated. A file-level load failure (vitest `FAIL [ ]`, jest `FAIL ` plus `Test suite failed to run`) reads UNVIABLE. Replaces per-agent runmut/mutrun/strykrun scripts. | Soul, Hands (scoped run) | `references/briefs.md` (Hands verification, Soul reruns) | | `tools/cargo-mutants.sh` | `SUMMARY= tools/cargo-mutants.sh [workdir]`: cargo-mutants on a revision range as ONE verify job, the one owner of running it. Plan container lists the range's mutants (diff taken at the workspace root); stage 1 runs each file's mutants against that file's tests only (filter derived from the path, `FILTERS` overrides), deciding only CAUGHT and UNVIABLE; stage 2 confirms every survivor, timeout, unfiltered file and zero-test file on the full suite, sharded; merge counts each name once and prints `MUTANTS` totals, `FILTER` lines and the final `MISSED`/`TIMEOUT` names. Containers = min(`SHARDS`, slots, units, 1 + free slots), leased with `flock -n` from Yggdrasil's slot pool (none while IO pressure full avg60 > 20). `NAMES=` reruns chosen survivors (no stage 1), `TEST_ARGS` skips flaky tests, `JOBS`, `MIN_TEST_TIMEOUT`, `CONFIRM_TIMEOUT_MULT`, `TIMEOUT`. Exit 0 on a green baseline whatever survives; a red baseline or a failed container is non-zero with no totals. Run once per pass. | Hands, Soul | `references/briefs.md` (Hands verification, Soul reruns), `SKILL.md` (mutation bullet) | @@ -21,16 +21,20 @@ gets a Soul pass before merge. ## From a Self seat on Yggdrasil A Mind's Self run reads these scripts from a read-only, `noexec` tmpfs mount of -the skill, and holds no Docker socket and no `ygg` ssh alias. So: +the skill, and holds no `ygg` ssh alias. So: - `tools/