#!/usr/bin/env bash
set -euo pipefail

readonly script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
readonly seed_script="$script_dir/seed-projects.sh"
readonly entrypoint="$script_dir/entrypoint.sh"
readonly test_root="$(mktemp -d)"

cleanup() {
  rm -rf -- "$test_root"
}
trap cleanup EXIT

fail() {
  echo "FAIL: $*" >&2
  exit 1
}

assert_exists() {
  [[ -e "$1" ]] || fail "expected path to exist: $1"
}

assert_not_exists() {
  [[ ! -e "$1" && ! -L "$1" ]] || fail "expected path not to exist: $1"
}

assert_equals() {
  [[ "$1" == "$2" ]] || fail "expected '$1' to equal '$2'"
}

assert_no_staging_entries() {
  local root="$1"
  local staging_entry

  staging_entry="$(find "$root" -mindepth 1 -maxdepth 1 \
    -name '.agent-sidecar-tmp-agent-codex-seed-*' \
    ! -name '.agent-sidecar-tmp-agent-codex-seed-lock' \
    -print -quit)"
  [[ -z "$staging_entry" ]] || fail "unexpected staging entry: $staging_entry"
}

expect_failure() {
  if "$@" >"$test_root/expected-failure.stdout" 2>"$test_root/expected-failure.stderr"; then
    fail "command unexpectedly succeeded: $*"
  fi
}

assert_new_git_repository() {
  local project_dir="$1"

  [[ -d "$project_dir/.git" ]] || fail "expected Git directory: $project_dir/.git"
  assert_equals "$(git -C "$project_dir" rev-parse --show-toplevel)" "$project_dir"
  assert_equals "$(git -C "$project_dir" symbolic-ref --short HEAD)" "main"
  assert_equals "$(git -C "$project_dir" ls-files)" ""
  expect_failure git -C "$project_dir" rev-parse --verify HEAD
}

new_case() {
  local name="$1"
  local case_dir="$test_root/$name"

  mkdir -p "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  printf '%s\n' "$case_dir"
}

test_initial_seed_and_idempotency() {
  local case_dir
  case_dir="$(new_case initial-seed)"

  mkdir -p "$case_dir/source/alpha/bin" "$case_dir/source/beta"
  printf 'alpha\n' >"$case_dir/source/alpha/README.md"
  printf 'hidden\n' >"$case_dir/source/alpha/.hidden"
  printf '#!/usr/bin/env bash\n' >"$case_dir/source/alpha/bin/run"
  chmod 0751 "$case_dir/source/alpha/bin/run"
  printf 'beta\n' >"$case_dir/source/beta/value"
  printf 'source metadata\n' >"$case_dir/source/README.md"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$case_dir/projects/alpha/README.md")" "alpha"
  assert_equals "$(<"$case_dir/projects/alpha/.hidden")" "hidden"
  assert_equals "$(stat -c '%a' "$case_dir/projects/alpha/bin/run")" "751"
  assert_equals "$(<"$case_dir/projects/beta/value")" "beta"
  assert_not_exists "$case_dir/projects/README.md"
  assert_new_git_repository "$case_dir/projects/alpha"
  assert_new_git_repository "$case_dir/projects/beta"

  printf 'user change\n' >"$case_dir/projects/alpha/README.md"
  git -C "$case_dir/projects/alpha" symbolic-ref HEAD refs/heads/custom
  git -C "$case_dir/projects/alpha" config seed.marker preserved
  git -C "$case_dir/projects/alpha" add README.md
  printf 'image update\n' >"$case_dir/source/alpha/README.md"
  mkdir -p "$case_dir/source/gamma"
  printf 'new project\n' >"$case_dir/source/gamma/value"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$case_dir/projects/alpha/README.md")" "user change"
  assert_equals "$(git -C "$case_dir/projects/alpha" symbolic-ref --short HEAD)" "custom"
  assert_equals "$(git -C "$case_dir/projects/alpha" config seed.marker)" "preserved"
  assert_equals "$(git -C "$case_dir/projects/alpha" show :README.md)" "user change"
  assert_equals "$(<"$case_dir/projects/gamma/value")" "new project"
  assert_new_git_repository "$case_dir/projects/gamma"
  assert_no_staging_entries "$case_dir/projects"
}

test_existing_project_without_git_is_skipped() {
  local case_dir
  case_dir="$(new_case existing-project-without-git)"
  mkdir -p "$case_dir/source/alpha" "$case_dir/projects/alpha"
  printf 'seed\n' >"$case_dir/source/alpha/value"
  printf 'existing\n' >"$case_dir/projects/alpha/value"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$case_dir/projects/alpha/value")" "existing"
  assert_not_exists "$case_dir/projects/alpha/.git"
  assert_no_staging_entries "$case_dir/projects"
}

