#!/usr/bin/env bash

set -u
set -o pipefail
umask 077

readonly EXIT_USAGE=2
readonly EXIT_DEPENDENCY=3
readonly EXIT_VALIDATION=4
readonly EXIT_CHECKSUM=5
readonly EXIT_DOWNLOAD=6
readonly EXIT_INSTALL=7

if [ "${BASH_VERSINFO[0]}" -lt 3 ] ||
  { [ "${BASH_VERSINFO[0]}" -eq 3 ] && [ "${BASH_VERSINFO[1]}" -lt 2 ]; }; then
  printf '{"status":"failed","code":"unsupported_bash","error":"Sharework requires Bash 3.2 or newer."}\n' >&2
  exit "$EXIT_DEPENDENCY"
fi

AGENT=""
SCOPE=""
PROJECT_DIR=""
ARCHIVE_SOURCE=""
CHECKSUM_SOURCE=""
ARCHIVE_URL=""
JQ_SOURCE=""
JQ_SOURCE_DIGEST=""
LOCAL_JQ=""
WORK_DIRECTORY=""
STAGED_PATH=""
BACKUP_PATH=""
TARGET_PATH=""
LOCK_PATH=""
LOCKED=0
REPLACEMENT_STARTED=0

error_json() {
  local exit_code="$1"
  local code="$2"
  local message="$3"
  if command -v jq >/dev/null 2>&1; then
    jq -cn --arg status "failed" --arg code "$code" --arg error "$message" \
      '{status:$status,code:$code,error:$error}' >&2
  else
    printf '{"status":"failed","code":"%s","error":"%s"}\n' "$code" "$message" >&2
  fi
  exit "$exit_code"
}

cleanup() {
  if [ "$REPLACEMENT_STARTED" -eq 1 ] && [ -n "$BACKUP_PATH" ] && [ -e "$BACKUP_PATH" ]; then
    if [ ! -e "$TARGET_PATH" ]; then
      if mv "$BACKUP_PATH" "$TARGET_PATH" 2>/dev/null; then
        BACKUP_PATH=""
      else
        jq -cn --arg status "recovery_required" --arg code "rollback_failed" --arg backupPath "$BACKUP_PATH" \
          '{status:$status,code:$code,backupPath:$backupPath,error:"Automatic rollback failed. Preserve backupPath and restore it manually."}' >&2
      fi
    fi
  fi
  if [ -n "$STAGED_PATH" ] && [ -e "$STAGED_PATH" ]; then
    rm -rf "$STAGED_PATH"
  fi
  if [ "$REPLACEMENT_STARTED" -eq 0 ] && [ -n "$BACKUP_PATH" ] && [ -e "$BACKUP_PATH" ]; then
    rm -rf "$BACKUP_PATH"
  fi
  if [ "$LOCKED" -eq 1 ] && [ -d "$LOCK_PATH" ]; then
    rmdir "$LOCK_PATH" 2>/dev/null || true
  fi
  if [ -n "$WORK_DIRECTORY" ] && [ -d "$WORK_DIRECTORY" ]; then
    rm -rf "$WORK_DIRECTORY"
  fi
}
trap cleanup EXIT
trap 'exit 130' HUP INT TERM

usage() {
  cat <<'EOF'
Install the verified Sharework skill for one agent.

Download a published release:
  install-sharework.sh --agent AGENT --scope SCOPE --url ARCHIVE_URL

Install an already downloaded release:
  install-sharework.sh --agent AGENT --scope SCOPE --archive FILE --checksum FILE

Options:
  --agent codex|claude-code|cursor|opencode   Required; never defaults to all.
  --scope global|project                     Required.
  --project-dir DIRECTORY                    Required for project scope.
  --url HTTPS_URL                            Downloads URL and URL.sha256.
  --archive FILE --checksum FILE             Verified offline installation.
  --jq-file FILE --jq-sha256 DIGEST          Verified local jq override.

The installer requires Bash 3.2+, curl, jq, tar, gzip, and sha256sum, shasum,
or openssl. It does not require Node, npm, root, or a package-manager change.
Reload the selected agent after a successful install.
EOF
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --agent)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--agent requires a value."
      AGENT="$2"
      shift 2
      ;;
    --scope)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--scope requires a value."
      SCOPE="$2"
      shift 2
      ;;
    --project-dir)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--project-dir requires a value."
      PROJECT_DIR="$2"
      shift 2
      ;;
    --archive)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--archive requires a value."
      ARCHIVE_SOURCE="$2"
      shift 2
      ;;
    --checksum)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--checksum requires a value."
      CHECKSUM_SOURCE="$2"
      shift 2
      ;;
    --url)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--url requires a value."
      ARCHIVE_URL="$2"
      shift 2
      ;;
    --jq-file)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--jq-file requires a value."
      JQ_SOURCE="$2"
      shift 2
      ;;
    --jq-sha256)
      [ "$#" -ge 2 ] || error_json "$EXIT_USAGE" "usage" "--jq-sha256 requires a value."
      JQ_SOURCE_DIGEST="$2"
      shift 2
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      error_json "$EXIT_USAGE" "usage" "Unknown argument. Run with --help for the command syntax."
      ;;
  esac
