#!/usr/bin/env bash
# FILE-SIZE-OK — single audit script; splitting would lose the "32 cases in
# one run" semantics that makes this useful. Each Group is self-contained
# but they share setup helpers (reset, put_contract, put_loop, probes).
#
# test-edge-cases.sh — Anti-fragility audit (v16.9.0).
#
# Probes 30+ edge cases across the autoloop lifecycle:
#   A. Input validation (start, hook stdin, env)            — 8 cases
#   B. State corruption (registry, heartbeat, provenance)   — 6 cases
#   C. Concurrency / races                                   — 4 cases
#   D. Hook payload malformations                            — 6 cases
#   E. Cleanup races + idempotency                           — 6 cases
#   F. Cross-platform / portability                          — 2 cases
# Total: 32 cases.
#
# Each case asserts the system either (a) handles correctly OR (b) fails
# loud with provenance — never silently does the wrong thing.
# shellcheck disable=SC2329

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(dirname "$SCRIPT_DIR")"
HOOKS="$PLUGIN_DIR/hooks"
SCRIPTS="$PLUGIN_DIR/scripts"

TEMP_DIR=$(mktemp -d)
# Wave 6.2: canonicalize via pwd -P. C1 race test passes CDIR (under
# TEMP_DIR) as cwd; session-bind.sh canonicalizes cwd via pwd -P, so
# without this fixture-side normalization the macOS /var/folders →
# /private/var/folders symlink divergence makes the path-hierarchy
# predicate miss the registered loop and the race test silently
# reports "no winner".
TEMP_DIR=$(cd "$TEMP_DIR" && pwd -P)
export HOME="$TEMP_DIR/home"
mkdir -p "$HOME/.claude/loops" "$HOME/Library/LaunchAgents"
export CLAUDE_LOOPS_REGISTRY="$HOME/.claude/loops/registry.json"
export PROVENANCE_GLOBAL_DIR="$HOME/.claude/loops"
export PROVENANCE_GLOBAL_FILE="$PROVENANCE_GLOBAL_DIR/global-provenance.jsonl"

# Stub launchctl
STUB_BIN="$TEMP_DIR/stub-bin"
mkdir -p "$STUB_BIN"
cat >"$STUB_BIN/launchctl" <<'STUB'
#!/usr/bin/env bash
case "${1:-}" in
  list) [ -f "$HOME/.claude/loops/.fake-launchctl-list" ] && cat "$HOME/.claude/loops/.fake-launchctl-list" ;;
  bootout) exit 0 ;;
  *) exit 0 ;;
esac
STUB
chmod +x "$STUB_BIN/launchctl"
export PATH="$STUB_BIN:$PATH"
trap 'rm -rf "$TEMP_DIR"' EXIT

PASS=0
FAIL=0
SKIP=0

assert() {
  local got="$1" want="$2" name="$3"
  if [ "$got" = "$want" ]; then
    echo "  ✓ $name"
    PASS=$((PASS + 1))
  else
    echo "  ✗ $name (got=\"$got\" want=\"$want\")"
    FAIL=$((FAIL + 1))
  fi
}
skip() {
  echo "  ⊘ SKIP: $1"
  SKIP=$((SKIP + 1))
}

reset() {
  rm -rf "$HOME/.claude/loops" "$TEMP_DIR/contracts"
  mkdir -p "$HOME/.claude/loops" "$TEMP_DIR/contracts"
  echo "" >"$HOME/.claude/loops/.fake-launchctl-list"
}

put_contract() {
  local dir="$1" name="${2:-}" status="${3:-}"
  mkdir -p "$dir"
  {
    echo "---"
    [ -n "$name" ] && echo "name: $name"
    [ -n "$status" ] && echo "status: $status"
    echo "loop_id: $(echo -n "$dir" | shasum -a 256 | cut -c1-12)"
    echo "---"
  } >"$dir/LOOP_CONTRACT.md"
  echo "$dir/LOOP_CONTRACT.md"
}

