#!/usr/bin/env bash

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BACKEND_DIR="${ROOT_DIR}/backend"
HOST_DIR="${ROOT_DIR}/host-service"
STACKS_DIR="${OYSTERUN_STACKS_DIR:-${HOME}/.oysterun-stacks}"
HOME_CONFIG_DIR="${HOME}/.oysterun"
PRODUCTION_STACK_NAME="production"
STAGING_STACK_NAME="staging"
STACK_NAME="${OYSTERUN_STACK:-${PRODUCTION_STACK_NAME}}"
STACK_KIND=""
STACK_ROOT=""
CONFIG_DIR=""
CONFIG_PATH=""
RUN_DIR=""
LOG_DIR=""
BACKEND_PID_FILE=""
HOST_PID_FILE=""
BACKEND_LOG=""
HOST_LOG=""
SERVICE_CONTROL_AUDIT_FILE=""
BACKEND_LABEL=""
HOST_LABEL=""
HOST_ORIGIN_FILE=""
BACKEND_BIND_HOST=""
BACKEND_PORT=""
BACKEND_INTERNAL_URL=""
BACKEND_PUBLIC_BASE_URL=""
BACKEND_DB_PATH=""
BACKEND_DB_URL=""
HOST_PORT_OVERRIDE=""
BACKEND_PORT_OVERRIDE=""
HOST_PORT=""
HOST_URL=""
STACK_READINESS_FILE=""
ROUTEC_STACK_READINESS_SCRIPT="${ROOT_DIR}/tool_scripts/routec_stack_readiness.mjs"
ROUTEC_RUNTIME_ENV_FILE=""
ROUTEC_RUNTIME_ENV_JSON_FILE=""
ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR=""
ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_FILE=""
ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_FILE=""
STACK_DASHBOARD_CREDENTIALS_PROOF_FILE=""
ROUTEC_WEB_CHAT_DIR="${ROOT_DIR}/dev/client/web-chat"
ROUTEC_WEB_CHAT_DIST_INDEX="${ROOT_DIR}/dev/client/web-chat/dist/index.html"
ROUTEC_WEB_CHAT_PREBUILT_MARKER="${ROOT_DIR}/dev/client/web-chat/oysterun-release-prebuilt.marker"
DASHBOARD_WEB_DIR="${ROOT_DIR}/dev/client/web"
DASHBOARD_WEB_INDEX="${ROOT_DIR}/dev/client/web/index.html"
DASHBOARD_WEB_PREBUILT_MARKER="${ROOT_DIR}/dev/client/web/oysterun-release-prebuilt.marker"
STACK_DASHBOARD_CREDENTIALS_SCRIPT="${ROOT_DIR}/tool_scripts/stack_dashboard_credentials.mjs"
HOST_TRANSCRIPTS_DB_PATH=""
MATRIX_DB_PATH=""
SYNAPSE_CONFIG_PATH=""
ROUTEC_HOST_ENV_ALLOWLIST=(
  OYSTERUN_UPDATE_REGISTRY_URL
  OYSTERUN_UPDATE_REGISTRY_STATE_PATH
  OYSTERUN_ROUTEC_ARTIFACT_ROOT
  OYSTERUN_ROUTEC_REQUEST_TRAFFIC_LOG_PATH
  OYSTERUN_ENABLE_TEST_FIXTURE_UI
  OYSTERUN_DEBUG_ROUTEC_STRUCTURAL_REPLAY_MANIFEST_PATH
  OYSTERUN_DEBUG_ROUTEC_STRUCTURAL_REPLAY_BATCH_DELAY_MS
)

PRODUCTION_HOST_PORT="8802"
STAGING_HOST_PORT="9902"
TEST1_HOST_PORT="3022"
TEST2_HOST_PORT="3302"
TEST3_HOST_PORT="4022"
TEST4_HOST_PORT="4402"
LEGACY_RUN_DIR="${HOME_CONFIG_DIR}/run"
LEGACY_BACKEND_LABEL="com.oysterun.backend"
LEGACY_HOST_LABEL="com.oysterun.host"
LEGACY_HOST_PORT_LABEL="com.oysterun.host.8802"
LEGACY_BACKEND_PID_FILE="${LEGACY_RUN_DIR}/oysterun-backend.pid"
LEGACY_HOST_PID_FILE="${LEGACY_RUN_DIR}/oysterun-host.pid"
LEGACY_HOST_PORT_PID_FILE="${LEGACY_RUN_DIR}/oysterun-host-8802.pid"

is_macos() {
  [[ "$(uname -s)" == "Darwin" ]]
}

is_linux() {
  [[ "$(uname -s)" == "Linux" ]]
}

json_escape_string() {
  local value="$1"
  value="${value//\\/\\\\}"
  value="${value//\"/\\\"}"
  value="${value//$'\n'/\\n}"
  value="${value//$'\r'/\\r}"
  value="${value//$'\t'/\\t}"
  printf '%s' "${value}"
}

append_service_control_audit() {
  local action="$1"
  local outcome="${2:-attempt}"
  local detail="${3:-}"
  local audit_file="${SERVICE_CONTROL_AUDIT_FILE:-}"
  local audit_dir=""
  local recorded_at=""
  local cwd=""
  local command_line=""
  local parent_command=""
  local launch_pid=""

  if [[ -z "${audit_file}" ]]; then
    return 0
  fi

  audit_dir="$(dirname "${audit_file}")"
  mkdir -p "${audit_dir}" 2>/dev/null || return 0

  recorded_at="$(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date)"
  cwd="$(pwd -P 2>/dev/null || pwd 2>/dev/null || true)"
  command_line="$(ps -p "$$" -o command= 2>/dev/null | sed 's/^[[:space:]]*//' || true)"
  parent_command="$(ps -p "${PPID:-}" -o command= 2>/dev/null | sed 's/^[[:space:]]*//' || true)"
  if is_macos && [[ -n "${HOST_LABEL:-}" ]]; then
    launch_pid="$(launchctl_pid_for_label "${HOST_LABEL}" 2>/dev/null || true)"
  fi

  printf '{"recorded_at":"%s","action":"%s","outcome":"%s","detail":"%s","operation_id":"%s","stack_name":"%s","host_label":"%s","host_port":"%s","host_url":"%s","config_dir":"%s","run_dir":"%s","log_dir":"%s","host_log":"%s","home":"%s","cwd":"%s","script":"%s","pid":"%s","ppid":"%s","parent_command":"%s","command_line":"%s","launch_pid":"%s"}\n' \
    "$(json_escape_string "${recorded_at}")" \
    "$(json_escape_string "${action}")" \
    "$(json_escape_string "${outcome}")" \
    "$(json_escape_string "${detail}")" \
    "$(json_escape_string "${OYSTERUN_LIFECYCLE_OPERATION_ID:-}")" \
    "$(json_escape_string "${STACK_NAME:-}")" \
    "$(json_escape_string "${HOST_LABEL:-}")" \
    "$(json_escape_string "${HOST_PORT:-}")" \
    "$(json_escape_string "${HOST_URL:-}")" \
    "$(json_escape_string "${CONFIG_DIR:-}")" \
    "$(json_escape_string "${RUN_DIR:-}")" \
    "$(json_escape_string "${LOG_DIR:-}")" \
    "$(json_escape_string "${HOST_LOG:-}")" \
    "$(json_escape_string "${HOME:-}")" \
    "$(json_escape_string "${cwd}")" \
    "$(json_escape_string "${0:-}")" \
    "$(json_escape_string "$$")" \
    "$(json_escape_string "${PPID:-}")" \
    "$(json_escape_string "${parent_command}")" \
    "$(json_escape_string "${command_line}")" \
    "$(json_escape_string "${launch_pid}")" \
    >> "${audit_file}" 2>/dev/null || true
}

prepare_host_log_for_service_start() {
  local log_file="$1"
  local label="${2:-Host service}"
  local rotated_log=""
  local timestamp=""

  mkdir -p "$(dirname "${log_file}")"
  if [[ -s "${log_file}" ]]; then
    timestamp="$(date -u +"%Y%m%dT%H%M%SZ" 2>/dev/null || date +%s)"
    rotated_log="${log_file}.${timestamp}"
    local suffix=0
    while [[ -e "${rotated_log}" ]]; do
      suffix=$((suffix + 1))
      rotated_log="${log_file}.${timestamp}.${suffix}"
    done
    mv "${log_file}" "${rotated_log}"
    append_service_control_audit "host_log_rotate" "done" "label=${label};rotated_log=${rotated_log}"
    {
      echo "[oysterun-service] Previous ${label} log preserved at ${rotated_log}"
      echo "[oysterun-service] New ${label} log started at $(date -u +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date)"
    } > "${log_file}"
  else
    : > "${log_file}"
    append_service_control_audit "host_log_prepare" "done" "label=${label};created_or_empty=${log_file}"
  fi
}

parse_common_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      --stack|-stack|-s)
        if [[ $# -lt 2 ]]; then
          echo "[oysterun-service] error: --stack requires a value" >&2
          exit 1
        fi
        STACK_NAME="$2"
        shift 2
        ;;
      --stack_name|-stack_name)
        if [[ $# -lt 2 ]]; then
          echo "[oysterun-service] error: --stack_name requires a value" >&2
          exit 1
        fi
        STACK_NAME="$2"
        shift 2
        ;;
      --port|-port|-p)
        if [[ $# -lt 2 ]]; then
          echo "[oysterun-service] error: --port requires a value" >&2
          exit 1
        fi
        HOST_PORT_OVERRIDE="$2"
        shift 2
        ;;
      --backend_port|-backend_port)
        if [[ $# -lt 2 ]]; then
          echo "[oysterun-service] error: --backend_port requires a value" >&2
          exit 1
        fi
        BACKEND_PORT_OVERRIDE="$2"
        shift 2
        ;;
      *)
        echo "[oysterun-service] error: unknown argument: $1" >&2
        exit 1
        ;;
    esac
  done
}

is_predefined_stack() {
  case "$1" in
    production|staging|test1|test2|test3|test4)
      return 0
      ;;
    *)
      return 1
      ;;
  esac
}

is_reserved_custom_stack_name() {
  case "$1" in
    production|staging|test1|test2|test3|test4|local|phone|daily|shared)
      return 0
      ;;
    *)
      return 1
      ;;
  esac
}

validate_stack_name_format() {
  [[ "$1" =~ ^[a-z0-9][a-z0-9_-]*$ ]]
}

validate_port_value() {
  local raw_port="$1"
  if ! [[ "${raw_port}" =~ ^[0-9]+$ ]]; then
    return 1
  fi
  if (( raw_port < 1 || raw_port > 65535 )); then
    return 1
  fi
  return 0
}

validate_stack() {
  if is_predefined_stack "${STACK_NAME}"; then
    STACK_KIND="preset"
    return
  fi

  if ! validate_stack_name_format "${STACK_NAME}"; then
    echo "[oysterun-service] error: invalid stack name: ${STACK_NAME}" >&2
    echo "[oysterun-service] error: stack names must match ^[a-z0-9][a-z0-9_-]*$" >&2
    exit 1
  fi

  if is_reserved_custom_stack_name "${STACK_NAME}"; then
    echo "[oysterun-service] error: reserved stack name: ${STACK_NAME}" >&2
    echo "[oysterun-service] error: reserved names are: production, staging, test1, test2, test3, test4, local, phone, daily, shared" >&2
    exit 1
  fi

  STACK_KIND="custom"
}

