@remnic/core 9.3.652 → 9.3.654
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-cli.js +17 -17
- package/dist/access-http.d.ts +4 -4
- package/dist/access-http.js +11 -11
- package/dist/access-mcp.d.ts +4 -4
- package/dist/access-mcp.js +10 -10
- package/dist/access-schema.d.ts +15 -12
- package/dist/access-schema.js +1 -1
- package/dist/{access-service-CdJFd3_b.d.ts → access-service-C8A5hoXJ.d.ts} +11 -2
- package/dist/access-service.d.ts +4 -4
- package/dist/access-service.js +8 -8
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +3 -3
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-KJDKZVF3.js → chunk-2DSTAWNZ.js} +3 -3
- package/dist/chunk-3RACUBII.js +212 -0
- package/dist/chunk-3RACUBII.js.map +1 -0
- package/dist/{chunk-Y7NWBBHV.js → chunk-6CVI6BP6.js} +2 -2
- package/dist/{chunk-R3PQUPQ4.js → chunk-6IMKOIZ6.js} +85 -3
- package/dist/chunk-6IMKOIZ6.js.map +1 -0
- package/dist/{chunk-WTI35CVJ.js → chunk-BJA6DQOC.js} +5 -5
- package/dist/{chunk-GI45G4BK.js → chunk-BP2EV6W5.js} +3 -3
- package/dist/{chunk-WLGE6KEO.js → chunk-DBM2BD22.js} +3 -3
- package/dist/{chunk-IENGGY2C.js → chunk-ENV6RDTD.js} +2 -2
- package/dist/{chunk-BEMWL2FZ.js → chunk-FVRBLJP6.js} +2 -2
- package/dist/{chunk-H3PHZLMF.js → chunk-GKKAXVAJ.js} +20 -11
- package/dist/chunk-GKKAXVAJ.js.map +1 -0
- package/dist/{chunk-MGGNV3H2.js → chunk-GPW2E4LN.js} +23 -8
- package/dist/chunk-GPW2E4LN.js.map +1 -0
- package/dist/{chunk-KWM33SPU.js → chunk-JMQSYGXS.js} +2 -2
- package/dist/{chunk-WSFNYPAT.js → chunk-JYN7QNTA.js} +87 -18
- package/dist/chunk-JYN7QNTA.js.map +1 -0
- package/dist/{chunk-AJE7FJVE.js → chunk-K6X553JB.js} +2 -2
- package/dist/{chunk-5V3TAB7D.js → chunk-LJCEWTG3.js} +19 -8
- package/dist/{chunk-5V3TAB7D.js.map → chunk-LJCEWTG3.js.map} +1 -1
- package/dist/{chunk-YOVKPOMD.js → chunk-NAZWHTYV.js} +13 -6
- package/dist/chunk-NAZWHTYV.js.map +1 -0
- package/dist/{chunk-XMN6MMTU.js → chunk-NCGWXCSW.js} +2 -2
- package/dist/{chunk-C43KEWEV.js → chunk-NE2JBMLN.js} +1 -1
- package/dist/chunk-NE2JBMLN.js.map +1 -0
- package/dist/{chunk-TCX4WLKK.js → chunk-OL2364SB.js} +2020 -368
- package/dist/chunk-OL2364SB.js.map +1 -0
- package/dist/{chunk-JF7SFXTG.js → chunk-QKK64Z6M.js} +2 -2
- package/dist/{chunk-IVYSVAC6.js → chunk-QW6JZO5P.js} +2 -2
- package/dist/{chunk-EHQLDFSH.js → chunk-RGPUQ66K.js} +2 -2
- package/dist/{chunk-CFOCZPIQ.js → chunk-T2C6QJG2.js} +2 -2
- package/dist/{chunk-4HYSMH7D.js → chunk-UAU5U5ML.js} +3 -2
- package/dist/chunk-UAU5U5ML.js.map +1 -0
- package/dist/{chunk-V4UDXYGG.js → chunk-XWQ6ERUG.js} +2 -2
- package/dist/{chunk-IJHLC5CH.js → chunk-Y2RIIF6H.js} +32 -22
- package/dist/{chunk-IJHLC5CH.js.map → chunk-Y2RIIF6H.js.map} +1 -1
- package/dist/{chunk-C63WC454.js → chunk-YLZLPVKK.js} +22 -1
- package/dist/chunk-YLZLPVKK.js.map +1 -0
- package/dist/{chunk-RZOBQ23O.js → chunk-Z5MQI7K2.js} +2 -2
- package/dist/{chunk-PRQXUSQV.js → chunk-ZCORQM74.js} +2 -2
- package/dist/{cli-DDo7Qgs-.d.ts → cli-uQgvDFNE.d.ts} +3 -3
- package/dist/cli.d.ts +5 -5
- package/dist/cli.js +23 -23
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +19 -1
- package/dist/contradiction/index.js +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +3 -3
- package/dist/explicit-capture.js +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +8 -8
- package/dist/index.js +31 -29
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +4 -4
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +52 -3
- package/dist/namespaces/storage.js +9 -5
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +7 -7
- package/dist/{orchestrator-8fTZsa0y.d.ts → orchestrator-B4Y4sWQH.d.ts} +503 -3
- package/dist/orchestrator.d.ts +3 -3
- package/dist/orchestrator.js +13 -13
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/{resolution-3SAP4SH2.js → resolution-IDTEBJFS.js} +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DKdYzQOg.d.ts → semantic-consolidation-BKd0Pype.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/{types-D8yUmSik.d.ts → types-BgChEr0M.d.ts} +11 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +1 -1
- package/src/access-http.ts +7 -0
- package/src/access-mcp.test.ts +70 -1
- package/src/access-mcp.ts +19 -2
- package/src/access-schema.ts +1 -0
- package/src/access-service.ts +12 -0
- package/src/briefing.test.ts +70 -0
- package/src/briefing.ts +30 -20
- package/src/cli.ts +104 -0
- package/src/config.test.ts +40 -0
- package/src/config.ts +29 -0
- package/src/contradiction/contradiction.test.ts +284 -0
- package/src/contradiction/resolution.ts +151 -4
- package/src/explicit-capture.ts +31 -10
- package/src/index.ts +10 -0
- package/src/namespaces/catalog.test.ts +3356 -0
- package/src/namespaces/catalog.ts +2123 -0
- package/src/namespaces/storage.ts +210 -30
- package/src/orchestrator-flush.test.ts +300 -0
- package/src/orchestrator.ts +851 -240
- package/src/types.ts +11 -0
- package/dist/chunk-4HYSMH7D.js.map +0 -1
- package/dist/chunk-C43KEWEV.js.map +0 -1
- package/dist/chunk-C63WC454.js.map +0 -1
- package/dist/chunk-H3PHZLMF.js.map +0 -1
- package/dist/chunk-MGGNV3H2.js.map +0 -1
- package/dist/chunk-ORGWWNJG.js +0 -131
- package/dist/chunk-ORGWWNJG.js.map +0 -1
- package/dist/chunk-R3PQUPQ4.js.map +0 -1
- package/dist/chunk-TCX4WLKK.js.map +0 -1
- package/dist/chunk-WSFNYPAT.js.map +0 -1
- package/dist/chunk-YOVKPOMD.js.map +0 -1
- /package/dist/{chunk-KJDKZVF3.js.map → chunk-2DSTAWNZ.js.map} +0 -0
- /package/dist/{chunk-Y7NWBBHV.js.map → chunk-6CVI6BP6.js.map} +0 -0
- /package/dist/{chunk-WTI35CVJ.js.map → chunk-BJA6DQOC.js.map} +0 -0
- /package/dist/{chunk-GI45G4BK.js.map → chunk-BP2EV6W5.js.map} +0 -0
- /package/dist/{chunk-WLGE6KEO.js.map → chunk-DBM2BD22.js.map} +0 -0
- /package/dist/{chunk-IENGGY2C.js.map → chunk-ENV6RDTD.js.map} +0 -0
- /package/dist/{chunk-BEMWL2FZ.js.map → chunk-FVRBLJP6.js.map} +0 -0
- /package/dist/{chunk-KWM33SPU.js.map → chunk-JMQSYGXS.js.map} +0 -0
- /package/dist/{chunk-AJE7FJVE.js.map → chunk-K6X553JB.js.map} +0 -0
- /package/dist/{chunk-XMN6MMTU.js.map → chunk-NCGWXCSW.js.map} +0 -0
- /package/dist/{chunk-JF7SFXTG.js.map → chunk-QKK64Z6M.js.map} +0 -0
- /package/dist/{chunk-IVYSVAC6.js.map → chunk-QW6JZO5P.js.map} +0 -0
- /package/dist/{chunk-EHQLDFSH.js.map → chunk-RGPUQ66K.js.map} +0 -0
- /package/dist/{chunk-CFOCZPIQ.js.map → chunk-T2C6QJG2.js.map} +0 -0
- /package/dist/{chunk-V4UDXYGG.js.map → chunk-XWQ6ERUG.js.map} +0 -0
- /package/dist/{chunk-RZOBQ23O.js.map → chunk-Z5MQI7K2.js.map} +0 -0
- /package/dist/{chunk-PRQXUSQV.js.map → chunk-ZCORQM74.js.map} +0 -0
- /package/dist/{resolution-3SAP4SH2.js.map → resolution-IDTEBJFS.js.map} +0 -0
package/dist/calibration.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FallbackLlmClient } from './fallback-llm.js';
|
|
2
|
-
import { G as GatewayConfig, f as AgentPersonaModelConfig } from './types-
|
|
2
|
+
import { G as GatewayConfig, f as AgentPersonaModelConfig } from './types-BgChEr0M.js';
|
|
3
3
|
import './resolve-provider-secret.js';
|
|
4
4
|
import './types-ByK7T3L6.js';
|
|
5
5
|
import './index-DJ9QWMw-.js';
|
|
@@ -2,7 +2,7 @@ import { CausalChainIndex } from './causal-chain.js';
|
|
|
2
2
|
import { ConsolidatedPreference } from './compounding/preference-consolidator.js';
|
|
3
3
|
import './causal-trajectory.js';
|
|
4
4
|
import './objective-state.js';
|
|
5
|
-
import './types-
|
|
5
|
+
import './types-BgChEr0M.js';
|
|
6
6
|
import './types-ByK7T3L6.js';
|
|
7
7
|
import './index-DJ9QWMw-.js';
|
|
8
8
|
import './lcm/engine.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { G as GatewayConfig, f as AgentPersonaModelConfig, P as PluginConfig, g as MemoryFile } from './types-
|
|
1
|
+
import { G as GatewayConfig, f as AgentPersonaModelConfig, P as PluginConfig, g as MemoryFile } from './types-BgChEr0M.js';
|
|
2
2
|
import { RolloutSummaryInput, MaterializeResult } from './connectors/codex-materialize.js';
|
|
3
3
|
import './types-ByK7T3L6.js';
|
|
4
4
|
import './index-DJ9QWMw-.js';
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-UXA5L2DZ.js";
|
|
5
5
|
import {
|
|
6
6
|
buildExtensionsBlockForConsolidation
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-T2C6QJG2.js";
|
|
8
8
|
import {
|
|
9
9
|
runPostConsolidationMaterialize
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QW6JZO5P.js";
|
|
11
11
|
import "./chunk-LN4YGHTM.js";
|
|
12
12
|
import "./chunk-JLNBQWZ2.js";
|
|
13
13
|
import "./chunk-3UXOZBHV.js";
|
|
@@ -20,11 +20,11 @@ import "./chunk-L2EXJQJP.js";
|
|
|
20
20
|
import "./chunk-7SI52C65.js";
|
|
21
21
|
import "./chunk-RK6F44Y6.js";
|
|
22
22
|
import "./chunk-HQ6NIBL6.js";
|
|
23
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-6CVI6BP6.js";
|
|
24
24
|
import "./chunk-M7XQSUBB.js";
|
|
25
25
|
import "./chunk-5UZXUTVO.js";
|
|
26
26
|
import "./chunk-J6A3CX5N.js";
|
|
27
|
-
import "./chunk-
|
|
27
|
+
import "./chunk-NE2JBMLN.js";
|
|
28
28
|
import "./chunk-CPPS65WS.js";
|
|
29
29
|
import "./chunk-RULE4VG5.js";
|
|
30
30
|
import "./chunk-SCU65EZI.js";
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
listMemoryGovernanceRuns,
|
|
12
12
|
readMemoryGovernanceRunArtifact
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XWQ6ERUG.js";
|
|
14
14
|
import {
|
|
15
15
|
StorageManager
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-6CVI6BP6.js";
|
|
17
17
|
import {
|
|
18
18
|
MEMORY_LIFECYCLE_EVENT_SORT_ORDER,
|
|
19
19
|
buildLifecycleEventsForMemory,
|
|
@@ -929,4 +929,4 @@ export {
|
|
|
929
929
|
verifyMemoryProjection,
|
|
930
930
|
repairMemoryProjection
|
|
931
931
|
};
|
|
932
|
-
//# sourceMappingURL=chunk-
|
|
932
|
+
//# sourceMappingURL=chunk-2DSTAWNZ.js.map
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
namespaceIdentityToken,
|
|
3
|
+
normalizeNamespaceIdentity
|
|
4
|
+
} from "./chunk-ZFXCQPNO.js";
|
|
5
|
+
import {
|
|
6
|
+
ALL_CATEGORY_DIRS,
|
|
7
|
+
StorageManager
|
|
8
|
+
} from "./chunk-6CVI6BP6.js";
|
|
9
|
+
import {
|
|
10
|
+
isSafeRouteNamespace
|
|
11
|
+
} from "./chunk-U3PN77QT.js";
|
|
12
|
+
|
|
13
|
+
// src/namespaces/storage.ts
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { access, lstat, readdir } from "fs/promises";
|
|
16
|
+
async function exists(p) {
|
|
17
|
+
try {
|
|
18
|
+
await access(p);
|
|
19
|
+
return true;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function hasStoredEntries(p) {
|
|
25
|
+
try {
|
|
26
|
+
const entry = await lstat(p);
|
|
27
|
+
if (entry.isSymbolicLink()) return true;
|
|
28
|
+
if (!entry.isDirectory()) return true;
|
|
29
|
+
const children = await readdir(p, { withFileTypes: true });
|
|
30
|
+
for (const child of children) {
|
|
31
|
+
const childPath = path.join(p, child.name);
|
|
32
|
+
if (child.isSymbolicLink() || child.isFile()) return true;
|
|
33
|
+
if (child.isDirectory() && await hasStoredEntries(childPath)) return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
} catch {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function resolveNamespaceDir(memoryDir, segment) {
|
|
41
|
+
if (segment.length === 0 || segment.includes("/") || segment.includes("\\") || segment.includes("..") || path.isAbsolute(segment)) {
|
|
42
|
+
throw new Error(`unsafe namespace path segment: ${segment}`);
|
|
43
|
+
}
|
|
44
|
+
return path.join(memoryDir, "namespaces", segment);
|
|
45
|
+
}
|
|
46
|
+
var LEGACY_NAMESPACE_CONTENT_CHILDREN = [
|
|
47
|
+
...ALL_CATEGORY_DIRS,
|
|
48
|
+
"entities",
|
|
49
|
+
"artifacts",
|
|
50
|
+
"identity",
|
|
51
|
+
"config",
|
|
52
|
+
"summaries",
|
|
53
|
+
"profile.md"
|
|
54
|
+
];
|
|
55
|
+
var LEGACY_NAMESPACE_RUNTIME_CHILDREN = ["state"];
|
|
56
|
+
async function hasAnyLegacyData(rootDir, options = {}) {
|
|
57
|
+
const children = options.includeRuntimeState === true ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN] : LEGACY_NAMESPACE_CONTENT_CHILDREN;
|
|
58
|
+
for (const child of children) {
|
|
59
|
+
if (await hasStoredEntries(path.join(rootDir, child))) return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
async function hasAnyNamespaceStorageMarker(rootDir, options = {}) {
|
|
64
|
+
const children = options.includeRuntimeState === true ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN] : LEGACY_NAMESPACE_CONTENT_CHILDREN;
|
|
65
|
+
for (const child of children) {
|
|
66
|
+
if (await exists(path.join(rootDir, child))) return true;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
async function resolveDefaultNamespaceRoot(config) {
|
|
71
|
+
if (!config.namespacesEnabled) {
|
|
72
|
+
return config.memoryDir;
|
|
73
|
+
}
|
|
74
|
+
const defaultIdentity = normalizeNamespaceIdentity(config.defaultNamespace);
|
|
75
|
+
const legacyNsDir = resolveNamespaceDir(config.memoryDir, defaultIdentity);
|
|
76
|
+
const tokenizedNsDir = resolveNamespaceDir(
|
|
77
|
+
config.memoryDir,
|
|
78
|
+
namespaceIdentityToken(config.defaultNamespace)
|
|
79
|
+
);
|
|
80
|
+
const tokenizedHasData = await exists(tokenizedNsDir) && await hasAnyNamespaceStorageMarker(tokenizedNsDir, { includeRuntimeState: true });
|
|
81
|
+
const nsDir = tokenizedHasData ? tokenizedNsDir : await exists(legacyNsDir) ? legacyNsDir : tokenizedNsDir;
|
|
82
|
+
return await exists(nsDir) && !await hasAnyLegacyData(config.memoryDir) ? nsDir : config.memoryDir;
|
|
83
|
+
}
|
|
84
|
+
async function resolveNamespaceStorageRoot(config, namespace) {
|
|
85
|
+
if (!config.namespacesEnabled) return config.memoryDir;
|
|
86
|
+
if (normalizeNamespaceIdentity(namespace) === normalizeNamespaceIdentity(config.defaultNamespace)) {
|
|
87
|
+
return resolveDefaultNamespaceRoot(config);
|
|
88
|
+
}
|
|
89
|
+
const legacyRoot = resolveNamespaceDir(config.memoryDir, namespace);
|
|
90
|
+
const tokenizedRoot = resolveNamespaceDir(config.memoryDir, namespaceIdentityToken(namespace));
|
|
91
|
+
if (await exists(tokenizedRoot) && await hasAnyNamespaceStorageMarker(tokenizedRoot, { includeRuntimeState: true })) {
|
|
92
|
+
return tokenizedRoot;
|
|
93
|
+
}
|
|
94
|
+
return await exists(legacyRoot) ? legacyRoot : tokenizedRoot;
|
|
95
|
+
}
|
|
96
|
+
var NamespaceStorageRouter = class {
|
|
97
|
+
constructor(config, hooks = {}) {
|
|
98
|
+
this.config = config;
|
|
99
|
+
this.hooks = hooks;
|
|
100
|
+
this.defaultNamespaceIdentity = normalizeNamespaceIdentity(config.defaultNamespace);
|
|
101
|
+
}
|
|
102
|
+
config;
|
|
103
|
+
hooks;
|
|
104
|
+
cache = /* @__PURE__ */ new Map();
|
|
105
|
+
defaultNsRootResolved = null;
|
|
106
|
+
// Dedup the resolve hook (round 6, cursor Medium — NCNL2). Recall/extraction
|
|
107
|
+
// call `storageFor` repeatedly; firing `onResolve` (→ catalog loadCompacted +
|
|
108
|
+
// append) on every cache hit grows `namespaces.jsonl` without bound between
|
|
109
|
+
// rebuilds. We fire the hook only when the (namespace, storageDir) pair is new
|
|
110
|
+
// or its dir changed, so a steady-state cache hit is a no-op for the catalog.
|
|
111
|
+
notifiedResolved = /* @__PURE__ */ new Map();
|
|
112
|
+
// In-flight resolve-hook dedup (NFJV-, codex P2). The catalog's `onResolve`
|
|
113
|
+
// hook is ASYNC (it returns `registerResolved(...)`), so `notifiedResolved` is
|
|
114
|
+
// only set after the hook's promise SETTLES. Without tracking the in-flight
|
|
115
|
+
// window, a burst of `storageFor()` cache hits for the SAME namespace before
|
|
116
|
+
// the first registration finishes would each pass the `notifiedResolved` guard
|
|
117
|
+
// and fire their OWN `onResolve` — queueing N duplicate catalog touches + lock
|
|
118
|
+
// acquisitions despite the once-per-namespace intent. We therefore record the
|
|
119
|
+
// (namespace → storageDir) being registered BEFORE awaiting the hook so a
|
|
120
|
+
// concurrent call for the same pair skips firing. On SUCCESS the pair is
|
|
121
|
+
// promoted to `notifiedResolved` (future calls skip permanently); on `false`
|
|
122
|
+
// (dropped touch — e.g. rebuild-lock timeout) OR rejection the in-flight marker
|
|
123
|
+
// is CLEARED so a later `storageFor()` can RETRY the dropped registration. The
|
|
124
|
+
// entry is always removed when the promise settles, so the map cannot grow
|
|
125
|
+
// unbounded (one transient entry per concurrently-resolving namespace).
|
|
126
|
+
inFlightResolved = /* @__PURE__ */ new Map();
|
|
127
|
+
// Normalized (trimmed) default namespace identity (NH-FH). `storageFor`
|
|
128
|
+
// normalizes its input, so default-namespace branches must compare against the
|
|
129
|
+
// normalized config default too — otherwise a whitespace-padded configured
|
|
130
|
+
// default name routes the default namespace to a tokenized non-default root.
|
|
131
|
+
defaultNamespaceIdentity;
|
|
132
|
+
async defaultNamespaceRoot() {
|
|
133
|
+
this.defaultNsRootResolved = await resolveDefaultNamespaceRoot(this.config);
|
|
134
|
+
return this.defaultNsRootResolved;
|
|
135
|
+
}
|
|
136
|
+
async namespaceRoot(namespace) {
|
|
137
|
+
if (!this.config.namespacesEnabled) return this.config.memoryDir;
|
|
138
|
+
if (normalizeNamespaceIdentity(namespace) === this.defaultNamespaceIdentity) {
|
|
139
|
+
return this.defaultNsRootResolved ?? this.config.memoryDir;
|
|
140
|
+
}
|
|
141
|
+
return resolveNamespaceStorageRoot(this.config, namespace);
|
|
142
|
+
}
|
|
143
|
+
async storageFor(namespace) {
|
|
144
|
+
const ns = normalizeNamespaceIdentity(namespace || this.config.defaultNamespace);
|
|
145
|
+
if (ns !== this.defaultNamespaceIdentity && !isSafeRouteNamespace(ns)) {
|
|
146
|
+
throw new Error(`unsafe namespace: ${ns}`);
|
|
147
|
+
}
|
|
148
|
+
let root;
|
|
149
|
+
if (ns === this.defaultNamespaceIdentity) {
|
|
150
|
+
root = await this.defaultNamespaceRoot();
|
|
151
|
+
const cached = this.cache.get(ns);
|
|
152
|
+
if (cached && cached.dir === root) {
|
|
153
|
+
this.notifyResolved(ns, root);
|
|
154
|
+
return cached;
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
const cached = this.cache.get(ns);
|
|
158
|
+
root = await this.namespaceRoot(ns);
|
|
159
|
+
if (cached && cached.dir === root) {
|
|
160
|
+
this.notifyResolved(ns, root);
|
|
161
|
+
return cached;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const sm = new StorageManager(root, this.config.entitySchemas);
|
|
165
|
+
sm.citationTemplate = this.config.inlineSourceAttributionFormat;
|
|
166
|
+
this.cache.set(ns, sm);
|
|
167
|
+
this.notifyResolved(ns, root);
|
|
168
|
+
return sm;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Fire the resolve hook defensively. A hook failure (e.g. a catalog write
|
|
172
|
+
* error) MUST NOT crash storage resolution — see CLAUDE.md gotcha #13.
|
|
173
|
+
*/
|
|
174
|
+
notifyResolved(namespace, storageDir) {
|
|
175
|
+
const hook = this.hooks.onResolve;
|
|
176
|
+
if (!hook) return;
|
|
177
|
+
if (this.notifiedResolved.get(namespace) === storageDir) return;
|
|
178
|
+
if (this.inFlightResolved.get(namespace) === storageDir) return;
|
|
179
|
+
try {
|
|
180
|
+
this.inFlightResolved.set(namespace, storageDir);
|
|
181
|
+
Promise.resolve(hook(namespace, storageDir)).then(
|
|
182
|
+
(persisted) => {
|
|
183
|
+
if (this.inFlightResolved.get(namespace) === storageDir) {
|
|
184
|
+
this.inFlightResolved.delete(namespace);
|
|
185
|
+
}
|
|
186
|
+
if (persisted !== false) {
|
|
187
|
+
this.notifiedResolved.set(namespace, storageDir);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
() => {
|
|
191
|
+
if (this.inFlightResolved.get(namespace) === storageDir) {
|
|
192
|
+
this.inFlightResolved.delete(namespace);
|
|
193
|
+
}
|
|
194
|
+
if (this.notifiedResolved.get(namespace) === storageDir) {
|
|
195
|
+
this.notifiedResolved.delete(namespace);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
} catch {
|
|
200
|
+
if (this.inFlightResolved.get(namespace) === storageDir) {
|
|
201
|
+
this.inFlightResolved.delete(namespace);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
resolveDefaultNamespaceRoot,
|
|
209
|
+
resolveNamespaceStorageRoot,
|
|
210
|
+
NamespaceStorageRouter
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=chunk-3RACUBII.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/namespaces/storage.ts"],"sourcesContent":["import path from \"node:path\";\nimport { access, lstat, readdir } from \"node:fs/promises\";\nimport { isSafeRouteNamespace } from \"../routing/engine.js\";\nimport { StorageManager } from \"../storage.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\nimport { namespaceIdentityToken, normalizeNamespaceIdentity } from \"./identity.js\";\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function hasStoredEntries(p: string): Promise<boolean> {\n try {\n const entry = await lstat(p);\n if (entry.isSymbolicLink()) return true;\n if (!entry.isDirectory()) return true;\n const children = await readdir(p, { withFileTypes: true });\n for (const child of children) {\n const childPath = path.join(p, child.name);\n if (child.isSymbolicLink() || child.isFile()) return true;\n if (child.isDirectory() && (await hasStoredEntries(childPath))) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n// Build a per-namespace directory under `<memoryDir>/namespaces` and assert the\n// resolved path stays inside that base. Namespace identifiers can originate from\n// operator config (config.defaultNamespace) and request-derived routing, so this\n// containment check prevents directory traversal (CodeQL js/path-injection).\n// For safe segments this returns exactly `path.join(base, segment)`, so there is\n// no behavioral change for valid namespaces.\nfunction resolveNamespaceDir(memoryDir: string, segment: string): string {\n // Mirror isSafeRouteNamespace's separator/parent-ref rejection (without its\n // 64-char cap, so identity tokens still pass). Rejecting separators and \"..\"\n // up front keeps the value a single contained child of <memoryDir>/namespaces.\n if (\n segment.length === 0 ||\n segment.includes(\"/\") ||\n segment.includes(\"\\\\\") ||\n segment.includes(\"..\") ||\n path.isAbsolute(segment)\n ) {\n throw new Error(`unsafe namespace path segment: ${segment}`);\n }\n return path.join(memoryDir, \"namespaces\", segment);\n}\n\nconst LEGACY_NAMESPACE_CONTENT_CHILDREN = [\n ...ALL_CATEGORY_DIRS,\n \"entities\",\n \"artifacts\",\n \"identity\",\n \"config\",\n \"summaries\",\n \"profile.md\",\n] as const;\n\nconst LEGACY_NAMESPACE_RUNTIME_CHILDREN = [\"state\"] as const;\n\nasync function hasAnyLegacyData(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await hasStoredEntries(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\nasync function hasAnyNamespaceStorageMarker(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await exists(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\n/**\n * Storage routing for namespaces.\n *\n * Compatibility note:\n * - When namespaces are enabled, existing raw namespace roots are preserved.\n * New namespace roots use tokenized names under `memoryDir/namespaces/<token>`.\n * - The default namespace continues to use the legacy `memoryDir` root unless the caller\n * has created `memoryDir/namespaces/<defaultNamespace>` (in which case we use that).\n *\n * This avoids surprising \"lost memories\" when an install flips namespaces on without\n * migrating existing data.\n */\n/**\n * Optional hooks for the storage router. `onResolve` fires whenever a namespace's\n * storage is resolved/created, so a downstream consumer (e.g. the namespace\n * catalog, issue #1499) can register the namespace. The hook MUST NOT throw into\n * the router; the router invokes it defensively and a hook failure never affects\n * storage resolution.\n *\n * The hook MAY return (or resolve to) a boolean indicating whether the\n * registration actually PERSISTED (round 6, codex P2 — NEFoX). When it resolves\n * to `false` (a dropped/no-op registration), the router does NOT mark the\n * (namespace, storageDir) pair as notified, so the next resolve RETRIES it\n * instead of suppressing it forever. A `void`/`undefined` result is treated as\n * success (legacy hooks).\n */\nexport interface NamespaceStorageRouterHooks {\n onResolve?: (\n namespace: string,\n storageDir: string,\n ) => void | boolean | Promise<void | boolean>;\n}\n\n/**\n * Resolve the runtime storage root for the configured DEFAULT namespace.\n *\n * Shared between the live router (`NamespaceStorageRouter.defaultNamespaceRoot`)\n * and the rebuildable catalog (`NamespaceCatalog.rebuildFromDisk`) so the two\n * can never diverge (CLAUDE.md rule #22/#42 — read & write paths resolve through\n * the same logic). The contract is: while legacy memory data still lives\n * directly under `memoryDir`, the default root stays `memoryDir`; only once the\n * legacy root is empty and a `namespaces/<default|token>` dir holds data does\n * the default migrate into that tokenized/legacy-named dir.\n */\nexport async function resolveDefaultNamespaceRoot(config: PluginConfig): Promise<string> {\n if (!config.namespacesEnabled) {\n return config.memoryDir;\n }\n\n // Build the legacy default root from the NORMALIZED (trimmed) name so a\n // whitespace-padded `defaultNamespace` still finds the live `namespaces/default`\n // root (NIabe). `storageFor()` classifies the trimmed value as the default, and\n // the on-disk legacy dir is created under the trimmed name; using the raw spaced\n // name here would look for `namespaces/<spaced>` and miss the real root, falling\n // back to memoryDir/tokenized. `namespaceIdentityToken` already normalizes\n // internally, so the tokenized path is unaffected.\n const defaultIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n const legacyNsDir = resolveNamespaceDir(config.memoryDir, defaultIdentity);\n const tokenizedNsDir = resolveNamespaceDir(\n config.memoryDir,\n namespaceIdentityToken(config.defaultNamespace),\n );\n const tokenizedHasData =\n (await exists(tokenizedNsDir)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedNsDir, { includeRuntimeState: true }));\n const nsDir = tokenizedHasData\n ? tokenizedNsDir\n : (await exists(legacyNsDir))\n ? legacyNsDir\n : tokenizedNsDir;\n return (await exists(nsDir)) && !(await hasAnyLegacyData(config.memoryDir))\n ? nsDir\n : config.memoryDir;\n}\n\n/**\n * Resolve the runtime storage root for ANY namespace exactly as the live router\n * would (`NamespaceStorageRouter.namespaceRoot`). Shared so the rebuildable\n * catalog records the SAME on-disk root the router routes to — a recall/read\n * touch must not guess `namespaces/<token>` when the router actually serves a\n * legacy raw-name dir or a migrated default root (CLAUDE.md rule #22/#42; round\n * 4, cursor Medium). The default namespace delegates to `resolveDefaultNamespaceRoot`;\n * every other namespace prefers the tokenized root when it has a storage marker,\n * else a legacy raw-name dir when present, else the tokenized root.\n */\nexport async function resolveNamespaceStorageRoot(\n config: PluginConfig,\n namespace: string,\n): Promise<string> {\n if (!config.namespacesEnabled) return config.memoryDir;\n // Compare on NORMALIZED identity so a whitespace-padded configured default name\n // still routes to the default root rather than a tokenized non-default dir\n // (NH-FH). The catalog keys records by the same normalized identity.\n if (normalizeNamespaceIdentity(namespace) === normalizeNamespaceIdentity(config.defaultNamespace)) {\n return resolveDefaultNamespaceRoot(config);\n }\n const legacyRoot = resolveNamespaceDir(config.memoryDir, namespace);\n const tokenizedRoot = resolveNamespaceDir(config.memoryDir, namespaceIdentityToken(namespace));\n if (\n (await exists(tokenizedRoot)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedRoot, { includeRuntimeState: true }))\n ) {\n return tokenizedRoot;\n }\n return (await exists(legacyRoot)) ? legacyRoot : tokenizedRoot;\n}\n\nexport class NamespaceStorageRouter {\n private readonly cache = new Map<string, StorageManager>();\n private defaultNsRootResolved: string | null = null;\n // Dedup the resolve hook (round 6, cursor Medium — NCNL2). Recall/extraction\n // call `storageFor` repeatedly; firing `onResolve` (→ catalog loadCompacted +\n // append) on every cache hit grows `namespaces.jsonl` without bound between\n // rebuilds. We fire the hook only when the (namespace, storageDir) pair is new\n // or its dir changed, so a steady-state cache hit is a no-op for the catalog.\n private readonly notifiedResolved = new Map<string, string>();\n // In-flight resolve-hook dedup (NFJV-, codex P2). The catalog's `onResolve`\n // hook is ASYNC (it returns `registerResolved(...)`), so `notifiedResolved` is\n // only set after the hook's promise SETTLES. Without tracking the in-flight\n // window, a burst of `storageFor()` cache hits for the SAME namespace before\n // the first registration finishes would each pass the `notifiedResolved` guard\n // and fire their OWN `onResolve` — queueing N duplicate catalog touches + lock\n // acquisitions despite the once-per-namespace intent. We therefore record the\n // (namespace → storageDir) being registered BEFORE awaiting the hook so a\n // concurrent call for the same pair skips firing. On SUCCESS the pair is\n // promoted to `notifiedResolved` (future calls skip permanently); on `false`\n // (dropped touch — e.g. rebuild-lock timeout) OR rejection the in-flight marker\n // is CLEARED so a later `storageFor()` can RETRY the dropped registration. The\n // entry is always removed when the promise settles, so the map cannot grow\n // unbounded (one transient entry per concurrently-resolving namespace).\n private readonly inFlightResolved = new Map<string, string>();\n\n // Normalized (trimmed) default namespace identity (NH-FH). `storageFor`\n // normalizes its input, so default-namespace branches must compare against the\n // normalized config default too — otherwise a whitespace-padded configured\n // default name routes the default namespace to a tokenized non-default root.\n private readonly defaultNamespaceIdentity: string;\n\n constructor(\n private readonly config: PluginConfig,\n private readonly hooks: NamespaceStorageRouterHooks = {},\n ) {\n this.defaultNamespaceIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n }\n\n private async defaultNamespaceRoot(): Promise<string> {\n this.defaultNsRootResolved = await resolveDefaultNamespaceRoot(this.config);\n return this.defaultNsRootResolved;\n }\n\n private async namespaceRoot(namespace: string): Promise<string> {\n // NOTE: only used after defaultNamespaceRoot() resolution.\n if (!this.config.namespacesEnabled) return this.config.memoryDir;\n if (normalizeNamespaceIdentity(namespace) === this.defaultNamespaceIdentity) {\n return this.defaultNsRootResolved ?? this.config.memoryDir;\n }\n return resolveNamespaceStorageRoot(this.config, namespace);\n }\n\n async storageFor(namespace: string): Promise<StorageManager> {\n const ns = normalizeNamespaceIdentity(namespace || this.config.defaultNamespace);\n if (ns !== this.defaultNamespaceIdentity && !isSafeRouteNamespace(ns)) {\n throw new Error(`unsafe namespace: ${ns}`);\n }\n // Even when the default namespace is exempt from the check above, every\n // on-disk path is built through resolveNamespaceDir(), which rejects\n // traversal segments — so an unsafe configured default still cannot escape\n // <memoryDir>/namespaces (CodeQL js/path-injection).\n\n let root: string;\n if (ns === this.defaultNamespaceIdentity) {\n root = await this.defaultNamespaceRoot();\n const cached = this.cache.get(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n } else {\n const cached = this.cache.get(ns);\n root = await this.namespaceRoot(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n }\n\n const sm = new StorageManager(root, this.config.entitySchemas);\n // Propagate the inline-attribution template so that router-created storages\n // (used by extraction and shared-promotion paths) strip citations consistently,\n // matching the behaviour of the primary this.storage instance in the orchestrator.\n sm.citationTemplate = this.config.inlineSourceAttributionFormat;\n this.cache.set(ns, sm);\n this.notifyResolved(ns, root);\n return sm;\n }\n\n /**\n * Fire the resolve hook defensively. A hook failure (e.g. a catalog write\n * error) MUST NOT crash storage resolution — see CLAUDE.md gotcha #13.\n */\n private notifyResolved(namespace: string, storageDir: string): void {\n const hook = this.hooks.onResolve;\n if (!hook) return;\n // Skip when we've already SUCCESSFULLY notified this exact (namespace,\n // storageDir) — a steady-state cache hit must not re-append to the catalog\n // log (NCNL2). A changed dir (rare: migration/realignment) still re-fires\n // once. We mark the pair as notified ONLY AFTER the hook succeeds, and CLEAR\n // it on failure, so a dropped registration (e.g. rebuild-lock timeout) is\n // RETRIED on the next cache hit instead of being suppressed forever (round 6,\n // cursor Medium — ND3EJ).\n if (this.notifiedResolved.get(namespace) === storageDir) return;\n // In-flight dedup (NFJV-, codex P2): if a registration for this exact\n // (namespace, storageDir) is already AWAITING its async hook, do not fire a\n // second one. Without this, concurrent cache-hit bursts before the first\n // append settles each pass the `notifiedResolved` guard above and queue\n // duplicate catalog touches/lock acquisitions. A pair with a DIFFERENT\n // in-flight dir (rare mid-migration realignment) still fires once.\n if (this.inFlightResolved.get(namespace) === storageDir) return;\n try {\n // Handle BOTH synchronous throws and asynchronous rejections (round 6,\n // codex P2 — NDo8C). The hook may be `async`; its rejected promise would\n // bypass this try/catch and, where unhandled rejections are fatal, crash\n // storage resolution. Mark the dedup pair as notified ONLY when the hook\n // resolves to a PERSISTED result (round 6, codex P2 — NEFoX): a result of\n // `false` means the registration was dropped/no-op (e.g. rebuild-lock\n // timeout), so we must NOT suppress its retry. `void`/`undefined` is treated\n // as success for legacy hooks. On rejection we leave it un-notified to retry.\n //\n // Record the in-flight marker BEFORE awaiting so concurrent calls for the\n // same pair skip (NFJV-). It is always cleared once the promise settles, so\n // the map holds at most one transient entry per concurrently-resolving\n // namespace and cannot grow unbounded.\n this.inFlightResolved.set(namespace, storageDir);\n Promise.resolve(hook(namespace, storageDir)).then(\n (persisted) => {\n // Clear the in-flight marker ONLY if it is still ours (a newer resolve\n // for a different dir may have replaced it).\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (persisted !== false) {\n this.notifiedResolved.set(namespace, storageDir);\n }\n // On `false` (dropped touch) we intentionally do NOT mark notified, so\n // a later `storageFor()` retries the registration. Clearing the\n // in-flight marker above is what re-enables that retry.\n },\n () => {\n // Registration failed — clear in-flight AND do NOT mark as notified, so\n // it is retried on the next cache hit.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (this.notifiedResolved.get(namespace) === storageDir) {\n this.notifiedResolved.delete(namespace);\n }\n },\n );\n } catch {\n // Synchronous throw: clear any in-flight marker we just set and leave the\n // pair un-notified so a later resolve retries.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
SPECULATIVE_TTL_DAYS,
|
|
15
15
|
confidenceTier
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NE2JBMLN.js";
|
|
17
17
|
import {
|
|
18
18
|
getCachedEntities,
|
|
19
19
|
invalidateCachedEntities,
|
|
@@ -5561,4 +5561,4 @@ export {
|
|
|
5561
5561
|
serializeEntityFile,
|
|
5562
5562
|
StorageManager
|
|
5563
5563
|
};
|
|
5564
|
-
//# sourceMappingURL=chunk-
|
|
5564
|
+
//# sourceMappingURL=chunk-6CVI6BP6.js.map
|
|
@@ -33,6 +33,34 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
33
33
|
let message = "";
|
|
34
34
|
let supersedeFailed = false;
|
|
35
35
|
let rollbackAfterResolveFailure = null;
|
|
36
|
+
let recordCatalogWriteTouch = null;
|
|
37
|
+
const buildCatalogTouch = () => {
|
|
38
|
+
if (!options.onMergedMemoryWritten) return null;
|
|
39
|
+
const onMergedMemoryWritten = options.onMergedMemoryWritten;
|
|
40
|
+
const namespace = pair.namespace;
|
|
41
|
+
const storageDir = resolutionStorage.dir;
|
|
42
|
+
return () => onMergedMemoryWritten(namespace, storageDir);
|
|
43
|
+
};
|
|
44
|
+
const catalogWriteTouch = buildCatalogTouch();
|
|
45
|
+
const recordCatalogWriteTouchSafely = (context, touch = catalogWriteTouch) => {
|
|
46
|
+
if (!touch) return;
|
|
47
|
+
try {
|
|
48
|
+
touch();
|
|
49
|
+
} catch (err) {
|
|
50
|
+
log.warn(
|
|
51
|
+
"[contradiction-resolution] catalog write touch failed for pair=%s context=%s: %s",
|
|
52
|
+
pairId,
|
|
53
|
+
context,
|
|
54
|
+
err instanceof Error ? err.message : err
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const touchCatalogIfRollbackLeftChange = async (context, snapshots, replacement) => {
|
|
59
|
+
if (!catalogWriteTouch) return;
|
|
60
|
+
if (await rollbackLeftDurableMutation(resolutionStorage, snapshots, replacement)) {
|
|
61
|
+
recordCatalogWriteTouchSafely(context);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
36
64
|
switch (verb) {
|
|
37
65
|
case "keep-a": {
|
|
38
66
|
const keepTarget = await validateKeepTarget(resolutionStorage, pairId, idA);
|
|
@@ -46,10 +74,14 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
46
74
|
if (ok) {
|
|
47
75
|
affectedIds.push(idB);
|
|
48
76
|
rollbackAfterResolveFailure = async () => restoreMemorySnapshot(resolutionStorage, sourceB, "contradiction-resolution:keep-a-rollback");
|
|
77
|
+
recordCatalogWriteTouch = catalogWriteTouch;
|
|
49
78
|
message = `Kept ${idA}, superseded ${idB}`;
|
|
50
79
|
} else {
|
|
51
80
|
supersedeFailed = true;
|
|
52
81
|
const rolledBack = sourceB ? await restoreMemorySnapshot(resolutionStorage, sourceB, "contradiction-resolution:keep-a-rollback") : false;
|
|
82
|
+
if (sourceB && !rolledBack) {
|
|
83
|
+
await touchCatalogIfRollbackLeftChange("keep-a-rollback-incomplete", [sourceB]);
|
|
84
|
+
}
|
|
53
85
|
message = rolledBack ? `Supersede failed for ${idB}; restored ${idB} and did not resolve` : `Supersede failed for ${idB}; rollback incomplete for ${idB} and pair is not resolved`;
|
|
54
86
|
}
|
|
55
87
|
break;
|
|
@@ -66,10 +98,14 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
66
98
|
if (ok) {
|
|
67
99
|
affectedIds.push(idA);
|
|
68
100
|
rollbackAfterResolveFailure = async () => restoreMemorySnapshot(resolutionStorage, sourceA, "contradiction-resolution:keep-b-rollback");
|
|
101
|
+
recordCatalogWriteTouch = catalogWriteTouch;
|
|
69
102
|
message = `Kept ${idB}, superseded ${idA}`;
|
|
70
103
|
} else {
|
|
71
104
|
supersedeFailed = true;
|
|
72
105
|
const rolledBack = sourceA ? await restoreMemorySnapshot(resolutionStorage, sourceA, "contradiction-resolution:keep-b-rollback") : false;
|
|
106
|
+
if (sourceA && !rolledBack) {
|
|
107
|
+
await touchCatalogIfRollbackLeftChange("keep-b-rollback-incomplete", [sourceA]);
|
|
108
|
+
}
|
|
73
109
|
message = rolledBack ? `Supersede failed for ${idA}; restored ${idA} and did not resolve` : `Supersede failed for ${idA}; rollback incomplete for ${idA} and pair is not resolved`;
|
|
74
110
|
}
|
|
75
111
|
break;
|
|
@@ -88,6 +124,8 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
88
124
|
message = rolledBackA ? `Merge failed for ${idA}; restored ${idA} and did not resolve` : `Merge failed for ${idA}; rollback incomplete for ${idA} and pair is not resolved`;
|
|
89
125
|
if (rolledBackA) {
|
|
90
126
|
await cleanupCreatedReplacement(resolutionStorage, replacement);
|
|
127
|
+
} else {
|
|
128
|
+
await touchCatalogIfRollbackLeftChange("merge-first-rollback-incomplete", [replacement.sourceA], replacement);
|
|
91
129
|
}
|
|
92
130
|
break;
|
|
93
131
|
}
|
|
@@ -102,6 +140,12 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
102
140
|
].filter(Boolean).join(", ")} and pair is not resolved`;
|
|
103
141
|
if (rolledBackA && rolledBackB) {
|
|
104
142
|
await cleanupCreatedReplacement(resolutionStorage, replacement);
|
|
143
|
+
} else {
|
|
144
|
+
await touchCatalogIfRollbackLeftChange(
|
|
145
|
+
"merge-second-rollback-incomplete",
|
|
146
|
+
[replacement.sourceA, replacement.sourceB],
|
|
147
|
+
replacement
|
|
148
|
+
);
|
|
105
149
|
}
|
|
106
150
|
break;
|
|
107
151
|
}
|
|
@@ -114,6 +158,7 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
114
158
|
}
|
|
115
159
|
return rolledBackA && rolledBackB;
|
|
116
160
|
};
|
|
161
|
+
recordCatalogWriteTouch = catalogWriteTouch;
|
|
117
162
|
message = `Both memories superseded by merged ${replacement.mergedId}`;
|
|
118
163
|
break;
|
|
119
164
|
}
|
|
@@ -142,10 +187,15 @@ async function executeResolution(memoryDir, storage, pairId, verb, options = {})
|
|
|
142
187
|
if (rollbackAfterResolveFailure) {
|
|
143
188
|
const rolledBack = await rollbackAfterResolveFailure();
|
|
144
189
|
affectedIds.length = 0;
|
|
145
|
-
message = rolledBack ? `Resolution persistence failed; rolled back memory changes and did not resolve ${pairId}` :
|
|
190
|
+
message = rolledBack ? `Resolution persistence failed; rolled back memory changes and did not resolve ${pairId}` : "Resolution persistence failed; rollback incomplete and pair is not resolved";
|
|
191
|
+
if (!rolledBack && recordCatalogWriteTouch) {
|
|
192
|
+
recordCatalogWriteTouchSafely("resolve-persistence-rollback-incomplete", recordCatalogWriteTouch);
|
|
193
|
+
}
|
|
146
194
|
} else {
|
|
147
|
-
message =
|
|
195
|
+
message = "Resolution persistence failed; pair is not resolved";
|
|
148
196
|
}
|
|
197
|
+
} else if (recordCatalogWriteTouch) {
|
|
198
|
+
recordCatalogWriteTouchSafely("resolved", recordCatalogWriteTouch);
|
|
149
199
|
}
|
|
150
200
|
}
|
|
151
201
|
log.info("[contradiction-resolution] pair=%s verb=%s affected=%d", pairId, verb, affectedIds.length);
|
|
@@ -257,6 +307,38 @@ async function restoreMemorySnapshot(storage, memory, reasonCode = "contradictio
|
|
|
257
307
|
return false;
|
|
258
308
|
}
|
|
259
309
|
}
|
|
310
|
+
async function rollbackLeftDurableMutation(storage, snapshots, replacement) {
|
|
311
|
+
for (const snapshot of snapshots) {
|
|
312
|
+
try {
|
|
313
|
+
const current = await storage.getMemoryById(snapshot.frontmatter.id);
|
|
314
|
+
if (!current) return true;
|
|
315
|
+
if (supersessionStateChanged(current, snapshot)) return true;
|
|
316
|
+
} catch (err) {
|
|
317
|
+
log.warn(
|
|
318
|
+
"[contradiction-resolution] rollback inspection failed for %s: %s",
|
|
319
|
+
snapshot.frontmatter.id,
|
|
320
|
+
err instanceof Error ? err.message : err
|
|
321
|
+
);
|
|
322
|
+
return true;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
if (replacement?.created) {
|
|
326
|
+
try {
|
|
327
|
+
return await storage.getMemoryById(replacement.mergedId) !== null;
|
|
328
|
+
} catch (err) {
|
|
329
|
+
log.warn(
|
|
330
|
+
"[contradiction-resolution] rollback replacement inspection failed for %s: %s",
|
|
331
|
+
replacement.mergedId,
|
|
332
|
+
err instanceof Error ? err.message : err
|
|
333
|
+
);
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
function supersessionStateChanged(current, snapshot) {
|
|
340
|
+
return current.frontmatter.status !== snapshot.frontmatter.status || current.frontmatter.supersededBy !== snapshot.frontmatter.supersededBy || current.frontmatter.supersededAt !== snapshot.frontmatter.supersededAt;
|
|
341
|
+
}
|
|
260
342
|
async function cleanupCreatedReplacement(storage, replacement) {
|
|
261
343
|
if (!replacement.created) return;
|
|
262
344
|
await cleanupMemoryId(storage, replacement.mergedId);
|
|
@@ -299,4 +381,4 @@ export {
|
|
|
299
381
|
isValidResolutionVerb,
|
|
300
382
|
executeResolution
|
|
301
383
|
};
|
|
302
|
-
//# sourceMappingURL=chunk-
|
|
384
|
+
//# sourceMappingURL=chunk-6IMKOIZ6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contradiction/resolution.ts"],"sourcesContent":["/**\n * Resolution Verbs — executes user-chosen resolution actions on contradiction pairs (issue #520).\n *\n * All resolution paths delegate to StorageManager.supersedeMemory. Do not\n * reimplement supersession logic here (rule 22: deduplicate resolution).\n */\n\nimport { log } from \"../logger.js\";\nimport type { StorageManager } from \"../storage.js\";\nimport type { MemoryCategory, MemoryFile } from \"../types.js\";\nimport type { ResolutionVerb } from \"./contradiction-review.js\";\nimport { readPair, resolvePair } from \"./contradiction-review.js\";\n\nexport interface ResolutionResult {\n pairId: string;\n verb: ResolutionVerb;\n /** Memory IDs affected by the resolution. */\n affectedIds: string[];\n /** Human-readable status. */\n message: string;\n}\n\nexport interface ExecuteResolutionOptions {\n /** Existing merged memory to supersede both source memories to. */\n mergedMemoryId?: string;\n /** Content for a new merged memory. Required for merge when mergedMemoryId is omitted. */\n mergedContent?: string;\n /** Category for a newly created merged memory. Defaults to the shared source category, or fact. */\n mergedCategory?: MemoryCategory;\n /** Resolve storage for the pair namespace, or the default namespace for legacy unscoped pairs. */\n storageForNamespace?: (namespace: string | undefined) => StorageManager | Promise<StorageManager>;\n /**\n * Best-effort hook invoked after a contradiction resolution leaves a durable\n * mutation in the namespace's memory files (issue #1499 sweep, NH1dX / NH3X3).\n * Every mutating verb — `merge` (creates a new memory and supersedes both\n * sources), `keep-a`, and `keep-b` (supersede the losing source + rewrite\n * frontmatter) — writes directly to the pair's (possibly DYNAMIC) namespace\n * storage, bypassing the extraction write path that records catalog writes. So\n * without this the namespace's `lastWriteAt` stays stale and QMD maintenance /\n * `writtenSince` can skip a namespace whose only post-write mutation is\n * resolving a contradiction. It fires after the resolution commits, or after a\n * failed resolution/rollback path when durable memory changes are still left on\n * disk. If a failure rolls back cleanly, this is never called, so the catalog\n * never records a write that did not survive (rule #25). Non-mutating verbs\n * (`both-valid`, `needs-more-context`) never trigger it. Callers wire this to\n * `Orchestrator.recordCatalogWrite(namespace, storageDir)`. Must be\n * failure-tolerant: it is fire-and-forget and must never affect resolution.\n */\n onMergedMemoryWritten?: (namespace: string | undefined, storageDir: string) => void;\n}\n\nconst VALID_VERBS: ResolutionVerb[] = [\"keep-a\", \"keep-b\", \"merge\", \"both-valid\", \"needs-more-context\"];\n\nexport function isValidResolutionVerb(value: string): value is ResolutionVerb {\n return VALID_VERBS.includes(value as ResolutionVerb);\n}\n\n/**\n * Execute a resolution verb on a contradiction pair.\n *\n * - `keep-a`: Supersede B, keep A active.\n * - `keep-b`: Supersede A, keep B active.\n * - `merge`: Create or verify a real merged memory, then supersede both inputs.\n * - `both-valid`: Mark pair as reviewed; no memories are superseded.\n * - `needs-more-context`: Defer; no action, short cooldown.\n */\nexport async function executeResolution(\n memoryDir: string,\n storage: StorageManager,\n pairId: string,\n verb: ResolutionVerb,\n options: ExecuteResolutionOptions = {},\n): Promise<ResolutionResult> {\n if (typeof verb !== \"string\" || !isValidResolutionVerb(verb)) {\n throw new Error(`Invalid contradiction resolution verb: ${String(verb)}`);\n }\n\n const pair = readPair(memoryDir, pairId);\n if (!pair) {\n return { pairId, verb, affectedIds: [], message: `Pair ${pairId} not found` };\n }\n\n if (pair.namespace && !options.storageForNamespace) {\n throw new Error(\n \"contradiction resolution requires storageForNamespace for namespaced pairs so callers resolve the correct namespace storage\",\n );\n }\n\n const resolutionStorage = options.storageForNamespace\n ? await options.storageForNamespace(pair.namespace)\n : storage;\n\n if (pair.resolution && pair.resolution !== \"needs-more-context\") {\n return { pairId, verb, affectedIds: [], message: `Pair already resolved with verb \"${pair.resolution}\"` };\n }\n\n const [idA, idB] = pair.memoryIds;\n const affectedIds: string[] = [];\n let message = \"\";\n let supersedeFailed = false;\n let rollbackAfterResolveFailure: (() => Promise<boolean>) | null = null;\n // Deferred catalog-write touch for any resolution that leaves durable namespace\n // memory mutations (issue #1499 sweep, NH1dX / NH3X3). Rule #25: never record a\n // catalog touch for a write that is fully rolled back. Successful mutating\n // resolutions invoke it after `resolvePair` persists. Failed paths invoke it\n // only when rollback inspection shows the namespace still differs from the\n // pre-mutation snapshot.\n let recordCatalogWriteTouch: (() => void) | null = null;\n // Returns the deferred touch fn for a mutating verb (or null when the caller\n // wired no catalog hook), so each branch assigns `recordCatalogWriteTouch`\n // directly in the function body — keeping TS control-flow narrowing intact at\n // the post-commit invocation below.\n const buildCatalogTouch = (): (() => void) | null => {\n if (!options.onMergedMemoryWritten) return null;\n const onMergedMemoryWritten = options.onMergedMemoryWritten;\n const namespace = pair.namespace;\n const storageDir = resolutionStorage.dir;\n return () => onMergedMemoryWritten(namespace, storageDir);\n };\n const catalogWriteTouch = buildCatalogTouch();\n const recordCatalogWriteTouchSafely = (context: string, touch = catalogWriteTouch): void => {\n if (!touch) return;\n try {\n touch();\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] catalog write touch failed for pair=%s context=%s: %s\",\n pairId,\n context,\n err instanceof Error ? err.message : err,\n );\n }\n };\n const touchCatalogIfRollbackLeftChange = async (\n context: string,\n snapshots: MemoryFile[],\n replacement?: Extract<MergeReplacement, { ok: true }>,\n ): Promise<void> => {\n if (!catalogWriteTouch) return;\n if (await rollbackLeftDurableMutation(resolutionStorage, snapshots, replacement)) {\n recordCatalogWriteTouchSafely(context);\n }\n };\n\n switch (verb) {\n case \"keep-a\": {\n const keepTarget = await validateKeepTarget(resolutionStorage, pairId, idA);\n if (!keepTarget.ok) {\n supersedeFailed = true;\n message = keepTarget.message;\n break;\n }\n const sourceB = await loadSourceSnapshot(resolutionStorage, idB);\n const ok = sourceB\n ? await supersedeSafe(resolutionStorage, idB, idA, \"contradiction-resolution:keep-a\")\n : false;\n if (ok) {\n affectedIds.push(idB);\n rollbackAfterResolveFailure = async () =>\n restoreMemorySnapshot(resolutionStorage, sourceB!, \"contradiction-resolution:keep-a-rollback\");\n // keep-a superseded idB in this namespace — record a catalog touch once\n // the resolution durably commits (NH3X3).\n recordCatalogWriteTouch = catalogWriteTouch;\n message = `Kept ${idA}, superseded ${idB}`;\n }\n else {\n supersedeFailed = true;\n const rolledBack = sourceB\n ? await restoreMemorySnapshot(resolutionStorage, sourceB, \"contradiction-resolution:keep-a-rollback\")\n : false;\n if (sourceB && !rolledBack) {\n await touchCatalogIfRollbackLeftChange(\"keep-a-rollback-incomplete\", [sourceB]);\n }\n message = rolledBack\n ? `Supersede failed for ${idB}; restored ${idB} and did not resolve`\n : `Supersede failed for ${idB}; rollback incomplete for ${idB} and pair is not resolved`;\n }\n break;\n }\n case \"keep-b\": {\n const keepTarget = await validateKeepTarget(resolutionStorage, pairId, idB);\n if (!keepTarget.ok) {\n supersedeFailed = true;\n message = keepTarget.message;\n break;\n }\n const sourceA = await loadSourceSnapshot(resolutionStorage, idA);\n const ok = sourceA\n ? await supersedeSafe(resolutionStorage, idA, idB, \"contradiction-resolution:keep-b\")\n : false;\n if (ok) {\n affectedIds.push(idA);\n rollbackAfterResolveFailure = async () =>\n restoreMemorySnapshot(resolutionStorage, sourceA!, \"contradiction-resolution:keep-b-rollback\");\n // keep-b superseded idA in this namespace — record a catalog touch once\n // the resolution durably commits (NH3X3).\n recordCatalogWriteTouch = catalogWriteTouch;\n message = `Kept ${idB}, superseded ${idA}`;\n }\n else {\n supersedeFailed = true;\n const rolledBack = sourceA\n ? await restoreMemorySnapshot(resolutionStorage, sourceA, \"contradiction-resolution:keep-b-rollback\")\n : false;\n if (sourceA && !rolledBack) {\n await touchCatalogIfRollbackLeftChange(\"keep-b-rollback-incomplete\", [sourceA]);\n }\n message = rolledBack\n ? `Supersede failed for ${idA}; restored ${idA} and did not resolve`\n : `Supersede failed for ${idA}; rollback incomplete for ${idA} and pair is not resolved`;\n }\n break;\n }\n case \"merge\": {\n const replacement = await prepareMergeReplacement(resolutionStorage, pairId, idA, idB, options);\n if (!replacement.ok) {\n supersedeFailed = true;\n message = replacement.message;\n break;\n }\n\n const okA = await supersedeSafe(resolutionStorage, idA, replacement.mergedId, \"contradiction-resolution:merge\");\n if (!okA) {\n supersedeFailed = true;\n const rolledBackA = await restoreMemorySnapshot(resolutionStorage, replacement.sourceA);\n message = rolledBackA\n ? `Merge failed for ${idA}; restored ${idA} and did not resolve`\n : `Merge failed for ${idA}; rollback incomplete for ${idA} and pair is not resolved`;\n if (rolledBackA) {\n await cleanupCreatedReplacement(resolutionStorage, replacement);\n }\n else {\n await touchCatalogIfRollbackLeftChange(\"merge-first-rollback-incomplete\", [replacement.sourceA], replacement);\n }\n break;\n }\n\n const okB = await supersedeSafe(resolutionStorage, idB, replacement.mergedId, \"contradiction-resolution:merge\");\n if (!okB) {\n supersedeFailed = true;\n const rolledBackA = await restoreMemorySnapshot(resolutionStorage, replacement.sourceA);\n const rolledBackB = await restoreMemorySnapshot(resolutionStorage, replacement.sourceB);\n message = rolledBackA && rolledBackB\n ? `Merge failed for ${idB}; restored ${idA} and ${idB} and did not resolve`\n : `Merge failed for ${idB}; rollback incomplete for ${[\n rolledBackA ? undefined : idA,\n rolledBackB ? undefined : idB,\n ].filter(Boolean).join(\", \")} and pair is not resolved`;\n if (rolledBackA && rolledBackB) {\n await cleanupCreatedReplacement(resolutionStorage, replacement);\n }\n else {\n await touchCatalogIfRollbackLeftChange(\n \"merge-second-rollback-incomplete\",\n [replacement.sourceA, replacement.sourceB],\n replacement,\n );\n }\n break;\n }\n\n affectedIds.push(idA, idB);\n rollbackAfterResolveFailure = async () => {\n const rolledBackA = await restoreMemorySnapshot(resolutionStorage, replacement.sourceA);\n const rolledBackB = await restoreMemorySnapshot(resolutionStorage, replacement.sourceB);\n if (rolledBackA && rolledBackB) {\n await cleanupCreatedReplacement(resolutionStorage, replacement);\n }\n return rolledBackA && rolledBackB;\n };\n // Catalog write touch (issue #1499 sweep): the merge supersedes BOTH sources\n // (and, when created, writes a fresh merged memory) in the pair's (possibly\n // dynamic) namespace storage — but the resolution is not durable yet\n // (resolvePair persists below, and a failure rolls the merge back). Defer\n // the touch so it fires ONLY after the resolution commits past the rollback\n // point (NH1dX, rule #25). Arm it for EVERY successful merge — even reusing\n // an existing merged-id still supersedes both sources, a namespace mutation\n // that must refresh `lastWriteAt` (NH3X3). Otherwise a dynamic namespace\n // whose only durable mutation is a contradiction merge stays invisible to\n // QMD maintenance / `writtenSince`. Best-effort on the caller side.\n recordCatalogWriteTouch = catalogWriteTouch;\n message = `Both memories superseded by merged ${replacement.mergedId}`;\n break;\n }\n case \"both-valid\": {\n message = \"Pair marked as both-valid; cooldown applied\";\n break;\n }\n case \"needs-more-context\": {\n message = \"Deferred; no action taken, short cooldown applied\";\n break;\n }\n }\n\n if (!supersedeFailed) {\n let resolved = false;\n try {\n resolved = resolvePair(memoryDir, pairId, verb) !== null;\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] failed to persist pair=%s verb=%s: %s\",\n pairId,\n verb,\n err instanceof Error ? err.message : err,\n );\n }\n if (!resolved) {\n if (rollbackAfterResolveFailure) {\n const rolledBack = await rollbackAfterResolveFailure();\n affectedIds.length = 0;\n message = rolledBack\n ? `Resolution persistence failed; rolled back memory changes and did not resolve ${pairId}`\n : \"Resolution persistence failed; rollback incomplete and pair is not resolved\";\n if (!rolledBack && recordCatalogWriteTouch) {\n recordCatalogWriteTouchSafely(\"resolve-persistence-rollback-incomplete\", recordCatalogWriteTouch);\n }\n } else {\n message = \"Resolution persistence failed; pair is not resolved\";\n }\n } else if (recordCatalogWriteTouch) {\n // The resolution durably committed (memory mutated AND the resolution\n // persisted past the rollback point). Only now is it safe to record the\n // catalog write for the namespace mutation (NH1dX / NH3X3, rule #25).\n // Best-effort: the caller's callback swallows errors; guard here so a\n // throwing callback never derails a successful resolution.\n recordCatalogWriteTouchSafely(\"resolved\", recordCatalogWriteTouch);\n }\n }\n log.info(\"[contradiction-resolution] pair=%s verb=%s affected=%d\", pairId, verb, affectedIds.length);\n return { pairId, verb, affectedIds, message };\n}\n\ntype MergeReplacement =\n | {\n ok: true;\n mergedId: string;\n sourceA: MemoryFile;\n sourceB: MemoryFile;\n created: boolean;\n }\n | {\n ok: false;\n message: string;\n };\n\nasync function prepareMergeReplacement(\n storage: StorageManager,\n pairId: string,\n idA: string,\n idB: string,\n options: ExecuteResolutionOptions,\n): Promise<MergeReplacement> {\n const sourceA = await storage.getMemoryById(idA);\n const sourceB = await storage.getMemoryById(idB);\n if (!sourceA || !sourceB) {\n return { ok: false, message: `Merge requires both source memories to exist; not resolving ${pairId}` };\n }\n\n const requestedMergedId = options.mergedMemoryId?.trim();\n if (requestedMergedId) {\n if (requestedMergedId === idA || requestedMergedId === idB) {\n return { ok: false, message: \"Merge replacement must be distinct from both source memories; not resolving\" };\n }\n const replacement = await storage.getMemoryById(requestedMergedId);\n if (!replacement) {\n return { ok: false, message: `Merged memory ${requestedMergedId} not found; not resolving` };\n }\n const replacementStatus = replacement.frontmatter.status ?? \"active\";\n if (replacementStatus !== \"active\") {\n return {\n ok: false,\n message: `Merged memory ${requestedMergedId} is ${replacementStatus}; not resolving`,\n };\n }\n return { ok: true, mergedId: requestedMergedId, sourceA, sourceB, created: false };\n }\n\n const mergedContent = options.mergedContent;\n if (typeof mergedContent !== \"string\" || mergedContent.trim().length === 0) {\n return {\n ok: false,\n message: \"Merge requires mergedMemoryId or mergedContent; no memories changed\",\n };\n }\n\n const category = options.mergedCategory ?? mergedMemoryCategory(sourceA, sourceB);\n let mergedId: string;\n try {\n mergedId = await storage.writeMemory(category, mergedContent, {\n actor: \"contradiction-resolution\",\n confidence: Math.min(sourceA.frontmatter.confidence ?? 0.8, sourceB.frontmatter.confidence ?? 0.8),\n tags: [\"contradiction-resolution\", \"merge\"],\n source: \"contradiction-resolution\",\n lineage: [idA, idB],\n derivedVia: \"merge\",\n });\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] merged memory creation failed for %s: %s\",\n pairId,\n err instanceof Error ? err.message : err,\n );\n return { ok: false, message: `Merged memory could not be created; not resolving ${pairId}` };\n }\n const replacement = await storage.getMemoryById(mergedId);\n if (!replacement) {\n await cleanupMemoryId(storage, mergedId);\n return { ok: false, message: `Merged memory ${mergedId} could not be verified; not resolving` };\n }\n return { ok: true, mergedId, sourceA, sourceB, created: true };\n}\n\nfunction mergedMemoryCategory(sourceA: MemoryFile, sourceB: MemoryFile): MemoryCategory {\n return sourceA.frontmatter.category === sourceB.frontmatter.category\n ? sourceA.frontmatter.category\n : \"fact\";\n}\n\ntype KeepTargetValidation =\n | { ok: true }\n | { ok: false; message: string };\n\nasync function validateKeepTarget(\n storage: StorageManager,\n pairId: string,\n keepId: string,\n): Promise<KeepTargetValidation> {\n const target = await loadSourceSnapshot(storage, keepId);\n if (!target) {\n return { ok: false, message: `Kept memory ${keepId} not found; not resolving ${pairId}` };\n }\n\n const status = target.frontmatter.status ?? \"active\";\n if (status !== \"active\") {\n return { ok: false, message: `Kept memory ${keepId} is ${status}; not resolving ${pairId}` };\n }\n\n return { ok: true };\n}\n\nasync function loadSourceSnapshot(storage: StorageManager, memoryId: string): Promise<MemoryFile | null> {\n try {\n return await storage.getMemoryById(memoryId);\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] source snapshot failed for %s: %s\",\n memoryId,\n err instanceof Error ? err.message : err,\n );\n return null;\n }\n}\n\nasync function restoreMemorySnapshot(\n storage: StorageManager,\n memory: MemoryFile,\n reasonCode = \"contradiction-resolution:merge-rollback\",\n): Promise<boolean> {\n try {\n const current = await storage.getMemoryById(memory.frontmatter.id);\n if (!current) return false;\n const restoredFrontmatter: Partial<MemoryFile[\"frontmatter\"]> = {\n ...memory.frontmatter,\n status: memory.frontmatter.status,\n supersededBy: memory.frontmatter.supersededBy,\n supersededAt: memory.frontmatter.supersededAt,\n };\n return await storage.writeMemoryFrontmatter(current, restoredFrontmatter, {\n actor: \"contradiction-resolution\",\n reasonCode,\n });\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] rollback failed for %s: %s\",\n memory.frontmatter.id,\n err instanceof Error ? err.message : err,\n );\n return false;\n }\n}\n\nasync function rollbackLeftDurableMutation(\n storage: StorageManager,\n snapshots: MemoryFile[],\n replacement?: Extract<MergeReplacement, { ok: true }>,\n): Promise<boolean> {\n for (const snapshot of snapshots) {\n try {\n const current = await storage.getMemoryById(snapshot.frontmatter.id);\n if (!current) return true;\n if (supersessionStateChanged(current, snapshot)) return true;\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] rollback inspection failed for %s: %s\",\n snapshot.frontmatter.id,\n err instanceof Error ? err.message : err,\n );\n return true;\n }\n }\n\n if (replacement?.created) {\n try {\n return (await storage.getMemoryById(replacement.mergedId)) !== null;\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] rollback replacement inspection failed for %s: %s\",\n replacement.mergedId,\n err instanceof Error ? err.message : err,\n );\n return true;\n }\n }\n\n return false;\n}\n\nfunction supersessionStateChanged(current: MemoryFile, snapshot: MemoryFile): boolean {\n return (\n current.frontmatter.status !== snapshot.frontmatter.status ||\n current.frontmatter.supersededBy !== snapshot.frontmatter.supersededBy ||\n current.frontmatter.supersededAt !== snapshot.frontmatter.supersededAt\n );\n}\n\nasync function cleanupCreatedReplacement(storage: StorageManager, replacement: Extract<MergeReplacement, { ok: true }>): Promise<void> {\n if (!replacement.created) return;\n await cleanupMemoryId(storage, replacement.mergedId);\n}\n\nasync function cleanupMemoryId(storage: StorageManager, memoryId: string): Promise<void> {\n try {\n const memory = await storage.getMemoryById(memoryId);\n const invalidated = await storage.invalidateMemory(memoryId);\n if (invalidated && memory?.frontmatter.category === \"fact\") {\n await storage.removeFactContentHashesForMemories([memory]);\n }\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] cleanup failed for merged memory %s: %s\",\n memoryId,\n err instanceof Error ? err.message : err,\n );\n }\n}\n\nasync function supersedeSafe(\n storage: StorageManager,\n oldId: string,\n newId: string,\n reason: string,\n): Promise<boolean> {\n try {\n const result = await storage.supersedeMemory(oldId, newId, reason);\n if (result === false) {\n log.warn(\"[contradiction-resolution] supersede returned false for %s → %s\", oldId, newId);\n return false;\n }\n return true;\n } catch (err) {\n log.warn(\n \"[contradiction-resolution] supersede failed %s → %s: %s\",\n oldId,\n newId,\n err instanceof Error ? err.message : err,\n );\n return false;\n }\n}\n"],"mappings":"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","names":["replacement"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listNamespaces
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-BP2EV6W5.js";
|
|
4
4
|
import {
|
|
5
5
|
runConsolidationProvenanceCheck
|
|
6
6
|
} from "./chunk-AL4RAJL5.js";
|
|
@@ -32,17 +32,17 @@ import {
|
|
|
32
32
|
} from "./chunk-AJU4PJGY.js";
|
|
33
33
|
import {
|
|
34
34
|
parseConfig
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-YLZLPVKK.js";
|
|
36
36
|
import {
|
|
37
37
|
listMemoryGovernanceRuns,
|
|
38
38
|
readMemoryGovernanceRunArtifact
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-XWQ6ERUG.js";
|
|
40
40
|
import {
|
|
41
41
|
analyzeGraphHealth
|
|
42
42
|
} from "./chunk-Y56J7CXW.js";
|
|
43
43
|
import {
|
|
44
44
|
StorageManager
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-6CVI6BP6.js";
|
|
46
46
|
import {
|
|
47
47
|
lintWorkspaceFiles
|
|
48
48
|
} from "./chunk-DM2T26WE.js";
|
|
@@ -1336,4 +1336,4 @@ export {
|
|
|
1336
1336
|
runBenchmarkRecall,
|
|
1337
1337
|
runOperatorRepair
|
|
1338
1338
|
};
|
|
1339
|
-
//# sourceMappingURL=chunk-
|
|
1339
|
+
//# sourceMappingURL=chunk-BJA6DQOC.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NamespaceStorageRouter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3RACUBII.js";
|
|
4
4
|
import {
|
|
5
5
|
namespaceCollectionName
|
|
6
6
|
} from "./chunk-JVRPJ7D4.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "./chunk-ZFXCQPNO.js";
|
|
11
11
|
import {
|
|
12
12
|
ALL_CATEGORY_DIRS
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6CVI6BP6.js";
|
|
14
14
|
import {
|
|
15
15
|
isSafeRouteNamespace
|
|
16
16
|
} from "./chunk-U3PN77QT.js";
|
|
@@ -204,4 +204,4 @@ export {
|
|
|
204
204
|
verifyNamespaces,
|
|
205
205
|
runNamespaceMigration
|
|
206
206
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
207
|
+
//# sourceMappingURL=chunk-BP2EV6W5.js.map
|