#!/usr/bin/env bash
# aTool - hooks/session-start
# Dynamic context generator: injects skill catalog, project context, and doc-sync reminders
# Works with Claude Code, Cursor, and other IDEs

set -euo pipefail

# Ensure we always exit cleanly — hook failures should not block the IDE
trap 'exit 0' EXIT

# Locate aTool installation
if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
    SCRIPT_DIR="$CLAUDE_PLUGIN_ROOT"
elif [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
    SCRIPT_DIR="$CURSOR_PLUGIN_ROOT"
else
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
fi

# Detect which IDE is running this hook
HOOK_IDE="claude"
if [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
    HOOK_IDE="cursor"
fi

# Read version, stripping potential CRLF from Windows
ATOOL_VERSION="${ATOOL_VERSION:-$(cat "$SCRIPT_DIR/../VERSION" 2>/dev/null || cat "$SCRIPT_DIR/VERSION" 2>/dev/null || echo "0.1.0")}"
ATOOL_VERSION="${ATOOL_VERSION%$'\r'}"

# Source common functions (scan_skills_catalog, stack_to_conventions_skill, count_stale_docs)
# Search order: PLUGIN_ROOT/lib/ → sibling lib/ → installed IDE lib/.
#
# SECURITY (v1.10.14, P1-SEC-2): the search path MUST NOT include any
# CWD-relative directory. Earlier versions iterated `${PWD}/.claude/lib`,
# which let a malicious repo ship its own `.claude/lib/common.sh`; if a user
# opened that repo and the hook fired (or was run standalone), the
# attacker's code was sourced under the user's account. The trusted set is
# now: paths anchored to the hook's own script dir (where atool installs
# its lib alongside) and paths under $HOME (installed by atool). PWD is
# explicitly excluded.
# shellcheck source=../lib/common.sh
_LIB_FOUND=false
for _lib_dir in "${SCRIPT_DIR}/lib" "${SCRIPT_DIR}/../lib" "$HOME/.claude/lib" "$HOME/.cursor/lib"; do
    if [[ -f "${_lib_dir}/common.sh" ]]; then
        source "${_lib_dir}/common.sh"
        _LIB_FOUND=true
        break
    fi
done

# Source detect-stack.sh for stack detection
# shellcheck source=../lib/detect-stack.sh
if [[ -f "${_lib_dir:-}/detect-stack.sh" ]]; then
    source "${_lib_dir}/detect-stack.sh"
fi

# Source registry.sh for role-resolution (spec §5.3, Task 3.2).
# Silently skip if not present — hook must never block session start.
# shellcheck source=../lib/registry.sh
if [[ -f "${_lib_dir:-}/registry.sh" ]]; then
    source "${_lib_dir}/registry.sh" 2>/dev/null || true
fi
unset _lib_dir _LIB_FOUND

# ── spec §5.3 static floor ──────────────────────────────────────────────────
# Safety net when registry is unavailable or registry_load fails.
# This constant replaces the old hardcoded dangling slash-command prose.
# Must contain at least: <ATOOL-ROLE-BINDINGS> … </ATOOL-ROLE-BINDINGS>.
ATOOL_STATIC_FLOOR='<ATOOL-ROLE-BINDINGS>
角色→技能 默认绑定（registry 不可用，使用静态地板）：
- requirements-authoring → /requirements-writer   (contract: prd)
- architecture-design    → /software-architecture  (contract: architecture)
- ui-design              → /ui-ux-pro               (contract: ui-design)
- code-quality-review    → /code-review             (contract: code-review)
- project-analysis       → /project-analyze         (contract: analysis)
</ATOOL-ROLE-BINDINGS>'

# build_role_bindings_block — emit <ATOOL-ROLE-BINDINGS> block (spec §5.3 / §7.4).
#
# Precedence:
#   1. registry_reconcile + registry_load succeed → live resolved table.
#   2. Any failure → fall back to ATOOL_STATIC_FLOOR (never crash the hook).
#
# Outputs: the complete XML-fenced block on stdout.
build_role_bindings_block() {
    # If registry.sh was not sourced (lib not found), emit static floor immediately.
    if ! declare -f registry_load &>/dev/null; then
        printf '%s' "$ATOOL_STATIC_FLOOR"
        return 0
    fi

    # reconcile-before-resolve (spec §F): prune ghost entries so a vanished skill
    # is never injected into the session context.
    registry_reconcile 2>/dev/null || true

    # Try to load registry; fall back to floor on failure.
    if ! registry_load 2>/dev/null; then
        printf '%s' "$ATOOL_STATIC_FLOOR"
        return 0
    fi

    local block
    block="<ATOOL-ROLE-BINDINGS>"$'\n'
    block+="角色→技能 当前绑定（引用 role 的指令请按此表解析；本表覆盖 SKILL.md 静态默认）："$'\n'

    local role skill contract
    for role in requirements-authoring architecture-design ui-design code-quality-review project-analysis; do
        skill=$(resolve_role "$role" 2>/dev/null || true)
        [[ -z "$skill" ]] && continue
        contract=$(role_contract "$role" 2>/dev/null || true)
        [[ -z "$contract" ]] && contract="-"
        block+="- ${role} → /${skill}  (contract: ${contract})"$'\n'
    done

    # List disabled/parked skills so the AI knows not to call them.
    local disabled
    disabled=$(printf '%s' "$_REGISTRY_CACHE" | \
        jq -r '.skills | to_entries[] | select(.value.enabled==false or .value.parkedPath!=null) | .key' \
        2>/dev/null | tr '\n' ' ' || true)
    [[ -n "${disabled// /}" ]] && block+="被禁用（不要调用）：${disabled}"$'\n'

    block+="</ATOOL-ROLE-BINDINGS>"
    printf '%s' "$block"
}

# Escape string for JSON embedding (same approach as Superpowers)
escape_for_json() {
    local s="$1"
    s="${s//\\/\\\\}"
    s="${s//\"/\\\"}"
    s="${s//$'\n'/\\n}"
    s="${s//$'\r'/\\r}"
    s="${s//$'\t'/\\t}"
    printf '%s' "$s"
}

# ═══════════════════════════════════════════════════════════════════════════
# 1. Inject using-superpowers skill content
# ═══════════════════════════════════════════════════════════════════════════

INJECTION=""
SUPERPOWERS_SKILLS=""
if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]]; then
    SUPERPOWERS_SKILLS="$CLAUDE_PLUGIN_ROOT/skills/using-superpowers"