test_empty_source_and_stale_cleanup() {
  local case_dir
  case_dir="$(new_case empty-source)"

  printf 'metadata\n' >"$case_dir/source/README.md"
  mkdir -p "$case_dir/source/__global__/skills"
  mkdir -p "$case_dir/projects/.agent-sidecar-tmp-agent-codex-seed-stale"
  printf 'partial\n' >"$case_dir/projects/.agent-sidecar-tmp-agent-codex-seed-stale/value"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_not_exists "$case_dir/projects/.agent-sidecar-tmp-agent-codex-seed-stale"
  assert_no_staging_entries "$case_dir/projects"
}

test_invalid_project_name() {
  local case_dir
  case_dir="$(new_case invalid-name)"
  mkdir -p "$case_dir/source/bad name"

  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/projects/bad name"
}

test_destination_conflicts() {
  local case_dir
  case_dir="$(new_case destination-file)"
  mkdir -p "$case_dir/source/alpha"
  printf 'conflict\n' >"$case_dir/projects/alpha"

  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case destination-symlink)"
  mkdir -p "$case_dir/source/alpha" "$case_dir/elsewhere"
  ln -s "$case_dir/elsewhere" "$case_dir/projects/alpha"

  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
}

test_rejects_source_symlinks_and_special_files() {
  local case_dir
  case_dir="$(new_case source-symlink)"
  mkdir -p "$case_dir/source/alpha"
  ln -s /tmp "$case_dir/source/alpha/link"

  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/projects/alpha"

  case_dir="$(new_case source-special-file)"
  mkdir -p "$case_dir/source/alpha"
  mkfifo "$case_dir/source/alpha/pipe"

  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/projects/alpha"
}

test_copy_failure_cleans_staging_directory() {
  local case_dir
  local mock_bin
  case_dir="$(new_case copy-failure)"
  mock_bin="$case_dir/mock-bin"
  mkdir -p "$case_dir/source/alpha" "$mock_bin"
  printf 'value\n' >"$case_dir/source/alpha/value"

  cat >"$mock_bin/cp" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
destination="${!#}"
printf 'partial\n' >"$destination/partial"
exit 1
EOF
  chmod 0755 "$mock_bin/cp"

  expect_failure env PATH="$mock_bin:$PATH" \
    "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/projects/alpha"
  assert_no_staging_entries "$case_dir/projects"
}

test_git_init_failure_cleans_staging_directory() {
  local case_dir
  local mock_bin
  case_dir="$(new_case git-init-failure)"
  mock_bin="$case_dir/mock-bin"
  mkdir -p "$case_dir/source/alpha" "$mock_bin"
  printf 'value\n' >"$case_dir/source/alpha/value"

  cat >"$mock_bin/git" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
destination="${!#}"
mkdir -p "$destination/.git"
printf 'partial\n' >"$destination/.git/HEAD"
exit 23
EOF
  chmod 0755 "$mock_bin/git"

  expect_failure env PATH="$mock_bin:$PATH" \
    "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/projects/alpha"
  assert_no_staging_entries "$case_dir/projects"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_equals "$(<"$case_dir/projects/alpha/value")" "value"
  assert_new_git_repository "$case_dir/projects/alpha"
}

test_concurrent_seeders_do_not_overwrite() {
  local case_dir
  local first_pid
  local second_pid
  case_dir="$(new_case concurrent)"
  mkdir -p "$case_dir/source/alpha"
  printf 'complete\n' >"$case_dir/source/alpha/value"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home" >"$case_dir/first.log" &
  first_pid=$!
  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home" >"$case_dir/second.log" &
  second_pid=$!
  wait "$first_pid"
  wait "$second_pid"

  assert_equals "$(<"$case_dir/projects/alpha/value")" "complete"
  assert_new_git_repository "$case_dir/projects/alpha"
  assert_no_staging_entries "$case_dir/projects"
}

