#!/usr/bin/env bash
# session-class.sh — the single definition of "a human at a TTY" vs "an agent runtime".
#
# Sourced by bin/_agent-unsafe.sh (which refuses agents) and bin/_human-session (which
# grants agents nothing and humans the protected slice). Both must agree, so the marker
# list lives here once.
#
# Ambiguity resolves to AGENT. A human misclassified as an agent gets today's confinement;
# an agent misclassified as a human gets an uncapped slice, which is how a fork bomb would
# reach the desktop.

# Env markers that prove a non-human caller. Every name here was READ from a live agent
# process on this machine (claude, codex and cursor-agent all carry
# AGENT_BUILD_SCOPE_ACTIVE and AI_AGENT); a human's interactive bash carries none.
SESSION_AGENT_MARKERS=(
  AGENT_BUILD_SCOPE_ACTIVE
  AI_AGENT
  CLAUDECODE
  CLAUDE_CODE_ENTRYPOINT
  CLAUDE_CODE_SESSION_ID
  CLAUDE_CODE_EXECPATH
  CLAUDE_CODE_CHILD_SESSION
  TMPJAIL_ACTIVE
  CONFINE_ACTIVE
)

session_agent_marker() { # prints the first marker that is set; 1 when none is
  local m
  for m in "${SESSION_AGENT_MARKERS[@]}"; do
    [[ -n "${!m:-}" ]] && { printf '%s' "$m"; return 0; }
  done
  return 1
}

session_container_signal() { # prints the signal; 1 when not in a container
  [[ -e /run/.containerenv ]] && { printf 'file:/run/.containerenv'; return 0; }
  [[ -e /.dockerenv ]] && { printf 'file:/.dockerenv'; return 0; }
  [[ -n "${container:-}" ]] && { printf 'env:container=%s' "$container"; return 0; }
  if [[ -r /proc/self/cgroup ]] &&
    grep -qEi '(libpod|docker|containerd|/machine\.slice/|kubepods)' /proc/self/cgroup; then
    printf 'cgroup:/proc/self/cgroup'
    return 0
  fi
  return 1
}

session_is_human() { # 0 when a human is at a terminal; 1 otherwise, reason on stdout
  local detail
  if detail="$(session_agent_marker)"; then
    printf 'agent-env-marker:%s' "$detail"
    return 1
  fi
  if detail="$(session_container_signal)"; then
    printf 'in-container:%s' "$detail"
    return 1
  fi
  # A process shelling out has no controlling terminal; a human typing this does.
  if [[ ! -t 0 || ! -t 1 ]]; then
    printf 'no-tty'
    return 1
  fi
  return 0
}
