Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
222 commits
Select commit Hold shift + click to select a range
2d71966
feat(remote): add authenticated mobile control service
sambitcreate Aug 20, 2026
ea49159
feat(remote-ui): add Remote Access settings and onboarding
sambitcreate Aug 20, 2026
5e416f7
feat(ios): add the Aiden On The Go native client
sambitcreate Aug 20, 2026
0241dbd
docs(ios): document remote architecture and rollout
sambitcreate Aug 20, 2026
096c568
feat(ios): refine the Aiden mobile workspace shell
sambitcreate Aug 20, 2026
8ab986f
test(ios): cover mobile shell edge cases
sambitcreate Aug 20, 2026
b5dbdea
docs(ios): record native shell validation
sambitcreate Aug 20, 2026
33d9904
feat(models): add visibility and custom provider artwork
sambitcreate Aug 20, 2026
6fd0fb2
feat(ios): refine model identity and listening UI
sambitcreate Aug 20, 2026
2ee3b15
fix(ios): float New Agent above home chats
sambitcreate Aug 20, 2026
5a186d8
chore(ios): prepare internal build 8
sambitcreate Aug 20, 2026
01f0e82
docs(ios): record internal TestFlight build 8
sambitcreate Aug 20, 2026
70bd218
feat(providers): add first-class Concentrate support
sambitcreate Aug 20, 2026
5e1cc6e
feat(ios): add Concentrate provider identity
sambitcreate Aug 20, 2026
f78ad4f
feat(ios): refine activity and sync generated titles
sambitcreate Aug 20, 2026
3f65df2
chore(ios): prepare internal build 9
sambitcreate Aug 20, 2026
66496f0
docs(ios): record internal TestFlight build 9
sambitcreate Aug 20, 2026
5cc94eb
docs: add remote multi-instance hardening plan
sambitcreate Aug 21, 2026
6ead7b8
docs(dev): update troubleshooting
sambitcreate Aug 22, 2026
2445458
docs(remote): update aiden-remote-api-v1
sambitcreate Aug 22, 2026
86a2843
docs(plans): update README
sambitcreate Aug 22, 2026
292d548
docs(plans): remove aiden-remote-multi-instance-hardening-plan
sambitcreate Aug 22, 2026
127d3f8
docs(security): update aiden-remote-threat-model
sambitcreate Aug 22, 2026
878950c
docs(ios): update phase-12
sambitcreate Aug 22, 2026
494a5c5
docs(ios): update phase-6
sambitcreate Aug 22, 2026
6994a91
docs(ios): update ASC_CLI
sambitcreate Aug 22, 2026
4112d0e
build(ios): update project
sambitcreate Aug 22, 2026
5c4a9ae
feat(ios): update ContentView
sambitcreate Aug 22, 2026
22b882d
feat(ios): update AidenChatFeature
sambitcreate Aug 22, 2026
fb9fcad
feat(ios): update AidenPairingView
sambitcreate Aug 22, 2026
cdc6369
feat(ios): update AidenRemoteCoordinator
sambitcreate Aug 22, 2026
525d60b
feat(ios): update AidenScheduledTasksView
sambitcreate Aug 22, 2026
c983255
feat(ios): update AidenWorkspaceEnvironmentView
sambitcreate Aug 22, 2026
e261a8d
feat(ios): update AidenWorkspaceShellView
sambitcreate Aug 22, 2026
66c36f8
feat(ios): update AidenRemoteLiveActivityManager
sambitcreate Aug 22, 2026
5c31be4
feat(ios): update AidenInstallation
sambitcreate Aug 22, 2026
1d56926
feat(ios): update AidenRemoteClient
sambitcreate Aug 22, 2026
41b9a09
feat(ios): update AidenRemoteContract
sambitcreate Aug 22, 2026
f629c10
feat(ios): update AidenServerTrust
sambitcreate Aug 22, 2026
74b922b
feat(ios): update AidenChatCache
sambitcreate Aug 22, 2026
8cc55d4
test(ios): update AidenChatTests
sambitcreate Aug 22, 2026
7a39641
test(ios): update AidenNativeIntegrationTests
sambitcreate Aug 22, 2026
594647a
test(ios): update AidenRemoteClientTests
sambitcreate Aug 22, 2026
342c692
test(ios): update AidenRemotePhase0Tests
sambitcreate Aug 22, 2026
3e1129f
test(ios): update AidenScheduledTaskTests
sambitcreate Aug 22, 2026
cea4a2a
test(ios): update AidenWorkspaceEnvironmentTests
sambitcreate Aug 22, 2026
b21c640
docs(ios): update PROJECT_SPEC
sambitcreate Aug 22, 2026
4cc6e23
docs(ios): update TESTFLIGHT
sambitcreate Aug 22, 2026
a48203c
feat(remote): update aiden-remote-parse
sambitcreate Aug 22, 2026
8ba0416
test(main): update aiden-remote.test
sambitcreate Aug 22, 2026
9628f33
feat(remote): update aiden-remote
sambitcreate Aug 22, 2026
adf8e02
feat(providers): update providers
sambitcreate Aug 22, 2026
dcd7090
feat(remote): update index
sambitcreate Aug 22, 2026
160c61f
test(main): update aiden-remote-chat-http.test
sambitcreate Aug 22, 2026
f41bd05
test(main): update aiden-remote-pairing.test
sambitcreate Aug 22, 2026
c872001
feat(remote): update aiden-remote-pairing
sambitcreate Aug 22, 2026
55979f1
test(main): update aiden-remote-protocol.test
sambitcreate Aug 22, 2026
8ece1be
feat(remote): update aiden-remote-protocol
sambitcreate Aug 22, 2026
0cfce64
test(main): update aiden-remote-router.test
sambitcreate Aug 22, 2026
33066ed
feat(remote): update aiden-remote-router
sambitcreate Aug 22, 2026
39216d7
feat(remote): update aiden-remote-service-main
sambitcreate Aug 22, 2026
68dd3a1
test(main): update aiden-remote-service.test
sambitcreate Aug 22, 2026
f4ede71
feat(remote): update aiden-remote-service
sambitcreate Aug 22, 2026
6015635
test(main): update aiden-remote-state.test
sambitcreate Aug 22, 2026
321f62e
feat(remote): update aiden-remote-state
sambitcreate Aug 22, 2026
7bcfa2f
test(main): update aiden-remote-streams.test
sambitcreate Aug 22, 2026
97abff2
feat(remote): update aiden-remote-streams
sambitcreate Aug 22, 2026
25b7226
test(main): update aiden-remote-tailscale-route.test
sambitcreate Aug 22, 2026
d4c3f6a
feat(remote): update aiden-remote-tailscale-route
sambitcreate Aug 22, 2026
588197d
test(main): update aiden-remote-tailscale.test
sambitcreate Aug 22, 2026
5ff954c
feat(remote): update aiden-remote-tailscale
sambitcreate Aug 22, 2026
2ec39da
test(main): update aiden-remote-workspace-http.test
sambitcreate Aug 22, 2026
fc287ca
test(main): update models.test
sambitcreate Aug 22, 2026
30e7101
feat(models): update models
sambitcreate Aug 22, 2026
4e281d8
feat(remote): update portable-config-core
sambitcreate Aug 22, 2026
c15b3d2
test(main): update provider-auth-flow-core.test
sambitcreate Aug 22, 2026
0c44868
feat(providers): update provider-auth-flow-core
sambitcreate Aug 22, 2026
821cb2b
test(main): update provider-credential-rotation-core.test
sambitcreate Aug 22, 2026
d88ca41
feat(providers): update provider-credential-rotation-core
sambitcreate Aug 22, 2026
344d106
feat(providers): update provider-registry
sambitcreate Aug 22, 2026
c4872d3
feat(remote): update types
sambitcreate Aug 22, 2026
0bf2645
test(repo): update package
sambitcreate Aug 22, 2026
729bbbd
feat(protocol): update contract
sambitcreate Aug 22, 2026
03c96cf
feat(protocol): update openapi
sambitcreate Aug 22, 2026
77e1427
test(renderer): update chat-sidebar.test
sambitcreate Aug 22, 2026
0885f90
feat(renderer): update chat-sidebar
sambitcreate Aug 22, 2026
e075749
test(renderer): update onboarding-flow.test
sambitcreate Aug 22, 2026
9a928ad
feat(onboarding): update onboarding-flow
sambitcreate Aug 22, 2026
4cb7631
feat(settings): update about-settings
sambitcreate Aug 22, 2026
39f5e20
feat(settings): update builtin-provider-editor
sambitcreate Aug 22, 2026
ff68f6d
feat(settings): update codex-provider-settings
sambitcreate Aug 22, 2026
157058a
test(renderer): update remote-access-settings.test
sambitcreate Aug 22, 2026
d824a4d
feat(settings): update remote-access-settings
sambitcreate Aug 22, 2026
e4474b8
feat(renderer): update ui
sambitcreate Aug 22, 2026
2f8f9bd
feat(renderer): update codex-auth-view-state
sambitcreate Aug 22, 2026
f499c07
feat(renderer): update ipc
sambitcreate Aug 22, 2026
f46e05c
test(renderer): update onboarding-state.test
sambitcreate Aug 22, 2026
0298533
feat(onboarding): update onboarding-state
sambitcreate Aug 22, 2026
d1ddfc4
feat(renderer): update types
sambitcreate Aug 22, 2026
8f8cc55
feat(renderer): update root-view
sambitcreate Aug 22, 2026
5c5c53d
feat(renderer): update aiden-remote
sambitcreate Aug 22, 2026
963fca0
feat(onboarding): update onboarding
sambitcreate Aug 22, 2026
8a2ed94
docs(plans): add aiden-manual-pairing-plan
sambitcreate Aug 22, 2026
3b2ee2d
docs(plans): add aiden-remote-multi-instance-hardening-plan
sambitcreate Aug 22, 2026
d12cdc9
docs(plans): add onboarding-auth-and-provider-validation-plan
sambitcreate Aug 22, 2026
31daaf2
test(main): add aiden-remote-revocation.test
sambitcreate Aug 22, 2026
ea2a8d5
feat(remote): add aiden-remote-revocation
sambitcreate Aug 22, 2026
b2b4336
test(main): add onboarding-provider-validation.test
sambitcreate Aug 22, 2026
794ffde
feat(onboarding): add onboarding-provider-validation
sambitcreate Aug 22, 2026
7f644a9
test(main): add onboarding-state-core.test
sambitcreate Aug 22, 2026
df79e07
feat(onboarding): add onboarding-state-core
sambitcreate Aug 22, 2026
2c7be5a
feat(onboarding): add onboarding-state
sambitcreate Aug 22, 2026
8848051
feat(protocol): add manual-pairing-vector
sambitcreate Aug 22, 2026
12e7e93
test(renderer): add remote-connection-popover.test
sambitcreate Aug 22, 2026
2b22425
feat(renderer): add remote-connection-popover
sambitcreate Aug 22, 2026
e89b224
test(renderer): add remote-connection-status.test
sambitcreate Aug 22, 2026
84b912f
feat(renderer): add remote-connection-status
sambitcreate Aug 22, 2026
2b3cc1c
test(renderer): add remote-pairing-lifecycle.test
sambitcreate Aug 22, 2026
a96d352
feat(renderer): add remote-pairing-lifecycle
sambitcreate Aug 22, 2026
91bcc5b
test(renderer): add onboarding.test
sambitcreate Aug 22, 2026
6ad260f
test(e2e): scope remote access readiness status
sambitcreate Aug 22, 2026
db366d7
test(e2e): scope disabled remote access status
sambitcreate Aug 22, 2026
b129252
fix(remote): close rollback sockets before listeners
sambitcreate Aug 22, 2026
5b75e4e
docs: record catalog and device tooling papercuts
sambitcreate Aug 22, 2026
2cf4ce7
docs: update dynamic catalog plan status
sambitcreate Aug 22, 2026
ba2b8c9
docs: record first-class iOS pairing choices
sambitcreate Aug 22, 2026
507c329
docs: finalize dynamic model catalog plan
sambitcreate Aug 22, 2026
4570d8c
docs: record physical pairing validation
sambitcreate Aug 22, 2026
f7bc713
feat(models): coordinate Pi catalog refreshes
sambitcreate Aug 22, 2026
d4efea5
feat(models): resolve provider model metadata
sambitcreate Aug 22, 2026
20b15d6
feat(models): define Pi provider compatibility
sambitcreate Aug 22, 2026
ddfa90e
feat(models): fetch bounded Pi remote catalogs
sambitcreate Aug 22, 2026
14f4397
test(models): cover Pi remote catalog hardening
sambitcreate Aug 22, 2026
ed340a6
feat(models): persist dynamic Pi model overlays
sambitcreate Aug 22, 2026
4b58208
feat(providers): merge refreshed Pi model catalogs
sambitcreate Aug 22, 2026
75b7e38
feat(providers): expose refreshed model metadata
sambitcreate Aug 22, 2026
2478b47
test(providers): verify dynamic model metadata
sambitcreate Aug 22, 2026
1aae5f5
feat(providers): refresh models after authentication
sambitcreate Aug 22, 2026
d0a1156
test(providers): cover authenticated model refresh
sambitcreate Aug 22, 2026
600d580
fix(onboarding): validate against refreshed models
sambitcreate Aug 22, 2026
4b22e49
test(onboarding): cover refreshed provider validation
sambitcreate Aug 22, 2026
84b1d6c
feat(config): persist model catalog refresh state
sambitcreate Aug 22, 2026
df8f410
test(config): cover model catalog persistence
sambitcreate Aug 22, 2026
0756556
feat(config): normalize portable model metadata
sambitcreate Aug 22, 2026
c01d09b
feat(models): type provider catalog warnings
sambitcreate Aug 22, 2026
1cd7965
fix(models): use compatible OpenCode Go transport
sambitcreate Aug 22, 2026
37b92d0
fix(thinking): align runtime model thinking levels
sambitcreate Aug 22, 2026
fb11971
test(thinking): cover dynamic runtime levels
sambitcreate Aug 22, 2026
fe44623
feat(remote): project refreshed models to iOS
sambitcreate Aug 22, 2026
f69c0c0
test(remote): cover dynamic iOS model projection
sambitcreate Aug 22, 2026
2459e6e
test(remote): lock additive thinking defaults
sambitcreate Aug 22, 2026
0e3a7a5
feat(providers): add explicit catalog refresh actions
sambitcreate Aug 22, 2026
b0a5b44
docs(protocol): expose model thinking defaults
sambitcreate Aug 22, 2026
5696e6e
feat(thinking): centralize provider thinking choices
sambitcreate Aug 22, 2026
773d7b3
test(thinking): cover provider thinking choices
sambitcreate Aug 22, 2026
91cfda9
feat(models): type dynamic provider catalog state
sambitcreate Aug 22, 2026
4a93bff
feat(models): expose catalog refresh IPC
sambitcreate Aug 22, 2026
949d19f
feat(settings): refresh provider model catalogs
sambitcreate Aug 22, 2026
138640c
feat(settings): show refreshed builtin models
sambitcreate Aug 22, 2026
ef74488
fix(onboarding): reconcile refreshed model choices
sambitcreate Aug 22, 2026
36e1ca3
feat(models): refresh catalog from command palette
sambitcreate Aug 22, 2026
dbcae51
feat(thinking): render dynamic thinking choices
sambitcreate Aug 22, 2026
75531ac
feat(models): refresh stale catalogs after launch
sambitcreate Aug 22, 2026
5619dfe
feat(ios): decode model thinking defaults
sambitcreate Aug 22, 2026
d440b12
feat(ios): apply remote thinking defaults
sambitcreate Aug 22, 2026
0b333c3
test(ios): cover model thinking defaults
sambitcreate Aug 22, 2026
f249b2c
test(ios): decode refreshed remote models
sambitcreate Aug 22, 2026
aca88c3
feat(ios): expose every Aiden pairing method
sambitcreate Aug 22, 2026
678efd5
test(ios): mirror Mac pairing choices
sambitcreate Aug 22, 2026
d6f2175
chore(models): refresh bundled model capabilities
sambitcreate Aug 22, 2026
886803d
test(ios): lock first-class pairing surfaces
sambitcreate Aug 22, 2026
0478732
test(models): register catalog refresh coverage
sambitcreate Aug 22, 2026
3498c1e
chore(ios): advance TestFlight build to 11
sambitcreate Aug 22, 2026
93f147e
docs(ios): record build 11 App Store state
sambitcreate Aug 22, 2026
963c7ab
docs(ios): update internal TestFlight candidate
sambitcreate Aug 22, 2026
7e5ac84
docs(ios): record build 11 release evidence
sambitcreate Aug 22, 2026
c667ff4
feat(ios): add progressive onboarding and pairing tabs
sambitcreate Aug 22, 2026
fe18160
chore(remote): advance fixture contract revision
sambitcreate Aug 22, 2026
fb28310
feat(remote): describe image content and turn outcomes
sambitcreate Aug 22, 2026
418980f
docs(remote): document image content and terminal outcomes
sambitcreate Aug 22, 2026
ec3e740
feat(remote): project image attachments and safe outcomes
sambitcreate Aug 22, 2026
8fc523d
test(remote): cover attachment content and outcomes
sambitcreate Aug 22, 2026
6ee28d7
feat(remote): serve authenticated attachment images
sambitcreate Aug 22, 2026
14ef747
test(remote): verify attachment image HTTP route
sambitcreate Aug 22, 2026
fb285ff
test(remote): cover attachment content route contract
sambitcreate Aug 22, 2026
f026c71
fix(remote): reconcile terminal stream outcomes
sambitcreate Aug 22, 2026
2d2e410
test(remote): cover cancellation and terminal replay
sambitcreate Aug 22, 2026
fbe3e0f
fix(agent): persist initialization terminal states once
sambitcreate Aug 22, 2026
5ab4f84
test(agent): cover initialization terminal persistence
sambitcreate Aug 22, 2026
5d628b0
fix(agent): publish durable initialization failures
sambitcreate Aug 22, 2026
f266ded
test(agent): enforce terminal state ordering
sambitcreate Aug 22, 2026
5a83c7a
test(agent): register initialization terminal coverage
sambitcreate Aug 22, 2026
4981ae4
feat(ios): model attachments and terminal outcomes
sambitcreate Aug 22, 2026
91f66dc
feat(ios): fetch authenticated chat images
sambitcreate Aug 22, 2026
6ad7965
feat(ios): cache bounded protected chat images
sambitcreate Aug 22, 2026
e2f7532
feat(ios): render stable sender-edge image decks
sambitcreate Aug 22, 2026
06d4bc9
test(ios): cover chat media rendering and outcomes
sambitcreate Aug 22, 2026
7f8655b
feat(ios): adapt onboarding actions across window sizes
sambitcreate Aug 22, 2026
8440c65
test(ios): cover adaptive onboarding layout
sambitcreate Aug 22, 2026
695e5aa
test(ios): verify authenticated image downloads
sambitcreate Aug 22, 2026
5df044a
test(ios): expect remote contract revision four
sambitcreate Aug 22, 2026
c39fae1
chore(ios): explain save-to-photos permission
sambitcreate Aug 22, 2026
c49f6f5
test(ios): lock adaptive onboarding action layout
sambitcreate Aug 22, 2026
7939a30
docs(plan): record attachment and carousel completion
sambitcreate Aug 22, 2026
55e93b9
chore(ios): bump internal TestFlight build to 12
sambitcreate Aug 22, 2026
a1f9ee3
fix(ios): preserve all inline image corners
sambitcreate Aug 22, 2026
bf09c78
test(ios): lock image mask modifier order
sambitcreate Aug 22, 2026
15e8002
docs(plan): record fitted image corner correction
sambitcreate Aug 22, 2026
b2a3f91
chore(ios): bump replacement TestFlight build to 13
sambitcreate Aug 22, 2026
b51ae42
docs(ios): record TestFlight build 13 identity
sambitcreate Aug 22, 2026
3d9eb98
docs(test): record build 13 release evidence
sambitcreate Aug 22, 2026
de68df3
feat(linux): checkpoint desktop support implementation
sambitcreate Aug 26, 2026
09d5890
feat(linux): sync desktop support with 0.36.0
sambitcreate Aug 30, 2026
bb96328
test(linux): tolerate native helper pipe closure
sambitcreate Aug 30, 2026
65183a6
feat(linux): sync native Pi extensions from 0.36.1
sambitcreate Aug 30, 2026
2cc31db
chore(linux): sync latest model catalog
sambitcreate Aug 30, 2026
901110a
ci(linux): verify baseline RPM on Fedora
sambitcreate Aug 30, 2026
f291676
test(linux): match shipped dictation fallback copy
sambitcreate Aug 30, 2026
32cb95d
docs(linux): archive completed desktop support plan
sambitcreate Aug 30, 2026
0e414b4
Merge remote-tracking branch 'origin/main' into feature/linux-desktop…
sambitcreate Aug 30, 2026
5b380a3
test(e2e): clear scheduled search deterministically
sambitcreate Aug 30, 2026
6a39757
test: harden watcher and scheduled search flows
sambitcreate Aug 30, 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
177 changes: 177 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,180 @@ jobs:
path: test-results/e2e-safe-receipt.json
if-no-files-found: error
retention-days: 7