elif [[ -n "${CURSOR_PLUGIN_ROOT:-}" ]]; then
    SUPERPOWERS_SKILLS="$CURSOR_PLUGIN_ROOT/skills/using-superpowers"
fi

# Fallback: scan IDE-specific config dirs
if [[ -z "$SUPERPOWERS_SKILLS" || ! -d "$SUPERPOWERS_SKILLS" ]]; then
    if [[ "$HOOK_IDE" == "cursor" ]] && declare -f get_cursor_config_dir &>/dev/null; then
        _sp_config_dir=$(get_cursor_config_dir 2>/dev/null || echo "")
        if [[ -d "$_sp_config_dir/skills/using-superpowers" ]]; then
            SUPERPOWERS_SKILLS="$_sp_config_dir/skills/using-superpowers"
        fi
    fi
fi
if [[ -z "$SUPERPOWERS_SKILLS" || ! -d "$SUPERPOWERS_SKILLS" ]]; then
    if [[ -d "$HOME/.claude/skills/using-superpowers" ]]; then
        SUPERPOWERS_SKILLS="$HOME/.claude/skills/using-superpowers"
    elif [[ -d "$HOME/.atool/cache/superpowers/skills/using-superpowers" ]]; then
        SUPERPOWERS_SKILLS="$HOME/.atool/cache/superpowers/skills/using-superpowers"
    fi
fi

