common-memory-core 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/.env.sample +3 -0
- package/CHANGELOG.md +39 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/SECURITY.md +48 -0
- package/dist/cli/codex/transcript-0.153.4.d.ts +20 -0
- package/dist/cli/codex/transcript-0.153.4.d.ts.map +1 -0
- package/dist/cli/codex/transcript-0.153.4.js +78 -0
- package/dist/cli/codex/transcript-0.153.4.js.map +1 -0
- package/dist/cli/codex-config.d.ts +2 -0
- package/dist/cli/codex-config.d.ts.map +1 -0
- package/dist/cli/codex-config.js +5 -0
- package/dist/cli/codex-config.js.map +1 -0
- package/dist/cli/codex-hook.d.ts +18 -0
- package/dist/cli/codex-hook.d.ts.map +1 -0
- package/dist/cli/codex-hook.js +140 -0
- package/dist/cli/codex-hook.js.map +1 -0
- package/dist/cli/codex-session.d.ts +3 -0
- package/dist/cli/codex-session.d.ts.map +1 -0
- package/dist/cli/codex-session.js +3 -0
- package/dist/cli/codex-session.js.map +1 -0
- package/dist/cli/flush-command.d.ts +6 -0
- package/dist/cli/flush-command.d.ts.map +1 -0
- package/dist/cli/flush-command.js +30 -0
- package/dist/cli/flush-command.js.map +1 -0
- package/dist/cli/host-launch.d.ts +28 -0
- package/dist/cli/host-launch.d.ts.map +1 -0
- package/dist/cli/host-launch.js +16 -0
- package/dist/cli/host-launch.js.map +1 -0
- package/dist/cli/host-process.d.ts +3 -0
- package/dist/cli/host-process.d.ts.map +1 -0
- package/dist/cli/host-process.js +35 -0
- package/dist/cli/host-process.js.map +1 -0
- package/dist/cli/host-session.d.ts +22 -0
- package/dist/cli/host-session.d.ts.map +1 -0
- package/dist/cli/host-session.js +204 -0
- package/dist/cli/host-session.js.map +1 -0
- package/dist/cli/import-command.d.ts +20 -0
- package/dist/cli/import-command.d.ts.map +1 -0
- package/dist/cli/import-command.js +98 -0
- package/dist/cli/import-command.js.map +1 -0
- package/dist/cli/interactive-process.d.ts +3 -0
- package/dist/cli/interactive-process.d.ts.map +1 -0
- package/dist/cli/interactive-process.js +15 -0
- package/dist/cli/interactive-process.js.map +1 -0
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +151 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/mcp-config.d.ts +16 -0
- package/dist/cli/mcp-config.d.ts.map +1 -0
- package/dist/cli/mcp-config.js +108 -0
- package/dist/cli/mcp-config.js.map +1 -0
- package/dist/cli/network-test.d.ts +4 -0
- package/dist/cli/network-test.d.ts.map +1 -0
- package/dist/cli/network-test.js +28 -0
- package/dist/cli/network-test.js.map +1 -0
- package/dist/cli/operations.d.ts +26 -0
- package/dist/cli/operations.d.ts.map +1 -0
- package/dist/cli/operations.js +55 -0
- package/dist/cli/operations.js.map +1 -0
- package/dist/cli/session-drain.d.ts +3 -0
- package/dist/cli/session-drain.d.ts.map +1 -0
- package/dist/cli/session-drain.js +34 -0
- package/dist/cli/session-drain.js.map +1 -0
- package/dist/cli/storage-paths.d.ts +4 -0
- package/dist/cli/storage-paths.d.ts.map +1 -0
- package/dist/cli/storage-paths.js +15 -0
- package/dist/cli/storage-paths.js.map +1 -0
- package/dist/cli/tui-integrations.d.ts +4 -0
- package/dist/cli/tui-integrations.d.ts.map +1 -0
- package/dist/cli/tui-integrations.js +143 -0
- package/dist/cli/tui-integrations.js.map +1 -0
- package/dist/cli/tui-prompts.d.ts +22 -0
- package/dist/cli/tui-prompts.d.ts.map +1 -0
- package/dist/cli/tui-prompts.js +64 -0
- package/dist/cli/tui-prompts.js.map +1 -0
- package/dist/cli/tui-settings.d.ts +21 -0
- package/dist/cli/tui-settings.d.ts.map +1 -0
- package/dist/cli/tui-settings.js +198 -0
- package/dist/cli/tui-settings.js.map +1 -0
- package/dist/cli/tui.d.ts +4 -0
- package/dist/cli/tui.d.ts.map +1 -0
- package/dist/cli/tui.js +292 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/cli/work-config.d.ts +24 -0
- package/dist/cli/work-config.d.ts.map +1 -0
- package/dist/cli/work-config.js +147 -0
- package/dist/cli/work-config.js.map +1 -0
- package/dist/config/config.d.ts +41 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +193 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/private-env.d.ts +8 -0
- package/dist/config/private-env.d.ts.map +1 -0
- package/dist/config/private-env.js +38 -0
- package/dist/config/private-env.js.map +1 -0
- package/dist/config/runtime.d.ts +32 -0
- package/dist/config/runtime.d.ts.map +1 -0
- package/dist/config/runtime.js +85 -0
- package/dist/config/runtime.js.map +1 -0
- package/dist/core/contracts/errors.d.ts +10 -0
- package/dist/core/contracts/errors.d.ts.map +1 -0
- package/dist/core/contracts/errors.js +23 -0
- package/dist/core/contracts/errors.js.map +1 -0
- package/dist/core/safety/external-preflight.d.ts +7 -0
- package/dist/core/safety/external-preflight.d.ts.map +1 -0
- package/dist/core/safety/external-preflight.js +47 -0
- package/dist/core/safety/external-preflight.js.map +1 -0
- package/dist/core/safety/redaction.d.ts +2 -0
- package/dist/core/safety/redaction.d.ts.map +1 -0
- package/dist/core/safety/redaction.js +4 -0
- package/dist/core/safety/redaction.js.map +1 -0
- package/dist/core/safety/rules.d.ts +6 -0
- package/dist/core/safety/rules.d.ts.map +1 -0
- package/dist/core/safety/rules.js +14 -0
- package/dist/core/safety/rules.js.map +1 -0
- package/dist/core/safety/scanner.d.ts +11 -0
- package/dist/core/safety/scanner.d.ts.map +1 -0
- package/dist/core/safety/scanner.js +18 -0
- package/dist/core/safety/scanner.js.map +1 -0
- package/dist/core/transaction/fsync.d.ts +6 -0
- package/dist/core/transaction/fsync.d.ts.map +1 -0
- package/dist/core/transaction/fsync.js +41 -0
- package/dist/core/transaction/fsync.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/ingress.d.ts +61 -0
- package/dist/mcp/ingress.d.ts.map +1 -0
- package/dist/mcp/ingress.js +134 -0
- package/dist/mcp/ingress.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +92 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/stdio.d.ts +5 -0
- package/dist/mcp/stdio.d.ts.map +1 -0
- package/dist/mcp/stdio.js +115 -0
- package/dist/mcp/stdio.js.map +1 -0
- package/dist/memory-manager/contracts/diagnostic.d.ts +14 -0
- package/dist/memory-manager/contracts/diagnostic.d.ts.map +1 -0
- package/dist/memory-manager/contracts/diagnostic.js +17 -0
- package/dist/memory-manager/contracts/diagnostic.js.map +1 -0
- package/dist/memory-manager/contracts/disclosure.d.ts +12 -0
- package/dist/memory-manager/contracts/disclosure.d.ts.map +1 -0
- package/dist/memory-manager/contracts/disclosure.js +8 -0
- package/dist/memory-manager/contracts/disclosure.js.map +1 -0
- package/dist/memory-manager/contracts/errors.d.ts +15 -0
- package/dist/memory-manager/contracts/errors.d.ts.map +1 -0
- package/dist/memory-manager/contracts/errors.js +25 -0
- package/dist/memory-manager/contracts/errors.js.map +1 -0
- package/dist/memory-manager/contracts/model-port.d.ts +38 -0
- package/dist/memory-manager/contracts/model-port.d.ts.map +1 -0
- package/dist/memory-manager/contracts/model-port.js +2 -0
- package/dist/memory-manager/contracts/model-port.js.map +1 -0
- package/dist/memory-manager/network/client.d.ts +13 -0
- package/dist/memory-manager/network/client.d.ts.map +1 -0
- package/dist/memory-manager/network/client.js +122 -0
- package/dist/memory-manager/network/client.js.map +1 -0
- package/dist/memory-manager/network/route.d.ts +31 -0
- package/dist/memory-manager/network/route.d.ts.map +1 -0
- package/dist/memory-manager/network/route.js +148 -0
- package/dist/memory-manager/network/route.js.map +1 -0
- package/dist/memory-manager/openai/abort.d.ts +4 -0
- package/dist/memory-manager/openai/abort.d.ts.map +1 -0
- package/dist/memory-manager/openai/abort.js +19 -0
- package/dist/memory-manager/openai/abort.js.map +1 -0
- package/dist/memory-manager/openai/bounded-body.d.ts +2 -0
- package/dist/memory-manager/openai/bounded-body.d.ts.map +1 -0
- package/dist/memory-manager/openai/bounded-body.js +49 -0
- package/dist/memory-manager/openai/bounded-body.js.map +1 -0
- package/dist/memory-manager/openai/openai-chat-adapter.d.ts +16 -0
- package/dist/memory-manager/openai/openai-chat-adapter.d.ts.map +1 -0
- package/dist/memory-manager/openai/openai-chat-adapter.js +51 -0
- package/dist/memory-manager/openai/openai-chat-adapter.js.map +1 -0
- package/dist/memory-manager/openai/openai-responses-adapter.d.ts +15 -0
- package/dist/memory-manager/openai/openai-responses-adapter.d.ts.map +1 -0
- package/dist/memory-manager/openai/openai-responses-adapter.js +14 -0
- package/dist/memory-manager/openai/openai-responses-adapter.js.map +1 -0
- package/dist/memory-manager/openai/options.d.ts +14 -0
- package/dist/memory-manager/openai/options.d.ts.map +1 -0
- package/dist/memory-manager/openai/options.js +29 -0
- package/dist/memory-manager/openai/options.js.map +1 -0
- package/dist/memory-manager/openai/remote-http.d.ts +33 -0
- package/dist/memory-manager/openai/remote-http.d.ts.map +1 -0
- package/dist/memory-manager/openai/remote-http.js +207 -0
- package/dist/memory-manager/openai/remote-http.js.map +1 -0
- package/dist/memory-manager/openai/response-decoder.d.ts +3 -0
- package/dist/memory-manager/openai/response-decoder.d.ts.map +1 -0
- package/dist/memory-manager/openai/response-decoder.js +57 -0
- package/dist/memory-manager/openai/response-decoder.js.map +1 -0
- package/dist/memory-manager/openai/retry.d.ts +8 -0
- package/dist/memory-manager/openai/retry.d.ts.map +1 -0
- package/dist/memory-manager/openai/retry.js +18 -0
- package/dist/memory-manager/openai/retry.js.map +1 -0
- package/dist/pi-extension/extraction-runtime.d.ts +51 -0
- package/dist/pi-extension/extraction-runtime.d.ts.map +1 -0
- package/dist/pi-extension/extraction-runtime.js +87 -0
- package/dist/pi-extension/extraction-runtime.js.map +1 -0
- package/dist/pi-extension/index.d.ts +19 -0
- package/dist/pi-extension/index.d.ts.map +1 -0
- package/dist/pi-extension/index.js +172 -0
- package/dist/pi-extension/index.js.map +1 -0
- package/dist/v2/canonical.d.ts +53 -0
- package/dist/v2/canonical.d.ts.map +1 -0
- package/dist/v2/canonical.js +321 -0
- package/dist/v2/canonical.js.map +1 -0
- package/dist/v2/contract.d.ts +34 -0
- package/dist/v2/contract.d.ts.map +1 -0
- package/dist/v2/contract.js +53 -0
- package/dist/v2/contract.js.map +1 -0
- package/dist/v2/document-import.d.ts +100 -0
- package/dist/v2/document-import.d.ts.map +1 -0
- package/dist/v2/document-import.js +259 -0
- package/dist/v2/document-import.js.map +1 -0
- package/dist/v2/errors.d.ts +6 -0
- package/dist/v2/errors.d.ts.map +1 -0
- package/dist/v2/errors.js +29 -0
- package/dist/v2/errors.js.map +1 -0
- package/dist/v2/import.d.ts +26 -0
- package/dist/v2/import.d.ts.map +1 -0
- package/dist/v2/import.js +48 -0
- package/dist/v2/import.js.map +1 -0
- package/dist/v2/lock.d.ts +3 -0
- package/dist/v2/lock.d.ts.map +1 -0
- package/dist/v2/lock.js +47 -0
- package/dist/v2/lock.js.map +1 -0
- package/dist/v2/memory-maintainer.md +38 -0
- package/dist/v2/read-guidance.d.ts +3 -0
- package/dist/v2/read-guidance.d.ts.map +1 -0
- package/dist/v2/read-guidance.js +3 -0
- package/dist/v2/read-guidance.js.map +1 -0
- package/dist/v2/reader.d.ts +25 -0
- package/dist/v2/reader.d.ts.map +1 -0
- package/dist/v2/reader.js +38 -0
- package/dist/v2/reader.js.map +1 -0
- package/dist/v2/registry.d.ts +14 -0
- package/dist/v2/registry.d.ts.map +1 -0
- package/dist/v2/registry.js +46 -0
- package/dist/v2/registry.js.map +1 -0
- package/dist/v2/runtime.d.ts +133 -0
- package/dist/v2/runtime.d.ts.map +1 -0
- package/dist/v2/runtime.js +326 -0
- package/dist/v2/runtime.js.map +1 -0
- package/dist/v2/session-drain.d.ts +14 -0
- package/dist/v2/session-drain.d.ts.map +1 -0
- package/dist/v2/session-drain.js +16 -0
- package/dist/v2/session-drain.js.map +1 -0
- package/dist/v2/session.d.ts +54 -0
- package/dist/v2/session.d.ts.map +1 -0
- package/dist/v2/session.js +158 -0
- package/dist/v2/session.js.map +1 -0
- package/dist/v2/writer.d.ts +40 -0
- package/dist/v2/writer.d.ts.map +1 -0
- package/dist/v2/writer.js +327 -0
- package/dist/v2/writer.js.map +1 -0
- package/docs/00-index.md +19 -0
- package/docs/03-target-architecture.md +49 -0
- package/docs/init-v0.1-closeout.md +152 -0
- package/docs/init-v0.1-design.md +237 -0
- package/docs/init-v0.1-verification.md +303 -0
- package/docs/outbound-network-design.md +100 -0
- package/docs/outbound-network-verification.json +300 -0
- package/docs/provider-verification.md +94 -0
- package/docs/releasing.md +138 -0
- package/docs/session-integration.md +134 -0
- package/docs/tui-workbench.md +173 -0
- package/docs/usage.md +815 -0
- package/docs/v2-ablation-results.json +12035 -0
- package/docs/v2-ablation.md +117 -0
- package/docs/v2-evaluation-repeat-results.json +7 -0
- package/docs/v2-evaluation-scripted-results.json +67 -0
- package/docs/v2-evaluation.md +35 -0
- package/docs/v2-optimization-plan.md +23 -0
- package/docs/v2-performance-baseline-runtime.js.txt +231 -0
- package/docs/v2-performance-baseline.json +338 -0
- package/docs/v2-performance-behavior-equivalence.json +17 -0
- package/docs/v2-performance-results.json +585 -0
- package/docs/v2-performance.md +88 -0
- package/docs/v2-replacement-test-map.md +14 -0
- package/docs/v2-verification.md +49 -0
- package/package.json +87 -0
package/docs/usage.md
ADDED
|
@@ -0,0 +1,815 @@
|
|
|
1
|
+
# Common Memory v0.2 — 使用与配置
|
|
2
|
+
|
|
3
|
+
Durable, user-owned memory maintenance for Pi and local MCP hosts, plus authorized
|
|
4
|
+
read-only disclosure of the resulting Markdown to Pi, Codex CLI and other local MCP
|
|
5
|
+
consumers. Markdown is the authority for current long-term content; SQLite stores
|
|
6
|
+
pending deliveries, observations, jobs, leases, source links and recovery metadata.
|
|
7
|
+
There is no Fact/Recall/Undo compatibility layer, search index, temporary memory
|
|
8
|
+
product, or resident background service. Reading returns the current documents as
|
|
9
|
+
they are; there is no retrieval ranking.
|
|
10
|
+
|
|
11
|
+
Init v0.1 (`docs/init-v0.1-design.md`, `docs/init-v0.1-verification.md`) adds the
|
|
12
|
+
cross-agent loop: another agent (ChatGPT desktop) imports its existing understanding
|
|
13
|
+
through `memory_init`, the user imports local Markdown files with `common-memory import`,
|
|
14
|
+
the unchanged Writer decides what to keep from either, and Codex CLI (native session hooks or MCP `memory_read`)
|
|
15
|
+
and Pi (system-prompt injection) read the same canonical files. On Windows, Common
|
|
16
|
+
Memory runs inside WSL and the ChatGPT/Codex desktop app reaches it through `wsl.exe`
|
|
17
|
+
(`common-memory mcp-config --wsl`).
|
|
18
|
+
|
|
19
|
+
配套的 Writer 评测规范已迁移到独立仓库:[Memory Benchmark](https://github.com/Mr-remon219/memory-benchmark)。
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
Requires Node.js 24. Install with `npm install -g common-memory-core@0.2.0`, then run
|
|
24
|
+
`common-memory`. Source contributors can use `npm ci && npm run build` followed by
|
|
25
|
+
`node dist/cli/main.js`. The default interactive workbench brings
|
|
26
|
+
configuration, memory browsing/import, projects and permissions, integration management,
|
|
27
|
+
and queue/session maintenance into one navigable interface. The local wizard writes
|
|
28
|
+
`~/.common-memory/config.json` and, when local credentials are supplied, a private
|
|
29
|
+
`.env` file (`COMMON_MEMORY_HOME` overrides this location). Configure an OpenAI-compatible
|
|
30
|
+
API root and choose a request mode in `remote.api` (omitted means `responses`).
|
|
31
|
+
Responses uses strict Structured Outputs; `chat_completions` uses JSON object mode
|
|
32
|
+
with the complete maintenance schema in the system message. Both use the same Core
|
|
33
|
+
validation and commit path. Keys are never stored in canonical memory.
|
|
34
|
+
V2 requires configuration `schemaVersion: 2`; pre-V2 configuration/data is not migrated
|
|
35
|
+
or automatically deleted. Existing V2 configurations remain valid; the V2 jobs table
|
|
36
|
+
receives an idempotent, transactional nullable diagnostic column when opened.
|
|
37
|
+
|
|
38
|
+
Optional fields in `remote` (Settings → Advanced tuning in the workbench, or edit
|
|
39
|
+
`config.json`). API keys remain in private `.env`; ordinary model edits can keep existing
|
|
40
|
+
or external credentials, and preserve unrelated configuration:
|
|
41
|
+
|
|
42
|
+
| Field | Accepted values / effect |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `api` | `responses` (default) or `chat_completions`; explicit selection, no fallback |
|
|
45
|
+
| `maxOutputTokens` | Integer 1–16384; default 4096; `max_output_tokens` for Responses, `max_tokens` for Chat |
|
|
46
|
+
| `reasoningEffort` | Responses only: `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`; sent as `reasoning.effort` |
|
|
47
|
+
| `thinking` | Chat only: `{ "type": "enabled" }` or `{ "type": "disabled" }` |
|
|
48
|
+
| `enableThinking` | Chat only: boolean, sent as `enable_thinking`; mutually exclusive with `thinking` |
|
|
49
|
+
|
|
50
|
+
Unconfigured thinking/effort fields are omitted. The endpoint and model must support
|
|
51
|
+
the selected fields; there is no brand detection, automatic parameter translation or
|
|
52
|
+
arbitrary body-field forwarding. The default Writer deadline remains 60 seconds.
|
|
53
|
+
Current provider evidence and the reusable verification procedure are recorded in
|
|
54
|
+
[Provider verification](provider-verification.md); earlier experiments remain in
|
|
55
|
+
[Init v0.1 closeout verification](init-v0.1-closeout.md).
|
|
56
|
+
|
|
57
|
+
Register the built package as a Pi extension using the package's `pi.extensions`
|
|
58
|
+
entry. It records input origins, durably records actual user `message_end` deliveries,
|
|
59
|
+
then binds stable transcript entries after Pi appends them. Assistant failure does not
|
|
60
|
+
discard delivered evidence. Input alone is not evidence. Ambiguous, detectably transformed, or
|
|
61
|
+
extension-originated messages are quarantined rather than silently trusted. No
|
|
62
|
+
assistant/tool/system/thinking/compaction text is supplied as new evidence.
|
|
63
|
+
|
|
64
|
+
The extension reads authorized memory once when the process first starts the session,
|
|
65
|
+
including startup with resumed history. It freezes only the Common Memory appended
|
|
66
|
+
block, combining that block with the host's current `event.systemPrompt` on each
|
|
67
|
+
`before_agent_start`. Reload, same-process resume, compact, branch navigation, fork
|
|
68
|
+
and `/new` do not trigger a new automatic read. Each session has separate counters.
|
|
69
|
+
The native `memory_read` tool remains available for explicit fresh reads, with the
|
|
70
|
+
same guidance and scope rules as MCP. Personal recommendations need a read when
|
|
71
|
+
relevant personal context is missing; generic explanations do not mechanically read.
|
|
72
|
+
Missing fields are unknown and memory content is data, not instructions.
|
|
73
|
+
|
|
74
|
+
Pi and Codex now use a durable session cache. One delivered user interaction counts
|
|
75
|
+
once at final settled, including steering and delivered follow-ups. The tenth settled
|
|
76
|
+
interaction immediately seals a session-only batch. A 21-turn session produces
|
|
77
|
+
10 + 10 + a one-turn exit tail. The logical batch may need several Writer requests,
|
|
78
|
+
always split between whole interactions; a single oversized interaction is retained
|
|
79
|
+
locally and quarantined. Assistant and tool text is context only, with separate
|
|
80
|
+
`conversation_context` disclosure permission (not added to existing configurations).
|
|
81
|
+
See [session design and validation](session-integration.md).
|
|
82
|
+
|
|
83
|
+
Optional `sessionCache` limits (omitted fields use these defaults):
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
"sessionCache": {
|
|
87
|
+
"maxSessionBytes": 8388608,
|
|
88
|
+
"maxTotalBytes": 67108864,
|
|
89
|
+
"contextTailTurns": 2
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
These are conservative engineering defaults, without capacity measurements or a
|
|
94
|
+
claim that two turns resolve every reference. Limits account for cached bodies,
|
|
95
|
+
input candidates, deliveries and Codex inbox bodies. Capacity rejection retains
|
|
96
|
+
existing content and recovery state; terminal metadata can still be persisted.
|
|
97
|
+
Old configurations remain valid and do not acquire `conversation_context` permission.
|
|
98
|
+
|
|
99
|
+
## Model network configuration
|
|
100
|
+
|
|
101
|
+
Common Memory owns one outbound client per configured model, shared by the CLI, MCP
|
|
102
|
+
and Pi paths. Run `common-memory config --network` to select a route. This changes
|
|
103
|
+
model calls only; it does not configure the host's other network clients.
|
|
104
|
+
|
|
105
|
+
| Mode | Request route |
|
|
106
|
+
| --- | --- |
|
|
107
|
+
| `direct` | Independent direct Agent; ignores HTTP/ALL proxy variables and the host global dispatcher |
|
|
108
|
+
| `env` | HTTPS: HTTPS_PROXY → HTTP_PROXY → ALL_PROXY; HTTP: HTTP_PROXY → ALL_PROXY; honors the supported NO_PROXY rules |
|
|
109
|
+
| `custom` | Explicit HTTP/HTTPS proxy; optional own bypass list, independent of host NO_PROXY; SOCKS5 is experimental |
|
|
110
|
+
| Old config without `remote.proxy` | Legacy host route, whose actual behavior is unknown to Common Memory; preserved until network settings are explicitly saved |
|
|
111
|
+
|
|
112
|
+
New installations default to `remote.proxy: {"mode":"env"}`. Existing schemaVersion 2
|
|
113
|
+
files retain field absence on load/save and ordinary API configuration, so upgrading
|
|
114
|
+
alone does not change their route. Legacy borrows the fetch captured at client creation
|
|
115
|
+
and preserves historic private environment loading, except for newly reserved network
|
|
116
|
+
secret names. It is a compatibility exception to network isolation.
|
|
117
|
+
|
|
118
|
+
In the new modes, proxy variables and API keys are read locally with **process env
|
|
119
|
+
before Common Memory's private `.env`**. For each standard proxy variable group, the
|
|
120
|
+
process source wins before checking lowercase/uppercase spelling; lowercase wins
|
|
121
|
+
within that source. A present empty value clears that group. No new-mode loading
|
|
122
|
+
changes `process.env`, global fetch, global dispatchers or global certificate trust.
|
|
123
|
+
The route and connections are fixed for the client's lifetime, including retries;
|
|
124
|
+
restart active MCP/Pi clients after changing configuration.
|
|
125
|
+
|
|
126
|
+
The wizard saves a custom proxy URL only as private `COMMON_MEMORY_PROXY_URL`, with
|
|
127
|
+
`remote.proxy: {"mode":"custom","urlEnv":"COMMON_MEMORY_PROXY_URL"}` in JSON. URL
|
|
128
|
+
credentials are supported. Optional extra CA certificates are referenced through
|
|
129
|
+
`remote.caFileEnv: "COMMON_MEMORY_CA_FILE"`; the private value is a PEM file path.
|
|
130
|
+
The CA file is limited to 1 MiB and is added to Node's default trust only for this
|
|
131
|
+
client. Certificate and hostname verification stay enabled. Other custom `urlEnv`
|
|
132
|
+
or `caFileEnv` names are read from external process env only. Reserved private network
|
|
133
|
+
keys are never exported by the legacy loader either.
|
|
134
|
+
|
|
135
|
+
NO_PROXY (or custom `noProxy`) accepts comma/whitespace-separated hostnames,
|
|
136
|
+
`example.com`, `.example.com` and `*.example.com` (apex plus subdomains), exact IPv4/
|
|
137
|
+
IPv6, optional ports and standalone `*` anywhere in the list. IPv6 ports require
|
|
138
|
+
brackets. Matching normalizes case, IDNA, trailing dots and IP spelling; it compares
|
|
139
|
+
effective ports, so HTTPS with omitted port matches `:443`. It performs no DNS lookup:
|
|
140
|
+
`localhost` does not imply `127.0.0.1` or `::1`. **CIDR ranges, URL/path entries and other
|
|
141
|
+
wildcards are rejected** with `no_proxy_invalid`; they are not silently ignored.
|
|
142
|
+
An environment containing CIDR entries needs an explicit supported bypass list or a
|
|
143
|
+
custom route. A failing selected proxy never falls back to direct.
|
|
144
|
+
|
|
145
|
+
Windows/macOS GUI processes can inherit different environment variables from terminals;
|
|
146
|
+
configure the private settings when that is the desired common source. WSL uses its
|
|
147
|
+
own visible environment and reachable proxy address; Common Memory does not guess a
|
|
148
|
+
Windows host address or copy Windows proxy settings. OS VPN/TUN routing still applies
|
|
149
|
+
in every mode. PAC/WPAD, SOCKS4 and NTLM/Kerberos are unsupported.
|
|
150
|
+
|
|
151
|
+
`status` describes configuration, selection/bypass reason and actual storage paths;
|
|
152
|
+
it does not open network connections. `network-test` explicitly sends a small synthetic
|
|
153
|
+
model API request without opening SQLite or writing memory. Its success does not prove
|
|
154
|
+
Writer commits. Proxy authentication (`PROXY_AUTHENTICATION`, `proxyStatus:407`) is
|
|
155
|
+
separate from provider API key authentication (`AUTHENTICATION`, `httpStatus:401/403`).
|
|
156
|
+
Errors expose controlled stages/reasons, not proxy credentials or provider bodies.
|
|
157
|
+
|
|
158
|
+
Configured model clients and configured Writers expose async `close()` and own their
|
|
159
|
+
connections. CLI/MCP/Pi await shutdown. Integrators creating them directly must also
|
|
160
|
+
`await close()`; a plain `Writer` still borrows its `MemoryModelPort` and does not close
|
|
161
|
+
caller-owned resources. The port itself remains analysis-only.
|
|
162
|
+
|
|
163
|
+
Research, explicit environment limits and acceptance evidence:
|
|
164
|
+
[network design and review](outbound-network-design.md).
|
|
165
|
+
|
|
166
|
+
## Interactive workbench
|
|
167
|
+
|
|
168
|
+
Run **`common-memory`** in a terminal. Home leads to:
|
|
169
|
+
|
|
170
|
+
| Area | Tasks |
|
|
171
|
+
| --- | --- |
|
|
172
|
+
| Overview | Configuration, actual storage paths, network selection and queue health; refresh locally |
|
|
173
|
+
| Memory | Browse authorized consumer documents with pagination; import local Markdown with explicit confirmation |
|
|
174
|
+
| Projects & permissions | Register/view/remove projects; independently manage disclosure, write scopes and provenance |
|
|
175
|
+
| Integrations | Local readiness; Pi's official package/resource manager; Codex/Work bundle preview/export; MCP configuration preview/export |
|
|
176
|
+
| Maintenance | Job diagnostics and dead-job retry; session summaries without bodies; flush and durable handoff recovery |
|
|
177
|
+
| Settings | Model/API/credentials, network/CA, explicit synthetic connection test, advanced tuning/limits/storage |
|
|
178
|
+
|
|
179
|
+
Use arrows and Enter, Space for multi-select, and Back to return. Esc/Ctrl+C cancels a
|
|
180
|
+
form; cancellation at Home exits. Pending work remains durable. No model call is made
|
|
181
|
+
just by opening the workbench. A generated integration is **not** reported as installed,
|
|
182
|
+
trusted or connected: Codex/Work/MCP config merging and hook trust stay in the host.
|
|
183
|
+
Pi management invokes the official `pi` command on PATH only after confirmation.
|
|
184
|
+
|
|
185
|
+
The interface requires both stdin and stdout to be TTYs. With no arguments outside a
|
|
186
|
+
TTY it prints entry-point guidance and exits; direct `config` wizards fail explicitly
|
|
187
|
+
rather than waiting for input. Scriptable commands and machine protocol entries remain
|
|
188
|
+
available. The same operations serve both CLI and TUI; read-only MCP still never opens
|
|
189
|
+
SQLite. See [design, entry-point inventory and limits](tui-workbench.md).
|
|
190
|
+
|
|
191
|
+
## Commands
|
|
192
|
+
|
|
193
|
+
These remain supported for automation and direct shortcuts; they are not prerequisites
|
|
194
|
+
for using the workbench.
|
|
195
|
+
|
|
196
|
+
```sh
|
|
197
|
+
common-memory
|
|
198
|
+
common-memory config
|
|
199
|
+
common-memory config --network
|
|
200
|
+
common-memory status
|
|
201
|
+
common-memory network-test
|
|
202
|
+
common-memory show [--workspace /absolute/project/path]
|
|
203
|
+
common-memory import <file.md> [--workspace /absolute/project/path] [--author user|agent|third_party|mixed|unknown] [--label <text>] [--no-wait]
|
|
204
|
+
common-memory flush
|
|
205
|
+
common-memory session-drain [--home <absolute-path>]
|
|
206
|
+
common-memory retry <dead-job-id>
|
|
207
|
+
common-memory project register /absolute/project/path "Display name"
|
|
208
|
+
common-memory project list
|
|
209
|
+
common-memory project remove <id>
|
|
210
|
+
common-memory mcp-config [--wsl] [--distro <name>] [--user <name>] [--workspace /absolute/project/path]...
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
`show` prints the memory directory and exactly what consumers (MCP `memory_read`, Pi)
|
|
214
|
+
receive for `global` plus the optional registered workspace, using the same
|
|
215
|
+
authorization. The canonical files themselves are plain Markdown under
|
|
216
|
+
`<dataRoot>/memory/` and can be opened with any editor.
|
|
217
|
+
|
|
218
|
+
### Importing a Markdown file
|
|
219
|
+
|
|
220
|
+
`common-memory import <file.md>` brings one local Markdown file into memory through the
|
|
221
|
+
same Writer that handles user turns and Init. It never copies the file into
|
|
222
|
+
`profile.md` or bypasses the Core. The import step is input preprocessing only:
|
|
223
|
+
|
|
224
|
+
- The file must be a regular `.md`/`.markdown` file (no symlinks), strict UTF-8 without
|
|
225
|
+
NUL bytes, non-empty after trimming, and at most 256 KiB. Anything else is rejected
|
|
226
|
+
with a code (`FILE_NOT_FOUND`, `UNSUPPORTED_FILE_TYPE`, `INVALID_ENCODING`,
|
|
227
|
+
`EMPTY_DOCUMENT`, `DOCUMENT_TOO_LARGE`) before anything is queued. Nothing is truncated.
|
|
228
|
+
- A file that fits the 32 KiB per-item budget is one observation, verbatim. Larger files
|
|
229
|
+
are split only at Markdown structure: headings start new units, blank lines separate
|
|
230
|
+
paragraphs, fenced code is never split, and whole sections stay together when they fit.
|
|
231
|
+
Every part records the ancestor headings it sits under (`heading_path`) and its position
|
|
232
|
+
(`part i of n`). A single paragraph or fence larger than the budget rejects the whole
|
|
233
|
+
import (`IMPORT_CHUNK_TOO_LARGE`); an unterminated fence makes the rest of the file one
|
|
234
|
+
fence. The 32 KiB budget is fixed; with a lowered `disclosure.maxTotalBytes` the Writer
|
|
235
|
+
may still quarantine a part that does not fit its request (`OVERSIZED_COMPLETE_TURN`).
|
|
236
|
+
- The Writer's outbound safety scan runs before queuing; a violating part is reported as
|
|
237
|
+
`SENSITIVE_CONTENT_REJECTED part i/n: <rule ids>` and the file is not imported.
|
|
238
|
+
- `--author` records who the importer says wrote the file (default `unknown`), `--label`
|
|
239
|
+
a display label (default the file name). Both are recorded metadata for the maintainer;
|
|
240
|
+
neither grants authority. Even `--author user` remains `document_import`, not a user
|
|
241
|
+
statement, because Markdown is a format and choosing to import a file is not asserting
|
|
242
|
+
each sentence in it.
|
|
243
|
+
- Identity is the content digest within the target context (`md-<sha256>`): the same bytes
|
|
244
|
+
under another file name, label or author are the same material (reported as a duplicate,
|
|
245
|
+
nothing new is queued, the original metadata stays); changed bytes are a new import.
|
|
246
|
+
Scope comes from `--workspace` (a registered project in `disclosure.allowedScopes`) or
|
|
247
|
+
defaults to `global`.
|
|
248
|
+
|
|
249
|
+
All parts are queued in one transaction with a flush request, then the command runs the
|
|
250
|
+
Writer loop like `flush` and prints per-part states (`pending`, `claimed`, `processed`,
|
|
251
|
+
`quarantined`, `dead`), the documents each part is retained in, and a final `complete`
|
|
252
|
+
flag that is true only when every part was processed. Parts are committed batch by batch
|
|
253
|
+
with their own receipts; a partially processed import is reported as incomplete (exit
|
|
254
|
+
code 1), never as success. Re-running `import` on the same file resumes pending or
|
|
255
|
+
retrying parts (dead jobs need `common-memory retry <job-id>`); a quarantined part is
|
|
256
|
+
final for that content and needs a changed file. `--no-wait` only queues. Enable the
|
|
257
|
+
provenance first:
|
|
258
|
+
`disclosure.allowedProvenance` must contain `document_import` (wizard option "Imported
|
|
259
|
+
Markdown documents"), otherwise `IMPORT_DISABLED`. Text inside the file is data: memory
|
|
260
|
+
commands, links and code in it are never executed or followed, and the import cannot
|
|
261
|
+
forget, remove or replace Sections that user turns produced (see "What Init means").
|
|
262
|
+
|
|
263
|
+
Project IDs are generated locally. Registry matching uses real paths and the longest
|
|
264
|
+
ancestor, frozen at capture time. Registration alone grants no permission: separately
|
|
265
|
+
authorize `project:<id>` under Projects & permissions in the workbench, or add it to
|
|
266
|
+
`disclosure.allowedScopes` and `writableScopes` in config.
|
|
267
|
+
Removing a registration leaves its Markdown intact. `status` reports pending,
|
|
268
|
+
quarantined, dead jobs and unbound deliveries without printing raw conversations.
|
|
269
|
+
It also shows the config path and resolved storage paths (including symlink targets);
|
|
270
|
+
absent storage is displayed without creating it. `flush` exits 1 if this invocation
|
|
271
|
+
fails, is cancelled, quarantines an observation, or ends with pending/claimed/dead
|
|
272
|
+
observations. An idle scheduler waiting for backoff or an active lease is incomplete.
|
|
273
|
+
Historical quarantine and retired jobs do not block an otherwise empty queue; flush
|
|
274
|
+
does not bypass backoff or take another process's lease.
|
|
275
|
+
Pi also provides `/memory-flush` for queued maintenance. It does not seal an unfinished
|
|
276
|
+
session batch. On actual quit, Pi hands off the tail and wakes a detached consumer;
|
|
277
|
+
reload and session switching preserve the open cache. `common-memory session-drain`
|
|
278
|
+
recovers durable handoffs and waits through retry backoff and leases.
|
|
279
|
+
|
|
280
|
+
## MCP access (stdio)
|
|
281
|
+
|
|
282
|
+
Build with `npm ci && npm run build`. Configure Common Memory using the existing
|
|
283
|
+
CLI, then give your MCP host an explicit command and argument array. Node 24 is
|
|
284
|
+
required. No running Pi process is needed; the existing Pi peer/package layout is
|
|
285
|
+
unchanged. The SDK stdio entry serves modern and legacy clients. No HTTP port,
|
|
286
|
+
automatic host installer, Roots discovery, Resources, Prompts or retrieval is added.
|
|
287
|
+
|
|
288
|
+
### Capability profiles
|
|
289
|
+
|
|
290
|
+
Each MCP process registers only the tools its launch arguments allow. `--capability`
|
|
291
|
+
is repeatable; the default without it is `relay`, the pre-existing behaviour.
|
|
292
|
+
|
|
293
|
+
| `--capability` | Tools registered | Needs Writer / API key | Intended host |
|
|
294
|
+
| --- | --- | --- | --- |
|
|
295
|
+
| `relay` (default) | `memory_submit_user_turn`, `memory_status` | yes (background processing) | trusted local agent relaying verbatim user turns |
|
|
296
|
+
| `init` | `memory_init`, `memory_status` | yes | ChatGPT desktop: one-shot import of its existing understanding |
|
|
297
|
+
| `read` | `memory_read`, `memory_status` | **no** (never opens the runtime database) | Codex CLI and other read-only consumers |
|
|
298
|
+
|
|
299
|
+
Capability is fixed per process at launch; a tool argument, client-reported name or
|
|
300
|
+
prompt can never widen it. Run one process per host role. Where two hosts share one
|
|
301
|
+
configuration file (see Codex below), use the host's own allow list and profiles as the
|
|
302
|
+
second layer.
|
|
303
|
+
|
|
304
|
+
For project input, use `--workspace /absolute/project/path` (repeatable). Register
|
|
305
|
+
projects with the existing CLI and separately authorize their disclosure/write scopes.
|
|
306
|
+
Use `--global` explicitly to allow global contexts. There is no cwd fallback. Each call
|
|
307
|
+
selects an allowed `contextId`; changed/unregistered workspace mappings are rejected
|
|
308
|
+
rather than silently rebound. Project source does not prohibit authorized Global
|
|
309
|
+
promotion: the existing Writer still decides applicability. Reading follows the same
|
|
310
|
+
contexts: a process launched for workspace A never returns project B's document, and
|
|
311
|
+
a process without `--global` never returns Profile/Preferences.
|
|
312
|
+
|
|
313
|
+
The server publishes MCP `instructions` describing when to use its tools. Tool discovery
|
|
314
|
+
and proactive calls depend on the host and model; configuring MCP alone does not
|
|
315
|
+
guarantee a read before an answer. Native Codex hooks below inject memory independently
|
|
316
|
+
of tool calls. Memory content is data, never agent instructions.
|
|
317
|
+
|
|
318
|
+
### Tools
|
|
319
|
+
|
|
320
|
+
- `memory_status {}`: this connection's capabilities, enabled features and allowed
|
|
321
|
+
context IDs.
|
|
322
|
+
- `memory_submit_user_turn { submissionId, conversationId?, contextId, text }`
|
|
323
|
+
(`relay`): submit one **complete user expression verbatim**, not an assistant summary
|
|
324
|
+
or a Markdown operation. IDs must be 1–128 ASCII letters/digits/underscores/hyphens.
|
|
325
|
+
- `memory_init { importId, contextId, sourceLabel, basis, understanding, gaps? }`
|
|
326
|
+
(`init`): import another agent's **visible existing material, quoted or faithfully summarized** of the user (`global`) or the current
|
|
327
|
+
project (`project:<id>`). `basis` ∈ `saved_memories | chat_history |
|
|
328
|
+
current_conversation | project_context | mixed | unknown`; `understanding` ≤ 32 KiB;
|
|
329
|
+
`gaps` describes what the agent could not access. The payload is stored as one
|
|
330
|
+
`agent_import` observation. `sourceLabel` is a recorded label, not an identity.
|
|
331
|
+
Reuse `importId` on retry: identical payloads are duplicates, changed payloads are
|
|
332
|
+
`SUBMISSION_CONFLICT`. Init requests an immediate flush, so the Core processes it at
|
|
333
|
+
the next stable boundary instead of waiting for the usual thresholds.
|
|
334
|
+
- `memory_read { contextId? }` (`read`): current Profile and Preferences for `global`
|
|
335
|
+
and the project document for an allowed project context; without `contextId`, every
|
|
336
|
+
allowed context. Returns Markdown plus `{ documents: [{ target, content, bytes,
|
|
337
|
+
empty }], empty }`. Documents are returned whole (the Writer keeps each ≤ 16 KiB);
|
|
338
|
+
an empty result says that nothing is stored so consumers do not invent facts.
|
|
339
|
+
- `memory_status { submissionId, conversationId? }` / `memory_status { importId }`:
|
|
340
|
+
that item's `state` (`pending`, `claimed`, `processed`, `quarantined`, `dead`), the
|
|
341
|
+
documents it is currently retained in (`retainedIn`, derived from Section source
|
|
342
|
+
links, never titles or bodies), the existing `issue` code, and `diagnostic`
|
|
343
|
+
(`stage`, local `reason`, optional `httpStatus`, `retryable`). It also returns
|
|
344
|
+
`jobId`, `jobState`, `attempts` and `retryAt` (Unix milliseconds, null unless
|
|
345
|
+
waiting for a job retry). Diagnostics follow the current linked job and survive
|
|
346
|
+
restart; processed observations hide earlier failures, while local job history
|
|
347
|
+
retains them. Provider messages/bodies are never persisted as diagnostics.
|
|
348
|
+
`retryable` describes the adapter's advice and does not change Runtime scheduling. `processed` with an
|
|
349
|
+
empty `retainedIn` means the Core kept nothing (ignored or reorganized only).
|
|
350
|
+
|
|
351
|
+
### What Init means
|
|
352
|
+
|
|
353
|
+
Init is a product action — "bring what another agent already understands about me
|
|
354
|
+
into my memory" — not MCP initialization and not a claim to export that agent's
|
|
355
|
+
internal memory. Record the material actually visible in this session, its source,
|
|
356
|
+
conditions and gaps; a product or mode name does not establish source or coverage.
|
|
357
|
+
[Official documentation](https://learn.chatgpt.com/docs/customization/memories)
|
|
358
|
+
separates ChatGPT memory from local Codex memory, while the
|
|
359
|
+
user-confirmed Work-local session read local Codex material and completed Init
|
|
360
|
+
([evidence and limits](init-v0.1-verification.md#work-local-evidence-2026-09-08)).
|
|
361
|
+
Whether that session also received cloud memory is unknown. The Core treats the submission as
|
|
362
|
+
untrusted agent-reported data: the maintainer receives `source_kind: "agent_import"`
|
|
363
|
+
with the label, basis and gaps, must keep the source nature visible in any retained
|
|
364
|
+
Section (for example "Imported from chatgpt-desktop on 2026-09-07 …"), must not
|
|
365
|
+
present it as the user's words, and must not overwrite conflicting user-stated content.
|
|
366
|
+
The executor enforces the hard part structurally for every import kind (`agent_import`
|
|
367
|
+
and `document_import` alike): imports are batched separately from user turns, and a
|
|
368
|
+
decision backed only by import evidence (or an evidence-free `maintain` in an import-only
|
|
369
|
+
batch) may append new Sections or rework Sections whose every linked source is itself an
|
|
370
|
+
import, but is rejected if it tries to `forget` (`UNAUTHORIZED_FORGET_EVIDENCE`), remove,
|
|
371
|
+
or replace a user-derived or unlinked Section (`UNAUTHORIZED_IMPORT_OVERWRITE`). A Section the user edited by hand counts as the
|
|
372
|
+
user's even if an import created it: its stale title links are not trusted. What the
|
|
373
|
+
executor cannot judge is semantic: whether an added assertion has factual support,
|
|
374
|
+
whether the claimed source is correct, whether a new attributed Section contradicts a
|
|
375
|
+
user-stated one, or whether first-person text in a file describes the user; the packaged
|
|
376
|
+
maintainer instructions make those the model's responsibility and require visible
|
|
377
|
+
attribution. Init therefore never clears existing documents or
|
|
378
|
+
runtime state; existing safety scanning, size limits, scope authorization, CAS, lease
|
|
379
|
+
fencing and recovery apply unchanged. Init does request a flush, which — like
|
|
380
|
+
`/memory-flush` — also lets already queued user turns be processed at the next stable
|
|
381
|
+
boundary. There is no preview or approval queue in the Core: the user's explicit
|
|
382
|
+
request plus the host's approval prompt for non-read-only tools are the confirmation,
|
|
383
|
+
and `memory_status.retainedIn`, `common-memory show` and the Markdown files are the
|
|
384
|
+
post-hoc review.
|
|
385
|
+
|
|
386
|
+
Init is enabled only when the process was launched with `--capability init` **and**
|
|
387
|
+
`disclosure.allowedProvenance` contains `agent_observation` (the wizard option
|
|
388
|
+
"Agent-reported understanding"); otherwise `memory_init` returns `INIT_DISABLED`.
|
|
389
|
+
|
|
390
|
+
### Migrate selected, checkable material
|
|
391
|
+
|
|
392
|
+
1. Save the original Memory Summary or legacy Saved Memories actually visible to the
|
|
393
|
+
account, including available dates and source references. The [Memory FAQ](https://help.openai.com/en/articles/8590148)
|
|
394
|
+
says the summary omits some memory and response source lists may be incomplete.
|
|
395
|
+
For missing topics, ask the source agent targeted questions and preserve checkable
|
|
396
|
+
references; leave unsupported new guesses in separate review notes.
|
|
397
|
+
2. Review the selected material before submission. Preserve historical goals, dates,
|
|
398
|
+
conditions, tentative claims and project boundaries. Put what the agent cannot
|
|
399
|
+
access in gaps; “unknown” does not mean the user has no such history. Exclude this
|
|
400
|
+
migration's connection, import and readback status. Approval to migrate does not
|
|
401
|
+
make every claim true.
|
|
402
|
+
3. Use `common-memory import selected.md --author agent --label "ChatGPT visible memory"`
|
|
403
|
+
for user-selected Markdown generated by an agent (choose the actual author class
|
|
404
|
+
for other material). It remains `document_import`, authorized through
|
|
405
|
+
`document_import` in `disclosure.allowedProvenance`. An agent's submission uses
|
|
406
|
+
`memory_init`, remains `agent_import`, and requires `agent_observation` authorization.
|
|
407
|
+
Direct quotation does not turn either import into authenticated user statements.
|
|
408
|
+
4. An isolated trial is recommended: configure a separate `COMMON_MEMORY_HOME` with
|
|
409
|
+
`common-memory config` and verify its `dataRoot` is also a new temporary directory.
|
|
410
|
+
Merely changing the home while copying a production `dataRoot` does not isolate it.
|
|
411
|
+
Authorize the chosen scope/provenance and remote provider there, then run the
|
|
412
|
+
existing import and `show` commands against that configuration. For MCP, launch
|
|
413
|
+
the trial process with that separate configuration and verify the generated
|
|
414
|
+
`mcp-config` paths. Do not connect consumers to the trial store.
|
|
415
|
+
5. Compare the trial result with the selected sources. Submit through the same
|
|
416
|
+
existing entry point to the intended destination and review **that destination's**
|
|
417
|
+
`common-memory show` output (with `--workspace` for a project). Check omissions,
|
|
418
|
+
altered conditions, scope, unknowns and new assertions. A trial cannot guarantee
|
|
419
|
+
identical model decisions when rerun against the destination's existing state.
|
|
420
|
+
|
|
421
|
+
The Init guidance is a **soft semantic defense**: it cannot prove provenance, prevent
|
|
422
|
+
all unsupported facts or semantic conflicts, or replace result review. v0.1 adds no
|
|
423
|
+
migration state machine, consumer pause/resume interface or Core approval queue.
|
|
424
|
+
There is no full-chat parser, profile generator or remote server in this workflow;
|
|
425
|
+
remote MCP would not itself expand the source agent's visible memory.
|
|
426
|
+
|
|
427
|
+
### ChatGPT desktop app (init only)
|
|
428
|
+
|
|
429
|
+
The ChatGPT desktop app configures MCP servers for its Codex host in the same
|
|
430
|
+
`config.toml` as Codex CLI (Settings → MCP servers, or edit the file). Add an
|
|
431
|
+
init-only server; the host prompts before non-read-only tools:
|
|
432
|
+
|
|
433
|
+
```toml
|
|
434
|
+
[mcp_servers.common_memory_init]
|
|
435
|
+
command = "/absolute/path/to/node"
|
|
436
|
+
args = ["/absolute/path/to/common-memory/dist/cli/main.js", "mcp",
|
|
437
|
+
"--client-id", "chatgpt-desktop", "--capability", "init", "--global"]
|
|
438
|
+
env = { COMMON_MEMORY_HOME = "/absolute/path/to/.common-memory" }
|
|
439
|
+
default_tools_approval_mode = "approve"
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
When the desktop app runs on Windows and Common Memory lives in WSL, use the WSL bridge
|
|
443
|
+
described under "Windows / WSL deployment" below: run `common-memory mcp-config --wsl`
|
|
444
|
+
inside WSL and paste its output. It pins the distribution, Linux user, configuration
|
|
445
|
+
directory, dataRoot, node binary and CLI entry, so the host cannot land on another store.
|
|
446
|
+
|
|
447
|
+
Then, in a chat that can use that host's MCP servers, ask: “把本次实际可见、已选定的既有理解导入
|
|
448
|
+
Common Memory;保留来源、时间、条件和不确定性,列明无法访问的材料,排除本次迁移执行状态。” The agent should call `memory_init`, then `memory_status` with the same
|
|
449
|
+
`importId` to report what was retained. Use `common-memory show` locally to review.
|
|
450
|
+
ChatGPT web and the desktop **Chat** mode do not read this configuration; use the
|
|
451
|
+
selected Markdown workflow above for this version. A remote HTTPS connector
|
|
452
|
+
is outside this version and would not guarantee access to more source material.
|
|
453
|
+
|
|
454
|
+
### ChatGPT Work local sessions and explicit refresh
|
|
455
|
+
|
|
456
|
+
Build first, then generate a reviewable bundle for the **actual agent environment**:
|
|
457
|
+
|
|
458
|
+
```sh
|
|
459
|
+
# macOS agent + runtime, or agent + runtime in the same WSL environment:
|
|
460
|
+
common-memory work-config --mode posix --output /absolute/new/bundle
|
|
461
|
+
# Native Windows agent with this runtime inside WSL:
|
|
462
|
+
common-memory work-config --mode windows-wsl --distro Ubuntu --user linux-user \
|
|
463
|
+
--output /mnt/c/Users/you/common-memory-bundle \
|
|
464
|
+
--bridge-path 'C:\Users\you\common-memory-bundle\common-memory-bridge.ps1'
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Choose the mode from the agent process and its configuration directory. Terminal type
|
|
468
|
+
and `WSL_DISTRO_NAME` alone do not identify where the desktop agent runs. Linux POSIX
|
|
469
|
+
configuration validation does not establish Linux Desktop product support. The bridge
|
|
470
|
+
pins absolute `wsl.exe`, distro, user, Node, CLI and Common Memory home. Store its
|
|
471
|
+
PowerShell launcher on a Windows local path; `--bridge-path` defaults to the Windows
|
|
472
|
+
translation of the output path. UNC locations may require signing under
|
|
473
|
+
the machine's execution policy. The generator does not change that policy.
|
|
474
|
+
|
|
475
|
+
Inspect `common-memory.config.toml`, then merge it into the actual Work agent's
|
|
476
|
+
configuration, and install `skills/memory-refresh` in that agent's skills directory.
|
|
477
|
+
Use repeatable `--workspace <absolute-runtime-path>` for registered project read access.
|
|
478
|
+
Review and trust Hook commands through `/hooks`. Generated files never overwrite
|
|
479
|
+
existing files. Work gets independent read and init MCP processes. The existing
|
|
480
|
+
`chatgpt-desktop` import identity is preserved for retry receipts; session capture and
|
|
481
|
+
read use `chatgpt-work`. Ordinary Chat is outside this integration.
|
|
482
|
+
|
|
483
|
+
For Codex, `codex-config --mode posix --output /absolute/new/bundle` generates the
|
|
484
|
+
same explicit Skill and a profile with init disabled. The no-argument form still
|
|
485
|
+
prints configuration. Use `--mode windows-wsl` with the bridge options for a native
|
|
486
|
+
Windows Codex host. Keep Work and Codex profiles separate when sharing a config home.
|
|
487
|
+
|
|
488
|
+
`/memory-refresh` has `allow_implicit_invocation: false`. Its generated command calls
|
|
489
|
+
`session-refresh --home <absolute-path> --client <client>` using the host process and
|
|
490
|
+
`CODEX_THREAD_ID`. Missing or nonmatching identity fails; cwd alone never selects a
|
|
491
|
+
session. Reading and replacement are transactional: failure leaves the prior snapshot
|
|
492
|
+
and pending delivery intact. `PostToolUse` injects the new block, with the next
|
|
493
|
+
`UserPromptSubmit` as fallback. Refresh does not reset the ten-turn count or import
|
|
494
|
+
anything. Pi provides the same command natively and replaces its frozen system block.
|
|
495
|
+
|
|
496
|
+
A live activation survives switching away, unsubscribe/resubscribe, same-process
|
|
497
|
+
resume, compact, clear and reload. A real `SessionEnd` closes it and drops its snapshot;
|
|
498
|
+
a subsequent startup/resume creates an independent activation while the old durable
|
|
499
|
+
inbox and tail drain remain recoverable. New-process resume reads once. Historical
|
|
500
|
+
messages may retain old snapshots: the host API appends context, while the adapter
|
|
501
|
+
owns and replaces one active slot. See [session integration](session-integration.md)
|
|
502
|
+
for validation and remaining real-UI limitations.
|
|
503
|
+
|
|
504
|
+
### Codex CLI (session hooks and read-only MCP)
|
|
505
|
+
|
|
506
|
+
For automatic injection, build Common Memory and run `common-memory codex-config`
|
|
507
|
+
(or `node dist/cli/main.js codex-config`). Save its stdout as
|
|
508
|
+
`common-memory.config.toml` under the **actual Codex CLI `CODEX_HOME`**
|
|
509
|
+
(default `~/.codex`). Inspect and merge any existing file with that name; do not
|
|
510
|
+
blindly overwrite it. The generator only prints configuration: it does not edit
|
|
511
|
+
base configuration, profiles or the hook trust store.
|
|
512
|
+
|
|
513
|
+
Launch `codex --profile common-memory`, then use Codex's official `/hooks` interface
|
|
514
|
+
to review and trust the generated commands. No trust bypass is generated.
|
|
515
|
+
The commands pin the current Node binary, built CLI entry and Common Memory
|
|
516
|
+
configuration directory as absolute, POSIX shell-quoted paths. Regenerate after
|
|
517
|
+
moving the installation or changing Node or `COMMON_MEMORY_HOME`.
|
|
518
|
+
Codex CLI and Common Memory must run in the same POSIX environment, including WSL;
|
|
519
|
+
macOS uses the same direct launch. For a native Windows agent with a WSL runtime, generate the bridge bundle below.
|
|
520
|
+
|
|
521
|
+
The generated synchronous hooks cover `SessionStart`, `UserPromptSubmit`, `Stop`,
|
|
522
|
+
`PostToolUse`, `Interrupt` and `SessionEnd`, with a three-second timeout. They use the local SQLite
|
|
523
|
+
FULL-synchronous durable inbox, then launch `session-drain` detached with independent
|
|
524
|
+
stdio. The inbox contains the transcript tail itself, so normal exit does not depend
|
|
525
|
+
on the transcript surviving. Consumers delete that copy only in the transaction that
|
|
526
|
+
admits it into the session cache. No model runs in the hook process.
|
|
527
|
+
|
|
528
|
+
Only the first qualifying `SessionStart` (`startup` or `resume`) for the process and
|
|
529
|
+
activation reads memory. Compact/clear/reload reattach the cached block without reading canonical files; ordinary turns do not repeat it. Startup
|
|
530
|
+
output remains bounded to 64 KiB and hook input to 1 MiB. Automatic snapshots are
|
|
531
|
+
frozen; call MCP `memory_read` for an independent current read, or explicitly invoke `/memory-refresh` to replace the frozen slot. Read failure returns
|
|
532
|
+
a controlled unavailable block. Ingress/protocol/capacity failures exit nonzero.
|
|
533
|
+
|
|
534
|
+
The rollout parser is isolated at `src/cli/codex/transcript-0.153.4.ts`; it accepts
|
|
535
|
+
only Codex CLI 0.153.4 metadata. User delivery requires `user_message` or `item_completed/UserMessage` events matching the separately recorded
|
|
536
|
+
UserPromptSubmit candidate for that turn, never arbitrary `response_item` user content, hook context, environment messages or
|
|
537
|
+
compaction summaries. `task_complete` / `turn_aborted` seal interactions. Stop starts
|
|
538
|
+
completion reconciliation immediately; a delayed final record needs no next prompt.
|
|
539
|
+
Unconfirmed completion keeps its durable watch for a later `session-drain` retry;
|
|
540
|
+
a reconciliation attempt is bounded to 60 seconds. Unknown formats do not advance
|
|
541
|
+
the cursor. Linux/WSL process identity uses boot ID, host PID and start time; native
|
|
542
|
+
macOS uses the host PID and process start time. The Windows bridge passes the native host PID and creation time, and converts cwd/transcript paths into the fixed WSL runtime.
|
|
543
|
+
|
|
544
|
+
Protocol reference: [official Codex hooks](https://learn.chatgpt.com/docs/hooks).
|
|
545
|
+
The earlier `scripts/smoke-codex-hooks.py` repeated-snapshot assertions are historical
|
|
546
|
+
and superseded by the session tests; they are not validation of this implementation.
|
|
547
|
+
Current synthetic coverage and remaining real-client gaps are recorded in
|
|
548
|
+
[session integration](session-integration.md). No personal data or live model
|
|
549
|
+
calls are needed for the tests.
|
|
550
|
+
|
|
551
|
+
MCP-only users can keep the read-only setup below; session hooks and MCP can coexist.
|
|
552
|
+
Hooks do not add MCP capabilities. To keep a desktop init server out of Codex, merge
|
|
553
|
+
`mcp_servers.common_memory_init.enabled = false` at the correct TOML table location
|
|
554
|
+
(or launch with `-c mcp_servers.common_memory_init.enabled=false`).
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
```toml
|
|
558
|
+
[mcp_servers.common_memory]
|
|
559
|
+
command = "/absolute/path/to/node"
|
|
560
|
+
args = ["/absolute/path/to/common-memory/dist/cli/main.js", "mcp",
|
|
561
|
+
"--client-id", "codex-cli", "--capability", "read", "--global",
|
|
562
|
+
"--workspace", "/absolute/project/path"]
|
|
563
|
+
env = { COMMON_MEMORY_HOME = "/absolute/path/to/.common-memory" }
|
|
564
|
+
enabled_tools = ["memory_read", "memory_status"]
|
|
565
|
+
default_tools_approval_mode = "auto"
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
`--workspace` is optional and must be a registered project whose `project:<id>` is in
|
|
569
|
+
`disclosure.allowedScopes`. The process is read-only by construction (server side) and
|
|
570
|
+
`enabled_tools` repeats that on the host side. If the same `config.toml` also holds the
|
|
571
|
+
ChatGPT init server, keep Codex CLI from seeing it with a profile file
|
|
572
|
+
`~/.codex/memory-reader.config.toml` containing
|
|
573
|
+
`mcp_servers.common_memory_init.enabled = false` and run `codex --profile
|
|
574
|
+
memory-reader`, or pass `-c mcp_servers.common_memory_init.enabled=false`. Disable
|
|
575
|
+
Codex's own local memories (`features.memories = false`) when you need to prove that
|
|
576
|
+
an answer came from Common Memory. `common-memory mcp-config` prints this block with the
|
|
577
|
+
paths of the runtime you are actually using.
|
|
578
|
+
|
|
579
|
+
### Windows / WSL deployment
|
|
580
|
+
|
|
581
|
+
On Windows, Common Memory runs in WSL only: one configuration authority
|
|
582
|
+
(`COMMON_MEMORY_HOME`, default `~/.common-memory` of the Linux user), one dataRoot, one
|
|
583
|
+
build. PowerShell and the ChatGPT/Codex desktop app are thin bridges that start the WSL
|
|
584
|
+
process with `wsl.exe`; there is no Windows-native Core, second store, installer or
|
|
585
|
+
resident service. Different MCP processes still start per host role (`init`, `read`) and
|
|
586
|
+
share the data the Core manages.
|
|
587
|
+
|
|
588
|
+
Inside WSL, after `npm run build` and `common-memory config`:
|
|
589
|
+
|
|
590
|
+
```sh
|
|
591
|
+
common-memory mcp-config --wsl [--workspace /home/<user>/project]
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
prints ready-to-paste `[mcp_servers.*]` blocks of the form
|
|
595
|
+
|
|
596
|
+
```toml
|
|
597
|
+
[mcp_servers.common_memory_init]
|
|
598
|
+
command = "wsl.exe"
|
|
599
|
+
args = ["-d", "Ubuntu", "-u", "<linux-user>", "-e", "/usr/bin/env",
|
|
600
|
+
"COMMON_MEMORY_HOME=/home/<linux-user>/.common-memory",
|
|
601
|
+
"/home/<linux-user>/.local/share/fnm/node-versions/v24.20.0/installation/bin/node",
|
|
602
|
+
"/home/<linux-user>/common-memory/dist/cli/main.js", "mcp",
|
|
603
|
+
"--client-id", "chatgpt-desktop", "--capability", "init", "--global"]
|
|
604
|
+
default_tools_approval_mode = "approve"
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
with a header recording the distribution (`WSL_DISTRO_NAME`), Linux user, configuration
|
|
608
|
+
directory, dataRoot, node and CLI entry that were in effect. `-d`/`-u` fix the
|
|
609
|
+
distribution and user instead of relying on the WSL defaults; `-e` runs no login shell,
|
|
610
|
+
so `PATH` and shell profiles are unavailable and every path is absolute. Paste the blocks
|
|
611
|
+
into the Windows `%USERPROFILE%\.codex\config.toml` (ChatGPT desktop / Codex host). The
|
|
612
|
+
WSL `~/.codex/config.toml` used by Codex CLI inside WSL takes the non-`--wsl` output.
|
|
613
|
+
Workspaces are WSL paths registered with `common-memory project register`; a Windows path
|
|
614
|
+
string (`C:\...`) is not a registered project and is rejected rather than mapped. Pi is
|
|
615
|
+
supported when it runs inside the same WSL distribution; Windows-native Pi is not covered.
|
|
616
|
+
`docs/init-v0.1-verification.md` records that a read-only process launched through
|
|
617
|
+
`wsl.exe -d Ubuntu -u <user> -e ...` returns byte-identical `memory_read` content to a
|
|
618
|
+
direct launch of the same store (`tests/cli/demo-and-bridge.test.ts`, skipped off-WSL).
|
|
619
|
+
|
|
620
|
+
### Relay (pre-existing)
|
|
621
|
+
|
|
622
|
+
Submissions are disabled unless `--accept-client-reported-user-turns` is set and
|
|
623
|
+
existing config permits user-expression disclosure. This flag explicitly trusts this
|
|
624
|
+
local host to relay user expressions: MCP cannot prove original user delivery or
|
|
625
|
+
faithful copying. The server records `mcp_user_submission`, never fabricates Pi
|
|
626
|
+
`rpc` delivery events. The flag gates new admissions, not retroactive revocation of
|
|
627
|
+
already accepted evidence. Only use trusted local agents belonging to the same user.
|
|
628
|
+
|
|
629
|
+
Use a distinct stable `--client-id` for each independent integration. Client identity
|
|
630
|
+
is a local namespace, **not authentication**. Reuse the same submission/conversation
|
|
631
|
+
IDs on retry, including after restart. Conflicting payloads are rejected. Without a
|
|
632
|
+
conversation ID, each submission has its own logical session. Two clients may use the
|
|
633
|
+
same IDs without colliding, but sharing a client ID deliberately shares that namespace.
|
|
634
|
+
|
|
635
|
+
Legacy relay sessions can share a same-scope/provenance batch under the existing
|
|
636
|
+
scheduler. Pi/Codex session batches are separate from relay/import and from each
|
|
637
|
+
other. The store is not a multi-tenant authorization boundary. All processes sharing a dataRoot must use the
|
|
638
|
+
same configuration authority and compatible release; stop old processes before upgrade.
|
|
639
|
+
|
|
640
|
+
Accepted means durably queued, not immediately committed. Background processing uses
|
|
641
|
+
the existing thresholds. Cancellation is best-effort; request cancellation after
|
|
642
|
+
admission does not retract evidence. Known SDK 2.0.0 limitation: cancellation with
|
|
643
|
+
JSON-RPC request ID `0` is ignored upstream (a same-tick call/cancel was reproduced);
|
|
644
|
+
use nonzero request IDs if cancellation-before-admission matters. No SDK patch or
|
|
645
|
+
request-ID compatibility shim is included in this first integration.
|
|
646
|
+
On EOF (all platforms) or SIGTERM (POSIX), the server queues a flush, aborts its own
|
|
647
|
+
Writer and closes after local cleanup. On Windows, Node's SIGTERM emulation kills
|
|
648
|
+
unconditionally: use stdin EOF for graceful shutdown; forced termination relies on
|
|
649
|
+
lease expiry and restart recovery. Pending work survives for the next Pi/MCP process
|
|
650
|
+
or `common-memory flush`.
|
|
651
|
+
Legacy relay/import shutdown does not launch a consumer. Session hooks/Pi quit do
|
|
652
|
+
launch an independent consumer, which may outlive both the host and MCP. Existing recovery wins over cancellation
|
|
653
|
+
once a durable commit has begun. Logs go to stderr; stdout is reserved for MCP.
|
|
654
|
+
|
|
655
|
+
Full runtime diagnostics, retry, flush, configuration and project management are
|
|
656
|
+
available in the default workbench and as CLI operations. Quotas, hot revocation,
|
|
657
|
+
optional-Pi packaging and broader compatibility matrices remain deferred. No personal data or live models are needed
|
|
658
|
+
for the MCP fake-provider protocol tests.
|
|
659
|
+
|
|
660
|
+
## Maintenance
|
|
661
|
+
|
|
662
|
+
Canonical files:
|
|
663
|
+
|
|
664
|
+
```text
|
|
665
|
+
<dataRoot>/memory/profile.md
|
|
666
|
+
<dataRoot>/memory/preferences.md
|
|
667
|
+
<dataRoot>/memory/projects/<id>.md
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
Models receive full user turns and current authorized documents, and choose retain,
|
|
671
|
+
forget, maintain or ignore using `memory_maintenance_v2`. Only put/remove Section
|
|
672
|
+
operations are accepted; confidence is not an admission threshold. Unmodified
|
|
673
|
+
Sections retain their bytes. The packaged `dist/v2/memory-maintainer.md` is trusted
|
|
674
|
+
instruction text; document and conversation content cannot override it.
|
|
675
|
+
|
|
676
|
+
Every projected observation carries a host-assigned `source_kind`: `user_turn`
|
|
677
|
+
(delivered user expressions from Pi or the MCP relay), `agent_import` (an Init
|
|
678
|
+
submission, with `import.source_label`, `import.basis` and `import.gaps`) or
|
|
679
|
+
`document_import` (one part of a `common-memory import` file, with `import.source_label`,
|
|
680
|
+
`import.file_name`, `import.declared_author`, `import.part {index, count}` and
|
|
681
|
+
`import.heading_path`). The observation's stored `source` maps to one disclosure
|
|
682
|
+
provenance class (`user_explicit`, `agent_observation`, `document_import`); that single
|
|
683
|
+
mapping decides admission, batching, the import guard and authorization. A batch holds one
|
|
684
|
+
scope and one provenance class: user turns, agent imports and document imports never
|
|
685
|
+
share a batch (parts of different Markdown files may). Before any network call the Writer
|
|
686
|
+
checks the batch's class against `disclosure.allowedProvenance`; an unauthorized batch is
|
|
687
|
+
quarantined locally, one head observation per run (`UNAUTHORIZED_PROVENANCE`, like
|
|
688
|
+
`UNAUTHORIZED_SOURCE`), so an init-only or import-only configuration processes what it
|
|
689
|
+
authorizes and never discloses user turns. Import
|
|
690
|
+
observations may support retain with visible attribution; as sole evidence they cannot
|
|
691
|
+
forget, remove or replace Sections that any user turn produced (see "What Init means").
|
|
692
|
+
The request projection gained these fields; the response schema, receipts, database
|
|
693
|
+
schema and existing Markdown are unchanged and need no migration.
|
|
694
|
+
|
|
695
|
+
Scope (`global` or the current project) means applicability. Profile, Preferences and
|
|
696
|
+
Project Markdown are target documents, not semantic domains. The maintainer uses
|
|
697
|
+
non-exhaustive domains such as background/abilities, goals/learning, communication,
|
|
698
|
+
collaboration/decisions, technology/tools, constraints/resources and current state
|
|
699
|
+
as cross-document guidance, not fixed slots. It may reuse or reorganize Sections;
|
|
700
|
+
there is no automatic taxonomy migration and no `domain` or `memory_type` field.
|
|
701
|
+
Domain ≠ Admission ≠ Lifetime ≠ Scope: classification alone does not justify retention.
|
|
702
|
+
|
|
703
|
+
Runtime/database observation `scope` remains source metadata. Model observations and
|
|
704
|
+
context-only turns expose it as `source_scope`. Every decision requires
|
|
705
|
+
`applicability: "global" | "project" | "uncertain"`; global targets authorized Profile
|
|
706
|
+
or Preferences, project targets only the current source project's Markdown (including
|
|
707
|
+
project-limited personal facts/preferences), and uncertain permits only ignore.
|
|
708
|
+
Operations within a decision share its applicability; a batch may contain separate
|
|
709
|
+
decisions for different scopes. The protocol remains `memory_maintenance_v2`, but old
|
|
710
|
+
responses lacking applicability are rejected rather than inferred: custom model
|
|
711
|
+
responses must be updated. Existing Markdown, database, receipts and package exports
|
|
712
|
+
need no migration.
|
|
713
|
+
|
|
714
|
+
Project-source information may introduce, update, correct or qualify Global state only
|
|
715
|
+
through retain with remember/update/correct admission, current valid evidence and the
|
|
716
|
+
existing lifetime judgment. Source scope alone never promotes information. Maintain
|
|
717
|
+
is not promotion: it only reorganizes state already in its target document, without
|
|
718
|
+
introducing new information or corrections. Authorized Global maintain in a Project
|
|
719
|
+
batch may use `evidence: []`; any supplied evidence must be current and valid.
|
|
720
|
+
Retain and forget still require valid current-batch evidence, never context-only turns.
|
|
721
|
+
|
|
722
|
+
Promotion alone leaves Project Markdown unchanged. Duplicate cleanup requires an
|
|
723
|
+
explicit, separate Project maintain decision that preserves unrelated content, not
|
|
724
|
+
forget; both scopes may commit atomically. Global retention associates the current
|
|
725
|
+
promotion evidence, not automatically the old Project Section's historical sources.
|
|
726
|
+
Disclosure, writable scopes, current-project registration, authorized target/section
|
|
727
|
+
handles, path and content safety, complete-snapshot CAS, lease fencing and recovery
|
|
728
|
+
continue to gate writes; cross-project A→B writes remain forbidden.
|
|
729
|
+
|
|
730
|
+
Legacy relay/import triggers: 6 delivered expressions, 16 KiB, 120-second idle debounce, 10-minute
|
|
731
|
+
oldest backlog, lifecycle flush, or explicit flush. Session caches instead seal after exactly ten
|
|
732
|
+
settled interactions, or an actual exit tail; scheduler settings cannot override ten. Empty queues do not call models.
|
|
733
|
+
Request limit is 128 KiB, document soft budget 8 KiB and hard cap 16 KiB. Full turns
|
|
734
|
+
are never truncated; oversized turns are quarantined. Limits are configurable in
|
|
735
|
+
`scheduler` and disclosure `maxTotalBytes` (Writer also exposes deadline/size options).
|
|
736
|
+
|
|
737
|
+
Commits use repository lock → runtime DB transaction, lease fencing, complete-read
|
|
738
|
+
CAS, and recoverable Markdown + permanent immutable receipt publication. No network
|
|
739
|
+
runs under these locks. File-success/DB-failure recovery consumes the original batch
|
|
740
|
+
without another model call; unexpected user edits fail closed. Receipts contain hashes
|
|
741
|
+
and references, not historical Markdown or raw model responses.
|
|
742
|
+
|
|
743
|
+
Processed observation bodies are pruned after 7 days; pending/quarantined bodies
|
|
744
|
+
are not silently consumed. Forget clears current state and related processed bodies,
|
|
745
|
+
not Pi transcripts or underlying storage media, and does not prohibit future explicit
|
|
746
|
+
re-expression from being remembered.
|
|
747
|
+
|
|
748
|
+
## Validation and limitations
|
|
749
|
+
|
|
750
|
+
```sh
|
|
751
|
+
npm ci
|
|
752
|
+
node scripts/verify.mjs
|
|
753
|
+
# 修改包导出/消费方式时,构建后追加:
|
|
754
|
+
npm run test:consumer # 真实 tarball 隔离安装,需要 npm registry;不调用真实模型
|
|
755
|
+
npm pack --dry-run
|
|
756
|
+
# 隔离数据目录 + 合成维护模型:Init 与 Markdown 导入 → 本地文件 → 读取 演示(不证明真实模型语义):
|
|
757
|
+
npm run build && node scripts/demo-init-synthetic.mjs [--home <new-or-empty-dir>] [--markdown notes.md]
|
|
758
|
+
# 构建后验证 smoke 自身的 Responses / Chat 流程(本地 fake Provider,无需 Key):
|
|
759
|
+
npm run test:provider-smoke
|
|
760
|
+
# 真实 Provider:使用现有格式的配置副本,仅复制 remote;Key 来自进程环境:
|
|
761
|
+
node scripts/smoke-provider.mjs --config /path/to/provider-config.json --live
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
The provider smoke requires an explicit `remote.proxy` mode, uses fresh temporary
|
|
765
|
+
storage, and checks source-linked durable receipts plus restarted reads. A processed
|
|
766
|
+
`ignore` does not pass retention. See [the procedure and evidence levels](provider-verification.md)
|
|
767
|
+
for network conditions, reports, and the retained DeepSeek entry point.
|
|
768
|
+
|
|
769
|
+
The demo only writes into a fresh directory (a new temp directory by default); it refuses
|
|
770
|
+
a non-empty `--home` and never deletes or overwrites an existing configuration, `.env` or
|
|
771
|
+
data directory. It prints the Codex/Pi/`show`/`mcp-config` invocations for its data
|
|
772
|
+
directory. Real ChatGPT desktop, Codex CLI and Pi sessions are recorded separately in
|
|
773
|
+
`docs/init-v0.1-verification.md`, which distinguishes synthetic tests, real client
|
|
774
|
+
protocol/host integration, and the real end-to-end loop.
|
|
775
|
+
|
|
776
|
+
### Reading limitations
|
|
777
|
+
|
|
778
|
+
Reads are lock-free file reads of atomically published Markdown; a crash between
|
|
779
|
+
staging and publication is repaired by the next Writer start, so a read-only process
|
|
780
|
+
can briefly see the previous published state. Reads never migrate, repair or create
|
|
781
|
+
canonical files. Consumers receive whole documents; only the Writer bounds their size.
|
|
782
|
+
The `instructions`/description text asks consumers to use memory for questions about
|
|
783
|
+
the user; whether a given client model actually calls `memory_read` for a given
|
|
784
|
+
question is client behaviour, not something this server can enforce.
|
|
785
|
+
|
|
786
|
+
Tests use scripted model responses to prove protocol, capture, scheduling and commit
|
|
787
|
+
behavior; they do not prove that a real model will classify scope correctly or avoid
|
|
788
|
+
misusing maintain for state changes. Those semantic judgments remain the model's
|
|
789
|
+
responsibility; the executor does not use text-comparison heuristics to infer them. Real-provider evaluation
|
|
790
|
+
requires explicit credentials and budget and is not run automatically. Transformed
|
|
791
|
+
inputs are conservatively quarantined; session assistant/tool context requires
|
|
792
|
+
independent `conversation_context` disclosure permission. No old user data directory is cleaned.
|
|
793
|
+
|
|
794
|
+
### Capture trust boundary
|
|
795
|
+
|
|
796
|
+
Pi does not expose an end-to-end original-input token. Common Memory validates the
|
|
797
|
+
input event it receives; an earlier extension can transform text before that event
|
|
798
|
+
reaches this extension, which is not distinguishable through the public API. Place
|
|
799
|
+
Common Memory before input-transforming extensions and treat earlier extensions as
|
|
800
|
+
trusted host components. Transformations after its capture (including built-in prompt
|
|
801
|
+
templates), mixed queued authorities/scopes and ambiguous candidates are isolated.
|
|
802
|
+
This is conservative host-event provenance, not proof against a malicious extension.
|
|
803
|
+
Mixed/image input is quarantined with complete text and an unsupported-content marker;
|
|
804
|
+
image blobs are not collected. Session assistant/tool and prior-turn context is
|
|
805
|
+
marked context_only and never authorizes a write. The default context tail is two
|
|
806
|
+
same-session/scope turns, resolved by reference; forget/prune clears related context.
|
|
807
|
+
|
|
808
|
+
Manual edits to a document invalidate its title-based source links. On the next
|
|
809
|
+
committed maintenance, its stale links and associated processed observation bodies
|
|
810
|
+
are conservatively cleared in the recoverable receipt; current Markdown and other
|
|
811
|
+
documents are not deleted. This avoids retaining orphan evidence after a manual
|
|
812
|
+
rename followed by forget, at the cost of that document's short-term evidence buffer.
|
|
813
|
+
Advanced library configuration exposes `documentSoftBytes`, `documentHardBytes`,
|
|
814
|
+
`retentionMs`, `deadlineMs` and `maxRequestBytes` on Writer. Pi compatibility is pinned
|
|
815
|
+
to 0.84.4, whose callback/queue ordering was inspected for this implementation.
|