TenantAtlas/scripts/validate-ui-productization-coverage-guard
ahmido e35706b846 Spec 324: add UI productization coverage guardrails (#384)
## Summary
- add the Spec 324 package for UI Productization Coverage Guardrails, including spec, plan, tasks, and requirements checklist
- update Spec Kit templates and implementation prompts so future work must record UI surface impact, including navigation and Filament panel/provider surfaces
- harden the UI productization coverage guard script and add the validation helper for lightweight guard execution
- document the proportional guardrail flow in the UI/UX enterprise audit README

## Validation
- not run in this step
- change set is docs/tooling/governance only; no product runtime implementation included

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #384
2026-05-17 19:01:48 +00:00

190 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
GUARD_SOURCE="${ROOT_DIR}/scripts/check-ui-productization-coverage"
TEMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/ui-productization-guard.XXXXXX")"
FAILED=0
trap 'rm -rf "${TEMP_ROOT}"' EXIT
write_file() {
local path="$1"
local content="$2"
mkdir -p "$(dirname "${path}")"
printf '%b' "${content}" > "${path}"
}
append_file() {
local path="$1"
local content="$2"
mkdir -p "$(dirname "${path}")"
printf '%b' "${content}" >> "${path}"
}
setup_repo() {
local case_id="$1"
local repo="${TEMP_ROOT}/${case_id}"
mkdir -p "${repo}"
git -C "${repo}" init -q
git -C "${repo}" config user.email "guard-validation@example.test"
git -C "${repo}" config user.name "Guard Validation"
mkdir -p "${repo}/scripts"
cp "${GUARD_SOURCE}" "${repo}/scripts/check-ui-productization-coverage"
chmod +x "${repo}/scripts/check-ui-productization-coverage"
write_file "${repo}/apps/platform/app/Filament/Dashboard.php" "<?php\n// baseline\n"
write_file "${repo}/apps/platform/app/Support/Navigation/WorkspaceNavigation.php" "<?php\n// baseline\n"
write_file "${repo}/apps/platform/app/Providers/Filament/AdminPanelProvider.php" "<?php\n// baseline\n"
write_file "${repo}/apps/platform/app/Services/BackendOnlyService.php" "<?php\n// baseline\n"
write_file "${repo}/docs/ui-ux-enterprise-audit/route-inventory.md" "# Route Inventory\n"
write_file "${repo}/docs/process-note.md" "# Process Note\n"
write_file "${repo}/.specify/templates/spec-template.md" "# Baseline Template\n"
git -C "${repo}" add .
git -C "${repo}" commit -q -m "baseline"
printf '%s\n' "${repo}"
}
touch_filament_page() {
local repo="$1"
append_file "${repo}/apps/platform/app/Filament/Dashboard.php" "// guarded UI change\n"
}
add_spec() {
local repo="$1"
local content="$2"
write_file "${repo}/specs/999-guard-validation/spec.md" "${content}"
}
case_ui_unchecked_template_heading() {
local repo="$1"
touch_filament_page "${repo}"
append_file "${repo}/.specify/templates/spec-template.md" "## UI Surface Impact\n\n- [ ] No UI surface impact\n- [ ] Navigation changed\n"
}
case_ui_unchecked_spec_checkbox() {
local repo="$1"
touch_filament_page "${repo}"
add_spec "${repo}" "# Spec\n\n## UI Surface Impact\n\n- [ ] Existing page changed\n\nRationale: unchecked should not pass.\n"
}
case_ui_checked_impact_spec() {
local repo="$1"
touch_filament_page "${repo}"
add_spec "${repo}" "# Spec\n\n## UI Surface Impact\n\n- [x] Existing page changed\n"
}
case_ui_checked_no_impact_with_rationale() {
local repo="$1"
touch_filament_page "${repo}"
add_spec "${repo}" "# Spec\n\n## UI Surface Impact\n\n- [x] No UI surface impact\n- [ ] Existing page changed\n\nRationale: guarded file changed for an internal refactor with identical rendered UI.\n"
}
case_ui_checked_no_impact_without_rationale() {
local repo="$1"
touch_filament_page "${repo}"
add_spec "${repo}" "# Spec\n\n## UI Surface Impact\n\n- [x] No UI surface impact\n- [ ] Existing page changed\n"
}
case_ui_real_audit_coverage_artifact() {
local repo="$1"
touch_filament_page "${repo}"
append_file "${repo}/docs/ui-ux-enterprise-audit/route-inventory.md" "\n| UI-999 | /admin/example | page | Example |\n"
}
case_navigation_provider_without_acknowledgment() {
local repo="$1"
append_file "${repo}/apps/platform/app/Support/Navigation/WorkspaceNavigation.php" "// navigation changed\n"
append_file "${repo}/apps/platform/app/Providers/Filament/AdminPanelProvider.php" "// provider changed\n"
}
case_navigation_provider_with_checked_acknowledgment() {
local repo="$1"
append_file "${repo}/apps/platform/app/Support/Navigation/WorkspaceNavigation.php" "// navigation changed\n"
append_file "${repo}/apps/platform/app/Providers/Filament/AdminPanelProvider.php" "// provider changed\n"
add_spec "${repo}" "# Spec\n\n## UI Surface Impact\n\n- [x] Navigation changed\n- [x] Filament panel/provider surface changed\n"
}
case_backend_only_diff() {
local repo="$1"
append_file "${repo}/apps/platform/app/Services/BackendOnlyService.php" "// backend-only change\n"
}
case_docs_only_diff() {
local repo="$1"
append_file "${repo}/docs/process-note.md" "\n## UI Surface Impact\n\nPlain documentation phrase without guarded UI changes.\n"
}
case_untracked_guarded_ui_without_acknowledgment() {
local repo="$1"
write_file "${repo}/apps/platform/app/Filament/NewUntrackedPage.php" "<?php\n// untracked guarded UI file\n"
}
run_case() {
local case_id="$1"
local expected="$2"
local setup_function="$3"
local repo
local status
local output_file="${TEMP_ROOT}/${case_id}.out"
repo="$(setup_repo "${case_id}")"
"${setup_function}" "${repo}"
set +e
(
cd "${repo}"
bash scripts/check-ui-productization-coverage HEAD
) >"${output_file}" 2>&1
status=$?
set -e
if [[ "${expected}" == "pass" && ${status} -eq 0 ]] || [[ "${expected}" == "fail" && ${status} -ne 0 ]]; then
printf 'PASS %s (%s)\n' "${case_id}" "${expected}"
return
fi
FAILED=1
printf 'FAIL %s expected %s but exit status was %s\n' "${case_id}" "${expected}" "${status}" >&2
sed 's/^/ /' "${output_file}" >&2
}
run_case "ui_unchecked_template_heading_fails" "fail" "case_ui_unchecked_template_heading"
run_case "ui_unchecked_spec_checkbox_fails" "fail" "case_ui_unchecked_spec_checkbox"
run_case "ui_checked_impact_spec_passes" "pass" "case_ui_checked_impact_spec"
run_case "ui_checked_no_impact_with_rationale_passes" "pass" "case_ui_checked_no_impact_with_rationale"
run_case "ui_checked_no_impact_without_rationale_fails" "fail" "case_ui_checked_no_impact_without_rationale"
run_case "ui_real_audit_coverage_artifact_passes" "pass" "case_ui_real_audit_coverage_artifact"
run_case "navigation_provider_without_acknowledgment_fails" "fail" "case_navigation_provider_without_acknowledgment"
run_case "navigation_provider_with_checked_acknowledgment_passes" "pass" "case_navigation_provider_with_checked_acknowledgment"
run_case "backend_only_diff_passes" "pass" "case_backend_only_diff"
run_case "docs_only_diff_passes" "pass" "case_docs_only_diff"
run_case "untracked_guarded_ui_without_acknowledgment_fails" "fail" "case_untracked_guarded_ui_without_acknowledgment"
if [[ ${FAILED} -ne 0 ]]; then
exit 1
fi
printf 'All UI/Productization Coverage guard validation cases passed.\n'