#!/usr/bin/env bash
# Tests for claudeCode — Claude Code session management
# Tests: process.find, session.save, session.recover, session.name, context.check, list.named

level=$1
if [ -z "$level" ]; then
  level=1
fi
echo "starting: ${BASH_SOURCE[@]##*/} <LOG_LEVEL=$level>"

source this
source test.suite

log.level $level

# ============================================================================
# T1: claudeCode is callable
# ============================================================================
test.case $level "claudeCode is callable" \
  which claudeCode

if which claudeCode &>/dev/null; then
  expect.pass "claudeCode found on PATH"
else
  expect.fail "claudeCode should be on PATH"
fi

# ============================================================================
# T2: claudeCode.process.find function exists
# ============================================================================
test.case $level "claudeCode.process.find function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.process.find'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.process.find 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.process.find function exists"
else
  expect.fail "claudeCode.process.find should be a function"
fi

# ============================================================================
# T3: claudeCode.session.save function exists
# ============================================================================
test.case $level "claudeCode.session.save function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.session.save'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.session.save 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.session.save function exists"
else
  expect.fail "claudeCode.session.save should be a function"
fi

# ============================================================================
# T4: claudeCode.session.recover function exists
# ============================================================================
test.case $level "claudeCode.session.recover function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.session.recover'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.session.recover 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.session.recover function exists"
else
  expect.fail "claudeCode.session.recover should be a function"
fi

# ============================================================================
# T5: claudeCode.session.name function exists
# ============================================================================
test.case $level "claudeCode.session.name function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.session.name'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.session.name 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.session.name function exists"
else
  expect.fail "claudeCode.session.name should be a function"
fi

# ============================================================================
# T6: claudeCode.context.check function exists
# ============================================================================
test.case $level "claudeCode.context.check function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.context.check'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.context.check 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.context.check function exists"
else
  expect.fail "claudeCode.context.check should be a function"
fi

# ============================================================================
# T7: claudeCode.list.named function exists
# ============================================================================
test.case $level "claudeCode.list.named function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.list.named'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.list.named 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.list.named function exists"
else
  expect.fail "claudeCode.list.named should be a function"
fi

# ============================================================================
# T8: claudeCode.session.id function exists
# ============================================================================
test.case $level "claudeCode.session.id function exists" \
  bash -c 'source this; source claudeCode; type -t claudeCode.session.id'

FUNC_EXISTS=$(bash -c 'source this; source claudeCode; type -t claudeCode.session.id 2>/dev/null')
if [ "$FUNC_EXISTS" = "function" ]; then
  expect.pass "claudeCode.session.id function exists"
else
  expect.fail "claudeCode.session.id should be a function"
fi

# ============================================================================
# T9: claudeCode.context.jsonl function accepts pane param
# ============================================================================
test.case $level "claudeCode.context.jsonl accepts pane parameter" \
  bash -c 'source this; source claudeCode; declare -f claudeCode.context.jsonl | grep -q "pane"'

HAS_PANE=$(bash -c 'source this; source claudeCode; declare -f claudeCode.context.jsonl 2>/dev/null | grep -c "pane"')
if [ "$HAS_PANE" -ge 1 ]; then
  expect.pass "claudeCode.context.jsonl references pane parameter"
else
  expect.fail "claudeCode.context.jsonl should accept pane parameter for per-agent JSONL resolution"
fi

# ============================================================================
# T10: claudeCode.agent.start does NOT use --dangerously-skip-permissions
# ============================================================================
# Check agent.start specifically — claudeCode.dangerously() is a separate opt-in function
test.case $level "claudeCode.agent.start does NOT use --dangerously-skip-permissions" \
  echo "checking agent.start"

# Extract agent.start function body only (between function def and next function)
SKIP_IN_AGENT_START=$(sed -n '/^claudeCode\.agent\.start()/,/^claudeCode\./p' "$OOSH_DIR/claudeCode" | grep -c "dangerously-skip-permissions")
if [ "$SKIP_IN_AGENT_START" -eq 0 ]; then
  expect.pass "claudeCode.agent.start does NOT use --dangerously-skip-permissions (security OK)"
else
  expect.fail "CRITICAL: claudeCode.agent.start uses --dangerously-skip-permissions — PO violation"
fi