put_loop() {
  local lid="$1" cp="$2" sid="${3:-pending-bind}" age_s="${4:-0}"
  local sd="$HOME/state-$lid"
  mkdir -p "$sd"
  local now_us
  now_us=$(python3 -c "import time; print(int(time.time()*1_000_000))")
  local start_us=$((now_us - age_s * 1000000))
  local entry
  entry=$(jq -nc --arg l "$lid" --arg c "$cp" --arg s "$sd/" --arg sid "$sid" --arg ts "$start_us" --arg pid "$$" \
    '{loop_id:$l, contract_path:$c, state_dir:$s, owner_session_id:$sid, owner_pid:$pid, owner_start_time_us:$ts, generation:0}')
  if [ ! -f "$CLAUDE_LOOPS_REGISTRY" ]; then
    echo '{"schema_version":1,"loops":[]}' >"$CLAUDE_LOOPS_REGISTRY"
  fi
  jq --argjson e "$entry" '.loops += [$e]' "$CLAUDE_LOOPS_REGISTRY" >"$CLAUDE_LOOPS_REGISTRY.tmp" && mv "$CLAUDE_LOOPS_REGISTRY.tmp" "$CLAUDE_LOOPS_REGISTRY"
  echo "$sd"
}

# Source libs once
# shellcheck source=/dev/null
source "$SCRIPTS/registry-lib.sh"
# shellcheck source=/dev/null
source "$SCRIPTS/provenance-lib.sh"

probe_pacing() {
  local delay="$1" reason="$2"
  local payload out
  payload=$(jq -nc --argjson d "$delay" --arg r "$reason" \
    '{session_id:"a",cwd:"/tmp",tool_name:"ScheduleWakeup",tool_input:{delaySeconds:$d,reason:$r,prompt:""},hook_event_name:"PreToolUse"}')
  out=$(echo "$payload" | bash "$HOOKS/pacing-veto.sh" 2>/dev/null || true)
  if [ -z "$out" ]; then
    echo "ALLOW"
  else
    echo "$out" | jq -r '.hookSpecificOutput.permissionDecision // "ALLOW"' 2>/dev/null || echo "ALLOW"
  fi
}

probe_session_bind() {
  local sid="$1" cwd="$2"
  jq -nc --arg s "$sid" --arg c "$cwd" \
    '{session_id:$s, cwd:$c, source:"startup", hook_event_name:"SessionStart"}' |
    bash "$HOOKS/session-bind.sh" 2>/dev/null
}

# ============================================================
echo "## Group A: Input validation"
# ============================================================

# A1: contract path with spaces
echo "A1: contract path with spaces"
reset
SPACEDIR="$TEMP_DIR/contracts/Project With Spaces"
mkdir -p "$SPACEDIR"
CP=$(put_contract "$SPACEDIR" "test-A1")
LID=$(derive_loop_id "$CP")
assert "$([ -n "$LID" ] && echo ok || echo fail)" "ok" "loop_id derives from spaced path"

# A2: contract path with non-ASCII (Chinese)
echo "A2: contract path with Chinese chars"
reset
CHDIR="$TEMP_DIR/contracts/项目-test"
mkdir -p "$CHDIR"
CP=$(put_contract "$CHDIR" "test-A2")
LID=$(derive_loop_id "$CP")
assert "$([ -n "$LID" ] && echo ok || echo fail)" "ok" "loop_id derives from non-ASCII path"

# A3: symlinked contract resolves to canonical path
echo "A3: symlinked contract"
reset
REAL="$TEMP_DIR/contracts/real-A3"
LINK="$TEMP_DIR/contracts/link-A3"
mkdir -p "$REAL"
put_contract "$REAL" "test-A3" >/dev/null
ln -sf "$REAL" "$LINK"
LID_REAL=$(derive_loop_id "$REAL/LOOP_CONTRACT.md")
LID_LINK=$(derive_loop_id "$LINK/LOOP_CONTRACT.md")
assert "$LID_REAL" "$LID_LINK" "symlink + canonical yield same loop_id (realpath used)"

# A4: contract that's a directory, not a file
echo "A4: contract path is a directory"
reset
DIR_AS_CONTRACT="$TEMP_DIR/contracts/iam-dir-A4"
mkdir -p "$DIR_AS_CONTRACT"
LID=$(derive_loop_id "$DIR_AS_CONTRACT" 2>/dev/null || echo "REJECTED")
case "$LID" in
  REJECTED|"") assert "ok" "ok" "directory-as-contract handled (rejected or empty id)" ;;
  *) assert "ok" "ok" "directory-as-contract still derives id (graceful)" ;;
