agents-can-communicate 0.1.18 → 0.3.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 (155) hide show
  1. package/README.md +87 -69
  2. package/SECURITY.md +31 -0
  3. package/bin/acc-bootstrap.mjs +56 -0
  4. package/bin/acc-claude-channel.mjs +177 -0
  5. package/bin/acc-hook.mjs +94 -12
  6. package/bin/acc-mcp.mjs +6 -2
  7. package/bin/acc.mjs +13 -3
  8. package/docs/ADAPTER_AUTHORING.md +204 -0
  9. package/docs/ARCHITECTURE.md +131 -0
  10. package/docs/CAPABILITIES.md +117 -214
  11. package/docs/CLI.md +164 -0
  12. package/docs/CONCEPTS.md +134 -0
  13. package/docs/CONFIGURATION.md +147 -0
  14. package/docs/DESIGN_DECISIONS.md +89 -0
  15. package/docs/GETTING_STARTED.md +145 -0
  16. package/docs/GLOSSARY.md +26 -0
  17. package/docs/HOW_IT_WORKS.md +277 -0
  18. package/docs/MCP.md +94 -0
  19. package/docs/PROTOCOL.md +200 -0
  20. package/docs/RELEASING.md +115 -0
  21. package/docs/SECURITY_MODEL.md +131 -0
  22. package/docs/TROUBLESHOOTING.md +108 -0
  23. package/docs/WHY_ACC.md +61 -0
  24. package/docs/index.md +44 -0
  25. package/node_modules/@agents-can-communicate/adapter-claude-code/certification.json +228 -0
  26. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse-Edit.json +19 -0
  27. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse.json +17 -0
  28. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionEnd.json +8 -0
  29. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionStart.json +7 -0
  30. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/UserPromptSubmit.json +9 -0
  31. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/certification-provenance.json +269 -0
  32. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.252.json +21 -0
  33. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.258.json +23 -0
  34. package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.260.json +23 -0
  35. package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +13 -2
  36. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/.mcp.json +8 -0
  37. package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +22 -22
  38. package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +45 -5
  39. package/node_modules/@agents-can-communicate/adapter-claude-code/src/channel.mjs +377 -0
  40. package/node_modules/@agents-can-communicate/adapter-claude-code/src/install.mjs +27 -7
  41. package/node_modules/@agents-can-communicate/adapter-claude-code/src/native-delivery.mjs +229 -0
  42. package/node_modules/@agents-can-communicate/adapter-codex/certification.json +150 -0
  43. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/PreToolUse.json +14 -0
  44. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionEnd.json +7 -0
  45. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionStart.json +9 -0
  46. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/UserPromptSubmit.json +10 -0
  47. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/certification-provenance.json +199 -0
  48. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/delivery/codex-cli-0.152.0.json +21 -0
  49. package/node_modules/@agents-can-communicate/adapter-codex/fixtures/delivery/codex-cli-0.152.1-remote-workspace.json +25 -0
  50. package/node_modules/@agents-can-communicate/adapter-codex/package.json +11 -2
  51. package/node_modules/@agents-can-communicate/adapter-codex/plugin/.codex-plugin/plugin.json +1 -1
  52. package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +22 -22
  53. package/node_modules/@agents-can-communicate/adapter-codex/src/adapter.mjs +54 -12
  54. package/node_modules/@agents-can-communicate/adapter-codex/src/app-server-client.mjs +121 -0
  55. package/node_modules/@agents-can-communicate/adapter-codex/src/native-delivery.mjs +151 -0
  56. package/node_modules/@agents-can-communicate/adapter-codex/src/ws-json-rpc.mjs +192 -0
  57. package/node_modules/@agents-can-communicate/adapter-gemini-cli/certification.json +68 -0
  58. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
  59. package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +22 -22
  60. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeAgent-0.57.0.json +8 -0
  61. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool-0.57.0.json +12 -0
  62. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool-shell-0.57.0.json +12 -0
  63. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionEnd-0.57.0.json +8 -0
  64. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionStart-0.57.0.json +8 -0
  65. package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/certification-provenance.json +293 -0
  66. package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +8 -1
  67. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/adapter.mjs +31 -13
  68. package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/install.mjs +4 -2
  69. package/node_modules/@agents-can-communicate/adapter-grok/certification.json +3 -0
  70. package/node_modules/@agents-can-communicate/adapter-grok/package.json +2 -1
  71. package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +22 -22
  72. package/node_modules/@agents-can-communicate/adapter-grok/src/adapter.mjs +11 -9
  73. package/node_modules/@agents-can-communicate/adapter-kimi/certification.json +52 -0
  74. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Bash.json +12 -0
  75. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Write.json +12 -0
  76. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionHeartbeat.json +7 -0
  77. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionStart.json +9 -0
  78. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/UserPromptSubmit.json +8 -0
  79. package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/certification-provenance.json +66 -0
  80. package/node_modules/@agents-can-communicate/adapter-kimi/package.json +8 -1
  81. package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +22 -22
  82. package/node_modules/@agents-can-communicate/adapter-kimi/src/adapter.mjs +7 -3
  83. package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
  84. package/node_modules/@agents-can-communicate/adapter-sdk/src/capabilities.mjs +52 -18
  85. package/node_modules/@agents-can-communicate/adapter-sdk/src/certification.mjs +158 -0
  86. package/node_modules/@agents-can-communicate/adapter-sdk/src/context-projector.mjs +36 -17
  87. package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +9 -1
  88. package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +7 -2
  89. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-activation.mjs +76 -0
  90. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-delivery.mjs +202 -0
  91. package/node_modules/@agents-can-communicate/adapter-sdk/src/native-vocabulary.mjs +101 -0
  92. package/node_modules/@agents-can-communicate/adapter-sdk/src/session-binding.mjs +28 -4
  93. package/node_modules/@agents-can-communicate/cli/package.json +1 -1
  94. package/node_modules/@agents-can-communicate/cli/src/args.mjs +12 -31
  95. package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +70 -5
  96. package/node_modules/@agents-can-communicate/cli/src/help.mjs +2 -5
  97. package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +111 -12
  98. package/node_modules/@agents-can-communicate/cli/src/main.mjs +100 -121
  99. package/node_modules/@agents-can-communicate/core/package.json +1 -1
  100. package/node_modules/@agents-can-communicate/core/src/attention.mjs +106 -0
  101. package/node_modules/@agents-can-communicate/core/src/conversations.mjs +276 -0
  102. package/node_modules/@agents-can-communicate/core/src/delivery-bindings.mjs +131 -0
  103. package/node_modules/@agents-can-communicate/core/src/finish-retries.mjs +97 -0
  104. package/node_modules/@agents-can-communicate/core/src/inbox.mjs +91 -107
  105. package/node_modules/@agents-can-communicate/core/src/index.mjs +3 -3
  106. package/node_modules/@agents-can-communicate/core/src/intents.mjs +0 -1
  107. package/node_modules/@agents-can-communicate/core/src/ports.mjs +2 -1
  108. package/node_modules/@agents-can-communicate/core/src/receipts.mjs +109 -0
  109. package/node_modules/@agents-can-communicate/core/src/service.mjs +21 -10
  110. package/node_modules/@agents-can-communicate/core/src/sessions.mjs +22 -20
  111. package/node_modules/@agents-can-communicate/core/src/status.mjs +11 -9
  112. package/node_modules/@agents-can-communicate/core/src/sync.mjs +3 -294
  113. package/node_modules/@agents-can-communicate/delivery-router/package.json +12 -0
  114. package/node_modules/@agents-can-communicate/delivery-router/src/index.mjs +1 -0
  115. package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +131 -0
  116. package/node_modules/@agents-can-communicate/hook-runner/package.json +4 -2
  117. package/node_modules/@agents-can-communicate/hook-runner/src/client-version.mjs +20 -0
  118. package/node_modules/@agents-can-communicate/hook-runner/src/native-binding.mjs +90 -0
  119. package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +190 -105
  120. package/node_modules/@agents-can-communicate/installer/package.json +1 -1
  121. package/node_modules/@agents-can-communicate/installer/src/apply.mjs +70 -10
  122. package/node_modules/@agents-can-communicate/installer/src/bootstrap-runtime.mjs +144 -0
  123. package/node_modules/@agents-can-communicate/installer/src/detect.mjs +89 -5
  124. package/node_modules/@agents-can-communicate/installer/src/index.mjs +10 -2
  125. package/node_modules/@agents-can-communicate/installer/src/native-activation.mjs +161 -0
  126. package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +112 -12
  127. package/node_modules/@agents-can-communicate/installer/src/plan.mjs +54 -2
  128. package/node_modules/@agents-can-communicate/installer/src/shell-bootstrap.mjs +210 -0
  129. package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
  130. package/node_modules/@agents-can-communicate/mcp-server/src/input-validator.mjs +79 -0
  131. package/node_modules/@agents-can-communicate/mcp-server/src/resources.mjs +23 -28
  132. package/node_modules/@agents-can-communicate/mcp-server/src/server.mjs +102 -72
  133. package/node_modules/@agents-can-communicate/mcp-server/src/tools.mjs +54 -97
  134. package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
  135. package/node_modules/@agents-can-communicate/protocol/src/config.mjs +1 -1
  136. package/node_modules/@agents-can-communicate/protocol/src/conversations.mjs +64 -0
  137. package/node_modules/@agents-can-communicate/protocol/src/fields.mjs +17 -0
  138. package/node_modules/@agents-can-communicate/protocol/src/index.mjs +4 -1
  139. package/node_modules/@agents-can-communicate/protocol/src/schema.mjs +64 -90
  140. package/node_modules/@agents-can-communicate/protocol/src/states.mjs +13 -40
  141. package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
  142. package/node_modules/@agents-can-communicate/storage-filesystem/src/active-journal.mjs +230 -0
  143. package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +77 -28
  144. package/node_modules/@agents-can-communicate/storage-filesystem/src/identity.mjs +1 -1
  145. package/node_modules/@agents-can-communicate/storage-filesystem/src/journal.mjs +83 -35
  146. package/node_modules/@agents-can-communicate/storage-filesystem/src/retention.mjs +112 -0
  147. package/node_modules/@agents-can-communicate/storage-filesystem/src/safe-file.mjs +18 -8
  148. package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +68 -26
  149. package/node_modules/@agents-can-communicate/storage-filesystem/src/writer-mutex.mjs +113 -35
  150. package/package.json +20 -1
  151. package/node_modules/@agents-can-communicate/core/src/communication.mjs +0 -334
  152. package/node_modules/@agents-can-communicate/core/src/message-signals.mjs +0 -41
  153. package/node_modules/@agents-can-communicate/core/src/notify.mjs +0 -95
  154. package/node_modules/@agents-can-communicate/core/src/tasks.mjs +0 -244
  155. package/node_modules/@agents-can-communicate/core/src/workstreams.mjs +0 -109
