Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
509e371
ci: make E2E recording opt-in
arzafran Aug 26, 2026
f7eaaac
test: reproduce duplicate instance arbitration race
arzafran Aug 26, 2026
95e67a2
fix: arbitrate simultaneous app launches
arzafran Aug 26, 2026
01c6d25
fix: exclude embedded cli from instance arbitration
arzafran Aug 26, 2026
22f58dd
test: cover safe duplicate termination
arzafran Aug 27, 2026
b6015dc
fix: harden duplicate app termination
arzafran Aug 27, 2026
2ef6316
test: cover validated duplicate shutdown
arzafran Aug 27, 2026
89c1f7f
fix: validate duplicate shutdown requests
arzafran Aug 27, 2026
d8431da
Merge remote-tracking branch 'origin/main' into followup/single-insta…
arzafran Aug 27, 2026
a18b3cf
wip: stability remainder batch (uncommitted work checkpoint)
arzafran Aug 28, 2026
f524978
Merge origin/main into followup/stability-remainder-2026-08-26
arzafran Aug 28, 2026
bd3c63c
test: reproduce provider usage probes stalling on an idle stderr pipe
arzafran Aug 28, 2026
e65408b
fix: read provider CLI pipes without the shared FileHandle.bytes reader
arzafran Aug 28, 2026
4558ad4
fix: widen the sidebar footer icon pitch
arzafran Aug 28, 2026
43cd0d9
Merge single-instance arbitration (#318) into stability remainder
arzafran Aug 28, 2026
274e8c1
Merge branch 'fix/provider-usage-pipe-starvation' into followup/stabi…
arzafran Aug 28, 2026
5a0f4d3
test: suspend for the git probe instead of spinning the run loop in s…
arzafran Aug 28, 2026
0e0eb45
fix: reject non-ref @ selectors and retry browser scripts in the page…
arzafran Aug 28, 2026
a8dd078
fix: name the candidate seal asset correctly and propagate rolling re…
arzafran Aug 28, 2026
04000af
fix: probe GNU stat before BSD stat so release asset sizes resolve on…
arzafran Aug 28, 2026
abbc2e7
fix: report unknown socket surface ids as not_found and make the mile…
arzafran Aug 28, 2026
52aed62
fix: mark the milestone release harness executable
arzafran Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/ci-macos-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,19 @@ jobs:
xcrun --sdk macosx --show-sdk-path
sw_vers

- name: Resolve Ghostty revision
id: ghostty-revision
run: |
set -euo pipefail
revision="$(./scripts/ghostty_cache_revision.sh)"
printf 'revision=%s\n' "$revision" >> "$GITHUB_OUTPUT"

- name: Cache GhosttyKit.xcframework
id: cache-ghosttykit
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: GhosttyKit.xcframework
key: ghosttykit-v2-${{ hashFiles('.gitmodules', 'ghostty') }}
key: ghosttykit-v3-${{ steps.ghostty-revision.outputs.revision }}

- name: Set up Zig 0.16.0
run: |
Expand Down
151 changes: 86 additions & 65 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,6 @@ on:
push:
branches:
- main
paths:
- ".github/workflows/ci.yml"
- ".github/workflows/ci-macos-compat.yml"
- ".github/workflows/build-ghosttykit.yml"
- "Sources/**"
- "CLI/**"
- "CLI-MCP/**"
- "daemon/**"
- "programaTests/**"
- "tests/**"
- "tests_v2/**"
- "vendor/**"
- "scripts/**"
- "GhosttyTabs.xcodeproj/**"
# Both forms are required: "ghostty/**" matches file changes when the
# submodule content is diffed, but a submodule POINTER bump records the
# bare gitlink path "ghostty", which "ghostty/**" does not match --
# without the exact entry, fork-bump commits skip CI (and therefore
# never auto-ship).
- "ghostty"
- "ghostty/**"
- "vendor/bonsplit/**"
- ".gitmodules"
pull_request:
paths:
- "Sources/**"
Expand All @@ -36,14 +13,22 @@ on:
- "programaTests/**"
- "tests/**"
- "tests_v2/**"
- "Resources/**"
- "Assets.xcassets/**"
- "vendor/**"
- "scripts/**"
- ".github/workflows/ci.yml"
- ".github/workflows/ci-macos-compat.yml"
- ".github/workflows/build-ghosttykit.yml"
- ".github/workflows/release.yml"
- "GhosttyTabs.xcodeproj/**"
# Same as the push filter: the bare "ghostty" entry catches submodule
# pointer bumps, which "ghostty/**" alone misses.
- "programa.entitlements"
- "programa-Bridging-Header.h"
- "ghostty.h"
- "session_escrow_shim.c"
- "session_escrow_shim.h"
# The bare "ghostty" entry catches submodule pointer bumps, which
# "ghostty/**" alone misses.
- "ghostty"
- "ghostty/**"
- ".gitmodules"
Expand Down Expand Up @@ -106,51 +91,42 @@ jobs:
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
git fetch --no-tags origin "${BASE_SHA}" "${HEAD_SHA}"
CHANGED_FILES="$(git diff --name-only "${BASE_SHA}...${HEAD_SHA}")"
RUN_APP_JOBS=false
RUN_REMOTE_DAEMON_JOBS=false
if [[ -z "${CHANGED_FILES}" ]]; then
RUN_APP_JOBS=true
RUN_REMOTE_DAEMON_JOBS=true
CLASSIFICATION="$(printf '%s' "$CHANGED_FILES" | ./scripts/classify_ci_changes.sh)"
APP_OUTPUT="${CLASSIFICATION%%$'\n'*}"
REMOTE_OUTPUT="${CLASSIFICATION#*$'\n'}"

if [[ "$APP_OUTPUT" == "$CLASSIFICATION" || "$REMOTE_OUTPUT" == *$'\n'* ]]; then
echo "CI change classifier returned an invalid output shape" >&2
exit 1
fi

while IFS= read -r path; do
[[ -z "$path" ]] && continue

case "$path" in
# Documentation and prose
*.md|docs/*|plans/*|AGENTS.md|CHANGELOG.md|PROJECTS.md|TODO.md|README.md|LICENSE*|THIRD_PARTY_LICENSES.md|.editorconfig|.gitattributes|.gitignore|*.png|*.jpg|*.jpeg|*.gif|*.webp|*.svg)
continue
;;
# Repository metadata / workflow-only edits are not app/runtime changes
.github/*)
continue
;;
# Localization-only resource edits are scoped out per request
Resources/*.xcstrings|Resources/*/*.xcstrings|Resources/*.strings|Resources/*/*.strings)
continue
;;
# Explicitly skip doc-only translation assets
Resources/*.lproj/*)
continue
;;
daemon/**)
RUN_REMOTE_DAEMON_JOBS=true
;;
*)
RUN_APP_JOBS=true
break
;;
esac
done <<< "$CHANGED_FILES"
case "$APP_OUTPUT" in
run_app_jobs=true) RUN_APP_JOBS=true ;;
run_app_jobs=false) RUN_APP_JOBS=false ;;
*)
echo "CI change classifier returned an invalid app result" >&2
exit 1
;;
esac

case "$REMOTE_OUTPUT" in
run_remote_daemon_jobs=true) RUN_REMOTE_DAEMON_JOBS=true ;;
run_remote_daemon_jobs=false) RUN_REMOTE_DAEMON_JOBS=false ;;
*)
echo "CI change classifier returned an invalid daemon result" >&2
exit 1
;;
esac

echo "run_app_jobs=${RUN_APP_JOBS}" >> "$GITHUB_OUTPUT"
echo "run_remote_daemon_jobs=${RUN_REMOTE_DAEMON_JOBS}" >> "$GITHUB_OUTPUT"
printf '%s\n' "$CLASSIFICATION" >> "$GITHUB_OUTPUT"
{
echo "### CI scope decision"
if [[ "$RUN_APP_JOBS" == "true" ]]; then
echo "Changed file set contains app-relevant changes; running full macOS jobs."
elif [[ "$RUN_REMOTE_DAEMON_JOBS" == "true" ]]; then
echo "Changed file set contains daemon-only changes; running remote daemon jobs."
else
echo "Pull request appears docs/localization-only; skipping heavy app/daemon jobs."
echo "Pull request appears docs/workflow/localization-only; skipping heavy app/daemon jobs."
fi
echo ""
echo "Changed files:"
Expand Down Expand Up @@ -181,6 +157,24 @@ jobs:
- name: Validate release artifact architecture checks
run: ./tests/test_ci_universal_release_settings.sh

- name: Validate rolling release publication
run: ./tests/test_rolling_release_publication.sh

- name: Validate rolling release state transitions
run: node --test scripts/rolling_release_state.test.js

- name: Validate release build identity
run: node --test scripts/release_build_identity.test.js

- name: Validate milestone payload handoff
run: node --test scripts/milestone_payload.test.js

- name: Validate milestone release publication
run: ./tests/test_milestone_release_publication.sh

- name: Validate Sparkle monotonic release guard
run: node --test scripts/sparkle_monotonic_guard.test.js

- name: Validate release asset guard
run: node scripts/release_asset_guard.test.js

Expand Down Expand Up @@ -243,15 +237,28 @@ jobs:
- name: Validate Release reload artifact discovery
run: ./tests/test_reloadp_programa_artifact.sh

- name: Validate Ghostty cache revision
run: ./tests/test_ghostty_cache_revision.sh

- name: Validate CI change classification
run: ./tests/test_ci_change_classification.sh

- name: Validate reload entrypoint artifacts and dependency preparation
run: ./tests/test_reload_entrypoints_artifacts.sh

- name: Resolve Ghostty revision
id: ghostty-revision
run: |
set -euo pipefail
revision="$(./scripts/ghostty_cache_revision.sh)"
printf 'revision=%s\n' "$revision" >> "$GITHUB_OUTPUT"

- name: Cache GhosttyKit.xcframework
id: cache-ghosttykit
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: GhosttyKit.xcframework
key: ghosttykit-v2-${{ hashFiles('.gitmodules', 'ghostty') }}
key: ghosttykit-v3-${{ steps.ghostty-revision.outputs.revision }}

- name: Download pre-built GhosttyKit.xcframework
if: steps.cache-ghosttykit.outputs.cache-hit != 'true'
Expand Down Expand Up @@ -453,12 +460,19 @@ jobs:
sudo xcode-select -s "$XCODE_DIR" || true
xcodebuild -version

- name: Resolve Ghostty revision
id: ghostty-revision
run: |
set -euo pipefail
revision="$(./scripts/ghostty_cache_revision.sh)"
printf 'revision=%s\n' "$revision" >> "$GITHUB_OUTPUT"

- name: Cache GhosttyKit.xcframework
id: cache-ghosttykit-tests-v2
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: GhosttyKit.xcframework
key: ghosttykit-v2-${{ hashFiles('.gitmodules', 'ghostty') }}
key: ghosttykit-v3-${{ steps.ghostty-revision.outputs.revision }}

- name: Download pre-built GhosttyKit.xcframework
if: steps.cache-ghosttykit-tests-v2.outputs.cache-hit != 'true'
Expand Down Expand Up @@ -595,12 +609,19 @@ jobs:
sudo xcode-select -s "$XCODE_DIR" || true
xcodebuild -version

- name: Resolve Ghostty revision
id: ghostty-revision
run: |
set -euo pipefail
revision="$(./scripts/ghostty_cache_revision.sh)"
printf 'revision=%s\n' "$revision" >> "$GITHUB_OUTPUT"

- name: Cache GhosttyKit.xcframework
id: cache-ghosttykit-lag
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: GhosttyKit.xcframework
key: ghosttykit-v2-${{ hashFiles('.gitmodules', 'ghostty') }}
key: ghosttykit-v3-${{ steps.ghostty-revision.outputs.revision }}

- name: Download pre-built GhosttyKit.xcframework
if: steps.cache-ghosttykit-lag.outputs.cache-hit != 'true'
Expand Down
Loading
Loading