agents-can-communicate 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +3 -1
  2. package/bin/entrypoints/acc-bootstrap.mjs +6 -48
  3. package/bin/entrypoints/acc-claude-channel.mjs +47 -157
  4. package/docs/ADAPTER_AUTHORING.md +41 -10
  5. package/docs/ARCHITECTURE.md +23 -13
  6. package/docs/CAPABILITIES.md +19 -16
  7. package/docs/CLI.md +48 -13
  8. package/docs/CONCEPTS.md +5 -4
  9. package/docs/CONFIGURATION.md +18 -11
  10. package/docs/GETTING_STARTED.md +15 -12
  11. package/docs/GLOSSARY.md +2 -1
  12. package/docs/HOW_IT_WORKS.md +8 -4
  13. package/docs/PROTOCOL.md +25 -6
  14. package/docs/RELEASING.md +3 -2
  15. package/docs/SECURITY_MODEL.md +14 -1
  16. package/docs/TROUBLESHOOTING.md +64 -27
  17. package/docs/UPGRADING.md +49 -8
  18. package/docs/WHY_ACC.md +5 -3
  19. package/node_modules/@agents-can-communicate/adapter-antigravity/package.json +1 -1
  20. package/node_modules/@agents-can-communicate/adapter-antigravity/plugin/plugin.json +1 -1
  21. package/node_modules/@agents-can-communicate/adapter-claude-code/certification.json +14 -73
  22. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/certification-provenance.json +29 -71
  23. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.282-product-evidence.json +161 -0
  24. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.282.json +28 -0
  25. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/inbox-wake-2.1.282.json +44 -0
  26. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +5 -2
  27. package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +25 -30
  28. package/node_modules/@agents-can-communicate/adapter-claude-code/src/hooks.mjs +6 -0
  29. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-contract.mjs +10 -0
  30. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-delivery.mjs +254 -0
  31. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-endpoint.mjs +166 -0
  32. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-registry.mjs +71 -0
  33. package/node_modules/@agents-can-communicate/adapter-claude-code/src/inbox-settings.mjs +109 -0
  34. package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +25 -31
  35. package/node_modules/@agents-can-communicate/adapter-codex/package.json +1 -1
  36. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
  37. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +1 -1
  38. package/node_modules/@agents-can-communicate/adapter-grok/package.json +1 -1
  39. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +1 -1
  40. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  41. package/node_modules/@agents-can-communicate/adapter-sdk/src/events.mjs +16 -3
  42. package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +4 -3
  43. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +1 -1
  44. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-activation.mjs +4 -14
  45. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-delivery.mjs +23 -11
  46. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +5 -1
  47. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  48. package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +8 -6
  49. package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +8 -23
  50. package/node_modules/@agents-can-communicate/cli/src/install-delivery-consent.mjs +3 -4
  51. package/node_modules/@agents-can-communicate/cli/src/main.mjs +25 -3
  52. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/entry.mjs +7 -43
  53. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/launchers.mjs +5 -3
  54. package/node_modules/@agents-can-communicate/cli/src/managed-runtime/refresh.mjs +3 -4
  55. package/node_modules/@agents-can-communicate/cli/src/native-delivery-status.mjs +2 -2
  56. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  57. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +25 -2
  58. package/node_modules/@agents-can-communicate/core/src/status.mjs +19 -1
  59. package/node_modules/@agents-can-communicate/delivery-router/package.json +1 -1
  60. package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +24 -7
  61. package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
  62. package/node_modules/@agents-can-communicate/hook-runner/src/native-attempt.mjs +6 -8
  63. package/node_modules/@agents-can-communicate/hook-runner/src/native-binding.mjs +24 -11
  64. package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +1 -1
  65. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  66. package/node_modules/@agents-can-communicate/installer/src/apply.mjs +19 -5
  67. package/node_modules/@agents-can-communicate/installer/src/detect.mjs +3 -7
  68. package/node_modules/@agents-can-communicate/installer/src/index.mjs +4 -7
  69. package/node_modules/@agents-can-communicate/installer/src/native-activation.mjs +23 -61
  70. package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +7 -1
  71. package/node_modules/@agents-can-communicate/installer/src/plan.mjs +15 -5
  72. package/node_modules/@agents-can-communicate/installer/src/shell-bootstrap.mjs +10 -133
  73. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  74. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  75. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  76. package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +6 -1
  77. package/package.json +1 -1
  78. package/bin/acc-bootstrap.mjs +0 -7
  79. package/bin/acc-claude-channel.mjs +0 -10
  80. package/bin/entrypoints/claude-channel-binding.mjs +0 -46
  81. package/bin/entrypoints/claude-channel-stdio.mjs +0 -29
  82. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/.mcp.json +0 -8
  83. package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +0 -381
  84. package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +0 -232
  85. package/node_modules/@agents-can-communicate/installer/src/bootstrap-runtime.mjs +0 -150
