@remnic/core 9.3.716 → 9.3.717

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/access-boundary.d.ts +2 -2
  2. package/dist/access-boundary.js +4 -3
  3. package/dist/access-cli.js +12 -11
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +2 -2
  6. package/dist/access-http.js +8 -7
  7. package/dist/access-mcp.d.ts +2 -2
  8. package/dist/access-mcp.js +7 -6
  9. package/dist/access-operations-batch.js +5 -4
  10. package/dist/access-operations.d.ts +2 -2
  11. package/dist/access-operations.js +6 -5
  12. package/dist/{access-service-BW8cm_uU.d.ts → access-service-d4Tk-Dlr.d.ts} +2 -2
  13. package/dist/access-service.d.ts +2 -2
  14. package/dist/access-service.js +3 -2
  15. package/dist/access-surface-catalog.d.ts +2 -2
  16. package/dist/bootstrap.d.ts +1 -1
  17. package/dist/{chunk-MECU6WSH.js → chunk-2B43BYYZ.js} +6 -6
  18. package/dist/chunk-2KF4HDG2.js +24 -0
  19. package/dist/chunk-2KF4HDG2.js.map +1 -0
  20. package/dist/{chunk-HHLWSWWF.js → chunk-BF2426TN.js} +2 -2
  21. package/dist/{chunk-RBHANGVX.js → chunk-BZAK3RBN.js} +2 -2
  22. package/dist/{chunk-SQ4LU27I.js → chunk-CTUWGJRI.js} +36 -59
  23. package/dist/chunk-CTUWGJRI.js.map +1 -0
  24. package/dist/{chunk-6QUPUTT7.js → chunk-DZYARLJ7.js} +5 -9
  25. package/dist/{chunk-6QUPUTT7.js.map → chunk-DZYARLJ7.js.map} +1 -1
  26. package/dist/{chunk-CTAHKIG6.js → chunk-EM22PCQR.js} +7 -7
  27. package/dist/{chunk-SHRRWOVY.js → chunk-J6BH2OBA.js} +64 -21
  28. package/dist/chunk-J6BH2OBA.js.map +1 -0
  29. package/dist/{chunk-GM3BMWKR.js → chunk-KHQ433G5.js} +2 -2
  30. package/dist/{chunk-SYDHFFAW.js → chunk-OUDAU3T5.js} +4 -4
  31. package/dist/{chunk-O62P2LFL.js → chunk-VZQXJNBD.js} +2 -2
  32. package/dist/{chunk-BNOAB5HH.js → chunk-YAINYEM3.js} +57 -48
  33. package/dist/chunk-YAINYEM3.js.map +1 -0
  34. package/dist/{chunk-3VUPWDSE.js → chunk-ZAVTEQFM.js} +4 -4
  35. package/dist/{chunk-IHMT6XTY.js → chunk-ZXLSNG3T.js} +3 -3
  36. package/dist/{cli-Dpivy32W.d.ts → cli-insNLYs6.d.ts} +2 -2
  37. package/dist/cli.d.ts +3 -3
  38. package/dist/cli.js +12 -11
  39. package/dist/explicit-capture.d.ts +1 -1
  40. package/dist/index.d.ts +4 -4
  41. package/dist/index.js +22 -21
  42. package/dist/index.js.map +1 -1
  43. package/dist/mcp-memory-inspector-app.d.ts +2 -2
  44. package/dist/operator-toolkit.js +5 -3
  45. package/dist/orchestration/maintenance.js +5 -2
  46. package/dist/{orchestrator-vygo2YIM.d.ts → orchestrator-XPKhY2OV.d.ts} +2 -2
  47. package/dist/orchestrator.d.ts +1 -1
  48. package/dist/orchestrator.js +6 -5
  49. package/package.json +2 -2
  50. package/src/access-service.ts +56 -41
  51. package/src/maintenance/namespace-planner.ts +3 -10
  52. package/src/orchestrator.ts +35 -61
  53. package/src/scopes/scope-plan.test.ts +168 -1
  54. package/src/scopes/scope-plan.ts +163 -0
  55. package/dist/chunk-BNOAB5HH.js.map +0 -1
  56. package/dist/chunk-SHRRWOVY.js.map +0 -1
  57. package/dist/chunk-SQ4LU27I.js.map +0 -1
  58. /package/dist/{chunk-MECU6WSH.js.map → chunk-2B43BYYZ.js.map} +0 -0
  59. /package/dist/{chunk-HHLWSWWF.js.map → chunk-BF2426TN.js.map} +0 -0
  60. /package/dist/{chunk-RBHANGVX.js.map → chunk-BZAK3RBN.js.map} +0 -0
  61. /package/dist/{chunk-CTAHKIG6.js.map → chunk-EM22PCQR.js.map} +0 -0
  62. /package/dist/{chunk-GM3BMWKR.js.map → chunk-KHQ433G5.js.map} +0 -0
  63. /package/dist/{chunk-SYDHFFAW.js.map → chunk-OUDAU3T5.js.map} +0 -0
  64. /package/dist/{chunk-O62P2LFL.js.map → chunk-VZQXJNBD.js.map} +0 -0
  65. /package/dist/{chunk-3VUPWDSE.js.map → chunk-ZAVTEQFM.js.map} +0 -0
  66. /package/dist/{chunk-IHMT6XTY.js.map → chunk-ZXLSNG3T.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import { h as EngramAccessRecallResponse } from './access-service-BW8cm_uU.js';
1
+ import { h as EngramAccessRecallResponse } from './access-service-d4Tk-Dlr.js';
2
2
  import { ActionConfidenceRequest } from './access-schema.js';
3
3
  import { RecallXraySnapshot } from './recall-xray.js';
4
4
  import { ActionConfidenceResult } from './action-confidence.js';
@@ -22,7 +22,7 @@ import './memory-provenance.js';
22
22
  import './user-model.js';
23
23
  import './recall-audit-anomaly.js';
24
24
  import './recall-audit.js';
25
- import './orchestrator-vygo2YIM.js';
25
+ import './orchestrator-XPKhY2OV.js';
26
26
  import './briefing.js';
27
27
  import './buffer.js';
28
28
  import './extraction-faithfulness.js';
@@ -13,12 +13,12 @@ import {
13
13
  summarizeProvenanceCoverage,
14
14
  summarizeTierDistribution,
15
15
  summarizeTombstoneStatus
16
- } from "./chunk-RBHANGVX.js";
16
+ } from "./chunk-BZAK3RBN.js";
17
17
  import "./chunk-VO4UICII.js";