# ============================================================================
# LIVE BEHAVIORAL TESTS — session.id accuracy vs /status ground truth
# DISABLED: These tests send /status to every Claude pane, which:
#   1. Disrupts running agents (sends commands to their active sessions)
#   2. Only works on this specific machine with the current tmux layout
#   3. Takes ~4s per pane — very slow for large session counts
# TODO: Redesign as fixture-based test using ooshDebug with known panes.
# Use T-ALIGN-1 (ps --resume UUID comparison) instead — non-disruptive.

LIVE_PANES=""  # Still needed by T-IDLE and T-ALIGN tests below
CURRENT_SESSION=""
while IFS= read -r line; do
  if echo "$line" | grep -qE '^[├└]── '; then
    CURRENT_SESSION=$(echo "$line" | sed 's/^[├└]── //' | sed 's/ (.*//')
    continue
  fi
  if echo "$line" | grep -qE '\[[0-9]+\.[0-9]+\.[0-9]+\]'; then
    PANE_ADDR=$(echo "$line" | grep -oE '[0-9]+\.[0-9]+' | head -1)
    if [ -n "$CURRENT_SESSION" ] && [ -n "$PANE_ADDR" ]; then
      LIVE_PANES="$LIVE_PANES ${CURRENT_SESSION}:${PANE_ADDR}"
    fi
  fi
done < <(otmux 2>/dev/null)

LIVE_TESTED=0
LIVE_PASSED=0
LIVE_FAILED=0

test.case $level "session.id /status live test (DISABLED — disruptive to agents)" \
  echo "skipped"
expect.pass "session.id /status live test skipped (use T-ALIGN-1 for non-disruptive UUID validation)"

# ============================================================================
# T-IDLE: session.id returns exit 1 for idle (non-Claude) pane
# ============================================================================

# Find a pane NOT in LIVE_PANES that runs a plain shell
IDLE_PANE=""
while IFS= read -r line; do
  # Pane lines with [bash] or [zsh] — no Claude version
  if echo "$line" | grep -qE '\[(bash|zsh)\]'; then
    PANE_ADDR=$(echo "$line" | grep -oE '[0-9]+\.[0-9]+' | head -1)
    if [ -n "$CURRENT_SESSION" ] && [ -n "$PANE_ADDR" ]; then
      candidate="${CURRENT_SESSION}:${PANE_ADDR}"
      # Verify no claude PID behind it
      if ! claudeCode process.find "$candidate" &>/dev/null 2>&1; then
        IDLE_PANE="$candidate"
        break
      fi
    fi
  fi
  # Track current session for context
  if echo "$line" | grep -qE '^[├└]── '; then
    CURRENT_SESSION=$(echo "$line" | sed 's/^[├└]── //' | sed 's/ (.*//')
  fi
done < <(otmux 2>/dev/null)

if [ -n "$IDLE_PANE" ]; then
  test.case $level "session.id returns exit 1 for idle pane $IDLE_PANE" \
    claudeCode session.id "$IDLE_PANE"

  claudeCode session.id "$IDLE_PANE" >/dev/null 2>&1
  IDLE_EXIT=$?
  IDLE_OUTPUT=$(claudeCode session.id "$IDLE_PANE" 2>/dev/null || true)

  if [ "$IDLE_EXIT" -ne 0 ] && [ -z "$IDLE_OUTPUT" ]; then
    expect.pass "session.id correctly returns exit 1 + empty for idle pane $IDLE_PANE"
  else
    expect.fail "session.id should return exit 1 + empty for idle pane, got exit=$IDLE_EXIT output='$IDLE_OUTPUT'"
  fi
else
  test.case $level "session.id idle pane test (skipped - no idle pane found)" \
    echo "skipped"
  expect.pass "session.id idle pane test skipped"
fi

# ============================================================================
# T-REGISTRY: hiveMind registry matches live session identity for ALL panes
# ============================================================================

