dev / bin / canon-drift
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env bash
# canon-drift — assert every vendored copy sits at its declared distance
# from its canon.
#
# House rule 6 promises the vendored layer is byte-identical across the rooms
# and CLJS lines "modulo the namespace rename". That promise was checked by
# hand, which means it was checked by memory. This makes it a number.
#
#   canon-drift            check every row of canon.tsv; non-zero exit on drift
#   canon-drift --list     print the table, change nothing
#   canon-drift --update   RE-BASELINE the deltas (a deliberate, reviewed act)
#
# The assertion is EQUALITY, not "at most". A copy that drifted further has an
# unpropagated fix; a copy that drifted less has usually had a sanctioned
# divergence silently reverted. Both are findings.
set -euo pipefail

DEV_DIR="$(cd "$(dirname "$0")/.." && pwd)"
WORKSPACE="$(cd "$DEV_DIR/.." && pwd)"
MANIFEST="$DEV_DIR/canon.tsv"
TAB="$(printf '\t')"

mode="check"
case "${1:-}" in
  --list)   mode="list" ;;
  --update) mode="update" ;;
  "")       ;;
  *) printf 'usage: canon-drift [--list|--update]\n' >&2; exit 2 ;;
esac

# The rename is a literal prefix substitution, exactly as ardz's _ns_rename
# does it: s/<from>/<to>/g with the dot escaped. Nothing else is rewritten —
# the protocol ids (/sueta/2/msg/1.0), the OrbitDB provider type ("sueta") and
# the domain tags (sueta-id|v2) have no dot after the name and so survive,
# which is precisely what wire compatibility depends on.
drift() { # canon copy from to -> changed-line count, or MISSING
  local canon="$WORKSPACE/$1" copy="$WORKSPACE/$2" from="$3" to="$4"
  # "-" in BOTH rename columns means the copy is not namespaced at all and is
  # expected byte-identical — the clj-kondo hooks, which are plain Clojure with
  # the same ns name in every repo. Substituting "-" for "-" would be a no-op
  # anyway; spelling it out keeps the manifest readable and stops the next
  # person inventing a sentinel string.
  if [ "$from" = "-" ] && [ "$to" = "-" ]; then
    [ -f "$canon" ] && [ -f "$copy" ] || { echo MISSING; return; }
    diff "$canon" "$copy" | grep -c '^[<>]' || true
    return
  fi
  [ -f "$canon" ] && [ -f "$copy" ] || { printf 'MISSING'; return 0; }
  diff <(sed "s/${from//./\\.}/$to/g" "$canon") "$copy" | grep -c '^[<>]' || true
}

fail=0
rows=0
out="$(mktemp)"; trap 'rm -f "$out"' EXIT

while IFS="$TAB" read -r canon copy from to want reason; do
  case "${canon:-}" in ''|'#'*) continue;; esac
  rows=$((rows + 1))
  got="$(drift "$canon" "$copy" "$from" "$to")"

  if [ "$mode" = "update" ]; then
    printf '%s\t%s\t%s\t%s\t%s\t%s\n' "$canon" "$copy" "$from" "$to" "$got" "$reason" >>"$out"
    [ "$got" = "$want" ] || printf '  ~ %s -> %s: %s => %s\n' "$canon" "$copy" "$want" "$got"
    continue
  fi

  if [ "$got" = "$want" ]; then
    [ "$mode" = "list" ] && printf '  ok   %-46s %-46s %s\n' "$canon" "$copy" "$got"
  else
    fail=1
    printf 'DRIFT %s\n         canon:    %s\n         copy:     %s\n         declared: %s changed lines\n         actual:   %s\n' \
      "$([ "$got" -gt "$want" ] 2>/dev/null && echo 'grew — an unpropagated canon change?' || echo 'shrank — a sanctioned divergence reverted?')" \
      "$canon" "$copy" "$want" "$got" >&2
    [ "$reason" != "-" ] && printf '         sanctioned: %s\n' "$reason" >&2
  fi
done < "$MANIFEST"

if [ "$mode" = "update" ]; then
  # keep the comment header, replace only the data rows
  { grep -E '^($|#)' "$MANIFEST"; cat "$out"; } > "$MANIFEST.new"
  mv "$MANIFEST.new" "$MANIFEST"
  printf 'canon-drift: re-baselined %s rows — REVIEW THE DIFF before committing.\n' "$rows"
  exit 0
fi

if [ "$fail" = 0 ]; then
  printf 'canon-drift: OK (%s vendored copies each at their declared distance)\n' "$rows"
else
  printf '\ncanon-drift: FAILED — propagate the change, or re-baseline deliberately\n         with `canon-drift --update` and explain the new delta in canon.tsv.\n' >&2
fi
exit "$fail"

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/dev.git