@@ -172,13 +172,13 @@
172
172
  ]
173
173
  },
174
174
  {
175
- "id": "native-delivery-2-1-258",
175
+ "id": "native-delivery-2-1-282-inbox",
176
176
  "client": "claude-code",
177
- "version": "2.1.258",
177
+ "version": "2.1.282",
178
178
  "platform": "darwin-arm64",
179
- "observedAt": "2026-09-02T21:20:11.676Z",
180
- "fixture": "fixtures/delivery/claude-code-2.1.258.json",
181
- "sha256": "c68e84989c02fa0657d0a8669a774ab1e301088d8c7856346cc9739d0fbad228",
179
+ "observedAt": "2026-09-25T21:35:56.792Z",
180
+ "fixture": "fixtures/delivery/claude-code-2.1.282.json",
181
+ "sha256": "7e335f61df97edbd08304227be7335931dae3bc71e3dc639804b656ea2dae66a",
182
182
  "event": null,
183
183
  "tool": null,
184
184
  "claims": [
@@ -188,80 +188,38 @@
188
188
  "outcome": {
189
189
  "kind": "native-delivery-observed",
190
190
  "idle": "offered",
191
- "busy": "queued_after_turn",
191
+ "busy": "presented_between_tool_calls",
192
192
  "authority": "experimental",
193
193
  "limitations": [
194
- "captured on darwin-arm64 only; Linux and Windows remain uncaptured",
195
- "the vendor development-channel warning stayed visible and was accepted by the operator by hand",
196
- "the plugin .mcp.json must live in the marketplace source copy; the plugin cache copy alone is not read",
197
- "acc_reply routed through the spike's explicit tool call; the spike created no durable ACC answer record",
198
- "presentation after the busy turn was observed by the operator; the channel log records the write at 21:18:45Z and the explicit reply at 21:19:21Z"
199
- ]
200
- }
201
- },
202
- {
203
- "capability": "delivery.replyRoute",
204
- "result": "pass",
205
- "outcome": {
206
- "kind": "native-delivery-observed",
207
- "idle": "offered",
208
- "busy": "queued_after_turn",
209
- "authority": "experimental",
210
- "limitations": [
211
- "captured on darwin-arm64 only; Linux and Windows remain uncaptured",
212
- "the vendor development-channel warning stayed visible and was accepted by the operator by hand",
213
- "the plugin .mcp.json must live in the marketplace source copy; the plugin cache copy alone is not read",
214
- "acc_reply routed through the spike's explicit tool call; the spike created no durable ACC answer record",
215
- "presentation after the busy turn was observed by the operator; the channel log records the write at 21:18:45Z and the explicit reply at 21:19:21Z"
194
+ "Observed on darwin-arm64 with Claude Code 2.1.282 in the TUI, model Sonnet 5, auto permission mode, through a private candidate built from this branch and installed with an isolated ACC data home; the plugin registration in the real Claude config directory was restored byte for byte afterwards.",
195
+ "Every wake carried ACC wording and the message id only. The body reached the model through the UserPromptSubmit projection that each delivered wake fired, inside the untrusted acc-peer-message block.",
196
+ "An idle session started a turn with no user input. A wake sent while a Bash tool call ran was taken after that call returned and before the next one, and the turn continued.",
197
+ "The observed reply loop uses the installed acc reply CLI; native delivery.replyRoute remains false. The router reports a wake as outcome woken via claude-inbox and leaves the receipt queued until the hook's output carried the body, which records it offered via next-turn.",
198
+ "A repeated logical send kept its message id, took the durable path because the receipt was already acknowledged, and produced exactly one wake.",
199
+ "Two sessions in one workspace each bound their own inbox; a message addressed to one never woke the other.",
200
+ "An exited session left no registry entry; the next message stayed queued as recipient_unavailable.",
201
+ "A receiving session in bypassPermissions mode was not captured; Claude Code documents that such a session holds each wake whose sender does not attest bypass, and ACC never attests a mode.",
202
+ "Linux and native Windows remain uncaptured."
216
203
  ]
217
204
  }
218
205
  }
219
- ]
220
- },
221
- {
222
- "id": "native-delivery-2-1-260",
223
- "client": "claude-code",
224
- "version": "2.1.260",
225
- "platform": "darwin-arm64",
226
- "observedAt": "2026-09-04T03:41:29.688Z",
227
- "fixture": "fixtures/delivery/claude-code-2.1.260.json",
228
- "sha256": "7513d13b6dc1c6b485d899550f43ae3577cd99fca108f06691f7ad07daf06f03",
229
- "event": null,
230
- "tool": null,
231
- "claims": [
206
+ ],
207
+ "productEvidence": {
208
+ "fixture": "fixtures/delivery/claude-code-2.1.282-product-evidence.json",
209
+ "sha256": "1ac87ee547c6fdb38e0bdd62830f1fbd23bca51219a7ba906c7a0a1b2efd1346"
210
+ },
211
+ "historicalFixtures": [
232
212
  {
233
- "capability": "delivery.livePush",
234
- "result": "pass",
235
- "outcome": {
236
- "kind": "native-delivery-observed",
237
- "idle": "offered",
238
- "busy": "queued_after_turn",
239
- "authority": "experimental",
240
- "limitations": [
241
- "captured on darwin-arm64 only; Linux and Windows remain uncaptured",
242
- "the vendor development-channel warning stayed visible and was accepted by the operator by hand",
243
- "two ordinary sessions in one workspace, each bound to its own client process; the earlier 2.1.259 attempt is what exposed the channel binding another session identity, and this run is the verification of that fix",
244
- "duplicate was observed as one logical message id and one native offer: the repeated send took the durable path, so the channel was never asked to notify twice, and exactly one answer was recorded",
245
- "busy was observed by the operator: the running turn completed before the channel presented the message, and the session named that order in its own answer"
246
- ]
247
- }
213
+ "fixture": "fixtures/inbox-wake-2.1.282.json",
214
+ "sha256": "247836aefd6e446670f53e63ed3a29483a9124bfc7b38fc69ba7cd5e866fa2e1"
248
215
  },
249
216
  {
250
- "capability": "delivery.replyRoute",
251
- "result": "pass",
252
- "outcome": {
253
- "kind": "native-delivery-observed",
254
- "idle": "offered",
255
- "busy": "queued_after_turn",
256
- "authority": "experimental",
257
- "limitations": [
258
- "captured on darwin-arm64 only; Linux and Windows remain uncaptured",
259
- "the vendor development-channel warning stayed visible and was accepted by the operator by hand",
260
- "two ordinary sessions in one workspace, each bound to its own client process; the earlier 2.1.259 attempt is what exposed the channel binding another session identity, and this run is the verification of that fix",
261
- "duplicate was observed as one logical message id and one native offer: the repeated send took the durable path, so the channel was never asked to notify twice, and exactly one answer was recorded",
262
- "busy was observed by the operator: the running turn completed before the channel presented the message, and the session named that order in its own answer"
263
- ]
264
- }
217
+ "fixture": "fixtures/delivery/claude-code-2.1.258.json",
218
+ "sha256": "c68e84989c02fa0657d0a8669a774ab1e301088d8c7856346cc9739d0fbad228"
219
+ },
220
+ {
221
+ "fixture": "fixtures/delivery/claude-code-2.1.260.json",
222
+ "sha256": "7513d13b6dc1c6b485d899550f43ae3577cd99fca108f06691f7ad07daf06f03"
265
223
  }
266
224
  ]
267
225
  }
