@reconcrap/people-network-memory 0.1.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 (61) hide show
  1. package/README.md +476 -0
  2. package/docs/mcp_tools.md +138 -0
  3. package/harness_adapters/openclaw/mcp.managed.unix.template.json +25 -0
  4. package/harness_adapters/openclaw/mcp.managed.windows.template.json +26 -0
  5. package/harness_adapters/openclaw/mcp.template.json +14 -0
  6. package/harness_adapters/openclaw/ppl/SKILL.md +114 -0
  7. package/package.json +30 -0
  8. package/pyproject.toml +26 -0
  9. package/scripts/install_windows.ps1 +92 -0
  10. package/scripts/npm/people-memory.js +276 -0
  11. package/scripts/people_memory_bootstrap.py +247 -0
  12. package/scripts/run_graphiti_live_from_liepin.ps1 +87 -0
  13. package/scripts/run_tests_with_artifacts.ps1 +307 -0
  14. package/src/people_network_memory/__init__.py +6 -0
  15. package/src/people_network_memory/application/__init__.py +16 -0
  16. package/src/people_network_memory/application/normalization.py +1441 -0
  17. package/src/people_network_memory/application/services.py +921 -0
  18. package/src/people_network_memory/cli.py +1212 -0
  19. package/src/people_network_memory/config.py +268 -0
  20. package/src/people_network_memory/domain/__init__.py +55 -0
  21. package/src/people_network_memory/domain/identity.py +77 -0
  22. package/src/people_network_memory/domain/models.py +355 -0
  23. package/src/people_network_memory/fixtures/__init__.py +6 -0
  24. package/src/people_network_memory/fixtures/eval.py +398 -0
  25. package/src/people_network_memory/fixtures/extractor_eval.py +364 -0
  26. package/src/people_network_memory/fixtures/generator.py +290 -0
  27. package/src/people_network_memory/fixtures/report.py +252 -0
  28. package/src/people_network_memory/graphiti_adapter/__init__.py +9 -0
  29. package/src/people_network_memory/graphiti_adapter/episode_formatter.py +70 -0
  30. package/src/people_network_memory/graphiti_adapter/graphiti_store.py +655 -0
  31. package/src/people_network_memory/graphiti_adapter/indexer.py +194 -0
  32. package/src/people_network_memory/graphiti_adapter/ontology.py +68 -0
  33. package/src/people_network_memory/harness_adapters/__init__.py +2 -0
  34. package/src/people_network_memory/harness_adapters/openclaw/__init__.py +9 -0
  35. package/src/people_network_memory/harness_adapters/openclaw/installer.py +577 -0
  36. package/src/people_network_memory/harness_adapters/openclaw/integration_eval.py +508 -0
  37. package/src/people_network_memory/harness_adapters/openclaw/smoke.py +292 -0
  38. package/src/people_network_memory/infrastructure/__init__.py +2 -0
  39. package/src/people_network_memory/infrastructure/archive_backup.py +171 -0
  40. package/src/people_network_memory/infrastructure/diagnostics.py +171 -0
  41. package/src/people_network_memory/infrastructure/embeddings.py +155 -0
  42. package/src/people_network_memory/infrastructure/file_store.py +129 -0
  43. package/src/people_network_memory/infrastructure/graphiti_promotion.py +212 -0
  44. package/src/people_network_memory/infrastructure/id_generator.py +40 -0
  45. package/src/people_network_memory/infrastructure/in_memory_store.py +1008 -0
  46. package/src/people_network_memory/infrastructure/llm_extractor.py +476 -0
  47. package/src/people_network_memory/infrastructure/llm_identity_advisor.py +200 -0
  48. package/src/people_network_memory/infrastructure/llm_judge.py +162 -0
  49. package/src/people_network_memory/infrastructure/redaction.py +21 -0
  50. package/src/people_network_memory/infrastructure/release_check.py +186 -0
  51. package/src/people_network_memory/infrastructure/retrieval_intent.py +98 -0
  52. package/src/people_network_memory/infrastructure/semantic_index.py +262 -0
  53. package/src/people_network_memory/mcp_server/__init__.py +2 -0
  54. package/src/people_network_memory/mcp_server/contracts.py +85 -0
  55. package/src/people_network_memory/mcp_server/runtime.py +133 -0
  56. package/src/people_network_memory/mcp_server/tools.py +588 -0
  57. package/src/people_network_memory/ports/__init__.py +2 -0
  58. package/src/people_network_memory/ports/errors.py +25 -0
  59. package/src/people_network_memory/ports/interfaces.py +103 -0
  60. package/src/people_network_memory/projection/__init__.py +6 -0
  61. package/src/people_network_memory/projection/builders.py +46 -0