@@ -0,0 +1,277 @@
1
+ # How ACC works
2
+
3
+ ACC is a local communication layer around AI sessions that the user opened independently.
4
+ It gives those sessions a shared set of coordination facts without giving ACC ownership of
5
+ their prompts, permissions, processes, or work.
6
+
7
+ This page follows one interaction from client startup to an acknowledged answer. It is the
8
+ engineering tour; [Protocol](PROTOCOL.md) is the normative record contract and
9
+ [Architecture](ARCHITECTURE.md) is the package-level reference.
10
+
11
+ ## The whole system in one picture
12
+
13
+ ```mermaid
14
+ flowchart LR
15
+ U["human direction and authority"] --> A["independent session A"]
16
+ U --> B["independent session B"]
17
+ A --> X["CLI, MCP, or adapter hook"]
18
+ X --> C["vendor-neutral core"]
19
+ C <--> S[("filesystem store outside the repository")]
20
+ C --> Y["B adapter hook or acc inbox"]
21
+ Y --> B
22
+ C --> R["optional live-delivery router"]
23
+ R -.-> B
24
+ B --> Z["CLI, MCP, or adapter hook"]
25
+ Z --> C
26
+ ```
27
+
28
+ There is no required ACC daemon and no coordinator model. CLI commands and native hooks
29
+ are short-lived local processes that open the same workspace store when needed. An MCP
30
+ client may keep its own `acc-mcp` stdio child running, but that child is a tool boundary for
31
+ one participant, not a scheduler or owner of the room.
32
+
33
+ ## 1. A client session joins a workspace
34
+
35
+ For a native client, an installed startup hook sends the client event to `acc-hook`. The
36
+ vendor adapter normalizes that event, then the hook runner:
37
+
38
+ 1. discovers the workspace;
39
+ 2. opens its filesystem store;
40
+ 3. resolves the exact client version and its certified capabilities;
41
+ 4. opens or resumes one ACC session generation; and
42
+ 5. stores a small binding from the client's session id to that ACC generation.
43
+
44
+ Workspace discovery uses an explicit `acc.workspace.json` first, the Git common directory
45
+ second, and the canonical plain directory otherwise. Git worktrees therefore share one
46
+ room but keep separate checkout and branch facts. Git itself is optional.
47
+
48
+ A participant is the address messages target. A session is one current opening of that
49
+ participant, and its unguessable generation token prevents an old process from mutating a
50
+ replacement session. The default participant name is derived from the client session. Set
51
+ `ACC_PARTICIPANT` in the client launch environment when an address must survive a client
52
+ restart and recover messages sent while it was away.
53
+
54
+ Attaching one session does not create durable workspace history. Its presence and intent
55
+ can remain ephemeral until a second live session appears or someone creates the first
56
+ claim, message, or handoff. This is how ACC stays silent when a session is alone without
57
+ making discovery unreliable when a peer arrives.
58
+
59
+ ## 2. Sessions publish awareness, not assignments
60
+
61
+ An intent records a short summary, mode, and resource hints. A claim adds a leased
62
+ reservation for a canonical resource such as `file:src/item.mjs` or `file:src/**`.
63
+ Neither creates a task or grants one session authority over another.
64
+
65
+ A claim is `guarded` only when every live client path involved has a captured pre-write
66
+ guard. Otherwise it is `advisory`: visible coordination that peers should respect, but not
67
+ an operating-system lock. Even a guarded claim cannot stop unrelated programs or a write
68
+ path the client never exposes to its adapter.
69
+
70
+ ## 3. Sending commits the durable truth first
71
+
72
+ When session A sends an addressed question, the CLI or MCP boundary validates the closed
73
+ protocol shape and resolves A's current session generation. Core then performs one
74
+ filesystem transaction that creates:
75
+
76
+ - the immutable logical message, including sender, recipients, kind, obligation, thread,
77
+ and explicit body;
78
+ - one `queued` receipt for each recipient; and
79
+ - a `message.recorded` event.
80
+
81
+ The first message in a thread uses its own `messageId` as `threadId`. A caller-supplied
82
+ `clientMessageId` is a retry key: identical retries return the original message, while the
83
+ same key with different content is rejected.
84
+
85
+ For a room message, recipients are the known peer participants with open sessions at
86
+ commit time. Participants arriving later can find the room record through full forensic
87
+ sync, but they do not receive retroactive receipts.
88
+
89
+ Only after the transaction commits may ACC try to make the message arrive sooner. Thus a
90
+ crashed, unsupported, or unreachable adapter cannot erase a successfully recorded
91
+ question.
92
+
93
+ ## 4. Delivery has three paths
94
+
95
+ The paths share one durable record but prove different facts.
96
+
97
+ ### Durable inbox
98
+
99
+ `acc inbox` is the universal recovery path. It returns only messages addressed to the
100
+ calling participant and atomically advances that participant's receipt to `retrieved`.
101
+ An exact `acc inbox --message message_x` remains usable after context compaction or when a
102
+ message was too large to project safely.
103
+
104
+ ### Certified next-turn projection
105
+
106
+ On an exact client version and platform with passing evidence, a before-turn hook asks core
107
+ for queued messages just before the client's next normal turn. The adapter projects each
108
+ complete body inside an attributed `untrusted peer message` frame. If the complete frame
109
+ does not fit the configured byte budget, the hook keeps the message id and the exact inbox
110
+ recovery command instead of silently truncating peer text.
111
+
112
+ The hook entry point records `offered` only after its stdout transport reports that the
113
+ bytes crossed the boundary. The state is not `retrieved`: ACC still has no observation
114
+ that the model attended to those bytes.
115
+
116
+ ### Native live push
117
+
118
+ The delivery router offers an actionable message to an already-running session when all of
119
+ these hold at once:
120
+
121
+ - exactly one live generation for the recipient;
122
+ - an unexpired generation-bound delivery binding published by that session's own start;
123
+ - a recorded policy permitting this message kind (`actionable` covers question, request,
124
+ answer, decision, and handoff; `all` adds note; room messages are never live);
125
+ - an adapter that declares `delivery.livePush` and a native contract; and
126
+ - adapter acceptance of the bytes.
127
+
128
+ Any missing condition leaves the receipt `queued` and returns a safe fallback reason. Two
129
+ adapters ship a native transport, both experimental and off until a per-client opt-in:
130
+
131
+ ```text
132
+ sender -> durable ACC record -> exact live binding -> vendor transport -> receiver
133
+ \-> queued inbox on every failure
134
+ ```
135
+
136
+ - **Claude Code 2.1.258** uses a vendor Channel: an ACC-owned MCP child, started only when
137
+ the user's ordinary `claude` launch carries the captured development-channel flag, offers
138
+ the message as a native notification and routes the model's explicit `acc_reply` back as a
139
+ real ACC answer. Claude's development-channel warning is vendor-owned and stays visible.
140
+ - **Codex 0.152.1** adds the message to the App Server thread queue over the vendor daemon's
141
+ control socket; it is presented on the idle thread or after the current turn. Codex answers
142
+ through the ordinary `acc reply` command, so its reply route is not native.
143
+
144
+ Compatibility is decided at the launch-time bootstrap and again by a per-session handshake
145
+ bound to the exact client process; there is no maximum client version, but a newer stable
146
+ release must pass a current probe and handshake for the captured protocol, and an older,
147
+ prerelease, known-bad, or uncaptured client stays durable-only. ACC is never the parent of
148
+ a model session after the shell `exec`, and `ACC_BYPASS=1` starts the unmodified client.
149
+
150
+ ## 5. Reply closes the communication obligation
151
+
152
+ The complete question-and-answer path is:
153
+
154
+ ```mermaid
155
+ sequenceDiagram
156
+ participant A as Session A
157
+ participant Core
158
+ participant Store
159
+ participant B as Session B
160
+ A->>Core: addressed question for B
161
+ Core->>Store: message + queued receipt + event
162
+ Store-->>Core: transaction committed
163
+ Core-->>A: recorded with delivery outcome
164
+ alt certified next-turn
165
+ B->>Core: normal turn hook
166
+ Core-->>B: attributed untrusted envelope
167
+ Core->>Store: receipt offered after transport accepts bytes
168
+ else durable inbox
169
+ B->>Core: acc inbox for the message
170
+ Core->>Store: advance B receipt to retrieved
171
+ Core-->>B: attributed message and receipt
172
+ end
173
+ B->>Core: reply to the question id
174
+ Core->>Store: answer + A receipt + acknowledge B receipt
175
+ Core-->>A: answer through next-turn or inbox
176
+ ```
177
+
178
+ `reply` verifies that B owns the original receipt, writes an `answer` in the same thread,
179
+ creates the answer's receipt for A, and advances B's original receipt to `acknowledged` in
180
+ one transaction. A transport failure after that cannot undo the reply. `ack` performs the
181
+ last transition without creating an answer when the obligation only asks for
182
+ acknowledgement.
183
+
184
+ Receipts are per recipient and monotonic:
185
+
186
+ ```text
187
+ queued -> offered -> retrieved -> acknowledged
188
+ ```
189
+
190
+ `recorded` is the successful send boundary, not a receipt state. `offered` does not mean
191
+ read, `retrieved` does not prove model attention, and `acknowledged` resolves communication
192
+ only. A reply saying “I will do it” is not evidence that the requested work finished; ACC
193
+ does not have accepted, running, or done task states.
194
+
195
+ ## 6. The filesystem is the control plane
196
+
197
+ Each workspace lives below the platform data home, conceptually:
198
+
199
+ ```text
200
+ <platform data home>/acc/workspaces/workspace_x/
201
+ ├── protocol.json store version and workspace identity
202
+ ├── state/<kind>/<id>.json materialised current records
203
+ ├── events/<sequence>.json immutable semantic history
204
+ ├── journal/ crash-recovery authority
205
+ ├── locks/ one cross-process writer mutex
206
+ ├── ephemeral/ non-durable presence, intent, and delivery bindings
207
+ ├── bindings/ client-session to ACC-generation mappings
208
+ ├── retained/ logical deletion and retired evidence
209
+ └── tmp/ staged atomic publications
210
+ ```
211
+
212
+ This layout is diagnostic, not a public mutation API. Clients write through the protocol
213
+ and core rather than editing these files.
214
+
215
+ On macOS the platform data home is `~/Library/Application Support`; on Linux it is
216
+ `$XDG_DATA_HOME` or `~/.local/share`. `ACC_DATA_HOME` replaces that base. Runtime paths are
217
+ checked against workspace roots so ACC state cannot be placed inside the project.
218
+
219
+ Every durable mutation holds the same writer mutex, loads only its declared record kinds,
220
+ checks state generations, stages the full result, and writes a recovery journal before
221
+ publishing. Events are immutable no-replace files; current state is a materialised view
222
+ replaced atomically. While publication is incomplete, the active journal bounds event
223
+ cursors below the transaction's first sequence; the next store opener rolls a decided
224
+ transaction forward before serving a read. The store prefers a recoverable duplicate offer
225
+ after a crash to an unearned delivery claim.
226
+
227
+ Paths are opened with containment and no-follow checks. Corrupt records, a foreign
228
+ workspace identity, and unknown store versions fail before mutation rather than being
229
+ guessed into a compatible shape.
230
+
231
+ ## 7. Adapters translate evidence, not product semantics
232
+
233
+ The vendor-neutral layers know nothing about Codex, Claude Code, Gemini CLI, Grok, or Kimi
234
+ Code. `protocol` owns record shapes and state transitions; `core` owns coordination rules;
235
+ `storage-filesystem` owns persistence. Vendor adapters own hook payloads, installation,
236
+ client-specific response shapes, and captured capability evidence. `hook-runner` applies
237
+ the common bounded fail-open lifecycle, while `delivery-router` evaluates optional live
238
+ delivery.
239
+
240
+ Unknown client versions and platforms inherit no capability. A method in an adapter or a
241
+ vendor documentation example is not enough: every `true` capability needs a retained
242
+ real-client fixture. This is why the same product can degrade visibly from next-turn
243
+ projection to inbox polling without changing its message or receipt semantics.
244
+
245
+ ## 8. What crosses the trust boundary
246
+
247
+ ACC stores only explicit coordination data: identity, presence, one-line intent, claims,
248
+ messages the sender chose to send, structured handoffs, receipts, artifacts, and events.
249
+ It does not collect raw prompts, assistant responses, transcripts, environment variables,
250
+ credentials, or permission approvals.
251
+
252
+ Peer bodies remain untrusted data. The projector attributes the sender, escapes framing
253
+ and terminal control sequences, and never promotes peer text to system authority. The
254
+ receiving session still evaluates it under its own instructions and permissions.
255
+
256
+ Every native hook has a five-second ceiling and fails open: if ACC cannot read the store or
257
+ decide safely, the client's action continues. Coordination may become less effective, but
258
+ ACC itself must not stop a session from working.
259
+
260
+ ## Trace the implementation
261
+
262
+ The shortest source-code path is:
263
+
264
+ 1. `packages/hook-runner/src/runner.mjs` — attach, before-turn projection, guards, and the
265
+ fail-open boundary;
266
+ 2. `packages/core/src/conversations.mjs` — record-first messages, threads, receipts, and
267
+ handoffs;
268
+ 3. `packages/core/src/inbox.mjs` — recipient-owned retrieval, reply, and acknowledgement;
269
+ 4. `packages/delivery-router/src/router.mjs` — policy, reachability, certification, and live
270
+ fallback;
271
+ 5. `packages/storage-filesystem/src/store.mjs` — transactions, snapshots, ephemeral state,
272
+ and recovery; and
273
+ 6. `packages/adapter-sdk/src/context-projector.mjs` — bounded untrusted peer framing.
274
+
275
+ Continue with [Capabilities](CAPABILITIES.md) for what each shipped client actually proves,
276
+ [Security model](SECURITY_MODEL.md) for trust boundaries and attack tests, and
277
+ [Adapter authoring](ADAPTER_AUTHORING.md) for the integration contract.
package/docs/MCP.md ADDED
@@ -0,0 +1,94 @@
1
+ # MCP
2
+
3
+ `acc-mcp` lets a client with no native ACC adapter participate over stdio. It exposes the
4
+ same durable messages, threads, receipts, intent, claims, and handoffs, but it cannot infer
5
+ the client's lifecycle, intercept writes, inject a normal turn, or push a message. The
6
+ client polls tools under its own control.
7
+
8
+ ```mermaid
9
+ graph LR
10
+ C["independently opened MCP client"] -->|"stdio JSON-RPC"| M["acc-mcp"]
11
+ M --> S[("ACC durable store")]
12
+ ```
13
+
14
+ ## Register
15
+
16
+ ```json
17
+ {
18
+ "command": "acc-mcp",
19
+ "env": {
20
+ "ACC_MCP_PARTICIPANT": "research",
21
+ "ACC_MCP_WORKSPACE": "/absolute/path/to/project"
22
+ }
23
+ }
24
+ ```
25
+
26
+ `acc-mcp` accepts no command-line arguments. `ACC_MCP_PARTICIPANT` is the stable recipient
27
+ identity for this server. It comes from user-owned launch configuration, never from MCP
28
+ `initialize` or `clientInfo`. `ACC_MCP_WORKSPACE` should be absolute; without it, the
29
+ server uses its launch directory, which may be a different workspace from the other
30
+ sessions.
31
+
32
+ The server implements MCP protocol revision `2026-07-28` over newline-delimited JSON-RPC
33
+ stdio. Tool input schemas are closed: unknown fields and invalid conditional shapes are
34
+ rejected before a session is resolved.
35
+
36
+ ## Tools
37
+
38
+ | Tool | Required input | Optional input |
39
+ |---|---|---|
40
+ | `acc_status` | — | — |
41
+ | `acc_sync` | — | `cursor`, `scope: delta|full`, `limit: 1..500` |
42
+ | `acc_work` | `summary` and `mode`, or `clear: true` | `state`, `resourceHints` |
43
+ | `acc_claim` | `action`; `resource` for acquire, `claimId` for renew | `mode`, `reason`, `leaseSeconds` where valid |
44
+ | `acc_release` | `claimId` | — |
45
+ | `acc_message` | `to`, `subject`, `body` | `kind`, `obligation`, `clientMessageId` |
46
+ | `acc_request` | `toParticipantId`, `title` | `detail`, `clientMessageId` |
47
+ | `acc_inbox` | — | `messageId` |
48
+ | `acc_reply` | `messageId`, `body` | `subject`, `clientMessageId` |
49
+ | `acc_ack` | `messageId` | — |
50
+ | `acc_finish` | `goal` | `status`, `completed`, `remaining`, `blockers`, `toParticipantId`, `clientMessageId` |
51
+
52
+ All tool names above are the complete model-facing surface. There are no execution or
53
+ client-control tools.
54
+
55
+ Send-like tools return a raw structured object with `{ message, delivery }`; their text
56
+ content is the JSON serialization of the same value. `acc_inbox` returns message/receipt
57
+ pairs and advances only this participant's receipts to `retrieved`. `acc_reply` writes an
58
+ `answer` and acknowledges the original atomically. `acc_ack` exposes no receipt-state
59
+ parameter.
60
+
61
+ Resources are `acc://snapshot`, `acc://roster`, and `acc://inbox`. Reading `acc://inbox`
62
+ resolves the configured MCP participant and advances only the returned receipts to
63
+ `retrieved`, just like the inbox tool. Snapshot and roster reads do not advance receipts.
64
+ A full snapshot is for explicit workspace forensics.
65
+
66
+ ## Capability floor
67
+
68
+ The generic MCP capability declaration is all false:
69
+
70
+ | Group | Effective behavior |
71
+ |---|---|
72
+ | lifecycle | no automatic session-start, resume, or end signal |
73
+ | context | no startup, before-turn, or safe-point injection |
74
+ | guards | no before-read, before-write, or before-shell interception |
75
+ | delivery | no `nextTurn`, `livePush`, or native `replyRoute` |
76
+
77
+ An MCP participant therefore reports `advisory` enforcement and `manual` lifecycle.
78
+ `manual` describes ACC presence reporting, not ownership of the external client. Because
79
+ workspace protection is the weakest live participant's real guarantee, one MCP session
80
+ makes guarded claims advisory for the room.
81
+
82
+ ## Durable polling semantics
83
+
84
+ Every outgoing message commits first. `acc_message`, `acc_request`, `acc_reply`, and
85
+ `acc_finish` cannot promise push; delivery results remain queued with a durable diagnostic.
86
+ The recipient calls `acc_inbox` to retrieve the body. Being returned by a tool is
87
+ `retrieved`, not proof that a model attended to or obeyed it. A reply or explicit ack is
88
+ `acknowledged`.
89
+
90
+ MCP is therefore a complete communication participant with higher latency, not a fake
91
+ native adapter. Use it when a client can call tools but exposes no measured hook boundary.
92
+
93
+ Next: [Protocol](PROTOCOL.md) · [Capabilities](CAPABILITIES.md) ·
94
+ [Security model](SECURITY_MODEL.md)
@@ -0,0 +1,200 @@
1
+ # Protocol
2
+
3
+ The protocol is the vendor-neutral contract shared by core, CLI, MCP, storage, and every
4
+ adapter. Version 0.2 uses store schema version `3` and deliberately rejects v0.1 state.
5
+ There is no compatibility reader, conversion, archive path, or automatic deletion.
6
+
7
+ ## Durable records
8
+
9
+ The store accepts only these durable kinds:
10
+
11
+ ```text
12
+ workspace · participant · session · intent · claim · message · receipt · event
13
+ ```
14
+
15
+ `deliveryBinding` is validated but ephemeral. It is tied to one open session generation
16
+ and never written inside a repository.
17
+
18
+ ## Identity
19
+
20
+ ```text
21
+ Workspace
22
+ └── Participant
23
+ └── Session generation
24
+ ```
25
+
26
+ - A workspace is one local coordination room.
27
+ - A participant is the stable recipient of a message.
28
+ - A session is one client conversation. Its unguessable generation token proves that a
29
+ later mutation still belongs to the current opening.
30
+
31
+ Sessions carry harness, checkout, branch, optional pid, enforcement, and lifecycle facts.
32
+ The `managed` lifecycle value means ACC hooks can report presence changes; it does not mean
33
+ ACC owns or controls the external client.
34
+
35
+ ## Intent and claims
36
+
37
+ Intent contains `summary`, `mode`, `resourceHints`, `state`, and `updatedAt`. It is
38
+ awareness only.
39
+
40
+ Claims contain the owner session and generation, canonical resource URI, shared or
41
+ exclusive mode, advisory or guarded enforcement, reason, and lease timestamps. Claim
42
+ acquisition and conflict detection are atomic. Presence becoming stale never releases a
43
+ claim; expiry or an explicit release does.
44
+
45
+ ## Message envelope
46
+
47
+ Every message contains:
48
+
49
+ ```text
50
+ messageId
51
+ threadId
52
+ clientMessageId
53
+ workspaceId
54
+ fromParticipantId
55
+ fromSessionId
56
+ toParticipantIds
57
+ kind
58
+ obligation
59
+ subject
60
+ body
61
+ inReplyTo
62
+ artifacts
63
+ handoff
64
+ sentAt
65
+ ```
66
+
67
+ `clientMessageId` is an idempotency key scoped to workspace plus sender participant. A
68
+ retry with the same logical content returns the original message. Reusing the key with
69
+ different content is a data error. CLI and MCP generate a key when omitted and return it
70
+ inside the message so an uncertain caller can retry explicitly.
71
+
72
+ An empty `toParticipantIds` creates a room record. At commit time, core resolves every
73
+ known peer participant with an open session and creates a receipt for each. Participants
74
+ that arrive later can inspect room history through a full sync but do not receive
75
+ retroactive receipts. Those already-present recipients get the normal inbox and certified
76
+ next-turn path; a successful next-turn write advances their room receipt to `offered`.
77
+ Room records are never eligible for native live push.
78
+
79
+ ## Kinds and obligations
80
+
81
+ | Kind | Valid obligation | Addressing |
82
+ |---|---|---|
83
+ | `note` | `none` | addressed or room |
84
+ | `question` | `reply` | addressed only |
85
+ | `request` | `reply` | addressed only |
86
+ | `answer` | `none` | addressed reply only |
87
+ | `decision` | `none`, or `acknowledge` | addressed or room; room must use `none` |
88
+ | `handoff` | `acknowledge`, or `none` | addressed must acknowledge; room must use `none` |
89
+
90
+ The generic `message` boundary accepts only `note`, `question`, `request`, and `decision`.
91
+ An `answer` must be made through `reply`, which supplies the thread link. A `handoff` must
92
+ be made through `finish`, which supplies the structured payload.
93
+
94
+ A request has no accepted, running, or done state. The reply resolves its communication
95
+ obligation; execution evidence belongs in the answer or handoff.
96
+
97
+ ## Threads
98
+
99
+ The root message uses its own id as the thread id:
100
+
101
+ ```text
102
+ threadId = messageId
103
+ inReplyTo = null
104
+ ```
105
+
106
+ An answer carries the same `threadId` and the original message id in `inReplyTo`. There is
107
+ no mutable thread record or hidden thread status.
108
+
109
+ ## Receipt lifecycle
110
+
111
+ Every resolved recipient gets an independent receipt:
112
+
113
+ ```text
114
+ queued -> offered -> retrieved -> acknowledged
115
+ ```
116
+
117
+ `recorded` is the send boundary's success result: the message is durable. It is not a
118
+ receipt state. `queued` is the distinct per-recipient fact created in the same transaction,
119
+ so one recorded room or multi-recipient message can have zero or several queued receipts.
120
+
121
+ - `queued` proves the durable message and receipt committed.
122
+ - `offered` proves bytes crossed ACC's transport boundary or the target client accepted a
123
+ certified native call.
124
+ - `retrieved` proves the participant explicitly received the body through inbox or an
125
+ equally strong certified adapter signal.
126
+ - `acknowledged` proves that participant acknowledged or replied.
127
+
128
+ Offered is not read. Retrieved is not model attention. Reply is not task completion.
129
+
130
+ Forward skips are allowed when the stronger observation implies the weaker ones. Repeating
131
+ a state is idempotent; moving backward is rejected. There is no `seen` state because ACC
132
+ cannot inspect model attention, and no terminal delivery `failed` state because the
133
+ durable path remains available.
134
+
135
+ ## Offer attempts
136
+
137
+ Delivery attempts are immutable events, not receipt states:
138
+
139
+ ```text
140
+ message.offer_succeeded
141
+ message.offer_failed
142
+ ```
143
+
144
+ Every attempt identifies `messageId`, `recipientParticipantId`, `targetSessionId`, and
145
+ `targetGeneration`, followed by the transport name, adapter, client version, and timestamp.
146
+ A failed attempt additionally carries a safe closed error code. Core validates the target
147
+ as that recipient's recorded session generation and derives event attribution from it; the
148
+ router cannot substitute the sender or omit the selected binding. Attempts never copy the
149
+ peer body into diagnostics.
150
+ Receipt `offered` is committed only after the transport accepts bytes. A failed attempt
151
+ leaves the receipt queued.
152
+
153
+ ## Inbox, reply, and acknowledgement
154
+
155
+ `inbox` returns unresolved messages owned by the calling participant and advances only
156
+ that participant's receipt to `retrieved`. An exact message id is the recovery path after
157
+ compaction or an over-budget projection.
158
+
159
+ `reply` verifies that ownership, records an `answer` in the original thread, and advances
160
+ the original receipt to `acknowledged` in one transaction. Only after that durable commit
161
+ may the answer be offered to the original author. A transport error cannot roll back it.
162
+
163
+ `ack` advances the caller's receipt without creating a reply. It exposes no state override;
164
+ callers cannot claim that a transport offered or a participant retrieved a message.
165
+
166
+ ## Handoff
167
+
168
+ `finish` creates a `handoff` with structured `status`, `completed`, `remaining`,
169
+ `blockers`, and `verification`, releases the sender session's claims, and ends its ACC
170
+ presence. An addressed handoff requires acknowledgement. A room handoff does not. Neither
171
+ form closes or otherwise controls the external AI client.
172
+
173
+ ## Delivery binding and recipient policy
174
+
175
+ A live-capable adapter may publish one ephemeral binding for its exact session generation:
176
+
177
+ ```text
178
+ sessionId · generation · adapterId · clientVersion · availableModes
179
+ livePolicy · opaqueEndpointRef · leaseUntil
180
+ ```
181
+
182
+ The recipient owns `livePolicy` because native push may start a model turn:
183
+
184
+ - `off`: inbox and normal next-turn paths only;
185
+ - `actionable`: questions, requests, answers, decisions, and addressed handoffs may use live push;
186
+ - `all`: every addressed kind may use live push.
187
+
188
+ Default is `off`. Policy never creates a capability. The router still requires a current
189
+ reachable binding, one unambiguous recipient generation, a passing exact-version
190
+ certification, and adapter acceptance. The current Codex and Claude captures do not meet
191
+ those requirements; all shipped native live routes therefore fall back durably.
192
+
193
+ ## Attention and sync
194
+
195
+ Bounded sync returns events after a cursor plus explicit attention. Full sync is a
196
+ forensic workspace snapshot, not the normal way to recover one message. Attention is
197
+ limited to six explicit rules: `reply_required`, `acknowledgement_required`,
198
+ `recipient_unavailable`, `claim_conflict`, `claim_contended`, and `claim_expired`.
199
+
200
+ Next: [CLI](CLI.md) · [MCP](MCP.md) · [Architecture](ARCHITECTURE.md)
@@ -0,0 +1,115 @@
1
+ # Releasing
2
+
3
+ ```mermaid
4
+ graph LR
5
+ A[npm ci] --> B[npm run check] --> C[npm test] --> D[clean candidate commit] --> E[npm pack] --> F[verify-package] --> G{approved?}
6
+ G -->|yes| H[tag · publish · release]
7
+ G -->|no| I[stop]
8
+ ```
9
+
10
+ ## Build the candidate
11
+
12
+ ```bash
13
+ npm ci
14
+ npm run check
15
+ env npm_config_cache=/private/tmp/acc-npm-cache-v02 npm test
16
+ git status --short
17
+ git commit -m "release: prepare ACC v0.2.0"
18
+ candidate_dir="$(mktemp -d /private/tmp/acc-v0.2.XXXXXX)"
19
+ env npm_config_cache=/private/tmp/acc-npm-cache-v02 npm pack --pack-destination "$candidate_dir"
20
+ env npm_config_cache=/private/tmp/acc-npm-cache-v02 node scripts/verify-package.mjs \
21
+ "$candidate_dir/agents-can-communicate-0.2.0.tgz"
22
+ git diff --check
23
+ ```
24
+
25
+ `verify-package.mjs` is the gate that matters. It installs the tarball into a
26
+ clean directory with **no workspace anywhere** and then drives the product. The
27
+ acceptance suite additionally opens independent Claude/Codex hook sessions from
28
+ the installed artifact, completes both message directions, proves downgrade and
29
+ restart behavior, exercises the installed MCP binary, and removes client wiring twice.
30
+
31
+ Development cannot catch what this catches. Workspace symlinks are always
32
+ present there, so an unbundled package imports fine right up until somebody
33
+ else installs it.
34
+
35
+ ## What it refuses
36
+
37
+ | Refused | Why |
38
+ |---|---|
39
+ | `tests/`, `test/` | test suite |
40
+ | unreferenced `fixtures/` | material that is not exact redacted certification evidence |
41
+ | `scripts/spikes/`, `*.sock` | development probes and local endpoints |
42
+ | runtime, transcript, or secret directories | machine state and private material |
43
+ | `.github/`, `.githooks/`, `.agents/` | local configuration |
44
+ | `*.jsonl` | looks like a transcript |
45
+ | Workspaces missing from `node_modules/` | every internal import would fail |
46
+
47
+ ## Record the evidence
48
+
49
+ Put the tarball name, sha256, **the commit it was built from**, exact platform/client
50
+ facts, fallback result, and known limitations in `docs/release-evidence/v0.3.0.md` and
51
+ the current `CHANGELOG.md` release table. A release without them is a release nobody can
52
+ audit later. Test count is deliberately left out: nothing verifies it, so it only
53
+ decorates or, when it drifts, misleads.
54
+
55
+ The commit matters because every workspace travels inside the tarball, so any
56
+ change to shipped code changes the digest. A digest recorded alone goes stale
57
+ on the next merge and then reads as a false claim about the current tree
58
+ rather than a true one about an older commit. `verify-package.mjs` prints
59
+ both on one line for exactly this reason, and refuses to imply
60
+ reproducibility when the working tree is dirty:
61
+
62
+ ```text
63
+ PASS agents-can-communicate-0.0.0.tgz sha256 a5c8bb1d… built from 39d0dcf
64
+ ```
65
+
66
+ It went stale four times in a row anyway, each caught by hand and only
67
+ because someone happened to run the script. So `npm test` now checks it:
68
+ `tests/acceptance/recorded-candidate.test.mjs` fails when shipped code has
69
+ changed since the recorded commit, and names the files. A shallow clone that
70
+ does not have the commit reports that instead of failing — the check is of
71
+ the record, not of the checkout depth.
72
+
73
+ The candidate therefore uses two commits. Commit A contains every packed file and every
74
+ release gate. Pack and verify clean commit A, then commit B records its digest and evidence
75
+ only in files that are not packed. Never record a dirty-tree digest: changing a packed file
76
+ after commit A means making a new candidate commit and packing again.
77
+
78
+ Native real-client tests run only where the retained capture proved that native boundary.
79
+ For v0.2.0 neither Codex 0.152.0 nor Claude Code 2.1.252 did: the Codex control socket was
80
+ absent and Claude stopped at the development-channel warning. Record those exact failed
81
+ captures and run the packed inbox/next-turn fallback instead of promoting an unobserved
82
+ native path. Windows is an explicit unsupported-platform skip, not a passing capture.
83
+
84
+ By v0.3.0 that had gone both ways, which is the point of doing it per release rather than
85
+ once. Claude Code passed and ships a live Channel; Codex's queue capture passed and the
86
+ capability was **withdrawn anyway**, because the mode it needs hides which workspace the
87
+ session belongs to, and a session that cannot be placed must not be addressed. A capture
88
+ that works is not the same claim as a capability that is safe to ship.
89
+
90
+ A published version's record is history and is not rewritten; later changes
91
+ get a new `## Unreleased` entry at the top, checked the same way against the
92
+ current tree.
93
+
94
+ ## Then stop
95
+
96
+ Publishing, tagging, and cutting a GitHub release are **external mutations**.
97
+ They need explicit approval from the maintainer, every time.
98
+
99
+ With two-factor authentication set to `auth-and-writes` — which is what `npm
100
+ profile get` reports for this account — every publish needs a code, and npm
101
+ does not prompt for one:
102
+
103
+ ```bash
104
+ npm publish --otp=123456
105
+ ```
106
+
107
+ An npm *Automation* token, or a granular token with write access, publishes
108
+ without a code. A granular token scoped to selected packages cannot create a
109
+ package that does not exist yet, which is the case exactly once per package.
110
+ The `Release` workflow builds and verifies a candidate and uploads it as an
111
+ artifact; it does not publish.
112
+
113
+ ---
114
+
115
+ See also: [README](index.md) for navigation and [Glossary](GLOSSARY.md) for terms.