quarantine_legacy_routec_runtime_env_files_if_present() {
  local node_bin="$1"
  local timestamp
  local entries_path
  local legacy_path
  local target_path
  local legacy_hash

  if [[ -z "${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR}" || -z "${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_FILE}" ]]; then
    echo "[oysterun-service] error: legacy Route C runtime-env quarantine path is not configured" >&2
    return 1
  fi

  timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
  mkdir -p "${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR}" "${RUN_DIR}"
  entries_path="${RUN_DIR}/legacy-routec-runtime-env-quarantine.entries.${timestamp}.$$"
  : > "${entries_path}"

  for legacy_path in "${ROUTEC_RUNTIME_ENV_FILE}" "${ROUTEC_RUNTIME_ENV_JSON_FILE}"; do
    if [[ -f "${legacy_path}" ]]; then
      legacy_hash="$(shasum -a 256 "${legacy_path}" | awk '{print $1}')"
      target_path="${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR}/${timestamp}-$$-$(basename "${legacy_path}")"
      mv "${legacy_path}" "${target_path}"
      chmod 0600 "${target_path}" 2>/dev/null || true
      printf '%s\t%s\t%s\n' "${legacy_path}" "${target_path}" "${legacy_hash}" >> "${entries_path}"
      echo "[oysterun-service] Quarantined legacy Route C runtime env $(basename "${legacy_path}")"
    fi
  done

  ROUTEC_LEGACY_RUNTIME_ENV_ENTRIES_PATH="${entries_path}" \
  ROUTEC_LEGACY_RUNTIME_ENV_PROOF_PATH="${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_FILE}" \
  ROUTEC_LEGACY_RUNTIME_ENV_SH_PATH="${ROUTEC_RUNTIME_ENV_FILE}" \
  ROUTEC_LEGACY_RUNTIME_ENV_JSON_PATH="${ROUTEC_RUNTIME_ENV_JSON_FILE}" \
  ROUTEC_LEGACY_RUNTIME_ENV_STACK_NAME="${STACK_NAME}" \
  ROUTEC_LEGACY_RUNTIME_ENV_STACK_ROOT="${STACK_ROOT}" \
  "${node_bin}" --input-type=module <<'NODE'
import { readFileSync, writeFileSync } from "node:fs";

const entriesPath = process.env.ROUTEC_LEGACY_RUNTIME_ENV_ENTRIES_PATH;
const rows = readFileSync(entriesPath, "utf8")
  .split("\n")
  .filter(Boolean)
  .map((line) => {
    const [legacy_path, quarantined_path, sha256] = line.split("\t");
    return { legacy_path, quarantined_path, sha256 };
  });

const proof = {
  schema_version: "routec.legacy_runtime_env_quarantine.v1",
  generated_at: new Date().toISOString(),
  stack_name: process.env.ROUTEC_LEGACY_RUNTIME_ENV_STACK_NAME,
  stack_root: process.env.ROUTEC_LEGACY_RUNTIME_ENV_STACK_ROOT,
  action: rows.length ? "quarantined_legacy_runtime_env_files" : "no_legacy_runtime_env_files_present",
  legacy_runtime_env_live_truth: false,
  raw_synapse_base_url_as_stack_truth: false,
  raw_synapse_token_as_stack_truth: false,
  fixed_matrix_room_user_as_stack_truth: false,
  legacy_paths_checked: [
    process.env.ROUTEC_LEGACY_RUNTIME_ENV_SH_PATH,
    process.env.ROUTEC_LEGACY_RUNTIME_ENV_JSON_PATH,
  ],
  quarantined_files: rows,
};

writeFileSync(process.env.ROUTEC_LEGACY_RUNTIME_ENV_PROOF_PATH, `${JSON.stringify(proof, null, 2)}\n`);
NODE
  rm -f "${entries_path}"
}

legacy_routec_spike0_synapse_pids() {
  ps -axo pid=,command= | awk '
    /synapse_homeserver/ && /artifacts\/spike0/ && /routec_spike0/ {
      print $1
    }
  '
}

cleanup_legacy_routec_spike0_synapse_processes_if_present() {
  local node_bin="$1"
  local timestamp
  local pids_path
  local pid
  local cleanup_status="clean"

  if [[ -z "${ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_FILE}" ]]; then
    echo "[oysterun-service] error: legacy Route C spike0 Synapse cleanup proof path is not configured" >&2
    return 1
  fi

  timestamp="$(date -u +%Y%m%dT%H%M%SZ)"
  mkdir -p "${RUN_DIR}"
  pids_path="${RUN_DIR}/legacy-routec-spike0-synapse-pids.${timestamp}.$$"
  legacy_routec_spike0_synapse_pids > "${pids_path}"

  while IFS= read -r pid; do
    if [[ -z "${pid}" ]]; then
      continue
    fi
    echo "[oysterun-service] Cleaning up legacy Route C spike0 Synapse PID ${pid}"
    append_service_control_audit "process_signal" "attempt" "signal=TERM;reason=legacy_routec_spike0_synapse_cleanup;pid=${pid}"
    kill "${pid}" 2>/dev/null || true
    append_service_control_audit "process_signal" "done" "signal=TERM;reason=legacy_routec_spike0_synapse_cleanup;pid=${pid}"
    if ! wait_for_exit "${pid}"; then
      append_service_control_audit "process_signal" "attempt" "signal=KILL;reason=legacy_routec_spike0_synapse_cleanup;pid=${pid}"
      kill -9 "${pid}" 2>/dev/null || true
      append_service_control_audit "process_signal" "done" "signal=KILL;reason=legacy_routec_spike0_synapse_cleanup;pid=${pid}"
      wait_for_exit "${pid}" || true
    fi
    if pid_is_running "${pid}"; then
      cleanup_status="blocked"
    fi
  done < "${pids_path}"

  ROUTEC_LEGACY_SPIKE0_SYNAPSE_PIDS_PATH="${pids_path}" \
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_PATH="${ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_FILE}" \
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_STATUS="${cleanup_status}" \
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_STACK_NAME="${STACK_NAME}" \
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_STACK_ROOT="${STACK_ROOT}" \
  "${node_bin}" --input-type=module <<'NODE'
import { readFileSync, writeFileSync } from "node:fs";

const pids = readFileSync(process.env.ROUTEC_LEGACY_SPIKE0_SYNAPSE_PIDS_PATH, "utf8")
  .split("\n")
  .map((line) => line.trim())
  .filter(Boolean);

const proof = {
  schema_version: "routec.legacy_spike0_synapse_cleanup.v1",
  generated_at: new Date().toISOString(),
  stack_name: process.env.ROUTEC_LEGACY_SPIKE0_SYNAPSE_STACK_NAME,
  stack_root: process.env.ROUTEC_LEGACY_SPIKE0_SYNAPSE_STACK_ROOT,
  action: pids.length ? "cleaned_known_legacy_routec_spike0_synapse_processes" : "no_known_legacy_routec_spike0_synapse_processes_present",
  cleanup_status: process.env.ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_STATUS,
  known_legacy_match: {
    command_contains: ["synapse_homeserver", "artifacts/spike0", "routec_spike0"],
    arbitrary_process_cleanup_allowed: false,
  },
  pids_seen: pids,
  manual_synapse_stop_required_for_accepted_path: false,
};

writeFileSync(process.env.ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_PATH, `${JSON.stringify(proof, null, 2)}\n`);
NODE
  rm -f "${pids_path}"

  if [[ "${cleanup_status}" != "clean" ]]; then
    echo "[oysterun-service] error: failed to clean known legacy Route C spike0 Synapse process" >&2
    return 1
  fi
}

collect_routec_host_env_args() {
  local key

  ROUTEC_HOST_ENV_ARGS=(
    "OYSTERUN_ROUTEC_MATRIX_STORAGE_PATH=${MATRIX_DB_PATH}"
    "OYSTERUN_ROUTEC_STACK_ROOT=${STACK_ROOT}"
    "OYSTERUN_ROUTEC_STACK_NAME=${STACK_NAME}"
  )
  for key in "${ROUTEC_HOST_ENV_ALLOWLIST[@]}"; do
    if [[ -n "${!key:-}" ]]; then
      ROUTEC_HOST_ENV_ARGS+=("${key}=${!key}")
    fi
  done
}

read_port_from_config_file() {
  local config_path="$1"
  local port
  if [[ ! -f "${config_path}" ]]; then
    return 1
  fi

  port="$(sed -n 's/^[[:space:]]*"port":[[:space:]]*\([0-9][0-9]*\).*/\1/p' "${config_path}" | head -n 1)"
  if [[ -z "${port}" ]]; then
    return 1
  fi
  printf '%s\n' "${port}"
}

read_port_from_origin_file() {
  local origin_path="$1"
  local port
  if [[ ! -f "${origin_path}" ]]; then
    return 1
  fi

  port="$(awk -F $'\t' '$1 == "host_port" { print $2; exit }' "${origin_path}")"
  if [[ -z "${port}" ]]; then
    return 1
  fi
  printf '%s\n' "${port}"
}

resolve_custom_stack_host_port() {
  local derived_port=""

  if [[ -n "${HOST_PORT_OVERRIDE}" ]]; then
    if ! validate_port_value "${HOST_PORT_OVERRIDE}"; then
      echo "[oysterun-service] error: invalid --port value: ${HOST_PORT_OVERRIDE}" >&2
      exit 1
    fi
    derived_port="${HOST_PORT_OVERRIDE}"
  elif derived_port="$(read_port_from_origin_file "${HOST_ORIGIN_FILE}")"; then
    :
  elif derived_port="$(read_port_from_config_file "${CONFIG_PATH}")"; then
    :
  else
    derived_port=""
  fi

  printf '%s' "${derived_port}"
}

require_host_port_configured() {
  if [[ -n "${HOST_PORT}" ]]; then
    return
  fi

  echo "[oysterun-service] error: stack ${STACK_NAME} requires --port for startup" >&2
  exit 1
}

configure_stack_runtime() {
  validate_stack

  if [[ "${STACK_KIND}" == "preset" && -n "${HOST_PORT_OVERRIDE}" ]]; then
    echo "[oysterun-service] error: --port is only supported for custom stacks" >&2
    exit 1
  fi
  if [[ "${STACK_KIND}" == "preset" && -n "${BACKEND_PORT_OVERRIDE}" ]]; then
    echo "[oysterun-service] error: --backend_port is only supported for custom stacks" >&2
    exit 1
  fi

  BACKEND_DB_PATH="${STACKS_DIR}/shared/backend/oysterun.db"
  BACKEND_DB_URL="sqlite+aiosqlite:///${BACKEND_DB_PATH}"

  case "${STACK_NAME}" in
    production)
      STACK_ROOT="${HOME_CONFIG_DIR}"
      CONFIG_DIR="${STACK_ROOT}"
      CONFIG_PATH="${CONFIG_DIR}/config.json"
      RUN_DIR="${STACK_ROOT}/run"
      LOG_DIR="${STACK_ROOT}/logs"
      BACKEND_PID_FILE="${RUN_DIR}/oysterun-backend.pid"
      HOST_PID_FILE="${RUN_DIR}/oysterun-host.pid"
      BACKEND_LOG="${LOG_DIR}/oysterun-backend.log"
      HOST_LOG="${LOG_DIR}/oysterun-host.log"
      BACKEND_LABEL="${LEGACY_BACKEND_LABEL}"
      HOST_LABEL="${LEGACY_HOST_LABEL}"
      HOST_ORIGIN_FILE="${RUN_DIR}/oysterun-host.origin.tsv"
      BACKEND_BIND_HOST="127.0.0.1"
      BACKEND_PORT="8000"
      BACKEND_INTERNAL_URL="http://127.0.0.1:8000"
      BACKEND_PUBLIC_BASE_URL="http://localhost:8000"
      HOST_PORT="${PRODUCTION_HOST_PORT}"
      ;;
    staging)
      STACK_ROOT="${STACKS_DIR}/${STACK_NAME}"
      CONFIG_DIR="${STACK_ROOT}/host"
      CONFIG_PATH="${CONFIG_DIR}/config.json"
      RUN_DIR="${STACK_ROOT}/run"
      LOG_DIR="${STACK_ROOT}/logs"
      BACKEND_PID_FILE="${RUN_DIR}/oysterun-backend.pid"
      HOST_PID_FILE="${RUN_DIR}/oysterun-host.pid"
      BACKEND_LOG="${LOG_DIR}/oysterun-backend.log"
      HOST_LOG="${LOG_DIR}/oysterun-host.log"
      BACKEND_LABEL="com.oysterun.backend.${STACK_NAME}"
      HOST_LABEL="com.oysterun.host.${STACK_NAME}"
      HOST_ORIGIN_FILE="${RUN_DIR}/oysterun-host.origin.tsv"
      BACKEND_BIND_HOST="0.0.0.0"
      BACKEND_PORT="9000"
      BACKEND_INTERNAL_URL="http://127.0.0.1:9000"
      BACKEND_PUBLIC_BASE_URL="http://${OYSTERUN_STAGING_LAN_HOST:-localhost}:9000"
      HOST_PORT="${STAGING_HOST_PORT}"
      ;;
    test1|test2|test3|test4)
      STACK_ROOT="${STACKS_DIR}/${STACK_NAME}"
      CONFIG_DIR="${STACK_ROOT}/host"
      CONFIG_PATH="${CONFIG_DIR}/config.json"
      RUN_DIR="${STACK_ROOT}/run"
      LOG_DIR="${STACK_ROOT}/logs"
      BACKEND_PID_FILE="${RUN_DIR}/oysterun-backend.pid"
      HOST_PID_FILE="${RUN_DIR}/oysterun-host.pid"
      BACKEND_LOG="${LOG_DIR}/oysterun-backend.log"
      HOST_LOG="${LOG_DIR}/oysterun-host.log"
      BACKEND_LABEL="com.oysterun.backend.${STACK_NAME}"
      HOST_LABEL="com.oysterun.host.${STACK_NAME}"
      HOST_ORIGIN_FILE="${RUN_DIR}/oysterun-host.origin.tsv"
      case "${STACK_NAME}" in
        test1) HOST_PORT="${TEST1_HOST_PORT}" ;;
        test2) HOST_PORT="${TEST2_HOST_PORT}" ;;
        test3) HOST_PORT="${TEST3_HOST_PORT}" ;;
        test4) HOST_PORT="${TEST4_HOST_PORT}" ;;
      esac
      ;;
    *)
      STACK_ROOT="${STACKS_DIR}/${STACK_NAME}"
      CONFIG_DIR="${STACK_ROOT}/host"
      CONFIG_PATH="${CONFIG_DIR}/config.json"
      RUN_DIR="${STACK_ROOT}/run"
      LOG_DIR="${STACK_ROOT}/logs"
      BACKEND_PID_FILE="${RUN_DIR}/oysterun-backend-${STACK_NAME}.pid"
      HOST_PID_FILE="${RUN_DIR}/oysterun-host-${STACK_NAME}.pid"
      BACKEND_LOG="${LOG_DIR}/oysterun-backend-${STACK_NAME}.log"
      HOST_LOG="${LOG_DIR}/oysterun-host-${STACK_NAME}.log"
      BACKEND_LABEL="com.oysterun.backend.${STACK_NAME}"
      HOST_LABEL="com.oysterun.host.${STACK_NAME}"
      HOST_ORIGIN_FILE="${RUN_DIR}/oysterun-host-${STACK_NAME}.origin.tsv"
      HOST_PORT="$(resolve_custom_stack_host_port)"
      ;;
  esac

  if [[ -n "${HOST_PORT}" ]]; then
    HOST_URL="http://localhost:${HOST_PORT}"
  else
    HOST_URL=""
  fi

  STACK_READINESS_FILE="${RUN_DIR}/stack_readiness.json"
  SERVICE_CONTROL_AUDIT_FILE="${LOG_DIR}/service-control.jsonl"
  ROUTEC_RUNTIME_ENV_FILE="${CONFIG_DIR}/routec-runtime-env.sh"
  ROUTEC_RUNTIME_ENV_JSON_FILE="${CONFIG_DIR}/routec-runtime-env.json"
  ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR="${CONFIG_DIR}/legacy-routec-runtime-env-quarantine"
  ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_FILE="${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_DIR}/latest-proof.json"
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_FILE="${RUN_DIR}/legacy-routec-spike0-synapse-cleanup.json"
  STACK_DASHBOARD_CREDENTIALS_PROOF_FILE="${RUN_DIR}/stack_dashboard_credentials.json"
  HOST_TRANSCRIPTS_DB_PATH="${CONFIG_DIR}/oysterun.sqlite"
  MATRIX_DB_PATH="${STACK_ROOT}/matrix/homeserver.db"
  SYNAPSE_CONFIG_PATH="${STACK_ROOT}/matrix/homeserver.yaml"
}

