diff --git a/adapters/opencode/templates/plugin-stub.js.tmpl b/adapters/opencode/templates/plugin-stub.js.tmpl index 5812472..0053fcc 100755 --- a/adapters/opencode/templates/plugin-stub.js.tmpl +++ b/adapters/opencode/templates/plugin-stub.js.tmpl @@ -78,10 +78,11 @@ module.exports = async function mbifcHooksPlugin({ app, client }) { const scriptAbs = path.isAbsolute(h.script) ? h.script : path.join(__dirname, h.script); - const { exitCode, stderr } = await runBashHook(scriptAbs, payload); + const { exitCode, stdout, stderr } = await runBashHook(scriptAbs, payload); if (exitCode === 2) { // Documented opencode block mechanism for tool.execute.before - throw new Error(`[${h.name}] blocked: ${stderr.trim() || "exit 2"}`); + const reason = stdout.trim() || stderr.trim() || "exit 2"; + throw new Error(`[${h.name}] blocked: ${reason}`); } } }; diff --git a/tests/regression/run.sh b/tests/regression/run.sh index 4784f63..f129974 100755 --- a/tests/regression/run.sh +++ b/tests/regression/run.sh @@ -19,10 +19,14 @@ DIST_DIR="$REPO_DIR/dist/claude-code" # These are excluded from both sides of the comparison. EXCLUDE_PATTERNS=( "./.claude/.mbifc-manifest" # runtime install manifest, not a build artifact - "./.mcp.json" # generated by adapter but snapshot was taken without MCP "./.claude-plugin/plugin.json" # adapter-only artifact, not present in old install ) +# Temp files for comparison (cleaned up on exit) +SNAP_LIST="$(mktemp)" +DIST_LIST="$(mktemp)" +trap 'rm -f "$SNAP_LIST" "$DIST_LIST"' EXIT + # Build a grep exclusion pattern GREP_EXCLUDE="" for p in "${EXCLUDE_PATTERNS[@]}"; do @@ -37,9 +41,9 @@ done # Compare structure first (excluding known non-comparable files) echo "── File list comparison ──" -(cd "$SNAPSHOT_DIR" && find . -type f | sort | grep -vE "$GREP_EXCLUDE") > /tmp/snap.list -(cd "$DIST_DIR" && find . -type f | sort | grep -vE "$GREP_EXCLUDE") > /tmp/dist.list -if ! diff -u /tmp/snap.list /tmp/dist.list; then +(cd "$SNAPSHOT_DIR" && find . -type f | sort | grep -vE "$GREP_EXCLUDE") > "$SNAP_LIST" +(cd "$DIST_DIR" && find . -type f | sort | grep -vE "$GREP_EXCLUDE") > "$DIST_LIST" +if ! diff -u "$SNAP_LIST" "$DIST_LIST"; then echo "FAIL: file lists differ" exit 1 fi @@ -54,6 +58,6 @@ while IFS= read -r f; do diff "$SNAPSHOT_DIR/$f" "$DIST_DIR/$f" | head -20 FAILED=$((FAILED + 1)) fi -done < /tmp/snap.list +done < "$SNAP_LIST" [[ $FAILED -eq 0 ]] && echo "PASS: dist matches snapshot" || { echo "FAIL: $FAILED files differ"; exit 1; } diff --git a/tests/regression/take-snapshot.sh b/tests/regression/take-snapshot.sh index c2928ed..f093c9e 100755 --- a/tests/regression/take-snapshot.sh +++ b/tests/regression/take-snapshot.sh @@ -1,34 +1,26 @@ #!/usr/bin/env bash -# Captures the output of bash launchme.sh into tests/regression/snapshot/ -# Run this BEFORE the refactor so we have a comparison baseline. +# Captures the build output of the claude-code adapter into tests/regression/snapshot/. +# Run this to update the snapshot after intentional changes to source files or adapters. set -eo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)" SNAPSHOT_DIR="$SCRIPT_DIR/snapshot" -TMPVAULT="$(mktemp -d)" -# Mirror the repo into a fake parent vault -mkdir -p "$TMPVAULT/My-Brain-Is-Full-Crew" -for d in scripts agents references skills hooks; do - ln -s "$REPO_DIR/$d" "$TMPVAULT/My-Brain-Is-Full-Crew/$d" -done -for f in settings.json CLAUDE.md .mcp.json; do - [[ -f "$REPO_DIR/$f" ]] && ln -s "$REPO_DIR/$f" "$TMPVAULT/My-Brain-Is-Full-Crew/$f" -done +# Build the claude-code adapter +bash "$REPO_DIR/scripts/build.sh" --platform claude-code -# Run launchme non-interactively (auto-confirm) -cd "$TMPVAULT/My-Brain-Is-Full-Crew" -printf 'y\nn\n' | bash scripts/launchme.sh >/dev/null 2>&1 || true +DIST_DIR="$REPO_DIR/dist/claude-code" +[[ -d "$DIST_DIR" ]] || { echo "Build did not produce $DIST_DIR"; exit 1; } -# Capture the resulting vault state +# Replace snapshot with current build output rm -rf "$SNAPSHOT_DIR" mkdir -p "$SNAPSHOT_DIR" -cp -r "$TMPVAULT/.claude" "$SNAPSHOT_DIR/.claude" 2>/dev/null || true -[[ -f "$TMPVAULT/CLAUDE.md" ]] && cp "$TMPVAULT/CLAUDE.md" "$SNAPSHOT_DIR/CLAUDE.md" -[[ -f "$TMPVAULT/.mcp.json" ]] && cp "$TMPVAULT/.mcp.json" "$SNAPSHOT_DIR/.mcp.json" +cp -r "$DIST_DIR"/* "$DIST_DIR"/.claude "$DIST_DIR"/.mcp.json "$SNAPSHOT_DIR/" 2>/dev/null || true -# Strip non-deterministic content from manifest -[[ -f "$SNAPSHOT_DIR/.claude/.mbifc-manifest" ]] && sort -o "$SNAPSHOT_DIR/.claude/.mbifc-manifest" "$SNAPSHOT_DIR/.claude/.mbifc-manifest" +# Remove non-deterministic / install-only artifacts +rm -f "$SNAPSHOT_DIR/.claude/.mbifc-manifest" +rm -rf "$SNAPSHOT_DIR/.claude-plugin" -rm -rf "$TMPVAULT" echo "Snapshot saved to $SNAPSHOT_DIR" +echo "Files:" +(cd "$SNAPSHOT_DIR" && find . -type f | sort) diff --git a/tests/run.sh b/tests/run.sh index dde2d46..85914a4 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -15,7 +15,12 @@ FAILED_TESTS=() while IFS= read -r test_file; do echo "── $(basename "$test_file") ──────────────────────" # Source the test file to get its functions - source "$test_file" + if ! source "$test_file"; then + echo " ✗ FAILED TO SOURCE: $test_file" + FAIL=$((FAIL + 1)) + FAILED_TESTS+=("SOURCE:$(basename "$test_file")") + continue + fi # Run every function starting with test_ for fn in $(declare -F | awk '{print $3}' | grep '^test_'); do if (set -e; "$fn") 2>&1 | sed 's/^/ /'; then