#!/usr/bin/env bash
# r4 HEAD IDENTITY READ - deployah 2026-09-09, doyle's step 3 (msg-doyle-33).
# Run BEFORE any push. Asserts hertz's rider-6 sha is the shape doyle ruled, and nothing else.
#
#   ./identity-r4.sh <40-hex-sha>
#
# Exit: 0 = identity matches the ruling · 1 = MISMATCH, do not push · 3 = VOID (could not read).
#
# WHY A SCRIPT AND NOT AN EYEBALL: r3 shipped a defect where a local branch name pointed at a
# parallel chain with identical TREES and no rider. A tree match proves CONTENT, never COMMIT
# IDENTITY, and a branch NAME is a stale target. Everything below is asserted against the sha.
set -uo pipefail

SHA=${1:-}
PARENT_EXPECTED=f6110c2a12df0dd50b87dfb60a2ec4120b5cf98d
REGISTRY_BLOB_EXPECTED=21917ea9

void() { echo "VOID: $*" >&2; exit 3; }
fail() { echo "MISMATCH: $*" >&2; FAILED=1; }
FAILED=0

case "$SHA" in
  [0-9a-f]*) [ ${#SHA} -eq 40 ] || void "sha must be 40 hex chars, got ${#SHA}" ;;
  *) void "usage: ./identity-r4.sh <40-hex-sha>" ;;
esac

git cat-file -t "$SHA" >/dev/null 2>&1 || void "sha $SHA is not an object in THIS repo - fetch it first"
[ "$(git cat-file -t "$SHA")" = commit ] || void "sha $SHA is not a commit"

echo "=== r4 identity read: $SHA ==="
echo "subject: $(git log -1 --format=%s "$SHA")"
echo "author : $(git log -1 --format='%an <%ae>' "$SHA")"
echo "tree   : $(git rev-parse "${SHA}^{tree}")"
echo

# --- 1. PARENT is the r3 ruled sha (rider 6 rides f6110c2a, not a re-commit) ---
parent=$(git rev-parse "${SHA}^" 2>/dev/null) || void "cannot read parent"
nparents=$(git cat-file -p "$SHA" | grep -c '^parent ')
echo "parents: $nparents"
[ "$nparents" = "1" ] || fail "expected exactly 1 parent, found $nparents (a merge is not the ruled shape)"
echo "parent : $parent"
[ "$parent" = "$PARENT_EXPECTED" ] || fail "parent is NOT the r3 ruled sha $PARENT_EXPECTED"
echo

# --- 2. TWO files, both CI-only ------------------------------------------
files=$(git diff --name-only "$PARENT_EXPECTED" "$SHA")
nfiles=$(printf '%s' "$files" | grep -c . || true)
echo "files changed ($nfiles):"
printf '%s\n' "$files" | sed 's/^/  /'
[ "$nfiles" = "2" ] || fail "expected exactly 2 files, found $nfiles"
printf '%s\n' "$files" | grep -qx '.github/workflows/golden.yml' || fail "golden.yml not in the diff"
printf '%s\n' "$files" | grep -qx '.github/workflows/ci.yml'     || fail "ci.yml not in the diff"
# CI-only means CI-only: nothing outside .github may move.
outside=$(printf '%s\n' "$files" | grep -v '^\.github/workflows/' || true)
[ -z "$outside" ] || fail "NON-CI files in a CI-only rider: $outside"
echo

# --- 3. FOUR timeout-minutes hunk lines, and nothing else of substance ----
# doyle's shape: golden test job 50 -> 80, ci unit 25 -> 40. That is 2 removed + 2 added.
tmo=$(git diff -U0 "$PARENT_EXPECTED" "$SHA" -- .github/workflows/ | grep -E '^[+-]' | grep -v '^[+-][+-]' | grep -c 'timeout-minutes' || true)
echo "timeout-minutes hunk lines (+/-): $tmo   (expect 4)"
[ "$tmo" = "4" ] || fail "expected 4 timeout-minutes hunk lines, found $tmo"
echo "  the four, verbatim:"
git diff -U0 "$PARENT_EXPECTED" "$SHA" -- .github/workflows/ | grep -E '^[+-]' | grep -v '^[+-][+-]' | grep 'timeout-minutes' | sed 's/^/    /'
echo "  new values in file (golden test job, ci unit):"
git show "$SHA:.github/workflows/golden.yml" | grep -n 'timeout-minutes' | sed 's/^/    golden /'
git show "$SHA:.github/workflows/ci.yml"     | grep -n 'timeout-minutes' | sed 's/^/    ci     /'
echo

# --- 4. ZERO requirement tags (a CI-only rider claims no evidence) --------
reqs=$(git diff "$PARENT_EXPECTED" "$SHA" | grep -E '^\+' | grep -cE '\[(doc|impl|unit|int)->REQ-' || true)
echo "added REQ evidence tags: $reqs   (expect 0)"
[ "$reqs" = "0" ] || fail "a CI-only rider added $reqs REQ tag(s) - that is a different change"
echo

# --- 5. IR-54 shape: release-bearing files untouched ----------------------
for f in Cargo.toml Cargo.lock CHANGELOG.md; do
  if git diff --name-only "$PARENT_EXPECTED" "$SHA" -- "$f" | grep -q .; then
    fail "$f MOVED - breaks the IR-54 shape for a CI-only rider"
  else
    echo "IR-54: $f untouched  OK"
  fi
done
echo

# --- 6. registry blob unchanged BY CONSTRUCTION, asserted anyway ----------
# "by construction" is a PREDICTION. An assertion is a MEASUREMENT. Do the measurement.
#
# THE PATH IS PINNED, and here is why it must be. The first cut searched the tree for a
# "registry"-ish filename and took the FIRST hit, which was .github/ci/flake-registry.json
# (blob 3ba3630c). doyle's 21917ea9 is `traceable-reqs.toml` -- the REQUIREMENTS registry, which
# is what a CI-only rider must not move, and which is the same claim as the 0-REQ-tags check
# above. The guessed path would have reported "registry blob unchanged" TRUTHFULLY, ABOUT THE
# WRONG FILE: a passing check that asserts nothing anyone asked for. A search that takes the
# first match is a guess wearing a measurement's clothes; name the file.
REGISTRY_PATH=traceable-reqs.toml
if ! git cat-file -e "$SHA:$REGISTRY_PATH" 2>/dev/null; then
  fail "$REGISTRY_PATH ABSENT at the head - that alone is disqualifying for a CI-only rider"
else
  reg_new=$(git rev-parse "$SHA:$REGISTRY_PATH")
  reg_old=$(git rev-parse "$PARENT_EXPECTED:$REGISTRY_PATH")
  echo "registry $REGISTRY_PATH:"
  echo "  parent=$(printf '%s' "$reg_old" | cut -c1-8)  head=$(printf '%s' "$reg_new" | cut -c1-8)  (doyle: $REGISTRY_BLOB_EXPECTED)"
  [ "$reg_new" = "$reg_old" ] || fail "$REGISTRY_PATH CHANGED between parent and head"
  case "$reg_new" in
    "$REGISTRY_BLOB_EXPECTED"*) echo "  matches the blob doyle named  OK" ;;
    *) fail "$REGISTRY_PATH blob does NOT start with doyle's $REGISTRY_BLOB_EXPECTED" ;;
  esac
fi
echo

# --- verdict --------------------------------------------------------------
if [ "$FAILED" = "0" ]; then
  echo "IDENTITY OK - this sha is the ruled rider-6 shape."
  echo "NEXT: push the OBJECT, never the branch name:"
  echo "  git push origin ${SHA}:refs/heads/golden/webserve-272-r4"
  echo "  git ls-remote origin refs/heads/golden/webserve-272-r4   # MUST equal $SHA"
  echo "Then the nine gates (gate-r3-rerun.ps1's gate set, gate8 included) and a watch bound to"
  echo "the NEW run id - never the r3 run id."
  exit 0
fi
echo "IDENTITY MISMATCH - DO NOT PUSH. Hand the lines above back to doyle and hertz."
exit 1