configure_backend_dev_runtime() {
  if [[ -z "${CONFIG_DIR}" || -z "${RUN_DIR}" || -z "${LOG_DIR}" ]]; then
    configure_stack_runtime
  fi

  case "${STACK_NAME}" in
    staging)
      if [[ -z "${BACKEND_BIND_HOST}" || -z "${BACKEND_PORT}" || -z "${BACKEND_INTERNAL_URL}" || -z "${BACKEND_PUBLIC_BASE_URL}" || -z "${BACKEND_DB_PATH}" || -z "${BACKEND_DB_URL}" ]]; then
        echo "[oysterun-service] error: backend dev runtime is not configured for stack ${STACK_NAME}" >&2
        exit 1
      fi
      ;;
    production)
      echo "[oysterun-service] error: production uses the home Host; use start_oysterun.sh for regular service or --stack staging for watch-mode development" >&2
      exit 1
      ;;
    test1|test2|test3|test4)
      echo "[oysterun-service] error: ${STACK_NAME} is a fixed Host-only test slot; use start_oysterun.sh or a custom stack with --backend_port for dev_up" >&2
      exit 1
      ;;
    *)
      require_host_port_configured
      if [[ -z "${BACKEND_PORT_OVERRIDE}" ]]; then
        echo "[oysterun-service] error: stack ${STACK_NAME} requires --backend_port for dev_up" >&2
        exit 1
      fi
      if ! validate_port_value "${BACKEND_PORT_OVERRIDE}"; then
        echo "[oysterun-service] error: invalid --backend_port value: ${BACKEND_PORT_OVERRIDE}" >&2
        exit 1
      fi
      BACKEND_BIND_HOST="127.0.0.1"
      BACKEND_PORT="${BACKEND_PORT_OVERRIDE}"
      BACKEND_INTERNAL_URL="http://127.0.0.1:${BACKEND_PORT}"
      BACKEND_PUBLIC_BASE_URL="http://localhost:${BACKEND_PORT}"
      ;;
  esac
}

fixed_stack_names() {
  printf '%s\n' production staging test1 test2 test3 test4
}

resolve_command_path() {
  local name="$1"
  local resolved=""
  resolved="$(command -v "${name}" 2>/dev/null || true)"
  if [[ -z "${resolved}" ]]; then
    resolved="$(which "${name}" 2>/dev/null || true)"
  fi
  if [[ -z "${resolved}" ]]; then
    local candidate=""
    for candidate in \
      "/opt/homebrew/bin/${name}" \
      "/usr/local/bin/${name}" \
      "${HOME}/.local/bin/${name}" \
      "${HOME}/bin/${name}"
    do
      if [[ -x "${candidate}" ]]; then
        resolved="${candidate}"
        break
      fi
    done
  fi
  printf '%s' "${resolved}"
}

resolve_node_command_path() {
  local override="${OYSTERUN_NODE_BIN:-}"
  if [[ -n "${override}" ]]; then
    if [[ -x "${override}" && ! -d "${override}" ]]; then
      printf '%s' "${override}"
      return 0
    fi
    echo "[oysterun-service] error: OYSTERUN_NODE_BIN is set but is not an executable file: ${override}" >&2
    echo "[oysterun-service] error: reinstall/update the service or set OYSTERUN_NODE_BIN to a Node.js >=20 executable." >&2
    return 1
  fi

  resolve_command_path node
}

resolve_bootstrap_node_command_path() {
  local bootstrap="${OYSTERUN_BOOTSTRAP_NODE_BIN:-}"
  if [[ -n "${bootstrap}" && -x "${bootstrap}" && ! -d "${bootstrap}" ]]; then
    printf '%s' "${bootstrap}"
    return 0
  fi
  resolve_command_path node
}

require_node_runtime() {
  local context="${1:-Oysterun service}"
  local node_bin=""
  local version_output=""
  local node_version=""
  local node_major=""

  if ! node_bin="$(resolve_node_command_path)"; then
    return 1
  fi
  if [[ -z "${node_bin}" ]]; then
    echo "[oysterun-service] error: Node.js >=20 is required for ${context}; node was not found." >&2
    echo "[oysterun-service] error: install Node.js >=20 or set OYSTERUN_NODE_BIN to an executable Node.js path." >&2
    return 1
  fi
  if ! version_output="$("${node_bin}" --version 2>&1)"; then
    echo "[oysterun-service] error: Node.js >=20 is required for ${context}; failed to run ${node_bin} --version." >&2
    echo "[oysterun-service] error: ${version_output}" >&2
    return 1
  fi

  node_version="${version_output%%$'\n'*}"
  node_major="${node_version#v}"
  node_major="${node_major%%.*}"
  if ! [[ "${node_major}" =~ ^[0-9]+$ ]]; then
    echo "[oysterun-service] error: Node.js >=20 is required for ${context}; could not parse version from ${node_bin}: ${node_version}" >&2
    return 1
  fi
  if (( node_major < 20 )); then
    echo "[oysterun-service] error: Node.js >=20 is required for ${context}; resolved ${node_bin} reports ${node_version}." >&2
    return 1
  fi

  printf '%s' "${node_bin}"
}

node_npm_runtime_identity_path() {
  if [[ -z "${CONFIG_DIR:-}" ]]; then
    echo "[oysterun-service] error: stack config directory is required for Node/npm runtime identity" >&2
    return 1
  fi
  printf '%s/node-npm-runtime-identity.json' "${CONFIG_DIR}"
}

resolve_host_node_npm_runtime_identity() {
  local mode="${1:-verify}"
  local node_bin="${2:-}"
  local print_field="${3:-npm_cli_path}"
  if [[ -z "${node_bin}" ]]; then
    node_bin="$(resolve_command_path node)"
  fi
  if [[ -z "${node_bin}" || ! -x "${node_bin}" || -d "${node_bin}" ]]; then
    echo "[oysterun-service] error: a bootstrap Node executable is required to verify the persisted Host runtime identity" >&2
    return 1
  fi
  local mode_arg="--verify"
  local identity_args=()
  case "${mode}" in
    write) mode_arg="--write" ;;
    ensure) mode_arg="--ensure" ;;
    verify) mode_arg="--verify" ;;
    verify-persisted) mode_arg="--verify-persisted" ;;
    *)
      echo "[oysterun-service] error: unsupported Node/npm runtime identity mode: ${mode}" >&2
      return 1
      ;;
  esac
  identity_args+=("${mode_arg}")
  if [[ "${mode}" != "verify-persisted" ]]; then
    identity_args+=(--node-bin "${node_bin}")
  fi
  identity_args+=(--config-dir "${CONFIG_DIR}" --print-field "${print_field}")
  "${node_bin}" \
    "${ROOT_DIR}/host-service/node-npm-runtime-identity.mjs" \
    "${identity_args[@]}"
}

load_host_node_npm_lifecycle_bundle() {
  local mode="${1:-verify-persisted}"
  local node_bin="${2:-}"
  local bundle_output=""
  local key=""
  local value=""

  if [[ -z "${node_bin}" ]]; then
    node_bin="$(resolve_bootstrap_node_command_path)"
  fi
  if [[ -z "${node_bin}" || ! -x "${node_bin}" || -d "${node_bin}" ]]; then
    echo "[oysterun-service] error: a bootstrap Node executable is required to load the persisted Host lifecycle bundle" >&2
    return 1
  fi
  bundle_output="$(resolve_host_node_npm_runtime_identity "${mode}" "${node_bin}" lifecycle_bundle_env)"
  NODE_NPM_BUNDLE_NODE_PATH=""
  NODE_NPM_BUNDLE_NPM_CLI_PATH=""
  NODE_NPM_BUNDLE_IDENTITY_DIGEST=""
  NODE_NPM_BUNDLE_IDENTITY_PATH=""
  NODE_NPM_BUNDLE_NODE_REALPATH=""
  NODE_NPM_BUNDLE_NPM_CLI_REALPATH=""
  NODE_NPM_BUNDLE_NODE_VERSION=""
  NODE_NPM_BUNDLE_NODE_ABI=""
  NODE_NPM_BUNDLE_NPM_VERSION=""
  NODE_NPM_BUNDLE_PACKAGE_ROOT=""
  NODE_NPM_BUNDLE_PACKAGE_PREFIX=""
  NODE_NPM_BUNDLE_PACKAGE_MANIFEST_SHA256=""
  while IFS='=' read -r key value; do
    case "${key}" in
      node_path) NODE_NPM_BUNDLE_NODE_PATH="${value}" ;;
      npm_cli_path) NODE_NPM_BUNDLE_NPM_CLI_PATH="${value}" ;;
      toolchain_identity_digest) NODE_NPM_BUNDLE_IDENTITY_DIGEST="${value}" ;;
      identity_path) NODE_NPM_BUNDLE_IDENTITY_PATH="${value}" ;;
      node_realpath) NODE_NPM_BUNDLE_NODE_REALPATH="${value}" ;;
      npm_cli_realpath) NODE_NPM_BUNDLE_NPM_CLI_REALPATH="${value}" ;;
      node_version) NODE_NPM_BUNDLE_NODE_VERSION="${value}" ;;
      node_abi) NODE_NPM_BUNDLE_NODE_ABI="${value}" ;;
      npm_version) NODE_NPM_BUNDLE_NPM_VERSION="${value}" ;;
      package_root) NODE_NPM_BUNDLE_PACKAGE_ROOT="${value}" ;;
      package_prefix) NODE_NPM_BUNDLE_PACKAGE_PREFIX="${value}" ;;
      package_manifest_sha256) NODE_NPM_BUNDLE_PACKAGE_MANIFEST_SHA256="${value}" ;;
    esac
  done <<< "${bundle_output}"
  if [[ -z "${NODE_NPM_BUNDLE_NODE_PATH}" ||
        -z "${NODE_NPM_BUNDLE_NPM_CLI_PATH}" ||
        -z "${NODE_NPM_BUNDLE_IDENTITY_DIGEST}" ||
        -z "${NODE_NPM_BUNDLE_IDENTITY_PATH}" ]]; then
    echo "[oysterun-service] error: persisted Host lifecycle bundle is incomplete (node=$([[ -n "${NODE_NPM_BUNDLE_NODE_PATH}" ]] && printf present || printf missing), npm=$([[ -n "${NODE_NPM_BUNDLE_NPM_CLI_PATH}" ]] && printf present || printf missing), digest=$([[ -n "${NODE_NPM_BUNDLE_IDENTITY_DIGEST}" ]] && printf present || printf missing), identity=$([[ -n "${NODE_NPM_BUNDLE_IDENTITY_PATH}" ]] && printf present || printf missing))" >&2
    return 1
  fi
  return 0
}

build_launch_path() {
  local node_bin="${1:-}"
  local config_path="${2:-${CONFIG_PATH:-}}"
  if [[ -z "${node_bin}" ]]; then
    node_bin="$(require_node_runtime "Host launch PATH")"
  fi
  if [[ -z "${config_path}" ]]; then
    echo "[oysterun-service] error: Host config path is required to build launch PATH" >&2
    return 1
  fi
  "${node_bin}" \
    "${ROOT_DIR}/host-service/provider-command-detection.mjs" \
    --print-launch-path \
    --config-path "${config_path}" \
    --node-bin "${node_bin}"
}

pid_is_running() {
  local pid="$1"
  [[ -n "${pid}" ]] && kill -0 "${pid}" 2>/dev/null
}