test_global_seed_and_idempotency() {
  local case_dir
  case_dir="$(new_case global-seed)"

  mkdir -p \
    "$case_dir/source/__global__/skills/alpha/bin" \
    "$case_dir/source/__global__/skills/beta"
  printf 'global instructions\n' >"$case_dir/source/__global__/AGENTS.md"
  chmod 0640 "$case_dir/source/__global__/AGENTS.md"
  printf '%s\n' '---' 'name: alpha' 'description: Alpha skill.' '---' \
    >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  printf 'hidden\n' >"$case_dir/source/__global__/skills/alpha/.hidden"
  printf '#!/usr/bin/env bash\n' >"$case_dir/source/__global__/skills/alpha/bin/run"
  chmod 0751 "$case_dir/source/__global__/skills/alpha/bin/run"
  printf '%s\n' '---' 'name: beta' 'description: Beta skill.' '---' \
    >"$case_dir/source/__global__/skills/beta/SKILL.md"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$case_dir/codex-home/AGENTS.md")" "global instructions"
  assert_equals "$(stat -c '%a' "$case_dir/codex-home/AGENTS.md")" "640"
  assert_equals "$(<"$case_dir/codex-home/skills/alpha/.hidden")" "hidden"
  assert_equals "$(stat -c '%a' "$case_dir/codex-home/skills/alpha/bin/run")" "751"
  assert_exists "$case_dir/codex-home/skills/beta/SKILL.md"
  assert_not_exists "$case_dir/projects/__global__"

  printf 'user instructions\n' >"$case_dir/codex-home/AGENTS.md"
  printf 'user skill\n' >"$case_dir/codex-home/skills/alpha/SKILL.md"
  printf 'image update\n' >"$case_dir/source/__global__/AGENTS.md"
  printf 'image skill update\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  mkdir -p "$case_dir/source/__global__/skills/gamma"
  printf '%s\n' '---' 'name: gamma' 'description: Gamma skill.' '---' \
    >"$case_dir/source/__global__/skills/gamma/SKILL.md"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$case_dir/codex-home/AGENTS.md")" "user instructions"
  assert_equals "$(<"$case_dir/codex-home/skills/alpha/SKILL.md")" "user skill"
  assert_exists "$case_dir/codex-home/skills/gamma/SKILL.md"
  assert_equals "$(find "$case_dir/codex-home" -name .git -print -quit)" ""
  assert_no_staging_entries "$case_dir/codex-home"
  assert_no_staging_entries "$case_dir/codex-home/skills"
}

test_grouped_global_seed_and_idempotency() {
  local case_dir
  case_dir="$(new_case global-grouped-seed)"
  local source_group="$case_dir/source/__global__/skills/lark-cli"
  local destination_group="$case_dir/codex-home/skills/lark-cli"

  mkdir -p "$source_group/alpha/scripts" "$source_group/nested/beta"
  printf 'alpha skill\n' >"$source_group/alpha/SKILL.md"
  printf 'beta skill\n' >"$source_group/nested/beta/SKILL.md"
  printf '#!/usr/bin/env bash\n' >"$source_group/alpha/scripts/run"
  chmod 0751 "$source_group/alpha/scripts/run"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$destination_group/alpha/SKILL.md")" "alpha skill"
  assert_exists "$destination_group/nested/beta/SKILL.md"
  assert_equals "$(stat -c '%a' "$destination_group/alpha/scripts/run")" "751"
  assert_not_exists "$case_dir/codex-home/skills/alpha"

  printf 'user skill\n' >"$destination_group/alpha/SKILL.md"
  printf 'image update\n' >"$source_group/alpha/SKILL.md"
  mkdir -p "$source_group/gamma"
  printf 'gamma skill\n' >"$source_group/gamma/SKILL.md"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_equals "$(<"$destination_group/alpha/SKILL.md")" "user skill"
  assert_not_exists "$destination_group/gamma"
  assert_no_staging_entries "$case_dir/codex-home/skills"
}

test_rejects_invalid_global_sources() {
  local case_dir

  case_dir="$(new_case global-unsupported-entry)"
  mkdir -p "$case_dir/source/__global__"
  printf 'unsupported\n' >"$case_dir/source/__global__/README.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skill-file)"
  mkdir -p "$case_dir/source/__global__/skills"
  printf 'not a directory\n' >"$case_dir/source/__global__/skills/alpha"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-missing-skill-file)"
  mkdir -p "$case_dir/source/__global__/skills/alpha"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-nested-missing-skill)"
  mkdir -p "$case_dir/source/__global__/skills/builtin/alpha"
  printf 'reference\n' >"$case_dir/source/__global__/skills/builtin/alpha/README.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-nested-skill-symlink)"
  mkdir -p "$case_dir/source/__global__/skills/builtin/alpha"
  printf 'skill\n' >"$case_dir/skill.md"
  ln -s "$case_dir/skill.md" "$case_dir/source/__global__/skills/builtin/alpha/SKILL.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-invalid-skill-name)"
  mkdir -p "$case_dir/source/__global__/skills/bad name"
  printf 'skill\n' >"$case_dir/source/__global__/skills/bad name/SKILL.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-agents-symlink)"
  mkdir -p "$case_dir/source/__global__"
  ln -s /tmp "$case_dir/source/__global__/AGENTS.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skill-special-file)"
  mkdir -p "$case_dir/source/__global__/skills/alpha"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  mkfifo "$case_dir/source/__global__/skills/alpha/pipe"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
}

