#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" BASE_REF="${1:-${GITHUB_BASE_REF:-${GITEA_BASE_REF:-}}}" if [[ -z "${BASE_REF}" ]]; then if git -C "${ROOT_DIR}" rev-parse --verify origin/dev >/dev/null 2>&1; then BASE_REF="origin/dev" elif git -C "${ROOT_DIR}" rev-parse --verify HEAD~1 >/dev/null 2>&1; then BASE_REF="HEAD~1" else echo "UI/Productization Coverage guard: no base ref supplied and no fallback ref exists." >&2 echo "Usage: scripts/check-ui-productization-coverage " >&2 exit 2 fi fi if ! git -C "${ROOT_DIR}" rev-parse --verify "${BASE_REF}^{commit}" >/dev/null 2>&1; then echo "UI/Productization Coverage guard: base ref '${BASE_REF}' is not available." >&2 echo "Fetch the target branch first or pass an available commit/ref." >&2 exit 2 fi if BASE_COMMIT="$(git -C "${ROOT_DIR}" merge-base "${BASE_REF}" HEAD 2>/dev/null)"; then CHANGED_FILES="$(git -C "${ROOT_DIR}" diff --name-only --diff-filter=ACMRT "${BASE_COMMIT}...HEAD")" else CHANGED_FILES="$(git -C "${ROOT_DIR}" diff --name-only --diff-filter=ACMRT "${BASE_REF}..HEAD")" fi ui_changes=() coverage_changes=() spec_no_impact_files=() while IFS= read -r file; do [[ -z "${file}" ]] && continue case "${file}" in apps/platform/app/Filament/*|apps/platform/app/Support/Navigation/*|apps/platform/app/Providers/Filament/*|apps/platform/resources/views/*|apps/platform/app/Livewire/*|apps/platform/routes/*) ui_changes+=("${file}") ;; esac case "${file}" in docs/ui-ux-enterprise-audit/route-inventory.md|\ docs/ui-ux-enterprise-audit/design-coverage-matrix.md|\ docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md|\ docs/ui-ux-enterprise-audit/strategic-surfaces.md|\ docs/ui-ux-enterprise-audit/unresolved-pages.md|\ docs/ui-ux-enterprise-audit/page-reports/*) coverage_changes+=("${file}") ;; esac if [[ "${file}" == specs/*/spec.md && -f "${ROOT_DIR}/${file}" ]] \ && grep -Eq '^- \[[xX]\] No UI surface impact[[:space:]]*$' "${ROOT_DIR}/${file}"; then spec_no_impact_files+=("${file}") fi done <<< "${CHANGED_FILES}" if [[ ${#ui_changes[@]} -eq 0 ]]; then echo "UI/Productization Coverage guard passed: no guarded UI surface paths changed." exit 0 fi if [[ ${#coverage_changes[@]} -gt 0 || ${#spec_no_impact_files[@]} -gt 0 ]]; then echo "UI/Productization Coverage guard passed." echo "Guarded UI surface changes:" printf ' - %s\n' "${ui_changes[@]}" if [[ ${#coverage_changes[@]} -gt 0 ]]; then echo "Coverage artifacts changed:" printf ' - %s\n' "${coverage_changes[@]}" fi if [[ ${#spec_no_impact_files[@]} -gt 0 ]]; then echo "No-impact decision found in:" printf ' - %s\n' "${spec_no_impact_files[@]}" fi exit 0 fi cat >&2 <<'EOF' UI/Productization Coverage guard failed. Guarded UI surface files changed, but no UI coverage artifact changed and no active spec contains: - [x] No UI surface impact Required: update at least one relevant artifact under docs/ui-ux-enterprise-audit/ (route inventory, design coverage matrix, page reports, grouped follow-up candidates, strategic surfaces, or unresolved pages), or document the checked no-impact decision in the active spec. Guarded UI surface changes: EOF printf ' - %s\n' "${ui_changes[@]}" >&2 exit 1