Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
425 commits
Select commit Hold shift + click to select a range
430d820
Leave a stopped turn's running tools to the agent's own end
brennanb2025 Oct 5, 2026
d22b154
Pin that a stopped turn's running tools hold budget until the agent's…
brennanb2025 Oct 5, 2026
76948c6
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-c1-t…
brennanb2025 Oct 5, 2026
1c49877
Type the stopped turn's tool progress update as a tool body
brennanb2025 Oct 5, 2026
d23e5c0
Merge remote-tracking branch 'origin/brennanb2025/acp-a1-opaque-handl…
brennanb2025 Oct 5, 2026
9ddbafd
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-a2-a…
brennanb2025 Oct 5, 2026
9fcb954
List every event the assembler hands to the decision step
brennanb2025 Oct 5, 2026
a902a0f
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
6d8eefc
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
a46e8b8
End a running call as its turn's journal row ends
brennanb2025 Oct 5, 2026
cf9d0ee
Say why a Grok turn failed, and keep task rows in Grok's own words
brennanb2025 Oct 5, 2026
e88bbf0
Read a monitor from Grok's exact output prefix
brennanb2025 Oct 5, 2026
ad7678c
Word a failed Grok turn in Grok's own text, not as a refused message
brennanb2025 Oct 5, 2026
fdba83d
Settle a stopped turn's running call as its turn row ended after a re…
brennanb2025 Oct 5, 2026
70fd4ba
Keep the dead-generation settlement under the line cap
brennanb2025 Oct 5, 2026
7aa40a9
Register the ACP schema verify step in the PR preflight phase test
brennanb2025 Oct 5, 2026
19c8cb5
refactor(agent-session): one required agent registry; declarations ad…
brennanb2025 Oct 5, 2026
cc38107
Merge remote-tracking branch 'origin/brennanb2025/acp-d1-protocol' in…
brennanb2025 Oct 5, 2026
c4655b4
Read ACP permissions, session events and prompt errors through the pr…
brennanb2025 Oct 5, 2026
c5aaee8
refactor(agent-session): the router applies the declared rewind itself
brennanb2025 Oct 5, 2026
ae44163
Merge remote-tracking branch 'origin/brennanb2025/acp-a2-agent-regist…
brennanb2025 Oct 5, 2026
9e7b78a
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-a3-wire
brennanb2025 Oct 5, 2026
b494ed6
test(agent-session): register the agents the merged-in tests now need
brennanb2025 Oct 5, 2026
7591167
chore(agent-session): the registry is the one lookup; drop the test-o…
brennanb2025 Oct 5, 2026
288f72c
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-a2-a…
brennanb2025 Oct 5, 2026
e260b93
Merge remote-tracking branch 'origin/brennanb2025/acp-a2-agent-regist…
brennanb2025 Oct 5, 2026
65a967b
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-a3-wire
brennanb2025 Oct 5, 2026
4f32dc9
fix(agent-session): keep "dismiss all" restart offers dismissed for t…
brennanb2025 Oct 5, 2026
212af51
fix(agent-session): a changed agent definition never hides that agent…
brennanb2025 Oct 5, 2026
e23946f
refactor(agent-session): each agent's registration says where it runs…
brennanb2025 Oct 5, 2026
a83313b
test(agent-session): drop a duplicate registry key; keep fences out o…
brennanb2025 Oct 5, 2026
b557e5e
fix(agent-session): a scoped dismiss-all persists no per-session fence
brennanb2025 Oct 5, 2026
f0e695f
fix(agent-session): refuse an attach whose agent is not the session's…
brennanb2025 Oct 5, 2026
7b52fb5
fix(agent-session): offer to start a chat only when the start would a…
brennanb2025 Oct 5, 2026
38d510d
fix(agent-session): the model-catalog probe uses a record's account o…
brennanb2025 Oct 5, 2026
1a569b8
refactor(agent-session): the record store admits agent ids; comments …
brennanb2025 Oct 5, 2026
364f11f
docs(agent-session): the record store admits the registered agents' ids
brennanb2025 Oct 5, 2026
ad2b25a
Merge remote-tracking branch 'origin/brennanb2025/acp-a3-wire' (364f1…
brennanb2025 Oct 5, 2026
4fbeafa
Merge remote-tracking branch 'origin/brennanb2025/acp-a6-provider-lif…
brennanb2025 Oct 5, 2026
c064b28
Merge remote-tracking branch 'origin/brennanb2025/acp-c5-tool-interru…
brennanb2025 Oct 5, 2026
4edf2b2
Merge remote-tracking branch 'origin/brennanb2025/acp-d2-translation'…
brennanb2025 Oct 5, 2026
b7279d1
Merge remote-tracking branch 'origin/main' (d17351401d7) into brennan…
brennanb2025 Oct 5, 2026
57a7a29
refactor(native-chat): Grok's registration declares where it runs; AC…
brennanb2025 Oct 5, 2026
0fc5a72
fix(native-chat): Grok follows the ACP runtime's request contract and…
brennanb2025 Oct 5, 2026
1108280
fix(native-chat): a Grok chat Orca already holds resumes without writ…
brennanb2025 Oct 5, 2026
d2764bc
refactor(native-chat): a failed Grok reattach needs no window close o…
brennanb2025 Oct 5, 2026
cba2dfa
test(native-chat): D3's merged tests use the shipped declarations and…
brennanb2025 Oct 5, 2026
da34dda
fix(native-chat): typecheck fallout of the base merges; any agent's e…
brennanb2025 Oct 5, 2026
4b4febc
fix(native-chat): a Grok Stop ends the process once Grok settles its …
brennanb2025 Oct 5, 2026
f6f9d66
test(native-chat): a Grok Stop ends the process only after Grok answe…
brennanb2025 Oct 5, 2026
2245710
fix(native-chat): Steer on a Grok card cancels the running prompt, th…
brennanb2025 Oct 5, 2026
bca0c77
refactor(native-chat): a close or Stop cancels a start through the ac…
brennanb2025 Oct 5, 2026
a30a89e
fix(native-chat): a Grok crash that closes stdout before its exit sti…
brennanb2025 Oct 5, 2026
5d68d91
fix(native-chat): nothing Grok sends while a held chat reattaches is …
brennanb2025 Oct 5, 2026
586e6a6
test(native-chat): a Stop after a resume finds no turn an unmarked ol…
brennanb2025 Oct 5, 2026
651ab47
test(native-chat): a resumed Grok chat keeps its last context reading…
brennanb2025 Oct 5, 2026
e8d1e11
test(native-chat): a Grok background task a Stop ended reads as stopp…
brennanb2025 Oct 5, 2026
294fd0d
refactor(native-chat): quit's stop of each start answers through one …
brennanb2025 Oct 5, 2026
cd9a138
fix(native-chat): quit aborts every start the host has in flight befo…
brennanb2025 Oct 5, 2026
2c2731d
fix(native-chat): a Grok start's abort stops reaching its child once …
brennanb2025 Oct 5, 2026
418aa57
fix(native-chat): a close or Stop during any attach phase stops the s…
brennanb2025 Oct 5, 2026
a0c5bba
test(native-chat): a close during the attach's owner probe asks no ad…
brennanb2025 Oct 5, 2026
b63c9b5
test(native-chat): a close's re-ask closes a Claude or Codex child a …
brennanb2025 Oct 5, 2026
7a4ac2f
fix(native-chat): Steer during a turn Grok began itself cancels it an…
brennanb2025 Oct 5, 2026
0ff2585
test(native-chat): a steer whose cancel Grok never answers ends Grok …
brennanb2025 Oct 5, 2026
0baae44
fix(native-chat): a Grok crash stays a crash when a stop lands before…
brennanb2025 Oct 5, 2026
b0f1e33
test(native-chat): fixtures this PR's registered Grok and desktop cap…
brennanb2025 Oct 5, 2026
9931665
fix(native-chat): a start quit stops is not the queued message's star…
brennanb2025 Oct 5, 2026
ff08986
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-c1a-…
brennanb2025 Oct 5, 2026
06e664b
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-c1-t…
brennanb2025 Oct 5, 2026
98e7403
Merge origin/main into acp-d2-translation
brennanb2025 Oct 5, 2026
7346f41
fix(native-chat): a message sent after a Stop or close aborted a star…
brennanb2025 Oct 5, 2026
ad8ebbd
Merge remote-tracking branch 'origin/brennanb2025/acp-c1a-timeline-tr…
brennanb2025 Oct 5, 2026
77c16ec
test(native-chat): the message sent after an aborted start is answere…
brennanb2025 Oct 5, 2026
c4a96e1
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-c5-t…
brennanb2025 Oct 5, 2026
16eef12
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
c1f0c7a
Merge acp-c1-timeline-assembler (main merged) into acp-d2-translation
brennanb2025 Oct 5, 2026
75231a4
fix(native-chat): a Grok model pick Grok never answers no longer hold…
brennanb2025 Oct 5, 2026
27a9db0
fix(agent-launch): a phone's launch opens a terminal for an agent who…
brennanb2025 Oct 5, 2026
d2e32d1
fix(acp): strip every agent hook variable from the ACP child, from th…
brennanb2025 Oct 5, 2026
2776c80
refactor(native-chat): the mutation context carries the provider-wait…
brennanb2025 Oct 5, 2026
a24cd11
fix(agent-launch): agent.launch.v2 still vouches for Claude and Codex…
brennanb2025 Oct 5, 2026
879f74a
refactor(native-chat): drop saved-history adoption from the timeline …
brennanb2025 Oct 5, 2026
d012bc2
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
0f4be81
refactor(acp): drop session/load history adoption from the translator
brennanb2025 Oct 5, 2026
58c3dd5
refactor(native-chat): a pending input is only Orca's send now
brennanb2025 Oct 5, 2026
d40fd03
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
2802460
test(acp): keep the task-result status table on live frames
brennanb2025 Oct 5, 2026
d613623
test(acp): a frame helper for a shell command Grok is running
brennanb2025 Oct 5, 2026
03ca1d9
fix(acp): a Grok crash settles through the host's provider-exit batch…
brennanb2025 Oct 5, 2026
8854fe8
test(acp): a crash seen first leaves the host no Grok turn to revise
brennanb2025 Oct 5, 2026
459b8cb
refactor(native-chat): what a gone generation left unfinished gets it…
brennanb2025 Oct 5, 2026
ed63665
refactor(native-chat): a watched exit revises what its child left unv…
brennanb2025 Oct 5, 2026
ed9fadc
test(native-chat): drop the duplicate itemFence on the fake that alre…
brennanb2025 Oct 5, 2026
16e84d0
test(claude, codex): an exit whose stdout ended first still reports a…
brennanb2025 Oct 5, 2026
374e740
Merge origin/main into acp-a1-opaque-handle
brennanb2025 Oct 5, 2026
75ddbbe
fix(acp): reopen a chat with session/load, as the common pattern does
brennanb2025 Oct 5, 2026
22d3d85
Merge acp-a1-opaque-handle (with origin/main) into acp-a2-agent-registry
brennanb2025 Oct 5, 2026
ce62189
fix(acp): drop the 60 s handshake bound; an abort fails the start's w…
brennanb2025 Oct 5, 2026
275455d
fix(acp): a Stop naming an ended turn follows Claude's rule
brennanb2025 Oct 5, 2026
ace8822
Merge acp-a2-agent-registry (with origin/main) into acp-a3-wire
brennanb2025 Oct 5, 2026
c832af5
fix(native-chat): a close no longer re-asks a failed start's unproven…
brennanb2025 Oct 5, 2026
c2bfd63
Merge origin/main into acp-a6-provider-lifecycle
brennanb2025 Oct 5, 2026
fe8108c
fix(acp): a message sent during a turn the agent began itself goes at…
brennanb2025 Oct 5, 2026
6143fb4
test(native-chat): dismiss-all through a remote client's audience kee…
brennanb2025 Oct 5, 2026
d717abf
fix(acp): launch Grok as `grok agent stdio`, without the update and l…
brennanb2025 Oct 5, 2026
e996bb1
Merge origin/main into acp-c1a-timeline-transitions
brennanb2025 Oct 5, 2026
aa80392
fix(acp): an agent that ends its stdout, or answers unreadably, is no…
brennanb2025 Oct 5, 2026
fa8e969
fix(native-chat): a person's close joining a failed one still binds t…
brennanb2025 Oct 5, 2026
a59276f
Merge remote-tracking branch 'origin/brennanb2025/acp-c1a-timeline-tr…
brennanb2025 Oct 5, 2026
5c4a89f
Merge remote-tracking branch 'origin/brennanb2025/acp-c1-timeline-ass…
brennanb2025 Oct 5, 2026
a08bbef
test(native-chat): Grok opens as a chat only behind the structured-ch…
brennanb2025 Oct 5, 2026
557a602
docs(acp): generic ACP comments say what holds for every agent, not Grok
brennanb2025 Oct 5, 2026
3b7d680
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d1-p…
brennanb2025 Oct 5, 2026
f5b6658
test(claude, codex): type the EOF-before-exit test's streams; the sup…
brennanb2025 Oct 5, 2026
76a91ab
feat(acp): a steer's cancel asks once and never ends the agent
brennanb2025 Oct 5, 2026
2a1cef2
chore(native-chat): keep the record store and recovery capsule under …
brennanb2025 Oct 5, 2026
58bb525
fix(acp): a repeated steer shares the cancel in flight; say what the …
brennanb2025 Oct 5, 2026
3b0c7ab
Merge origin/main into acp-a2-agent-registry (main #24862)
brennanb2025 Oct 5, 2026
42c2e2f
Merge acp-a2-agent-registry (main #24862) into acp-a3-wire
brennanb2025 Oct 5, 2026
636f6f1
Merge origin/main into acp-a6-provider-lifecycle (main #24862 landed)
brennanb2025 Oct 5, 2026
f77b590
Merge acp-c1-timeline-assembler into acp-c5-tool-interrupted
brennanb2025 Oct 5, 2026
105ba89
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-c5-t…
brennanb2025 Oct 5, 2026
162e973
Merge A3 #25159 (42c2e2fb532) into D3
brennanb2025 Oct 5, 2026
d3342e3
Merge A6 #25204 (636f6f1bdc4) into D3
brennanb2025 Oct 5, 2026
13f9ad8
Merge C5 #25181 (105ba896929) into D3
brennanb2025 Oct 5, 2026
75f36ac
Merge D2 #25090 (5c4a89f0613) into D3
brennanb2025 Oct 5, 2026
c862fe7
Merge D1 #24990 (58bb525f828) into D3
brennanb2025 Oct 5, 2026
3bc888b
Merge origin/main (e9ed75a5de1) into D3
brennanb2025 Oct 5, 2026
804c2bb
fix(native-chat): drop the stopDelivery the A3 merge doubled
brennanb2025 Oct 5, 2026
964db92
fix(acp): a steer's cancel asks Grok once and never ends it
brennanb2025 Oct 5, 2026
28b5036
fix(acp): a permission Grok asks with no prompt of Orca's running is …
brennanb2025 Oct 5, 2026
a6bd840
fix(acp): a Grok that dies while starting is reported with its own la…
brennanb2025 Oct 5, 2026
212d0d2
test: a Stop after a steer sends its own cancel; drop the import the …
brennanb2025 Oct 5, 2026
10673e9
test(native-chat): main's Stop-note test builds its turn context with…
brennanb2025 Oct 5, 2026
d47e26e
test(claude): say why the close test's fake child cast is safe
brennanb2025 Oct 5, 2026
bb082ea
Merge origin/main (a3bd6a6a1e7) into D3
brennanb2025 Oct 5, 2026
fc120f7
Merge origin/main into acp-a2-agent-registry (main squash of A1 #2499…
brennanb2025 Oct 5, 2026
fb8bcb8
test(native-chat): build the Stop-opened-turn test's identity and tur…
brennanb2025 Oct 5, 2026
7c4112f
Merge acp-a2-agent-registry (with origin/main d791421568c) into acp-a…
brennanb2025 Oct 5, 2026
f1e98c3
Merge origin/main into acp-a6-provider-lifecycle (main squash of #249…
brennanb2025 Oct 5, 2026
5c6a834
test(native-chat): build the Stop-opened-turn test's identity with th…
brennanb2025 Oct 5, 2026
e35bf18
test(ratchet): require src/main/provider-process now that it has landed
brennanb2025 Oct 5, 2026
0bb3919
Merge origin/main into acp-a2-agent-registry (main #25706, #25073)
brennanb2025 Oct 5, 2026
5f8deca
Merge brennanb2025/ratchet-provider-process-required (#25710) into ac…
brennanb2025 Oct 5, 2026
5b75928
test(native-chat): keep main's opaque-handle import in the Stop-opene…
brennanb2025 Oct 5, 2026
4e53819
Merge origin/main into acp-a6-provider-lifecycle (main #25706, #25073)
brennanb2025 Oct 5, 2026
1a5c70e
test(native-chat): keep main's opaque-handle import in the Stop-opene…
brennanb2025 Oct 5, 2026
ab066e6
Merge brennanb2025/ratchet-provider-process-required (#25710) into ac…
brennanb2025 Oct 5, 2026
a21812b
Merge acp-a2-agent-registry (main 9def4b9ba19 + ratchet fix #25710) i…
brennanb2025 Oct 5, 2026
1717828
Merge origin/main into acp-c5-tool-interrupted (main #25073 and the A…
brennanb2025 Oct 5, 2026
433c302
Merge brennanb2025/ratchet-provider-process-required (#25710) into ac…
brennanb2025 Oct 5, 2026
9dbd818
Merge origin/main into acp-a2-agent-registry (main's submission-posit…
brennanb2025 Oct 5, 2026
8e35d9a
Merge origin/main into acp-c5-tool-interrupted (main's submission-pos…
brennanb2025 Oct 5, 2026
5d011d7
Merge origin/main into acp-a6-provider-lifecycle (main's submission-p…
brennanb2025 Oct 5, 2026
547158c
Merge acp-a2-agent-registry (main e65bbc95cec) into acp-a3-wire
brennanb2025 Oct 5, 2026
1f7f7fa
feat(native-chat): record a fresh provider conversation that replaced…
brennanb2025 Oct 5, 2026
54c9f21
test(native-chat): build this stack's journal identities with main's …
brennanb2025 Oct 5, 2026
a6923e4
docs(acp): every reattach drops the agent's replay, not only for a ch…
brennanb2025 Oct 5, 2026
6312c30
Merge origin/main into acp-a2-agent-registry (main's duplicate-import…
brennanb2025 Oct 6, 2026
8e3331c
Merge acp-a2-agent-registry (main c6827fe02a5) into acp-a3-wire
brennanb2025 Oct 6, 2026
a26ef64
Merge origin/main into acp-a6-provider-lifecycle (main's duplicate-im…
brennanb2025 Oct 6, 2026
6130495
Merge origin/main into acp-c5-tool-interrupted (main's duplicate-impo…
brennanb2025 Oct 6, 2026
ab992ed
refactor(native-chat): store a replaced conversation flat; refuse it …
brennanb2025 Oct 6, 2026
ed9996e
Merge A3 #25159 (8e3331cd0e8) into D3
brennanb2025 Oct 6, 2026
528f256
Merge A6 #25204 (a26ef64fd9b) into D3
brennanb2025 Oct 6, 2026
c6ce409
Merge C5 #25181 (6130495f57b) into D3
brennanb2025 Oct 6, 2026
c95cc45
Merge origin/main (9756daeced4) into D3
brennanb2025 Oct 6, 2026
a31b528
refactor(native-chat): read hosts' structured agents from the app-she…
brennanb2025 Oct 6, 2026
2a57650
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-hand…
brennanb2025 Oct 6, 2026
5e84b09
Merge current main into agent registry branch
brennanb2025 Oct 6, 2026
6b1ed63
Merge 5e84b09c0d94 into acp-a3-wire
brennanb2025 Oct 6, 2026
e21865a
Merge 8127d9478218 into acp-a6-provider-lifecycle
brennanb2025 Oct 6, 2026
4dfc78f
Merge 8127d9478218 into acp-c5-tool-interrupted
brennanb2025 Oct 6, 2026
503e483
Merge 8127d9478218 into acp-c1a-timeline-transitions
brennanb2025 Oct 6, 2026
eba27a3
Use current provider handles in transition tests
brennanb2025 Oct 6, 2026
bbd96e1
Merge eba27a3c784e into acp-c1-timeline-assembler
brennanb2025 Oct 6, 2026
a7d8bcb
Use current provider handles in timeline fixtures
brennanb2025 Oct 6, 2026
63f79a9
Merge a7d8bcbb64fb into acp-d2-translation
brennanb2025 Oct 6, 2026
3b064e8
test(native-chat): prove replacement rows survive downgrade and re-up…
brennanb2025 Oct 6, 2026
503ebe4
Require the ACP directory in the runtime import check
brennanb2025 Oct 6, 2026
db71a89
Merge 08a970a3f117 into acp-a2-agent-registry
brennanb2025 Oct 6, 2026
a94f7ec
Merge db71a89d7438 into acp-a3-wire
brennanb2025 Oct 6, 2026
5df4db2
Merge 08a970a3f117 into acp-a6-provider-lifecycle
brennanb2025 Oct 6, 2026
85d1b66
Merge 08a970a3f117 into acp-c5-tool-interrupted
brennanb2025 Oct 6, 2026
383b0dc
Merge 08a970a3f117 into acp-c1a-timeline-transitions
brennanb2025 Oct 6, 2026
b5b0068
Merge 383b0dc2c420 into acp-c1-timeline-assembler
brennanb2025 Oct 6, 2026
bb93479
Merge b5b0068f885c into acp-d2-translation
brennanb2025 Oct 6, 2026
e7c0c5d
Merge origin/main (1b52be62550) into D3
brennanb2025 Oct 6, 2026
754fe5b
test(ratchet): require src/main/acp now that this PR lands it
brennanb2025 Oct 6, 2026
ba22513
Merge #25747 (3b064e88821) into D3
brennanb2025 Oct 6, 2026
541ecbd
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-hand…
brennanb2025 Oct 6, 2026
b6f57c3
feat(acp): a saved session the agent cannot reopen continues in a new…
brennanb2025 Oct 6, 2026
df8468e
Merge #25747 (541ecbd6835) into D3
brennanb2025 Oct 6, 2026
dbeef45
chore(acp): rewrap the acquire header comment
brennanb2025 Oct 6, 2026
bcff300
test(acp): a start closed while the agent reopens fails without openi…
brennanb2025 Oct 6, 2026
93ec93f
Merge A3 #25159 (a94f7ecd33e) into D3
brennanb2025 Oct 6, 2026
42b61b1
Merge A6 #25204 (5df4db2900c) into D3
brennanb2025 Oct 6, 2026
bbd9694
Merge C5 #25181 (85d1b669941) into D3
brennanb2025 Oct 6, 2026
2ac670f
Merge D2 #25090 (bb93479f1a2) into D3
brennanb2025 Oct 6, 2026
cc22251
Merge origin/main (5f7c8483e9c) into D3
brennanb2025 Oct 6, 2026
67e12c3
Merge current main and landed protocol client into translation branch
brennanb2025 Oct 6, 2026
82baab3
Merge origin/main (4e64fa9940f) into D3
brennanb2025 Oct 6, 2026
798fc3b
Let ACP connections own their supervised agent process
brennanb2025 Oct 6, 2026
613ca21
Preserve ACP cleanup evidence and isolate exit observers
brennanb2025 Oct 6, 2026
20f7f8a
Expose ACP cleanup observations and type the permission fixture
brennanb2025 Oct 6, 2026
9bd27f9
Merge landed timeline assembler and current main into ACP translation…
brennanb2025 Oct 6, 2026
e7212b2
Merge origin/main (1de3aa405f7) into D3
brennanb2025 Oct 6, 2026
0ef6d21
refactor(native-chat): the registered-agents capability lives in its …
brennanb2025 Oct 6, 2026
2de0157
Merge origin/main (9905765e3b8) into D3
brennanb2025 Oct 6, 2026
aebc700
Merge ACP-ALIGN #25810 (20f7f8a9531) into D3
brennanb2025 Oct 6, 2026
eae097e
Merge D2 #25090 (9bd27f9d16b) into D3
brennanb2025 Oct 6, 2026
03584f0
refactor(acp): one connection owns the Grok process and its protocol
brennanb2025 Oct 6, 2026
c23d1ce
Merge origin/main (4de9f9f85a8) into D3
brennanb2025 Oct 6, 2026
fa957dc
fix(acp): Grok signs in on its own machine with its API key or cached…
brennanb2025 Oct 6, 2026
bb32fe8
fix(acp): the adapter decides which of Grok's requests reach the person
brennanb2025 Oct 6, 2026
9c7c2eb
fix(acp): a plan Grok proposes shows as a plan, with no approval card
brennanb2025 Oct 6, 2026
7b8bdaa
fix(orchestration): worker-start opens a Grok worker in a terminal, a…
brennanb2025 Oct 6, 2026
606d1f6
fix(acp): a prompt answer Orca can't read ends the turn instead of ha…
brennanb2025 Oct 6, 2026
a652f15
fix(acp): send Grok's prompt-identity extension only to agents that e…
brennanb2025 Oct 6, 2026
06c7314
Merge origin/main (3ec38b8c6d1) into D3
brennanb2025 Oct 6, 2026
2f7da77
refactor(native-chat): the registered-agents capability lives in prot…
brennanb2025 Oct 6, 2026
b972838
test(acp): read the sign-in method with a schema, not a type assertion
brennanb2025 Oct 6, 2026
6aadfde
refactor(native-chat): composer transport and Stop control in their o…
brennanb2025 Oct 6, 2026
1c3f726
Merge origin/main (b75213100b5) into D3
brennanb2025 Oct 6, 2026
06dd7ea
test(native-chat): read registered agents by id, as main's structured…
brennanb2025 Oct 6, 2026
ccc2a8d
fix(acp): a first reopen warns when Grok forgets a chat that exchange…
brennanb2025 Oct 6, 2026
b194994
fix(acp): a start writes the warning row an earlier attach failure dr…
brennanb2025 Oct 6, 2026
c43cf4c
fix(acp): a question during a turn the agent began itself gets its ca…
brennanb2025 Oct 6, 2026
bc33e91
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 6, 2026
99a36ef
Merge commit '842c6c667a86d66d55b8cc3b2486ea6be5c56fcc' into brennanb…
brennanb2025 Oct 6, 2026
940e05a
test(native-chat): import the unfinished-work capture from the module…
brennanb2025 Oct 6, 2026
1daf4da
Merge commit '61c9a3aeab1f46035731da4e781cfc3ab2f71512' into brennanb…
brennanb2025 Oct 6, 2026
92b03e0
Merge commit 'b922342199bb4c816072deb42cc58cf755420488' into brennanb…
brennanb2025 Oct 6, 2026
9fd32b9
Merge commit '81a1968bc656c0faa3731859a64f29f3adbb0ed1' into brennanb…
brennanb2025 Oct 6, 2026
6544fc7
refactor(native-chat): keep the session host within its line budget a…
brennanb2025 Oct 6, 2026
7a712ac
test(codex): move the stdout-before-exit test into its own file
brennanb2025 Oct 6, 2026
eaa1a98
fix(acp): cancel a running turn before a close, dispose or quit ends …
brennanb2025 Oct 6, 2026
2dec239
Merge origin/main (6aa12c30ef5) into brennanb2025/acp-d3-grok
brennanb2025 Oct 6, 2026
48567d2
test(codex): pass resolveLaunchArgs in the stopped-send-order test so…
brennanb2025 Oct 6, 2026
b081e2d
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 6, 2026
22cb149
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 6, 2026
554d1a5
test(native-chat): run the close-aborts-start test on the Node runtim…
brennanb2025 Oct 6, 2026
0b592cc
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 6, 2026
27c6371
refactor(native-chat): the Stop control reads the outbox itself, so t…
brennanb2025 Oct 7, 2026
db981e9
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 7, 2026
a74cd83
Merge origin/main into brennanb2025/acp-d3-grok
brennanb2025 Oct 7, 2026
e1b7cf4
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 7, 2026
1d98732
Keep the session host under the line cap after main's two new delegates
brennanb2025 Oct 7, 2026
412d159
Merge remote-tracking branch 'origin/main' into brennanb2025/acp-d3-grok
brennanb2025 Oct 7, 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
1 change: 1 addition & 0 deletions config/scripts/vitest-sqlite-runtime-files.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export const SQLITE_RUNTIME_INCLUDE = [
'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-exit-ends-record.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-note-end.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-claude-stop-turn-end.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-close-aborts-start.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-close-verdict.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-codex-stop-note-end.test.ts',
'src/main/native-chat/agent-session-wire/structured-agent-session-codex-stop-row.test.ts',
Expand Down
6 changes: 6 additions & 0 deletions src/main/acp/acp-dialects/acp-dialect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export type AcpRequestPresentation = {
reply(response: AgentSessionPromptResponse | null): unknown
}

/** A request the client answers at once, asking no one: the reply, and a plan it carried for the
* chat's existing plan row. */
export type AcpRequestSettlement = { reply: unknown; plan?: string }

export type AcpBackgroundTaskUpdate = Pick<NativeChatBackgroundTaskBlock, 'taskId' | 'state'> &
Partial<Omit<NativeChatBackgroundTaskBlock, 'type' | 'taskId' | 'state'>> & {
/** Used only until a provider description is known. */
Expand Down Expand Up @@ -45,6 +49,8 @@ export type AcpDialect = {
notification?(method: string, params: unknown, at: number): AcpDialectNotification | undefined
contextWindow?(models: unknown): number | undefined
request?(method: string, params: unknown): AcpRequestPresentation | undefined
/** Requests answered at once instead of shown to the person. */
settleRequest?(method: string, params: unknown): AcpRequestSettlement | undefined
/** The provider's words in a `session/prompt` error answer, when its message is generic. */
promptErrorDetail?(error: AcpAgentError): string | undefined
/** The row for a failed turn the provider gave no words for. */
Expand Down
3 changes: 2 additions & 1 deletion src/main/acp/acp-dialects/grok-dialect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { z } from 'zod'
import { acpNotificationEnvelopeSchema } from '../acp-context-usage'
import type { AcpDialect, AcpDialectNotification } from './acp-dialect'
import { grokRequest } from './grok-requests'
import { grokRequest, grokSettleRequest } from './grok-requests'
import { grokBackgroundTaskNotification, grokToolBackgroundTasks } from './grok-background-tasks'

const tokenCount = z.number().int().nonnegative()
Expand Down Expand Up @@ -173,6 +173,7 @@ export const GROK_ACP_DIALECT: AcpDialect = {
return parsed.success ? parsed.data['x.ai/tool'].name : undefined
},
request: grokRequest,
settleRequest: grokSettleRequest,
toolBackgroundTasks: grokToolBackgroundTasks,
notification,
contextWindow,
Expand Down
52 changes: 20 additions & 32 deletions src/main/acp/acp-dialects/grok-requests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from '../../../shared/agent-session-question-answer'
import { AcpRpcError } from '../acp-errors'
import { pendingAcpResolution } from '../acp-timeline-requests'
import type { AcpRequestPresentation } from './acp-dialect'
import type { AcpRequestPresentation, AcpRequestSettlement } from './acp-dialect'

const questionRequestSchema = z.object({
sessionId: z.string(),
Expand Down Expand Up @@ -98,47 +98,35 @@ function questionRequest(params: unknown): AcpRequestPresentation {
}
}

function planRequest(params: unknown): AcpRequestPresentation {
/** What Grok hears once Orca has shown its plan: no approval is given for the person. */
const PLAN_SHOWN_FEEDBACK =
'Orca showed your plan to the user. Stop here and wait for their feedback or a request to implement it in a later turn.'

/** Grok's plan-mode exit: its plan goes to the chat's plan row and the gate is answered at once
* (`abandoned`), so the turn ends instead of waiting on an approval card. */
function settlePlanRequest(params: unknown): AcpRequestSettlement {
const parsed = planRequestSchema.safeParse(params)
if (!parsed.success) {
throw new AcpRpcError(-32602, 'Invalid agent plan approval request')
throw new AcpRpcError(-32602, 'Invalid agent plan request')
}
return {
body: {
kind: 'approval',
title: 'Approve plan',
detail: null,
subject: {
kind: 'plan',
text: parsed.data.planContent ?? 'The agent exited plan mode without writing a plan.'
},
options: [
{ id: 'approved', label: 'Approve plan' },
{ id: 'request_changes', label: 'Request changes' }
],
resolution: pendingAcpResolution
},
reply: (response) => {
if (response === null) {
return { outcome: 'abandoned' }
}
if (
response.kind !== 'option' ||
!['approved', 'request_changes'].includes(response.optionId)
) {
throw new AcpRpcError(-32602, 'Plan answer must select an offered option')
}
return { outcome: response.optionId }
}
reply: { outcome: 'abandoned', feedback: PLAN_SHOWN_FEEDBACK },
plan: parsed.data.planContent?.trim() || 'The agent exited plan mode without writing a plan.'
}
}

export function grokSettleRequest(
method: string,
params: unknown
): AcpRequestSettlement | undefined {
return ['_x.ai/exit_plan_mode', 'x.ai/exit_plan_mode'].includes(method)
? settlePlanRequest(params)
: undefined
}

export function grokRequest(method: string, params: unknown): AcpRequestPresentation | undefined {
if (['_x.ai/ask_user_question', 'x.ai/ask_user_question'].includes(method)) {
return questionRequest(params)
}
if (['_x.ai/exit_plan_mode', 'x.ai/exit_plan_mode'].includes(method)) {
return planRequest(params)
}
return undefined
}
76 changes: 76 additions & 0 deletions src/main/acp/acp-launch-specs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// How Orca starts each ACP agent, as data: adding an agent is one more row (plus a dialect when it
// speaks protocol extensions). Nothing outside `acp-dialects/` branches on an agent's name.

import { join } from 'node:path'
import {
ORCA_SCRUB_SAFE_LAUNCH_ENV,
ORCA_SCRUB_SAFE_PANE_ENV
} from '../../shared/agent-hook-scrub-safe-env'
import { AGENT_HOOK_RUNTIME_ENV_KEYS } from '../ipc/pty/host-env/spawn-env-keys'
import type { AcpDialect } from './acp-dialects/acp-dialect'
import { GROK_ACP_DIALECT } from './acp-dialects/grok-dialect'

export type AcpLaunchSpec = {
/** The Orca agent id (a `TuiAgent`), which names the agent's records and its catalog label. */
agent: string
command: string
/** Built per launch: `fullAccess` is the Agent Permissions setting's bypass posture. */
args(input: { fullAccess: boolean }): string[]
/** Overlaid on the child's environment. */
env: Readonly<Record<string, string>>
dialect: AcpDialect
/** The agent's own sign-in command, for a person to run when it reports auth required. */
loginCommand: readonly string[]
/** Which advertised sign-in method to use when the agent reports auth required, read from the
* environment it was launched with (on its own machine); none leaves it not signed in. */
authMethod?(input: {
advertised: readonly string[]
env: Readonly<Record<string, string>>
}): string | undefined
/** Variable naming the agent's config directory, pinned as each record's account home. */
accountHomeVariable: string
/** The config directory the agent uses when the variable is unset, under the user's home. */
defaultAccountHome(homePath: string): string
/** Where the agent installs its own binary, searched after PATH. */
installDirectories(accountHomePath: string): string[]
}

const GROK_LAUNCH_SPEC: AcpLaunchSpec = {
agent: 'grok',
command: 'grok',
// `--always-approve` only for full access, as the user's setting chooses.
args: ({ fullAccess }) => ['agent', ...(fullAccess ? ['--always-approve'] : []), 'stdio'],
env: {},
dialect: GROK_ACP_DIALECT,
loginCommand: ['grok', 'login'],
// An API key in Grok's own environment, else the sign-in Grok already cached; never interactive.
authMethod: ({ advertised, env }) =>
env.XAI_API_KEY?.trim() && advertised.includes('xai.api_key')
? 'xai.api_key'
: advertised.includes('cached_token')
? 'cached_token'
: undefined,
accountHomeVariable: 'GROK_HOME',
defaultAccountHome: (homePath) => join(homePath, '.grok'),
installDirectories: (accountHomePath) => [join(accountHomePath, 'bin')]
}

export const ACP_LAUNCH_SPECS: readonly AcpLaunchSpec[] = [GROK_LAUNCH_SPEC]

export function acpLaunchSpecFor(agent: string): AcpLaunchSpec | null {
return ACP_LAUNCH_SPECS.find((spec) => spec.agent === agent) ?? null
}

/**
* A pane's identity in the inherited environment would let the agent's own Orca status hooks
* report for this session too; the structured session is its one status producer.
*/
export const ACP_CHILD_ENV_TO_DELETE: readonly string[] = [
'ORCA_PANE_KEY',
'ORCA_TAB_ID',
'ORCA_WORKTREE_ID',
'ORCA_AGENT_LAUNCH_TOKEN',
ORCA_SCRUB_SAFE_PANE_ENV,
ORCA_SCRUB_SAFE_LAUNCH_ENV,
...AGENT_HOOK_RUNTIME_ENV_KEYS
]
9 changes: 9 additions & 0 deletions src/main/acp/acp-prompt-turns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ export class AcpPromptTurns {
this.current = undefined
}

/** Forgets a prompt the agent refused before its turn opened; false for any other. */
refuse(clientMessageId: string): boolean {
if (this.current?.clientMessageId !== clientMessageId || this.current.opened) {
return false
}
this.current = undefined
return true
}

start(turn: string, at: number): ProviderTimelineEvent[] {
const prompt = this.current
if (prompt?.turn !== turn || prompt.opened) {
Expand Down
65 changes: 65 additions & 0 deletions src/main/acp/acp-session-reopen-failure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// What takes over when an ACP agent cannot reopen the session a chat proved. A session this chat
// created and never exchanged a turn on, which the agent says it does not hold, is superseded:
// there was nothing to remember. Any other is replaced by a new session that names it, and the
// chat says once that the agent forgot: the row names the lost conversation, so a later start
// can tell whether it was ever written.

import { agentSessionFailureFact } from '../../shared/agent-session-failure'
import { agentSessionFailureWords } from '../../shared/agent-session-failure-words'
import type { AgentSessionProviderHandleLink } from '../../shared/agent-session-provider-handle'
import type { ProviderTimelineEvent } from '../native-chat/agent-session-timeline/provider-timeline-event'
import { AcpAuthRequiredError, AcpRpcError } from './acp-errors'
import type { AcpStructuredLaunch } from './acp-structured-launch-resolution'

/** ACP's "resource not found": the agent holds no session under the id this chat proved. */
const ACP_RESOURCE_NOT_FOUND = -32002
export const ACP_REOPEN_FAILED = 'ACP agent could not reopen its saved session; starting a new one'

/** The fields the new session's link carries; rethrows `error` when the start must fail instead. */
export function acpReopenTakeover(
error: unknown,
resume: NonNullable<AcpStructuredLaunch['resume']>,
start: { over: boolean; now: number; warn: (fields: { scope: string; error: unknown }) => void }
): Pick<AgentSessionProviderHandleLink, 'supersedesKey' | 'replaces'> {
// Signed out, or the start is over (Close, Stop, a lost agent): a new session would not help.
if (error instanceof AcpAuthRequiredError || start.over) {
throw error
}
if (
error instanceof AcpRpcError &&
error.code === ACP_RESOURCE_NOT_FOUND &&
resume.mayBeUnsaved()
) {
return { supersedesKey: resume.key }
}
start.warn({ scope: 'acp-restore-failed', error })
return { replaces: { key: resume.key, reason: 'restore-failed', replacedAt: start.now } }
}

/** The provider item key of the row saying the conversation under chain key `lostKey` was lost. */
export function acpSessionNotRestoredItem(lostKey: string): string {
return `session-not-restored:${lostKey}`
}

/** The one row a lost conversation gets: the agent no longer remembers what came before. */
export function acpSessionNotRestoredRow(
lostKey: string,
providerSessionId: string,
agentName: string
): ProviderTimelineEvent[] {
return [
{
type: 'item.update',
item: acpSessionNotRestoredItem(lostKey),
body: {
kind: 'status',
tone: 'warning',
...agentSessionFailureWords(agentSessionFailureFact('sessionNotRestored'), {
surface: 'row',
agentName
})
},
join: { thread: providerSessionId }
}
]
}
Loading
Loading