if [[ -n "$SUPERPOWERS_SKILLS" && -d "$SUPERPOWERS_SKILLS" ]]; then
    SKILL_FILE=""
    if [[ -f "$SUPERPOWERS_SKILLS/SKILL.md" ]]; then
        SKILL_FILE="$SUPERPOWERS_SKILLS/SKILL.md"
    elif [[ -f "$SUPERPOWERS_SKILLS/skill.md" ]]; then
        SKILL_FILE="$SUPERPOWERS_SKILLS/skill.md"
    fi

    if [[ -n "$SKILL_FILE" ]]; then
        INJECTION+=$(cat "$SKILL_FILE")
        INJECTION+=$'\n\n'
    fi
fi

# ═══════════════════════════════════════════════════════════════════════════
# 2. Scan installed skills and generate catalog
# ═══════════════════════════════════════════════════════════════════════════

# Use IDE-appropriate skills directory
SKILLS_DIR="$HOME/.claude/skills"
if [[ "$HOOK_IDE" == "cursor" ]] && declare -f get_cursor_config_dir &>/dev/null; then
    _cursor_skills=$(get_cursor_config_dir 2>/dev/null || echo "$HOME/.cursor")
    _cursor_skills="$_cursor_skills/skills"
    if [[ -d "$_cursor_skills" ]]; then
        SKILLS_DIR="$_cursor_skills"
    fi
fi
unset _cursor_skills _sp_config_dir 2>/dev/null || true

CATALOG=""
if declare -f scan_skills_catalog &>/dev/null; then
    CATALOG=$(scan_skills_catalog "$SKILLS_DIR")
fi

# ═══════════════════════════════════════════════════════════════════════════
# 3. Detect project context (only when in a project directory)
# ═══════════════════════════════════════════════════════════════════════════

PROJECT_CONTEXT=""
DOC_SYNC=""
PROJECT_DIR="${PWD:-}"

# Only inject project context if we're in a real project (has .git or signal files)
IS_PROJECT=false
if [[ -d "$PROJECT_DIR/.git" ]] || [[ -f "$PROJECT_DIR/pom.xml" ]] || \
   [[ -f "$PROJECT_DIR/package.json" ]] || [[ -f "$PROJECT_DIR/Cargo.toml" ]] || \
   [[ -f "$PROJECT_DIR/go.mod" ]] || [[ -f "$PROJECT_DIR/pyproject.toml" ]] || \
   [[ -f "$PROJECT_DIR/requirements.txt" ]] || [[ -f "$PROJECT_DIR/pubspec.yaml" ]] || \
   [[ -f "$PROJECT_DIR/build.gradle" ]] || [[ -f "$PROJECT_DIR/build.gradle.kts" ]] || \
   [[ -f "$PROJECT_DIR/dbt_project.yml" ]] || [[ -f "$PROJECT_DIR/spark-defaults.conf" ]]; then
    IS_PROJECT=true
fi