pid_from_file() {
  local pid_file="$1"
  if [[ -f "${pid_file}" ]]; then
    tr -d '[:space:]' < "${pid_file}"
  fi
}

origin_host_pid_from_file() {
  local origin_file="$1"
  if [[ -f "${origin_file}" ]]; then
    awk -F $'\t' '$1 == "host_pid" { print $2; exit }' "${origin_file}"
  fi
}

macos_lsof_path() {
  local candidate=""
  for candidate in /usr/sbin/lsof /usr/bin/lsof; do
    if [[ -x "${candidate}" && ! -d "${candidate}" ]]; then
      printf '%s\n' "${candidate}"
      return 0
    fi
  done
  return 1
}

linux_ss_path() {
  resolve_command_path ss
}

linux_fuser_path() {
  resolve_command_path fuser
}

validate_listener_pid_lines() {
  local raw="${1:-}"
  local value=""
  if [[ -z "${raw}" ]]; then
    return 0
  fi
  while IFS= read -r value; do
    if [[ -z "${value}" || ! "${value}" =~ ^[0-9]+$ || "${value}" == "0" ]]; then
      return 1
    fi
  done <<< "${raw}"
}

listener_pids_for_port() {
  local port="$1"
  local detector=""
  local raw=""
  local normalized=""
  local line=""
  local remaining=""
  local pid_value=""
  local ss_pid_output=""
  local status=0

  if ! validate_port_value "${port}"; then
    echo "[oysterun-service] error: invalid port for listener ownership: ${port}" >&2
    return 2
  fi

  if is_macos; then
    if ! detector="$(macos_lsof_path)" || [[ -z "${detector}" ]]; then
      echo "[oysterun-service] error: macOS listener ownership requires an absolute system lsof" >&2
      return 2
    fi
    set +e
    raw="$("${detector}" -nP -t -iTCP:"${port}" -sTCP:LISTEN 2>/dev/null)"
    status=$?
    set -e
    if [[ "${status}" -eq 1 && -z "${raw}" ]]; then
      return 0
    fi
    if [[ "${status}" -ne 0 ]]; then
      echo "[oysterun-service] error: macOS lsof could not determine listener ownership for port ${port}" >&2
      return 2
    fi
    normalized="$(printf '%s\n' "${raw}" | sed '/^$/d' | sort -nu)"
  elif is_linux; then
    detector="$(linux_ss_path)"
    if [[ -n "${detector}" ]]; then
      set +e
      raw="$("${detector}" -H -ltnp "sport = :${port}" 2>/dev/null)"
      status=$?
      set -e
      if [[ "${status}" -ne 0 ]]; then
        echo "[oysterun-service] error: Linux ss could not determine listener ownership for port ${port}" >&2
        return 2
      fi
      if [[ -n "${raw}" ]]; then
        while IFS= read -r line; do
          [[ -n "${line}" ]] || continue
          if [[ ! "${line}" =~ ^LISTEN[[:space:]] ]]; then
            echo "[oysterun-service] error: Linux ss returned an unrecognized listener row for port ${port}" >&2
            return 2
          fi
          remaining="${line}"
          local line_pid_count=0
          while [[ "${remaining}" == *"pid="* ]]; do
            remaining="${remaining#*pid=}"
            pid_value="${remaining%%[,)]*}"
            if [[ ! "${pid_value}" =~ ^[0-9]+$ ]] || [[ "${pid_value}" == "0" ]]; then
              echo "[oysterun-service] error: Linux ss reported a non-numeric listener owner for port ${port}" >&2
              return 2
            fi
            ss_pid_output="${ss_pid_output}${pid_value}"$'\n'
            line_pid_count=$((line_pid_count + 1))
            remaining="${remaining#"${pid_value}"}"
          done
          if [[ "${line_pid_count}" -eq 0 ]]; then
            echo "[oysterun-service] error: Linux ss reported a listener without a numeric process owner for port ${port}" >&2
            return 2
          fi
        done <<< "${raw}"
        normalized="$(printf '%s' "${ss_pid_output}" | sed '/^$/d' | sort -nu)"
      fi
    else
      detector="$(linux_fuser_path)"
      if [[ -z "${detector}" ]]; then
        echo "[oysterun-service] error: no supported Linux listener ownership detector is available for port ${port}" >&2
        return 2
      fi
      set +e
      raw="$("${detector}" -n tcp "${port}" 2>/dev/null)"
      status=$?
      set -e
      if [[ "${status}" -eq 1 && -z "${raw}" ]]; then
        return 0
      fi
      if [[ "${status}" -ne 0 ]]; then
        echo "[oysterun-service] error: Linux fuser could not determine listener ownership for port ${port}" >&2
        return 2
      fi
      normalized="$(printf '%s\n' "${raw}" | tr '[:space:]' '\n' | sed '/^$/d' | sort -nu)"
    fi
  else
    echo "[oysterun-service] error: unsupported operating system for listener ownership on port ${port}" >&2
    return 2
  fi

  if ! validate_listener_pid_lines "${normalized}"; then
    echo "[oysterun-service] error: listener ownership for port ${port} was not numeric-only" >&2
    return 2
  fi
  if [[ -n "${normalized}" ]]; then
    printf '%s\n' "${normalized}"
  fi
}

ensure_port_available() {
  local port="$1"
  local listeners

  if [[ -z "${port}" ]]; then
    echo "[oysterun-service] error: port required" >&2
    exit 1
  fi

  if ! listeners="$(listener_pids_for_port "${port}")"; then
    echo "[oysterun-service] error: unable to determine listener ownership for port ${port}; refusing to continue" >&2
    exit 1
  fi
  if [[ -n "${listeners}" ]]; then
    listeners="$(printf '%s\n' "${listeners}" | paste -sd ',' -)"
    echo "[oysterun-service] error: Port ${port} is already in use by PID ${listeners}" >&2
    exit 1
  fi
}

ensure_port_listener_matches_expected_process() {
  local port="$1"
  local expected_pid="${2:-}"
  local listeners=""
  local listener=""

  if [[ -n "${expected_pid}" && ! "${expected_pid}" =~ ^[0-9]+$ ]]; then
    echo "[oysterun-service] error: expected Host PID must be numeric for port ${port}" >&2
    return 1
  fi
  if ! listeners="$(listener_pids_for_port "${port}")"; then
    echo "[oysterun-service] error: unable to determine listener ownership for stack ${STACK_NAME} port ${port}; current Host remains unchanged" >&2
    return 1
  fi
  if [[ -z "${listeners}" ]]; then
    return 0
  fi
  if [[ -z "${expected_pid}" ]]; then
    listeners="$(printf '%s\n' "${listeners}" | paste -sd ',' -)"
    echo "[oysterun-service] error: stack ${STACK_NAME} port ${port} is owned by numeric PID ${listeners}, but no exact current Host PID is available" >&2
    return 1
  fi
  while IFS= read -r listener; do
    if [[ "${listener}" != "${expected_pid}" ]]; then
      listeners="$(printf '%s\n' "${listeners}" | paste -sd ',' -)"
      echo "[oysterun-service] error: stack ${STACK_NAME} port ${port} is owned by numeric PID ${listeners}; expected current Host PID ${expected_pid}" >&2
      return 1
    fi
  done <<< "${listeners}"
}

launchctl_label_exists() {
  local label="$1"
  if ! is_macos; then
    return 1
  fi
  launchctl list "${label}" >/dev/null 2>&1 || launchctl print "$(launchd_gui_domain)/${label}" >/dev/null 2>&1
}

launchctl_pid_for_label() {
  local label="$1"
  local pid=""

  if ! is_macos; then
    return 0
  fi

  pid="$(launchctl list "${label}" 2>/dev/null | awk '
    /"PID" = / {
      gsub(/[^0-9]/, "", $0);
      if (length($0) > 0) {
        print $0;
        exit;
      }
    }
  ' || true)"
  if [[ -n "${pid}" ]]; then
    printf '%s\n' "${pid}"
    return 0
  fi

  pid="$(launchctl print "$(launchd_gui_domain)/${label}" 2>/dev/null | awk '
    $1 == "pid" && $2 == "=" {
      gsub(/[^0-9]/, "", $3);
      if (length($3) > 0) {
        print $3;
        exit;
      }
    }
  ' || true)"
  if [[ -n "${pid}" ]]; then
    printf '%s\n' "${pid}"
  fi
  return 0
}

launchd_gui_domain() {
  local uid=""
  if ! is_macos; then
    echo "[oysterun-service] error: launchd domain is only available on macOS" >&2
    return 1
  fi
  uid="$(id -u)"
  if launchctl print "gui/${uid}" >/dev/null 2>&1; then
    printf 'gui/%s' "${uid}"
    return
  fi
  printf 'user/%s' "${uid}"
}

launch_agent_plist_path_for_label() {
  local label="$1"
  if ! is_macos; then
    return 0
  fi
  printf '%s/Library/LaunchAgents/%s.plist\n' "${HOME}" "${label}"
}

launch_agent_is_installed_for_label() {
  local label="$1"
  local plist_path=""
  if ! is_macos; then
    return 1
  fi
  plist_path="$(launch_agent_plist_path_for_label "${label}")"
  [[ -f "${plist_path}" ]]
}

launch_service_is_loaded() {
  local label="$1"
  if ! is_macos; then
    return 1
  fi
  launchctl print "$(launchd_gui_domain)/${label}" >/dev/null 2>&1
}

bootstrap_launch_agent_plist() {
  local plist_path="$1"
  if ! is_macos; then
    echo "[oysterun-service] error: launchd bootstrap is only available on macOS" >&2
    return 1
  fi
  append_service_control_audit "launchctl_bootstrap" "attempt" "plist_path=${plist_path}"
  if launchctl bootstrap "$(launchd_gui_domain)" "${plist_path}"; then
    append_service_control_audit "launchctl_bootstrap" "done" "plist_path=${plist_path}"
    return 0
  fi
  append_service_control_audit "launchctl_bootstrap" "failed" "plist_path=${plist_path}"
  return 1
}

bootout_launch_agent_service() {
  local label="$1"
  local plist_path=""
  if ! is_macos; then
    return 0
  fi
  plist_path="$(launch_agent_plist_path_for_label "${label}")"

  append_service_control_audit "launchctl_bootout" "attempt" "label=${label};plist_path=${plist_path}"
  if launchctl bootout "$(launchd_gui_domain)/${label}" >/dev/null 2>&1; then
    append_service_control_audit "launchctl_bootout" "done" "label=${label};method=label"
    return 0
  fi
  if launchctl bootout "$(launchd_gui_domain)" "${plist_path}" >/dev/null 2>&1; then
    append_service_control_audit "launchctl_bootout" "done" "label=${label};method=plist;plist_path=${plist_path}"
    return 0
  fi
  append_service_control_audit "launchctl_bootout" "ignored_failure" "label=${label};plist_path=${plist_path}"
  return 0
}

kickstart_launch_agent_service() {
  local label="$1"
  if ! is_macos; then
    echo "[oysterun-service] error: launchd kickstart is only available on macOS" >&2
    return 1
  fi
  append_service_control_audit "launchctl_kickstart" "attempt" "label=${label}"
  if launchctl kickstart -k "$(launchd_gui_domain)/${label}"; then
    append_service_control_audit "launchctl_kickstart" "done" "label=${label}"
    return 0
  fi
  append_service_control_audit "launchctl_kickstart" "failed" "label=${label}"
  return 1
}

ensure_runtime_dirs() {
  mkdir -p "${CONFIG_DIR}" "${RUN_DIR}" "${LOG_DIR}" "$(dirname "${BACKEND_DB_PATH}")" "$(dirname "${MATRIX_DB_PATH}")"
}

ensure_backend_dev_runtime_dirs() {
  if [[ -z "${BACKEND_DB_PATH}" ]]; then
    echo "[oysterun-service] error: backend dev runtime is not configured" >&2
    exit 1
  fi

  mkdir -p "$(dirname "${BACKEND_DB_PATH}")"
}

sync_host_stack_port_config() {
  local node_bin

  require_host_port_configured
  if ! node_bin="$(require_node_runtime "stack config sync")"; then
    return 1
  fi
  (
    cd "${ROOT_DIR}"
    OYSTERUN_CONFIG_DIR="${CONFIG_DIR}" \
    OYSTERUN_PORT="${HOST_PORT}" \
    "${node_bin}" tool_scripts/sync_host_stack_config.mjs
  )
}

ensure_stack_dashboard_credentials() {
  local node_bin="$1"

  if [[ -z "${node_bin}" ]]; then
    echo "[oysterun-service] error: node is required for dashboard credential readiness" >&2
    return 1
  fi
  if [[ -z "${CONFIG_DIR}" || -z "${HOST_URL}" || -z "${STACK_DASHBOARD_CREDENTIALS_PROOF_FILE}" ]]; then
    echo "[oysterun-service] error: dashboard credential readiness requires configured stack runtime" >&2
    return 1
  fi

  (
    cd "${ROOT_DIR}"
    OYSTERUN_CONFIG_DIR="${CONFIG_DIR}" \
    OYSTERUN_STACK_NAME="${STACK_NAME}" \
    OYSTERUN_HOST_ORIGIN="${HOST_URL}" \
    OYSTERUN_STACK_DASHBOARD_CREDENTIALS_PROOF_PATH="${STACK_DASHBOARD_CREDENTIALS_PROOF_FILE}" \
    "${node_bin}" "${STACK_DASHBOARD_CREDENTIALS_SCRIPT}" ensure
  )
}