@@ -0,0 +1,161 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "source": "real-client-capture",
4
+ "client": "claude-code",
5
+ "phase": "product",
6
+ "clientVersion": "2.1.282",
7
+ "platform": "darwin-arm64",
8
+ "packageSha256": "fa81c55588988ed7274636c564a0adb5c442110f014f82e7a3f94da26fdd8891",
9
+ "startedAt": "2026-09-25T21:31:56.000Z",
10
+ "finishedAt": "2026-09-25T21:35:56.792Z",
11
+ "scenarioCount": 6,
12
+ "passedCount": 6,
13
+ "failedCount": 0,
14
+ "cleanup": {
15
+ "attempted": true,
16
+ "outcome": "passed",
17
+ "ownedProcesses": "stopped",
18
+ "temporaryState": "removed"
19
+ },
20
+ "scenarios": [
21
+ {
22
+ "caseId": "C01",
23
+ "outcome": "passed",
24
+ "startedAt": "2026-09-25T21:31:56.000Z",
25
+ "finishedAt": "2026-09-25T21:32:44.339Z",
26
+ "messageId": "message_EaLKeCerBFIR_o0gQpT4vQ",
27
+ "observations": [
28
+ {
29
+ "kind": "delivery",
30
+ "at": "2026-09-25T21:32:44.339Z",
31
+ "outcome": "woken"
32
+ },
33
+ {
34
+ "kind": "wake",
35
+ "at": "2026-09-25T21:31:56.373Z",
36
+ "outcome": "started-turn"
37
+ },
38
+ {
39
+ "kind": "projection",
40
+ "at": "2026-09-25T21:31:56.808Z",
41
+ "outcome": "body-shown"
42
+ },
43
+ {
44
+ "kind": "offer",
45
+ "at": "2026-09-25T21:31:56.724Z",
46
+ "outcome": "next-turn"
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ "caseId": "C02",
52
+ "outcome": "passed",
53
+ "startedAt": "2026-09-25T21:33:05.000Z",
54
+ "finishedAt": "2026-09-25T21:34:19.560Z",
55
+ "messageId": "message_YFDLjj4jtNLDsC67GV9Y1g",
56
+ "observations": [
57
+ {
58
+ "kind": "delivery",
59
+ "at": "2026-09-25T21:34:19.560Z",
60
+ "outcome": "woken"
61
+ },
62
+ {
63
+ "kind": "wake",
64
+ "at": "2026-09-25T21:33:05.316Z",
65
+ "outcome": "between-tool-calls"
66
+ },
67
+ {
68
+ "kind": "projection",
69
+ "at": "2026-09-25T21:33:17.285Z",
70
+ "outcome": "body-shown"
71
+ },
72
+ {
73
+ "kind": "offer",
74
+ "at": "2026-09-25T21:33:17.207Z",
75
+ "outcome": "next-turn"
76
+ }
77
+ ]
78
+ },
79
+ {
80
+ "caseId": "C03",
81
+ "outcome": "passed",
82
+ "startedAt": "2026-09-25T21:31:56.000Z",
83
+ "finishedAt": "2026-09-25T21:32:44.370Z",
84
+ "messageId": "message_EaLKeCerBFIR_o0gQpT4vQ",
85
+ "observations": [
86
+ {
87
+ "kind": "answer",
88
+ "at": "2026-09-25T21:32:16.968Z",
89
+ "outcome": "recorded"
90
+ },
91
+ {
92
+ "kind": "receipt",
93
+ "at": "2026-09-25T21:32:16.968Z",
94
+ "outcome": "acknowledged"
95
+ }
96
+ ]
97
+ },
98
+ {
99
+ "caseId": "C04",
100
+ "outcome": "passed",
101
+ "startedAt": "2026-09-25T21:34:28.000Z",
102
+ "finishedAt": "2026-09-25T21:34:56.510Z",
103
+ "messageId": "message_zzo8wi26wFyq8hfGvAsWIw",
104
+ "observations": [
105
+ {
106
+ "kind": "logical-message",
107
+ "at": "2026-09-25T21:34:56.510Z",
108
+ "outcome": "same-message-id"
109
+ },
110
+ {
111
+ "kind": "wake",
112
+ "at": "2026-09-25T21:34:28.385Z",
113
+ "outcome": "delivered-once"
114
+ }
115
+ ]
116
+ },
117
+ {
118
+ "caseId": "C05",
119
+ "outcome": "passed",
120
+ "startedAt": "2026-09-25T21:35:44.000Z",
121
+ "finishedAt": "2026-09-25T21:35:56.792Z",
122
+ "messageId": "message_owEZDIuuC0KygynZk-b0Hg",
123
+ "observations": [
124
+ {
125
+ "kind": "delivery",
126
+ "at": "2026-09-25T21:35:56.792Z",
127
+ "outcome": "queued"
128
+ },
129
+ {
130
+ "kind": "client",
131
+ "outcome": "exited",
132
+ "at": "2026-09-25T21:35:47.000Z"
133
+ }
134
+ ]
135
+ },
136
+ {
137
+ "caseId": "C06",
138
+ "outcome": "passed",
139
+ "startedAt": "2026-09-25T21:35:05.000Z",
140
+ "finishedAt": "2026-09-25T21:35:34.783Z",
141
+ "messageId": "message_tDm0K7jQWFVKmVhs_t_29Q",
142
+ "observations": [
143
+ {
144
+ "kind": "delivery",
145
+ "at": "2026-09-25T21:35:34.783Z",
146
+ "outcome": "woken"
147
+ },
148
+ {
149
+ "kind": "wake",
150
+ "at": "2026-09-25T21:35:05.754Z",
151
+ "outcome": "started-turn"
152
+ },
153
+ {
154
+ "kind": "other-session",
155
+ "at": "2026-09-25T21:35:34.783Z",
156
+ "outcome": "not-woken"
157
+ }
158
+ ]
159
+ }
160
+ ]
161
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "client": "claude-code",
3
+ "version": "2.1.282",
4
+ "platform": "darwin-arm64",
5
+ "observedAt": "2026-09-25T21:35:56.792Z",
6
+ "capability": "native_delivery",
7
+ "result": "pass",
8
+ "fixture": "claude-code-2.1.282",
9
+ "launchMode": "ordinary-command-with-installed-hooks",
10
+ "protocolContract": "claude-code-inbox-socket-v1",
11
+ "idle": "offered",
12
+ "busy": "presented_between_tool_calls",
13
+ "reply": "routed",
14
+ "duplicate": "same_message_id",
15
+ "fallback": "queued",
16
+ "limitations": [
17
+ "Observed on darwin-arm64 with Claude Code 2.1.282 in the TUI, model Sonnet 5, auto permission mode, through a private candidate built from this branch and installed with an isolated ACC data home; the plugin registration in the real Claude config directory was restored byte for byte afterwards.",
18
+ "Every wake carried ACC wording and the message id only. The body reached the model through the UserPromptSubmit projection that each delivered wake fired, inside the untrusted acc-peer-message block.",
19
+ "An idle session started a turn with no user input. A wake sent while a Bash tool call ran was taken after that call returned and before the next one, and the turn continued.",
20
+ "The observed reply loop uses the installed acc reply CLI; native delivery.replyRoute remains false. The router reports a wake as outcome woken via claude-inbox and leaves the receipt queued until the hook's output carried the body, which records it offered via next-turn.",
21
+ "A repeated logical send kept its message id, took the durable path because the receipt was already acknowledged, and produced exactly one wake.",
22
+ "Two sessions in one workspace each bound their own inbox; a message addressed to one never woke the other.",
23
+ "An exited session left no registry entry; the next message stayed queued as recipient_unavailable.",
24
+ "A receiving session in bypassPermissions mode was not captured; Claude Code documents that such a session holds each wake whose sender does not attest bypass, and ACC never attests a mode.",
25
+ "Linux and native Windows remain uncaptured."
26
+ ],
27
+ "packageSha256": "fa81c55588988ed7274636c564a0adb5c442110f014f82e7a3f94da26fdd8891"
28
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "note": "Transport capture of the Claude Code session inbox, run on Claude Code 2.1.282, macOS arm64, 2026-09-25, before any ACC code used it. A receiving interactive TUI session ran from the real executable in auto mode with ACC 0.7.0 hooks installed and no Channel. A separate process, not a child of the receiver, wrote one JSON line per connection to the socket the session registry named, with no auth line and no token. Session ids, paths, pids and message text are redacted; outcomes are read from the receiver's own transcript records and ACC's store events.",
3
+ "clientVersion": "2.1.282",
4
+ "platform": "darwin-arm64",
5
+ "observedAt": "2026-09-25T19:40:41.000Z",
6
+ "registry": {
7
+ "file": "<config>/sessions/<pid>.json",
8
+ "fieldsRead": ["pid", "sessionId", "messagingSocketPath"],
9
+ "sessionIdEqualsHookSessionId": true,
10
+ "statusValuesSeen": ["idle", "busy", "waiting"]
11
+ },
12
+ "frame": {
13
+ "shape": { "type": "user", "message": { "role": "user", "content": "<text>" }, "msg_id": "<id>" },
14
+ "authLine": "absent",
15
+ "socketAnswer": "none"
16
+ },
17
+ "idle": {
18
+ "result": "new turn started without user input",
19
+ "transcriptRecord": "user, isMeta, origin.kind peer, verifiedPeerPid set",
20
+ "userPromptSubmitFired": true
21
+ },
22
+ "busy": {
23
+ "result": "queued while a Bash tool call ran; delivered after its tool_result, before the next tool call; the turn continued",
24
+ "transcriptRecord": "attachment queued_command, origin.kind peer",
25
+ "userPromptSubmitFired": true
26
+ },
27
+ "accWake": {
28
+ "frameCarried": "ACC wording and the message id only",
29
+ "idle": "the beforeTurn projection showed the queued ACC question in its untrusted block; the model answered with acc reply; the store recorded the answer and acknowledged",
30
+ "midTurn": "the same projection arrived with the UserPromptSubmit that the mid-turn frame fired; the model answered after its running commands",
31
+ "offerRecordedAs": "next-turn"
32
+ },
33
+ "inbound": {
34
+ "promptingReceiverUnattestedSender": "delivered",
35
+ "promptingReceiverSenderAttestsBypass": "held with an approval dialog; registry status waiting; deny dropped it",
36
+ "bypassReceiver": "unobserved"
37
+ },
38
+ "burst": {
39
+ "framesFromSeparateProcesses": 6,
40
+ "delivered": 6,
41
+ "queuedFramesDeliveredInOneTurn": 5,
42
+ "userPromptSubmitPerFrame": true
43
+ }
44
+ }
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@agents-can-communicate/adapter-claude-code",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./src/adapter.mjs",
8
- "./channel": "./src/channel.mjs"
8
+ "./inbox-delivery": "./src/inbox-delivery.mjs"
9
9
  },
