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.
Files changed (284) hide show
  1. package/.env.sample +3 -0
  2. package/CHANGELOG.md +39 -0
  3. package/LICENSE +21 -0
  4. package/README.md +120 -0
  5. package/SECURITY.md +48 -0
  6. package/dist/cli/codex/transcript-0.153.4.d.ts +20 -0
  7. package/dist/cli/codex/transcript-0.153.4.d.ts.map +1 -0
  8. package/dist/cli/codex/transcript-0.153.4.js +78 -0
  9. package/dist/cli/codex/transcript-0.153.4.js.map +1 -0
  10. package/dist/cli/codex-config.d.ts +2 -0
  11. package/dist/cli/codex-config.d.ts.map +1 -0
  12. package/dist/cli/codex-config.js +5 -0
  13. package/dist/cli/codex-config.js.map +1 -0
  14. package/dist/cli/codex-hook.d.ts +18 -0
  15. package/dist/cli/codex-hook.d.ts.map +1 -0
  16. package/dist/cli/codex-hook.js +140 -0
  17. package/dist/cli/codex-hook.js.map +1 -0
  18. package/dist/cli/codex-session.d.ts +3 -0
  19. package/dist/cli/codex-session.d.ts.map +1 -0
  20. package/dist/cli/codex-session.js +3 -0
  21. package/dist/cli/codex-session.js.map +1 -0
  22. package/dist/cli/flush-command.d.ts +6 -0
  23. package/dist/cli/flush-command.d.ts.map +1 -0
  24. package/dist/cli/flush-command.js +30 -0
  25. package/dist/cli/flush-command.js.map +1 -0
  26. package/dist/cli/host-launch.d.ts +28 -0
  27. package/dist/cli/host-launch.d.ts.map +1 -0
  28. package/dist/cli/host-launch.js +16 -0
  29. package/dist/cli/host-launch.js.map +1 -0
  30. package/dist/cli/host-process.d.ts +3 -0
  31. package/dist/cli/host-process.d.ts.map +1 -0
  32. package/dist/cli/host-process.js +35 -0
  33. package/dist/cli/host-process.js.map +1 -0
  34. package/dist/cli/host-session.d.ts +22 -0
  35. package/dist/cli/host-session.d.ts.map +1 -0
  36. package/dist/cli/host-session.js +204 -0
  37. package/dist/cli/host-session.js.map +1 -0
  38. package/dist/cli/import-command.d.ts +20 -0
  39. package/dist/cli/import-command.d.ts.map +1 -0
  40. package/dist/cli/import-command.js +98 -0
  41. package/dist/cli/import-command.js.map +1 -0
  42. package/dist/cli/interactive-process.d.ts +3 -0
  43. package/dist/cli/interactive-process.d.ts.map +1 -0
  44. package/dist/cli/interactive-process.js +15 -0
  45. package/dist/cli/interactive-process.js.map +1 -0
  46. package/dist/cli/main.d.ts +3 -0
  47. package/dist/cli/main.d.ts.map +1 -0
  48. package/dist/cli/main.js +151 -0
  49. package/dist/cli/main.js.map +1 -0
  50. package/dist/cli/mcp-config.d.ts +16 -0
  51. package/dist/cli/mcp-config.d.ts.map +1 -0
  52. package/dist/cli/mcp-config.js +108 -0
  53. package/dist/cli/mcp-config.js.map +1 -0
  54. package/dist/cli/network-test.d.ts +4 -0
  55. package/dist/cli/network-test.d.ts.map +1 -0
  56. package/dist/cli/network-test.js +28 -0
  57. package/dist/cli/network-test.js.map +1 -0
  58. package/dist/cli/operations.d.ts +26 -0
  59. package/dist/cli/operations.d.ts.map +1 -0
  60. package/dist/cli/operations.js +55 -0
  61. package/dist/cli/operations.js.map +1 -0
  62. package/dist/cli/session-drain.d.ts +3 -0
  63. package/dist/cli/session-drain.d.ts.map +1 -0
  64. package/dist/cli/session-drain.js +34 -0
  65. package/dist/cli/session-drain.js.map +1 -0
  66. package/dist/cli/storage-paths.d.ts +4 -0
  67. package/dist/cli/storage-paths.d.ts.map +1 -0
  68. package/dist/cli/storage-paths.js +15 -0
  69. package/dist/cli/storage-paths.js.map +1 -0
  70. package/dist/cli/tui-integrations.d.ts +4 -0
  71. package/dist/cli/tui-integrations.d.ts.map +1 -0
  72. package/dist/cli/tui-integrations.js +143 -0
  73. package/dist/cli/tui-integrations.js.map +1 -0
  74. package/dist/cli/tui-prompts.d.ts +22 -0
  75. package/dist/cli/tui-prompts.d.ts.map +1 -0
  76. package/dist/cli/tui-prompts.js +64 -0
  77. package/dist/cli/tui-prompts.js.map +1 -0
  78. package/dist/cli/tui-settings.d.ts +21 -0
  79. package/dist/cli/tui-settings.d.ts.map +1 -0
  80. package/dist/cli/tui-settings.js +198 -0
  81. package/dist/cli/tui-settings.js.map +1 -0
  82. package/dist/cli/tui.d.ts +4 -0
  83. package/dist/cli/tui.d.ts.map +1 -0
  84. package/dist/cli/tui.js +292 -0
  85. package/dist/cli/tui.js.map +1 -0
  86. package/dist/cli/work-config.d.ts +24 -0
  87. package/dist/cli/work-config.d.ts.map +1 -0
  88. package/dist/cli/work-config.js +147 -0
  89. package/dist/cli/work-config.js.map +1 -0
  90. package/dist/config/config.d.ts +41 -0
  91. package/dist/config/config.d.ts.map +1 -0
  92. package/dist/config/config.js +193 -0
  93. package/dist/config/config.js.map +1 -0
  94. package/dist/config/private-env.d.ts +8 -0
  95. package/dist/config/private-env.d.ts.map +1 -0
  96. package/dist/config/private-env.js +38 -0
  97. package/dist/config/private-env.js.map +1 -0
  98. package/dist/config/runtime.d.ts +32 -0
  99. package/dist/config/runtime.d.ts.map +1 -0
  100. package/dist/config/runtime.js +85 -0
  101. package/dist/config/runtime.js.map +1 -0
  102. package/dist/core/contracts/errors.d.ts +10 -0
  103. package/dist/core/contracts/errors.d.ts.map +1 -0
  104. package/dist/core/contracts/errors.js +23 -0
  105. package/dist/core/contracts/errors.js.map +1 -0
  106. package/dist/core/safety/external-preflight.d.ts +7 -0
  107. package/dist/core/safety/external-preflight.d.ts.map +1 -0
  108. package/dist/core/safety/external-preflight.js +47 -0
  109. package/dist/core/safety/external-preflight.js.map +1 -0
  110. package/dist/core/safety/redaction.d.ts +2 -0
  111. package/dist/core/safety/redaction.d.ts.map +1 -0
  112. package/dist/core/safety/redaction.js +4 -0
  113. package/dist/core/safety/redaction.js.map +1 -0
  114. package/dist/core/safety/rules.d.ts +6 -0
  115. package/dist/core/safety/rules.d.ts.map +1 -0
  116. package/dist/core/safety/rules.js +14 -0
  117. package/dist/core/safety/rules.js.map +1 -0
  118. package/dist/core/safety/scanner.d.ts +11 -0
  119. package/dist/core/safety/scanner.d.ts.map +1 -0
  120. package/dist/core/safety/scanner.js +18 -0
  121. package/dist/core/safety/scanner.js.map +1 -0
  122. package/dist/core/transaction/fsync.d.ts +6 -0
  123. package/dist/core/transaction/fsync.d.ts.map +1 -0
  124. package/dist/core/transaction/fsync.js +41 -0
  125. package/dist/core/transaction/fsync.js.map +1 -0
  126. package/dist/index.d.ts +16 -0
  127. package/dist/index.d.ts.map +1 -0
  128. package/dist/index.js +13 -0
  129. package/dist/index.js.map +1 -0
  130. package/dist/mcp/ingress.d.ts +61 -0
  131. package/dist/mcp/ingress.d.ts.map +1 -0
  132. package/dist/mcp/ingress.js +134 -0
  133. package/dist/mcp/ingress.js.map +1 -0
  134. package/dist/mcp/server.d.ts +4 -0
  135. package/dist/mcp/server.d.ts.map +1 -0
  136. package/dist/mcp/server.js +92 -0
  137. package/dist/mcp/server.js.map +1 -0
  138. package/dist/mcp/stdio.d.ts +5 -0
  139. package/dist/mcp/stdio.d.ts.map +1 -0
  140. package/dist/mcp/stdio.js +115 -0
  141. package/dist/mcp/stdio.js.map +1 -0
  142. package/dist/memory-manager/contracts/diagnostic.d.ts +14 -0
  143. package/dist/memory-manager/contracts/diagnostic.d.ts.map +1 -0
  144. package/dist/memory-manager/contracts/diagnostic.js +17 -0
  145. package/dist/memory-manager/contracts/diagnostic.js.map +1 -0
  146. package/dist/memory-manager/contracts/disclosure.d.ts +12 -0
  147. package/dist/memory-manager/contracts/disclosure.d.ts.map +1 -0
  148. package/dist/memory-manager/contracts/disclosure.js +8 -0
  149. package/dist/memory-manager/contracts/disclosure.js.map +1 -0
  150. package/dist/memory-manager/contracts/errors.d.ts +15 -0
  151. package/dist/memory-manager/contracts/errors.d.ts.map +1 -0
  152. package/dist/memory-manager/contracts/errors.js +25 -0
  153. package/dist/memory-manager/contracts/errors.js.map +1 -0
  154. package/dist/memory-manager/contracts/model-port.d.ts +38 -0
  155. package/dist/memory-manager/contracts/model-port.d.ts.map +1 -0
  156. package/dist/memory-manager/contracts/model-port.js +2 -0
  157. package/dist/memory-manager/contracts/model-port.js.map +1 -0
  158. package/dist/memory-manager/network/client.d.ts +13 -0
  159. package/dist/memory-manager/network/client.d.ts.map +1 -0
  160. package/dist/memory-manager/network/client.js +122 -0
  161. package/dist/memory-manager/network/client.js.map +1 -0
  162. package/dist/memory-manager/network/route.d.ts +31 -0
  163. package/dist/memory-manager/network/route.d.ts.map +1 -0
  164. package/dist/memory-manager/network/route.js +148 -0
  165. package/dist/memory-manager/network/route.js.map +1 -0
  166. package/dist/memory-manager/openai/abort.d.ts +4 -0
  167. package/dist/memory-manager/openai/abort.d.ts.map +1 -0
  168. package/dist/memory-manager/openai/abort.js +19 -0
  169. package/dist/memory-manager/openai/abort.js.map +1 -0
  170. package/dist/memory-manager/openai/bounded-body.d.ts +2 -0
  171. package/dist/memory-manager/openai/bounded-body.d.ts.map +1 -0
  172. package/dist/memory-manager/openai/bounded-body.js +49 -0
  173. package/dist/memory-manager/openai/bounded-body.js.map +1 -0
  174. package/dist/memory-manager/openai/openai-chat-adapter.d.ts +16 -0
  175. package/dist/memory-manager/openai/openai-chat-adapter.d.ts.map +1 -0
  176. package/dist/memory-manager/openai/openai-chat-adapter.js +51 -0
  177. package/dist/memory-manager/openai/openai-chat-adapter.js.map +1 -0
  178. package/dist/memory-manager/openai/openai-responses-adapter.d.ts +15 -0
  179. package/dist/memory-manager/openai/openai-responses-adapter.d.ts.map +1 -0
  180. package/dist/memory-manager/openai/openai-responses-adapter.js +14 -0
  181. package/dist/memory-manager/openai/openai-responses-adapter.js.map +1 -0
  182. package/dist/memory-manager/openai/options.d.ts +14 -0
  183. package/dist/memory-manager/openai/options.d.ts.map +1 -0
  184. package/dist/memory-manager/openai/options.js +29 -0
  185. package/dist/memory-manager/openai/options.js.map +1 -0
  186. package/dist/memory-manager/openai/remote-http.d.ts +33 -0
  187. package/dist/memory-manager/openai/remote-http.d.ts.map +1 -0
  188. package/dist/memory-manager/openai/remote-http.js +207 -0
  189. package/dist/memory-manager/openai/remote-http.js.map +1 -0
  190. package/dist/memory-manager/openai/response-decoder.d.ts +3 -0
  191. package/dist/memory-manager/openai/response-decoder.d.ts.map +1 -0
  192. package/dist/memory-manager/openai/response-decoder.js +57 -0
  193. package/dist/memory-manager/openai/response-decoder.js.map +1 -0
  194. package/dist/memory-manager/openai/retry.d.ts +8 -0
  195. package/dist/memory-manager/openai/retry.d.ts.map +1 -0
  196. package/dist/memory-manager/openai/retry.js +18 -0
  197. package/dist/memory-manager/openai/retry.js.map +1 -0
  198. package/dist/pi-extension/extraction-runtime.d.ts +51 -0
  199. package/dist/pi-extension/extraction-runtime.d.ts.map +1 -0
  200. package/dist/pi-extension/extraction-runtime.js +87 -0
  201. package/dist/pi-extension/extraction-runtime.js.map +1 -0
  202. package/dist/pi-extension/index.d.ts +19 -0
  203. package/dist/pi-extension/index.d.ts.map +1 -0
  204. package/dist/pi-extension/index.js +172 -0
  205. package/dist/pi-extension/index.js.map +1 -0
  206. package/dist/v2/canonical.d.ts +53 -0
  207. package/dist/v2/canonical.d.ts.map +1 -0
  208. package/dist/v2/canonical.js +321 -0
  209. package/dist/v2/canonical.js.map +1 -0
  210. package/dist/v2/contract.d.ts +34 -0
  211. package/dist/v2/contract.d.ts.map +1 -0
  212. package/dist/v2/contract.js +53 -0
  213. package/dist/v2/contract.js.map +1 -0
  214. package/dist/v2/document-import.d.ts +100 -0
  215. package/dist/v2/document-import.d.ts.map +1 -0
  216. package/dist/v2/document-import.js +259 -0
  217. package/dist/v2/document-import.js.map +1 -0
  218. package/dist/v2/errors.d.ts +6 -0
  219. package/dist/v2/errors.d.ts.map +1 -0
  220. package/dist/v2/errors.js +29 -0
  221. package/dist/v2/errors.js.map +1 -0
  222. package/dist/v2/import.d.ts +26 -0
  223. package/dist/v2/import.d.ts.map +1 -0
  224. package/dist/v2/import.js +48 -0
  225. package/dist/v2/import.js.map +1 -0
  226. package/dist/v2/lock.d.ts +3 -0
  227. package/dist/v2/lock.d.ts.map +1 -0
  228. package/dist/v2/lock.js +47 -0
  229. package/dist/v2/lock.js.map +1 -0
  230. package/dist/v2/memory-maintainer.md +38 -0
  231. package/dist/v2/read-guidance.d.ts +3 -0
  232. package/dist/v2/read-guidance.d.ts.map +1 -0
  233. package/dist/v2/read-guidance.js +3 -0
  234. package/dist/v2/read-guidance.js.map +1 -0
  235. package/dist/v2/reader.d.ts +25 -0
  236. package/dist/v2/reader.d.ts.map +1 -0
  237. package/dist/v2/reader.js +38 -0
  238. package/dist/v2/reader.js.map +1 -0
  239. package/dist/v2/registry.d.ts +14 -0
  240. package/dist/v2/registry.d.ts.map +1 -0
  241. package/dist/v2/registry.js +46 -0
  242. package/dist/v2/registry.js.map +1 -0
  243. package/dist/v2/runtime.d.ts +133 -0
  244. package/dist/v2/runtime.d.ts.map +1 -0
  245. package/dist/v2/runtime.js +326 -0
  246. package/dist/v2/runtime.js.map +1 -0
  247. package/dist/v2/session-drain.d.ts +14 -0
  248. package/dist/v2/session-drain.d.ts.map +1 -0
  249. package/dist/v2/session-drain.js +16 -0
  250. package/dist/v2/session-drain.js.map +1 -0
  251. package/dist/v2/session.d.ts +54 -0
  252. package/dist/v2/session.d.ts.map +1 -0
  253. package/dist/v2/session.js +158 -0
  254. package/dist/v2/session.js.map +1 -0
  255. package/dist/v2/writer.d.ts +40 -0
  256. package/dist/v2/writer.d.ts.map +1 -0
  257. package/dist/v2/writer.js +327 -0
  258. package/dist/v2/writer.js.map +1 -0
  259. package/docs/00-index.md +19 -0
  260. package/docs/03-target-architecture.md +49 -0
  261. package/docs/init-v0.1-closeout.md +152 -0
  262. package/docs/init-v0.1-design.md +237 -0
  263. package/docs/init-v0.1-verification.md +303 -0
  264. package/docs/outbound-network-design.md +100 -0
  265. package/docs/outbound-network-verification.json +300 -0
  266. package/docs/provider-verification.md +94 -0
  267. package/docs/releasing.md +138 -0
  268. package/docs/session-integration.md +134 -0
  269. package/docs/tui-workbench.md +173 -0
  270. package/docs/usage.md +815 -0
  271. package/docs/v2-ablation-results.json +12035 -0
  272. package/docs/v2-ablation.md +117 -0
  273. package/docs/v2-evaluation-repeat-results.json +7 -0
  274. package/docs/v2-evaluation-scripted-results.json +67 -0
  275. package/docs/v2-evaluation.md +35 -0
  276. package/docs/v2-optimization-plan.md +23 -0
  277. package/docs/v2-performance-baseline-runtime.js.txt +231 -0
  278. package/docs/v2-performance-baseline.json +338 -0
  279. package/docs/v2-performance-behavior-equivalence.json +17 -0
  280. package/docs/v2-performance-results.json +585 -0
  281. package/docs/v2-performance.md +88 -0
  282. package/docs/v2-replacement-test-map.md +14 -0
  283. package/docs/v2-verification.md +49 -0
  284. package/package.json +87 -0