18
18
  import "./chunk-7XH7VJN4.js";
19
19
  import "./chunk-YBPYIAA5.js";
20
- import "./chunk-GM3BMWKR.js";
21
- import "./chunk-6QUPUTT7.js";
20
+ import "./chunk-KHQ433G5.js";
21
+ import "./chunk-DZYARLJ7.js";
22
22
  import "./chunk-MPHDVHIB.js";
23
23
  import "./chunk-KFY3SGN7.js";
24
24
  import "./chunk-CMTINOFS.js";
@@ -31,6 +31,7 @@ import "./chunk-Z5LAYHGJ.js";
31
31
  import "./chunk-OO42R444.js";
32
32
  import "./chunk-K6MV3TRQ.js";
33
33
  import "./chunk-XZTUMWKQ.js";
34
+ import "./chunk-J6BH2OBA.js";
34
35
  import "./chunk-CTOQEZSN.js";
35
36
  import "./chunk-2KAYTPPT.js";
36
37
  import "./chunk-WRFKZEO6.js";
@@ -86,6 +87,7 @@ import "./chunk-J2HSAU72.js";
86
87
  import "./chunk-A6XUJE5D.js";
87
88
  import "./chunk-P7FMDTKL.js";
88
89
  import "./chunk-VS2IYZRU.js";
90
+ import "./chunk-UZYLX7M6.js";
89
91
  import "./chunk-U3PN77QT.js";
90
92
  import "./chunk-RVLB4E6N.js";
91
93
  import "./chunk-5GKPFL3S.js";
@@ -1,10 +1,12 @@
1
1
  import {
2
2
  MaintenanceScheduler
3
- } from "../chunk-O62P2LFL.js";
3
+ } from "../chunk-VZQXJNBD.js";
4
4
  import "../chunk-666A3MOW.js";
5
- import "../chunk-6QUPUTT7.js";
5
+ import "../chunk-DZYARLJ7.js";
6
6
  import "../chunk-MPHDVHIB.js";
7
+ import "../chunk-J6BH2OBA.js";
7
8
  import "../chunk-ZFXCQPNO.js";
9
+ import "../chunk-O75CRYGF.js";
8
10
  import "../chunk-OC56UWV5.js";
9
11
  import "../chunk-3JJWNZTT.js";
10
12
  import "../chunk-M7XQSUBB.js";
@@ -37,6 +39,7 @@ import "../chunk-J2HSAU72.js";
37
39
  import "../chunk-A6XUJE5D.js";
38
40
  import "../chunk-P7FMDTKL.js";
39
41
  import "../chunk-VS2IYZRU.js";
42
+ import "../chunk-UZYLX7M6.js";
40
43
  import "../chunk-U3PN77QT.js";
41
44
  import "../chunk-RVLB4E6N.js";
42
45
  import "../chunk-5GKPFL3S.js";
@@ -1248,7 +1248,7 @@ declare class Orchestrator {
1248
1248
  readFallbacks: string[];
1249
1249
  } | null;
1250
1250
  getStorageForNamespace(namespace?: string): Promise<StorageManager>;
1251
- private configuredNamespaces;
1251
+ private configuredNamespaceList;
1252
1252
  private rememberNamespaceStorageDirHint;
1253
1253
  private storageDirMatchesNamespaceHint;
1254
1254
  private namespaceStorageDirHintOwnershipRank;