10
10
  "files": [
11
11
  "certification.json",
@@ -18,6 +18,9 @@
18
18
  "fixtures/delivery/claude-code-2.1.252.json",
19
19
  "fixtures/delivery/claude-code-2.1.258.json",
20
20
  "fixtures/delivery/claude-code-2.1.260.json",
21
+ "fixtures/delivery/claude-code-2.1.282.json",
22
+ "fixtures/delivery/claude-code-2.1.282-product-evidence.json",
23
+ "fixtures/inbox-wake-2.1.282.json",
21
24
  "src/",
22
25
  "plugin/"
23
26
  ]
@@ -2,18 +2,15 @@ import { defineAdapter, projectContext, projectContextResult }
2
2
  from "@agents-can-communicate/adapter-sdk";
3
3
  import certification from "../certification.json" with { type: "json" };
4
4
 
5
- import { PROTOCOL_CONTRACT } from "./channel.mjs";
6
5
  import { denyOutcome, injectOutcome, injectStartOwnerOutcome, normalizeClaudeHook } from "./hooks.mjs";
6
+ import { MIN_VERSION, PROTOCOL_CONTRACT, bindNativeSession, offerMessage, planNativeActivation,
7
+ probeNativeDelivery, refreshNativeSession, retireNativeSession } from "./inbox-delivery.mjs";
7
8
  import { planClaudeInstall, detectClaude, installClaudePlugin, uninstallClaudePlugin } from "./install.mjs";
