#!/usr/bin/env bash
# Standing guard for the markdown task-id leak scan. If a fixture citation under
# a shipped plugin/template .md stops failing the gate, the markdown coverage
# regressed back to code-only and internal task numbers can ship to clients
# again. The gate reads its scan root from TASK_ID_LEAK_ROOT so this test points
# it at a mktemp fixture tree, never the real corpus.
set -u
GATE="$(cd "$(dirname "$0")/.." && pwd)/check-no-task-id-leaks.mjs"
[[ -f "$GATE" ]] || { echo "FAIL: $GATE missing" >&2; exit 1; }
PASS=0; FAIL=0

ROOT=$(mktemp -d)
trap 'rm -rf "$ROOT"' EXIT
mkdir -p "$ROOT/platform/plugins/demo/skills/demo" \
         "$ROOT/platform/templates/specialists" \
         "$ROOT/premium-plugins/demo-bundle/skills/demo" \
         "$ROOT/.docs"

clean_skill() { printf '# Demo skill\n\nDoes a thing.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"; }
clean_skill

# 1. Clean corpus -> gate passes.
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -eq 0 ]]; then
  echo "PASS: clean markdown corpus -> exit 0"; PASS=$((PASS+1))
else
  echo "FAIL: clean corpus tripped gate (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi

# 2. `(Task 999)` parenthetical under a shipped skill -> gate fails + names it.
printf '# Demo skill\n\nDoes a thing (Task 999).\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] file=platform/plugins/demo/skills/demo/SKILL.md'; then
  echo "PASS: (Task 999) in shipped skill fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: parenthetical citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 3. Bare `Task 999` (prose form) under a shipped template -> gate fails + names it.
printf 'Task 999 changed the routing.\n' > "$ROOT/platform/templates/specialists/AGENT.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] file=platform/templates/specialists/AGENT.md'; then
  echo "PASS: bare Task 999 in shipped template fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: bare prose citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
rm -f "$ROOT/platform/templates/specialists/AGENT.md"

# 3b. `(Task 999)` under a shipped premium bundle -> gate fails + names it.
#     Premium bundles are copied verbatim into the client payload, so any
#     citation in their markdown leaks to paying clients the same as core.
printf '# Demo skill\n\nDoes a thing (Task 999).\n' > "$ROOT/premium-plugins/demo-bundle/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] file=premium-plugins/demo-bundle/skills/demo/SKILL.md'; then
  echo "PASS: (Task 999) in shipped premium bundle fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: premium citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
rm -f "$ROOT/premium-plugins/demo-bundle/skills/demo/SKILL.md"

# 4. `Tasks 12 and 34` plural form under a shipped skill -> gate fails.
printf '# Demo skill\n\nMerged behaviour (Tasks 12 and 34).\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] .*match=Tasks 12'; then
  echo "PASS: plural Tasks NNN form fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: plural citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 4b. Hyphenated `Pre-Task-748` form under a shipped skill -> gate fails.
printf '# Demo skill\n\nPre-Task-748 the index was small.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] .*match=Task-748'; then
  echo "PASS: hyphenated Pre-Task-748 form fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: hyphenated citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 4c. A lowercase `task-836-foo` slug (branch/file name) -> gate does NOT trip.
printf '# Demo skill\n\nWork landed on branch task-836-foo.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -eq 0 ]]; then
  echo "PASS: lowercase task-836 slug is not flagged"; PASS=$((PASS+1))
else
  echo "FAIL: lowercase slug wrongly tripped gate (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 4d. Lowercase prose `before task 127` under a shipped skill -> gate fails.
printf '# Demo skill\n\nResults from before task 127 remain in the graph.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] .*match=task 127'; then
  echo "PASS: lowercase prose 'task 127' fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: lowercase prose citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 4e. A `.tasks/<n>-…-task-NNN.md` file-path reference -> gate does NOT trip
#     (file paths are out of scope; the hyphenated-lowercase shape is exempt).
printf '# Demo skill\n\nTracked in `.tasks/339-installer-smoke-task-297.md` for now.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -eq 0 ]]; then
  echo "PASS: .tasks/ file-path reference is not flagged"; PASS=$((PASS+1))
else
  echo "FAIL: .tasks/ path wrongly tripped gate (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 4f. A `(Task NNN)` citation a soft line-wrap split across two source lines ->
#     gate fails + names it. Markdown rejoins the lines, so the client agent
#     still reads `(Task 900)`; a per-line scan sees `Task` and `900` separately
#     and misses it. printf emits a real newline between `Task` and `900`.
printf '# Demo skill\n\nThe method-capture flow (Task\n900) fills it in later.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -ne 0 ]] \
   && printf '%s' "$out" | grep -q '\[task-id-leak\] file=platform/plugins/demo/skills/demo/SKILL.md'; then
  echo "PASS: line-wrapped (Task\\n900) citation fails the gate"; PASS=$((PASS+1))
else
  echo "FAIL: line-wrapped citation not caught (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 5. A hex colour `#999` in a shipped .md -> gate does NOT trip (not a citation).
printf '# Demo skill\n\nUse colour `#999` for labels.\n' > "$ROOT/platform/plugins/demo/skills/demo/SKILL.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -eq 0 ]]; then
  echo "PASS: hex colour #999 is not flagged as a citation"; PASS=$((PASS+1))
else
  echo "FAIL: hex colour wrongly tripped gate (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi
clean_skill

# 6. Citation in a dev-only .docs doc -> gate does NOT trip (not a shipped root).
printf 'Internal note about Task 999.\n' > "$ROOT/.docs/note.md"
out=$(TASK_ID_LEAK_ROOT="$ROOT" node "$GATE" 2>&1); rc=$?
if [[ "$rc" -eq 0 ]]; then
  echo "PASS: .docs citation is exempt (dev-only, unscanned)"; PASS=$((PASS+1))
else
  echo "FAIL: .docs citation wrongly tripped gate (rc=$rc): $out" >&2; FAIL=$((FAIL+1))
fi

echo "----"; echo "PASS=$PASS FAIL=$FAIL"
[[ "$FAIL" -eq 0 ]]
