···3131make format # Run swift-format
3232```
33333434+### Local Ghostty sync (avoid submodule/XCFramework drift)
3535+3636+```bash
3737+make ensure-ghostty # fast SHA check, rebuilds only when ThirdParty/ghostty changed
3838+make sync-ghostty # force rebuild + clear DerivedData
3939+```
4040+4141+`build-app` and `test` already run `ensure-ghostty` automatically.
4242+3443## Contributing
35443645- I actual prefer a well written issue describing features/bugs u want rather than a vibe-coded PR
+64
scripts/print-xcresult-failures.sh
···11+#!/usr/bin/env bash
22+33+set -euo pipefail
44+55+if [ "$#" -ne 1 ]; then
66+ echo "usage: $0 <xcresult-path>" >&2
77+ exit 0
88+fi
99+1010+result_bundle="$1"
1111+1212+if [ ! -d "$result_bundle" ]; then
1313+ echo "warning: xcresult bundle not found at $result_bundle"
1414+ exit 0
1515+fi
1616+1717+if ! command -v jq >/dev/null 2>&1; then
1818+ echo "warning: jq is required to parse xcresult summary details"
1919+ exit 0
2020+fi
2121+2222+summary_json="$(mktemp)"
2323+cleanup() {
2424+ rm -f "$summary_json"
2525+}
2626+trap cleanup EXIT
2727+2828+if ! xcrun xcresulttool get test-results summary --path "$result_bundle" --compact >"$summary_json" 2>/dev/null; then
2929+ echo "warning: failed to parse xcresult summary from $result_bundle"
3030+ exit 0
3131+fi
3232+3333+failed_tests="$(
3434+ jq -r '
3535+ if (.failedTests? | type) == "number" then .failedTests
3636+ elif (.failedTests? | type) == "string" then (.failedTests | tonumber? // 0)
3737+ else 0
3838+ end
3939+ ' "$summary_json"
4040+)"
4141+4242+if [ "$failed_tests" -eq 0 ]; then
4343+ echo "No failed tests found in xcresult summary."
4444+ exit 0
4545+fi
4646+4747+echo
4848+echo "================ xcresult failure details ================"
4949+5050+jq -r '
5151+ (.testFailures // []) as $failures
5252+ | if ($failures | length) == 0 then
5353+ "warning: summary has failedTests=\(.failedTests // "unknown"), but no testFailures entries were found."
5454+ else
5555+ $failures[]
5656+ | "test: \(.testName // "unknown")",
5757+ "target: \(.targetName // "unknown")",
5858+ "identifier: \(.testIdentifierString // "n/a")",
5959+ ("failure: " + ((.failureText // "n/a") | gsub("\\n"; "\n "))),
6060+ ""
6161+ end
6262+' "$summary_json"
6363+6464+echo "=========================================================="