@remnic/core 9.3.622 → 9.3.623
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 +24 -24
- package/dist/access-http.js +9 -9
- package/dist/access-mcp.js +8 -8
- package/dist/access-service.js +7 -7
- package/dist/briefing.js +4 -4
- package/dist/buffer-surprise.js +3 -3
- package/dist/calibration.js +2 -2
- package/dist/causal-consolidation.js +8 -8
- package/dist/{chunk-UK727RHF.js → chunk-2L54V4ZO.js} +3 -3
- package/dist/{chunk-YPNGPHNZ.js → chunk-2UFQYU5F.js} +2 -2
- package/dist/{chunk-XAZOWLW4.js → chunk-3VONWEQB.js} +3 -3
- package/dist/{chunk-BF7ZRHH2.js → chunk-66SLUXKM.js} +2 -2
- package/dist/{chunk-AVHPSLQ2.js → chunk-AYHXQR53.js} +2 -2
- package/dist/{chunk-LANHQ7EN.js → chunk-BNW5NJJH.js} +2 -2
- package/dist/{chunk-6GMPIJAZ.js → chunk-C3IW2F5Z.js} +2 -2
- package/dist/{chunk-VNR3K2R3.js → chunk-C4PZTWTG.js} +14 -14
- package/dist/{chunk-3GM7ZY6H.js → chunk-FMGWXIES.js} +4 -4
- package/dist/{chunk-LMZ7XQBB.js → chunk-GLWW3EJQ.js} +3 -3
- package/dist/{chunk-2GRRN7SZ.js → chunk-GYTVOLNX.js} +2 -2
- package/dist/{chunk-IMA6GU4Y.js → chunk-H3PHZLMF.js} +3 -3
- package/dist/chunk-H3PHZLMF.js.map +1 -0
- package/dist/{chunk-XQUIHXNI.js → chunk-I6UCUHLK.js} +4 -4
- package/dist/{chunk-2I2MDQIB.js → chunk-I74SUMNI.js} +2 -2
- package/dist/chunk-I74SUMNI.js.map +1 -0
- package/dist/{chunk-4H5ZJHEN.js → chunk-J6A3CX5N.js} +8 -3
- package/dist/{chunk-4H5ZJHEN.js.map → chunk-J6A3CX5N.js.map} +1 -1
- package/dist/{chunk-DEVUWMME.js → chunk-KGIGRNR6.js} +2 -2
- package/dist/{chunk-EOLCAPOU.js → chunk-KQFQ3IS5.js} +5 -5
- package/dist/{chunk-QSVPYQPG.js → chunk-LDXUBPMO.js} +2 -2
- package/dist/chunk-LDXUBPMO.js.map +1 -0
- package/dist/{chunk-JFEKNTX7.js → chunk-LN4YGHTM.js} +6 -2
- package/dist/chunk-LN4YGHTM.js.map +1 -0
- package/dist/{chunk-WB3LYXC5.js → chunk-MON3LMO7.js} +3 -3
- package/dist/{chunk-GA3PMY73.js → chunk-O4UNM6OR.js} +2 -2
- package/dist/{chunk-4G2RQTAE.js → chunk-OZXVGYGZ.js} +2 -2
- package/dist/{chunk-WCYKT2DE.js → chunk-P4BC54KI.js} +23 -14
- package/dist/chunk-P4BC54KI.js.map +1 -0
- package/dist/{chunk-DXBCNDVD.js → chunk-PJGB7XRR.js} +5 -5
- package/dist/chunk-PJGB7XRR.js.map +1 -0
- package/dist/{chunk-ZNCDQZIS.js → chunk-QFQQFX2H.js} +3 -3
- package/dist/{chunk-ZNCDQZIS.js.map → chunk-QFQQFX2H.js.map} +1 -1
- package/dist/{chunk-CCNZM5UM.js → chunk-R3OQGYOU.js} +2 -2
- package/dist/{chunk-UZB5KHKX.js → chunk-RGMVMVMF.js} +2 -2
- package/dist/chunk-RGMVMVMF.js.map +1 -0
- package/dist/{chunk-EDP57PFC.js → chunk-RKW6QR7W.js} +22 -18
- package/dist/chunk-RKW6QR7W.js.map +1 -0
- package/dist/{chunk-4MHHUPNH.js → chunk-UGEBPVNI.js} +3 -3
- package/dist/{chunk-4WMCPJWX.js → chunk-UQ7RN5HK.js} +22 -13
- package/dist/chunk-UQ7RN5HK.js.map +1 -0
- package/dist/{chunk-ZUNNG6PC.js → chunk-W3BKVM64.js} +2 -2
- package/dist/{chunk-K5O2QY6T.js → chunk-YTWNKQ2G.js} +2 -2
- package/dist/chunk-YTWNKQ2G.js.map +1 -0
- package/dist/{chunk-2SGJY2UY.js → chunk-Z3CCEP6F.js} +3 -3
- package/dist/{chunk-4NS2ELXF.js → chunk-ZJSZNTEI.js} +4 -4
- package/dist/{chunk-UCGCSZP2.js → chunk-ZZPIJPPD.js} +2 -2
- package/dist/chunking.js +1 -1
- package/dist/cli.js +19 -19
- package/dist/compounding/engine.js +4 -4
- package/dist/connectors/codex-materialize-runner.js +5 -5
- package/dist/connectors/codex-materialize.js +1 -1
- package/dist/connectors/index.js +5 -5
- package/dist/contradiction/index.js +2 -2
- package/dist/{contradiction-scan-GD7KUFWS.js → contradiction-scan-AZTGFMPY.js} +3 -3
- package/dist/entity-retrieval.js +4 -4
- package/dist/explicit-capture.js +1 -1
- package/dist/extraction-judge.js +3 -3
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.js +2 -2
- package/dist/identity-continuity.js +1 -1
- package/dist/index.js +39 -36
- package/dist/index.js.map +1 -1
- package/dist/json-extract.js +1 -1
- package/dist/maintenance/memory-governance.js +4 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
- package/dist/maintenance/rebuild-memory-projection.js +5 -5
- package/dist/namespaces/migrate.js +5 -5
- package/dist/namespaces/storage.js +4 -4
- package/dist/operator-toolkit.js +7 -7
- package/dist/orchestrator.js +21 -21
- package/dist/peers/index.js +1 -1
- package/dist/recall-planner-llm.js +2 -2
- package/dist/schemas.d.ts +22 -22
- package/dist/semantic-chunking.js +2 -2
- package/dist/semantic-consolidation.js +6 -6
- package/dist/semantic-rule-promotion.js +4 -4
- package/dist/semantic-rule-verifier.js +4 -4
- package/dist/source-attribution.js +1 -1
- package/dist/storage.js +3 -3
- package/dist/summarizer.js +3 -3
- package/dist/temporal-supersession.js +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/verified-recall.js +4 -4
- package/package.json +1 -1
- package/src/chunking.ts +38 -23
- package/src/coding/review-context.ts +7 -1
- package/src/connectors/codex-materialize.ts +6 -1
- package/src/explicit-capture.ts +7 -2
- package/src/identity-continuity.ts +7 -1
- package/src/json-extract.ts +4 -1
- package/src/orchestrator.ts +5 -1
- package/src/peers/profile-reasoner.ts +4 -1
- package/src/semantic-chunking.ts +32 -16
- package/src/semantic-consolidation.ts +4 -1
- package/src/source-attribution.test.ts +21 -0
- package/src/source-attribution.ts +17 -2
- package/src/storage.ts +11 -2
- package/src/temporal-supersession.ts +4 -1
- package/dist/chunk-2I2MDQIB.js.map +0 -1
- package/dist/chunk-4WMCPJWX.js.map +0 -1
- package/dist/chunk-DXBCNDVD.js.map +0 -1
- package/dist/chunk-EDP57PFC.js.map +0 -1
- package/dist/chunk-IMA6GU4Y.js.map +0 -1
- package/dist/chunk-JFEKNTX7.js.map +0 -1
- package/dist/chunk-K5O2QY6T.js.map +0 -1
- package/dist/chunk-QSVPYQPG.js.map +0 -1
- package/dist/chunk-UZB5KHKX.js.map +0 -1
- package/dist/chunk-WCYKT2DE.js.map +0 -1
- /package/dist/{chunk-UK727RHF.js.map → chunk-2L54V4ZO.js.map} +0 -0
- /package/dist/{chunk-YPNGPHNZ.js.map → chunk-2UFQYU5F.js.map} +0 -0
- /package/dist/{chunk-XAZOWLW4.js.map → chunk-3VONWEQB.js.map} +0 -0
- /package/dist/{chunk-BF7ZRHH2.js.map → chunk-66SLUXKM.js.map} +0 -0
- /package/dist/{chunk-AVHPSLQ2.js.map → chunk-AYHXQR53.js.map} +0 -0
- /package/dist/{chunk-LANHQ7EN.js.map → chunk-BNW5NJJH.js.map} +0 -0
- /package/dist/{chunk-6GMPIJAZ.js.map → chunk-C3IW2F5Z.js.map} +0 -0
- /package/dist/{chunk-VNR3K2R3.js.map → chunk-C4PZTWTG.js.map} +0 -0
- /package/dist/{chunk-3GM7ZY6H.js.map → chunk-FMGWXIES.js.map} +0 -0
- /package/dist/{chunk-LMZ7XQBB.js.map → chunk-GLWW3EJQ.js.map} +0 -0
- /package/dist/{chunk-2GRRN7SZ.js.map → chunk-GYTVOLNX.js.map} +0 -0
- /package/dist/{chunk-XQUIHXNI.js.map → chunk-I6UCUHLK.js.map} +0 -0
- /package/dist/{chunk-DEVUWMME.js.map → chunk-KGIGRNR6.js.map} +0 -0
- /package/dist/{chunk-EOLCAPOU.js.map → chunk-KQFQ3IS5.js.map} +0 -0
- /package/dist/{chunk-WB3LYXC5.js.map → chunk-MON3LMO7.js.map} +0 -0
- /package/dist/{chunk-GA3PMY73.js.map → chunk-O4UNM6OR.js.map} +0 -0
- /package/dist/{chunk-4G2RQTAE.js.map → chunk-OZXVGYGZ.js.map} +0 -0
- /package/dist/{chunk-CCNZM5UM.js.map → chunk-R3OQGYOU.js.map} +0 -0
- /package/dist/{chunk-4MHHUPNH.js.map → chunk-UGEBPVNI.js.map} +0 -0
- /package/dist/{chunk-ZUNNG6PC.js.map → chunk-W3BKVM64.js.map} +0 -0
- /package/dist/{chunk-2SGJY2UY.js.map → chunk-Z3CCEP6F.js.map} +0 -0
- /package/dist/{chunk-4NS2ELXF.js.map → chunk-ZJSZNTEI.js.map} +0 -0
- /package/dist/{chunk-UCGCSZP2.js.map → chunk-ZZPIJPPD.js.map} +0 -0
- /package/dist/{contradiction-scan-GD7KUFWS.js.map → contradiction-scan-AZTGFMPY.js.map} +0 -0
package/dist/summarizer.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HourlySummarizer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3VONWEQB.js";
|
|
4
4
|
import "./chunk-XJNBEDFE.js";
|
|
5
5
|
import "./chunk-XZ4WBBB5.js";
|
|
6
6
|
import "./chunk-77NAFXUD.js";
|
|
7
7
|
import "./chunk-FF4KLI5W.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-KGIGRNR6.js";
|
|
9
9
|
import "./chunk-B5XMS73R.js";
|
|
10
10
|
import "./chunk-7SI52C65.js";
|
|
11
11
|
import "./chunk-L2EXJQJP.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-RGMVMVMF.js";
|
|
13
13
|
import "./chunk-RK6F44Y6.js";
|
|
14
14
|
import "./chunk-NNVTUXEB.js";
|
|
15
15
|
import "./chunk-EYIEWJNI.js";
|
package/dist/transfer/types.d.ts
CHANGED
|
@@ -313,13 +313,13 @@ declare const CapsuleBlockSchema: z.ZodObject<{
|
|
|
313
313
|
peerProfiles: boolean;
|
|
314
314
|
}>;
|
|
315
315
|
}, "strip", z.ZodTypeAny, {
|
|
316
|
-
schemaVersion: string;
|
|
317
316
|
includes: {
|
|
318
317
|
procedural: boolean;
|
|
319
318
|
taxonomy: boolean;
|
|
320
319
|
identityAnchors: boolean;
|
|
321
320
|
peerProfiles: boolean;
|
|
322
321
|
};
|
|
322
|
+
schemaVersion: string;
|
|
323
323
|
id: string;
|
|
324
324
|
description: string;
|
|
325
325
|
version: string;
|
|
@@ -334,13 +334,13 @@ declare const CapsuleBlockSchema: z.ZodObject<{
|
|
|
334
334
|
directAnswerEnabled: boolean;
|
|
335
335
|
};
|
|
336
336
|
}, {
|
|
337
|
-
schemaVersion: string;
|
|
338
337
|
includes: {
|
|
339
338
|
procedural: boolean;
|
|
340
339
|
taxonomy: boolean;
|
|
341
340
|
identityAnchors: boolean;
|
|
342
341
|
peerProfiles: boolean;
|
|
343
342
|
};
|
|
343
|
+
schemaVersion: string;
|
|
344
344
|
id: string;
|
|
345
345
|
description: string;
|
|
346
346
|
version: string;
|
|
@@ -464,13 +464,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
464
464
|
peerProfiles: boolean;
|
|
465
465
|
}>;
|
|
466
466
|
}, "strip", z.ZodTypeAny, {
|
|
467
|
-
schemaVersion: string;
|
|
468
467
|
includes: {
|
|
469
468
|
procedural: boolean;
|
|
470
469
|
taxonomy: boolean;
|
|
471
470
|
identityAnchors: boolean;
|
|
472
471
|
peerProfiles: boolean;
|
|
473
472
|
};
|
|
473
|
+
schemaVersion: string;
|
|
474
474
|
id: string;
|
|
475
475
|
description: string;
|
|
476
476
|
version: string;
|
|
@@ -485,13 +485,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
485
485
|
directAnswerEnabled: boolean;
|
|
486
486
|
};
|
|
487
487
|
}, {
|
|
488
|
-
schemaVersion: string;
|
|
489
488
|
includes: {
|
|
490
489
|
procedural: boolean;
|
|
491
490
|
taxonomy: boolean;
|
|
492
491
|
identityAnchors: boolean;
|
|
493
492
|
peerProfiles: boolean;
|
|
494
493
|
};
|
|
494
|
+
schemaVersion: string;
|
|
495
495
|
id: string;
|
|
496
496
|
description: string;
|
|
497
497
|
version: string;
|
|
@@ -518,13 +518,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
518
518
|
pluginVersion: string;
|
|
519
519
|
includesTranscripts: boolean;
|
|
520
520
|
capsule: {
|
|
521
|
-
schemaVersion: string;
|
|
522
521
|
includes: {
|
|
523
522
|
procedural: boolean;
|
|
524
523
|
taxonomy: boolean;
|
|
525
524
|
identityAnchors: boolean;
|
|
526
525
|
peerProfiles: boolean;
|
|
527
526
|
};
|
|
527
|
+
schemaVersion: string;
|
|
528
528
|
id: string;
|
|
529
529
|
description: string;
|
|
530
530
|
version: string;
|
|
@@ -551,13 +551,13 @@ declare const ExportManifestV2Schema: z.ZodObject<{
|
|
|
551
551
|
pluginVersion: string;
|
|
552
552
|
includesTranscripts: boolean;
|
|
553
553
|
capsule: {
|
|
554
|
-
schemaVersion: string;
|
|
555
554
|
includes: {
|
|
556
555
|
procedural: boolean;
|
|
557
556
|
taxonomy: boolean;
|
|
558
557
|
identityAnchors: boolean;
|
|
559
558
|
peerProfiles: boolean;
|
|
560
559
|
};
|
|
560
|
+
schemaVersion: string;
|
|
561
561
|
id: string;
|
|
562
562
|
description: string;
|
|
563
563
|
version: string;
|
|
@@ -683,13 +683,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
683
683
|
peerProfiles: boolean;
|
|
684
684
|
}>;
|
|
685
685
|
}, "strip", z.ZodTypeAny, {
|
|
686
|
-
schemaVersion: string;
|
|
687
686
|
includes: {
|
|
688
687
|
procedural: boolean;
|
|
689
688
|
taxonomy: boolean;
|
|
690
689
|
identityAnchors: boolean;
|
|
691
690
|
peerProfiles: boolean;
|
|
692
691
|
};
|
|
692
|
+
schemaVersion: string;
|
|
693
693
|
id: string;
|
|
694
694
|
description: string;
|
|
695
695
|
version: string;
|
|
@@ -704,13 +704,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
704
704
|
directAnswerEnabled: boolean;
|
|
705
705
|
};
|
|
706
706
|
}, {
|
|
707
|
-
schemaVersion: string;
|
|
708
707
|
includes: {
|
|
709
708
|
procedural: boolean;
|
|
710
709
|
taxonomy: boolean;
|
|
711
710
|
identityAnchors: boolean;
|
|
712
711
|
peerProfiles: boolean;
|
|
713
712
|
};
|
|
713
|
+
schemaVersion: string;
|
|
714
714
|
id: string;
|
|
715
715
|
description: string;
|
|
716
716
|
version: string;
|
|
@@ -737,13 +737,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
737
737
|
pluginVersion: string;
|
|
738
738
|
includesTranscripts: boolean;
|
|
739
739
|
capsule: {
|
|
740
|
-
schemaVersion: string;
|
|
741
740
|
includes: {
|
|
742
741
|
procedural: boolean;
|
|
743
742
|
taxonomy: boolean;
|
|
744
743
|
identityAnchors: boolean;
|
|
745
744
|
peerProfiles: boolean;
|
|
746
745
|
};
|
|
746
|
+
schemaVersion: string;
|
|
747
747
|
id: string;
|
|
748
748
|
description: string;
|
|
749
749
|
version: string;
|
|
@@ -770,13 +770,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
770
770
|
pluginVersion: string;
|
|
771
771
|
includesTranscripts: boolean;
|
|
772
772
|
capsule: {
|
|
773
|
-
schemaVersion: string;
|
|
774
773
|
includes: {
|
|
775
774
|
procedural: boolean;
|
|
776
775
|
taxonomy: boolean;
|
|
777
776
|
identityAnchors: boolean;
|
|
778
777
|
peerProfiles: boolean;
|
|
779
778
|
};
|
|
779
|
+
schemaVersion: string;
|
|
780
780
|
id: string;
|
|
781
781
|
description: string;
|
|
782
782
|
version: string;
|
|
@@ -815,13 +815,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
815
815
|
pluginVersion: string;
|
|
816
816
|
includesTranscripts: boolean;
|
|
817
817
|
capsule: {
|
|
818
|
-
schemaVersion: string;
|
|
819
818
|
includes: {
|
|
820
819
|
procedural: boolean;
|
|
821
820
|
taxonomy: boolean;
|
|
822
821
|
identityAnchors: boolean;
|
|
823
822
|
peerProfiles: boolean;
|
|
824
823
|
};
|
|
824
|
+
schemaVersion: string;
|
|
825
825
|
id: string;
|
|
826
826
|
description: string;
|
|
827
827
|
version: string;
|
|
@@ -854,13 +854,13 @@ declare const ExportBundleV2Schema: z.ZodObject<{
|
|
|
854
854
|
pluginVersion: string;
|
|
855
855
|
includesTranscripts: boolean;
|
|
856
856
|
capsule: {
|
|
857
|
-
schemaVersion: string;
|
|
858
857
|
includes: {
|
|
859
858
|
procedural: boolean;
|
|
860
859
|
taxonomy: boolean;
|
|
861
860
|
identityAnchors: boolean;
|
|
862
861
|
peerProfiles: boolean;
|
|
863
862
|
};
|
|
863
|
+
schemaVersion: string;
|
|
864
864
|
id: string;
|
|
865
865
|
description: string;
|
|
866
866
|
version: string;
|
package/dist/verified-recall.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
searchVerifiedEpisodes
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-R3OQGYOU.js";
|
|
4
4
|
import "./chunk-HQ6NIBL6.js";
|
|
5
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-PJGB7XRR.js";
|
|
6
6
|
import "./chunk-5UZXUTVO.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-J6A3CX5N.js";
|
|
8
8
|
import "./chunk-4R4KTDIE.js";
|
|
9
9
|
import "./chunk-RULE4VG5.js";
|
|
10
10
|
import "./chunk-SCU65EZI.js";
|
|
@@ -12,7 +12,7 @@ import "./chunk-MB5RSUW6.js";
|
|
|
12
12
|
import "./chunk-6KYMPV2O.js";
|
|
13
13
|
import "./chunk-CPPS65WS.js";
|
|
14
14
|
import "./chunk-DM2T26WE.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-LDXUBPMO.js";
|
|
16
16
|
import "./chunk-FVQJYWH7.js";
|
|
17
17
|
import "./chunk-G7D6GZ5J.js";
|
|
18
18
|
import "./chunk-ALEPI75L.js";
|
package/package.json
CHANGED
package/src/chunking.ts
CHANGED
|
@@ -50,32 +50,47 @@ function estimateTokens(text: string): number {
|
|
|
50
50
|
* Handles common abbreviations and edge cases.
|
|
51
51
|
*/
|
|
52
52
|
function splitSentences(text: string): string[] {
|
|
53
|
-
// Split on sentence-ending punctuation
|
|
54
|
-
//
|
|
53
|
+
// Split on sentence-ending punctuation (. ! ?) that is followed by whitespace
|
|
54
|
+
// or end of string; the punctuation stays with the sentence.
|
|
55
|
+
//
|
|
56
|
+
// Implemented as a single linear scan rather than a regex. Every regex form of
|
|
57
|
+
// this split is either polynomial (CodeQL js/polynomial-redos) or — once
|
|
58
|
+
// bounded/anchored to satisfy CodeQL — mishandles long runs or non-boundary
|
|
59
|
+
// punctuation (a global match silently drops a skipped prefix; a sticky match
|
|
60
|
+
// stops at the first interior `.` that is not a real boundary, e.g. "v1.2.3"
|
|
61
|
+
// or "example.com", emitting the whole document as one chunk). A character
|
|
62
|
+
// scan is O(n), allocation-free, drops nothing, and treats interior
|
|
63
|
+
// punctuation correctly. Normal prose splits identically to the previous
|
|
64
|
+
// /[^.!?]*[.!?]+(?:\s+|$)/g form.
|
|
55
65
|
const sentences: string[] = [];
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
sentences.push(
|
|
66
|
+
let start = 0;
|
|
67
|
+
for (let i = 0; i < text.length; i++) {
|
|
68
|
+
const ch = text[i];
|
|
69
|
+
if (ch !== "." && ch !== "!" && ch !== "?") continue;
|
|
70
|
+
// Consume a run of terminators (e.g. "?!", "...").
|
|
71
|
+
let end = i;
|
|
72
|
+
while (end + 1 < text.length) {
|
|
73
|
+
const n = text[end + 1];
|
|
74
|
+
if (n !== "." && n !== "!" && n !== "?") break;
|
|
75
|
+
end++;
|
|
76
|
+
}
|
|
77
|
+
const after = text[end + 1];
|
|
78
|
+
// A real boundary only if the terminator run ends the string or is followed
|
|
79
|
+
// by whitespace. Interior punctuation (no following whitespace) is left in
|
|
80
|
+
// place and the scan continues.
|
|
81
|
+
if (after === undefined || /\s/.test(after)) {
|
|
82
|
+
const sentence = text.slice(start, end + 1).trim();
|
|
83
|
+
if (sentence.length > 0) sentences.push(sentence);
|
|
84
|
+
start = end + 1;
|
|
74
85
|
}
|
|
86
|
+
i = end;
|
|
75
87
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
// Trailing text without a closing terminator.
|
|
89
|
+
if (start < text.length) {
|
|
90
|
+
const remaining = text.slice(start).trim();
|
|
91
|
+
if (remaining.length > 0) sentences.push(remaining);
|
|
92
|
+
}
|
|
93
|
+
return sentences;
|
|
79
94
|
}
|
|
80
95
|
|
|
81
96
|
/**
|
|
@@ -142,7 +142,13 @@ export function parseTouchedFiles(diff: string | null | undefined): string[] {
|
|
|
142
142
|
// everything after the first whitespace in a quoted path.
|
|
143
143
|
const headerPrefix = line.match(/^(?:---|\+\+\+)[ \t]+/);
|
|
144
144
|
if (headerPrefix) {
|
|
145
|
-
|
|
145
|
+
// Linear trailing space/tab trim instead of /[ \t]+$/, whose anchored
|
|
146
|
+
// quantifier backtracks polynomially on a long diff line (CodeQL
|
|
147
|
+
// js/polynomial-redos).
|
|
148
|
+
const sliced = line.slice(headerPrefix[0].length);
|
|
149
|
+
let tailEnd = sliced.length;
|
|
150
|
+
while (tailEnd > 0 && (sliced[tailEnd - 1] === " " || sliced[tailEnd - 1] === "\t")) tailEnd--;
|
|
151
|
+
const tail = sliced.slice(0, tailEnd);
|
|
146
152
|
const raw = extractSingleDiffPathToken(tail);
|
|
147
153
|
if (raw) {
|
|
148
154
|
const stripped = stripDiffPathPrefix(raw);
|
|
@@ -550,7 +550,12 @@ export function renderMemorySummary(ctx: SummaryRenderContext): string {
|
|
|
550
550
|
lines.push("");
|
|
551
551
|
}
|
|
552
552
|
|
|
553
|
-
|
|
553
|
+
// Collapse trailing newlines to one without the anchored /\n+$/ quantifier,
|
|
554
|
+
// which backtracks polynomially (CodeQL js/polynomial-redos).
|
|
555
|
+
const joined = lines.join("\n");
|
|
556
|
+
let joinedEnd = joined.length;
|
|
557
|
+
while (joinedEnd > 0 && joined[joinedEnd - 1] === "\n") joinedEnd--;
|
|
558
|
+
const full = joinedEnd === joined.length ? joined : `${joined.slice(0, joinedEnd)}\n`;
|
|
554
559
|
return truncateToTokenBudget(full, ctx.maxTokens);
|
|
555
560
|
}
|
|
556
561
|
|
package/src/explicit-capture.ts
CHANGED
|
@@ -40,8 +40,13 @@ export type ValidExplicitCapture = {
|
|
|
40
40
|
export type ExplicitCaptureSource = "memory_store" | "memory_capture" | "suggestion_submit" | "inline";
|
|
41
41
|
type ExplicitCaptureValidationMode = "legacy_tool" | "strict_explicit";
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// Bounded body {0,100000} instead of an unbounded lazy *? so scanning for the
|
|
44
|
+
// closing tag cannot backtrack polynomially on unterminated <memory_note>
|
|
45
|
+
// markup in hostile turn text (CodeQL js/polynomial-redos). 100 000 chars far
|
|
46
|
+
// exceeds any real inline note, so matching is behavior-preserving; the outer
|
|
47
|
+
// \s* groups were also dropped (body absorbs whitespace; captures are trimmed).
|
|
48
|
+
const INLINE_NOTE_RE = /<memory_note>([\s\S]{0,100000}?)<\/memory_note>/gi;
|
|
49
|
+
const INLINE_NOTE_MARKUP_RE = /<memory_note>[\s\S]{0,100000}?<\/memory_note>/i;
|
|
45
50
|
const INLINE_ALLOWED_CATEGORIES = new Set<MemoryCategory>([
|
|
46
51
|
"fact",
|
|
47
52
|
"preference",
|
|
@@ -200,7 +200,13 @@ function splitLoopMarkdown(raw: string | null): { header: string; sections: Mark
|
|
|
200
200
|
let current: MarkdownSection | null = null;
|
|
201
201
|
|
|
202
202
|
for (const line of lines) {
|
|
203
|
-
|
|
203
|
+
// /^##\s(.+)$/ + the trim below is exactly equivalent to the original
|
|
204
|
+
// /^##\s+(.+?)\s*$/ (same match/no-match and same trimmed title across all
|
|
205
|
+
// inputs, including "## " → no-match and "## " → empty title) but has no
|
|
206
|
+
// adjacent overlapping quantifiers, so it cannot backtrack polynomially
|
|
207
|
+
// (CodeQL js/polynomial-redos). \s matches a single fixed-width char and
|
|
208
|
+
// .+ runs greedily to the line end — no \s+/.* overlap.
|
|
209
|
+
const sectionMatch = line.match(/^##\s(.+)$/);
|
|
204
210
|
if (sectionMatch) {
|
|
205
211
|
if (current) sections.push({ title: current.title, body: current.body.trimEnd() });
|
|
206
212
|
current = { title: sectionMatch[1].trim(), body: "" };
|
package/src/json-extract.ts
CHANGED
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
export function stripCodeFences(text: string): string {
|
|
13
|
-
|
|
13
|
+
// Drop the leading \s* before the lazy body: it overlapped the body and caused
|
|
14
|
+
// polynomial backtracking on unterminated fences (CodeQL js/polynomial-redos).
|
|
15
|
+
// inner is trimmed, so captured content is identical.
|
|
16
|
+
return text.replace(/```(?:json)?([\s\S]*?)```/gi, (_m, inner) => String(inner).trim());
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export function extractJsonCandidates(text: string): string[] {
|
package/src/orchestrator.ts
CHANGED
|
@@ -943,7 +943,11 @@ export function formatCompressionGuidelinesForRecall(
|
|
|
943
943
|
): string | null {
|
|
944
944
|
if (typeof raw !== "string" || raw.trim().length === 0) return null;
|
|
945
945
|
const sectionMatch = raw.match(
|
|
946
|
-
|
|
946
|
+
// End the section at `\n## ` or end-of-string. Plain $ (not \s*$): the
|
|
947
|
+
// \s* branch overlapped the lazy body and backtracked polynomially
|
|
948
|
+
// (CodeQL js/polynomial-redos). Captured lines are trimmed/filtered below,
|
|
949
|
+
// so trailing whitespace handling is unchanged.
|
|
950
|
+
/## Suggested Guidelines\s*\n([\s\S]*?)(?:\n##\s+|$)/i,
|
|
947
951
|
);
|
|
948
952
|
if (!sectionMatch) return null;
|
|
949
953
|
|
|
@@ -262,7 +262,10 @@ export function parsePeerProfileReasonerResponse(
|
|
|
262
262
|
): PeerProfileReasonerProposal[] {
|
|
263
263
|
if (typeof raw !== "string" || raw.trim() === "") return [];
|
|
264
264
|
const trimmed = raw.trim();
|
|
265
|
-
|
|
265
|
+
// Dropped the \s* groups around the lazy body (they overlapped it and
|
|
266
|
+
// backtracked polynomially — CodeQL js/polynomial-redos). Input is already
|
|
267
|
+
// trimmed and fenced[1] is trimmed below, so matches are identical.
|
|
268
|
+
const fenced = /^```(?:json)?([\s\S]*?)```$/u.exec(trimmed);
|
|
266
269
|
const payload = fenced ? fenced[1].trim() : trimmed;
|
|
267
270
|
let parsed: unknown;
|
|
268
271
|
try {
|
package/src/semantic-chunking.ts
CHANGED
|
@@ -185,25 +185,41 @@ export function findLocalMinima(
|
|
|
185
185
|
* Preserves punctuation with the preceding sentence.
|
|
186
186
|
*/
|
|
187
187
|
function splitSentences(text: string): string[] {
|
|
188
|
+
// Linear character scan instead of a regex. Every regex form of this split is
|
|
189
|
+
// either polynomial (CodeQL js/polynomial-redos) or — once bounded/anchored to
|
|
190
|
+
// satisfy CodeQL — mishandles long runs or interior punctuation (a global
|
|
191
|
+
// match drops a skipped prefix; a sticky match stops at the first non-boundary
|
|
192
|
+
// `.`, e.g. "v1.2.3" / "example.com", returning the whole document as one
|
|
193
|
+
// sentence and bypassing chunking). The scan is O(n), drops nothing, and
|
|
194
|
+
// handles interior punctuation correctly; normal prose splits identically to
|
|
195
|
+
// the previous /[^.!?]*[.!?]+(?:\s+|$)/g form.
|
|
188
196
|
const sentences: string[] = [];
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
197
|
+
let start = 0;
|
|
198
|
+
for (let i = 0; i < text.length; i++) {
|
|
199
|
+
const ch = text[i];
|
|
200
|
+
if (ch !== "." && ch !== "!" && ch !== "?") continue;
|
|
201
|
+
let end = i;
|
|
202
|
+
while (end + 1 < text.length) {
|
|
203
|
+
const n = text[end + 1];
|
|
204
|
+
if (n !== "." && n !== "!" && n !== "?") break;
|
|
205
|
+
end++;
|
|
206
|
+
}
|
|
207
|
+
const after = text[end + 1];
|
|
208
|
+
// A real boundary only if the terminator run ends the string or is followed
|
|
209
|
+
// by whitespace. Interior punctuation (no following whitespace) is left in
|
|
210
|
+
// place and the scan continues.
|
|
211
|
+
if (after === undefined || /\s/.test(after)) {
|
|
212
|
+
const sentence = text.slice(start, end + 1).trim();
|
|
213
|
+
if (sentence.length > 0) sentences.push(sentence);
|
|
214
|
+
start = end + 1;
|
|
203
215
|
}
|
|
216
|
+
i = end;
|
|
204
217
|
}
|
|
205
|
-
|
|
206
|
-
|
|
218
|
+
if (start < text.length) {
|
|
219
|
+
const remaining = text.slice(start).trim();
|
|
220
|
+
if (remaining.length > 0) sentences.push(remaining);
|
|
221
|
+
}
|
|
222
|
+
return sentences;
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
// ---------------------------------------------------------------------------
|
|
@@ -289,7 +289,10 @@ export function parseOperatorAwareConsolidationResponse(
|
|
|
289
289
|
if (trimmed.length === 0) return fallback;
|
|
290
290
|
|
|
291
291
|
// Strip a fenced code block if present.
|
|
292
|
-
|
|
292
|
+
// Dropped the \s* groups around the lazy body (they overlapped it and
|
|
293
|
+
// backtracked polynomially — CodeQL js/polynomial-redos). Input is already
|
|
294
|
+
// trimmed and fenced[1] is trimmed below, so matches are identical.
|
|
295
|
+
const fenced = /^```(?:json)?([\s\S]*?)```$/u.exec(trimmed);
|
|
293
296
|
const payload = fenced ? fenced[1].trim() : trimmed;
|
|
294
297
|
|
|
295
298
|
// Find a balanced brace-delimited JSON object that has an `operator`
|
|
@@ -1431,3 +1431,24 @@ test("hasCitationForTemplate: multi-separator template detects citation when int
|
|
|
1431
1431
|
"multi-colon citation where intermediate value contains the separator should be detected",
|
|
1432
1432
|
);
|
|
1433
1433
|
});
|
|
1434
|
+
|
|
1435
|
+
test("citation matcher resists polynomial ReDoS on hostile unterminated input (CodeQL js/polynomial-redos)", () => {
|
|
1436
|
+
// A "[Source:" with a long run of whitespace and no closing "]" is the
|
|
1437
|
+
// backtracking trigger for the old /\[Source:\s*([^\]\n]+?)\]/ pattern.
|
|
1438
|
+
const hostile = `prefix [Source:${" ".repeat(100000)}no closing bracket`;
|
|
1439
|
+
const start = process.hrtime.bigint();
|
|
1440
|
+
const detected = hasCitation(hostile);
|
|
1441
|
+
const parsed = parseAllCitations(hostile);
|
|
1442
|
+
const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6;
|
|
1443
|
+
|
|
1444
|
+
// No complete citation token (no closing "]"), so nothing should be detected.
|
|
1445
|
+
assert.equal(detected, false);
|
|
1446
|
+
assert.deepEqual(parsed, []);
|
|
1447
|
+
// Linear scan: completes near-instantly. Generous bound guards against the
|
|
1448
|
+
// quadratic blowup the old regex exhibited (seconds-to-minutes on this input).
|
|
1449
|
+
assert.ok(elapsedMs < 1000, `citation scan took ${elapsedMs.toFixed(1)}ms (expected < 1000ms)`);
|
|
1450
|
+
|
|
1451
|
+
// A well-formed citation with surrounding whitespace is still parsed correctly.
|
|
1452
|
+
const valid = parseAllCitations("body [Source: doc-1 , 2026-06-08 ]");
|
|
1453
|
+
assert.equal(valid.length, 1);
|
|
1454
|
+
});
|
|
@@ -71,7 +71,22 @@ export interface ParsedCitation {
|
|
|
71
71
|
* the text. Kept as a getter factory so callers do not share regex state.
|
|
72
72
|
*/
|
|
73
73
|
function defaultCitationMatcher(): RegExp {
|
|
74
|
-
|
|
74
|
+
// Bounded repetition {1,1024} instead of + so the match cannot backtrack
|
|
75
|
+
// polynomially over hostile memory text (CodeQL js/polynomial-redos). A real
|
|
76
|
+
// citation is far shorter than 1024 chars, so this is behavior-preserving for
|
|
77
|
+
// any genuine [Source: …] block; only pathological/oversized input is excluded.
|
|
78
|
+
return /\[Source:([^\]\n]{1,1024})\]/gi;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Linear trailing-whitespace trim. Replaces text.replace(/\s+$/u, ""), whose
|
|
82
|
+
// anchored quantifier backtracks polynomially on long inputs (CodeQL
|
|
83
|
+
// js/polynomial-redos). Matches the exact \s (with u flag) semantics one char
|
|
84
|
+
// at a time, so the trailing-content preservation logic in attachCitation is
|
|
85
|
+
// unaffected.
|
|
86
|
+
function trimTrailingWhitespace(text: string): string {
|
|
87
|
+
let end = text.length;
|
|
88
|
+
while (end > 0 && /\s/u.test(text[end - 1]!)) end--;
|
|
89
|
+
return text.slice(0, end);
|
|
75
90
|
}
|
|
76
91
|
|
|
77
92
|
/**
|
|
@@ -444,7 +459,7 @@ export function attachCitation(
|
|
|
444
459
|
): string {
|
|
445
460
|
if (typeof text !== "string") return text as unknown as string;
|
|
446
461
|
if (hasCitationForTemplate(text, template)) return text;
|
|
447
|
-
const trimmedEnd = text
|
|
462
|
+
const trimmedEnd = trimTrailingWhitespace(text);
|
|
448
463
|
if (trimmedEnd.length === 0) return text;
|
|
449
464
|
const citation = formatCitation(ctx, template);
|
|
450
465
|
// Preserve any trailing newline that callers rely on for markdown rendering.
|
package/src/storage.ts
CHANGED
|
@@ -1905,7 +1905,12 @@ export function parseEntityFile(
|
|
|
1905
1905
|
break;
|
|
1906
1906
|
case "connected to": {
|
|
1907
1907
|
// Format: [[target-entity]] — relationship label
|
|
1908
|
-
|
|
1908
|
+
// Drop the \s* after the dash and let (.+) capture the rest (trimmed
|
|
1909
|
+
// below). This removes the \s*/(.+) overlap that backtracks polynomially
|
|
1910
|
+
// (CodeQL js/polynomial-redos) while staying exactly equivalent to the
|
|
1911
|
+
// original /…\s*[—–-]\s*(.+)$/ — including whitespace-only labels, which
|
|
1912
|
+
// still match and trim to "" (unlike a \S-anchored capture).
|
|
1913
|
+
const relMatch = bullet.match(/^\[\[([^\]]+)\]\]\s*[—–-](.+)$/);
|
|
1909
1914
|
if (relMatch) {
|
|
1910
1915
|
relationships.push({ target: relMatch[1].trim(), label: relMatch[2].trim() });
|
|
1911
1916
|
}
|
|
@@ -1913,7 +1918,11 @@ export function parseEntityFile(
|
|
|
1913
1918
|
}
|
|
1914
1919
|
case "activity": {
|
|
1915
1920
|
// Format: YYYY-MM-DD: note
|
|
1916
|
-
|
|
1921
|
+
// Drop the \s* after the colon and let (.+) capture the rest (trimmed
|
|
1922
|
+
// below): removes the \s*/(.+) overlap (CodeQL js/polynomial-redos) and
|
|
1923
|
+
// stays exactly equivalent to the original, including whitespace-only
|
|
1924
|
+
// notes which still match and trim to "".
|
|
1925
|
+
const actMatch = bullet.match(/^(\d{4}-\d{2}-\d{2}):(.+)$/);
|
|
1917
1926
|
if (actMatch) {
|
|
1918
1927
|
activity.push({ date: actMatch[1], note: actMatch[2].trim() });
|
|
1919
1928
|
}
|
|
@@ -37,7 +37,10 @@ export function normalizeSupersessionKey(raw: string): string {
|
|
|
37
37
|
.trim()
|
|
38
38
|
.toLowerCase()
|
|
39
39
|
.replace(/[\s\-]+/g, "-")
|
|
40
|
-
|
|
40
|
+
// The previous line already collapsed runs to single hyphens, so ^-|-$ is
|
|
41
|
+
// equivalent to ^-+|-+$ here and drops the anchored quantifier flagged by
|
|
42
|
+
// CodeQL js/polynomial-redos.
|
|
43
|
+
.replace(/^-|-$/g, "");
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
/**
|