Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
960 commits
Select commit Hold shift + click to select a range
8838e4f
fix(linux-remote-desktop): wire the same-version worker repair on Lin…
Sep 17, 2026
f34c30b
fix(linux-remote-desktop): stop dropping the disclosure capability th…
Sep 17, 2026
7d0a092
fix(linux-remote-desktop): give the spawned worker a real DISPLAY to …
Sep 17, 2026
260eed7
fix(server): stop rejecting every Linux controlled node as unsupporte…
Sep 17, 2026
117d076
fix(shared): stop deciding controlled-node remote-desktop OS support …
Sep 17, 2026
83323fd
fix(linux-remote-desktop): stop the worker aborting on a real audio d…
Sep 17, 2026
64de94c
feat(scripts): default the Linux desktop bootstrap to XFCE + Whisker …
Sep 17, 2026
04f6c51
feat(linux-remote-desktop): wire pointer/keyboard input, not just vie…
Sep 17, 2026
4afce5d
fix(linux-remote-desktop): stop the worker's own STATUS claiming inpu…
Sep 17, 2026
5f49a67
feat(web): quick-open remote desktop from the sub-session window too
Sep 17, 2026
3ff894d
fix(linux-remote-desktop): actually enter Controlling state, not just…
Sep 17, 2026
d5af81c
fix(macos-remote-desktop): stop the idle worker respawn loop behind t…
Sep 17, 2026
e1e82c4
fix(daemon): stop supervision task console messages from logging as u…
Sep 17, 2026
3230b2b
fix(linux-remote-desktop): send selectedDisplayId/layoutRevision on S…
Sep 17, 2026
3f3e2c9
fix(web): recognize the macOS install-capability wire name too
Sep 17, 2026
32b479a
fix(linux-remote-desktop): send display_topology, the piece 3ff894d2 …
Sep 17, 2026
338411d
fix(daemon): give a not-yet-seen assistant response the same wait bud…
Sep 17, 2026
0438dff
fix(linux-remote-desktop): drop the wire-invalid "selectable" key fro…
Sep 17, 2026
9d480b7
fix(ci): stop cancelling dev/main/master runs mid-publish
Sep 17, 2026
a15438f
fix(macos-remote-desktop): stop ready/installable flipping on ordinar…
Sep 17, 2026
0e9533c
fix(daemon): resolve integration-bundle files against the task's comm…
Sep 17, 2026
2c0cc6d
fix(daemon): replace a raw NUL byte with its escape sequence in the c…
Sep 17, 2026
c6a3fa9
fix(linux-remote-desktop): wire PREPARE's ice_servers into the peer c…
Sep 17, 2026
dad97c0
fix(linux-remote-desktop): let concurrent sessions share one X11 capture
Sep 17, 2026
e05883a
fix(macos-remote-desktop): throttle the unthrottled peer_disconnected…
Sep 17, 2026
b50c9ad
fix(web): auto-continue timeline catch-up past one round's page budget
Sep 17, 2026
7b25fbb
fix(remote-desktop): make mobile IME Enter actually reach the remote …
Sep 17, 2026
0b23a19
fix(daemon): don't fail-close assignment scope projection when no sco…
Sep 17, 2026
2711ee4
fix(daemon): give implicit task-candidate completion grace the same n…
Sep 17, 2026
ebceae8
Merge remote-tracking branch 'origin/dev' into HEAD
Sep 17, 2026
0aadc3d
Merge remote-tracking branch 'origin/dev' into HEAD
Sep 17, 2026
6253fea
fix(linux-remote-desktop): report firstFramePresented so sessions sur…
Sep 17, 2026
27bf925
fix(remote-desktop): stop macOS worker respawn churn and a guaranteed…
Sep 17, 2026
d8d1473
fix(daemon): dispatchReadyAudit honors a legitimate re-audit request …
Sep 18, 2026
39ffd4d
feat(web): pinch-to-zoom and mouse-wheel zoom for ImageLightbox
Sep 18, 2026
9da5b73
fix(linux-remote-desktop): record real outbound video RTP bytes so me…
Sep 18, 2026
c7509c5
fix(daemon): let the project's own Brain attach coordinator to a task…
Sep 18, 2026
0ff57e8
fix(daemon): redeliver a stale never-evidenced audit dispatch, and st…
Sep 18, 2026
78160e7
fix(macos-remote-desktop): let the background installer re-check afte…
Sep 18, 2026
b087e01
fix(linux-remote-desktop): decode UTF-8 codepoints in EmitText instea…
Sep 18, 2026
1babb53
fix(web): clear the mobile IME text input even when the remote send f…
Sep 18, 2026
701dbb5
fix(linux-remote-desktop): make Lease::captured_frames_ atomic
Sep 18, 2026
d6041d0
fix(remote-desktop): recover a suspended route on daemon reconnect wh…
Sep 18, 2026
ec5d498
fix(linux-remote-desktop): translate KeyboardEvent.code to an X11 key…
Sep 18, 2026
4e0f56d
test(linux-remote-desktop): add EmitKey DOM-code qualification coverage
Sep 18, 2026
3a1008a
fix(remote-desktop): keep the browser signaling socket alive with a p…
Sep 18, 2026
7324264
fix(web): put Append-mode sends straight into the timeline
Sep 18, 2026
94500b3
fix(linux-remote-desktop): apply LEASE renewals and MODE_STATE instea…
Sep 18, 2026
d9b5c6e
fix(linux-remote-desktop): acknowledge input so a keypress or click n…
Sep 18, 2026
247d8b6
Revert "fix(remote-desktop): keep the browser signaling socket alive …
Sep 18, 2026
f7820cf
Revert "fix(remote-desktop): recover a suspended route on daemon reco…
Sep 18, 2026
45ff321
fix(remote-desktop): let a failed peer report disconnected after a ho…
Sep 18, 2026
f58e136
fix(web): make a popped-out remote desktop window fill the browser wi…
Sep 18, 2026
a02f2b2
feat(remote-desktop): remote-desktop button for Linux/macOS daemons, …
Sep 18, 2026
ddcaafb
fix: keep heartbeats and acks flowing when the daemon uplink is conge…
Sep 18, 2026
45a95dd
test(shared): pin the controlled_node.local_daemons message in the wi…
Sep 18, 2026
cf69b8d
feat(web): make remote desktop window tabs read as tabs, open pop-out…
Sep 18, 2026
10ed5f5
style(web): quiet neutral remote desktop toolbar, textured window tabs
Sep 18, 2026
2257607
fix: let server/session participants see and edit the owner's project…
Sep 18, 2026
cc58c3a
feat(web): remember the chosen machine group in this browser
Sep 18, 2026
560b467
feat(identity): raise project identity to 150k and session identity t…
Sep 18, 2026
6ea711a
style(web): machine group counts as true corner superscripts
Sep 18, 2026
4d06e07
fix(share): whole-server participants can browse and act before a ses…
Sep 18, 2026
25f913f
style(web): put the active remote desktop tab marker on the bottom edge
Sep 18, 2026
1002fd7
fix(linux-remote-desktop): make copy and paste work on Linux targets
Sep 18, 2026
ab32f6f
feat(remote-desktop): translate shortcuts between Mac, Windows and Li…
Sep 18, 2026
79a1a8f
fix(linux-remote-desktop): ending one session no longer stops screen …
Sep 18, 2026
7e8a055
fix(remote-desktop): do not spend reconnect attempts while the page i…
Sep 18, 2026
0b3e72a
fix(macos-remote-desktop): hold a reconnect until the replacement wor…
Sep 18, 2026
6988c8c
chore(macos-remote-desktop): say why a PREPARE was refused
Sep 18, 2026
f45d427
fix(node): keep each remote-desktop session's commands in order
Sep 18, 2026
737b3aa
fix(remote-desktop): do not abort when a backlogged encoder gets a su…
Sep 19, 2026
96c7cdf
fix(macos): build aiDesk's agent for the macOS release it declares
Sep 19, 2026
1efa544
feat(remote-desktop): name displays by position and open on the main one
Sep 19, 2026
5d2f1df
fix(macos-remote-desktop): give every media start a fresh sender gene…
Sep 19, 2026
8bb5e26
fix(node): link the daemon on this computer whatever domain it was bo…
Sep 19, 2026
38bb809
fix(server): let the daemon's install buttons reach the daemon, owner…
Sep 19, 2026
89f34dc
feat(remote-desktop): install the controlled node from a Linux or Mac…
Sep 19, 2026
d5957a8
fix(node): start only this release's macOS components after an upgrade
Sep 19, 2026
a3a30e4
fix(remote-desktop): phone remote control -- ring drags, keyboard key…
Sep 19, 2026
2f7a639
fix(server): relay the daemon's install progress back to the browser
Sep 19, 2026
b76f6c0
fix(server): admit a node that cannot take input to View, not a faili…
Sep 19, 2026
89e82c6
fix(web): tell a Mac owner to re-check a permission that looks grante…
Sep 19, 2026
4c5957c
feat(web): align machine actions in two rows and add open-in-new-wind…
Sep 19, 2026
60ba8f1
fix(web): hide the macOS remote-desktop readiness line once everythin…
Sep 19, 2026
37d2612
fix(node): keep the macOS worker socket non-blocking after peer verif…
Sep 19, 2026
2db0e7b
fix(web): offer a Mac for remote desktop only once both permissions a…
Sep 19, 2026
7c9ee03
fix(server): apply daemon capability frames in the order they were sent
Sep 19, 2026
d6ab43d
fix(macos-remote-desktop): connect to the window server before queryi…
Sep 19, 2026
d48b250
fix(remote-desktop): lift screen above the OS keyboard; add special-c…
Sep 19, 2026
60c3799
feat(remote-desktop): swipe up on number/punctuation keys for their s…
Sep 19, 2026
c85d63f
feat(remote-desktop): small minimized chip under AI Desk, with a shri…
Sep 19, 2026
c96048d
fix(macos-remote-desktop): capture macOS 12 desktops with CGDisplaySt…
Sep 19, 2026
478bdc8
fix(queue): stop delivered messages lingering as queued ghosts
Sep 19, 2026
9be71df
feat(skills): manage Agent Skills in ~/.agents/skills on each machine
Sep 19, 2026
5331544
feat(web): preview composer image attachments on hover and tap
Sep 19, 2026
26c0457
feat(remote-desktop): show FPS, bitrate and latency on macOS and Linu…
Sep 19, 2026
ae04509
feat(skills): search skills.sh, show its security audits, flag missin…
Sep 19, 2026
87a74a5
fix(cli): a mistyped imcodes command no longer prints a crash
Sep 19, 2026
3f7faa8
test: fix CI for the attachment preview badge
Sep 19, 2026
96ee72b
feat(mcp): install MCP servers into each agent's own config, per machine
Sep 19, 2026
cefe568
fix(linux-remote-desktop): stop capture outside the frame fan-out lock
Sep 19, 2026
1f0c8d8
feat(remote-desktop): per-viewer stream quality modes and a relay bit…
Sep 19, 2026
bc7e834
feat(remote-desktop): compact quality dropdown, remembered per server
Sep 19, 2026
cc74b35
fix(web): keep the remote-desktop setup dialog a normal width
Sep 19, 2026
338b3d1
fix(file-transfer): resume interrupted HTTP downloads; let P2P outlas…
Sep 19, 2026
08064e8
fix(remote-desktop): retry transient capability failures
Sep 19, 2026
b7ddbf3
feat(controlled-node): set up a basic desktop on a headless Linux box
Sep 19, 2026
790c683
test: make the download-resume tests observe Range under jsdom
Sep 19, 2026
472e930
test(node): make enrollment-runtime tests independent of the host's X…
Sep 19, 2026
4728f77
fix(mcp): mark IM.codes' own server built in; allow slower directory …
Sep 19, 2026
72f8269
fix(memory): stop the summary compressor freezing the daemon's main t…
Sep 19, 2026
6f4f35a
fix(preview): back off a preview worker that keeps crashing
Sep 19, 2026
b5437e1
perf(daemon): remove measured main-thread persistence stalls
Sep 19, 2026
9de7777
fix: relax cross-region file direct timeouts
Sep 19, 2026
bbb6254
fix(chat): show appended messages immediately
Sep 19, 2026
6392cbd
fix(remote-desktop): maximize space above mobile keyboard
Sep 19, 2026
e6022f7
fix(exec): keep remote commands out of replies
Sep 19, 2026
7f4ef4e
fix(remote-desktop): refine mobile touch controls
Sep 19, 2026
5063413
fix(chat): prioritize local timeline cache
Sep 19, 2026
207ab85
fix(remote-desktop): lift the 2.5 Mbps stream cap; add Ultra HD (4K);…
Sep 19, 2026
b58a0e3
feat(macos-remote-desktop): several viewers on one Mac at once
Sep 19, 2026
1c3700c
fix(remote-desktop): hold relayed Linux and macOS streams to the rela…
Sep 19, 2026
7cce418
fix(chat): reserve timeline cache for recent text
Sep 19, 2026
879a84c
fix(remote-desktop): Ultra stuck at 360p5 on phones; keyboard keeps t…
Sep 19, 2026
040cccb
feat(file-transfer): resume interrupted uploads and downloads
Sep 19, 2026
7199010
fix(chat): isolate recent timeline caches per window
Sep 20, 2026
77a8b65
fix(supervision): settle WAITING turns once, without cancelling a new…
Sep 20, 2026
d00be7f
fix(computer-use): real browser error causes, text-selector fallback,…
Sep 20, 2026
2484efd
fix(supervision): bind session resource identity per query; supersede…
Sep 20, 2026
e35423d
fix(remote-desktop): keep a hand-set zoom when the stage resizes
Sep 20, 2026
924f497
fix(chat): bootstrap every visible history window
Sep 20, 2026
6ba0f1b
fix(web): stop clipping the delegation reply card header on desktop
Sep 20, 2026
b2c8ab7
fix(delegation): stop cutting the task title on the reply card
Sep 20, 2026
ecaf737
fix(supervision): distinguish revision-recovery rejection causes; pin…
Sep 19, 2026
b3009b4
docs(computer-use): exec_remote accepts timeoutMs (1000..3600000); on…
Sep 20, 2026
1dd5b03
fix(supervision): route audits with the exact selected config; identi…
Sep 20, 2026
4b99025
fix(remote-desktop): phone keyboard stays up, stops flickering, and s…
Sep 20, 2026
347adcf
feat(contract): file_output_v1 — agents present files as [name](/abso…
Sep 20, 2026
7fa4cb5
test(remote-desktop): dispatch pointercancel the way the DOM under te…
Sep 20, 2026
e9fe9e0
fix(supervision): adopt a Brain WAITING turn woken by internal notifi…
Sep 20, 2026
adc0d7c
fix(supervision): integration bundles with unchanged scope files no l…
Sep 20, 2026
1546788
fix(remote-desktop): a tap on the picture no longer closes the phone …
Sep 20, 2026
980d5f2
feat(remote-desktop): open on Balanced rather than Smooth
Sep 20, 2026
83636e8
fix(supervision): a delayed state-only running projection no longer e…
Sep 20, 2026
baa2a6c
fix(macos-remote-desktop): a session starts on a clean keyboard, so a…
Sep 20, 2026
bdd43d4
fix(remote-desktop): Windows and Linux sessions start on a clean keyb…
Sep 20, 2026
ddcc31b
test(macos-remote-desktop): the production-chain sanitizer build gets…
Sep 20, 2026
ce92cb3
fix(supervision): reclaim worktrees of finished and cancelled tasks, …
Sep 20, 2026
1172126
fix(delegation-claim): only real task delegations are projected and s…
Sep 20, 2026
ca88766
feat(remote-desktop): fullscreen forwards the shortcuts the browser k…
Sep 20, 2026
0cfe32b
feat(chat): WAITING/NEEDS_INPUT status chip and collapsed supervision…
Sep 20, 2026
8182936
test(chat): daemon execution parsing stays authoritative while the di…
Sep 20, 2026
80a6a59
feat(remote-desktop): say so when the browser keeps a Command shortcu…
Sep 20, 2026
54e5735
fix(delegation): the reply card shows a concise task title; the full …
Sep 20, 2026
1891e51
fix(console): the task console list uses the shared concise task titl…
Sep 20, 2026
9e24f3d
feat(web): Shared-with-me panel — capped scrolling list, collapse tog…
Sep 20, 2026
96fd421
fix(delegation): deliver and show each audit result once; render find…
Sep 20, 2026
51ef822
fix(web): timeline cache — instant first paint from the window own ca…
Sep 20, 2026
dfefa91
fix(supervision): auto-provision busy pool with concurrency guard, bo…
Sep 20, 2026
b8cb093
feat(web,daemon): supervision heartbeat countdown badge and prominent…
Sep 20, 2026
f21c637
feat(web,daemon): three-line clamped, expandable task objective on de…
Sep 20, 2026
5963617
fix(memory-mcp): lightweight bootstrap with self-healing backend, bou…
Sep 20, 2026
1136a36
fix(web,daemon): two-line minimum objective fold and legacy title ref…
Sep 20, 2026
c1f4669
fix(web,daemon): heartbeat badge shows countdown when armed; pause gl…
Sep 20, 2026
ba59d27
test(web): deterministic multipass timeline prune test under coverage
Sep 20, 2026
3ce69f4
fix(supervision): live-sync the supervision task console from registr…
Sep 20, 2026
95b70d6
fix(supervision): auditor default-accepts the implementer report; sma…
Sep 20, 2026
755c14c
fix(supervision): restore preamble headroom by dropping two redundant…
Sep 20, 2026
51c3dee
test(daemon): quiesce in-flight OpenSpec auto-deliver advances before…
Sep 20, 2026
50340f9
fix(remote-desktop): Firefox's end-of-candidates marker no longer sto…
Sep 20, 2026
2cfaaf7
test(remote-desktop): lock the end-of-candidates contract across both…
Sep 20, 2026
71de7d4
feat(web): double-click window title bar toggles in-window maximize
Sep 20, 2026
e10a656
feat(web): separate supervision settings from session settings; model…
Sep 20, 2026
c661633
fix(web): model switch confirmation, sub-session model local state, e…
Sep 20, 2026
5be21ea
test/fix: audit CLI defers evidence authority to the daemon; more pre…
Sep 20, 2026
d02392f
feat(i18n): localize daemon-authored user notices through a shared co…
Sep 20, 2026
c790c39
fix(supervision): console subscribe timeout, task heartbeat refresh, …
Sep 20, 2026
58bfa38
feat(supervision): show the audit round (R1, R2, ...) on PASS/REWORK …
Sep 20, 2026
4285e09
feat(web): show the audit round chip on the delegation reply card; ve…
Sep 20, 2026
a1f115b
fix(supervision): reclaim worktrees of finished tasks automatically; …
Sep 20, 2026
dd61681
fix(supervision): reclaim merged worktrees directly with no backup; s…
Sep 20, 2026
a760f1d
feat(web): one-line 5h+7d quota, unclipped audit heartbeat badge, ref…
Sep 20, 2026
e089c8d
test(daemon): arm the tasks.md gate before publishing the marker in t…
Sep 20, 2026
2995f59
feat(web): remove the redundant remote-control button from the mobile…
Sep 20, 2026
f1ebc67
test(daemon): make the machine hook-port containment guard snapshot-b…
Sep 20, 2026
1cfa7fd
feat(supervision): validation load rule in every contract path; Docke…
Sep 20, 2026
b4695b2
feat(cron): scheduled runs are user-authorized execution (contract v2…
Sep 21, 2026
a0dbe47
test(web): resolve cron run card locale files independent of the work…
Sep 21, 2026
e6c4860
feat(cron): trust clause for imcodes-cron-control lives in the perman…
Sep 21, 2026
34aba2b
test(daemon): assert IM.codes authority in the native system channel …
Sep 21, 2026
072122a
feat(web): participant status bar shows the latest audit verdict with…
Sep 21, 2026
7bff66d
fix(claude-sdk): deliver the IM.codes system prompt through the SDK p…
Sep 21, 2026
a71e3de
fix(linux-remote-desktop): use only X displays the worker can open
Sep 21, 2026
e29cbe8
fix(web): the pinned scheduled-task edit dialog is no longer clipped …
Sep 21, 2026
898040a
test(e2e): read the Claude SDK system prompt from the preset append
Sep 21, 2026
b69bd0b
feat(web): fold runs of supervision heartbeat and marker-only waiting…
Sep 21, 2026
52e7127
fix(memory): recalled memory that calls the cron wrapper prompt injec…
Sep 21, 2026
1704d76
feat(web): remove the floating participant status bar from the top of…
Sep 21, 2026
1d7a242
fix(share): participant viewers receive the bounded provider quota an…
Sep 21, 2026
cae6700
fix(web): an old window with only non-renderable cached rows now self…
Sep 21, 2026
54fece4
feat(supervision): task titles and objectives are authored in the sel…
Sep 21, 2026
592a854
test(web): assert sub-session quota and heartbeat on the original foo…
Sep 21, 2026
fa24832
fix(macos-remote-desktop): an idle worker no longer reports a phantom…
Sep 21, 2026
fe25f8d
fix(remote-desktop): invitation and password proofs need an account, …
Sep 21, 2026
9daa29b
feat(remote-desktop): one local management panel for the controlled n…
Sep 21, 2026
027e2e9
fix(remote-desktop): the fleet presence gate applies to controlled an…
Sep 21, 2026
ed7596b
fix(web): every quick-input list (# @ ; ^) follows the keyboard selec…
Sep 21, 2026
8df3d14
fix(supervision): integration compares files through Git normalizatio…
Sep 21, 2026
af7fafb
feat(aidesk): persistent edge indicator with connection badge and use…
Sep 21, 2026
9775aa4
feat(aidesk): local management IPC core shared by all platforms
Sep 21, 2026
9e42519
fix(claude-sdk): probe the bundled claude binary in connect(), not a …
Sep 21, 2026
4ed5a04
feat(aidesk): native FLTK main window shared by all platforms
Sep 21, 2026
8635b2b
fix(supervision): task and assignment revisions bind atomically, and …
Sep 21, 2026
52792f3
fix(node): reinstall replaces the old generation, wake and clock jump…
Sep 21, 2026
c264089
feat(supervision): the project Brain can reset a task to a given revi…
Sep 21, 2026
bcb79f2
fix(node): an interrupted Windows self-upgrade recovers itself instea…
Sep 21, 2026
a6fe1c5
feat(supervision): Brain repair contract names reset_revision as the …
Sep 22, 2026
f85bf87
fix(node): fence rolled-back Windows upgrade targets
Sep 22, 2026
7828f38
fix(chat): file downloads resolve hidden-path, full-path, and relativ…
Sep 22, 2026
6810da6
feat(node): persistent startup diagnostics for the 120s health-lease …
Sep 22, 2026
631d019
fix(server): legacy Windows upgrade restart backoff survives reconnects
Sep 22, 2026
94689ee
fix(node): a stale legacy-shaped upgrade marker no longer bricks a node
Sep 22, 2026
c91cd3a
fix(node): stale-upgrade-task sweep no longer deletes the legacy resc…
Sep 22, 2026
64b237d
fix(supervision): surface why integration-artifact resolution failed
Sep 22, 2026
a5e273b
fix(node): retry transient artifact-download failures within one upgr…
Sep 22, 2026
825e6f1
fix(shared): recognize page-by-page read-only description as analysis
Sep 22, 2026
d930e40
fix(daemon): auto-adopt a project with no prior Git history for super…
Sep 22, 2026
c6438ef
fix(daemon): surface non-delivering reactive audit dispatch in the re…
Sep 22, 2026
186fb87
fix(daemon): auto-attach the project Brain as coordinator on task cre…
Sep 22, 2026
34e9151
feat(daemon): let a formal participant delegate small bounded work to…
Sep 22, 2026
0e36198
fix(web): always send viewed session identity on chat file downloads
Sep 22, 2026
6f220e4
test(web): update file-change preview assertions for real session ide…
Sep 22, 2026
8bb1811
feat(daemon): session_identity_set/clear fan out to affected sessions…
Sep 22, 2026
58e22c1
fix(node): stop popping the aiDesk 127.0.0.1 panel on every macOS upg…
Sep 22, 2026
55f8911
fix(web): let a file-browser retry after a listing timeout actually r…
Sep 22, 2026
33975d2
fix(web): show a visible state while a stuck P2P upload recovers
Sep 22, 2026
92a1f6e
fix(server): stop a NUL byte in a memory summary from breaking replic…
Sep 22, 2026
0b36d2f
fix(daemon): stop serializing 4 independent reads behind one PERSONAL…
Sep 22, 2026
ea049c4
fix(web): time out a stalled relay upload instead of hanging forever
Sep 22, 2026
a5fc5ce
fix(server): replay daemon.hello capability snapshot to participants too
Sep 22, 2026
4183412
fix(server,web): let a share participant enable automatic supervision…
Sep 22, 2026
0a1faad
fix(daemon): make session_identity all=true actually fan out writes, …
Sep 23, 2026
09607cb
fix(web): stop a late duplicate CREDIT from masking a P2P upload's re…
Sep 23, 2026
4a8a593
fix(web): stop a stalled getStats() from blocking a completed P2P upl…
Sep 23, 2026
990be5d
fix(daemon): surface the unbound-revision sentinel instead of a bare …
Sep 23, 2026
e699edb
feat(shared): raise session identity character limits (user 5万→10万, p…
Sep 23, 2026
9713afb
fix(daemon): stop swallowing the underlying cause of a worktree_unava…
Sep 23, 2026
0895744
fix(daemon): stop misrouting a coordinator's own-assignment finish th…
Sep 23, 2026
a3f3402
fix(daemon): auto-rebind delegation replies stranded by an ordinary c…
Sep 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
208 changes: 208 additions & 0 deletions .github/workflows/build-node-exe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,200 @@ jobs:
$sha256 = [System.Security.Cryptography.SHA256]::Create()
try { $signerSha256 = [BitConverter]::ToString($sha256.ComputeHash($certificate.RawData)).Replace('-', '').ToLowerInvariant() } finally { $sha256.Dispose() }
"IMCODES_WINDOWS_SIGNING_CERT_SHA256=$signerSha256" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Import macOS release-signing identity
if: runner.os == 'macOS'
env:
IMCODES_MACOS_SIGNING_P12_BASE64: ${{ secrets.IMCODES_MACOS_SIGNING_P12_BASE64 }}
IMCODES_MACOS_SIGNING_P12_PASSWORD: ${{ secrets.IMCODES_MACOS_SIGNING_P12_PASSWORD }}
IMCODES_MACOS_KEYCHAIN_PASSWORD: ${{ secrets.IMCODES_MACOS_KEYCHAIN_PASSWORD }}
IMCODES_MACOS_TEAM_ID: ${{ secrets.IMCODES_MACOS_TEAM_ID }}
run: |
set -euo pipefail
IDENTITY="$(node scripts/macos-release-signing.mjs import)"
# The fingerprint, not the common name: a name can match several
# certificates, and the build plan pins the exact one it signed with.
echo "IMCODES_MACOS_SIGNING_IDENTITY=$(printf '%s' "$IDENTITY" | node -e 'process.stdin.on("data",(d)=>process.stdout.write(JSON.parse(d).sha1))')" >> "$GITHUB_ENV"
- name: Write macOS notary API key
if: runner.os == 'macOS'
env:
IMCODES_MACOS_NOTARY_KEY_BASE64: ${{ secrets.IMCODES_MACOS_NOTARY_KEY_BASE64 }}
run: |
set -euo pipefail
if [ -z "${IMCODES_MACOS_NOTARY_KEY_BASE64:-}" ]; then
echo 'macOS notary API key is required.' >&2
exit 1
fi
KEY_PATH="$RUNNER_TEMP/imcodes-macos-notary.p8"
printf '%s' "$IMCODES_MACOS_NOTARY_KEY_BASE64" | base64 --decode > "$KEY_PATH"
chmod 600 "$KEY_PATH"
echo "IMCODES_MACOS_NOTARY_KEY_PATH=$KEY_PATH" >> "$GITHUB_ENV"
- name: Build controlled-node executable
run: npm run build:node-exe
- name: Notarize macOS controlled-node executable
if: runner.os == 'macOS'
env:
IMCODES_MACOS_NOTARY_KEY_ID: ${{ secrets.IMCODES_MACOS_NOTARY_KEY_ID }}
IMCODES_MACOS_NOTARY_ISSUER: ${{ secrets.IMCODES_MACOS_NOTARY_ISSUER }}
run: |
set -euo pipefail
node scripts/macos-release-signing.mjs notarize dist-node-exe/imcodes-node-macos
- name: Prove the signed macOS executable still runs
if: runner.os == 'macOS'
run: |
set -euo pipefail
codesign --verify --strict --verbose=2 dist-node-exe/imcodes-node-macos
./dist-node-exe/imcodes-node-macos --version
- name: Build and notarize the aiDesk application bundle
if: runner.os == 'macOS'
env:
IMCODES_MACOS_NOTARY_KEY_ID: ${{ secrets.IMCODES_MACOS_NOTARY_KEY_ID }}
IMCODES_MACOS_NOTARY_ISSUER: ${{ secrets.IMCODES_MACOS_NOTARY_ISSUER }}
run: |
set -euo pipefail
# One signed bundle holding every helper that needs a permission, so
# macOS attributes Screen Recording and Accessibility to the app the
# person chose rather than to whatever launched a helper. Unlike the
# bare executable this one CAN carry its notarization ticket, so it
# verifies with no network.
# Built during `build:node-exe`, before the manifest recorded the
# helper archive's hash -- swapping the archive afterwards makes
# every consumer reject the set as tampered with.
APP="dist-node-exe/aiDesk.to by IM.codes.app"
node scripts/macos-release-signing.mjs notarize "$APP"
xcrun stapler validate "$APP"
- name: Build, sign and notarize the aiDesk disk image
if: runner.os == 'macOS'
env:
IMCODES_MACOS_NOTARY_KEY_ID: ${{ secrets.IMCODES_MACOS_NOTARY_KEY_ID }}
IMCODES_MACOS_NOTARY_ISSUER: ${{ secrets.IMCODES_MACOS_NOTARY_ISSUER }}
run: |
set -euo pipefail
# Built from the app as it now stands, which already carries its own
# stapled ticket -- so the app keeps verifying offline after being
# dragged out of the image. A disk image rather than a package: both
# can be stapled, but one is a drag and the other is a wizard.
DMG="$(node scripts/build-aidesk-app.mjs dmg dist-node-exe)"
node scripts/macos-release-signing.mjs notarize "$DMG"
xcrun stapler validate "$DMG"
# The macOS remote-desktop components, built from the published
# immutable SDK. Both architectures are produced here because each ships
# thin -- the build plan sets universalBinary = false and the runtime
# verifier rejects a fat Mach-O -- and both SDKs carry an arm64
# toolchain, so this must run on an Apple silicon runner.
- name: Build, sign and notarize the macOS remote-desktop components
if: runner.os == 'macOS'
shell: bash
env:
GH_TOKEN: ${{ github.token }}
# IMCODES_MACOS_SIGNING_IDENTITY and IMCODES_MACOS_NOTARY_KEY_PATH
# are already in the job environment, written by the import and
# notary-key steps above; these are the two the driver additionally
# needs, under the same names macos-release-signing.mjs uses.
IMCODES_MACOS_NOTARY_KEY_ID: ${{ secrets.IMCODES_MACOS_NOTARY_KEY_ID }}
IMCODES_MACOS_NOTARY_ISSUER: ${{ secrets.IMCODES_MACOS_NOTARY_ISSUER }}
IMCODES_MACOS_TEAM_ID: ${{ secrets.IMCODES_MACOS_TEAM_ID }}
run: |
set -euo pipefail
for arch in arm64 x64; do
lock="native/macos-remote-desktop/libwebrtc-sdk-$arch.lock.json"
tag="$(node -p "require('./$lock').releaseTag")"
asset="$(node -p "require('./$lock').assetName")"
repository="$(node -p "require('./$lock').repository")"
download="$RUNNER_TEMP/libwebrtc-sdk-download-$arch"
sdk="$RUNNER_TEMP/libwebrtc-sdk-$arch"
mkdir -p "$download"
gh release download "$tag" --repo "$repository" --pattern "$asset" \
--dir "$download" --clobber
node scripts/install-libwebrtc-sdk.mjs --target "macos-$arch" \
"$download/$asset" "$sdk"
node scripts/libwebrtc-sdk-artifacts.mjs verify-sdk-lock \
--target "macos-$arch" "$lock" "$sdk"
# The driver, not the build script: it also signs each component
# with its own entitlements, notarizes each one, runs the guards the
# daemon applies on a user's Mac, and writes the manifest.
node scripts/build-macos-remote-desktop-release.mjs \
--arch "$arch" \
--sdk-root "$sdk" \
--artifact-root "dist-node-exe/remote-desktop-worker/darwin-$arch" \
--worker-version "$IMCODES_BUILD_VERSION" \
--jobs 3
# Reclaimed immediately: two extracted SDKs are ~1.7GB, and the
# runner still has the signing and packaging steps to do.
rm -rf "$download" "$sdk"
done
# The Linux remote-desktop worker, from the same published, locked SDK
# build-libwebrtc-sdk.sh produces once. See ci.yml's own copy of this
# block for the full rationale; kept in sync with it deliberately.
- name: Install X11 development libraries, Xvfb, and pulseaudio
if: runner.os == 'Linux'
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libx11-dev libxext-dev libxtst-dev libxfixes-dev libxrandr-dev xvfb pulseaudio
- name: Build and test the Linux remote-desktop worker from the SDK
if: runner.os == 'Linux'
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
lock="native/linux-remote-desktop/libwebrtc-sdk.lock.json"
tag="$(node -p "require('./$lock').releaseTag")"
asset="$(node -p "require('./$lock').assetName")"
repository="$(node -p "require('./$lock').repository")"
download="$RUNNER_TEMP/libwebrtc-sdk-archives-linux"
sdk="$RUNNER_TEMP/libwebrtc-sdk-linux"
mkdir -p "$download"
gh release download "$tag" --repo "$repository" --pattern "$asset" \
--dir "$download" --clobber
node scripts/install-libwebrtc-sdk.mjs --target linux-x64 \
"$download/$asset" "$sdk"
node scripts/libwebrtc-sdk-artifacts.mjs verify-sdk-lock \
--target linux-x64 "$lock" "$sdk"
Xvfb :99 -screen 0 1920x1080x24 &
echo $! > "$RUNNER_TEMP/xvfb.pid"
export DISPLAY=:99
for _ in $(seq 1 50); do
[ -e /tmp/.X11-unix/X99 ] && break
sleep 0.1
done
# A bare CI runner has no /proc/asound/cards entry at all (no sound
# card, real or virtual), which makes WebRTC's
# AudioDeviceModule::Init() hard-abort at session start ("Fatal
# error ... Check failed: 0 == adm->Init()") even though the
# qualification test never asked for audio -- there was simply
# nothing to open. Same fix as install-linux-desktop-environment.sh
# uses for a real headless server: pulseaudio gives it a real, if
# silent, device.
pulseaudio --start --exit-idle-time=-1 || true
bash native/linux-remote-desktop/build-worker-from-sdk.sh \
--sdk-root "$sdk" \
--artifact-root dist-node-exe/remote-desktop-worker/linux-x64 \
--worker-version "$IMCODES_BUILD_VERSION" \
--run-native-tests
kill "$(cat "$RUNNER_TEMP/xvfb.pid")" 2>/dev/null || true
rm -rf "$download" "$sdk"
- name: Verify the Linux remote-desktop worker artifact
if: runner.os == 'Linux'
run: |
set -euo pipefail
ARTIFACT="dist-node-exe/remote-desktop-worker/linux-x64/imcodes-linux-remote-desktop-worker"
MANIFEST="$ARTIFACT.manifest.json"
[ -f "$ARTIFACT" ] || { echo "missing $ARTIFACT" >&2; exit 1; }
[ -x "$ARTIFACT" ] || { echo "$ARTIFACT is not executable" >&2; exit 1; }
[ -f "$MANIFEST" ] || { echo "missing $MANIFEST" >&2; exit 1; }
node -e "
const fs = require('node:fs');
const crypto = require('node:crypto');
const manifest = JSON.parse(fs.readFileSync('$MANIFEST', 'utf8'));
const bytes = fs.readFileSync('$ARTIFACT');
const sha256 = crypto.createHash('sha256').update(bytes).digest('hex');
if (manifest.artifact.fileName !== 'imcodes-linux-remote-desktop-worker') throw new Error('manifest fileName mismatch');
if (manifest.artifact.os !== 'linux' || manifest.artifact.arch !== 'x64') throw new Error('manifest os/arch mismatch');
if (manifest.artifact.size !== bytes.length) throw new Error('manifest size mismatch: ' + manifest.artifact.size + ' vs ' + bytes.length);
if (manifest.artifact.sha256 !== sha256) throw new Error('manifest sha256 mismatch');
console.log('Linux remote-desktop worker manifest matches artifact:', sha256);
"
- name: Resolve fixed libwebrtc SDK release
if: runner.os == 'Windows'
id: libwebrtc_sdk
Expand Down Expand Up @@ -142,6 +334,18 @@ jobs:
RunNativeTests = $true
}
& .\native\windows-remote-desktop\build-worker-from-sdk.ps1 @buildArguments
- name: Verify the produced macOS remote-desktop component sets
if: runner.os == 'macOS'
shell: bash
run: |
set -euo pipefail
# Per architecture and as a SET: the per-component guards already ran
# inside the driver, but this is what checks the manifest describes
# exactly the files present, at the version this build claims.
for arch in arm64 x64; do
node scripts/remote-desktop-worker-artifacts.mjs verify \
dist-node-exe "$IMCODES_BUILD_VERSION" darwin "$arch"
done
- name: Verify production remote-desktop worker artifact
if: runner.os == 'Windows'
run: node scripts/remote-desktop-worker-artifacts.mjs verify dist-node-exe "${{ env.IMCODES_BUILD_VERSION }}"
Expand Down Expand Up @@ -178,9 +382,13 @@ jobs:
dist-node-exe/${{ matrix.artifact }}
dist-node-exe/${{ matrix.artifact }}.manifest.json
dist-node-exe/computer-use-helper/**
dist-node-exe/*.dmg
dist-node-exe/remote-desktop-worker/**
if-no-files-found: error
retention-days: 30
- name: Remove macOS release-signing material
if: always() && runner.os == 'macOS'
run: node scripts/macos-release-signing.mjs cleanup
- name: Remove Windows release-signing material
if: always() && runner.os == 'Windows'
shell: powershell
Expand Down
Loading
Loading