@pcircle/memesh 4.7.3 → 4.8.1

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 (140) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +3 -1
  4. package/README.de.md +42 -16
  5. package/README.md +46 -19
  6. package/README.zh-TW.md +42 -17
  7. package/dashboard/dist/index.html +1 -1
  8. package/dist/core/agent-message-storage.d.ts +76 -0
  9. package/dist/core/agent-message-storage.d.ts.map +1 -0
  10. package/dist/core/agent-message-storage.js +359 -0
  11. package/dist/core/agent-message-storage.js.map +1 -0
  12. package/dist/core/agent-messaging.d.ts +224 -0
  13. package/dist/core/agent-messaging.d.ts.map +1 -0
  14. package/dist/core/agent-messaging.js +881 -0
  15. package/dist/core/agent-messaging.js.map +1 -0
  16. package/dist/core/agent-router.d.ts +194 -0
  17. package/dist/core/agent-router.d.ts.map +1 -0
  18. package/dist/core/agent-router.js +1138 -0
  19. package/dist/core/agent-router.js.map +1 -0
  20. package/dist/core/briefing.d.ts.map +1 -1
  21. package/dist/core/briefing.js +8 -1
  22. package/dist/core/briefing.js.map +1 -1
  23. package/dist/core/config.d.ts.map +1 -1
  24. package/dist/core/config.js.map +1 -1
  25. package/dist/core/doctor.d.ts +19 -0
  26. package/dist/core/doctor.d.ts.map +1 -1
  27. package/dist/core/doctor.js +176 -2
  28. package/dist/core/doctor.js.map +1 -1
  29. package/dist/core/dreamer.d.ts +8 -5
  30. package/dist/core/dreamer.d.ts.map +1 -1
  31. package/dist/core/dreamer.js +88 -3
  32. package/dist/core/dreamer.js.map +1 -1
  33. package/dist/core/product-improvements.d.ts +61 -0
  34. package/dist/core/product-improvements.d.ts.map +1 -0
  35. package/dist/core/product-improvements.js +216 -0
  36. package/dist/core/product-improvements.js.map +1 -0
  37. package/dist/core/repo-state.d.ts +11 -0
  38. package/dist/core/repo-state.d.ts.map +1 -0
  39. package/dist/core/repo-state.js +70 -0
  40. package/dist/core/repo-state.js.map +1 -0
  41. package/dist/core/schema-export.d.ts.map +1 -1
  42. package/dist/core/schema-export.js +70 -0
  43. package/dist/core/schema-export.js.map +1 -1
  44. package/dist/core/task-state.d.ts.map +1 -1
  45. package/dist/core/task-state.js +3 -3
  46. package/dist/core/task-state.js.map +1 -1
  47. package/dist/core/updater.d.ts +2 -0
  48. package/dist/core/updater.d.ts.map +1 -1
  49. package/dist/core/updater.js +11 -5
  50. package/dist/core/updater.js.map +1 -1
  51. package/dist/core/work-topology.d.ts.map +1 -1
  52. package/dist/core/work-topology.js +1 -0
  53. package/dist/core/work-topology.js.map +1 -1
  54. package/dist/host-adapters/acp-client.d.ts +147 -0
  55. package/dist/host-adapters/acp-client.d.ts.map +1 -0
  56. package/dist/host-adapters/acp-client.js +793 -0
  57. package/dist/host-adapters/acp-client.js.map +1 -0
  58. package/dist/host-adapters/claude-channel.d.ts +75 -0
  59. package/dist/host-adapters/claude-channel.d.ts.map +1 -0
  60. package/dist/host-adapters/claude-channel.js +255 -0
  61. package/dist/host-adapters/claude-channel.js.map +1 -0
  62. package/dist/host-adapters/codex-app-server.d.ts +83 -0
  63. package/dist/host-adapters/codex-app-server.d.ts.map +1 -0
  64. package/dist/host-adapters/codex-app-server.js +360 -0
  65. package/dist/host-adapters/codex-app-server.js.map +1 -0
  66. package/dist/host-adapters/codex-cli-queue.d.ts +17 -0
  67. package/dist/host-adapters/codex-cli-queue.d.ts.map +1 -0
  68. package/dist/host-adapters/codex-cli-queue.js +85 -0
  69. package/dist/host-adapters/codex-cli-queue.js.map +1 -0
  70. package/dist/host-runtime/acp.d.ts +57 -0
  71. package/dist/host-runtime/acp.d.ts.map +1 -0
  72. package/dist/host-runtime/acp.js +338 -0
  73. package/dist/host-runtime/acp.js.map +1 -0
  74. package/dist/host-runtime/claude.d.ts +41 -0
  75. package/dist/host-runtime/claude.d.ts.map +1 -0
  76. package/dist/host-runtime/claude.js +213 -0
  77. package/dist/host-runtime/claude.js.map +1 -0
  78. package/dist/host-runtime/codex-session.d.ts +24 -0
  79. package/dist/host-runtime/codex-session.d.ts.map +1 -0
  80. package/dist/host-runtime/codex-session.js +98 -0
  81. package/dist/host-runtime/codex-session.js.map +1 -0
  82. package/dist/host-runtime/codex.d.ts +33 -0
  83. package/dist/host-runtime/codex.d.ts.map +1 -0
  84. package/dist/host-runtime/codex.js +215 -0
  85. package/dist/host-runtime/codex.js.map +1 -0
  86. package/dist/host-runtime/config.d.ts +9 -0
  87. package/dist/host-runtime/config.d.ts.map +1 -0
  88. package/dist/host-runtime/config.js +91 -0
  89. package/dist/host-runtime/config.js.map +1 -0
  90. package/dist/host-runtime/router-client.d.ts +38 -0
  91. package/dist/host-runtime/router-client.d.ts.map +1 -0
  92. package/dist/host-runtime/router-client.js +463 -0
  93. package/dist/host-runtime/router-client.js.map +1 -0
  94. package/dist/host-runtime/router.d.ts +3 -0
  95. package/dist/host-runtime/router.d.ts.map +1 -0
  96. package/dist/host-runtime/router.js +43 -0
  97. package/dist/host-runtime/router.js.map +1 -0
  98. package/dist/mcp/server.js +2 -2
  99. package/dist/mcp/server.js.map +1 -1
  100. package/dist/skills-manifest.json +22 -17
  101. package/dist/storage/conflicts.d.ts.map +1 -1
  102. package/dist/storage/conflicts.js +8 -1
  103. package/dist/storage/conflicts.js.map +1 -1
  104. package/dist/storage/schema.d.ts +1 -1
  105. package/dist/storage/schema.d.ts.map +1 -1
  106. package/dist/storage/schema.js +255 -0
  107. package/dist/storage/schema.js.map +1 -1
  108. package/dist/transports/agent-messaging.d.ts +11 -0
  109. package/dist/transports/agent-messaging.d.ts.map +1 -0
  110. package/dist/transports/agent-messaging.js +273 -0
  111. package/dist/transports/agent-messaging.js.map +1 -0
  112. package/dist/transports/cli/cli.d.ts +6 -1
  113. package/dist/transports/cli/cli.d.ts.map +1 -1
  114. package/dist/transports/cli/cli.js +392 -17
  115. package/dist/transports/cli/cli.js.map +1 -1
  116. package/dist/transports/http/server.d.ts.map +1 -1
  117. package/dist/transports/http/server.js +31 -2
  118. package/dist/transports/http/server.js.map +1 -1
  119. package/dist/transports/mcp/handlers.d.ts +152 -1
  120. package/dist/transports/mcp/handlers.d.ts.map +1 -1
  121. package/dist/transports/mcp/handlers.js +108 -3
  122. package/dist/transports/mcp/handlers.js.map +1 -1
  123. package/dist/transports/schemas.d.ts +106 -1
  124. package/dist/transports/schemas.d.ts.map +1 -1
  125. package/dist/transports/schemas.js +86 -0
  126. package/dist/transports/schemas.js.map +1 -1
  127. package/docs/platforms/README.md +167 -0
  128. package/docs/platforms/agent-messaging.md +290 -0
  129. package/hooks/hooks.json +11 -0
  130. package/llms-install.md +101 -25
  131. package/package.json +14 -5
  132. package/scripts/hooks/_generated/repo-state.js +77 -0
  133. package/scripts/hooks/_generated/schema.js +255 -0
  134. package/scripts/hooks/_generated/task-state.js +3 -3
  135. package/scripts/hooks/_generated/work-topology.js +1 -0
  136. package/scripts/hooks/_shared.js +77 -97
  137. package/scripts/hooks/auto-update-runner.mjs +243 -0
  138. package/scripts/hooks/session-start.js +12 -2
  139. package/scripts/hooks/session-summary.js +7 -6
  140. package/skills/memesh/SKILL.md +40 -1
