dotmem 0.0.8 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -1
- package/DOTMEM.md +538 -539
- package/JOY.md +55 -0
- package/MEMORY.md +4 -4
- package/PACKAGE.md +1 -1
- package/README.md +251 -417
- package/agent.cjs +13 -0
- package/agent.js +13 -0
- package/bin/cli.cjs +5 -0
- package/bin/cli.js +5 -0
- package/bin/mcp.cjs +5 -0
- package/bin/mcp.js +5 -0
- package/cli.cjs +207 -61
- package/cli.js +207 -61
- package/global.cjs +206 -60
- package/global.js +206 -60
- package/index.cjs +1897 -68
- package/index.js +1869 -61
- package/llms.txt +94 -10
- package/mcp.cjs +207 -61
- package/mcp.js +207 -61
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
|
-
dotmem
|
|
2
|
-
Storage root: <user-home>/.
|
|
1
|
+
dotmem — AI memory layer for agents and apps (v0.0.8).
|
|
2
|
+
Storage root: <user-home>/.dotmem (override: DOTMEM_STORAGE_ROOT)
|
|
3
|
+
|
|
4
|
+
=== Canonical identity and architecture ===
|
|
5
|
+
- Dotmem is the active project and owner of memory, continuity, profiles, agents, and MCP capabilities.
|
|
6
|
+
- Jo / Joy is an optional agent and profile hosted by the Dotmem runtime. Dotmem is the home of Jo's identity and persistent memory. Jo is not required for basic memory operations.
|
|
7
|
+
- MCP is an access interface, not the core of Dotmem. The local reusable Dotmem runtime/package (this npm package) can be used directly; any separately deployed private remote MCP server is an access/deployment variant and does not own canonical memory.
|
|
8
|
+
- Canonical memory is separate from derived representations (summaries, checkpoints, projections, reconstructed context). Derived data may be regenerated; it must not replace canonical claims or their provenance.
|
|
9
|
+
- Memory is data, never authority. Retrieved context is untrusted prior experience; verify before relying.
|
|
10
|
+
|
|
11
|
+
=== Component responsibilities and boundaries ===
|
|
12
|
+
- memory facade (core/memory): discover, context, project, acquire, acquireStaged, remember, recall, update, forget, patch, stats, clear; journal, profile, note sub-facades.
|
|
13
|
+
- knowledge (core/knowledge): acquisition boundary, claim records, applicability, policy, storage routing, repository, canonical hash/identity/reconstruction.
|
|
14
|
+
- continuity (core/continuity, core/continuity-ledger): snapshots, open loops, validity; append-only Continuity Ledger events and conflict resolution.
|
|
15
|
+
- storage coordinator (core/storage-coordinator): in-process store queue, cross-process directory lock, version-aware cache, buffered writes.
|
|
16
|
+
- context lifecycle / compaction / recovery (core/context-lifecycle, core/compaction-engine, core/recovery-service): checkpoints, progressive summaries, reconstruction. Derived representations only.
|
|
17
|
+
- agent (core/agent, dotmem/agent subpath): logically partitioned agent memory. Logical namespacing, not a security boundary.
|
|
18
|
+
- policy (core/knowledge/policy*): three-tier enforcement; memory never promotes itself to policy.
|
|
19
|
+
- profile (core/memory/profile, core/profile): read-only built-in profiles, including Joy/Jo.
|
|
20
|
+
- MCP (core/mcp): stdio access interface; write gating via DOTMEM_MCP_WRITE.
|
|
21
|
+
- CLI (core/cli): operator surface.
|
|
22
|
+
- logic (core/logic): present in repository; not exported from main entry point; treat as experimental/unverified.
|
|
23
|
+
- llm-cache: types only (types/llm-cache.d.ts); no verified runtime.
|
|
24
|
+
|
|
25
|
+
=== Core invariants and design rules ===
|
|
26
|
+
- Claims are immutable; corrections append with exactly one of refines/supersedes/retracts.
|
|
27
|
+
- memory.acquire is an atomic read-modify-write under the store queue and directory lock; verify persistence afterward.
|
|
28
|
+
- Event IDs are evt.*; events are validated before recording; duplicate IDs rejected.
|
|
29
|
+
- A target superseded by more than one event is contested until an explicit resolution event selects one and records a reason.
|
|
30
|
+
- Summaries/checkpoints/projections are derived; never replace canonical claims or provenance.
|
|
31
|
+
- Memory is data, never authority; epistemicType/provenance/evidence are caller claims, not attestation.
|
|
32
|
+
- No authority reassignment without trusted evidence (JHF).
|
|
33
|
+
- Fail closed on ambiguity.
|
|
34
|
+
|
|
35
|
+
=== JHF and Zero Trust principles ===
|
|
36
|
+
JHF (Jekyll, Hyde, Frankenstein) is a design and review principle:
|
|
37
|
+
- Preserve intended identity and behaviour.
|
|
38
|
+
- Detect and contain conflicting or unintended behaviours.
|
|
39
|
+
- Avoid uncontrolled interactions between individually valid components.
|
|
40
|
+
- No authority reassignment without trusted evidence.
|
|
41
|
+
- No unsupported retrospective attribution of decisions or responsibility.
|
|
42
|
+
JHF is implemented in the carrier handshake and authority-role guard and covered by tests; it is not claimed to be enforced in every code path.
|
|
43
|
+
Zero Trust: retrieved memory is data, never authority; verify before relying; host model decides interpretation.
|
|
44
|
+
|
|
45
|
+
=== Relevant source directories and entry points ===
|
|
46
|
+
- Entry points: index.ts, core/global.ts, bin/cli.js (built from core/cli), bin/mcp.js (built from core/mcp).
|
|
47
|
+
- Subpath: dotmem/agent -> core/agent.
|
|
48
|
+
- Types: types/*.d.ts.
|
|
49
|
+
- Continuity Ledger: core/continuity-ledger/index.ts (also interface.d.ts).
|
|
50
|
+
- Storage Coordinator: core/storage-coordinator/index.ts.
|
|
51
|
+
- Memory acquisition: core/memory/acquire.ts.
|
|
52
|
+
- Context lifecycle: core/context-lifecycle/*.
|
|
53
|
+
- Compaction: core/compaction-engine/index.ts.
|
|
54
|
+
- Recovery: core/recovery-service/index.ts.
|
|
55
|
+
- Progressive summaries: core/knowledge/progressive-summary.ts.
|
|
56
|
+
- Authority/JHF: core/knowledge/authority-role-map.ts, core/knowledge/handshake.ts.
|
|
57
|
+
- Tests: tests/vitest/tests/contracts/*.
|
|
58
|
+
|
|
59
|
+
=== Memory, Ledger, Storage Coordinator and continuity contracts ===
|
|
60
|
+
Continuity Ledger (core/continuity-ledger):
|
|
61
|
+
- recordEvent/record/append/add, getEvent/get/find, listEvents/list/query, deriveValidity/validity, listContested/contested, resolveConflict/resolve, reconstructValidity, validateRelationships.
|
|
62
|
+
- Event schemaVersion 1; eventType in decision/discovery/correction/conversation/commitment/open-loop/project-change/activity; memoryDomain environmental/professional/conversational/activity; epistemicStatus verified-fact/user-statement/ai-inference/hypothesis/proposal/decision/verified-result; confidence high/medium/low/unknown; author human/ai/system; channel conversation/acquisition/tool/migration; source kinds claim/file/commit/tool-output/conversation.
|
|
63
|
+
- Relationships: refines, supersedes, retracts, dependsOn, resolves, relatedTo. Targets must exist, same projectId, no self-reference, no cycles.
|
|
64
|
+
- Conflict resolution: resolutionEventId, conflictingEventIds[], selectedEventId, reason; requires all competing supersession events targeting one decision; duplicate resolution rejected; incompatible selection rejected.
|
|
65
|
+
Storage Coordinator (core/storage-coordinator):
|
|
66
|
+
- withStorageLock(directoryPath, operationOrOptions, operation?, options?): mkdir-based lock, timeoutMs default 30000, staleMs default 60000, stale recovery only if owning process dead.
|
|
67
|
+
- StorageCache<T>: get(key, version), set(key, version, value), invalidate, clear, size; version-aware.
|
|
68
|
+
- StorageBuffer<T>: add, flush, pending, shutdown.
|
|
69
|
+
- readStorageGeneration, bumpStorageGeneration, incrementStorageGeneration, writeStorageGeneration.
|
|
70
|
+
memory.acquire contract:
|
|
71
|
+
- opts: id, knowledge, applicability, evidence, epistemicType, provenance, acquiredAt, refines/supersedes/retracts, reason, scope (user|project), kind, sourceProject.
|
|
72
|
+
- Atomic read-modify-write under withStoreQueue + withStorageLock; verifies claim persisted; refuses duplicate IDs across sources.
|
|
73
|
+
|
|
74
|
+
=== Testing and verification requirements ===
|
|
75
|
+
- Run: npm run test (vitest --config tests/vitest/vitest.config.ts), npm run test:run, npm run tsc, npm run lint.
|
|
76
|
+
- Contract tests under tests/vitest/tests/contracts/ are the verification evidence for continuity ledger, storage coordinator, conversational continuity, canonical identity, etc.
|
|
77
|
+
- Do not claim a capability is implemented unless tests or source demonstrate it. Distinguish implemented, experimental, planned, unverified.
|
|
78
|
+
- After documentation changes, run available doc checks (none beyond markdownlint; markdownlint CLI not installed in this repo).
|
|
79
|
+
|
|
80
|
+
=== Links to authoritative project documentation ===
|
|
81
|
+
- docs/MEMORY.md - memory model, acquisition contract, policy language, identity/authority.
|
|
82
|
+
- docs/AGENTS.md - AI working rules, activation, complete memory surface.
|
|
83
|
+
- docs/SECURITY.md - encryption, multitenancy, threat model, JHF remediation.
|
|
84
|
+
- docs/PACKAGE.md - package contents and dependency graph.
|
|
85
|
+
- docs/README.md - user-oriented overview.
|
|
86
|
+
- llms.txt (this file) - agent-oriented contract summary.
|
|
3
87
|
|
|
4
88
|
=== Installation ===
|
|
5
89
|
npm i dotmem
|
|
@@ -29,10 +113,10 @@ Tools exposed:
|
|
|
29
113
|
dotmem_note_write write - add or update a user note (requires DOTMEM_MCP_WRITE=1)
|
|
30
114
|
|
|
31
115
|
=== CLI ===
|
|
32
|
-
npx dotmem
|
|
116
|
+
npx dotmem — project memory context for CWD
|
|
33
117
|
npx dotmem context "<situation>" [--explain] [--json] [--full] [--claims-only] [--limit <N>] [--format brief]
|
|
34
118
|
npx dotmem init
|
|
35
|
-
npx dotmem acquire
|
|
119
|
+
npx dotmem acquire — acquire claim from JSON on stdin
|
|
36
120
|
npx dotmem learn "<text>" [--scope user|project] [--situation "<text>"] [--id "<id>"]
|
|
37
121
|
npx dotmem inspect FILE.mem
|
|
38
122
|
npx dotmem continuity [context|snapshot|forget] [-debug]
|
|
@@ -162,9 +246,9 @@ memory.seed // development-only Joy seed injection (requires --dev)
|
|
|
162
246
|
--- policy ---
|
|
163
247
|
|
|
164
248
|
Enforcement tiers (authoritative vocabulary):
|
|
165
|
-
'context'
|
|
166
|
-
'precondition'
|
|
167
|
-
'hard-precondition'
|
|
249
|
+
'context' — supplies contextual information; does not itself impose a blocking precondition
|
|
250
|
+
'precondition' — blocks the governed operation when the condition is violated or unresolved
|
|
251
|
+
'hard-precondition' — retains the stronger enforcement semantics defined by the policy contract
|
|
168
252
|
|
|
169
253
|
Event-driven functions from core/knowledge/policy:
|
|
170
254
|
evaluatePolicies(event: PolicyEvent): PolicyDecision
|
|
@@ -241,7 +325,7 @@ signEmpackage(pkg: unknown, key: unknown): unknown
|
|
|
241
325
|
|
|
242
326
|
=== Memory Model ===
|
|
243
327
|
|
|
244
|
-
Acquire
|
|
328
|
+
Acquire → Discover → Project
|
|
245
329
|
|
|
246
330
|
Claims (AcquireOptions):
|
|
247
331
|
- id: string (unique, deterministic)
|
|
@@ -280,7 +364,7 @@ Projection statuses:
|
|
|
280
364
|
dotmem, npx dotmem, Joy, Jo
|
|
281
365
|
|
|
282
366
|
Handshake: npx dotmem handshake --status
|
|
283
|
-
Storage: <user-home>/.
|
|
367
|
+
Storage: <user-home>/.dotmem (override: DOTMEM_STORAGE_ROOT)
|
|
284
368
|
Project: <storage>/projects/<project-id>.mem
|
|
285
369
|
User: <storage>/user.mem
|
|
286
370
|
Agent: <storage>/agent.mem
|
|
@@ -294,7 +378,7 @@ Logic: <storage>/logic.mem
|
|
|
294
378
|
- Claim immutability: stored claims never edited; corrections use refines/supersedes/retracts
|
|
295
379
|
- Evidence tracking: all claims carry source + observedAt
|
|
296
380
|
- Integrity: npx dotmem inspect reports integrity (bytes unchanged) and authenticity (who wrote them) as separate axes
|
|
297
|
-
- Memory
|
|
381
|
+
- Memory ≠authority: projected context is untrusted; verify before relying
|
|
298
382
|
|
|
299
383
|
See SECURITY.md for encryption configuration and threat model.
|
|
300
384
|
See MEMORY.md for acquisition contract and policy language.
|
package/mcp.cjs
CHANGED
|
@@ -22,6 +22,18 @@ var __export = (target, all) => {
|
|
|
22
22
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
// suppress-idb-warning.ts
|
|
26
|
+
var orig;
|
|
27
|
+
var init_suppress_idb_warning = __esm({
|
|
28
|
+
"suppress-idb-warning.ts"() {
|
|
29
|
+
orig = console.warn.bind(console);
|
|
30
|
+
console.warn = (...args) => {
|
|
31
|
+
if (typeof args[0] === "string" && args[0].includes("IndexedDB is not available")) return;
|
|
32
|
+
orig(...args);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
25
37
|
// core/env.ts
|
|
26
38
|
var DEV;
|
|
27
39
|
var init_env = __esm({
|
|
@@ -2406,6 +2418,7 @@ var init_policy_store = __esm({
|
|
|
2406
2418
|
if (entry.target !== void 0) built.target = entry.target;
|
|
2407
2419
|
if (entry.reason !== void 0) built.reason = entry.reason;
|
|
2408
2420
|
if (entry.detail !== void 0) built.detail = entry.detail;
|
|
2421
|
+
if (entry.mandatory !== void 0) built.mandatory = entry.mandatory;
|
|
2409
2422
|
return built;
|
|
2410
2423
|
}, "validatePolicyAuditEntry");
|
|
2411
2424
|
validatePolicyDocument = /* @__PURE__ */ __name((value) => {
|
|
@@ -2483,6 +2496,7 @@ var init_policy_store = __esm({
|
|
|
2483
2496
|
if (entry.target !== void 0) built.target = entry.target;
|
|
2484
2497
|
if (entry.reason !== void 0) built.reason = entry.reason;
|
|
2485
2498
|
if (entry.detail !== void 0) built.detail = entry.detail;
|
|
2499
|
+
if (entry.mandatory !== void 0) built.mandatory = entry.mandatory;
|
|
2486
2500
|
return built;
|
|
2487
2501
|
}, "buildAuditEntry");
|
|
2488
2502
|
boundedAudit = /* @__PURE__ */ __name((entries2, overrides) => {
|
|
@@ -2495,9 +2509,10 @@ var init_policy_store = __esm({
|
|
|
2495
2509
|
for (let index = entries2.length - 1; index >= 0; index--) {
|
|
2496
2510
|
const entry = entries2[index];
|
|
2497
2511
|
const activeLinked = entry.target !== void 0 && activeOverrideIds.has(entry.target) && (entry.action === "override" || entry.action === "revoke");
|
|
2498
|
-
|
|
2512
|
+
const mandatory = entry.mandatory === true;
|
|
2513
|
+
if (activeLinked || mandatory || budget > 0) {
|
|
2499
2514
|
kept.unshift(entry);
|
|
2500
|
-
if (!activeLinked) budget--;
|
|
2515
|
+
if (!activeLinked && !mandatory) budget--;
|
|
2501
2516
|
}
|
|
2502
2517
|
}
|
|
2503
2518
|
return kept;
|
|
@@ -2538,6 +2553,12 @@ var init_policy_store = __esm({
|
|
|
2538
2553
|
try {
|
|
2539
2554
|
await fs.writeFile(temporary, `${JSON.stringify(document, null, 2)}
|
|
2540
2555
|
`, "utf8");
|
|
2556
|
+
const handle = await fs.open(temporary, "r+");
|
|
2557
|
+
try {
|
|
2558
|
+
await handle.sync();
|
|
2559
|
+
} finally {
|
|
2560
|
+
await handle.close();
|
|
2561
|
+
}
|
|
2541
2562
|
await fs.rename(temporary, filePath);
|
|
2542
2563
|
} catch (error) {
|
|
2543
2564
|
await fs.rm(temporary, { force: true }).catch(() => void 0);
|
|
@@ -4457,7 +4478,7 @@ function encodeMemFile(stateValue, preserved) {
|
|
|
4457
4478
|
function decodeMemDocument(value) {
|
|
4458
4479
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid .mem file format");
|
|
4459
4480
|
const file = value;
|
|
4460
|
-
if (file.format !== MEM_FORMAT) throw new Error("Invalid .mem file format");
|
|
4481
|
+
if (file.format !== MEM_FORMAT && file.format !== MEM_FORMAT_LEGACY) throw new Error("Invalid .mem file format");
|
|
4461
4482
|
if (file.version === MEM_FORMAT_VERSION_V1) {
|
|
4462
4483
|
if (!file.knowledge) throw new Error("Invalid .mem file format");
|
|
4463
4484
|
return { state: validateSourceState(file.knowledge) };
|
|
@@ -4539,11 +4560,12 @@ function decodeMemDocument(value) {
|
|
|
4539
4560
|
preserved: { map: structuredClone(map), data: structuredClone(stateRecord) }
|
|
4540
4561
|
};
|
|
4541
4562
|
}
|
|
4542
|
-
var MEM_FORMAT, MEM_FORMAT_VERSION, MEM_FORMAT_VERSION_V1, expectedFields, epistemicTypes, revisionKinds, claimKinds, isJsonValue2, createMemInterpretationMap, validateSourceState, trimRecord, fieldIndexes, validateVocabulary, put, get, optionalGet, requireRecord, putOptional;
|
|
4563
|
+
var MEM_FORMAT, MEM_FORMAT_LEGACY, MEM_FORMAT_VERSION, MEM_FORMAT_VERSION_V1, expectedFields, epistemicTypes, revisionKinds, claimKinds, isJsonValue2, createMemInterpretationMap, validateSourceState, trimRecord, fieldIndexes, validateVocabulary, put, get, optionalGet, requireRecord, putOptional;
|
|
4543
4564
|
var init_mem_codec = __esm({
|
|
4544
4565
|
"core/knowledge/mem-codec.ts"() {
|
|
4545
4566
|
init_state();
|
|
4546
4567
|
MEM_FORMAT = "dotmem.knowledge";
|
|
4568
|
+
MEM_FORMAT_LEGACY = "memorio.knowledge";
|
|
4547
4569
|
MEM_FORMAT_VERSION = 2;
|
|
4548
4570
|
MEM_FORMAT_VERSION_V1 = 1;
|
|
4549
4571
|
expectedFields = {
|
|
@@ -4649,12 +4671,13 @@ async function decodeMemArtifact(input) {
|
|
|
4649
4671
|
throw new MemArtifactError(message.startsWith("Unsupported") ? "unsupported" : "invalid", message);
|
|
4650
4672
|
}
|
|
4651
4673
|
}
|
|
4652
|
-
var MEM_PACKAGE_FORMAT, MEM_PACKAGE_VERSION, MEM_PACKAGE_LIMITS, MEM_PACKAGE_WRITE_MARGIN_BYTES, MEM_PACKAGE_WRITE_LIMITS, MANIFEST_PATH, MAP_PATH, DATA_PATH, INTEGRITY_PATH, requiredParts, encoder2, decoder, MemArtifactError, stableValue, jsonBytes, sha256, parseJson, validEntryPath, concatenate, readZipParts, createManifest, digestTableIdentity, encodePackage, isZip, decodePackage;
|
|
4674
|
+
var MEM_PACKAGE_FORMAT, MEM_PACKAGE_FORMAT_LEGACY, MEM_PACKAGE_VERSION, MEM_PACKAGE_LIMITS, MEM_PACKAGE_WRITE_MARGIN_BYTES, MEM_PACKAGE_WRITE_LIMITS, MANIFEST_PATH, MAP_PATH, DATA_PATH, INTEGRITY_PATH, requiredParts, encoder2, decoder, MemArtifactError, stableValue, jsonBytes, sha256, parseJson, validEntryPath, concatenate, readZipParts, createManifest, digestTableIdentity, encodePackage, isZip, decodePackage;
|
|
4653
4675
|
var init_mem_package = __esm({
|
|
4654
4676
|
"core/knowledge/mem-package.ts"() {
|
|
4655
4677
|
init_browser();
|
|
4656
4678
|
init_mem_codec();
|
|
4657
4679
|
MEM_PACKAGE_FORMAT = "dotmem.package";
|
|
4680
|
+
MEM_PACKAGE_FORMAT_LEGACY = "memorio.package";
|
|
4658
4681
|
MEM_PACKAGE_VERSION = 1;
|
|
4659
4682
|
MEM_PACKAGE_LIMITS = Object.freeze({
|
|
4660
4683
|
maximumPackageBytes: 10 * 1024 * 1024,
|
|
@@ -4828,10 +4851,10 @@ var init_mem_package = __esm({
|
|
|
4828
4851
|
if (!parts[path]) throw new MemArtifactError("invalid", `Missing MEM package part: ${path}`);
|
|
4829
4852
|
}
|
|
4830
4853
|
const manifest = parseJson(parts[MANIFEST_PATH], MANIFEST_PATH);
|
|
4831
|
-
if (manifest.format !== MEM_PACKAGE_FORMAT && manifest.format || manifest.version !== MEM_PACKAGE_VERSION) {
|
|
4854
|
+
if (manifest.format !== MEM_PACKAGE_FORMAT && manifest.format !== MEM_PACKAGE_FORMAT_LEGACY || manifest.version !== MEM_PACKAGE_VERSION) {
|
|
4832
4855
|
throw new MemArtifactError("unsupported", "Unsupported MEM package format or version");
|
|
4833
4856
|
}
|
|
4834
|
-
if (manifest.memory?.format !== MEM_FORMAT && manifest.memory?.format || manifest.memory.version !== MEM_FORMAT_VERSION || manifest.parts?.map !== MAP_PATH || manifest.parts?.data !== DATA_PATH || manifest.parts?.integrity !== INTEGRITY_PATH) {
|
|
4857
|
+
if (manifest.memory?.format !== MEM_FORMAT && manifest.memory?.format !== MEM_FORMAT_LEGACY || manifest.memory.version !== MEM_FORMAT_VERSION || manifest.parts?.map !== MAP_PATH || manifest.parts?.data !== DATA_PATH || manifest.parts?.integrity !== INTEGRITY_PATH) {
|
|
4835
4858
|
throw new MemArtifactError("invalid", "Invalid MEM package manifest");
|
|
4836
4859
|
}
|
|
4837
4860
|
const integrity = parseJson(parts[INTEGRITY_PATH], INTEGRITY_PATH);
|
|
@@ -4874,6 +4897,109 @@ var init_mem_package = __esm({
|
|
|
4874
4897
|
}
|
|
4875
4898
|
});
|
|
4876
4899
|
|
|
4900
|
+
// core/storage-coordinator/index.ts
|
|
4901
|
+
var nodeFs4, withStorageLock, readStorageGeneration, writeStorageGeneration;
|
|
4902
|
+
var init_storage_coordinator = __esm({
|
|
4903
|
+
"core/storage-coordinator/index.ts"() {
|
|
4904
|
+
nodeFs4 = /* @__PURE__ */ __name(async () => import('fs/promises'), "nodeFs");
|
|
4905
|
+
withStorageLock = /* @__PURE__ */ __name(async (directoryPath, operationOrOptions, operation, _options = {}) => {
|
|
4906
|
+
const opts = typeof operationOrOptions === "function" ? operation ?? {} : operationOrOptions ?? {};
|
|
4907
|
+
const op = typeof operationOrOptions === "function" ? operationOrOptions : operation;
|
|
4908
|
+
const timeoutMs = opts.timeoutMs ?? 3e4;
|
|
4909
|
+
const staleMs = opts.staleMs ?? 6e4;
|
|
4910
|
+
const lockName = opts.lockName ?? ".storage.lock";
|
|
4911
|
+
const lockPath = `${directoryPath}/${lockName}`;
|
|
4912
|
+
const fs = await nodeFs4();
|
|
4913
|
+
const started = Date.now();
|
|
4914
|
+
await fs.mkdir(directoryPath, { recursive: true });
|
|
4915
|
+
while (true) {
|
|
4916
|
+
try {
|
|
4917
|
+
await fs.mkdir(lockPath);
|
|
4918
|
+
const token2 = `${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
4919
|
+
await fs.writeFile(`${lockPath}/owner.json`, JSON.stringify({ token: token2, pid: process.pid, createdAt: Date.now() }), { flag: "wx" });
|
|
4920
|
+
break;
|
|
4921
|
+
} catch (error) {
|
|
4922
|
+
const code = error.code;
|
|
4923
|
+
if (code !== "EEXIST" && code !== "ENOENT" && code !== "EPERM" && code !== "ENOTEMPTY") throw error;
|
|
4924
|
+
let stale = false;
|
|
4925
|
+
let processDead = false;
|
|
4926
|
+
try {
|
|
4927
|
+
const raw = await fs.readFile(`${lockPath}/owner.json`, "utf8");
|
|
4928
|
+
const parsed = JSON.parse(raw);
|
|
4929
|
+
const ageStale = typeof parsed.createdAt === "number" && Date.now() - parsed.createdAt > staleMs;
|
|
4930
|
+
if (typeof parsed.pid === "number") {
|
|
4931
|
+
try {
|
|
4932
|
+
process.kill(parsed.pid, 0);
|
|
4933
|
+
} catch {
|
|
4934
|
+
processDead = true;
|
|
4935
|
+
}
|
|
4936
|
+
} else {
|
|
4937
|
+
processDead = true;
|
|
4938
|
+
}
|
|
4939
|
+
if (ageStale || processDead) stale = true;
|
|
4940
|
+
} catch {
|
|
4941
|
+
stale = true;
|
|
4942
|
+
}
|
|
4943
|
+
if (stale) {
|
|
4944
|
+
if (processDead) {
|
|
4945
|
+
try {
|
|
4946
|
+
await fs.rm(lockPath, { recursive: true, force: true });
|
|
4947
|
+
continue;
|
|
4948
|
+
} catch {
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
try {
|
|
4952
|
+
await fs.rmdir(lockPath);
|
|
4953
|
+
continue;
|
|
4954
|
+
} catch {
|
|
4955
|
+
}
|
|
4956
|
+
}
|
|
4957
|
+
if (Date.now() - started > timeoutMs) {
|
|
4958
|
+
throw new Error(`Storage lock timeout for ${directoryPath}`);
|
|
4959
|
+
}
|
|
4960
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
let token = "";
|
|
4964
|
+
try {
|
|
4965
|
+
const raw = await fs.readFile(`${lockPath}/owner.json`, "utf8");
|
|
4966
|
+
token = JSON.parse(raw).token ?? "";
|
|
4967
|
+
} catch {
|
|
4968
|
+
token = "";
|
|
4969
|
+
}
|
|
4970
|
+
try {
|
|
4971
|
+
return await op();
|
|
4972
|
+
} finally {
|
|
4973
|
+
try {
|
|
4974
|
+
const raw = await fs.readFile(`${lockPath}/owner.json`, "utf8");
|
|
4975
|
+
const parsed = JSON.parse(raw);
|
|
4976
|
+
if (parsed.token === token && token) {
|
|
4977
|
+
await fs.rm(lockPath, { recursive: true, force: true });
|
|
4978
|
+
}
|
|
4979
|
+
} catch {
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
}, "withStorageLock");
|
|
4983
|
+
readStorageGeneration = /* @__PURE__ */ __name(async (directoryPath) => {
|
|
4984
|
+
const fs = await nodeFs4();
|
|
4985
|
+
try {
|
|
4986
|
+
const raw = await fs.readFile(`${directoryPath}/.storage.generation`, "utf8");
|
|
4987
|
+
const value = Number(raw.trim());
|
|
4988
|
+
return Number.isFinite(value) && value >= 0 ? value : 0;
|
|
4989
|
+
} catch {
|
|
4990
|
+
return 0;
|
|
4991
|
+
}
|
|
4992
|
+
}, "readStorageGeneration");
|
|
4993
|
+
writeStorageGeneration = /* @__PURE__ */ __name(async (directoryPath, value) => {
|
|
4994
|
+
const fs = await nodeFs4();
|
|
4995
|
+
await fs.mkdir(directoryPath, { recursive: true });
|
|
4996
|
+
const temp = `${directoryPath}/.storage.generation.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
4997
|
+
await fs.writeFile(temp, String(value));
|
|
4998
|
+
await fs.rename(temp, `${directoryPath}/.storage.generation`);
|
|
4999
|
+
}, "writeStorageGeneration");
|
|
5000
|
+
}
|
|
5001
|
+
});
|
|
5002
|
+
|
|
4877
5003
|
// core/knowledge/mem-repository.ts
|
|
4878
5004
|
function resolveDuplicate(existing, existingSource, current, currentSource) {
|
|
4879
5005
|
const existingRetracts = existing.revision?.kind === "retracts";
|
|
@@ -4914,19 +5040,20 @@ async function parseMemFile(value, sourceId) {
|
|
|
4914
5040
|
throw new Error(`${message} in ${sourceId}`);
|
|
4915
5041
|
}
|
|
4916
5042
|
}
|
|
4917
|
-
var DOTMEM_DIRECTORY, DEFAULT_MEM_FILE,
|
|
5043
|
+
var DOTMEM_DIRECTORY, DEFAULT_MEM_FILE, nodeFs5, repositoryLoadCaches, separator2, normalizePath, isAbsolutePath, resolvePath, joinPath2, parentPath, uniqueSuffix, isMissingDirectory, sourcePriority, memFilePath, MemDirectoryKnowledgeRepository;
|
|
4918
5044
|
var init_mem_repository = __esm({
|
|
4919
5045
|
"core/knowledge/mem-repository.ts"() {
|
|
4920
5046
|
init_mem_codec();
|
|
4921
5047
|
init_mem_package();
|
|
4922
5048
|
init_state();
|
|
4923
5049
|
init_acquisition_limits();
|
|
5050
|
+
init_storage_coordinator();
|
|
4924
5051
|
DOTMEM_DIRECTORY = ".dotmem";
|
|
4925
5052
|
DEFAULT_MEM_FILE = "project.mem";
|
|
4926
|
-
|
|
4927
|
-
nodeFs4 = /* @__PURE__ */ __name(async () => {
|
|
5053
|
+
nodeFs5 = /* @__PURE__ */ __name(async () => {
|
|
4928
5054
|
return import('fs/promises');
|
|
4929
5055
|
}, "nodeFs");
|
|
5056
|
+
repositoryLoadCaches = /* @__PURE__ */ new Map();
|
|
4930
5057
|
separator2 = /* @__PURE__ */ __name(() => process.platform === "win32" ? "\\" : "/", "separator");
|
|
4931
5058
|
normalizePath = /* @__PURE__ */ __name((value) => value.replace(/[\\/]+/g, separator2()), "normalizePath");
|
|
4932
5059
|
isAbsolutePath = /* @__PURE__ */ __name((value) => /^(?:[A-Za-z]:[\\/]|[\\/])/.test(value), "isAbsolutePath");
|
|
@@ -4938,25 +5065,8 @@ var init_mem_repository = __esm({
|
|
|
4938
5065
|
return index <= 0 ? "." : normalized.slice(0, index);
|
|
4939
5066
|
}, "parentPath");
|
|
4940
5067
|
uniqueSuffix = /* @__PURE__ */ __name(() => globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`, "uniqueSuffix");
|
|
4941
|
-
withDirectoryLock = /* @__PURE__ */ __name(async (directoryPath, operation) => {
|
|
4942
|
-
const previous = directoryLocks.get(directoryPath) ?? Promise.resolve();
|
|
4943
|
-
let release = /* @__PURE__ */ __name(() => void 0, "release");
|
|
4944
|
-
const gate = new Promise((resolveGate) => {
|
|
4945
|
-
release = resolveGate;
|
|
4946
|
-
});
|
|
4947
|
-
const queued = previous.then(() => gate);
|
|
4948
|
-
directoryLocks.set(directoryPath, queued);
|
|
4949
|
-
await previous;
|
|
4950
|
-
try {
|
|
4951
|
-
return await operation();
|
|
4952
|
-
} finally {
|
|
4953
|
-
release();
|
|
4954
|
-
if (directoryLocks.get(directoryPath) === queued) directoryLocks.delete(directoryPath);
|
|
4955
|
-
}
|
|
4956
|
-
}, "withDirectoryLock");
|
|
4957
5068
|
isMissingDirectory = /* @__PURE__ */ __name((error) => error.code === "ENOENT", "isMissingDirectory");
|
|
4958
5069
|
sourcePriority = /* @__PURE__ */ __name((sourceId, scope) => {
|
|
4959
|
-
if (sourceId.endsWith(".mem") && sourceId !== "project.mem" && sourceId !== "user.mem" && sourceId !== "agent.mem") return 0;
|
|
4960
5070
|
if (scope === "project" || sourceId === "project.mem") return 4;
|
|
4961
5071
|
if (scope === "user" || sourceId === "user.mem") return 3;
|
|
4962
5072
|
if (sourceId === "agent.mem" || sourceId === "agent") return 2;
|
|
@@ -4984,7 +5094,7 @@ var init_mem_repository = __esm({
|
|
|
4984
5094
|
this.loadWritableOnly = loadWritableOnly;
|
|
4985
5095
|
}
|
|
4986
5096
|
async discover() {
|
|
4987
|
-
const { readdir } = await
|
|
5097
|
+
const { readdir } = await nodeFs5();
|
|
4988
5098
|
try {
|
|
4989
5099
|
const entries2 = await readdir(this.directoryPath, { withFileTypes: true });
|
|
4990
5100
|
return entries2.filter((entry) => entry.isFile() && entry.name.endsWith(".mem") && entry.name !== "@brain.mem").map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
@@ -4999,7 +5109,7 @@ var init_mem_repository = __esm({
|
|
|
4999
5109
|
* receive a clear failure instead of discovering corruption on first use.
|
|
5000
5110
|
*/
|
|
5001
5111
|
async initialize() {
|
|
5002
|
-
const { mkdir } = await
|
|
5112
|
+
const { mkdir } = await nodeFs5();
|
|
5003
5113
|
await mkdir(this.directoryPath, { recursive: true });
|
|
5004
5114
|
await this.load();
|
|
5005
5115
|
}
|
|
@@ -5014,7 +5124,7 @@ var init_mem_repository = __esm({
|
|
|
5014
5124
|
* that does not delete is not a delete.
|
|
5015
5125
|
*/
|
|
5016
5126
|
async clearWritable() {
|
|
5017
|
-
const { rm, readdir } = await
|
|
5127
|
+
const { rm, readdir } = await nodeFs5();
|
|
5018
5128
|
const filePath = memFilePath(this.directoryPath, this.writableSourceId);
|
|
5019
5129
|
await rm(filePath, { force: true });
|
|
5020
5130
|
await rm(`${filePath}.bak`, { force: true });
|
|
@@ -5031,15 +5141,28 @@ var init_mem_repository = __esm({
|
|
|
5031
5141
|
}
|
|
5032
5142
|
}
|
|
5033
5143
|
async load() {
|
|
5034
|
-
const
|
|
5035
|
-
|
|
5144
|
+
const cacheKey = `${this.directoryPath}:${this.writableSourceId}:${this.loadWritableOnly}`;
|
|
5145
|
+
for (let attempt = 0; attempt < 5; attempt += 1) {
|
|
5146
|
+
const generationBefore = await readStorageGeneration(this.directoryPath);
|
|
5147
|
+
const cached = repositoryLoadCaches.get(cacheKey);
|
|
5148
|
+
if (cached && cached.signature === String(generationBefore)) {
|
|
5149
|
+
return structuredClone(cached.state);
|
|
5150
|
+
}
|
|
5151
|
+
const loaded = this.loadWritableOnly ? await this.loadSources([this.writableSourceId]) : await this.loadSources();
|
|
5152
|
+
const state2 = this.combine(loaded);
|
|
5153
|
+
const generationAfter = await readStorageGeneration(this.directoryPath);
|
|
5154
|
+
if (generationBefore !== generationAfter && attempt < 4) continue;
|
|
5155
|
+
repositoryLoadCaches.set(cacheKey, { signature: String(generationAfter), state: structuredClone(state2) });
|
|
5156
|
+
return state2;
|
|
5157
|
+
}
|
|
5158
|
+
throw new Error("Unable to load stable repository state");
|
|
5036
5159
|
}
|
|
5037
|
-
async save(state2, expectedVersion) {
|
|
5160
|
+
async save(state2, expectedVersion, locked = false) {
|
|
5038
5161
|
const validated = validateKnowledgeState(state2);
|
|
5039
5162
|
if (!Number.isInteger(expectedVersion) || expectedVersion < 0 || validated.version !== expectedVersion + 1) {
|
|
5040
5163
|
throw new Error("Invalid expected persisted version");
|
|
5041
5164
|
}
|
|
5042
|
-
|
|
5165
|
+
const doWrite = /* @__PURE__ */ __name(async () => {
|
|
5043
5166
|
const loaded = await this.loadSources();
|
|
5044
5167
|
const writable = loaded.find((source) => source.id === this.writableSourceId) ?? {
|
|
5045
5168
|
id: this.writableSourceId,
|
|
@@ -5061,10 +5184,16 @@ var init_mem_repository = __esm({
|
|
|
5061
5184
|
claims: [...writable.state.claims, ...newClaims]
|
|
5062
5185
|
};
|
|
5063
5186
|
await this.writeSource(writable.filePath, nextWritable, writable.preserved, writable.package);
|
|
5064
|
-
|
|
5187
|
+
await writeStorageGeneration(this.directoryPath, await readStorageGeneration(this.directoryPath) + 1);
|
|
5188
|
+
}, "doWrite");
|
|
5189
|
+
if (locked) {
|
|
5190
|
+
await doWrite();
|
|
5191
|
+
} else {
|
|
5192
|
+
await withStorageLock(this.directoryPath, doWrite);
|
|
5193
|
+
}
|
|
5065
5194
|
}
|
|
5066
5195
|
async loadSources(sourceIds) {
|
|
5067
|
-
const { readFile: readFile5 } = await
|
|
5196
|
+
const { readFile: readFile5 } = await nodeFs5();
|
|
5068
5197
|
const ids = sourceIds ?? await this.discover();
|
|
5069
5198
|
const sources = [];
|
|
5070
5199
|
for (const sourceId of ids) {
|
|
@@ -5154,7 +5283,7 @@ var init_mem_repository = __esm({
|
|
|
5154
5283
|
* valid package, so the backup is always a version this library can read.
|
|
5155
5284
|
*/
|
|
5156
5285
|
async keepLastValidVersion(filePath) {
|
|
5157
|
-
const { readFile: readFile5, copyFile, rename, rm } = await
|
|
5286
|
+
const { readFile: readFile5, copyFile, rename, rm } = await nodeFs5();
|
|
5158
5287
|
let current;
|
|
5159
5288
|
try {
|
|
5160
5289
|
current = await readFile5(filePath);
|
|
@@ -5178,7 +5307,7 @@ var init_mem_repository = __esm({
|
|
|
5178
5307
|
}
|
|
5179
5308
|
/** Best-effort directory sync: the rename is durable once the directory is. */
|
|
5180
5309
|
async syncDirectory(directoryPath) {
|
|
5181
|
-
const { open } = await
|
|
5310
|
+
const { open } = await nodeFs5();
|
|
5182
5311
|
try {
|
|
5183
5312
|
const handle = await open(directoryPath, "r");
|
|
5184
5313
|
try {
|
|
@@ -5190,7 +5319,7 @@ var init_mem_repository = __esm({
|
|
|
5190
5319
|
}
|
|
5191
5320
|
}
|
|
5192
5321
|
async writeSource(filePath, state2, preserved, preservedPackage) {
|
|
5193
|
-
const { mkdir, rename, rm, open, readFile: readFile5 } = await
|
|
5322
|
+
const { mkdir, rename, rm, open, readFile: readFile5 } = await nodeFs5();
|
|
5194
5323
|
if (!Number.isInteger(state2.version) || state2.version < 0) throw new Error("Invalid writable .mem knowledge version");
|
|
5195
5324
|
for (const claim of state2.claims) validateClaim(claim);
|
|
5196
5325
|
await mkdir(parentPath(filePath), { recursive: true });
|
|
@@ -5677,7 +5806,7 @@ var init_project_identity = __esm({
|
|
|
5677
5806
|
});
|
|
5678
5807
|
|
|
5679
5808
|
// core/knowledge/staging.ts
|
|
5680
|
-
var DOTMEM_STAGE_FORMAT, DOTMEM_STAGE_VERSION, StageFileError, generateRequestId, nodeCwd, resolveStagingDirectory, stagePathFor,
|
|
5809
|
+
var DOTMEM_STAGE_FORMAT, DOTMEM_STAGE_VERSION, StageFileError, generateRequestId, nodeCwd, resolveStagingDirectory, stagePathFor, nodeFs6, normalizeClaimIds, revisionFromOptions, writeStageFile, readStageFile, validateStageFile, commitStageFile, cleanupStageFile;
|
|
5681
5810
|
var init_staging = __esm({
|
|
5682
5811
|
"core/knowledge/staging.ts"() {
|
|
5683
5812
|
init_claim_record();
|
|
@@ -5712,7 +5841,7 @@ var init_staging = __esm({
|
|
|
5712
5841
|
return `${base}/dotmem`;
|
|
5713
5842
|
}, "resolveStagingDirectory");
|
|
5714
5843
|
stagePathFor = /* @__PURE__ */ __name((requestId) => `${resolveStagingDirectory()}/${requestId}.stage`, "stagePathFor");
|
|
5715
|
-
|
|
5844
|
+
nodeFs6 = /* @__PURE__ */ __name(async () => import('fs/promises'), "nodeFs");
|
|
5716
5845
|
normalizeClaimIds = /* @__PURE__ */ __name((value) => {
|
|
5717
5846
|
if (!value) return [];
|
|
5718
5847
|
return Array.isArray(value) ? value : [value];
|
|
@@ -5737,7 +5866,7 @@ var init_staging = __esm({
|
|
|
5737
5866
|
};
|
|
5738
5867
|
const requestId = generateRequestId();
|
|
5739
5868
|
const stagePath = stagePathFor(requestId);
|
|
5740
|
-
const fs = await
|
|
5869
|
+
const fs = await nodeFs6();
|
|
5741
5870
|
await fs.mkdir(resolveStagingDirectory(), { recursive: true });
|
|
5742
5871
|
const stageFile = {
|
|
5743
5872
|
format: DOTMEM_STAGE_FORMAT,
|
|
@@ -5757,7 +5886,7 @@ var init_staging = __esm({
|
|
|
5757
5886
|
}, "writeStageFile");
|
|
5758
5887
|
readStageFile = /* @__PURE__ */ __name(async (requestId) => {
|
|
5759
5888
|
const stagePath = stagePathFor(requestId);
|
|
5760
|
-
const fs = await
|
|
5889
|
+
const fs = await nodeFs6();
|
|
5761
5890
|
try {
|
|
5762
5891
|
const content = await fs.readFile(stagePath, "utf8");
|
|
5763
5892
|
return JSON.parse(content);
|
|
@@ -5868,7 +5997,7 @@ var init_staging = __esm({
|
|
|
5868
5997
|
}, "commitStageFile");
|
|
5869
5998
|
cleanupStageFile = /* @__PURE__ */ __name(async (requestId) => {
|
|
5870
5999
|
const stagePath = stagePathFor(requestId);
|
|
5871
|
-
const fs = await
|
|
6000
|
+
const fs = await nodeFs6();
|
|
5872
6001
|
try {
|
|
5873
6002
|
await fs.unlink(stagePath);
|
|
5874
6003
|
} catch (error) {
|
|
@@ -6690,6 +6819,7 @@ function _inferConfidence(claim) {
|
|
|
6690
6819
|
var LOGIC_MEM_FILE, nodeCwd2, cachedRuntime, LogicEngine, logic, logic_default;
|
|
6691
6820
|
var init_logic = __esm({
|
|
6692
6821
|
"core/logic/index.ts"() {
|
|
6822
|
+
init_suppress_idb_warning();
|
|
6693
6823
|
init_knowledge();
|
|
6694
6824
|
init_mem_repository();
|
|
6695
6825
|
init_acquisition_boundary();
|
|
@@ -7053,11 +7183,18 @@ var init_note_types = __esm({
|
|
|
7053
7183
|
}
|
|
7054
7184
|
});
|
|
7055
7185
|
|
|
7186
|
+
// core/mcp/index.ts
|
|
7187
|
+
init_suppress_idb_warning();
|
|
7188
|
+
|
|
7056
7189
|
// package.json
|
|
7057
7190
|
var package_default = {
|
|
7058
|
-
version: "0.0
|
|
7191
|
+
version: "0.1.0"};
|
|
7192
|
+
|
|
7193
|
+
// core/memory/index.ts
|
|
7194
|
+
init_suppress_idb_warning();
|
|
7059
7195
|
|
|
7060
7196
|
// core/memory/journal.ts
|
|
7197
|
+
init_suppress_idb_warning();
|
|
7061
7198
|
init_env();
|
|
7062
7199
|
var g = globalThis;
|
|
7063
7200
|
function namespace() {
|
|
@@ -7264,6 +7401,7 @@ var journal_default = journal;
|
|
|
7264
7401
|
init_brain();
|
|
7265
7402
|
|
|
7266
7403
|
// core/memory/knowledge-runtime.ts
|
|
7404
|
+
init_suppress_idb_warning();
|
|
7267
7405
|
init_knowledge();
|
|
7268
7406
|
init_project_identity();
|
|
7269
7407
|
init_user_paths();
|
|
@@ -7661,6 +7799,7 @@ var policy = {
|
|
|
7661
7799
|
};
|
|
7662
7800
|
|
|
7663
7801
|
// core/memory/entries.ts
|
|
7802
|
+
init_suppress_idb_warning();
|
|
7664
7803
|
init_env();
|
|
7665
7804
|
var MEMORY_INDEX_KEY = "__dotmem_memory_index__";
|
|
7666
7805
|
var SUPERSEDED_PREFIX = "__dotmem_superseded__";
|
|
@@ -8205,15 +8344,18 @@ var context = {
|
|
|
8205
8344
|
};
|
|
8206
8345
|
|
|
8207
8346
|
// core/memory/acquire.ts
|
|
8347
|
+
init_suppress_idb_warning();
|
|
8208
8348
|
init_env();
|
|
8209
8349
|
init_project_identity();
|
|
8210
8350
|
init_project_anchor();
|
|
8211
8351
|
init_acquisition_boundary();
|
|
8212
8352
|
init_claim_record();
|
|
8353
|
+
init_state();
|
|
8213
8354
|
init_router();
|
|
8214
8355
|
init_store_queue();
|
|
8215
8356
|
init_staging();
|
|
8216
8357
|
init_user_paths();
|
|
8358
|
+
init_storage_coordinator();
|
|
8217
8359
|
init_mem_repository();
|
|
8218
8360
|
function normalizeClaimIds3(value) {
|
|
8219
8361
|
if (!value) return [];
|
|
@@ -8291,23 +8433,27 @@ var acquire = {
|
|
|
8291
8433
|
);
|
|
8292
8434
|
}
|
|
8293
8435
|
const revision = revisionFromAcquire2(opts);
|
|
8436
|
+
const repository = target.repository;
|
|
8294
8437
|
await withStoreQueue(acquisitionStoreKey(kind, scope, sourceProject), async () => {
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
8298
|
-
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8438
|
+
await withStorageLock(repository.directoryPath, async () => {
|
|
8439
|
+
const state2 = await repository.load();
|
|
8440
|
+
const next = updateKnowledge(state2, {
|
|
8441
|
+
basedOnVersion: state2.version,
|
|
8442
|
+
claims: [buildClaimRecord({
|
|
8443
|
+
id: opts.id,
|
|
8444
|
+
knowledge: boundary.knowledge,
|
|
8445
|
+
applicability: opts.applicability,
|
|
8446
|
+
evidence: opts.evidence,
|
|
8447
|
+
epistemicType: opts.epistemicType,
|
|
8448
|
+
provenance: opts.provenance,
|
|
8449
|
+
acquiredAt: opts.acquiredAt,
|
|
8450
|
+
revision,
|
|
8451
|
+
scope,
|
|
8452
|
+
sourceProject,
|
|
8453
|
+
kind
|
|
8454
|
+
})]
|
|
8455
|
+
});
|
|
8456
|
+
await repository.save(next, state2.version, true);
|
|
8311
8457
|
});
|
|
8312
8458
|
});
|
|
8313
8459
|
const verification = await target.repository.load();
|