@remnic/core 9.44.0 → 9.45.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/dist/access-admin-ops-surface.d.ts +5 -5
- package/dist/access-admin-ops-surface.js +14 -13
- package/dist/access-authorization-probe.d.ts +5 -5
- package/dist/access-authorization-probe.js +15 -14
- package/dist/access-boundary.d.ts +5 -5
- package/dist/access-boundary.js +14 -13
- package/dist/access-cli.js +37 -36
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +5 -5
- package/dist/access-extraction-force-flush.js +14 -13
- package/dist/access-http-lcm-compaction.d.ts +5 -5
- package/dist/access-http-lifecycle-flush.d.ts +5 -5
- package/dist/access-http-query.js +14 -13
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +21 -20
- package/dist/access-identity-continuity-surface.d.ts +4 -4
- package/dist/access-identity-continuity-surface.js +14 -13
- package/dist/access-lcm-surface.d.ts +5 -5
- package/dist/access-lcm-surface.js +14 -13
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +19 -18
- package/dist/access-namespace-preflight.js +14 -13
- package/dist/access-observe-write-surface.d.ts +5 -5
- package/dist/access-observe-write-surface.js +14 -13
- package/dist/access-operations-batch.js +16 -15
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +18 -17
- package/dist/access-recall-concurrency.d.ts +5 -5
- package/dist/access-recall-concurrency.js +14 -13
- package/dist/access-recall-response.d.ts +5 -5
- package/dist/access-recall-response.js +14 -13
- package/dist/access-recall-surface.d.ts +5 -5
- package/dist/access-recall-surface.js +14 -13
- package/dist/access-schema.d.ts +84 -84
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-BCZJbX0f.d.ts → access-service-DBo88Dmm.d.ts} +3 -3
- package/dist/access-service-helpers.d.ts +5 -5
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +14 -13
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/access-wearables-meetings-surface.d.ts +2 -2
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +4 -3
- package/dist/buffer.d.ts +1 -1
- package/dist/causal-consolidation.js +5 -4
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-OHLNFI6Z.js → chunk-3HKQOFOV.js} +7 -5
- package/dist/{chunk-OHLNFI6Z.js.map → chunk-3HKQOFOV.js.map} +1 -1
- package/dist/{chunk-PJUHQC4T.js → chunk-3HLCRYBV.js} +3 -3
- package/dist/{chunk-N7LPS4Z3.js → chunk-5SM35XZR.js} +2 -2
- package/dist/{chunk-E6JYVPBK.js → chunk-5YGO5VEH.js} +2 -2
- package/dist/{chunk-EUVPB5TA.js → chunk-65V4K4MT.js} +8 -8
- package/dist/{chunk-WX6KOVVK.js → chunk-6OLQJJYE.js} +2 -2
- package/dist/chunk-6UWB5PTR.js +413 -0
- package/dist/chunk-6UWB5PTR.js.map +1 -0
- package/dist/{chunk-G24HJJ67.js → chunk-7JO6RVBI.js} +6 -6
- package/dist/{chunk-WUDWRUGK.js → chunk-7PVFOFPJ.js} +2 -2
- package/dist/{chunk-UUQLB2HJ.js → chunk-C7EI7CA6.js} +2 -2
- package/dist/{chunk-MUKLQDJP.js → chunk-FLBPATMZ.js} +18 -18
- package/dist/{chunk-HGFILS2Q.js → chunk-FVGQ5LIS.js} +2 -2
- package/dist/{chunk-OPVOUBHT.js → chunk-G24XIK6H.js} +2 -2
- package/dist/{chunk-CH2WTP6R.js → chunk-GBJJUPNV.js} +2 -2
- package/dist/{chunk-HXTUA7QM.js → chunk-GOPWZYZH.js} +6 -6
- package/dist/{chunk-WMHO3WLC.js → chunk-GQBZ7EVF.js} +2 -2
- package/dist/{chunk-KQAFEZQX.js → chunk-IPLYGWQF.js} +5 -5
- package/dist/{chunk-OZL7KB6B.js → chunk-J4OKD6QX.js} +2 -2
- package/dist/{chunk-TRBIJS2T.js → chunk-JZ7SSAQ5.js} +3 -3
- package/dist/{chunk-YUOKZ3LJ.js → chunk-K6OTW3TP.js} +2 -2
- package/dist/{chunk-I22U5YYD.js → chunk-QQ3NDJOM.js} +2 -2
- package/dist/{chunk-2FTRRQKZ.js → chunk-RVLJEII5.js} +30 -511
- package/dist/chunk-RVLJEII5.js.map +1 -0
- package/dist/chunk-S5SLVSVY.js +517 -0
- package/dist/chunk-S5SLVSVY.js.map +1 -0
- package/dist/{chunk-7PLHD7EO.js → chunk-SS7YWVPF.js} +2 -2
- package/dist/{chunk-J43XN7N3.js → chunk-U5G66ORD.js} +18 -18
- package/dist/{chunk-EMC5GT4H.js → chunk-VCGPO2VD.js} +4 -4
- package/dist/{chunk-JDDTNK5P.js → chunk-VRYJSKOM.js} +2 -2
- package/dist/{chunk-PLQCPMJA.js → chunk-WC4SPYHX.js} +7 -7
- package/dist/{chunk-IADUAH35.js → chunk-WG2PI44B.js} +2 -2
- package/dist/{chunk-35IC3EVP.js → chunk-XFQRFWVS.js} +2 -2
- package/dist/{chunk-MYFFOPO2.js → chunk-XMZV27S5.js} +2 -2
- package/dist/{chunk-IXFI6E3Q.js → chunk-YQQK7W7T.js} +2 -2
- package/dist/{chunk-3F2LKUMU.js → chunk-ZAB5PG65.js} +2 -2
- package/dist/{chunk-O4BADU6R.js → chunk-ZPJJE7MF.js} +2 -2
- package/dist/{chunk-U5SX74DV.js → chunk-ZS5UZU5M.js} +3 -3
- package/dist/{cli-U30A3jyx.d.ts → cli-DQ4VhjqX.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +31 -30
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +4 -3
- package/dist/connectors/codex-materialize-runner.js +4 -3
- package/dist/connectors/index.js +4 -3
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +1 -1
- package/dist/convergence-refresh.js +6 -5
- package/dist/corpus-watermark.js +6 -5
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +4 -3
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/explicit-capture.js +3 -2
- package/dist/extraction.js +4 -3
- package/dist/index.d.ts +398 -398
- package/dist/index.js +37 -36
- package/dist/maintenance/memory-governance.js +4 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -3
- package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-projection.js +5 -4
- package/dist/{maintenance-DVBLXkFw.d.ts → maintenance-_RV38GlE.d.ts} +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +5 -4
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +4 -3
- package/dist/operator-doctor-corpus.js +7 -6
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -10
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +9 -8
- package/dist/{orchestrator-DUxbhhqO.d.ts → orchestrator-B2ecFpRO.d.ts} +3 -3
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +37 -36
- package/dist/reconcile/manifest.d.ts +33 -0
- package/dist/reconcile/manifest.js +248 -0
- package/dist/reconcile/manifest.js.map +1 -0
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/reconcile/plan.js +8 -404
- package/dist/reconcile/plan.js.map +1 -1
- package/dist/schemas.d.ts +76 -76
- package/dist/semantic-consolidation.js +5 -4
- package/dist/semantic-rule-promotion.js +4 -3
- package/dist/semantic-rule-verifier.js +4 -3
- package/dist/{service-CLuMO-pa.d.ts → service-DW06sY3P.d.ts} +1 -1
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +4 -3
- package/dist/{storage-Blr71GpS.d.ts → storage-qRIQPA6F.d.ts} +12 -0
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +3 -2
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/verified-recall.js +4 -3
- package/package.json +12 -2
- package/src/reconcile/manifest.test.ts +261 -0
- package/src/reconcile/manifest.ts +278 -0
- package/src/reconcile/plan.ts +1 -0
- package/src/storage/content-hash-index.ts +26 -0
- package/dist/chunk-2FTRRQKZ.js.map +0 -1
- /package/dist/{chunk-PJUHQC4T.js.map → chunk-3HLCRYBV.js.map} +0 -0
- /package/dist/{chunk-N7LPS4Z3.js.map → chunk-5SM35XZR.js.map} +0 -0
- /package/dist/{chunk-E6JYVPBK.js.map → chunk-5YGO5VEH.js.map} +0 -0
- /package/dist/{chunk-EUVPB5TA.js.map → chunk-65V4K4MT.js.map} +0 -0
- /package/dist/{chunk-WX6KOVVK.js.map → chunk-6OLQJJYE.js.map} +0 -0
- /package/dist/{chunk-G24HJJ67.js.map → chunk-7JO6RVBI.js.map} +0 -0
- /package/dist/{chunk-WUDWRUGK.js.map → chunk-7PVFOFPJ.js.map} +0 -0
- /package/dist/{chunk-UUQLB2HJ.js.map → chunk-C7EI7CA6.js.map} +0 -0
- /package/dist/{chunk-MUKLQDJP.js.map → chunk-FLBPATMZ.js.map} +0 -0
- /package/dist/{chunk-HGFILS2Q.js.map → chunk-FVGQ5LIS.js.map} +0 -0
- /package/dist/{chunk-OPVOUBHT.js.map → chunk-G24XIK6H.js.map} +0 -0
- /package/dist/{chunk-CH2WTP6R.js.map → chunk-GBJJUPNV.js.map} +0 -0
- /package/dist/{chunk-HXTUA7QM.js.map → chunk-GOPWZYZH.js.map} +0 -0
- /package/dist/{chunk-WMHO3WLC.js.map → chunk-GQBZ7EVF.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-IPLYGWQF.js.map} +0 -0
- /package/dist/{chunk-OZL7KB6B.js.map → chunk-J4OKD6QX.js.map} +0 -0
- /package/dist/{chunk-TRBIJS2T.js.map → chunk-JZ7SSAQ5.js.map} +0 -0
- /package/dist/{chunk-YUOKZ3LJ.js.map → chunk-K6OTW3TP.js.map} +0 -0
- /package/dist/{chunk-I22U5YYD.js.map → chunk-QQ3NDJOM.js.map} +0 -0
- /package/dist/{chunk-7PLHD7EO.js.map → chunk-SS7YWVPF.js.map} +0 -0
- /package/dist/{chunk-J43XN7N3.js.map → chunk-U5G66ORD.js.map} +0 -0
- /package/dist/{chunk-EMC5GT4H.js.map → chunk-VCGPO2VD.js.map} +0 -0
- /package/dist/{chunk-JDDTNK5P.js.map → chunk-VRYJSKOM.js.map} +0 -0
- /package/dist/{chunk-PLQCPMJA.js.map → chunk-WC4SPYHX.js.map} +0 -0
- /package/dist/{chunk-IADUAH35.js.map → chunk-WG2PI44B.js.map} +0 -0
- /package/dist/{chunk-35IC3EVP.js.map → chunk-XFQRFWVS.js.map} +0 -0
- /package/dist/{chunk-MYFFOPO2.js.map → chunk-XMZV27S5.js.map} +0 -0
- /package/dist/{chunk-IXFI6E3Q.js.map → chunk-YQQK7W7T.js.map} +0 -0
- /package/dist/{chunk-3F2LKUMU.js.map → chunk-ZAB5PG65.js.map} +0 -0
- /package/dist/{chunk-O4BADU6R.js.map → chunk-ZPJJE7MF.js.map} +0 -0
- /package/dist/{chunk-U5SX74DV.js.map → chunk-ZS5UZU5M.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/storage/content-hash-index.ts","../src/storage/tombstone-blocked-capture-mutation.ts","../src/storage/tombstone-blocked-capture-sync.ts","../src/storage/tombstone-blocked-capture-index.ts"],"sourcesContent":["// Content-hash dedup index for facts, extracted from storage.ts (issue #1909 /\n// PR #2016 write-hot-paths). Self-contained: cross-process locked reconcile /\n// rebuild saves plus the deferred durable-retry machinery. storage.ts imports\n// these back and re-exports the class + companion types that were previously\n// part of its public API.\nimport { mkdir, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { log } from \"../logger.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport { withHeldFileLock } from \"../utils/serialize-mutations.js\";\nimport { normalizeContent, computeContentHash } from \"../content-hash.js\";\nimport {\n SecureStoreLockedError,\n readMaybeEncryptedFile,\n writeMaybeEncryptedFile,\n} from \"../secure-store/secure-fs.js\";\n\n/**\n * Stale threshold (ms) for the per-file advisory lock guarding a fact-hash\n * index merge-save (issue #1909 review round 7). The critical section is a\n * single read+atomic-rewrite of one index file (≤ a few MB), so a holder older\n * than this is treated as crashed. Generous to tolerate slow/encrypted disks\n * without breaking a legitimately in-progress publish.\n */\nconst CONTENT_HASH_INDEX_LOCK_STALE_MS = 30_000;\n\n/**\n * Durable-retry policy for a deferred content-hash reconcile save whose\n * cross-process lock acquire timed out (issue #1909 / PR #2016). When the lock\n * is contended past `withHeldFileLock`'s bounded wait, the added hashes are held\n * only in this process's memory; relying on \"some later batch save\" is not\n * durable (the run may be the last before idle/shutdown), and a long-lived peer\n * that already built its authoritative in-memory index will not see the write.\n * So we schedule a bounded, exponentially-backed-off background retry that keeps\n * re-attempting the locked publish until it lands. Bounded because the durable\n * fact `.md` is already on disk and a process restart rebuilds the index from\n * the corpus regardless — exhausting retries degrades to that rebuild safety\n * net, never to data loss or a fatal append failure.\n */\nconst CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS = 5;\n/** Base backoff (ms) before the first deferred reconcile-save retry; doubles each attempt. */\nconst CONTENT_HASH_INDEX_RETRY_BASE_MS = 500;\n/** Ceiling (ms) for the exponential reconcile-save retry backoff. */\nexport const CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS = 5_000;\n\n/**\n * Tuning for {@link ContentHashIndex} cross-process lock waits and the\n * deferred reconcile-save durable retry (issue #1909 / PR #2016). All optional;\n * production uses the module defaults. Tests inject small values so the\n * lock-timeout + retry path is exercised deterministically without real\n * multi-second waits.\n */\nexport interface ContentHashIndexLockOptions {\n /** Bounded wait to acquire the per-file advisory lock; passed to `withHeldFileLock` (default 5000ms). */\n readonly maxWaitMs?: number;\n /** Poll interval while waiting for a busy lock (default 50ms). */\n readonly pollMs?: number;\n /** Base backoff before the first deferred-save retry (default 500ms). */\n readonly retryBaseMs?: number;\n /** Max deferred-save retries before falling back to the corpus-rebuild safety net (default 5). */\n readonly retryMaxAttempts?: number;\n}\n\n/**\n * Thrown when the fact-hash index cannot be made authoritative — the\n * cross-process rebuild lock could not be acquired within the bounded retry\n * budget (PR #2016). Callers that require an authoritative dedup answer surface\n * this instead of silently trusting a stale loaded snapshot.\n */\nexport class FactHashIndexNotAuthoritativeError extends Error {\n constructor(stateDir: string) {\n super(\n `fact-hash index is not authoritative: the cross-process rebuild lock for ${stateDir} could not be acquired within the bounded retry budget`,\n );\n this.name = \"FactHashIndexNotAuthoritativeError\";\n }\n}\n\ntype DiskFingerprint = {\n mtimeMs: number;\n size: number;\n dev: number;\n ino: number;\n ctimeMs: number;\n birthtimeMs: number;\n};\n/**\n * Content-hash dedup index for facts.\n * Normalizes content (lowercase, strip punctuation, collapse whitespace),\n * computes SHA-256, and stores hashes in a line-delimited file.\n * Prevents writing semantically identical facts.\n */\nexport class ContentHashIndex {\n private hashes: Set<string> = new Set();\n private dirty = false;\n /**\n * Hashes explicitly removed since the last successful save (issue #1909 review\n * round 8 thread 3). Tracked separately so `saveMergingWithDisk` can be\n * removal-AWARE: under the file lock it reads the latest on-disk set, DROPS\n * these, then unions our additions — so a removal batch cannot resurrect a\n * hash (union alone would) and cannot clobber a concurrent extraction's\n * appended hash (blind overwrite would). Consumed + cleared by every save.\n */\n private removed: Set<string> = new Set();\n /**\n * Hashes added by THIS instance since the last successful save (issue #1909\n * review round 9 finding 3). Tracked separately from the loaded snapshot so a\n * reconciling save publishes `(on-disk \\ removed) ∪ added` — it re-applies only\n * OUR additions, never the stale loaded entries. Without this, seeding the\n * merge from `this.hashes` (loaded ∪ added) would resurrect a hash a peer\n * removed on disk while this instance held a stale snapshot.\n */\n private added: Set<string> = new Set();\n private readonly filePath: string;\n private readonly secureStoreKeyProvider: () => Buffer | null;\n private readonly secureStoreWriteKeyProvider: () => Buffer | null;\n private readonly memoryDir: string;\n private readonly lockOptions: ContentHashIndexLockOptions;\n /**\n * Deferred reconcile-save durable-retry state (issue #1909 / PR #2016). At\n * most ONE retry is ever armed (`reconcileRetryTimer` is the reentrancy guard)\n * so successive timed-out saves cannot stack duplicate/parallel retries.\n * `reconcileRetryBarrier` resolves when the chain settles (published or gave\n * up) — awaited by tests and any caller wanting the eventual result.\n */\n private reconcileRetryTimer: NodeJS.Timeout | null = null;\n private reconcileRetryAttempts = 0;\n private reconcileRetryBarrier: Promise<void> | null = null;\n private reconcileRetryResolve: (() => void) | null = null;\n /**\n * On-disk fingerprint captured at the last point THIS instance's in-memory\n * set matched disk — after `load()`, `save()`, or a reconcile publish. A peer\n * process that advances the durable index changes its file generation even\n * when byte size and mtime collide, so the freshness check remains safe\n * without an O(file-size) read on the hot path.\n */\n private lastSyncedFingerprint: DiskFingerprint | null = null;\n\n constructor(\n stateDir: string,\n secureStoreKeyProvider: () => Buffer | null = () => null,\n secureStoreWriteKeyProvider: () => Buffer | null = secureStoreKeyProvider,\n memoryDir: string = path.dirname(stateDir),\n lockOptions: ContentHashIndexLockOptions = {}\n ) {\n this.filePath = path.join(stateDir, \"fact-hashes.txt\");\n this.secureStoreKeyProvider = secureStoreKeyProvider;\n this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;\n this.memoryDir = memoryDir;\n this.lockOptions = lockOptions;\n }\n\n /** Load existing hashes from disk. Safe to call multiple times. */\n async load(): Promise<void> {\n try {\n const raw = await readMaybeEncryptedFile(this.filePath, this.secureStoreKeyProvider(), this.memoryDir);\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n if (trimmed.length > 0) {\n this.hashes.add(trimmed);\n }\n }\n log.debug(`content-hash index: loaded ${this.hashes.size} hashes`);\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n log.debug(\"content-hash index: no existing index — starting fresh\");\n }\n // The loaded set now reflects the on-disk file — baseline the fingerprint so\n // a later peer write is detectable (PR #2016 review).\n await this.captureSyncedFingerprint();\n }\n\n /** Cheap `stat` of the durable index file; null when it does not exist yet. */\n private async statIndexFile(): Promise<DiskFingerprint | null> {\n try {\n const s = await stat(this.filePath);\n return {\n mtimeMs: s.mtimeMs,\n size: s.size,\n dev: s.dev,\n ino: s.ino,\n ctimeMs: s.ctimeMs,\n birthtimeMs: s.birthtimeMs,\n };\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return null;\n throw err;\n }\n }\n\n /** Record the current on-disk fingerprint as this instance's synced baseline. */\n private async captureSyncedFingerprint(): Promise<void> {\n try {\n this.lastSyncedFingerprint = await this.statIndexFile();\n } catch (err) {\n // A stat failure other than ENOENT leaves no baseline; the next freshness\n // check reports non-current and the caller confirms against the corpus.\n this.lastSyncedFingerprint = null;\n log.debug(`content-hash index: could not fingerprint ${this.filePath}: ${err}`);\n }\n }\n\n /**\n * True when the durable index file is unchanged since this instance last\n * synced it (load / save / reconcile). False when a peer advanced it, when\n * the file appeared or vanished, or when freshness cannot be established\n * (stat error) — the caller then treats the in-memory snapshot as\n * non-authoritative and confirms a dedup miss against the durable corpus.\n * The stat includes file identity and generation metadata so same-size,\n * same-mtime atomic replacements are detected without reading the file body.\n */\n async isDiskFingerprintCurrent(): Promise<boolean> {\n let current: DiskFingerprint | null;\n try {\n current = await this.statIndexFile();\n } catch {\n return false;\n }\n const last = this.lastSyncedFingerprint;\n if (last === null || current === null) {\n return last === null && current === null;\n }\n return (\n current.mtimeMs === last.mtimeMs &&\n current.size === last.size &&\n current.dev === last.dev &&\n current.ino === last.ino &&\n current.ctimeMs === last.ctimeMs &&\n current.birthtimeMs === last.birthtimeMs\n );\n }\n\n /** Check if content already exists in the index. */\n has(content: string): boolean {\n return this.hashes.has(ContentHashIndex.computeHash(content));\n }\n\n /** Add content hash to the index. */\n add(content: string): void {\n const hash = ContentHashIndex.computeHash(content);\n // A re-add supersedes a pending removal of the same hash (round 8 thread 3).\n this.removed.delete(hash);\n // Record OUR durable delta even when the local snapshot already holds the\n // hash (PR #2016 thread SD-nG): local membership can be STALE — a peer\n // removed this hash on disk while this instance kept it in memory. Skipping\n // `added`/`dirty` on that path let the reconciling save compute\n // (on-disk \\ removed) ∪ added and silently drop the reintroduced hash, so\n // the peer never saw it again. Set semantics keep this idempotent (no\n // duplicate entries) and the `removed.delete` above preserves remove/add\n // ordering.\n this.hashes.add(hash);\n this.added.add(hash);\n this.dirty = true;\n }\n\n get size(): number {\n return this.hashes.size;\n }\n\n /** Clear all loaded hashes so the next save rewrites the index from scratch. */\n clear(): void {\n if (this.hashes.size > 0) {\n this.hashes.clear();\n }\n // A full clear is always paired with a plain overwrite save() (rebuild);\n // pending per-hash add/remove deltas are subsumed by writing the rebuilt set.\n // Cancel any armed deferred-reconcile retry (PR #2016) so it cannot fire in\n // the clear→rebuild→save window and union the pre-clear on-disk rows back.\n this.added.clear();\n this.removed.clear();\n this.cancelReconcileRetry();\n this.dirty = true;\n }\n\n /** Persist index to disk if changed (plain whole-file overwrite). */\n async save(): Promise<void> {\n if (!this.dirty) return;\n await mkdir(path.dirname(this.filePath), { recursive: true });\n // Snapshot the deltas + overwrite body THIS save publishes BEFORE the write\n // yields the event loop. `writeMaybeEncryptedFile` materializes `serialized`\n // eagerly, then the disk await lets a concurrent same-process add()/remove()\n // land a late delta (PR #2016 thread PRRT_kwDORJXyws6SEBri). Clearing the\n // LIVE added/removed sets afterward — as the previous unconditional\n // clear()+`dirty = false` did — would drop that late hash from the index AND\n // leave no retry, so peers never see it until a corpus rebuild. Consume only\n // what we published; late deltas stay pending. Mirrors saveMergingWithDisk.\n const publishedAdded = new Set<string>(this.added);\n const publishedRemoved = new Set<string>(this.removed);\n const serialized = [...this.hashes].join(\"\\n\") + \"\\n\";\n await writeMaybeEncryptedFile(\n this.filePath,\n serialized,\n this.secureStoreWriteKeyProvider(),\n {},\n this.memoryDir\n );\n // Consume ONLY the deltas this overwrite published; anything that arrived\n // during the awaits above remains pending for the next save.\n for (const h of publishedAdded) this.added.delete(h);\n for (const h of publishedRemoved) this.removed.delete(h);\n // Honest dirty state: true iff late deltas remain unpersisted.\n this.dirty = this.added.size > 0 || this.removed.size > 0;\n // This overwrite is now the on-disk state — re-baseline the freshness\n // fingerprint so our own write is not later mistaken for a peer's (PR #2016).\n await this.captureSyncedFingerprint();\n if (this.dirty) {\n // Late deltas landed mid-save: arm a bounded durable retry so they reach\n // disk even without a further batch save — never a silent in-memory-only\n // hash. The locked reconcile republishes only OUR delta onto the overwrite.\n this.scheduleReconcileRetry();\n } else {\n // Clean overwrite supersedes any pending deferred reconcile work.\n this.cancelReconcileRetry();\n }\n log.debug(`content-hash index: saved ${this.hashes.size} hashes`);\n }\n\n /**\n * Persist the index by RECONCILING with the latest on-disk state under a\n * cross-process lock (issue #1909). Used by the extraction-persist batch save\n * for BOTH append and removal batches, so appends and removals to the same\n * index serialize against each other:\n * final = (on-disk \\ this.removed) ∪ this.added\n * Note it re-applies only OUR local additions (`added`), NOT the loaded\n * snapshot (review round 9 finding 3): seeding from `this.hashes` would\n * resurrect a hash a peer removed on disk while we held a stale snapshot. This\n * preserves a concurrent writer's appended hashes (a blind overwrite would\n * drop them), never resurrects a removed hash, and never loses our additions.\n *\n * Hardening:\n * - Dirty short-circuit (round 7 finding 3): when this instance neither added\n * nor removed anything this run, skip the O(file) read+rewrite entirely.\n * - Cross-process lock (round 7 finding 2): serialize the read→reconcile→write\n * window on a per-file advisory lock. If the lock is NOT acquired (timeout),\n * do NOT publish (round 9 finding 2): keep `dirty` set AND schedule a bounded\n * durable background retry (PR #2016) that keeps re-attempting the locked\n * publish until the deferred additions land — never an unlocked write that\n * could clobber a peer, and never a silent \"batch save complete\" that leaves\n * the addition in this process's memory only.\n */\n async saveMergingWithDisk(): Promise<void> {\n if (!this.dirty) return;\n // The advisory lock file lives beside the index — ensure the dir exists\n // before acquiring it (the index dir may not exist on a first write).\n await mkdir(path.dirname(this.filePath), { recursive: true });\n const publish = async (): Promise<void> => {\n // Snapshot the deltas this publish is responsible for. The read+rewrite\n // below yields the event loop, so a concurrent add()/remove() can land\n // new deltas while we await disk (PR #2016 thread SD7Tj). Consuming the\n // LIVE sets afterward would drop those late deltas AND clear `dirty`,\n // stranding them in no save at all. We consume only what we published;\n // anything that arrived meanwhile stays pending for the next save.\n const publishedAdded = new Set<string>(this.added);\n const publishedRemoved = new Set<string>(this.removed);\n const merged = new Set<string>(publishedAdded);\n try {\n const raw = await readMaybeEncryptedFile(\n this.filePath,\n this.secureStoreKeyProvider(),\n this.memoryDir\n );\n for (const line of raw.split(\"\\n\")) {\n const trimmed = line.trim();\n // Keep prior/concurrent on-disk hashes EXCEPT the ones we removed.\n if (trimmed.length > 0 && !publishedRemoved.has(trimmed)) merged.add(trimmed);\n }\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n // ENOENT → no on-disk index yet; write our additions as-is.\n }\n await mkdir(path.dirname(this.filePath), { recursive: true });\n await writeMaybeEncryptedFile(\n this.filePath,\n [...merged].join(\"\\n\") + \"\\n\",\n this.secureStoreWriteKeyProvider(),\n {},\n this.memoryDir\n );\n // Consume ONLY the deltas we just published; deltas that arrived during\n // the awaits above remain pending.\n for (const h of publishedAdded) this.added.delete(h);\n for (const h of publishedRemoved) this.removed.delete(h);\n // Fold any still-pending deltas onto the reconciled set so the in-memory\n // view stays consistent with what the next save will publish.\n for (const h of this.added) merged.add(h);\n for (const h of this.removed) merged.delete(h);\n this.hashes = merged;\n // Honest dirty state: true iff late deltas remain to be persisted. A\n // subsequent batch save or the shutdown flush drains them.\n this.dirty = this.added.size > 0 || this.removed.size > 0;\n // The reconciled set is now the on-disk state — re-baseline the freshness\n // fingerprint (captured under the held lock) so our own publish is not\n // later mistaken for a peer's advance (PR #2016 review).\n await this.captureSyncedFingerprint();\n };\n await withHeldFileLock(\n `${this.filePath}.lock`,\n {\n staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,\n ...(this.lockOptions.maxWaitMs !== undefined ? { maxWaitMs: this.lockOptions.maxWaitMs } : {}),\n ...(this.lockOptions.pollMs !== undefined ? { pollMs: this.lockOptions.pollMs } : {}),\n },\n async (acquired) => {\n if (!acquired) {\n // Never publish unlocked (round 9 finding 2): keep dirty AND schedule a\n // durable background retry (PR #2016). Relying on an unguaranteed later\n // batch save silently left the addition in this process's memory only;\n // the retry keeps re-attempting the locked publish until the addition\n // lands on disk.\n log.warn(\n `content-hash index: lock not acquired for ${this.filePath}; deferring reconcile save (dirty retained, scheduling durable retry)`,\n );\n this.scheduleReconcileRetry();\n return;\n }\n await publish();\n if (this.dirty) {\n // A concurrent add()/remove() landed during publish's disk awaits, so\n // deltas remain unpersisted (PR #2016 thread SD7Tj). Arm a bounded\n // durable retry so they reach disk even if no further batch save comes\n // — never leave a settled barrier over pending work.\n this.scheduleReconcileRetry();\n } else {\n // Published cleanly: any pending deferred retry is now satisfied.\n this.cancelReconcileRetry();\n }\n },\n );\n log.debug(`content-hash index: reconcile-saved ${this.hashes.size} hashes`);\n }\n\n /**\n * Rebuild-and-publish the index from an authoritative source (the durable\n * corpus) under the SAME per-file cross-process lock the reconciling\n * append/removal saves (`saveMergingWithDisk`) use (issue #1909 / PR #2016).\n * The `populate` callback runs WHILE the lock is held and MUST repopulate this\n * index from the corpus (`clear()` then `addByHash(...)` for every corpus\n * hash); the rebuilt set is then published with a plain overwrite that is now\n * serialized against every locked writer.\n *\n * This closes the finding where the previous unlocked clear→scan→save() could\n * overwrite a peer's newer lock-merged or deferred additions: a locked writer\n * that committed BEFORE the rebuild acquired the lock has its memory `.md` on\n * disk and is re-scanned; one that commits AFTER the rebuild releases\n * reconciles its additions on top of the freshly-published set. No union with\n * the raw on-disk file is performed, so the rebuild keeps its\n * garbage-collection property (orphaned hashes for deleted memories drop).\n *\n * Lock-acquisition failure is explicit and non-destructive: `populate` is NOT\n * run and nothing is written (never an unlocked overwrite). Returns true when\n * the rebuild was published under the lock, false when the lock timed out —\n * the caller keeps the index non-authoritative and retries on next use. Uses\n * the same non-reentrant file lock as the reconcile path, so it can never\n * deadlock with the deferred reconcile-retry: a concurrent locked writer (or a\n * fired retry) simply yields `acquired=false` after the bounded wait.\n */\n async rebuildUnderLock(populate: () => Promise<void>): Promise<boolean> {\n // The advisory lock file lives beside the index — ensure the dir exists\n // before acquiring it (the index dir may not exist on a first rebuild).\n await mkdir(path.dirname(this.filePath), { recursive: true });\n let published = false;\n await withHeldFileLock(\n `${this.filePath}.lock`,\n {\n staleMs: CONTENT_HASH_INDEX_LOCK_STALE_MS,\n ...(this.lockOptions.maxWaitMs !== undefined ? { maxWaitMs: this.lockOptions.maxWaitMs } : {}),\n ...(this.lockOptions.pollMs !== undefined ? { pollMs: this.lockOptions.pollMs } : {}),\n },\n async (acquired) => {\n if (!acquired) {\n // Never publish unlocked: a concurrent locked writer holds the lock,\n // so overwriting now could clobber its addition. Leave the index as-is\n // and let the caller retry the authoritative rebuild on next use.\n log.warn(\n `content-hash index: lock not acquired for ${this.filePath}; deferring authoritative rebuild (index left non-authoritative, retried on next use)`,\n );\n return;\n }\n await populate();\n // Publish under the held lock. save() takes no lock (no re-entrancy) and\n // is a full overwrite that supersedes any pending add/remove deltas.\n await this.save();\n published = true;\n },\n );\n return published;\n }\n\n /**\n * True while a background durable reconcile-save retry is armed (PR #2016).\n * Test/introspection hook.\n */\n get hasPendingReconcileRetry(): boolean {\n return this.reconcileRetryTimer !== null;\n }\n\n /** True while this index has in-memory changes not yet published to disk. */\n get hasPendingChanges(): boolean {\n return this.dirty;\n }\n\n /**\n * Resolve once any armed background reconcile-save retry chain has settled —\n * either it published the deferred additions, or it exhausted its bounded\n * attempts and fell back to the corpus-rebuild safety net. Resolves\n * immediately when nothing is armed. Lets a caller (or a test) await the\n * eventual durability outcome of a lock-timed-out save.\n */\n async whenReconcileRetrySettled(): Promise<void> {\n await (this.reconcileRetryBarrier ?? Promise.resolve());\n }\n\n /**\n * Drive any deferred lock-timeout reconcile save to completion INLINE at a\n * lifecycle boundary (PR #2016 finding 3). The background retry timer is\n * `unref`'d so it never keeps a long-lived daemon alive — but a short-lived\n * writer (a one-shot CLI) can exit before it fires, leaving a durable fact\n * `.md` whose hash never reached `fact-hashes.txt` for peers that already\n * built their in-memory index. `orchestrator.destroy()` calls this so the\n * addition publishes before the process exits; long-lived hosts only reach it\n * at their own shutdown, so their in-flight retries keep running in the\n * background until then. Bounded by the same attempt ceiling as the background\n * retry; a permanently contended lock falls back to the corpus-rebuild-on-\n * restart safety net (the fact `.md` is already durable). No deadlock: each\n * attempt is the same non-reentrant, bounded-wait file lock.\n */\n async flushReconcileRetry(): Promise<void> {\n if (!this.dirty) return;\n const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;\n const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;\n for (let attempt = 0; this.dirty && attempt < maxAttempts; attempt += 1) {\n // Cancel the unref'd background timer — we drive the locked publish inline.\n if (this.reconcileRetryTimer) {\n clearTimeout(this.reconcileRetryTimer);\n this.reconcileRetryTimer = null;\n }\n await this.saveMergingWithDisk();\n if (!this.dirty) break;\n if (attempt < maxAttempts - 1) {\n const wait = Math.min(baseMs * 2 ** attempt, CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);\n await new Promise<void>((resolve) => setTimeout(resolve, wait));\n }\n }\n // Clear any timer the final saveMergingWithDisk armed and settle the barrier\n // so awaiters unblock — the bounded inline drain has done its best.\n if (this.reconcileRetryTimer) {\n clearTimeout(this.reconcileRetryTimer);\n this.reconcileRetryTimer = null;\n }\n this.reconcileRetryAttempts = 0;\n this.settleReconcileRetry();\n }\n\n /**\n * Schedule ONE bounded, exponentially-backed-off background retry of the\n * deferred reconcile save (PR #2016). Reentrant-safe: an already-armed timer\n * short-circuits, so successive timed-out saves never stack duplicate retries.\n * When attempts are exhausted the chain settles without publishing — the\n * durable fact `.md` is on disk and a process restart rebuilds the index from\n * the corpus, so this degrades to that safety net, never a fatal failure.\n */\n private scheduleReconcileRetry(): void {\n if (this.reconcileRetryTimer) return; // one retry in flight — no duplicate/reentrant retries\n const maxAttempts = this.lockOptions.retryMaxAttempts ?? CONTENT_HASH_INDEX_RETRY_MAX_ATTEMPTS;\n if (this.reconcileRetryAttempts >= maxAttempts) {\n log.warn(\n `content-hash index: exhausted ${maxAttempts} deferred reconcile-save retries for ${this.filePath}; ` +\n `${this.added.size} addition(s) remain dirty in-memory (a process restart rebuilds the index from the durable corpus)`,\n );\n this.reconcileRetryAttempts = 0;\n this.settleReconcileRetry();\n return;\n }\n if (!this.reconcileRetryBarrier) {\n this.reconcileRetryBarrier = new Promise<void>((resolve) => {\n this.reconcileRetryResolve = resolve;\n });\n }\n const attempt = this.reconcileRetryAttempts + 1;\n const baseMs = this.lockOptions.retryBaseMs ?? CONTENT_HASH_INDEX_RETRY_BASE_MS;\n const delay = Math.min(baseMs * 2 ** (attempt - 1), CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);\n this.reconcileRetryTimer = setTimeout(() => {\n this.reconcileRetryTimer = null;\n this.reconcileRetryAttempts = attempt;\n void this.saveMergingWithDisk()\n .catch((err) => {\n // A publish-time I/O/encryption error (not a lock timeout) is best-effort:\n // log and let the corpus-rebuild safety net cover it rather than loop.\n log.warn(`content-hash index: deferred reconcile-save retry failed for ${this.filePath}: ${err}`);\n })\n .finally(() => {\n // If the attempt neither published (dirty cleared → cancelReconcileRetry)\n // nor re-armed a further retry, the chain has ended — settle the barrier.\n if (this.dirty && !this.reconcileRetryTimer) this.settleReconcileRetry();\n });\n }, delay);\n this.reconcileRetryTimer.unref?.();\n }\n\n /** Cancel any armed reconcile-save retry and settle the barrier (a publish landed). */\n private cancelReconcileRetry(): void {\n if (this.reconcileRetryTimer) {\n clearTimeout(this.reconcileRetryTimer);\n this.reconcileRetryTimer = null;\n }\n this.reconcileRetryAttempts = 0;\n this.settleReconcileRetry();\n }\n\n /** Resolve and clear the retry barrier if one is outstanding. */\n private settleReconcileRetry(): void {\n const resolve = this.reconcileRetryResolve;\n this.reconcileRetryBarrier = null;\n this.reconcileRetryResolve = null;\n resolve?.();\n }\n\n /** Remove a hash from the index (used when archiving/deleting). */\n remove(content: string): void {\n const hash = ContentHashIndex.computeHash(content);\n // Record the removal (round 8 thread 3) even when the hash is not in our\n // in-memory set — a reconciling save must still drop it from the latest\n // on-disk state. A removal supersedes a pending add. Always mark dirty.\n this.added.delete(hash);\n this.removed.add(hash);\n this.hashes.delete(hash);\n this.dirty = true;\n }\n\n /**\n * Remove a pre-computed SHA-256 hash directly from the index without\n * re-hashing. Use this when the caller already holds the stored hash\n * (e.g. `memory.frontmatter.contentHash`) to avoid the double-hash bug\n * where `remove(hash)` would compute `hash(hash)` and never match the\n * entry.\n */\n removeByHash(hash: string): void {\n this.added.delete(hash);\n this.removed.add(hash);\n this.hashes.delete(hash);\n this.dirty = true;\n }\n\n /**\n * Add a pre-computed SHA-256 hash directly to the index without re-hashing.\n * Use this when the caller already holds the stored hash\n * (e.g. `memory.frontmatter.contentHash`) so that the index records the raw\n * content hash rather than re-hashing the citation-annotated body.\n *\n * @internal Only called from `StorageManager.ensureFactHashIndexAuthoritative`.\n * Not part of the public API — prefer `add(content)` for external callers.\n */\n addByHash(hash: string): void {\n // A re-add supersedes a pending removal of the same hash.\n this.removed.delete(hash);\n // Record OUR durable delta even when the local snapshot already holds the\n // hash (PR #2016 thread PRRT_kwDORJXyws6SEHve). Outside a rebuild\n // (StorageManager.addActiveFactContentHash on reactivation) local\n // membership can be STALE: a peer removed this hash on disk while this\n // instance kept it in memory. Skipping added/dirty on that path let the\n // reconciling save compute (on-disk \\ removed) ∪ added and silently drop\n // the reintroduced hash, so the peer never saw it again. Set semantics keep\n // this idempotent (no duplicate entries) and the removed.delete above\n // preserves remove/add ordering. Mirrors add().\n this.hashes.add(hash);\n this.added.add(hash);\n this.dirty = true;\n }\n\n /** Normalize content (delegates to content-hash.ts for a single source of truth). */\n static normalizeContent(content: string): string {\n return normalizeContent(content);\n }\n\n /** Compute SHA-256 hash (delegates to content-hash.ts for a single source of truth). */\n static computeHash(content: string): string {\n return computeContentHash(content);\n }\n}\n","import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { withHeldFileLock } from \"../utils/serialize-mutations.js\";\nimport type { MemoryFile, MemoryFrontmatter } from \"../types.js\";\nconst TOMBSTONE_CAPTURE_WRITE_LOCK_STALE_MS = 60_000;\nconst CAPTURE_WRITE_LOCK_MAX_ATTEMPTS = 3;\nconst CAPTURE_WRITE_LOCK_RETRY_BASE_MS = 25;\nconst CAPTURE_WRITE_LOCK_BUSY_MESSAGE = \"tombstone-blocked capture write lock remained busy\";\n\nexport function isTombstoneBlockedCaptureWriteLockBusy(error: unknown): boolean {\n return error instanceof Error && error.message === CAPTURE_WRITE_LOCK_BUSY_MESSAGE;\n}\n\nexport function normalizeExplicitCaptureContent(value: string): string {\n return value.toLowerCase().replace(/\\s+/g, \" \").trim();\n}\n\nexport function buildExplicitCaptureDedupKey(\n content: string,\n category: string,\n sourceConnector: string | undefined\n): string {\n const encode = (label: string, value: string): string => `${label} ${value.length} ${value}`;\n return [\n encode(\"category\", category),\n encode(\"connector\", sourceConnector?.trim() ?? \"\"),\n encode(\"content\", normalizeExplicitCaptureContent(content)),\n ].join(\" \");\n}\n\nexport function captureIdentityHash(memory: MemoryFile): string {\n return createHash(\"sha256\")\n .update(buildExplicitCaptureDedupKey(memory.content, memory.frontmatter.category, memory.frontmatter.sourceConnector))\n .digest(\"hex\");\n}\n\nexport type TombstoneBlockedCaptureWriteLockOptions = {\n readonly stateDir: string;\n readonly withHeldFileLock?: typeof withHeldFileLock;\n};\n\nexport class TombstoneBlockedCaptureWriteLock {\n private readonly context = new AsyncLocalStorage<ReadonlySet<string>>();\n\n constructor(private readonly options: TombstoneBlockedCaptureWriteLockOptions) {}\n\n private captureWriteLockPathForHash(identityHash: string): string {\n const filename =\n identityHash.length === 0\n ? \"explicit-capture-write.lock\"\n : `explicit-capture-write-${identityHash}.lock`;\n return path.join(this.options.stateDir, \"tombstone-blocked-capture\", filename);\n }\n\n private async withSingleCaptureWriteLock<T>(lockPath: string, task: () => Promise<T>): Promise<T> {\n await mkdir(path.dirname(lockPath), { recursive: true });\n const retry = Symbol(\"retry\");\n const permanentFailure = Symbol(\"permanent-failure\");\n const runWithHeldFileLock = this.options.withHeldFileLock ?? withHeldFileLock;\n for (let attempt = 0; attempt < CAPTURE_WRITE_LOCK_MAX_ATTEMPTS; attempt += 1) {\n const result = await runWithHeldFileLock<T | typeof retry | typeof permanentFailure>(\n lockPath,\n {\n staleMs: TOMBSTONE_CAPTURE_WRITE_LOCK_STALE_MS,\n maxWaitMs: 1_000,\n pollMs: 25,\n },\n async (acquired, controller) => {\n if (acquired) return await task();\n return controller.failure === \"error\" ? permanentFailure : retry;\n }\n );\n if (result === permanentFailure) {\n throw new Error(\"tombstone-blocked capture write lock acquisition failed\");\n }\n if (result !== retry) return result;\n if (attempt === CAPTURE_WRITE_LOCK_MAX_ATTEMPTS - 1) break;\n const delayState = Promise.withResolvers<void>();\n setTimeout(delayState.resolve, CAPTURE_WRITE_LOCK_RETRY_BASE_MS * 2 ** attempt);\n await delayState.promise;\n }\n throw new Error(CAPTURE_WRITE_LOCK_BUSY_MESSAGE);\n }\n private async withPhysicalCaptureWriteLocks<T>(\n task: () => Promise<T>,\n identityHashes: readonly string[]\n ): Promise<T> {\n const lockPaths = [...new Set(identityHashes.map((hash) => this.captureWriteLockPathForHash(hash)))].sort();\n const acquire = async (index: number): Promise<T> => {\n if (index === lockPaths.length) return await task();\n return await this.withSingleCaptureWriteLock(lockPaths[index], () => acquire(index + 1));\n };\n return await acquire(0);\n }\n\n\n async withCaptureWriteLock<T>(\n task: () => Promise<T>,\n identity?: string | readonly string[]\n ): Promise<T> {\n const identities =\n Array.isArray(identity) && identity.length > 0 ? identity : [typeof identity === \"string\" ? identity : \"\"];\n return await this.withCaptureWriteLocks(task, identities, []);\n }\n\n async withCaptureWriteLockHashes<T>(\n task: () => Promise<T>,\n identityHashes: readonly string[]\n ): Promise<T> {\n return await this.withCaptureWriteLocks(task, [], identityHashes);\n }\n\n async withCaptureWriteLockAndHashes<T>(\n task: () => Promise<T>,\n identity: string | readonly string[] | undefined,\n identityHashes: readonly string[]\n ): Promise<T> {\n const identities =\n Array.isArray(identity) && identity.length > 0 ? identity : [typeof identity === \"string\" ? identity : \"\"];\n return await this.withCaptureWriteLocks(task, identities, identityHashes);\n }\n\n private async withCaptureWriteLocks<T>(\n task: () => Promise<T>,\n identities: readonly string[],\n identityHashes: readonly string[]\n ): Promise<T> {\n const current = this.context.getStore();\n const hashToken = (key: string): string =>\n `\\u0000${key.length === 0 ? \"\" : createHash(\"sha256\").update(key).digest(\"hex\")}`;\n const identityHash = (key: string): string =>\n key.length === 0 ? \"\" : createHash(\"sha256\").update(key).digest(\"hex\");\n const identityKeys = [...new Set(identities)];\n const hashes = [...new Set(identityHashes)];\n const missingIdentityHashes = identityKeys\n .filter((key) => !current || (!current.has(key) && !current.has(hashToken(key))))\n .map(identityHash);\n const missingHashes = hashes.filter((hash) => !current || !current.has(`\\u0000${hash}`));\n const physicalMissing = [...new Set([...missingIdentityHashes, ...missingHashes])];\n if (current && physicalMissing.length > 0) {\n const heldLockPaths = [...current]\n .filter((token) => token.startsWith(\"\\u0000\"))\n .map((token) => this.captureWriteLockPathForHash(token.slice(1)));\n const requestedLockPaths = physicalMissing.map((hash) => this.captureWriteLockPathForHash(hash));\n if (heldLockPaths.some((held) => requestedLockPaths.some((requested) => requested < held))) {\n throw new Error(CAPTURE_WRITE_LOCK_BUSY_MESSAGE);\n }\n }\n const next = new Set(current);\n for (const key of identityKeys) {\n next.add(key);\n next.add(hashToken(key));\n }\n for (const hash of hashes) next.add(`\\u0000${hash}`);\n const run = () => this.context.run(next, task);\n if (physicalMissing.length === 0) return await run();\n return await this.withPhysicalCaptureWriteLocks(run, physicalMissing);\n }\n}\n\n\nexport type TombstoneBlockedMutationHost = {\n readCurrent: () => Promise<MemoryFile | null>;\n isBlocked: (memory: MemoryFile | null) => boolean;\n isQueuedReview: (memory: MemoryFile | null) => boolean;\n memoryIdentity: (memory: MemoryFile) => string;\n prepareWrite: () => Promise<string>;\n commitWrite: (marker: string) => Promise<void>;\n discardWrite: (marker: string) => Promise<void>;\n markUntrusted: () => void;\n writeStorageSecureFile: (pathname: string, fileContent: string) => Promise<void>;\n withCaptureWriteLock: (task: () => Promise<void>, identity: string | readonly string[]) => Promise<void>;\n logWarning: (message: string) => void;\n};\n\nexport type TombstoneBlockedMutation = {\n blocked: boolean;\n pathname: string;\n fileContent: string;\n identity: string | readonly string[];\n updateIndex: (rebuildMarker?: string, current?: MemoryFile | null) => Promise<void>;\n beforeIndexUpdate?: () => Promise<void>;\n coordinate?: boolean;\n};\n\nexport async function runTombstoneBlockedMutation(\n host: TombstoneBlockedMutationHost,\n mutation: TombstoneBlockedMutation,\n): Promise<void> {\n let lockIdentity: string | readonly string[] = mutation.identity;\n let mustLock = mutation.blocked || mutation.coordinate === true;\n for (;;) {\n let retryIdentity: string | undefined;\n const mutate = async (): Promise<void> => {\n const current = await host.readCurrent();\n const currentBlocked = host.isBlocked(current);\n const currentQueuedReview = host.isQueuedReview(current);\n if (current !== null && (currentBlocked || currentQueuedReview)) {\n const currentIdentity = host.memoryIdentity(current);\n const heldIdentities = Array.isArray(lockIdentity) ? lockIdentity : [lockIdentity];\n if (!heldIdentities.includes(currentIdentity)) {\n retryIdentity = currentIdentity;\n return;\n }\n }\n const rebuildMarker = mutation.blocked || currentBlocked ? await host.prepareWrite() : undefined;\n try {\n await host.writeStorageSecureFile(mutation.pathname, mutation.fileContent);\n } catch (err) {\n if (rebuildMarker) {\n try {\n await host.discardWrite(rebuildMarker);\n } catch (cleanupError) {\n host.markUntrusted();\n host.logWarning(`storage.tombstoneBlocked failed to clear write marker: ${cleanupError}`);\n }\n }\n throw err;\n }\n if (rebuildMarker) {\n try {\n await host.commitWrite(rebuildMarker);\n } catch (err) {\n host.markUntrusted();\n host.logWarning(`storage.tombstoneBlocked committed write marker failed: ${err}`);\n }\n }\n if (rebuildMarker) await mutation.beforeIndexUpdate?.();\n await mutation.updateIndex(rebuildMarker, currentBlocked && current !== null ? current : undefined);\n };\n if (mustLock) {\n await host.withCaptureWriteLock(mutate, lockIdentity);\n } else {\n await mutate();\n }\n if (retryIdentity === undefined) return;\n const identities = Array.isArray(lockIdentity)\n ? [...lockIdentity, retryIdentity]\n : [lockIdentity, retryIdentity];\n lockIdentity = [...new Set(identities)];\n mustLock = true;\n }\n}\n\nexport function tombstoneBlocked(frontmatter: MemoryFrontmatter): boolean {\n return frontmatter.status === \"pending_review\" && Boolean(frontmatter.blockedBy);\n}\n\nexport function isQueuedReviewFrontmatter(frontmatter: MemoryFrontmatter): boolean {\n return frontmatter.status === \"pending_review\" && (frontmatter.tags ?? []).includes(\"queued-review\");\n}\n\nexport function isQueuedReviewMemory(memory: MemoryFile | null): memory is MemoryFile {\n return memory !== null && isQueuedReviewFrontmatter(memory.frontmatter);\n}\n\nexport type TombstoneBlockedChunkMutation = {\n blocked: boolean;\n id: string;\n identity: string;\n findDuplicate: () => Promise<MemoryFile | null>;\n persistMemory: () => Promise<void>;\n afterWrite: () => Promise<void>;\n withCaptureWriteLock: (task: () => Promise<string>, identity: string) => Promise<string>;\n};\n\nexport async function runTombstoneBlockedChunkMutation(\n mutation: TombstoneBlockedChunkMutation,\n): Promise<string> {\n const persist = async (): Promise<string> => {\n if (mutation.blocked) {\n const duplicate = await mutation.findDuplicate();\n if (duplicate) return duplicate.frontmatter.id;\n }\n await mutation.persistMemory();\n await mutation.afterWrite();\n return mutation.id;\n };\n return mutation.blocked\n ? await mutation.withCaptureWriteLock(persist, mutation.identity)\n : await persist();\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { unlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { isDeepStrictEqual } from \"node:util\";\nimport { log } from \"../logger.js\";\nimport type { MemoryFile, MemoryFrontmatter } from \"../types.js\";\nimport { markProjectedMemoryPathInvalid } from \"../memory-projection-store.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport {\n pathMayCarryEntityRefs,\n requestEntityCanonicalIdReconcile,\n} from \"./entity-canonical-id-references.js\";\nimport {\n readMaybeEncryptedFileFromChunks,\n writeMaybeEncryptedFileFromChunks,\n} from \"../secure-store/secure-fs.js\";\nimport {\n buildExplicitCaptureDedupKey,\n captureIdentityHash,\n tombstoneBlocked,\n isQueuedReviewFrontmatter,\n isQueuedReviewMemory,\n runTombstoneBlockedChunkMutation,\n runTombstoneBlockedMutation,\n type TombstoneBlockedMutationHost,\n} from \"./tombstone-blocked-capture-mutation.js\";\nimport { TombstoneBlockedCaptureIndex } from \"./tombstone-blocked-capture-index.js\";\nimport type { TombstoneBlockedCaptureIndexOptions } from \"./tombstone-blocked-capture-index.js\";\n\nconst OFFLINE_SYNC_BUFFER_LIMIT_BYTES = 1_048_576;\nconst OFFLINE_SYNC_STAGE_READ_BYTES = 64 * 1024;\nconst OFFLINE_SYNC_FRONTMATTER_DELIMITER = Buffer.from(\"\\n---\\n\", \"utf8\");\n\ntype StreamedOfflineSyncIdentity = {\n identityHash: string;\n};\n\ntype PreparedOfflineSyncChunks = {\n after: MemoryFile | null;\n chunks: AsyncIterable<Buffer>;\n stagePath?: string;\n streamedIdentity?: StreamedOfflineSyncIdentity;\n};\n\nfunction createExplicitContentNormalizer(onChunk: (chunk: string) => void): {\n push: (text: string) => void;\n finish: () => void;\n} {\n let started = false;\n let pendingSpace = false;\n let output = \"\";\n const flush = () => {\n if (output.length > 0) {\n onChunk(output);\n output = \"\";\n }\n };\n return {\n push(text) {\n for (const character of text.toLowerCase()) {\n if (/\\s/u.test(character)) {\n if (started) pendingSpace = true;\n continue;\n }\n if (pendingSpace) {\n output += \" \";\n pendingSpace = false;\n }\n output += character;\n started = true;\n if (output.length >= OFFLINE_SYNC_STAGE_READ_BYTES) flush();\n }\n },\n finish: flush,\n };\n}\n\nasync function forEachStagedTextChunk(\n stagePath: string,\n offset: number,\n onText: (text: string) => void,\n key: Buffer | null,\n memoryDir: string\n): Promise<void> {\n const decoder = new TextDecoder(\"utf-8\");\n let remaining = offset;\n for await (const chunk of readMaybeEncryptedFileFromChunks(stagePath, key, memoryDir)) {\n const textChunk =\n remaining >= chunk.length\n ? null\n : chunk.subarray(remaining);\n remaining = Math.max(0, remaining - chunk.length);\n if (textChunk === null || textChunk.length === 0) continue;\n const text = decoder.decode(textChunk, { stream: true });\n if (text.length > 0) onText(text);\n }\n const finalText = decoder.decode();\n if (finalText.length > 0) onText(finalText);\n}\n\nasync function findStagedBodyOffset(\n stagePath: string,\n key: Buffer | null,\n memoryDir: string\n): Promise<number | null> {\n let scannedBytes = 0;\n let tail = Buffer.alloc(0);\n for await (const chunk of readMaybeEncryptedFileFromChunks(stagePath, key, memoryDir)) {\n const window = tail.length > 0 ? Buffer.concat([tail, chunk]) : chunk;\n const windowStart = scannedBytes - tail.length;\n for (let searchFrom = 0; ; ) {\n const delimiterStart = window.indexOf(OFFLINE_SYNC_FRONTMATTER_DELIMITER, searchFrom);\n if (delimiterStart < 0) break;\n if (windowStart + delimiterStart >= 4) {\n return windowStart + delimiterStart + OFFLINE_SYNC_FRONTMATTER_DELIMITER.length;\n }\n searchFrom = delimiterStart + 1;\n }\n scannedBytes += chunk.length;\n const tailLength = Math.min(OFFLINE_SYNC_FRONTMATTER_DELIMITER.length - 1, window.length);\n tail = Buffer.from(window.subarray(window.length - tailLength));\n }\n return null;\n}\n\nasync function readStagedPrefix(\n stagePath: string,\n byteLimit: number,\n key: Buffer | null,\n memoryDir: string\n): Promise<Buffer> {\n const chunks: Buffer[] = [];\n let bytesRead = 0;\n for await (const chunk of readMaybeEncryptedFileFromChunks(stagePath, key, memoryDir)) {\n const length = Math.min(chunk.length, byteLimit - bytesRead);\n if (length > 0) chunks.push(chunk.subarray(0, length));\n bytesRead += length;\n if (bytesRead >= byteLimit) break;\n }\n return Buffer.concat(chunks, bytesRead);\n}\n\nexport type OfflineSyncMemoryParser = (filePath: string, content: Buffer) => MemoryFile | null;\n\nexport function parseTombstoneBlockedOfflineSyncMemory(\n filePath: string,\n content: Buffer,\n memoryDir: string,\n parseFrontmatter: (raw: string) => { frontmatter: MemoryFrontmatter; content: string } | null,\n normalizeFrontmatterForPath: (frontmatter: MemoryFrontmatter, pathRel: string, content?: string) => MemoryFrontmatter,\n toMemoryPathRel: (baseDir: string, filePath: string) => string\n): MemoryFile | null {\n const parsed = parseFrontmatter(content.toString(\"utf8\"));\n if (!parsed) return null;\n return {\n path: filePath,\n frontmatter: normalizeFrontmatterForPath(parsed.frontmatter, toMemoryPathRel(memoryDir, filePath), parsed.content),\n content: parsed.content,\n };\n}\n\nexport abstract class TombstoneBlockedCaptureIndexHost {\n private tombstoneBlockedCaptureIndex: TombstoneBlockedCaptureIndex | null = null;\n protected abstract tombstoneBlockedCaptureIndexOptions(): TombstoneBlockedCaptureIndexOptions;\n protected abstract writeStorageSecureFile(\n filePath: string,\n content: string | Buffer,\n forceEncrypt?: boolean\n ): Promise<void>;\n protected abstract assertManagedStoragePath(filePath: string, method: string): string;\n protected abstract notifyCatalogWriteForPath(filePath: string): void;\n protected abstract readMemoryByPath(filePath: string): Promise<MemoryFile | null>;\n protected abstract invalidateAllMemoriesCache(): void;\n protected abstract invalidateKnowledgeIndexCache(): void;\n protected abstract invalidateColdMemoriesCache(): void;\n protected abstract bumpArtifactWriteVersion(): number;\n protected abstract bumpMemoryStatusVersion(): void;\n protected abstract bumpMemoryCorpusVersion(): void;\n protected abstract markFactHashIndexNotAuthoritative(): void;\n\n private async writeStorageSecureFileChunks(filePath: string, chunks: AsyncIterable<Buffer>): Promise<void> {\n const options = this.tombstoneBlockedCaptureIndexOptions();\n await writeMaybeEncryptedFileFromChunks(\n filePath,\n chunks,\n options.secureStoreWriteKeyProvider(),\n {},\n options.memoryDir\n );\n this.notifyCatalogWriteForPath(filePath);\n }\n\n protected getTombstoneBlockedCaptureIndex(): TombstoneBlockedCaptureIndex {\n if (this.tombstoneBlockedCaptureIndex === null) {\n this.tombstoneBlockedCaptureIndex = new TombstoneBlockedCaptureIndex(this.tombstoneBlockedCaptureIndexOptions());\n }\n return this.tombstoneBlockedCaptureIndex;\n }\n async withTombstoneBlockedCaptureWriteLock<T>(\n task: () => Promise<T>,\n identity?: string | readonly string[]\n ): Promise<T> {\n return await this.getTombstoneBlockedCaptureIndex().withCaptureWriteLock(task, identity);\n }\n\n protected async withTombstoneBlockedCaptureWriteLockAndHashes<T>(\n task: () => Promise<T>,\n identity: string | readonly string[] | undefined,\n identityHashes: readonly string[]\n ): Promise<T> {\n return await this.getTombstoneBlockedCaptureIndex().withCaptureWriteLockAndHashes(task, identity, identityHashes);\n }\n\n private async writeTombstoneBlockedMutation(\n blocked: boolean,\n pathname: string,\n fileContent: string,\n identity: string | readonly string[],\n updateIndex: (rebuildMarker?: string, current?: MemoryFile | null) => Promise<void>,\n beforeIndexUpdate?: () => Promise<void>,\n coordinate = false\n ): Promise<void> {\n const host: TombstoneBlockedMutationHost = {\n readCurrent: () => this.readMemoryByPath(pathname),\n isBlocked: (memory) => this.isTombstoneBlockedMemory(memory),\n isQueuedReview: (memory) => isQueuedReviewMemory(memory),\n memoryIdentity: (memory) => this.offlineSyncMemoryIdentity(memory),\n prepareWrite: () => this.getTombstoneBlockedCaptureIndex().prepareWrite(),\n commitWrite: (marker) => this.getTombstoneBlockedCaptureIndex().commitWrite(marker),\n discardWrite: (marker) => this.getTombstoneBlockedCaptureIndex().discardWrite(marker),\n markUntrusted: () => this.getTombstoneBlockedCaptureIndex().markUntrusted(),\n writeStorageSecureFile: (target, content) => this.writeStorageSecureFile(target, content),\n withCaptureWriteLock: (task, lockIdentity) =>\n this.withTombstoneBlockedCaptureWriteLock(task, lockIdentity),\n logWarning: (message) => log.warn(message),\n };\n await runTombstoneBlockedMutation(host, {\n blocked,\n pathname,\n fileContent,\n identity,\n updateIndex,\n beforeIndexUpdate,\n coordinate,\n });\n }\n\n protected async writeTombstoneBlockedMemory(\n pathname: string,\n fileContent: string,\n frontmatter: MemoryFrontmatter,\n content: string,\n beforeIndexUpdate?: () => Promise<void>\n ): Promise<void> {\n await this.writeTombstoneBlockedMutation(\n tombstoneBlocked(frontmatter),\n pathname,\n fileContent,\n buildExplicitCaptureDedupKey(content, frontmatter.category, frontmatter.sourceConnector),\n (rebuildMarker) =>\n this.getTombstoneBlockedCaptureIndex().addWrittenMemory(pathname, frontmatter, content, rebuildMarker),\n beforeIndexUpdate\n );\n }\n\n protected async writeTombstoneBlockedChunk(\n pathname: string,\n fileContent: string,\n frontmatter: MemoryFrontmatter,\n content: string,\n findDuplicate: () => Promise<MemoryFile | null>,\n afterWrite: () => Promise<void>\n ): Promise<string> {\n return await runTombstoneBlockedChunkMutation({\n blocked: tombstoneBlocked(frontmatter),\n id: frontmatter.id,\n identity: buildExplicitCaptureDedupKey(content, frontmatter.category, frontmatter.sourceConnector),\n findDuplicate,\n persistMemory: () => this.writeTombstoneBlockedMemory(pathname, fileContent, frontmatter, content),\n afterWrite,\n withCaptureWriteLock: (task, identity) => this.withTombstoneBlockedCaptureWriteLock(task, identity),\n });\n }\n\n protected async writeTombstoneBlockedUpdate(\n before: MemoryFile,\n fileContent: string,\n frontmatter: MemoryFrontmatter,\n content: string,\n beforeIndexUpdate?: () => Promise<void>\n ): Promise<void> {\n await this.writeTombstoneBlockedMutation(\n tombstoneBlocked(before.frontmatter) || tombstoneBlocked(frontmatter),\n before.path,\n fileContent,\n [\n ...(tombstoneBlocked(before.frontmatter)\n ? [\n buildExplicitCaptureDedupKey(\n before.content,\n before.frontmatter.category,\n before.frontmatter.sourceConnector\n ),\n ]\n : []),\n ...(tombstoneBlocked(frontmatter)\n ? [buildExplicitCaptureDedupKey(content, frontmatter.category, frontmatter.sourceConnector)]\n : []),\n ...(isQueuedReviewMemory(before)\n ? [\n buildExplicitCaptureDedupKey(\n before.content,\n before.frontmatter.category,\n before.frontmatter.sourceConnector\n ),\n ]\n : []),\n ...(isQueuedReviewFrontmatter(frontmatter)\n ? [buildExplicitCaptureDedupKey(content, frontmatter.category, frontmatter.sourceConnector)]\n : []),\n ],\n (rebuildMarker, current) =>\n this.getTombstoneBlockedCaptureIndex().syncUpdatedMemory(\n current ?? before,\n frontmatter,\n content,\n rebuildMarker\n ),\n beforeIndexUpdate,\n isQueuedReviewMemory(before) || isQueuedReviewFrontmatter(frontmatter)\n );\n }\n\n protected async writeTombstoneBlockedFrontmatter(\n before: MemoryFile,\n fileContent: string,\n frontmatter: MemoryFrontmatter,\n beforeIndexUpdate?: () => Promise<void>\n ): Promise<void> {\n await this.writeTombstoneBlockedMutation(\n tombstoneBlocked(before.frontmatter) || tombstoneBlocked(frontmatter),\n before.path,\n fileContent,\n [\n ...(tombstoneBlocked(before.frontmatter)\n ? [\n buildExplicitCaptureDedupKey(\n before.content,\n before.frontmatter.category,\n before.frontmatter.sourceConnector\n ),\n ]\n : []),\n ...(tombstoneBlocked(frontmatter)\n ? [buildExplicitCaptureDedupKey(before.content, frontmatter.category, frontmatter.sourceConnector)]\n : []),\n ...(isQueuedReviewMemory(before)\n ? [\n buildExplicitCaptureDedupKey(\n before.content,\n before.frontmatter.category,\n before.frontmatter.sourceConnector\n ),\n ]\n : []),\n ...(isQueuedReviewFrontmatter(frontmatter)\n ? [buildExplicitCaptureDedupKey(before.content, frontmatter.category, frontmatter.sourceConnector)]\n : []),\n ],\n (rebuildMarker, current) =>\n this.getTombstoneBlockedCaptureIndex().syncUpdatedFrontmatter(\n current ?? before,\n frontmatter,\n rebuildMarker\n ),\n beforeIndexUpdate,\n isQueuedReviewMemory(before) || isQueuedReviewFrontmatter(frontmatter)\n );\n }\n\n private isTombstoneBlockedMemory(memory: MemoryFile | null): memory is MemoryFile {\n return memory !== null && memory.frontmatter.status === \"pending_review\" && Boolean(memory.frontmatter.blockedBy);\n }\n\n private offlineSyncMemoryIdentity(memory: MemoryFile): string {\n return buildExplicitCaptureDedupKey(\n memory.content,\n memory.frontmatter.category,\n memory.frontmatter.sourceConnector\n );\n }\n private async isDuplicateTombstoneBlockedOfflineSync(\n target: string,\n incoming: MemoryFile,\n streamedIdentity?: StreamedOfflineSyncIdentity\n ): Promise<boolean> {\n const before = await this.readMemoryByPath(target);\n const duplicate = streamedIdentity\n ? true\n : await this.getTombstoneBlockedCaptureIndex().has(\n incoming.content,\n incoming.frontmatter.category,\n incoming.frontmatter.sourceConnector\n );\n if (!duplicate) return false;\n const incomingIdentity = streamedIdentity?.identityHash ?? this.offlineSyncMemoryIdentity(incoming);\n const options = this.tombstoneBlockedCaptureIndexOptions();\n const existing = [...(await options.readAllMemories()), ...(await options.readAllColdMemories())];\n const exactMatch = existing.some(\n (memory) =>\n this.isTombstoneBlockedMemory(memory) &&\n (streamedIdentity ? captureIdentityHash(memory) : this.offlineSyncMemoryIdentity(memory)) === incomingIdentity\n );\n if (!exactMatch) return false;\n if (before === null) return true;\n if (!this.isTombstoneBlockedMemory(before)) return false;\n const beforeIdentity = streamedIdentity ? captureIdentityHash(before) : this.offlineSyncMemoryIdentity(before);\n if (beforeIdentity !== incomingIdentity) return false;\n return streamedIdentity\n ? isDeepStrictEqual(before.frontmatter, incoming.frontmatter)\n : before.content === incoming.content && isDeepStrictEqual(before.frontmatter, incoming.frontmatter);\n }\n\n private async invalidateAfterOfflineSyncMutation(filePath: string, ownedMarker?: string): Promise<void> {\n this.invalidateAllMemoriesCache();\n this.invalidateKnowledgeIndexCache();\n this.markFactHashIndexNotAuthoritative();\n if (filePath.includes(`${path.sep}cold${path.sep}`)) {\n this.invalidateColdMemoriesCache();\n }\n await this.rebuildTombstoneBlockedCaptureAfterInvalidationForPath(filePath, ownedMarker);\n if (filePath.includes(`${path.sep}artifacts${path.sep}`)) {\n this.bumpArtifactWriteVersion();\n }\n this.bumpMemoryStatusVersion();\n }\n\n protected async runTombstoneBlockedArchive(\n memory: MemoryFile,\n task: (current: MemoryFile, markDurable: () => void) => Promise<string | null>\n ): Promise<string | null> {\n if (!this.isTombstoneBlockedMemory(memory) && !isQueuedReviewMemory(memory)) {\n return await task(memory, () => {});\n }\n let archivedPath: string | null = null;\n const archived = await this.runTombstoneBlockedInvalidation(\n memory,\n async (current, rebuildMarker, markDurable) => {\n let archiveDurable = false;\n const markArchiveDurable = () => {\n archiveDurable = true;\n markDurable();\n };\n archivedPath = await task(current, markArchiveDurable);\n if (rebuildMarker !== undefined && (archivedPath !== null || archiveDurable)) {\n await this.rebuildTombstoneBlockedCaptureAfterInvalidation(rebuildMarker);\n } else if (rebuildMarker !== undefined) {\n const index = this.getTombstoneBlockedCaptureIndex();\n try { await index.discardWrite(rebuildMarker); } catch { index.markUntrusted(); }\n }\n return archivedPath !== null;\n }\n );\n return archived ? archivedPath : null;\n }\n\n protected async runTombstoneBlockedInvalidation(\n memory: MemoryFile,\n task: (\n current: MemoryFile,\n rebuildMarker: string | undefined,\n markDurable: () => void\n ) => Promise<boolean>,\n propagateErrors = false,\n coordinate = false\n ): Promise<boolean> {\n let lockIdentity =\n coordinate || this.isTombstoneBlockedMemory(memory) || isQueuedReviewMemory(memory)\n ? this.offlineSyncMemoryIdentity(memory)\n : undefined;\n for (;;) {\n const attempt = async () => {\n const options = this.tombstoneBlockedCaptureIndexOptions();\n const current =\n (await this.readMemoryByPath(memory.path)) ??\n (await options.readAllMemories()).find((candidate) => candidate.frontmatter.id === memory.frontmatter.id) ??\n (await options.readAllColdMemories()).find((candidate) => candidate.frontmatter.id === memory.frontmatter.id);\n if (!current) return { result: false };\n const blocked = this.isTombstoneBlockedMemory(current);\n const queuedReview = isQueuedReviewMemory(current);\n if (blocked || queuedReview) {\n const currentIdentity = this.offlineSyncMemoryIdentity(current);\n if (lockIdentity !== currentIdentity) return { retryIdentity: currentIdentity };\n }\n const blockedIndex = blocked ? this.getTombstoneBlockedCaptureIndex() : null;\n let rebuildMarker: string | undefined;\n let durable = false;\n try {\n if (blockedIndex) rebuildMarker = await blockedIndex.prepareWrite();\n const result = await task(current, rebuildMarker, () => {\n durable = true;\n });\n if (!result && rebuildMarker && !durable && blockedIndex) {\n try {\n await blockedIndex.discardWrite(rebuildMarker);\n } catch {\n blockedIndex.markUntrusted();\n }\n }\n return { result };\n } catch (error) {\n if (rebuildMarker && !durable && blockedIndex) {\n try {\n await blockedIndex.discardWrite(rebuildMarker);\n } catch {\n blockedIndex.markUntrusted();\n }\n }\n if (propagateErrors) throw error;\n return { result: false };\n }\n };\n const result =\n lockIdentity === undefined\n ? await attempt()\n : await this.withTombstoneBlockedCaptureWriteLock(attempt, lockIdentity);\n if (result.retryIdentity !== undefined) {\n lockIdentity = result.retryIdentity;\n continue;\n }\n return result.result;\n }\n }\n async deleteMemoryForMaintenance(\n memory: MemoryFile,\n shouldDelete: (current: MemoryFile) => boolean = () => true\n ): Promise<MemoryFile | null> {\n let deleted: MemoryFile | null = null;\n const removed = await this.runTombstoneBlockedInvalidation(\n memory,\n async (current, rebuildMarker, markDurable) => {\n if (!shouldDelete(current)) return false;\n await unlink(current.path);\n markDurable();\n deleted = current;\n const memoryDir = this.tombstoneBlockedCaptureIndexOptions().memoryDir;\n markProjectedMemoryPathInvalid(memoryDir, current.frontmatter.id);\n this.invalidateAllMemoriesCache();\n if (current.path.includes(`${path.sep}cold${path.sep}`)) {\n this.invalidateColdMemoriesCache();\n }\n await this.rebuildTombstoneBlockedCaptureAfterInvalidation(rebuildMarker);\n this.bumpMemoryCorpusVersion();\n this.bumpMemoryStatusVersion();\n return true;\n },\n true,\n true\n );\n return removed ? deleted : null;\n }\n\n protected async runTombstoneBlockedOfflineSyncMutation(\n target: string,\n after: MemoryFile | null,\n write: () => Promise<void>,\n coordinate = false,\n streamedIdentity?: StreamedOfflineSyncIdentity\n ): Promise<void> {\n for (;;) {\n const before = await this.readMemoryByPath(target);\n const targetIdentity = this.isTombstoneBlockedMemory(before)\n ? this.offlineSyncMemoryIdentity(before)\n : undefined;\n const blocked = coordinate || targetIdentity !== undefined || this.isTombstoneBlockedMemory(after);\n const identities = [\n ...(targetIdentity === undefined ? [] : [targetIdentity]),\n ...(!streamedIdentity && this.isTombstoneBlockedMemory(after)\n ? [this.offlineSyncMemoryIdentity(after)]\n : []),\n ...(coordinate ? [target] : []),\n ...(coordinate && after === null && streamedIdentity === undefined ? [\"\"] : []),\n ];\n let retryIdentity: string | undefined;\n const mutate = async (): Promise<void> => {\n const current = await this.readMemoryByPath(target);\n if (this.isTombstoneBlockedMemory(current)) {\n const currentIdentity = this.offlineSyncMemoryIdentity(current);\n if (currentIdentity !== targetIdentity) {\n retryIdentity = currentIdentity;\n return;\n }\n }\n if (\n this.isTombstoneBlockedMemory(after) &&\n (await this.isDuplicateTombstoneBlockedOfflineSync(target, after, streamedIdentity))\n ) {\n return;\n }\n const marker = blocked ? await this.getTombstoneBlockedCaptureIndex().prepareWrite() : undefined;\n let durable = false;\n try {\n await write();\n durable = true;\n if (marker) {\n try {\n await this.getTombstoneBlockedCaptureIndex().commitWrite(marker);\n } catch (err) {\n this.getTombstoneBlockedCaptureIndex().markUntrusted();\n log.warn(`storage.offlineSyncFile committed write marker failed: ${err}`);\n }\n }\n await this.invalidateAfterOfflineSyncMutation(target, marker);\n } catch (err) {\n if (marker && !durable) {\n try {\n await this.getTombstoneBlockedCaptureIndex().discardWrite(marker);\n } catch (cleanupError) {\n this.getTombstoneBlockedCaptureIndex().markUntrusted();\n log.warn(`storage.offlineSyncFile failed to clear write marker: ${cleanupError}`);\n }\n }\n throw err;\n }\n };\n if (!blocked) {\n await mutate();\n } else {\n if (streamedIdentity) {\n await this.withTombstoneBlockedCaptureWriteLockAndHashes(\n mutate,\n identities,\n [streamedIdentity.identityHash]\n );\n } else {\n await this.withTombstoneBlockedCaptureWriteLock(mutate, identities);\n }\n }\n if (retryIdentity !== undefined) continue;\n return;\n }\n }\n\n protected async writeTombstoneBlockedOfflineSyncFile(target: string, content: Buffer): Promise<void> {\n await this.runTombstoneBlockedOfflineSyncMutation(\n target,\n this.tombstoneBlockedCaptureIndexOptions().parseMemory?.(target, content) ?? null,\n () => this.writeStorageSecureFile(target, content)\n );\n }\n\n private async prepareTombstoneBlockedOfflineSyncChunks(\n target: string,\n chunks: AsyncIterable<Buffer>\n ): Promise<PreparedOfflineSyncChunks> {\n const parseMemory = this.tombstoneBlockedCaptureIndexOptions().parseMemory;\n if (!parseMemory) return { after: null, chunks };\n\n const iterator = chunks[Symbol.asyncIterator]();\n const buffered: Buffer[] = [];\n let bufferedBytes = 0;\n let firstOverflow: Buffer | undefined;\n for (;;) {\n const next = await iterator.next();\n if (next.done) break;\n if (bufferedBytes + next.value.length > OFFLINE_SYNC_BUFFER_LIMIT_BYTES) {\n firstOverflow = next.value;\n break;\n }\n bufferedBytes += next.value.length;\n buffered.push(next.value);\n }\n const overflow = firstOverflow;\n if (overflow === undefined) {\n let after: MemoryFile | null = null;\n try {\n after = parseMemory(target, Buffer.concat(buffered));\n } catch {\n after = null;\n }\n const replay = (async function* (): AsyncIterable<Buffer> {\n for (const chunk of buffered) yield chunk;\n })();\n return { after, chunks: replay };\n }\n\n const options = this.tombstoneBlockedCaptureIndexOptions();\n const stagePath = path.join(\n options.stateDir,\n \"tombstone-blocked-capture\",\n \"offline-sync-staging\",\n `${randomUUID()}.stage`\n );\n const stagedChunks = (async function* (): AsyncIterable<Buffer> {\n for (const chunk of buffered) yield chunk;\n yield overflow;\n for (;;) {\n const next = await iterator.next();\n if (next.done) break;\n yield next.value;\n }\n })();\n try {\n await writeMaybeEncryptedFileFromChunks(\n stagePath,\n stagedChunks,\n options.secureStoreWriteKeyProvider(),\n { atomic: false },\n options.memoryDir\n );\n return await this.describeStagedOfflineSyncChunks(target, stagePath, parseMemory);\n } catch (err) {\n await unlink(stagePath).catch(() => {});\n throw err;\n }\n }\n\n private async describeStagedOfflineSyncChunks(\n target: string,\n stagePath: string,\n parseMemory: OfflineSyncMemoryParser\n ): Promise<PreparedOfflineSyncChunks> {\n const options = this.tombstoneBlockedCaptureIndexOptions();\n const key = options.secureStoreKeyProvider();\n const bodyOffset = await findStagedBodyOffset(stagePath, key, options.memoryDir);\n if (bodyOffset === null) {\n return { after: null, chunks: this.readStagedOfflineSyncChunks(stagePath), stagePath };\n }\n const prefix = await readStagedPrefix(stagePath, bodyOffset, key, options.memoryDir);\n let after: MemoryFile | null = null;\n try {\n after = parseMemory(target, prefix.subarray(0, bodyOffset));\n } catch {\n after = null;\n }\n if (after === null) {\n return { after: null, chunks: this.readStagedOfflineSyncChunks(stagePath), stagePath };\n }\n const streamedIdentity = await this.computeStagedOfflineSyncIdentity(stagePath, bodyOffset, after);\n return {\n after,\n chunks: this.readStagedOfflineSyncChunks(stagePath),\n stagePath,\n streamedIdentity,\n };\n }\n\n private async computeStagedOfflineSyncIdentity(\n stagePath: string,\n bodyOffset: number,\n after: MemoryFile\n ): Promise<StreamedOfflineSyncIdentity> {\n let normalizedLength = 0;\n const countNormalizer = createExplicitContentNormalizer((chunk) => {\n normalizedLength += chunk.length;\n });\n const options = this.tombstoneBlockedCaptureIndexOptions();\n const key = options.secureStoreKeyProvider();\n await forEachStagedTextChunk(\n stagePath,\n bodyOffset,\n (text) => countNormalizer.push(text),\n key,\n options.memoryDir\n );\n countNormalizer.finish();\n\n const category = after.frontmatter.category;\n const connector = after.frontmatter.sourceConnector?.trim() ?? \"\";\n const encode = (label: string, value: string): string => `${label} ${value.length} ${value}`;\n const identityPrefix =\n [encode(\"category\", category), encode(\"connector\", connector), `content ${normalizedLength} `].join(\" \");\n const identityHash = createHash(\"sha256\");\n identityHash.update(identityPrefix);\n const identityNormalizer = createExplicitContentNormalizer((chunk) => identityHash.update(chunk));\n await forEachStagedTextChunk(\n stagePath,\n bodyOffset,\n (text) => identityNormalizer.push(text),\n key,\n options.memoryDir\n );\n identityNormalizer.finish();\n return {\n identityHash: identityHash.digest(\"hex\"),\n };\n }\n\n private async *readStagedOfflineSyncChunks(stagePath: string): AsyncIterable<Buffer> {\n const options = this.tombstoneBlockedCaptureIndexOptions();\n for await (const chunk of readMaybeEncryptedFileFromChunks(\n stagePath,\n options.secureStoreKeyProvider(),\n options.memoryDir\n )) {\n yield chunk;\n }\n }\n\n protected async writeTombstoneBlockedOfflineSyncFileChunks(\n target: string,\n chunks: AsyncIterable<Buffer>\n ): Promise<void> {\n const coordinate = this.getTombstoneBlockedCaptureIndex().shouldRebuildAfterInvalidationForPath(target);\n const prepared: PreparedOfflineSyncChunks = coordinate\n ? await this.prepareTombstoneBlockedOfflineSyncChunks(target, chunks)\n : { after: null, chunks };\n const streamedIdentity = prepared.streamedIdentity;\n const mutate = async (): Promise<void> => {\n try {\n await this.runTombstoneBlockedOfflineSyncMutation(\n target,\n prepared.after,\n () => this.writeStorageSecureFileChunks(target, prepared.chunks),\n coordinate,\n streamedIdentity\n );\n } finally {\n if (prepared.stagePath !== undefined) await unlink(prepared.stagePath).catch(() => {});\n }\n };\n await mutate();\n }\n\n async writeOfflineSyncFile(filePath: string, content: Buffer): Promise<void> {\n const target = this.assertManagedStoragePath(filePath, \"storage.writeOfflineSyncFile\");\n await this.writeTombstoneBlockedOfflineSyncFile(target, content);\n await this.requestSyncReconcileIfMemoryPath(target);\n }\n\n async writeOfflineSyncFileChunks(filePath: string, chunks: AsyncIterable<Buffer>): Promise<void> {\n const target = this.assertManagedStoragePath(filePath, \"storage.writeOfflineSyncFileChunks\");\n await this.writeTombstoneBlockedOfflineSyncFileChunks(target, chunks);\n await this.requestSyncReconcileIfMemoryPath(target);\n }\n\n /**\n * Replicated bytes are opaque (possibly encrypted) and can carry legacy\n * entity references a completed migration already renamed (issue #2213) —\n * but only memory-tier markdown can, so transcript/state/other sync traffic\n * must not trigger the full-corpus reconcile pass.\n */\n private async requestSyncReconcileIfMemoryPath(target: string): Promise<void> {\n const stateDir = this.tombstoneBlockedCaptureIndexOptions().stateDir;\n if (!pathMayCarryEntityRefs(path.dirname(stateDir), target)) return;\n await requestEntityCanonicalIdReconcile(stateDir);\n }\n\n async deleteOfflineSyncFile(filePath: string): Promise<void> {\n const target = this.assertManagedStoragePath(filePath, \"storage.deleteOfflineSyncFile\");\n await this.deleteTombstoneBlockedOfflineSyncFile(target);\n }\n\n protected async deleteTombstoneBlockedOfflineSyncFile(target: string): Promise<void> {\n await this.runTombstoneBlockedOfflineSyncMutation(target, null, async () => {\n await unlink(target).catch((error: unknown) => {\n if (isErrnoCode(error, \"ENOENT\")) return;\n throw error;\n });\n });\n }\n\n async checkTombstoneBlockedExplicitCapture(\n ...args: [string, string, string?]\n ): Promise<{ has: boolean; authoritative: boolean }> {\n return this.getTombstoneBlockedCaptureIndex().check(...args);\n }\n\n async hasTombstoneBlockedExplicitCapture(...args: [string, string, string?]): Promise<boolean> {\n return this.getTombstoneBlockedCaptureIndex().has(...args);\n }\n\n async isTombstoneBlockedExplicitCaptureIndexAuthoritative(): Promise<boolean> {\n return this.getTombstoneBlockedCaptureIndex().isAuthoritative();\n }\n\n protected async rebuildTombstoneBlockedCaptureAfterInvalidationForPath(\n filePath: string,\n ownedMarker?: string\n ): Promise<void> {\n const index = this.getTombstoneBlockedCaptureIndex();\n if (index.shouldRebuildAfterInvalidationForPath(filePath)) {\n await this.rebuildTombstoneBlockedCaptureAfterInvalidation(ownedMarker);\n }\n }\n protected async rebuildTombstoneBlockedCaptureAfterInvalidation(ownedMarker?: string): Promise<void> {\n await this.getTombstoneBlockedCaptureIndex().rebuildAfterInvalidation(ownedMarker);\n }\n}\n","import { execFile } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, readdir, rename, stat, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { log } from \"../logger.js\";\nimport type { MemoryFile, MemoryFrontmatter } from \"../types.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport { withHeldFileLock } from \"../utils/serialize-mutations.js\";\nimport {\n CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS,\n ContentHashIndex,\n type ContentHashIndexLockOptions,\n} from \"./content-hash-index.js\";\nimport {\n buildExplicitCaptureDedupKey,\n TombstoneBlockedCaptureWriteLock,\n} from \"./tombstone-blocked-capture-mutation.js\";\nimport type { OfflineSyncMemoryParser } from \"./tombstone-blocked-capture-sync.js\";\nexport {\n buildExplicitCaptureDedupKey,\n isTombstoneBlockedCaptureWriteLockBusy,\n normalizeExplicitCaptureContent,\n} from \"./tombstone-blocked-capture-mutation.js\";\nexport {\n parseTombstoneBlockedOfflineSyncMemory,\n type OfflineSyncMemoryParser,\n TombstoneBlockedCaptureIndexHost,\n} from \"./tombstone-blocked-capture-sync.js\";\n\nconst REBUILD_MAX_ATTEMPTS = 3;\nconst execFileAsync = promisify(execFile);\nconst REBUILD_RETRY_BASE_MS = 50;\n\nconst ABANDONED_MARKER_MIN_AGE_MS = 60_000;\nconst MARKER_PROCESS_START_TOLERANCE_MS = 2_000;\nconst DOTNET_UNIX_EPOCH_TICKS = 621_355_968_000_000_000;\nconst MARKER_PROCESS_STARTED_AT_MS = Date.now() - process.uptime() * 1000;\n\n\ntype RebuildMarker = {\n path: string;\n committed: boolean;\n pid?: number;\n ownerId?: string;\n createdAt?: number;\n processStartedAtMs?: number;\n malformed?: boolean;\n};\n\n\nexport type TombstoneBlockedCaptureIndexOptions = {\n readonly stateDir: string;\n readonly memoryDir: string;\n readonly secureStoreKeyProvider: () => Buffer | null;\n readonly secureStoreWriteKeyProvider: () => Buffer | null;\n readonly lockOptions: () => ContentHashIndexLockOptions;\n readonly readAllMemories: () => Promise<MemoryFile[]>;\n readonly readAllColdMemories: () => Promise<MemoryFile[]>;\n readonly parseMemory?: OfflineSyncMemoryParser;\n readonly withHeldFileLock?: typeof withHeldFileLock;\n};\n\n/**\n * Durable targeted deduplication for tombstone-blocked explicit captures.\n *\n * The active fact-hash index intentionally excludes blocked rows. This small\n * companion index keeps the blocked identity visible without making every\n * authoritative active-index miss scan the full corpus.\n */\nexport class TombstoneBlockedCaptureIndex {\n private readonly options: TombstoneBlockedCaptureIndexOptions;\n private index: ContentHashIndex | null = null;\n private loadPromise: Promise<ContentHashIndex> | null = null;\n private refreshPromise: Promise<ContentHashIndex> | null = null;\n private authoritative = false;\n private readonly captureWriteLock: TombstoneBlockedCaptureWriteLock;\n\n constructor(options: TombstoneBlockedCaptureIndexOptions) {\n this.options = options;\n this.captureWriteLock = new TombstoneBlockedCaptureWriteLock(options);\n }\n\n private createIndex(): ContentHashIndex {\n return new ContentHashIndex(\n path.join(this.options.stateDir, \"tombstone-blocked-capture\"),\n this.options.secureStoreKeyProvider,\n this.options.secureStoreWriteKeyProvider,\n this.options.memoryDir,\n this.options.lockOptions()\n );\n }\n\n private indexPath(): string {\n return path.join(this.options.stateDir, \"tombstone-blocked-capture\", \"fact-hashes.txt\");\n }\n\n private rebuildMarkerPath(): string {\n return path.join(this.options.stateDir, \"tombstone-blocked-capture\", \"rebuild-required\");\n }\n\n private async readRebuildMarkers(): Promise<RebuildMarker[]> {\n try {\n const entries = (await readdir(this.rebuildMarkerPath())).filter((entry) => !entry.startsWith(\".\"));\n return (\n await Promise.all(\n entries.map(async (entry) => {\n const markerPath = path.join(this.rebuildMarkerPath(), entry);\n try {\n const raw = (await readFile(markerPath, \"utf8\")).trim();\n if (raw === \"committed\") return { path: markerPath, committed: true };\n let value: Record<string, unknown>;\n let malformed = false;\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n malformed = true;\n value = {};\n } else {\n value = parsed as Record<string, unknown>;\n }\n } catch {\n malformed = true;\n value = {};\n }\n const state = value.state;\n if (state !== \"pending\" && state !== \"committed\") malformed = true;\n const markerStat = await stat(markerPath).catch(() => null);\n // A torn payload can lose its JSON metadata, but the atomic\n // marker filename and filesystem mtime still identify its owner\n // and age. Preserve both so stale malformed markers can be\n // reaped without treating a fresh pre-commit gap as abandoned.\n const createdAt =\n typeof value.createdAt === \"number\" && Number.isFinite(value.createdAt)\n ? value.createdAt\n : markerStat?.mtimeMs;\n if (typeof value.pid !== \"number\" || !Number.isInteger(value.pid)) malformed = true;\n const ownerId =\n typeof value.ownerId === \"string\" && value.ownerId.length > 0\n ? value.ownerId\n : path.basename(markerPath);\n if (typeof value.ownerId !== \"string\" || value.ownerId.length === 0) malformed = true;\n const processStartedAtMs =\n typeof value.processStartedAtMs === \"number\" &&\n Number.isFinite(value.processStartedAtMs) &&\n value.processStartedAtMs > 0\n ? value.processStartedAtMs\n : undefined;\n return {\n path: markerPath,\n committed: state === \"committed\",\n ...(typeof value.pid === \"number\" && Number.isInteger(value.pid) ? { pid: value.pid } : {}),\n ...(ownerId.length > 0 ? { ownerId } : {}),\n ...(typeof createdAt === \"number\" && Number.isFinite(createdAt) ? { createdAt } : {}),\n ...(processStartedAtMs === undefined ? {} : { processStartedAtMs }),\n ...(malformed ? { malformed: true } : {}),\n };\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return null;\n throw err;\n }\n })\n )\n ).filter((marker): marker is RebuildMarker => marker !== null);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return [];\n throw err;\n }\n }\n private async isAbandonedMarker(marker: RebuildMarker): Promise<boolean> {\n if (marker.committed || marker.createdAt === undefined) return false;\n if (Date.now() - marker.createdAt < ABANDONED_MARKER_MIN_AGE_MS) return false;\n if (marker.malformed) return true;\n return marker.pid !== undefined && !(await this.isProcessAlive(marker.pid, marker.processStartedAtMs));\n }\n\n private async isProcessAlive(pid: number, processStartedAtMs?: number): Promise<boolean> {\n try {\n process.kill(pid, 0);\n } catch (err) {\n return !isErrnoCode(err, \"ESRCH\");\n }\n if (processStartedAtMs === undefined) return true;\n const runningStartedAtMs = await this.readProcessStartedAtMs(pid);\n if (runningStartedAtMs === null) return true;\n return runningStartedAtMs <= processStartedAtMs + MARKER_PROCESS_START_TOLERANCE_MS;\n }\n private async readProcessStartedAtMs(pid: number): Promise<number | null> {\n try {\n if (process.platform === \"win32\") {\n const { stdout } = await execFileAsync(\n \"powershell.exe\",\n [\n \"-NoLogo\",\n \"-NoProfile\",\n \"-NonInteractive\",\n \"-Command\",\n `(Get-Process -Id ${pid} -ErrorAction Stop).StartTime.ToUniversalTime().Ticks`,\n ],\n { encoding: \"utf8\", timeout: 1_000 }\n );\n const ticks = Number(stdout.trim());\n return Number.isFinite(ticks) ? (ticks - DOTNET_UNIX_EPOCH_TICKS) / 10_000 : null;\n }\n const { stdout } = await execFileAsync(\"ps\", [\"-p\", String(pid), \"-o\", \"lstart=\"], {\n encoding: \"utf8\",\n timeout: 1_000,\n });\n const output = stdout.trim();\n if (!output) return null;\n const startedAtMs = Date.parse(output);\n return Number.isFinite(startedAtMs) ? startedAtMs : null;\n } catch {\n return null;\n }\n }\n\n private async getClearableRebuildMarkerPaths(markers: readonly RebuildMarker[]): Promise<string[]> {\n const paths = await Promise.all(\n markers.map(async (marker) => (marker.committed || (await this.isAbandonedMarker(marker)) ? marker.path : null))\n );\n return paths.filter((markerPath): markerPath is string => markerPath !== null);\n }\n\n private async getRebuildMarkers(): Promise<RebuildMarker[]> {\n return await this.readRebuildMarkers();\n }\n\n // A pending marker protects the pre-commit gap; only committed markers are safe for another writer to clear.\n private async writeMarkerAtomically(markerPath: string, payload: string): Promise<void> {\n const temporaryPath = `${markerPath}.tmp-${process.pid}-${randomUUID()}`;\n try {\n await writeFile(temporaryPath, payload, \"utf8\");\n await rename(temporaryPath, markerPath);\n } finally {\n await unlink(temporaryPath).catch((err: unknown) => {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n });\n }\n }\n\n private async markRebuildRequired(committed = false): Promise<string> {\n const markerDir = this.rebuildMarkerPath();\n await mkdir(markerDir, { recursive: true });\n const ownerId = randomUUID();\n const markerPath = path.join(markerDir, ownerId);\n await this.writeMarkerAtomically(\n markerPath,\n `${JSON.stringify({\n state: committed ? \"committed\" : \"pending\",\n pid: process.pid,\n ownerId,\n createdAt: Date.now(),\n processStartedAtMs: MARKER_PROCESS_STARTED_AT_MS,\n })}\\n`\n );\n return markerPath;\n }\n\n private async markRebuildCommitted(markerPath: string): Promise<void> {\n await this.writeMarkerAtomically(\n markerPath,\n `${JSON.stringify({\n state: \"committed\",\n pid: process.pid,\n ownerId: path.basename(markerPath),\n createdAt: Date.now(),\n processStartedAtMs: MARKER_PROCESS_STARTED_AT_MS,\n })}\\n`\n );\n }\n\n private async clearRebuildRequired(markerPaths: readonly string[]): Promise<void> {\n await Promise.all(\n markerPaths.map(async (markerPath) => {\n try {\n await unlink(markerPath);\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n }\n })\n );\n }\n\n private async hasRebuildRequired(excludedMarkers: readonly string[] = []): Promise<boolean> {\n const excluded = new Set(excludedMarkers);\n return (await this.getRebuildMarkers()).some((marker) => !excluded.has(marker.path));\n }\n\n private async setAuthoritative(rebuilt: boolean): Promise<void> {\n this.authoritative = rebuilt && !(await this.getRebuildMarkers()).some((marker) => !marker.committed);\n }\n private isBlocked(memory: MemoryFile): boolean {\n return memory.frontmatter.status === \"pending_review\" && Boolean(memory.frontmatter.blockedBy);\n }\n\n private async rebuild(index: ContentHashIndex): Promise<boolean> {\n return await index.rebuildUnderLock(async () => {\n index.clear();\n const existing = [...(await this.options.readAllMemories()), ...(await this.options.readAllColdMemories())];\n for (const memory of existing) {\n if (!this.isBlocked(memory)) continue;\n index.add(\n buildExplicitCaptureDedupKey(memory.content, memory.frontmatter.category, memory.frontmatter.sourceConnector)\n );\n }\n });\n }\n\n private async hasPersistedIndexOrMarkers(): Promise<boolean> {\n try {\n await stat(this.indexPath());\n return true;\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n return (await this.readRebuildMarkers()).length > 0;\n }\n }\n\n private async getIndex(): Promise<ContentHashIndex> {\n if (this.index) return this.index;\n if (!this.loadPromise) {\n const index = this.createIndex();\n this.loadPromise = (async () => {\n await index.load();\n const rebuildMarkers = await this.getRebuildMarkers();\n const clearableRebuildMarkers = await this.getClearableRebuildMarkerPaths(rebuildMarkers);\n let persisted = true;\n try {\n await stat(this.indexPath());\n if (rebuildMarkers.length > 0) persisted = false;\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) persisted = false;\n else throw err;\n }\n if (!persisted) {\n const lockOptions = this.options.lockOptions();\n const maxAttempts = lockOptions.retryMaxAttempts ?? REBUILD_MAX_ATTEMPTS;\n const baseMs = lockOptions.retryBaseMs ?? REBUILD_RETRY_BASE_MS;\n let rebuilt = false;\n for (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n rebuilt = await this.rebuild(index);\n if (rebuilt || attempt === maxAttempts - 1) break;\n const wait = Math.min(baseMs * 2 ** attempt, CONTENT_HASH_INDEX_RETRY_MAX_DELAY_MS);\n const delayState = Promise.withResolvers<void>();\n setTimeout(delayState.resolve, wait);\n await delayState.promise;\n }\n if (!rebuilt) {\n throw new Error(\"tombstone-blocked capture index rebuild lock unavailable\");\n }\n await this.clearRebuildRequired(clearableRebuildMarkers);\n }\n await this.setAuthoritative(true);\n this.index = index;\n return index;\n })().catch((err) => {\n this.loadPromise = null;\n throw err;\n });\n }\n return this.loadPromise;\n }\n\n async withCaptureWriteLock<T>(task: () => Promise<T>, identity?: string | readonly string[]): Promise<T> {\n return await this.captureWriteLock.withCaptureWriteLock(task, identity);\n }\n\n async withCaptureWriteLockHashes<T>(task: () => Promise<T>, identityHashes: readonly string[]): Promise<T> {\n return await this.captureWriteLock.withCaptureWriteLockHashes(task, identityHashes);\n }\n async withCaptureWriteLockAndHashes<T>(\n task: () => Promise<T>,\n identity: string | readonly string[] | undefined,\n identityHashes: readonly string[]\n ): Promise<T> {\n return await this.captureWriteLock.withCaptureWriteLockAndHashes(task, identity, identityHashes);\n }\n\n private async reload(): Promise<ContentHashIndex> {\n if (!this.refreshPromise) {\n this.refreshPromise = (async () => {\n this.index = null;\n this.loadPromise = null;\n return await this.getIndex();\n })().finally(() => {\n this.refreshPromise = null;\n });\n }\n return this.refreshPromise;\n }\n\n /** Return blocked-row membership and authority from one index snapshot. */\n async check(\n content: string,\n category: string,\n sourceConnector?: string\n ): Promise<{ has: boolean; authoritative: boolean }> {\n const key = buildExplicitCaptureDedupKey(content, category, sourceConnector);\n let index = await this.getIndex();\n if ((await this.hasRebuildRequired()) || !(await index.isDiskFingerprintCurrent())) {\n index = await this.reload();\n }\n return { has: index.has(key), authoritative: this.authoritative };\n }\n\n /** Return whether a blocked row matches this explicit-capture identity. */\n async has(content: string, category: string, sourceConnector?: string): Promise<boolean> {\n return (await this.check(content, category, sourceConnector)).has;\n }\n\n /** Return whether the in-memory index is safe to answer an authoritative miss. */\n async isAuthoritative(): Promise<boolean> {\n const index = await this.getIndex();\n if ((await this.hasRebuildRequired()) || !(await index.isDiskFingerprintCurrent())) {\n await this.reload();\n }\n return this.authoritative;\n }\n\n /** Reserve durable rebuild intent before a blocked memory file is committed. */\n async prepareWrite(): Promise<string> {\n return this.markRebuildRequired();\n }\n\n /** Mark a prepared write committed once its memory file is durable. */\n async commitWrite(rebuildMarker: string): Promise<void> {\n await this.markRebuildCommitted(rebuildMarker);\n }\n\n /** Drop a pending marker when the protected memory write never commits. */\n async discardWrite(rebuildMarker: string): Promise<void> {\n await this.clearRebuildRequired([rebuildMarker]);\n }\n\n /** Add a newly persisted blocked row to the durable targeted index. */\n async add(memory: MemoryFile, rebuildMarker?: string): Promise<void> {\n if (!this.isBlocked(memory)) return;\n let index = await this.getIndex();\n if (\n (await this.hasRebuildRequired(rebuildMarker ? [rebuildMarker] : [])) ||\n !(await index.isDiskFingerprintCurrent())\n ) {\n index = await this.reload();\n }\n index.add(\n buildExplicitCaptureDedupKey(memory.content, memory.frontmatter.category, memory.frontmatter.sourceConnector)\n );\n const marker = rebuildMarker ?? (await this.markRebuildRequired(true));\n if (rebuildMarker) await this.markRebuildCommitted(rebuildMarker);\n await index.saveMergingWithDisk();\n await index.flushReconcileRetry();\n if (index.hasPendingChanges) {\n this.markUntrusted();\n return;\n }\n await this.clearRebuildRequired([marker]);\n await this.setAuthoritative(true);\n }\n\n /** Rebuild the index after a blocked row changes or is removed. */\n async rebuildIfLoaded(ownedMarker?: string): Promise<void> {\n const index = this.index ?? ((await this.hasPersistedIndexOrMarkers()) ? this.getIndex() : null);\n if (!index) return;\n const rebuildMarkers = await this.getRebuildMarkers();\n const rebuildMarker = await this.markRebuildRequired(true);\n const clearableRebuildMarkers = await this.getClearableRebuildMarkerPaths(rebuildMarkers);\n const rebuilt = await this.rebuild(await index);\n if (rebuilt) {\n await this.clearRebuildRequired([\n ...clearableRebuildMarkers,\n ...(ownedMarker === undefined || clearableRebuildMarkers.includes(ownedMarker) ? [] : [ownedMarker]),\n rebuildMarker,\n ]);\n }\n await this.setAuthoritative(rebuilt);\n }\n\n /** Rebuild when either side of a write is blocked and its identity changed. */\n async sync(before: MemoryFile, after: MemoryFile, rebuildMarker?: string): Promise<void> {\n const beforeBlocked = this.isBlocked(before);\n const afterBlocked = this.isBlocked(after);\n if (!beforeBlocked && !afterBlocked) return;\n const beforeKey = buildExplicitCaptureDedupKey(\n before.content,\n before.frontmatter.category,\n before.frontmatter.sourceConnector\n );\n const afterKey = buildExplicitCaptureDedupKey(\n after.content,\n after.frontmatter.category,\n after.frontmatter.sourceConnector\n );\n if (beforeBlocked && afterBlocked && beforeKey === afterKey) {\n if (rebuildMarker) {\n await this.markRebuildCommitted(rebuildMarker);\n await this.clearRebuildRequired([rebuildMarker]);\n }\n return;\n }\n const existingMarkers = await this.getRebuildMarkers();\n const marker = rebuildMarker ?? (await this.markRebuildRequired(true));\n const clearableExistingMarkers = await this.getClearableRebuildMarkerPaths(existingMarkers);\n if (rebuildMarker) await this.markRebuildCommitted(rebuildMarker);\n const rebuilt = await this.rebuild(await this.getIndex());\n if (rebuilt) {\n await this.clearRebuildRequired([\n ...clearableExistingMarkers,\n marker,\n ]);\n }\n await this.setAuthoritative(rebuilt);\n }\n markUntrusted(): void {\n this.authoritative = false;\n }\n\n private async failOpen(operation: string, action: () => Promise<void>): Promise<void> {\n try {\n await action();\n } catch (err) {\n this.markUntrusted();\n log.warn(`storage.${operation} completed but failed to update tombstone-blocked capture index: ${err}`);\n }\n }\n\n async addWrittenMemory(\n pathname: string,\n frontmatter: MemoryFrontmatter,\n content: string,\n rebuildMarker?: string\n ): Promise<void> {\n await this.failOpen(\"writeMemory\", () => this.add({ path: pathname, frontmatter, content }, rebuildMarker));\n }\n\n async rebuildAfterInvalidation(ownedMarker?: string): Promise<void> {\n await this.failOpen(\"invalidateMemory\", () => this.rebuildIfLoaded(ownedMarker));\n }\n\n async syncUpdatedMemory(\n before: MemoryFile,\n frontmatter: MemoryFrontmatter,\n content: string,\n rebuildMarker?: string\n ): Promise<void> {\n await this.failOpen(\"updateMemory\", () => this.sync(before, { ...before, frontmatter, content }, rebuildMarker));\n }\n\n async syncUpdatedFrontmatter(\n before: MemoryFile,\n frontmatter: MemoryFrontmatter,\n rebuildMarker?: string\n ): Promise<void> {\n await this.failOpen(\"writeMemoryFrontmatter\", () => this.sync(before, { ...before, frontmatter }, rebuildMarker));\n }\n shouldRebuildAfterInvalidationForPath(filePath: string): boolean {\n const relative = path.relative(path.resolve(this.options.memoryDir), path.resolve(filePath));\n const category = relative.split(path.sep)[0];\n return category === \"cold\" || RECALL_FALLBACK_DIRS.includes(category);\n }\n}\n"],"mappings":"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","names":["mkdir","path","path","mkdir","createHash","randomUUID","unlink","path","mkdir","stat","path","path","stat","stdout","mkdir","path","result","unlink","randomUUID","createHash"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|