linux:
name: Linux ${{ matrix.arch }}
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
- arch: arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
steps:
- name: Check out source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803

- name: Use Node.js 22
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
with:
node-version: 22.22.3
cache: npm

- name: Install Linux test dependencies
run: sudo apt-get update && sudo apt-get install --yes rpm xvfb

- name: Install locked dependencies
run: npm ci

- name: Verify TypeScript and lint
run: npm run type-check && npm run lint

- name: Run Pi extension, Linux contract, and native helper tests
run: npm run test:pi-extensions && npm run test:linux-contracts && npm run test:linux-native

- name: Build, install, and verify Linux distributions
run: |
set -euo pipefail
npm run dist:linux
node scripts/verify-linux-package.mjs release/linux-distribution
sudo apt-get install --yes ./release/linux-distribution/*.deb
dpkg --verify aiden-agent
! ldd "/opt/Aiden Agent/aiden-agent" | grep -q "not found"
test -f /usr/share/applications/com.sambitcreate.aiden-agent.desktop
grep -F 'StartupWMClass=com.sambitcreate.aiden-agent' /usr/share/applications/com.sambitcreate.aiden-agent.desktop
expected_version="$(node -p 'require("./package.json").version')"
test "$(aiden-agent --no-sandbox --version)" = "$expected_version"
chmod +x ./release/linux-distribution/*.AppImage
appimage_output="$(./release/linux-distribution/*.AppImage --appimage-extract-and-run --no-sandbox --version)"
grep -F "$expected_version" <<<"$appimage_output"

- name: Prepare baseline-verified RPM for Fedora acceptance
if: matrix.arch == 'x64'
shell: bash
run: |
set -euo pipefail
shopt -s nullglob
rpm_files=(release/linux-distribution/*.rpm)
test "${#rpm_files[@]}" -eq 1
rpm_name="$(basename "${rpm_files[0]}")"
(
cd release/linux-distribution
sha256sum "$rpm_name" > rpm.sha256
)

- name: Upload baseline-verified RPM for Fedora acceptance
if: matrix.arch == 'x64'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: linux-rpm-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: |
release/linux-distribution/*.rpm
release/linux-distribution/rpm.sha256
if-no-files-found: error
retention-days: 1

- name: Smoke the installed GUI without a keyring session
shell: bash
run: |
set -euo pipefail
smoke_root="$RUNNER_TEMP/aiden-linux-smoke-${{ matrix.arch }}"
mkdir -p "$smoke_root/home" "$smoke_root/config" "$smoke_root/cache" "$smoke_root/data"
set +e
HOME="$smoke_root/home" \
XDG_CONFIG_HOME="$smoke_root/config" \
XDG_CACHE_HOME="$smoke_root/cache" \
XDG_DATA_HOME="$smoke_root/data" \
timeout --signal=KILL 15s xvfb-run --auto-servernum aiden-agent --no-sandbox \
>"$smoke_root/output.log" 2>&1
status=$?
set -e
# A living GUI is the success condition. Kill the whole timeout
# process group instead of asking Electron to perform a production
# shutdown inside an incomplete headless desktop session.
if [[ "$status" -ne 137 ]]; then
cat "$smoke_root/output.log"
exit 1
fi
if grep -Eiq '(FATAL|symbol lookup error|error while loading shared libraries|Failed to start Aiden Agent)' "$smoke_root/output.log"; then
cat "$smoke_root/output.log"
exit 1
fi

- name: Run deterministic Electron E2E gate
if: matrix.arch == 'x64'
run: xvfb-run --auto-servernum npm run test:e2e

- name: Build sanitized E2E failure receipt
if: ${{ failure() && matrix.arch == 'x64' }}
run: npm run diagnostics:failure-receipt -- test-results/e2e-safe-receipt.json electron-e2e test-failed

- name: Upload sanitized E2E failure receipt
if: ${{ failure() && matrix.arch == 'x64' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: playwright-e2e-linux-${{ github.run_id }}-${{ github.run_attempt }}
path: test-results/e2e-safe-receipt.json
if-no-files-found: error
retention-days: 7

linux-rpm:
name: Linux x64 · Fedora RPM
needs: linux
runs-on: ubuntu-24.04
container: fedora:44
timeout-minutes: 60
steps:
- name: Install Fedora build prerequisites
run: dnf install --assumeyes git gcc gcc-c++ make python3

- name: Check out source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803

- name: Use Node.js 22
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
with:
node-version: 22.22.3
cache: npm

- name: Install locked dependencies
run: npm ci

- name: Verify Fedora Pi extensions, contracts, and native helpers
run: npm run type-check && npm run test:pi-extensions && npm run test:linux-contracts && npm run test:linux-native

- name: Download baseline-verified RPM
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
with:
name: linux-rpm-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: release/linux-rpm-smoke

- name: Install and verify baseline-verified RPM package
run: |
set -euo pipefail
shopt -s nullglob
rpm_files=(release/linux-rpm-smoke/*.rpm)
test "${#rpm_files[@]}" -eq 1
(
cd release/linux-rpm-smoke
sha256sum --check rpm.sha256
)
expected_version="$(node -p 'require("./package.json").version')"
test "$(rpm -qp --queryformat '%{NAME} %{VERSION} %{ARCH}' "${rpm_files[0]}")" = \
"aiden-agent $expected_version x86_64"
dnf install --assumeyes "${rpm_files[0]}"
node scripts/verify-linux-package.mjs "/opt/Aiden Agent"
rpm_verify_output="$(rpm --verify aiden-agent || true)"
if [ -n "$rpm_verify_output" ]; then
# electron-builder deliberately enables its setuid fallback when
# user namespaces do not work (including containerized CI). Keep
# every other RPM integrity difference fatal and prove the exact
# privileged file owner/mode before accepting that one transition.
test "$rpm_verify_output" = '.M....... /opt/Aiden Agent/chrome-sandbox'
test "$(stat -c '%a:%U:%G' '/opt/Aiden Agent/chrome-sandbox')" = '4755:root:root'
fi
! ldd "/opt/Aiden Agent/aiden-agent" | grep -q "not found"
test "$(aiden-agent --no-sandbox --version)" = "$expected_version"
173 changes: 168 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Release macOS
name: Release desktop

on:
push:
Expand All @@ -14,7 +14,7 @@ permissions:
contents: write

concurrency:
group: aiden-agent-macos-release
group: aiden-agent-desktop-release
cancel-in-progress: false

jobs:
Expand Down Expand Up @@ -145,13 +145,176 @@ jobs:
if: ${{ steps.version.outputs.publish == 'true' }}
run: npm run test:e2e:diagnostics:packaged

- name: Stage verified macOS release assets
if: ${{ steps.version.outputs.publish == 'true' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: release-macos
path: release/distribution
if-no-files-found: error
retention-days: 2

linux-release:
if: vars.RELEASES_ENABLED == 'true'
name: Linux ${{ matrix.arch }} release
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: ubuntu-24.04
- arch: arm64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
timeout-minutes: 90
environment: release
steps:
- name: Check out source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803

- name: Use Node.js 22
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
with:
node-version: 22.22.3
cache: npm

- name: Resolve the declared release version
id: version
shell: bash
run: |
set -euo pipefail
base_version="$(node -p "require('./package.json').version")"
base_tag_match="$(git ls-remote --tags origin "refs/tags/v${base_version}")"
base_tag_exists=false
if [[ -n "$base_tag_match" ]]; then
base_tag_exists=true
fi
selection="$(node scripts/prepare-ci-release.mjs "$base_tag_exists")"
release_version="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).version)' "$selection")"
release_tag="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).tag)' "$selection")"
should_publish="$(node -e 'process.stdout.write(String(JSON.parse(process.argv[1]).publish))' "$selection")"
echo "version=$release_version" >> "$GITHUB_OUTPUT"
echo "tag=$release_tag" >> "$GITHUB_OUTPUT"
echo "publish=$should_publish" >> "$GITHUB_OUTPUT"

- name: Install Linux package dependencies
if: ${{ steps.version.outputs.publish == 'true' }}
run: sudo apt-get update && sudo apt-get install --yes rpm xvfb

- name: Install locked dependencies
if: ${{ steps.version.outputs.publish == 'true' }}
run: npm ci

- name: Verify Linux contracts, diagnostics, and native helpers
if: ${{ steps.version.outputs.publish == 'true' }}
run: npm run type-check && npm run lint && npm run test:diagnostics && npm run test:linux-contracts && npm run test:linux-native

- name: Build and verify Linux distributions
if: ${{ steps.version.outputs.publish == 'true' }}
run: |
set -euo pipefail
npm run models:refresh
npm run dist:linux
node scripts/verify-linux-package.mjs release/linux-distribution
sudo apt-get install --yes ./release/linux-distribution/*.deb
dpkg --verify aiden-agent
! ldd "/opt/Aiden Agent/aiden-agent" | grep -q "not found"
expected_version="$(node -p 'require("./package.json").version')"
test "$(aiden-agent --no-sandbox --version)" = "$expected_version"
chmod +x ./release/linux-distribution/*.AppImage
appimage_output="$(./release/linux-distribution/*.AppImage --appimage-extract-and-run --no-sandbox --version)"
grep -F "$expected_version" <<<"$appimage_output"

- name: Smoke the exact release GUI without a keyring session
if: ${{ steps.version.outputs.publish == 'true' }}
shell: bash
run: |
set -euo pipefail
smoke_root="$RUNNER_TEMP/aiden-linux-release-smoke-${{ matrix.arch }}"
mkdir -p "$smoke_root/home" "$smoke_root/config" "$smoke_root/cache" "$smoke_root/data"
set +e
HOME="$smoke_root/home" \
XDG_CONFIG_HOME="$smoke_root/config" \
XDG_CACHE_HOME="$smoke_root/cache" \
XDG_DATA_HOME="$smoke_root/data" \
timeout --signal=KILL 15s xvfb-run --auto-servernum aiden-agent --no-sandbox \
>"$smoke_root/output.log" 2>&1
status=$?
set -e
# A living GUI is the success condition. Kill the whole timeout
# process group instead of asking Electron to perform a production
# shutdown inside an incomplete headless desktop session.
if [[ "$status" -ne 137 ]]; then
cat "$smoke_root/output.log"
exit 1
fi
if grep -Eiq '(FATAL|symbol lookup error|error while loading shared libraries|Failed to start Aiden Agent)' "$smoke_root/output.log"; then
cat "$smoke_root/output.log"
exit 1
fi

- name: Stage verified Linux release assets
if: ${{ steps.version.outputs.publish == 'true' }}
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: release-linux-${{ matrix.arch }}
path: |
release/linux-distribution/*.AppImage
release/linux-distribution/*.deb
release/linux-distribution/*.rpm
if-no-files-found: error
retention-days: 2

publish:
if: vars.RELEASES_ENABLED == 'true'
name: Publish verified desktop release
needs:
- release
- linux-release
runs-on: ubuntu-24.04
timeout-minutes: 20
environment: release
steps:
- name: Check out source
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803

- name: Use Node.js 22
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
with:
node-version: 22.22.3

- name: Resolve release identity
id: version
shell: bash
run: |
set -euo pipefail
base_version="$(node -p "require('./package.json').version")"
base_tag_match="$(git ls-remote --tags origin "refs/tags/v${base_version}")"
base_tag_exists=false
if [[ -n "$base_tag_match" ]]; then
base_tag_exists=true
fi
selection="$(node scripts/prepare-ci-release.mjs "$base_tag_exists")"
release_version="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).version)' "$selection")"
release_tag="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).tag)' "$selection")"
should_publish="$(node -e 'process.stdout.write(String(JSON.parse(process.argv[1]).publish))' "$selection")"
echo "version=$release_version" >> "$GITHUB_OUTPUT"
echo "tag=$release_tag" >> "$GITHUB_OUTPUT"
echo "publish=$should_publish" >> "$GITHUB_OUTPUT"

- name: Download verified desktop assets
if: ${{ steps.version.outputs.publish == 'true' }}
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e
with:
pattern: release-*
path: release/distribution
merge-multiple: true

- name: Publish verified release assets
if: ${{ steps.version.outputs.publish == 'true' }}
shell: bash
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ steps.version.outputs.tag }}
RELEASE_VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
bash scripts/publish-github-release.sh release/distribution
run: bash scripts/publish-github-release.sh release/distribution
Loading
Loading