From 3e3d8bbd5acc36ce6148f32d3e21206f37bd90da Mon Sep 17 00:00:00 2001 From: codex-bot-andresmgsl <4+codex-bot-andresmgsl@users.noreply.github.com> Date: Tue, 18 Aug 2026 07:04:33 +0000 Subject: [PATCH] fix: preserve evidence across drill failures --- CHANGELOG.md | 2 +- drill/drill.sh | 98 +++++++++++++++++++++++++++++++----------------- drills/README.md | 6 +++ test/cli.sh | 8 ++++ 4 files changed, 78 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 665c28b..5be1eb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ which records not just what changed but what each drill run proved. ### Added -- The hardware drill can emit an uncoloured release-record draft with a shared run ID (#152) +- The hardware drill can pin inputs and emit an uncoloured release-record draft with a shared run ID (#152) - `kimi-box` template — the Moonshot Kimi CLI agent seed (#158; rig#109's tenant) ## 0.9.0 — 2026-07-21 diff --git a/drill/drill.sh b/drill/drill.sh index 3651db2..fd13111 100755 --- a/drill/drill.sh +++ b/drill/drill.sh @@ -78,6 +78,50 @@ inf() { printf ' %s\n' "$*"; } phase(){ printf '\n\033[1m══ %s\033[0m\n' "$*"; } aud() { audit+=("$*"); } # an answer for the #15 audit +record_version="$(cat "$(dirname "$SELF")/../VERSION" 2>/dev/null || echo unknown)" +record_box_sha="${DRILL_BOX_SHA:-}" +record_rig_repo="${DRILL_RIG_REPO:-}" +record_rig_ref="${DRILL_RIG_REF:-}" +record_rig_sha="${DRILL_RIG_SHA:-}" +INSTALL_REF="${DRILL_INSTALL_REF:-$REF}" + +finish_drill() { + local rc="$1" record_os record_host record_elapsed + trap - EXIT + if [ "$rc" -ne 0 ] && [ "$fail" -eq 0 ]; then + fail=1 + findings+=("FAIL: drill exited early with status $rc; inspect the terminal output") + fi + [ -n "$RUN_ID" ] || RUN_ID="$(drill_default_run_id "$record_version" "$DRILL_DATE")" + # Standard host metadata, optional by design when a preflight fails before + # Incus exists. + # shellcheck disable=SC1091 + record_os="$(. /etc/os-release 2>/dev/null; printf '%s' "${PRETTY_NAME:-unknown OS}")" + record_host="$(hostname) / $record_os, $(uname -srmo), Incus $(incus --version 2>/dev/null || echo unknown)" + record_elapsed=$(($(date +%s) - DRILL_STARTED_EPOCH)) + if drill_write_record "$EMIT_RECORD" "$record_version" "$RUN_ID" "$record_host" \ + "$DRILL_DATE" "$REPO" "$REF" "$record_box_sha" \ + "$record_rig_repo" "$record_rig_ref" "$record_rig_sha" \ + "$DRILL_INVOCATION" "$pass" "$fail" "$record_elapsed" findings; then + inf "wrote editable release-record draft: $EMIT_RECORD" + else + rc=1 + fi + exit "$rc" +} + +if [ -n "$EMIT_RECORD" ]; then + trap 'finish_drill "$?"' EXIT + if [ "$record_box_sha" = '' ]; then + if ! record_box_sha="$(drill_resolve_ref_sha "$REPO" "$REF")"; then + echo "drill: cannot resolve exact box SHA for $REPO@$REF — refusing to drill an unpinned source" >&2 + exit 1 + fi + INSTALL_REF="$record_box_sha" + fi + export DRILL_BOX_SHA="$record_box_sha" DRILL_INSTALL_REF="$INSTALL_REF" +fi + wait_box() { # poll until exec answers (the VM agent can take a while), ~4 min # 2 min was too short: run 17's legacy box came up AFTER the window closed — # the drill called it dead and then every migration check on it passed. @@ -238,8 +282,8 @@ EOF # OWNS still suppresses the setup prompt via BOX_SKIP_SETUP_HOST above. export BOX_YES=1 - BOX_REPO="$REPO" BOX_REF="$REF" \ - bash -c "$(curl -fsSL "https://raw.githubusercontent.com/$REPO/$REF/install.sh")" \ + BOX_REPO="$REPO" BOX_REF="$INSTALL_REF" \ + bash -c "$(curl -fsSL "https://raw.githubusercontent.com/$REPO/$INSTALL_REF/install.sh")" \ || { echo "install failed"; exit 1; } export PATH="$HOME/.local/bin:$PATH" @@ -250,15 +294,15 @@ EOF # the wrong tree while reporting success. A drill that silently drills the # wrong code is worse than one that fails. got="$(cat "$HOME/.local/share/box/current/INSTALLED_FROM" 2>/dev/null || echo '')" - if [ "$got" != "$REPO@$REF" ]; then - echo "drill: FATAL — asked to install $REPO@$REF, but the tree says '$got'." >&2 + if [ "$got" != "$REPO@$INSTALL_REF" ]; then + echo "drill: FATAL — asked to install $REPO@$INSTALL_REF, but the tree says '$got'." >&2 echo " Your local drill.sh is probably STALE (pre-0.5.0 it passed CLAUDEBOX_*," >&2 echo " which today's install.sh ignores, so it fell back to main). Fix:" >&2 echo " git fetch origin && git checkout && git pull" >&2 echo " then re-run this drill." >&2 exit 1 fi - inf "installed tree confirms: $got" + inf "installed tree confirms: $got (requested as $REPO@$REF)" phase "Host setup (Incus, boxnet, ACL, profile, firewall)" if [ "$fw_absent_pre" = 1 ]; then @@ -305,20 +349,22 @@ EOF "BOX_REPO=$REPO" "BOX_REF=$REF" "KEEP=$KEEP" \ "DRILL_EMIT_RECORD=$EMIT_RECORD" "DRILL_RUN_ID=$RUN_ID" \ "DRILL_STARTED_EPOCH=$DRILL_STARTED_EPOCH" "DRILL_DATE=$DRILL_DATE" \ - "DRILL_INVOCATION=$DRILL_INVOCATION" bash "$SELF" --in-group + "DRILL_INVOCATION=$DRILL_INVOCATION" "DRILL_BOX_SHA=$record_box_sha" \ + "DRILL_INSTALL_REF=$INSTALL_REF" bash "$SELF" --in-group exec sg incus-admin -c "$reexec" fi export PATH="$HOME/.local/bin:$PATH" KEEP="${KEEP:-0}" -record_version=''; record_box_sha='' -record_rig_repo=''; record_rig_ref=''; record_rig_sha='' -if [ -n "$EMIT_RECORD" ]; then - record_version="$(cat "$HOME/.local/share/box/current/VERSION" 2>/dev/null || echo unknown)" - [ -n "$RUN_ID" ] || RUN_ID="$(drill_default_run_id "$record_version" "$DRILL_DATE")" - if ! record_box_sha="$(drill_resolve_ref_sha "$REPO" "$REF")"; then - no "could not resolve exact box SHA for $REPO@$REF — the record cannot pin what ran" +if [ -n "$EMIT_RECORD" ] && [ "$record_rig_sha" = '' ]; then + record_rig_repo="${RIG_REPO:-heavy-duty/rig}" + record_rig_ref="${RIG_REF:-main}" + if ! record_rig_sha="$(drill_resolve_ref_sha "$record_rig_repo" "$record_rig_ref")"; then + echo "drill: cannot resolve exact rig SHA for $record_rig_repo@$record_rig_ref — refusing to mint from an unpinned source" >&2 + exit 1 fi + export RIG_REPO="$record_rig_repo" RIG_REF="$record_rig_sha" + export DRILL_RIG_REPO="$record_rig_repo" DRILL_RIG_REF="$record_rig_ref" DRILL_RIG_SHA="$record_rig_sha" fi # PROVE THE INSTALLER'S CONTRACT (#64) — first, before the clean or anything @@ -626,12 +672,10 @@ t0=$SECONDS if mint_box /tmp/mint-drill.log --name drill --template claude-box; then ok "box new --name drill --template claude-box ($((SECONDS - t0))s)" if [ -n "$EMIT_RECORD" ]; then - record_rig_repo="$(incus config get drill user.box.rig.repo 2>/dev/null)" - record_rig_ref="$(incus config get drill user.box.rig.ref 2>/dev/null)" - if [ -z "$record_rig_repo" ] || [ -z "$record_rig_ref" ]; then - no "minted box did not record the rig repo/ref — the record cannot pin what converged it" - elif ! record_rig_sha="$(drill_resolve_ref_sha "$record_rig_repo" "$record_rig_ref")"; then - no "could not resolve exact rig SHA for $record_rig_repo@$record_rig_ref" + minted_rig_repo="$(incus config get drill user.box.rig.repo 2>/dev/null)" + minted_rig_ref="$(incus config get drill user.box.rig.ref 2>/dev/null)" + if [ "$minted_rig_repo" != "$record_rig_repo" ] || [ "$minted_rig_ref" != "$record_rig_sha" ]; then + no "minted box records $minted_rig_repo@$minted_rig_ref, expected pinned $record_rig_repo@$record_rig_sha" fi fi else @@ -1022,22 +1066,6 @@ else || no "a drill box survived teardown: $(printf '%s' "$leftover" | awk '{print $1}' | tr '\n' ' ')" fi -if [ -n "$EMIT_RECORD" ]; then - # Standard host metadata, optional by design. - # shellcheck disable=SC1091 - record_os="$(. /etc/os-release 2>/dev/null; printf '%s' "${PRETTY_NAME:-unknown OS}")" - record_host="$(hostname) / $record_os, $(uname -srmo), Incus $(incus --version 2>/dev/null || echo unknown)" - record_elapsed=$(($(date +%s) - DRILL_STARTED_EPOCH)) - if drill_write_record "$EMIT_RECORD" "$record_version" "$RUN_ID" "$record_host" \ - "$DRILL_DATE" "$REPO" "$REF" "$record_box_sha" \ - "$record_rig_repo" "$record_rig_ref" "$record_rig_sha" \ - "$DRILL_INVOCATION" "$pass" "$fail" "$record_elapsed" findings; then - inf "wrote editable release-record draft: $EMIT_RECORD" - else - no "could not emit the release-record draft at $EMIT_RECORD" - fi -fi - phase "Summary" printf ' %s passed, %s failed\n' "$pass" "$fail" if [ "${#findings[@]}" -gt 0 ]; then diff --git a/drills/README.md b/drills/README.md index 117d8df..abe208f 100644 --- a/drills/README.md +++ b/drills/README.md @@ -62,6 +62,12 @@ bash drill/drill.sh --ref release/0.9.1 \ drill so their records reconcile. The emitter refuses to overwrite an existing file, and its Markdown contains no terminal colour escapes. +When record emission is requested, the harness resolves the requested box and +rig refs before their installers run and feeds those installers the resulting +full commit SHAs. The draft keeps both the human-facing refs and the immutable +SHAs. If either ref cannot be pinned, the drill refuses before mutating the host +and still writes the failed preflight record. + The generated file is a **draft, not finished release evidence**. It records the host, invocation, elapsed time, findings, and the exact box and rig refs and SHAs the run selected. Before committing it, verify those facts and add the diff --git a/test/cli.sh b/test/cli.sh index 65c2a65..6dc71e0 100644 --- a/test/cli.sh +++ b/test/cli.sh @@ -3164,6 +3164,14 @@ TAG_SHA="$(git -C "$REF_FIXTURE" rev-parse 'refs/tags/candidate^{commit}')" # shellcheck disable=SC2016 check "drill record: tag resolution matches the installer's tag-first channel" 0 "$TAG_SHA" \ bash -c '. "$1/drill/record.sh"; drill_resolve_ref_sha "$2" candidate' _ "$ROOT" "$REF_FIXTURE" + +EMPTY_REMOTE="$DRILL_RECORD_DIR/empty.git" +git init -q --bare "$EMPTY_REMOTE" +EARLY_RECORD="$DRILL_RECORD_DIR/early-failure.md" +check "drill record: an unresolved source fails before consent or mutation" 1 "cannot resolve exact box SHA" \ + bash "$ROOT/drill/drill.sh" --repo "$EMPTY_REMOTE" --ref absent --emit-record "$EARLY_RECORD" +check "drill record: an early preflight failure still emits evidence" 0 "drill exited early" \ + cat "$EARLY_RECORD" check "drill: help names --emit-record" 0 "--emit-record " bash "$ROOT/drill/drill.sh" --help check "drill: help names --run-id" 0 "--run-id " bash "$ROOT/drill/drill.sh" --help check "drill: --emit-record needs a value before any mutation" 2 "--emit-record needs a value" \