feat: add runner conversion scripts and strengthen cutover automation

This commit is contained in:
S
2026-03-04 13:32:06 -06:00
parent e624885bb9
commit c2087d5087
43 changed files with 6995 additions and 42 deletions

View File

@@ -0,0 +1,115 @@
#!/usr/bin/env bash
# check-contract-drift.sh — Enforce Constitution Principle V (contracts stay in lock-step).
#
# Fails when boundary-signature changes are detected under internal layers without
# any update under contracts/*.md in the same diff range.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO_ROOT"
log() {
printf '[contract-drift] %s\n' "$*"
}
err() {
printf '[contract-drift] ERROR: %s\n' "$*" >&2
}
resolve_range() {
if [[ -n "${AUGUR_CONTRACT_DRIFT_RANGE:-}" ]]; then
printf '%s' "$AUGUR_CONTRACT_DRIFT_RANGE"
return 0
fi
if [[ -n "${GITHUB_BASE_REF:-}" ]]; then
git fetch --no-tags --depth=1 origin "$GITHUB_BASE_REF" >/dev/null 2>&1 || true
printf 'origin/%s...HEAD' "$GITHUB_BASE_REF"
return 0
fi
if [[ -n "${GITHUB_EVENT_BEFORE:-}" ]] && [[ -n "${GITHUB_SHA:-}" ]] && [[ "$GITHUB_EVENT_BEFORE" != "0000000000000000000000000000000000000000" ]]; then
printf '%s...%s' "$GITHUB_EVENT_BEFORE" "$GITHUB_SHA"
return 0
fi
if git rev-parse --verify HEAD~1 >/dev/null 2>&1; then
printf 'HEAD~1...HEAD'
return 0
fi
printf ''
}
USE_WORKTREE="${AUGUR_CONTRACT_DRIFT_USE_WORKTREE:-0}"
RANGE=""
if [[ "$USE_WORKTREE" == "1" ]]; then
log "Diff source: working tree (HEAD -> working tree)"
changed_files="$(git diff --name-only)"
else
RANGE="$(resolve_range)"
if [[ -z "$RANGE" ]]; then
log "No diff range could be resolved; skipping contract drift check."
exit 0
fi
log "Diff range: $RANGE"
changed_files="$(git diff --name-only "$RANGE")"
fi
if [[ -z "$changed_files" ]]; then
log "No changed files in range; skipping."
exit 0
fi
if printf '%s\n' "$changed_files" | grep -Eq '^contracts/.*\.md$'; then
log "Contract files changed in range; check passed."
exit 0
fi
# Boundary-sensitive files that define cross-layer contracts.
boundary_files="$(printf '%s\n' "$changed_files" | grep -E '^internal/(cli|service|provider|storage|sync|model)/.*\.go$' || true)"
if [[ -z "$boundary_files" ]]; then
log "No boundary-sensitive Go files changed; check passed."
exit 0
fi
violations=()
while IFS= read -r file; do
[[ -z "$file" ]] && continue
# Canonical model and provider interface are always contract-relevant.
if [[ "$file" == "internal/model/conversation.go" ]] || [[ "$file" == "internal/provider/provider.go" ]]; then
violations+=("$file")
continue
fi
# Heuristic: exported symbol signature/shape changes in boundary layers are contract-relevant.
# Matches exported funcs, exported interfaces, and exported struct fields with JSON tags.
diff_output=""
if [[ "$USE_WORKTREE" == "1" ]]; then
diff_output="$(git diff -U0 -- "$file")"
else
diff_output="$(git diff -U0 "$RANGE" -- "$file")"
fi
if printf '%s\n' "$diff_output" | grep -Eq '^[+-](func (\([^)]*\) )?[A-Z][A-Za-z0-9_]*\(|type [A-Z][A-Za-z0-9_]* interface|[[:space:]]+[A-Z][A-Za-z0-9_]*[[:space:]].*`json:"[^"]+"`)'; then
violations+=("$file")
fi
done <<< "$boundary_files"
if [[ "${#violations[@]}" -eq 0 ]]; then
log "No contract-relevant signature drift detected; check passed."
exit 0
fi
err "Contract drift detected: contract-relevant files changed without contracts/*.md updates."
err "Update the applicable contract file(s) in contracts/ in the same change."
err "Impacted files:"
for file in "${violations[@]}"; do
err " - $file"
done
exit 1