@@ -0,0 +1,290 @@
1
+ # Local Agent Messaging Guide
2
+
3
+ MeMesh provides two complementary collaboration surfaces on one machine:
4
+
5
+ - shared durable memory, including the `team` namespace, for knowledge, decisions, and coarse handoffs;
6
+ - the `message` tool for explicit durable messages to one named recipient on the same MeMesh instance.
7
+
8
+ The messaging path is durable store-and-forward. For an explicitly configured,
9
+ active local Codex CLI session, MeMesh queues a metadata-only native wakeup;
10
+ the session then fetches the durable payload through the scoped `message`
11
+ operation. SQLite remains the audit and recovery authority. `poll`/`watch` are
12
+ compatibility and diagnostic APIs, not the normal delivery loop for that active
13
+ Codex path. A queue admission or `host_accept` is not proof that an agent read
14
+ the payload, acknowledged it, or accepted the work.
15
+
16
+ ## One-time owner-private local-host setup
17
+
18
+ Native delivery is optional and local to one Unix account. Do this setup once
19
+ for the account that owns both the MeMesh database and the active host
20
+ sessions; do not place router tokens or host config in a repository, shared
21
+ dotfile, or world-readable temp directory.
22
+
23
+ Each configured host connection attempts to start the packaged router and
24
+ retries when its owner-private socket is absent or refused. You can also start
25
+ the router yourself when you want to inspect it directly; it creates an
26
+ owner-private token and socket beside the active MeMesh database on first
27
+ start:
28
+
29
+ ```bash
30
+ umask 077
31
+ memesh-router
32
+ ```
33
+
34
+ If you start it yourself, leave that process running. In a second terminal,
35
+ verify only the installed adapter imports and the live router socket separately:
36
+
37
+ ```bash
38
+ MEMESH_DOCTOR_PROBE_MESSAGE_CAPABILITY=1 memesh doctor
39
+ MEMESH_DOCTOR_PROBE_MESSAGE_ROUTER=1 memesh doctor
40
+ ```
41
+
42
+ The first command proves the installed MCP schema and adapter imports. The
43
+ second only proves that the owner-private router socket accepts a connection.
44
+ Neither command starts or registers a host, sends a message, proves
45
+ `host_accept`, or wakes a stopped session.
46
+ In particular, a socket check does not start the host it observes.
47
+
48
+ The secure host-native router and adapter runtime currently supports macOS and
49
+ Linux. Windows remains supported for core MeMesh memory, durable message
50
+ storage, and MCP tools, but host-native wakeup fails closed before creating
51
+ credentials, configuration, IPC listeners, or managed child processes.
52
+
53
+ Create one reusable owner-private config for each local path and principal.
54
+ The stable principal is the logical recipient. Managed processes generate a
55
+ fresh exact session identity; the ordinary Codex path instead uses the Codex
56
+ thread identity supplied at SessionStart. No thread ID is copied by hand.
57
+ Ordinary sessions outside the explicit `codex-session` workspace opt-in remain
58
+ `presence-only/inbound-unavailable`.
59
+
60
+ ```bash
61
+ memesh agent setup codex-session --project my-project --principal codex-reviewer --workspace "$PWD"
62
+ memesh agent setup codex --project my-project --principal codex-reviewer --workspace "$PWD"
63
+ memesh agent setup claude --project my-project --principal claude-reviewer
64
+ ```
65
+
66
+ ### Ordinary active Codex CLI session
67
+
68
+ `codex-session` is the opt-in path for an ordinary local Codex session and
69
+ requires the MeMesh Codex plugin to be installed and enabled so Codex loads
70
+ the packaged SessionStart hook. Run
71
+ the setup command from the exact workspace that Codex will use; it stores the
72
+ configured real workspace and stable principal in the owner-private
73
+ `codex-session.json` config. Restart Codex in that workspace after setup.
74
+
75
+ On `SessionStart` for `startup` or `resume`, the asynchronous companion checks
76
+ the Codex thread identity, hook session identity, and configured workspace
77
+ realpath before it connects to the router. A missing identity, a different
78
+ workspace, compact lifecycle input, or a failed/disconnected connection does
79
+ not register a host and does not wake anything.
80
+
81
+ For a registered session, MeMesh invokes `codex queue` with a
82
+ `memesh_message_available` marker containing only the project, recipient,
83
+ target kind, message ID, and delivery ID. The message payload stays in the
84
+ durable MeMesh inbox. Codex must then use the `message` tool to `fetch` that
85
+ same project/recipient/target/message scope. The persisted `host_accept` means
86
+ only that the local Codex queue accepted the marker; it is neither payload
87
+ readback nor an `ack` or workflow disposition.
88
+
89
+ If the configured Codex session is stopped, missing, disconnected, or no
90
+ longer matches its configured workspace, MeMesh does not start or replace it.
91
+ The durable inbox and its receipt history remain available to scoped fetch,
92
+ cursor recovery, `poll`, or `memesh message watch` for audit and diagnosis.
93
+
94
+ ### Separate: MeMesh-managed Codex app-server runner
95
+
96
+ ```bash
97
+ memesh-host-codex --config "$HOME/.memesh/hosts/codex.json"
98
+ ```
99
+
100
+ This is separate from `codex-session`: it starts a MeMesh-owned `codex
101
+ app-server`, creates its own thread through the private Unix/WebSocket control
102
+ path, and registers only after that thread is ready. It does not attach to an
103
+ ordinary Codex session. Message content never appears in MeMesh or Codex
104
+ process arguments.
105
+
106
+ ### Claude channel runner
107
+
108
+ Run the printed `registration_command` once to add `memesh-channel` as a
109
+ user-scoped stdio MCP server. Claude owns that process for the session:
110
+
111
+ ```bash
112
+ claude mcp add --transport stdio --scope user memesh-channel -- \
113
+ memesh-host-claude --config "$HOME/.memesh/hosts/claude.json"
114
+ ```
115
+
116
+ Claude Channels is an upstream research-preview opt-in. Custom channels are
117
+ not on Anthropic's approved allowlist, so start every participating Claude
118
+ session with the printed launch command and confirm the local-development
119
+ warning:
120
+
121
+ ```bash
122
+ claude --dangerously-load-development-channels server:memesh-channel
123
+ ```
124
+
125
+ Without that flag Claude may initialize the ordinary MCP transport while
126
+ silently dropping channel events; a MeMesh `host_accept` then proves only that
127
+ the notification was written to stdio, not that Claude admitted it. With the
128
+ channel admitted, initialization creates and registers the exact MeMesh
129
+ session automatically; EOF, MCP close, or normal signals unregister it.
130
+
131
+ ### Experimental ACP runner (not release-gated)
132
+
133
+ An internal generic ACP runner remains an experimental adapter surface. No ACP
134
+ provider is documented as a supported native-wakeup path here; protocol or
135
+ process readiness alone is not proof that a provider accepted a message.
136
+
137
+ The managed Codex app-server and Claude channel paths deliver only while their
138
+ configured target is active and registered. If it is stopped, missing, disconnected, or replaced, MeMesh keeps the durable message but does not start
139
+ the host, recreate the session, or silently redirect an exact-session target.
140
+ A later eligible managed-principal registration drains only post-activation
141
+ pending work; an exact-session target never moves to a replacement. Manual
142
+ cursor reads remain available for audit and diagnostics, not as a requirement
143
+ for active Codex-session delivery.
144
+
145
+ ## What Works Today
146
+
147
+ - MCP, HTTP, and CLI use the same message lifecycle and SQLite system of record.
148
+ - `send` creates one canonical message, recipient delivery, and payload-free notification event under an idempotency key.
149
+ - `poll` and `memesh message watch` return only events for the exact project and recipient. They are compatibility and diagnostic paths; the opaque cursor can be persisted and reused after a timeout, dropped hint, duplicate delivery, or process restart.
150
+ - `fetch` returns the payload only to the named recipient and matching `target_kind` in the named project. Exact-session messages require `target_kind=session`; polling and fetching do not acknowledge the message.
151
+ - `intake`, `ack`, `disposition`, and `activation` are explicit, separate, idempotent receipt facts. Inbox/MCP ACK is valid without a host-native acceptance; host-native ACK remains bound to its `host_accept`. `receipts` returns one ordered projection and identifies each underlying fact source. For example, `manual_resume_required` does not imply ACK, acceptance, rejection, cancellation, or completion.
152
+ - The transport, rather than model-provided payload data, records sender-host provenance.
153
+
154
+ ## Identity and lifecycle
155
+
156
+ A **principal** is the stable logical recipient. A **session** is one live host connection for that principal. A **generation** changes when that session is replaced. An exact-session target never reroutes. A principal target can deliver only to an eligible active session after its activation checkpoint; it does not replay historical inbox contents into a first session.
157
+
158
+ Persistence, dispatch attempt, host acceptance, intake, acknowledgement,
159
+ workflow disposition, retention, and presence are independent state axes. An
160
+ active configured Codex session receives a host-native metadata marker without
161
+ polling. A stopped, missing, busy beyond its queue limit, disconnected, or
162
+ unsupported session is not awakened, resumed, or replaced; durable state
163
+ remains available for audit and recovery, subject to exact-session and
164
+ activation-checkpoint rules.
165
+
166
+ ## Bounded storage and audit retention
167
+
168
+ Message payload growth is observable and owner-controlled. MeMesh never deletes
169
+ unresolved, unacknowledged, retryable, or offline-pending messages to satisfy a
170
+ limit. Inspect logical payload bytes, protected rows, SQLite reusable pages,
171
+ and main/WAL file sizes with an explicit policy cutoff:
172
+
173
+ ```bash
174
+ memesh message storage report --cutoff 2026-08-01T00:00:00Z
175
+ ```
176
+
177
+ Preview one bounded batch of old terminal payloads; nothing changes without
178
+ `--apply`:
179
+
180
+ ```bash
181
+ memesh message storage prune --cutoff 2026-08-01T00:00:00Z --batch-size 100
182
+ memesh message storage prune --cutoff 2026-08-01T00:00:00Z --batch-size 100 --apply
183
+ ```
184
+
185
+ Applied pruning replaces only payload content whose every delivery has an
186
+ explicit ACK and a terminal workflow disposition older than the cutoff with a hash-bound
187
+ tombstone. Message identity, routing, receipts, ACK, workflow, presence, and
188
+ retention audit facts remain queryable. Freed SQLite pages become reusable;
189
+ the main database file is a high-watermark and is not promised to shrink.
190
+ Full `VACUUM` is never run by a hook or this bounded command.
191
+
192
+ An owner may set `MEMESH_AGENT_MESSAGE_STORAGE_QUOTA_BYTES` to a non-negative
193
+ integer. This is a hard **logical payload** budget, not a whole SQLite file or
194
+ disk quota. The canonical send transaction checks it before inserting any
195
+ message effect; an over-quota send returns `storage_quota_exceeded` and leaves
196
+ no partial message, delivery, event, idempotency, dispatch, or receipt row.
197
+ Metadata, indexes, append-only audit facts, reusable pages, and WAL bytes still
198
+ consume disk and remain visible in the report; keep separate filesystem
199
+ headroom and monitoring. Heartbeats refresh the connection lease in place;
200
+ they do not append one audit row every interval. Connected, disconnected, and
201
+ superseded transitions remain auditable. There is deliberately no default
202
+ quota or automatic retention policy.
203
+
204
+ ## Local and Cloud boundary
205
+
206
+ This guide describes only one local MeMesh instance: its SQLite durable event
207
+ store and same-machine host-native input. Remote and cross-machine transport is
208
+ the responsibility of MeMesh Cloud and requires its own verified relay; Cloud
209
+ state is not evidence that this local host received a marker. A native marker,
210
+ persistence, or fetch does not promise exactly-once cognition, a reply, or a
211
+ stopped-session wake-up.
212
+
213
+ ## What This Is Not Yet
214
+
215
+ - Not universal host support or stopped-session resume. This document only
216
+ describes the explicitly configured ordinary Codex path and the separate
217
+ managed Codex/Claude paths above.
218
+ - Not topic, broadcast, lease/claim, or TTL routing. The current delivery target is one exact recipient.
219
+ - Not arbitrary external-user access or cross-machine delivery. A local MeMesh instance is not a public collaboration service.
220
+ - Not permission to execute payload content. The receiving host must apply its own policy and required human approval.
221
+
222
+ ## Support Matrix
223
+
224
+ | Participant | Current path | Status today | Notes |
225
+ |---|---|---|---|
226
+ | Ordinary Codex CLI | `codex-session` owner-private opt-in | metadata-only native wakeup while active | Exact workspace, principal, and SessionStart identity must match; stopped or disconnected sessions are not awakened |
227
+ | MeMesh-managed Codex app-server | `memesh-host-codex` | separate managed path | It creates its own Codex thread; it does not attach to an ordinary session |
228
+ | Claude channel | `memesh-host-claude` | separate channel path | Requires the documented Channel opt-in; no stopped-session resume |
229
+ | Other local MCP clients | MCP, HTTP, or CLI message operations | durable messaging only | Use `poll`/`watch` and scoped fetch where their own host loop supports it; this guide makes no native-wakeup claim |
230
+
231
+ ## Lifecycle
232
+
233
+ 1. A sender calls `message` with `action: "send"`, a stable sender, one recipient, a project, an idempotency key, and a payload.
234
+ 2. For an eligible ordinary Codex session, the router queues only a
235
+ privacy-minimized `memesh_message_available` marker. An explicit
236
+ `poll`/`watch` client may instead read privacy-minimized events for
237
+ compatibility or diagnosis.
238
+ 3. Codex calls `fetch` with the marker's project, recipient, target kind, and
239
+ message ID to read the durable payload. The marker and queue admission do
240
+ not acknowledge the message.
241
+ 4. The receiver records only the facts that actually happened:
242
+ - `intake`: payload fetched or durably ingested;
243
+ - `ack`: explicit recipient acknowledgement;
244
+ - `disposition`: accepted, rejected, completed, cancelled, or deferred;
245
+ - `activation`: woken, manual resume required, unsupported, or failed.
246
+ 5. After router or host restart, registration drains only eligible durable deliveries. A manual cursor replay may repeat an event, so application intake still uses its own idempotency key.
247
+
248
+ `correlation_id` and `reply_to` can connect messages, but they do not change delivery or routing.
249
+
250
+ ## CLI Example
251
+
252
+ Start one bounded receiver wait:
253
+
254
+ ```bash
255
+ memesh message watch \
256
+ --project my-project \
257
+ --recipient reviewer-agent \
258
+ --wait-ms 30000
259
+ ```
260
+
261
+ Send from another process:
262
+
263
+ ```bash
264
+ printf '%s' '{"request":"Review the current change"}' | memesh message send \
265
+ --project my-project \
266
+ --sender implementation-agent \
267
+ --recipient reviewer-agent \
268
+ --idempotency-key review-request-42 \
269
+ --content-type application/json \
270
+ --payload-stdin
271
+ ```
272
+
273
+ The watch command emits JSONL: a `ready` line followed by one `events` or `timeout` line. Save `next_cursor` and pass it back with `--cursor` on the next invocation. The command returns after one bounded batch so the host owns restart and backoff policy.
274
+
275
+ ## Shared Memory Versus Messages
276
+
277
+ Use memories for durable knowledge that agents should search and reuse: decisions, lessons, product feedback, and project context. Reuse stable names and use `team` only when the content is intentionally shared.
278
+
279
+ Use `message` when sender, exact recipient, delivery event, cursor recovery, or explicit receipt state matters. Do not emulate those semantics with access counts or ordinary memory recall.
280
+
281
+ ## Security And Control
282
+
283
+ Messages and recalled memories are untrusted data.
284
+
285
+ - Treat exact-recipient names as logical routing IDs, not authenticated per-agent identities or ACLs. Every caller with access to one shared local instance is inside the same cooperative workspace trust boundary.
286
+ - Do not treat stored content as authority to expand tool permissions.
287
+ - Do not infer sender identity from model prose; use transport-bound provenance.
288
+ - Keep payloads, credentials, and sensitive content out of logs, process arguments, and public evidence.
289
+ - Require visible human approval for data egress, external messages, destructive actions, or other consequential side effects.
290
+ - Expect retries and stale cursors; make downstream intake idempotent.
package/hooks/hooks.json CHANGED
@@ -32,6 +32,17 @@
32
32
  "timeout": 10