ensure_dashboard_static_app() {
  local node_bin="$1"

  if [[ -f "${DASHBOARD_WEB_PREBUILT_MARKER}" ]]; then
    if [[ ! -f "${DASHBOARD_WEB_INDEX}" ]]; then
      echo "[oysterun-service] error: prebuilt dashboard marker exists but ${DASHBOARD_WEB_INDEX} is missing" >&2
      return 1
    fi
    echo "[oysterun-service] Using prebuilt dashboard static app for stack ${STACK_NAME}."
    return 0
  fi

  echo "[oysterun-service] Building web client for stack ${STACK_NAME}..."
  (
    cd "${ROOT_DIR}"
    exec "${node_bin}" dev/client/web/build-index.mjs
  )
}

ensure_routec_web_chat_static_app() {
  local node_bin="${1:-}"
  local npm_cli="${2:-}"

  if [[ -f "${ROUTEC_WEB_CHAT_PREBUILT_MARKER}" ]]; then
    if [[ ! -f "${ROUTEC_WEB_CHAT_DIST_INDEX}" ]]; then
      echo "[oysterun-service] error: prebuilt Route C web-chat marker exists but ${ROUTEC_WEB_CHAT_DIST_INDEX} is missing" >&2
      return 1
    fi
    echo "[oysterun-service] Using prebuilt Route C web-chat static app for stack ${STACK_NAME}."
    return 0
  fi

  if [[ ! -f "${ROUTEC_WEB_CHAT_DIR}/package.json" ]]; then
    echo "[oysterun-service] error: Route C web-chat package.json is missing: ${ROUTEC_WEB_CHAT_DIR}/package.json" >&2
    return 1
  fi
  if [[ ! -f "${ROUTEC_WEB_CHAT_DIR}/package-lock.json" ]]; then
    echo "[oysterun-service] error: Route C web-chat package-lock.json is missing: ${ROUTEC_WEB_CHAT_DIR}/package-lock.json" >&2
    return 1
  fi
  if [[ ! -x "${ROUTEC_WEB_CHAT_DIR}/node_modules/.bin/vite" ]]; then
    echo "[oysterun-service] error: Route C web-chat dependencies are not materialized in ${ROUTEC_WEB_CHAT_DIR}/node_modules" >&2
    echo "[oysterun-service] error: run 'cd ${ROUTEC_WEB_CHAT_DIR} && npm ci' before starting this stack" >&2
    return 1
  fi

  if [[ -z "${node_bin}" || -z "${npm_cli}" || ! -x "${node_bin}" || ! -f "${npm_cli}" ]]; then
    echo "[oysterun-service] error: persisted absolute Node/npm identity is required to build Route C web-chat" >&2
    return 1
  fi

  echo "[oysterun-service] Building Route C web-chat static app for stack ${STACK_NAME}..."
  (
    cd "${ROUTEC_WEB_CHAT_DIR}"
    "${node_bin}" "${npm_cli}" run build
  )

  if [[ ! -f "${ROUTEC_WEB_CHAT_DIST_INDEX}" ]]; then
    echo "[oysterun-service] error: Route C web-chat build did not produce ${ROUTEC_WEB_CHAT_DIST_INDEX}" >&2
    return 1
  fi
}

assert_host_config_port_matches_stack() {
  local node_bin="$1"
  "${node_bin}" -e '
    const fs = require("fs");
    const path = process.env.OYSTERUN_PREFLIGHT_CONFIG_PATH;
    const expected = Number(process.env.OYSTERUN_PREFLIGHT_HOST_PORT);
    const value = JSON.parse(fs.readFileSync(path, "utf8"));
    if (!Number.isInteger(expected) || expected <= 0 || Number(value.port) !== expected) {
      throw new Error("Host config port does not match the bounded stack port");
    }
  ' >/dev/null
}

assert_macos_launch_agent_definition() {
  local plist_path="$1"
  local node_bin="$2"
  local npm_cli="$3"
  local identity_path="$4"
  local lifecycle_path="$5"
  local plist_json=""

  if [[ ! -x /usr/bin/plutil ]]; then
    echo "[oysterun-service] error: macOS lifecycle preflight requires /usr/bin/plutil" >&2
    return 1
  fi
  if ! plist_json="$(/usr/bin/plutil -convert json -o - "${plist_path}" 2>/dev/null)"; then
    echo "[oysterun-service] error: installed LaunchAgent plist is not structurally readable for stack ${STACK_NAME}" >&2
    return 1
  fi
  OYSTERUN_PREFLIGHT_PLIST_JSON="${plist_json}" \
    OYSTERUN_PREFLIGHT_PLIST_LABEL="${HOST_LABEL}" \
    OYSTERUN_PREFLIGHT_PLIST_ROOT="${ROOT_DIR}" \
    OYSTERUN_PREFLIGHT_PLIST_STACK="${STACK_NAME}" \
    OYSTERUN_PREFLIGHT_PLIST_STACK_KIND="${STACK_KIND}" \
    OYSTERUN_PREFLIGHT_PLIST_HOST_PORT="${HOST_PORT}" \
    OYSTERUN_PREFLIGHT_PLIST_STACKS_DIR="$([[ "${STACK_NAME}" != "production" && -n "${STACK_KIND}" ]] && printf '%s' "${STACKS_DIR}" || true)" \
    OYSTERUN_PREFLIGHT_PLIST_NODE="${node_bin}" \
    OYSTERUN_PREFLIGHT_PLIST_NPM="${npm_cli}" \
    OYSTERUN_PREFLIGHT_PLIST_IDENTITY="${identity_path}" \
    OYSTERUN_PREFLIGHT_PLIST_PATH="${lifecycle_path}" \
    OYSTERUN_PREFLIGHT_PLIST_REGISTRY="${OYSTERUN_UPDATE_REGISTRY_URL:-}" \
    OYSTERUN_PREFLIGHT_PLIST_REGISTRY_STATE="${OYSTERUN_UPDATE_REGISTRY_STATE_PATH:-}" \
    OYSTERUN_PREFLIGHT_PLIST_LOG="${HOST_LOG}" \
    "${node_bin}" -e '
      const plist = JSON.parse(process.env.OYSTERUN_PREFLIGHT_PLIST_JSON);
      const expectedArguments = [
        `${process.env.OYSTERUN_PREFLIGHT_PLIST_ROOT}/tool_scripts/run_oysterun_host.sh`,
        "--stack",
        process.env.OYSTERUN_PREFLIGHT_PLIST_STACK,
      ];
      if (process.env.OYSTERUN_PREFLIGHT_PLIST_STACK_KIND === "custom") {
        expectedArguments.push("--port", process.env.OYSTERUN_PREFLIGHT_PLIST_HOST_PORT);
      }
      const env = plist.EnvironmentVariables;
      const exactKeys = (value, expected) =>
        value && typeof value === "object" && !Array.isArray(value) &&
        Object.keys(value).sort().join("\n") === [...expected].sort().join("\n");
      const exactTopLevelKeys = exactKeys(plist, [
        "Label",
        "ProgramArguments",
        "WorkingDirectory",
        "EnvironmentVariables",
        "RunAtLoad",
        "KeepAlive",
        "ThrottleInterval",
        "StandardOutPath",
        "StandardErrorPath",
      ]);
      const expectedEnvironmentKeys = [
        "OYSTERUN_NODE_BIN",
        "OYSTERUN_NPM_CLI",
        "OYSTERUN_NODE_NPM_IDENTITY_PATH",
        "PATH",
      ];
      if (process.env.OYSTERUN_PREFLIGHT_PLIST_STACKS_DIR) {
        expectedEnvironmentKeys.push("OYSTERUN_STACKS_DIR");
      }
      if (process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY) {
        expectedEnvironmentKeys.push("OYSTERUN_UPDATE_REGISTRY_URL");
      }
      if (process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY_STATE) {
        expectedEnvironmentKeys.push("OYSTERUN_UPDATE_REGISTRY_STATE_PATH");
      }
      const exactEnvironmentKeys = exactKeys(env, expectedEnvironmentKeys);
      const exactArguments = Array.isArray(plist.ProgramArguments) &&
        plist.ProgramArguments.length === expectedArguments.length &&
        plist.ProgramArguments.every((value, index) => value === expectedArguments[index]);
      if (
        !exactTopLevelKeys ||
        plist.Label !== process.env.OYSTERUN_PREFLIGHT_PLIST_LABEL ||
        plist.WorkingDirectory !== process.env.OYSTERUN_PREFLIGHT_PLIST_ROOT ||
        !exactArguments ||
        !exactEnvironmentKeys ||
        env.OYSTERUN_NODE_BIN !== process.env.OYSTERUN_PREFLIGHT_PLIST_NODE ||
        env.OYSTERUN_NPM_CLI !== process.env.OYSTERUN_PREFLIGHT_PLIST_NPM ||
        env.OYSTERUN_NODE_NPM_IDENTITY_PATH !== process.env.OYSTERUN_PREFLIGHT_PLIST_IDENTITY ||
        (process.env.OYSTERUN_PREFLIGHT_PLIST_STACKS_DIR
          ? env.OYSTERUN_STACKS_DIR !== process.env.OYSTERUN_PREFLIGHT_PLIST_STACKS_DIR
          : Object.hasOwn(env, "OYSTERUN_STACKS_DIR")) ||
        (process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY
          ? env.OYSTERUN_UPDATE_REGISTRY_URL !== process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY
          : Object.hasOwn(env, "OYSTERUN_UPDATE_REGISTRY_URL")) ||
        (process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY_STATE
          ? env.OYSTERUN_UPDATE_REGISTRY_STATE_PATH !== process.env.OYSTERUN_PREFLIGHT_PLIST_REGISTRY_STATE
          : Object.hasOwn(env, "OYSTERUN_UPDATE_REGISTRY_STATE_PATH")) ||
        env.PATH !== process.env.OYSTERUN_PREFLIGHT_PLIST_PATH ||
        plist.RunAtLoad !== true ||
        plist.KeepAlive !== true ||
        plist.ThrottleInterval !== 10 ||
        plist.StandardOutPath !== process.env.OYSTERUN_PREFLIGHT_PLIST_LOG ||
        plist.StandardErrorPath !== process.env.OYSTERUN_PREFLIGHT_PLIST_LOG
      ) {
        throw new Error("installed LaunchAgent definition does not exactly match the bounded stack runtime");
      }
    '
}