@@ -0,0 +1,327 @@
1
+ import { sessionGroup, sessionProjection } from './session.js';
2
+ import { readFileSync } from 'node:fs';
3
+ import { createHash } from 'node:crypto';
4
+ import { CanonicalStore } from './canonical.js';
5
+ import { RuntimeStore } from './runtime.js';
6
+ import { ProjectRegistry } from './registry.js';
7
+ import { withRepositoryLock } from './lock.js';
8
+ import { sanitizeDiagnostic } from '../memory-manager/contracts/diagnostic.js';
9
+ import { failureDiagnostic, failureCode } from './errors.js';
10
+ import { maintenanceSchema, validateDecision } from './contract.js';
11
+ import { externalPreflight } from '../core/safety/external-preflight.js';
12
+ import { AGENT_IMPORT_SOURCE, DOCUMENT_IMPORT_SOURCE, decodeAgentImport, isImportSource, provenanceOf } from './import.js';
13
+ import { decodeDocumentChunk } from './document-import.js';
14
+ export const maintainerPrompt = readFileSync(new URL('./memory-maintainer.md', import.meta.url), 'utf8');
15
+ /** Network runs outside both locks. Canonical commits are fenced inside lock -> DB. */
16
+ export class Writer {
17
+ store;
18
+ canonical;
19
+ #options;
20
+ constructor(options) {
21
+ this.#options = { ...options, allowedScopes: [...options.allowedScopes], writableScopes: [...(options.writableScopes ?? options.allowedScopes)] };
22
+ for (const n of [options.deadlineMs ?? 60000, options.maxRequestBytes ?? 131072, options.retentionMs ?? 604800000, options.documentSoftBytes ?? 8192])
23
+ if (!Number.isSafeInteger(n) || n <= 0)
24
+ throw new Error('INVALID_WRITER_LIMIT');
25
+ if ((options.documentSoftBytes ?? 8192) > (options.documentHardBytes ?? 16384))
26
+ throw new Error('INVALID_DOCUMENT_BUDGET');
27
+ this.canonical = new CanonicalStore(options.dataRoot, { hardLimitBytes: options.documentHardBytes ?? 16384 });
28
+ this.store = new RuntimeStore(options.dataRoot, options.scheduler);
29
+ try {
30
+ this.recover();
31
+ this.store.pruneProcessed(this.#options.retentionMs);
32
+ }
33
+ catch (error) {
34
+ this.store.close();
35
+ throw error;
36
+ }
37
+ }
38
+ recover() { this.#recover(); }
39
+ #recover(jobId) {
40
+ return withRepositoryLock(this.#options.dataRoot, () => this.store.transaction(() => {
41
+ this.canonical.recover();
42
+ const receipts = this.canonical.receipts();
43
+ for (const receipt of receipts)
44
+ this.store.recoverReceipt(receipt);
45
+ if (!jobId || !this.store.hasReceipt(jobId))
46
+ return null;
47
+ // File commits have immutable canonical receipts; ignore commits have a durable DB receipt only.
48
+ // Another lease may have made a different decision from this run's late response.
49
+ return receipts.some(receipt => receipt.id === jobId) ? 'committed' : 'ignored';
50
+ }));
51
+ }
52
+ async run(options = {}) {
53
+ this.store.pruneProcessed(this.#options.retentionMs);
54
+ if (!this.store.hasWork())
55
+ return { outcome: 'idle' };
56
+ this.recover();
57
+ const claimed = this.store.claim(options);
58
+ if (!claimed)
59
+ return { outcome: 'idle' };
60
+ let job = claimed;
61
+ const controller = new AbortController();
62
+ // First terminal cause wins, even if the model rejects with its own generic cancellation later.
63
+ const terminate = (reason) => { if (!controller.signal.aborted)
64
+ controller.abort(new Error(reason)); };
65
+ const cancelled = () => terminate('CANCELLED');
66
+ options.signal?.addEventListener('abort', cancelled, { once: true });
67
+ if (options.signal?.aborted)
68
+ cancelled();
69
+ const deadlineTimer = setTimeout(() => terminate('TIMEOUT'), this.#options.deadlineMs ?? 60000);
70
+ deadlineTimer.unref();
71
+ const signal = controller.signal;
72
+ let stage = 'core_validation';
73
+ let remoteContext = null;
74
+ const timer = setInterval(() => { try {
75
+ this.store.renew(job);
76
+ }
77
+ catch {
78
+ terminate('LEASE_RENEWAL_FAILED');
79
+ } }, Math.max(1, Math.floor((this.#options.scheduler?.leaseMs ?? 120000) / 3)));
80
+ timer.unref();
81
+ try {
82
+ signal.throwIfAborted();
83
+ const scope = job.observations[0].scope;
84
+ if (!this.#options.allowedScopes.includes(scope))
85
+ return this.#quarantine(job, 'UNAUTHORIZED_SOURCE');
86
+ // Disclosure authorization is per provenance class, not per process: an init-only configuration
87
+ // processes imports while any user turn that reaches this queue stays local.
88
+ const provenance = provenanceOf(job.observations[0].source);
89
+ if (this.#options.allowedProvenance && (!provenance || !this.#options.allowedProvenance.includes(provenance)))
90
+ return this.#quarantine(job, 'UNAUTHORIZED_PROVENANCE');
91
+ const registered = new ProjectRegistry(this.#options.dataRoot).list();
92
+ if (scope !== 'global' && !registered.some(p => `project:${p.id}` === scope))
93
+ return this.#quarantine(job, 'UNREGISTERED_PROJECT');
94
+ const documents = withRepositoryLock(this.#options.dataRoot, () => this.canonical.snapshot(scope === 'global' ? [] : [scope.slice(8)]))
95
+ .filter(doc => this.#options.allowedScopes.includes(documentScope(doc)));
96
+ const cap = this.#options.maxRequestBytes ?? 131072;
97
+ for (const observation of job.observations) {
98
+ try {
99
+ externalPreflight({ text: observation.text }, { maxExcerptBytes: cap, maxCandidateBytes: cap, maxTotalBytes: Number.MAX_SAFE_INTEGER });
100
+ }
101
+ catch {
102
+ this.store.quarantine(job, observation.id, 'SENSITIVE_INPUT');
103
+ return { outcome: 'quarantined' };
104
+ }
105
+ }
106
+ let context = this.#options.allowedProvenance?.includes('conversation_context') === true ? this.store.context(job.observations[0]) : [];
107
+ let sessionTail = this.#options.sessionCache?.contextTailTurns ?? 2;
108
+ let request = this.#request(job, documents, context, sessionTail);
109
+ if (this.#bytes(request) > cap) {
110
+ sessionTail = 0;
111
+ request = this.#request(job, documents, context, sessionTail);
112
+ }
113
+ while (this.#bytes(request) > cap && context.length) {
114
+ context = context.slice(1);
115
+ request = this.#request(job, documents, context, sessionTail);
116
+ }
117
+ while (this.#bytes(request) > cap && job.observations.length > 1) {
118
+ const last = sessionGroup(this.store, job.observations.at(-1));
119
+ const count = last ? job.observations.findIndex(o => sessionGroup(this.store, o)?.turn === last.turn) : job.observations.length - 1;
120
+ if (count === 0)
121
+ break;
122
+ job = this.store.trim(job, count);
123
+ request = this.#request(job, documents, context, sessionTail);
124
+ }
125
+ if (this.#bytes(request) > cap)
126
+ return this.#quarantine(job, 'OVERSIZED_COMPLETE_TURN');
127
+ externalPreflight(request.projection, { maxExcerptBytes: cap, maxCandidateBytes: cap, maxTotalBytes: cap });
128
+ signal.throwIfAborted();
129
+ const result = await abortable(this.#options.model.analyze(request, { requestId: job.id, deadlineMs: this.#options.deadlineMs ?? 60000, signal, onDiagnosticContext: context => { remoteContext = sanitizeDiagnostic({ ...context, reason: 'timeout', retryable: true }); } }), signal);
130
+ signal.throwIfAborted();
131
+ if (result.kind === 'refusal')
132
+ throw new Error('MODEL_REFUSAL');
133
+ const evidence = new Map(job.observations.map(o => [`ev_${o.id}`, o.scope]));
134
+ const decision = validateDecision(result.body, job.id, documents, evidence);
135
+ this.#guardImports(job, decision.decisions, documents);
136
+ const operations = decision.decisions.flatMap(d => d.kind === 'ignore' ? [] : d.operations);
137
+ for (const op of operations)
138
+ if (op.target.startsWith('project:') && op.target !== scope)
139
+ throw new Error('UNAUTHORIZED_SCOPE');
140
+ for (const op of operations)
141
+ if (!this.#options.writableScopes.includes(op.target.startsWith('project:') ? op.target : 'global'))
142
+ throw new Error('UNAUTHORIZED_WRITE');
143
+ const updates = this.canonical.apply(documents, operations);
144
+ externalPreflight(Object.fromEntries(updates), { maxExcerptBytes: cap, maxCandidateBytes: cap, maxTotalBytes: cap });
145
+ stage = 'commit';
146
+ withRepositoryLock(this.#options.dataRoot, () => this.store.transaction(() => {
147
+ signal.throwIfAborted();
148
+ this.store.assertLease(job);
149
+ if (scope !== 'global' && !new ProjectRegistry(this.#options.dataRoot).list().some(p => `project:${p.id}` === scope))
150
+ throw new Error('UNAUTHORIZED_SCOPE');
151
+ // Even ignore is tied to the complete snapshot, never consume a stale analysis.
152
+ const current = this.canonical.snapshot(scope === 'global' ? [] : [scope.slice(8)]);
153
+ if (documents.some(doc => current.find(d => d.target === doc.target)?.hash !== doc.hash))
154
+ throw new Error('STALE_REVISION');
155
+ const receipt = this.#receipt(job, documents, decision.decisions, updates);
156
+ if (!operations.length) {
157
+ this.store.finish(job, receipt);
158
+ return;
159
+ }
160
+ this.canonical.commit(documents, updates, { ...receipt, id: job.id, version: 2, decisions: decision.decisions.map(d => d.kind),
161
+ promptDigest: digest(maintainerPrompt), modelVersion: this.#options.modelVersion ?? 'configured-model', timestamp: new Date().toISOString(), usage: result.usage,
162
+ sources: job.observations.map(o => ({ id: o.id, sessionId: o.sessionId, entryId: o.entryId, digest: digest(o.text ?? '') })),
163
+ documents: documents.map(doc => ({ target: doc.target, before: doc.hash, after: updates.has(doc.target) ? digest(updates.get(doc.target)) : doc.hash })),
164
+ }, () => { signal.throwIfAborted(); this.store.assertLease(job); });
165
+ this.#options.checkpoint?.('files_committed');
166
+ this.store.finish(job, receipt);
167
+ }));
168
+ return { outcome: operations.length ? 'committed' : 'ignored' };
169
+ }
170
+ catch (error) {
171
+ // A durable receipt wins over transient DB failure; startup reconciles without another model call.
172
+ let recovered;
173
+ try {
174
+ recovered = this.#recover(job.id);
175
+ }
176
+ catch {
177
+ try {
178
+ this.store.fail(job, new Error('RECOVERY_CONFLICT'));
179
+ }
180
+ catch { /* Lease may already be fenced. */ }
181
+ return { outcome: 'failed', reason: 'RECOVERY_CONFLICT' };
182
+ }
183
+ if (recovered)
184
+ return { outcome: recovered };
185
+ const cause = signal.aborted ? signal.reason : error;
186
+ const diagnostic = failureDiagnostic(cause, stage);
187
+ // The abort reason remains authoritative; only controlled progress scalars supply missing HTTP context.
188
+ const context = remoteContext;
189
+ if (signal.aborted && context && ['TIMEOUT', 'CANCELLED'].includes(failureCode(cause))) {
190
+ diagnostic.stage = context.stage;
191
+ if (context.httpStatus !== undefined)
192
+ diagnostic.httpStatus = context.httpStatus;
193
+ }
194
+ try {
195
+ this.store.fail(job, cause, diagnostic);
196
+ }
197
+ catch { /* A recovered receipt or superseded lease owns this batch. */ }
198
+ const reason = failureCode(cause);
199
+ return { outcome: reason === 'CANCELLED' ? 'cancelled' : 'failed', reason };
200
+ }
201
+ finally {
202
+ clearInterval(timer);
203
+ clearTimeout(deadlineTimer);
204
+ options.signal?.removeEventListener('abort', cancelled);
205
+ }
206
+ }
207
+ #quarantine(job, issue) { this.store.quarantine(job, job.observations[0].id, issue); return { outcome: 'quarantined' }; }
208
+ /**
209
+ * Imports (another agent's summary, an imported document) are data, not authority over what the user
210
+ * said. A decision backed only by import evidence (or an evidence-free decision in an import-only
211
+ * batch) may append new Sections or rework Sections whose every linked source is itself an import;
212
+ * it can never forget, remove or replace user-derived or unlinked Sections.
213
+ */
214
+ #guardImports(job, decisions, documents) {
215
+ const imported = new Set(job.observations.filter(o => isImportSource(o.source)).map(o => `ev_${o.id}`));
216
+ if (!imported.size)
217
+ return;
218
+ const importOnlyBatch = imported.size === job.observations.length;
219
+ for (const d of decisions) {
220
+ if (d.kind === 'ignore')
221
+ continue;
222
+ const importOnly = d.evidence.length ? d.evidence.every(ref => imported.has(ref)) : importOnlyBatch;
223
+ if (!importOnly)
224
+ continue;
225
+ if (d.kind === 'forget')
226
+ throw new Error('UNAUTHORIZED_FORGET_EVIDENCE');
227
+ for (const op of d.operations) {
228
+ if (op.section === null)
229
+ continue;
230
+ const doc = documents.find(doc => doc.target === op.target);
231
+ const title = doc?.sections.find(s => s.ref === op.section)?.title;
232
+ // A manually edited document has stale title links (the receipt below clears them); a hand-edited
233
+ // Section is the user's, so its old import links must not authorize an import to rewrite it.
234
+ const prior = doc ? this.store.documentVersion(doc.target) : null;
235
+ const externallyEdited = doc !== undefined && prior !== null && prior !== doc.hash;
236
+ const sources = title === undefined || externallyEdited ? [] : this.store.sources(`${op.target}:${digest(title)}`);
237
+ const ownedByImports = sources.length > 0 && this.store.sourceKinds(sources).every(isImportSource);
238
+ if (!ownedByImports)
239
+ throw new Error('UNAUTHORIZED_IMPORT_OVERWRITE');
240
+ }
241
+ }
242
+ }
243
+ #request(job, documents, context = [], sessionTail = 2) {
244
+ return { prompt: maintainerPrompt, schema: maintenanceSchema, schemaName: 'memory_maintenance_v2', projection: {
245
+ conversation_turns: sessionProjection(this.store, job, this.#options.allowedProvenance?.includes('conversation_context') === true, sessionTail),
246
+ version: 'memory_maintenance_v2', request_id: job.id, now: new Date().toISOString(),
247
+ observations: job.observations.map(o => ({ ref: `ev_${o.id}`, ...describeSource(o), source_scope: o.scope, observed_at: o.observedAt, context_only: false })),
248
+ documents: documents.map(doc => ({ target: doc.target, hash: doc.hash, content: doc.content, sections: doc.sections, soft_budget_bytes: this.#options.documentSoftBytes ?? 8192, hard_budget_bytes: this.canonical.hardLimitBytes, writable: this.#options.writableScopes.includes(documentScope(doc)) })),
249
+ context_only: context.map(o => ({ ...describeSource(o), observed_at: o.observedAt, source_scope: o.scope, context_only: true })),
250
+ } };
251
+ }
252
+ #bytes(request) { return this.#options.model.serializedRequestBytes?.(request) ?? Buffer.byteLength(JSON.stringify(request)); }
253
+ #receipt(job, documents, decisions, updates) {
254
+ const associations = [], removeTargets = [], forget = new Set();
255
+ // Manual Markdown edits invalidate title-based sidecar identities. Keep current
256
+ // Markdown, but conservatively purge this document's short-lived source bodies
257
+ // and stale links in the same recoverable receipt, never guess a rename.
258
+ const externallyEdited = new Set();
259
+ for (const doc of documents) {
260
+ const prior = this.store.documentVersion(doc.target);
261
+ if (prior !== null && prior !== doc.hash) {
262
+ externallyEdited.add(doc.target);
263
+ for (const key of this.store.documentSourceKeys(doc.target)) {
264
+ removeTargets.push(key);
265
+ for (const id of this.store.sources(key))
266
+ forget.add(id);
267
+ }
268
+ }
269
+ }
270
+ for (const d of decisions) {
271
+ if (d.kind === 'ignore')
272
+ continue;
273
+ const removedSources = new Set();
274
+ const priorSources = new Map();
275
+ for (const op of d.operations) {
276
+ const title = documents.find(doc => doc.target === op.target)?.sections.find(s => s.ref === op.section)?.title;
277
+ if (title !== undefined) {
278
+ const key = `${op.target}:${digest(title)}`;
279
+ removeTargets.push(key);
280
+ const sources = externallyEdited.has(op.target) ? [] : this.store.sources(key);
281
+ priorSources.set(`${op.target}:${op.section}`, sources);
282
+ for (const id of sources) {
283
+ if (op.op === 'remove_section')
284
+ removedSources.add(id);
285
+ if (d.kind === 'forget')
286
+ forget.add(id);
287
+ }
288
+ }
289
+ }
290
+ if (d.kind === 'forget')
291
+ for (const ref of d.evidence)
292
+ forget.add(Number(ref.slice(3)));
293
+ for (const op of d.operations)
294
+ if (op.op === 'put_section') {
295
+ // Replacements inherit themselves, never other replaced sections. Explicit
296
+ // removals in this decision supply move/merge sources to the destination.
297
+ const inherited = [...(priorSources.get(`${op.target}:${op.section}`) ?? []), ...removedSources];
298
+ associations.push({ target: `${op.target}:${digest(op.title)}`, sourceIds: [...new Set([...inherited, ...d.evidence.map(ref => Number(ref.slice(3)))])] });
299
+ }
300
+ }
301
+ return { documents: documents.map(doc => ({ target: doc.target, after: updates.has(doc.target) ? digest(updates.get(doc.target)) : doc.hash })), jobId: job.id, observationIds: job.observations.map(o => o.id), associations, removeTargets, forgetSourceIds: [...forget] };
302
+ }
303
+ close() { this.store.close(); }
304
+ }
305
+ function documentScope(doc) { return doc.target.startsWith('project:') ? doc.target : 'global'; }
306
+ /** The host, not the text, tells the model whether it reads a user turn, another agent's summary or an imported file. */
307
+ function describeSource(o) {
308
+ if (o.source === AGENT_IMPORT_SOURCE) {
309
+ const payload = o.text === null ? null : decodeAgentImport(o.text);
310
+ if (!payload)
311
+ return { text: o.text, source_kind: 'agent_import', import: { source_label: 'unknown', basis: 'unknown', gaps: null } };
312
+ return { text: payload.understanding, source_kind: 'agent_import', import: { source_label: payload.sourceLabel, basis: payload.basis, gaps: payload.gaps ?? null } };
313
+ }
314
+ if (o.source === DOCUMENT_IMPORT_SOURCE) {
315
+ const chunk = o.text === null ? null : decodeDocumentChunk(o.text);
316
+ if (!chunk)
317
+ return { text: o.text, source_kind: 'document_import', import: { source_label: 'unknown', declared_author: 'unknown', file_name: 'unknown', part: { index: 1, count: 1 }, heading_path: [] } };
318
+ return { text: chunk.text, source_kind: 'document_import', import: { source_label: chunk.sourceLabel, declared_author: chunk.declaredAuthor, file_name: chunk.fileName, part: chunk.part, heading_path: chunk.headingPath } };
319
+ }
320
+ return { text: o.text, source_kind: 'user_turn' };
321
+ }
322
+ function digest(value) { return createHash('sha256').update(value).digest('hex'); }
323
+ function abortable(promise, signal) {
324
+ return new Promise((resolve, reject) => { const abort = () => reject(signal.reason); signal.addEventListener('abort', abort, { once: true }); if (signal.aborted)
325
+ abort(); promise.then(resolve, reject).finally(() => signal.removeEventListener('abort', abort)); });
326
+ }
327
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/v2/writer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ # Common Memory V2 文档
2
+
3
+ - [发布、支持范围、安装与备份](releasing.md)
4
+ - [安全与隐私](../SECURITY.md)
5
+ - [版本变更](../CHANGELOG.md)
6
+ - [统一交互工作台:设计、入口清单与边界](tui-workbench.md)
7
+ - [会话接入与验收边界](session-integration.md)
8
+ - [实施规格与架构决定](03-target-architecture.md)
9
+ - [Init v0.1:跨 Agent 记忆迁移与复用 — 研究、设计与计划](init-v0.1-design.md)
10
+ - [Init v0.1:验收记录](init-v0.1-verification.md)
11
+ - [旧测试替换边界](v2-replacement-test-map.md)
12
+ - [合成轨迹与真实模型评测边界](v2-evaluation.md)
13
+ - [实现性能优化](v2-performance.md)
14
+ - [调度机制消融实验](v2-ablation.md)
15
+ - [交付验证与独立审查](v2-verification.md)
16
+ - [安装与快速开始](../README.md)
17
+ - [完整使用与配置](usage.md)
18
+
19
+ Write/current-state 之外,Init v0.1 增加了三条受授权约束的接口:Init(其他 Agent 提交自述理解)、Markdown 导入(`common-memory import`,文件经输入预处理成为 `document_import` 观察)——两者都仍由同一个 Writer 决定写入——与只读披露(MCP `memory_read`、Pi 系统提示注入、CLI `show`,按 `disclosure.allowedScopes` 与启动上下文返回当前 Markdown 原文)。旧 YAML Fact、Proposal、Review、Recall/FTS、Undo 文档及资产已随实现删除,不作为 V2 规范或兼容保证;本版也不引入检索、索引或排序。
@@ -0,0 +1,49 @@
1
+ # Common Memory V2:批准规格与实现决定
2
+
3
+ ## 产品边界
4
+
5
+ 持久化实际用户投递 → 稳定消息身份绑定 → session 十轮封批 / legacy 混合触发 → 模型决策 → 有限 Markdown Section 更新 → 可恢复提交。
6
+ Write 及必要当前状态检查。Markdown 是长期内容权威;runtime SQLite 是不可随意重建的队列、租约和来源元数据。删除 Fact/Proposal/Review、Recall/FTS/ranking/context pack、治理/Undo 及兼容层,不迁移、不删除工作区外用户数据。不引入 Temporary Store、向量库或常驻服务。
7
+
8
+ **Init v0.1 增补(2026-09-07,见 `init-v0.1-design.md`)**:本节最初写的“仅 Write”已放宽为两条受授权约束的接口。(1) Init:`memory_init` 把其他 Agent 的自述理解作为 `agent_import` 观察进入同一队列,由不变的 Writer 决策;投影新增 `source_kind`/`import` 字段,输出协议不变;agent_import 不能单独作为 forget 证据。(1b) Markdown 导入(收尾增补,见 `init-v0.1-design.md` §9):`common-memory import <file.md>` 经输入预处理(文件校验、结构化分块、信封)成为 `document_import` 观察,走同一队列、同一 Writer、同一导入守卫;来源→provenance 映射(`src/v2/import.ts`)统一决定入队、分批与按 `disclosure.allowedProvenance` 的逐批授权。(2) 只读披露:`src/v2/reader.ts` 按启动上下文 ∩ `disclosure.allowedScopes` 返回当前 Markdown 原文(不建目录、不开 SQLite、不取锁),供 MCP `memory_read`(`--capability read` 进程)、Pi `before_agent_start` 注入与 CLI `show` 共用。仍不引入检索、索引、排序或 Recall 写权限。
9
+
10
+ ## 理由与批准计划的研究记录
11
+
12
+ 有限 Section patch 而非整篇重写:CAS 只能防并发覆盖,无法识别模型遗漏。未修改 Section 逐字节保留。模型决定 admission、生命周期和语义;执行器仅校验协议、权限、秘密与资源边界,不设 confidence 阈值。
13
+
14
+ 以下参考来源继承自批准的研究计划,属于设计启发,不是本实现的实测优胜证据:
15
+ - Hermes 周期检查:[turn_context](https://github.com/NousResearch/hermes-agent/blob/2e24e06e5513fa425ccf935d2e41991cb11ff383/agent/turn_context.py#L542-L551)、[后台隔离](https://github.com/NousResearch/hermes-agent/blob/2e24e06e5513fa425ccf935d2e41991cb11ff383/agent/turn_finalizer.py#L602-L616)。
16
+ - LangGraph/LangMem:[memory-template](https://github.com/langchain-ai/memory-template)。
17
+ - Letta:[sleep-time](https://www.letta.com/blog/sleep-time-compute/)、[memory blocks](https://www.letta.com/blog/memory-blocks/)。
18
+ - Mem0 更新、合并、删除:[论文](https://arxiv.org/abs/2504.19413)。
19
+ - 更新与不写应独立验收:[LongMemEval](https://arxiv.org/abs/2410.10813)。
20
+
21
+ Legacy relay/import 保留混合调度;Pi/Codex 会话以十次 settled 交互与退出尾批封批,详见 [会话接入](session-integration.md)。不宣称参数已优化。宿主事件顺序以锁文件安装的 Pi 源码核验。
22
+
23
+ ## Capture / 调度
24
+
25
+ input 只登记来源与冻结 cwd→project。message_end 持久化待绑定,再用稳定 Entry ID 绑定;不依赖助手成功。未投递输入不得成为 evidence。模板变换、扩展来源、无法证明唯一关系和不支持的多模态输入保守隔离,不重标 global。宿主缺少完整投递链 ID 时宁可隔离,不猜来源。
26
+
27
+ Legacy 默认 6 条 / 16 KiB / 120 秒空闲 / 10 分钟最老积压;生命周期和本地 flush 请求处理。Pi/Codex 十轮会话批次不混入其他 session 或 import;真正退出封尾并唤醒独立消费者,等待正常租约与退避。dataRoot 单任务、领取后不合并新观察、正常 FIFO;隔离/dead-letter 可见且不堵后续正常队列。60 秒 deadline、120 秒续租 lease、指数退避最多 5 次,可本地 retry。
28
+
29
+ ## Model / Markdown
30
+
31
+ profile.md、preferences.md、projects/<宿主 id>.md。固定 H1、唯一 H2、自然 Markdown 正文;put_section/remove_section,合并/移动/改名组合原子操作。受限 ATX、识别 fenced code、拒绝未声明 H1/H2/Setext。软/硬预算初始 8/16 KiB。
32
+
33
+ 完整用户表达 + conversation_turns 的消息角色/顺序/证据引用 + 当前授权完整文档 + 时间/版本/宿主句柄。会话 assistant/tool 与前轮上下文须独立授权 conversation_context;系统、thinking、compaction 不进入请求。精确序列化上限 128 KiB,先减 context,再减完整 Turn;单条超限隔离、不截断、不消费。
34
+
35
+ memory_maintenance_v2:retain(remember/update/correct, stable/until_changed)、forget、maintain、ignore。引用必须宿主提供;context_only 不是新增 evidence。无效响应失败,不降级 no-op;ignore 原子消费。Project 来源批次可按 applicability 与既有授权写 Global;Project maintain 不得跨项目。
36
+
37
+ 维护指令随包发布,模型不能修改。新状态替换旧状态,纠正不是追加矛盾,临时通常 ignore,不从一次行为推出永久偏好,不把助手完成声明当事实,条件不泛化。Project realpath/最长祖先匹配;注册、披露、写授权分离;移除注册不删 Markdown。
38
+
39
+ ## Recovery / Privacy
40
+
41
+ 网络不持锁。repository lock → runtime DB 写事务 → token/generation/expiry fencing → 完整读取文档 CAS → Markdown + 永久回执事务 → DB 消费/来源关联 → DB commit。ignore 只做 DB 原子消费,但仍检查 snapshot CAS。
42
+
43
+ 文件成功 DB 失败依永久回执恢复,不调用模型。COMMITTING 前不发布;标记后恢复原子替换;外部非预期改动 fail closed。测试含真实子进程强制退出。
44
+
45
+ 永久回执仅来源引用、digest、before/after hash、决策枚举、模型/提示词版本、时间、usage;不留历史 Markdown、模型原响应、reason 或 Section 标题明文。关联键是 target+标题 hash,仅同一 decision 的合并/移动继承相关来源。processed body 默认 7 天清理;pending/隔离不伪装消费。forget 清理相关 processed body,保留不相关当前状态;不承诺删除 Pi transcript、安全擦除或永久禁止未来重新表达。
46
+
47
+ ## 交付门槛
48
+
49
+ typecheck/lint/全量测试/build、remote contract(离线适配器协议)、真实 tarball typed consumer/Prompt/Pi/CLI 启动。30 轨迹三策略比较仅证明 scripted executor;真实模型语义质量独立 opt-in,未执行则明确标注缺口。
@@ -0,0 +1,152 @@
1
+ # Init v0.1 收尾验收 — 2026-09-07
2
+
3
+ 后续证据:2026-09-08 用户确认的 Work 本地会话已实际完成 Init 与读回,见 [验证增补](init-v0.1-verification.md#work-local-evidence-2026-09-08)。下文保留各次运行当时的范围与结果。
4
+
5
+ 本轮基线 `e09262c`,Node `24.20.0`,Linux。`v0.1` 是 Init 里程碑;包仍为 `0.2.0`、`private:true`,未发布、未切换正式配置。修改范围来自审批版方案,不涉及检索、索引、HTTP MCP、额外模型预处理、Memory 自动清理或 provenance 扩权。
6
+
7
+ 后续 smoke 复用改造、重构后的 DeepSeek 复验及当前各 Provider 等级见 [Provider 验证复用](provider-verification.md)。本文保留各阶段原始验收条件与历史结果。
8
+
9
+ ## 2026-09-08 统一网络层后的最新结果
10
+
11
+ **指定模型的完整 Init + Markdown 真实链路已在三套独立临时存储中通过。**
12
+ 以下新结果替代下文“Markdown 未通过”的历史验收状态;原失败证据保留,不重置旧 dead/retry job。
13
+
14
+ 前期使用相同完整维护请求对照:默认 Node 路线收到 HTTP 200 后正文连接重置;显式代理路线约 1.9 秒得到完整输出。由此确认当时 Markdown 失败包含**该环境的请求路线问题**,没有证据说明 Markdown 解析器损坏或 DeepSeek 不支持 Responses。补齐 schema 字段类型解决的 HTTP 400 是另一个已单独确认的问题。关闭思考、调整角色的作用不能冒充所有历史失败的单一根因;预算仍为 4096,Writer 期限仍为 60 秒。
15
+
16
+ 本次采用 `deepseek-v4-flash-vision-exp` / `https://api.deepseek.com/responses` / strict schema / 显式 `reasoning.effort=none`,通过 Common Memory 自己的 env 网络客户端。每轮创建全新 home/dataRoot;Key 仅从环境读取,不写配置或报告。**隔离子进程明确设置 `no_proxy=""`、`NO_PROXY=""`**:原宿主列表含 CIDR,而本轮产品明确拒绝 CIDR。因此这里证明的是这条明确配置的代理路线,不能宣称“原宿主环境原样可用”。正式配置、symlink 和 Memory 均未改。
17
+
18
+ | 独立轮次 | Init Runtime 尝试 | Markdown Runtime 尝试 | 最终证据 |
19
+ | --- | --- | --- | --- |
20
+ | A:`/tmp/cm-deepseek-smoke-3MCAyv/report.json` | 2;首轮 Core 拒绝不合法 decision | 2;首轮 HTTP 200 / model_output / invalid_json | CLI 退出 0;2 份 DB 回执、2 份文件回执;重启无 Key read 同时读到 Quillon、Fedora、fish |
21
+ | B:`/tmp/cm-deepseek-smoke-Zqd7hN/report.json` | 1 | 1 | 同上 |
22
+ | C:`/tmp/cm-deepseek-smoke-FSvXWo/report.json` | 1 | 1 | 同上 |
23
+
24
+ 每次重试沿用原 Runtime 退避和上限,没有放宽 Core、修复模型 JSON、换模型或制造回执。成功 observation 不显示旧错误,job 仍保留受控历史诊断。此前初步网络 smoke `/tmp/cm-deepseek-smoke-oz5Ux7/report.json` 的 Markdown 首次非法 JSON 也保留为失败记录,不从报告中剔除。
25
+
26
+ 真实模型仍偶发非法 JSON 或 Core 不接受的 decision,不能承诺每次首次成功。原 tide-table 样本与 Init 的 Rust 周末偏好部分重复,实际模型合法 `ignore` 不能作为“未提交却冒称 retained”。最终留存样本改为明确且非重复的 Fedora Silverblue / fish 偏好;原始文档仍是 `document_import`,没有提升为用户声明,也没有合成模型替代 Writer。
27
+
28
+ 统一网络层、迁移规则、NO_PROXY 精确语义、局部秘密、连接 ownership 和错误分层见 [研究与审查设计](outbound-network-design.md);逐轮安全诊断、job/receipt ID 和读取摘要见 [机器可读验收记录](outbound-network-verification.json)。
29
+
30
+ 最终完整 `node scripts/verify.mjs`:**26 文件 / 341 测试、类型检查、46 源文件边界检查、干净构建通过**,日志 `/tmp/cm-network-verify-final.log`。构建后 Linux `npm run test:consumer` 验证真实 pack 的类型、资源、Writer、Pi 加载与 CLI,日志 `/tmp/cm-network-consumer-final.log`。独立设计审查与实施复审已完成;确认并修复 legacy fetch 捕获时机、隧道后断连归因、Pi flush 异常清理。新保留秘密名过滤同时覆盖大小写,但 Windows 仍未实跑。
31
+
32
+ 三轮正式 Memory 前后摘要均为 `c4e1a57b4617869cc30b69d1c4e93c76bb0112985bedde2b4f9662ba17ac75a7`。
33
+
34
+ 剩余限制:原宿主 CIDR bypass 列表需要用户明确改成支持的列表或使用 custom;SOCKS5 仅实验支持;Windows/macOS/WSL、桌面客户端及其他 Provider 未完成真实验收。此轮 Linux/指定模型留存验收已解除此前 Markdown 发布阻碍,不能据此宣布全环境正式发布。包仍为 `0.2.0`、`private:true`,未发布或切换正式环境。
35
+
36
+ ## 模型名更正后的历史验收(统一网络层之前)
37
+
38
+ 用户将测试模型更正为 **`deepseek-v4-flash-vision-exp`**。测试脚本已固定使用此 ID;之前错误模型名的 HTTP 400 记录仅作为历史,不应用于判断这个模型是否可用。个人配置和 API Key 保存方式未改。
39
+
40
+ 更正后发现第二个明确原因:原维护 schema 的纯字符串 `const` / `enum` 字段省略了显式 `type`,DeepSeek 的 strict schema 解析器以 HTTP 400 拒绝。已在**同一份** `maintenanceSchema` 为这些字段补上 `type: "string"`,没有 Provider 专用 schema 转译,所有合法值和 Core 校验范围保持不变。AJV 前后接受域回归与独立 Review 均通过。补齐后真实请求返回 HTTP 200,证实 schema 拒绝已消除。
41
+
42
+ | 更正后实验 | 实际结果 |
43
+ | --- | --- |
44
+ | 原 schema;system / 4096 / 未指定 reasoning | Init 与 Markdown 均 HTTP 400;定位为 schema 缺显式类型 |
45
+ | 补类型;system / 4096 / 未指定 reasoning | 两入口均 HTTP 200,但响应正文未在原有 60 秒期限内读完;无提交 |
46
+ | 补类型;仅显式 reasoning.effort=none 的单次探测 | 曾出现非法输出 JSON、正文读取失败,均安全拒绝,未修复或放宽输出解析 |
47
+ | 完整 smoke,显式 none | **Init 首次尝试成功**,processed,retainedIn 为 preferences/profile,有真实 Writer 提交和持久回执 |
48
+ | 同库 Markdown 导入及恢复 | 5 次 Runtime 尝试后仍失败:首次正文超时,随后正文读取失败;第 4 次暂态诊断确认 ECONNRESET;最后一次请求阶段网络不可用,达到原 maxAttempts=5 后为 dead |
49
+ | 重启后的无 Key MCP read | 能读到 Init 的 Quillon 等内容,来源可见;未读到未提交的 tide-table |
50
+
51
+ 最终结果是 **真实 Init 链路通过,完整 Init + Markdown 链路仍未通过**。不能把连接重置认定为 Core 校验失败,也不能据此确定故障位于服务端还是中间网络。正文读失败的已知传输代码现在映射为 `UNAVAILABLE / response_body / network_error / retryable:true` 并保留 HTTP 状态;最后一次未收到响应头则是 `request / network_error`。仅匹配四个本地白名单代码,不持久化原消息、地址或 cause,不改变重试调度。
52
+
53
+ 本轮全过程保持 4096 输出预算和 60 秒默认超时;未换模型、自动 fallback、修补非法 JSON、绕过退避或重置尝试次数。`--no-thinking` 仅是 smoke 的显式对照开关,无参依旧不发送 reasoning 配置:
54
+
55
+ ```sh
56
+ node scripts/smoke-deepseek-init.mjs
57
+ node scripts/smoke-deepseek-init.mjs --no-thinking
58
+ ```
59
+
60
+ 证据保留于隔离目录:
61
+
62
+ - 原 schema 的更正模型测试:`/tmp/cm-deepseek-smoke-H9dMyY/report.json`。
63
+ - 补类型后的默认思考测试:`/tmp/cm-deepseek-smoke-SK85s8/report.json`。
64
+ - 关闭思考的完整 smoke:`/tmp/cm-deepseek-smoke-FqDiLy/report.json`。
65
+ - 同一 Markdown 恢复至第 5 次并再次重启 read 的最终状态:`/tmp/cm-deepseek-smoke-FqDiLy/resumed-report.json`。队列有 1 条 processed、1 条 dead;DB 与文件回执各 1 份,均属于 Init。
66
+
67
+ Init 的 Profile/Preferences Section 明确标注来自 smoke-fixture、saved_memories、合成且未验证。两次重启读取均保留这些内容。现有 Memory 前后摘要仍为 `c4e1a57b4617869cc30b69d1c4e93c76bb0112985bedde2b4f9662ba17ac75a7`,个人 Memory 未修改。
68
+
69
+ 最终复验:完整 `verify` **23 文件 / 260 测试通过**,42 源文件边界检查、类型检查和干净构建通过;构建后 Linux consumer 通过。日志分别为 `/tmp/cm-init-verify-vision-final.log`、`/tmp/cm-init-consumer-vision-final.log`。增量独立 Review 确认 schema 等价、诊断脱敏及显式开关边界,聚焦验证 45 项与后续连接重置 2 项通过。Windows CI、桌面客户端和其他 Provider 的真实调用仍未执行。
70
+
71
+ ## 模型名更正前的历史结论
72
+
73
+ 以下保留用户更正模型名之前的历史实验;不代表更正后模型的结果。实现与自动化验证已完成;当时指定的真实模型写入验收未通过。`https://api.deepseek.com/responses` + `deepseek-v4-flash-exp` + Responses 在本次账户下返回 HTTP 400,安全诊断是 `http / request_rejected / retryable:false`,旧 `issue` 保持 `INVALID_RESPONSE`。错误 code 为已识别的通用 `invalid_request_error`;未记录任意 provider 错误消息或正文。最小 schema 请求、最小普通文本请求也被拒绝;`GET /models` 返回 HTTP 200、列出 3 个模型,但不包含指定 ID。模型清单缺席支持“该模型在当前服务不可用”的判断,不能单独证明具体服务端校验失败的字段或旧请求的全部历史根因。本轮不擅自替换模型。
74
+
75
+ 因此真实 DeepSeek 的 Init、Markdown import **没有**进入模型输出校验与提交,没有持久成功回执。新启动的 MCP read 进程读到空记忆。假模型回归、协议连通与空读取不构成真实 Writer 成功。此项仍是 Init 里程碑交付阻碍。
76
+
77
+ ## 已定位的问题与被推翻的判断
78
+
79
+ | 问题 | 源码/实验结论 | 处理 |
80
+ | --- | --- | --- |
81
+ | 构建资源缺失 | 原 `verify` 直接运行 tsc,不清理、不复制 `memory-maintainer.md`;旧 dist 可能掩盖问题 | build 与 verify 共用 `scripts/build.mjs`,清理、编译、复制资源 |
82
+ | 错误信息压缩 | 原 adapter 丢弃 HTTP 状态,解析错误共用 INVALID_RESPONSE;Init 只查 observation.issue | 受控诊断贯穿 adapter、Writer、jobs、各入口查询 |
83
+ | flush 假成功 | 原失败只打印 JSON,退出 0;退避和别人租约都可能返回 idle | 记录本次失败/取消/隔离并检查最终 pending/claimed/dead |
84
+ | Writer 竞争 | 原代码把退休 job 的 done 当作 committed;初版修复仍可能采用旧租约的决策 | 在仓库锁与 DB 事务内恢复并检查真实回执;文件回执表示 committed,仅 DB 回执表示 ignored |
85
+ | 终止原因混淆 | 原超时与续租失败都走 cancelled;外层取消还可能丢已收到的 HTTP 状态 | 首个终止原因固定;受控进度上下文保留 HTTP 阶段/状态 |
86
+ | demo 数据复用 | 默认 `~/.common-memory` 实际指向 `/home/mrremon/common-memory-test`,本进程 COMMON_MEMORY_HOME 也指向它 | 原保护保留,status 显示配置与真实路径;实验全部用新目录 |
87
+
88
+ “DeepSeek 不支持 Responses”被官方接口资料推翻;官方文档还明确 `developer` 被视为 `user`。维护提示现用 `system`,原观察仍以独立 user 数据投影传入。角色差异是必须修正的语义问题,不能据此宣称它造成了当前 HTTP 400。[DeepSeek Responses API](https://api-docs.deepseek.com/api/create-response/)
89
+
90
+ 没有证据表明不同 dataRoot 之间串写。现有 Memory 前后逐文件摘要相同;原符号链接和数据均未删除或重写。
91
+
92
+ ## 请求模式与诊断契约
93
+
94
+ - Responses 保留公开 `OpenAIResponsesMemoryModel`、strict schema、`store:false`;旧配置缺省 Responses。
95
+ - 新增 `OpenAIChatMemoryModel`,配置工厂返回 `MemoryModelPort`。Chat 发 `json_object`,完整 schema 放 system 提示,之后同样进入 `validateDecision`、provenance/import 守卫、CAS、租约和提交事务。
96
+ - 共用 HTTP、完整请求字节计数与安全扫描、响应限额和有限重试。拒绝截断、工具调用、异常完成、非法 envelope/JSON;拒绝内容仅保留指纹。
97
+ - 输出默认 4096、上限 16384。Responses 可选 `reasoningEffort`;Chat 可选 `thinking` 或 `enableThinking`,互斥;未配置不发送。不给任意字段透传、不作品牌检测/fallback/schema 转译,不提高默认超时。
98
+ - HTTP 错误正文最多读取 16 KiB / 2 秒,同时服从请求 deadline。读取失败保留 HTTP 状态;网络/正文不配合取消时也会被期限隔离。已知错误 code 或受控 schema 错误前缀映射成更具体的本地 reason,未知错误保持 request_rejected。已知连接重置/超时错误码可映射为 response_body/network_error,保留 HTTP 状态;原始消息与 cause 不持久化。
99
+ - `jobs.diagnostic` 是可空 TEXT;`BEGIN IMMEDIATE` 中检查列并 ALTER,显式 INSERT 列名支持新旧库。没有新增错误事件表。诊断只接受本地 stage/reason 枚举、100–599 HTTP 状态和 retryable 布尔值。
100
+ - 三类查询关联当前 job,返回 jobId/jobState/attempts/retryAt(Unix 毫秒)。成功 observation 不展示旧 issue/diagnostic;已退休 job 的历史诊断保留。接入层 retryable 不改变 Runtime 的退避、次数或手动 retry 规则。
101
+
102
+ ## DeepSeek 分步实验(更正模型名之前)
103
+
104
+ 只使用 `DEEPSEEK_API_KEY` 环境变量,模型始终固定。使用仓库原合成 Init 内容重建原请求形态;未获得此前失败请求的逐字网络录制,因此不声称是历史请求的逐字重放。
105
+
106
+ | 实验 | 与对照相比唯一请求参数变化 | 结果 |
107
+ | --- | --- | --- |
108
+ | 诊断补齐后基线 | developer,4096,未指定 reasoning | HTTP 400,请求拒绝,无回执 |
109
+ | 角色对照 | developer → system | HTTP 400,请求拒绝,无回执 |
110
+ | 输出预算对照 | system 基线上 4096 → 8192 | HTTP 400,请求拒绝,无回执 |
111
+ | 思考对照 | system/4096 基线上 reasoning.effort → none | HTTP 400,请求拒绝,无回执 |
112
+ | 最小独立探测 | 同模型,最小 JSON schema / 普通文本请求 | 均 HTTP 400;并非完整维护 schema 或角色改动能解决 |
113
+ | 模型清单 | GET /models,只检查指定模型是否出现 | HTTP 200;3 个 ID 中没有指定模型 |
114
+
115
+ 真实构建产物 smoke:`node scripts/smoke-deepseek-init.mjs`。脚本固定 endpoint/model,新建 home 和独立 dataRoot,不写 `.env`。Init 用真实 MCP stdio 进程,Markdown 用真实 CLI,均使用真实 HTTP model 与现有 Writer。Init 失败时不动其 retry,而在第二套新目录测试 Markdown;因此此失败分支不冒充同库成功。读取使用重启后的独立 MCP read 进程,移除测试 Key。
116
+
117
+ 本轮 smoke 退出 1,报告 `/tmp/cm-deepseek-smoke-tvvlXj/report.json`:
118
+
119
+ | 步骤 | 实测 |
120
+ | --- | --- |
121
+ | Init | accepted:true → claimed,jobState:retry,attempts:1,HTTP 400 |
122
+ | Markdown import | 退出 1,jobState:retry,attempts:1,HTTP 400 |
123
+ | 持久回执 | 两个库 DB receipts=0,文件 receipts=0 |
124
+ | 重启 MCP read | 工具仅 memory_read/memory_status;两个库均 empty:true |
125
+ | 现有 Memory | 前后摘要 `c4e1a57b4617869cc30b69d1c4e93c76bb0112985bedde2b4f9662ba17ac75a7` 相同 |
126
+
127
+ 临时报告只记录枚举、标量、路径、回执 ID 与摘要;不含 Key、原始 HTTP 正文或任意错误消息。合成观察与可能生成的记忆只保留在隔离目录,不清理任何已有数据。探测版摘要只包含文件;最终 smoke 摘要还包含目录条目,不能把这两种算法的摘要直接比较。
128
+
129
+ ## Provider 验证等级
130
+
131
+ 等级针对“端点 + 模型 + 模式”。通用 fake-provider 通过不表示某品牌全部模型兼容。
132
+
133
+ | 端点 | 具体模型 | 模式 | 本轮证据与等级 |
134
+ | --- | --- | --- | --- |
135
+ | `https://api.openai.com/v1` | `gpt-test`(fixture;未指定真实模型) | Responses strict schema | 既有路径保留,fake fetch 合约回归通过;本轮无真实 OpenAI 调用 |
136
+ | `https://api.deepseek.com` | `deepseek-v4-flash-exp`(历史误写) | Responses strict schema | 旧实验 HTTP 400;不能用于评定更正后的模型 |
137
+ | `https://api.deepseek.com` | `deepseek-v4-flash-vision-exp` | Responses strict schema,显式 reasoning.effort=none | 统一网络客户端 + 明确隔离 NO_PROXY 条件下,三轮真实 Init/Markdown 提交、回执、重启读取通过;有模型输出重试,详见本文最新结果 |
138
+ | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `qwen-plus` | Chat json_object | 官方文档候选;enableThinking:false 可显式关闭思考;本轮无真实调用 |
139
+ | `https://open.bigmodel.cn/api/paas/v4` | `glm-4.5` | Chat json_object | 官方直接 API 支持 JSON 输出及 thinking.type;是新增 Chat 路径的独立依据,本轮无真实调用 |
140
+ | `https://api.hunyuan.cloud.tencent.com/v1` | `hunyuan-turbos-latest` | Chat | 官方有兼容接口;该精确模型的 json_object 组合尚未证实,本轮无真实调用,不声明支持 |
141
+
142
+ Qwen JSON 模式与思考开关依据 [Chat API](https://help.aliyun.com/zh/model-studio/qwen-api-via-openai-chat-completions) 和 [结构化输出](https://help.aliyun.com/zh/model-studio/qwen-structured-output);GLM 依据 [对话补全](https://docs.bigmodel.cn/api-reference/模型-api/对话补全) 和 [GLM-4.5](https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5);Hunyuan 仅依据 [直接兼容接口](https://cloud.tencent.com/document/product/1729/111007),不把腾讯 TokenHub 的另一端点能力混用。
143
+
144
+ ## 验证与独立 Review
145
+
146
+ 首轮完整 `node scripts/verify.mjs`:类型检查、42 源文件边界检查、23 文件 / 250 测试、干净构建通过。构建后 Linux `npm run test:consumer` 通过实际 npm pack 中的类型消费、提示资源、Writer、Pi 加载和 CLI 启动。fake-provider demo 也使用新的临时 home;它仅证明机制。
147
+
148
+ 独立只读 Review 使用隔离 fake model/fetch 复现并确认两项残留:P1 竞争 ignore 回执误报 committed、P2 Writer 超时丢已收到的 HTTP 状态。均修复:恢复结果从真实回执导出,模型端受控阶段上下文只补充已知 HTTP 标量、首个终止原因仍固定。新增双方向竞争回执、HTTP 200/503 停滞正文的完整 Writer 测试;另补 Chat 配置通过真实本地 HTTP、Core、回执和读取的 CLI 测试。
149
+
150
+ 最终 `node scripts/verify.mjs` 全部通过:类型检查、42 源文件边界检查、23 文件 / **256 测试**、干净构建。完整原始输出保留于 `/tmp/cm-init-verify-reviewed.log`,首轮输出保留于 `/tmp/cm-init-verify-1.log`。独立短复审另发现新请求沿用上次 HTTP 上下文,已在每次 attempt 开始前清空,并新增 429 → 第二次网络卡住的 Writer 回归。短复审共 5 项聚焦测试通过,确认已报问题均修复,未发现新阻断缺陷。最终构建后再次运行 Linux `npm run test:consumer` 通过,实际打包产物验证了新增 Chat/诊断公开类型,输出保留于 `/tmp/cm-init-consumer-reviewed.log`。此前一次新增测试 fixture 的 typecheck 失败为缺少 chunk 的 headingPath/bytes,已按实际类型补齐;未改契约来迁就测试。
151
+
152
+ Windows 原生 CI、本次真实 Windows/WSL 客户端、ChatGPT 桌面 GUI、Codex/Pi 使用远程模型回答及其他 Provider 真实调用均未执行。Linux 检查与 MCP SDK 子进程证据不覆盖这些项。此前历史实验见 [原验收记录](init-v0.1-verification.md)。