if $IS_PROJECT && declare -f detect_stack &>/dev/null; then
    STACK=$(detect_stack "$PROJECT_DIR")
    STACK_DESC=""
    if declare -f get_stack_description &>/dev/null; then
        STACK_DESC=$(get_stack_description "$STACK")
    fi

    CONVENTIONS_SKILL=""
    if declare -f stack_to_conventions_skill &>/dev/null; then
        CONVENTIONS_SKILL=$(stack_to_conventions_skill "$STACK")
    fi

    PROJECT_CONTEXT="<ATOOL-PROJECT-CONTEXT>"
    PROJECT_CONTEXT+=$'\n'
    PROJECT_CONTEXT+="Current project: ${STACK_DESC} (${STACK})"
    PROJECT_CONTEXT+=$'\n'
    if [[ -n "$CONVENTIONS_SKILL" ]]; then
        PROJECT_CONTEXT+="Primary conventions: /${CONVENTIONS_SKILL}"
        PROJECT_CONTEXT+=$'\n'
    fi

    # Check doc freshness against ALL documentation files
    STALE_COUNT=0
    _DOC_FILES=()
    for _doc in "README.md" "COMPONENT.md" "UI_STYLE.md" "DESIGN.md" "ARCHITECTURE.md" "CODE_REVIEW.md"; do
        [[ -f "$PROJECT_DIR/$_doc" ]] && _DOC_FILES+=("$_doc")
    done
    if [[ -d "$PROJECT_DIR/docs" ]]; then
        while IFS= read -r _doc; do
            [[ -n "$_doc" ]] && _DOC_FILES+=("$_doc")
        done < <(find "$PROJECT_DIR/docs" -maxdepth 1 -name '*.md' -type f 2>/dev/null | head -20 | sed "s|^$PROJECT_DIR/||")
    fi
    if declare -f count_stale_docs &>/dev/null && [[ ${#_DOC_FILES[@]} -gt 0 ]]; then
        STALE_COUNT=$(count_stale_docs "$PROJECT_DIR" "${_DOC_FILES[@]}")
    fi
    if [[ "$STALE_COUNT" -gt 0 ]]; then
        PROJECT_CONTEXT+="Doc status: STALE — ${STALE_COUNT} source files newer than docs (${#_DOC_FILES[@]} docs checked)"
        PROJECT_CONTEXT+=$'\n'
    else
        PROJECT_CONTEXT+="Doc status: All docs up to date (${#_DOC_FILES[@]} docs checked)"
        PROJECT_CONTEXT+=$'\n'
    fi

    # Check if UI project is missing UI_STYLE.md
    IS_UI_PROJECT=false
    case "$STACK" in
        web-*|android-*|mobile-*|harmony|rust-tauri) IS_UI_PROJECT=true ;;
    esac
    if $IS_UI_PROJECT && [[ ! -f "$PROJECT_DIR/UI_STYLE.md" ]]; then
        PROJECT_CONTEXT+="UI spec: MISSING — This is a UI project but UI_STYLE.md not found. Consider running /ui-ux-pro to establish design guidelines."
        PROJECT_CONTEXT+=$'\n'
    fi
    if $IS_UI_PROJECT && [[ ! -f "$PROJECT_DIR/DESIGN.md" ]]; then
        PROJECT_CONTEXT+="Design system: MISSING — DESIGN.md not found (Google Stitch protocol). Run /ui-ux-pro to generate a design system manifest."
        PROJECT_CONTEXT+=$'\n'
    fi

    # Data Warehouse project context
    if [[ "$STACK" == "data-warehouse" ]]; then
        # Route each data role through resolve_role so disabled skills are suppressed.
        # Fall back to the well-known skill name only when registry is unavailable
        # (declare -f registry_load fails) — never emit dangling prose unconditionally.
        _dw_lines=""
        _dw_role_map=(
            "data-conventions:data-conventions:DW naming, layering, SQL standards"
            "data-warehouse-modeling:data-warehouse-modeling:Dimensional modeling, ER design"
            "sql-development:sql-development:SQL coding standards and patterns"
            "sql-optimization:sql-optimization:Query performance tuning"
            "data-quality:data-quality:Data quality checks and rules"
            "data-code-review:data-code-review:SQL/DW code review"
            "scheduling-design:scheduling-design:Airflow DAG scheduling"
            "requirement-analysis:requirement-analysis:Data requirement analysis"
            "test-case-generation:test-case-generator:S2T/T2S test cases"
            "deployment:deployment:Data deployment and release"
        )
        for _entry in "${_dw_role_map[@]}"; do
            _role="${_entry%%:*}"; _rest="${_entry#*:}"
            _fallback_skill="${_rest%%:*}"; _desc="${_rest#*:}"
            if declare -f resolve_role &>/dev/null; then
                _resolved=$(resolve_role "$_role" 2>/dev/null || true)
                [[ -z "$_resolved" ]] && continue   # disabled or unresolved → suppress
            else
                _resolved="$_fallback_skill"        # no registry → use floor name
            fi
            _dw_lines+="  /${_resolved} — ${_desc}"$'\n'
        done
        unset _entry _role _rest _fallback_skill _desc _resolved

        if [[ -n "$_dw_lines" ]]; then
            PROJECT_CONTEXT+="Data stack: Data Warehouse detected. Available skills:"
            PROJECT_CONTEXT+=$'\n'
            PROJECT_CONTEXT+="$_dw_lines"
        fi
        unset _dw_lines _dw_role_map

        # Check DW-specific docs
        if [[ ! -f "$PROJECT_DIR/COMPONENT.md" ]]; then
            PROJECT_CONTEXT+="DW docs: MISSING — COMPONENT.md not found. Run /data-warehouse-modeling to document layer architecture."
            PROJECT_CONTEXT+=$'\n'
        fi
    fi

    # Check analysis status
    if [[ -d "$PROJECT_DIR/.atool-docs" ]]; then
        PROJECT_CONTEXT+="Analysis status: Project analyzed (see .atool-docs/)"
        PROJECT_CONTEXT+=$'\n'
    else
        PROJECT_CONTEXT+="Analysis status: Not yet analyzed - consider running /project-analyze"
        PROJECT_CONTEXT+=$'\n'
    fi

    PROJECT_CONTEXT+="</ATOOL-PROJECT-CONTEXT>"

    # Hard rules — non-bypassable gates extracted from skills.
    # These apply in ALL modes: normal, Plan Mode, etc.
    # Skill references are routed through resolve_role so they reflect the live
    # registry binding; the floor name is used when the registry is unavailable.
    _hr_verification=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "completion-verification" 2>/dev/null || true)
            echo "${_s:-verification-before-completion}"
        else
            echo "verification-before-completion"
        fi)
    _hr_debugging=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "systematic-debugging" 2>/dev/null || true)
            echo "${_s:-systematic-debugging}"
        else
            echo "systematic-debugging"
        fi)
    _hr_tdd=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "tdd" 2>/dev/null || true)
            echo "${_s:-test-driven-development}"
        else
            echo "test-driven-development"
        fi)
    _hr_requirements=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "requirements-authoring" 2>/dev/null || true)
            echo "${_s:-requirements-writer}"
        else
            echo "requirements-writer"
        fi)
    _hr_architecture=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "architecture-design" 2>/dev/null || true)
            echo "${_s:-software-architecture}"
        else
            echo "software-architecture"
        fi)
    _hr_uidesign=$(
        if declare -f resolve_role &>/dev/null; then
            _s=$(resolve_role "ui-design" 2>/dev/null || true)
            echo "${_s:-ui-ux-pro}"
        else
            echo "ui-ux-pro"
        fi)

    DOC_SYNC="<ATOOL-HARD-RULES>"
    DOC_SYNC+=$'\n'
    DOC_SYNC+="Five NON-NEGOTIABLE rules that apply in ALL modes (Plan Mode, normal mode, etc.):"
    DOC_SYNC+=$'\n\n'
    DOC_SYNC+="1. **Doc Sync Gate**: After modifying any source file, update affected docs (README.md, COMPONENT.md, UI_STYLE.md, DESIGN.md, docs/) BEFORE claiming done. If docs stale -> task NOT done."
    DOC_SYNC+=$'\n'
    DOC_SYNC+="2. **Verification Gate**: Before claiming complete: (a) tests pass, (b) docs fresh, (c) no critical issues. Any fail -> task NOT done. Invoke /${_hr_verification}."
    DOC_SYNC+=$'\n'
    DOC_SYNC+="3. **Root Cause Gate**: When debugging, identify root cause BEFORE writing fix. Never guess-fix. See /${_hr_debugging}."
    DOC_SYNC+=$'\n'
    DOC_SYNC+="4. **Pre-Doc Gate**: Before coding new features, required docs must exist — PRD in docs/300-requirements/, architecture in docs/400-architecture/, UI design in docs/500-design/. Missing = implementation MUST NOT start. Create via /${_hr_requirements}, /${_hr_architecture}, /${_hr_uidesign}."
    DOC_SYNC+=$'\n'
    DOC_SYNC+="5. **TDD Gate**: New features/behavior changes -> write failing test FIRST, then minimal code to pass. No test = no implementation. See /${_hr_tdd}."
    DOC_SYNC+=$'\n\n'
    DOC_SYNC+="When writing plans (any mode): MUST include a final Documentation Sync task. Plans without it are INCOMPLETE."
    DOC_SYNC+=$'\n'
    DOC_SYNC+="</ATOOL-HARD-RULES>"
    unset _hr_verification _hr_debugging _hr_tdd _hr_requirements _hr_architecture _hr_uidesign