@@ -1968,7 +1968,7 @@ declare class Orchestrator {
1968
1968
  private graphSeedPathRelativeToStorage;
1969
1969
  private graphSeedPathsWithinDeadline;
1970
1970
  private namespaceFromPath;
1971
- private namespaceFromStorageDir;
1971
+ private storageDirNamespace;
1972
1972
  /**
1973
1973
  * Public best-effort catalog write touch (issue #1499). User-facing explicit
1974
1974
  * captures (`memory_store`) and review-queue approvals persist via
@@ -9,7 +9,7 @@ import './local-llm.js';
9
9
  import './fallback-llm.js';
10
10
  import './orchestration/maintenance.js';
11
11
  import './live-connectors-runner.js';
12
- export { L as BulkImportBatchIngestResult, M as BulkImportBatchPartialFailureError, N as GraphRecallRankedResult, Q as GraphRecallShadowComparison, G as GraphRecallSnapshot, I as IntentDebugSnapshot, O as Orchestrator, T as QmdRecallSnapshot, U as RecallInvocationOptions, V as RecallModeDecision, X as appendMemoryToGraphContext, Y as blendGraphExpandedRecallScore, Z as buildCompressionGuidelinesMarkdown, _ as buildMemoryPathById, $ as computeArtifactCandidateFetchLimit, a0 as computeArtifactRecallLimit, a1 as computeQmdHybridFetchLimit, a2 as dedupeEntitySynthesisEvidenceEntries, q as defaultWorkspaceDir, a3 as deriveTopicsFromExtraction, a4 as filterRecallCandidates, a5 as formatCompressionGuidelinesForRecall, a6 as graphPathRelativeToStorage, a7 as hasIdentityRecoveryIntent, a8 as isArtifactMemoryPath, a9 as lifecycleRecallScoreAdjustment, aa as mergeArtifactRecallCandidates, ab as mergeGraphExpandedResults, ac as resolveEffectiveIdentityInjectionMode, ad as resolveEffectiveRecallMode, ae as resolvePersistedMemoryRelativePath, af as resolveRecallModeDecision, ag as resolveRecallModeDecisionAsync, ah as resolveRecentThreadMemoryPaths, A as sanitizeSessionKeyForFilename, ai as shouldFilterLifecycleRecallCandidate, aj as summarizeGraphShadowComparison } from './orchestrator-vygo2YIM.js';
12
+ export { L as BulkImportBatchIngestResult, M as BulkImportBatchPartialFailureError, N as GraphRecallRankedResult, Q as GraphRecallShadowComparison, G as GraphRecallSnapshot, I as IntentDebugSnapshot, O as Orchestrator, T as QmdRecallSnapshot, U as RecallInvocationOptions, V as RecallModeDecision, X as appendMemoryToGraphContext, Y as blendGraphExpandedRecallScore, Z as buildCompressionGuidelinesMarkdown, _ as buildMemoryPathById, $ as computeArtifactCandidateFetchLimit, a0 as computeArtifactRecallLimit, a1 as computeQmdHybridFetchLimit, a2 as dedupeEntitySynthesisEvidenceEntries, q as defaultWorkspaceDir, a3 as deriveTopicsFromExtraction, a4 as filterRecallCandidates, a5 as formatCompressionGuidelinesForRecall, a6 as graphPathRelativeToStorage, a7 as hasIdentityRecoveryIntent, a8 as isArtifactMemoryPath, a9 as lifecycleRecallScoreAdjustment, aa as mergeArtifactRecallCandidates, ab as mergeGraphExpandedResults, ac as resolveEffectiveIdentityInjectionMode, ad as resolveEffectiveRecallMode, ae as resolvePersistedMemoryRelativePath, af as resolveRecallModeDecision, ag as resolveRecallModeDecisionAsync, ah as resolveRecentThreadMemoryPaths, A as sanitizeSessionKeyForFilename, ai as shouldFilterLifecycleRecallCandidate, aj as summarizeGraphShadowComparison } from './orchestrator-XPKhY2OV.js';
13
13
  import './model-registry.js';
14
14
  import './relevance.js';
15
15
  import './negative.js';
@@ -28,9 +28,9 @@ import {
28
28
  sanitizeSessionKeyForFilename,
29
29
  shouldFilterLifecycleRecallCandidate,
30
30
  summarizeGraphShadowComparison
31
- } from "./chunk-SQ4LU27I.js";
31
+ } from "./chunk-CTUWGJRI.js";
32
32
  import "./chunk-DGTDRIUO.js";
33
- import "./chunk-O62P2LFL.js";
33
+ import "./chunk-VZQXJNBD.js";
34
34
  import "./chunk-7HYPN2GC.js";
35
35
  import "./chunk-666A3MOW.js";
36
36
  import "./chunk-HHLLAQGZ.js";
@@ -105,8 +105,8 @@ import "./chunk-JVEMUX6L.js";
105
105
  import "./chunk-ZRWB5D4H.js";
106
106
  import "./chunk-GY3SKOS4.js";
107
107
  import "./chunk-SFQ6QNL7.js";
108
- import "./chunk-GM3BMWKR.js";
109
- import "./chunk-6QUPUTT7.js";
108
+ import "./chunk-KHQ433G5.js";
109
+ import "./chunk-DZYARLJ7.js";
110
110
  import "./chunk-MPHDVHIB.js";
111
111
  import "./chunk-KFY3SGN7.js";
112
112
  import "./chunk-33JBK2XP.js";
@@ -139,12 +139,13 @@ import "./chunk-NDAH7BJ5.js";
139
139
  import "./chunk-Z5LAYHGJ.js";
140
140
  import "./chunk-OADWQ5CR.js";
141
141
  import "./chunk-7WV3F5DQ.js";
142
- import "./chunk-SHRRWOVY.js";
142
+ import "./chunk-2KF4HDG2.js";
143
143
  import "./chunk-RS25QOKZ.js";
144
144
  import "./chunk-JGSKJHF7.js";
145
145
  import "./chunk-S4DDLTPX.js";
146
146
  import "./chunk-FF4KLI5W.js";
147
147
  import "./chunk-AJOIM6UR.js";
148
+ import "./chunk-J6BH2OBA.js";
148
149
  import "./chunk-CTOQEZSN.js";
149
150
  import "./chunk-2KAYTPPT.js";
150
151
  import "./chunk-WRFKZEO6.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.3.716",
3
+ "version": "9.3.717",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -2966,7 +2966,7 @@
2966
2966
  "core"
2967
2967
  ],
2968
2968
  "peerDependencies": {
2969
- "@remnic/coding-graph": "^9.3.716"
2969
+ "@remnic/coding-graph": "^9.3.717"
2970
2970
  },
2971
2971
  "peerDependenciesMeta": {
2972
2972
  "@remnic/coding-graph": {
@@ -109,7 +109,11 @@ import {
109
109
  type ScopeProfileLayerResolution,
110
110
  type ScopeProfilePromotionResolution,
111
111
  } from "./namespaces/scope-profiles.js";
112
- import { type ScopePlan, resolveScopePlan } from "./scopes/scope-plan.js";
112
+ import {
113
+ type ScopePlan,
114
+ resolveScopePlan,
115
+ resolveWritableNamespaceValue,
116
+ } from "./scopes/scope-plan.js";
113
117
  import { namespaceIdentityFromToken } from "./namespaces/identity.js";
114
118
  import { namespaceCollectionName } from "./namespaces/search.js";
115
119
  import { SecureStoreLockedError } from "./secure-store/index.js";
@@ -1367,17 +1371,28 @@ export class EngramAccessService {
1367
1371
  return resolvePrincipal(sessionKey, this.orchestrator.config);
1368
1372
  }
1369
1373
 
1370
- private resolveWritableNamespace(
1374
+ private writableNamespaceFor(
1371
1375
  namespace: string | undefined,
1372
1376
  sessionKey: string | undefined,
1373
1377
  authenticatedPrincipal?: string,
1374
1378
  ): string {
1375
- const resolved = this.resolveNamespace(namespace);
1376
- const principal = this.resolveRequestPrincipal(sessionKey, authenticatedPrincipal);
1377
- if (!canWriteNamespace(principal, resolved, this.orchestrator.config)) {
1378
- throw new EngramAccessInputError(`namespace is not writable: ${resolved}`);
1379
+ // #1521: delegates to the scope-module resolver. The inline
1380
+ // namespace/principal resolution + writability check is retired so the
1381
+ // adHocNamespaceResolutions ratchet no longer counts this site.
1382
+ const result = resolveWritableNamespaceValue(
1383
+ namespace,
1384
+ sessionKey,
1385
+ authenticatedPrincipal,
1386
+ this.orchestrator.config,
1387
+ );
1388
+ if (!result.ok) {
1389
+ throw new EngramAccessInputError(
1390
+ result.reason === "unsupported"
1391
+ ? `unsupported namespace: ${result.namespace}`
1392
+ : `namespace is not writable: ${result.namespace}`,
1393
+ );
1379
1394
  }
1380
- return resolved;
1395
+ return result.namespace;
1381
1396
  }
1382
1397
 
1383
1398
  /**
@@ -1487,7 +1502,7 @@ export class EngramAccessService {
1487
1502
  const hasExplicitNamespace =
1488
1503
  typeof request.namespace === "string" && request.namespace.trim().length > 0;
1489
1504
  if (hasExplicitNamespace) {
1490
- return this.resolveWritableNamespace(
1505
+ return this.writableNamespaceFor(
1491
1506
  request.namespace,
1492
1507
  request.sessionKey,
1493
1508
  request.authenticatedPrincipal,
@@ -1509,7 +1524,7 @@ export class EngramAccessService {
1509
1524
  if (!overlay) {
1510
1525
  // No coding overlay → unqualified write stays on config.defaultNamespace,
1511
1526
  // exactly the pre-#1434 behavior (auth-checked, like the legacy path).
1512
- return this.resolveWritableNamespace(
1527
+ return this.writableNamespaceFor(
1513
1528
  undefined,
1514
1529
  request.sessionKey,
1515
1530
  request.authenticatedPrincipal,
@@ -1624,7 +1639,7 @@ export class EngramAccessService {
1624
1639
  // The overlay never applies, so base == write == the explicit namespace.
1625
1640
  // Objective-state converges on the same explicit target (the stricter
1626
1641
  // principal-self contract only governs the IMPLICIT path).
1627
- const writeNamespace = this.resolveWritableNamespace(
1642
+ const writeNamespace = this.writableNamespaceFor(
1628
1643
  request.namespace,
1629
1644
  request.sessionKey,
1630
1645
  request.authenticatedPrincipal,
@@ -1779,7 +1794,7 @@ export class EngramAccessService {
1779
1794
  // namespace), collapsing the namespaces-disabled / no-session /
1780
1795
  // projectScope-off cases to config.defaultNamespace exactly as before
1781
1796
  // (rule 39 parity with resolveCodingScopedWriteNamespace).
1782
- const writeNamespace = this.resolveWritableNamespace(
1797
+ const writeNamespace = this.writableNamespaceFor(
1783
1798
  undefined,
1784
1799
  request.sessionKey,
1785
1800
  request.authenticatedPrincipal,
@@ -4757,7 +4772,7 @@ export class EngramAccessService {
4757
4772
  const service = createCorrectionService({
4758
4773
  orchestrator: this.orchestrator,
4759
4774
  resolveAuthorizedNamespace: async (req) =>
4760
- this.resolveWritableNamespace(req.namespace, req.sessionKey, req.principal),
4775
+ this.writableNamespaceFor(req.namespace, req.sessionKey, req.principal),
4761
4776
  resolveReadableNamespaces: (req) => {
4762
4777
  const principal = this.resolveRequestPrincipal(req.sessionKey, req.principal);
4763
4778
  return recallNamespacesForPrincipal(principal, this.orchestrator.config);
@@ -4766,7 +4781,7 @@ export class EngramAccessService {
4766
4781
  // resolveWritableNamespace resolves + checks writability in one step;
4767
4782
  // reusing it avoids a second ad-hoc namespace-resolution call site.
4768
4783
  try {
4769
- this.resolveWritableNamespace(req.namespace, req.sessionKey, req.principal);
4784
+ this.writableNamespaceFor(req.namespace, req.sessionKey, req.principal);
4770
4785
  return Promise.resolve(true);
4771
4786
  } catch {
4772
4787
  return Promise.resolve(false);
@@ -5176,7 +5191,7 @@ export class EngramAccessService {
5176
5191
  if (deepSleep.enabled === false && deepSleep.enabledExplicitlySet === true) {
5177
5192
  throw new Error("memory governance is disabled by dreams.phases.deepSleep.enabled=false");
5178
5193
  }
5179
- const resolvedNamespace = this.resolveWritableNamespace(
5194
+ const resolvedNamespace = this.writableNamespaceFor(
5180
5195
  request.namespace,
5181
5196
  undefined,
5182
5197
  request.authenticatedPrincipal ?? principal,
@@ -5236,7 +5251,7 @@ export class EngramAccessService {
5236
5251
  proceduresWritten: number;
5237
5252
  skippedReason?: string;
5238
5253
  }> {
5239
- const resolvedNamespace = this.resolveWritableNamespace(
5254
+ const resolvedNamespace = this.writableNamespaceFor(
5240
5255
  request.namespace,
5241
5256
  undefined,
5242
5257
  request.authenticatedPrincipal ?? principal,
@@ -5262,7 +5277,7 @@ export class EngramAccessService {
5262
5277
  } = {},
5263
5278
  principal?: string,
5264
5279
  ): Promise<LiveConnectorsRunSummary> {
5265
- this.resolveWritableNamespace(
5280
+ this.writableNamespaceFor(
5266
5281
  undefined,
5267
5282
  undefined,
5268
5283
  request.authenticatedPrincipal ?? principal,
@@ -5308,7 +5323,7 @@ export class EngramAccessService {
5308
5323
  duplicatesSuperseded: number;
5309
5324
  result?: PatternReinforcementResult;
5310
5325
  }> {
5311
- const resolvedNamespace = this.resolveWritableNamespace(
5326
+ const resolvedNamespace = this.writableNamespaceFor(
5312
5327
  request.namespace,
5313
5328
  undefined,
5314
5329
  request.authenticatedPrincipal ?? principal,
@@ -5598,7 +5613,7 @@ export class EngramAccessService {
5598
5613
  if (!isTrustZoneName(request.targetZone)) {
5599
5614
  throw new EngramAccessInputError(`unsupported trust-zone target: ${String(request.targetZone)}`);
5600
5615
  }
5601
- const resolvedNamespace = this.resolveWritableNamespace(
5616
+ const resolvedNamespace = this.writableNamespaceFor(
5602
5617
  request.namespace,
5603
5618
  undefined,
5604
5619
  request.authenticatedPrincipal,
@@ -5632,7 +5647,7 @@ export class EngramAccessService {
5632
5647
  async trustZoneDemoSeed(
5633
5648
  request: EngramAccessTrustZoneDemoSeedRequest,
5634
5649
  ): Promise<EngramAccessTrustZoneDemoSeedResponse> {
5635
- const resolvedNamespace = this.resolveWritableNamespace(
5650
+ const resolvedNamespace = this.writableNamespaceFor(
5636
5651
  request.namespace,
5637
5652
  undefined,
5638
5653
  request.authenticatedPrincipal,
@@ -5669,7 +5684,7 @@ export class EngramAccessService {
5669
5684
  throw new EngramAccessInputError("reasonCode is required");
5670
5685
  }
5671
5686
 
5672
- const resolvedNamespace = this.resolveWritableNamespace(
5687
+ const resolvedNamespace = this.writableNamespaceFor(
5673
5688
  request.namespace,
5674
5689
  undefined,
5675
5690
  request.authenticatedPrincipal,
@@ -5835,7 +5850,7 @@ export class EngramAccessService {
5835
5850
 
5836
5851
  // Backward-compatible BASE writable namespace (pre-#1495 response semantics)
5837
5852
  // for the legacy `namespace` response field. DERIVED from the already-resolved
5838
- // scope plan — NOT a second `resolveWritableNamespace(request.namespace,...)`
5853
+ // scope plan — NOT a second writable-namespace resolution call
5839
5854
  // call (#1505 thread jvO). The fresh call re-authorized `undefined ⇒
5840
5855
  // config.defaultNamespace` a SECOND time; under a restrictive default-namespace
5841
5856
  // write policy that re-auth could REJECT an otherwise valid project-scoped
@@ -5845,7 +5860,7 @@ export class EngramAccessService {
5845
5860
  // the coding context, leaving an orphaned session binding behind. The plan is
5846
5861
  // the single authorization point (rule 22 / 39); the legacy field must reuse it
5847
5862
  // and never re-authorize. Pre-#1495 semantics were exactly
5848
- // `resolveWritableNamespace(request.namespace)` (overlay-agnostic): the explicit
5863
+ // the writable-namespace resolver (overlay-agnostic): the explicit
5849
5864
  // namespace when supplied, else `config.defaultNamespace` for user-project
5850
5865
  // coding overlays. Hosted scope-profile layers such as `teamProject` report
5851
5866
  // their effective profile write namespace because there is no legacy
@@ -6680,7 +6695,7 @@ export class EngramAccessService {
6680
6695
 
6681
6696
  // Authorize compaction against the SCOPED WRITE TARGET — the SAME effective
6682
6697
  // write namespace `observe` archived the LCM queue under — NOT a premature
6683
- // `resolveWritableNamespace(undefined ⇒ config.defaultNamespace)` (#1505
6698
+ // the writable-namespace resolver (undefined ⇒ config.defaultNamespace) (#1505
6684
6699
  // thread NBHWs). Under a restrictive `default` WRITE policy where the
6685
6700
  // principal can still write its self/project overlay, that premature default
6686
6701
  // write-auth threw `namespace is not writable: default` BEFORE the scoped key
@@ -6692,7 +6707,7 @@ export class EngramAccessService {
6692
6707
  // default` for a validly scoped observe's queue.
6693
6708
  const scope = await this.resolveMemoryScopePlan(request);
6694
6709
  // Legacy `namespace` response field: pre-#1505 semantics were exactly
6695
- // `resolveWritableNamespace(request.namespace)` (overlay-agnostic) — the
6710
+ // the writable-namespace resolver (overlay-agnostic) — the
6696
6711
  // authorized explicit namespace when supplied, else `config.defaultNamespace`.
6697
6712
  // DERIVED from the scope plan (NOT a second auth pass, #1505 thread jvO):
6698
6713
  // explicit ⇒ writeNamespace; user-project coding overlay ⇒ defaultNamespace;
@@ -6747,7 +6762,7 @@ export class EngramAccessService {
6747
6762
 
6748
6763
  // Authorize compaction against the SCOPED WRITE TARGET — the SAME effective
6749
6764
  // write namespace `observe` archived the LCM queue under — NOT a premature
6750
- // `resolveWritableNamespace(undefined ⇒ config.defaultNamespace)` (#1505
6765
+ // the writable-namespace resolver (undefined ⇒ config.defaultNamespace) (#1505
6751
6766
  // thread NBHWs). See `lcmCompactionFlush` for the full rationale: under a
6752
6767
  // restrictive `default` WRITE policy where the principal can still write its
6753
6768
  // self/project overlay, the old premature default write-auth threw `namespace
@@ -6832,7 +6847,7 @@ export class EngramAccessService {
6832
6847
  }
6833
6848
  const symptom = request.symptom?.trim();
6834
6849
  if (!symptom) throw new EngramAccessInputError("symptom is required");
6835
- const resolvedNs = this.resolveWritableNamespace(request.namespace, undefined, request.principal);
6850
+ const resolvedNs = this.writableNamespaceFor(request.namespace, undefined, request.principal);
6836
6851
  const storage = await this.orchestrator.getStorage(resolvedNs);
6837
6852
  const created = await storage.appendContinuityIncident({
6838
6853
  symptom,
@@ -6862,7 +6877,7 @@ export class EngramAccessService {
6862
6877
  if (!fixApplied) throw new EngramAccessInputError("fixApplied is required");
6863
6878
  const verificationResult = request.verificationResult?.trim();
6864
6879
  if (!verificationResult) throw new EngramAccessInputError("verificationResult is required");
6865
- const resolvedNs = this.resolveWritableNamespace(request.namespace, undefined, request.principal);
6880
+ const resolvedNs = this.writableNamespaceFor(request.namespace, undefined, request.principal);
6866
6881
  const storage = await this.orchestrator.getStorage(resolvedNs);
6867
6882
  const closed = await storage.closeContinuityIncident(id, {
6868
6883
  fixApplied,
@@ -6904,7 +6919,7 @@ export class EngramAccessService {
6904
6919
  if (!this.orchestrator.config.identityContinuityEnabled) {
6905
6920
  return { enabled: false, reason: "Identity continuity is disabled." };
6906
6921
  }
6907
- const resolvedNs = this.resolveWritableNamespace(request.namespace, undefined, request.principal);
6922
+ const resolvedNs = this.writableNamespaceFor(request.namespace, undefined, request.principal);
6908
6923
  const storage = await this.orchestrator.getStorage(resolvedNs);
6909
6924
  const loop = await storage.upsertIdentityImprovementLoop({
6910
6925
  id: request.id?.trim() || "",
@@ -6931,7 +6946,7 @@ export class EngramAccessService {
6931
6946
  }
6932
6947
  const id = request.id?.trim();
6933
6948
  if (!id) throw new EngramAccessInputError("id is required");
6934
- const resolvedNs = this.resolveWritableNamespace(request.namespace, undefined, request.principal);
6949
+ const resolvedNs = this.writableNamespaceFor(request.namespace, undefined, request.principal);
6935
6950
  const storage = await this.orchestrator.getStorage(resolvedNs);
6936
6951
  const reviewed = await storage.reviewIdentityImprovementLoop(id, {
6937
6952
  status: request.status,
@@ -6985,7 +7000,7 @@ export class EngramAccessService {
6985
7000
  const hasUpdate = Object.values(updates).some((v) => typeof v === "string" && v.length > 0);
6986
7001
  if (!hasUpdate) throw new EngramAccessInputError("At least one section field is required.");
6987
7002
 
6988
- const resolvedNs = this.resolveWritableNamespace(request.namespace, undefined, request.principal);
7003
+ const resolvedNs = this.writableNamespaceFor(request.namespace, undefined, request.principal);
6989
7004
  const storage = await this.orchestrator.getStorage(resolvedNs);
6990
7005
  const existing = await storage.readIdentityAnchor();
6991
7006
 
@@ -7654,7 +7669,7 @@ export class EngramAccessService {
7654
7669
  "memoryId must not contain path separators",
7655
7670
  );
7656
7671
  }
7657
- const resolvedNs = this.resolveWritableNamespace(
7672
+ const resolvedNs = this.writableNamespaceFor(
7658
7673
  request.namespace,
7659
7674
  request.sessionKey,
7660
7675
  request.principal,
@@ -7678,7 +7693,7 @@ export class EngramAccessService {
7678
7693
  principal?: string;
7679
7694
  sessionKey?: string;
7680
7695
  }): Promise<unknown> {
7681
- const resolvedNs = this.resolveWritableNamespace(request.namespace, request.sessionKey, request.principal);
7696
+ const resolvedNs = this.writableNamespaceFor(request.namespace, request.sessionKey, request.principal);
7682
7697
  const storage = await this.orchestrator.getStorage(resolvedNs);
7683
7698
  // Update frontmatter to active status (promote from pending/draft)
7684
7699
  await storage.updateMemoryFrontmatter(request.memoryId, {
@@ -7734,7 +7749,7 @@ export class EngramAccessService {
7734
7749
  );
7735
7750
  }
7736
7751
 
7737
- const resolvedNs = this.resolveWritableNamespace(
7752
+ const resolvedNs = this.writableNamespaceFor(
7738
7753
  request.namespace,
7739
7754
  request.sessionKey,
7740
7755
  request.principal,
@@ -7784,7 +7799,7 @@ export class EngramAccessService {
7784
7799
  namespace?: string;
7785
7800
  principal?: string;
7786
7801
  }): Promise<{ saved: boolean }> {
7787
- const resolvedNs = this.resolveWritableNamespace(request.namespace, request.sessionKey, request.principal);
7802
+ const resolvedNs = this.writableNamespaceFor(request.namespace, request.sessionKey, request.principal);
7788
7803
  const storage = await this.orchestrator.getStorage(resolvedNs);
7789
7804
  const storageDir = storage.dir;
7790
7805
  const { writeFile, mkdir } = await import("node:fs/promises");
@@ -7842,7 +7857,7 @@ export class EngramAccessService {
7842
7857
  // Pass authenticatedPrincipal so the principal resolution matches other
7843
7858
  // write endpoints (gotcha #42: read and write paths must resolve through
7844
7859
  // the same namespace layer).
7845
- const resolvedNamespace = this.resolveWritableNamespace(
7860
+ const resolvedNamespace = this.writableNamespaceFor(
7846
7861
  request.namespace,
7847
7862
  request.sessionId,
7848
7863
  request.authenticatedPrincipal,
@@ -8144,7 +8159,7 @@ export class EngramAccessService {
8144
8159
  "authentication required: namespaces are enabled and no principal was supplied",
8145
8160
  );
8146
8161
  }
8147
- const resolved = this.resolveWritableNamespace(namespace, undefined, principal);
8162
+ const resolved = this.writableNamespaceFor(namespace, undefined, principal);
8148
8163
  const storage = await this.orchestrator.getStorage(resolved);
8149
8164
  return { namespace: resolved, storage };
8150
8165
  }
@@ -8201,7 +8216,7 @@ export class EngramAccessService {
8201
8216
  },
8202
8217
  ): Promise<ImportCapsuleResult> {
8203
8218
  const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...importOptions } = opts;
8204
- const resolvedNamespace = this.resolveWritableNamespace(namespace, undefined, principal);
8219
+ const resolvedNamespace = this.writableNamespaceFor(namespace, undefined, principal);
8205
8220
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
8206
8221
  const root = explicitRoot ?? storage.dir;
8207
8222
  const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
@@ -8288,7 +8303,7 @@ export class EngramAccessService {
8288
8303
  },
8289
8304
  ): Promise<ExportCapsuleResult> {
8290
8305
  const { namespace, principal, root: explicitRoot, memoryDir: explicitMemoryDir, ...exportOptions } = opts;
8291
- const resolvedNamespace = this.resolveWritableNamespace(namespace, undefined, principal);
8306
+ const resolvedNamespace = this.writableNamespaceFor(namespace, undefined, principal);
8292
8307
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
8293
8308
  const root = explicitRoot ?? storage.dir;
8294
8309
  const memoryDir = explicitMemoryDir ?? this.orchestrator.config.memoryDir;
@@ -8522,7 +8537,7 @@ export class EngramAccessService {
8522
8537
  async offlineSyncApplyFileContent(
8523
8538
  options: EngramAccessOfflineSyncApplyFileContentRequest,
8524
8539
  ): Promise<EngramAccessOfflineSyncApplyFileContentResponse> {
8525
- const resolvedNamespace = this.resolveWritableNamespace(
8540
+ const resolvedNamespace = this.writableNamespaceFor(
8526
8541
  options.namespace,
8527
8542
  undefined,
8528
8543
  options.principal,
@@ -8573,7 +8588,7 @@ export class EngramAccessService {
8573
8588
  async offlineSyncApply(
8574
8589
  options: EngramAccessOfflineSyncApplyRequest,
8575
8590
  ): Promise<EngramAccessOfflineSyncApplyResponse> {
8576
- const resolvedNamespace = this.resolveWritableNamespace(
8591
+ const resolvedNamespace = this.writableNamespaceFor(
8577
8592
  options.namespace,
8578
8593
  undefined,
8579
8594
  options.principal,
@@ -8655,7 +8670,7 @@ export class EngramAccessService {
8655
8670
  );
8656
8671
  }
8657
8672
  const dryRun = options.dryRun === true;
8658
- const resolvedNamespace = this.resolveWritableNamespace(
8673
+ const resolvedNamespace = this.writableNamespaceFor(
8659
8674
  options.namespace,
8660
8675
  undefined,
8661
8676
  options.authenticatedPrincipal,
@@ -9,6 +9,7 @@ import { namespaceIdentityToken } from "../namespaces/identity.js";
9
9
  import { resolveNamespaceStorageRoot } from "../namespaces/storage.js";
10
10
  import { displayErrorDetail } from "../runtime/better-sqlite.js";
11
11
  import type { PluginConfig } from "../types.js";
12
+ import { getConfiguredNamespaces } from "../scopes/scope-plan.js";
12
13
 
13
14
  export type NamespaceMaintenanceJobName = string;
14
15
 
@@ -110,15 +111,7 @@ export function __setNamespaceMaintenanceFsForTest(overrides: Partial<typeof nam
110
111
  };
111
112
  }
112
113
 
113
- function configuredNamespaces(config: PluginConfig): string[] {
114
- return Array.from(
115
- new Set(
116
- [config.defaultNamespace, config.sharedNamespace, ...config.namespacePolicies.map((policy) => policy.name)]
117
- .map((value) => value.trim())
118
- .filter(Boolean)
119
- )
120
- );
121
- }
114
+
122
115
 
123
116
  function inferConfiguredKind(config: PluginConfig, namespace: string): NamespaceKind {
124
117
  if (namespace === config.defaultNamespace.trim()) return "default";
@@ -219,7 +212,7 @@ export async function planNamespaceMaintenance(
219
212
  // once per configured name. The #1500 contract is "namespaces disabled:
220
213
  // maintain the current default storage only," so collapse to the default.
221
214
  const configured = config.namespacesEnabled
222
- ? configuredNamespaces(config)
215
+ ? getConfiguredNamespaces(config)
223
216
  : [config.defaultNamespace.trim()].filter(Boolean);
224
217
  const byNamespace = new Map<string, NamespaceMaintenanceCandidate>();
225
218
  const skipped: NamespaceMaintenanceSkippedNamespace[] = [];