From dbb14231644b9b6bdb37e1be17b9baed26d6cef8 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 5 May 2026 06:34:29 +0900 Subject: [PATCH 1/2] fix(scripts): inject GIT_SHA in dogfood-build.sh so provenance check passes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cargo build without GIT_SHA env var → option_env!("GIT_SHA") = None → version JSON returns git_sha:null → dogfood-build.sh fails its own provenance check every time. Fix: pass GIT_SHA=$(git rev-parse --short HEAD) to cargo build. The script now: 1. Sets GIT_SHA to current HEAD before cargo build 2. Reads git_sha from the built binary 3. Compares against HEAD — fails if still null or mismatched Also adds latency note: cargo run = ~1s overhead/invocation vs 7ms for pre-built binary; pre-built is recommended for dogfood loops. Closes the broken provenance check introduced in the initial dogfood-build.sh commit. --- scripts/dogfood-build.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/dogfood-build.sh b/scripts/dogfood-build.sh index 5617a27eb7..21ba48eb82 100755 --- a/scripts/dogfood-build.sh +++ b/scripts/dogfood-build.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash # dogfood-build.sh — Build claw from current checkout and verify provenance. +# Injects GIT_SHA at build time so version JSON is non-null. # Usage: bash scripts/dogfood-build.sh # On success: prints the verified binary path. Use as: # CLAW=$(bash scripts/dogfood-build.sh) && $CLAW version --output-format json @@ -11,7 +12,11 @@ BINARY="$RUST_DIR/target/debug/claw" EXPECTED_SHA="$(git -C "$REPO_ROOT" rev-parse --short HEAD)" echo "▶ Building claw from $REPO_ROOT ($(git -C "$REPO_ROOT" log --oneline -1))..." >&2 -cargo build --manifest-path "$RUST_DIR/Cargo.toml" -p rusty-claude-cli -q +# Inject GIT_SHA so that version --output-format json returns a non-null sha. +# Without this, option_env!("GIT_SHA") in main.rs always yields None → null. +GIT_SHA="$EXPECTED_SHA" cargo build \ + --manifest-path "$RUST_DIR/Cargo.toml" \ + -p rusty-claude-cli -q if [[ ! -x "$BINARY" ]]; then echo "✗ Build succeeded but binary not found at $BINARY" >&2 @@ -19,10 +24,12 @@ if [[ ! -x "$BINARY" ]]; then fi BINARY_SHA=$("$BINARY" version --output-format json 2>/dev/null \ - | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('git_sha','null'))" 2>/dev/null || echo "null") + | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('git_sha') or 'null')" 2>/dev/null \ + || echo "null") if [[ "$BINARY_SHA" == "null" || -z "$BINARY_SHA" ]]; then echo "✗ Provenance check failed: binary reports git_sha: null" >&2 + echo " Ensure GIT_SHA is passed to cargo build (this script does it automatically)." >&2 echo " Binary: $BINARY" >&2 exit 1 fi @@ -34,5 +41,6 @@ if [[ "$BINARY_SHA" != "$EXPECTED_SHA" ]]; then fi echo "✓ Binary verified: $BINARY_SHA == HEAD ($EXPECTED_SHA)" >&2 +echo " cargo run alternative: ~1s overhead per invocation (vs 7ms for pre-built)" >&2 echo " To dogfood: export CLAW=$BINARY" >&2 echo "$BINARY" From 72cdab877f33aabf3e92ea0ec4f68a25825ec48c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Tue, 5 May 2026 06:35:56 +0900 Subject: [PATCH 2/2] fix(scripts): suppress cargo noise and document CLAW_CONFIG_HOME isolation Two gaps from Gaebal's 21:30 dogfood round: 1. cargo compile noise leaked to stderr during dogfood probes 2. real user config (~/.claw/settings.json) bled in via deprecation warnings ("enabledPlugins") even for purely local introspection Changes: - Redirect cargo build stderr to /dev/null (-q flag + 2>/dev/null) with a fallback re-run on failure so errors remain visible - Document CLAW_CONFIG_HOME isolation pattern in script output: CLAW_ISOLATED=$(mktemp -d) CLAW_CONFIG_HOME=$CLAW_ISOLATED $CLAW --output-format json rm -rf $CLAW_ISOLATED - With isolation: zero stderr lines for plugins list probe, pure JSON stdout, no config warnings Verified: exit 0, kind:plugin, 0 stderr lines, 0 sessions created. --- scripts/dogfood-build.sh | 54 ++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/scripts/dogfood-build.sh b/scripts/dogfood-build.sh index 21ba48eb82..7643dc9dcb 100755 --- a/scripts/dogfood-build.sh +++ b/scripts/dogfood-build.sh @@ -1,9 +1,16 @@ #!/usr/bin/env bash # dogfood-build.sh — Build claw from current checkout and verify provenance. +# # Injects GIT_SHA at build time so version JSON is non-null. -# Usage: bash scripts/dogfood-build.sh -# On success: prints the verified binary path. Use as: -# CLAW=$(bash scripts/dogfood-build.sh) && $CLAW version --output-format json +# Suppresses Cargo compile noise on stderr. +# Prints the verified binary path on success. Use as: +# +# CLAW=$(bash scripts/dogfood-build.sh) +# +# Then dogfood with config isolation (avoids real user config bleeding in): +# +# CLAW_CONFIG_HOME=$(mktemp -d) $CLAW plugins list --output-format json +# set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" @@ -11,15 +18,25 @@ RUST_DIR="$REPO_ROOT/rust" BINARY="$RUST_DIR/target/debug/claw" EXPECTED_SHA="$(git -C "$REPO_ROOT" rev-parse --short HEAD)" -echo "▶ Building claw from $REPO_ROOT ($(git -C "$REPO_ROOT" log --oneline -1))..." >&2 -# Inject GIT_SHA so that version --output-format json returns a non-null sha. -# Without this, option_env!("GIT_SHA") in main.rs always yields None → null. -GIT_SHA="$EXPECTED_SHA" cargo build \ - --manifest-path "$RUST_DIR/Cargo.toml" \ - -p rusty-claude-cli -q +echo "▶ Building claw from $REPO_ROOT" >&2 +echo " Commit: $(git -C "$REPO_ROOT" log --oneline -1)" >&2 + +# Inject GIT_SHA so version JSON returns a non-null sha. +# Redirect cargo stderr to /dev/null to suppress compile noise; +# on build failure cargo exits non-zero and set -e aborts. +if ! GIT_SHA="$EXPECTED_SHA" cargo build \ + --manifest-path "$RUST_DIR/Cargo.toml" \ + -p rusty-claude-cli -q 2>/dev/null; then + # Re-run with visible output so the user sees the error + echo "✗ Build failed — rerunning with output:" >&2 + GIT_SHA="$EXPECTED_SHA" cargo build \ + --manifest-path "$RUST_DIR/Cargo.toml" \ + -p rusty-claude-cli 2>&1 | sed 's/^/ /' >&2 + exit 1 +fi if [[ ! -x "$BINARY" ]]; then - echo "✗ Build succeeded but binary not found at $BINARY" >&2 + echo "✗ Binary not found at $BINARY" >&2 exit 1 fi @@ -29,18 +46,23 @@ BINARY_SHA=$("$BINARY" version --output-format json 2>/dev/null \ if [[ "$BINARY_SHA" == "null" || -z "$BINARY_SHA" ]]; then echo "✗ Provenance check failed: binary reports git_sha: null" >&2 - echo " Ensure GIT_SHA is passed to cargo build (this script does it automatically)." >&2 - echo " Binary: $BINARY" >&2 exit 1 fi if [[ "$BINARY_SHA" != "$EXPECTED_SHA" ]]; then echo "✗ Provenance mismatch: binary=$BINARY_SHA, HEAD=$EXPECTED_SHA" >&2 - echo " Rerun after 'git pull' or check for uncommitted changes." >&2 exit 1 fi -echo "✓ Binary verified: $BINARY_SHA == HEAD ($EXPECTED_SHA)" >&2 -echo " cargo run alternative: ~1s overhead per invocation (vs 7ms for pre-built)" >&2 -echo " To dogfood: export CLAW=$BINARY" >&2 +echo "✓ Binary verified: $BINARY_SHA == HEAD" >&2 +echo "" >&2 +echo " export CLAW=$BINARY" >&2 +echo "" >&2 +echo " Dogfood with isolated config (no real user config on stderr):" >&2 +echo " CLAW_ISOLATED=\$(mktemp -d)" >&2 +echo " CLAW_CONFIG_HOME=\$CLAW_ISOLATED \$CLAW plugins list --output-format json" >&2 +echo " rm -rf \$CLAW_ISOLATED" >&2 +echo "" >&2 +echo " cargo run overhead: ~1s/invocation vs 7ms for pre-built binary." >&2 +echo " Prefer pre-built binary (\$CLAW) for dogfood loops." >&2 echo "$BINARY"