fi

# ═══════════════════════════════════════════════════════════════════════════
# 4. Assemble and output
# ═══════════════════════════════════════════════════════════════════════════

INJECTION+="<system-reminder>"
INJECTION+=$'\n'
INJECTION+="SessionStart: aTool v${ATOOL_VERSION} active. Skills, hooks, and MCP servers configured."
INJECTION+=$'\n'
INJECTION+="</system-reminder>"
INJECTION+=$'\n\n'
INJECTION+="<EXTREMELY_IMPORTANT>"
INJECTION+=$'\n'
INJECTION+="<ATOOL-SESSION>"
INJECTION+=$'\n'
INJECTION+="aTool v${ATOOL_VERSION} active."
INJECTION+=$'\n\n'

if [[ -n "$CATALOG" ]]; then
    INJECTION+="<ATOOL-SKILL-CATALOG>"
    INJECTION+=$'\n'
    INJECTION+="$CATALOG"
    INJECTION+=$'\n'
    INJECTION+="Invoke skills with: /{skill-name}"
    INJECTION+=$'\n'
    INJECTION+="</ATOOL-SKILL-CATALOG>"
    INJECTION+=$'\n\n'
fi

if [[ -n "$PROJECT_CONTEXT" ]]; then
    INJECTION+="$PROJECT_CONTEXT"
    INJECTION+=$'\n\n'
