#!/usr/bin/env bash # generate-fixtures.sh — Run all scenarios and write golden fixtures to tests/golden/ # Run from any directory. Uses absolute paths throughout. # SAFETY: Verifies real memsearch HEAD is unchanged after session-end scenarios. set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" # Set HOOKS_DIR to override, e.g. for Python port replay: # HOOKS_DIR=/path/to/python-hooks bash generate-fixtures.sh --replay-dir /tmp/out HOOKS_DIR="${HOOKS_DIR:-$(cd "$SCRIPT_DIR/../hooks" && pwd -P)}" GOLDEN_DIR="$SCRIPT_DIR/golden" INPUTS_DIR="$SCRIPT_DIR/inputs" REPLAY_DIR="" EXPECTED_HEAD="15804ed63ebf6400f22d719ee102857985f9a9d9" # --------------------------------------------------------------------------- # Parse arguments # --------------------------------------------------------------------------- while [[ $# -gt 0 ]]; do case "$1" in --replay-dir) REPLAY_DIR="$2"; shift 2 ;; *) echo "Unknown arg: $1" >&2; exit 1 ;; esac done # If --replay-dir is set, write there instead of golden/ if [[ -n "$REPLAY_DIR" ]]; then mkdir -p "$REPLAY_DIR" GOLDEN_DIR="$REPLAY_DIR" fi # --------------------------------------------------------------------------- # Safety: record real memsearch HEAD # --------------------------------------------------------------------------- REAL_HEAD_BEFORE=$(git -C /home/jared/.memsearch rev-parse HEAD 2>/dev/null || echo "NO_REAL_REPO") echo "=== SAFETY CHECK: real HEAD before = $REAL_HEAD_BEFORE ===" # In replay mode, skip the strict hash check (HEAD may have advanced since fixtures were made). # The safety invariant is before==after, not before==EXPECTED_HEAD. if [[ -z "$REPLAY_DIR" && "$REAL_HEAD_BEFORE" != "$EXPECTED_HEAD" ]]; then echo "ERROR: HEAD mismatch before run. Expected $EXPECTED_HEAD, got $REAL_HEAD_BEFORE" >&2 exit 1 fi # --------------------------------------------------------------------------- # Pre-run global cleanup of /tmp stale flags # --------------------------------------------------------------------------- cleanup_tmp_flags() { rm -f /tmp/memory-context-injected-golden-sess-{003,004,005,006,006b,006c,007,008} rm -f /tmp/claude-vault-touched-golden-sess-{006,006b,006c,007,008} } cleanup_tmp_flags mkdir -p "$GOLDEN_DIR" # --------------------------------------------------------------------------- # Normalization helper — takes sandbox path as $1, reads stdin # --------------------------------------------------------------------------- normalize() { local sandbox_path="$1" sed \ -e "s|[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}T[0-9]\{2\}:[0-9]\{2\}:[0-9]\{2\}Z|__TIMESTAMP__|g" \ -e "s|[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}|__DATE__|g" \ -e "s|${sandbox_path}|__SANDBOX__|g" \ -e "s|cwd=[^ ]*|cwd=__CWD__|g" \ -e "s|/home/jared|__REAL_HOME__|g" } # --------------------------------------------------------------------------- # Build a fresh sandbox for a scenario # Returns sandbox path in SANDBOX (exported) # --------------------------------------------------------------------------- make_sandbox() { local scenario="$1" local sb sb=$(mktemp -d) sb=$(cd "$sb" && pwd -P) mkdir -p "$sb/.claude/plugins/os-vault" cat > "$sb/.claude/plugins/os-vault/config.yaml" < "$sb/bin/graphify" <> "${sb}/graphify-shim.log" exit 0 BASH chmod +x "$sb/bin/graphify" # Git shim — log path BAKED IN (absolute, not env-var-only) for safety in subshells # Emits NOTHING to stdout/stderr cat > "$sb/bin/git" <> "${sb}/git-shim.log" exit 0 fi done exec /usr/bin/git "\$@" BASH chmod +x "$sb/bin/git" echo "$sb" } # --------------------------------------------------------------------------- # Helper: write all fixture files for a scenario # --------------------------------------------------------------------------- write_fixture() { local scenario="$1" local sb="$2" local stdout_content="$3" local exit_code="$4" local orig_input="$5" local sdir="$GOLDEN_DIR/$scenario" mkdir -p "$sdir/sideeffects" echo "$stdout_content" | normalize "$sb" > "$sdir/stdout.txt" echo "$exit_code" > "$sdir/exit_code.txt" cp "$orig_input" "$sdir/input.json" } # --------------------------------------------------------------------------- # SCENARIO: session-start-fresh # --------------------------------------------------------------------------- run_session_start_fresh() { echo "" echo "--- session-start-fresh ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-start-fresh") local sdir="$GOLDEN_DIR/session-start-fresh" mkdir -p "$sdir/sideeffects" # Setup: stamp file exists (fresh mtime) → rebuild NOT needed mkdir -p "$sb/.cache/graphify" touch "$sb/.cache/graphify/vault-rebuild.stamp" # Record log offset local log_offset=0 [[ -f /tmp/memory-hook.log ]] && log_offset=$(wc -c < /tmp/memory-hook.log) # Expand __SANDBOX__ in input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-start-fresh.json" > "$input_expanded" # Run hook local stdout exit_code=0 stdout=$(HOME="$sb" PATH="$sb/bin:$PATH" GRAPHIFY_SHIM_LOG="$sb/graphify-shim.log" \ bash "$HOOKS_DIR/session-start.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Write main fixtures write_fixture "session-start-fresh" "$sb" "$stdout" "$exit_code" "$INPUTS_DIR/session-start-fresh.json" # Side effect: memory-hook.log delta if [[ -f /tmp/memory-hook.log ]]; then dd if=/tmp/memory-hook.log bs=1 skip="$log_offset" 2>/dev/null \ | normalize "$sb" > "$sdir/sideeffects/memory-hook-log-delta.txt" else echo "(no log entries)" > "$sdir/sideeffects/memory-hook-log-delta.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "log delta: $(cat "$sdir/sideeffects/memory-hook-log-delta.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-start-stale # --------------------------------------------------------------------------- run_session_start_stale() { echo "" echo "--- session-start-stale ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-start-stale") local sdir="$GOLDEN_DIR/session-start-stale" mkdir -p "$sdir/sideeffects" # Setup: NO stamp file → rebuild needed # (we do NOT create vault-rebuild.stamp) # Record log offset local log_offset=0 [[ -f /tmp/memory-hook.log ]] && log_offset=$(wc -c < /tmp/memory-hook.log) # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-start-stale.json" > "$input_expanded" # Run hook local stdout exit_code=0 stdout=$(HOME="$sb" PATH="$sb/bin:$PATH" GRAPHIFY_SHIM_LOG="$sb/graphify-shim.log" \ bash "$HOOKS_DIR/session-start.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Poll for graphify shim log (background nohup'd call) for i in $(seq 1 10); do [[ -f "$sb/graphify-shim.log" ]] && break sleep 0.5 done # Write main fixtures write_fixture "session-start-stale" "$sb" "$stdout" "$exit_code" "$INPUTS_DIR/session-start-stale.json" # Side effect: memory-hook.log delta if [[ -f /tmp/memory-hook.log ]]; then dd if=/tmp/memory-hook.log bs=1 skip="$log_offset" 2>/dev/null \ | normalize "$sb" > "$sdir/sideeffects/memory-hook-log-delta.txt" else echo "(no log entries)" > "$sdir/sideeffects/memory-hook-log-delta.txt" fi # Side effect: graphify shim args if [[ -f "$sb/graphify-shim.log" ]]; then normalize "$sb" < "$sb/graphify-shim.log" > "$sdir/sideeffects/graphify-shim-args.txt" else echo "(graphify not invoked within 5s)" > "$sdir/sideeffects/graphify-shim-args.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "log delta: $(cat "$sdir/sideeffects/memory-hook-log-delta.txt")" echo "graphify shim: $(cat "$sdir/sideeffects/graphify-shim-args.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-context-first-with-graph # --------------------------------------------------------------------------- run_session_context_first_with_graph() { echo "" echo "--- session-context-first-with-graph ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-context-first-with-graph") local sdir="$GOLDEN_DIR/session-context-first-with-graph" mkdir -p "$sdir/sideeffects" # Setup: create a real git repo with graph.json mkdir -p "$sb/vault-project/graphify-out" echo '{"nodes":[],"edges":[]}' > "$sb/vault-project/graphify-out/graph.json" /usr/bin/git init "$sb/vault-project" >/dev/null 2>&1 /usr/bin/git -C "$sb/vault-project" config user.email "test@test.com" /usr/bin/git -C "$sb/vault-project" config user.name "Test" /usr/bin/git -C "$sb/vault-project" commit --allow-empty -m "init" >/dev/null 2>&1 # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-context-first-with-graph.json" > "$input_expanded" # Run hook from vault-project cwd local stdout exit_code=0 stdout=$(cd "$sb/vault-project" && HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/session-context.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Write main fixtures write_fixture "session-context-first-with-graph" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/session-context-first-with-graph.json" # Side effect: flag file created? if [[ -f /tmp/memory-context-injected-golden-sess-003 ]]; then echo "yes" > "$sdir/sideeffects/flag-file-created.txt" else echo "no" > "$sdir/sideeffects/flag-file-created.txt" fi echo "stdout (normalized): $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "flag created: $(cat "$sdir/sideeffects/flag-file-created.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-context-reentry # --------------------------------------------------------------------------- run_session_context_reentry() { echo "" echo "--- session-context-reentry ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-context-reentry") local sdir="$GOLDEN_DIR/session-context-reentry" mkdir -p "$sdir/sideeffects" # Setup: flag file already exists (reentry) touch /tmp/memory-context-injected-golden-sess-004 # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-context-reentry.json" > "$input_expanded" # Run hook from /tmp local stdout exit_code=0 stdout=$(cd /tmp && HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/session-context.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Write main fixtures write_fixture "session-context-reentry" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/session-context-reentry.json" echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-context-no-graph # --------------------------------------------------------------------------- run_session_context_no_graph() { echo "" echo "--- session-context-no-graph ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-context-no-graph") local sdir="$GOLDEN_DIR/session-context-no-graph" mkdir -p "$sdir/sideeffects" # Setup: git repo but NO graphify-out/graph.json mkdir -p "$sb/noproject" /usr/bin/git init "$sb/noproject" >/dev/null 2>&1 /usr/bin/git -C "$sb/noproject" config user.email "test@test.com" /usr/bin/git -C "$sb/noproject" config user.name "Test" /usr/bin/git -C "$sb/noproject" commit --allow-empty -m "init" >/dev/null 2>&1 # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-context-no-graph.json" > "$input_expanded" # Run hook from noproject cwd local stdout exit_code=0 stdout=$(cd "$sb/noproject" && HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/session-context.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Write main fixtures write_fixture "session-context-no-graph" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/session-context-no-graph.json" echo "stdout (normalized): $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: post-tool-use-vault-md # --------------------------------------------------------------------------- run_post_tool_use_vault_md() { echo "" echo "--- post-tool-use-vault-md ---" cleanup_tmp_flags local sb sb=$(make_sandbox "post-tool-use-vault-md") local sdir="$GOLDEN_DIR/post-tool-use-vault-md" mkdir -p "$sdir/sideeffects" # Setup: fresh stamp + vault notes dir touch "$sb/.cache/graphify/vault-rebuild.stamp" mkdir -p "$sb/vault/notes" # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/post-tool-use-vault-md.json" > "$input_expanded" # Run hook local stdout exit_code=0 stdout=$(HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/post-tool-use-write.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Write main fixtures write_fixture "post-tool-use-vault-md" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/post-tool-use-vault-md.json" # Side effect: touch file content if [[ -f /tmp/claude-vault-touched-golden-sess-006 ]]; then normalize "$sb" < /tmp/claude-vault-touched-golden-sess-006 \ > "$sdir/sideeffects/touch-file.txt" else echo "(not created)" > "$sdir/sideeffects/touch-file.txt" fi # Side effect: post-tool-use.log if [[ -f "$sb/.cache/graphify/post-tool-use.log" ]]; then normalize "$sb" < "$sb/.cache/graphify/post-tool-use.log" \ > "$sdir/sideeffects/post-tool-use-log.txt" else echo "(not created)" > "$sdir/sideeffects/post-tool-use-log.txt" fi # Side effect: stamp deleted? if [[ ! -f "$sb/.cache/graphify/vault-rebuild.stamp" ]]; then echo "yes" > "$sdir/sideeffects/stamp-deleted.txt" else echo "no" > "$sdir/sideeffects/stamp-deleted.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "touch-file: $(cat "$sdir/sideeffects/touch-file.txt")" echo "log: $(cat "$sdir/sideeffects/post-tool-use-log.txt")" echo "stamp-deleted: $(cat "$sdir/sideeffects/stamp-deleted.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: post-tool-use-non-md # --------------------------------------------------------------------------- run_post_tool_use_non_md() { echo "" echo "--- post-tool-use-non-md ---" cleanup_tmp_flags local sb sb=$(make_sandbox "post-tool-use-non-md") local sdir="$GOLDEN_DIR/post-tool-use-non-md" mkdir -p "$sdir/sideeffects" mkdir -p "$sb/vault/notes" # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/post-tool-use-non-md.json" > "$input_expanded" # Run hook local stdout exit_code=0 stdout=$(HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/post-tool-use-write.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? write_fixture "post-tool-use-non-md" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/post-tool-use-non-md.json" # Confirm touch file and log were NOT created (no-op) if [[ -f /tmp/claude-vault-touched-golden-sess-006b ]]; then echo "UNEXPECTED: touch file was created" > "$sdir/sideeffects/noops.txt" else echo "ok: no touch file (non-md guard fired)" > "$sdir/sideeffects/noops.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "noops: $(cat "$sdir/sideeffects/noops.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: post-tool-use-outside-vault # --------------------------------------------------------------------------- run_post_tool_use_outside_vault() { echo "" echo "--- post-tool-use-outside-vault ---" cleanup_tmp_flags local sb sb=$(make_sandbox "post-tool-use-outside-vault") local sdir="$GOLDEN_DIR/post-tool-use-outside-vault" mkdir -p "$sdir/sideeffects" # Expand input (no __SANDBOX__ in this one but run through sed anyway) local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/post-tool-use-outside-vault.json" > "$input_expanded" # Run hook local stdout exit_code=0 stdout=$(HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/post-tool-use-write.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? write_fixture "post-tool-use-outside-vault" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/post-tool-use-outside-vault.json" if [[ -f /tmp/claude-vault-touched-golden-sess-006c ]]; then echo "UNEXPECTED: touch file was created" > "$sdir/sideeffects/noops.txt" else echo "ok: no touch file (outside-vault guard fired)" > "$sdir/sideeffects/noops.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "noops: $(cat "$sdir/sideeffects/noops.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-end-with-touches # SAFETY: real HEAD must be verified after this run. # --------------------------------------------------------------------------- run_session_end_with_touches() { echo "" echo "--- session-end-with-touches ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-end-with-touches") local sdir="$GOLDEN_DIR/session-end-with-touches" mkdir -p "$sdir/sideeffects" # Git shim preflight echo " [preflight] Testing git shim..." "$sb/bin/git" -C /home/jared/.memsearch status >/dev/null 2>/dev/null if [[ -f "$sb/git-shim.log" ]]; then echo " [preflight] PASS — shim intercepted /home/jared/.memsearch call" cat "$sb/git-shim.log" # Clear the preflight entry so fixture only captures hook-time calls rm -f "$sb/git-shim.log" else echo " [preflight] WARNING — shim log not found; proceeding anyway" fi # Setup: touch file with two paths printf '%s\n%s\n' "${sb}/vault/notes/test.md" "${sb}/vault/notes/other.md" \ > /tmp/claude-vault-touched-golden-sess-007 # Ensure journal dir exists mkdir -p "$sb/vault/journal" # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-end-with-touches.json" > "$input_expanded" # Run hook from /tmp (avoids git rev-parse returning cc-os repo as project) local stdout exit_code=0 stdout=$(cd /tmp && HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/session-end.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # IMMEDIATE HEAD CHECK after first session-end run local head_after head_after=$(git -C /home/jared/.memsearch rev-parse HEAD 2>/dev/null || echo "NO_REAL_REPO") echo " [safety] HEAD after session-end-with-touches: $head_after" if [[ "$head_after" != "$REAL_HEAD_BEFORE" ]]; then echo "SAFETY BREACH: memsearch HEAD changed! $head_after != $REAL_HEAD_BEFORE" >&2 rm -rf "$sb" exit 99 fi echo " [safety] PASS" write_fixture "session-end-with-touches" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/session-end-with-touches.json" # Side effect: journal content (find by glob, not recomputing date) local journal_file journal_file=$(ls "$sb/vault/journal/"*.md 2>/dev/null | head -1) if [[ -n "$journal_file" && -f "$journal_file" ]]; then normalize "$sb" < "$journal_file" > "$sdir/sideeffects/journal.txt" else echo "(journal file not created)" > "$sdir/sideeffects/journal.txt" fi # Side effect: git shim log if [[ -f "$sb/git-shim.log" ]]; then normalize "$sb" < "$sb/git-shim.log" > "$sdir/sideeffects/git-shim-log.txt" else echo "(no git shim log — memsearch block not triggered?)" > "$sdir/sideeffects/git-shim-log.txt" fi # Side effect: touch file deleted? if [[ ! -f /tmp/claude-vault-touched-golden-sess-007 ]]; then echo "deleted" > "$sdir/sideeffects/touch-file-deleted.txt" else echo "NOT deleted (unexpected)" > "$sdir/sideeffects/touch-file-deleted.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "journal (first 10 lines):" head -10 "$sdir/sideeffects/journal.txt" || true echo "git-shim-log: $(cat "$sdir/sideeffects/git-shim-log.txt")" echo "touch-file-deleted: $(cat "$sdir/sideeffects/touch-file-deleted.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # SCENARIO: session-end-no-touches # --------------------------------------------------------------------------- run_session_end_no_touches() { echo "" echo "--- session-end-no-touches ---" cleanup_tmp_flags local sb sb=$(make_sandbox "session-end-no-touches") local sdir="$GOLDEN_DIR/session-end-no-touches" mkdir -p "$sdir/sideeffects" # Setup: NO touch file for golden-sess-008 mkdir -p "$sb/vault/journal" # Expand input local input_expanded="$sb/input-expanded.json" sed "s|__SANDBOX__|${sb}|g" "$INPUTS_DIR/session-end-no-touches.json" > "$input_expanded" # Run hook from /tmp local stdout exit_code=0 stdout=$(cd /tmp && HOME="$sb" PATH="$sb/bin:$PATH" \ bash "$HOOKS_DIR/session-end.sh" < "$input_expanded" 2>/dev/null) || exit_code=$? # Safety check local head_after head_after=$(git -C /home/jared/.memsearch rev-parse HEAD 2>/dev/null || echo "NO_REAL_REPO") echo " [safety] HEAD after session-end-no-touches: $head_after" if [[ "$head_after" != "$REAL_HEAD_BEFORE" ]]; then echo "SAFETY BREACH: memsearch HEAD changed!" >&2 rm -rf "$sb" exit 99 fi echo " [safety] PASS" write_fixture "session-end-no-touches" "$sb" "$stdout" "$exit_code" \ "$INPUTS_DIR/session-end-no-touches.json" # Side effect: journal content local journal_file journal_file=$(ls "$sb/vault/journal/"*.md 2>/dev/null | head -1) if [[ -n "$journal_file" && -f "$journal_file" ]]; then normalize "$sb" < "$journal_file" > "$sdir/sideeffects/journal.txt" else echo "(journal file not created)" > "$sdir/sideeffects/journal.txt" fi # Side effect: git shim log if [[ -f "$sb/git-shim.log" ]]; then normalize "$sb" < "$sb/git-shim.log" > "$sdir/sideeffects/git-shim-log.txt" else echo "(no git shim log — memsearch block not triggered?)" > "$sdir/sideeffects/git-shim-log.txt" fi echo "stdout: $(cat "$sdir/stdout.txt")" echo "exit_code: $exit_code" echo "journal (first 10 lines):" head -10 "$sdir/sideeffects/journal.txt" || true echo "git-shim-log: $(cat "$sdir/sideeffects/git-shim-log.txt")" rm -rf "$sb" } # --------------------------------------------------------------------------- # Run all scenarios # --------------------------------------------------------------------------- echo "=== Generating golden fixtures ===" run_session_start_fresh run_session_start_stale run_session_context_first_with_graph run_session_context_reentry run_session_context_no_graph run_post_tool_use_vault_md run_post_tool_use_non_md run_post_tool_use_outside_vault run_session_end_with_touches # safety-critical — HEAD checked immediately after run_session_end_no_touches # --------------------------------------------------------------------------- # Final safety check # --------------------------------------------------------------------------- echo "" echo "=== FINAL SAFETY CHECK ===" REAL_HEAD_AFTER=$(git -C /home/jared/.memsearch rev-parse HEAD 2>/dev/null || echo "NO_REAL_REPO") echo "BEFORE: $REAL_HEAD_BEFORE" echo "AFTER: $REAL_HEAD_AFTER" if [[ "$REAL_HEAD_AFTER" == "$REAL_HEAD_BEFORE" ]]; then echo "SAFETY CHECK PASSED — real memsearch HEAD unchanged" else echo "SAFETY CHECK FAILED — HEAD CHANGED from $REAL_HEAD_BEFORE to $REAL_HEAD_AFTER" exit 1 fi echo "" echo "=== All fixtures written to $GOLDEN_DIR ===" find "$GOLDEN_DIR" -type f | sort