render_macos_launch_agent_definition() {
  local output_path="$1"
  local action="${2:-render}"
  local lifecycle_path="$3"
  local package_realpath=""
  package_realpath="$(cd "${ROOT_DIR}" && pwd -P)"
  OYSTERUN_SERVICE_RENDER_OUTPUT="${output_path}" \
  OYSTERUN_SERVICE_RENDER_ACTION="${action}" \
  OYSTERUN_SERVICE_RENDER_ROOT="${ROOT_DIR}" \
  OYSTERUN_SERVICE_RENDER_REALROOT="${package_realpath}" \
  OYSTERUN_SERVICE_RENDER_STACK="${STACK_NAME}" \
  OYSTERUN_SERVICE_RENDER_PORT="${HOST_PORT}" \
  OYSTERUN_SERVICE_RENDER_CONFIG="${CONFIG_DIR}" \
  OYSTERUN_SERVICE_RENDER_STACK_ROOT="${STACK_ROOT}" \
  OYSTERUN_SERVICE_RENDER_LOG_DIR="${LOG_DIR}" \
  OYSTERUN_SERVICE_RENDER_HOST_LOG="${HOST_LOG}" \
  OYSTERUN_SERVICE_RENDER_LABEL="${HOST_LABEL}" \
  OYSTERUN_SERVICE_RENDER_STACK_KIND="${STACK_KIND}" \
  OYSTERUN_SERVICE_RENDER_PATH="${lifecycle_path}" \
  OYSTERUN_SERVICE_RENDER_IDENTITY="${CONFIG_DIR}/node-npm-runtime-identity.json" \
  OYSTERUN_SERVICE_RENDER_NODE="${NODE_NPM_BUNDLE_NODE_PATH}" \
  OYSTERUN_SERVICE_RENDER_NPM="${NODE_NPM_BUNDLE_NPM_CLI_PATH}" \
  "${NODE_NPM_BUNDLE_NODE_PATH}" --input-type=module -e '
    import { createHash } from "node:crypto";
    import { readFileSync, writeFileSync } from "node:fs";
    import { realpathSync } from "node:fs";
    import { pathToFileURL } from "node:url";
    const e = process.env;
    const manifestRaw = readFileSync(`${e.OYSTERUN_SERVICE_RENDER_ROOT}/package.json`, "utf8");
    const manifest = JSON.parse(manifestRaw);
    let identity;
    try {
      identity = JSON.parse(readFileSync(e.OYSTERUN_SERVICE_RENDER_IDENTITY, "utf8"));
    } catch (error) {
      if (e.OYSTERUN_SERVICE_RENDER_ACTION !== "install") throw error;
      const identityModule = await import(pathToFileURL(`${e.OYSTERUN_SERVICE_RENDER_ROOT}/host-service/node-npm-runtime-identity.mjs`));
      identity = identityModule.resolveNodeNpmRuntimeIdentity({
        nodeBin: e.OYSTERUN_SERVICE_RENDER_NODE, npmCli: e.OYSTERUN_SERVICE_RENDER_NPM,
      });
      identityModule.writeNodeNpmRuntimeIdentity(e.OYSTERUN_SERVICE_RENDER_CONFIG, identity);
    }
    const owned = manifest.oysterun_service_definition || {};
    const module = await import(pathToFileURL(`${e.OYSTERUN_SERVICE_RENDER_ROOT}/host-service/service-definition-migration.mjs`));
    const bundle = {
      schema_version: 1,
      artifact: {
        package_root: e.OYSTERUN_SERVICE_RENDER_ROOT,
        package_realpath: realpathSync(e.OYSTERUN_SERVICE_RENDER_ROOT),
        package_version: manifest.version,
        integrity_sha256: createHash("sha256").update(manifestRaw).digest("hex"),
      },
      host: {
        launch_domain: `gui/${process.getuid?.() ?? 0}`,
        user: e.USER || "unknown",
        stack_name: e.OYSTERUN_SERVICE_RENDER_STACK,
        port: Number(e.OYSTERUN_SERVICE_RENDER_PORT),
        config_dir: e.OYSTERUN_SERVICE_RENDER_CONFIG,
        stack_root: e.OYSTERUN_SERVICE_RENDER_STACK_ROOT,
        log_dir: e.OYSTERUN_SERVICE_RENDER_LOG_DIR,
        host_log: e.OYSTERUN_SERVICE_RENDER_HOST_LOG,
        service_label: e.OYSTERUN_SERVICE_RENDER_LABEL,
        stack_kind: e.OYSTERUN_SERVICE_RENDER_STACK_KIND,
        production: e.OYSTERUN_SERVICE_RENDER_STACK === "production",
      },
      runtime: {
        node_path: identity.node_path, node_realpath: identity.node_realpath,
        node_version: identity.node_version, node_abi: identity.node_abi,
        npm_cli_path: identity.npm_cli_path, npm_cli_realpath: identity.npm_cli_realpath,
        npm_version: identity.npm_version, platform: identity.platform,
        architecture: identity.architecture,
        toolchain_identity_digest: identity.toolchain_identity_digest,
      },
      update: {
        registry_authority: "installed_package",
        registry_url: e.OYSTERUN_UPDATE_REGISTRY_URL || null,
        state_path: e.OYSTERUN_UPDATE_REGISTRY_STATE_PATH || null,
      },
      provider_resolution: { path_entries: e.OYSTERUN_SERVICE_RENDER_PATH.split(":"), environment: {} },
      version_owned: {
        serializer: owned.serializer || null,
        environment: owned.environment || {}, top_level: owned.top_level || {},
        run_at_load: owned.run_at_load ?? true, keep_alive: owned.keep_alive ?? true,
        throttle_interval: owned.throttle_interval ?? 10,
      },
    };
    const rendered = module.renderServiceDefinition(bundle);
    if (e.OYSTERUN_SERVICE_RENDER_ACTION === "install") {
      module.writeRenderedServiceDefinition({ definitionPath: e.OYSTERUN_SERVICE_RENDER_OUTPUT, rendered });
    } else {
      writeFileSync(e.OYSTERUN_SERVICE_RENDER_OUTPUT, rendered.bytes, { mode: 0o600 });
    }
    process.stdout.write(`${rendered.sha256}\n`);
  '
}

preflight_macos_launch_agent_definition() {
  local node_bin="$1"
  local npm_cli="$2"
  local identity_path="$3"
  local lifecycle_path="$4"
  local plist_path=""
  plist_path="$(launch_agent_plist_path_for_label "${HOST_LABEL}")"

  if launchctl_label_exists "${HOST_LABEL}" && [[ ! -r "${plist_path}" ]]; then
    echo "[oysterun-service] error: loaded LaunchAgent label ${HOST_LABEL} has no readable exact service definition; current Host remains unchanged" >&2
    return 1
  fi
  if [[ ! -e "${plist_path}" ]]; then
    return 0
  fi
  if [[ ! -r "${plist_path}" || ! -f "${plist_path}" ]]; then
    echo "[oysterun-service] error: installed LaunchAgent is unreadable for stack ${STACK_NAME}" >&2
    return 1
  fi
  local rendered_path=""
  rendered_path="$(mktemp "${CONFIG_DIR}/.service-definition-preflight.XXXXXX")"
  if ! render_macos_launch_agent_definition "${rendered_path}" render "${lifecycle_path}" >/dev/null; then
    rm -f "${rendered_path}"
    printf '[oysterun-service] P226_CHECK stage=full_preflight check=deterministic_target_render result=failed code=render_failed\n' >&2
    return 1
  fi
  if ! cmp -s "${plist_path}" "${rendered_path}"; then
    rm -f "${rendered_path}"
    printf '[oysterun-service] P226_CHECK stage=full_preflight check=target_render_equality result=failed code=definition_mismatch\n' >&2
    return 1
  fi
  rm -f "${rendered_path}"
  printf '[oysterun-service] P226_CHECK stage=full_preflight check=target_render_equality result=passed code=exact_match\n'
}

assert_receipt_bound_macos_launch_agent_digest() {
  local expected_digest="$1"
  local authority="$2"
  local plist_path=""
  local observed_digest=""
  plist_path="$(launch_agent_plist_path_for_label "${HOST_LABEL}")"
  if [[ "${expected_digest}" == "absent" ]]; then
    if [[ -e "${plist_path}" ]]; then
      echo "[oysterun-service] error: ${authority} service definition was expected to remain absent" >&2
      return 1
    fi
    printf '[oysterun-service] P226_CHECK stage=transitional_preflight check=%s_service_definition_digest result=passed code=absent\n' "${authority}"
    return 0
  fi
  if [[ ! "${expected_digest}" =~ ^[a-f0-9]{64}$ || ! -f "${plist_path}" || -L "${plist_path}" ]]; then
    echo "[oysterun-service] error: ${authority} service definition digest authority is incomplete" >&2
    return 1
  fi
  observed_digest="$(shasum -a 256 "${plist_path}" | awk '{print $1}')"
  if [[ "${observed_digest}" != "${expected_digest}" ]]; then
    echo "[oysterun-service] error: ${authority} service definition changed after the receipt-bound snapshot" >&2
    return 1
  fi
  printf '[oysterun-service] P226_CHECK stage=transitional_preflight check=%s_service_definition_digest result=passed code=exact_match\n' "${authority}"
}