REG_FILE="${HIVEMIND_REGISTRY:-${CONFIG_PATH:-$HOME/config}/hivemind.roles.env}"
if [ -f "$REG_FILE" ]; then
  for pane in $LIVE_PANES; do
    # Get registry role for this pane
    REG_ROLE=$(grep "^${pane}|" "$REG_FILE" 2>/dev/null | cut -d'|' -f2)
    [ -z "$REG_ROLE" ] && continue

    # Get actual session name
    SID=$(claudeCode session.id "$pane" 2>/dev/null || true)
    [ -z "$SID" ] && continue
    SNAME=$(claudeCode session.name "$SID" 2>/dev/null || true)
    [ -z "$SNAME" ] && continue

    # Extract role from session name (role@model format)
    if [[ "$SNAME" == *"@"* ]]; then
      ACTUAL_ROLE="${SNAME%%@*}"
    else
      # Not a /rename'd session — skip registry check (can't compare)
      continue
    fi

    test.case $level "registry matches session.name for $pane" \
      echo "registry='$REG_ROLE' session='$ACTUAL_ROLE'"

    if [ "$REG_ROLE" = "$ACTUAL_ROLE" ]; then
      expect.pass "registry $pane = $REG_ROLE (matches session.name)"
    else
      expect.fail "registry MISMATCH $pane: registry='$REG_ROLE' but session='$ACTUAL_ROLE'"
    fi
  done
fi

# ============================================================================
# IDENTITY ALIGNMENT TESTS — 4-layer chain integrity
# Layer 1: Pane → Registry Role (hivemind.roles.env)
# Layer 2: Role → Session UUID (hivemind.sessions.env)
# Layer 3: session.id output → actual process UUID (ps --resume args)
# Layer 4: Registry role name validity (not boot prompt garbage)
#
# These tests discover when the identity chain is broken. They don't
# need /status (slow, intrusive) — they compare what the system CLAIMS
# against what ps and the file system actually show.
# ============================================================================

REG_FILE="${HIVEMIND_REGISTRY:-${CONFIG_PATH:-$HOME/config}/hivemind.roles.env}"
SES_FILE="${HIVEMIND_SESSIONS:-${CONFIG_PATH:-$HOME/config}/hivemind.sessions.env}"

ALIGN_TESTED=0
ALIGN_PASSED=0
ALIGN_FAILED=0

# ── T-ALIGN-1: session.id matches --resume UUID from ps ──────────────────
# For every Claude pane that was started with --resume, the UUID in ps args
# is ground truth. session.id MUST return the same value.

