Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
823 commits
Select commit Hold shift + click to select a range
8c2aea4
fix(server): release delivered snapshots from live RPC streams
juliusmarminge Sep 19, 2026
612927b
fix(shared): release successful results from completed trace spans
juliusmarminge Sep 19, 2026
1710595
fix(v2): reconcile main cleanup and mobile device controls
juliusmarminge Sep 19, 2026
ed322cb
fix(server): decode transcript tool payloads only once
juliusmarminge Sep 19, 2026
79fb689
fix(server): refresh completed runs without loading transcripts
juliusmarminge Sep 19, 2026
0982aae
fix(server): avoid transcript reloads during run completion
juliusmarminge Sep 19, 2026
5c3921b
fix(server): load targeted state when starting provider turns
juliusmarminge Sep 20, 2026
5879be6
fix(notifications): silence subagent threads
maria-rcks Sep 19, 2026
334655f
fix(preview): restore v2 sizing and project access (#12548)
juliusmarminge Sep 19, 2026
bcef17d
fix(server): settle V2 threads after linked PR merges (#12568)
Bil0000 Sep 19, 2026
04f0fda
fix(web): show subagent models and running count in Lineage (#12491)
Bil0000 Sep 19, 2026
cc6a351
fix(web): show Auto balance in the workspace host menu (#12481)
Bil0000 Sep 19, 2026
dc8c228
fix(chat): present and summarize all T3 tools (#12671)
juliusmarminge Sep 20, 2026
c390539
feat(web): list linked PRs in workspace card (#12574)
Bil0000 Sep 20, 2026
0b1ee28
fix(web): make PR badge hover lists easy to click (#12378)
Bil0000 Sep 20, 2026
9b0d644
fix(mobile): preserve native send choices and keyboard (#12770)
juliusmarminge Sep 20, 2026
45c7e75
fix(server): surface actionable provider failure messages (#12560)
juliusmarminge Sep 20, 2026
3edc5d5
fix(web): keep workspace card action hover uniform (#12766)
Bil0000 Sep 20, 2026
05abce1
fix(web): stop citation popovers flying into position
juliusmarminge Sep 21, 2026
d612487
fix(web): hide raw image markup in queue previews (#12820)
maria-rcks Sep 21, 2026
6c56ad6
feat(v2): show provider limit stops as Limited (#12677)
juliusmarminge Sep 21, 2026
6d074cd
feat(v2): resume limited threads when usage resets (#12686)
juliusmarminge Sep 21, 2026
4728886
feat(v2): snooze limited threads until usage resets (#12687)
juliusmarminge Sep 21, 2026
b7a147d
fix(v2): keep failed turns visible in the transcript (#12783)
juliusmarminge Sep 21, 2026
e459214
refactor(server): share scheduling for tasks and limit recovery (#12795)
juliusmarminge Sep 21, 2026
894f6c4
fix(v2): reconcile main UI, attachment limits, and logging fixtures
juliusmarminge Sep 21, 2026
98b03d9
test(v2): align handoff fixtures with larger attachment limits
juliusmarminge Sep 21, 2026
7b13cd9
feat(web): color handoff model names with their provider brand color …
maria-rcks Sep 21, 2026
5d4423b
refactor(web): remove the agents right panel (#12835)
maria-rcks Sep 21, 2026
b4544f9
feat(web): clearer icons for the workspace panel controls (#12838)
maria-rcks Sep 21, 2026
e3bdfd7
feat(web): give lineage subagent hovers the thread hover card (#12842)
maria-rcks Sep 21, 2026
ccf43cc
fix(v2): reconcile main composer layout and undo actions
juliusmarminge Sep 21, 2026
3409430
fix(v2): remove obsolete composer breakpoint animation
juliusmarminge Sep 21, 2026
534b7d4
fix(server): avoid transcript reads when checking run interrupts
juliusmarminge Sep 21, 2026
28051c4
fix(server): replace unnecessary full projection reads
juliusmarminge Sep 21, 2026
7a4a03c
perf(pr): reduce quota use when refreshing workspace checks (#12442)
Bil0000 Sep 21, 2026
1b8dd36
test(v2): expose scoped reads in provider replay harness
juliusmarminge Sep 21, 2026
d37d9b4
fix(server): recover Pi resumes without reusing native history (#12933)
juliusmarminge Sep 21, 2026
9efeb18
fix(settings): restore V2 controls and shared settings layout
juliusmarminge Sep 21, 2026
35b9f0c
feat(web): edit the last queued message with Option+Up (#12599)
jakeleventhal Sep 21, 2026
8383410
fix(web): edit automations from thread details (#12408)
saphid Sep 21, 2026
943ab9a
fix(server): preserve provider history across repeated rollbacks (#12…
Derpedyea Sep 21, 2026
474124a
fix(server): start ACP MCP bridge in self-contained runtime (#12747)
pekth Sep 21, 2026
6f3cb06
fix(server): launch contained ACP providers from packaged runtimes (#…
pekth Sep 21, 2026
2f534ff
fix(web): restore sidebar order during thread context drags
juliusmarminge Sep 21, 2026
3d564a5
refactor(server): resolve self invocations through one shared helper …
juliusmarminge Sep 21, 2026
7a0c47f
perf(server): stop decoding unrelated events during startup (#12846)
extoci Sep 21, 2026
630cf22
perf(server): stop maintaining redundant projection indexes (#12847)
extoci Sep 21, 2026
47d533e
feat(cursor): support browser login for the agent SDK (#12948)
Yash-Singh1 Sep 21, 2026
bcbe95e
fix(server): fail V2 runs when provider sessions cannot open (#12790)
pekth Sep 21, 2026
1421612
fix(server): fail runs when provider startup preparation fails (#12409)
saphid Sep 21, 2026
324038f
fix(server): select an available provider for delegated tasks (#11870)
saphid Sep 21, 2026
45e2485
feat(web): show a turn's subagents as one collapsible card (#12839)
maria-rcks Sep 21, 2026
4ccfdee
feat(mobile): show subagents in a collapsible card (#12961)
juliusmarminge Sep 22, 2026
c267ec1
fix(chat): link agent attribution to its source thread (#12971)
juliusmarminge Sep 22, 2026
77acaf5
fix(orchestration): settle subagent statuses and activation timers (#…
juliusmarminge Sep 22, 2026
52db643
fix(server): retry provider session opens before failing the run (#13…
t3dotgg Sep 22, 2026
b8aadbf
feat(auth): share provider sign-in flows across clients (#12965)
juliusmarminge Sep 22, 2026
33817c1
refactor(cursor): use shared provider account setup and storage (#12966)
juliusmarminge Sep 22, 2026
acebb3f
feat(acp): connect registry providers to shared sign-in flows (#12967)
juliusmarminge Sep 22, 2026
19c1428
fix(v2): reconcile main settings, auth, and shared controls
juliusmarminge Sep 23, 2026
ebf8a82
fix(v2): preserve main scroll fixes and mobile module boundaries
juliusmarminge Sep 23, 2026
81f2d75
fix(v2): hidden automatic queued runs no longer block settling a thread
juliusmarminge Sep 23, 2026
00056fd
fix(v2): reconcile main mobile lists and provider compatibility
juliusmarminge Sep 23, 2026
486a270
fix(v2): reconcile main shared controls and render recovery
juliusmarminge Sep 23, 2026
1688f02
fix(v2): remove stale panel styling exports
juliusmarminge Sep 23, 2026
f4b0b5b
feat(web): integrate responsive chat and thread details
juliusmarminge Sep 23, 2026
b245b09
feat(v2): make worktree branch naming configurable (#13294)
juliusmarminge Sep 23, 2026
15cc654
fix(cua): show call titles and align app icons (#13307)
Yash-Singh1 Sep 23, 2026
3c82794
fix(server): reduce retained thread memory in PR lookups and turn sta…
juliusmarminge Sep 23, 2026
c851f8c
refactor(server): detach PR lookup stacks instead of a custom cache (…
juliusmarminge Sep 23, 2026
33868db
fix(mobile): lift working control above question overlay (#13297)
gabrielelpidio Sep 23, 2026
a1a7de2
perf(server): speed up cold desktop launches (#13320)
Yash-Singh1 Sep 23, 2026
6f3040d
fix(web): handle thread details context clicks (#13323)
Yash-Singh1 Sep 24, 2026
a28fc10
fix(desktop): resolve Windows userData without yielding before the Cl…
SunkenInTime Sep 24, 2026
68cd258
fix(v2): reconcile latest main after rebase
juliusmarminge Sep 24, 2026
6dbe344
fix(v2): keep relay helpers private after rebase
juliusmarminge Sep 24, 2026
3b89388
fix(v2): cover Pi compatibility after main sync
juliusmarminge Sep 24, 2026
1c339ef
fix(orchestration): report subagent models and use live model choices…
Bil0000 Sep 24, 2026
cadac54
fix(server): keep Claude subagent output in the subagent's thread (#1…
scratchyone Sep 24, 2026
833d52e
fix(web): align workspace card controls
juliusmarminge Sep 24, 2026
2b6f2af
fix(server): link agent-sent messages to their source thread
juliusmarminge Sep 24, 2026
d10bebc
test(server): remove skipped, duplicate, and constant-restating V2 te…
juliusmarminge Sep 24, 2026
2e01848
fix(server): Codex V2 runs skills typed with any currency sigil (#13461)
juliusmarminge Sep 24, 2026
4784fba
refactor(server): remove the unused V1 Codex session runtime (#13462)
juliusmarminge Sep 24, 2026
7bc65c0
fix(server): Codex V2 sessions use the configured launch arguments (#…
juliusmarminge Sep 24, 2026
f6924fd
fix(server): merged PRs update and auto-settle threads again (#13476)
Bil0000 Sep 24, 2026
430dfd1
fix(server): Codex V2 sessions expand ~ in the binary path (#13470)
juliusmarminge Sep 24, 2026
d861582
fix(server): Claude V2 sessions expand ~ in the binary path (#13471)
juliusmarminge Sep 24, 2026
e7b2407
chore(server): unexport OpenCode capabilities left unused by test rem…
juliusmarminge Sep 24, 2026
3eb213c
test(server): make the provider-switch resume-failure test reach the …
juliusmarminge Sep 24, 2026
a967baf
fix(v2): reconcile latest main protocol and theme updates
juliusmarminge Sep 24, 2026
c9ad902
chore(web): drop the right panel sheet class left unused by the V2 re…
juliusmarminge Sep 24, 2026
13aec8a
fix(server): Cursor V2 threads load project skills and rules (#13499)
juliusmarminge Sep 24, 2026
a99b46e
test(server): re-record Cursor replay fixtures and cover skills live …
juliusmarminge Sep 24, 2026
b0abc48
fix(codex): replay legacy user-input requests as blocking (#13509)
juliusmarminge Sep 24, 2026
a63d9c5
test(server): record the Codex thread rollback fixture live on 0.156.…
juliusmarminge Sep 24, 2026
d4af1c4
test(server): record Codex multi-agent V2 subagents live on 0.156.1 (…
juliusmarminge Sep 24, 2026
f720d27
fix(v2): reconcile main auto-settle controls and preview migrations
juliusmarminge Sep 24, 2026
e692dbb
fix(web): ungroup single subagents and stabilize group expansion
juliusmarminge Sep 25, 2026
3413d33
fix(codex): preserve native item start times (#13525)
Yash-Singh1 Sep 25, 2026
899a93a
test(server): replace Pi adapter unit tests with live replay fixtures…
juliusmarminge Sep 25, 2026
06e80a6
test(server): remove replay harness self-tests (#13531)
juliusmarminge Sep 25, 2026
85aaa11
test(server): record Claude background task and subagent lifecycles l…
juliusmarminge Sep 25, 2026
75c7e9e
test(server): record Codex replay fixtures on gpt-6-luna and Codex 0.…
juliusmarminge Sep 25, 2026
cb879a9
fix(server): keep a Claude wake reply off the user's queued message (…
juliusmarminge Sep 25, 2026
37da532
fix(web): align workspace controls and restore split hover states
juliusmarminge Sep 25, 2026
3cb31a1
fix(server): Cursor sandboxed threads find their helper when running …
juliusmarminge Sep 25, 2026
c361921
chore(web): keep the thread details split surface class module-privat…
juliusmarminge Sep 25, 2026
20c5739
fix(server): Codex V2 threads show todo lists again (#13546)
juliusmarminge Sep 25, 2026
3d23e15
fix(web): resize floating previews smoothly above the composer
juliusmarminge Sep 25, 2026
7381ed9
refactor(server): record Cursor replay fixtures with Effect (#13556)
juliusmarminge Sep 25, 2026
cb8dce4
test(server): record Grok replay fixtures from a live grok agent (#13…
juliusmarminge Sep 25, 2026
bf1e8c5
fix: reconcile latest main changes with V2
juliusmarminge Sep 25, 2026
175e2bd
fix(server): Grok monitor updates stay running until Grok says they f…
juliusmarminge Sep 25, 2026
81744b3
test(server): assert the read-only on-request write by its permission…
juliusmarminge Sep 25, 2026
87c67bd
test(clients): retain main relay compatibility regression coverage
juliusmarminge Sep 25, 2026
f8b8634
fix(server): ACP agents can read files under on-request approval (#13…
juliusmarminge Sep 25, 2026
1f2f91d
fix(server): show diffs for ACP edits that send oldText/newText (#13579)
juliusmarminge Sep 25, 2026
b64278c
fix(clients): native subagent threads show when they are working (#13…
juliusmarminge Sep 25, 2026
6c39f90
fix(server): startup recovery settles native subagent threads (#13619)
juliusmarminge Sep 25, 2026
690c57f
fix(server): Claude subagent threads show their thinking (#13626)
juliusmarminge Sep 25, 2026
a4cd403
fix(server): a resumed Claude subagent's thread shows the message tha…
juliusmarminge Sep 25, 2026
d3179b6
fix(clients): native subagent threads show status instead of a compos…
juliusmarminge Sep 25, 2026
e1b6476
fix(server): Codex subagent approvals show up in the parent thread (#…
juliusmarminge Sep 25, 2026
fed2604
test(server): support replay gates for ACP providers (#13594)
juliusmarminge Sep 25, 2026
48b5111
fix(server): finish Grok background subagents from subagent_finished …
juliusmarminge Sep 25, 2026
541b6b9
fix(server): V2 Grok launches in the thread's permission mode (#13616)
juliusmarminge Sep 25, 2026
1d1b3bc
fix(server): Antigravity keeps its workspace containment (#13613)
juliusmarminge Sep 25, 2026
6107b66
refactor(server): ACP client fs and terminals are opt-in per flavor (…
juliusmarminge Sep 25, 2026
fe565ae
fix(server): Grok no longer offers Auto-accept edits (#13719)
juliusmarminge Sep 25, 2026
86e3487
refactor(server): remove the generic ACP client fs guard and write gr…
juliusmarminge Sep 25, 2026
cbe13c4
fix(server): ACP mode picks reach agents that name their mode option …
juliusmarminge Sep 26, 2026
01dba73
fix(server): subagent approvals always land in the parent run (#13726)
juliusmarminge Sep 26, 2026
f969b21
fix(server): Grok replies finish when Grok finishes them, not when ba…
juliusmarminge Sep 26, 2026
4812e12
refactor(server): fence the ACP registry adapter's per-agent exceptio…
juliusmarminge Sep 26, 2026
d1f92e6
fix(clients): provider subagent threads never show a composer (#13727)
juliusmarminge Sep 26, 2026
bb89d58
fix(clients): subagent threads fold their work like other threads (#1…
juliusmarminge Sep 26, 2026
c48e8a9
fix(server): finished Claude subagents leave no running rows (#13730)
juliusmarminge Sep 26, 2026
fd4d3f0
fix(server): Grok's Auto mode asks you about commands its classifier …
juliusmarminge Sep 26, 2026
de612cf
docs: ACP agents run their own tools, and Grok has no Auto-accept edi…
juliusmarminge Sep 26, 2026
70629cd
fix(server): a Claude subagent resumed after a server restart stays i…
juliusmarminge Sep 26, 2026
b882b10
fix(server): allow forks from provider-finished runs (#13541)
Yash-Singh1 Sep 26, 2026
954dbd7
fix(server): Grok's "Always allow this session" no longer saves a pro…
juliusmarminge Sep 26, 2026
98400c6
fix(server): ACP auto-approvals allow once instead of always (#13802)
juliusmarminge Sep 26, 2026
3ec7df1
fix(server): Claude asks before commands in Auto-accept edits (#13786)
juliusmarminge Sep 26, 2026
55cb2fc
fix(server): Implement starts a run from a proposed plan again (#13775)
juliusmarminge Sep 26, 2026
0481b76
fix(server): Codex plans offer Implement again (#13793)
juliusmarminge Sep 26, 2026
43b480b
fix(web): a command you stop stays in the timeline (#13790)
juliusmarminge Sep 26, 2026
c38c60f
fix(server): a Cursor command you stop shows as interrupted (#13806)
juliusmarminge Sep 26, 2026
75afe68
fix(server): Grok background shell commands stay in the run that star…
juliusmarminge Sep 26, 2026
d2269c3
fix(server): Pi rollback works past a turn you stopped (#13797)
juliusmarminge Sep 26, 2026
4fafbbe
fix(server): sandboxed Cursor threads keep working after a Full acces…
juliusmarminge Sep 26, 2026
2c388da
fix(server): Codex rollback works after the app-server restarts (#13787)
juliusmarminge Sep 26, 2026
0b4f386
chore(v2): merge main into the V2 branch (48 commits) (#13800)
juliusmarminge Sep 26, 2026
18cf621
Merge main into the V2 branch (record ancestry)
juliusmarminge Sep 26, 2026
65cab67
Merge main into the V2 branch (#13742)
juliusmarminge Sep 26, 2026
d6c539e
fix(server): retry Cursor text generation without sandboxing (#13863)
Yash-Singh1 Sep 26, 2026
bfb3501
fix(server): keep running after Cursor shell spawn failures (#13862)
Yash-Singh1 Sep 26, 2026
6cae455
fix(server): preserve context occupancy across model handoffs (#13871)
Yash-Singh1 Sep 26, 2026
eec0514
fix(server): recover Cursor sends from abandoned local runs (#13878)
Yash-Singh1 Sep 26, 2026
2e68ee5
perf(server): Claude item ordinals no longer copy a session-wide map …
juliusmarminge Sep 26, 2026
2d359e3
perf(server): Cursor item ordinals no longer copy a session-wide map …
juliusmarminge Sep 26, 2026
52d84bd
perf(server): ACP item ordinals no longer copy a session-wide map per…
juliusmarminge Sep 26, 2026
93dbb55
perf(server): Codex item maps no longer grow and copy for the whole s…
juliusmarminge Sep 26, 2026
00e1a9c
fix(server): allow handoff after a provider session detaches (#13882)
Yash-Singh1 Sep 26, 2026
069058c
fix(server): Stop ends a Claude thread's background work after the tu…
juliusmarminge Sep 27, 2026
9fcc9a4
fix(server): a failed rollback shows an error instead of hanging (#13…
juliusmarminge Sep 27, 2026
4018a6c
fix(server): preserve queued messages after usage limits (#13877)
Yash-Singh1 Sep 27, 2026
a3fbbe4
fix(v2): show read and search tool activity accurately (#13375)
Yash-Singh1 Sep 27, 2026
0dcb029
fix(server): Claude wake turns keep the rejected limit's reset time (…
saphid Sep 27, 2026
402205e
feat(mcp): expose thread settlement in t3_thread_list and t3_thread_r…
SunkenInTime Sep 27, 2026
b39e62d
fix(server): parents keep getting woken for every delegated task that…
juliusmarminge Sep 27, 2026
b222464
fix(clients): older clients skip event types they don't know instead …
juliusmarminge Sep 27, 2026
6134998
test(server): stop ACP soft-steer tests racing the prompt settle (#13…
saphid Sep 28, 2026
fe6553e
fix(server): stop OpenCode servers left behind by a crashed server (#…
juliusmarminge Sep 28, 2026
b2ed076
fix(server): harden the rollback failure marker (#13911)
juliusmarminge Sep 28, 2026
6e0c38e
refactor(server): project commands commit through EventSinkV2 (#13960)
juliusmarminge Sep 28, 2026
1d6bc0e
refactor(server): project reads and replay stats leave ProjectionSnap…
juliusmarminge Sep 28, 2026
7b80085
fix(server): "Edit from here" works on a message after a stopped run …
juliusmarminge Sep 28, 2026
613a1b2
refactor(server): thread search and git project lookup read V2 (#14015)
juliusmarminge Sep 28, 2026
f100c04
chore(server): delete the V1 decider, projector and V1-only repos (#1…
juliusmarminge Sep 28, 2026
babea40
refactor(server): quarantine the V1 importer (#14018)
juliusmarminge Sep 28, 2026
f9ff8e2
refactor(contracts): retire the legacy orchestration schemas (#14024)
juliusmarminge Sep 28, 2026
e78f5b3
chore(clients): delete client code nothing calls (#14056)
juliusmarminge Sep 28, 2026
39e6fbb
fix(server): tell the provider when a restart killed its background w…
juliusmarminge Sep 28, 2026
fc1ecf8
feat(server): continue settled threads that lost background work in a…
juliusmarminge Sep 28, 2026
b76f762
feat(server): background wakes say which subagent, command, or monito…
juliusmarminge Sep 28, 2026
b9ffe49
feat(clients): background work says what it is and which subagent fin…
juliusmarminge Sep 28, 2026
30f2131
chore(v2): merge main into the V2 branch (18 commits)
juliusmarminge Sep 28, 2026
977bf4a
fix(server): shell reads no longer scan every runless item per failed…
juliusmarminge Sep 28, 2026
2b9a4ad
fix(server): threads mid-turn continue after a restart on every provi…
juliusmarminge Sep 29, 2026
e2a8620
fix(server): a turn that fails to start after its session opens now f…
juliusmarminge Sep 29, 2026
a3f967a
fix(server): detaching a Codex thread unloads it from the shared app-…
juliusmarminge Sep 29, 2026
e364854
fix(clients): a failed turn shows as failed while background work is …
juliusmarminge Sep 29, 2026
e49357f
fix(server): OpenCode background subagents keep their session alive (…
juliusmarminge Sep 29, 2026
cb64162
fix(server): Claude monitors show as monitors, not commands (#14191)
juliusmarminge Sep 29, 2026
cd66adf
chore(v2): merge main into the V2 branch (17 commits)
juliusmarminge Sep 29, 2026
1f2311c
fix(web): grow tool groups when details expand (#13171)
saphid Sep 30, 2026
d2a8797
chore(v2): merge main into the V2 branch (9 commits)
juliusmarminge Sep 30, 2026
8ca8bd7
fix(web): thread panel lists the project's saved scripts (#14350)
gabrielelpidio Sep 30, 2026
82f884d
fix(clients): a thread left running a dev server alerts as completed …
juliusmarminge Sep 30, 2026
f71c079
fix(server): V2 Codex sessions identify as T3 Code, like main (#14377)
juliusmarminge Sep 30, 2026
8297ccf
fix(server): managed Codex refreshes after sign-out even when a check…
juliusmarminge Sep 30, 2026
0a42dd3
fix(web): Stop works while a run is still starting (#14201)
shivamhwp Sep 30, 2026
89f4f81
fix(web): show accurate, steady thread relationship status (#14412)
shivamhwp Sep 30, 2026
6562235
fix(server): process-group kills never reach every process the user o…
juliusmarminge Sep 30, 2026
1716694
fix(server): reject overlapping v2 checkpoint restore workspaces (#14…
juliusmarminge Sep 30, 2026
16d72f4
refactor(server): import Effect services as namespaces (#14385)
juliusmarminge Sep 30, 2026
4e51609
refactor(clients): import Effect services as namespaces (#14389)
juliusmarminge Sep 30, 2026
2dfd313
refactor(orchestration-v2): import Effect services as namespaces (#14…
juliusmarminge Sep 30, 2026
0fb3731
fix(server): preview builds keep their bundled OpenCode 2 compatibili…
juliusmarminge Sep 30, 2026
f82eb0f
fix(server): Grok API errors fail the run instead of completing it em…
juliusmarminge Sep 30, 2026
9449473
fix(server): Grok's reply to a finished background command opens its …
juliusmarminge Sep 30, 2026
14f74e1
feat(server): detect OpenCode 1.x or 2.x per instance and route by it…
juliusmarminge Oct 1, 2026
79e3d0a
build(server): add the OpenCode 2 Effect client (#14221)
juliusmarminge Oct 1, 2026
1f657e8
feat(server): run OpenCode 2 servers from the driver (#14241)
juliusmarminge Oct 1, 2026
f3eb99e
feat(server): run turns, text, reasoning and tools on OpenCode 2 (#14…
juliusmarminge Oct 1, 2026
f1e6515
chore(v2): merge main into the V2 branch (12 commits)
juliusmarminge Oct 1, 2026
f48d257
fix(server): checkpoint restore ignores the cwd of a provider session…
juliusmarminge Oct 1, 2026
6b1d22f
chore(v2): merge t3code/codex-turn-mapping into the main sync
juliusmarminge Oct 1, 2026
18e38d3
refactor(server): threads without a project run through a ScratchWork…
juliusmarminge Oct 1, 2026
1f0a1ad
fix(server): two Scratch threads never share a folder
juliusmarminge Oct 1, 2026
d17305f
fix(server): keep ScratchWorkspace.make private
juliusmarminge Oct 1, 2026
253ef68
feat(server): report OpenCode 2 usage, context windows, models and hi…
juliusmarminge Oct 1, 2026
5eae8ff
feat(server): OpenCode 2 approvals, questions and every runtime mode …
juliusmarminge Oct 1, 2026
4ee6c32
fix(build): desktop and CLI builds resolve catalog overrides on selec…
juliusmarminge Oct 1, 2026
2330919
feat(server): OpenCode 2 subagents and background wake-ups (#14474)
juliusmarminge Oct 1, 2026
bb607b0
chore(v2): merge main into the V2 branch (11 commits)
juliusmarminge Oct 1, 2026
a5d108e
refactor(server): projects T3 creates for you run through one service
juliusmarminge Oct 1, 2026
3b6d791
fix(server): a named project never deletes a folder another project owns
juliusmarminge Oct 1, 2026
981cd69
fix(clients): stop stranded thinking after a steer (#14546)
Yash-Singh1 Oct 1, 2026
fa65ee6
chore(v2): merge t3code/codex-turn-mapping into the project-folders r…
juliusmarminge Oct 1, 2026
40920d9
feat(server): OpenCode 2 native steering, fork and rollback (#14468)
juliusmarminge Oct 1, 2026
0613071
fix(server): Claude steers no longer fail when only next-turn options…
juliusmarminge Oct 1, 2026
7b616a3
fix(clients): a paused queue no longer shows the thread as working (#…
juliusmarminge Oct 1, 2026
6fa450f
feat(server): OpenCode 2 compaction, plan mode and workspace inventor…
juliusmarminge Oct 1, 2026
4d72e2c
fix(server): a Claude subagent's own subagents run on their requested…
juliusmarminge Oct 1, 2026
0fbd755
fix(server): a Claude-initiated turn no longer ends a queued /compact…
juliusmarminge Oct 1, 2026
b08e051
fix(server): a Claude subagent's own subagents no longer wake the roo…
juliusmarminge Oct 1, 2026
a2ca40a
feat(server): OpenCode 2 text generation, MCP injection and restart r…
juliusmarminge Oct 1, 2026
f438d65
fix(server): a subagent's events are no longer stored twice across ru…
juliusmarminge Oct 1, 2026
6f042ef
chore(v2): merge main into the V2 branch (#14668)
juliusmarminge Oct 1, 2026
b729550
fix(server): OpenCode 2 keeps a reused subagent's background work and…
juliusmarminge Oct 1, 2026
de95adc
feat(server): Pi 1.0 support, with replay fixtures recorded on 1.0 (#…
juliusmarminge Oct 2, 2026
66a9107
fix(server): Stop always ends the background work a thread shows (#14…
juliusmarminge Oct 2, 2026
3eaae44
fix(server): long T3 tool calls from Claude no longer time out at 60 …
SunkenInTime Oct 2, 2026
3d45bd9
chore(v2): merge main into the V2 branch (15 commits)
juliusmarminge Oct 2, 2026
af7de21
test(web): import the drop helpers the Working shelf tests use
juliusmarminge Oct 2, 2026
b37fcea
chore(v2): merge main into the V2 branch (3 commits)
juliusmarminge Oct 2, 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
  •  
  •  
  •  
23 changes: 22 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ jobs:
!/.repos/
sparse-checkout-cone-mode: false

# Blacksmith boots GitHub's Ubuntu runner image (gcc is usually present),
# but ACP process-tree live tests compile a small pthread fixture with `cc`
# and soft-skip when it is missing. Install build-essential so that path
# always runs in CI instead of silently no-oping.
- name: Install C toolchain for process-tree fixtures
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends build-essential
command -v cc
- uses: ./.github/actions/setup-apt-mirrors

# The desktop tests compile the browser secret helper. The install runs in
Expand Down Expand Up @@ -251,7 +261,7 @@ jobs:
T3CODE_TRANSFER_BUDGET_RESULT_PATH: ${{ runner.temp }}/thread-transfer-result.json
run: vp run --filter t3 test --shard ${{ matrix.shard }}/${{ strategy.job-total }}

# src/server.test.ts writes the budget report, so exactly one shard
# integration/transferBudgetV2.integration.test.ts writes the report; exactly one shard
# produces these files. Gating the upload on their presence keeps a
# single `thread-transfer-results` artifact per run, which is the name
# thread-transfer-report.yml resolves.
Expand Down Expand Up @@ -283,6 +293,17 @@ jobs:
if-no-files-found: ignore
retention-days: 30

transfer-report:
name: Transfer report artifact
needs: test_server
runs-on: ubuntu-24.04
steps:
- name: Require transfer measurements
uses: actions/download-artifact@v8
with:
name: thread-transfer-results
path: ${{ runner.temp }}/thread-transfer

# Split out of Check and Test: both paid ~7-9s to install a Rust toolchain
# for checks that take under 3s, on the critical path of every PR.
rust:
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/mobile-eas-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ name: Mobile EAS Production
# workflow_dispatch remains as a manual override for both modes (e.g. to
# retry an errored build or force an OTA).
# Manual v2-preview builds keep the production app identity and disable OTA.
# They auto-submit to TestFlight and the Google Play closed testing track v2.
# Select the v2 branch when dispatching a preview build.
on:
workflow_dispatch:
inputs:
mode:
description: "build (+ auto-submit to TestFlight) or update (OTA)"
description: "build (+ auto-submit to TestFlight / Google Play) or update (OTA)"
required: true
type: choice
default: build
options:
- build
- update
profile:
description: "Store build profile (v2-preview supports build mode only)"
description: "Store build profile (v2-preview: TestFlight + Play closed track v2; build only)"
required: true
type: choice
default: production
Expand All @@ -49,7 +50,7 @@ on:
description: "Target platform"
required: true
type: choice
default: ios
default: all
options:
- ios
- android
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ squashfs-root/
.vercel
.gstack/
.plans/
/audits/
dist-electron/
.electron-runtime/
.showcase/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ Full docs live in [docs/](./docs). There's no docs site yet.
- [Permission modes](./docs/user/permission-modes.md)
- [Keyboard shortcuts](./docs/user/keybindings.md)
- [Project settings](./docs/user/project-settings.md)
- [Appearance preferences](./docs/user/appearance.md)
- [Remote access from a phone or another machine](./docs/user/remote-access.md)
- [Keeping app and server in sync](./docs/user/updating.md)
- [Source control integrations](./docs/user/source-control.md)
Expand Down
37 changes: 29 additions & 8 deletions apps/desktop/src/app/DesktopAppIdentity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as DesktopAppIdentity from "./DesktopAppIdentity.ts";
import * as DesktopAssets from "./DesktopAssets.ts";
import * as DesktopConfig from "./DesktopConfig.ts";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";
import * as DesktopUserData from "./DesktopUserData.ts";

const defaultEnvironmentInput = {
dirname: "/repo/apps/desktop/dist-electron",
Expand Down Expand Up @@ -124,13 +125,14 @@ const withIdentity = <A, E, R>(
return effect.pipe(
Effect.provide(
DesktopAppIdentity.layer.pipe(
Layer.provide(NodePath.layerPosix),
Layer.provideMerge(
FileSystem.layerNoop({
exists: (path) =>
input.legacyPathProbeError
? Effect.fail(input.legacyPathProbeError)
: Effect.succeed(
input.legacyPathExists === true && path.includes("T3 Code (Alpha)"),
input.legacyPathExists === true && /T3 Code \((Alpha|Dev)\)/.test(path),
),
readFileString: () =>
Effect.succeed(input.packageJson ?? '{"t3codeCommitHash":"abcdef1234567890"}'),
Expand All @@ -145,20 +147,36 @@ const withIdentity = <A, E, R>(
};

describe("DesktopAppIdentity", () => {
it.effect("keeps using the legacy userData path when it already exists", () =>
it.effect("isolates the V2 profile even when the legacy V1 profile exists", () =>
withIdentity(
Effect.gen(function* () {
const identity = yield* DesktopAppIdentity.DesktopAppIdentity;
const userDataPath = yield* identity.resolveUserDataPath;

assert.equal(userDataPath, "/Users/alice/Library/Application Support/T3 Code (Alpha)");
assert.equal(userDataPath, "/Users/alice/Library/Application Support/t3code-v2");
}),
{ legacyPathExists: true },
),
);

it.effect("keeps using the legacy development profile", () =>
withIdentity(
Effect.gen(function* () {
const identity = yield* DesktopAppIdentity.DesktopAppIdentity;
assert.equal(
yield* identity.resolveUserDataPath,
"/Users/alice/Library/Application Support/T3 Code (Dev)",
);
}),
{
legacyPathExists: true,
environment: { env: { VITE_DEV_SERVER_URL: "http://localhost:5173" } },
},
),
);

it.effect("preserves failures while inspecting the legacy userData path", () => {
const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Alpha)";
const legacyPath = "/Users/alice/Library/Application Support/T3 Code (Dev)";
const cause = PlatformError.systemError({
_tag: "PermissionDenied",
module: "FileSystem",
Expand All @@ -172,15 +190,18 @@ describe("DesktopAppIdentity", () => {
const identity = yield* DesktopAppIdentity.DesktopAppIdentity;
const error = yield* identity.resolveUserDataPath.pipe(Effect.flip);

assert.instanceOf(error, DesktopAppIdentity.DesktopUserDataPathResolutionError);
assert.equal(error.legacyPath, legacyPath);
assert.instanceOf(error, DesktopUserData.DesktopUserDataInitializationError);
assert.equal(error.resourcePath, legacyPath);
assert.strictEqual(error.cause, cause);
assert.equal(
error.message,
`Failed to inspect legacy desktop user-data path at "${legacyPath}".`,
`Could not initialize Electron user data during inspect at ${legacyPath} (PermissionDenied).`,
);
}),
{ legacyPathProbeError: cause },
{
legacyPathProbeError: cause,
environment: { env: { VITE_DEV_SERVER_URL: "http://localhost:5173" } },
},
);
});

Expand Down
47 changes: 9 additions & 38 deletions apps/desktop/src/app/DesktopAppIdentity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import * as Effect from "effect/Effect";
import * as FileSystem from "effect/FileSystem";
import * as Layer from "effect/Layer";
import * as Option from "effect/Option";
import * as Path from "effect/Path";
import * as Ref from "effect/Ref";
import * as Schema from "effect/Schema";

import * as ElectronApp from "../electron/ElectronApp.ts";
import * as DesktopAssets from "./DesktopAssets.ts";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";
import * as DesktopUserData from "./DesktopUserData.ts";

const COMMIT_HASH_PATTERN = /^[0-9a-f]{7,40}$/i;
const COMMIT_HASH_DISPLAY_LENGTH = 12;
Expand All @@ -18,22 +20,13 @@ const AppPackageMetadata = Schema.Struct({
});
const decodeAppPackageMetadata = Schema.decodeEffect(Schema.fromJsonString(AppPackageMetadata));

export class DesktopUserDataPathResolutionError extends Schema.TaggedError<DesktopUserDataPathResolutionError>()(
"DesktopUserDataPathResolutionError",
{
legacyPath: Schema.String,
cause: Schema.Defect(),
},
) {
override get message(): string {
return `Failed to inspect legacy desktop user-data path at "${this.legacyPath}".`;
}
}

export class DesktopAppIdentity extends Context.Service<
DesktopAppIdentity,
{
readonly resolveUserDataPath: Effect.Effect<string, DesktopUserDataPathResolutionError>;
readonly resolveUserDataPath: Effect.Effect<
string,
DesktopUserData.DesktopUserDataInitializationError
>;
readonly configure: Effect.Effect<void>;
}
>()("@t3tools/desktop/app/DesktopAppIdentity") {}
Expand All @@ -45,33 +38,13 @@ const normalizeCommitHash = (value: string): Option.Option<string> => {
: Option.none();
};

export const resolveUserDataPath = Effect.gen(function* () {
const environment = yield* DesktopEnvironment.DesktopEnvironment;
const fileSystem = yield* FileSystem.FileSystem;
const legacyPath = environment.path.join(
environment.appDataDirectory,
environment.legacyUserDataDirName,
);
const legacyPathExists = yield* fileSystem.exists(legacyPath).pipe(
Effect.mapError(
(cause) =>
new DesktopUserDataPathResolutionError({
legacyPath,
cause,
}),
),
);
return legacyPathExists
? legacyPath
: environment.path.join(environment.appDataDirectory, environment.userDataDirName);
}).pipe(Effect.withSpan("desktop.appIdentity.resolveUserDataPath"));

/** @public Service construction is part of the canonical Effect module API. */
export const make = Effect.gen(function* () {
const assets = yield* DesktopAssets.DesktopAssets;
const electronApp = yield* ElectronApp.ElectronApp;
const environment = yield* DesktopEnvironment.DesktopEnvironment;
const fileSystem = yield* FileSystem.FileSystem;
const userDataContext = yield* Effect.context<FileSystem.FileSystem | Path.Path>();
const commitHashCache = yield* Ref.make<Option.Option<Option.Option<string>>>(Option.none());

const resolveEmbeddedCommitHash = Effect.gen(function* () {
Expand Down Expand Up @@ -112,10 +85,8 @@ export const make = Effect.gen(function* () {
return commitHash;
});

const userDataPath = resolveUserDataPath.pipe(
Effect.provide(
yield* Effect.context<DesktopEnvironment.DesktopEnvironment | FileSystem.FileSystem>(),
),
const userDataPath = DesktopUserData.resolveUserDataPath(environment).pipe(
Effect.provide(userDataContext),
);

const configure = Effect.gen(function* () {
Expand Down
52 changes: 47 additions & 5 deletions apps/desktop/src/app/DesktopClerk.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @effect-diagnostics nodeBuiltinImport:off globalFetchInEffect:off - Hosted handoff test uses a real localhost listener without an OpenAI account.
import * as NodeHttp from "node:http";
import * as NodePath from "@effect/platform-node/NodePath";
import { codexAuthHandoffUrl, readCodexAuthDelivery } from "@t3tools/shared/codexAuthHandoff";
import { EnvironmentId, ProviderInstanceId } from "@t3tools/contracts";
import { HostProcessArguments } from "@t3tools/shared/hostProcess";
Expand Down Expand Up @@ -35,10 +36,15 @@ import * as ElectronShell from "../electron/ElectronShell.ts";
import * as ElectronWindow from "../electron/ElectronWindow.ts";
import * as DesktopClerk from "./DesktopClerk.ts";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";
import * as DesktopPreReadyFileSystem from "./DesktopPreReadyFileSystem.ts";

const makeDesktopClerkLayer = (
isDevelopment = true,
events: string[] = [],
platform: NodeJS.Platform = "darwin",
fileSystemLayer: Layer.Layer<FileSystem.FileSystem> = FileSystem.layerNoop({
exists: () => Effect.succeed(false),
}),
shell: ElectronShell.ElectronShell["Service"] = {
openExternal: () => Effect.succeed(true),
openSystemSettings: () => Effect.succeed(false),
Expand All @@ -49,9 +55,7 @@ const makeDesktopClerkLayer = (
stateDir: "/tmp/t3-state",
isDevelopment,
appDataDirectory: "/tmp/app-data",
userDataDirName: isDevelopment ? "t3code-dev" : "t3code",
legacyUserDataDirName: isDevelopment ? "T3 Code (Dev)" : "T3 Code (Alpha)",
path: { join: (...parts: ReadonlyArray<string>) => parts.join("/") },
platform,
} as unknown as DesktopEnvironment.DesktopEnvironment["Service"]);

const electronApp = {
Expand All @@ -64,10 +68,11 @@ const makeDesktopClerkLayer = (
return DesktopClerk.layer.pipe(
Layer.provide(
Layer.mergeAll(
NodePath.layerPosix,
Layer.succeed(DesktopEnvironment.DesktopEnvironment, environment),
Layer.succeed(ElectronApp.ElectronApp, electronApp),
Layer.succeed(ElectronShell.ElectronShell, shell),
FileSystem.layerNoop({ exists: () => Effect.succeed(false) }),
fileSystemLayer,
),
),
);
Expand Down Expand Up @@ -110,6 +115,43 @@ describe("DesktopClerk", () => {
});
});

it.each([
{
name: "packaged Windows",
isDevelopment: false,
platform: "win32" as const,
userData: "/tmp/app-data/t3code-v2",
},
{
name: "development",
isDevelopment: true,
platform: "win32" as const,
userData: "/tmp/app-data/t3code-dev",
},
])(
"creates the bridge before startup can yield to the event loop ($name)",
({ isDevelopment, platform, userData }) => {
const events: string[] = [];
storageMock.mockReturnValue(storageAdapter);
createClerkBridgeMock.mockImplementation(() => {
events.push("createClerkBridge");
return { cleanup: vi.fn(), isPrimaryInstance: true };
});
// runSync throws if the layer ever suspends, which would let Electron emit
// ready before the bridge exists. main.ts provides the same FileSystem.
// oxlint-disable-next-line t3code/no-manual-effect-runtime-in-tests -- The assertion IS that the layer builds synchronously; it.effect would mask a regression to async.
Effect.runSync(
Effect.scoped(
Layer.build(
makeDesktopClerkLayer(isDevelopment, events, platform, DesktopPreReadyFileSystem.layer),
),
),
);

assert.deepEqual(events, [`setPath:userData:${userData}`, "createClerkBridge"]);
},
);

it.effect("preserves bridge initialization failures", () => {
const cause = new Error("bridge initialization failed");
storageMock.mockReturnValue(storageAdapter);
Expand Down Expand Up @@ -331,7 +373,7 @@ for (const entry of ["startup", "open-url"] as const) {
assert.strictEqual(delivery?.flowId, request.flowId);
assert.strictEqual(delivery?.returnUrl, request.returnUrl);
}).pipe(
Effect.provide(makeDesktopClerkLayer(true, [], shell)),
Effect.provide(makeDesktopClerkLayer(true, [], "darwin", undefined, shell)),
Effect.provideService(HostProcessArguments, entry === "startup" ? ["t3", link] : ["t3"]),
Effect.provideService(ElectronApp.ElectronApp, electronApp),
Effect.provideService(
Expand Down
12 changes: 4 additions & 8 deletions apps/desktop/src/app/DesktopClerk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { clerkFrontendApiHostnameFromPublishableKey } from "@t3tools/shared/rela
import * as ElectronApp from "../electron/ElectronApp.ts";
import * as ElectronProtocol from "../electron/ElectronProtocol.ts";
import * as ElectronWindow from "../electron/ElectronWindow.ts";
import * as DesktopAppIdentity from "./DesktopAppIdentity.ts";
import * as DesktopUserData from "./DesktopUserData.ts";
import * as DesktopEnvironment from "./DesktopEnvironment.ts";

declare const __T3CODE_BUILD_CLERK_PUBLISHABLE_KEY__: string | undefined;
Expand Down Expand Up @@ -94,13 +94,9 @@ export const make = Effect.gen(function* () {
const electronApp = yield* ElectronApp.ElectronApp;
const shell = yield* ElectronShell.ElectronShell;

// Electron scopes the single-instance lock to the userData directory and
// creates that directory when the lock is acquired. The SDK bridge takes
// the lock at creation, so userData must already point at the real
// directory here — under the default productName-derived path, acquiring
// the lock would create "T3 Code (Alpha)" and make the legacy-install
// detection in resolveUserDataPath match on fresh installs.
const userDataPath = yield* DesktopAppIdentity.resolveUserDataPath;
// The SDK bridge acquires Electron's profile-scoped single-instance lock.
// Must not yield: the bridge registers a scheme Electron rejects once ready.
const userDataPath = yield* DesktopUserData.resolveUserDataPath(environment);
yield* electronApp.setPath("userData", userDataPath);

const bridge = yield* Effect.acquireRelease(
Expand Down
Loading
Loading