resolve_preflight_current_host_cwd() {
  local expected_retained_cwd="${1:-}"
  local active_root=""
  local global_prefix=""
  local retained_cwd=""
  local retained_package_root=""
  local operation_root=""

  if [[ -z "${expected_retained_cwd}" ]]; then
    printf '%s\n' "${HOST_DIR}"
    return 0
  fi
  if [[ "${expected_retained_cwd}" != /* || ! -d "${expected_retained_cwd}" ]]; then
    echo "[oysterun-service] error: retained current Host cwd must be an existing absolute directory" >&2
    return 1
  fi
  active_root="$(cd "${ROOT_DIR}" && pwd -P)"
  global_prefix="$(cd "${active_root}/../../.." && pwd -P)"
  retained_cwd="$(cd "${expected_retained_cwd}" && pwd -P)"
  retained_package_root="$(dirname "${retained_cwd}")"
  operation_root="$(dirname "${retained_package_root}")"
  if [[ "${retained_cwd}" != "${expected_retained_cwd}" ||
        "$(basename "${retained_cwd}")" != "host-service" ||
        ( "$(basename "${retained_package_root}")" != "previous-oysterun" &&
          "$(basename "${retained_package_root}")" != "failed-oysterun" ) ||
        "$(dirname "${operation_root}")" != "${global_prefix}" ||
        "$(basename "${operation_root}")" != .oysterun-update-* ]]; then
    echo "[oysterun-service] error: retained current Host cwd is outside the exact active-prefix update attempt boundary" >&2
    return 1
  fi
  printf '%s\n' "${retained_cwd}"
}

preflight_host_restart_readiness() {
  local expected_pid="${1:-}"
  local allow_operation_id="${2:-}"
  local expected_retained_current_host_cwd="${3:-}"
  local expected_source_service_definition_sha256="${4:-}"
  local expected_target_service_definition_sha256="${5:-}"
  local expected_current_host_cwd=""
  local bootstrap_node=""
  local node_bin=""
  local npm_cli=""
  local identity_digest=""
  local identity_path=""
  local lifecycle_path=""
  local conflict_args=()
  local p226_check="resolve_stack_and_runtime"
  local p226_code="preflight_check_failed"
  trap 'p226_status=$?; trap - RETURN; if [[ ${p226_status} -ne 0 ]]; then printf "[oysterun-service] P226_CHECK stage=preflight check=%s result=failed code=%s operation_id=%s\n" "${p226_check}" "${p226_code}" "${allow_operation_id}" >&2; fi' RETURN

  p226_check="stack_config_resolution"
  require_host_port_configured
  if [[ -z "${STACK_NAME}" || -z "${CONFIG_DIR}" || -z "${CONFIG_PATH}" || -z "${HOST_LABEL}" || -z "${ROOT_DIR}" ]]; then
    echo "[oysterun-service] error: lifecycle preflight could not resolve the exact stack, config, service label, and package root" >&2
    return 1
  fi
  if [[ ! -d "${ROOT_DIR}" || ! -r "${CONFIG_PATH}" ]]; then
    echo "[oysterun-service] error: lifecycle preflight requires a readable package root and Host config" >&2
    return 1
  fi
  if [[ -n "${expected_retained_current_host_cwd}" && -z "${expected_pid}" ]]; then
    echo "[oysterun-service] error: retained current Host cwd requires an exact current Host PID" >&2
    return 1
  fi
  expected_current_host_cwd="$(resolve_preflight_current_host_cwd "${expected_retained_current_host_cwd}")"

  p226_check="node_npm_runtime_identity"
  bootstrap_node="$(resolve_bootstrap_node_command_path)"
  if [[ -z "${bootstrap_node}" ]]; then
    echo "[oysterun-service] error: lifecycle preflight needs an entry Node only to load the persisted service identity" >&2
    return 1
  fi
  load_host_node_npm_lifecycle_bundle verify-persisted "${bootstrap_node}"
  node_bin="${NODE_NPM_BUNDLE_NODE_PATH}"
  npm_cli="${NODE_NPM_BUNDLE_NPM_CLI_PATH}"
  identity_digest="${NODE_NPM_BUNDLE_IDENTITY_DIGEST}"
  identity_path="${NODE_NPM_BUNDLE_IDENTITY_PATH}"
  if [[ -z "${node_bin}" || -z "${npm_cli}" || -z "${identity_digest}" ]]; then
    echo "[oysterun-service] error: persisted Node/npm runtime identity is incomplete" >&2
    return 1
  fi
  printf '[oysterun-service] P226_CHECK stage=preflight check=node_npm_runtime_identity result=passed code=exact_match operation_id=%s\n' "${allow_operation_id}"

  lifecycle_path="$(build_launch_path "${node_bin}" "${CONFIG_PATH}")"
  if [[ ":${lifecycle_path}:" != *":/usr/sbin:"* || ":${lifecycle_path}:" != *":/sbin:"* ]]; then
    echo "[oysterun-service] error: canonical lifecycle PATH is missing required system tool directories" >&2
    return 1
  fi
  export PATH="${lifecycle_path}"
  export OYSTERUN_NODE_BIN="${node_bin}"
  export OYSTERUN_NPM_CLI="${npm_cli}"
  export OYSTERUN_NODE_NPM_IDENTITY_DIGEST="${identity_digest}"

  p226_check="operation_ownership"
  if [[ -n "${allow_operation_id}" ]]; then
    conflict_args+=(--allow-operation-id "${allow_operation_id}")
  fi
  if [[ "${#conflict_args[@]}" -gt 0 ]]; then
    "${node_bin}" "${ROOT_DIR}/host-service/cli/assert-lifecycle-operation-available.mjs" \
      --config-dir "${CONFIG_DIR}" \
      "${conflict_args[@]}"
  else
    "${node_bin}" "${ROOT_DIR}/host-service/cli/assert-lifecycle-operation-available.mjs" \
      --config-dir "${CONFIG_DIR}"
  fi
  printf '[oysterun-service] P226_CHECK stage=preflight check=operation_ownership result=passed code=available operation_id=%s\n' "${allow_operation_id}"

  p226_check="stack_config_port_identity"
  OYSTERUN_PREFLIGHT_CONFIG_PATH="${CONFIG_PATH}" \
    OYSTERUN_PREFLIGHT_HOST_PORT="${HOST_PORT}" \
    assert_host_config_port_matches_stack "${node_bin}"
  printf '[oysterun-service] P226_CHECK stage=preflight check=stack_config_port_identity result=passed code=exact_match operation_id=%s\n' "${allow_operation_id}"

  p226_check="lifecycle_executables"
  for required_path in \
    "${ROOT_DIR}/tool_scripts/oysterun_release_service.sh" \
    "${ROOT_DIR}/tool_scripts/restart_oysterun.sh" \
    "${ROOT_DIR}/tool_scripts/start_oysterun.sh" \
    "${ROOT_DIR}/tool_scripts/stop_oysterun.sh" \
    "${ROOT_DIR}/tool_scripts/run_oysterun_host.sh"
  do
    if [[ ! -x "${required_path}" ]]; then
      echo "[oysterun-service] error: replacement Host command is not executable: ${required_path}" >&2
      return 1
    fi
  done
  printf '[oysterun-service] P226_CHECK stage=preflight check=lifecycle_executables result=passed code=complete operation_id=%s\n' "${allow_operation_id}"
  for required_path in \
    "${ROOT_DIR}/host-service/server.mjs" \
    "${ROOT_DIR}/host-service/package.json"
  do
    if [[ ! -r "${required_path}" ]]; then
      echo "[oysterun-service] error: replacement Host prerequisite is unreadable: ${required_path}" >&2
      return 1
    fi
  done

  if [[ ! -f "${DASHBOARD_WEB_PREBUILT_MARKER}" && ! -r "${ROOT_DIR}/dev/client/web/build-index.mjs" ]]; then
    echo "[oysterun-service] error: replacement Host dashboard build entry is unreadable: ${ROOT_DIR}/dev/client/web/build-index.mjs" >&2
    return 1
  fi

  p226_check="service_definition"
  if is_macos; then
    if [[ -n "${expected_source_service_definition_sha256}" && -n "${expected_target_service_definition_sha256}" ]]; then
      echo "[oysterun-service] error: lifecycle preflight cannot accept both source and target service-definition authority" >&2
      return 1
    elif [[ -n "${expected_source_service_definition_sha256}" ]]; then
      assert_receipt_bound_macos_launch_agent_digest \
        "${expected_source_service_definition_sha256}" source
    elif [[ -n "${expected_target_service_definition_sha256}" ]]; then
      assert_receipt_bound_macos_launch_agent_digest \
        "${expected_target_service_definition_sha256}" target
    else
      preflight_macos_launch_agent_definition \
        "${node_bin}" \
        "${npm_cli}" \
        "${identity_path}" \
        "${lifecycle_path}"
    fi
  fi

  p226_check="browser_assets"
  if [[ ! -r "${DASHBOARD_WEB_INDEX}" ]]; then
    echo "[oysterun-service] error: replacement Host dashboard asset is unreadable: ${DASHBOARD_WEB_INDEX}" >&2
    return 1
  fi
  if [[ ! -r "${ROUTEC_WEB_CHAT_DIST_INDEX}" ]]; then
    echo "[oysterun-service] error: replacement Host Route C asset is unreadable: ${ROUTEC_WEB_CHAT_DIST_INDEX}" >&2
    return 1
  fi
  if [[ ! -f "${ROUTEC_WEB_CHAT_PREBUILT_MARKER}" ]]; then
    if [[ ! -r "${ROUTEC_WEB_CHAT_DIR}/package.json" || ! -r "${ROUTEC_WEB_CHAT_DIR}/package-lock.json" || ! -x "${ROUTEC_WEB_CHAT_DIR}/node_modules/.bin/vite" ]]; then
      echo "[oysterun-service] error: replacement Host Route C build prerequisites are incomplete" >&2
      return 1
    fi
  fi
  printf '[oysterun-service] P226_CHECK stage=preflight check=browser_assets result=passed code=readable operation_id=%s\n' "${allow_operation_id}"

  p226_check="process_and_listener_identity"
  if [[ -n "${expected_pid}" ]]; then
    if [[ ! "${expected_pid}" =~ ^[0-9]+$ ]] || ! pid_is_running "${expected_pid}"; then
      echo "[oysterun-service] error: exact current Host PID is unavailable for stack ${STACK_NAME}" >&2
      return 1
    fi
    verify_process_cwd "${expected_pid}" "${expected_current_host_cwd}" "current Host service"
  fi
  ensure_port_listener_matches_expected_process "${HOST_PORT}" "${expected_pid}"
  printf '[oysterun-service] P226_CHECK stage=preflight check=process_and_listener_identity result=passed code=exact_match operation_id=%s\n' "${allow_operation_id}"

  printf '[oysterun-service] lifecycle preflight passed stack=%s port=%s host_pid=%s node=%s npm=%s detector=numeric-only\n' \
    "${STACK_NAME}" "${HOST_PORT}" "${expected_pid:--}" "${node_bin}" "${npm_cli}"
  trap - RETURN
}

clear_stale_pid_file() {
  local pid_file="$1"
  local label="$2"
  local pid

  pid="$(pid_from_file "${pid_file}")"
  if [[ -n "${pid}" ]] && ! pid_is_running "${pid}"; then
    rm -f "${pid_file}"
    echo "[oysterun-service] Removed stale ${label} PID file (${pid})"
  fi
}

ensure_process_not_running() {
  local launch_label="$1"
  local pid_file="$2"
  local label="$3"
  local port="$4"
  local pid

  clear_stale_pid_file "${pid_file}" "${label}"

  if launchctl_label_exists "${launch_label}"; then
    if is_macos && ! launch_agent_is_installed_for_label "${launch_label}"; then
      append_service_control_audit "launchctl_remove" "blocked" "reason=loaded_label_without_visible_plist;label=${launch_label};expected_plist=$(launch_agent_plist_path_for_label "${launch_label}")"
      echo "[oysterun-service] error: ${label} launchctl label exists but the LaunchAgent plist is not visible from HOME=${HOME}" >&2
      echo "[oysterun-service] error: refusing to remove ${launch_label} and restart it as a transient job." >&2
      echo "[oysterun-service] error: run from the correct user HOME or use 'oysterun service:restart' after verifying the LaunchAgent plist path." >&2
      exit 1
    fi
    pid="$(launchctl_pid_for_label "${launch_label}")"
    if [[ -n "${pid}" ]] && pid_is_running "${pid}"; then
      echo "[oysterun-service] error: ${label} is already running with PID ${pid}" >&2
      exit 1
    fi
    append_service_control_audit "launchctl_remove" "attempt" "reason=ensure_process_not_running;label=${launch_label};pid=${pid}"
    launchctl remove "${launch_label}" >/dev/null 2>&1 || true
    append_service_control_audit "launchctl_remove" "done" "reason=ensure_process_not_running;label=${launch_label};pid=${pid}"
    rm -f "${pid_file}"
    echo "[oysterun-service] Removed stale launchctl job for ${label}"
  fi

  ensure_port_available "${port}"
}

wait_for_http() {
  local url="$1"
  local label="$2"
  local pid="$3"
  local log_file="$4"
  local launch_label="${5:-}"
  local attempts=0

  until curl -fsS "${url}" >/dev/null 2>&1; do
    local current_pid="${pid}"
    if [[ -n "${launch_label}" ]] && is_macos; then
      current_pid="$(launchctl_pid_for_label "${launch_label}")"
    fi

    if [[ -n "${current_pid}" ]] && ! pid_is_running "${current_pid}" 2>/dev/null; then
      if [[ -n "${launch_label}" ]] && launchctl_label_exists "${launch_label}"; then
        attempts=$((attempts + 1))
        if [[ "${attempts}" -ge 60 ]]; then
          echo "[oysterun-service] error: timed out waiting for ${label} at ${url}" >&2
          if [[ -f "${log_file}" ]]; then
            echo "[oysterun-service] Last ${label} log lines:" >&2
            tail -n 40 "${log_file}" >&2 || true
          fi
          exit 1
        fi
        sleep 1
        continue
      fi
      echo "[oysterun-service] error: ${label} exited before becoming healthy" >&2
      if [[ -f "${log_file}" ]]; then
        echo "[oysterun-service] Last ${label} log lines:" >&2
        tail -n 40 "${log_file}" >&2 || true
      fi
      exit 1
    fi

    attempts=$((attempts + 1))
    if [[ "${attempts}" -ge 60 ]]; then
      echo "[oysterun-service] error: timed out waiting for ${label} at ${url}" >&2
      if [[ -f "${log_file}" ]]; then
        echo "[oysterun-service] Last ${label} log lines:" >&2
        tail -n 40 "${log_file}" >&2 || true
      fi
      exit 1
    fi

    sleep 1
  done
}

write_pid_file_from_label() {
  local launch_label="$1"
  local pid_file="$2"
  local pid

  if ! is_macos; then
    return 0
  fi

  pid="$(launchctl_pid_for_label "${launch_label}")"
  if [[ -n "${pid}" ]]; then
    printf '%s\n' "${pid}" > "${pid_file}"
  else
    rm -f "${pid_file}"
  fi
}

submit_launchctl_job() {
  local launch_label="$1"
  local log_file="$2"
  local command_string="$3"

  if ! is_macos; then
    echo "[oysterun-service] error: launchctl submit is only available on macOS" >&2
    return 1
  fi

  append_service_control_audit "launchctl_submit" "attempt" "label=${launch_label};log_file=${log_file};command_redacted=true"
  if launchctl submit -l "${launch_label}" -o "${log_file}" -e "${log_file}" -- /bin/zsh -lc "${command_string}"; then
    append_service_control_audit "launchctl_submit" "done" "label=${launch_label};log_file=${log_file};command_redacted=true"
    return 0
  fi
  append_service_control_audit "launchctl_submit" "failed" "label=${launch_label};log_file=${log_file};command_redacted=true"
  return 1
}

start_pid_file_host_process() {
  local pid_file="$1"
  local log_file="$2"
  local host_dir="$3"
  local launch_path="$4"
  local config_dir="$5"
  local host_port="$6"
  local root_dir="$7"
  local node_bin="$8"
  shift 8

  "${node_bin}" --input-type=module - -- \
    "${pid_file}" \
    "${log_file}" \
    "${host_dir}" \
    "${launch_path}" \
    "${config_dir}" \
    "${host_port}" \
    "${root_dir}" \
    "${node_bin}" \
    "$@" <<'NODE'
import { openSync, writeFileSync } from "node:fs";
import { dirname } from "node:path";
import { mkdirSync } from "node:fs";
import { spawn } from "node:child_process";

const [
  pidFile,
  logFile,
  hostDir,
  launchPath,
  configDir,
  hostPort,
  rootDir,
  nodeBin,
  ...extraEnvArgs
] = process.argv.slice(3);

if (!pidFile || !logFile || !hostDir || !launchPath || !configDir || !hostPort || !rootDir || !nodeBin) {
  throw new Error("missing required Host pid-file supervision argument");
}

const env = {
  ...process.env,
  PATH: launchPath,
  OYSTERUN_CONFIG_DIR: configDir,
  OYSTERUN_PORT: hostPort,
  OYSTERUN_REPO_ROOT: rootDir,
  OYSTERUN_NODE_BIN: nodeBin,
};

for (const rawArg of extraEnvArgs) {
  const separator = rawArg.indexOf("=");
  if (separator <= 0) {
    throw new Error(`invalid Host environment argument: ${rawArg}`);
  }
  env[rawArg.slice(0, separator)] = rawArg.slice(separator + 1);
}

mkdirSync(dirname(pidFile), { recursive: true });
mkdirSync(dirname(logFile), { recursive: true });
const out = openSync(logFile, "a");
const err = openSync(logFile, "a");
const child = spawn(nodeBin, ["server.mjs"], {
  cwd: hostDir,
  detached: true,
  env,
  stdio: ["ignore", out, err],
});

writeFileSync(pidFile, `${child.pid}\n`);
child.unref();
NODE
}

wait_for_exit() {
  local pid="$1"
  local attempts=0

  while pid_is_running "${pid}"; do
    attempts=$((attempts + 1))
    if [[ "${attempts}" -ge 40 ]]; then
      return 1
    fi
    sleep 0.5
  done

  return 0
}

process_cwd_for_pid() {
  local pid="$1"

  if [[ -e "/proc/${pid}/cwd" ]]; then
    readlink "/proc/${pid}/cwd" 2>/dev/null || true
    return 0
  fi
  if command -v lsof >/dev/null 2>&1; then
    lsof -a -d cwd -p "${pid}" -Fn 2>/dev/null | sed -n 's/^n//p' | head -n 1
  fi
}

process_command_for_pid() {
  local pid="$1"
  ps -p "${pid}" -o command= 2>/dev/null || true
}

sqlite_sidecar_paths_for_db() {
  local db_path="$1"
  if [[ -z "${db_path}" ]]; then
    return 0
  fi
  printf '%s\n' "${db_path}" "${db_path}-wal" "${db_path}-shm"
}

stack_host_state_paths() {
  sqlite_sidecar_paths_for_db "${HOST_TRANSCRIPTS_DB_PATH}"
  sqlite_sidecar_paths_for_db "${MATRIX_DB_PATH}"
}

stack_host_state_holder_pids() {
  local paths=()
  local path

  while IFS= read -r path; do
    if [[ -n "${path}" && -e "${path}" ]]; then
      paths+=("${path}")
    fi
  done < <(stack_host_state_paths)

  if (( ${#paths[@]} == 0 )); then
    return 0
  fi

  if command -v lsof >/dev/null 2>&1; then
    lsof -t "${paths[@]}" 2>/dev/null | sort -u || true
    return 0
  fi

  if command -v fuser >/dev/null 2>&1; then
    fuser "${paths[@]}" 2>/dev/null | tr ' ' '\n' | sed '/^$/d' | sort -u || true
    return 0
  fi

  return 0
}

pid_matches_oysterun_host_server() {
  local pid="$1"
  local command_line=""
  local cwd=""

  command_line="$(process_command_for_pid "${pid}")"
  cwd="$(process_cwd_for_pid "${pid}")"

  case "${command_line}" in
    *server.mjs*) ;;
    *) return 1 ;;
  esac

  case "${cwd}" in
    */host-service) return 0 ;;
    *) return 1 ;;
  esac
}

