#!/usr/bin/env bash
# Concurrency cap for agent sessions: at most AGENT_SESSION_SLOTS run at once, and a
# launch above the cap waits in the buildslot FIFO until one exits. Nothing is ever
# signalled and no memory threshold is consulted.
#
# The pool is buildslot's, but a dedicated lock directory: a session holds its slot for
# its whole life, so sharing the build pool would leave the machine's builds queued
# behind long-lived agents. BUILD_SLOT_ISOLATED keeps the session's slot and pool
# selection out of the environment the session runs with, so builds inside it still
# face the build gate normally.
#
# A session launched inside another session's process tree inherits that session's slot
# (buildslot's ancestor check reads the on-disk stamp), so a nested runtime or a hook
# shelling out to one is admitted immediately and can never wait on its own ancestor.
set -euo pipefail

if (( $# == 0 )); then
  printf '_agent-session-admission: command required\n' >&2
  exit 64
fi

BIN_DIR="$(cd "$(dirname "$(readlink -f -- "${BASH_SOURCE[0]}")")" && pwd)"

slots=${AGENT_SESSION_SLOTS:-4}
if ! [[ "$slots" =~ ^[1-9][0-9]*$ ]]; then
  printf '_agent-session-admission: AGENT_SESSION_SLOTS must be a positive integer: %s\n' "$slots" >&2
  exit 64
fi

export BUILD_SLOT_ISOLATED=1
export BUILD_SLOTS="$slots"
export BUILD_SLOT_DIR="${AGENT_SESSION_SLOT_DIR:-/run/user/$UID/agent-session-slots}"
# The cap is a count of sessions, not a load reading: sessions are not niced, so
# adaptive slots would read the running sessions as demand and collapse the cap to
# the floor exactly when the queue is longest.
export BUILD_SLOT_FIXED=1
export BUILD_SLOT_FLOOR=1
# Admit or queue: a timeout would turn a capped launch into a failed one, and an
# inherited status file belongs to the build job that opened it.
unset BUILD_SLOT_TIMEOUT BUILD_SLOT_STATUS
# An interactive session must not be reparented under the build job supervisor.
unset BUILD_SUPERVISOR_AFTER_ADMISSION

exec "$BIN_DIR/../lib/buildslot.sh" "$BIN_DIR/_agent-build-scope" "$@"
