@remnic/core 9.3.716 → 9.3.718
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-boundary.d.ts +5 -5
- package/dist/access-boundary.js +10 -9
- package/dist/access-cli.js +26 -25
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +14 -13
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +13 -12
- package/dist/access-operations-batch.js +11 -10
- package/dist/access-operations.d.ts +5 -5
- package/dist/access-operations.js +12 -11
- package/dist/{access-service-BW8cm_uU.d.ts → access-service-CZbnt0t2.d.ts} +4 -4
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +9 -8
- package/dist/access-surface-catalog.d.ts +5 -5
- 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 +4 -4
- package/dist/briefing.d.ts +3 -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/capabilities.d.ts +1 -1
- package/dist/{catalog-CbR0CsUw.d.ts → catalog-CEYlMs9X.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-JEIROMLX.js → chunk-2COL35PK.js} +95 -9
- package/dist/chunk-2COL35PK.js.map +1 -0
- package/dist/{chunk-XZTUMWKQ.js → chunk-2PTBLS2S.js} +2 -2
- package/dist/{chunk-2Y6LMOQQ.js → chunk-2VHMVWPU.js} +2 -2
- package/dist/{chunk-6UU43ZGD.js → chunk-4KZGLDJJ.js} +2 -2
- package/dist/{chunk-K44MIN6D.js → chunk-5RHM43BJ.js} +3 -3
- package/dist/{chunk-MECU6WSH.js → chunk-72VDBALG.js} +18 -18
- package/dist/{chunk-UY4JMEAK.js → chunk-7EEVXW7X.js} +2 -2
- package/dist/{chunk-XCTDHF7U.js → chunk-A5TUPZ3N.js} +33 -1
- package/dist/chunk-A5TUPZ3N.js.map +1 -0
- package/dist/{chunk-WI4QX7GH.js → chunk-A66YRSOS.js} +2 -2
- package/dist/{chunk-CTAHKIG6.js → chunk-ANI5DUAE.js} +10 -8
- package/dist/{chunk-CTAHKIG6.js.map → chunk-ANI5DUAE.js.map} +1 -1
- package/dist/{chunk-O62P2LFL.js → chunk-APUJIMDM.js} +2 -2
- package/dist/{chunk-MPHDVHIB.js → chunk-DIFU33GU.js} +2 -2
- package/dist/{chunk-DXGS5YOQ.js → chunk-EH27LHML.js} +2 -2
- package/dist/{chunk-BNOAB5HH.js → chunk-F3PVXKHP.js} +78 -1442
- package/dist/chunk-F3PVXKHP.js.map +1 -0
- package/dist/{chunk-6QUPUTT7.js → chunk-HLIR3RJ7.js} +6 -10
- package/dist/{chunk-6QUPUTT7.js.map → chunk-HLIR3RJ7.js.map} +1 -1
- package/dist/{chunk-SHRRWOVY.js → chunk-J6BH2OBA.js} +64 -21
- package/dist/chunk-J6BH2OBA.js.map +1 -0
- package/dist/{chunk-6FUJ2VYY.js → chunk-JAKYZGV4.js} +3 -3
- package/dist/{chunk-3VUPWDSE.js → chunk-JIZGYQYH.js} +4 -4
- package/dist/{chunk-QOIONSOI.js → chunk-KRGC4EDX.js} +2 -2
- package/dist/{chunk-AJOIM6UR.js → chunk-L5ASZA2F.js} +2 -2
- package/dist/{chunk-I56LKMF7.js → chunk-LXSG4L55.js} +2 -2
- package/dist/{chunk-MSVSP5VO.js → chunk-N3DUH6OO.js} +1 -1
- package/dist/chunk-N3DUH6OO.js.map +1 -0
- package/dist/{chunk-SQ4LU27I.js → chunk-NFRBADNR.js} +195 -80
- package/dist/chunk-NFRBADNR.js.map +1 -0
- package/dist/chunk-OJU73BUX.js +1688 -0
- package/dist/chunk-OJU73BUX.js.map +1 -0
- package/dist/{chunk-JVEMUX6L.js → chunk-OZ2KQ7HF.js} +2 -2
- package/dist/{chunk-SYDHFFAW.js → chunk-P5IPFZVH.js} +5 -5
- package/dist/{chunk-GM3BMWKR.js → chunk-REWQAFSA.js} +2 -2
- package/dist/{chunk-V7GDTQ6I.js → chunk-S35FX6MU.js} +2 -2
- package/dist/{chunk-MTHNJCOJ.js → chunk-S3OPGGZB.js} +2 -2
- package/dist/{chunk-IHMT6XTY.js → chunk-U5H7WHTS.js} +6 -4
- package/dist/{chunk-IHMT6XTY.js.map → chunk-U5H7WHTS.js.map} +1 -1
- package/dist/{chunk-RBHANGVX.js → chunk-UCJ5CDTK.js} +6 -6
- package/dist/{chunk-HHLWSWWF.js → chunk-URM3HW2R.js} +2 -2
- package/dist/{chunk-VO4UICII.js → chunk-YTZLBBEB.js} +2 -2
- package/dist/{chunk-OC56UWV5.js → chunk-YYOK4GVF.js} +2 -2
- package/dist/{cli-Dpivy32W.d.ts → cli-1orcdXOY.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +28 -27
- 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 +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 +4 -4
- package/dist/extraction-faithfulness.d.ts +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 +9 -9
- package/dist/index.js +42 -41
- 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 +5 -5
- 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 +2 -2
- 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 +2 -2
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -9
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +8 -5
- package/dist/{orchestrator-vygo2YIM.d.ts → orchestrator-kOxredSr.d.ts} +22 -5
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +17 -16
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.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/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/schemas.d.ts +22 -22
- 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-DSjMDZ1u.d.ts → semantic-consolidation-B58v3S-a.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/transfer/types.d.ts +12 -12
- package/dist/{types-D9dwzU_x.d.ts → types-ACmDOScJ.d.ts} +36 -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 +2 -2
- package/src/access-service.ts +56 -41
- package/src/briefing.ts +32 -0
- package/src/config.ts +32 -0
- package/src/correction/index.ts +24 -0
- package/src/correction/passive-capture.test.ts +500 -0
- package/src/correction/passive-capture.ts +335 -0
- package/src/correction/passive-correction-detector.test.ts +263 -0
- package/src/correction/passive-correction-detector.ts +325 -0
- package/src/correction/passive-correction-notifications.ts +123 -0
- package/src/maintenance/namespace-planner.ts +3 -10
- package/src/orchestrator.ts +231 -73
- package/src/scopes/scope-plan.test.ts +168 -1
- package/src/scopes/scope-plan.ts +163 -0
- package/src/types.ts +36 -0
- package/dist/chunk-BNOAB5HH.js.map +0 -1
- package/dist/chunk-JEIROMLX.js.map +0 -1
- package/dist/chunk-MSVSP5VO.js.map +0 -1
- package/dist/chunk-SHRRWOVY.js.map +0 -1
- package/dist/chunk-SQ4LU27I.js.map +0 -1
- package/dist/chunk-XCTDHF7U.js.map +0 -1
- /package/dist/{chunk-XZTUMWKQ.js.map → chunk-2PTBLS2S.js.map} +0 -0
- /package/dist/{chunk-2Y6LMOQQ.js.map → chunk-2VHMVWPU.js.map} +0 -0
- /package/dist/{chunk-6UU43ZGD.js.map → chunk-4KZGLDJJ.js.map} +0 -0
- /package/dist/{chunk-K44MIN6D.js.map → chunk-5RHM43BJ.js.map} +0 -0
- /package/dist/{chunk-MECU6WSH.js.map → chunk-72VDBALG.js.map} +0 -0
- /package/dist/{chunk-UY4JMEAK.js.map → chunk-7EEVXW7X.js.map} +0 -0
- /package/dist/{chunk-WI4QX7GH.js.map → chunk-A66YRSOS.js.map} +0 -0
- /package/dist/{chunk-O62P2LFL.js.map → chunk-APUJIMDM.js.map} +0 -0
- /package/dist/{chunk-MPHDVHIB.js.map → chunk-DIFU33GU.js.map} +0 -0
- /package/dist/{chunk-DXGS5YOQ.js.map → chunk-EH27LHML.js.map} +0 -0
- /package/dist/{chunk-6FUJ2VYY.js.map → chunk-JAKYZGV4.js.map} +0 -0
- /package/dist/{chunk-3VUPWDSE.js.map → chunk-JIZGYQYH.js.map} +0 -0
- /package/dist/{chunk-QOIONSOI.js.map → chunk-KRGC4EDX.js.map} +0 -0
- /package/dist/{chunk-AJOIM6UR.js.map → chunk-L5ASZA2F.js.map} +0 -0
- /package/dist/{chunk-I56LKMF7.js.map → chunk-LXSG4L55.js.map} +0 -0
- /package/dist/{chunk-JVEMUX6L.js.map → chunk-OZ2KQ7HF.js.map} +0 -0
- /package/dist/{chunk-SYDHFFAW.js.map → chunk-P5IPFZVH.js.map} +0 -0
- /package/dist/{chunk-GM3BMWKR.js.map → chunk-REWQAFSA.js.map} +0 -0
- /package/dist/{chunk-V7GDTQ6I.js.map → chunk-S35FX6MU.js.map} +0 -0
- /package/dist/{chunk-MTHNJCOJ.js.map → chunk-S3OPGGZB.js.map} +0 -0
- /package/dist/{chunk-RBHANGVX.js.map → chunk-UCJ5CDTK.js.map} +0 -0
- /package/dist/{chunk-HHLWSWWF.js.map → chunk-URM3HW2R.js.map} +0 -0
- /package/dist/{chunk-VO4UICII.js.map → chunk-YTZLBBEB.js.map} +0 -0
- /package/dist/{chunk-OC56UWV5.js.map → chunk-YYOK4GVF.js.map} +0 -0
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
} from "./chunk-H7XKCNR6.js";
|
|
23
23
|
import {
|
|
24
24
|
toRecallExplainJson
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-LXSG4L55.js";
|
|
26
26
|
import {
|
|
27
27
|
buildProposedActions,
|
|
28
28
|
buildQualityScore,
|
|
@@ -30,20 +30,12 @@ import {
|
|
|
30
30
|
listMemoryGovernanceRuns,
|
|
31
31
|
readMemoryGovernanceRunArtifact,
|
|
32
32
|
runMemoryGovernance
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-2PTBLS2S.js";
|
|
34
34
|
import {
|
|
35
35
|
clusterByKey,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
lcmSessionKeyForNamespace,
|
|
40
|
-
projectTagProjectId,
|
|
41
|
-
resolveCodingNamespaceOverlay,
|
|
42
|
-
resolveGitContext,
|
|
43
|
-
resolveScopePlan,
|
|
44
|
-
resolveScopeProfilePlan,
|
|
45
|
-
sanitizeFragment
|
|
46
|
-
} from "./chunk-SHRRWOVY.js";
|
|
36
|
+
createCorrectionService,
|
|
37
|
+
isCorrectionFeatureEnabled
|
|
38
|
+
} from "./chunk-OJU73BUX.js";
|
|
47
39
|
import {
|
|
48
40
|
getTrustZoneStoreStatus,
|
|
49
41
|
isTrustZoneName,
|
|
@@ -58,7 +50,20 @@ import {
|
|
|
58
50
|
} from "./chunk-FF4KLI5W.js";
|
|
59
51
|
import {
|
|
60
52
|
estimateRecallTokens
|
|
61
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-L5ASZA2F.js";
|
|
54
|
+
import {
|
|
55
|
+
combineNamespaces,
|
|
56
|
+
defaultGitInvoker,
|
|
57
|
+
expandScopeProfileReadNamespaces,
|
|
58
|
+
lcmSessionKeyForNamespace,
|
|
59
|
+
projectTagProjectId,
|
|
60
|
+
resolveCodingNamespaceOverlay,
|
|
61
|
+
resolveGitContext,
|
|
62
|
+
resolveScopePlan,
|
|
63
|
+
resolveScopeProfilePlan,
|
|
64
|
+
resolveWritableNamespaceValue,
|
|
65
|
+
sanitizeFragment
|
|
66
|
+
} from "./chunk-J6BH2OBA.js";
|
|
62
67
|
import {
|
|
63
68
|
namespaceCollectionName
|
|
64
69
|
} from "./chunk-CTOQEZSN.js";
|
|
@@ -107,20 +112,17 @@ import {
|
|
|
107
112
|
buildBriefing,
|
|
108
113
|
parseBriefingFocus,
|
|
109
114
|
parseBriefingWindow
|
|
110
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-2COL35PK.js";
|
|
111
116
|
import {
|
|
112
117
|
parseEntityFile
|
|
113
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-YYOK4GVF.js";
|
|
114
119
|
import {
|
|
115
120
|
stripAttributesSuffix
|
|
116
121
|
} from "./chunk-SVOZFLIQ.js";
|
|
117
|
-
import {
|
|
118
|
-
serializeMutations
|
|
119
|
-
} from "./chunk-LTJAMRGI.js";
|
|
120
122
|
import {
|
|
121
123
|
DEFAULT_RECALL_DISCLOSURE,
|
|
122
124
|
isRecallDisclosure
|
|
123
|
-
} from "./chunk-
|
|
125
|
+
} from "./chunk-N3DUH6OO.js";
|
|
124
126
|
import {
|
|
125
127
|
inferMemoryStatus,
|
|
126
128
|
toMemoryPathRel
|
|
@@ -1150,12 +1152,12 @@ async function findArchitectureCardMemory(storage) {
|
|
|
1150
1152
|
});
|
|
1151
1153
|
return cards[0] ?? null;
|
|
1152
1154
|
}
|
|
1153
|
-
function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDir, memoryDir,
|
|
1155
|
+
function createArchitectureVersioningHook(enabled, maxVersionsPerPage, sidecarDir, memoryDir, readFile4, writeVersion) {
|
|
1154
1156
|
return {
|
|
1155
1157
|
async snapshotIfExists(memory) {
|
|
1156
1158
|
if (!enabled) return;
|
|
1157
1159
|
try {
|
|
1158
|
-
const fullContent = await
|
|
1160
|
+
const fullContent = await readFile4(memory.path);
|
|
1159
1161
|
await writeVersion(
|
|
1160
1162
|
memory.path,
|
|
1161
1163
|
fullContent,
|
|
@@ -2137,1381 +2139,10 @@ async function deltaGet(request, ctx, codingContext) {
|
|
|
2137
2139
|
}
|
|
2138
2140
|
}
|
|
2139
2141
|
|
|
2140
|
-
// src/correction/correction-contract.ts
|
|
2141
|
-
var MEMORY_CATEGORIES = [
|
|
2142
|
-
"fact",
|
|
2143
|
-
"preference",
|
|
2144
|
-
"correction",
|
|
2145
|
-
"entity",
|
|
2146
|
-
"decision",
|
|
2147
|
-
"relationship",
|
|
2148
|
-
"principle",
|
|
2149
|
-
"commitment",
|
|
2150
|
-
"moment",
|
|
2151
|
-
"skill",
|
|
2152
|
-
"rule",
|
|
2153
|
-
"procedure",
|
|
2154
|
-
"reasoning_trace"
|
|
2155
|
-
];
|
|
2156
|
-
var CORRECTION_ACTION_KINDS = [
|
|
2157
|
-
"supersede",
|
|
2158
|
-
"edit",
|
|
2159
|
-
"retract",
|
|
2160
|
-
"rescope",
|
|
2161
|
-
"redaction_rule"
|
|
2162
|
-
];
|
|
2163
|
-
var CORRECTION_TEXT_MAX = 1e4;
|
|
2164
|
-
var REDACTION_PATTERN_MAX = 256;
|
|
2165
|
-
function validateCorrectionRequest(request) {
|
|
2166
|
-
if (!request || typeof request !== "object") {
|
|
2167
|
-
throw new CorrectionContractError("CorrectionRequest must be an object.");
|
|
2168
|
-
}
|
|
2169
|
-
const text = typeof request.text === "string" ? request.text.trim() : "";
|
|
2170
|
-
if (text.length === 0) {
|
|
2171
|
-
throw new CorrectionContractError("CorrectionRequest.text is required and must be non-empty.");
|
|
2172
|
-
}
|
|
2173
|
-
if (text.length > CORRECTION_TEXT_MAX) {
|
|
2174
|
-
throw new CorrectionContractError(
|
|
2175
|
-
`CorrectionRequest.text exceeds the ${CORRECTION_TEXT_MAX}-character limit (${text.length}).`
|
|
2176
|
-
);
|
|
2177
|
-
}
|
|
2178
|
-
const targetIds = Array.isArray(request.targetIds) ? request.targetIds.filter((id) => typeof id === "string" && id.length > 0) : void 0;
|
|
2179
|
-
if (targetIds !== void 0 && targetIds.length === 0) {
|
|
2180
|
-
return {
|
|
2181
|
-
text,
|
|
2182
|
-
...request.sessionKey ? { sessionKey: request.sessionKey } : {},
|
|
2183
|
-
...request.principal ? { principal: request.principal } : {},
|
|
2184
|
-
...request.namespace ? { namespace: request.namespace } : {}
|
|
2185
|
-
};
|
|
2186
|
-
}
|
|
2187
|
-
return {
|
|
2188
|
-
text,
|
|
2189
|
-
...targetIds ? { targetIds } : {},
|
|
2190
|
-
...request.sessionKey ? { sessionKey: request.sessionKey } : {},
|
|
2191
|
-
...request.principal ? { principal: request.principal } : {},
|
|
2192
|
-
...request.namespace ? { namespace: request.namespace } : {}
|
|
2193
|
-
};
|
|
2194
|
-
}
|
|
2195
|
-
function validateRedactionPattern(pattern) {
|
|
2196
|
-
if (typeof pattern !== "string") {
|
|
2197
|
-
throw new CorrectionContractError("redaction_rule.pattern must be a string.");
|
|
2198
|
-
}
|
|
2199
|
-
const trimmed = pattern.trim();
|
|
2200
|
-
if (trimmed.length === 0) {
|
|
2201
|
-
throw new CorrectionContractError("redaction_rule.pattern is required.");
|
|
2202
|
-
}
|
|
2203
|
-
if (trimmed.length > REDACTION_PATTERN_MAX) {
|
|
2204
|
-
throw new CorrectionContractError(
|
|
2205
|
-
`redaction_rule.pattern exceeds the ${REDACTION_PATTERN_MAX}-character bound.`
|
|
2206
|
-
);
|
|
2207
|
-
}
|
|
2208
|
-
if (isRegexLike(trimmed) && isOverlyBroadRegex(trimmed)) {
|
|
2209
|
-
throw new CorrectionContractError(
|
|
2210
|
-
"redaction_rule.pattern is too broad \u2014 use a bounded literal or a more specific pattern."
|
|
2211
|
-
);
|
|
2212
|
-
}
|
|
2213
|
-
return trimmed;
|
|
2214
|
-
}
|
|
2215
|
-
function isRegexLike(pattern) {
|
|
2216
|
-
if (pattern.startsWith("/") && pattern.endsWith("/") && pattern.length >= 2) return true;
|
|
2217
|
-
return /[\\^$.|?*+()[\]{}]/.test(pattern);
|
|
2218
|
-
}
|
|
2219
|
-
function isOverlyBroadRegex(pattern) {
|
|
2220
|
-
const body = pattern.startsWith("/") && pattern.endsWith("/") ? pattern.slice(1, -1) : pattern;
|
|
2221
|
-
if (/(?:^|[^\\])\(\.\*\)|(?:^|[^\\])\.\*|(?:^|[^\\])\.\+|^\.([^*+]?)$/.test(body)) {
|
|
2222
|
-
return true;
|
|
2223
|
-
}
|
|
2224
|
-
return false;
|
|
2225
|
-
}
|
|
2226
|
-
function validateCorrectionAction(action) {
|
|
2227
|
-
if (!action || typeof action !== "object") {
|
|
2228
|
-
throw new CorrectionContractError("CorrectionAction must be an object.");
|
|
2229
|
-
}
|
|
2230
|
-
const a = action;
|
|
2231
|
-
if (typeof a.kind !== "string" || !CORRECTION_ACTION_KINDS.includes(a.kind)) {
|
|
2232
|
-
throw new CorrectionContractError(
|
|
2233
|
-
`CorrectionAction.kind must be one of: ${CORRECTION_ACTION_KINDS.join(", ")}.`
|
|
2234
|
-
);
|
|
2235
|
-
}
|
|
2236
|
-
switch (a.kind) {
|
|
2237
|
-
case "supersede":
|
|
2238
|
-
if (typeof a.loserId !== "string" || a.loserId.length === 0) {
|
|
2239
|
-
throw new CorrectionContractError("supersede.loserId is required.");
|
|
2240
|
-
}
|
|
2241
|
-
if (a.replacement !== void 0 && a.replacement !== null) {
|
|
2242
|
-
validateMemoryDraft(a.replacement);
|
|
2243
|
-
}
|
|
2244
|
-
break;
|
|
2245
|
-
case "edit":
|
|
2246
|
-
if (typeof a.memoryId !== "string" || a.memoryId.length === 0) {
|
|
2247
|
-
throw new CorrectionContractError("edit.memoryId is required.");
|
|
2248
|
-
}
|
|
2249
|
-
if (typeof a.patch !== "string" || a.patch.length === 0) {
|
|
2250
|
-
throw new CorrectionContractError("edit.patch is required and must be non-empty.");
|
|
2251
|
-
}
|
|
2252
|
-
break;
|
|
2253
|
-
case "retract":
|
|
2254
|
-
if (typeof a.memoryId !== "string" || a.memoryId.length === 0) {
|
|
2255
|
-
throw new CorrectionContractError("retract.memoryId is required.");
|
|
2256
|
-
}
|
|
2257
|
-
break;
|
|
2258
|
-
case "rescope":
|
|
2259
|
-
if (typeof a.memoryId !== "string" || a.memoryId.length === 0) {
|
|
2260
|
-
throw new CorrectionContractError("rescope.memoryId is required.");
|
|
2261
|
-
}
|
|
2262
|
-
if (typeof a.toNamespace !== "string" || a.toNamespace.trim().length === 0) {
|
|
2263
|
-
throw new CorrectionContractError("rescope.toNamespace is required.");
|
|
2264
|
-
}
|
|
2265
|
-
break;
|
|
2266
|
-
case "redaction_rule":
|
|
2267
|
-
if (typeof a.pattern !== "string") {
|
|
2268
|
-
throw new CorrectionContractError("redaction_rule.pattern is required.");
|
|
2269
|
-
}
|
|
2270
|
-
validateRedactionPattern(a.pattern);
|
|
2271
|
-
break;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
function validateMemoryDraft(draft) {
|
|
2275
|
-
if (!draft || typeof draft !== "object") {
|
|
2276
|
-
throw new CorrectionContractError("MemoryDraft must be an object.");
|
|
2277
|
-
}
|
|
2278
|
-
const d = draft;
|
|
2279
|
-
if (typeof d.content !== "string" || d.content.trim().length === 0) {
|
|
2280
|
-
throw new CorrectionContractError("MemoryDraft.content is required and must be non-empty.");
|
|
2281
|
-
}
|
|
2282
|
-
if (d.category !== void 0) {
|
|
2283
|
-
if (typeof d.category !== "string" || !MEMORY_CATEGORIES.includes(d.category)) {
|
|
2284
|
-
throw new CorrectionContractError(
|
|
2285
|
-
`MemoryDraft.category must be one of: ${MEMORY_CATEGORIES.join(", ")}.`
|
|
2286
|
-
);
|
|
2287
|
-
}
|
|
2288
|
-
}
|
|
2289
|
-
if (d.confidence !== void 0 && (typeof d.confidence !== "number" || d.confidence < 0 || d.confidence > 1)) {
|
|
2290
|
-
throw new CorrectionContractError("MemoryDraft.confidence must be a number in [0, 1].");
|
|
2291
|
-
}
|
|
2292
|
-
if (d.tags !== void 0 && !Array.isArray(d.tags)) {
|
|
2293
|
-
throw new CorrectionContractError("MemoryDraft.tags must be an array.");
|
|
2294
|
-
}
|
|
2295
|
-
if (d.structuredAttributes !== void 0 && (typeof d.structuredAttributes !== "object" || d.structuredAttributes === null)) {
|
|
2296
|
-
throw new CorrectionContractError("MemoryDraft.structuredAttributes must be an object.");
|
|
2297
|
-
}
|
|
2298
|
-
}
|
|
2299
|
-
function deterministicFallbackPlan(args) {
|
|
2300
|
-
return {
|
|
2301
|
-
planId: newPlanId(),
|
|
2302
|
-
request: args.request,
|
|
2303
|
-
namespace: args.namespace,
|
|
2304
|
-
affected: args.affected,
|
|
2305
|
-
classification: "outdated",
|
|
2306
|
-
actions: [],
|
|
2307
|
-
diff: "",
|
|
2308
|
-
confidence: 0,
|
|
2309
|
-
warnings: [...args.warnings, "planner LLM unavailable \u2014 manual action selection required"],
|
|
2310
|
-
createdAt: args.createdAt,
|
|
2311
|
-
expiresAt: args.expiresAt,
|
|
2312
|
-
status: "pending"
|
|
2313
|
-
};
|
|
2314
|
-
}
|
|
2315
|
-
function newPlanId() {
|
|
2316
|
-
return `corr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
2317
|
-
}
|
|
2318
|
-
var CorrectionContractError = class extends Error {
|
|
2319
|
-
constructor(message) {
|
|
2320
|
-
super(message);
|
|
2321
|
-
this.name = "CorrectionContractError";
|
|
2322
|
-
}
|
|
2323
|
-
};
|
|
2324
|
-
|
|
2325
|
-
// src/correction/correction-planner.ts
|
|
2326
|
-
import { mkdir as mkdir2, readFile as readFile3, rename as rename2, unlink, readdir as readdir2, writeFile as writeFile2 } from "fs/promises";
|
|
2327
|
-
import path4 from "path";
|
|
2328
|
-
var CorrectionPlanner = class {
|
|
2329
|
-
constructor(deps) {
|
|
2330
|
-
this.deps = deps;
|
|
2331
|
-
}
|
|
2332
|
-
deps;
|
|
2333
|
-
/**
|
|
2334
|
-
* Plan a correction. `readableNamespaces` is the AUTHORIZED read scope the
|
|
2335
|
-
* service resolved for this caller; the planner never trusts a caller string.
|
|
2336
|
-
*/
|
|
2337
|
-
async plan(request, readableNamespaces) {
|
|
2338
|
-
const cleaned = validateCorrectionRequest(request);
|
|
2339
|
-
if (cleaned.text.length > CORRECTION_TEXT_MAX) {
|
|
2340
|
-
throw new CorrectionContractError("CorrectionRequest.text too long.");
|
|
2341
|
-
}
|
|
2342
|
-
if (cleaned.targetIds && cleaned.targetIds.length > this.deps.maxAffected) {
|
|
2343
|
-
throw new CorrectionContractError(
|
|
2344
|
-
`Correction target list (${cleaned.targetIds.length}) exceeds maxAffected (${this.deps.maxAffected}) \u2014 narrow the target set.`
|
|
2345
|
-
);
|
|
2346
|
-
}
|
|
2347
|
-
const namespaces = readableNamespaces;
|
|
2348
|
-
if (namespaces.length === 0) {
|
|
2349
|
-
throw new CorrectionContractError(
|
|
2350
|
-
"Correction requires at least one readable namespace \u2014 principal has no read scope."
|
|
2351
|
-
);
|
|
2352
|
-
}
|
|
2353
|
-
const located = await this.locateCandidates(cleaned, namespaces);
|
|
2354
|
-
if (located.candidates.length === 0) {
|
|
2355
|
-
return this.persist(
|
|
2356
|
-
this.emptyPlan(cleaned, namespaces[0], "no matching memories found for the correction text")
|
|
2357
|
-
);
|
|
2358
|
-
}
|
|
2359
|
-
const llm = await this.deps.classifyAndDraft({
|
|
2360
|
-
text: cleaned.text,
|
|
2361
|
-
candidates: located.candidates
|
|
2362
|
-
});
|
|
2363
|
-
for (const action of llm.actions) {
|
|
2364
|
-
validateCorrectionAction(action);
|
|
2365
|
-
if (action.kind === "redaction_rule") {
|
|
2366
|
-
validateRedactionPattern(action.pattern);
|
|
2367
|
-
}
|
|
2368
|
-
}
|
|
2369
|
-
const affected = this.deriveAffected(located.candidates, llm);
|
|
2370
|
-
const touchedCount = new Set(
|
|
2371
|
-
llm.actions.map(
|
|
2372
|
-
(a) => a.kind === "supersede" ? a.loserId : a.kind === "edit" || a.kind === "retract" || a.kind === "rescope" ? a.memoryId : null
|
|
2373
|
-
).filter((id) => id !== null)
|
|
2374
|
-
).size;
|
|
2375
|
-
if (touchedCount > this.deps.maxAffected) {
|
|
2376
|
-
throw new CorrectionContractError(
|
|
2377
|
-
`Correction touches ${touchedCount} memories, exceeding the maxAffected limit of ${this.deps.maxAffected}. Narrow the correction text or supply explicit targetIds.`
|
|
2378
|
-
);
|
|
2379
|
-
}
|
|
2380
|
-
const candidateIds = new Set(located.candidates.map((c) => c.memoryId));
|
|
2381
|
-
if (llm.actions.length > 0 && candidateIds.size > 0) {
|
|
2382
|
-
const filtered = llm.actions.filter((action) => {
|
|
2383
|
-
const id = action.kind === "supersede" ? action.loserId : action.kind === "edit" || action.kind === "retract" || action.kind === "rescope" ? action.memoryId : null;
|
|
2384
|
-
return id === null || candidateIds.has(id);
|
|
2385
|
-
});
|
|
2386
|
-
if (filtered.length < llm.actions.length) {
|
|
2387
|
-
const dropped = llm.actions.length - filtered.length;
|
|
2388
|
-
llm.warnings = [...llm.warnings, `${dropped} action(s) targeted memories outside the located candidate set and were dropped (prompt-injection guard).`];
|
|
2389
|
-
llm.actions = filtered;
|
|
2390
|
-
}
|
|
2391
|
-
}
|
|
2392
|
-
const diff = llm.fallback ? "" : await this.deps.renderDiff({ candidates: located.candidates, actions: llm.actions });
|
|
2393
|
-
const createdAt = this.deps.now().toISOString();
|
|
2394
|
-
const expiresAt = new Date(
|
|
2395
|
-
this.deps.now().getTime() + this.deps.planTtlHours * 60 * 60 * 1e3
|
|
2396
|
-
).toISOString();
|
|
2397
|
-
const plan = llm.fallback ? deterministicFallbackPlan({
|
|
2398
|
-
request: cleaned,
|
|
2399
|
-
namespace: namespaces[0],
|
|
2400
|
-
affected,
|
|
2401
|
-
warnings: llm.warnings,
|
|
2402
|
-
createdAt,
|
|
2403
|
-
expiresAt
|
|
2404
|
-
}) : {
|
|
2405
|
-
planId: newPlanId(),
|
|
2406
|
-
request: cleaned,
|
|
2407
|
-
namespace: namespaces[0],
|
|
2408
|
-
affected,
|
|
2409
|
-
classification: llm.classification,
|
|
2410
|
-
actions: llm.actions,
|
|
2411
|
-
diff,
|
|
2412
|
-
confidence: clampConfidence(llm.confidence),
|
|
2413
|
-
warnings: llm.warnings,
|
|
2414
|
-
createdAt,
|
|
2415
|
-
expiresAt,
|
|
2416
|
-
status: "pending"
|
|
2417
|
-
};
|
|
2418
|
-
return this.persist(plan);
|
|
2419
|
-
}
|
|
2420
|
-
async locateCandidates(request, namespaces) {
|
|
2421
|
-
if (request.targetIds && request.targetIds.length > 0) {
|
|
2422
|
-
const targets = await this.deps.resolveTargets({
|
|
2423
|
-
targetIds: request.targetIds,
|
|
2424
|
-
namespaces
|
|
2425
|
-
});
|
|
2426
|
-
const seedIds2 = targets.map((c) => c.memoryId);
|
|
2427
|
-
const neighbors2 = await this.deps.expandNeighbors({
|
|
2428
|
-
seedIds: seedIds2,
|
|
2429
|
-
namespaces,
|
|
2430
|
-
limit: this.deps.maxAffected
|
|
2431
|
-
});
|
|
2432
|
-
return { candidates: mergeCandidates(targets, neighbors2).slice(0, this.deps.maxAffected) };
|
|
2433
|
-
}
|
|
2434
|
-
const searched = await this.deps.searchCorpus({
|
|
2435
|
-
text: request.text,
|
|
2436
|
-
namespaces,
|
|
2437
|
-
limit: this.deps.maxAffected
|
|
2438
|
-
});
|
|
2439
|
-
if (searched.length === 0) return { candidates: [] };
|
|
2440
|
-
const seedIds = searched.slice(0, Math.min(5, searched.length)).map((c) => c.memoryId);
|
|
2441
|
-
const neighbors = await this.deps.expandNeighbors({
|
|
2442
|
-
seedIds,
|
|
2443
|
-
namespaces,
|
|
2444
|
-
limit: this.deps.maxAffected
|
|
2445
|
-
});
|
|
2446
|
-
return { candidates: mergeCandidates(searched, neighbors).slice(0, this.deps.maxAffected) };
|
|
2447
|
-
}
|
|
2448
|
-
deriveAffected(candidates, llm) {
|
|
2449
|
-
const byId = new Map(candidates.map((c) => [c.memoryId, c]));
|
|
2450
|
-
const out = [];
|
|
2451
|
-
for (const rel of llm.relevance) {
|
|
2452
|
-
const c = byId.get(rel.memoryId);
|
|
2453
|
-
if (!c) continue;
|
|
2454
|
-
out.push({
|
|
2455
|
-
memoryId: c.memoryId,
|
|
2456
|
-
path: c.path,
|
|
2457
|
-
excerpt: c.excerpt,
|
|
2458
|
-
why: rel.why,
|
|
2459
|
-
...c.sourceQuote ? { sourceQuote: c.sourceQuote } : {}
|
|
2460
|
-
});
|
|
2461
|
-
}
|
|
2462
|
-
const annotated = new Set(out.map((e) => e.memoryId));
|
|
2463
|
-
for (const action of llm.actions) {
|
|
2464
|
-
const id = action.kind === "supersede" ? action.loserId : action.kind === "edit" || action.kind === "retract" || action.kind === "rescope" ? action.memoryId : null;
|
|
2465
|
-
if (id && !annotated.has(id)) {
|
|
2466
|
-
const c = byId.get(id);
|
|
2467
|
-
if (c) {
|
|
2468
|
-
out.push({
|
|
2469
|
-
memoryId: c.memoryId,
|
|
2470
|
-
path: c.path,
|
|
2471
|
-
excerpt: c.excerpt,
|
|
2472
|
-
why: "touched by a drafted action",
|
|
2473
|
-
...c.sourceQuote ? { sourceQuote: c.sourceQuote } : {}
|
|
2474
|
-
});
|
|
2475
|
-
annotated.add(id);
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
}
|
|
2479
|
-
return out;
|
|
2480
|
-
}
|
|
2481
|
-
emptyPlan(request, namespace, warning) {
|
|
2482
|
-
const createdAt = this.deps.now().toISOString();
|
|
2483
|
-
const expiresAt = new Date(
|
|
2484
|
-
this.deps.now().getTime() + this.deps.planTtlHours * 60 * 60 * 1e3
|
|
2485
|
-
).toISOString();
|
|
2486
|
-
return {
|
|
2487
|
-
planId: newPlanId(),
|
|
2488
|
-
request,
|
|
2489
|
-
namespace,
|
|
2490
|
-
affected: [],
|
|
2491
|
-
classification: "outdated",
|
|
2492
|
-
actions: [],
|
|
2493
|
-
diff: "",
|
|
2494
|
-
confidence: 0,
|
|
2495
|
-
warnings: [warning],
|
|
2496
|
-
createdAt,
|
|
2497
|
-
expiresAt,
|
|
2498
|
-
status: "pending"
|
|
2499
|
-
};
|
|
2500
|
-
}
|
|
2501
|
-
// -------------------------------------------------------------------------
|
|
2502
|
-
// Plan persistence — atomic write (rule 54), serialized per plan id (rule 40).
|
|
2503
|
-
// -------------------------------------------------------------------------
|
|
2504
|
-
/** Directory holding pending plans for one namespace. */
|
|
2505
|
-
async pendingDir(namespace) {
|
|
2506
|
-
return path4.join(await this.deps.storageDir(namespace), "state", "corrections", "pending");
|
|
2507
|
-
}
|
|
2508
|
-
async persist(plan) {
|
|
2509
|
-
const dir = await this.pendingDir(plan.namespace);
|
|
2510
|
-
const target = path4.join(dir, `${plan.planId}.json`);
|
|
2511
|
-
await serializeMutations(`correction-plan:${target}`, async () => {
|
|
2512
|
-
await mkdir2(dir, { recursive: true });
|
|
2513
|
-
const tmp = `${target}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
2514
|
-
await writeFile2(tmp, `${JSON.stringify(plan)}
|
|
2515
|
-
`, "utf-8");
|
|
2516
|
-
await rename2(tmp, target);
|
|
2517
|
-
});
|
|
2518
|
-
return plan;
|
|
2519
|
-
}
|
|
2520
|
-
/** Load a pending plan by id (used by the service / executor). */
|
|
2521
|
-
async loadPlan(namespace, planId) {
|
|
2522
|
-
assertSafePlanId(planId);
|
|
2523
|
-
const file = path4.join(await this.pendingDir(namespace), `${planId}.json`);
|
|
2524
|
-
return serializeMutations(`correction-plan:${file}`, async () => {
|
|
2525
|
-
let raw;
|
|
2526
|
-
try {
|
|
2527
|
-
raw = await readFile3(file, "utf-8");
|
|
2528
|
-
} catch (err) {
|
|
2529
|
-
const code = err?.code;
|
|
2530
|
-
if (code === "ENOENT") return null;
|
|
2531
|
-
throw err;
|
|
2532
|
-
}
|
|
2533
|
-
return parsePlan(raw);
|
|
2534
|
-
});
|
|
2535
|
-
}
|
|
2536
|
-
/** List pending plans (newest first), excluding consumed (applied/discarded). */
|
|
2537
|
-
async listPending(namespace) {
|
|
2538
|
-
const dir = await this.pendingDir(namespace);
|
|
2539
|
-
let files;
|
|
2540
|
-
try {
|
|
2541
|
-
files = await readdir2(dir);
|
|
2542
|
-
} catch (err) {
|
|
2543
|
-
const code = err?.code;
|
|
2544
|
-
if (code === "ENOENT") return [];
|
|
2545
|
-
throw err;
|
|
2546
|
-
}
|
|
2547
|
-
const plans = [];
|
|
2548
|
-
for (const f of files) {
|
|
2549
|
-
if (!f.endsWith(".json")) continue;
|
|
2550
|
-
let plan = null;
|
|
2551
|
-
try {
|
|
2552
|
-
plan = await this.loadPlan(namespace, f.replace(/\.json$/, ""));
|
|
2553
|
-
} catch {
|
|
2554
|
-
continue;
|
|
2555
|
-
}
|
|
2556
|
-
if (plan && plan.status === "pending") plans.push(plan);
|
|
2557
|
-
}
|
|
2558
|
-
plans.sort((a, b) => a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0);
|
|
2559
|
-
return plans;
|
|
2560
|
-
}
|
|
2561
|
-
async markConsumed(namespace, planId, status) {
|
|
2562
|
-
assertSafePlanId(planId);
|
|
2563
|
-
const file = path4.join(await this.pendingDir(namespace), `${planId}.json`);
|
|
2564
|
-
await serializeMutations(`correction-plan:${file}`, async () => {
|
|
2565
|
-
let raw;
|
|
2566
|
-
try {
|
|
2567
|
-
raw = await readFile3(file, "utf-8");
|
|
2568
|
-
} catch (err) {
|
|
2569
|
-
const code = err?.code;
|
|
2570
|
-
if (code === "ENOENT") return;
|
|
2571
|
-
throw err;
|
|
2572
|
-
}
|
|
2573
|
-
const plan = parsePlan(raw);
|
|
2574
|
-
if (!plan) return;
|
|
2575
|
-
plan.status = status;
|
|
2576
|
-
const tmp = `${file}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
2577
|
-
await writeFile2(tmp, `${JSON.stringify(plan)}
|
|
2578
|
-
`, "utf-8");
|
|
2579
|
-
await rename2(tmp, file);
|
|
2580
|
-
});
|
|
2581
|
-
}
|
|
2582
|
-
async deletePlan(namespace, planId) {
|
|
2583
|
-
assertSafePlanId(planId);
|
|
2584
|
-
const file = path4.join(await this.pendingDir(namespace), `${planId}.json`);
|
|
2585
|
-
await serializeMutations(`correction-plan:${file}`, async () => {
|
|
2586
|
-
try {
|
|
2587
|
-
await unlink(file);
|
|
2588
|
-
} catch (err) {
|
|
2589
|
-
const code = err?.code;
|
|
2590
|
-
if (code === "ENOENT") return;
|
|
2591
|
-
throw err;
|
|
2592
|
-
}
|
|
2593
|
-
});
|
|
2594
|
-
}
|
|
2595
|
-
};
|
|
2596
|
-
function assertSafePlanId(planId) {
|
|
2597
|
-
if (typeof planId !== "string" || planId.length === 0 || planId.includes("/") || planId.includes("\\") || planId.includes("\0") || planId === "." || planId === ".." || planId.startsWith(".") || planId.includes("..")) {
|
|
2598
|
-
throw new CorrectionContractError(
|
|
2599
|
-
`Invalid plan id: ${JSON.stringify(planId)} \u2014 must be a bare file basename with no path separators or parent segments.`
|
|
2600
|
-
);
|
|
2601
|
-
}
|
|
2602
|
-
}
|
|
2603
|
-
function clampConfidence(n) {
|
|
2604
|
-
if (!Number.isFinite(n)) return 0;
|
|
2605
|
-
return Math.min(1, Math.max(0, n));
|
|
2606
|
-
}
|
|
2607
|
-
function mergeCandidates(a, b) {
|
|
2608
|
-
const map = /* @__PURE__ */ new Map();
|
|
2609
|
-
for (const c of a) {
|
|
2610
|
-
const existing = map.get(c.memoryId);
|
|
2611
|
-
if (!existing || c.score > existing.score) map.set(c.memoryId, c);
|
|
2612
|
-
}
|
|
2613
|
-
for (const c of b) {
|
|
2614
|
-
const existing = map.get(c.memoryId);
|
|
2615
|
-
if (!existing || c.score > existing.score) map.set(c.memoryId, c);
|
|
2616
|
-
}
|
|
2617
|
-
return [...map.values()].sort((x, y) => y.score - x.score);
|
|
2618
|
-
}
|
|
2619
|
-
function parsePlan(raw) {
|
|
2620
|
-
let parsed;
|
|
2621
|
-
try {
|
|
2622
|
-
parsed = JSON.parse(raw);
|
|
2623
|
-
} catch {
|
|
2624
|
-
return null;
|
|
2625
|
-
}
|
|
2626
|
-
if (!parsed || typeof parsed !== "object") return null;
|
|
2627
|
-
const p = parsed;
|
|
2628
|
-
if (typeof p.planId !== "string" || typeof p.namespace !== "string") return null;
|
|
2629
|
-
if (typeof p.createdAt !== "string" || typeof p.expiresAt !== "string") return null;
|
|
2630
|
-
if (!Array.isArray(p.actions) || !Array.isArray(p.affected)) return null;
|
|
2631
|
-
for (const action of p.actions) {
|
|
2632
|
-
try {
|
|
2633
|
-
validateCorrectionAction(action);
|
|
2634
|
-
} catch {
|
|
2635
|
-
return null;
|
|
2636
|
-
}
|
|
2637
|
-
}
|
|
2638
|
-
return parsed;
|
|
2639
|
-
}
|
|
2640
|
-
|
|
2641
|
-
// src/correction/correction-executor.ts
|
|
2642
|
-
var CorrectionExecutor = class {
|
|
2643
|
-
constructor(deps, planner) {
|
|
2644
|
-
this.deps = deps;
|
|
2645
|
-
this.planner = planner;
|
|
2646
|
-
}
|
|
2647
|
-
deps;
|
|
2648
|
-
planner;
|
|
2649
|
-
/**
|
|
2650
|
-
* Apply a persisted plan by id. Idempotent-once: a second apply of the same
|
|
2651
|
-
* plan is rejected. Returns the {@link CorrectionOutcome}.
|
|
2652
|
-
*/
|
|
2653
|
-
async apply(namespace, planId, opts) {
|
|
2654
|
-
if (!opts.confirm) {
|
|
2655
|
-
throw new CorrectionContractError(
|
|
2656
|
-
"Correction apply requires explicit confirmation (correction.applyRequiresConfirm)."
|
|
2657
|
-
);
|
|
2658
|
-
}
|
|
2659
|
-
return serializeMutations(
|
|
2660
|
-
`correction-apply:${namespace}:${planId}`,
|
|
2661
|
-
() => this.applyInternal(namespace, planId, opts.canWriteDestination)
|
|
2662
|
-
);
|
|
2663
|
-
}
|
|
2664
|
-
async applyInternal(namespace, planId, canWriteDestination) {
|
|
2665
|
-
const plan = await this.planner.loadPlan(namespace, planId);
|
|
2666
|
-
if (!plan) {
|
|
2667
|
-
throw new CorrectionContractError(`Correction plan not found: ${planId}`);
|
|
2668
|
-
}
|
|
2669
|
-
if (plan.namespace !== namespace) {
|
|
2670
|
-
throw new CorrectionContractError(
|
|
2671
|
-
`Correction plan ${planId} belongs to namespace '${plan.namespace}', not '${namespace}'.`
|
|
2672
|
-
);
|
|
2673
|
-
}
|
|
2674
|
-
if (plan.status === "applied" || plan.status === "partial" || plan.status === "applying") {
|
|
2675
|
-
throw new CorrectionContractError(
|
|
2676
|
-
`Correction plan ${planId} has already been applied or is in progress (status=${plan.status}).`
|
|
2677
|
-
);
|
|
2678
|
-
}
|
|
2679
|
-
if (plan.status === "discarded") {
|
|
2680
|
-
throw new CorrectionContractError(`Correction plan ${planId} has been discarded.`);
|
|
2681
|
-
}
|
|
2682
|
-
if (this.deps.now().getTime() > new Date(plan.expiresAt).getTime()) {
|
|
2683
|
-
await this.planner.markConsumed(namespace, planId, "discarded");
|
|
2684
|
-
throw new CorrectionContractError(
|
|
2685
|
-
`Correction plan ${planId} expired at ${plan.expiresAt} and has been discarded.`
|
|
2686
|
-
);
|
|
2687
|
-
}
|
|
2688
|
-
for (const action of plan.actions) {
|
|
2689
|
-
validateCorrectionAction(action);
|
|
2690
|
-
if (action.kind === "redaction_rule") {
|
|
2691
|
-
validateRedactionPattern(action.pattern);
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
try {
|
|
2695
|
-
await this.planner.markConsumed(namespace, planId, "applying");
|
|
2696
|
-
} catch {
|
|
2697
|
-
throw new CorrectionContractError(
|
|
2698
|
-
`Correction plan ${planId}: cannot mark in-progress (filesystem unwritable?) \u2014 aborting before any mutation.`
|
|
2699
|
-
);
|
|
2700
|
-
}
|
|
2701
|
-
const results = [];
|
|
2702
|
-
const appliedTouched = [];
|
|
2703
|
-
for (const action of plan.actions) {
|
|
2704
|
-
if (action.kind === "supersede" && action.replacement) {
|
|
2705
|
-
const loser = await this.deps.getMemory(namespace, action.loserId);
|
|
2706
|
-
if (!loser) {
|
|
2707
|
-
results.push({
|
|
2708
|
-
action,
|
|
2709
|
-
status: "failed",
|
|
2710
|
-
error: `supersede loser not found: ${action.loserId}`
|
|
2711
|
-
});
|
|
2712
|
-
continue;
|
|
2713
|
-
}
|
|
2714
|
-
try {
|
|
2715
|
-
const newId = await this.deps.writeReplacement(namespace, {
|
|
2716
|
-
content: action.replacement.content,
|
|
2717
|
-
...action.replacement.category ? { category: action.replacement.category } : {},
|
|
2718
|
-
...action.replacement.confidence !== void 0 ? { confidence: action.replacement.confidence } : {},
|
|
2719
|
-
...action.replacement.tags ? { tags: action.replacement.tags } : {},
|
|
2720
|
-
...action.replacement.entityRef ? { entityRef: action.replacement.entityRef } : {},
|
|
2721
|
-
...action.replacement.validAt ? { validAt: action.replacement.validAt } : {},
|
|
2722
|
-
...action.replacement.observedAt ? { observedAt: action.replacement.observedAt } : {},
|
|
2723
|
-
...action.replacement.structuredAttributes ? { structuredAttributes: action.replacement.structuredAttributes } : {},
|
|
2724
|
-
supersedes: action.loserId
|
|
2725
|
-
});
|
|
2726
|
-
results.push({ action, status: "applied", memoryId: newId });
|
|
2727
|
-
appliedTouched.push(newId);
|
|
2728
|
-
} catch (err) {
|
|
2729
|
-
results.push({
|
|
2730
|
-
action,
|
|
2731
|
-
status: "failed",
|
|
2732
|
-
error: errMsg(err)
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
} else if (action.kind === "edit") {
|
|
2736
|
-
try {
|
|
2737
|
-
const editedId = await this.deps.applyEdit(namespace, action.memoryId, action.patch);
|
|
2738
|
-
results.push({ action, status: "applied", memoryId: editedId });
|
|
2739
|
-
appliedTouched.push(editedId);
|
|
2740
|
-
} catch (err) {
|
|
2741
|
-
results.push({ action, status: "failed", error: errMsg(err) });
|
|
2742
|
-
}
|
|
2743
|
-
} else if (action.kind === "redaction_rule") {
|
|
2744
|
-
try {
|
|
2745
|
-
await this.deps.registerRedactionRule(namespace, action.pattern);
|
|
2746
|
-
results.push({ action, status: "applied" });
|
|
2747
|
-
} catch (err) {
|
|
2748
|
-
results.push({ action, status: "failed", error: errMsg(err) });
|
|
2749
|
-
}
|
|
2750
|
-
}
|
|
2751
|
-
}
|
|
2752
|
-
for (const action of plan.actions) {
|
|
2753
|
-
if (action.kind === "supersede") {
|
|
2754
|
-
const replacementResult = results.find(
|
|
2755
|
-
(r) => r.action === action && r.status === "applied"
|
|
2756
|
-
);
|
|
2757
|
-
if (action.replacement && !replacementResult) {
|
|
2758
|
-
continue;
|
|
2759
|
-
}
|
|
2760
|
-
await this.retireAndTombstone(namespace, action, "supersession", results, appliedTouched, {
|
|
2761
|
-
supersededBy: replacementResult?.memoryId
|
|
2762
|
-
});
|
|
2763
|
-
} else if (action.kind === "retract") {
|
|
2764
|
-
await this.retireAndTombstone(namespace, action, "retraction", results, appliedTouched);
|
|
2765
|
-
} else if (action.kind === "rescope") {
|
|
2766
|
-
try {
|
|
2767
|
-
const allowed = canWriteDestination ? await canWriteDestination(action.toNamespace) : true;
|
|
2768
|
-
if (!allowed) {
|
|
2769
|
-
results.push({
|
|
2770
|
-
action,
|
|
2771
|
-
status: "failed",
|
|
2772
|
-
error: `rescope destination namespace not writable: ${action.toNamespace}`
|
|
2773
|
-
});
|
|
2774
|
-
continue;
|
|
2775
|
-
}
|
|
2776
|
-
const destId = await this.deps.rescopeMemory(namespace, action.memoryId, action.toNamespace);
|
|
2777
|
-
results.push({ action, status: "applied", memoryId: action.memoryId });
|
|
2778
|
-
appliedTouched.push(action.memoryId);
|
|
2779
|
-
try {
|
|
2780
|
-
await this.deps.propagate(action.toNamespace, [destId]);
|
|
2781
|
-
} catch {
|
|
2782
|
-
}
|
|
2783
|
-
} catch (err) {
|
|
2784
|
-
results.push({ action, status: "failed", error: errMsg(err) });
|
|
2785
|
-
}
|
|
2786
|
-
}
|
|
2787
|
-
}
|
|
2788
|
-
const propagationWarnings = [];
|
|
2789
|
-
if (appliedTouched.length > 0) {
|
|
2790
|
-
try {
|
|
2791
|
-
await this.deps.propagate(namespace, appliedTouched);
|
|
2792
|
-
} catch (err) {
|
|
2793
|
-
propagationWarnings.push(`propagation failed (non-fatal): ${errMsg(err)}`);
|
|
2794
|
-
}
|
|
2795
|
-
}
|
|
2796
|
-
const anyFailed = results.some((r) => r.status === "failed");
|
|
2797
|
-
const status = anyFailed ? "partial" : "applied";
|
|
2798
|
-
const appliedAt = this.deps.now().toISOString();
|
|
2799
|
-
const outcome = {
|
|
2800
|
-
planId,
|
|
2801
|
-
status,
|
|
2802
|
-
results,
|
|
2803
|
-
auditMemoryId: "",
|
|
2804
|
-
// filled after the audit write
|
|
2805
|
-
appliedAt
|
|
2806
|
-
};
|
|
2807
|
-
if (propagationWarnings.length > 0) {
|
|
2808
|
-
outcome.warnings = propagationWarnings;
|
|
2809
|
-
}
|
|
2810
|
-
try {
|
|
2811
|
-
const auditId = await this.deps.appendAuditRecord(namespace, {
|
|
2812
|
-
planId,
|
|
2813
|
-
classification: plan.classification,
|
|
2814
|
-
outcome,
|
|
2815
|
-
requestText: plan.request.text
|
|
2816
|
-
});
|
|
2817
|
-
outcome.auditMemoryId = auditId;
|
|
2818
|
-
} catch (err) {
|
|
2819
|
-
outcome.warnings = [
|
|
2820
|
-
...propagationWarnings,
|
|
2821
|
-
`audit record write failed (non-fatal): ${errMsg(err)}`
|
|
2822
|
-
];
|
|
2823
|
-
}
|
|
2824
|
-
try {
|
|
2825
|
-
await this.planner.markConsumed(namespace, planId, status);
|
|
2826
|
-
} catch (err) {
|
|
2827
|
-
const w = outcome;
|
|
2828
|
-
w.warnings = [...w.warnings ?? [], `plan mark-consumed failed (non-fatal): ${errMsg(err)}`];
|
|
2829
|
-
}
|
|
2830
|
-
return outcome;
|
|
2831
|
-
}
|
|
2832
|
-
async retireAndTombstone(namespace, action, reason, results, appliedTouched, opts = {}) {
|
|
2833
|
-
const memoryId = action.kind === "supersede" ? action.loserId : action.kind === "retract" ? action.memoryId : null;
|
|
2834
|
-
if (!memoryId) return;
|
|
2835
|
-
try {
|
|
2836
|
-
const memory = await this.deps.getMemory(namespace, memoryId);
|
|
2837
|
-
if (!memory) {
|
|
2838
|
-
results.push({
|
|
2839
|
-
action,
|
|
2840
|
-
status: "failed",
|
|
2841
|
-
error: `memory not found: ${memoryId}`
|
|
2842
|
-
});
|
|
2843
|
-
return;
|
|
2844
|
-
}
|
|
2845
|
-
const validUntil = this.deps.biTemporalEnabled ? this.deps.now().toISOString() : void 0;
|
|
2846
|
-
const tombstoneId = await this.deps.appendTombstone(namespace, {
|
|
2847
|
-
reason,
|
|
2848
|
-
sourceMemoryId: memoryId,
|
|
2849
|
-
rawContent: memory.rawContent,
|
|
2850
|
-
...memory.entityRef ? { entityRef: memory.entityRef } : {},
|
|
2851
|
-
...memory.supersessionKey ? { supersessionKey: memory.supersessionKey } : {}
|
|
2852
|
-
});
|
|
2853
|
-
await this.deps.retireMemory(namespace, memoryId, {
|
|
2854
|
-
status: reason === "supersession" ? "superseded" : "retracted",
|
|
2855
|
-
...opts.supersededBy ? { supersededBy: opts.supersededBy } : {},
|
|
2856
|
-
...validUntil ? { validUntil } : {}
|
|
2857
|
-
});
|
|
2858
|
-
results.push({
|
|
2859
|
-
action,
|
|
2860
|
-
status: "applied",
|
|
2861
|
-
memoryId,
|
|
2862
|
-
...tombstoneId ? { tombstoneId } : {}
|
|
2863
|
-
});
|
|
2864
|
-
appliedTouched.push(memoryId);
|
|
2865
|
-
} catch (err) {
|
|
2866
|
-
results.push({ action, status: "failed", error: errMsg(err) });
|
|
2867
|
-
}
|
|
2868
|
-
}
|
|
2869
|
-
};
|
|
2870
|
-
function errMsg(err) {
|
|
2871
|
-
if (err instanceof Error) return err.message;
|
|
2872
|
-
return String(err);
|
|
2873
|
-
}
|
|
2874
|
-
|
|
2875
|
-
// src/correction/correction-service.ts
|
|
2876
|
-
var CorrectionService = class {
|
|
2877
|
-
constructor(deps) {
|
|
2878
|
-
this.deps = deps;
|
|
2879
|
-
this.planner = new CorrectionPlanner(deps.plannerDeps());
|
|
2880
|
-
this.executor = new CorrectionExecutor(deps.executorDeps(), this.planner);
|
|
2881
|
-
}
|
|
2882
|
-
deps;
|
|
2883
|
-
planner;
|
|
2884
|
-
executor;
|
|
2885
|
-
/**
|
|
2886
|
-
* Plan a correction. Read-only — produces + persists a {@link CorrectionPlan}.
|
|
2887
|
-
* Safe to run with the gate ON (default) since the plan writes no memory state.
|
|
2888
|
-
*
|
|
2889
|
-
* The plan is stored under the AUTHORIZED (writable) namespace — the same
|
|
2890
|
-
* namespace apply/listPending/discard resolve — so the plan is always
|
|
2891
|
-
* found by the caller that created it (review threads: plan-stored-wrong-
|
|
2892
|
-
* namespace + cross-namespace candidate mismatch). Candidates are located
|
|
2893
|
-
* within that single namespace too: a correction can only affect memories
|
|
2894
|
-
* the principal can write, so reading from a non-writable namespace to
|
|
2895
|
-
* draft a correction that can never be applied would be misleading.
|
|
2896
|
-
*/
|
|
2897
|
-
async plan(request) {
|
|
2898
|
-
this.requireEnabled();
|
|
2899
|
-
const authorized = await this.deps.policy.resolveAuthorizedNamespace(request);
|
|
2900
|
-
return this.planner.plan(request, [authorized]);
|
|
2901
|
-
}
|
|
2902
|
-
/**
|
|
2903
|
-
* Apply a persisted plan by id. Requires `confirm: true` (or interactive
|
|
2904
|
-
* yes at the CLI) when `applyRequiresConfirm` is on (default).
|
|
2905
|
-
*/
|
|
2906
|
-
async apply(planId, opts) {
|
|
2907
|
-
this.requireEnabled();
|
|
2908
|
-
if (this.deps.applyRequiresConfirm() && opts.confirm !== true) {
|
|
2909
|
-
throw new CorrectionContractError(
|
|
2910
|
-
"Correction apply requires explicit confirmation (pass `confirm: true`)."
|
|
2911
|
-
);
|
|
2912
|
-
}
|
|
2913
|
-
const namespace = await this.deps.policy.resolveAuthorizedNamespace({
|
|
2914
|
-
...opts.namespace ? { namespace: opts.namespace } : {},
|
|
2915
|
-
...opts.sessionKey ? { sessionKey: opts.sessionKey } : {},
|
|
2916
|
-
...opts.principal ? { principal: opts.principal } : {}
|
|
2917
|
-
});
|
|
2918
|
-
return this.executor.apply(namespace, planId, {
|
|
2919
|
-
confirm: true,
|
|
2920
|
-
// Authorize rescope destinations through the namespace policy bound to
|
|
2921
|
-
// THIS caller's principal (review thread: authorize-rescope-destination).
|
|
2922
|
-
canWriteDestination: (dest) => this.deps.policy.canWriteNamespace({
|
|
2923
|
-
namespace: dest,
|
|
2924
|
-
...opts.sessionKey ? { sessionKey: opts.sessionKey } : {},
|
|
2925
|
-
...opts.principal ? { principal: opts.principal } : {}
|
|
2926
|
-
})
|
|
2927
|
-
});
|
|
2928
|
-
}
|
|
2929
|
-
/** List pending (not-yet-applied) plans for the caller's namespace. */
|
|
2930
|
-
async listPending(opts) {
|
|
2931
|
-
this.requireEnabled();
|
|
2932
|
-
const namespace = await this.deps.policy.resolveAuthorizedNamespace(opts);
|
|
2933
|
-
return this.planner.listPending(namespace);
|
|
2934
|
-
}
|
|
2935
|
-
/** Discard a pending plan. Idempotent. */
|
|
2936
|
-
async discard(planId, opts) {
|
|
2937
|
-
this.requireEnabled();
|
|
2938
|
-
const namespace = await this.deps.policy.resolveAuthorizedNamespace(opts);
|
|
2939
|
-
await this.planner.markConsumed(namespace, planId, "discarded");
|
|
2940
|
-
await this.planner.deletePlan(namespace, planId);
|
|
2941
|
-
}
|
|
2942
|
-
requireEnabled() {
|
|
2943
|
-
if (!this.deps.isEnabled()) {
|
|
2944
|
-
throw new CorrectionContractError(
|
|
2945
|
-
"Correction Contract is disabled (set correction.enabled = true to enable)."
|
|
2946
|
-
);
|
|
2947
|
-
}
|
|
2948
|
-
}
|
|
2949
|
-
};
|
|
2950
|
-
|
|
2951
|
-
// src/correction/correction-access-wiring.ts
|
|
2952
|
-
import path5 from "path";
|
|
2953
|
-
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
2954
|
-
function createCorrectionService(wiring) {
|
|
2955
|
-
const cfg = wiring.orchestrator.config;
|
|
2956
|
-
const correctionEnabled = isCorrectionFeatureEnabled(cfg);
|
|
2957
|
-
const applyRequiresConfirm = typeof cfg.correctionApplyRequiresConfirm === "boolean" ? cfg.correctionApplyRequiresConfirm : readCorrectionFlag(cfg, "applyRequiresConfirm", true);
|
|
2958
|
-
const maxAffected = typeof cfg.correctionMaxAffected === "number" && cfg.correctionMaxAffected >= 1 ? Math.floor(cfg.correctionMaxAffected) : readCorrectionNumber(cfg, "maxAffected", 10);
|
|
2959
|
-
const planTtlHours = typeof cfg.correctionPlanTtlHours === "number" && cfg.correctionPlanTtlHours > 0 ? cfg.correctionPlanTtlHours : readCorrectionNumber(cfg, "planTtlHours", 24);
|
|
2960
|
-
const biTemporalEnabled = cfg.temporalBiTemporal === true;
|
|
2961
|
-
const serviceDeps = {
|
|
2962
|
-
policy: {
|
|
2963
|
-
resolveAuthorizedNamespace: (req) => wiring.resolveAuthorizedNamespace(req),
|
|
2964
|
-
canWriteNamespace: (req) => wiring.canWriteNamespace(req),
|
|
2965
|
-
readableNamespaces: (req) => Promise.resolve(wiring.resolveReadableNamespaces(req))
|
|
2966
|
-
},
|
|
2967
|
-
plannerDeps: () => makePlannerDeps(wiring, { maxAffected, planTtlHours }),
|
|
2968
|
-
executorDeps: () => makeExecutorDeps(wiring, { biTemporalEnabled }),
|
|
2969
|
-
isEnabled: () => correctionEnabled,
|
|
2970
|
-
applyRequiresConfirm: () => applyRequiresConfirm
|
|
2971
|
-
};
|
|
2972
|
-
return new CorrectionService(serviceDeps);
|
|
2973
|
-
}
|
|
2974
|
-
function makePlannerDeps(wiring, opts) {
|
|
2975
|
-
return {
|
|
2976
|
-
searchCorpus: async ({ text, namespaces, limit }) => searchMemories(wiring, text, namespaces, limit),
|
|
2977
|
-
resolveTargets: async ({ targetIds, namespaces }) => resolveTargetMemories(wiring, targetIds, namespaces),
|
|
2978
|
-
expandNeighbors: async ({ seedIds, namespaces, limit }) => expandEntityNeighbors(wiring, seedIds, namespaces, limit),
|
|
2979
|
-
classifyAndDraft: async ({ text, candidates }) => classifyAndDraft(wiring, text, candidates),
|
|
2980
|
-
renderDiff: async ({ candidates, actions }) => renderCorrectionDiff(wiring, candidates, actions),
|
|
2981
|
-
storageDir: async (namespace) => (await wiring.orchestrator.getStorage(namespace)).dir,
|
|
2982
|
-
maxAffected: opts.maxAffected,
|
|
2983
|
-
planTtlHours: opts.planTtlHours,
|
|
2984
|
-
now: () => /* @__PURE__ */ new Date()
|
|
2985
|
-
};
|
|
2986
|
-
}
|
|
2987
|
-
async function searchMemories(wiring, text, namespaces, limit) {
|
|
2988
|
-
const tokens = tokenize(text);
|
|
2989
|
-
if (tokens.length === 0) return [];
|
|
2990
|
-
const scored = [];
|
|
2991
|
-
for (const ns of namespaces) {
|
|
2992
|
-
const storage = await wiring.orchestrator.getStorage(ns);
|
|
2993
|
-
const all = await storage.readAllMemories();
|
|
2994
|
-
for (const m of all) {
|
|
2995
|
-
if (m.frontmatter.status && m.frontmatter.status !== "active") continue;
|
|
2996
|
-
const hay = `${m.content} ${m.frontmatter.tags?.join(" ") ?? ""}`.toLowerCase();
|
|
2997
|
-
let hits = 0;
|
|
2998
|
-
for (const tok of tokens) {
|
|
2999
|
-
if (hay.includes(tok)) hits++;
|
|
3000
|
-
}
|
|
3001
|
-
if (hits === 0) continue;
|
|
3002
|
-
scored.push({ m, ns, score: hits / tokens.length });
|
|
3003
|
-
}
|
|
3004
|
-
}
|
|
3005
|
-
scored.sort((a, b) => b.score - a.score);
|
|
3006
|
-
return scored.slice(0, limit).map((s, i) => toCandidate(s.m, s.ns, s.score - i * 0.01));
|
|
3007
|
-
}
|
|
3008
|
-
function tokenize(text) {
|
|
3009
|
-
const STOP = /* @__PURE__ */ new Set([
|
|
3010
|
-
"the",
|
|
3011
|
-
"a",
|
|
3012
|
-
"an",
|
|
3013
|
-
"is",
|
|
3014
|
-
"are",
|
|
3015
|
-
"was",
|
|
3016
|
-
"were",
|
|
3017
|
-
"be",
|
|
3018
|
-
"been",
|
|
3019
|
-
"being",
|
|
3020
|
-
"to",
|
|
3021
|
-
"of",
|
|
3022
|
-
"in",
|
|
3023
|
-
"on",
|
|
3024
|
-
"at",
|
|
3025
|
-
"by",
|
|
3026
|
-
"for",
|
|
3027
|
-
"with",
|
|
3028
|
-
"from",
|
|
3029
|
-
"into",
|
|
3030
|
-
"and",
|
|
3031
|
-
"or",
|
|
3032
|
-
"but",
|
|
3033
|
-
"not",
|
|
3034
|
-
"no",
|
|
3035
|
-
"yes",
|
|
3036
|
-
"this",
|
|
3037
|
-
"that",
|
|
3038
|
-
"these",
|
|
3039
|
-
"those",
|
|
3040
|
-
"it",
|
|
3041
|
-
"its",
|
|
3042
|
-
"we",
|
|
3043
|
-
"you",
|
|
3044
|
-
"i",
|
|
3045
|
-
"he",
|
|
3046
|
-
"she",
|
|
3047
|
-
"they",
|
|
3048
|
-
"them",
|
|
3049
|
-
"our",
|
|
3050
|
-
"your",
|
|
3051
|
-
"my",
|
|
3052
|
-
"his",
|
|
3053
|
-
"her",
|
|
3054
|
-
"their",
|
|
3055
|
-
"as",
|
|
3056
|
-
"so",
|
|
3057
|
-
"if",
|
|
3058
|
-
"then",
|
|
3059
|
-
"than",
|
|
3060
|
-
"too",
|
|
3061
|
-
"very",
|
|
3062
|
-
"can",
|
|
3063
|
-
"will",
|
|
3064
|
-
"just",
|
|
3065
|
-
"should",
|
|
3066
|
-
"now",
|
|
3067
|
-
"has",
|
|
3068
|
-
"have",
|
|
3069
|
-
"had",
|
|
3070
|
-
"do",
|
|
3071
|
-
"does",
|
|
3072
|
-
"did",
|
|
3073
|
-
"about",
|
|
3074
|
-
"which",
|
|
3075
|
-
"what",
|
|
3076
|
-
"who",
|
|
3077
|
-
"when",
|
|
3078
|
-
"where",
|
|
3079
|
-
"why",
|
|
3080
|
-
"how",
|
|
3081
|
-
"all",
|
|
3082
|
-
"each",
|
|
3083
|
-
"every",
|
|
3084
|
-
"both",
|
|
3085
|
-
"few",
|
|
3086
|
-
"more",
|
|
3087
|
-
"most",
|
|
3088
|
-
"other",
|
|
3089
|
-
"some",
|
|
3090
|
-
"such",
|
|
3091
|
-
"only",
|
|
3092
|
-
"own",
|
|
3093
|
-
"same",
|
|
3094
|
-
"up"
|
|
3095
|
-
]);
|
|
3096
|
-
const raw = text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
3097
|
-
const out = raw.filter((w) => w.length >= 3 && !STOP.has(w));
|
|
3098
|
-
return [...new Set(out)];
|
|
3099
|
-
}
|
|
3100
|
-
async function resolveTargetMemories(wiring, targetIds, namespaces) {
|
|
3101
|
-
const out = [];
|
|
3102
|
-
const missing = [];
|
|
3103
|
-
for (const id of targetIds) {
|
|
3104
|
-
let found = null;
|
|
3105
|
-
for (const ns of namespaces) {
|
|
3106
|
-
const storage = await wiring.orchestrator.getStorage(ns);
|
|
3107
|
-
const m = await storage.getMemoryById(id);
|
|
3108
|
-
if (m) {
|
|
3109
|
-
found = toCandidate(m, ns, 1);
|
|
3110
|
-
break;
|
|
3111
|
-
}
|
|
3112
|
-
}
|
|
3113
|
-
if (found) out.push(found);
|
|
3114
|
-
else missing.push(id);
|
|
3115
|
-
}
|
|
3116
|
-
if (missing.length > 0) {
|
|
3117
|
-
throw new CorrectionContractError(`target memory not found: ${missing[0]}`);
|
|
3118
|
-
}
|
|
3119
|
-
return out;
|
|
3120
|
-
}
|
|
3121
|
-
async function expandEntityNeighbors(wiring, seedIds, namespaces, limit) {
|
|
3122
|
-
if (seedIds.length === 0 || limit <= 0 || namespaces.length === 0) return [];
|
|
3123
|
-
const out = [];
|
|
3124
|
-
const seen = new Set(seedIds);
|
|
3125
|
-
const seedRefs = /* @__PURE__ */ new Set();
|
|
3126
|
-
for (const ns of namespaces) {
|
|
3127
|
-
const storage = await wiring.orchestrator.getStorage(ns);
|
|
3128
|
-
const all = await storage.readAllMemories();
|
|
3129
|
-
for (const m of all) {
|
|
3130
|
-
if (seedIds.includes(m.frontmatter.id) && m.frontmatter.entityRef) {
|
|
3131
|
-
seedRefs.add(m.frontmatter.entityRef);
|
|
3132
|
-
}
|
|
3133
|
-
}
|
|
3134
|
-
}
|
|
3135
|
-
if (seedRefs.size === 0) return [];
|
|
3136
|
-
for (const ns of namespaces) {
|
|
3137
|
-
if (out.length >= limit) break;
|
|
3138
|
-
const storage = await wiring.orchestrator.getStorage(ns);
|
|
3139
|
-
const all = await storage.readAllMemories();
|
|
3140
|
-
for (const m of all) {
|
|
3141
|
-
if (out.length >= limit) break;
|
|
3142
|
-
if (seen.has(m.frontmatter.id)) continue;
|
|
3143
|
-
if (m.frontmatter.status && m.frontmatter.status !== "active") continue;
|
|
3144
|
-
if (m.frontmatter.entityRef && seedRefs.has(m.frontmatter.entityRef)) {
|
|
3145
|
-
out.push(toCandidate(m, ns, 0.5));
|
|
3146
|
-
seen.add(m.frontmatter.id);
|
|
3147
|
-
}
|
|
3148
|
-
}
|
|
3149
|
-
}
|
|
3150
|
-
return out;
|
|
3151
|
-
}
|
|
3152
|
-
async function classifyAndDraft(wiring, text, candidates) {
|
|
3153
|
-
try {
|
|
3154
|
-
if (!wiring.llmComplete) {
|
|
3155
|
-
return fallbackClassification(candidates, "no LLM client available");
|
|
3156
|
-
}
|
|
3157
|
-
const user = buildClassifyPrompt(text, candidates);
|
|
3158
|
-
const raw = await wiring.llmComplete({ system: CLASSIFY_SYSTEM_PROMPT, user });
|
|
3159
|
-
return parseClassifyResponse(raw, candidates);
|
|
3160
|
-
} catch (err) {
|
|
3161
|
-
return fallbackClassification(candidates, `LLM unavailable: ${errMsg2(err)}`);
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
async function renderCorrectionDiff(_wiring, candidates, actions) {
|
|
3165
|
-
const lines = [];
|
|
3166
|
-
for (const action of actions) {
|
|
3167
|
-
const id = action.kind === "supersede" ? action.loserId : action.kind === "edit" || action.kind === "retract" || action.kind === "rescope" ? action.memoryId : null;
|
|
3168
|
-
const candidate = id ? candidates.find((c) => c.memoryId === id) : null;
|
|
3169
|
-
const before = candidate?.content ?? "(new)";
|
|
3170
|
-
const after = describeAfterState(action);
|
|
3171
|
-
lines.push(`--- ${id ?? "redaction-rule"} (${action.kind})`);
|
|
3172
|
-
lines.push(`- ${before.slice(0, 120)}`);
|
|
3173
|
-
lines.push(`+ ${after.slice(0, 120)}`);
|
|
3174
|
-
}
|
|
3175
|
-
return lines.join("\n");
|
|
3176
|
-
}
|
|
3177
|
-
function describeAfterState(action) {
|
|
3178
|
-
switch (action.kind) {
|
|
3179
|
-
case "supersede":
|
|
3180
|
-
return action.replacement?.content ?? "(superseded without replacement)";
|
|
3181
|
-
case "edit":
|
|
3182
|
-
return action.patch;
|
|
3183
|
-
case "retract":
|
|
3184
|
-
return "(retracted + tombstoned)";
|
|
3185
|
-
case "rescope":
|
|
3186
|
-
return `(moved to namespace '${action.toNamespace}')`;
|
|
3187
|
-
case "redaction_rule":
|
|
3188
|
-
return `(redaction rule persisted for pattern '${action.pattern}')`;
|
|
3189
|
-
}
|
|
3190
|
-
}
|
|
3191
|
-
function makeExecutorDeps(wiring, opts) {
|
|
3192
|
-
return {
|
|
3193
|
-
getMemory: async (namespace, memoryId) => getExecutorMemory(wiring, namespace, memoryId),
|
|
3194
|
-
writeReplacement: async (namespace, draft) => writeReplacementMemory(wiring, namespace, draft),
|
|
3195
|
-
applyEdit: async (namespace, memoryId, patch) => applyEditMemory(wiring, namespace, memoryId, patch),
|
|
3196
|
-
retireMemory: async (namespace, memoryId, retireOpts) => retireMemoryFn(wiring, namespace, memoryId, retireOpts),
|
|
3197
|
-
rescopeMemory: async (namespace, memoryId, toNamespace) => rescopeMemoryFn(wiring, namespace, memoryId, toNamespace),
|
|
3198
|
-
appendTombstone: async (namespace, input) => appendTombstoneFn(wiring, namespace, input),
|
|
3199
|
-
registerRedactionRule: async (namespace, pattern) => registerRedactionRuleFn(wiring, namespace, pattern),
|
|
3200
|
-
appendAuditRecord: async (namespace, record) => appendAuditRecordFn(wiring, namespace, record),
|
|
3201
|
-
propagate: async (namespace, touchedMemoryIds) => propagateFn(wiring, namespace, touchedMemoryIds),
|
|
3202
|
-
biTemporalEnabled: opts.biTemporalEnabled,
|
|
3203
|
-
now: () => /* @__PURE__ */ new Date()
|
|
3204
|
-
};
|
|
3205
|
-
}
|
|
3206
|
-
async function getExecutorMemory(wiring, namespace, memoryId) {
|
|
3207
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3208
|
-
const m = await storage.getMemoryById(memoryId);
|
|
3209
|
-
if (!m) return null;
|
|
3210
|
-
return toExecutorMemory(m);
|
|
3211
|
-
}
|
|
3212
|
-
async function writeReplacementMemory(wiring, namespace, draft) {
|
|
3213
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3214
|
-
const id = await storage.writeMemory(
|
|
3215
|
-
draft.category ?? "fact",
|
|
3216
|
-
draft.content,
|
|
3217
|
-
{
|
|
3218
|
-
source: "correction",
|
|
3219
|
-
confidence: draft.confidence ?? 0.9,
|
|
3220
|
-
tags: draft.tags ?? [],
|
|
3221
|
-
...draft.entityRef ? { entityRef: draft.entityRef } : {},
|
|
3222
|
-
...draft.validAt ? { validAt: draft.validAt } : {},
|
|
3223
|
-
...draft.observedAt ? { observedAt: draft.observedAt } : {},
|
|
3224
|
-
...draft.structuredAttributes ? { structuredAttributes: draft.structuredAttributes } : {},
|
|
3225
|
-
...draft.supersedes ? { supersedes: draft.supersedes } : {}
|
|
3226
|
-
}
|
|
3227
|
-
);
|
|
3228
|
-
return id;
|
|
3229
|
-
}
|
|
3230
|
-
async function applyEditMemory(wiring, namespace, memoryId, patch) {
|
|
3231
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3232
|
-
const existing = await storage.getMemoryById(memoryId);
|
|
3233
|
-
if (!existing) throw new CorrectionContractError(`memory not found for edit: ${memoryId}`);
|
|
3234
|
-
await storage.writeMemoryFrontmatter(
|
|
3235
|
-
{ ...existing, content: patch },
|
|
3236
|
-
{ updated: (/* @__PURE__ */ new Date()).toISOString() }
|
|
3237
|
-
);
|
|
3238
|
-
return memoryId;
|
|
3239
|
-
}
|
|
3240
|
-
async function retireMemoryFn(wiring, namespace, memoryId, opts) {
|
|
3241
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3242
|
-
const memory = await storage.getMemoryById(memoryId);
|
|
3243
|
-
if (!memory) throw new CorrectionContractError(`memory not found for retire: ${memoryId}`);
|
|
3244
|
-
const storageStatus = opts.status === "retracted" ? "forgotten" : "superseded";
|
|
3245
|
-
await storage.writeMemoryFrontmatter(memory, {
|
|
3246
|
-
status: storageStatus,
|
|
3247
|
-
...opts.supersededBy ? { supersededBy: opts.supersededBy } : {},
|
|
3248
|
-
...opts.status === "superseded" ? { supersededAt: (/* @__PURE__ */ new Date()).toISOString() } : {},
|
|
3249
|
-
// validUntil is the bi-temporal end; absent when the gate is off.
|
|
3250
|
-
...opts.validUntil ? { invalid_at: opts.validUntil } : {}
|
|
3251
|
-
});
|
|
3252
|
-
}
|
|
3253
|
-
async function rescopeMemoryFn(wiring, namespace, memoryId, toNamespace) {
|
|
3254
|
-
const sourceStorage = await wiring.orchestrator.getStorage(namespace);
|
|
3255
|
-
const memory = await sourceStorage.getMemoryById(memoryId);
|
|
3256
|
-
if (!memory) throw new CorrectionContractError(`memory not found for rescope: ${memoryId}`);
|
|
3257
|
-
if (memory.frontmatter.status && memory.frontmatter.status !== "active") {
|
|
3258
|
-
throw new CorrectionContractError(
|
|
3259
|
-
`cannot rescope memory ${memoryId}: source is ${memory.frontmatter.status}, not active`
|
|
3260
|
-
);
|
|
3261
|
-
}
|
|
3262
|
-
const destStorage = await wiring.orchestrator.getStorage(toNamespace);
|
|
3263
|
-
const fm = memory.frontmatter;
|
|
3264
|
-
const destContent = fm.structuredAttributes ? stripAttributesSuffix(memory.content) : memory.content;
|
|
3265
|
-
const destId = await destStorage.writeMemory(fm.category, destContent, {
|
|
3266
|
-
source: `correction:rescope:${namespace}`,
|
|
3267
|
-
...typeof fm.confidence === "number" ? { confidence: fm.confidence } : {},
|
|
3268
|
-
...Array.isArray(fm.tags) ? { tags: fm.tags } : {},
|
|
3269
|
-
...fm.entityRef ? { entityRef: fm.entityRef } : {},
|
|
3270
|
-
...fm.structuredAttributes ? { structuredAttributes: fm.structuredAttributes } : {},
|
|
3271
|
-
...fm.valid_at ? { validAt: fm.valid_at } : {},
|
|
3272
|
-
...fm.observedAt ? { observedAt: fm.observedAt } : {},
|
|
3273
|
-
...fm.memoryKind ? { memoryKind: fm.memoryKind } : {},
|
|
3274
|
-
...Array.isArray(fm.links) ? { links: fm.links } : {},
|
|
3275
|
-
...fm.intentGoal ? { intentGoal: fm.intentGoal } : {}
|
|
3276
|
-
});
|
|
3277
|
-
try {
|
|
3278
|
-
await sourceStorage.writeMemoryFrontmatter(memory, {
|
|
3279
|
-
status: "archived",
|
|
3280
|
-
archivedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3281
|
-
});
|
|
3282
|
-
} catch (err) {
|
|
3283
|
-
try {
|
|
3284
|
-
const destMem = await destStorage.getMemoryById(destId);
|
|
3285
|
-
if (destMem) {
|
|
3286
|
-
await destStorage.writeMemoryFrontmatter(destMem, {
|
|
3287
|
-
status: "archived",
|
|
3288
|
-
archivedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
3289
|
-
});
|
|
3290
|
-
}
|
|
3291
|
-
} catch {
|
|
3292
|
-
}
|
|
3293
|
-
throw err;
|
|
3294
|
-
}
|
|
3295
|
-
return destId;
|
|
3296
|
-
}
|
|
3297
|
-
async function appendTombstoneFn(wiring, namespace, input) {
|
|
3298
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3299
|
-
const enabled = typeof storage.isTombstonesEnabled === "function" ? storage.isTombstonesEnabled() : true;
|
|
3300
|
-
const result = await storage.appendTombstone({
|
|
3301
|
-
reason: input.reason,
|
|
3302
|
-
createdBy: "user_correction",
|
|
3303
|
-
sourceMemoryId: input.sourceMemoryId,
|
|
3304
|
-
rawContent: input.rawContent,
|
|
3305
|
-
...input.entityRef ? { entityRef: input.entityRef } : {},
|
|
3306
|
-
...input.supersessionKey ? { supersessionKey: input.supersessionKey } : {}
|
|
3307
|
-
});
|
|
3308
|
-
if (result === null && enabled) {
|
|
3309
|
-
throw new CorrectionContractError(
|
|
3310
|
-
`tombstone persistence failed for memory ${input.sourceMemoryId} (tombstones enabled but store returned null \u2014 I/O error swallowed)`
|
|
3311
|
-
);
|
|
3312
|
-
}
|
|
3313
|
-
return result;
|
|
3314
|
-
}
|
|
3315
|
-
async function registerRedactionRuleFn(wiring, namespace, pattern) {
|
|
3316
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3317
|
-
const dir = path5.join(storage.dir, "state", "corrections", "redaction-rules");
|
|
3318
|
-
await mkdir3(dir, { recursive: true });
|
|
3319
|
-
const slug = pattern.replace(/[^a-zA-Z0-9]+/g, "-").slice(0, 64) || "rule";
|
|
3320
|
-
await writeFile3(
|
|
3321
|
-
path5.join(dir, `${slug}.json`),
|
|
3322
|
-
`${JSON.stringify({ pattern, namespace, createdAt: (/* @__PURE__ */ new Date()).toISOString() })}
|
|
3323
|
-
`,
|
|
3324
|
-
"utf-8"
|
|
3325
|
-
);
|
|
3326
|
-
}
|
|
3327
|
-
async function appendAuditRecordFn(wiring, namespace, record) {
|
|
3328
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3329
|
-
const id = await storage.writeMemory("correction", buildAuditBody(record), {
|
|
3330
|
-
source: "correction-contract",
|
|
3331
|
-
confidence: 1,
|
|
3332
|
-
tags: ["correction-audit", `plan:${record.planId}`, `classification:${record.classification}`]
|
|
3333
|
-
});
|
|
3334
|
-
return id;
|
|
3335
|
-
}
|
|
3336
|
-
function buildAuditBody(record) {
|
|
3337
|
-
const sensitive = record.classification === "never_store" || record.outcome.results.some((r) => r.action.kind === "redaction_rule");
|
|
3338
|
-
const safeRequest = sensitive ? "[redacted \u2014 never-store/redaction correction text withheld from the audit trail]" : record.requestText.slice(0, 200);
|
|
3339
|
-
const lines = [
|
|
3340
|
-
`Correction plan ${record.planId} applied (${record.outcome.status}).`,
|
|
3341
|
-
"",
|
|
3342
|
-
`Request: ${safeRequest}`,
|
|
3343
|
-
`Classification: ${record.classification}`,
|
|
3344
|
-
`Applied at: ${record.outcome.appliedAt}`,
|
|
3345
|
-
"",
|
|
3346
|
-
"Actions:"
|
|
3347
|
-
];
|
|
3348
|
-
for (const r of record.outcome.results) {
|
|
3349
|
-
const withhold = r.action.kind === "redaction_rule" || record.classification === "never_store";
|
|
3350
|
-
const errPart = r.error ? withhold ? " (error withheld)" : ` (${r.error})` : "";
|
|
3351
|
-
lines.push(` - ${r.action.kind}: ${r.status}${errPart}`);
|
|
3352
|
-
}
|
|
3353
|
-
return lines.join("\n");
|
|
3354
|
-
}
|
|
3355
|
-
async function propagateFn(wiring, namespace, touchedMemoryIds) {
|
|
3356
|
-
for (const id of touchedMemoryIds) {
|
|
3357
|
-
try {
|
|
3358
|
-
const storage = await wiring.orchestrator.getStorage(namespace);
|
|
3359
|
-
const orchestrator = wiring.orchestrator;
|
|
3360
|
-
if (typeof orchestrator.indexPersistedMemory === "function") {
|
|
3361
|
-
await orchestrator.indexPersistedMemory(storage, id);
|
|
3362
|
-
}
|
|
3363
|
-
} catch {
|
|
3364
|
-
}
|
|
3365
|
-
}
|
|
3366
|
-
}
|
|
3367
|
-
function toCandidate(m, namespace, score) {
|
|
3368
|
-
return {
|
|
3369
|
-
memoryId: m.frontmatter.id,
|
|
3370
|
-
path: m.path,
|
|
3371
|
-
content: m.content,
|
|
3372
|
-
excerpt: m.content.slice(0, 160),
|
|
3373
|
-
...m.frontmatter.entityRef ? { entityRef: m.frontmatter.entityRef } : {},
|
|
3374
|
-
score
|
|
3375
|
-
// namespace is implicit (the planner scopes by namespace); keep it on the
|
|
3376
|
-
// candidate for diff rendering if needed.
|
|
3377
|
-
};
|
|
3378
|
-
}
|
|
3379
|
-
function toExecutorMemory(m) {
|
|
3380
|
-
const fm = m.frontmatter;
|
|
3381
|
-
const rawBody = fm.structuredAttributes ? stripAttributesSuffix(m.content) : m.content;
|
|
3382
|
-
return {
|
|
3383
|
-
memoryId: fm.id,
|
|
3384
|
-
content: m.content,
|
|
3385
|
-
category: fm.category,
|
|
3386
|
-
rawContent: rawBody,
|
|
3387
|
-
...fm.entityRef ? { entityRef: fm.entityRef } : {}
|
|
3388
|
-
};
|
|
3389
|
-
}
|
|
3390
|
-
function isCorrectionFeatureEnabled(config) {
|
|
3391
|
-
if (typeof config.correctionEnabled === "boolean") return config.correctionEnabled;
|
|
3392
|
-
const nested = config.correction;
|
|
3393
|
-
if (nested && typeof nested.enabled === "boolean") return nested.enabled;
|
|
3394
|
-
if (nested && typeof nested.enabled === "string") return nested.enabled === "true" || nested.enabled === "1";
|
|
3395
|
-
return readCorrectionFlag(config, "enabled", true);
|
|
3396
|
-
}
|
|
3397
|
-
function readCorrectionFlag(config, key, fallback) {
|
|
3398
|
-
const nested = config.correction;
|
|
3399
|
-
if (nested && typeof nested[key] === "boolean") return nested[key];
|
|
3400
|
-
if (nested && typeof nested[key] === "string") return nested[key] === "true" || nested[key] === "1";
|
|
3401
|
-
const raw = config[`correction${capitalize(key)}`];
|
|
3402
|
-
if (typeof raw === "boolean") return raw;
|
|
3403
|
-
if (typeof raw === "string") return raw === "true" || raw === "1";
|
|
3404
|
-
return fallback;
|
|
3405
|
-
}
|
|
3406
|
-
function readCorrectionNumber(config, key, fallback) {
|
|
3407
|
-
const nested = config.correction;
|
|
3408
|
-
if (nested) {
|
|
3409
|
-
const nv = nested[key];
|
|
3410
|
-
if (typeof nv === "number" && Number.isFinite(nv)) return nv;
|
|
3411
|
-
if (typeof nv === "string") {
|
|
3412
|
-
const nn = Number(nv);
|
|
3413
|
-
if (Number.isFinite(nn)) return nn;
|
|
3414
|
-
}
|
|
3415
|
-
}
|
|
3416
|
-
const raw = config[`correction${capitalize(key)}`];
|
|
3417
|
-
if (typeof raw === "number" && Number.isFinite(raw)) return raw;
|
|
3418
|
-
if (typeof raw === "string") {
|
|
3419
|
-
const n = Number(raw);
|
|
3420
|
-
if (Number.isFinite(n)) return n;
|
|
3421
|
-
}
|
|
3422
|
-
return fallback;
|
|
3423
|
-
}
|
|
3424
|
-
function capitalize(s) {
|
|
3425
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
3426
|
-
}
|
|
3427
|
-
function errMsg2(err) {
|
|
3428
|
-
if (err instanceof Error) return err.message;
|
|
3429
|
-
return String(err);
|
|
3430
|
-
}
|
|
3431
|
-
var CLASSIFY_SYSTEM_PROMPT = `You classify memory corrections and draft per-memory actions.
|
|
3432
|
-
|
|
3433
|
-
Given a correction statement and candidate memories, respond with a JSON object:
|
|
3434
|
-
{
|
|
3435
|
-
"classification": "wrong" | "outdated" | "incomplete" | "wrong_scope" | "never_store",
|
|
3436
|
-
"confidence": <number 0..1>,
|
|
3437
|
-
"actions": [<one or more correction actions>],
|
|
3438
|
-
"relevance": [{"memoryId": "<id>", "why": "<one short sentence>"}]
|
|
3439
|
-
}
|
|
3440
|
-
|
|
3441
|
-
Action shapes:
|
|
3442
|
-
- {"kind":"supersede","loserId":"<id>","replacement":{"content":"<new fact>"}}
|
|
3443
|
-
- {"kind":"edit","memoryId":"<id>","patch":"<new full content>"}
|
|
3444
|
-
- {"kind":"retract","memoryId":"<id>"}
|
|
3445
|
-
- {"kind":"rescope","memoryId":"<id>","toNamespace":"<ns>"}
|
|
3446
|
-
- {"kind":"redaction_rule","pattern":"<bounded literal or regex>"}
|
|
3447
|
-
|
|
3448
|
-
Only emit actions you are confident in. If uncertain, return confidence < 0.5 and few actions.`;
|
|
3449
|
-
function buildClassifyPrompt(text, candidates) {
|
|
3450
|
-
const lines = [
|
|
3451
|
-
`Correction: ${text}`,
|
|
3452
|
-
"",
|
|
3453
|
-
"Candidate memories:"
|
|
3454
|
-
];
|
|
3455
|
-
for (const c of candidates.slice(0, 20)) {
|
|
3456
|
-
lines.push(`[${c.memoryId}] ${c.excerpt}`);
|
|
3457
|
-
}
|
|
3458
|
-
lines.push("", "Respond with the JSON object only.");
|
|
3459
|
-
return lines.join("\n");
|
|
3460
|
-
}
|
|
3461
|
-
function parseClassifyResponse(raw, candidates) {
|
|
3462
|
-
let parsed;
|
|
3463
|
-
try {
|
|
3464
|
-
parsed = JSON.parse(raw);
|
|
3465
|
-
} catch {
|
|
3466
|
-
return fallbackClassification(candidates, "LLM returned non-JSON response");
|
|
3467
|
-
}
|
|
3468
|
-
if (!parsed || typeof parsed !== "object") {
|
|
3469
|
-
return fallbackClassification(candidates, "LLM returned non-object response");
|
|
3470
|
-
}
|
|
3471
|
-
const obj = parsed;
|
|
3472
|
-
const classification = isClassification(obj.classification) ? obj.classification : "outdated";
|
|
3473
|
-
const confidence = typeof obj.confidence === "number" ? Math.min(1, Math.max(0, obj.confidence)) : 0.5;
|
|
3474
|
-
const rawActions = Array.isArray(obj.actions) ? obj.actions : [];
|
|
3475
|
-
const actions = [];
|
|
3476
|
-
const warnings = [];
|
|
3477
|
-
for (const rawAction of rawActions) {
|
|
3478
|
-
try {
|
|
3479
|
-
validateCorrectionAction(rawAction);
|
|
3480
|
-
actions.push(rawAction);
|
|
3481
|
-
} catch (err) {
|
|
3482
|
-
warnings.push(`dropped malformed action: ${errMsg2(err)}`);
|
|
3483
|
-
}
|
|
3484
|
-
}
|
|
3485
|
-
const relevance = Array.isArray(obj.relevance) ? obj.relevance.filter((r) => !!r && typeof r === "object").map((r) => ({
|
|
3486
|
-
memoryId: typeof r.memoryId === "string" ? r.memoryId : "",
|
|
3487
|
-
why: typeof r.why === "string" ? r.why : ""
|
|
3488
|
-
})).filter((r) => r.memoryId.length > 0) : [];
|
|
3489
|
-
return {
|
|
3490
|
-
classification,
|
|
3491
|
-
confidence,
|
|
3492
|
-
actions,
|
|
3493
|
-
relevance,
|
|
3494
|
-
warnings
|
|
3495
|
-
};
|
|
3496
|
-
}
|
|
3497
|
-
function isClassification(value) {
|
|
3498
|
-
return value === "wrong" || value === "outdated" || value === "incomplete" || value === "wrong_scope" || value === "never_store";
|
|
3499
|
-
}
|
|
3500
|
-
function fallbackClassification(candidates, reason) {
|
|
3501
|
-
return {
|
|
3502
|
-
classification: "outdated",
|
|
3503
|
-
confidence: 0,
|
|
3504
|
-
actions: [],
|
|
3505
|
-
relevance: candidates.map((c) => ({ memoryId: c.memoryId, why: "located for review" })),
|
|
3506
|
-
warnings: [reason],
|
|
3507
|
-
fallback: true
|
|
3508
|
-
};
|
|
3509
|
-
}
|
|
3510
|
-
|
|
3511
2142
|
// src/procedural/procedure-miner.ts
|
|
3512
2143
|
import { createHash as createHash2 } from "crypto";
|
|
3513
|
-
import { mkdir as
|
|
3514
|
-
import
|
|
2144
|
+
import { mkdir as mkdir2, rm, stat } from "fs/promises";
|
|
2145
|
+
import path4 from "path";
|
|
3515
2146
|
var PROCEDURE_CLUSTER_ATTR_MAX = 500;
|
|
3516
2147
|
var PROCEDURE_CLUSTER_LOCK_STALE_MS = 12e4;
|
|
3517
2148
|
var PROCEDURE_CLUSTER_LOCK_TIMEOUT_MS = 3e4;
|
|
@@ -3531,14 +2162,14 @@ function sleep(ms) {
|
|
|
3531
2162
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
3532
2163
|
}
|
|
3533
2164
|
async function acquireClusterWriteLock(memoryDir, clusterHash) {
|
|
3534
|
-
const lockRoot =
|
|
3535
|
-
const lockDir =
|
|
3536
|
-
await
|
|
2165
|
+
const lockRoot = path4.join(path4.resolve(memoryDir), "state", "procedure-miner-locks");
|
|
2166
|
+
const lockDir = path4.join(lockRoot, `${clusterHash}.lock`);
|
|
2167
|
+
await mkdir2(lockRoot, { recursive: true });
|
|
3537
2168
|
const startedAt = Date.now();
|
|
3538
2169
|
let attempts = 0;
|
|
3539
2170
|
while (true) {
|
|
3540
2171
|
try {
|
|
3541
|
-
await
|
|
2172
|
+
await mkdir2(lockDir);
|
|
3542
2173
|
return async () => {
|
|
3543
2174
|
await rm(lockDir, { recursive: true, force: true });
|
|
3544
2175
|
};
|
|
@@ -3563,7 +2194,7 @@ async function acquireClusterWriteLock(memoryDir, clusterHash) {
|
|
|
3563
2194
|
}
|
|
3564
2195
|
}
|
|
3565
2196
|
async function withClusterWriteLock(memoryDir, clusterHash, fn) {
|
|
3566
|
-
const inProcessKey = `${
|
|
2197
|
+
const inProcessKey = `${path4.resolve(memoryDir)}:${clusterHash}`;
|
|
3567
2198
|
const previous = inProcessClusterWriteLocks.get(inProcessKey) ?? Promise.resolve();
|
|
3568
2199
|
let releaseInProcess;
|
|
3569
2200
|
const current = previous.catch(() => void 0).then(
|
|
@@ -3802,7 +2433,7 @@ function formatProcedureStatsText(report) {
|
|
|
3802
2433
|
}
|
|
3803
2434
|
|
|
3804
2435
|
// src/admin/admin-surfaces.ts
|
|
3805
|
-
import
|
|
2436
|
+
import path5 from "path";
|
|
3806
2437
|
var REDACTED = "<redacted>";
|
|
3807
2438
|
var SENSITIVE_KEY_RE = /(token|secret|password|api[_-]?key|bearer|authorization|credential|private[_-]?key)/i;
|
|
3808
2439
|
var BEARER_VALUE_RE = /^(bearer|sk-|pk-|xox[bp]-|AKIA)/i;
|
|
@@ -4033,7 +2664,7 @@ async function auditTranscripts(memoryDir) {
|
|
|
4033
2664
|
movedEntries: file.groups.reduce((sum, group) => sum + group.entryCount, 0),
|
|
4034
2665
|
unmovableLines: file.unmovableLines
|
|
4035
2666
|
}));
|
|
4036
|
-
const mixedOtherDefault = files.some((file) => file.sourceRelPath.split(
|
|
2667
|
+
const mixedOtherDefault = files.some((file) => file.sourceRelPath.split(path5.sep).includes("other"));
|
|
4037
2668
|
const summary = plan.movedEntries === 0 ? "No mixed-session transcript data detected; nothing to migrate." : `Found ${plan.movedEntries} entries across ${plan.distinctSessions} distinct sessions stranded in shared/legacy directories. Run the CLI migration command to re-home them.`;
|
|
4038
2669
|
return {
|
|
4039
2670
|
generatedAt: plan.generatedAt,
|
|
@@ -4412,13 +3043,19 @@ var EngramAccessService = class {
|
|
|
4412
3043
|
if (trusted) return trusted;
|
|
4413
3044
|
return resolvePrincipal(sessionKey, this.orchestrator.config);
|
|
4414
3045
|
}
|
|
4415
|
-
|
|
4416
|
-
const
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
3046
|
+
writableNamespaceFor(namespace, sessionKey, authenticatedPrincipal) {
|
|
3047
|
+
const result = resolveWritableNamespaceValue(
|
|
3048
|
+
namespace,
|
|
3049
|
+
sessionKey,
|
|
3050
|
+
authenticatedPrincipal,
|
|
3051
|
+
this.orchestrator.config
|
|
3052
|
+
);
|
|
3053
|
+
if (!result.ok) {
|
|
3054
|
+
throw new EngramAccessInputError(
|
|
3055
|
+
result.reason === "unsupported" ? `unsupported namespace: ${result.namespace}` : `namespace is not writable: ${result.namespace}`
|
|
3056
|
+
);
|
|
4420
3057
|
}
|
|
4421
|
-
return
|
|
3058
|
+
return result.namespace;
|
|
4422
3059
|
}
|
|
4423
3060
|
/**
|
|
4424
3061
|
* Resolve a coding context from `cwd`/`projectTag` WITHOUT persisting it to
|
|
@@ -4486,7 +3123,7 @@ var EngramAccessService = class {
|
|
|
4486
3123
|
async resolveCodingScopedWriteNamespace(request) {
|
|
4487
3124
|
const hasExplicitNamespace = typeof request.namespace === "string" && request.namespace.trim().length > 0;
|
|
4488
3125
|
if (hasExplicitNamespace) {
|
|
4489
|
-
return this.
|
|
3126
|
+
return this.writableNamespaceFor(
|
|
4490
3127
|
request.namespace,
|
|
4491
3128
|
request.sessionKey,
|
|
4492
3129
|
request.authenticatedPrincipal
|
|
@@ -4504,7 +3141,7 @@ var EngramAccessService = class {
|
|
|
4504
3141
|
return profilePlan.writeNamespace;
|
|
4505
3142
|
}
|
|
4506
3143
|
if (!overlay) {
|
|
4507
|
-
return this.
|
|
3144
|
+
return this.writableNamespaceFor(
|
|
4508
3145
|
void 0,
|
|
4509
3146
|
request.sessionKey,
|
|
4510
3147
|
request.authenticatedPrincipal
|
|
@@ -4582,7 +3219,7 @@ var EngramAccessService = class {
|
|
|
4582
3219
|
);
|
|
4583
3220
|
const hasExplicitNamespace = typeof request.namespace === "string" && request.namespace.trim().length > 0;
|
|
4584
3221
|
if (hasExplicitNamespace) {
|
|
4585
|
-
const writeNamespace2 = this.
|
|
3222
|
+
const writeNamespace2 = this.writableNamespaceFor(
|
|
4586
3223
|
request.namespace,
|
|
4587
3224
|
request.sessionKey,
|
|
4588
3225
|
request.authenticatedPrincipal
|
|
@@ -4676,7 +3313,7 @@ var EngramAccessService = class {
|
|
|
4676
3313
|
};
|
|
4677
3314
|
}
|
|
4678
3315
|
if (!codingOverlayApplied) {
|
|
4679
|
-
const writeNamespace2 = this.
|
|
3316
|
+
const writeNamespace2 = this.writableNamespaceFor(
|
|
4680
3317
|
void 0,
|
|
4681
3318
|
request.sessionKey,
|
|
4682
3319
|
request.authenticatedPrincipal
|
|
@@ -6687,14 +5324,14 @@ var EngramAccessService = class {
|
|
|
6687
5324
|
if (this._correctionService) return this._correctionService;
|
|
6688
5325
|
const service = createCorrectionService({
|
|
6689
5326
|
orchestrator: this.orchestrator,
|
|
6690
|
-
resolveAuthorizedNamespace: async (req) => this.
|
|
5327
|
+
resolveAuthorizedNamespace: async (req) => this.writableNamespaceFor(req.namespace, req.sessionKey, req.principal),
|
|
6691
5328
|
resolveReadableNamespaces: (req) => {
|
|
6692
5329
|
const principal = this.resolveRequestPrincipal(req.sessionKey, req.principal);
|
|
6693
5330
|
return recallNamespacesForPrincipal(principal, this.orchestrator.config);
|
|
6694
5331
|
},
|
|
6695
5332
|
canWriteNamespace: (req) => {
|
|
6696
5333
|
try {
|
|
6697
|
-
this.
|
|
5334
|
+
this.writableNamespaceFor(req.namespace, req.sessionKey, req.principal);
|
|
6698
5335
|
return Promise.resolve(true);
|
|
6699
5336
|
} catch {
|
|
6700
5337
|
return Promise.resolve(false);
|
|
@@ -7016,7 +5653,7 @@ var EngramAccessService = class {
|
|
|
7016
5653
|
if (deepSleep.enabled === false && deepSleep.enabledExplicitlySet === true) {
|
|
7017
5654
|
throw new Error("memory governance is disabled by dreams.phases.deepSleep.enabled=false");
|
|
7018
5655
|
}
|
|
7019
|
-
const resolvedNamespace = this.
|
|
5656
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7020
5657
|
request.namespace,
|
|
7021
5658
|
void 0,
|
|
7022
5659
|
request.authenticatedPrincipal ?? principal
|
|
@@ -7054,7 +5691,7 @@ var EngramAccessService = class {
|
|
|
7054
5691
|
};
|
|
7055
5692
|
}
|
|
7056
5693
|
async procedureMiningRun(request, principal) {
|
|
7057
|
-
const resolvedNamespace = this.
|
|
5694
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7058
5695
|
request.namespace,
|
|
7059
5696
|
void 0,
|
|
7060
5697
|
request.authenticatedPrincipal ?? principal
|
|
@@ -7073,7 +5710,7 @@ var EngramAccessService = class {
|
|
|
7073
5710
|
};
|
|
7074
5711
|
}
|
|
7075
5712
|
async liveConnectorsRun(request = {}, principal) {
|
|
7076
|
-
this.
|
|
5713
|
+
this.writableNamespaceFor(
|
|
7077
5714
|
void 0,
|
|
7078
5715
|
void 0,
|
|
7079
5716
|
request.authenticatedPrincipal ?? principal
|
|
@@ -7103,7 +5740,7 @@ var EngramAccessService = class {
|
|
|
7103
5740
|
* other maintenance MCP tools.
|
|
7104
5741
|
*/
|
|
7105
5742
|
async patternReinforcementRun(request = {}, principal) {
|
|
7106
|
-
const resolvedNamespace = this.
|
|
5743
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7107
5744
|
request.namespace,
|
|
7108
5745
|
void 0,
|
|
7109
5746
|
request.authenticatedPrincipal ?? principal
|
|
@@ -7337,7 +5974,7 @@ var EngramAccessService = class {
|
|
|
7337
5974
|
if (!isTrustZoneName(request.targetZone)) {
|
|
7338
5975
|
throw new EngramAccessInputError(`unsupported trust-zone target: ${String(request.targetZone)}`);
|
|
7339
5976
|
}
|
|
7340
|
-
const resolvedNamespace = this.
|
|
5977
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7341
5978
|
request.namespace,
|
|
7342
5979
|
void 0,
|
|
7343
5980
|
request.authenticatedPrincipal
|
|
@@ -7368,7 +6005,7 @@ var EngramAccessService = class {
|
|
|
7368
6005
|
};
|
|
7369
6006
|
}
|
|
7370
6007
|
async trustZoneDemoSeed(request) {
|
|
7371
|
-
const resolvedNamespace = this.
|
|
6008
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7372
6009
|
request.namespace,
|
|
7373
6010
|
void 0,
|
|
7374
6011
|
request.authenticatedPrincipal
|
|
@@ -7401,7 +6038,7 @@ var EngramAccessService = class {
|
|
|
7401
6038
|
if (reasonCode.length === 0) {
|
|
7402
6039
|
throw new EngramAccessInputError("reasonCode is required");
|
|
7403
6040
|
}
|
|
7404
|
-
const resolvedNamespace = this.
|
|
6041
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
7405
6042
|
request.namespace,
|
|
7406
6043
|
void 0,
|
|
7407
6044
|
request.authenticatedPrincipal
|
|
@@ -8148,7 +6785,7 @@ var EngramAccessService = class {
|
|
|
8148
6785
|
}
|
|
8149
6786
|
const symptom = request.symptom?.trim();
|
|
8150
6787
|
if (!symptom) throw new EngramAccessInputError("symptom is required");
|
|
8151
|
-
const resolvedNs = this.
|
|
6788
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, void 0, request.principal);
|
|
8152
6789
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8153
6790
|
const created = await storage.appendContinuityIncident({
|
|
8154
6791
|
symptom,
|
|
@@ -8170,7 +6807,7 @@ var EngramAccessService = class {
|
|
|
8170
6807
|
if (!fixApplied) throw new EngramAccessInputError("fixApplied is required");
|
|
8171
6808
|
const verificationResult = request.verificationResult?.trim();
|
|
8172
6809
|
if (!verificationResult) throw new EngramAccessInputError("verificationResult is required");
|
|
8173
|
-
const resolvedNs = this.
|
|
6810
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, void 0, request.principal);
|
|
8174
6811
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8175
6812
|
const closed = await storage.closeContinuityIncident(id, {
|
|
8176
6813
|
fixApplied,
|
|
@@ -8195,7 +6832,7 @@ var EngramAccessService = class {
|
|
|
8195
6832
|
if (!this.orchestrator.config.identityContinuityEnabled) {
|
|
8196
6833
|
return { enabled: false, reason: "Identity continuity is disabled." };
|
|
8197
6834
|
}
|
|
8198
|
-
const resolvedNs = this.
|
|
6835
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, void 0, request.principal);
|
|
8199
6836
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8200
6837
|
const loop = await storage.upsertIdentityImprovementLoop({
|
|
8201
6838
|
id: request.id?.trim() || "",
|
|
@@ -8214,7 +6851,7 @@ var EngramAccessService = class {
|
|
|
8214
6851
|
}
|
|
8215
6852
|
const id = request.id?.trim();
|
|
8216
6853
|
if (!id) throw new EngramAccessInputError("id is required");
|
|
8217
|
-
const resolvedNs = this.
|
|
6854
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, void 0, request.principal);
|
|
8218
6855
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8219
6856
|
const reviewed = await storage.reviewIdentityImprovementLoop(id, {
|
|
8220
6857
|
status: request.status,
|
|
@@ -8254,7 +6891,7 @@ var EngramAccessService = class {
|
|
|
8254
6891
|
};
|
|
8255
6892
|
const hasUpdate = Object.values(updates).some((v) => typeof v === "string" && v.length > 0);
|
|
8256
6893
|
if (!hasUpdate) throw new EngramAccessInputError("At least one section field is required.");
|
|
8257
|
-
const resolvedNs = this.
|
|
6894
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, void 0, request.principal);
|
|
8258
6895
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8259
6896
|
const existing = await storage.readIdentityAnchor();
|
|
8260
6897
|
const merged = this.mergeIdentityAnchorSections(existing, updates);
|
|
@@ -8757,7 +7394,7 @@ ${next}`);
|
|
|
8757
7394
|
"memoryId must not contain path separators"
|
|
8758
7395
|
);
|
|
8759
7396
|
}
|
|
8760
|
-
const resolvedNs = this.
|
|
7397
|
+
const resolvedNs = this.writableNamespaceFor(
|
|
8761
7398
|
request.namespace,
|
|
8762
7399
|
request.sessionKey,
|
|
8763
7400
|
request.principal
|
|
@@ -8770,7 +7407,7 @@ ${next}`);
|
|
|
8770
7407
|
});
|
|
8771
7408
|
}
|
|
8772
7409
|
async memoryPromote(request) {
|
|
8773
|
-
const resolvedNs = this.
|
|
7410
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, request.sessionKey, request.principal);
|
|
8774
7411
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8775
7412
|
await storage.updateMemoryFrontmatter(request.memoryId, {
|
|
8776
7413
|
lifecycleState: "active",
|
|
@@ -8804,7 +7441,7 @@ ${next}`);
|
|
|
8804
7441
|
`memory_action_apply: outcome must be "applied", "skipped", or "failed"; got ${JSON.stringify(outcome)}`
|
|
8805
7442
|
);
|
|
8806
7443
|
}
|
|
8807
|
-
const resolvedNs = this.
|
|
7444
|
+
const resolvedNs = this.writableNamespaceFor(
|
|
8808
7445
|
request.namespace,
|
|
8809
7446
|
request.sessionKey,
|
|
8810
7447
|
request.principal
|
|
@@ -8839,10 +7476,10 @@ ${next}`);
|
|
|
8839
7476
|
return { recorded, event: preview };
|
|
8840
7477
|
}
|
|
8841
7478
|
async contextCheckpoint(request) {
|
|
8842
|
-
const resolvedNs = this.
|
|
7479
|
+
const resolvedNs = this.writableNamespaceFor(request.namespace, request.sessionKey, request.principal);
|
|
8843
7480
|
const storage = await this.orchestrator.getStorage(resolvedNs);
|
|
8844
7481
|
const storageDir = storage.dir;
|
|
8845
|
-
const { writeFile:
|
|
7482
|
+
const { writeFile: writeFile2, mkdir: mkdir3 } = await import("fs/promises");
|
|
8846
7483
|
const { join: join2, resolve: resolve2 } = await import("path");
|
|
8847
7484
|
const safeKey = request.sessionKey.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8848
7485
|
if (!safeKey) throw new EngramAccessInputError("sessionKey is required");
|
|
@@ -8851,10 +7488,10 @@ ${next}`);
|
|
|
8851
7488
|
if (!resolved.startsWith(resolve2(storageDir))) {
|
|
8852
7489
|
throw new EngramAccessInputError("Invalid sessionKey");
|
|
8853
7490
|
}
|
|
8854
|
-
await
|
|
7491
|
+
await mkdir3(checkpointDir, { recursive: true });
|
|
8855
7492
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8856
7493
|
const filePath = join2(checkpointDir, `checkpoint-${ts}.md`);
|
|
8857
|
-
await
|
|
7494
|
+
await writeFile2(filePath, request.context, "utf-8");
|
|
8858
7495
|
return { saved: true };
|
|
8859
7496
|
}
|
|
8860
7497
|
async lcmStatus() {
|
|
@@ -8881,7 +7518,7 @@ ${next}`);
|
|
|
8881
7518
|
*/
|
|
8882
7519
|
async recordCitationUsage(request) {
|
|
8883
7520
|
if (request.entries.length === 0) return { submitted: 0, matched: 0 };
|
|
8884
|
-
const resolvedNamespace = this.
|
|
7521
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
8885
7522
|
request.namespace,
|
|
8886
7523
|
request.sessionId,
|
|
8887
7524
|
request.authenticatedPrincipal
|
|
@@ -9108,7 +7745,7 @@ ${next}`);
|
|
|
9108
7745
|
"authentication required: namespaces are enabled and no principal was supplied"
|
|
9109
7746
|
);
|
|
9110
7747
|
}
|
|
9111
|
-
const resolved = this.
|
|
7748
|
+
const resolved = this.writableNamespaceFor(namespace, void 0, principal);
|
|
9112
7749
|
const storage = await this.orchestrator.getStorage(resolved);
|
|
9113
7750
|
return { namespace: resolved, storage };
|
|
9114
7751
|
}
|
|
@@ -9151,7 +7788,7 @@ ${next}`);
|
|
|
9151
7788
|
*/
|
|
9152
7789
|
async capsuleImport(opts) {
|
|
9153
7790
|
const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...importOptions } = opts;
|
|
9154
|
-
const resolvedNamespace = this.
|
|
7791
|
+
const resolvedNamespace = this.writableNamespaceFor(namespace, void 0, principal);
|
|
9155
7792
|
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
9156
7793
|
const root = explicitRoot ?? storage.dir;
|
|
9157
7794
|
const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
|
|
@@ -9211,7 +7848,7 @@ ${next}`);
|
|
|
9211
7848
|
*/
|
|
9212
7849
|
async capsuleExport(opts) {
|
|
9213
7850
|
const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...exportOptions } = opts;
|
|
9214
|
-
const resolvedNamespace = this.
|
|
7851
|
+
const resolvedNamespace = this.writableNamespaceFor(namespace, void 0, principal);
|
|
9215
7852
|
const storage = await this.orchestrator.getStorage(resolvedNamespace);
|
|
9216
7853
|
const root = explicitRoot ?? storage.dir;
|
|
9217
7854
|
const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
|
|
@@ -9394,7 +8031,7 @@ ${next}`);
|
|
|
9394
8031
|
}
|
|
9395
8032
|
}
|
|
9396
8033
|
async offlineSyncApplyFileContent(options) {
|
|
9397
|
-
const resolvedNamespace = this.
|
|
8034
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
9398
8035
|
options.namespace,
|
|
9399
8036
|
void 0,
|
|
9400
8037
|
options.principal
|
|
@@ -9431,7 +8068,7 @@ ${next}`);
|
|
|
9431
8068
|
}
|
|
9432
8069
|
}
|
|
9433
8070
|
async offlineSyncApply(options) {
|
|
9434
|
-
const resolvedNamespace = this.
|
|
8071
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
9435
8072
|
options.namespace,
|
|
9436
8073
|
void 0,
|
|
9437
8074
|
options.principal
|
|
@@ -9497,7 +8134,7 @@ ${next}`);
|
|
|
9497
8134
|
);
|
|
9498
8135
|
}
|
|
9499
8136
|
const dryRun = options.dryRun === true;
|
|
9500
|
-
const resolvedNamespace = this.
|
|
8137
|
+
const resolvedNamespace = this.writableNamespaceFor(
|
|
9501
8138
|
options.namespace,
|
|
9502
8139
|
void 0,
|
|
9503
8140
|
options.authenticatedPrincipal
|
|
@@ -9743,7 +8380,6 @@ export {
|
|
|
9743
8380
|
DECISION_SUBCOMMANDS,
|
|
9744
8381
|
isCodegraphToolName,
|
|
9745
8382
|
DELTA_SUBCOMMANDS,
|
|
9746
|
-
CorrectionContractError,
|
|
9747
8383
|
computeProcedureStats,
|
|
9748
8384
|
formatProcedureStatsText,
|
|
9749
8385
|
EngramAccessInputError,
|
|
@@ -9751,4 +8387,4 @@ export {
|
|
|
9751
8387
|
shapeMemorySummary,
|
|
9752
8388
|
EngramAccessService
|
|
9753
8389
|
};
|
|
9754
|
-
//# sourceMappingURL=chunk-
|
|
8390
|
+
//# sourceMappingURL=chunk-F3PVXKHP.js.map
|