for pane in $LIVE_PANES; do
  claude_pid=$(claudeCode process.find "$pane" 2>/dev/null || true)
  [ -z "$claude_pid" ] && continue

  # Get the --resume UUID from ps args (ground truth when available)
  resume_uuid=$(ps -p "$claude_pid" -o args= 2>/dev/null | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' || true)
  [ -z "$resume_uuid" ] && continue  # skip panes without --resume

  sid_result=$(claudeCode session.id "$pane" 2>/dev/null || true)

  test.case $level "session.id matches --resume UUID for $pane" \
    echo "sid=$sid_result resume=$resume_uuid"

  ALIGN_TESTED=$((ALIGN_TESTED + 1))
  if [ "$sid_result" = "$resume_uuid" ]; then
    expect.pass "session.id $pane = ${sid_result:0:8}... matches --resume"
    ALIGN_PASSED=$((ALIGN_PASSED + 1))
  else
    expect.fail "session.id STALE $pane: returns ${sid_result:0:8}... but --resume is ${resume_uuid:0:8}..."
    ALIGN_FAILED=$((ALIGN_FAILED + 1))
  fi
done

# ── T-ALIGN-2: Registry role names are valid (not boot prompt garbage) ────
# A valid role name matches an agent directory in .claude/agents/.
# Boot prompt text leaking into the registry is a known bug.

AGENTS_BASE="${CLAUDE_PROJECT_DIR:-/Users/Shared/Workspaces/AI/Claude}/.claude/agents"

if [ -f "$REG_FILE" ]; then
  while IFS='|' read -r pane_target role; do
    [ -z "$role" ] && continue

    test.case $level "registry role is valid agent name: $pane_target" \
      echo "role='$role'"

    ALIGN_TESTED=$((ALIGN_TESTED + 1))

    # Check 1: role name should be short (agent names are < 30 chars)
    if [ "${#role}" -gt 30 ]; then
      expect.fail "registry GARBAGE $pane_target: role is ${#role} chars — likely boot prompt text: '${role:0:40}...'"
      ALIGN_FAILED=$((ALIGN_FAILED + 1))
      continue
    fi

    # Check 2: role name should not contain spaces (agent names use hyphens)
    if echo "$role" | grep -q ' '; then
      expect.fail "registry GARBAGE $pane_target: role contains spaces: '$role'"
      ALIGN_FAILED=$((ALIGN_FAILED + 1))
      continue
    fi

    # Check 3: role directory should exist
    if [ -d "$AGENTS_BASE/$role" ]; then
      expect.pass "registry $pane_target = '$role' (agent dir exists)"
      ALIGN_PASSED=$((ALIGN_PASSED + 1))
    else
      expect.fail "registry ORPHAN $pane_target: role='$role' has no .claude/agents/$role/ directory"
      ALIGN_FAILED=$((ALIGN_FAILED + 1))
    fi
  done < "$REG_FILE"
fi

# ── T-ALIGN-3: No duplicate role→UUID in sessions file ───────────────────
# Each role should map to exactly one UUID. Duplicates mean stale entries.

if [ -f "$SES_FILE" ]; then
  DUP_ROLES=$(cut -d'|' -f1 "$SES_FILE" | sort | uniq -d)
  test.case $level "sessions file has no duplicate role entries" \
    echo "checking $SES_FILE"

  ALIGN_TESTED=$((ALIGN_TESTED + 1))
  if [ -z "$DUP_ROLES" ]; then
    expect.pass "no duplicate role entries in sessions file"
    ALIGN_PASSED=$((ALIGN_PASSED + 1))
  else
    expect.fail "duplicate roles in sessions file: $DUP_ROLES"
    ALIGN_FAILED=$((ALIGN_FAILED + 1))
  fi
fi

# ── T-ALIGN-4: Sessions file UUIDs exist in sessions-index.json ──────────
# Every UUID in the sessions file should be a real Claude Code session.

CLAUDE_PROJECTS_DIR="$HOME/.claude/projects"
if [ -f "$SES_FILE" ]; then
  while IFS='|' read -r role sid; do
    [ -z "$sid" ] && continue

    test.case $level "sessions UUID exists in Claude index: $role" \
      echo "sid=$sid"

    ALIGN_TESTED=$((ALIGN_TESTED + 1))

    # Search all sessions-index.json files
    found=0
    for index_file in "$CLAUDE_PROJECTS_DIR"/*/sessions-index.json; do
      [ -f "$index_file" ] || continue
      if jq -e --arg sid "$sid" '.entries[] | select(.sessionId == $sid)' "$index_file" >/dev/null 2>&1; then
        found=1
        break
      fi
    done

    if [ "$found" -eq 1 ]; then
      expect.pass "sessions file $role → ${sid:0:8}... found in Claude index"
      ALIGN_PASSED=$((ALIGN_PASSED + 1))
    else
      expect.fail "sessions file $role → ${sid:0:8}... NOT in any sessions-index.json (phantom UUID)"
      ALIGN_FAILED=$((ALIGN_FAILED + 1))
    fi
  done < "$SES_FILE"
fi

# ── T-ALIGN-5: Registry pane targets still exist in tmux ─────────────────
# Stale entries for dead sessions/panes should not persist.

if [ -f "$REG_FILE" ]; then
  while IFS='|' read -r pane_target role; do
    [ -z "$pane_target" ] && continue

    test.case $level "registry pane still exists: $pane_target" \
      echo "checking tmux pane"

    ALIGN_TESTED=$((ALIGN_TESTED + 1))

    if tmux display-message -t "$pane_target" -p "#{pane_id}" >/dev/null 2>&1; then
      expect.pass "registry $pane_target ($role) — pane exists"
      ALIGN_PASSED=$((ALIGN_PASSED + 1))
    else
      expect.fail "registry STALE $pane_target ($role) — pane no longer exists in tmux"
      ALIGN_FAILED=$((ALIGN_FAILED + 1))
    fi
  done < "$REG_FILE"
fi

# ── T-ALIGN-6: claudeCode.join writes UUID back to sessions file ─────────
# When a session is resumed via claudeCode join, the new UUID should be
# reflected in the sessions file. Check panes started with 'claudeCode join'.

for pane in $LIVE_PANES; do
  claude_pid=$(claudeCode process.find "$pane" 2>/dev/null || true)
  [ -z "$claude_pid" ] && continue

  # Check if this was started via 'claudeCode join <uuid>'
  full_cmd=$(ps -p "$claude_pid" -o args= 2>/dev/null)
  echo "$full_cmd" | grep -q 'claudeCode join' || continue

  resume_uuid=$(echo "$full_cmd" | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
  [ -z "$resume_uuid" ] && continue

  # Get registry role for this pane
  reg_role=$(grep "^${pane}|" "$REG_FILE" 2>/dev/null | cut -d'|' -f2)
  [ -z "$reg_role" ] && continue

  # Check if sessions file has THIS uuid for this role
  ses_uuid=$(grep "^${reg_role}|" "$SES_FILE" 2>/dev/null | tail -1 | cut -d'|' -f2)

  test.case $level "join UUID in sessions file for $pane ($reg_role)" \
    echo "resume=$resume_uuid sessions=$ses_uuid"

  ALIGN_TESTED=$((ALIGN_TESTED + 1))
  if [ "$ses_uuid" = "$resume_uuid" ]; then
    expect.pass "sessions file $reg_role → ${resume_uuid:0:8}... matches join UUID"
    ALIGN_PASSED=$((ALIGN_PASSED + 1))
  else
    expect.fail "sessions file STALE $reg_role: has ${ses_uuid:0:8}... but claudeCode join used ${resume_uuid:0:8}..."
    ALIGN_FAILED=$((ALIGN_FAILED + 1))
  fi
done

# ── T-ALIGN-7: session.id Method 0 vs Method 1 consistency ───────────────
# Method 0 (registry lookup) and Method 1 (ps args) should agree.
# If they disagree, Method 0 is returning stale data.

for pane in $LIVE_PANES; do
  claude_pid=$(claudeCode process.find "$pane" 2>/dev/null || true)
  [ -z "$claude_pid" ] && continue

  # Method 1: ps args UUID
  ps_uuid=$(ps -p "$claude_pid" -o args= 2>/dev/null | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
  [ -z "$ps_uuid" ] && continue  # can only compare if --resume was used

  # Method 0: registry → sessions file
  reg_role=$(grep "^${pane}|" "$REG_FILE" 2>/dev/null | cut -d'|' -f2)
  [ -z "$reg_role" ] && continue
  m0_uuid=$(grep "^${reg_role}|" "$SES_FILE" 2>/dev/null | tail -1 | cut -d'|' -f2)
  [ -z "$m0_uuid" ] && continue

  test.case $level "Method 0 vs Method 1 agree for $pane" \
    echo "M0=${m0_uuid:0:8} M1=${ps_uuid:0:8}"

  ALIGN_TESTED=$((ALIGN_TESTED + 1))
  if [ "$m0_uuid" = "$ps_uuid" ]; then
    expect.pass "Methods agree for $pane: ${ps_uuid:0:8}..."
    ALIGN_PASSED=$((ALIGN_PASSED + 1))
  else
    expect.fail "Method CONFLICT $pane: M0(registry)=${m0_uuid:0:8}... M1(ps)=${ps_uuid:0:8}... — M0 is stale"
    ALIGN_FAILED=$((ALIGN_FAILED + 1))
  fi
done

echo ""
echo "  identity alignment summary: $ALIGN_TESTED tested, $ALIGN_PASSED passed, $ALIGN_FAILED failed"
echo ""

# ── T-ALIGN-8: No duplicate UUIDs across different panes ────────────────
# Two different panes should NEVER share the same session.id.
# Bug 6: projectTeam:1.2, 1.3, 1.4 all returned 5fff44f4 — stale mapping.
# Shows tmux session start date per pane so you can distinguish:
#   - Same agent --resumed in a newer session (benign if old pane is dead)
#   - Stale session.id returning cached UUID for a different/dead pane (bug)

echo ""
echo "=== T-ALIGN-8: Duplicate UUID detection across panes ==="
echo ""

DUP_TESTED=0
DUP_PASSED=0
DUP_FAILED=0

# Pre-collect session creation dates
declare -A SESS_DATES
for sess_info in $(tmux list-sessions -F "#{session_name}|#{session_created}" 2>/dev/null); do
  s_name="${sess_info%%|*}"
  s_epoch="${sess_info##*|}"
  s_date=$(date -r "$s_epoch" "+%b %-d" 2>/dev/null || date -d "@$s_epoch" "+%b %-d" 2>/dev/null || echo "?")
  SESS_DATES[$s_name]="$s_date"
done

# Collect all pane→UUID mappings with metadata
declare -A UUID_MAP      # uuid → first pane that had it
declare -A UUID_HAS_PID  # uuid → 1 if first pane has a live Claude PID
DUP_REPORT=""
DUP_COUNT=0

for sess in $(tmux list-sessions -F "#{session_name}" 2>/dev/null); do
  sess_date="${SESS_DATES[$sess]:-?}"
  for pane in $(tmux list-panes -t "$sess" -s -F "#{session_name}:#{window_index}.#{pane_index}" 2>/dev/null); do
    sid=$(claudeCode session.id "$pane" 2>/dev/null || true)
    [ -z "$sid" ] && continue

    short="${sid:0:8}"
    # Check if this pane has a live Claude process
    has_pid=0
    claude_pid=$(claudeCode process.find "$pane" 2>/dev/null || true)
    [ -n "$claude_pid" ] && has_pid=1

    if [ -n "${UUID_MAP[$sid]+x}" ]; then
      # Duplicate found — get the first pane's info
      first_pane="${UUID_MAP[$sid]}"
      first_sess="${first_pane%%:*}"
      first_date="${SESS_DATES[$first_sess]:-?}"
      first_has_pid="${UUID_HAS_PID[$sid]:-0}"

      # Determine severity
      severity="STALE"
      if [ "$has_pid" -eq 1 ] && [ "$first_has_pid" -eq 1 ]; then
        severity="CONFLICT"  # both panes have live Claude — real problem
      elif [ "$has_pid" -eq 1 ] || [ "$first_has_pid" -eq 1 ]; then
        severity="STALE"     # one is live, one is dead — stale mapping
      else
        severity="GHOST"     # neither has Claude — both are stale
      fi

      pid_label_1=""
      pid_label_2=""
      [ "$first_has_pid" -eq 1 ] && pid_label_1=" (LIVE)"
      [ "$has_pid" -eq 1 ] && pid_label_2=" (LIVE)"

      DUP_REPORT="${DUP_REPORT}  ${severity}: ${short} shared by:\n"
      DUP_REPORT="${DUP_REPORT}    ${first_pane} (${first_date})${pid_label_1}\n"
      DUP_REPORT="${DUP_REPORT}    ${pane} (${sess_date})${pid_label_2}\n"
      DUP_COUNT=$((DUP_COUNT + 1))
    else
      UUID_MAP[$sid]="$pane"
      UUID_HAS_PID[$sid]="$has_pid"
    fi
  done
done

UNIQUE_COUNT=${#UUID_MAP[@]}
test.case $level "no duplicate session.id UUIDs across panes ($UNIQUE_COUNT unique, $DUP_COUNT duplicates)" \
  echo "scanning all panes"

DUP_TESTED=1
if [ "$DUP_COUNT" -eq 0 ]; then
  expect.pass "all $UNIQUE_COUNT session.id UUIDs are unique across panes"
  DUP_PASSED=1
else
  expect.fail "$DUP_COUNT duplicate UUID(s) found:"
  echo -e "$DUP_REPORT"
  DUP_FAILED=1
fi

ALIGN_TESTED=$((ALIGN_TESTED + DUP_TESTED))
ALIGN_PASSED=$((ALIGN_PASSED + DUP_PASSED))
ALIGN_FAILED=$((ALIGN_FAILED + DUP_FAILED))

echo ""
echo "  duplicate UUID summary: $DUP_TESTED tested, $DUP_PASSED passed, $DUP_FAILED failed"
echo ""

# ============================================================================
# OOSH ARCHITECTURE COMPLIANCE TESTS
# Detect flag-style arguments and raw system commands in method interfaces.
# These violations break OOSH conventions: positional args only, use wrappers.
# ============================================================================

# ── T-ARCH-1: No --flag patterns in method signatures ──────────────────────
# OOSH methods use positional args: script.method arg1 arg2
# Never: script.method --flag value
test.case $level "no --flag patterns in claudeCode method signatures" \
  echo "scanning method signatures"

# Method signatures are the comment after () — e.g., method() # <arg1> <?arg2>
FLAG_SIGS=$(grep -nE '^\w+\.\w+\(\)\s*#.*<\?--' "$OOSH_DIR/claudeCode" || true)
if [ -z "$FLAG_SIGS" ]; then
  expect.pass "no --flag patterns in method signatures"
else
  expect.fail "flag-style args in method signatures (OOSH violation):"
  echo "$FLAG_SIGS"
fi

# ── T-ARCH-2: No --flag case parsing in method bodies ──────────────────────
# Methods should not use case/getopt to parse --flags.
# Acceptable: passing --flags to external commands (claude --resume, git --quiet)
# Violation: parsing --flags as method arguments (case "$arg" in --model))
test.case $level "no --flag case parsing in claudeCode methods" \
  echo "scanning for flag-style case parsing"

# Look for case patterns that match --something) inside method bodies
# Exclude: comments, external command flags (--resume, --version, etc.)
FLAG_CASE=$(grep -nE '^\s+--[a-z]+\)' "$OOSH_DIR/claudeCode" || true)
if [ -z "$FLAG_CASE" ]; then
  expect.pass "no --flag case parsing in method bodies"
else
  expect.fail "flag-style case parsing found (OOSH violation — use positional args):"
  echo "$FLAG_CASE"
fi

# ── T-ARCH-3: Raw stat not used outside private.claudeCode.jsonl.age ───────
# private.claudeCode.jsonl.age wraps stat. Other methods should use the wrapper.
test.case $level "raw stat calls only in private.claudeCode.jsonl.age" \
  echo "scanning for raw stat usage"

# Count stat calls outside the jsonl.age function
# jsonl.age is lines ~54-62; any stat outside that function is a violation
STAT_OUTSIDE=$(awk '
  /^private\.claudeCode\.jsonl\.age\(\)/ { in_func=1; next }
  in_func && /^[^ \t]/ { in_func=0 }
  !in_func && /stat -[fc] %[mY]/ { print NR": "$0 }
' "$OOSH_DIR/claudeCode")

if [ -z "$STAT_OUTSIDE" ]; then
  expect.pass "all stat calls use private.claudeCode.jsonl.age wrapper"
else
  expect.fail "raw stat calls found outside jsonl.age wrapper (DRY violation):"
  echo "$STAT_OUTSIDE"
fi

# ── T-ARCH-4: JSONL find pattern not duplicated ───────────────────────────
# find ... -name "*.jsonl" should be in one helper, not repeated
test.case $level "JSONL find pattern not duplicated" \
  echo "scanning for repeated find patterns"

JSONL_FINDS=$(grep -c 'find.*-name.*\.jsonl' "$OOSH_DIR/claudeCode" || echo "0")
if [ "$JSONL_FINDS" -le 1 ]; then
  expect.pass "JSONL find pattern used at most once (or in a helper)"
else
  expect.fail "JSONL find pattern appears $JSONL_FINDS times (DRY violation — extract to helper)"
fi

# ── T-ARCH-5: hiveMind teams.restore uses positional args (not --fork) ─────
test.case $level "hiveMind teams.restore uses positional mode arg" \
  echo "checking teams.restore signature"

RESTORE_SIG=$(grep -E 'hiveMind\.teams\.restore\(\)' "$OOSH_DIR/hiveMind" | head -1)
if echo "$RESTORE_SIG" | grep -q '\-\-fork'; then
  expect.fail "teams.restore still uses --fork flag: $RESTORE_SIG"
else
  expect.pass "teams.restore uses positional args (no --fork flag)"
fi

# ── T-ARCH-6: otmux ghost detection uses proper private method ─────────────
test.case $level "otmux ghost detection uses private method" \
  echo "checking ghost detection pattern"

if grep -q 'private\.otmux\.pane\.isGhost' "$OOSH_DIR/otmux"; then
  expect.pass "ghost detection uses private.otmux.pane.isGhost method"
else
  expect.fail "ghost detection should use private.otmux.pane.isGhost, not inline logic"
fi

echo ""
echo "  architecture compliance tests complete"
echo ""

# ============================================================================
# Test Summary
# ============================================================================

test.suite.save.results