esac

# A5: contract missing frontmatter entirely
echo "A5: contract with no frontmatter"
reset
NOFM="$TEMP_DIR/contracts/nofm-A5/LOOP_CONTRACT.md"
mkdir -p "$(dirname "$NOFM")"
echo "Just body text, no frontmatter" >"$NOFM"
NAME=$(awk '/^---$/{n++; next} n==1 && /^name:/ {sub(/^name:[[:space:]]*/, ""); print; exit}' "$NOFM" 2>/dev/null || echo "")
assert "$NAME" "" "missing frontmatter → name extraction returns empty (graceful)"

# A6: contract with empty name field
echo "A6: empty name field"
reset
EMPTY_NAME="$TEMP_DIR/contracts/empty-A6"
mkdir -p "$EMPTY_NAME"
{
  echo "---"
  echo "name:"
  echo "loop_id: aaaaaaaaaaaa"
  echo "---"
} >"$EMPTY_NAME/LOOP_CONTRACT.md"
NAME=$(awk '/^---$/{n++; next} n==1 && /^name:[[:space:]]*$/ {print "EMPTY"; exit} n==1 && /^name:/ {sub(/^name:[[:space:]]*/, ""); print; exit}' "$EMPTY_NAME/LOOP_CONTRACT.md" 2>/dev/null || echo "")
case "$NAME" in
  ""|EMPTY) assert "ok" "ok" "empty name field handled" ;;
  *) assert "$NAME" "EMPTY" "empty name field" ;;
esac

# A7: name field with only special chars
echo "A7: name with only special chars '@#\$%'"
reset
SPECIAL="$TEMP_DIR/contracts/special-A7"
mkdir -p "$SPECIAL"
put_contract "$SPECIAL" '@#$%^&*()' >/dev/null
NAME_RAW=$(awk '/^---$/{n++; next} n==1 && /^name:/ {sub(/^name:[[:space:]]*/, ""); print; exit}' "$SPECIAL/LOOP_CONTRACT.md")
SANITIZED=$(echo "$NAME_RAW" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9_-' '-' | sed -E 's/^-+|-+$//g; s/-+/-/g' | cut -c1-40)
# sanitize should produce empty string → fallback to loop_id triggers
case "$SANITIZED" in
  ""|"-") assert "ok" "ok" "special-only name sanitizes to empty (will use fallback)" ;;
  *) assert "$SANITIZED" "" "special chars stripped" ;;
esac

# A8: invalid hex chars in loop_id arg
echo "A8: loop_id with non-hex chars"
LID_BAD="zzz!notvalid"
RC=0
read_registry_entry "$LID_BAD" >/dev/null 2>&1 || RC=$?
assert "$RC" "1" "read_registry_entry rejects non-hex loop_id with rc=1"

# ============================================================
echo ""
echo "## Group B: State corruption"
# ============================================================

# B1: registry.json malformed JSON
echo "B1: malformed registry.json"
reset
echo '{ this is not json' >"$CLAUDE_LOOPS_REGISTRY"
OUT=$(read_registry "$CLAUDE_LOOPS_REGISTRY" 2>/dev/null)
HAS_LOOPS=$(echo "$OUT" | jq -r '.loops | type' 2>/dev/null || echo "fail")
assert "$HAS_LOOPS" "array" "malformed registry → fallback to empty registry"

# B2: registry.json deleted mid-runtime
echo "B2: registry.json missing"
rm -f "$CLAUDE_LOOPS_REGISTRY"
OUT=$(read_registry "$CLAUDE_LOOPS_REGISTRY" 2>/dev/null)
COUNT=$(echo "$OUT" | jq -r '.loops | length' 2>/dev/null || echo "fail")
assert "$COUNT" "0" "missing registry → empty array, no crash"

# B3: heartbeat.json malformed
echo "B3: malformed heartbeat.json"
reset
SD=$(put_loop "bbbbbbbbbbbb" "$TEMP_DIR/contract.md" "uuid-1")
echo '{ broken' >"$SD/heartbeat.json"
HB=$(jq -r '.bound_cwd // "missing"' "$SD/heartbeat.json" 2>/dev/null || echo "missing")
assert "$HB" "missing" "malformed heartbeat → jq returns 'missing' (or fails to default)"

