#!/usr/bin/env bash
# SessionStart hook for superpowers plugin

set -euo pipefail

# Determine plugin root directory.
# Splits $0 on its last / or \ (run-hook.cmd's cmd half passes a Windows
# path), with no separator meaning the current directory. This avoids
# dirname because a SessionStart:startup hook can run with a broken/empty
# PATH (anthropics/claude-code#43127) before any PATH-repairing sibling hook
# in the same startup batch takes effect.
#
# No command substitution or pipe runs in this script: each one forks, and a
# fork costs tens of milliseconds under Git Bash on Windows. The paths stay
# relative to the current directory, which is all the file read below needs.
case "$0" in
  */*|*\\*) SCRIPT_DIR="${0%[/\\]*}" ;;
  *) SCRIPT_DIR="." ;;
esac
PLUGIN_ROOT="${SCRIPT_DIR}/.."

# Read using-superpowers content with the read builtin (no cat, for the same
# PATH-independence reason, and no $(< file) subshell). read returns 1 at end
# of file, hence || true; the loop drops trailing newlines as $(< file) did.
skill_md="${PLUGIN_ROOT}/skills/using-superpowers/SKILL.md"
using_superpowers_content="Error reading using-superpowers skill"
if [ -r "$skill_md" ]; then
  IFS= read -r -d '' using_superpowers_content < "$skill_md" || true
  while [[ $using_superpowers_content == *$'\n' ]]; do
    using_superpowers_content="${using_superpowers_content%$'\n'}"
  done
fi

# Escape string for JSON embedding using bash parameter substitution.
# Each ${s//old/new} is a single C-level pass - orders of magnitude
# faster than the character-by-character loop this replaces. The result
# goes to a variable instead of stdout, so no $(...) subshell is needed.
escape_for_json() {
    local s="$1"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//$'\n'/\\n}"
    s="${s//$'\r'/\\r}"
    s="${s//$'\t'/\\t}"
    using_superpowers_escaped="$s"
}

escape_for_json "$using_superpowers_content"
session_context="<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${using_superpowers_escaped}\n</EXTREMELY_IMPORTANT>"

# Output context injection as JSON.
# Cursor hooks expect additional_context (snake_case).
# Claude Code hooks expect hookSpecificOutput.additionalContext (nested).
# Copilot CLI (v1.0.11+) and others expect additionalContext (top-level, SDK standard).
# Claude Code reads BOTH additional_context and hookSpecificOutput without
# deduplication, so we must emit only the field the current platform consumes.
# Muse sets MUSE_PLUGIN_ROOT and expects additionalContext (SDK standard).
#
# Uses printf instead of heredoc to work around bash 5.3+ heredoc hang.
# See: https://github.com/obra/superpowers/issues/571
#
# emit_json absorbs EPIPE without a pipe through `cat`. On Windows + Git
# Bash, the harness can close the hook's stdout before printf finishes, and
# Git Bash's printf reports that EPIPE as "printf: write error: Permission
# denied", which `set -euo pipefail` would let escape as a startup diagnostic
# every session (#1612). SIGPIPE is ignored so other platforms see the same
# EPIPE error instead of a signal; the error message is dropped and the
# status ignored. No external command is involved, so a broken PATH (#2310)
# changes nothing.
emit_json() {
  trap '' PIPE
  # shellcheck disable=SC2059 # every caller passes a literal format string
  printf "$@" 2>/dev/null || true
}

if [ -n "${CURSOR_PLUGIN_ROOT:-}" ]; then
  # Cursor sets CURSOR_PLUGIN_ROOT (may also set CLAUDE_PLUGIN_ROOT)
  emit_json '{\n  "additional_context": "%s"\n}\n' "$session_context"
elif [ -n "${CLAUDE_PLUGIN_ROOT:-}" ] && [ -z "${COPILOT_CLI:-}" ] && [ -z "${MUSE_PLUGIN_ROOT:-}" ]; then
  # Claude Code sets CLAUDE_PLUGIN_ROOT without COPILOT_CLI/MUSE_PLUGIN_ROOT
  emit_json '{\n  "hookSpecificOutput": {\n    "hookEventName": "SessionStart",\n    "additionalContext": "%s"\n  }\n}\n' "$session_context"
elif [ -n "${MUSE_PLUGIN_ROOT:-}" ]; then
  # Muse sets MUSE_PLUGIN_ROOT — try Claude-style nested output for Muse Spark
  emit_json '{\n  "hookSpecificOutput": {\n    "hookEventName": "SessionStart",\n    "additionalContext": "%s"\n  }\n}\n' "$session_context"
else
  # Copilot CLI (sets COPILOT_CLI=1) or unknown platform — SDK standard format
  emit_json '{\n  "additionalContext": "%s"\n}\n' "$session_context"
fi

exit 0
