
Pre Merge Checklist
- 45 installs
- 8 repo stars
- Updated February 6, 2026
- hieutrtr/ai1-skills
A systematic pre-merge validation checklist for Python/React PRs covering linting, type checking, coverage, migrations, and API compatibility.
About
Provides a comprehensive checklist run before approving or merging a PR, covering code quality, test coverage, docs, migration safety, API compatibility, accessibility, and bundle size. A developer uses it to ensure nothing is missed before merge.
- Covers ruff/mypy/pytest checks, coverage, and migration safety
- Includes API contract compatibility, accessibility, and bundle-size checks
Pre Merge Checklist by the numbers
- 45 all-time installs (skills.sh)
- Ranked #604 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/hieutrtr/ai1-skills --skill pre-merge-checklistAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 45 |
|---|---|
| repo stars | ★ 8 |
| Last updated | February 6, 2026 |
| Repository | hieutrtr/ai1-skills ↗ |
What it does
A systematic pre-merge validation checklist for Python/React PRs covering linting, type checking, coverage, migrations, and API compatibility.
Files
Pre-Merge Checklist
When to Use
Activate this skill when:
- Reviewing a pull request before approving
- Preparing your own PR for merge
- Verifying that all automated checks pass before merging
- Auditing a PR that has been approved but not yet merged
- Running a final validation pass after addressing review feedback
Output: Write results to pre-merge-report.md with pass/fail status for each check and blocking issues.
Do NOT use this skill for:
- In-depth security review (use
code-review-security) - Writing implementation code (use
python-backend-expertorreact-frontend-expert) - Architecture decisions (use
system-architecture) - E2E test creation (use
e2e-testing)
Instructions
Automated Checks (Ordered)
Run automated checks in this order. Each check must pass before proceeding to the next. Use scripts/run-all-checks.sh to execute all checks at once.
1. Linting and Formatting
Python (ruff):
# Check linting
ruff check app/ tests/
# Check formatting
ruff format --check app/ tests/
# Auto-fix (if needed before commit)
ruff check --fix app/ tests/
ruff format app/ tests/TypeScript/React (eslint + prettier):
# Check linting
npx eslint 'src/**/*.{ts,tsx}' --max-warnings 0
# Check formatting
npx prettier --check 'src/**/*.{ts,tsx}'
# Auto-fix (if needed)
npx eslint 'src/**/*.{ts,tsx}' --fix
npx prettier --write 'src/**/*.{ts,tsx}'Pass criteria:
- Zero lint errors (warnings are tolerated only with justification)
- All files formatted consistently
- No
# noqaoreslint-disablewithout a comment explaining why
2. Type Checking
Python (mypy):
mypy app/ --strict --no-error-summaryTypeScript:
npx tsc --noEmitUse scripts/type-check.sh to run both in sequence with report output.
Pass criteria:
- Zero type errors in changed files
- No new
type: ignoreor@ts-ignorewithout justification - Generic types used correctly (no
Anyleaks)
3. Tests
Python:
pytest tests/ -q --tb=shortReact:
npm test -- --run --reporter=verbosePass criteria:
- All tests pass (zero failures)
- No skipped tests without a linked issue/ticket
- New code has corresponding tests
4. Coverage
Python:
pytest --cov=app --cov-report=term-missing --cov-fail-under=80React:
npx vitest run --coverage --coverage.thresholds.lines=80Pass criteria:
- Overall coverage >= 80%
- New code coverage >= 90%
- No critical paths left uncovered (auth, payment, data mutation)
5. Security Scan
# Python dependencies
pip-audit --requirement requirements.txt
# npm dependencies
npm audit --audit-level=high
# Custom code scan (if code-review-security skill is available)
python scripts/security-scan.py --path app/ --output-dir ./security-resultsPass criteria:
- No critical or high severity vulnerability in dependencies
- No critical findings in code scan
- All new endpoints have authentication checks
---
Manual Review Checklist
After automated checks pass, review the PR manually against these categories.
Code Quality
- [ ] Naming: Variables, functions, and classes have clear, descriptive names
- [ ] Functions: Each function does one thing; no function exceeds 50 lines
- [ ] DRY: No duplicated logic that should be extracted into a shared function
- [ ] Comments: Complex logic is documented; no commented-out code left in
- [ ] Imports: No unused imports; imports are organized (stdlib, third-party, local)
- [ ] Constants: No magic numbers or strings; use named constants or enums
- [ ] Logging: New features have appropriate log statements at correct levels
Testing
- [ ] Coverage: New code has tests (unit and/or integration as appropriate)
- [ ] Edge cases: Tests cover happy path, error paths, and boundary conditions
- [ ] Test names: Test names describe the scenario and expected outcome
- [ ] Test isolation: Tests do not depend on each other or on execution order
- [ ] No flakiness: Tests do not use hardcoded delays or environment-specific paths
- [ ] Factories: Test data uses factories, not hardcoded fixtures
Type Safety
- [ ] No `Any`: Return types and parameters are properly typed (no escape hatches)
- [ ] Null safety: Optional values are handled (null checks, default values)
- [ ] Schema validation: API inputs use Pydantic schemas (Python) or Zod (React)
- [ ] Generic types: Collections use proper generics (
list[User], notlist)
Error Handling
- [ ] Graceful errors: All error paths return meaningful messages
- [ ] HTTP status codes: Correct codes used (404 for not found, 409 for conflict, etc.)
- [ ] Error boundaries: React components have error boundaries for async failures
- [ ] Retry logic: External service calls have retry with backoff (where appropriate)
- [ ] No silent failures: Caught exceptions are logged, not silently swallowed
Backwards Compatibility
- [ ] API contracts: No breaking changes to existing API response shapes
- [ ] Database migrations: Migrations are reversible and non-destructive
- [ ] Feature flags: Breaking changes are behind feature flags
- [ ] Deprecation: Removed features have deprecation warnings in prior release
- [ ] Configuration: No new required environment variables without documentation
Documentation
- [ ] API docs: New endpoints are documented (OpenAPI/Swagger via FastAPI)
- [ ] README: Setup instructions updated if new dependencies or steps added
- [ ] Migration notes: Database migration has a description comment
- [ ] ADR: Significant architectural decisions documented (if applicable)
Performance
- [ ] N+1 queries: No N+1 database query patterns (use eager loading)
- [ ] Pagination: List endpoints use cursor-based pagination
- [ ] Indexes: New query patterns have supporting database indexes
- [ ] Bundle size: No unnecessary large dependencies added to frontend
Accessibility
- [ ] Semantic HTML: Correct HTML elements used (button, nav, main, etc.)
- [ ] ARIA labels: Interactive elements have accessible labels
- [ ] Keyboard navigation: New UI elements are keyboard-accessible
- [ ] Color contrast: Text meets WCAG 2.1 AA contrast requirements
Use scripts/accessibility-check.sh to run automated accessibility checks.
---
Failure Protocol
When a check fails, follow this escalation path:
Automated check failure: 1. Fix the issue in the PR 2. Push the fix and re-run checks 3. Do not merge until all automated checks pass
Manual review finding: 1. Add a review comment with the finding 2. Request changes on the PR 3. Re-review after the author addresses feedback
Severity-based response:
| Finding Type | Action | Can Override? |
|---|---|---|
| Lint/format error | Fix before merge | No |
| Type error | Fix before merge | No |
| Test failure | Fix before merge | No |
| Coverage below threshold | Add tests or justify | Yes, with tech lead approval |
| Security finding (critical/high) | Fix before merge | No |
| Security finding (medium/low) | Fix or create follow-up ticket | Yes, with ticket reference |
| Accessibility violation | Fix or create follow-up ticket | Yes, with justification |
| Performance concern | Discuss in PR, may defer | Yes, with tech lead approval |
Override Process
If a check must be overridden:
1. Document the reason in a PR comment explaining why the override is acceptable 2. Get explicit approval from a tech lead or senior engineer 3. Create a follow-up ticket to resolve the underlying issue 4. Add a code comment at the override point referencing the ticket
# OVERRIDE: Coverage below 80% for this module. See TICKET-1234.
# Approved by @tech-lead on 2024-01-15.
# Reason: Legacy code migration in progress; full coverage planned for Sprint 12.Overrides are never acceptable for:
- Critical security vulnerabilities
- Broken tests
- Type errors that mask bugs
Examples
Running All Checks
# Run the full check suite
./scripts/run-all-checks.sh --output-dir ./check-results
# Run only type checks
./scripts/type-check.sh --output-dir ./check-results
# Run accessibility checks
./scripts/accessibility-check.sh --output-dir ./check-resultsQuick PR Review Workflow
1. Pull the branch locally 2. Run ./scripts/run-all-checks.sh --output-dir ./pr-review 3. Review the automated results file 4. Walk through the manual checklist above 5. Leave review comments or approve
Output File
Write results to pre-merge-report.md:
# Pre-Merge Report: [PR Title]
## Status: READY TO MERGE | BLOCKING ISSUES
## Automated Checks
| Check | Status | Details |
|-------|--------|---------|
| Linting (ruff) | PASS | No issues |
| Type check (mypy) | PASS | No errors |
| Tests (pytest) | PASS | 142 passed, 0 failed |
| Coverage | PASS | 85% (threshold: 80%) |
| Frontend lint | PASS | No issues |
| Frontend types | PASS | No errors |
## Manual Checks
- [x] Code follows project patterns
- [x] Tests cover new functionality
- [x] No breaking API changes
- [ ] Documentation updated (BLOCKING)
## Blocking Issues
1. README needs update for new CLI flag
## Recommendation
Address documentation before merge.#!/usr/bin/env bash
# accessibility-check.sh — Run axe-core accessibility scan against the application.
#
# Usage:
# ./accessibility-check.sh [--output-dir <dir>] [--url <url>] [--pages <file>]
#
# Options:
# --output-dir <dir> Directory to write results (default: ./check-results)
# --url <url> Base URL to scan (default: http://localhost:3000)
# --pages <file> File with list of page paths to scan (one per line)
#
# Prerequisites:
# npm install -g @axe-core/cli
# # or use npx: npx @axe-core/cli
set -uo pipefail
# ─── Defaults ───────────────────────────────────────────────────────────────────
OUTPUT_DIR="./check-results"
BASE_URL="http://localhost:3000"
PAGES_FILE=""
# Default pages to scan if no pages file is provided
DEFAULT_PAGES=(
"/"
"/login"
"/users"
"/settings"
)
# ─── Parse arguments ────────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--output-dir)
OUTPUT_DIR="$2"
shift 2
;;
--url)
BASE_URL="$2"
shift 2
;;
--pages)
PAGES_FILE="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 [--output-dir <dir>] [--url <url>] [--pages <file>]"
echo ""
echo "Options:"
echo " --output-dir <dir> Directory for results (default: ./check-results)"
echo " --url <url> Base URL to scan (default: http://localhost:3000)"
echo " --pages <file> File listing page paths to scan (one per line)"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# ─── Setup ───────────────────────────────────────────────────────────────────────
mkdir -p "$OUTPUT_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RESULTS_FILE="$OUTPUT_DIR/accessibility-report-${TIMESTAMP}.txt"
JSON_FILE="$OUTPUT_DIR/accessibility-report-${TIMESTAMP}.json"
OVERALL_EXIT=0
TOTAL_VIOLATIONS=0
echo "=== Accessibility Check (axe-core) ==="
echo "Base URL: ${BASE_URL}"
echo "Output directory: ${OUTPUT_DIR}"
echo ""
# ─── Determine pages to scan ─────────────────────────────────────────────────────
PAGES=()
if [[ -n "$PAGES_FILE" && -f "$PAGES_FILE" ]]; then
while IFS= read -r line; do
[[ -z "$line" || "$line" == \#* ]] && continue
PAGES+=("$line")
done < "$PAGES_FILE"
else
PAGES=("${DEFAULT_PAGES[@]}")
fi
echo "Pages to scan: ${#PAGES[@]}"
echo "Timestamp: $(date -Iseconds)" > "$RESULTS_FILE"
echo "Base URL: ${BASE_URL}" >> "$RESULTS_FILE"
echo "" >> "$RESULTS_FILE"
# ─── Check if axe CLI is available ───────────────────────────────────────────────
if ! command -v axe &> /dev/null && ! npx @axe-core/cli --version &> /dev/null 2>&1; then
echo "WARNING: axe-core CLI not found. Install with: npm install -g @axe-core/cli"
echo "Falling back to Playwright-based accessibility check..."
# Fallback: use Playwright with @axe-core/playwright
echo "Running Playwright accessibility tests..."
npx playwright test --grep accessibility 2>&1 | tee -a "$RESULTS_FILE"
OVERALL_EXIT=$?
if [[ $OVERALL_EXIT -eq 0 ]]; then
echo "PASS: Accessibility checks passed (Playwright fallback)."
else
echo "FAIL: Accessibility violations found. See ${RESULTS_FILE}"
fi
exit $OVERALL_EXIT
fi
# ─── Scan each page ──────────────────────────────────────────────────────────────
ALL_RESULTS="["
for page_path in "${PAGES[@]}"; do
full_url="${BASE_URL}${page_path}"
echo "Scanning: ${full_url}"
echo "─── ${full_url} ───" >> "$RESULTS_FILE"
PAGE_JSON="$OUTPUT_DIR/axe-page-${TIMESTAMP}.json"
PAGE_EXIT=0
# Run axe-core scan
npx @axe-core/cli "${full_url}" \
--save "${PAGE_JSON}" \
--stdout \
2>&1 | tee -a "$RESULTS_FILE" || PAGE_EXIT=$?
if [[ $PAGE_EXIT -ne 0 ]]; then
OVERALL_EXIT=1
echo " VIOLATIONS FOUND on ${page_path}" >> "$RESULTS_FILE"
else
echo " PASS: ${page_path}" >> "$RESULTS_FILE"
fi
# Collect results
if [[ -f "$PAGE_JSON" ]]; then
# Count violations
violations=$(python3 -c "
import json, sys
try:
data = json.load(open('${PAGE_JSON}'))
violations = data.get('violations', []) if isinstance(data, dict) else []
print(len(violations))
except Exception:
print(0)
" 2>/dev/null || echo "0")
TOTAL_VIOLATIONS=$((TOTAL_VIOLATIONS + violations))
fi
echo "" >> "$RESULTS_FILE"
done
# ─── Summary ─────────────────────────────────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "ACCESSIBILITY SUMMARY"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Pages scanned: ${#PAGES[@]}"
echo "Total violations: ${TOTAL_VIOLATIONS}"
echo "" >> "$RESULTS_FILE"
echo "SUMMARY:" >> "$RESULTS_FILE"
echo "Pages scanned: ${#PAGES[@]}" >> "$RESULTS_FILE"
echo "Total violations: ${TOTAL_VIOLATIONS}" >> "$RESULTS_FILE"
if [[ $OVERALL_EXIT -eq 0 && $TOTAL_VIOLATIONS -eq 0 ]]; then
echo "OVERALL: PASS"
echo "Status: PASS" >> "$RESULTS_FILE"
else
echo "OVERALL: FAIL — ${TOTAL_VIOLATIONS} violation(s) found."
echo "Status: FAIL" >> "$RESULTS_FILE"
echo "Review details in: ${RESULTS_FILE}"
OVERALL_EXIT=1
fi
echo "Full report: ${RESULTS_FILE}"
exit $OVERALL_EXIT
#!/usr/bin/env bash
# run-all-checks.sh — Orchestrate all pre-merge checks with pass/fail reporting.
#
# Usage:
# ./run-all-checks.sh [--output-dir <dir>]
#
# Options:
# --output-dir <dir> Directory to write results (default: ./check-results)
#
# Runs in order: linting, type checking, tests, coverage, security scan.
# Continues through all checks even if one fails, then reports overall status.
set -uo pipefail
# ─── Defaults ───────────────────────────────────────────────────────────────────
OUTPUT_DIR="./check-results"
# ─── Parse arguments ────────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--output-dir)
OUTPUT_DIR="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 [--output-dir <dir>]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# ─── Setup ───────────────────────────────────────────────────────────────────────
mkdir -p "$OUTPUT_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
REPORT_FILE="$OUTPUT_DIR/all-checks-${TIMESTAMP}.txt"
FAILED_CHECKS=()
PASSED_CHECKS=()
# ─── Helper: run a check and record result ───────────────────────────────────────
run_check() {
local name="$1"
shift
local cmd="$*"
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "CHECK: ${name}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
local check_file="$OUTPUT_DIR/${name// /-}-${TIMESTAMP}.txt"
local exit_code=0
eval "$cmd" 2>&1 | tee "$check_file" || exit_code=$?
if [[ $exit_code -eq 0 ]]; then
echo "RESULT: PASS"
PASSED_CHECKS+=("$name")
echo "PASS: ${name}" >> "$REPORT_FILE"
else
echo "RESULT: FAIL (exit code: ${exit_code})"
FAILED_CHECKS+=("$name")
echo "FAIL: ${name}" >> "$REPORT_FILE"
fi
return 0 # Always continue to next check
}
# ─── Header ──────────────────────────────────────────────────────────────────────
echo "=== Pre-Merge Check Suite ==="
echo "Output directory: ${OUTPUT_DIR}"
echo "Timestamp: $(date -Iseconds)"
echo ""
echo "Timestamp: $(date -Iseconds)" > "$REPORT_FILE"
echo "Output directory: ${OUTPUT_DIR}" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
# ─── 1. Python Linting (ruff) ────────────────────────────────────────────────────
run_check "python-lint" "ruff check app/ tests/ 2>&1; ruff format --check app/ tests/ 2>&1"
# ─── 2. TypeScript/React Linting (eslint + prettier) ─────────────────────────────
run_check "ts-lint" "npx eslint 'src/**/*.{ts,tsx}' --max-warnings 0 2>&1; npx prettier --check 'src/**/*.{ts,tsx}' 2>&1"
# ─── 3. Python Type Checking (mypy) ──────────────────────────────────────────────
run_check "python-types" "mypy app/ --strict --no-error-summary 2>&1"
# ─── 4. TypeScript Type Checking (tsc) ───────────────────────────────────────────
run_check "ts-types" "npx tsc --noEmit 2>&1"
# ─── 5. Python Tests ─────────────────────────────────────────────────────────────
run_check "python-tests" "pytest tests/ -q --tb=short 2>&1"
# ─── 6. React Tests ──────────────────────────────────────────────────────────────
run_check "react-tests" "npm test -- --run --reporter=verbose 2>&1"
# ─── 7. Python Coverage ──────────────────────────────────────────────────────────
run_check "python-coverage" "pytest --cov=app --cov-report=term-missing --cov-fail-under=80 -q 2>&1"
# ─── 8. Dependency Security (pip-audit + npm audit) ───────────────────────────────
run_check "dep-security" "pip-audit --requirement requirements.txt 2>&1; npm audit --audit-level=high 2>&1"
# ─── Summary ─────────────────────────────────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "SUMMARY"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "" >> "$REPORT_FILE"
echo "SUMMARY:" >> "$REPORT_FILE"
TOTAL=$((${#PASSED_CHECKS[@]} + ${#FAILED_CHECKS[@]}))
echo "Total checks: ${TOTAL}"
echo "Passed: ${#PASSED_CHECKS[@]}"
echo "Failed: ${#FAILED_CHECKS[@]}"
echo "Total: ${TOTAL}" >> "$REPORT_FILE"
echo "Passed: ${#PASSED_CHECKS[@]}" >> "$REPORT_FILE"
echo "Failed: ${#FAILED_CHECKS[@]}" >> "$REPORT_FILE"
if [[ ${#PASSED_CHECKS[@]} -gt 0 ]]; then
echo ""
echo "Passed checks:"
for check in "${PASSED_CHECKS[@]}"; do
echo " [PASS] ${check}"
done
fi
if [[ ${#FAILED_CHECKS[@]} -gt 0 ]]; then
echo ""
echo "Failed checks:"
for check in "${FAILED_CHECKS[@]}"; do
echo " [FAIL] ${check}"
done
echo ""
echo "OVERALL: FAIL"
echo "Overall: FAIL" >> "$REPORT_FILE"
echo "Full report: ${REPORT_FILE}"
exit 1
else
echo ""
echo "OVERALL: PASS"
echo "Overall: PASS" >> "$REPORT_FILE"
echo "Full report: ${REPORT_FILE}"
exit 0
fi
#!/usr/bin/env bash
# type-check.sh — Run Python (mypy --strict) and TypeScript (tsc --noEmit) type checks.
#
# Usage:
# ./type-check.sh [--output-dir <dir>] [--python-only] [--ts-only]
#
# Options:
# --output-dir <dir> Directory to write results (default: ./check-results)
# --python-only Run only Python type checking (mypy)
# --ts-only Run only TypeScript type checking (tsc)
set -uo pipefail
# ─── Defaults ───────────────────────────────────────────────────────────────────
OUTPUT_DIR="./check-results"
RUN_PYTHON=true
RUN_TS=true
# ─── Parse arguments ────────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--output-dir)
OUTPUT_DIR="$2"
shift 2
;;
--python-only)
RUN_TS=false
shift
;;
--ts-only)
RUN_PYTHON=false
shift
;;
-h|--help)
echo "Usage: $0 [--output-dir <dir>] [--python-only] [--ts-only]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# ─── Setup ───────────────────────────────────────────────────────────────────────
mkdir -p "$OUTPUT_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
OVERALL_EXIT=0
echo "=== Type Check Suite ==="
echo "Output directory: ${OUTPUT_DIR}"
echo ""
# ─── Python Type Checking (mypy) ─────────────────────────────────────────────────
if [[ "$RUN_PYTHON" == true ]]; then
echo "─── Python (mypy --strict) ───"
MYPY_FILE="$OUTPUT_DIR/mypy-report-${TIMESTAMP}.txt"
mypy app/ --strict \
--no-error-summary \
--show-column-numbers \
--show-error-codes \
--pretty \
2>&1 | tee "$MYPY_FILE"
MYPY_EXIT=${PIPESTATUS[0]}
echo "" >> "$MYPY_FILE"
echo "Timestamp: $(date -Iseconds)" >> "$MYPY_FILE"
if [[ $MYPY_EXIT -eq 0 ]]; then
echo "Python type check: PASS"
echo "Status: PASS" >> "$MYPY_FILE"
else
echo "Python type check: FAIL"
echo "Status: FAIL" >> "$MYPY_FILE"
OVERALL_EXIT=1
fi
echo ""
fi
# ─── TypeScript Type Checking (tsc) ──────────────────────────────────────────────
if [[ "$RUN_TS" == true ]]; then
echo "─── TypeScript (tsc --noEmit) ───"
TSC_FILE="$OUTPUT_DIR/tsc-report-${TIMESTAMP}.txt"
npx tsc --noEmit --pretty 2>&1 | tee "$TSC_FILE"
TSC_EXIT=${PIPESTATUS[0]}
echo "" >> "$TSC_FILE"
echo "Timestamp: $(date -Iseconds)" >> "$TSC_FILE"
if [[ $TSC_EXIT -eq 0 ]]; then
echo "TypeScript type check: PASS"
echo "Status: PASS" >> "$TSC_FILE"
else
echo "TypeScript type check: FAIL"
echo "Status: FAIL" >> "$TSC_FILE"
OVERALL_EXIT=1
fi
echo ""
fi
# ─── Summary ─────────────────────────────────────────────────────────────────────
if [[ $OVERALL_EXIT -eq 0 ]]; then
echo "OVERALL: PASS — All type checks passed."
else
echo "OVERALL: FAIL — One or more type checks failed. See reports in ${OUTPUT_DIR}/"
fi
exit $OVERALL_EXIT