fi

if [[ -n "$DOC_SYNC" ]]; then
    INJECTION+="$DOC_SYNC"
    INJECTION+=$'\n\n'
fi

# spec §5.3 / Task 3.2 — inject live role→skill binding table (or static floor).
# Runs unconditionally: the AI always needs to know which concrete skill fills
# each role. The hook must not abort on registry errors — build_role_bindings_block
# is itself guarded; any failure falls through to the static floor.
ROLE_BINDINGS=$(build_role_bindings_block 2>/dev/null || printf '%s' "$ATOOL_STATIC_FLOOR")
INJECTION+="$ROLE_BINDINGS"
INJECTION+=$'\n\n'
unset ROLE_BINDINGS

# Only inject clarify rule if in a code project (detected by presence of common project files)
if [[ -f "package.json" || -f "pom.xml" || -f "go.mod" || -f "Cargo.toml" || -f "requirements.txt" || -f "build.gradle" || -f ".gradle" || -f "setup.py" || -f "Gemfile" ]]; then
    INJECTION+="<ATOOL-CLARIFY-RULE>"
    INJECTION+=$'\n'
    INJECTION+="Before implementing ANY feature, first classify task complexity:"
    INJECTION+=$'\n'
    INJECTION+="Tier 0 (direct): single-value change, typo, format fix -> just do it"
    INJECTION+=$'\n'
    INJECTION+="Tier 1 (1-2 questions): small change with ambiguity -> ask key questions"
    INJECTION+=$'\n'
    INJECTION+="Tier 2 (3-5 questions): new feature, medium complexity -> structured clarification"
    INJECTION+=$'\n'
    INJECTION+="Tier 3: architecture-level, vague requirements -> delegate to /brainstorming"
    INJECTION+=$'\n'
    INJECTION+="Rules: Read project files BEFORE asking (CLAUDE.md, package.json, source code). Never assume installed libs or existing patterns. Ask context-aware questions, not obvious ones."
    INJECTION+=$'\n'
    INJECTION+="Exit: If user says '别问了'/'直接做'/'just do it'/'stop asking' -> skip all questions, Tier 0."
    INJECTION+=$'\n'
    INJECTION+="See /clarify-before-build for full methodology."
    INJECTION+=$'\n'
    INJECTION+="</ATOOL-CLARIFY-RULE>"
    INJECTION+=$'\n'