package/README.md ADDED
@@ -0,0 +1,476 @@
1
+ # People Network Memory MCP
2
+
3
+ Local-first V1 scaffold for a personal social-memory MCP. The implementation keeps the product logic independent from Graphiti/MCP/OpenClaw so the core can be tested without external services.
4
+
5
+ ## Quick Commands
6
+
7
+ ```powershell
8
+ python -m pip install -e .
9
+ python -m unittest discover -s tests -v
10
+ people-memory start --test-mode --once
11
+ people-memory doctor --test-mode
12
+ people-memory load-fixtures --summary
13
+ people-memory eval-fixtures
14
+ people-memory eval-fixtures --failures-only --output .people-network-memory/eval-report.json
15
+ people-memory spike-graphiti
16
+ people-memory check-embedding
17
+ people-memory tool-schemas
18
+ people-memory smoke-graphiti --isolated
19
+ people-memory graphiti-gate --isolated --output .people-network-memory/graphiti-gate.json
20
+ people-memory index-graphiti --resume --limit 10 --output .people-network-memory/index-graphiti.json
21
+ people-memory graphiti-ladder --steps 1,3,10 --cumulative --output-dir .people-network-memory/test-artifacts/graphiti-ladder
22
+ people-memory smoke-openclaw
23
+ people-memory eval-harness-integration
24
+ people-memory release-check
25
+ people-memory eval-graphiti --isolated --max-interactions 3 --max-queries 3
26
+ people-memory install-openclaw --dry-run
27
+ people-memory list-reviews
28
+ people-memory backup --output .people-network-memory/backup.json
29
+ people-memory backup-archive --output .people-network-memory/backup.zip
30
+ people-memory restore --input .people-network-memory/backup.json
31
+ ```
32
+
33
+ The base test suite uses `unittest` and does not require Graphiti, Docker, or a graph
34
+ database:
35
+
36
+ ```powershell
37
+ python -m unittest discover -s tests -v
38
+ python -m people_network_memory.cli release-check
39
+ powershell -ExecutionPolicy Bypass -File .\scripts\run_tests_with_artifacts.ps1
40
+ ```
41
+
42
+ The artifact runner writes command output, JSON reports, and a manifest with
43
+ exit codes to `.people-network-memory/test-artifacts/latest/` by default. That
44
+ directory is ignored by git so local verification reports do not leak into the
45
+ package.
46
+
47
+ ## Local Install
48
+
49
+ ### npm Install
50
+
51
+ The recommended end-user distribution path is the npm wrapper. It keeps the
52
+ product code in Python, but gives OpenClaw users a familiar install/update
53
+ surface:
54
+
55
+ ```powershell
56
+ npm install -g @reconcrap/people-network-memory
57
+ people-memory doctor --test-mode
58
+ people-memory install-openclaw --backend local_json
59
+ people-memory doctor --agent openclaw
60
+ ```
61
+
62
+ The npm `people-memory` command lazily creates a private Python 3.11+ venv and
63
+ installs this package into it. The default venv locations are:
64
+
65
+ - Windows: `%LOCALAPPDATA%\people-network-memory\npm-venv`
66
+ - macOS: `~/Library/Application Support/people-network-memory/npm-venv`
67
+ - Linux: `${XDG_DATA_HOME:-~/.local/share}/people-network-memory/npm-venv`
68
+
69
+ Set `PEOPLE_MEMORY_NPM_VENV` to override that location, or
70
+ `PEOPLE_MEMORY_PYTHON` to choose a specific Python command. For Graphiti extras,
71
+ either run with `--backend graphiti` or set
72
+ `PEOPLE_MEMORY_NPM_EXTRAS=graphiti`.
73
+
74
+ When `install-openclaw` is run through the npm command, the installer writes
75
+ OpenClaw to launch the absolute Node executable plus the npm wrapper script.
76
+ That keeps the MCP server independent of shell PATH differences between visible
77
+ terminals and hidden OpenClaw gateway sessions on Windows and macOS.
78
+
79
+ Update flow:
80
+
81
+ ```powershell
82
+ npm update -g @reconcrap/people-network-memory
83
+ people-memory install-openclaw --backend local_json
84
+ ```
85
+
86
+ ### Source Checkout Install
87
+
88
+ For a clean Windows checkout, use the bootstrap script. It creates `.venv`,
89
+ installs the package, runs the test suite, runs `doctor`, and starts the MCP
90
+ server once in test mode:
91
+
92
+ ```powershell
93
+ powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1
94
+ ```
95
+
96
+ Install optional Graphiti/Kuzu dependencies as part of the same flow:
97
+
98
+ ```powershell
99
+ powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1 -Graphiti
100
+ ```
101
+
102
+ To also wire OpenClaw to a managed bootstrap command:
103
+
104
+ ```powershell
105
+ powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1 -OpenClaw
106
+ ```
107
+
108
+ The managed OpenClaw entry starts `scripts/people_memory_bootstrap.py`. On each
109
+ server start, that bootstrapper checks for a local `.venv`, creates it if
110
+ missing, installs or updates dependencies when `pyproject.toml` changes, then
111
+ launches the MCP server from the venv. This lets an AI harness repair missing
112
+ Python package dependencies without the user manually running pip.
113
+
114
+ For a trusted git checkout, add `-AutoUpdate` to let the bootstrapper run
115
+ `git pull --ff-only` before dependency checks:
116
+
117
+ ```powershell
118
+ powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1 -OpenClaw -AutoUpdate
119
+ ```
120
+
121
+ This still requires a system Python 3.11+ command to exist. On Windows the
122
+ managed entry uses `py -3.11`; on macOS/Linux it uses `python3`.
123
+
124
+ For Graphiti-backed OpenClaw, first configure the embedding and LLM environment
125
+ variables in OpenClaw or the launching shell, then run:
126
+
127
+ ```powershell
128
+ powershell -ExecutionPolicy Bypass -File .\scripts\install_windows.ps1 -Graphiti -OpenClaw -Backend graphiti
129
+ ```
130
+
131
+ The bootstrap script does not write API keys or model credentials.
132
+
133
+ For the current Windows development setup, the live Graphiti artifact run can
134
+ reuse Volcengine/Doubao embeddings and the LLM values from the Liepin screening
135
+ config:
136
+
137
+ ```powershell
138
+ $env:VOLCENGINE_API_KEY="<secret>"
139
+ powershell -ExecutionPolicy Bypass -File .\scripts\run_graphiti_live_from_liepin.ps1
140
+ ```
141
+
142
+ That wrapper maps the embedding endpoint/model to Volcengine, reads
143
+ `baseUrl`/`model`/credential from `~/.liepin-recommend-mcp/screening-config.json`
144
+ for the LLM provider, disables Graphiti telemetry, and stores verification
145
+ artifacts under `.people-network-memory/test-artifacts/graphiti-live/`.
146
+
147
+ `spike-graphiti` is the prerequisite gate. `graphiti-gate` is the promotion
148
+ gate: it keeps `local_json` as the default, runs live embedding plus a full
149
+ Graphiti/Kuzu fixture eval when providers are configured, and reports whether
150
+ Graphiti/Kuzu is ready to become the recommended recall backend.
151
+
152
+ ## Backends
153
+
154
+ - `local_json` is the default non-test backend and persists to
155
+ `~/.people-network-memory/people-memory.json`.
156
+ - `inmemory` is used for tests and quick smoke checks.
157
+ - `graphiti` is gated behind `people-memory graphiti-gate`; do not treat it as
158
+ the recommended recall backend until that command passes with live providers.
159
+ - For local Graphiti, prefer embedded Kuzu first. It avoids Docker and server setup.
160
+
161
+ Python 3.11 venv setup for Graphiti + Kuzu:
162
+
163
+ ```powershell
164
+ py -3.11 -m venv .venv
165
+ .\.venv\Scripts\python.exe -m pip install --upgrade pip
166
+ .\.venv\Scripts\python.exe -m pip install -e ".[graphiti]"
167
+ .\.venv\Scripts\python.exe -m people_network_memory.cli spike-graphiti
168
+ .\.venv\Scripts\python.exe -m people_network_memory.cli smoke-graphiti --isolated
169
+ .\.venv\Scripts\python.exe -m people_network_memory.cli eval-graphiti --isolated --max-interactions 3 --max-queries 3 --output .people-network-memory/graphiti-eval.json
170
+ .\.venv\Scripts\python.exe -m people_network_memory.cli graphiti-gate --isolated --output .people-network-memory/graphiti-gate.json
171
+ ```
172
+
173
+ Eval reports include Recall@3, Recall@5, per-category breakdowns, evidence
174
+ coverage, no-result counts, sensitive-leak counts, and optional case-level
175
+ diagnostics. When `--max-interactions` is used, evals default to queries whose
176
+ source fixture interactions were ingested. Add `--all-queries` only when you
177
+ intentionally want to test missing/unanswerable targets.
178
+
179
+ Case-level diagnostics include the query, expected people/terms, matched and
180
+ missed expected values, and the actual top retrieval results with evidence
181
+ source text/date. The artifact runner saves these full case diagnostics by
182
+ default in `eval-fixtures.json`; Graphiti live artifacts save them in
183
+ `graphiti-gate.json` and `graphiti-eval.json`.
184
+
185
+ `eval-graphiti` without `--max-*` runs the full fixture set. The small bounded
186
+ form above is only a quick smoke check. `graphiti-gate` uses the full fixture
187
+ set by default and requires Recall@3 >= 70%, Recall@5 >= 85%, complete returned
188
+ evidence, zero sensitive leaks, at least 40 checked queries, and at least 60
189
+ ingested interactions unless you intentionally bound the run.
190
+
191
+ Graphiti indexing should be treated as resumable background work. Local JSON is
192
+ the canonical capture store; `index-graphiti` reads saved local interactions and
193
+ adds compact text episodes into Graphiti/Kuzu one by one, saving progress after
194
+ each successful episode:
195
+
196
+ ```powershell
197
+ people-memory index-graphiti --resume --limit 10 --output .people-network-memory/index-graphiti.json
198
+ people-memory index-graphiti --resume --limit 10
199
+ ```
200
+
201
+ Use the ingestion ladder to find the point where the live Graphiti/LLM path
202
+ slows down or fails. Each step writes a separate JSON artifact:
203
+
204
+ ```powershell
205
+ people-memory graphiti-ladder --steps 1,3,10,20,40,90 --output-dir .people-network-memory/test-artifacts/graphiti-ladder
206
+ ```
207
+
208
+ Add `--cumulative` when testing larger rungs. It reuses one artifact-local
209
+ Graphiti/Kuzu store plus one state file, so a `20,40,90` run indexes only the
210
+ additional interactions at each step and leaves the test database under the
211
+ artifact directory:
212
+
213
+ ```powershell
214
+ people-memory graphiti-ladder --steps 20,40,90 --cumulative --output-dir .people-network-memory/test-artifacts/graphiti-ladder-cumulative
215
+ ```
216
+
217
+ If that command is interrupted, rerun it with `--resume-cumulative` against the
218
+ same output directory to keep the existing state file:
219
+
220
+ ```powershell
221
+ people-memory graphiti-ladder --steps 20,40,90 --cumulative --resume-cumulative --output-dir .people-network-memory/test-artifacts/graphiti-ladder-cumulative
222
+ ```
223
+
224
+ For slow live providers, raise the per-episode timeout without changing code:
225
+
226
+ ```powershell
227
+ $env:PEOPLE_MEMORY_GRAPHITI_ADD_TIMEOUT_SECONDS="600"
228
+ $env:PEOPLE_MEMORY_GRAPHITI_RETRY_ATTEMPTS="4"
229
+ people-memory graphiti-ladder --steps 20,40,90 --cumulative --resume-cumulative --output-dir .people-network-memory/test-artifacts/graphiti-ladder-cumulative
230
+ ```
231
+
232
+ Bounded ladder runs are diagnostics only; they cannot promote Graphiti/Kuzu to
233
+ the recommended backend.
234
+
235
+ After an existing Graphiti/Kuzu fixture graph has been indexed, evaluate search
236
+ quality without re-ingesting episodes:
237
+
238
+ ```powershell
239
+ people-memory eval-graphiti-search --data-path .people-network-memory/test-artifacts/graphiti-ladder-cumulative/cumulative-store/projection --graphiti-kuzu-path .people-network-memory/test-artifacts/graphiti-ladder-cumulative/cumulative-store/graphiti.kuzu --indexed-interactions 90 --output .people-network-memory/test-artifacts/graphiti-search/eval.json
240
+ ```
241
+
242
+ If the graph was populated by the fixture ladder before the projection cache was
243
+ hydrated, rebuild that local cache without calling Graphiti again:
244
+
245
+ ```powershell
246
+ people-memory hydrate-graphiti-cache --data-path .people-network-memory/test-artifacts/graphiti-ladder-cumulative/cumulative-store/projection --fixture-seed 42 --limit 90 --output .people-network-memory/test-artifacts/graphiti-search/cache-hydration.json
247
+ ```
248
+
249
+ Build the optional local semantic sidecar over the hydrated projection cache:
250
+
251
+ ```powershell
252
+ people-memory build-semantic-cache --data-path .people-network-memory/test-artifacts/graphiti-ladder-cumulative/cumulative-store/projection --limit 90 --reset --output .people-network-memory/test-artifacts/graphiti-search/semantic-cache.json
253
+ ```
254
+
255
+ With that sidecar present, Graphiti retrieval merges three sources: Graphiti
256
+ graph search, local semantic interaction search, and local token/event search.
257
+ The strict eval report checks intent-aware matches, not just loose token
258
+ overlap: `who mentioned X` must return the speaker, promise queries must return
259
+ follow-up items, and profile queries must combine the requested terms in one
260
+ returned result. For intentionally broad fixture queries, the report also keeps
261
+ `expected_person_rank` as a diagnostic because several mock people may satisfy
262
+ the same place/topic or company/topic query.
263
+
264
+ ## Optional LLM Retrieval Judge
265
+
266
+ The default retrieval path is deterministic and fully testable. For a final
267
+ quality pass, enable the optional OpenAI-compatible LLM judge:
268
+
269
+ ```powershell
270
+ $env:PEOPLE_MEMORY_RETRIEVAL_JUDGE="llm"
271
+ $env:PEOPLE_MEMORY_RETRIEVAL_JUDGE_TIMEOUT_SECONDS="30"
272
+ $env:PEOPLE_MEMORY_LLM_BASE_URL="<base-url>"
273
+ $env:PEOPLE_MEMORY_LLM_MODEL="<model>"
274
+ $env:PEOPLE_MEMORY_LLM_API_KEY="<secret>"
275
+ ```
276
+
277
+ When enabled, `retrieve_network_context` fetches a broader candidate set, asks
278
+ the judge to rank only candidates that directly answer the query, and falls back
279
+ to deterministic ranking if the judge fails or returns invalid JSON.
280
+
281
+ The intended harness split is hybrid:
282
+
283
+ - This tool owns social-memory retrieval quality: query expansion, graph/semantic
284
+ search, deterministic social-intent checks, optional LLM reranking, evidence,
285
+ sensitivity policy, and stable person IDs.
286
+ - The AI harness owns user-aware synthesis: applying its memory of the user's
287
+ goals, style, preferences, and current constraints to the retrieved social
288
+ evidence.
289
+ - The OpenClaw skill instructs the harness to retrieve from this MCP first,
290
+ treat returned people/network facts as source-backed evidence, then combine
291
+ them with the harness's own user memory for final recommendations, briefs,
292
+ drafts, or plans.
293
+
294
+ Run the deterministic harness integration eval to check that contract without
295
+ needing a live AI harness:
296
+
297
+ ```powershell
298
+ people-memory eval-harness-integration --output .people-network-memory/harness-integration-eval.json
299
+ ```
300
+
301
+ The eval seeds a small social graph and verifies planning, intro drafting,
302
+ conflict resolution, missing-person evidence, and follow-up cases. Each case
303
+ records the prompt, simulated harness memory, MCP tool calls, actual retrieval
304
+ results, hydrated person cards when needed, and pass/fail checks for source
305
+ boundaries.
306
+
307
+ ## LLM Ingestion Extractor
308
+
309
+ The capture path defaults to the OpenAI-compatible LLM extractor when usable,
310
+ then falls back to deterministic normalization. This improves messier Chinese,
311
+ alias, and bilingual social notes without making a fresh install depend on LLM
312
+ credentials. To provide an LLM, set:
313
+
314
+ ```powershell
315
+ $env:PEOPLE_MEMORY_INGESTION_EXTRACTOR="llm"
316
+ $env:PEOPLE_MEMORY_INGESTION_EXTRACTOR_TIMEOUT_SECONDS="30"
317
+ $env:PEOPLE_MEMORY_LLM_BASE_URL="<base-url>"
318
+ $env:PEOPLE_MEMORY_LLM_MODEL="<model>"
319
+ $env:PEOPLE_MEMORY_LLM_API_KEY="<secret>"
320
+ ```
321
+
322
+ The extractor proposes participants, aliases, topics, claims, relationships,
323
+ and follow-ups from `source_text`. The application layer still preserves the
324
+ original note as evidence, strips model-invented `person_id` values, applies the
325
+ deterministic normalizer, and sends identity ambiguity to review instead of
326
+ silently merging cards. If the extractor fails or returns invalid JSON, capture
327
+ falls back to the deterministic rules.
328
+
329
+ To force deterministic-only capture:
330
+
331
+ ```powershell
332
+ $env:PEOPLE_MEMORY_INGESTION_EXTRACTOR="off"
333
+ ```
334
+
335
+ OpenClaw installs default to `PEOPLE_MEMORY_INGESTION_EXTRACTOR=llm`. Use
336
+ `people-memory install-openclaw --ingestion-extractor off` only when you want to
337
+ disable the LLM extraction pass for that harness.
338
+
339
+ ## Embeddings
340
+
341
+ Local-first default recommendation:
342
+
343
+ ```powershell
344
+ $env:PEOPLE_MEMORY_EMBEDDING_PROVIDER="ollama"
345
+ $env:PEOPLE_MEMORY_EMBEDDING_BASE_URL="http://localhost:11434/v1"
346
+ $env:PEOPLE_MEMORY_EMBEDDING_MODEL="nomic-embed-text"
347
+ people-memory check-embedding
348
+ ```
349
+
350
+ OpenAI-compatible cloud endpoints use the same command with:
351
+
352
+ ```powershell
353
+ $env:PEOPLE_MEMORY_EMBEDDING_PROVIDER="openai_compatible"
354
+ $env:PEOPLE_MEMORY_EMBEDDING_BASE_URL="https://ark.cn-beijing.volces.com/api/coding/v3"
355
+ $env:PEOPLE_MEMORY_EMBEDDING_MODEL="doubao-embedding-vision-251215"
356
+ $env:PEOPLE_MEMORY_EMBEDDING_API_KEY="<secret>"
357
+ people-memory check-embedding
358
+ ```
359
+
360
+ Do not commit API keys or write them into config files.
361
+
362
+ ## Sensitivity Policy
363
+
364
+ Sensitivity labels such as `sensitive` and `do_not_surface_unprompted` are kept
365
+ as metadata, but V1 defaults to `personal` surfacing because this is a private
366
+ single-user memory tool.
367
+
368
+ ```powershell
369
+ $env:PEOPLE_MEMORY_SENSITIVITY_POLICY="personal" # private recall includes sensitive context
370
+ $env:PEOPLE_MEMORY_SENSITIVITY_POLICY="strict" # hide sensitive context unless explicitly requested
371
+ $env:PEOPLE_MEMORY_SENSITIVITY_POLICY="task_aware" # include for private recall, hide for shareable output
372
+ ```
373
+
374
+ The MCP retrieval tool also accepts `sensitivity_policy`, `output_context`, and
375
+ the explicit `include_sensitive` override per request.
376
+
377
+ Graphiti also needs an LLM provider for episode extraction. Embeddings alone are
378
+ enough for vector smoke checks, but not enough for live Graphiti ingestion.
379
+ Some OpenAI-compatible gateways do not support `response_format`; leave
380
+ `PEOPLE_MEMORY_LLM_RESPONSE_FORMAT` unset or set it to `none` for those
381
+ providers. Use `json_object` or `json_schema` only when the provider explicitly
382
+ supports that mode.
383
+
384
+ ```powershell
385
+ $env:PEOPLE_MEMORY_BACKEND="graphiti"
386
+ $env:PEOPLE_MEMORY_GRAPH_BACKEND="kuzu"
387
+ $env:PEOPLE_MEMORY_LLM_PROVIDER="openai_compatible"
388
+ $env:PEOPLE_MEMORY_LLM_BASE_URL="<base-url>"
389
+ $env:PEOPLE_MEMORY_LLM_MODEL="<model>"
390
+ $env:PEOPLE_MEMORY_LLM_API_KEY="<secret>"
391
+ $env:PEOPLE_MEMORY_LLM_RESPONSE_FORMAT="none"
392
+ .\.venv\Scripts\python.exe -m people_network_memory.cli smoke-graphiti --isolated
393
+ ```
394
+
395
+ `reset` is intentionally guarded:
396
+
397
+ ```powershell
398
+ people-memory reset --confirm DELETE
399
+ ```
400
+
401
+ It deletes only the configured local JSON data file for `local_json`.
402
+
403
+ ## Backup
404
+
405
+ Use JSON backup for portable person-card projection data:
406
+
407
+ ```powershell
408
+ people-memory backup --output .people-network-memory/backup.json
409
+ people-memory restore --input .people-network-memory/backup.json
410
+ ```
411
+
412
+ Use archive backup when the backend has local storage beyond the projection
413
+ cache. For `graphiti` + Kuzu, the archive includes `projection.json` and the
414
+ configured Kuzu database directory:
415
+
416
+ ```powershell
417
+ people-memory backup-archive --backend graphiti --output .people-network-memory/graphiti-backup.zip
418
+ people-memory restore-archive --backend graphiti --input .people-network-memory/graphiti-backup.zip --confirm OVERWRITE
419
+ ```
420
+
421
+ `restore-archive` requires explicit confirmation and rejects unsafe archive
422
+ member paths.
423
+
424
+ ## Low-Friction Capture
425
+
426
+ The MCP tool accepts raw `source_text` first. If the harness can confidently
427
+ extract structure, it should include it. If not, it can still send the original
428
+ note and the server will conservatively normalize obvious people, places,
429
+ topics, mentions, work/school facts, contacts, interests, and follow-ups.
430
+
431
+ ## Review Queue
432
+
433
+ Ambiguous identity matches are captured without blocking the original note. Use
434
+ the review commands to clean them up later:
435
+
436
+ ```powershell
437
+ people-memory list-reviews
438
+ people-memory resolve-review --review-id review_0001 --source-person-id person_0003 --target-person-id alice
439
+ people-memory dismiss-review --review-id review_0002 --note "not enough information"
440
+ ```
441
+
442
+ Resolving an identity review merges the source person into the target person,
443
+ preserves aliases, interactions, facts, claims, follow-ups, relationships, and
444
+ evidence, then marks the review item as resolved.
445
+
446
+ ## OpenClaw
447
+
448
+ Install or preview the OpenClaw adapter:
449
+
450
+ ```powershell
451
+ people-memory install-openclaw --dry-run
452
+ people-memory install-openclaw
453
+ people-memory install-openclaw --managed-bootstrap
454
+ people-memory doctor --agent openclaw
455
+ people-memory smoke-openclaw
456
+ people-memory eval-harness-integration
457
+ ```
458
+
459
+ The installer updates only the `people-network-memory` MCP server entry in the
460
+ active OpenClaw config. Current OpenClaw builds use `~/.openclaw/openclaw.json`
461
+ under `mcp.servers`; when that file exists the installer updates it, and also
462
+ maintains the legacy/generic `~/.openclaw/mcp.json` shape for older MCP
463
+ harnesses. It preserves unrelated MCP servers and writes the mirrored skill to
464
+ `~/.openclaw/skills/ppl/SKILL.md`. The MCP server namespace remains
465
+ `people-network-memory` for tool compatibility, but the user-facing OpenClaw
466
+ slash trigger is `/ppl`; `/people_network_memory` and `/people-network-memory`
467
+ remain accepted aliases for existing prompts.
468
+ By default it uses the active Python executable with
469
+ `-m people_network_memory.cli start`, so it does not require the `people-memory`
470
+ console script to be on PATH. For end-user harness installs, prefer
471
+ `--managed-bootstrap`: that stores a tiny stdlib launcher in the MCP command so
472
+ the harness can recreate the venv and refresh Python dependencies automatically.
473
+
474
+ `smoke-openclaw` installs into a temporary OpenClaw home by default, checks the
475
+ adapter config and skill text, verifies prompt-routing examples, and exercises
476
+ the three public MCP workflows with the test backend.
@@ -0,0 +1,138 @@
1
+ # MCP Tool Contract
2
+
3
+ V1 exposes exactly three public tools. The machine-readable source of truth is:
4
+
5
+ ```powershell
6
+ people-memory tool-schemas
7
+ ```
8
+
9
+ Adapters should treat the schema as stable within contract version `v1`.
10
+
11
+ ## record_interaction
12
+
13
+ Use for a meeting, coffee, dinner, call, message, intro, event, or loose memory
14
+ note. The required field is `source_text`; all structured fields are optional so
15
+ the harness can preserve the user's original wording and add structure only when
16
+ it can do so confidently.
17
+
18
+ The server performs conservative normalization for obvious raw notes. By
19
+ default, `PEOPLE_MEMORY_INGESTION_EXTRACTOR=llm` lets an OpenAI-compatible LLM
20
+ propose structure first when LLM provider settings are available; without those
21
+ settings, capture starts directly with deterministic normalization. Either way,
22
+ the same identity policy, evidence preservation, and review rules still run.
23
+ For example, `source_text` alone can capture simple patterns such as:
24
+
25
+ - `Met Alice Zhang at Blue Bottle. We discussed robotics hiring. Alice mentioned Bob.`
26
+ - `Remember Alice Zhang. Alice works at Tencent Robotics as product lead. Alice studied at Tsinghua. Email alice@example.com.`
27
+ - `在Blue Bottle见了Alice Zhang,聊了robotics hiring,Alice Zhang提到Henry Guo。`
28
+ - `今天在潘家园见了胡八一(胖子),聊了北京的项目。胖子提到王凯。`
29
+
30
+ The harness should still pass structured fields when it has them, but it does
31
+ not need to interrupt the user just to fill a form.
32
+
33
+ Important modeling rules:
34
+
35
+ - Put people who were present in `participants`.
36
+ - Put people discussed but not present in `mentioned_people`.
37
+ - Store "A said B ..." in `attributed_claims`, not as a direct fact about B.
38
+ - Store relationship phrases such as "A knows B", "A works with B", or
39
+ "A introduced me to B" in `relationships`. If B is not already known, the
40
+ service creates a provisional second-degree card and returns a non-blocking
41
+ enrichment item.
42
+ - Preserve Chinese names and aliases exactly. Explicit alias forms such as
43
+ `胡八一(胖子)`, `胡八一又叫胖子`, and `胡八一绰号胖子` are modeled as one
44
+ canonical person with `胖子` as an alias unless the server returns an identity
45
+ review because the alias already points to a different card.
46
+ - Store promises and next actions in `follow_ups`.
47
+ - Preserve sensitivity labels when the user marks something private, sensitive,
48
+ secondhand, unverified, or not to surface unprompted.
49
+
50
+ Output fields that matter for harness autonomy:
51
+
52
+ - `capture_summary`: a short structured checkpoint the harness should show the
53
+ user after saving, including people created/updated, key details, follow-ups,
54
+ review items, and a correction hint.
55
+ - `captured_follow_ups`: follow-ups preserved from the capture.
56
+ - `post_capture_opportunities`: a structured list of useful next actions the
57
+ harness may take after capture.
58
+ - `harness_context_requests`: suggested ways for the harness to use its own
59
+ memory or available tools to enrich the result.
60
+ - `needs_review`: ambiguity or data-quality items that should be handled
61
+ carefully rather than silently auto-merged.
62
+
63
+ `post_capture_opportunities` include `recommended_default`, `risk_level`,
64
+ `reversibility`, `external_visibility`, `requires_confirmation`, `undo_hint`,
65
+ related people, and evidence. A harness should proactively execute low-risk,
66
+ private/local, easily reversible opportunities when supported, then report what
67
+ it did and how to undo it. It should ask first before externally visible,
68
+ costly, destructive, privacy-sensitive, or hard-to-reverse actions such as
69
+ sending messages, inviting other people to calendar events, merging ambiguous
70
+ identities, deleting data, or publishing information.
71
+
72
+ The harness should show the `capture_summary` every time because it is the
73
+ fastest way for the user to catch mistakes immediately, such as "this was a
74
+ different Alice", "that follow-up is wrong", or "remove that sensitive note".
75
+
76
+ ## retrieve_network_context
77
+
78
+ Use for vague recall, relationship questions, and pre-meeting briefs.
79
+
80
+ Input:
81
+
82
+ - `query`: required natural-language query.
83
+ - `limit`: optional result limit from 1 to 50, default 10.
84
+ - `include_sensitive`: optional override. Use `true` to force sensitive facts
85
+ into the response, `false` to force-hide them, or omit it to use policy.
86
+ - `sensitivity_policy`: optional `personal`, `strict`, or `task_aware`.
87
+ The default app policy is `personal` because this V1 is a single-user private
88
+ memory tool.
89
+ - `output_context`: `private` or `shareable`, default `private`. In
90
+ `task_aware` mode, sensitive facts are included only for private recall and
91
+ hidden for shareable drafts or messages.
92
+ - `mode`: `recall` or `brief`.
93
+
94
+ Every result should include evidence, confidence-bearing source notes, and
95
+ `why_matched`.
96
+
97
+ Sensitivity labels are still preserved as metadata. They control surfacing
98
+ policy; they do not delete or weaken the underlying memory.
99
+
100
+ Harness integration guidance:
101
+
102
+ - Treat this tool as the source of truth for people/network memory: social
103
+ notes, relationships, claims, follow-ups, and person-card facts.
104
+ - Treat the AI harness's own memory as the source of truth for user-level
105
+ preferences, work style, current projects, and prior instructions.
106
+ - Retrieve from this tool first, then let the harness combine the returned
107
+ evidence with its own user memory to curate the final answer.
108
+ - If tool evidence and harness memory conflict about a person or interaction,
109
+ prefer the tool evidence for social facts and mention uncertainty only when it
110
+ affects the answer.
111
+ - If the tool has no matching evidence, the harness may still use its own user
112
+ memory, but it should clearly separate that inference from social-graph
113
+ recall.
114
+ - For task curation, such as dinner planning or intro drafting, retrieve with
115
+ the user's full task constraints, optionally call `get_person` for shortlisted
116
+ candidates, then explain recommendations using both source-backed social
117
+ evidence and user-preference context.
118
+
119
+ The deterministic harness integration eval checks this behavior without
120
+ requiring a live AI harness:
121
+
122
+ ```powershell
123
+ people-memory eval-harness-integration --output .people-network-memory/harness-integration-eval.json
124
+ ```
125
+
126
+ The eval report includes the prompt, simulated harness memory, MCP tool calls,
127
+ actual retrieval results, hydrated person cards, and source-boundary checks for
128
+ each case.
129
+
130
+ ## get_person
131
+
132
+ Use when the caller already has a stable `person_id`, usually after retrieval.
133
+ The tool also accepts `name` as a best-effort harness fallback because some AI
134
+ harnesses may ask for a card by visible person name after capture or recall.
135
+ When both are available, prefer `person_id`.
136
+
137
+ The response returns either a full person card with `found: true`, or a small
138
+ missing response with `found: false` and `missing_info`.
@@ -0,0 +1,25 @@
1
+ {
2
+ "mcpServers": {
3
+ "people-network-memory": {
4
+ "command": "python3",
5
+ "args": [
6
+ "__REPO_ROOT__/scripts/people_memory_bootstrap.py",
7
+ "run",
8
+ "--repo",
9
+ "__REPO_ROOT__",
10
+ "--venv",
11
+ "__REPO_ROOT__/.venv",
12
+ "--backend",
13
+ "local_json",
14
+ "--extra",
15
+ "base"
16
+ ],
17
+ "env": {
18
+ "PEOPLE_MEMORY_BACKEND": "local_json",
19
+ "PEOPLE_MEMORY_INGESTION_EXTRACTOR": "llm",
20
+ "PEOPLE_MEMORY_SENSITIVITY_POLICY": "personal",
21
+ "GRAPHITI_TELEMETRY_ENABLED": "false"
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "mcpServers": {
3
+ "people-network-memory": {
4
+ "command": "py",
5
+ "args": [
6
+ "-3.11",
7
+ "__REPO_ROOT__\\scripts\\people_memory_bootstrap.py",
8
+ "run",
9
+ "--repo",
10
+ "__REPO_ROOT__",
11
+ "--venv",
12
+ "__REPO_ROOT__\\.venv",
13
+ "--backend",
14
+ "local_json",
15
+ "--extra",
16
+ "base"
17
+ ],
18
+ "env": {
19
+ "PEOPLE_MEMORY_BACKEND": "local_json",
20
+ "PEOPLE_MEMORY_INGESTION_EXTRACTOR": "llm",
21
+ "PEOPLE_MEMORY_SENSITIVITY_POLICY": "personal",
22
+ "GRAPHITI_TELEMETRY_ENABLED": "false"
23
+ }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "mcpServers": {
3
+ "people-network-memory": {
4
+ "command": "python",
5
+ "args": ["scripts/people_memory_bootstrap.py", "run", "--repo", ".", "--venv", ".venv"],
6
+ "env": {
7
+ "PEOPLE_MEMORY_BACKEND": "local_json",
8
+ "PEOPLE_MEMORY_INGESTION_EXTRACTOR": "llm",
9
+ "PEOPLE_MEMORY_SENSITIVITY_POLICY": "personal",
10
+ "GRAPHITI_TELEMETRY_ENABLED": "false"
11
+ }
12
+ }
13
+ }
14
+ }