# B4: provenance with one torn line in middle
echo "B4: provenance with torn line"
reset
PROV="$PROVENANCE_GLOBAL_FILE"
mkdir -p "$(dirname "$PROV")"
{
  echo '{"event":"good1","schema_version":1}'
  echo '{"event":"torn"  THIS IS BROKEN'
  echo '{"event":"good2","schema_version":1}'
} >"$PROV"
GOOD=$(jq -sr '[.[] | select(.schema_version == 1)] | length' "$PROV" 2>/dev/null || echo "0")
assert "$GOOD" "0" "torn line poisons whole jq -s read (known limitation; per-line iteration would fix)"

# B5: generation counter type confusion (string vs int)
echo "B5: generation as string '0' vs int 0"
reset
ENTRY_STR=$(jq -nc '{loop_id:"ccccccccccccc",contract_path:"/x",state_dir:"/x/",generation:"0"}')
echo "$ENTRY_STR" | jq -e '.generation == "0"' >/dev/null
RC=$?
assert "$RC" "0" "string generation matches as string"

# B6: registry with two entries having same loop_id
echo "B6: duplicate loop_id in registry"
reset
echo '{"schema_version":1,"loops":[{"loop_id":"dddddddddddd","contract_path":"/a","state_dir":"/a/","generation":0},{"loop_id":"dddddddddddd","contract_path":"/b","state_dir":"/b/","generation":1}]}' >"$CLAUDE_LOOPS_REGISTRY"
ENTRY=$(read_registry_entry "dddddddddddd" 2>/dev/null)
COUNT=$(echo "$ENTRY" | jq -s '. | length' 2>/dev/null || echo 0)
# With two duplicates, jq query returns BOTH; read_registry_entry picks first via jq head behavior
case "$COUNT" in
  1|2) assert "ok" "ok" "duplicate loop_id readable (count=$COUNT)" ;;
  *) assert "$COUNT" "1-or-2" "duplicate handling" ;;
esac

# ============================================================
echo ""
echo "## Group C: Concurrency"
# ============================================================

# C1: parallel session-bind for same cwd → exactly one wins
# Wave 6.2: fixture must use real UUIDs. session-bind.sh enforces strict
# UUID regex (added with the marketplace-pollution defense); the
# pre-existing `uuid-race-N` placeholders were silently rejected, so the
# race "had no contestants" and `pending-bind` survived — test failed
# without ever exercising the actual race semantics.
echo "C1: 5 parallel session-bind for same loop"
reset
CDIR="$TEMP_DIR/contracts/parallel-C1"
mkdir -p "$CDIR"
put_contract "$CDIR" "parallel-test" >/dev/null
LID=$(derive_loop_id "$CDIR/LOOP_CONTRACT.md")
put_loop "$LID" "$CDIR/LOOP_CONTRACT.md" "pending-bind" 0 >/dev/null
for i in 1 2 3 4 5; do
  ( probe_session_bind "0000000$i-1111-2222-3333-444444444444" "$CDIR" >/dev/null 2>&1 ) &
done
wait
WINNER=$(jq -r --arg l "$LID" '.loops[] | select(.loop_id == $l) | .owner_session_id' "$CLAUDE_LOOPS_REGISTRY")
case "$WINNER" in
  0000000[1-5]-1111-2222-3333-444444444444) assert "ok" "ok" "exactly one race winner ($WINNER)" ;;
  *) assert "$WINNER" "0000000?-1111-2222-3333-444444444444" "race winner not bound" ;;
esac

# C2: provenance concurrent writes (already covered in test-provenance)
echo "C2: provenance concurrent writes"
skip "covered exhaustively by test-provenance.sh"

# C3: heal-self idempotent under concurrent calls
echo "C3: heal-self double-invocation"
reset
put_loop "eeeeeeeeeeee" "/x" "pending-bind" 7200 >/dev/null
( bash "$SCRIPTS/heal-self.sh" >/dev/null 2>&1 ) &
( bash "$SCRIPTS/heal-self.sh" >/dev/null 2>&1 ) &
wait
ARCHIVED=0
[ -f "$HOME/.claude/loops/registry.archive.jsonl" ] && ARCHIVED=$(wc -l <"$HOME/.claude/loops/registry.archive.jsonl" | tr -d ' ')
# Both processes might race the hash check; archive count should be 1 or 2 (idempotent enough)
case "$ARCHIVED" in
  1|2) assert "ok" "ok" "concurrent heal-self archives 1-2 times (race tolerable)" ;;
  *) assert "$ARCHIVED" "1-or-2" "concurrent archive count out of bounds" ;;
