#!/usr/bin/env bash
# Memory MCP boot-smoke gate.
#
# Spawns dist/index.js with a stub env, holds stdin open via `tail -f /dev/null`
# (the MCP SDK's StdioServerTransport exits on EOF — closing stdin would mask a
# clean boot as a failure), sleeps 2s, then asserts the process is still alive.
# A schema-loader throw, an import failure, or any other module-load fault
# would have killed the child by now and `kill -0` would return non-zero.
#
# Wired to the memory MCP `prepublish` script in package.json so a regression
# can never reach npm publish without the gate firing first. Local matrix:
#
#   $ ./scripts/boot-smoke.sh
#   [boot-smoke] memory ok
#
#   $ # break the schema content, rebuild, retry
#   $ ./scripts/boot-smoke.sh
#   [boot-smoke] memory FAILED tail=<schema-loader throw>
#   exit 1
set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
MCP_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
ENTRY="$MCP_DIR/dist/index.js"
PLATFORM_ROOT=$(cd "$MCP_DIR/../../.." && pwd)

if [ ! -f "$ENTRY" ]; then
  echo "[boot-smoke] memory FAILED tail=\"dist/index.js missing — run npm run build first\"" >&2
  exit 1
fi

LOG_DIR=$(mktemp -d -t mcp-boot-smoke.XXXXXX)
trap 'rm -rf "$LOG_DIR"' EXIT

# stdin from a `tail -f /dev/null` keeps the StdioServerTransport open. The
# pipeline's left side is a tiny long-running process; the right side is the
# MCP server we are smoke-testing. Both are killed below.
# Disable pipefail for this block — when bash forks the pipeline, $! is the
# PID of the LAST command (the node process), which is what we test below.
set +o pipefail

tail -f /dev/null | env \
  ACCOUNT_ID=boot-smoke-test \
  PLATFORM_ROOT="$PLATFORM_ROOT" \
  LOG_DIR="$LOG_DIR" \
  STREAM_LOG_PATH="$LOG_DIR/stream.log" \
  NEO4J_URI=bolt://localhost:7687 \
  SESSION_ID=boot-smoke \
  node "$ENTRY" > /dev/null 2>"$LOG_DIR/stderr-direct.log" &

NODE_PID=$!
sleep 2

if ! kill -0 "$NODE_PID" 2>/dev/null; then
  TAIL=$(tail -n 5 "$LOG_DIR/stderr-direct.log" 2>/dev/null | tr '\n' ' ' | sed 's/"/\\"/g')
  echo "[boot-smoke] memory FAILED tail=\"$TAIL\"" >&2
  # Reap the tail process by killing its parent group (the pipeline subshell).
  kill 0 2>/dev/null || true
  exit 1
fi

echo "[boot-smoke] memory ok"
kill "$NODE_PID" 2>/dev/null || true
# Reap the still-running `tail -f /dev/null` so the script exits cleanly.
# `disown` first so bash does not print a job-control "Terminated" line
# when the pipeline subshell is killed by exit-trap.
{ disown -a 2>/dev/null; pkill -P $$ -f "tail -f /dev/null"; } 2>/dev/null || true
wait 2>/dev/null || true
exit 0