8
- import { bindNativeSession, offerMessage, planNativeActivation, probeNativeDelivery, routeReply }
9
- from "./native-delivery.mjs";
10
9
 
11
10
  export const CLAUDE_CODE_VERSION = "2.1.233";
12
- export const CLAUDE_CHANNEL_MINIMUM = "2.1.258";
13
11
  export const CLAUDE_DELIVERY_FALLBACK = Object.freeze({
14
- diagnostic: "Claude Code native delivery requires client-side Channels activation; "
15
- + "a successful bootstrap or connected ACC MCP server does not prove inbound delivery "
16
- + "is enabled. Messages remain durable for certified next-turn delivery or acc inbox",
12
+ diagnostic: `Claude Code live delivery wakes a session through its inbox socket from ${MIN_VERSION}; `
13
+ + "fallback: next-turn hooks or acc inbox",
17
14
  });
18
15
 
19
16
  /**
@@ -25,7 +22,8 @@ export const CLAUDE_DELIVERY_FALLBACK = Object.freeze({
25
22
  * and a parent/child mapping claimed without observation is the kind of thing
26
23
  * that quietly maps every child onto its parent. `startupInjection` and
27
24
  * `safePointInjection` were not exercised - only the before-turn path was.
28
- * Native live delivery and reply routing are not certified for this harness.
25
+ * Native live delivery is the inbox wake, certified from 2.1.282 on
26
+ * darwin-arm64; reply routing through the transport is not claimed.
29
27
  */