esac

# C4: registry update under concurrent reads
echo "C4: 10 concurrent read_registry"
reset
put_loop "ffffffffffff" "/x" "uuid-x" 0 >/dev/null
RESULTS=$(mktemp)
for _ in $(seq 1 10); do
  ( read_registry_entry "ffffffffffff" 2>/dev/null | jq -r '.loop_id' >>"$RESULTS" ) &
done
wait
LINES=$(wc -l <"$RESULTS" | tr -d ' ')
rm -f "$RESULTS"
assert "$LINES" "10" "10 concurrent reads each return valid entry"

# ============================================================
echo ""
echo "## Group D: Hook payload malformations"
# ============================================================

# D1: pacing-veto with malformed JSON stdin
echo "D1: pacing-veto malformed JSON"
OUT=$(echo '{ broken json' | bash "$HOOKS/pacing-veto.sh" 2>/dev/null || echo "")
RC=$?
assert "$RC" "0" "pacing-veto exits 0 on malformed stdin (graceful)"

# D2: pacing-veto with empty stdin (no piped input)
echo "D2: pacing-veto empty stdin"
RC=0
echo "" | bash "$HOOKS/pacing-veto.sh" 2>/dev/null || RC=$?
assert "$RC" "0" "pacing-veto exits 0 on empty stdin"

# D3: ScheduleWakeup with delay=0 → DENY (v16.9.0 Rule 0)
echo "D3: ScheduleWakeup delay=0 (nonsense)"
DEC=$(probe_pacing 0 "rate limit immediate")
assert "$DEC" "deny" "delay=0 denied as nonsense (v16.9.0 Rule 0)"

# D4: ScheduleWakeup with negative delay → DENY
echo "D4: ScheduleWakeup delay=-100 (nonsense)"
DEC=$(probe_pacing -100 "negative delay")
assert "$DEC" "deny" "delay<0 denied as nonsense"

# D5: session_id is null in payload
echo "D5: session-bind with null session_id"
RC=0
echo '{"session_id":null,"cwd":"/tmp","source":"startup","hook_event_name":"SessionStart"}' | bash "$HOOKS/session-bind.sh" 2>/dev/null || RC=$?
assert "$RC" "0" "null session_id handled (graceful exit 0)"

# D6: oversized stdin (1MB) — wrap producer to swallow SIGPIPE under pipefail
echo "D6: oversized stdin (1MB)"
PADFILE=$(mktemp)
# dd directly produces a known size; avoids `yes | head` SIGPIPE under pipefail
dd if=/dev/zero of="$PADFILE" bs=1024 count=1000 2>/dev/null
RC=0
bash "$HOOKS/pacing-veto.sh" <"$PADFILE" >/dev/null 2>&1 || RC=$?
rm -f "$PADFILE"
assert "$RC" "0" "1MB oversized stdin doesn't crash hook"

# ============================================================
echo ""
echo "## Group E: Cleanup races + idempotency"
# ============================================================

# E1: tinker --fix when state_dir already deleted
echo "E1: tinker --fix with deleted state_dir"
reset
# shellcheck source=/dev/null
source "$SCRIPTS/triage-lib.sh"
SD=$(put_loop "111aaa111aaa" "$HOME/c-E1.md" "pending-bind" 7200)
{
  echo "---"
  echo "name: e1"
  echo "status: DONE"
  echo "---"
} >"$HOME/c-E1.md"
rm -rf "$SD"
RC=0
loop_triage_fix >/dev/null 2>&1 || RC=$?
assert "$RC" "0" "tinker --fix tolerates missing state_dir"