test_global_destination_conflicts() {
  local case_dir

  case_dir="$(new_case codex-home-symlink)"
  mkdir -p "$case_dir/elsewhere"
  rm -rf -- "$case_dir/codex-home"
  ln -s "$case_dir/elsewhere" "$case_dir/codex-home"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skills-file)"
  printf 'conflict\n' >"$case_dir/codex-home/skills"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skills-symlink)"
  mkdir -p "$case_dir/elsewhere"
  ln -s "$case_dir/elsewhere" "$case_dir/codex-home/skills"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-agents-directory)"
  mkdir -p "$case_dir/source/__global__" "$case_dir/codex-home/AGENTS.md"
  printf 'instructions\n' >"$case_dir/source/__global__/AGENTS.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-agents-symlink-conflict)"
  mkdir -p "$case_dir/source/__global__" "$case_dir/elsewhere"
  printf 'instructions\n' >"$case_dir/source/__global__/AGENTS.md"
  ln -s "$case_dir/elsewhere" "$case_dir/codex-home/AGENTS.md"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skill-file-conflict)"
  mkdir -p "$case_dir/source/__global__/skills/alpha" "$case_dir/codex-home/skills"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  printf 'conflict\n' >"$case_dir/codex-home/skills/alpha"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  case_dir="$(new_case global-skill-symlink-conflict)"
  mkdir -p \
    "$case_dir/source/__global__/skills/alpha" \
    "$case_dir/codex-home/skills" \
    "$case_dir/elsewhere"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  ln -s "$case_dir/elsewhere" "$case_dir/codex-home/skills/alpha"
  expect_failure "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
}

test_global_stale_cleanup_and_copy_failure() {
  local case_dir
  local mock_bin

  case_dir="$(new_case global-stale-cleanup)"
  mkdir -p "$case_dir/source/__global__/skills/alpha" "$case_dir/codex-home/skills"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  printf 'partial\n' >"$case_dir/codex-home/.agent-sidecar-tmp-agent-codex-seed-global-AGENTS.md.stale"
  mkdir -p "$case_dir/codex-home/skills/.agent-sidecar-tmp-agent-codex-seed-global-skill-stale"
  printf 'keep\n' >"$case_dir/codex-home/.agent-sidecar-tmp-agent-codex-other"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"

  assert_no_staging_entries "$case_dir/codex-home"
  assert_no_staging_entries "$case_dir/codex-home/skills"
  assert_exists "$case_dir/codex-home/.agent-sidecar-tmp-agent-codex-other"

  case_dir="$(new_case global-copy-failure)"
  mock_bin="$case_dir/mock-bin"
  mkdir -p "$case_dir/source/__global__/skills/alpha" "$mock_bin"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"

  cat >"$mock_bin/cp" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
destination="${!#}"
printf 'partial\n' >"$destination/partial"
exit 1
EOF
  chmod 0755 "$mock_bin/cp"

  expect_failure env PATH="$mock_bin:$PATH" \
    "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home"
  assert_not_exists "$case_dir/codex-home/skills/alpha"
  assert_no_staging_entries "$case_dir/codex-home/skills"
}

test_concurrent_global_seeders_do_not_overwrite() {
  local case_dir
  local first_pid
  local second_pid
  case_dir="$(new_case global-concurrent)"
  mkdir -p "$case_dir/source/__global__/skills/alpha"
  printf 'skill\n' >"$case_dir/source/__global__/skills/alpha/SKILL.md"
  printf 'instructions\n' >"$case_dir/source/__global__/AGENTS.md"

  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home" >"$case_dir/first.log" &
  first_pid=$!
  "$seed_script" "$case_dir/source" "$case_dir/projects" "$case_dir/codex-home" >"$case_dir/second.log" &
  second_pid=$!
  wait "$first_pid"
  wait "$second_pid"

  assert_equals "$(<"$case_dir/codex-home/AGENTS.md")" "instructions"
  assert_equals "$(<"$case_dir/codex-home/skills/alpha/SKILL.md")" "skill"
  assert_no_staging_entries "$case_dir/codex-home"
  assert_no_staging_entries "$case_dir/codex-home/skills"
}