done

case "$AGENT" in
  codex|claude-code|cursor|opencode) ;;
  "") error_json "$EXIT_USAGE" "usage" "Provide an explicit --agent." ;;
  *) error_json "$EXIT_USAGE" "unsupported_agent" "Unsupported agent. Choose codex, claude-code, cursor, or opencode." ;;
esac
case "$SCOPE" in
  global|project) ;;
  "") error_json "$EXIT_USAGE" "usage" "Provide an explicit --scope." ;;
  *) error_json "$EXIT_USAGE" "unsupported_scope" "Unsupported scope. Choose global or project." ;;
esac

if [ "$SCOPE" = "project" ] && [ -z "$PROJECT_DIR" ]; then
  error_json "$EXIT_USAGE" "usage" "Project scope requires --project-dir."
fi
if [ "$SCOPE" = "project" ]; then
  case "$PROJECT_DIR" in
    /*) ;;
    *) error_json "$EXIT_VALIDATION" "invalid_project" "--project-dir must be an absolute path to an existing directory." ;;
  esac
  [ -d "$PROJECT_DIR" ] || error_json "$EXIT_VALIDATION" "invalid_project" "--project-dir must be an absolute path to an existing directory."
fi
if [ "$SCOPE" = "global" ]; then
  case "${HOME:-}" in
    /*) ;;
    *) error_json "$EXIT_VALIDATION" "invalid_home" "Global scope requires an absolute HOME directory." ;;
  esac
fi
if [ -n "$ARCHIVE_URL" ] && { [ -n "$ARCHIVE_SOURCE" ] || [ -n "$CHECKSUM_SOURCE" ]; }; then
  error_json "$EXIT_USAGE" "usage" "Use either --url or --archive with --checksum, not both."
fi
if [ -z "$ARCHIVE_URL" ] && { [ -z "$ARCHIVE_SOURCE" ] || [ -z "$CHECKSUM_SOURCE" ]; }; then
  error_json "$EXIT_USAGE" "usage" "Provide --url or both --archive and --checksum."
fi
if { [ -n "$JQ_SOURCE" ] && [ -z "$JQ_SOURCE_DIGEST" ]; } ||
  { [ -z "$JQ_SOURCE" ] && [ -n "$JQ_SOURCE_DIGEST" ]; }; then
  error_json "$EXIT_USAGE" "usage" "Use --jq-file and --jq-sha256 together."
fi
if [ -n "$ARCHIVE_URL" ]; then
  case "$ARCHIVE_URL" in
    https://*) ;;
    http://127.0.0.1:*|http://localhost:*|http://\[::1\]:*) ;;
    *) error_json "$EXIT_VALIDATION" "invalid_url" "Use HTTPS, or loopback HTTP for local verification." ;;
  esac
fi

missing=""
for command_name in curl tar gzip awk wc tr sed find sort cmp mktemp mkdir chmod mv cp rm rmdir dirname basename uname; do
  if ! command -v "$command_name" >/dev/null 2>&1; then
    if [ -n "$missing" ]; then missing="$missing, $command_name"; else missing="$command_name"; fi
  fi
done
if ! command -v sha256sum >/dev/null 2>&1 &&
  ! command -v shasum >/dev/null 2>&1 &&
  ! command -v openssl >/dev/null 2>&1; then
  if [ -n "$missing" ]; then missing="$missing, SHA-256 tool"; else missing="SHA-256 tool"; fi
fi
[ -z "$missing" ] || error_json "$EXIT_DEPENDENCY" "missing_dependencies" "Missing required commands: $missing. Install them before installing Sharework."

case "$(uname -s)" in
  Darwin|Linux) ;;
  *) error_json "$EXIT_VALIDATION" "unsupported_platform" "The standalone installer supports macOS and Linux."
esac

sha256_file() {
  if command -v sha256sum >/dev/null 2>&1; then
    sha256sum "$1" | awk '{print $1}'
  elif command -v shasum >/dev/null 2>&1; then
    shasum -a 256 "$1" | awk '{print $1}'
  else
    openssl dgst -sha256 "$1" | sed 's/^.*= //'
  fi
}

case "$SCOPE:$AGENT" in
  global:codex) TARGET_PATH="${CODEX_HOME:-$HOME/.codex}/skills/sharework" ;;
  global:claude-code) TARGET_PATH="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/skills/sharework" ;;
  global:cursor) TARGET_PATH="$HOME/.cursor/skills/sharework" ;;
  global:opencode) TARGET_PATH="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/skills/sharework" ;;
  project:codex|project:cursor|project:opencode) TARGET_PATH="$PROJECT_DIR/.agents/skills/sharework" ;;
  project:claude-code) TARGET_PATH="$PROJECT_DIR/.claude/skills/sharework" ;;
esac
case "$TARGET_PATH" in
  /*) ;;
  *) error_json "$EXIT_VALIDATION" "invalid_destination" "The selected agent destination must be absolute." ;;
esac

WORK_DIRECTORY=$(mktemp -d "${TMPDIR:-/tmp}/sharework-install.XXXXXX") ||
  error_json "$EXIT_INSTALL" "temporary_directory_failed" "Could not create a private temporary directory."
LOCAL_ARCHIVE="$WORK_DIRECTORY/sharework.tar.gz"
LOCAL_CHECKSUM="$WORK_DIRECTORY/sharework.tar.gz.sha256"
EXTRACTED="$WORK_DIRECTORY/extracted"
mkdir "$EXTRACTED" || error_json "$EXIT_INSTALL" "temporary_directory_failed" "Could not prepare the temporary directory."

if ! command -v jq >/dev/null 2>&1; then
  mkdir "$WORK_DIRECTORY/local-bin" || error_json "$EXIT_INSTALL" "temporary_directory_failed" "Could not prepare a local dependency directory."
  LOCAL_JQ="$WORK_DIRECTORY/local-bin/jq"
  if [ -n "$JQ_SOURCE" ]; then
    [ -f "$JQ_SOURCE" ] && [ ! -L "$JQ_SOURCE" ] ||
      error_json "$EXIT_VALIDATION" "invalid_jq" "--jq-file must be a regular file, not a symlink."
    cp "$JQ_SOURCE" "$LOCAL_JQ" || error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not copy the local jq dependency."
    EXPECTED_JQ_DIGEST="$JQ_SOURCE_DIGEST"
  else
    case "$(uname -s):$(uname -m)" in
      Darwin:arm64) JQ_ASSET="jq-macos-arm64"; EXPECTED_JQ_DIGEST="a9fe3ea2f86dfc72f6728417521ec9067b343277152b114f4e98d8cb0e263603" ;;
      Darwin:x86_64) JQ_ASSET="jq-macos-amd64"; EXPECTED_JQ_DIGEST="e80dbe0d2a2597e3c11c404f03337b981d74b4a8504b70586c354b7697a7c27f" ;;
      Linux:aarch64|Linux:arm64) JQ_ASSET="jq-linux-arm64"; EXPECTED_JQ_DIGEST="6bc62f25981328edd3cfcfe6fe51b073f2d7e7710d7ef7fcdac28d4e384fc3d4" ;;
      Linux:x86_64|Linux:amd64) JQ_ASSET="jq-linux-amd64"; EXPECTED_JQ_DIGEST="020468de7539ce70ef1bceaf7cde2e8c4f2ca6c3afb84642aabc5c97d9fc2a0d" ;;
      *) error_json "$EXIT_DEPENDENCY" "unsupported_jq_platform" "No checksum-pinned local jq build is available for this OS and architecture." ;;
    esac
    curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' \
      --output "$LOCAL_JQ.part" "https://github.com/jqlang/jq/releases/download/jq-1.8.1/$JQ_ASSET" ||
      error_json "$EXIT_DOWNLOAD" "dependency_download_failed" "The checksum-pinned jq dependency download did not complete."
    mv "$LOCAL_JQ.part" "$LOCAL_JQ" || error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not finalize the local jq dependency."
  fi
  case "$EXPECTED_JQ_DIGEST" in
    *[!0-9a-fA-F]*|"") error_json "$EXIT_CHECKSUM" "invalid_jq_checksum" "The local jq checksum is not a SHA-256 digest." ;;
  esac
  [ "${#EXPECTED_JQ_DIGEST}" -eq 64 ] || error_json "$EXIT_CHECKSUM" "invalid_jq_checksum" "The local jq checksum is not a SHA-256 digest."
  ACTUAL_JQ_DIGEST=$(sha256_file "$LOCAL_JQ") || error_json "$EXIT_CHECKSUM" "checksum_failed" "Could not calculate the local jq checksum."
  [ "$ACTUAL_JQ_DIGEST" = "$EXPECTED_JQ_DIGEST" ] || error_json "$EXIT_CHECKSUM" "jq_checksum_mismatch" "The local jq dependency does not match its pinned SHA-256 checksum."
  chmod 755 "$LOCAL_JQ" || error_json "$EXIT_INSTALL" "permission_failed" "Could not make the verified local jq dependency executable."
  PATH="$WORK_DIRECTORY/local-bin:$PATH"
  export PATH
  jq --version >/dev/null 2>&1 || error_json "$EXIT_DEPENDENCY" "invalid_jq" "The verified local jq dependency cannot run on this platform."
fi

if [ -n "$ARCHIVE_URL" ]; then
  curl --fail --silent --show-error --location --proto '=https,http' --proto-redir '=https' --output "$LOCAL_ARCHIVE.part" "$ARCHIVE_URL" ||
    error_json "$EXIT_DOWNLOAD" "download_failed" "The Sharework archive download did not complete."
  mv "$LOCAL_ARCHIVE.part" "$LOCAL_ARCHIVE" ||
    error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not finalize the downloaded archive."
  curl --fail --silent --show-error --location --proto '=https,http' --proto-redir '=https' --output "$LOCAL_CHECKSUM.part" "$ARCHIVE_URL.sha256" ||
    error_json "$EXIT_DOWNLOAD" "download_failed" "The Sharework checksum download did not complete."
  mv "$LOCAL_CHECKSUM.part" "$LOCAL_CHECKSUM" ||
    error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not finalize the downloaded checksum."
else
  [ -f "$ARCHIVE_SOURCE" ] && [ ! -L "$ARCHIVE_SOURCE" ] ||
    error_json "$EXIT_VALIDATION" "invalid_archive" "The local archive must be a regular file, not a symlink."
  [ -f "$CHECKSUM_SOURCE" ] && [ ! -L "$CHECKSUM_SOURCE" ] ||
    error_json "$EXIT_VALIDATION" "invalid_checksum" "The local checksum must be a regular file, not a symlink."
  cp "$ARCHIVE_SOURCE" "$LOCAL_ARCHIVE" ||
    error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not copy the local archive."
  cp "$CHECKSUM_SOURCE" "$LOCAL_CHECKSUM" ||
    error_json "$EXIT_INSTALL" "temporary_file_failed" "Could not copy the local checksum."
fi

EXPECTED_DIGEST=$(awk 'NR == 1 {print $1}' "$LOCAL_CHECKSUM")
case "$EXPECTED_DIGEST" in
  *[!0-9a-fA-F]*|"") error_json "$EXIT_CHECKSUM" "invalid_checksum" "The release checksum is not a SHA-256 digest." ;;
esac
[ "${#EXPECTED_DIGEST}" -eq 64 ] || error_json "$EXIT_CHECKSUM" "invalid_checksum" "The release checksum is not a SHA-256 digest."
ACTUAL_DIGEST=$(sha256_file "$LOCAL_ARCHIVE") ||
  error_json "$EXIT_CHECKSUM" "checksum_failed" "Could not calculate the archive checksum."
[ "$ACTUAL_DIGEST" = "$EXPECTED_DIGEST" ] ||
  error_json "$EXIT_CHECKSUM" "checksum_mismatch" "The archive does not match its published SHA-256 checksum."

ARCHIVE_LIST="$WORK_DIRECTORY/archive-list"
tar -tzf "$LOCAL_ARCHIVE" > "$ARCHIVE_LIST" 2>/dev/null ||
  error_json "$EXIT_VALIDATION" "invalid_archive" "The downloaded file is not a readable gzip tar archive."
while IFS= read -r archive_path; do
  case "$archive_path" in
    sharework|sharework/|sharework/*) ;;
    *) error_json "$EXIT_VALIDATION" "unsafe_archive" "The archive contains a path outside the Sharework skill." ;;
  esac
  case "/$archive_path/" in
    */../*|*/./*) error_json "$EXIT_VALIDATION" "unsafe_archive" "The archive contains an unsafe path." ;;
  esac
done < "$ARCHIVE_LIST"
tar -xzf "$LOCAL_ARCHIVE" -C "$EXTRACTED" 2>/dev/null ||
  error_json "$EXIT_VALIDATION" "invalid_archive" "The Sharework archive could not be extracted."
[ -z "$(find "$EXTRACTED" ! -type d ! -type f -print)" ] ||
  error_json "$EXIT_VALIDATION" "unsafe_archive" "The archive contains a special filesystem entry."

SOURCE="$EXTRACTED/sharework"
[ -f "$SOURCE/SKILL.md" ] && [ -f "$SOURCE/manifest.json" ] && [ -f "$SOURCE/checksums.sha256" ] ||
  error_json "$EXIT_VALIDATION" "invalid_bundle" "The archive is missing required Sharework metadata."
NAME=$(jq -er '.name' "$SOURCE/manifest.json" 2>/dev/null) ||
  error_json "$EXIT_VALIDATION" "invalid_manifest" "The bundle manifest is not valid JSON."
VERSION=$(jq -er '.version | select(test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))' "$SOURCE/manifest.json" 2>/dev/null) ||
  error_json "$EXIT_VALIDATION" "invalid_manifest" "The bundle manifest has no version."
[ "$NAME" = "sharework" ] || error_json "$EXIT_VALIDATION" "invalid_manifest" "The bundle name is not sharework."

MANIFEST_LINES="$WORK_DIRECTORY/manifest-lines"
jq -er '.files[] | [.path, .sha256, (.size | tostring), (.mode | tostring)] | @tsv' \
  "$SOURCE/manifest.json" > "$MANIFEST_LINES" 2>/dev/null ||
  error_json "$EXIT_VALIDATION" "invalid_manifest" "The bundle manifest file list is invalid."
[ -s "$MANIFEST_LINES" ] || error_json "$EXIT_VALIDATION" "invalid_manifest" "The bundle manifest has no files."
while IFS="$(printf '\t')" read -r relative expected size mode; do
  case "$relative" in
    SKILL.md|references/*.md|scripts/*.sh) ;;
    *) error_json "$EXIT_VALIDATION" "invalid_manifest" "The manifest contains a file outside the public skill surface." ;;
  esac
  case "/$relative/" in
    */../*|*/./*) error_json "$EXIT_VALIDATION" "invalid_manifest" "The manifest contains an unsafe path." ;;
  esac
  file="$SOURCE/$relative"
  [ -f "$file" ] && [ ! -L "$file" ] || error_json "$EXIT_VALIDATION" "invalid_bundle" "A declared bundle file is missing or unsafe."
  actual=$(sha256_file "$file") || error_json "$EXIT_CHECKSUM" "checksum_failed" "Could not verify a bundled file."
  [ "$actual" = "$expected" ] || error_json "$EXIT_CHECKSUM" "checksum_mismatch" "A bundled file does not match the manifest."
  actual_size=$(wc -c < "$file" | tr -d ' ')
  [ "$actual_size" = "$size" ] || error_json "$EXIT_CHECKSUM" "checksum_mismatch" "A bundled file has the wrong size."
  case "$mode" in
    420) permission=644 ;;
    493) permission=755 ;;
    *) error_json "$EXIT_VALIDATION" "invalid_manifest" "A bundled file has an unsupported permission mode." ;;
  esac
  chmod "$permission" "$file" || error_json "$EXIT_INSTALL" "permission_failed" "Could not set a bundled file's permissions."
done < "$MANIFEST_LINES"

MANIFEST_DIGEST=$(sha256_file "$SOURCE/manifest.json")
EXPECTED_INTERNAL="$WORK_DIRECTORY/expected-checksums"
while IFS="$(printf '\t')" read -r relative expected _size _mode; do
  printf '%s  %s\n' "$expected" "$relative"
done < "$MANIFEST_LINES" > "$EXPECTED_INTERNAL"
printf '%s  manifest.json\n' "$MANIFEST_DIGEST" >> "$EXPECTED_INTERNAL"
if ! cmp -s "$EXPECTED_INTERNAL" "$SOURCE/checksums.sha256"; then
  error_json "$EXIT_CHECKSUM" "checksum_mismatch" "The bundle manifest does not match its internal checksum."
fi
while IFS= read -r bundled_file; do
  relative=${bundled_file#"$SOURCE/"}
  case "$relative" in
    manifest.json|checksums.sha256) ;;
    *)
      jq -e --arg path "$relative" 'any(.files[]; .path == $path)' "$SOURCE/manifest.json" >/dev/null 2>&1 ||
        error_json "$EXIT_VALIDATION" "invalid_bundle" "The archive contains an undeclared file."
      ;;
  esac
done <<EOF
$(find "$SOURCE" -type f -print | sort)
EOF

if [ -n "$LOCAL_JQ" ]; then
  mkdir "$SOURCE/bin" || error_json "$EXIT_INSTALL" "dependency_install_failed" "Could not prepare the skill's local dependency directory."
  cp "$LOCAL_JQ" "$SOURCE/bin/jq" || error_json "$EXIT_INSTALL" "dependency_install_failed" "Could not install the verified local jq dependency."
  chmod 755 "$SOURCE/bin/jq" || error_json "$EXIT_INSTALL" "permission_failed" "Could not set local jq permissions."
  printf '%s  jq\n' "$EXPECTED_JQ_DIGEST" > "$SOURCE/bin/jq.sha256"
fi

PARENT=$(dirname "$TARGET_PATH")
mkdir -p "$PARENT" || error_json "$EXIT_INSTALL" "destination_failed" "Could not create the selected agent skill directory."
[ ! -L "$TARGET_PATH" ] || error_json "$EXIT_VALIDATION" "unsafe_destination" "The existing Sharework destination is a symbolic link."
[ ! -e "$TARGET_PATH" ] || [ -d "$TARGET_PATH" ] || error_json "$EXIT_VALIDATION" "unsafe_destination" "The existing Sharework destination is not a directory."
LOCK_PATH="$PARENT/.sharework.install.lock"
mkdir "$LOCK_PATH" 2>/dev/null || error_json "$EXIT_INSTALL" "install_locked" "Another Sharework installation is changing this destination."
LOCKED=1
STAGED_PATH="$PARENT/.sharework.install.$$"
BACKUP_PATH="$PARENT/.sharework.backup.$$"
mv "$SOURCE" "$STAGED_PATH" || error_json "$EXIT_INSTALL" "staging_failed" "Could not stage the verified skill."
if [ -e "$TARGET_PATH" ]; then
  REPLACEMENT_STARTED=1
  mv "$TARGET_PATH" "$BACKUP_PATH" || error_json "$EXIT_INSTALL" "replacement_failed" "Could not preserve the existing Sharework skill."
fi
mv "$STAGED_PATH" "$TARGET_PATH" || error_json "$EXIT_INSTALL" "replacement_failed" "Could not activate the verified Sharework skill."
STAGED_PATH=""
REPLACEMENT_STARTED=0
if [ -e "$BACKUP_PATH" ]; then
  rm -rf "$BACKUP_PATH" || error_json "$EXIT_INSTALL" "cleanup_failed" "Sharework was installed, but the prior copy could not be removed."
fi
BACKUP_PATH=""

jq -cn \
  --arg status "installed" \
  --arg agent "$AGENT" \
  --arg scope "$SCOPE" \
  --arg version "$VERSION" \
  --arg path "$TARGET_PATH" \
  '{status:$status,agent:$agent,scope:$scope,version:$version,path:$path,reloadRequired:true}'