# E2: heal-self with read-only archive file
echo "E2: heal-self with read-only archive"
reset
put_loop "222bbb222bbb" "/x" "pending-bind" 7200 >/dev/null
touch "$HOME/.claude/loops/registry.archive.jsonl"
chmod 0444 "$HOME/.claude/loops/registry.archive.jsonl"
RC=0
bash "$SCRIPTS/heal-self.sh" 2>/dev/null || RC=$?
chmod 0644 "$HOME/.claude/loops/registry.archive.jsonl"
assert "$RC" "0" "heal-self exits 0 even with read-only archive"

# E3: DONE detection with status='done' (lowercase)
echo "E3: status='done' lowercase"
reset
{
  echo "---"
  echo "loop_id: 333ccc333ccc"
  echo "status: done"
  echo "---"
} >"$HOME/c-E3.md"
SD=$(put_loop "333ccc333ccc" "$HOME/c-E3.md" "pending-bind" 0)
echo "<plist/>" >"$HOME/Library/LaunchAgents/com.user.claude.loop.333ccc333ccc.plist"
loop_triage_fix >/dev/null 2>&1
PLIST_GONE="no"
[ ! -f "$HOME/Library/LaunchAgents/com.user.claude.loop.333ccc333ccc.plist" ] && PLIST_GONE="yes"
assert "$PLIST_GONE" "yes" "lowercase 'done' triggers cleanup"

# E4: DONE detection with multi-line status
echo "E4: status with continuation line"
reset
{
  echo "---"
  echo "loop_id: 444ddd444ddd"
  echo "status: DONE — and lots of detail spanning the line that is also relevant"
  echo "---"
} >"$HOME/c-E4.md"
put_loop "444ddd444ddd" "$HOME/c-E4.md" "pending-bind" 0 >/dev/null
JSON=$(loop_triage_report --json 2>/dev/null)
VERDICT=$(echo "$JSON" | jq -r '.loops[] | select(.loop_id == "444ddd444ddd") | .verdict')
assert "$VERDICT" "YELLOW" "long status starting with DONE flagged YELLOW"

# E5: idempotent tinker --fix (run twice)
echo "E5: tinker --fix run twice"
reset
{
  echo "---"
  echo "loop_id: 555eee555eee"
  echo "status: COMPLETE"
  echo "---"
} >"$HOME/c-E5.md"
put_loop "555eee555eee" "$HOME/c-E5.md" "pending-bind" 0 >/dev/null
loop_triage_fix >/dev/null 2>&1
RC=0
loop_triage_fix >/dev/null 2>&1 || RC=$?
assert "$RC" "0" "tinker --fix idempotent on second call"

# E6: cleanup of loop with "ABORTED" status (synonym)
echo "E6: status='ABORTED' triggers cleanup"
reset
{
  echo "---"
  echo "loop_id: 666fff666fff"
  echo "status: ABORTED — failed mid-iter"
  echo "---"
} >"$HOME/c-E6.md"
put_loop "666fff666fff" "$HOME/c-E6.md" "pending-bind" 0 >/dev/null
loop_triage_fix >/dev/null 2>&1
GONE=$(jq -r '.loops[] | select(.loop_id == "666fff666fff") | .loop_id' "$CLAUDE_LOOPS_REGISTRY" || echo "")
assert "$GONE" "" "ABORTED status loop removed from active registry"

# ============================================================
echo ""
echo "## Group F: Cross-platform"
# ============================================================

# F1: now_us returns valid integer
echo "F1: now_us microsecond resolution"
T1=$(_prov_now_us)
sleep 0.01
T2=$(_prov_now_us)
DELTA=$((T2 - T1))
[ "$DELTA" -gt 0 ] && [ "$DELTA" -lt 1000000 ] && OK=ok || OK="delta=$DELTA"
assert "$OK" "ok" "now_us monotonic and within 1s window"

# F2: ISO timestamp valid format
echo "F2: ISO timestamp format"
TS=$(_prov_now_iso)
case "$TS" in
  20[0-9][0-9]-[0-1][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-5][0-9]*Z) OK=ok ;;
  *) OK="bad format: $TS" ;;
esac
assert "$OK" "ok" "ISO 8601 UTC format"

echo ""
echo "═══════════════════════════════════════════"
echo "Edge-case audit: $PASS passed, $FAIL failed, $SKIP skipped (32 cases)"
echo "═══════════════════════════════════════════"
[ "$FAIL" -gt 0 ] && exit 1
echo "All applicable edge cases handled."
exit 0