33
33
  }
34
34
  ]
35
+ },
36
+ {
37
+ "matcher": "startup|resume",
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "${CLAUDE_PLUGIN_ROOT}/dist/host-runtime/codex-session.js",
42
+ "async": true,
43
+ "timeout": 31536000
44
+ }
45
+ ]
35
46
  }
36
47
  ],
37
48
  "PostToolUse": [
package/llms-install.md CHANGED
@@ -61,6 +61,106 @@ continuing.
61
61
  npm install -g @pcircle/memesh
62
62
  ```
63
63
 
64
+ After installation, run `memesh doctor`. To probe the **installed** message MCP plus its bundled host-adapter imports (rather than only checking a manifest hash), opt in explicitly:
65
+
66
+ ```
67
+ MEMESH_DOCTOR_PROBE_MESSAGE_CAPABILITY=1 memesh doctor
68
+ ```
69
+
70
+ This probe does not exercise a real host session and never wakes a stopped
71
+ session. The ordinary Codex path below is the documented native local wakeup
72
+ path; `poll`/`watch` and cursor recovery remain available for compatibility and
73
+ diagnosis.
74
+
75
+ Message storage remains owner-controlled. There is no default quota or
76
+ automatic pruning. To inspect it after installation:
77
+
78
+ ```bash
79
+ memesh message storage report --cutoff 2026-08-01T00:00:00Z
80
+ memesh message storage prune --cutoff 2026-08-01T00:00:00Z --batch-size 100
81
+ ```
82
+
83
+ The prune command is a dry-run unless `--apply` is supplied. Only old terminal
84
+ payload content is tombstoned; unresolved/offline-pending messages and all
85
+ lifecycle audit facts are preserved. Set an explicit hard quota for all send
86
+ transports with `MEMESH_AGENT_MESSAGE_STORAGE_QUOTA_BYTES=<bytes>`; an
87
+ over-quota send is rejected atomically.
88
+
89
+ ### Optional: one-time local host setup
90
+
91
+ This is separate from MCP setup. It is for the owner of an active local Codex
92
+ session, a MeMesh-managed Codex app-server, or a Claude channel. Keep all
93
+ files private to that Unix account; do not commit the token or config files.
94
+ This secure host-native runtime currently supports macOS and Linux. Windows
95
+ can still use core MeMesh, durable messages, and MCP tools, but not this
96
+ host-native wakeup path.
97
+
98
+ Each configured host connection starts the packaged router and retries its
99
+ connection when the owner-private socket is absent or refused. Start the router
100
+ yourself only when you want to inspect the socket directly:
101
+
102
+ ```bash
103
+ umask 077
104
+ memesh-router
105
+ ```
106
+
107
+ If you start it yourself, it creates `agent-router.sock` and `agent-router.token` beside the active
108
+ MeMesh database (normally `~/.memesh/`) with owner-private permissions. Check
109
+ the installed adapter imports and the live socket as distinct facts:
110
+
111
+ ```bash
112
+ MEMESH_DOCTOR_PROBE_MESSAGE_CAPABILITY=1 memesh doctor
113
+ MEMESH_DOCTOR_PROBE_MESSAGE_ROUTER=1 memesh doctor
114
+ ```
115
+
116
+ The router probe does not register a host, send content, or wake a stopped
117
+ session. Generate reusable `0600` configs; session identities are not copied
118
+ from an active ordinary session.
119
+
120
+ For an ordinary active local Codex session, first install and enable the MeMesh
121
+ Codex plugin (Option A), which supplies the packaged SessionStart hook. Then
122
+ run this from the exact workspace you want to configure and restart Codex in
123
+ that same workspace:
124
+
125
+ ```bash
126
+ memesh agent setup codex-session --project my-project --principal codex-recipient --workspace "$PWD"
127
+ ```
128
+
129
+ This stores the configured workspace realpath and principal in
130
+ `~/.memesh/hosts/codex-session.json`. On `SessionStart` (`startup` or
131
+ `resume`), an asynchronous companion registers only when its Codex thread ID,
132
+ hook session ID, and workspace realpath match that config. It receives no
133
+ message payload. Instead, an active registered session receives a
134
+ metadata-only `memesh_message_available` queue marker with routing identifiers,
135
+ then uses the scoped `message` `fetch` operation to read the durable payload.
136
+
137
+ `host_accept` records only that the local Codex queue accepted that marker. It
138
+ does not prove an agent read the payload, acknowledged it, or accepted the
139
+ work. If the session is stopped, missing, disconnected, or in another
140
+ workspace, MeMesh neither starts nor replaces it; the durable inbox remains
141
+ available to scoped fetch, cursor recovery, `poll`, and `memesh message watch`
142
+ for audit and diagnosis.
143
+
144
+ The following are separate managed-host paths:
145
+
146
+ ```bash
147
+ memesh agent setup codex --project my-project --principal codex-recipient --workspace "$PWD"
148
+ memesh-host-codex --config "$HOME/.memesh/hosts/codex.json"
149
+
150
+ memesh agent setup claude --project my-project --principal claude-recipient
151
+ # Run the printed `registration_command` (`claude mcp add ... memesh-host-claude ...`) once.
152
+ # Start each participating session with the printed research-preview launch command:
153
+ claude --dangerously-load-development-channels server:memesh-channel
154
+ ```
155
+
156
+ The managed Codex runner owns its app-server and thread; Claude owns its
157
+ Channel MCP child. Neither is the ordinary Codex-session path, and neither
158
+ attaches to, resumes, or replaces an ordinary stopped host. When no active
159
+ registration exists, the message remains durable with no false dispatch or
160
+ host acceptance. The package also contains the experimental
161
+ `memesh-host-acp` binary for protocol development, but no ACP provider is a
162
+ documented native-wakeup integration here.
163
+
64
164
  Expected: exits without error; `memesh`, `memesh-mcp` and `memesh-http` are
65
165
  now in `$(npm prefix -g)/bin/`. No compiler is involved and no install script
66
166
  runs.
@@ -113,31 +213,7 @@ Expected: `memesh` is listed as enabled.
113
213
  | `memesh` absent from the list | The add did not persist. Re-run `codex mcp add memesh -- memesh-mcp` and re-check. |
114
214
  | Listed, but tool calls fail | Run `command -v memesh-mcp`. Empty output means section 2 is incomplete or PATH is wrong — fix per section 2's table. |
115
215
 
116
- ## 4. Gemini CLI
117
-
118
- Prerequisite: section 2 — `memesh-mcp` must resolve on PATH.
119
-
120
- ```
121
- gemini mcp add -s user memesh memesh-mcp
122
- ```
123
-
124
- `-s user` registers at user scope, so it works from every folder.
125
-
126
- **Verify**:
127
-
128
- ```
129
- gemini mcp list
130
- ```
131
-
132
- Expected: `memesh` shows **Connected**.
133
-
134
- | Failure | Remedy |
135
- |---|---|
136
- | `command not found: gemini` | Gemini CLI itself is not installed — out of scope here; install it first, then re-run the add. |
137
- | Shows Disconnected | Run `command -v memesh-mcp`. Empty output means section 2 is incomplete or PATH is wrong — fix per section 2's table, then re-run `gemini mcp list`. |
138
- | `memesh` absent from the list | The add was made in a different scope or did not persist. Re-run `gemini mcp add -s user memesh memesh-mcp`. |
139
-
140
- ## 5. Cursor
216
+ ## 4. Cursor
141
217
 
142
218
  Prerequisite: section 2 — `memesh-mcp` must resolve on PATH.
143
219
 
package/package.json CHANGED
@@ -1,13 +1,18 @@
1
1
  {
2
2
  "name": "@pcircle/memesh",
3
- "version": "4.7.3",
3
+ "version": "4.8.1",
4
4
  "description": "MeMesh — agentic memory for coding agents. Captured from the agent's real work via hooks, recalled when it acts. One SQLite file, zero cloud required.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
8
  "memesh": "dist/transports/cli/cli.js",
9
9
  "memesh-mcp": "dist/mcp/server.js",
10
- "memesh-http": "dist/transports/http/server.js"
10
+ "memesh-http": "dist/transports/http/server.js",
11
+ "memesh-router": "dist/host-runtime/router.js",
12
+ "memesh-host-claude": "dist/host-runtime/claude.js",
13
+ "memesh-host-codex": "dist/host-runtime/codex.js",
14
+ "memesh-host-codex-session": "dist/host-runtime/codex-session.js",
15
+ "memesh-host-acp": "dist/host-runtime/acp.js"
11
16
  },
12
17
  "files": [
13
18
  "dist/",
@@ -17,6 +22,7 @@
17
22
  "scripts/hooks/",
18
23
  "scripts/upgrade-plugin.sh",
19
24
  "skills/",
25
+ "docs/platforms/agent-messaging.md",
20
26
  ".claude-plugin/",
21
27
  "README.md",
22
28
  "LICENSE",
@@ -29,10 +35,11 @@
29
35
  "test": "vitest",
30
36
  "test:e2e-dashboard": "node scripts/dashboard-e2e-smoke.mjs",
31
37
  "test:packaged": "node scripts/smoke-packed-artifact.mjs",
38
+ "test:packaged:upgrade": "node scripts/smoke-packed-upgrade.mjs",
32
39
  "audit:prod": "node scripts/check-consumer-audit.mjs",
33
- "verify:release": "npm run lint && npm run typecheck && node scripts/check-version-coherence.mjs && node scripts/check-generated-mirror.mjs && node scripts/check-doc-claims.mjs && node scripts/audit/verification-audit.mjs && npm run audit:prod",
40
+ "verify:release": "npm run lint && npm run typecheck && node scripts/check-version-coherence.mjs && node scripts/check-generated-mirror.mjs && node scripts/check-agent-message-sync.mjs && node scripts/check-readme-tool-parity.mjs && node scripts/check-doc-claims.mjs && node scripts/audit/verification-audit.mjs && npm run audit:prod",
34
41
  "release:finish": "node scripts/finish-release.mjs",
35
- "prepublishOnly": "npm run build && npm run verify:release && npm run test:isolated && npm run test:packaged",
42
+ "prepublishOnly": "npm run build && npm run verify:release && npm run test:isolated && npm run test:packaged && npm run test:packaged:upgrade",
36
43
  "typecheck": "tsc -p tsconfig.check.json && tsc -p tsconfig.check-dashboard.json",
37
44
  "lint": "eslint src/ scripts/ tests/ dashboard/src/ --max-warnings 0",
38
45
  "lint:fix": "eslint src/ scripts/ tests/ dashboard/src/ --fix",
@@ -69,6 +76,7 @@
69
76
  "express": "^5.2.1",
70
77
  "express-rate-limit": "8.5.1",
71
78
  "sqlite-vec": "^0.1.9",
79
+ "ws": "^8.21.3",
72
80
  "zod": "4.4.3"
73
81
  },
74
82
  "overrides": {
@@ -83,7 +91,7 @@
83
91
  "protobufjs": "^7.6.5",
84
92
  "qs": "^6.15.3",
85
93
  "sharp": "^0.35.3",
86
- "ws": "^8.21.1",
94
+ "ws": "$ws",
87
95
  "vite": "7.3.6"
88
96
  },
89
97
  "devDependencies": {
@@ -93,6 +101,7 @@
93
101
  "@testing-library/preact": "^3.2.4",
94
102
  "@types/express": "^5.0.6",
95
103
  "@types/node": "25.6.2",
104
+ "@types/ws": "^8.18.1",
96
105
  "@vitest/coverage-v8": "4.1.5",
97
106
  "eslint": "^10.3.0",
98
107
  "happy-dom": "^20.9.0",
@@ -0,0 +1,77 @@
1
+ // ============================================================================
2
+ // AUTO-GENERATED from src/core/repo-state.ts — DO NOT EDIT BY HAND.
3
+ // Regenerate with: npm run build (scripts/generate-hook-core.mjs)
4
+ //
5
+ // Claude Code hooks import this committed copy instead of dist/, so the
6
+ // always-on capture path survives a missing or stale dist/ while staying
7
+ // byte-locked to core — eliminating the hand-mirror drift behind the P0 FTS bug.
8
+ // ============================================================================
9
+ import { execFileSync } from 'child_process';
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ const GIT_TIMEOUT_MS = 5000;
13
+ function tryGit(cwd, args) {
14
+ try {
15
+ return execFileSync('git', ['-C', cwd, ...args], {
16
+ encoding: 'utf8',
17
+ timeout: GIT_TIMEOUT_MS,
18
+ stdio: ['ignore', 'pipe', 'pipe'],
19
+ }).trim();
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ }
25
+ function declaredVersionOf(repoRoot) {
26
+ try {
27
+ const raw = fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8');
28
+ const version = JSON.parse(raw).version;
29
+ return typeof version === 'string' && version.length > 0 ? version : null;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ export function readRepoState(cwdInput) {
36
+ const cwd = cwdInput && cwdInput.length > 0 ? cwdInput : process.cwd();
37
+ const repoRoot = tryGit(cwd, ['rev-parse', '--show-toplevel']);
38
+ if (!repoRoot)
39
+ return null;
40
+ const branchRaw = tryGit(cwd, ['rev-parse', '--abbrev-ref', 'HEAD']);
41
+ const branch = branchRaw && branchRaw !== 'HEAD' ? branchRaw : null;
42
+ const statusOut = tryGit(cwd, ['status', '--porcelain']);
43
+ const uncommitted = statusOut ? statusOut.split('\n').filter(l => l.trim() !== '').length : 0;
44
+ const lastTag = tryGit(cwd, ['describe', '--tags', '--abbrev=0']);
45
+ let commitsSinceTag = null;
46
+ if (lastTag) {
47
+ const count = tryGit(cwd, ['rev-list', '--count', `${lastTag}..HEAD`]);
48
+ const parsed = count === null ? Number.NaN : Number.parseInt(count, 10);
49
+ commitsSinceTag = Number.isFinite(parsed) ? parsed : null;
50
+ }
51
+ const declaredVersion = declaredVersionOf(repoRoot);
52
+ let declaredVersionIsTagged = null;
53
+ if (declaredVersion) {
54
+ const hit = tryGit(cwd, ['tag', '--list', `v${declaredVersion}`]);
55
+ declaredVersionIsTagged = hit === null ? null : hit.length > 0;
56
+ }
57
+ return { branch, uncommitted, lastTag, commitsSinceTag, declaredVersion, declaredVersionIsTagged };
58
+ }
59
+ export function repoStateLines(state) {
60
+ if (!state)
61
+ return [];
62
+ const first = [];
63
+ if (state.branch)
64
+ first.push(`branch ${state.branch}`);
65
+ first.push(state.uncommitted === 0 ? 'working tree clean' : `${state.uncommitted} uncommitted`);
66
+ const lines = ['Where the repository actually stands (read just now):', `- ${first.join(' · ')}`];
67
+ if (state.lastTag) {
68
+ const since = state.commitsSinceTag;
69
+ lines.push(since === null ? `- last tag ${state.lastTag}`
70
+ : since === 0 ? `- at tag ${state.lastTag}`
71
+ : `- ${since} commit${since === 1 ? '' : 's'} since ${state.lastTag}`);
72
+ }
73
+ if (state.declaredVersion && state.declaredVersionIsTagged === false) {
74
+ lines.push(`- package.json declares ${state.declaredVersion}, which has no tag yet`);
75
+ }
76
+ return lines;
77
+ }