fi

# Inject language rule (always, for all projects)
INJECTION+="<ATOOL-LANGUAGE-RULE>"
INJECTION+=$'\n'
INJECTION+="语言要求 (Language Requirement):"
INJECTION+=$'\n'
INJECTION+="- 项目文档 (docs/, README, 架构指南): 必须中文"
INJECTION+=$'\n'
INJECTION+="- SKILL.md: 保持英文（AI 指令文件）"
INJECTION+=$'\n'
INJECTION+="- Commit message: 推荐中文"
INJECTION+=$'\n'
INJECTION+="- 代码注释: 可中文或英文（跟随代码风格）"
INJECTION+=$'\n'
INJECTION+="如果误用英文写项目文档，请用 /doc-coauthoring 重写为中文。"
INJECTION+=$'\n'
INJECTION+="</ATOOL-LANGUAGE-RULE>"
INJECTION+=$'\n'

# v1.10.23 — opt-in update notifier. When ATOOL_UPDATE_NOTIFIER=1 and the 24h
# cache shows an available update, inject a one-liner so the model can mention
# it. Default OFF so this hook adds zero noise unless the user opts in.
# Reads ~/.atool/cache/update-check.json populated by `atool check-updates`.
if [[ "${ATOOL_UPDATE_NOTIFIER:-0}" == "1" ]]; then
    _update_cache="$HOME/.atool/cache/update-check.json"
    if [[ -f "$_update_cache" ]] && command -v jq >/dev/null 2>&1; then
        # Resolve installed version. Prefer ATOOL_ROOT/VERSION (set by install.sh
        # when this hook is sourced), fall back to walking up from $BASH_SOURCE.
        _hook_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
        _installed=""
        for _candidate in "${ATOOL_ROOT:-$_hook_dir/..}/VERSION" "$_hook_dir/../VERSION"; do
            if [[ -f "$_candidate" ]]; then
                _installed=$(tr -d '\n' < "$_candidate")
                break
            fi
        done
        _latest=$(jq -r '.latest // empty' "$_update_cache" 2>/dev/null || true)
        if [[ -n "$_latest" && -n "$_installed" && "$_latest" != "$_installed" ]]; then
            INJECTION+=$'\n'
            INJECTION+="<ATOOL-UPDATE-AVAILABLE>"
            INJECTION+=$'\n'
            INJECTION+="aTool update available: ${_installed} → ${_latest}. Run: atool update"
            INJECTION+=$'\n'
            INJECTION+="(Cached check; refresh with: atool check-updates --force)"
            INJECTION+=$'\n'
            INJECTION+="</ATOOL-UPDATE-AVAILABLE>"
            INJECTION+=$'\n'
        fi
    fi
fi

INJECTION+="</ATOOL-SESSION>"
INJECTION+=$'\n'
INJECTION+="</EXTREMELY_IMPORTANT>"

# Output in the format expected by the running IDE.
# Claude Code reads BOTH additional_context and hookSpecificOutput without deduplication,
# so we must emit only the appropriate field to avoid double injection.
if [[ "$HOOK_IDE" == "cursor" ]]; then
    INJECTION_ESCAPED=$(escape_for_json "$INJECTION")
    printf '{\n  "additional_context": "%s"\n}\n' "$INJECTION_ESCAPED"
else
    # Claude Code: plain text output (hook framework wraps it automatically)
    printf '%s' "$INJECTION"
fi

exit 0