30
28
  export function createClaudeCodeAdapter() {
31
29
  return defineAdapter({
@@ -44,28 +42,22 @@ export function createClaudeCodeAdapter() {
44
42
  context: { beforeTurnInjection: true },
45
43
  // PreToolUse denied both a Write and a Bash call; neither ran.
46
44
  guards: { beforeWrite: true, beforeShell: true },
47
- // nextTurn is the certified 2.1.233 hook projection; livePush and
48
- // replyRoute rest on the 2.1.258 Channel capture and the native contract
49
- // below. effectiveCapabilities() carries each of those captures forward
50
- // to later clients; the native contract is the separate live rule.
51
- delivery: { nextTurn: true, livePush: true, replyRoute: true },
45
+ // nextTurn is the certified 2.1.233 hook projection. livePush rests on
46
+ // the 2.1.282 product capture of the inbox wake; the reply is the
47
+ // ordinary `acc reply` every adapter has, so replyRoute stays false.
48
+ delivery: { nextTurn: true, livePush: true },
52
49
  },
53
- // The first passing capture is the shipped minimum; the research lower
54
- // bound (2.1.80) is documented but not admitted without its own capture.
55
- //
56
- // The 2.1.260 release capture is passing evidence beside this, deliberately
57
- // not a second anchor: an anchor is the minimum's proof, one per platform,
58
- // and this contract has no maximum precisely so a newer stable client is
59
- // admitted by probe and a generation-bound handshake instead of by another
60
- // anchor. That capture is what exercised the rule - every branch observed
61
- // on 2.1.260 while the minimum stayed here. Two minor versions of drift,
62
- // served without a capture at either of them, is the rule working.
50
+
51
+ // The first passing capture is the minimum, and there is no maximum: a
52
+ // newer stable client is admitted by the probe and the per-session
53
+ // handshake. The offer is a wake; see src/inbox-delivery.mjs.
63
54
  nativeDelivery: {
64
- minimumByPlatform: { "darwin-arm64": CLAUDE_CHANNEL_MINIMUM },
65
- anchors: [{ platform: "darwin-arm64", version: CLAUDE_CHANNEL_MINIMUM,
66
- protocolContract: PROTOCOL_CONTRACT }],
55
+ minimumByPlatform: { "darwin-arm64": MIN_VERSION },
56
+ anchors: [{ platform: "darwin-arm64", version: MIN_VERSION, protocolContract: PROTOCOL_CONTRACT }],
67
57
  knownBad: [],
68
- activationKinds: ["shell-bootstrap", "native-config"],
58
+ activationKinds: ["native-service"],
59
+ policySource: "installation-record",
60
+ offerKind: "wake",
69
61
  },
70
62
 
71
63
  startSession: async () => ({ ok: true, changes: [], diagnostics: [] }),
@@ -75,8 +67,7 @@ export function createClaudeCodeAdapter() {
75
67
 
76
68
  planInstall: context => planClaudeInstall(context),
77
69
  detect: context => detectClaude(context),
78
- install: context => installClaudePlugin({ ...context,
79
- livePolicy: context.livePolicy ?? "off" }),
70
+ install: context => installClaudePlugin(context),
80
71
  uninstall: context => uninstallClaudePlugin(context),
81
72
 
82
73
  doctor: async context => {
@@ -85,6 +76,9 @@ export function createClaudeCodeAdapter() {
85
76
  ...detected.diagnostics,
86
77
  "hook payloads captured from Claude Code 2.1.233",
87
78
  CLAUDE_DELIVERY_FALLBACK.diagnostic,
79
+ // Claude Code's own inbound control decides whether a wake reaches the
80
+ // model; ACC never attests a permission mode. Said only when it matters.
81
+ ...(detected.inboundDelivery.diagnostic === null ? [] : [detected.inboundDelivery.diagnostic]),
88
82
  // SessionEnd is advisory and cannot summarise a conversation that has
89
83
  // already stopped, so the handoff is written from Stop or the skill.
90
84
  "handoff is written while the model is active, not at SessionEnd",
@@ -94,8 +88,9 @@ export function createClaudeCodeAdapter() {
94
88
  probeNativeDelivery,
95
89
  planNativeActivation,
96
90
  bindNativeSession,
91
+ refreshNativeSession,
92
+ retireNativeSession,
97
93
  offerMessage,
98
- routeReply,
99
94
 
100
95
  denyOutcome,
101
96
  injectOutcome,
@@ -50,6 +50,12 @@ export function normalizeClaudeHook(payload) {
50
50
  parentSessionId: typeof payload.agent_id === "string" ? payload.session_id : null,
51
51
  tool,
52
52
  targets: writeTargets(tool, payload.tool_input),
53
+ // Documented as conditional; SessionStart carried none on 2.1.233.
54
+ permissionMode: typeof payload.permission_mode === "string" && payload.permission_mode !== ""
55
+ ? payload.permission_mode : null,
56
+ // SessionEnd says why: "clear", "logout", "prompt_input_exit", "other".
57
+ endReason: event === "SessionEnd" && typeof payload.reason === "string" && payload.reason !== ""
58
+ ? payload.reason : null,
53
59
  });
54
60
  }
55
61
 
@@ -0,0 +1,10 @@
1
+ // The facts of the inbox transport every module of it shares, kept apart so
2
+ // the endpoint record and the delivery methods import them without a cycle.
3
+
4
+ export const PROTOCOL_CONTRACT = "claude-code-inbox-socket-v1";
5
+ // The first release the inbox wake was captured on. 2.1.224 binds the socket,
6
+ // but only 2.1.282 was observed firing UserPromptSubmit for a delivered frame,
7
+ // and that is what brings the message body in with the wake.
8
+ export const MIN_VERSION = "2.1.282";
9
+ export const INBOX_MODES = Object.freeze(["livePush", "idleWake", "busyQueue"]);
10
+ export const TRANSPORT = "claude-inbox";