@remnic/core 9.3.664 → 9.3.665
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +2 -2
- package/dist/access-schema.d.ts +36 -36
- package/dist/{chunk-NLF54XMD.js → chunk-2OPARZ4B.js} +3 -3
- package/dist/{chunk-XB5P5P2L.js → chunk-7C4MPEPE.js} +2 -2
- package/dist/{chunk-7ILWCUWH.js → chunk-D7IXTY5E.js} +27 -2
- package/dist/chunk-D7IXTY5E.js.map +1 -0
- package/dist/{chunk-LIERUFPO.js → chunk-WH4SKYPX.js} +2 -2
- package/dist/{chunk-YKX63GBK.js → chunk-XRSIGVTS.js} +2 -2
- package/dist/cli.js +4 -4
- package/dist/index.js +5 -5
- package/dist/namespaces/migrate.js +2 -2
- package/dist/namespaces/storage.d.ts +13 -0
- package/dist/namespaces/storage.js +1 -1
- package/dist/operator-toolkit.js +3 -3
- package/dist/orchestrator.js +2 -2
- package/dist/schemas.d.ts +42 -42
- package/dist/shared-context/manager.d.ts +2 -2
- package/package.json +1 -1
- package/src/namespaces/catalog.test.ts +12 -12
- package/src/namespaces/storage.ts +28 -1
- package/dist/chunk-7ILWCUWH.js.map +0 -1
- /package/dist/{chunk-NLF54XMD.js.map → chunk-2OPARZ4B.js.map} +0 -0
- /package/dist/{chunk-XB5P5P2L.js.map → chunk-7C4MPEPE.js.map} +0 -0
- /package/dist/{chunk-LIERUFPO.js.map → chunk-WH4SKYPX.js.map} +0 -0
- /package/dist/{chunk-YKX63GBK.js.map → chunk-XRSIGVTS.js.map} +0 -0
package/dist/access-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Orchestrator
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WH4SKYPX.js";
|
|
4
4
|
import "./chunk-4SKKVWLQ.js";
|
|
5
5
|
import "./chunk-7HYPN2GC.js";
|
|
6
6
|
import "./chunk-666A3MOW.js";
|
|
@@ -83,7 +83,7 @@ import "./chunk-AGRPGAKR.js";
|
|
|
83
83
|
import "./chunk-S4DDLTPX.js";
|
|
84
84
|
import "./chunk-SFQ6QNL7.js";
|
|
85
85
|
import "./chunk-33JBK2XP.js";
|
|
86
|
-
import "./chunk-
|
|
86
|
+
import "./chunk-D7IXTY5E.js";
|
|
87
87
|
import "./chunk-KFY3SGN7.js";
|
|
88
88
|
import {
|
|
89
89
|
resolvePluginEntry
|
package/dist/access-schema.d.ts
CHANGED
|
@@ -104,9 +104,9 @@ declare const recallRequestSchema: z.ZodObject<{
|
|
|
104
104
|
includeLowConfidence: z.ZodOptional<z.ZodBoolean>;
|
|
105
105
|
}, "strip", z.ZodTypeAny, {
|
|
106
106
|
query: string;
|
|
107
|
+
namespace?: string | undefined;
|
|
107
108
|
sessionKey?: string | undefined;
|
|
108
109
|
tags?: string[] | undefined;
|
|
109
|
-
namespace?: string | undefined;
|
|
110
110
|
topK?: number | undefined;
|
|
111
111
|
mode?: "auto" | "no_recall" | "minimal" | "full" | "graph_mode" | undefined;
|
|
112
112
|
cwd?: string | undefined;
|
|
@@ -125,9 +125,9 @@ declare const recallRequestSchema: z.ZodObject<{
|
|
|
125
125
|
tagMatch?: "all" | "any" | undefined;
|
|
126
126
|
}, {
|
|
127
127
|
query: string;
|
|
128
|
+
namespace?: string | undefined;
|
|
128
129
|
sessionKey?: string | undefined;
|
|
129
130
|
tags?: string[] | undefined;
|
|
130
|
-
namespace?: string | undefined;
|
|
131
131
|
topK?: number | undefined;
|
|
132
132
|
mode?: "auto" | "no_recall" | "minimal" | "full" | "graph_mode" | undefined;
|
|
133
133
|
cwd?: string | undefined;
|
|
@@ -149,11 +149,11 @@ declare const recallExplainRequestSchema: z.ZodObject<{
|
|
|
149
149
|
sessionKey: z.ZodOptional<z.ZodString>;
|
|
150
150
|
namespace: z.ZodOptional<z.ZodString>;
|
|
151
151
|
}, "strip", z.ZodTypeAny, {
|
|
152
|
-
sessionKey?: string | undefined;
|
|
153
152
|
namespace?: string | undefined;
|
|
154
|
-
}, {
|
|
155
153
|
sessionKey?: string | undefined;
|
|
154
|
+
}, {
|
|
156
155
|
namespace?: string | undefined;
|
|
156
|
+
sessionKey?: string | undefined;
|
|
157
157
|
}>;
|
|
158
158
|
/**
|
|
159
159
|
* Standalone "set coding context" request. Used by the HTTP endpoint
|
|
@@ -365,30 +365,30 @@ declare const memoryStoreRequestSchema: z.ZodObject<{
|
|
|
365
365
|
projectTag: z.ZodOptional<z.ZodString>;
|
|
366
366
|
}, "strip", z.ZodTypeAny, {
|
|
367
367
|
content: string;
|
|
368
|
+
namespace?: string | undefined;
|
|
369
|
+
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
370
|
+
confidence?: number | undefined;
|
|
371
|
+
ttl?: string | undefined;
|
|
368
372
|
schemaVersion?: number | undefined;
|
|
369
373
|
sessionKey?: string | undefined;
|
|
370
374
|
tags?: string[] | undefined;
|
|
371
375
|
dryRun?: boolean | undefined;
|
|
372
|
-
namespace?: string | undefined;
|
|
373
|
-
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
374
|
-
confidence?: number | undefined;
|
|
375
376
|
entityRef?: string | undefined;
|
|
376
|
-
ttl?: string | undefined;
|
|
377
377
|
sourceReason?: string | undefined;
|
|
378
378
|
cwd?: string | undefined;
|
|
379
379
|
idempotencyKey?: string | undefined;
|
|
380
380
|
projectTag?: string | undefined;
|
|
381
381
|
}, {
|
|
382
382
|
content: string;
|
|
383
|
+
namespace?: string | undefined;
|
|
384
|
+
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
385
|
+
confidence?: number | undefined;
|
|
386
|
+
ttl?: string | undefined;
|
|
383
387
|
schemaVersion?: number | undefined;
|
|
384
388
|
sessionKey?: string | undefined;
|
|
385
389
|
tags?: string[] | undefined;
|
|
386
390
|
dryRun?: boolean | undefined;
|
|
387
|
-
namespace?: string | undefined;
|
|
388
|
-
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
389
|
-
confidence?: number | undefined;
|
|
390
391
|
entityRef?: string | undefined;
|
|
391
|
-
ttl?: string | undefined;
|
|
392
392
|
sourceReason?: string | undefined;
|
|
393
393
|
cwd?: string | undefined;
|
|
394
394
|
idempotencyKey?: string | undefined;
|
|
@@ -411,30 +411,30 @@ declare const suggestionSubmitRequestSchema: z.ZodObject<{
|
|
|
411
411
|
projectTag: z.ZodOptional<z.ZodString>;
|
|
412
412
|
}, "strip", z.ZodTypeAny, {
|
|
413
413
|
content: string;
|
|
414
|
+
namespace?: string | undefined;
|
|
415
|
+
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
416
|
+
confidence?: number | undefined;
|
|
417
|
+
ttl?: string | undefined;
|
|
414
418
|
schemaVersion?: number | undefined;
|
|
415
419
|
sessionKey?: string | undefined;
|
|
416
420
|
tags?: string[] | undefined;
|
|
417
421
|
dryRun?: boolean | undefined;
|
|
418
|
-
namespace?: string | undefined;
|
|
419
|
-
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
420
|
-
confidence?: number | undefined;
|
|
421
422
|
entityRef?: string | undefined;
|
|
422
|
-
ttl?: string | undefined;
|
|
423
423
|
sourceReason?: string | undefined;
|
|
424
424
|
cwd?: string | undefined;
|
|
425
425
|
idempotencyKey?: string | undefined;
|
|
426
426
|
projectTag?: string | undefined;
|
|
427
427
|
}, {
|
|
428
428
|
content: string;
|
|
429
|
+
namespace?: string | undefined;
|
|
430
|
+
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
431
|
+
confidence?: number | undefined;
|
|
432
|
+
ttl?: string | undefined;
|
|
429
433
|
schemaVersion?: number | undefined;
|
|
430
434
|
sessionKey?: string | undefined;
|
|
431
435
|
tags?: string[] | undefined;
|
|
432
436
|
dryRun?: boolean | undefined;
|
|
433
|
-
namespace?: string | undefined;
|
|
434
|
-
category?: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace" | undefined;
|
|
435
|
-
confidence?: number | undefined;
|
|
436
437
|
entityRef?: string | undefined;
|
|
437
|
-
ttl?: string | undefined;
|
|
438
438
|
sourceReason?: string | undefined;
|
|
439
439
|
cwd?: string | undefined;
|
|
440
440
|
idempotencyKey?: string | undefined;
|
|
@@ -468,18 +468,18 @@ declare const trustZonePromoteRequestSchema: z.ZodObject<{
|
|
|
468
468
|
recordId: string;
|
|
469
469
|
targetZone: "working" | "trusted";
|
|
470
470
|
promotionReason: string;
|
|
471
|
+
namespace?: string | undefined;
|
|
471
472
|
recordedAt?: string | undefined;
|
|
472
473
|
summary?: string | undefined;
|
|
473
474
|
dryRun?: boolean | undefined;
|
|
474
|
-
namespace?: string | undefined;
|
|
475
475
|
}, {
|
|
476
476
|
recordId: string;
|
|
477
477
|
targetZone: "working" | "trusted";
|
|
478
478
|
promotionReason: string;
|
|
479
|
+
namespace?: string | undefined;
|
|
479
480
|
recordedAt?: string | undefined;
|
|
480
481
|
summary?: string | undefined;
|
|
481
482
|
dryRun?: boolean | undefined;
|
|
482
|
-
namespace?: string | undefined;
|
|
483
483
|
}>;
|
|
484
484
|
declare const trustZoneDemoSeedRequestSchema: z.ZodObject<{
|
|
485
485
|
scenario: z.ZodOptional<z.ZodString>;
|
|
@@ -487,14 +487,14 @@ declare const trustZoneDemoSeedRequestSchema: z.ZodObject<{
|
|
|
487
487
|
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
488
488
|
namespace: z.ZodOptional<z.ZodString>;
|
|
489
489
|
}, "strip", z.ZodTypeAny, {
|
|
490
|
+
namespace?: string | undefined;
|
|
490
491
|
recordedAt?: string | undefined;
|
|
491
492
|
dryRun?: boolean | undefined;
|
|
492
|
-
namespace?: string | undefined;
|
|
493
493
|
scenario?: string | undefined;
|
|
494
494
|
}, {
|
|
495
|
+
namespace?: string | undefined;
|
|
495
496
|
recordedAt?: string | undefined;
|
|
496
497
|
dryRun?: boolean | undefined;
|
|
497
|
-
namespace?: string | undefined;
|
|
498
498
|
scenario?: string | undefined;
|
|
499
499
|
}>;
|
|
500
500
|
declare const lcmSearchRequestSchema: z.ZodObject<{
|
|
@@ -505,15 +505,15 @@ declare const lcmSearchRequestSchema: z.ZodObject<{
|
|
|
505
505
|
limit: z.ZodOptional<z.ZodNumber>;
|
|
506
506
|
}, "strip", z.ZodTypeAny, {
|
|
507
507
|
query: string;
|
|
508
|
-
sessionKey?: string | undefined;
|
|
509
508
|
namespace?: string | undefined;
|
|
510
509
|
limit?: number | undefined;
|
|
510
|
+
sessionKey?: string | undefined;
|
|
511
511
|
sessionPrefix?: string | undefined;
|
|
512
512
|
}, {
|
|
513
513
|
query: string;
|
|
514
|
-
sessionKey?: string | undefined;
|
|
515
514
|
namespace?: string | undefined;
|
|
516
515
|
limit?: number | undefined;
|
|
516
|
+
sessionKey?: string | undefined;
|
|
517
517
|
sessionPrefix?: string | undefined;
|
|
518
518
|
}>;
|
|
519
519
|
declare const lcmCompactionFlushRequestSchema: z.ZodObject<{
|
|
@@ -548,14 +548,14 @@ declare const daySummaryRequestSchema: z.ZodObject<{
|
|
|
548
548
|
namespace: z.ZodOptional<z.ZodString>;
|
|
549
549
|
timeZone: z.ZodOptional<z.ZodEffects<z.ZodString, string, string>>;
|
|
550
550
|
}, "strip", z.ZodTypeAny, {
|
|
551
|
+
namespace?: string | undefined;
|
|
551
552
|
sessionKey?: string | undefined;
|
|
552
553
|
timeZone?: string | undefined;
|
|
553
|
-
namespace?: string | undefined;
|
|
554
554
|
memories?: string | undefined;
|
|
555
555
|
}, {
|
|
556
|
+
namespace?: string | undefined;
|
|
556
557
|
sessionKey?: string | undefined;
|
|
557
558
|
timeZone?: string | undefined;
|
|
558
|
-
namespace?: string | undefined;
|
|
559
559
|
memories?: string | undefined;
|
|
560
560
|
}>;
|
|
561
561
|
declare const capsuleExportRequestSchema: z.ZodObject<{
|
|
@@ -603,11 +603,11 @@ declare const capsuleListRequestSchema: z.ZodObject<{
|
|
|
603
603
|
namespace: z.ZodOptional<z.ZodString>;
|
|
604
604
|
sessionKey: z.ZodOptional<z.ZodString>;
|
|
605
605
|
}, "strip", z.ZodTypeAny, {
|
|
606
|
-
sessionKey?: string | undefined;
|
|
607
606
|
namespace?: string | undefined;
|
|
608
|
-
}, {
|
|
609
607
|
sessionKey?: string | undefined;
|
|
608
|
+
}, {
|
|
610
609
|
namespace?: string | undefined;
|
|
610
|
+
sessionKey?: string | undefined;
|
|
611
611
|
}>;
|
|
612
612
|
declare const offlineSyncSnapshotRequestSchema: z.ZodObject<{
|
|
613
613
|
namespace: z.ZodOptional<z.ZodString>;
|
|
@@ -748,11 +748,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
748
748
|
safety: z.ZodEffects<z.ZodNullable<z.ZodOptional<z.ZodEnum<["safe", "requires-review", "blocked"]>>>, NonNullable<"blocked" | "safe" | "requires-review"> | undefined, "blocked" | "safe" | "requires-review" | null | undefined>;
|
|
749
749
|
safetyReasons: z.ZodEffects<z.ZodNullable<z.ZodOptional<z.ZodArray<z.ZodString, "many">>>, string[] | undefined, string[] | null | undefined>;
|
|
750
750
|
}, "strict", z.ZodTypeAny, {
|
|
751
|
+
confidence?: number | undefined;
|
|
751
752
|
source?: string | undefined;
|
|
752
753
|
stale?: boolean | undefined;
|
|
753
754
|
created?: string | undefined;
|
|
754
755
|
updated?: string | undefined;
|
|
755
|
-
confidence?: number | undefined;
|
|
756
756
|
scope?: string | undefined;
|
|
757
757
|
retrievalReason?: string | undefined;
|
|
758
758
|
safety?: NonNullable<"blocked" | "safe" | "requires-review"> | undefined;
|
|
@@ -762,11 +762,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
762
762
|
safetyReasons?: string[] | undefined;
|
|
763
763
|
userContextScopes?: string[] | undefined;
|
|
764
764
|
}, {
|
|
765
|
+
confidence?: number | null | undefined;
|
|
765
766
|
source?: string | null | undefined;
|
|
766
767
|
stale?: boolean | null | undefined;
|
|
767
768
|
created?: string | null | undefined;
|
|
768
769
|
updated?: string | null | undefined;
|
|
769
|
-
confidence?: number | null | undefined;
|
|
770
770
|
scope?: string | null | undefined;
|
|
771
771
|
retrievalReason?: string | null | undefined;
|
|
772
772
|
safety?: "blocked" | "safe" | "requires-review" | null | undefined;
|
|
@@ -776,11 +776,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
776
776
|
safetyReasons?: string[] | null | undefined;
|
|
777
777
|
userContextScopes?: string[] | null | undefined;
|
|
778
778
|
}>, "many">>>, {
|
|
779
|
+
confidence?: number | undefined;
|
|
779
780
|
source?: string | undefined;
|
|
780
781
|
stale?: boolean | undefined;
|
|
781
782
|
created?: string | undefined;
|
|
782
783
|
updated?: string | undefined;
|
|
783
|
-
confidence?: number | undefined;
|
|
784
784
|
scope?: string | undefined;
|
|
785
785
|
retrievalReason?: string | undefined;
|
|
786
786
|
safety?: NonNullable<"blocked" | "safe" | "requires-review"> | undefined;
|
|
@@ -790,11 +790,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
790
790
|
safetyReasons?: string[] | undefined;
|
|
791
791
|
userContextScopes?: string[] | undefined;
|
|
792
792
|
}[] | undefined, {
|
|
793
|
+
confidence?: number | null | undefined;
|
|
793
794
|
source?: string | null | undefined;
|
|
794
795
|
stale?: boolean | null | undefined;
|
|
795
796
|
created?: string | null | undefined;
|
|
796
797
|
updated?: string | null | undefined;
|
|
797
|
-
confidence?: number | null | undefined;
|
|
798
798
|
scope?: string | null | undefined;
|
|
799
799
|
retrievalReason?: string | null | undefined;
|
|
800
800
|
safety?: "blocked" | "safe" | "requires-review" | null | undefined;
|
|
@@ -816,11 +816,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
816
816
|
matched?: boolean | undefined;
|
|
817
817
|
}[] | undefined;
|
|
818
818
|
retrievedMemories?: {
|
|
819
|
+
confidence?: number | undefined;
|
|
819
820
|
source?: string | undefined;
|
|
820
821
|
stale?: boolean | undefined;
|
|
821
822
|
created?: string | undefined;
|
|
822
823
|
updated?: string | undefined;
|
|
823
|
-
confidence?: number | undefined;
|
|
824
824
|
scope?: string | undefined;
|
|
825
825
|
retrievalReason?: string | undefined;
|
|
826
826
|
safety?: NonNullable<"blocked" | "safe" | "requires-review"> | undefined;
|
|
@@ -842,11 +842,11 @@ declare const actionConfidenceRequestSchema: z.ZodObject<{
|
|
|
842
842
|
matched?: boolean | null | undefined;
|
|
843
843
|
}[] | null | undefined;
|
|
844
844
|
retrievedMemories?: {
|
|
845
|
+
confidence?: number | null | undefined;
|
|
845
846
|
source?: string | null | undefined;
|
|
846
847
|
stale?: boolean | null | undefined;
|
|
847
848
|
created?: string | null | undefined;
|
|
848
849
|
updated?: string | null | undefined;
|
|
849
|
-
confidence?: number | null | undefined;
|
|
850
850
|
scope?: string | null | undefined;
|
|
851
851
|
retrievalReason?: string | null | undefined;
|
|
852
852
|
safety?: "blocked" | "safe" | "requires-review" | null | undefined;
|
|
@@ -93,12 +93,12 @@ import {
|
|
|
93
93
|
runOperatorInventory,
|
|
94
94
|
runOperatorRepair,
|
|
95
95
|
runOperatorSetup
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-XRSIGVTS.js";
|
|
97
97
|
import {
|
|
98
98
|
listNamespaces,
|
|
99
99
|
runNamespaceMigration,
|
|
100
100
|
verifyNamespaces
|
|
101
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-7C4MPEPE.js";
|
|
102
102
|
import {
|
|
103
103
|
collectPatternMemories,
|
|
104
104
|
explainPatternMemory,
|
|
@@ -7311,4 +7311,4 @@ export {
|
|
|
7311
7311
|
listMemoryMarkdownFilePaths,
|
|
7312
7312
|
registerCli
|
|
7313
7313
|
};
|
|
7314
|
-
//# sourceMappingURL=chunk-
|
|
7314
|
+
//# sourceMappingURL=chunk-2OPARZ4B.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
NamespaceStorageRouter
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-D7IXTY5E.js";
|
|
4
4
|
import {
|
|
5
5
|
namespaceCollectionName
|
|
6
6
|
} from "./chunk-DQY7NJ5L.js";
|
|
@@ -204,4 +204,4 @@ export {
|
|
|
204
204
|
verifyNamespaces,
|
|
205
205
|
runNamespaceMigration
|
|
206
206
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
207
|
+
//# sourceMappingURL=chunk-7C4MPEPE.js.map
|
|
@@ -126,6 +126,11 @@ var NamespaceStorageRouter = class {
|
|
|
126
126
|
// entry is always removed when the promise settles, so the map cannot grow
|
|
127
127
|
// unbounded (one transient entry per concurrently-resolving namespace).
|
|
128
128
|
inFlightResolved = /* @__PURE__ */ new Map();
|
|
129
|
+
// Tracks every in-flight resolve-hook promise so callers can deterministically
|
|
130
|
+
// await the fire-and-forget registrations that `storageFor()` kicks off (see
|
|
131
|
+
// `whenResolveHooksSettled`). Entries are removed as each hook settles, so the
|
|
132
|
+
// set holds at most one promise per concurrently-resolving namespace.
|
|
133
|
+
pendingResolveHooks = /* @__PURE__ */ new Set();
|
|
129
134
|
// Normalized (trimmed) default namespace identity (NH-FH). `storageFor`
|
|
130
135
|
// normalizes its input, so default-namespace branches must compare against the
|
|
131
136
|
// normalized config default too — otherwise a whitespace-padded configured
|
|
@@ -180,7 +185,9 @@ var NamespaceStorageRouter = class {
|
|
|
180
185
|
if (this.inFlightResolved.get(namespace) === storageDir) return;
|
|
181
186
|
try {
|
|
182
187
|
this.inFlightResolved.set(namespace, storageDir);
|
|
183
|
-
Promise.resolve(hook(namespace, storageDir))
|
|
188
|
+
const hookResult = Promise.resolve(hook(namespace, storageDir));
|
|
189
|
+
this.pendingResolveHooks.add(hookResult);
|
|
190
|
+
hookResult.then(
|
|
184
191
|
(persisted) => {
|
|
185
192
|
if (this.inFlightResolved.get(namespace) === storageDir) {
|
|
186
193
|
this.inFlightResolved.delete(namespace);
|
|
@@ -188,6 +195,7 @@ var NamespaceStorageRouter = class {
|
|
|
188
195
|
if (persisted !== false) {
|
|
189
196
|
this.notifiedResolved.set(namespace, storageDir);
|
|
190
197
|
}
|
|
198
|
+
this.pendingResolveHooks.delete(hookResult);
|
|
191
199
|
},
|
|
192
200
|
() => {
|
|
193
201
|
if (this.inFlightResolved.get(namespace) === storageDir) {
|
|
@@ -196,6 +204,7 @@ var NamespaceStorageRouter = class {
|
|
|
196
204
|
if (this.notifiedResolved.get(namespace) === storageDir) {
|
|
197
205
|
this.notifiedResolved.delete(namespace);
|
|
198
206
|
}
|
|
207
|
+
this.pendingResolveHooks.delete(hookResult);
|
|
199
208
|
}
|
|
200
209
|
);
|
|
201
210
|
} catch {
|
|
@@ -204,6 +213,22 @@ var NamespaceStorageRouter = class {
|
|
|
204
213
|
}
|
|
205
214
|
}
|
|
206
215
|
}
|
|
216
|
+
/**
|
|
217
|
+
* Resolve once every in-flight `onResolve` registration has settled.
|
|
218
|
+
*
|
|
219
|
+
* `storageFor()` fires the resolve hook fire-and-forget, so its catalog side
|
|
220
|
+
* effect (e.g. `registerResolved(...)`) is not observable the moment
|
|
221
|
+
* `storageFor()` returns. Callers that must act on that side effect — notably
|
|
222
|
+
* tests asserting the catalog was updated — should await this instead of
|
|
223
|
+
* racing a timer. Resolves immediately when no hook is registered or nothing
|
|
224
|
+
* is in flight. The loop re-checks because a settling hook could, in
|
|
225
|
+
* principle, trigger a follow-on resolution.
|
|
226
|
+
*/
|
|
227
|
+
async whenResolveHooksSettled() {
|
|
228
|
+
while (this.pendingResolveHooks.size > 0) {
|
|
229
|
+
await Promise.allSettled([...this.pendingResolveHooks]);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
207
232
|
};
|
|
208
233
|
|
|
209
234
|
export {
|
|
@@ -211,4 +236,4 @@ export {
|
|
|
211
236
|
resolveNamespaceStorageRoot,
|
|
212
237
|
NamespaceStorageRouter
|
|
213
238
|
};
|
|
214
|
-
//# sourceMappingURL=chunk-
|
|
239
|
+
//# sourceMappingURL=chunk-D7IXTY5E.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/namespaces/storage.ts"],"sourcesContent":["import path from \"node:path\";\nimport { access, lstat, readdir } from \"node:fs/promises\";\nimport { isSafeRouteNamespace } from \"../routing/engine.js\";\nimport { StorageManager } from \"../storage.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\nimport { namespaceIdentityToken, normalizeNamespaceIdentity } from \"./identity.js\";\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function hasStoredEntries(p: string): Promise<boolean> {\n try {\n const entry = await lstat(p);\n if (entry.isSymbolicLink()) return true;\n if (!entry.isDirectory()) return true;\n const children = await readdir(p, { withFileTypes: true });\n for (const child of children) {\n const childPath = path.join(p, child.name);\n if (child.isSymbolicLink() || child.isFile()) return true;\n if (child.isDirectory() && (await hasStoredEntries(childPath))) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n// Build a per-namespace directory under `<memoryDir>/namespaces` and assert the\n// resolved path stays inside that base. Namespace identifiers can originate from\n// operator config (config.defaultNamespace) and request-derived routing, so this\n// containment check prevents directory traversal (CodeQL js/path-injection).\n// For safe segments this returns exactly `path.join(base, segment)`, so there is\n// no behavioral change for valid namespaces.\nfunction resolveNamespaceDir(memoryDir: string, segment: string): string {\n // Mirror isSafeRouteNamespace's separator/parent-ref rejection (without its\n // 64-char cap, so identity tokens still pass). Rejecting separators and \"..\"\n // up front keeps the value a single contained child of <memoryDir>/namespaces.\n if (\n segment.length === 0 ||\n segment.includes(\"/\") ||\n segment.includes(\"\\\\\") ||\n segment.includes(\"..\") ||\n path.isAbsolute(segment)\n ) {\n throw new Error(`unsafe namespace path segment: ${segment}`);\n }\n return path.join(memoryDir, \"namespaces\", segment);\n}\n\nconst LEGACY_NAMESPACE_CONTENT_CHILDREN = [\n ...ALL_CATEGORY_DIRS,\n \"entities\",\n \"artifacts\",\n \"identity\",\n \"config\",\n \"summaries\",\n \"profile.md\",\n] as const;\n\nconst LEGACY_NAMESPACE_RUNTIME_CHILDREN = [\"state\"] as const;\n\nasync function hasAnyLegacyData(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await hasStoredEntries(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\nasync function hasAnyNamespaceStorageMarker(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await exists(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\n/**\n * Storage routing for namespaces.\n *\n * Compatibility note:\n * - When namespaces are enabled, existing raw namespace roots are preserved.\n * New namespace roots use tokenized names under `memoryDir/namespaces/<token>`.\n * - The default namespace continues to use the legacy `memoryDir` root unless the caller\n * has created `memoryDir/namespaces/<defaultNamespace>` (in which case we use that).\n *\n * This avoids surprising \"lost memories\" when an install flips namespaces on without\n * migrating existing data.\n */\n/**\n * Optional hooks for the storage router. `onResolve` fires whenever a namespace's\n * storage is resolved/created, so a downstream consumer (e.g. the namespace\n * catalog, issue #1499) can register the namespace. The hook MUST NOT throw into\n * the router; the router invokes it defensively and a hook failure never affects\n * storage resolution.\n *\n * The hook MAY return (or resolve to) a boolean indicating whether the\n * registration actually PERSISTED (round 6, codex P2 — NEFoX). When it resolves\n * to `false` (a dropped/no-op registration), the router does NOT mark the\n * (namespace, storageDir) pair as notified, so the next resolve RETRIES it\n * instead of suppressing it forever. A `void`/`undefined` result is treated as\n * success (legacy hooks).\n */\nexport interface NamespaceStorageRouterHooks {\n onResolve?: (\n namespace: string,\n storageDir: string,\n ) => void | boolean | Promise<void | boolean>;\n}\n\n/**\n * Resolve the runtime storage root for the configured DEFAULT namespace.\n *\n * Shared between the live router (`NamespaceStorageRouter.defaultNamespaceRoot`)\n * and the rebuildable catalog (`NamespaceCatalog.rebuildFromDisk`) so the two\n * can never diverge (CLAUDE.md rule #22/#42 — read & write paths resolve through\n * the same logic). The contract is: while legacy memory data still lives\n * directly under `memoryDir`, the default root stays `memoryDir`; only once the\n * legacy root is empty and a `namespaces/<default|token>` dir holds data does\n * the default migrate into that tokenized/legacy-named dir.\n */\nexport async function resolveDefaultNamespaceRoot(config: PluginConfig): Promise<string> {\n if (!config.namespacesEnabled) {\n return config.memoryDir;\n }\n\n // Build the legacy default root from the NORMALIZED (trimmed) name so a\n // whitespace-padded `defaultNamespace` still finds the live `namespaces/default`\n // root (NIabe). `storageFor()` classifies the trimmed value as the default, and\n // the on-disk legacy dir is created under the trimmed name; using the raw spaced\n // name here would look for `namespaces/<spaced>` and miss the real root, falling\n // back to memoryDir/tokenized. `namespaceIdentityToken` already normalizes\n // internally, so the tokenized path is unaffected.\n const defaultIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n const legacyNsDir = resolveNamespaceDir(config.memoryDir, defaultIdentity);\n const tokenizedNsDir = resolveNamespaceDir(\n config.memoryDir,\n namespaceIdentityToken(config.defaultNamespace),\n );\n const tokenizedHasData =\n (await exists(tokenizedNsDir)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedNsDir, { includeRuntimeState: true }));\n const nsDir = tokenizedHasData\n ? tokenizedNsDir\n : (await exists(legacyNsDir))\n ? legacyNsDir\n : tokenizedNsDir;\n return (await exists(nsDir)) && !(await hasAnyLegacyData(config.memoryDir))\n ? nsDir\n : config.memoryDir;\n}\n\n/**\n * Resolve the runtime storage root for ANY namespace exactly as the live router\n * would (`NamespaceStorageRouter.namespaceRoot`). Shared so the rebuildable\n * catalog records the SAME on-disk root the router routes to — a recall/read\n * touch must not guess `namespaces/<token>` when the router actually serves a\n * legacy raw-name dir or a migrated default root (CLAUDE.md rule #22/#42; round\n * 4, cursor Medium). The default namespace delegates to `resolveDefaultNamespaceRoot`;\n * every other namespace prefers the tokenized root when it has a storage marker,\n * else a legacy raw-name dir when present, else the tokenized root.\n */\nexport async function resolveNamespaceStorageRoot(\n config: PluginConfig,\n namespace: string,\n): Promise<string> {\n if (!config.namespacesEnabled) return config.memoryDir;\n // Compare on NORMALIZED identity so a whitespace-padded configured default name\n // still routes to the default root rather than a tokenized non-default dir\n // (NH-FH). The catalog keys records by the same normalized identity.\n if (normalizeNamespaceIdentity(namespace) === normalizeNamespaceIdentity(config.defaultNamespace)) {\n return resolveDefaultNamespaceRoot(config);\n }\n const legacyRoot = resolveNamespaceDir(config.memoryDir, namespace);\n const tokenizedRoot = resolveNamespaceDir(config.memoryDir, namespaceIdentityToken(namespace));\n if (\n (await exists(tokenizedRoot)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedRoot, { includeRuntimeState: true }))\n ) {\n return tokenizedRoot;\n }\n return (await exists(legacyRoot)) ? legacyRoot : tokenizedRoot;\n}\n\nexport class NamespaceStorageRouter {\n private readonly cache = new Map<string, StorageManager>();\n private defaultNsRootResolved: string | null = null;\n // Dedup the resolve hook (round 6, cursor Medium — NCNL2). Recall/extraction\n // call `storageFor` repeatedly; firing `onResolve` (→ catalog loadCompacted +\n // append) on every cache hit grows `namespaces.jsonl` without bound between\n // rebuilds. We fire the hook only when the (namespace, storageDir) pair is new\n // or its dir changed, so a steady-state cache hit is a no-op for the catalog.\n private readonly notifiedResolved = new Map<string, string>();\n // In-flight resolve-hook dedup (NFJV-, codex P2). The catalog's `onResolve`\n // hook is ASYNC (it returns `registerResolved(...)`), so `notifiedResolved` is\n // only set after the hook's promise SETTLES. Without tracking the in-flight\n // window, a burst of `storageFor()` cache hits for the SAME namespace before\n // the first registration finishes would each pass the `notifiedResolved` guard\n // and fire their OWN `onResolve` — queueing N duplicate catalog touches + lock\n // acquisitions despite the once-per-namespace intent. We therefore record the\n // (namespace → storageDir) being registered BEFORE awaiting the hook so a\n // concurrent call for the same pair skips firing. On SUCCESS the pair is\n // promoted to `notifiedResolved` (future calls skip permanently); on `false`\n // (dropped touch — e.g. rebuild-lock timeout) OR rejection the in-flight marker\n // is CLEARED so a later `storageFor()` can RETRY the dropped registration. The\n // entry is always removed when the promise settles, so the map cannot grow\n // unbounded (one transient entry per concurrently-resolving namespace).\n private readonly inFlightResolved = new Map<string, string>();\n // Tracks every in-flight resolve-hook promise so callers can deterministically\n // await the fire-and-forget registrations that `storageFor()` kicks off (see\n // `whenResolveHooksSettled`). Entries are removed as each hook settles, so the\n // set holds at most one promise per concurrently-resolving namespace.\n private readonly pendingResolveHooks = new Set<Promise<unknown>>();\n\n // Normalized (trimmed) default namespace identity (NH-FH). `storageFor`\n // normalizes its input, so default-namespace branches must compare against the\n // normalized config default too — otherwise a whitespace-padded configured\n // default name routes the default namespace to a tokenized non-default root.\n private readonly defaultNamespaceIdentity: string;\n\n constructor(\n private readonly config: PluginConfig,\n private readonly hooks: NamespaceStorageRouterHooks = {},\n ) {\n this.defaultNamespaceIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n }\n\n private async defaultNamespaceRoot(): Promise<string> {\n this.defaultNsRootResolved = await resolveDefaultNamespaceRoot(this.config);\n return this.defaultNsRootResolved;\n }\n\n private async namespaceRoot(namespace: string): Promise<string> {\n // NOTE: only used after defaultNamespaceRoot() resolution.\n if (!this.config.namespacesEnabled) return this.config.memoryDir;\n if (normalizeNamespaceIdentity(namespace) === this.defaultNamespaceIdentity) {\n return this.defaultNsRootResolved ?? this.config.memoryDir;\n }\n return resolveNamespaceStorageRoot(this.config, namespace);\n }\n\n async storageFor(namespace: string): Promise<StorageManager> {\n const ns = normalizeNamespaceIdentity(namespace || this.config.defaultNamespace);\n if (ns !== this.defaultNamespaceIdentity && !isSafeRouteNamespace(ns)) {\n throw new Error(`unsafe namespace: ${ns}`);\n }\n // Even when the default namespace is exempt from the check above, every\n // on-disk path is built through resolveNamespaceDir(), which rejects\n // traversal segments — so an unsafe configured default still cannot escape\n // <memoryDir>/namespaces (CodeQL js/path-injection).\n\n let root: string;\n if (ns === this.defaultNamespaceIdentity) {\n root = await this.defaultNamespaceRoot();\n const cached = this.cache.get(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n } else {\n const cached = this.cache.get(ns);\n root = await this.namespaceRoot(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n }\n\n const sm = new StorageManager(root, this.config.entitySchemas);\n // Propagate the inline-attribution template so that router-created storages\n // (used by extraction and shared-promotion paths) strip citations consistently,\n // matching the behaviour of the primary this.storage instance in the orchestrator.\n sm.citationTemplate = this.config.inlineSourceAttributionFormat;\n this.cache.set(ns, sm);\n this.notifyResolved(ns, root);\n return sm;\n }\n\n /**\n * Fire the resolve hook defensively. A hook failure (e.g. a catalog write\n * error) MUST NOT crash storage resolution — see CLAUDE.md gotcha #13.\n */\n private notifyResolved(namespace: string, storageDir: string): void {\n const hook = this.hooks.onResolve;\n if (!hook) return;\n // Skip when we've already SUCCESSFULLY notified this exact (namespace,\n // storageDir) — a steady-state cache hit must not re-append to the catalog\n // log (NCNL2). A changed dir (rare: migration/realignment) still re-fires\n // once. We mark the pair as notified ONLY AFTER the hook succeeds, and CLEAR\n // it on failure, so a dropped registration (e.g. rebuild-lock timeout) is\n // RETRIED on the next cache hit instead of being suppressed forever (round 6,\n // cursor Medium — ND3EJ).\n if (this.notifiedResolved.get(namespace) === storageDir) return;\n // In-flight dedup (NFJV-, codex P2): if a registration for this exact\n // (namespace, storageDir) is already AWAITING its async hook, do not fire a\n // second one. Without this, concurrent cache-hit bursts before the first\n // append settles each pass the `notifiedResolved` guard above and queue\n // duplicate catalog touches/lock acquisitions. A pair with a DIFFERENT\n // in-flight dir (rare mid-migration realignment) still fires once.\n if (this.inFlightResolved.get(namespace) === storageDir) return;\n try {\n // Handle BOTH synchronous throws and asynchronous rejections (round 6,\n // codex P2 — NDo8C). The hook may be `async`; its rejected promise would\n // bypass this try/catch and, where unhandled rejections are fatal, crash\n // storage resolution. Mark the dedup pair as notified ONLY when the hook\n // resolves to a PERSISTED result (round 6, codex P2 — NEFoX): a result of\n // `false` means the registration was dropped/no-op (e.g. rebuild-lock\n // timeout), so we must NOT suppress its retry. `void`/`undefined` is treated\n // as success for legacy hooks. On rejection we leave it un-notified to retry.\n //\n // Record the in-flight marker BEFORE awaiting so concurrent calls for the\n // same pair skip (NFJV-). It is always cleared once the promise settles, so\n // the map holds at most one transient entry per concurrently-resolving\n // namespace and cannot grow unbounded.\n this.inFlightResolved.set(namespace, storageDir);\n const hookResult = Promise.resolve(hook(namespace, storageDir));\n // Track the in-flight promise so `whenResolveHooksSettled()` can await it.\n this.pendingResolveHooks.add(hookResult);\n hookResult.then(\n (persisted) => {\n // Clear the in-flight marker ONLY if it is still ours (a newer resolve\n // for a different dir may have replaced it).\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (persisted !== false) {\n this.notifiedResolved.set(namespace, storageDir);\n }\n // On `false` (dropped touch) we intentionally do NOT mark notified, so\n // a later `storageFor()` retries the registration. Clearing the\n // in-flight marker above is what re-enables that retry.\n this.pendingResolveHooks.delete(hookResult);\n },\n () => {\n // Registration failed — clear in-flight AND do NOT mark as notified, so\n // it is retried on the next cache hit.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (this.notifiedResolved.get(namespace) === storageDir) {\n this.notifiedResolved.delete(namespace);\n }\n this.pendingResolveHooks.delete(hookResult);\n },\n );\n } catch {\n // Synchronous throw: clear any in-flight marker we just set and leave the\n // pair un-notified so a later resolve retries.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n }\n }\n\n /**\n * Resolve once every in-flight `onResolve` registration has settled.\n *\n * `storageFor()` fires the resolve hook fire-and-forget, so its catalog side\n * effect (e.g. `registerResolved(...)`) is not observable the moment\n * `storageFor()` returns. Callers that must act on that side effect — notably\n * tests asserting the catalog was updated — should await this instead of\n * racing a timer. Resolves immediately when no hook is registered or nothing\n * is in flight. The loop re-checks because a settling hook could, in\n * principle, trigger a follow-on resolution.\n */\n async whenResolveHooksSettled(): Promise<void> {\n while (this.pendingResolveHooks.size > 0) {\n await Promise.allSettled([...this.pendingResolveHooks]);\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -236,7 +236,7 @@ import {
|
|
|
236
236
|
NamespaceStorageRouter,
|
|
237
237
|
resolveDefaultNamespaceRoot,
|
|
238
238
|
resolveNamespaceStorageRoot
|
|
239
|
-
} from "./chunk-
|
|
239
|
+
} from "./chunk-D7IXTY5E.js";
|
|
240
240
|
import {
|
|
241
241
|
isAboveImportanceThreshold,
|
|
242
242
|
scoreImportance
|
|
@@ -17357,4 +17357,4 @@ export {
|
|
|
17357
17357
|
resolvePersistedMemoryRelativePath,
|
|
17358
17358
|
Orchestrator
|
|
17359
17359
|
};
|
|
17360
|
-
//# sourceMappingURL=chunk-
|
|
17360
|
+
//# sourceMappingURL=chunk-WH4SKYPX.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
listNamespaces
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-7C4MPEPE.js";
|
|
4
4
|
import {
|
|
5
5
|
runConsolidationProvenanceCheck
|
|
6
6
|
} from "./chunk-7XH7VJN4.js";
|
|
@@ -1336,4 +1336,4 @@ export {
|
|
|
1336
1336
|
runBenchmarkRecall,
|
|
1337
1337
|
runOperatorRepair
|
|
1338
1338
|
};
|
|
1339
|
-
//# sourceMappingURL=chunk-
|
|
1339
|
+
//# sourceMappingURL=chunk-XRSIGVTS.js.map
|
package/dist/cli.js
CHANGED
|
@@ -90,7 +90,7 @@ import {
|
|
|
90
90
|
runWorkProductStatusCliCommand,
|
|
91
91
|
runWorkProjectCliCommand,
|
|
92
92
|
runWorkTaskCliCommand
|
|
93
|
-
} from "./chunk-
|
|
93
|
+
} from "./chunk-2OPARZ4B.js";
|
|
94
94
|
import "./chunk-MC4FJXPA.js";
|
|
95
95
|
import "./chunk-LQHDIS7L.js";
|
|
96
96
|
import "./chunk-7F7Z6MOS.js";
|
|
@@ -123,8 +123,8 @@ import "./chunk-IHG6CC7T.js";
|
|
|
123
123
|
import "./chunk-TGQ2NTWH.js";
|
|
124
124
|
import "./chunk-PEPHBH2W.js";
|
|
125
125
|
import "./chunk-SXYCVRLK.js";
|
|
126
|
-
import "./chunk-
|
|
127
|
-
import "./chunk-
|
|
126
|
+
import "./chunk-XRSIGVTS.js";
|
|
127
|
+
import "./chunk-7C4MPEPE.js";
|
|
128
128
|
import "./chunk-3T74IZB3.js";
|
|
129
129
|
import "./chunk-HL4DB7TO.js";
|
|
130
130
|
import "./chunk-YNDLCWXS.js";
|
|
@@ -145,7 +145,7 @@ import "./chunk-AGRPGAKR.js";
|
|
|
145
145
|
import "./chunk-S4DDLTPX.js";
|
|
146
146
|
import "./chunk-SFQ6QNL7.js";
|
|
147
147
|
import "./chunk-33JBK2XP.js";
|
|
148
|
-
import "./chunk-
|
|
148
|
+
import "./chunk-D7IXTY5E.js";
|
|
149
149
|
import "./chunk-KFY3SGN7.js";
|
|
150
150
|
import "./chunk-CMTINOFS.js";
|
|
151
151
|
import "./chunk-TQNRI55H.js";
|
package/dist/index.js
CHANGED
|
@@ -94,7 +94,7 @@ import {
|
|
|
94
94
|
registerTrainingExportAdapter,
|
|
95
95
|
runBulkImportCliCommand,
|
|
96
96
|
runWearablesCliCommand
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-2OPARZ4B.js";
|
|
98
98
|
import "./chunk-MC4FJXPA.js";
|
|
99
99
|
import "./chunk-LQHDIS7L.js";
|
|
100
100
|
import "./chunk-7F7Z6MOS.js";
|
|
@@ -147,8 +147,8 @@ import {
|
|
|
147
147
|
parseXrayBudgetFlag,
|
|
148
148
|
parseXrayCliOptions
|
|
149
149
|
} from "./chunk-SXYCVRLK.js";
|
|
150
|
-
import "./chunk-
|
|
151
|
-
import "./chunk-
|
|
150
|
+
import "./chunk-XRSIGVTS.js";
|
|
151
|
+
import "./chunk-7C4MPEPE.js";
|
|
152
152
|
import {
|
|
153
153
|
parseStrictCliDate
|
|
154
154
|
} from "./chunk-3T74IZB3.js";
|
|
@@ -192,7 +192,7 @@ import {
|
|
|
192
192
|
saveTaxonomy,
|
|
193
193
|
validateSlug,
|
|
194
194
|
validateTaxonomy
|
|
195
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-WH4SKYPX.js";
|
|
196
196
|
import {
|
|
197
197
|
WEARABLE_SOURCE_PREFIX,
|
|
198
198
|
buildExtractionTurns,
|
|
@@ -399,7 +399,7 @@ import {
|
|
|
399
399
|
} from "./chunk-S4DDLTPX.js";
|
|
400
400
|
import "./chunk-SFQ6QNL7.js";
|
|
401
401
|
import "./chunk-33JBK2XP.js";
|
|
402
|
-
import "./chunk-
|
|
402
|
+
import "./chunk-D7IXTY5E.js";
|
|
403
403
|
import "./chunk-KFY3SGN7.js";
|
|
404
404
|
import {
|
|
405
405
|
resolvePluginEntry
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
listNamespaces,
|
|
3
3
|
runNamespaceMigration,
|
|
4
4
|
verifyNamespaces
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-7C4MPEPE.js";
|
|
6
|
+
import "../chunk-D7IXTY5E.js";
|
|
7
7
|
import "../chunk-DQY7NJ5L.js";
|
|
8
8
|
import "../chunk-ROHLEUTH.js";
|
|
9
9
|
import "../chunk-DOCTITOP.js";
|
|
@@ -68,6 +68,7 @@ declare class NamespaceStorageRouter {
|
|
|
68
68
|
private defaultNsRootResolved;
|
|
69
69
|
private readonly notifiedResolved;
|
|
70
70
|
private readonly inFlightResolved;
|
|
71
|
+
private readonly pendingResolveHooks;
|
|
71
72
|
private readonly defaultNamespaceIdentity;
|
|
72
73
|
constructor(config: PluginConfig, hooks?: NamespaceStorageRouterHooks);
|
|
73
74
|
private defaultNamespaceRoot;
|
|
@@ -78,6 +79,18 @@ declare class NamespaceStorageRouter {
|
|
|
78
79
|
* error) MUST NOT crash storage resolution — see CLAUDE.md gotcha #13.
|
|
79
80
|
*/
|
|
80
81
|
private notifyResolved;
|
|
82
|
+
/**
|
|
83
|
+
* Resolve once every in-flight `onResolve` registration has settled.
|
|
84
|
+
*
|
|
85
|
+
* `storageFor()` fires the resolve hook fire-and-forget, so its catalog side
|
|
86
|
+
* effect (e.g. `registerResolved(...)`) is not observable the moment
|
|
87
|
+
* `storageFor()` returns. Callers that must act on that side effect — notably
|
|
88
|
+
* tests asserting the catalog was updated — should await this instead of
|
|
89
|
+
* racing a timer. Resolves immediately when no hook is registered or nothing
|
|
90
|
+
* is in flight. The loop re-checks because a settling hook could, in
|
|
91
|
+
* principle, trigger a follow-on resolution.
|
|
92
|
+
*/
|
|
93
|
+
whenResolveHooksSettled(): Promise<void>;
|
|
81
94
|
}
|
|
82
95
|
|
|
83
96
|
export { NamespaceStorageRouter, type NamespaceStorageRouterHooks, resolveDefaultNamespaceRoot, resolveNamespaceStorageRoot };
|
package/dist/operator-toolkit.js
CHANGED
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
summarizeMemoryWorthLegacyCounters,
|
|
12
12
|
summarizeObservationThroughput,
|
|
13
13
|
summarizeTierDistribution
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-XRSIGVTS.js";
|
|
15
|
+
import "./chunk-7C4MPEPE.js";
|
|
16
16
|
import "./chunk-7XH7VJN4.js";
|
|
17
17
|
import "./chunk-YBPYIAA5.js";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-D7IXTY5E.js";
|
|
19
19
|
import "./chunk-KFY3SGN7.js";
|
|
20
20
|
import "./chunk-CMTINOFS.js";
|
|
21
21
|
import "./chunk-BEUDU7Y4.js";
|
package/dist/orchestrator.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
sanitizeSessionKeyForFilename,
|
|
29
29
|
shouldFilterLifecycleRecallCandidate,
|
|
30
30
|
summarizeGraphShadowComparison
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-WH4SKYPX.js";
|
|
32
32
|
import "./chunk-4SKKVWLQ.js";
|
|
33
33
|
import "./chunk-7HYPN2GC.js";
|
|
34
34
|
import "./chunk-666A3MOW.js";
|
|
@@ -111,7 +111,7 @@ import "./chunk-AGRPGAKR.js";
|
|
|
111
111
|
import "./chunk-S4DDLTPX.js";
|
|
112
112
|
import "./chunk-SFQ6QNL7.js";
|
|
113
113
|
import "./chunk-33JBK2XP.js";
|
|
114
|
-
import "./chunk-
|
|
114
|
+
import "./chunk-D7IXTY5E.js";
|
|
115
115
|
import "./chunk-KFY3SGN7.js";
|
|
116
116
|
import "./chunk-TQNRI55H.js";
|
|
117
117
|
import "./chunk-6GUG4YNM.js";
|
package/dist/schemas.d.ts
CHANGED
|
@@ -7,13 +7,13 @@ declare const MemoryActionEligibilityContextSchema: z.ZodObject<{
|
|
|
7
7
|
importance: z.ZodNumber;
|
|
8
8
|
source: z.ZodEnum<["extraction", "consolidation", "replay", "manual", "unknown"]>;
|
|
9
9
|
}, "strict", z.ZodTypeAny, {
|
|
10
|
-
source: "manual" | "extraction" | "consolidation" | "replay" | "unknown";
|
|
11
10
|
confidence: number;
|
|
11
|
+
source: "unknown" | "manual" | "extraction" | "consolidation" | "replay";
|
|
12
12
|
lifecycleState: "active" | "archived" | "candidate" | "validated" | "stale";
|
|
13
13
|
importance: number;
|
|
14
14
|
}, {
|
|
15
|
-
source: "manual" | "extraction" | "consolidation" | "replay" | "unknown";
|
|
16
15
|
confidence: number;
|
|
16
|
+
source: "unknown" | "manual" | "extraction" | "consolidation" | "replay";
|
|
17
17
|
lifecycleState: "active" | "archived" | "candidate" | "validated" | "stale";
|
|
18
18
|
importance: number;
|
|
19
19
|
}>;
|
|
@@ -149,10 +149,10 @@ declare const ExtractedFactSchema: z.ZodEffects<z.ZodObject<{
|
|
|
149
149
|
observed_outcome?: string | null | undefined;
|
|
150
150
|
}>>>;
|
|
151
151
|
}, "strip", z.ZodTypeAny, {
|
|
152
|
-
tags: string[];
|
|
153
|
-
content: string;
|
|
154
152
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
153
|
+
content: string;
|
|
155
154
|
confidence: number;
|
|
155
|
+
tags: string[];
|
|
156
156
|
entityRef?: string | null | undefined;
|
|
157
157
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
158
158
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -178,10 +178,10 @@ declare const ExtractedFactSchema: z.ZodEffects<z.ZodObject<{
|
|
|
178
178
|
observed_outcome?: string | null | undefined;
|
|
179
179
|
} | null | undefined;
|
|
180
180
|
}, {
|
|
181
|
-
tags: string[];
|
|
182
|
-
content: string;
|
|
183
181
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
182
|
+
content: string;
|
|
184
183
|
confidence: number;
|
|
184
|
+
tags: string[];
|
|
185
185
|
entityRef?: string | null | undefined;
|
|
186
186
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
187
187
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -207,10 +207,10 @@ declare const ExtractedFactSchema: z.ZodEffects<z.ZodObject<{
|
|
|
207
207
|
observed_outcome?: string | null | undefined;
|
|
208
208
|
} | null | undefined;
|
|
209
209
|
}>, {
|
|
210
|
-
tags: string[];
|
|
211
|
-
content: string;
|
|
212
210
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
211
|
+
content: string;
|
|
213
212
|
confidence: number;
|
|
213
|
+
tags: string[];
|
|
214
214
|
entityRef?: string | null | undefined;
|
|
215
215
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
216
216
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -236,10 +236,10 @@ declare const ExtractedFactSchema: z.ZodEffects<z.ZodObject<{
|
|
|
236
236
|
observed_outcome?: string | null | undefined;
|
|
237
237
|
} | null | undefined;
|
|
238
238
|
}, {
|
|
239
|
-
tags: string[];
|
|
240
|
-
content: string;
|
|
241
239
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
240
|
+
content: string;
|
|
242
241
|
confidence: number;
|
|
242
|
+
tags: string[];
|
|
243
243
|
entityRef?: string | null | undefined;
|
|
244
244
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
245
245
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -457,10 +457,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
457
457
|
observed_outcome?: string | null | undefined;
|
|
458
458
|
}>>>;
|
|
459
459
|
}, "strip", z.ZodTypeAny, {
|
|
460
|
-
tags: string[];
|
|
461
|
-
content: string;
|
|
462
460
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
461
|
+
content: string;
|
|
463
462
|
confidence: number;
|
|
463
|
+
tags: string[];
|
|
464
464
|
entityRef?: string | null | undefined;
|
|
465
465
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
466
466
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -486,10 +486,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
486
486
|
observed_outcome?: string | null | undefined;
|
|
487
487
|
} | null | undefined;
|
|
488
488
|
}, {
|
|
489
|
-
tags: string[];
|
|
490
|
-
content: string;
|
|
491
489
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
490
|
+
content: string;
|
|
492
491
|
confidence: number;
|
|
492
|
+
tags: string[];
|
|
493
493
|
entityRef?: string | null | undefined;
|
|
494
494
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
495
495
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -515,10 +515,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
515
515
|
observed_outcome?: string | null | undefined;
|
|
516
516
|
} | null | undefined;
|
|
517
517
|
}>, {
|
|
518
|
-
tags: string[];
|
|
519
|
-
content: string;
|
|
520
518
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
519
|
+
content: string;
|
|
521
520
|
confidence: number;
|
|
521
|
+
tags: string[];
|
|
522
522
|
entityRef?: string | null | undefined;
|
|
523
523
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
524
524
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -544,10 +544,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
544
544
|
observed_outcome?: string | null | undefined;
|
|
545
545
|
} | null | undefined;
|
|
546
546
|
}, {
|
|
547
|
-
tags: string[];
|
|
548
|
-
content: string;
|
|
549
547
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
548
|
+
content: string;
|
|
550
549
|
confidence: number;
|
|
550
|
+
tags: string[];
|
|
551
551
|
entityRef?: string | null | undefined;
|
|
552
552
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
553
553
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -631,10 +631,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
631
631
|
}>, "many">>>;
|
|
632
632
|
}, "strip", z.ZodTypeAny, {
|
|
633
633
|
facts: {
|
|
634
|
-
tags: string[];
|
|
635
|
-
content: string;
|
|
636
634
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
635
|
+
content: string;
|
|
637
636
|
confidence: number;
|
|
637
|
+
tags: string[];
|
|
638
638
|
entityRef?: string | null | undefined;
|
|
639
639
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
640
640
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -680,10 +680,10 @@ declare const ProactiveExtractionResultSchema: z.ZodObject<{
|
|
|
680
680
|
}[] | null | undefined;
|
|
681
681
|
}, {
|
|
682
682
|
facts: {
|
|
683
|
-
tags: string[];
|
|
684
|
-
content: string;
|
|
685
683
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
684
|
+
content: string;
|
|
686
685
|
confidence: number;
|
|
686
|
+
tags: string[];
|
|
687
687
|
entityRef?: string | null | undefined;
|
|
688
688
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
689
689
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -825,10 +825,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
825
825
|
observed_outcome?: string | null | undefined;
|
|
826
826
|
}>>>;
|
|
827
827
|
}, "strip", z.ZodTypeAny, {
|
|
828
|
-
tags: string[];
|
|
829
|
-
content: string;
|
|
830
828
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
829
|
+
content: string;
|
|
831
830
|
confidence: number;
|
|
831
|
+
tags: string[];
|
|
832
832
|
entityRef?: string | null | undefined;
|
|
833
833
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
834
834
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -854,10 +854,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
854
854
|
observed_outcome?: string | null | undefined;
|
|
855
855
|
} | null | undefined;
|
|
856
856
|
}, {
|
|
857
|
-
tags: string[];
|
|
858
|
-
content: string;
|
|
859
857
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
858
|
+
content: string;
|
|
860
859
|
confidence: number;
|
|
860
|
+
tags: string[];
|
|
861
861
|
entityRef?: string | null | undefined;
|
|
862
862
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
863
863
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -883,10 +883,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
883
883
|
observed_outcome?: string | null | undefined;
|
|
884
884
|
} | null | undefined;
|
|
885
885
|
}>, {
|
|
886
|
-
tags: string[];
|
|
887
|
-
content: string;
|
|
888
886
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
887
|
+
content: string;
|
|
889
888
|
confidence: number;
|
|
889
|
+
tags: string[];
|
|
890
890
|
entityRef?: string | null | undefined;
|
|
891
891
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
892
892
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -912,10 +912,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
912
912
|
observed_outcome?: string | null | undefined;
|
|
913
913
|
} | null | undefined;
|
|
914
914
|
}, {
|
|
915
|
-
tags: string[];
|
|
916
|
-
content: string;
|
|
917
915
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
916
|
+
content: string;
|
|
918
917
|
confidence: number;
|
|
918
|
+
tags: string[];
|
|
919
919
|
entityRef?: string | null | undefined;
|
|
920
920
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
921
921
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -1013,10 +1013,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
1013
1013
|
}>, "many">>>;
|
|
1014
1014
|
}, "strip", z.ZodTypeAny, {
|
|
1015
1015
|
facts: {
|
|
1016
|
-
tags: string[];
|
|
1017
|
-
content: string;
|
|
1018
1016
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
1017
|
+
content: string;
|
|
1019
1018
|
confidence: number;
|
|
1019
|
+
tags: string[];
|
|
1020
1020
|
entityRef?: string | null | undefined;
|
|
1021
1021
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
1022
1022
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -1068,10 +1068,10 @@ declare const ExtractionResultSchema: z.ZodObject<{
|
|
|
1068
1068
|
identityReflection?: string | null | undefined;
|
|
1069
1069
|
}, {
|
|
1070
1070
|
facts: {
|
|
1071
|
-
tags: string[];
|
|
1072
|
-
content: string;
|
|
1073
1071
|
category: "fact" | "preference" | "correction" | "entity" | "decision" | "relationship" | "principle" | "commitment" | "moment" | "skill" | "rule" | "procedure" | "reasoning_trace";
|
|
1072
|
+
content: string;
|
|
1074
1073
|
confidence: number;
|
|
1074
|
+
tags: string[];
|
|
1075
1075
|
entityRef?: string | null | undefined;
|
|
1076
1076
|
structuredAttributes?: Record<string, string> | null | undefined;
|
|
1077
1077
|
promptedByQuestion?: string | null | undefined;
|
|
@@ -1285,13 +1285,13 @@ declare const ContradictionVerificationSchema: z.ZodObject<{
|
|
|
1285
1285
|
reasoning: z.ZodString;
|
|
1286
1286
|
whichIsNewer: z.ZodEnum<["first", "second", "unclear"]>;
|
|
1287
1287
|
}, "strip", z.ZodTypeAny, {
|
|
1288
|
-
reasoning: string;
|
|
1289
1288
|
confidence: number;
|
|
1289
|
+
reasoning: string;
|
|
1290
1290
|
isContradiction: boolean;
|
|
1291
1291
|
whichIsNewer: "second" | "first" | "unclear";
|
|
1292
1292
|
}, {
|
|
1293
|
-
reasoning: string;
|
|
1294
1293
|
confidence: number;
|
|
1294
|
+
reasoning: string;
|
|
1295
1295
|
isContradiction: boolean;
|
|
1296
1296
|
whichIsNewer: "second" | "first" | "unclear";
|
|
1297
1297
|
}>;
|
|
@@ -1386,8 +1386,8 @@ declare const BehaviorLoopAdjustmentSchema: z.ZodObject<{
|
|
|
1386
1386
|
reason: z.ZodString;
|
|
1387
1387
|
appliedAt: z.ZodString;
|
|
1388
1388
|
}, "strip", z.ZodTypeAny, {
|
|
1389
|
-
reason: string;
|
|
1390
1389
|
confidence: number;
|
|
1390
|
+
reason: string;
|
|
1391
1391
|
parameter: string;
|
|
1392
1392
|
previousValue: number;
|
|
1393
1393
|
nextValue: number;
|
|
@@ -1395,8 +1395,8 @@ declare const BehaviorLoopAdjustmentSchema: z.ZodObject<{
|
|
|
1395
1395
|
evidenceCount: number;
|
|
1396
1396
|
appliedAt: string;
|
|
1397
1397
|
}, {
|
|
1398
|
-
reason: string;
|
|
1399
1398
|
confidence: number;
|
|
1399
|
+
reason: string;
|
|
1400
1400
|
parameter: string;
|
|
1401
1401
|
previousValue: number;
|
|
1402
1402
|
nextValue: number;
|
|
@@ -1420,8 +1420,8 @@ declare const BehaviorLoopPolicyStateSchema: z.ZodObject<{
|
|
|
1420
1420
|
reason: z.ZodString;
|
|
1421
1421
|
appliedAt: z.ZodString;
|
|
1422
1422
|
}, "strip", z.ZodTypeAny, {
|
|
1423
|
-
reason: string;
|
|
1424
1423
|
confidence: number;
|
|
1424
|
+
reason: string;
|
|
1425
1425
|
parameter: string;
|
|
1426
1426
|
previousValue: number;
|
|
1427
1427
|
nextValue: number;
|
|
@@ -1429,8 +1429,8 @@ declare const BehaviorLoopPolicyStateSchema: z.ZodObject<{
|
|
|
1429
1429
|
evidenceCount: number;
|
|
1430
1430
|
appliedAt: string;
|
|
1431
1431
|
}, {
|
|
1432
|
-
reason: string;
|
|
1433
1432
|
confidence: number;
|
|
1433
|
+
reason: string;
|
|
1434
1434
|
parameter: string;
|
|
1435
1435
|
previousValue: number;
|
|
1436
1436
|
nextValue: number;
|
|
@@ -1447,8 +1447,8 @@ declare const BehaviorLoopPolicyStateSchema: z.ZodObject<{
|
|
|
1447
1447
|
maxDeltaPerCycle: number;
|
|
1448
1448
|
protectedParams: string[];
|
|
1449
1449
|
adjustments: {
|
|
1450
|
-
reason: string;
|
|
1451
1450
|
confidence: number;
|
|
1451
|
+
reason: string;
|
|
1452
1452
|
parameter: string;
|
|
1453
1453
|
previousValue: number;
|
|
1454
1454
|
nextValue: number;
|
|
@@ -1464,8 +1464,8 @@ declare const BehaviorLoopPolicyStateSchema: z.ZodObject<{
|
|
|
1464
1464
|
maxDeltaPerCycle: number;
|
|
1465
1465
|
protectedParams: string[];
|
|
1466
1466
|
adjustments: {
|
|
1467
|
-
reason: string;
|
|
1468
1467
|
confidence: number;
|
|
1468
|
+
reason: string;
|
|
1469
1469
|
parameter: string;
|
|
1470
1470
|
previousValue: number;
|
|
1471
1471
|
nextValue: number;
|
|
@@ -22,9 +22,9 @@ declare const SharedFeedbackEntrySchema: z.ZodObject<{
|
|
|
22
22
|
date: string;
|
|
23
23
|
agent: string;
|
|
24
24
|
reason: string;
|
|
25
|
+
confidence?: number | undefined;
|
|
25
26
|
workflow?: string | undefined;
|
|
26
27
|
tags?: string[] | undefined;
|
|
27
|
-
confidence?: number | undefined;
|
|
28
28
|
severity?: "high" | "low" | "medium" | undefined;
|
|
29
29
|
outcome?: string | undefined;
|
|
30
30
|
refs?: string[] | undefined;
|
|
@@ -36,9 +36,9 @@ declare const SharedFeedbackEntrySchema: z.ZodObject<{
|
|
|
36
36
|
date: string;
|
|
37
37
|
agent: string;
|
|
38
38
|
reason: string;
|
|
39
|
+
confidence?: number | undefined;
|
|
39
40
|
workflow?: string | undefined;
|
|
40
41
|
tags?: string[] | undefined;
|
|
41
|
-
confidence?: number | undefined;
|
|
42
42
|
severity?: "high" | "low" | "medium" | undefined;
|
|
43
43
|
outcome?: string | undefined;
|
|
44
44
|
refs?: string[] | undefined;
|
package/package.json
CHANGED
|
@@ -487,13 +487,13 @@ test("StorageRouter integration: catalog registers namespace on storageFor", asy
|
|
|
487
487
|
const config = makeConfig(memoryDir);
|
|
488
488
|
const catalog = new NamespaceCatalog(config);
|
|
489
489
|
const router = new NamespaceStorageRouter(config, {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
490
|
+
// Return the registration promise so the router tracks it as in-flight and
|
|
491
|
+
// `whenResolveHooksSettled()` can await it deterministically (no timer race).
|
|
492
|
+
onResolve: (namespace, storageDir) => catalog.registerResolved(namespace, storageDir),
|
|
493
493
|
});
|
|
494
494
|
await router.storageFor("project-origin-abc123");
|
|
495
|
-
//
|
|
496
|
-
await
|
|
495
|
+
// Deterministically await the fire-and-forget registration instead of sleeping.
|
|
496
|
+
await router.whenResolveHooksSettled();
|
|
497
497
|
|
|
498
498
|
const record = await catalog.getNamespaceRecord("project-origin-abc123");
|
|
499
499
|
assert.ok(record, "storageFor should have registered the namespace");
|
|
@@ -2523,8 +2523,8 @@ test("an async onResolve hook rejection does not crash storage resolution", asyn
|
|
|
2523
2523
|
// Must not throw or produce an unhandled rejection that fails the test.
|
|
2524
2524
|
const sm = await router.storageFor("default");
|
|
2525
2525
|
assert.ok(sm, "storage resolution succeeds despite a rejecting async hook");
|
|
2526
|
-
//
|
|
2527
|
-
await
|
|
2526
|
+
// Deterministically await the swallowed rejection instead of sleeping.
|
|
2527
|
+
await router.whenResolveHooksSettled();
|
|
2528
2528
|
assert.ok(called >= 1, "the async hook was invoked");
|
|
2529
2529
|
} finally {
|
|
2530
2530
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -2564,7 +2564,7 @@ test("concurrent storageFor() for one namespace fires the resolve hook ONCE whil
|
|
|
2564
2564
|
// Let the in-flight registration settle, then a steady-state cache hit must
|
|
2565
2565
|
// still be a catalog no-op (now deduped via notifiedResolved).
|
|
2566
2566
|
release();
|
|
2567
|
-
await
|
|
2567
|
+
await router.whenResolveHooksSettled();
|
|
2568
2568
|
await router.storageFor("project-origin-inflight");
|
|
2569
2569
|
assert.equal(calls, 1, "a steady-state cache hit after settle must not re-fire the hook");
|
|
2570
2570
|
} finally {
|
|
@@ -2589,20 +2589,20 @@ test("a dropped resolve registration (hook returns false) is retried on a later
|
|
|
2589
2589
|
});
|
|
2590
2590
|
|
|
2591
2591
|
await router.storageFor("project-origin-retry");
|
|
2592
|
-
//
|
|
2593
|
-
await
|
|
2592
|
+
// Deterministically await the async hook so the in-flight marker is cleared.
|
|
2593
|
+
await router.whenResolveHooksSettled();
|
|
2594
2594
|
assert.equal(calls, 1, "the hook fired once for the dropped registration");
|
|
2595
2595
|
|
|
2596
2596
|
// Now the registration will succeed; a later resolve must RETRY (not be
|
|
2597
2597
|
// suppressed by a stale in-flight/notified marker from the dropped attempt).
|
|
2598
2598
|
result = undefined; // success (legacy void)
|
|
2599
2599
|
await router.storageFor("project-origin-retry");
|
|
2600
|
-
await
|
|
2600
|
+
await router.whenResolveHooksSettled();
|
|
2601
2601
|
assert.equal(calls, 2, "a dropped registration must be retried on the next storageFor()");
|
|
2602
2602
|
|
|
2603
2603
|
// After a SUCCESSFUL registration, further cache hits are deduped (no retry).
|
|
2604
2604
|
await router.storageFor("project-origin-retry");
|
|
2605
|
-
await
|
|
2605
|
+
await router.whenResolveHooksSettled();
|
|
2606
2606
|
assert.equal(calls, 2, "a successful registration is not re-fired on subsequent cache hits");
|
|
2607
2607
|
} finally {
|
|
2608
2608
|
await rm(memoryDir, { recursive: true, force: true });
|
|
@@ -223,6 +223,11 @@ export class NamespaceStorageRouter {
|
|
|
223
223
|
// entry is always removed when the promise settles, so the map cannot grow
|
|
224
224
|
// unbounded (one transient entry per concurrently-resolving namespace).
|
|
225
225
|
private readonly inFlightResolved = new Map<string, string>();
|
|
226
|
+
// Tracks every in-flight resolve-hook promise so callers can deterministically
|
|
227
|
+
// await the fire-and-forget registrations that `storageFor()` kicks off (see
|
|
228
|
+
// `whenResolveHooksSettled`). Entries are removed as each hook settles, so the
|
|
229
|
+
// set holds at most one promise per concurrently-resolving namespace.
|
|
230
|
+
private readonly pendingResolveHooks = new Set<Promise<unknown>>();
|
|
226
231
|
|
|
227
232
|
// Normalized (trimmed) default namespace identity (NH-FH). `storageFor`
|
|
228
233
|
// normalizes its input, so default-namespace branches must compare against the
|
|
@@ -325,7 +330,10 @@ export class NamespaceStorageRouter {
|
|
|
325
330
|
// the map holds at most one transient entry per concurrently-resolving
|
|
326
331
|
// namespace and cannot grow unbounded.
|
|
327
332
|
this.inFlightResolved.set(namespace, storageDir);
|
|
328
|
-
Promise.resolve(hook(namespace, storageDir))
|
|
333
|
+
const hookResult = Promise.resolve(hook(namespace, storageDir));
|
|
334
|
+
// Track the in-flight promise so `whenResolveHooksSettled()` can await it.
|
|
335
|
+
this.pendingResolveHooks.add(hookResult);
|
|
336
|
+
hookResult.then(
|
|
329
337
|
(persisted) => {
|
|
330
338
|
// Clear the in-flight marker ONLY if it is still ours (a newer resolve
|
|
331
339
|
// for a different dir may have replaced it).
|
|
@@ -338,6 +346,7 @@ export class NamespaceStorageRouter {
|
|
|
338
346
|
// On `false` (dropped touch) we intentionally do NOT mark notified, so
|
|
339
347
|
// a later `storageFor()` retries the registration. Clearing the
|
|
340
348
|
// in-flight marker above is what re-enables that retry.
|
|
349
|
+
this.pendingResolveHooks.delete(hookResult);
|
|
341
350
|
},
|
|
342
351
|
() => {
|
|
343
352
|
// Registration failed — clear in-flight AND do NOT mark as notified, so
|
|
@@ -348,6 +357,7 @@ export class NamespaceStorageRouter {
|
|
|
348
357
|
if (this.notifiedResolved.get(namespace) === storageDir) {
|
|
349
358
|
this.notifiedResolved.delete(namespace);
|
|
350
359
|
}
|
|
360
|
+
this.pendingResolveHooks.delete(hookResult);
|
|
351
361
|
},
|
|
352
362
|
);
|
|
353
363
|
} catch {
|
|
@@ -358,4 +368,21 @@ export class NamespaceStorageRouter {
|
|
|
358
368
|
}
|
|
359
369
|
}
|
|
360
370
|
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Resolve once every in-flight `onResolve` registration has settled.
|
|
374
|
+
*
|
|
375
|
+
* `storageFor()` fires the resolve hook fire-and-forget, so its catalog side
|
|
376
|
+
* effect (e.g. `registerResolved(...)`) is not observable the moment
|
|
377
|
+
* `storageFor()` returns. Callers that must act on that side effect — notably
|
|
378
|
+
* tests asserting the catalog was updated — should await this instead of
|
|
379
|
+
* racing a timer. Resolves immediately when no hook is registered or nothing
|
|
380
|
+
* is in flight. The loop re-checks because a settling hook could, in
|
|
381
|
+
* principle, trigger a follow-on resolution.
|
|
382
|
+
*/
|
|
383
|
+
async whenResolveHooksSettled(): Promise<void> {
|
|
384
|
+
while (this.pendingResolveHooks.size > 0) {
|
|
385
|
+
await Promise.allSettled([...this.pendingResolveHooks]);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
361
388
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/namespaces/storage.ts"],"sourcesContent":["import path from \"node:path\";\nimport { access, lstat, readdir } from \"node:fs/promises\";\nimport { isSafeRouteNamespace } from \"../routing/engine.js\";\nimport { StorageManager } from \"../storage.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\nimport { namespaceIdentityToken, normalizeNamespaceIdentity } from \"./identity.js\";\n\nasync function exists(p: string): Promise<boolean> {\n try {\n await access(p);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function hasStoredEntries(p: string): Promise<boolean> {\n try {\n const entry = await lstat(p);\n if (entry.isSymbolicLink()) return true;\n if (!entry.isDirectory()) return true;\n const children = await readdir(p, { withFileTypes: true });\n for (const child of children) {\n const childPath = path.join(p, child.name);\n if (child.isSymbolicLink() || child.isFile()) return true;\n if (child.isDirectory() && (await hasStoredEntries(childPath))) return true;\n }\n return false;\n } catch {\n return false;\n }\n}\n\n// Build a per-namespace directory under `<memoryDir>/namespaces` and assert the\n// resolved path stays inside that base. Namespace identifiers can originate from\n// operator config (config.defaultNamespace) and request-derived routing, so this\n// containment check prevents directory traversal (CodeQL js/path-injection).\n// For safe segments this returns exactly `path.join(base, segment)`, so there is\n// no behavioral change for valid namespaces.\nfunction resolveNamespaceDir(memoryDir: string, segment: string): string {\n // Mirror isSafeRouteNamespace's separator/parent-ref rejection (without its\n // 64-char cap, so identity tokens still pass). Rejecting separators and \"..\"\n // up front keeps the value a single contained child of <memoryDir>/namespaces.\n if (\n segment.length === 0 ||\n segment.includes(\"/\") ||\n segment.includes(\"\\\\\") ||\n segment.includes(\"..\") ||\n path.isAbsolute(segment)\n ) {\n throw new Error(`unsafe namespace path segment: ${segment}`);\n }\n return path.join(memoryDir, \"namespaces\", segment);\n}\n\nconst LEGACY_NAMESPACE_CONTENT_CHILDREN = [\n ...ALL_CATEGORY_DIRS,\n \"entities\",\n \"artifacts\",\n \"identity\",\n \"config\",\n \"summaries\",\n \"profile.md\",\n] as const;\n\nconst LEGACY_NAMESPACE_RUNTIME_CHILDREN = [\"state\"] as const;\n\nasync function hasAnyLegacyData(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await hasStoredEntries(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\nasync function hasAnyNamespaceStorageMarker(\n rootDir: string,\n options: { includeRuntimeState?: boolean } = {},\n): Promise<boolean> {\n const children = options.includeRuntimeState === true\n ? [...LEGACY_NAMESPACE_CONTENT_CHILDREN, ...LEGACY_NAMESPACE_RUNTIME_CHILDREN]\n : LEGACY_NAMESPACE_CONTENT_CHILDREN;\n for (const child of children) {\n if (await exists(path.join(rootDir, child))) return true;\n }\n return false;\n}\n\n/**\n * Storage routing for namespaces.\n *\n * Compatibility note:\n * - When namespaces are enabled, existing raw namespace roots are preserved.\n * New namespace roots use tokenized names under `memoryDir/namespaces/<token>`.\n * - The default namespace continues to use the legacy `memoryDir` root unless the caller\n * has created `memoryDir/namespaces/<defaultNamespace>` (in which case we use that).\n *\n * This avoids surprising \"lost memories\" when an install flips namespaces on without\n * migrating existing data.\n */\n/**\n * Optional hooks for the storage router. `onResolve` fires whenever a namespace's\n * storage is resolved/created, so a downstream consumer (e.g. the namespace\n * catalog, issue #1499) can register the namespace. The hook MUST NOT throw into\n * the router; the router invokes it defensively and a hook failure never affects\n * storage resolution.\n *\n * The hook MAY return (or resolve to) a boolean indicating whether the\n * registration actually PERSISTED (round 6, codex P2 — NEFoX). When it resolves\n * to `false` (a dropped/no-op registration), the router does NOT mark the\n * (namespace, storageDir) pair as notified, so the next resolve RETRIES it\n * instead of suppressing it forever. A `void`/`undefined` result is treated as\n * success (legacy hooks).\n */\nexport interface NamespaceStorageRouterHooks {\n onResolve?: (\n namespace: string,\n storageDir: string,\n ) => void | boolean | Promise<void | boolean>;\n}\n\n/**\n * Resolve the runtime storage root for the configured DEFAULT namespace.\n *\n * Shared between the live router (`NamespaceStorageRouter.defaultNamespaceRoot`)\n * and the rebuildable catalog (`NamespaceCatalog.rebuildFromDisk`) so the two\n * can never diverge (CLAUDE.md rule #22/#42 — read & write paths resolve through\n * the same logic). The contract is: while legacy memory data still lives\n * directly under `memoryDir`, the default root stays `memoryDir`; only once the\n * legacy root is empty and a `namespaces/<default|token>` dir holds data does\n * the default migrate into that tokenized/legacy-named dir.\n */\nexport async function resolveDefaultNamespaceRoot(config: PluginConfig): Promise<string> {\n if (!config.namespacesEnabled) {\n return config.memoryDir;\n }\n\n // Build the legacy default root from the NORMALIZED (trimmed) name so a\n // whitespace-padded `defaultNamespace` still finds the live `namespaces/default`\n // root (NIabe). `storageFor()` classifies the trimmed value as the default, and\n // the on-disk legacy dir is created under the trimmed name; using the raw spaced\n // name here would look for `namespaces/<spaced>` and miss the real root, falling\n // back to memoryDir/tokenized. `namespaceIdentityToken` already normalizes\n // internally, so the tokenized path is unaffected.\n const defaultIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n const legacyNsDir = resolveNamespaceDir(config.memoryDir, defaultIdentity);\n const tokenizedNsDir = resolveNamespaceDir(\n config.memoryDir,\n namespaceIdentityToken(config.defaultNamespace),\n );\n const tokenizedHasData =\n (await exists(tokenizedNsDir)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedNsDir, { includeRuntimeState: true }));\n const nsDir = tokenizedHasData\n ? tokenizedNsDir\n : (await exists(legacyNsDir))\n ? legacyNsDir\n : tokenizedNsDir;\n return (await exists(nsDir)) && !(await hasAnyLegacyData(config.memoryDir))\n ? nsDir\n : config.memoryDir;\n}\n\n/**\n * Resolve the runtime storage root for ANY namespace exactly as the live router\n * would (`NamespaceStorageRouter.namespaceRoot`). Shared so the rebuildable\n * catalog records the SAME on-disk root the router routes to — a recall/read\n * touch must not guess `namespaces/<token>` when the router actually serves a\n * legacy raw-name dir or a migrated default root (CLAUDE.md rule #22/#42; round\n * 4, cursor Medium). The default namespace delegates to `resolveDefaultNamespaceRoot`;\n * every other namespace prefers the tokenized root when it has a storage marker,\n * else a legacy raw-name dir when present, else the tokenized root.\n */\nexport async function resolveNamespaceStorageRoot(\n config: PluginConfig,\n namespace: string,\n): Promise<string> {\n if (!config.namespacesEnabled) return config.memoryDir;\n // Compare on NORMALIZED identity so a whitespace-padded configured default name\n // still routes to the default root rather than a tokenized non-default dir\n // (NH-FH). The catalog keys records by the same normalized identity.\n if (normalizeNamespaceIdentity(namespace) === normalizeNamespaceIdentity(config.defaultNamespace)) {\n return resolveDefaultNamespaceRoot(config);\n }\n const legacyRoot = resolveNamespaceDir(config.memoryDir, namespace);\n const tokenizedRoot = resolveNamespaceDir(config.memoryDir, namespaceIdentityToken(namespace));\n if (\n (await exists(tokenizedRoot)) &&\n (await hasAnyNamespaceStorageMarker(tokenizedRoot, { includeRuntimeState: true }))\n ) {\n return tokenizedRoot;\n }\n return (await exists(legacyRoot)) ? legacyRoot : tokenizedRoot;\n}\n\nexport class NamespaceStorageRouter {\n private readonly cache = new Map<string, StorageManager>();\n private defaultNsRootResolved: string | null = null;\n // Dedup the resolve hook (round 6, cursor Medium — NCNL2). Recall/extraction\n // call `storageFor` repeatedly; firing `onResolve` (→ catalog loadCompacted +\n // append) on every cache hit grows `namespaces.jsonl` without bound between\n // rebuilds. We fire the hook only when the (namespace, storageDir) pair is new\n // or its dir changed, so a steady-state cache hit is a no-op for the catalog.\n private readonly notifiedResolved = new Map<string, string>();\n // In-flight resolve-hook dedup (NFJV-, codex P2). The catalog's `onResolve`\n // hook is ASYNC (it returns `registerResolved(...)`), so `notifiedResolved` is\n // only set after the hook's promise SETTLES. Without tracking the in-flight\n // window, a burst of `storageFor()` cache hits for the SAME namespace before\n // the first registration finishes would each pass the `notifiedResolved` guard\n // and fire their OWN `onResolve` — queueing N duplicate catalog touches + lock\n // acquisitions despite the once-per-namespace intent. We therefore record the\n // (namespace → storageDir) being registered BEFORE awaiting the hook so a\n // concurrent call for the same pair skips firing. On SUCCESS the pair is\n // promoted to `notifiedResolved` (future calls skip permanently); on `false`\n // (dropped touch — e.g. rebuild-lock timeout) OR rejection the in-flight marker\n // is CLEARED so a later `storageFor()` can RETRY the dropped registration. The\n // entry is always removed when the promise settles, so the map cannot grow\n // unbounded (one transient entry per concurrently-resolving namespace).\n private readonly inFlightResolved = new Map<string, string>();\n\n // Normalized (trimmed) default namespace identity (NH-FH). `storageFor`\n // normalizes its input, so default-namespace branches must compare against the\n // normalized config default too — otherwise a whitespace-padded configured\n // default name routes the default namespace to a tokenized non-default root.\n private readonly defaultNamespaceIdentity: string;\n\n constructor(\n private readonly config: PluginConfig,\n private readonly hooks: NamespaceStorageRouterHooks = {},\n ) {\n this.defaultNamespaceIdentity = normalizeNamespaceIdentity(config.defaultNamespace);\n }\n\n private async defaultNamespaceRoot(): Promise<string> {\n this.defaultNsRootResolved = await resolveDefaultNamespaceRoot(this.config);\n return this.defaultNsRootResolved;\n }\n\n private async namespaceRoot(namespace: string): Promise<string> {\n // NOTE: only used after defaultNamespaceRoot() resolution.\n if (!this.config.namespacesEnabled) return this.config.memoryDir;\n if (normalizeNamespaceIdentity(namespace) === this.defaultNamespaceIdentity) {\n return this.defaultNsRootResolved ?? this.config.memoryDir;\n }\n return resolveNamespaceStorageRoot(this.config, namespace);\n }\n\n async storageFor(namespace: string): Promise<StorageManager> {\n const ns = normalizeNamespaceIdentity(namespace || this.config.defaultNamespace);\n if (ns !== this.defaultNamespaceIdentity && !isSafeRouteNamespace(ns)) {\n throw new Error(`unsafe namespace: ${ns}`);\n }\n // Even when the default namespace is exempt from the check above, every\n // on-disk path is built through resolveNamespaceDir(), which rejects\n // traversal segments — so an unsafe configured default still cannot escape\n // <memoryDir>/namespaces (CodeQL js/path-injection).\n\n let root: string;\n if (ns === this.defaultNamespaceIdentity) {\n root = await this.defaultNamespaceRoot();\n const cached = this.cache.get(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n } else {\n const cached = this.cache.get(ns);\n root = await this.namespaceRoot(ns);\n if (cached && cached.dir === root) {\n this.notifyResolved(ns, root);\n return cached;\n }\n }\n\n const sm = new StorageManager(root, this.config.entitySchemas);\n // Propagate the inline-attribution template so that router-created storages\n // (used by extraction and shared-promotion paths) strip citations consistently,\n // matching the behaviour of the primary this.storage instance in the orchestrator.\n sm.citationTemplate = this.config.inlineSourceAttributionFormat;\n this.cache.set(ns, sm);\n this.notifyResolved(ns, root);\n return sm;\n }\n\n /**\n * Fire the resolve hook defensively. A hook failure (e.g. a catalog write\n * error) MUST NOT crash storage resolution — see CLAUDE.md gotcha #13.\n */\n private notifyResolved(namespace: string, storageDir: string): void {\n const hook = this.hooks.onResolve;\n if (!hook) return;\n // Skip when we've already SUCCESSFULLY notified this exact (namespace,\n // storageDir) — a steady-state cache hit must not re-append to the catalog\n // log (NCNL2). A changed dir (rare: migration/realignment) still re-fires\n // once. We mark the pair as notified ONLY AFTER the hook succeeds, and CLEAR\n // it on failure, so a dropped registration (e.g. rebuild-lock timeout) is\n // RETRIED on the next cache hit instead of being suppressed forever (round 6,\n // cursor Medium — ND3EJ).\n if (this.notifiedResolved.get(namespace) === storageDir) return;\n // In-flight dedup (NFJV-, codex P2): if a registration for this exact\n // (namespace, storageDir) is already AWAITING its async hook, do not fire a\n // second one. Without this, concurrent cache-hit bursts before the first\n // append settles each pass the `notifiedResolved` guard above and queue\n // duplicate catalog touches/lock acquisitions. A pair with a DIFFERENT\n // in-flight dir (rare mid-migration realignment) still fires once.\n if (this.inFlightResolved.get(namespace) === storageDir) return;\n try {\n // Handle BOTH synchronous throws and asynchronous rejections (round 6,\n // codex P2 — NDo8C). The hook may be `async`; its rejected promise would\n // bypass this try/catch and, where unhandled rejections are fatal, crash\n // storage resolution. Mark the dedup pair as notified ONLY when the hook\n // resolves to a PERSISTED result (round 6, codex P2 — NEFoX): a result of\n // `false` means the registration was dropped/no-op (e.g. rebuild-lock\n // timeout), so we must NOT suppress its retry. `void`/`undefined` is treated\n // as success for legacy hooks. On rejection we leave it un-notified to retry.\n //\n // Record the in-flight marker BEFORE awaiting so concurrent calls for the\n // same pair skip (NFJV-). It is always cleared once the promise settles, so\n // the map holds at most one transient entry per concurrently-resolving\n // namespace and cannot grow unbounded.\n this.inFlightResolved.set(namespace, storageDir);\n Promise.resolve(hook(namespace, storageDir)).then(\n (persisted) => {\n // Clear the in-flight marker ONLY if it is still ours (a newer resolve\n // for a different dir may have replaced it).\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (persisted !== false) {\n this.notifiedResolved.set(namespace, storageDir);\n }\n // On `false` (dropped touch) we intentionally do NOT mark notified, so\n // a later `storageFor()` retries the registration. Clearing the\n // in-flight marker above is what re-enables that retry.\n },\n () => {\n // Registration failed — clear in-flight AND do NOT mark as notified, so\n // it is retried on the next cache hit.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n if (this.notifiedResolved.get(namespace) === storageDir) {\n this.notifiedResolved.delete(namespace);\n }\n },\n );\n } catch {\n // Synchronous throw: clear any in-flight marker we just set and leave the\n // pair un-notified so a later resolve retries.\n if (this.inFlightResolved.get(namespace) === storageDir) {\n this.inFlightResolved.delete(namespace);\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|