write_entrypoint_mocks() {
  local mock_bin="$1"
  mkdir -p "$mock_bin"

  cat >"$mock_bin/agent-codex-seed-projects" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' "$@" >"$TEST_OUTPUT_DIR/seed-args"
if [[ -v CODEX_APP_SERVER_TOKEN ]]; then
  printf 'set\n' >"$TEST_OUTPUT_DIR/seed-token"
else
  printf 'unset\n' >"$TEST_OUTPUT_DIR/seed-token"
fi
exit "${MOCK_SEED_EXIT:-0}"
EOF

  cat >"$mock_bin/codex" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' "$@" >"$TEST_OUTPUT_DIR/codex-args"
if [[ -v CODEX_APP_SERVER_TOKEN ]]; then
  printf 'set\n' >"$TEST_OUTPUT_DIR/codex-token"
else
  printf 'unset\n' >"$TEST_OUTPUT_DIR/codex-token"
fi
EOF

  chmod 0755 "$mock_bin/agent-codex-seed-projects" "$mock_bin/codex"
}

test_entrypoint_success() {
  local case_dir="$test_root/entrypoint-success"
  local mock_bin="$case_dir/mock-bin"
  local expected_hash
  local -a args
  mkdir -p "$case_dir"
  write_entrypoint_mocks "$mock_bin"

  PATH="$mock_bin:$PATH" TEST_OUTPUT_DIR="$case_dir" CODEX_APP_SERVER_TOKEN="secret" \
    PROJECTS_ROOT_DIR="/custom/projects" CODEX_HOME="/custom/codex-home" \
    bash "$entrypoint" --listen ws://test --strict-config

  mapfile -t args <"$case_dir/seed-args"
  assert_equals "${#args[@]}" "3"
  assert_equals "${args[0]}" "/opt/agent-codex/project-seeds"
  assert_equals "${args[1]}" "/custom/projects"
  assert_equals "${args[2]}" "/custom/codex-home"
  assert_equals "$(<"$case_dir/seed-token")" "unset"
  assert_equals "$(<"$case_dir/codex-token")" "unset"

  expected_hash="$(printf '%s' 'secret' | sha256sum)"
  expected_hash="${expected_hash%% *}"
  mapfile -t args <"$case_dir/codex-args"
  assert_equals "${#args[@]}" "8"
  assert_equals "${args[0]}" "app-server"
  assert_equals "${args[1]}" "--ws-auth"
  assert_equals "${args[2]}" "capability-token"
  assert_equals "${args[3]}" "--ws-token-sha256"
  assert_equals "${args[4]}" "$expected_hash"
  assert_equals "${args[5]}" "--listen"
  assert_equals "${args[6]}" "ws://test"
  assert_equals "${args[7]}" "--strict-config"
}

test_entrypoint_failures() {
  local case_dir="$test_root/entrypoint-failures"
  local mock_bin="$case_dir/mock-bin"
  mkdir -p "$case_dir"
  write_entrypoint_mocks "$mock_bin"

  expect_failure env PATH="$mock_bin:$PATH" TEST_OUTPUT_DIR="$case_dir" bash "$entrypoint"
  assert_not_exists "$case_dir/seed-args"
  assert_not_exists "$case_dir/codex-args"

  expect_failure env PATH="$mock_bin:$PATH" TEST_OUTPUT_DIR="$case_dir" \
    MOCK_SEED_EXIT=23 CODEX_APP_SERVER_TOKEN=secret \
    PROJECTS_ROOT_DIR=/custom/projects CODEX_HOME=/custom/codex-home bash "$entrypoint"
  assert_exists "$case_dir/seed-args"
  assert_not_exists "$case_dir/codex-args"
}

test_initial_seed_and_idempotency
test_existing_project_without_git_is_skipped
test_empty_source_and_stale_cleanup
test_invalid_project_name
test_destination_conflicts
test_rejects_source_symlinks_and_special_files
test_copy_failure_cleans_staging_directory
test_git_init_failure_cleans_staging_directory
test_concurrent_seeders_do_not_overwrite
test_global_seed_and_idempotency
test_grouped_global_seed_and_idempotency
test_rejects_invalid_global_sources
test_global_destination_conflicts
test_global_stale_cleanup_and_copy_failure
test_concurrent_global_seeders_do_not_overwrite
test_entrypoint_success
test_entrypoint_failures

echo "All Agent Codex project seeding tests passed."