stop_stale_stack_host_state_holders() {
  local reason="${1:-stack cleanup}"
  local pid=""
  local holders=""
  local candidates=()

  holders="$(stack_host_state_holder_pids)"
  if [[ -z "${holders}" ]]; then
    return 0
  fi

  while IFS= read -r pid; do
    if [[ -z "${pid}" || "${pid}" == "$$" ]]; then
      continue
    fi
    if ! pid_is_running "${pid}"; then
      continue
    fi
    if pid_matches_oysterun_host_server "${pid}"; then
      candidates+=("${pid}")
    else
      echo "[oysterun-service] Warning: stack ${STACK_NAME} state files are held by non-Host PID ${pid}; leaving it running" >&2
    fi
  done <<< "${holders}"

  if (( ${#candidates[@]} == 0 )); then
    return 0
  fi

  echo "[oysterun-service] Stopping stale stack ${STACK_NAME} Host process(es) holding state files (${reason}): ${candidates[*]}"
  for pid in "${candidates[@]}"; do
    append_service_control_audit "process_signal" "attempt" "signal=TERM;reason=stale_stack_host_state_holder:${reason};pid=${pid}"
    kill "${pid}" 2>/dev/null || true
    append_service_control_audit "process_signal" "done" "signal=TERM;reason=stale_stack_host_state_holder:${reason};pid=${pid}"
  done
  for pid in "${candidates[@]}"; do
    if pid_is_running "${pid}" && ! wait_for_exit "${pid}"; then
      echo "[oysterun-service] Stale Host process ${pid} did not stop in time; sending SIGKILL"
      append_service_control_audit "process_signal" "attempt" "signal=KILL;reason=stale_stack_host_state_holder:${reason};pid=${pid}"
      kill -9 "${pid}" 2>/dev/null || true
      append_service_control_audit "process_signal" "done" "signal=KILL;reason=stale_stack_host_state_holder:${reason};pid=${pid}"
      wait_for_exit "${pid}" || true
    fi
  done
}

verify_process_cwd() {
  local pid="$1"
  local expected_cwd="$2"
  local label="$3"
  local actual_cwd

  actual_cwd="$(process_cwd_for_pid "${pid}")"
  if [[ -z "${actual_cwd}" ]]; then
    echo "[oysterun-service] error: could not resolve ${label} cwd for PID ${pid}" >&2
    return 1
  fi
  if [[ "${actual_cwd}" != "${expected_cwd}" ]]; then
    echo "[oysterun-service] error: ${label} started from unexpected cwd" >&2
    echo "[oysterun-service] error: expected ${expected_cwd}" >&2
    echo "[oysterun-service] error: actual   ${actual_cwd}" >&2
    return 1
  fi
}

write_host_origin_file() {
  local pid="$1"
  local launch_label="$2"
  local actual_cwd

  actual_cwd="$(process_cwd_for_pid "${pid}")"
  if [[ -z "${actual_cwd}" ]]; then
    echo "[oysterun-service] error: could not resolve Host service cwd for PID ${pid}" >&2
    return 1
  fi

  cat > "${HOST_ORIGIN_FILE}" <<EOF
key	value
started_at_utc	$(date -u +"%Y-%m-%dT%H:%M:%SZ")
repo_root	${ROOT_DIR}
host_dir	${HOST_DIR}
actual_cwd	${actual_cwd}
config_dir	${CONFIG_DIR}
host_port	${HOST_PORT}
host_pid	${pid}
launch_label	${launch_label}
EOF
}

clear_host_origin_file() {
  rm -f "${HOST_ORIGIN_FILE}"
}

wait_for_host_identity_files() {
  local label="$1"
  local expected_cwd="$2"
  local attempts="${3:-100}"
  local attempt=0
  local pid=""
  local origin_pid=""

  while (( attempt < attempts )); do
    pid="$(pid_from_file "${HOST_PID_FILE}" || true)"
    origin_pid="$(origin_host_pid_from_file "${HOST_ORIGIN_FILE}" || true)"
    if [[ -n "${pid}" && -n "${origin_pid}" && "${pid}" == "${origin_pid}" ]] && pid_is_running "${pid}"; then
      if verify_process_cwd "${pid}" "${expected_cwd}" "${label}" >/dev/null 2>&1; then
        printf '%s\n' "${pid}"
        return 0
      fi
    fi
    attempt=$((attempt + 1))
    sleep 0.2
  done

  echo "[oysterun-service] error: Host started but runtime identity files did not become ready in time." >&2
  echo "[oysterun-service] error: Run 'oysterun service:status' to inspect the service, then retry restart." >&2
  return 1
}

derive_routec_worker_slot() {
  case "${STACK_NAME}" in
    test_w[0-9]*)
      printf 'W%s' "${STACK_NAME#test_w}"
      ;;
    w[0-9]*)
      printf 'W%s' "${STACK_NAME#w}"
      ;;
    *)
      printf '%s' "${STACK_NAME}"
      ;;
  esac
}

run_routec_stack_readiness() {
  local command_name="$1"
  shift
  local node_bin
  local host_pid=""

  if [[ -z "${STACK_READINESS_FILE}" || -z "${HOST_URL}" || -z "${HOST_PORT}" ]]; then
    echo "[oysterun-service] error: stack readiness requires configured stack runtime" >&2
    return 1
  fi

  if ! node_bin="$(require_node_runtime "stack readiness")"; then
    return 1
  fi

  host_pid="$(pid_from_file "${HOST_PID_FILE}")"
  if [[ -z "${host_pid}" ]]; then
    host_pid="$(origin_host_pid_from_file "${HOST_ORIGIN_FILE}" || true)"
  fi
  if [[ -z "${host_pid}" ]] && is_macos && launchctl_label_exists "${HOST_LABEL}"; then
    host_pid="$(launchctl_pid_for_label "${HOST_LABEL}")"
  fi

  ROUTEC_REPO_ROOT="${ROOT_DIR}" \
  ROUTEC_STACK_READINESS_PATH="${STACK_READINESS_FILE}" \
  ROUTEC_GENERATED_BY_SCRIPT="${command_name}" \
  ROUTEC_STACK_NAME="${STACK_NAME}" \
  ROUTEC_STACK_ROOT="${STACK_ROOT}" \
  ROUTEC_CONFIG_DIR="${CONFIG_DIR}" \
  ROUTEC_RUN_DIR="${RUN_DIR}" \
  ROUTEC_LOG_DIR="${LOG_DIR}" \
  ROUTEC_WORKER_SLOT="$(derive_routec_worker_slot)" \
  ROUTEC_USABLE_ORIGIN="${HOST_URL}" \
  ROUTEC_HOST_PORT="${HOST_PORT}" \
  ROUTEC_BACKEND_PORT="${BACKEND_PORT:-}" \
  ROUTEC_HOST_PID="${host_pid}" \
  ROUTEC_HOST_LABEL="${HOST_LABEL}" \
  ROUTEC_HOST_ORIGIN_FILE="${HOST_ORIGIN_FILE}" \
  ROUTEC_HOST_LOG="${HOST_LOG}" \
  ROUTEC_STACK_CONFIG_PATH="${CONFIG_PATH}" \
  ROUTEC_RUNTIME_ENV_PATH="${ROUTEC_RUNTIME_ENV_FILE}" \
  ROUTEC_RUNTIME_ENV_JSON_PATH="${ROUTEC_RUNTIME_ENV_JSON_FILE}" \
  ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_PATH="${ROUTEC_LEGACY_RUNTIME_ENV_QUARANTINE_PROOF_FILE}" \
  ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_PATH="${ROUTEC_LEGACY_SPIKE0_SYNAPSE_CLEANUP_PROOF_FILE}" \
  ROUTEC_STACK_DASHBOARD_CREDENTIALS_PROOF_PATH="${STACK_DASHBOARD_CREDENTIALS_PROOF_FILE}" \
  ROUTEC_SERVED_WEB_BUILD_PATH="${ROUTEC_WEB_CHAT_DIST_INDEX}" \
  ROUTEC_HOST_START_SCRIPT_PATH="${ROOT_DIR}/tool_scripts/start_oysterun.sh" \
  ROUTEC_HOST_DB_PATH="${HOST_TRANSCRIPTS_DB_PATH}" \
  ROUTEC_MATRIX_DB_PATH="${MATRIX_DB_PATH}" \
  ROUTEC_SYNAPSE_CONFIG_PATH="${SYNAPSE_CONFIG_PATH}" \
  "${node_bin}" "${ROUTEC_STACK_READINESS_SCRIPT}" "$@"
}

invalidate_routec_stack_readiness() {
  local reason="$1"
  local command_name="${2:-tool_scripts/unknown}"
  run_routec_stack_readiness "${command_name}" invalidate "${reason}"
}

write_current_routec_stack_readiness() {
  local command_name="${1:-tool_scripts/start_oysterun.sh}"
  run_routec_stack_readiness "${command_name}" write-current
}

stop_managed_process() {
  local launch_label="$1"
  local pid_file="$2"
  local label="$3"
  local pid

  clear_stale_pid_file "${pid_file}" "${label}"
  pid=""

  if launchctl_label_exists "${launch_label}"; then
    pid="$(launchctl_pid_for_label "${launch_label}")"
  else
    pid="$(pid_from_file "${pid_file}")"
  fi

  if [[ -z "${pid}" ]]; then
    if launchctl_label_exists "${launch_label}"; then
      echo "[oysterun-service] Removing stale ${label} launchctl job"
      append_service_control_audit "launchctl_remove" "attempt" "reason=stop_managed_process_no_pid;label=${launch_label}"
      launchctl remove "${launch_label}" >/dev/null 2>&1 || true
      append_service_control_audit "launchctl_remove" "done" "reason=stop_managed_process_no_pid;label=${launch_label}"
    fi
    rm -f "${pid_file}"
    echo "[oysterun-service] ${label} is not running"
    return 0
  fi

  if ! pid_is_running "${pid}"; then
    if launchctl_label_exists "${launch_label}"; then
      append_service_control_audit "launchctl_remove" "attempt" "reason=stop_managed_process_stale_pid;label=${launch_label};pid=${pid}"
      launchctl remove "${launch_label}" >/dev/null 2>&1 || true
      append_service_control_audit "launchctl_remove" "done" "reason=stop_managed_process_stale_pid;label=${launch_label};pid=${pid}"
    fi
    rm -f "${pid_file}"
    echo "[oysterun-service] Removed stale ${label} PID file (${pid})"
    return 0
  fi

  echo "[oysterun-service] Stopping ${label} (PID ${pid})..."

  if launchctl_label_exists "${launch_label}"; then
    append_service_control_audit "launchctl_remove" "attempt" "reason=stop_managed_process_running;label=${launch_label};pid=${pid}"
    launchctl remove "${launch_label}" >/dev/null 2>&1 || true
    append_service_control_audit "launchctl_remove" "done" "reason=stop_managed_process_running;label=${launch_label};pid=${pid}"
  else
    append_service_control_audit "process_signal" "attempt" "signal=TERM;label=${launch_label};pid=${pid}"
    kill "${pid}" 2>/dev/null || true
    append_service_control_audit "process_signal" "done" "signal=TERM;label=${launch_label};pid=${pid}"
  fi

  if ! wait_for_exit "${pid}"; then
    echo "[oysterun-service] ${label} did not stop in time; sending SIGKILL"
    append_service_control_audit "process_signal" "attempt" "signal=KILL;label=${launch_label};pid=${pid}"
    kill -9 "${pid}" 2>/dev/null || true
    append_service_control_audit "process_signal" "done" "signal=KILL;label=${launch_label};pid=${pid}"
    wait_for_exit "${pid}" || true
  fi

  rm -f "${pid_file}"
}

cleanup_legacy_home_port_host_jobs_if_needed() {
  if [[ "${STACK_NAME}" != "production" ]]; then
    return
  fi

  stop_managed_process "${LEGACY_HOST_PORT_LABEL}" "${LEGACY_HOST_PORT_PID_FILE}" "legacy Host service" >/dev/null 2>&1 || true
}

cleanup_legacy_home_backend_jobs_if_needed() {
  if [[ "${STACK_NAME}" != "production" ]]; then
    return
  fi

  stop_managed_process "${LEGACY_BACKEND_LABEL}" "${LEGACY_BACKEND_PID_FILE}" "legacy backend" >/dev/null 2>&1 || true
}
