Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
674 commits
Select commit Hold shift + click to select a range
594b99a
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
799cd5f
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
29c887d
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
2aff5f5
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
e8f7052
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
ce3d477
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
482db19
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
92bbecc
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
784035a
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
9195703
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
a31ea73
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
a5ac23e
chore: merge upstream main into resume recovery
JustYannicc Nov 2, 2026
734cabe
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
7202450
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
21fb340
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
7903ba0
fix(web): await file save completion without draining background timers
JustYannicc Nov 3, 2026
b0569db
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
d9beec5
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
6b6b7ac
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
f2b8bf7
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
b4b22e1
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
df995a5
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
8a7ff1f
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
5e9c81e
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
7d479bc
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
56695ae
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
5a2936e
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
9ab6387
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 3, 2026
d90093a
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
e1e3e55
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
a0472fa
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
75c659b
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
c3a68c8
chore: merge upstream main into resume recovery
JustYannicc Nov 3, 2026
06f1c13
chore: merge upstream main into resume recovery
JustYannicc Nov 4, 2026
50212de
chore: merge upstream main into resume recovery
JustYannicc Nov 4, 2026
35d6384
chore: merge upstream main into resume recovery
JustYannicc Nov 4, 2026
762b1d0
chore: merge upstream main into resume recovery
JustYannicc Nov 4, 2026
17ebd11
chore: merge upstream main into resume recovery
JustYannicc Nov 4, 2026
bf0cd5a
chore: merge upstream main into resume completion deadline
JustYannicc Nov 4, 2026
13e5421
fix(client-runtime): preserve resume recovery when merging stream def…
JustYannicc Nov 4, 2026
168d6f7
chore: merge upstream scanner test synchronization fix
JustYannicc Nov 4, 2026
d27babe
chore: merge upstream PDF preview test fix
JustYannicc Nov 4, 2026
2531215
chore: merge upstream Claude MCP Apps support
JustYannicc Nov 4, 2026
865343c
chore: merge upstream Effect diagnostics changes
JustYannicc Nov 5, 2026
114c68b
chore: merge upstream browser and mobile fixes
JustYannicc Nov 5, 2026
410b36c
chore: merge upstream thread cache and connection fixes
JustYannicc Nov 5, 2026
a736958
chore: merge upstream environment access refactor
JustYannicc Nov 5, 2026
6100cb7
chore: merge upstream typed error refactors
JustYannicc Nov 5, 2026
44b7172
chore: merge upstream thread history budget fix
JustYannicc Nov 5, 2026
a5a0d9b
chore: merge upstream mobile and branch status fixes
JustYannicc Nov 5, 2026
bc89863
chore: merge upstream thread and worktree fixes
JustYannicc Nov 5, 2026
66eb68b
chore: merge upstream mobile rendering and Pi usage fixes
JustYannicc Nov 5, 2026
a1a8aa8
chore: merge upstream snoozing and secret handling fixes
JustYannicc Nov 5, 2026
25b91e3
chore: merge upstream fresh session support
JustYannicc Nov 5, 2026
99bab75
chore: merge upstream PR media and sidebar fixes
JustYannicc Nov 5, 2026
45fb0ba
chore: merge upstream main into resume recovery
JustYannicc Nov 5, 2026
31ca2b2
chore: merge upstream main into resume recovery
JustYannicc Nov 5, 2026
a32725a
chore: merge upstream main into resume recovery
JustYannicc Nov 5, 2026
643cd8d
chore: merge upstream main into resume recovery
JustYannicc Nov 5, 2026
accef7c
chore: merge upstream main into resume recovery
JustYannicc Nov 5, 2026
f769a7f
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
b4c7fa6
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
32f8170
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
e0d6002
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
c3b1658
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
528eeda
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
f4332a8
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
d5adef3
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
6b892de
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
80a3a71
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
cb6f125
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
4b91910
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
60c9c90
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
a250fae
chore: merge upstream main into resume recovery
JustYannicc Nov 6, 2026
8bc7306
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
abeeb43
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
87436dc
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
1b13ff1
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
e2dc066
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
9516663
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
bb4db3c
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
7b2f795
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
9b10d3c
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 6, 2026
1e68aca
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
4b9d435
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
bef6871
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
1bdb99f
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
cbc8547
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
1f3e0d3
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
6ad2954
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
a23c7bd
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
fe36eda
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
17f9c49
chore: merge upstream main into resume recovery
JustYannicc Nov 7, 2026
8e9921c
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
4672d37
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
783b9ee
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
ccbb9cd
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
d0a6a2f
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 7, 2026
dd4aa72
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 8, 2026
9924bac
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 8, 2026
38fa4fa
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 8, 2026
875b312
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 8, 2026
f4260c9
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
25ce7a3
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
8d6d3b7
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
0fcefa2
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
9185a89
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
fc17865
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
2f190e4
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
43ad15e
merge: keep resume recovery current with main
JustYannicc Nov 8, 2026
6946788
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
bda626d
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
a1b2108
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
4920b70
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
42dd483
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
ee17bc9
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
2d97140
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
be289b0
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
7964490
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
8be1795
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
3d0d528
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
8eb07ec
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
3fab274
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
f960c45
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
516ddaa
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
dddeac8
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
855bf76
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
b5600ac
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
cb961a1
Merge upstream main and preserve thread recovery
JustYannicc Nov 9, 2026
0aadbfb
Merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
a42fc51
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
b51ef43
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
d422723
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
c71a933
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
f1790ab
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
538f946
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
315aac3
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
923c862
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
e121178
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
e1330a3
chore: merge upstream main into resume recovery
JustYannicc Nov 9, 2026
be6401d
chore: merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
dde9876
chore: merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
73fdff0
chore: merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
14c72e1
chore: merge upstream main into resume recovery branch
JustYannicc Nov 9, 2026
2a32167
chore: merge upstream main into resume recovery branch
JustYannicc Nov 10, 2026
4c91305
chore: merge upstream main into resume recovery branch
JustYannicc Nov 10, 2026
bf21dc0
chore: merge upstream main into resume recovery branch
JustYannicc Nov 10, 2026
b70465c
chore: merge upstream main into resume recovery branch
JustYannicc Nov 10, 2026
4410847
chore: merge upstream main into resume recovery branch
JustYannicc Nov 10, 2026
18c2ac9
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
1e1db74
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
a5add30
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
c1a3933
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
956315a
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
5fa02c7
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
e190487
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
95aa224
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
4d918b8
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
270d24c
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
b780cf5
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
c7f7fb9
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
a5e97cd
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
b0ebc48
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
6f55931
chore: merge upstream main into resume recovery
JustYannicc Nov 10, 2026
d818e4d
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
72376b6
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
0d2b3c2
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
c35aacd
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
6c014a7
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
e3ba42e
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
5f4179b
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
4416e70
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
8da4a75
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
dd70100
chore: merge main into resume recovery branch
JustYannicc Nov 10, 2026
115dfb4
Merge remote-tracking branch 'github/main' into fix/resume-completion…
maria-rcks Nov 10, 2026
f7ca5ca
Merge commit '1fed70cd19998cee7907f6fde3b4d4290ba99cfc' into babysit/…
JustYannicc Nov 10, 2026
57a1634
Merge commit '71a1c49b75a209284ea24617e6a4b0cc339390e7' into babysit/…
JustYannicc Nov 10, 2026
c0b3768
Merge commit '5be6bc99c234b0db92ffb0b3ebd8746fd579112b' into babysit/…
JustYannicc Nov 10, 2026
ef5974b
Merge commit '871b00907d0bcf2705224de6c6e90de925c7cbb9' into babysit/…
JustYannicc Nov 10, 2026
a62dd8b
Merge commit 'd756fed7aaac06134bc68cbe0047e6f14b0e9aa2' into babysit/…
JustYannicc Nov 10, 2026
21097de
Merge commit '9cd7a04797184c92a8f636ae1e918f42c139d850' into babysit/…
JustYannicc Nov 10, 2026
212feaa
Merge commit '44ebb2fe57465d32f2bd07c5eb3d8e871bdf5ed5' into babysit/…
JustYannicc Nov 10, 2026
5e821ea
chore: merge upstream main into resume completion fix
JustYannicc Nov 10, 2026
e5f9810
chore: merge upstream main into resume completion fix
JustYannicc Nov 10, 2026
6ee7e6a
chore: merge upstream main into resume completion fix
JustYannicc Nov 10, 2026
90e6722
chore: merge upstream main into resume completion fix
JustYannicc Nov 11, 2026
791b1e8
Merge commit '3a8c250cb0c8056f2f563091fd412fe5db809fa1' into babysit/…
JustYannicc Nov 11, 2026
14fd1ba
Merge commit 'b883156e269de2002873aebdef6019f336b687a7' into babysit/…
JustYannicc Nov 11, 2026
6fa457f
Merge commit '768f17c5187db6e3559856dc867ac5e5f988ed11' into babysit/…
JustYannicc Nov 11, 2026
052a8c8
Merge commit '5c97adaf6b1be33ab08caa432f7a2656ae49df53' into babysit/…
JustYannicc Nov 11, 2026
459b514
Merge commit '0f13d2ccbd76ee1fc314b8c54f575f9691f78b51' into babysit/…
JustYannicc Nov 11, 2026
469d514
Merge commit 'ed52af3a478652c55aeaaf5a64bbf6584dd6a0b4' into babysit/…
JustYannicc Nov 11, 2026
c6cc5e5
Merge commit 'ba4d01cf7f78b29f2fb3a5be019e7ea8562ee692' into babysit/…
JustYannicc Nov 11, 2026
cd77698
Merge commit '11611419f39eb2bdc222989e842f3da4033b99b5' into babysit/…
JustYannicc Nov 11, 2026
6f42ba8
Merge commit '42185a6206245c1cde5368e8ce368b384e7a400a' into babysit/…
JustYannicc Nov 11, 2026
0982f6a
Merge commit 'a03d9bce026ef11930b35e9855adc1cdb5ea6eb7' into babysit/…
JustYannicc Nov 11, 2026
8c4b91f
Merge commit '8cbc95923a7168b3ee85c9dbeb224f57ca48f820' into babysit/…
JustYannicc Nov 11, 2026
92b407d
Merge commit '950c34226cc08ca4d9fc0e387b059a30463a1e47' into babysit/…
JustYannicc Nov 11, 2026
323f6c0
Merge commit 'a536ff7ac0c080190f098965d0a0d244caf5b211' into babysit/…
JustYannicc Nov 11, 2026
56941fd
Merge commit 'c50dd8e12d694110d7344707668b85b01583875f' into babysit/…
JustYannicc Nov 11, 2026
feabecf
Merge commit '24e77473ecf41bc1f7142529c7911c1c1aae1d76' into babysit/…
JustYannicc Nov 11, 2026
9382e15
chore: merge upstream main into resume completion recovery
JustYannicc Nov 11, 2026
a2c438a
chore: merge upstream main into resume completion recovery
JustYannicc Nov 11, 2026
3eb0901
Merge remote-tracking branch 'github/main' into fix/resume-completion…
maria-rcks Nov 11, 2026
3e5d576
fix(web): keep send blocked and local errors visible after sync failures
maria-rcks Nov 11, 2026
0bcd9d5
Merge remote-tracking branch 'github/main' into fix/resume-completion…
maria-rcks Nov 11, 2026
ebe517b
fix(web): preserve thread error recovery and send guards
JustYannicc Nov 11, 2026
14899b6
test(web): target the history failure scenario's thread row
JustYannicc Nov 11, 2026
0358209
chore: merge remote fixes and retain thread error follow-ups
JustYannicc Nov 11, 2026
4d4187b
chore: merge upstream main into resume recovery
JustYannicc Nov 11, 2026
a916e17
fix(web): retain session dismissal for identical sync errors
JustYannicc Nov 11, 2026
7496c58
chore: merge upstream main into resume recovery
JustYannicc Nov 11, 2026
06f12c6
chore: merge upstream main into resume recovery
JustYannicc Nov 11, 2026
2fb702c
chore: merge upstream main into resume recovery
JustYannicc Nov 11, 2026
e15bdba
chore: merge upstream main into resume recovery
JustYannicc Nov 11, 2026
6d566d6
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
6c4cbc2
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
e2fbaf4
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
86fe593
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
21c0843
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
6be0ce0
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
66eed57
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
d1cdeb3
Merge upstream main into resume recovery branch
JustYannicc Nov 11, 2026
3283165
fix(server): pass services to the systemd unit lookup
JustYannicc Nov 11, 2026
cd94aeb
chore: merge main and resolve the systemd lookup conflict
JustYannicc Nov 11, 2026
496983f
chore: merge main into resume recovery branch
JustYannicc Nov 11, 2026
991a42a
chore: merge main into resume recovery branch
JustYannicc Nov 11, 2026
fb98fa3
chore: merge main and deduplicate the mobile Notice import
JustYannicc Nov 11, 2026
80a1348
chore: merge main into resume recovery branch
JustYannicc Nov 11, 2026
f2ece68
chore: merge main into resume recovery branch
JustYannicc Nov 11, 2026
3f64a09
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 11, 2026
aba0f30
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 11, 2026
0c5c487
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 12, 2026
6f011cd
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 12, 2026
46e146e
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 12, 2026
479af3e
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 12, 2026
90fb416
Merge upstream main into fix/resume-completion-deadline-upstream
JustYannicc Nov 12, 2026
4a07012
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
23617fc
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
10e66e2
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
25fdbc3
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
e598ef5
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
78d7b16
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
f527f45
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
02df887
chore: merge upstream main into resume recovery
JustYannicc Nov 12, 2026
0b13485
chore: merge latest upstream main
JustYannicc Nov 12, 2026
0163e9b
chore: merge latest upstream main
JustYannicc Nov 12, 2026
b7c736f
chore: merge latest upstream main
JustYannicc Nov 12, 2026
d22e2af
chore: merge latest upstream main
JustYannicc Nov 12, 2026
fc0bd5b
chore: merge latest upstream main
JustYannicc Nov 12, 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
13 changes: 13 additions & 0 deletions apps/mobile/src/features/threads/ThreadDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export interface ThreadDetailScreenProps {
readonly respondingUserInputId: RuntimeRequestId | null;
readonly connectionStateLabel: EnvironmentConnectionPhase;
readonly threadSyncStatus?: EnvironmentThreadStatus;
readonly threadSyncError?: string | null;
readonly historyControls?: ThreadFeedHistoryControls;
readonly activeThreadBusy: boolean;
readonly canStopThread: boolean;
Expand Down Expand Up @@ -567,6 +568,7 @@ function ThreadDetailBody(
const composerKeyboardOffset = composerBottomInset;
const contentPresentationKind = props.contentPresentation.kind;
const realThreadSyncLabel = (() => {
if (props.threadSyncError != null) return null;
switch (props.threadSyncStatus) {
case "empty":
case "cached":
Expand Down Expand Up @@ -1686,6 +1688,17 @@ function ThreadDetailBody(
onDismiss={() => props.onDismissFeedback(submission.id)}
/>
))}
{props.threadSyncError != null && contentPresentationKind === "ready" ? (
<View className="shrink-0 px-4 pb-3">
<Notice
message={props.threadSyncError}
icon="exclamationmark.circle"
tone="danger"
iconTone="danger"
floating
/>
</View>
) : null}
{freshSessionAvailable ? (
<FreshSessionNotice threadKey={selectedThreadKey} />
) : null}
Expand Down
19 changes: 9 additions & 10 deletions apps/mobile/src/features/threads/ThreadRouteScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -952,16 +952,14 @@ function ThreadRouteContent(
return <OpeningThreadLoadingScreen />;
}

// Queued creation displays its prompt before server creation; temporary not-found is expected.
const contentPresentation =
creationState !== null
? { kind: "ready" as const }
: projectThreadContentPresentation({
hasDetail: selectedThreadDetail !== null,
detailError: Option.getOrNull(selectedThreadDetailState.error),
detailDeleted: selectedThreadDetailState.status === "deleted",
connectionState: routeConnectionState,
});
const threadDetailError = Option.getOrNull(selectedThreadDetailState.error);
const contentPresentation = projectThreadContentPresentation({
hasDetail: selectedThreadDetail !== null,
detailError: threadDetailError,
detailDeleted: selectedThreadDetailState.status === "deleted",
connectionState: routeConnectionState,
hasPendingCreation: creationState !== null,
});
const serverConfig = routeEnvironmentRuntime?.serverConfig ?? null;
const renderThreadRouteBody = () => (
<>
Expand Down Expand Up @@ -1040,6 +1038,7 @@ function ThreadRouteContent(
respondingUserInputId={requests.respondingUserInputId}
connectionStateLabel={routeConnectionState}
threadSyncStatus={selectedThreadDetailState.status}
threadSyncError={threadDetailError}
historyControls={historyControls}
activeThreadBusy={composer.activeThreadBusy}
canStopThread={awaitingBootstrapTurn || composer.interruptibleRunId !== null}
Expand Down
40 changes: 40 additions & 0 deletions apps/mobile/src/features/threads/threadContentPresentation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,44 @@ describe("thread content presentation", () => {
detail: "Reconnect this environment to load the conversation.",
});
});

it("keeps a pending creation's prompt visible before its thread exists", () => {
expect(
projectThreadContentPresentation({
hasDetail: false,
detailError: null,
detailDeleted: true,
connectionState: "connected",
hasPendingCreation: true,
}),
).toEqual({ kind: "ready" });
});

it("surfaces a synchronization failure while creation is still pending", () => {
expect(
projectThreadContentPresentation({
hasDetail: false,
detailError: "Message synchronization timed out.",
detailDeleted: false,
connectionState: "connected",
hasPendingCreation: true,
}),
).toEqual({
kind: "unavailable",
title: "Could not load conversation",
detail: "Message synchronization timed out.",
});
});

it("keeps cached messages visible after a synchronization failure during creation", () => {
expect(
projectThreadContentPresentation({
hasDetail: true,
detailError: "Message synchronization timed out.",
detailDeleted: false,
connectionState: "connected",
hasPendingCreation: true,
}),
).toEqual({ kind: "ready" });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ export function projectThreadContentPresentation(input: {
readonly detailError: string | null;
readonly detailDeleted: boolean;
readonly connectionState: EnvironmentConnectionPhase;
readonly hasPendingCreation?: boolean;
}): ThreadContentPresentation {
if (input.hasDetail) {
// The local prompt remains usable before creation reaches the server. A real
// synchronization failure still needs the unavailable state or a cached-detail notice.
if (input.hasDetail || (input.hasPendingCreation && input.detailError === null)) {
return { kind: "ready" };
}
if (input.detailDeleted) {
Expand Down
14 changes: 13 additions & 1 deletion apps/server/src/cloud/bootService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ const makeHarness = Effect.fn("test.make_boot_service_harness")(function* (
timeouts,
control,
runtime,
runner,
};
});

Expand Down Expand Up @@ -680,7 +681,7 @@ it.layer(NodeServices.layer)("boot service install", (it) => {
: setting === "manager-only"
? path.join(configRoot, "config root")
: undefined;
const { service, makeService, home, statePath, timeouts, runtime, control } =
const { service, makeService, home, statePath, timeouts, runtime, control, runner } =
yield* makeHarness("linux", undefined, xdgConfigHome, managerXdgConfigHome);
const unitPath = path.join(
setting === "relocated" || setting === "manager-only" || setting === "manager-unavailable"
Expand All @@ -697,6 +698,17 @@ it.layer(NodeServices.layer)("boot service install", (it) => {
control.failCommand =
"busctl --user --json=short get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager UnitPath";
}
expect(
yield* BootService.bootServiceUnitPath().pipe(
Effect.provideService(ProcessRunner.ProcessRunner, runner),
Effect.provideService(HostProcess.Platform, "linux"),
Effect.provideService(HostProcess.HomeDirectory, home),
Effect.provideService(
HostProcess.Environment,
xdgConfigHome === undefined ? {} : { XDG_CONFIG_HOME: xdgConfigHome },
),
),
).toBe(unitPath);
const discoveredService = yield* makeService();

expect(parseServiceState(yield* fs.readFileString(statePath))).toEqual({
Expand Down
172 changes: 172 additions & 0 deletions apps/web/src/components/ChatView.syncErrors.browser.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import { createMemoryHistory } from "@tanstack/react-router";
import {
EnvironmentAuthorizationError,
ORCHESTRATION_V2_WS_METHODS,
OrchestrationV2DispatchCommandError,
} from "@t3tools/contracts";
import { DEFAULT_CLIENT_SETTINGS } from "@t3tools/contracts/settings";
import type * as Context from "effect/Context";
import * as Deferred from "effect/Deferred";
import * as Effect from "effect/Effect";
import * as Stream from "effect/Stream";
import { expect, it, vi } from "vite-plus/test";
import { page } from "vite-plus/test/browser";

import { AppRoot } from "~/AppRoot";
import "~/components/ChatView";
import { __setClientSettingsForTests } from "~/hooks/useSettings";
import { getRouter } from "~/router";
import { appAtomRegistry } from "~/rpc/atomRegistry";
import { environmentThreadDetails } from "~/state/threads";
import {
ENVIRONMENT_ID,
fakeDriver,
installFakeEnvironment,
threadWithHistory,
type FakeDriver,
} from "../../test/fakeEnvironment";
import { act, render } from "../../test/render";

vi.mock("../../../../packages/client-runtime/src/connection/driver.ts", async (importOriginal) => {
const [actual, { fakeDriver }, Layer] = await Promise.all([
importOriginal<{ readonly ConnectionDriver: Context.Key<unknown, FakeDriver> }>(),
import("../../test/fakeEnvironment"),
import("effect/Layer"),
]);
return { ...actual, layer: Layer.succeed(actual.ConnectionDriver, fakeDriver) };
});

vi.mock(import("~/rpc/requestLatencyState"), async (original) => ({
...(await original()),
trackRpcRequestSent: () => {},
}));

// The environment session outlives a render, so its failing subscriptions need their own file.
it("keeps synchronization failures separate from local errors and first-load send eligibility", async () => {
const cold = threadWithHistory("cold-sync-failure", 1);
const warm = threadWithHistory("warm-sync-failure", 1);
using _environment = installFakeEnvironment([cold, warm]);
const firstFailure = Deferred.makeUnsafe<void>();
const nextFailure = Deferred.makeUnsafe<void>();
let warmSubscriptions = 0;
const connect = fakeDriver.connect;
using _connect = vi.spyOn(fakeDriver, "connect").mockImplementation((entry) =>
connect(entry).pipe(
Effect.map((lease) => ({
...lease,
session: {
...lease.session,
client: new Proxy(lease.session.client, {
get(target, method, receiver) {
if (method === ORCHESTRATION_V2_WS_METHODS.subscribeThread) {
return (
input: Parameters<
(typeof target)[typeof ORCHESTRATION_V2_WS_METHODS.subscribeThread]
>[0],
) => {
if (input.threadId === cold.id) {
return Stream.fail(
new EnvironmentAuthorizationError({
message: "Thread history unavailable",
requiredScope: "orchestration:read",
}),
);
}
warmSubscriptions += 1;
const initial =
warmSubscriptions === 1
? target[ORCHESTRATION_V2_WS_METHODS.subscribeThread](input).pipe(
Stream.take(2),
)
: Stream.empty;
return initial.pipe(
Stream.concat(
Stream.fromEffect(
Deferred.await(warmSubscriptions === 1 ? firstFailure : nextFailure).pipe(
Effect.andThen(Effect.die(new Error("Broken thread stream"))),
),
),
),
);
};
}
if (method === ORCHESTRATION_V2_WS_METHODS.dispatchCommand) {
return (
command: Parameters<
(typeof target)[typeof ORCHESTRATION_V2_WS_METHODS.dispatchCommand]
>[0],
) =>
Effect.fail(
new OrchestrationV2DispatchCommandError({
commandId: command.commandId,
commandType: command.type,
message: "Local send failed",
}),
);
}
return Reflect.get(target, method, receiver);
},
}),
},
})),
),
);
__setClientSettingsForTests({
...DEFAULT_CLIENT_SETTINGS,
onboardingCompletedAt: "2026-01-01T00:00:00.000Z",
});
const router = getRouter(
createMemoryHistory({ initialEntries: [`/${ENVIRONMENT_ID}/${cold.id}`] }),
);
await router.load();
await using _app = await render(<AppRoot router={router} />, {
// AppRoot brings its own router.
router: false,
});
await expect.element(page.getByText("Thread history unavailable", { exact: true })).toBeVisible();
await page.getByTestId("composer-editor").fill("Do not send before history arrives");
await expect
.element(page.getByRole("button", { name: /^(Submit message|Messages loading)$/ }))
.toBeDisabled();

await act(() =>
router.navigate({
to: "/$environmentId/$threadId",
params: { environmentId: ENVIRONMENT_ID, threadId: warm.id },
}),
);
await expect.element(page.getByText(`Answer 0 for ${warm.id}.`)).toBeVisible();
await act(() => Deferred.doneUnsafe(firstFailure, Effect.void));
const syncFailure = page.getByText("Could not synchronize the thread.", { exact: true });
await expect.element(syncFailure).toBeVisible();
const threadState = environmentThreadDetails.stateAtom({
environmentId: ENVIRONMENT_ID,
threadId: warm.id,
});
const firstSyncFailure = appAtomRegistry.get(threadState).error;
await page.getByTestId("composer-editor").fill("Retry the work");
await page.getByRole("button", { name: "Submit message", exact: true }).click();
await expect.element(page.getByTestId("composer-editor")).toHaveTextContent("Retry the work");
await expect.element(page.getByText("Local send failed", { exact: true })).toBeVisible();
await page.getByRole("button", { name: "Dismiss error" }).click();
await expect
.element(page.getByText("Local send failed", { exact: true }))
.not.toBeInTheDocument();

await expect.element(syncFailure).toBeVisible();
await page.getByRole("button", { name: "Dismiss error" }).click();
await expect.element(syncFailure).not.toBeInTheDocument();

document.dispatchEvent(new Event("visibilitychange"));
await vi.waitFor(() => expect(warmSubscriptions).toBe(2));
await act(() => Deferred.doneUnsafe(nextFailure, Effect.void));
await vi.waitFor(() => {
const failure = appAtomRegistry.get(threadState).error;
expect(failure).toMatchObject({ _tag: "Some", value: "Could not synchronize the thread." });
expect(failure).not.toBe(firstSyncFailure);
});
await expect.element(syncFailure).not.toBeInTheDocument();
await expect
.element(page.getByText("Local send failed", { exact: true }))
.not.toBeInTheDocument();
});
Loading
Loading