agents-can-communicate 0.1.18 → 0.2.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.
- package/README.md +78 -70
- package/SECURITY.md +31 -0
- package/bin/acc-hook.mjs +94 -12
- package/bin/acc-mcp.mjs +6 -2
- package/bin/acc.mjs +6 -1
- package/docs/ADAPTER_AUTHORING.md +172 -0
- package/docs/ARCHITECTURE.md +131 -0
- package/docs/CAPABILITIES.md +102 -214
- package/docs/CLI.md +157 -0
- package/docs/CONCEPTS.md +134 -0
- package/docs/CONFIGURATION.md +143 -0
- package/docs/DESIGN_DECISIONS.md +89 -0
- package/docs/GETTING_STARTED.md +145 -0
- package/docs/GLOSSARY.md +26 -0
- package/docs/MCP.md +94 -0
- package/docs/PROTOCOL.md +200 -0
- package/docs/RELEASING.md +109 -0
- package/docs/SECURITY_MODEL.md +131 -0
- package/docs/TROUBLESHOOTING.md +102 -0
- package/docs/WHY_ACC.md +61 -0
- package/docs/index.md +42 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/certification.json +78 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse-Edit.json +19 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/PreToolUse.json +17 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionEnd.json +8 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/SessionStart.json +7 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/UserPromptSubmit.json +9 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/certification-provenance.json +77 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/fixtures/delivery/claude-code-2.1.252.json +19 -0
- package/node_modules/@agents-can-communicate/adapter-claude-code/package.json +9 -1
- package/node_modules/@agents-can-communicate/adapter-claude-code/plugin/skills/acc/SKILL.md +20 -22
- package/node_modules/@agents-can-communicate/adapter-claude-code/src/adapter.mjs +12 -4
- package/node_modules/@agents-can-communicate/adapter-codex/certification.json +117 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/PreToolUse.json +14 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionEnd.json +7 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/SessionStart.json +9 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/UserPromptSubmit.json +10 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/certification-provenance.json +66 -0
- package/node_modules/@agents-can-communicate/adapter-codex/fixtures/delivery/codex-cli-0.152.0.json +19 -0
- package/node_modules/@agents-can-communicate/adapter-codex/package.json +8 -1
- package/node_modules/@agents-can-communicate/adapter-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-codex/plugin/skills/acc/SKILL.md +20 -22
- package/node_modules/@agents-can-communicate/adapter-codex/src/adapter.mjs +18 -11
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/certification.json +52 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/gemini-extension.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/extension/skills/acc/SKILL.md +20 -22
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeAgent.json +8 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool-shell.json +12 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/BeforeTool.json +12 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionEnd.json +8 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/SessionStart.json +8 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/fixtures/certification-provenance.json +66 -0
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/package.json +8 -1
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/adapter.mjs +7 -3
- package/node_modules/@agents-can-communicate/adapter-gemini-cli/src/install.mjs +4 -2
- package/node_modules/@agents-can-communicate/adapter-grok/certification.json +3 -0
- package/node_modules/@agents-can-communicate/adapter-grok/package.json +2 -1
- package/node_modules/@agents-can-communicate/adapter-grok/plugin/skills/acc/SKILL.md +20 -22
- package/node_modules/@agents-can-communicate/adapter-grok/src/adapter.mjs +9 -9
- package/node_modules/@agents-can-communicate/adapter-kimi/certification.json +52 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Bash.json +12 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/PreToolUse-Write.json +12 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionHeartbeat.json +7 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/SessionStart.json +9 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/UserPromptSubmit.json +8 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/fixtures/certification-provenance.json +66 -0
- package/node_modules/@agents-can-communicate/adapter-kimi/package.json +8 -1
- package/node_modules/@agents-can-communicate/adapter-kimi/plugin/skills/acc/SKILL.md +20 -22
- package/node_modules/@agents-can-communicate/adapter-kimi/src/adapter.mjs +7 -3
- package/node_modules/@agents-can-communicate/adapter-sdk/package.json +1 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/capabilities.mjs +34 -18
- package/node_modules/@agents-can-communicate/adapter-sdk/src/certification.mjs +158 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/context-projector.mjs +36 -17
- package/node_modules/@agents-can-communicate/adapter-sdk/src/hook-shim.mjs +7 -1
- package/node_modules/@agents-can-communicate/adapter-sdk/src/index.mjs +1 -0
- package/node_modules/@agents-can-communicate/adapter-sdk/src/session-binding.mjs +13 -4
- package/node_modules/@agents-can-communicate/cli/package.json +1 -1
- package/node_modules/@agents-can-communicate/cli/src/args.mjs +11 -30
- package/node_modules/@agents-can-communicate/cli/src/doctor-command.mjs +3 -0
- package/node_modules/@agents-can-communicate/cli/src/help.mjs +2 -5
- package/node_modules/@agents-can-communicate/cli/src/install-command.mjs +9 -2
- package/node_modules/@agents-can-communicate/cli/src/main.mjs +100 -121
- package/node_modules/@agents-can-communicate/core/package.json +1 -1
- package/node_modules/@agents-can-communicate/core/src/attention.mjs +106 -0
- package/node_modules/@agents-can-communicate/core/src/conversations.mjs +276 -0
- package/node_modules/@agents-can-communicate/core/src/delivery-bindings.mjs +81 -0
- package/node_modules/@agents-can-communicate/core/src/finish-retries.mjs +97 -0
- package/node_modules/@agents-can-communicate/core/src/inbox.mjs +91 -107
- package/node_modules/@agents-can-communicate/core/src/index.mjs +3 -3
- package/node_modules/@agents-can-communicate/core/src/intents.mjs +0 -1
- package/node_modules/@agents-can-communicate/core/src/ports.mjs +2 -1
- package/node_modules/@agents-can-communicate/core/src/receipts.mjs +109 -0
- package/node_modules/@agents-can-communicate/core/src/service.mjs +11 -10
- package/node_modules/@agents-can-communicate/core/src/sessions.mjs +22 -20
- package/node_modules/@agents-can-communicate/core/src/status.mjs +11 -9
- package/node_modules/@agents-can-communicate/core/src/sync.mjs +3 -294
- package/node_modules/@agents-can-communicate/delivery-router/package.json +12 -0
- package/node_modules/@agents-can-communicate/delivery-router/src/index.mjs +1 -0
- package/node_modules/@agents-can-communicate/delivery-router/src/router.mjs +117 -0
- package/node_modules/@agents-can-communicate/hook-runner/package.json +1 -1
- package/node_modules/@agents-can-communicate/hook-runner/src/client-version.mjs +20 -0
- package/node_modules/@agents-can-communicate/hook-runner/src/runner.mjs +115 -63
- package/node_modules/@agents-can-communicate/installer/package.json +1 -1
- package/node_modules/@agents-can-communicate/installer/src/apply.mjs +23 -7
- package/node_modules/@agents-can-communicate/installer/src/detect.mjs +20 -5
- package/node_modules/@agents-can-communicate/installer/src/index.mjs +3 -2
- package/node_modules/@agents-can-communicate/installer/src/ownership.mjs +108 -12
- package/node_modules/@agents-can-communicate/installer/src/plan.mjs +19 -2
- package/node_modules/@agents-can-communicate/mcp-server/package.json +1 -1
- package/node_modules/@agents-can-communicate/mcp-server/src/input-validator.mjs +79 -0
- package/node_modules/@agents-can-communicate/mcp-server/src/resources.mjs +23 -28
- package/node_modules/@agents-can-communicate/mcp-server/src/server.mjs +102 -72
- package/node_modules/@agents-can-communicate/mcp-server/src/tools.mjs +54 -97
- package/node_modules/@agents-can-communicate/protocol/package.json +1 -1
- package/node_modules/@agents-can-communicate/protocol/src/config.mjs +1 -1
- package/node_modules/@agents-can-communicate/protocol/src/conversations.mjs +64 -0
- package/node_modules/@agents-can-communicate/protocol/src/index.mjs +4 -1
- package/node_modules/@agents-can-communicate/protocol/src/schema.mjs +49 -90
- package/node_modules/@agents-can-communicate/protocol/src/states.mjs +13 -40
- package/node_modules/@agents-can-communicate/storage-filesystem/package.json +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/src/active-journal.mjs +230 -0
- package/node_modules/@agents-can-communicate/storage-filesystem/src/atomic-json.mjs +77 -28
- package/node_modules/@agents-can-communicate/storage-filesystem/src/identity.mjs +1 -1
- package/node_modules/@agents-can-communicate/storage-filesystem/src/journal.mjs +83 -35
- package/node_modules/@agents-can-communicate/storage-filesystem/src/retention.mjs +112 -0
- package/node_modules/@agents-can-communicate/storage-filesystem/src/safe-file.mjs +18 -8
- package/node_modules/@agents-can-communicate/storage-filesystem/src/store.mjs +68 -26
- package/node_modules/@agents-can-communicate/storage-filesystem/src/writer-mutex.mjs +113 -35
- package/package.json +19 -1
- package/node_modules/@agents-can-communicate/core/src/communication.mjs +0 -334
- package/node_modules/@agents-can-communicate/core/src/message-signals.mjs +0 -41
- package/node_modules/@agents-can-communicate/core/src/notify.mjs +0 -95
- package/node_modules/@agents-can-communicate/core/src/tasks.mjs +0 -244
- package/node_modules/@agents-can-communicate/core/src/workstreams.mjs +0 -109
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
ACC is a local control plane for communication facts. The execution planes remain the AI
|
|
4
|
+
clients the user opened. Core records the truth before a delivery adapter is asked to make
|
|
5
|
+
it arrive sooner.
|
|
6
|
+
|
|
7
|
+
```mermaid
|
|
8
|
+
flowchart LR
|
|
9
|
+
S["sender session"] -->|record| C["core"]
|
|
10
|
+
C --> D[("filesystem store<br/>outside repositories")]
|
|
11
|
+
C -->|message id| R["delivery router"]
|
|
12
|
+
R --> A["certified recipient adapter"]
|
|
13
|
+
A --> T["already-running recipient session"]
|
|
14
|
+
T -->|reply or acknowledge| C
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
ACC never starts, resumes, interrupts, supervises, or terminates the target client. A
|
|
18
|
+
transport that requires owning that lifecycle is outside the product boundary.
|
|
19
|
+
|
|
20
|
+
## Packages and dependency direction
|
|
21
|
+
|
|
22
|
+
| Package | Owns |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `protocol` | ids, closed schemas, semantic validation, receipt transitions, error and exit codes |
|
|
25
|
+
| `core` | sessions, intent, claims, conversations, inbox, receipts, attention, ephemeral delivery bindings |
|
|
26
|
+
| `storage-filesystem` | atomic transactions, event journal, materialised views, recovery, writer lock |
|
|
27
|
+
| `adapter-sdk` | capability validation, exact-version certification, context projection, hook and install helpers |
|
|
28
|
+
| `adapter-*` | vendor-specific hooks, responses, installation, evidence, and optional transport |
|
|
29
|
+
| `delivery-router` | recipient policy, one-generation selection, safe offer, then receipt commit |
|
|
30
|
+
| `hook-runner` | bounded adapter hook entry point |
|
|
31
|
+
| `mcp-server` | polling participation for clients without a native adapter |
|
|
32
|
+
| `cli` | universal local command boundary |
|
|
33
|
+
|
|
34
|
+
Core cannot branch on a vendor name or import an adapter, Git, or
|
|
35
|
+
`node:child_process`. Package-boundary tests enforce this rather than relying on
|
|
36
|
+
convention.
|
|
37
|
+
|
|
38
|
+
## Record, then offer
|
|
39
|
+
|
|
40
|
+
The order is part of the public guarantee:
|
|
41
|
+
|
|
42
|
+
1. validate and commit the message plus one `queued` receipt per resolved recipient;
|
|
43
|
+
2. resolve the recipient's current delivery bindings;
|
|
44
|
+
3. check recipient policy, current reachability, and exact client-version certification;
|
|
45
|
+
4. ask one adapter to cross its transport boundary;
|
|
46
|
+
5. only after acceptance, commit `offered` and an immutable success event.
|
|
47
|
+
|
|
48
|
+
A failed offer records the selected recipient session id and generation with a safe
|
|
49
|
+
diagnostic code, then leaves the receipt queued. Core validates that target provenance and
|
|
50
|
+
derives the event actor from it. A crash after bytes cross the boundary but before the
|
|
51
|
+
receipt commit may duplicate a later offer; ACC prefers that truthful underclaim to
|
|
52
|
+
claiming delivery before it happened.
|
|
53
|
+
|
|
54
|
+
## Delivery router is not a session manager
|
|
55
|
+
|
|
56
|
+
Messages address participants. The router may choose a live path only when exactly one
|
|
57
|
+
unexpired session generation is eligible. It does not open a session to make one eligible.
|
|
58
|
+
Zero candidates, several candidates, an unknown version, recipient policy `off`, or an
|
|
59
|
+
adapter refusal all produce durable fallback.
|
|
60
|
+
|
|
61
|
+
The binding is ephemeral and stores:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
sessionId · generation · adapterId · clientVersion · availableModes
|
|
65
|
+
livePolicy · opaqueEndpointRef · leaseUntil
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Core validates identity and expiry but never interprets the opaque endpoint. That remains
|
|
69
|
+
inside the owning adapter. `acc status` reports available modes, policy, reachability, and
|
|
70
|
+
lease without exposing the endpoint.
|
|
71
|
+
|
|
72
|
+
## Certified capability versus current reachability
|
|
73
|
+
|
|
74
|
+
A capability says an exact client version on an exact platform passed a captured behavior.
|
|
75
|
+
It does not say one particular session is reachable now. A binding says what that current
|
|
76
|
+
generation exposes and whether its lease is current. Recipient policy says whether it may
|
|
77
|
+
spend a turn. All three must agree before live delivery is possible.
|
|
78
|
+
|
|
79
|
+
Codex and Claude Code currently ship failed native-delivery captures, so their
|
|
80
|
+
`delivery.livePush` and `delivery.replyRoute` capabilities resolve false. Gemini CLI and
|
|
81
|
+
Kimi Code have exact-version next-turn evidence only. Grok and generic MCP use inbox
|
|
82
|
+
polling. The architecture includes a live seam without pretending the current clients
|
|
83
|
+
proved it.
|
|
84
|
+
|
|
85
|
+
## Storage and workspace identity
|
|
86
|
+
|
|
87
|
+
The filesystem store is the durable source of truth. Every meaningful mutation updates
|
|
88
|
+
materialised records and appends an immutable event in one transaction. Sequence ids sort
|
|
89
|
+
lexically, so a cursor is simply the last sequence returned.
|
|
90
|
+
|
|
91
|
+
Workspace discovery checks an explicit config first, then the Git common directory, then
|
|
92
|
+
the plain directory. Multiple worktrees share a workspace id while each session records
|
|
93
|
+
its checkout and branch. Nothing written by ACC lands inside those roots.
|
|
94
|
+
|
|
95
|
+
A lone session can remain ephemeral. Durable state materialises when a second live session
|
|
96
|
+
appears or the first claim, message, or handoff is committed. This makes “silent when
|
|
97
|
+
alone” an architectural behavior, not a UI preference.
|
|
98
|
+
|
|
99
|
+
## Inbox, attention, and projection
|
|
100
|
+
|
|
101
|
+
Inbox reads only messages addressed to the calling participant and advances that
|
|
102
|
+
participant's receipt to `retrieved`. Reply validates ownership, creates an `answer` in the
|
|
103
|
+
same thread, and acknowledges the original atomically. No participant can advance another
|
|
104
|
+
participant's receipt.
|
|
105
|
+
|
|
106
|
+
Attention is computed from six explicit rules:
|
|
107
|
+
|
|
108
|
+
| Priority | Kind | Observable trigger |
|
|
109
|
+
|---|---|---|
|
|
110
|
+
| 1 | `reply_required` | this participant owns an unacknowledged receipt whose message requires a reply |
|
|
111
|
+
| 2 | `acknowledgement_required` | this participant owns an unacknowledged receipt whose message requires acknowledgement |
|
|
112
|
+
| 3 | `recipient_unavailable` | a required recipient of this participant's message has no online session |
|
|
113
|
+
| 4 | `claim_conflict` | this session's intent hint overlaps another live claim |
|
|
114
|
+
| 5 | `claim_contended` | a peer intent hint overlaps a live claim this session owns |
|
|
115
|
+
| 6 | `claim_expired` | a claim this session owned has reached its lease time |
|
|
116
|
+
|
|
117
|
+
Semantic relevance belongs to the receiving model; correctness never depends on a hidden
|
|
118
|
+
classifier.
|
|
119
|
+
|
|
120
|
+
Adapters project peer bodies in an attributed untrusted frame. If a complete body cannot
|
|
121
|
+
fit, the projection keeps the message id and points to `acc inbox --message <id>` instead
|
|
122
|
+
of silently truncating it.
|
|
123
|
+
|
|
124
|
+
## Hooks fail open
|
|
125
|
+
|
|
126
|
+
Hook execution is bounded. If coordination state cannot be read or a decision cannot be
|
|
127
|
+
made in time, the client action continues. ACC may warn or guard where a real hook allows
|
|
128
|
+
it, but a coordination tool must not be the reason a session stops working.
|
|
129
|
+
|
|
130
|
+
Next: [Protocol](PROTOCOL.md) · [Capabilities](CAPABILITIES.md) ·
|
|
131
|
+
[Security model](SECURITY_MODEL.md)
|
package/docs/CAPABILITIES.md
CHANGED
|
@@ -1,219 +1,107 @@
|
|
|
1
1
|
# Capabilities
|
|
2
2
|
|
|
3
|
-
Capability honesty
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
|
21
|
-
|
|
22
|
-
| `
|
|
23
|
-
|
|
24
|
-
## Matrix
|
|
25
|
-
|
|
26
|
-
| Capability | codex | claude_code | gemini_cli | grok | kimi |
|
|
27
|
-
|---|---|---|---|---|---|
|
|
28
|
-
| `lifecycle.sessionStart` | yes | yes | yes | yes | yes |
|
|
29
|
-
| `lifecycle.sessionResume` | no | no | no | no | no |
|
|
30
|
-
| `lifecycle.sessionEnd` | yes | yes | yes | yes | no |
|
|
3
|
+
Capability honesty separates four questions that are easy to collapse:
|
|
4
|
+
|
|
5
|
+
1. **Certified support** — did this exact client version and platform pass a shipped
|
|
6
|
+
real-client fixture?
|
|
7
|
+
2. **Current reachability** — does one current session generation expose a live binding
|
|
8
|
+
whose lease is valid now?
|
|
9
|
+
3. **Recipient policy** — did that recipient opt into spending a turn for this message
|
|
10
|
+
kind?
|
|
11
|
+
4. **Fallback** — what durable path remains when any earlier answer is no?
|
|
12
|
+
|
|
13
|
+
A source method or vendor documentation is not certification. Unknown versions and
|
|
14
|
+
platforms degrade to false. No weaker session inherits a stronger peer's capability.
|
|
15
|
+
|
|
16
|
+
## Certified support
|
|
17
|
+
|
|
18
|
+
Passing evidence currently ships for these exact versions on `darwin-arm64`:
|
|
19
|
+
|
|
20
|
+
| Capability | Codex 0.147.0 | Claude Code 2.1.233 | Gemini CLI 0.37.0 | Grok 1.0.13 | Kimi 0.36.1 |
|
|
21
|
+
|---|---:|---:|---:|---:|---:|
|
|
22
|
+
| `lifecycle.sessionStart` | yes | yes | yes | no | yes |
|
|
23
|
+
| `lifecycle.sessionEnd` | yes | yes | yes | no | no |
|
|
31
24
|
| `lifecycle.heartbeat` | no | no | no | no | yes |
|
|
32
|
-
| `lifecycle.childSessions` | no | no | no | no | no |
|
|
33
|
-
| `context.startupInjection` | no | no | no | no | no |
|
|
34
25
|
| `context.beforeTurnInjection` | yes | yes | yes | no | yes |
|
|
35
|
-
| `context.safePointInjection` | no | no | no | no | no |
|
|
36
|
-
| `guards.beforeRead` | no | no | no | no | no |
|
|
37
26
|
| `guards.beforeWrite` | yes | yes | yes | no | yes |
|
|
38
|
-
| `guards.beforeShell` |
|
|
39
|
-
| `delivery.
|
|
40
|
-
| `delivery.
|
|
41
|
-
| `delivery.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
reads `offline` — and disappears from the default `acc status` view — only after thirty
|
|
120
|
-
minutes of silence, not on its declared 60s heartbeat cadence. Interactive sessions
|
|
121
|
-
heartbeat and do not have this problem.
|
|
122
|
-
|
|
123
|
-
**`lifecycle.heartbeat` is Kimi's alone.** It fires on a timer — observed at 60002, 120004
|
|
124
|
-
and 180006 ms of uptime — so an idle Kimi session keeps its presence honest. The other
|
|
125
|
-
clients reach a hook only when the user takes a turn, so their idle sessions go stale while
|
|
126
|
-
alive. This is why it is a capability of its own rather than a flavour of
|
|
127
|
-
`delivery.polling`.
|
|
128
|
-
|
|
129
|
-
**`context.beforeTurnInjection` on `grok` is false.** Grok 1.0.13 discards
|
|
130
|
-
UserPromptSubmit stdout and `additionalContext`. The hook still runs (presence
|
|
131
|
-
and polling), but the model is not shown that text. Agents on this client read
|
|
132
|
-
`acc status` / `acc inbox` from the skill.
|
|
133
|
-
|
|
134
|
-
**`guards.beforeWrite` / `beforeShell` on `grok` are false.** PreToolUse fires, and
|
|
135
|
-
the matcher names `write`, `search_replace`, and `run_terminal_command`. A deny
|
|
136
|
-
has not yet been captured blocking a real call, so the capability stays false.
|
|
137
|
-
|
|
138
|
-
## Response contracts, which do not port
|
|
139
|
-
|
|
140
|
-
The single most portable-looking mistake an adapter can make. Measured by running each
|
|
141
|
-
candidate against a real session of each client and checking whether the tool actually
|
|
142
|
-
ran. A dash means the candidate was never run against that client, not that it fails —
|
|
143
|
-
only the shape each shipped adapter actually uses was measured on every client.
|
|
144
|
-
|
|
145
|
-
| Reply to a guard hook | codex | claude_code | gemini_cli | grok | kimi |
|
|
146
|
-
|---|---|---|---|---|---|
|
|
147
|
-
| exit code 2 | denies | - | denies | - | denies |
|
|
148
|
-
| `{"hookSpecificOutput":{…,"permissionDecision":"deny"}}` | - | denies | **ignored** | documented | denies |
|
|
149
|
-
| `{"decision":"deny","reason":…}` | - | - | - | documented | - |
|
|
150
|
-
| `{"decision":"block","reason":…}` | - | - | denies | - | **ignored** |
|
|
151
|
-
| `{"permission":"deny"}` | - | - | ignored | - | ignored |
|
|
152
|
-
| exit code 1 | - | - | ignored | - | ignored |
|
|
153
|
-
|
|
154
|
-
Codex has no structured reply at all: it denies by exiting 2 with the reason on stderr.
|
|
155
|
-
Gemini ignores the shape that Claude Code and Kimi Code both honour, and Kimi ignores the
|
|
156
|
-
shape Gemini needs. Each ignored case fails silently — the write goes through and the
|
|
157
|
-
client reports nothing.
|
|
158
|
-
|
|
159
|
-
Context injection does not follow the deny contract even within one client:
|
|
160
|
-
|
|
161
|
-
| Injection | codex | claude_code | gemini_cli | grok | kimi |
|
|
162
|
-
|---|---|---|---|---|---|
|
|
163
|
-
| `hookSpecificOutput.additionalContext` | - | works | works | **discarded** on UserPromptSubmit | works, but **not unwrapped** |
|
|
164
|
-
| plain text on stdout | works | - | dropped | **discarded** on UserPromptSubmit | works |
|
|
165
|
-
|
|
166
|
-
Codex delivers a hook's stdout as a `developer` role message, verbatim — the most direct
|
|
167
|
-
of the four channels, and a reason for care rather than comfort: at that role a model
|
|
168
|
-
reads text as instruction, so peer-authored text has to stay framed as data.
|
|
169
|
-
|
|
170
|
-
Kimi Code shows the model whatever a hook printed, wrapped in
|
|
171
|
-
`<hook_result hook_event="…">`, so the JSON envelope itself would end up in the
|
|
172
|
-
conversation. Gemini unwraps the envelope and appends `<hook_context>…</hook_context>` to
|
|
173
|
-
the user turn, and drops a bare string entirely.
|
|
174
|
-
|
|
175
|
-
These two tables are the measurement; they say nothing about how an adapter produces the
|
|
176
|
-
right shape without knowing which client it is talking to. That contract —
|
|
177
|
-
`denyOutcome()` / `injectOutcome()` — is documented in
|
|
178
|
-
[ADAPTER_AUTHORING.md](ADAPTER_AUTHORING.md#response-contracts-do-not-port).
|
|
179
|
-
|
|
180
|
-
## Installation is not uniform either
|
|
181
|
-
|
|
182
|
-
| | codex | claude_code | gemini_cli | grok | kimi |
|
|
183
|
-
|---|---|---|---|---|---|
|
|
184
|
-
| Where hooks live | marketplace plugin | plugin | `settings.json` | `~/.grok/hooks/acc.json` | `config.toml` |
|
|
185
|
-
| Project-level config | no | no | yes | yes (`<project>/.grok/hooks`, unused) | **no** |
|
|
186
|
-
| Hook `timeout` unit | - | - | milliseconds | **seconds** | **seconds** (max 600) |
|
|
187
|
-
| Command path | absolute required | `${CLAUDE_PLUGIN_ROOT}` | absolute required | absolute required | absolute required |
|
|
188
|
-
| Extra step by the user | hook trust | - | - | - | - |
|
|
189
|
-
|
|
190
|
-
Kimi Code is the only one with no project-level config, so ACC edits the user's global
|
|
191
|
-
`config.toml` — as a delimited block it owns, because ACC ships without dependencies and a
|
|
192
|
-
hand-written TOML round-tripper would take the user's comments and formatting with it.
|
|
193
|
-
|
|
194
|
-
Codex needs four things before a hook runs, not one: the plugin directory, a parseable
|
|
195
|
-
marketplace, both `[marketplaces.…]` and `[plugins."…"]` registered in its config, and the
|
|
196
|
-
plugin copied into `plugins/cache/<marketplace>/<plugin>/<version>/`. ACC does all four —
|
|
197
|
-
that last copy is exactly and only what `codex plugin add` does, measured by diffing the
|
|
198
|
-
home around it. Hook trust remains a manual step, which is the client's security model.
|
|
199
|
-
|
|
200
|
-
## What a participant declares about itself
|
|
201
|
-
|
|
202
|
-
Every session records `enforcement` (`guarded` | `advisory`) and `lifecycle`
|
|
203
|
-
(`managed` | `manual`), taken from the adapter's proven capabilities in this matrix rather
|
|
204
|
-
than from the harness's name — both default to the weaker reading, so a generic MCP client
|
|
205
|
-
or a human at the CLI reads as advisory and manual. What that downgrade means for a
|
|
206
|
-
workspace, and why one MCP participant in the room is enough to drop everyone else's
|
|
207
|
-
protection, is explained canonically in
|
|
208
|
-
[MCP.md](MCP.md#native-adapter-vs-mcp-client).
|
|
209
|
-
|
|
210
|
-
**"Stoppable" is not "unevadable".** Even in a guarded workspace, a session that writes
|
|
211
|
-
through a language runtime rather than a recognised shell form gets past — see
|
|
212
|
-
`guards.beforeShell` above. The claim still says who is working where; enforcement is the
|
|
213
|
-
floor, not the ceiling.
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
See also: [README](index.md) for navigation, [Glossary](GLOSSARY.md) for terms,
|
|
218
|
-
[Adapter authoring](ADAPTER_AUTHORING.md) for the deny/inject implementation contract, and
|
|
219
|
-
[MCP](MCP.md) for the participation tier and the native-vs-MCP explanation.
|
|
27
|
+
| `guards.beforeShell` | no | yes | yes | no | yes |
|
|
28
|
+
| `delivery.nextTurn` | yes | yes | yes | no | yes |
|
|
29
|
+
| `delivery.livePush` | no | no | no | no | no |
|
|
30
|
+
| `delivery.replyRoute` | no | no | no | no | no |
|
|
31
|
+
|
|
32
|
+
Every other capability in the closed shape defaults to false, including session resume,
|
|
33
|
+
child sessions, startup or safe-point injection, and before-read guards.
|
|
34
|
+
|
|
35
|
+
The limitations belong next to the adapters they affect:
|
|
36
|
+
|
|
37
|
+
| Adapter | Exact limitation and evidence |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Codex | 0.147.0 next-turn stdout arrives as unwrapped developer-role context and requires plugin trust. The separate 0.152.0 native capture found no daemon control socket; ACC did not start one, so live push and reply routing remain false. |
|
|
40
|
+
| Claude Code | 2.1.233 next-turn delivery waits for the next user prompt. The 2.1.252 channel capture stopped at the development-channel warning before the ACC MCP child started; native delivery branches are unobserved and false. |
|
|
41
|
+
| Gemini CLI | Only 0.37.0 has package-shipped next-turn certification. Write and shell tools depend on approval mode; other versions and platforms retain inbox access but no effective delivery capability. |
|
|
42
|
+
| Grok | Documentation-shaped payloads do not count as real captures. UserPromptSubmit context was observed discarded, and no deny was captured stopping a real write; all capabilities remain false. |
|
|
43
|
+
| Kimi Code | 0.36.1 has next-turn and guard evidence, plus a 60-second heartbeat. Prompt-mode `SessionEnd` never fired, and its next-turn path does not interrupt an active turn. |
|
|
44
|
+
| Generic MCP | Tool polling is not next-turn injection, live push, or a native reply route. It has no write guard or client-lifecycle evidence. |
|
|
45
|
+
|
|
46
|
+
`certification.json` beside each adapter is machine-readable. `COMPATIBILITY.md` records the
|
|
47
|
+
captured client behavior, including what could not be observed.
|
|
48
|
+
|
|
49
|
+
## Current reachability
|
|
50
|
+
|
|
51
|
+
Certification is static evidence; reachability is runtime state. A live-capable adapter
|
|
52
|
+
would publish a generation-bound binding with `availableModes`, `clientVersion`,
|
|
53
|
+
`livePolicy`, and `leaseUntil`. `acc status --json` reports these as `deliveryBindings`
|
|
54
|
+
with a computed `reachable` boolean while keeping the opaque endpoint private.
|
|
55
|
+
|
|
56
|
+
The router requires exactly one current eligible generation. No binding, an expired lease,
|
|
57
|
+
several live sessions for one participant, a busy target, or a version that does not match
|
|
58
|
+
passing evidence all stay on durable fallback.
|
|
59
|
+
|
|
60
|
+
Current shipped reality: no adapter publishes a native live binding, and no adapter has
|
|
61
|
+
passing `livePush` certification. Codex and Claude Code are next-turn or inbox only;
|
|
62
|
+
Gemini CLI and Kimi Code are next-turn only at their exact captured versions; Grok and MCP
|
|
63
|
+
poll inbox.
|
|
64
|
+
|
|
65
|
+
## Recipient policy
|
|
66
|
+
|
|
67
|
+
Native live delivery may start a model turn and spend tokens, so the recipient owns the
|
|
68
|
+
policy:
|
|
69
|
+
|
|
70
|
+
| Policy | Meaning |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `off` | normal next-turn and inbox only |
|
|
73
|
+
| `actionable` | questions, requests, and addressed handoffs may use live push |
|
|
74
|
+
| `all` | every addressed message kind may use live push |
|
|
75
|
+
|
|
76
|
+
The default is `off`. `acc install --delivery actionable|all` is an explicit request, not
|
|
77
|
+
a force switch. The installer applies it only when the detected exact client has certified
|
|
78
|
+
live push; otherwise effective policy remains off and the fallback diagnostic is printed.
|
|
79
|
+
Room messages are never live-push candidates.
|
|
80
|
+
|
|
81
|
+
## Fallback
|
|
82
|
+
|
|
83
|
+
| Participant | Durable behavior when acceleration is unavailable |
|
|
84
|
+
|---|---|
|
|
85
|
+
| exact-certified Codex 0.147.0 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
|
|
86
|
+
| exact-certified Claude Code 2.1.233 | complete peer body at the next normal prompt; `acc inbox` remains recoverable |
|
|
87
|
+
| exact-certified Gemini CLI 0.37.0 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
|
|
88
|
+
| exact-certified Kimi Code 0.36.1 | complete peer body at the next normal turn; `acc inbox` remains recoverable |
|
|
89
|
+
| Grok, generic MCP, unknown version, other platform | explicit `acc inbox` polling |
|
|
90
|
+
|
|
91
|
+
A send that committed durably succeeds even if a transport later fails. The delivery array
|
|
92
|
+
names the queued fallback and safe error code. There is no terminal failed receipt.
|
|
93
|
+
|
|
94
|
+
## Guard limitations
|
|
95
|
+
|
|
96
|
+
A guarded claim stops only paths the client exposes to a captured pre-tool hook. Codex's
|
|
97
|
+
write guard depends on the model offering `apply_patch`; recognised shell writes can be
|
|
98
|
+
matched, but a language runtime opening a file cannot. Gemini's edit tools depend on
|
|
99
|
+
approval mode. Grok has no certified guard. One live advisory session lowers workspace
|
|
100
|
+
protection to advisory because that is the strongest honest room-wide statement.
|
|
101
|
+
|
|
102
|
+
Hook response shapes are vendor-specific and not portable. An ignored deny response often
|
|
103
|
+
fails silently, which is why each true cell above needs its own fixture rather than a
|
|
104
|
+
shared documentation example.
|
|
105
|
+
|
|
106
|
+
Next: [Protocol](PROTOCOL.md) · [MCP](MCP.md) ·
|
|
107
|
+
[Adapter authoring](ADAPTER_AUTHORING.md)
|
package/docs/CLI.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# CLI
|
|
2
|
+
|
|
3
|
+
The `acc` command is the universal local boundary. Setup commands are for a person;
|
|
4
|
+
communication commands are the small surface installed skills teach to agents. Every
|
|
5
|
+
command accepts `--json` and `--cwd <path>`. `--workspace <config>` selects an explicit
|
|
6
|
+
workspace config where supported by the common boundary.
|
|
7
|
+
|
|
8
|
+
<!-- test:command -->
|
|
9
|
+
```bash
|
|
10
|
+
acc help
|
|
11
|
+
acc version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Communication commands
|
|
15
|
+
|
|
16
|
+
| Command | Required | Optional |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| `acc status` | — | `--participant`, `--all` |
|
|
19
|
+
| `acc sync` | — | `--session`, `--cursor`, `--limit`, `--scope delta|full` |
|
|
20
|
+
| `acc work` | `--summary` unless `--clear` | `--session`, `--generation`, `--mode`, `--state`, repeated `--hint`, `--clear` |
|
|
21
|
+
| `acc claim` | `--resource` | `--session`, `--generation`, `--mode`, `--enforcement`, `--reason`, `--lease` |
|
|
22
|
+
| `acc release` | `--claim` or `--resource` | `--session`, `--generation`, `--authority`, `--reason` |
|
|
23
|
+
| `acc message` | `--subject`, `--body` | repeated `--to`, `--type`, `--obligation`, `--client-message-id`, owner flags |
|
|
24
|
+
| `acc request` | `--to`, `--title` | `--detail`, `--client-message-id`, owner flags |
|
|
25
|
+
| `acc inbox` | — | `--message`, owner flags |
|
|
26
|
+
| `acc reply` | `--message`, `--body` | `--subject`, `--client-message-id`, owner flags |
|
|
27
|
+
| `acc ack` | `--message` | owner flags |
|
|
28
|
+
| `acc finish` | `--goal` | `--status`, `--to`, repeated `--completed`, `--remaining`, `--blocker`, `--client-message-id`, owner flags |
|
|
29
|
+
|
|
30
|
+
Owner flags are `--session` and `--generation`. A normal hooked session omits them because
|
|
31
|
+
the CLI resolves its current binding. Scripts and adapters may pass them explicitly.
|
|
32
|
+
|
|
33
|
+
### Presence and intent
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
acc status
|
|
37
|
+
acc work --summary "checking receipt transitions" --mode review \
|
|
38
|
+
--hint 'file:packages/core/src/receipts.mjs'
|
|
39
|
+
acc work --clear
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`status` returns participants, current intent, claims, protection, attention, and current
|
|
43
|
+
delivery bindings. `sync` is a bounded event read; use `--scope full` only for an explicit
|
|
44
|
+
whole-workspace forensic question. Neither is the recovery path for one message.
|
|
45
|
+
|
|
46
|
+
### Claims
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
acc claim --resource 'file:packages/core/**' --reason "editing receipt logic"
|
|
50
|
+
acc release --resource 'file:packages/core/**'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
File resources use repository-relative paths. A directory claim ends in `/**`. Exit code
|
|
54
|
+
`5` means a conflict. `--authority` is the explicit force-release path and should carry a
|
|
55
|
+
reason; ordinary sessions release only their own claims.
|
|
56
|
+
|
|
57
|
+
### Messages and requests
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
acc message --to models --type question --subject "receipt wording" \
|
|
61
|
+
--body "Should transport acceptance be called offered?" \
|
|
62
|
+
--client-message-id client_stable_1
|
|
63
|
+
|
|
64
|
+
acc request --to models --title "review receipt wording" \
|
|
65
|
+
--detail "Check CLI and MCP results; reply with defects only."
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`message` accepts generic kinds `note`, `question`, `request`, and `decision`. Defaults are
|
|
69
|
+
`note` plus obligation `none`; questions and requests require `reply`; an addressed
|
|
70
|
+
decision may explicitly use `--obligation acknowledge`. `answer` is created only by
|
|
71
|
+
`reply`, and `handoff` only by `finish`.
|
|
72
|
+
|
|
73
|
+
No `--to` creates a room message where the kind allows it. Addressed messages create a
|
|
74
|
+
separate receipt for each recipient. `request` is convenience for one addressed `request`
|
|
75
|
+
message with a reply obligation; it creates no execution record.
|
|
76
|
+
|
|
77
|
+
The JSON result for `message`, `request`, `reply`, and `finish` is:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
{
|
|
81
|
+
"message": { "messageId": "message_x", "clientMessageId": "client_x" },
|
|
82
|
+
"delivery": [
|
|
83
|
+
{ "recipientParticipantId": "models", "outcome": "queued",
|
|
84
|
+
"transport": "durable", "errorCode": "delivery_disabled" }
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Human output starts with `recorded message_x`. A transport failure after that commit does
|
|
90
|
+
not change the command exit code. Reuse an explicit `--client-message-id` after an
|
|
91
|
+
uncertain result to recover the same logical message.
|
|
92
|
+
|
|
93
|
+
### Inbox, reply, and acknowledgement
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
acc inbox
|
|
97
|
+
acc inbox --message message_x
|
|
98
|
+
acc reply --message message_x --body "Yes. Use offered."
|
|
99
|
+
acc ack --message message_y
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Inbox returns only unresolved messages addressed to this participant. Reading advances
|
|
103
|
+
that participant's receipt to `retrieved`. Reply creates an `answer` in the same thread and
|
|
104
|
+
acknowledges the original atomically. `ack` acknowledges without writing an answer and has
|
|
105
|
+
no state override.
|
|
106
|
+
|
|
107
|
+
### Handoff
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
acc finish --goal "document receipt semantics" --status partial \
|
|
111
|
+
--completed "protocol updated" --remaining "acceptance proof" \
|
|
112
|
+
--blocker "packed test not run" --to models
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Status is `complete`, `partial`, or `blocked`. `finish` records a structured handoff,
|
|
116
|
+
releases the caller's claims, and ends ACC presence for that session. It never closes the
|
|
117
|
+
external AI client. An addressed handoff requires acknowledgement; a room handoff does not.
|
|
118
|
+
|
|
119
|
+
## Setup and maintenance
|
|
120
|
+
|
|
121
|
+
| Command | Flags |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `acc install` | `--adapter`, `--home`, `--delivery off|actionable|all`, `--dry-run`, `--downgrade` |
|
|
124
|
+
| `acc uninstall` | `--adapter`, `--home`, `--dry-run` |
|
|
125
|
+
| `acc doctor` | `--home`, `--repair` |
|
|
126
|
+
| `acc config init` | `--yes`, `--force` |
|
|
127
|
+
| `acc config validate` | — |
|
|
128
|
+
| `acc update` | `--apply` |
|
|
129
|
+
| `acc help` | — |
|
|
130
|
+
| `acc version` | — |
|
|
131
|
+
|
|
132
|
+
`--delivery` is a recipient policy request, not a capability switch. The default is
|
|
133
|
+
`off`. If the detected exact client version lacks certified live push, installation keeps
|
|
134
|
+
the effective policy off and prints the adapter's durable fallback.
|
|
135
|
+
|
|
136
|
+
Only `update` touches the network. `ACC_NO_UPDATE_CHECK=1` disables update checks. Hooks
|
|
137
|
+
never perform them.
|
|
138
|
+
|
|
139
|
+
## Adapter lifecycle commands
|
|
140
|
+
|
|
141
|
+
`acc attach --participant <id>`, `acc heartbeat --session <id> --generation <token>`, and
|
|
142
|
+
`acc detach --session <id> --generation <token>` are public executable boundaries used by
|
|
143
|
+
adapters. Installed skills do not teach models to call them. They maintain ACC presence;
|
|
144
|
+
they do not start, keep alive, or close the external client process.
|
|
145
|
+
|
|
146
|
+
## Exit codes
|
|
147
|
+
|
|
148
|
+
| Code | Meaning |
|
|
149
|
+
|---|---|
|
|
150
|
+
| `0` | success |
|
|
151
|
+
| `2` | usage |
|
|
152
|
+
| `3` | timeout |
|
|
153
|
+
| `4` | data or incompatible state |
|
|
154
|
+
| `5` | claim or generation conflict |
|
|
155
|
+
| `6` | attention |
|
|
156
|
+
|
|
157
|
+
Next: [Protocol](PROTOCOL.md) · [MCP](MCP.md) · [Configuration](CONFIGURATION.md)
|