@agenr/skeln-plugin 3.3.0 → 2026.6.2
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/build-before-turn-artifact-NPUHVWFE.js +71 -0
- package/dist/build-recall-artifact-F3LS3PZX.js +62 -0
- package/dist/chunk-5AXMFBHR.js +14 -0
- package/dist/chunk-5AYIXQRF.js +4452 -0
- package/dist/{chunk-Z5X7T4QZ.js → chunk-5TIP2EPP.js} +1519 -2565
- package/dist/{chunk-5LADPJ4C.js → chunk-GAERET5Q.js} +138 -504
- package/dist/chunk-GF3PX3VM.js +41 -0
- package/dist/chunk-GKZQ5AG5.js +44 -0
- package/dist/chunk-LDJN7CVU.js +3231 -0
- package/dist/{chunk-ZYADFKX3.js → chunk-MC3C2XM5.js} +34 -1
- package/dist/chunk-NBS62ES5.js +3012 -0
- package/dist/chunk-NSLTJBUC.js +270 -0
- package/dist/chunk-OJSIZDZD.js +9 -0
- package/dist/chunk-OWGQWQUP.js +45 -0
- package/dist/chunk-Q5UTJXHZ.js +1069 -0
- package/dist/{chunk-M5M65AYP.js → chunk-SOQW7356.js} +271 -1934
- package/dist/chunk-VBPYU7GO.js +597 -0
- package/dist/chunk-VTHBPXDQ.js +1750 -0
- package/dist/{chunk-KH52KJSJ.js → chunk-XFJ4S4G2.js} +844 -39
- package/dist/chunk-Y5NB3FTH.js +106 -0
- package/dist/{chunk-RYMSM3OS.js → chunk-ZX55JBV2.js} +1710 -322
- package/dist/claim-slot-policy-CdrW_1l4.d.ts +13 -0
- package/dist/index.d.ts +630 -51
- package/dist/index.js +881 -4682
- package/dist/lifecycle-checkpoint-IAC5FCQU.js +154 -0
- package/dist/{claim-slot-policy-CQ-h0GaV.d.ts → ports-C4QkwDBS.d.ts} +168 -78
- package/dist/scan-6JKPOQHD.js +6 -0
- package/dist/service-EKFACEN6.js +15 -0
- package/dist/service-RHNB5AEQ.js +861 -0
- package/dist/sink-AUAAWC5O.js +8 -0
- package/package.json +1 -1
- package/dist/cli.d.ts +0 -1
- package/dist/internal-eval-server.d.ts +0 -1
- package/dist/internal-recall-eval-server.d.ts +0 -1
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isCurrentlyValidMemory,
|
|
3
|
+
isStaleMemory,
|
|
4
|
+
isWithinValidityWindow,
|
|
5
|
+
normalizeClaimKey,
|
|
6
|
+
resolveKeyedDurableLifecycleStatus
|
|
7
|
+
} from "./chunk-VBPYU7GO.js";
|
|
8
|
+
|
|
1
9
|
// src/core/recall/cross-encoder.ts
|
|
2
10
|
var DEFAULT_CROSS_ENCODER_TOP_K = 10;
|
|
3
11
|
var DEFAULT_CROSS_ENCODER_ALPHA = 0.6;
|
|
@@ -125,6 +133,41 @@ function elapsedMs(startedAt) {
|
|
|
125
133
|
return Math.max(0, Date.now() - startedAt);
|
|
126
134
|
}
|
|
127
135
|
|
|
136
|
+
// src/core/recall/entry-lineage.ts
|
|
137
|
+
function describeDurableLineageState(entry, nowMs) {
|
|
138
|
+
if (entry.superseded_by) {
|
|
139
|
+
return "superseded";
|
|
140
|
+
}
|
|
141
|
+
if (!isCurrentlyValidMemory(entry, nowMs)) {
|
|
142
|
+
return "historical";
|
|
143
|
+
}
|
|
144
|
+
return "current";
|
|
145
|
+
}
|
|
146
|
+
function formatDurableClaimLifecycle(entry) {
|
|
147
|
+
const status = resolveKeyedDurableLifecycleStatus(entry);
|
|
148
|
+
return status === "no_key" ? "no-key" : status;
|
|
149
|
+
}
|
|
150
|
+
function summarizeClaimFamilyTransition(entries, nowMs) {
|
|
151
|
+
const current = entries.find((entry) => isCurrentlyValidMemory(entry, nowMs));
|
|
152
|
+
const prior = [...entries].reverse().find((entry) => entry.id !== current?.id && isHistoricalFamilyMember(entry, nowMs));
|
|
153
|
+
if (current && prior) {
|
|
154
|
+
return `${prior.id} -> ${current.id}`;
|
|
155
|
+
}
|
|
156
|
+
if (prior) {
|
|
157
|
+
return `${prior.id} is historical with no current sibling in the traced family`;
|
|
158
|
+
}
|
|
159
|
+
if (current) {
|
|
160
|
+
return `${current.id} is the only current sibling in the traced family`;
|
|
161
|
+
}
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
function isHistoricalFamilyMember(entry, nowMs) {
|
|
165
|
+
if (entry.superseded_by) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
return !isCurrentlyValidMemory(entry, nowMs);
|
|
169
|
+
}
|
|
170
|
+
|
|
128
171
|
// src/core/recall/fusion.ts
|
|
129
172
|
var DEFAULT_RRF_RANK_CONSTANT = 60;
|
|
130
173
|
var DEFAULT_RRF_SMALL_POOL_RANK_CONSTANT = 8;
|
|
@@ -268,9 +311,10 @@ var STOP_WORDS = /* @__PURE__ */ new Set([
|
|
|
268
311
|
]);
|
|
269
312
|
var FTS_OPERATOR_TOKENS = /* @__PURE__ */ new Set(["or", "not", "near"]);
|
|
270
313
|
var LEXICAL_TOKEN_PATTERN = /[\p{L}\p{N}][\p{L}\p{N}._-]*/gu;
|
|
314
|
+
var TOKEN_EDGE_PUNCTUATION_PATTERN = /^[._-]+|[._-]+$/gu;
|
|
271
315
|
function tokenize(text) {
|
|
272
316
|
const matches = normalizeLexicalText(text).match(LEXICAL_TOKEN_PATTERN) ?? [];
|
|
273
|
-
return matches.filter((token) => token.length >= 2 && !STOP_WORDS.has(token));
|
|
317
|
+
return matches.map((token) => token.replace(TOKEN_EDGE_PUNCTUATION_PATTERN, "")).filter((token) => token.length >= 2 && !STOP_WORDS.has(token));
|
|
274
318
|
}
|
|
275
319
|
function buildLexicalPlan(text) {
|
|
276
320
|
const trimmed = text.trim();
|
|
@@ -696,468 +740,6 @@ function sanitizeInteger(value, fallback) {
|
|
|
696
740
|
return Math.floor(value);
|
|
697
741
|
}
|
|
698
742
|
|
|
699
|
-
// src/core/claim-key.ts
|
|
700
|
-
var UNKNOWN_SEGMENT = "unknown";
|
|
701
|
-
var SELF_REFERENTIAL_ENTITIES = /* @__PURE__ */ new Set(["i", "me", "myself", "the_user", "user", "we", "our_team", "the_project", "this_project"]);
|
|
702
|
-
var GENERIC_ENTITIES = /* @__PURE__ */ new Set([
|
|
703
|
-
"app",
|
|
704
|
-
"company",
|
|
705
|
-
"config",
|
|
706
|
-
"data",
|
|
707
|
-
"device",
|
|
708
|
-
"entity",
|
|
709
|
-
"environment",
|
|
710
|
-
"item",
|
|
711
|
-
"organization",
|
|
712
|
-
"person",
|
|
713
|
-
"place",
|
|
714
|
-
"project",
|
|
715
|
-
"service",
|
|
716
|
-
"setting",
|
|
717
|
-
"system",
|
|
718
|
-
"team",
|
|
719
|
-
"thing",
|
|
720
|
-
"user",
|
|
721
|
-
"workspace"
|
|
722
|
-
]);
|
|
723
|
-
var GENERIC_ATTRIBUTES = /* @__PURE__ */ new Set(["info", "details", "config", "stuff", "thing", "data"]);
|
|
724
|
-
var COMPACTION_RELATION_TOKENS = /* @__PURE__ */ new Set([
|
|
725
|
-
"after",
|
|
726
|
-
"before",
|
|
727
|
-
"depend",
|
|
728
|
-
"depends",
|
|
729
|
-
"follows",
|
|
730
|
-
"follow",
|
|
731
|
-
"keep",
|
|
732
|
-
"keeps",
|
|
733
|
-
"maintain",
|
|
734
|
-
"maintains",
|
|
735
|
-
"need",
|
|
736
|
-
"needs",
|
|
737
|
-
"precede",
|
|
738
|
-
"precedes",
|
|
739
|
-
"preserve",
|
|
740
|
-
"preserves",
|
|
741
|
-
"require",
|
|
742
|
-
"required",
|
|
743
|
-
"requires",
|
|
744
|
-
"retain",
|
|
745
|
-
"retains"
|
|
746
|
-
]);
|
|
747
|
-
var COMPACTION_BREAK_TOKENS = /* @__PURE__ */ new Set(["about", "across", "and", "between", "during", "for", "from", "into", "onto", "or", "to", "with"]);
|
|
748
|
-
var COMPACTION_WEAK_LEADING_TOKENS = /* @__PURE__ */ new Set(["actual", "authoritative", "canonical", "concrete", "current", "durable", "existing", "real"]);
|
|
749
|
-
var ACTION_CONDITION_TOKENS = /* @__PURE__ */ new Set(["activate", "activation", "apply", "fire", "launch", "run", "start", "trigger"]);
|
|
750
|
-
var TRAILING_OBJECT_COMPACTION_PREPOSITIONS = /* @__PURE__ */ new Set(["about", "for", "from", "into", "onto", "to", "with"]);
|
|
751
|
-
var TRAILING_OBJECT_TRANSFER_HEADS = /* @__PURE__ */ new Set([
|
|
752
|
-
"access",
|
|
753
|
-
"boundary",
|
|
754
|
-
"condition",
|
|
755
|
-
"contract",
|
|
756
|
-
"guide",
|
|
757
|
-
"path",
|
|
758
|
-
"policy",
|
|
759
|
-
"preference",
|
|
760
|
-
"process",
|
|
761
|
-
"rule",
|
|
762
|
-
"schedule",
|
|
763
|
-
"support",
|
|
764
|
-
"surface",
|
|
765
|
-
"window",
|
|
766
|
-
"workflow"
|
|
767
|
-
]);
|
|
768
|
-
var STABLE_ATTRIBUTE_HEADS = /* @__PURE__ */ new Set([
|
|
769
|
-
"access",
|
|
770
|
-
"boundary",
|
|
771
|
-
"condition",
|
|
772
|
-
"contract",
|
|
773
|
-
"default",
|
|
774
|
-
"dependency",
|
|
775
|
-
"guide",
|
|
776
|
-
"mode",
|
|
777
|
-
"order",
|
|
778
|
-
"path",
|
|
779
|
-
"policy",
|
|
780
|
-
"preference",
|
|
781
|
-
"preservation",
|
|
782
|
-
"process",
|
|
783
|
-
"requirement",
|
|
784
|
-
"rule",
|
|
785
|
-
"schedule",
|
|
786
|
-
"setting",
|
|
787
|
-
"status",
|
|
788
|
-
"strategy",
|
|
789
|
-
"support",
|
|
790
|
-
"surface",
|
|
791
|
-
"timezone",
|
|
792
|
-
"truth",
|
|
793
|
-
"version",
|
|
794
|
-
"window",
|
|
795
|
-
"workflow"
|
|
796
|
-
]);
|
|
797
|
-
function normalizeClaimKeySegment(value) {
|
|
798
|
-
return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
799
|
-
}
|
|
800
|
-
function normalizeClaimKey(value) {
|
|
801
|
-
const trimmed = value.trim();
|
|
802
|
-
if (trimmed.length === 0) {
|
|
803
|
-
return { ok: false, reason: "empty" };
|
|
804
|
-
}
|
|
805
|
-
const slashCount = Array.from(trimmed).filter((character) => character === "/").length;
|
|
806
|
-
if (slashCount === 0) {
|
|
807
|
-
return { ok: false, reason: "missing_separator" };
|
|
808
|
-
}
|
|
809
|
-
if (slashCount !== 1) {
|
|
810
|
-
return { ok: false, reason: "too_many_segments" };
|
|
811
|
-
}
|
|
812
|
-
const [rawEntity = "", rawAttribute = ""] = trimmed.split("/");
|
|
813
|
-
const entity = normalizeClaimKeySegment(rawEntity);
|
|
814
|
-
if (entity.length === 0) {
|
|
815
|
-
return { ok: false, reason: "empty_entity" };
|
|
816
|
-
}
|
|
817
|
-
const attribute = normalizeClaimKeySegment(rawAttribute);
|
|
818
|
-
if (attribute.length === 0) {
|
|
819
|
-
return { ok: false, reason: "empty_attribute" };
|
|
820
|
-
}
|
|
821
|
-
if (entity === UNKNOWN_SEGMENT && attribute === UNKNOWN_SEGMENT) {
|
|
822
|
-
return { ok: false, reason: "unknown_pair" };
|
|
823
|
-
}
|
|
824
|
-
return {
|
|
825
|
-
ok: true,
|
|
826
|
-
value: {
|
|
827
|
-
claimKey: `${entity}/${attribute}`,
|
|
828
|
-
entity,
|
|
829
|
-
attribute
|
|
830
|
-
}
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
function compactClaimKey(claimKey) {
|
|
834
|
-
const normalized = normalizeClaimKey(claimKey);
|
|
835
|
-
if (!normalized.ok) {
|
|
836
|
-
return null;
|
|
837
|
-
}
|
|
838
|
-
let attributeTokens = normalized.value.attribute.split("_").filter((token) => token.length > 0);
|
|
839
|
-
const entityTokens = normalized.value.entity.split("_").filter((token) => token.length > 0);
|
|
840
|
-
const reasons = [];
|
|
841
|
-
if (entityTokens.length > 0 && startsWithTokens(attributeTokens, entityTokens) && attributeTokens.length > entityTokens.length) {
|
|
842
|
-
attributeTokens = attributeTokens.slice(entityTokens.length);
|
|
843
|
-
reasons.push("removed duplicated entity prefix from attribute");
|
|
844
|
-
}
|
|
845
|
-
if (entityTokens.length > 0 && attributeTokens.length > entityTokens.length + 1 && endsWithTokens(attributeTokens, entityTokens) && TRAILING_OBJECT_COMPACTION_PREPOSITIONS.has(attributeTokens[attributeTokens.length - entityTokens.length - 1] ?? "")) {
|
|
846
|
-
attributeTokens = attributeTokens.slice(0, attributeTokens.length - entityTokens.length - 1);
|
|
847
|
-
reasons.push("removed duplicated entity suffix from attribute");
|
|
848
|
-
}
|
|
849
|
-
const sourceOfTruthCompaction = compactSourceOfTruthAttribute(attributeTokens);
|
|
850
|
-
if (sourceOfTruthCompaction) {
|
|
851
|
-
attributeTokens = sourceOfTruthCompaction.attributeTokens;
|
|
852
|
-
reasons.push(sourceOfTruthCompaction.reason);
|
|
853
|
-
} else {
|
|
854
|
-
const relationCompaction = compactRelationAttribute(attributeTokens);
|
|
855
|
-
if (relationCompaction) {
|
|
856
|
-
attributeTokens = relationCompaction.attributeTokens;
|
|
857
|
-
reasons.push(relationCompaction.reason);
|
|
858
|
-
} else {
|
|
859
|
-
const trailingObjectCompaction = compactTrailingObjectAttribute(attributeTokens);
|
|
860
|
-
if (trailingObjectCompaction) {
|
|
861
|
-
attributeTokens = trailingObjectCompaction.attributeTokens;
|
|
862
|
-
reasons.push(trailingObjectCompaction.reason);
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
const attribute = attributeTokens.join("_");
|
|
867
|
-
if (attribute.length === 0) {
|
|
868
|
-
return {
|
|
869
|
-
claimKey: normalized.value.claimKey,
|
|
870
|
-
entity: normalized.value.entity,
|
|
871
|
-
attribute: normalized.value.attribute,
|
|
872
|
-
compactedFrom: null,
|
|
873
|
-
reason: null
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
const compactedClaimKey = `${normalized.value.entity}/${attribute}`;
|
|
877
|
-
return {
|
|
878
|
-
claimKey: compactedClaimKey,
|
|
879
|
-
entity: normalized.value.entity,
|
|
880
|
-
attribute,
|
|
881
|
-
compactedFrom: compactedClaimKey !== normalized.value.claimKey ? normalized.value.claimKey : null,
|
|
882
|
-
reason: reasons.length > 0 ? joinCompactionReasons(reasons) : null
|
|
883
|
-
};
|
|
884
|
-
}
|
|
885
|
-
function validateExtractedClaimKey(claimKey) {
|
|
886
|
-
if (SELF_REFERENTIAL_ENTITIES.has(claimKey.entity)) {
|
|
887
|
-
return {
|
|
888
|
-
ok: false,
|
|
889
|
-
reason: "self_referential_entity",
|
|
890
|
-
value: claimKey
|
|
891
|
-
};
|
|
892
|
-
}
|
|
893
|
-
if (GENERIC_ATTRIBUTES.has(claimKey.attribute)) {
|
|
894
|
-
return {
|
|
895
|
-
ok: false,
|
|
896
|
-
reason: "generic_attribute",
|
|
897
|
-
value: claimKey
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
if (isValueShapedAttribute(claimKey.attribute)) {
|
|
901
|
-
return {
|
|
902
|
-
ok: false,
|
|
903
|
-
reason: "value_shaped_attribute",
|
|
904
|
-
value: claimKey
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
|
-
return {
|
|
908
|
-
ok: true,
|
|
909
|
-
value: claimKey
|
|
910
|
-
};
|
|
911
|
-
}
|
|
912
|
-
function inspectClaimKey(value) {
|
|
913
|
-
const rawClaimKey = value.trim();
|
|
914
|
-
const normalized = normalizeClaimKey(rawClaimKey);
|
|
915
|
-
if (!normalized.ok) {
|
|
916
|
-
return {
|
|
917
|
-
rawClaimKey,
|
|
918
|
-
canonical: false,
|
|
919
|
-
normalizationFailure: normalized.reason,
|
|
920
|
-
suspectReasons: []
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
const suspectReasons = /* @__PURE__ */ new Set();
|
|
924
|
-
const validation = validateExtractedClaimKey(normalized.value);
|
|
925
|
-
if (!validation.ok) {
|
|
926
|
-
suspectReasons.add(validation.reason);
|
|
927
|
-
}
|
|
928
|
-
if (GENERIC_ENTITIES.has(normalized.value.entity)) {
|
|
929
|
-
suspectReasons.add("generic_entity");
|
|
930
|
-
}
|
|
931
|
-
return {
|
|
932
|
-
rawClaimKey,
|
|
933
|
-
canonical: normalized.value.claimKey === rawClaimKey,
|
|
934
|
-
normalized: normalized.value,
|
|
935
|
-
suspectReasons: [...suspectReasons]
|
|
936
|
-
};
|
|
937
|
-
}
|
|
938
|
-
function isTrustedClaimKeyForCleanup(value) {
|
|
939
|
-
const inspection = inspectClaimKey(value);
|
|
940
|
-
return Boolean(inspection.canonical && inspection.normalized && inspection.suspectReasons.length === 0);
|
|
941
|
-
}
|
|
942
|
-
function describeClaimKeyNormalizationFailure(reason) {
|
|
943
|
-
switch (reason) {
|
|
944
|
-
case "empty":
|
|
945
|
-
return "claim key was empty";
|
|
946
|
-
case "missing_separator":
|
|
947
|
-
return "claim key must contain exactly one '/'";
|
|
948
|
-
case "too_many_segments":
|
|
949
|
-
return "claim key must contain exactly one '/'";
|
|
950
|
-
case "empty_entity":
|
|
951
|
-
return "claim key entity was empty after normalization";
|
|
952
|
-
case "empty_attribute":
|
|
953
|
-
return "claim key attribute was empty after normalization";
|
|
954
|
-
case "unknown_pair":
|
|
955
|
-
return 'claim key "unknown/unknown" is not allowed';
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
function describeExtractedClaimKeyRejection(reason, claimKey) {
|
|
959
|
-
switch (reason) {
|
|
960
|
-
case "self_referential_entity":
|
|
961
|
-
return `entity "${claimKey.entity}" is self-referential`;
|
|
962
|
-
case "generic_attribute":
|
|
963
|
-
return `attribute "${claimKey.attribute}" is too generic`;
|
|
964
|
-
case "value_shaped_attribute":
|
|
965
|
-
return `attribute "${claimKey.attribute}" looks value-shaped`;
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
function describeClaimKeySuspicion(reason, claimKey) {
|
|
969
|
-
switch (reason) {
|
|
970
|
-
case "generic_entity":
|
|
971
|
-
return `entity "${claimKey.entity}" is too generic`;
|
|
972
|
-
case "self_referential_entity":
|
|
973
|
-
case "generic_attribute":
|
|
974
|
-
case "value_shaped_attribute":
|
|
975
|
-
return describeExtractedClaimKeyRejection(reason, claimKey);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
function isValueShapedAttribute(attribute) {
|
|
979
|
-
return /^\d+(?:_\d+)*$/u.test(attribute) || /^v\d+(?:_\d+)*$/u.test(attribute);
|
|
980
|
-
}
|
|
981
|
-
function compactSourceOfTruthAttribute(attributeTokens) {
|
|
982
|
-
const sourceOfTruthIndex = findSourceOfTruthPhraseIndex(attributeTokens);
|
|
983
|
-
if (sourceOfTruthIndex === -1) {
|
|
984
|
-
return null;
|
|
985
|
-
}
|
|
986
|
-
const normalizedPhrase = ["source", "of", "truth"];
|
|
987
|
-
if (attributeTokens.length === normalizedPhrase.length && startsWithTokens(attributeTokens, normalizedPhrase)) {
|
|
988
|
-
return null;
|
|
989
|
-
}
|
|
990
|
-
const before = attributeTokens.slice(0, sourceOfTruthIndex);
|
|
991
|
-
const after = attributeTokens.slice(sourceOfTruthIndex + normalizedPhrase.length);
|
|
992
|
-
const leadingAllowed = before.every((token) => COMPACTION_WEAK_LEADING_TOKENS.has(token));
|
|
993
|
-
const hasMixedStableFamily = before.some((token) => STABLE_ATTRIBUTE_HEADS.has(token)) || after.some((token) => STABLE_ATTRIBUTE_HEADS.has(token));
|
|
994
|
-
const hasConjunctionNoise = before.includes("and") || before.includes("or") || after.includes("and") || after.includes("or");
|
|
995
|
-
if (!leadingAllowed || hasMixedStableFamily || hasConjunctionNoise) {
|
|
996
|
-
return null;
|
|
997
|
-
}
|
|
998
|
-
return {
|
|
999
|
-
attributeTokens: normalizedPhrase,
|
|
1000
|
-
reason: "collapsed source-of-truth phrasing into the stable canonical slot"
|
|
1001
|
-
};
|
|
1002
|
-
}
|
|
1003
|
-
function compactRelationAttribute(attributeTokens) {
|
|
1004
|
-
const relationIndex = attributeTokens.findIndex((token) => COMPACTION_RELATION_TOKENS.has(token));
|
|
1005
|
-
if (relationIndex === -1) {
|
|
1006
|
-
return null;
|
|
1007
|
-
}
|
|
1008
|
-
const relation = attributeTokens[relationIndex] ?? "";
|
|
1009
|
-
const left = attributeTokens.slice(0, relationIndex);
|
|
1010
|
-
const right = attributeTokens.slice(relationIndex + 1);
|
|
1011
|
-
if (left.length === 0 && right.length === 0) {
|
|
1012
|
-
return null;
|
|
1013
|
-
}
|
|
1014
|
-
if (isRequirementRelation(relation)) {
|
|
1015
|
-
const conditionAction = extractConditionAction(right);
|
|
1016
|
-
if (conditionAction) {
|
|
1017
|
-
return {
|
|
1018
|
-
attributeTokens: [conditionAction, "condition"],
|
|
1019
|
-
reason: `collapsed a sentence-like ${conditionAction} requirement into a stable condition slot`
|
|
1020
|
-
};
|
|
1021
|
-
}
|
|
1022
|
-
const requirementFocus = extractCompactionFocus(right, 2) ?? extractCompactionFocus(left, 2);
|
|
1023
|
-
if (!requirementFocus) {
|
|
1024
|
-
return null;
|
|
1025
|
-
}
|
|
1026
|
-
return {
|
|
1027
|
-
attributeTokens: [...requirementFocus, "requirement"],
|
|
1028
|
-
reason: "collapsed a sentence-like requirement phrase into a stable requirement slot"
|
|
1029
|
-
};
|
|
1030
|
-
}
|
|
1031
|
-
if (isOrderingRelation(relation)) {
|
|
1032
|
-
const orderingFocus = extractCompactionFocus(right, 2) ?? extractCompactionFocus(left, 2);
|
|
1033
|
-
if (!orderingFocus) {
|
|
1034
|
-
return null;
|
|
1035
|
-
}
|
|
1036
|
-
return {
|
|
1037
|
-
attributeTokens: [...orderingFocus, "order"],
|
|
1038
|
-
reason: "collapsed a sentence-like ordering phrase into a stable order slot"
|
|
1039
|
-
};
|
|
1040
|
-
}
|
|
1041
|
-
if (isPreservationRelation(relation)) {
|
|
1042
|
-
const preservationFocus = extractCompactionFocus(right, 2) ?? extractCompactionFocus(left, 2);
|
|
1043
|
-
if (!preservationFocus) {
|
|
1044
|
-
return null;
|
|
1045
|
-
}
|
|
1046
|
-
return {
|
|
1047
|
-
attributeTokens: [...preservationFocus, "preservation"],
|
|
1048
|
-
reason: "collapsed a sentence-like preservation phrase into a stable preservation slot"
|
|
1049
|
-
};
|
|
1050
|
-
}
|
|
1051
|
-
return null;
|
|
1052
|
-
}
|
|
1053
|
-
function compactTrailingObjectAttribute(attributeTokens) {
|
|
1054
|
-
const prepositionIndex = attributeTokens.findIndex((token) => TRAILING_OBJECT_COMPACTION_PREPOSITIONS.has(token));
|
|
1055
|
-
if (prepositionIndex <= 0 || prepositionIndex >= attributeTokens.length - 1) {
|
|
1056
|
-
return null;
|
|
1057
|
-
}
|
|
1058
|
-
const left = trimWeakLeadingTokens(attributeTokens.slice(0, prepositionIndex));
|
|
1059
|
-
const right = attributeTokens.slice(prepositionIndex + 1);
|
|
1060
|
-
if (left.length === 0 || left.length > 3 || left.includes("and") || left.includes("or") || left.some((token) => COMPACTION_RELATION_TOKENS.has(token))) {
|
|
1061
|
-
return null;
|
|
1062
|
-
}
|
|
1063
|
-
const head = left[left.length - 1];
|
|
1064
|
-
if (!head || !TRAILING_OBJECT_TRANSFER_HEADS.has(head)) {
|
|
1065
|
-
return null;
|
|
1066
|
-
}
|
|
1067
|
-
const objectFocus = extractCompactionFocus(right, 2);
|
|
1068
|
-
if (!objectFocus) {
|
|
1069
|
-
return null;
|
|
1070
|
-
}
|
|
1071
|
-
const headCore = extractStableHeadCore(left, 2);
|
|
1072
|
-
if (!headCore) {
|
|
1073
|
-
return null;
|
|
1074
|
-
}
|
|
1075
|
-
return {
|
|
1076
|
-
attributeTokens: [...objectFocus, ...headCore],
|
|
1077
|
-
reason: "collapsed a trailing object phrase into a compact stable slot name"
|
|
1078
|
-
};
|
|
1079
|
-
}
|
|
1080
|
-
function findSourceOfTruthPhraseIndex(tokens) {
|
|
1081
|
-
for (let index = 0; index <= tokens.length - 3; index += 1) {
|
|
1082
|
-
if (tokens[index] === "source" && tokens[index + 1] === "of" && tokens[index + 2] === "truth") {
|
|
1083
|
-
return index;
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
return -1;
|
|
1087
|
-
}
|
|
1088
|
-
function extractConditionAction(tokens) {
|
|
1089
|
-
for (let index = tokens.length - 1; index >= 0; index -= 1) {
|
|
1090
|
-
const token = tokens[index];
|
|
1091
|
-
if (token && ACTION_CONDITION_TOKENS.has(token)) {
|
|
1092
|
-
return token;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
return null;
|
|
1096
|
-
}
|
|
1097
|
-
function extractCompactionFocus(tokens, limit) {
|
|
1098
|
-
const compactable = trimWeakLeadingTokens(tokens).filter((token) => token.length > 0);
|
|
1099
|
-
const segments = splitTokensOnBreaks(compactable).filter((segment) => segment.length > 0);
|
|
1100
|
-
const preferredSegment = segments[0];
|
|
1101
|
-
if (!preferredSegment || preferredSegment.length === 0) {
|
|
1102
|
-
return null;
|
|
1103
|
-
}
|
|
1104
|
-
return preferredSegment.slice(0, limit);
|
|
1105
|
-
}
|
|
1106
|
-
function extractStableHeadCore(tokens, limit) {
|
|
1107
|
-
const compactable = trimWeakLeadingTokens(tokens).filter((token) => token.length > 0);
|
|
1108
|
-
const head = compactable[compactable.length - 1];
|
|
1109
|
-
if (!head || !STABLE_ATTRIBUTE_HEADS.has(head)) {
|
|
1110
|
-
return null;
|
|
1111
|
-
}
|
|
1112
|
-
return compactable.slice(Math.max(0, compactable.length - limit));
|
|
1113
|
-
}
|
|
1114
|
-
function splitTokensOnBreaks(tokens) {
|
|
1115
|
-
const segments = [];
|
|
1116
|
-
let current = [];
|
|
1117
|
-
for (const token of tokens) {
|
|
1118
|
-
if (COMPACTION_BREAK_TOKENS.has(token)) {
|
|
1119
|
-
if (current.length > 0) {
|
|
1120
|
-
segments.push(current);
|
|
1121
|
-
current = [];
|
|
1122
|
-
}
|
|
1123
|
-
continue;
|
|
1124
|
-
}
|
|
1125
|
-
current.push(token);
|
|
1126
|
-
}
|
|
1127
|
-
if (current.length > 0) {
|
|
1128
|
-
segments.push(current);
|
|
1129
|
-
}
|
|
1130
|
-
return segments;
|
|
1131
|
-
}
|
|
1132
|
-
function trimWeakLeadingTokens(tokens) {
|
|
1133
|
-
let start = 0;
|
|
1134
|
-
while (start < tokens.length && COMPACTION_WEAK_LEADING_TOKENS.has(tokens[start] ?? "")) {
|
|
1135
|
-
start += 1;
|
|
1136
|
-
}
|
|
1137
|
-
return tokens.slice(start);
|
|
1138
|
-
}
|
|
1139
|
-
function joinCompactionReasons(reasons) {
|
|
1140
|
-
if (reasons.length <= 1) {
|
|
1141
|
-
return reasons[0] ?? "";
|
|
1142
|
-
}
|
|
1143
|
-
return `${reasons.slice(0, -1).join(", ")} and ${reasons[reasons.length - 1]}`;
|
|
1144
|
-
}
|
|
1145
|
-
function isRequirementRelation(token) {
|
|
1146
|
-
return token === "depend" || token === "depends" || token === "need" || token === "needs" || token === "required" || token === "require" || token === "requires";
|
|
1147
|
-
}
|
|
1148
|
-
function isOrderingRelation(token) {
|
|
1149
|
-
return token === "after" || token === "before" || token === "follow" || token === "follows" || token === "precede" || token === "precedes";
|
|
1150
|
-
}
|
|
1151
|
-
function isPreservationRelation(token) {
|
|
1152
|
-
return token === "keep" || token === "keeps" || token === "maintain" || token === "maintains" || token === "preserve" || token === "preserves" || token === "retain" || token === "retains";
|
|
1153
|
-
}
|
|
1154
|
-
function startsWithTokens(tokens, prefix) {
|
|
1155
|
-
return prefix.every((token, index) => tokens[index] === token);
|
|
1156
|
-
}
|
|
1157
|
-
function endsWithTokens(tokens, suffix) {
|
|
1158
|
-
return suffix.every((token, index) => tokens[tokens.length - suffix.length + index] === token);
|
|
1159
|
-
}
|
|
1160
|
-
|
|
1161
743
|
// src/core/claim-slot-policy.ts
|
|
1162
744
|
var MULTIVALUED_ATTRIBUTE_HEADS = /* @__PURE__ */ new Set(["access", "dependency", "guide", "integration", "preference", "requirement", "support"]);
|
|
1163
745
|
function resolveClaimSlotPolicy(claimKey, config) {
|
|
@@ -1294,6 +876,38 @@ var inferMonthAnchor = (monthName, now) => {
|
|
|
1294
876
|
return new Date(Date.UTC(year, monthIndex, 15));
|
|
1295
877
|
};
|
|
1296
878
|
|
|
879
|
+
// src/core/recall/as-of-validity.ts
|
|
880
|
+
function resolveRecallValidAsOf(params) {
|
|
881
|
+
if (params.rankingProfile === "historical_state") {
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
return new Date(params.asOfDate ? params.asOfDate.getTime() : params.nowMs);
|
|
885
|
+
}
|
|
886
|
+
function applyAsOfValidityFilter(mergeOutcome, summary, params) {
|
|
887
|
+
const asOf = resolveRecallValidAsOf(params);
|
|
888
|
+
if (asOf === null) {
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
const asOfMs = asOf.getTime();
|
|
892
|
+
const removed = /* @__PURE__ */ new Set();
|
|
893
|
+
for (const [id, candidate] of mergeOutcome.merged) {
|
|
894
|
+
if (!isWithinValidityWindow(candidate.entry.valid_from, candidate.entry.valid_to, asOfMs)) {
|
|
895
|
+
mergeOutcome.merged.delete(id);
|
|
896
|
+
removed.add(id);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
if (removed.size > 0) {
|
|
900
|
+
mergeOutcome.vectorRanks = mergeOutcome.vectorRanks.filter((id) => !removed.has(id));
|
|
901
|
+
mergeOutcome.ftsRanks = mergeOutcome.ftsRanks.filter((id) => !removed.has(id));
|
|
902
|
+
}
|
|
903
|
+
summary.filtering.asOfValidity = {
|
|
904
|
+
applied: true,
|
|
905
|
+
anchor: new Date(asOfMs).toISOString(),
|
|
906
|
+
source: params.asOfDate ? "explicit_as_of" : "now",
|
|
907
|
+
excludedCount: removed.size
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
|
|
1297
911
|
// src/core/recall/trace.ts
|
|
1298
912
|
var NOOP_RECALL_TRACE_SINK = {
|
|
1299
913
|
reportSummary() {
|
|
@@ -1308,7 +922,7 @@ var HISTORICAL_NEIGHBORHOOD_FAMILIES = ["supersession_chain", "claim_key_sibling
|
|
|
1308
922
|
var MIN_VECTOR_ONLY_EVIDENCE = 0.3;
|
|
1309
923
|
var HISTORICAL_STATE_FLAT_RECENCY = 0.5;
|
|
1310
924
|
var HISTORICAL_PREDECESSOR_BOOST = 0.08;
|
|
1311
|
-
var
|
|
925
|
+
var HISTORICAL_STALE_PREDECESSOR_BOOST = 0.06;
|
|
1312
926
|
var HISTORICAL_OLDER_STATE_BOOST = 0.08;
|
|
1313
927
|
var HISTORICAL_LINEAGE_GAP_MARGIN = 0.02;
|
|
1314
928
|
var HISTORICAL_LINEAGE_MAX_BONUS = 0.45;
|
|
@@ -1343,14 +957,20 @@ var MIN_VECTOR_WITHOUT_GROUNDED_LEXICAL_SUPPORT = 0.45;
|
|
|
1343
957
|
var GROUNDING_SORT_MAX_SCORE_GAP = 0.03;
|
|
1344
958
|
async function recall(query, ports, options = {}) {
|
|
1345
959
|
const text = query.text.trim();
|
|
960
|
+
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
961
|
+
const nowMs = now.getTime();
|
|
1346
962
|
const limit = normalizeLimit(query.limit);
|
|
1347
963
|
const threshold = normalizeThreshold(query.threshold);
|
|
1348
964
|
const budget = normalizeBudget(query.budget);
|
|
1349
|
-
const asOfDate = query.asOf ? parseAroundDate(query.asOf) : null;
|
|
1350
|
-
const aroundDate = query.around !== void 0 ? parseAroundDate(query.around) : inferAroundDate(text);
|
|
1351
|
-
const since = query.since ? parseRelativeDate(query.since) : null;
|
|
1352
|
-
const until = query.until ? parseRelativeDate(query.until) : null;
|
|
1353
|
-
const filters =
|
|
965
|
+
const asOfDate = query.asOf ? parseAroundDate(query.asOf, now) : null;
|
|
966
|
+
const aroundDate = query.around !== void 0 ? parseAroundDate(query.around, now) : inferAroundDate(text, now);
|
|
967
|
+
const since = query.since ? parseRelativeDate(query.since, now) : null;
|
|
968
|
+
const until = query.until ? parseRelativeDate(query.until, now) : null;
|
|
969
|
+
const filters = buildDurableFilters(query.types, query.tags, since, until, {
|
|
970
|
+
asOfDate,
|
|
971
|
+
nowMs,
|
|
972
|
+
rankingProfile: query.rankingProfile
|
|
973
|
+
});
|
|
1354
974
|
const trace = options.trace ?? createNoopRecallTraceSink();
|
|
1355
975
|
const slotPolicyConfig = options.slotPolicyConfig;
|
|
1356
976
|
const summary = buildRecallTraceSummary({
|
|
@@ -1413,6 +1033,11 @@ async function recall(query, ports, options = {}) {
|
|
|
1413
1033
|
summary.degraded.lexicalOnly = summary.degraded.active && queryEmbedding.length === 0;
|
|
1414
1034
|
const mergeStartedAt = Date.now();
|
|
1415
1035
|
const mergeOutcome = mergeCandidates(vectorCandidates, ftsCandidates);
|
|
1036
|
+
applyAsOfValidityFilter(mergeOutcome, summary, {
|
|
1037
|
+
rankingProfile: query.rankingProfile,
|
|
1038
|
+
asOfDate,
|
|
1039
|
+
nowMs
|
|
1040
|
+
});
|
|
1416
1041
|
const neighborhoodEnabled = options.rankingPolicy?.neighborhood !== "disabled";
|
|
1417
1042
|
const expansionRanks = neighborhoodEnabled ? await expandEntryNeighborhood(mergeOutcome.merged, queryEmbedding, ports, {
|
|
1418
1043
|
rankingProfile: query.rankingProfile,
|
|
@@ -1434,18 +1059,20 @@ async function recall(query, ports, options = {}) {
|
|
|
1434
1059
|
asOfDate,
|
|
1435
1060
|
aroundDate,
|
|
1436
1061
|
aroundRadius: query.aroundRadius,
|
|
1437
|
-
rankingProfile: query.rankingProfile
|
|
1062
|
+
rankingProfile: query.rankingProfile,
|
|
1063
|
+
now
|
|
1438
1064
|
})
|
|
1439
1065
|
),
|
|
1440
1066
|
{
|
|
1441
1067
|
aroundDate,
|
|
1442
|
-
rankingProfile: query.rankingProfile
|
|
1068
|
+
rankingProfile: query.rankingProfile,
|
|
1069
|
+
nowMs
|
|
1443
1070
|
},
|
|
1444
1071
|
summary.claimKey,
|
|
1445
1072
|
slotPolicyConfig
|
|
1446
1073
|
);
|
|
1447
1074
|
const rerankedCandidates = neighborhoodEnabled ? applySeededEntryRerank(historicallyBoosted, summary.neighborhood) : historicallyBoosted;
|
|
1448
|
-
const shaped = applyClaimKeyResultShaping(rerankedCandidates, summary.claimKey, slotPolicyConfig).sort((left, right) => right.score - left.score);
|
|
1075
|
+
const shaped = applyClaimKeyResultShaping(rerankedCandidates, summary.claimKey, nowMs, slotPolicyConfig).sort((left, right) => right.score - left.score);
|
|
1449
1076
|
const diversified = applyMmrDiversification(shaped, queryEmbedding, options.rankingPolicy, summary.mmr);
|
|
1450
1077
|
const scored = await applyEntryCrossEncoderRerank(diversified, text, ports.crossEncoder, options.rankingPolicy, summary.crossEncoder);
|
|
1451
1078
|
summary.timings.scoreCandidatesMs = elapsedMs2(scoreStartedAt);
|
|
@@ -1550,7 +1177,7 @@ function buildRecallTraceSummary(params) {
|
|
|
1550
1177
|
expansionRequested: false,
|
|
1551
1178
|
expansionAvailable: false,
|
|
1552
1179
|
familiesRequested: [],
|
|
1553
|
-
|
|
1180
|
+
includeHistorical: false,
|
|
1554
1181
|
seedIds: [],
|
|
1555
1182
|
expansionCandidates: 0,
|
|
1556
1183
|
strongSeedIds: [],
|
|
@@ -1696,17 +1323,17 @@ async function expandEntryNeighborhood(mergedCandidates, queryEmbedding, ports,
|
|
|
1696
1323
|
return [];
|
|
1697
1324
|
}
|
|
1698
1325
|
const families = HISTORICAL_NEIGHBORHOOD_FAMILIES;
|
|
1699
|
-
const
|
|
1326
|
+
const includeHistorical = true;
|
|
1700
1327
|
const seedIds = Array.from(mergedCandidates.keys());
|
|
1701
1328
|
trace.expansionRequested = true;
|
|
1702
1329
|
trace.familiesRequested = [...families];
|
|
1703
|
-
trace.
|
|
1330
|
+
trace.includeHistorical = includeHistorical;
|
|
1704
1331
|
trace.seedIds = seedIds;
|
|
1705
1332
|
const expanded = await ports.expandNeighborhood({
|
|
1706
1333
|
seedIds,
|
|
1707
1334
|
budget: DEFAULT_NEIGHBORHOOD_BUDGET,
|
|
1708
1335
|
families,
|
|
1709
|
-
|
|
1336
|
+
includeHistorical
|
|
1710
1337
|
});
|
|
1711
1338
|
const ranked = expanded.filter((entry) => !mergedCandidates.has(entry.id)).map((entry) => ({
|
|
1712
1339
|
entry,
|
|
@@ -1772,7 +1399,7 @@ function resolveRecencyScore(entry, params) {
|
|
|
1772
1399
|
if (params.rankingProfile === "historical_state") {
|
|
1773
1400
|
return HISTORICAL_STATE_FLAT_RECENCY;
|
|
1774
1401
|
}
|
|
1775
|
-
return recencyScore(entry.created_at, entry.expiry);
|
|
1402
|
+
return recencyScore(entry.created_at, entry.expiry, params.now);
|
|
1776
1403
|
}
|
|
1777
1404
|
function resolveAsOfScore(entry, asOfDate) {
|
|
1778
1405
|
const validFrom = parseTimestamp(entry.valid_from);
|
|
@@ -1808,7 +1435,7 @@ function applyHistoricalLineageBoosts(candidates, params, claimKeyTrace, slotPol
|
|
|
1808
1435
|
const entries = candidates.map((candidate) => candidate.entry);
|
|
1809
1436
|
const scoresById = new Map(candidates.map((candidate) => [candidate.entry.id, candidate.score]));
|
|
1810
1437
|
return candidates.map((candidate) => {
|
|
1811
|
-
const decision = resolveHistoricalLineageBonus(candidate.entry, entries, scoresById, candidate.score, params.aroundDate, slotPolicyConfig);
|
|
1438
|
+
const decision = resolveHistoricalLineageBonus(candidate.entry, entries, scoresById, candidate.score, params.aroundDate, params.nowMs, slotPolicyConfig);
|
|
1812
1439
|
if (decision.tentativeLineageSuppressed) {
|
|
1813
1440
|
claimKeyTrace.tentativeLineageSuppressed += 1;
|
|
1814
1441
|
}
|
|
@@ -1827,7 +1454,7 @@ function applyHistoricalLineageBoosts(candidates, params, claimKeyTrace, slotPol
|
|
|
1827
1454
|
};
|
|
1828
1455
|
});
|
|
1829
1456
|
}
|
|
1830
|
-
function resolveHistoricalLineageBonus(entry, entries, scoresById, candidateScore, aroundDate, slotPolicyConfig) {
|
|
1457
|
+
function resolveHistoricalLineageBonus(entry, entries, scoresById, candidateScore, aroundDate, nowMs, slotPolicyConfig) {
|
|
1831
1458
|
const directSuccessor = entries.find((peer) => peer.id !== entry.id && entry.superseded_by === peer.id);
|
|
1832
1459
|
if (directSuccessor) {
|
|
1833
1460
|
const successorScore = scoresById.get(directSuccessor.id) ?? 0;
|
|
@@ -1846,7 +1473,7 @@ function resolveHistoricalLineageBonus(entry, entries, scoresById, candidateScor
|
|
|
1846
1473
|
let bestPeerScore = 0;
|
|
1847
1474
|
let peerMatched = false;
|
|
1848
1475
|
for (const peer of entries) {
|
|
1849
|
-
if (peer.id === entry.id || !isPotentialCurrentPeer(peer) || createdAtMs(entry.created_at) >= createdAtMs(peer.created_at)) {
|
|
1476
|
+
if (peer.id === entry.id || !isPotentialCurrentPeer(peer, nowMs) || createdAtMs(entry.created_at) >= createdAtMs(peer.created_at)) {
|
|
1850
1477
|
continue;
|
|
1851
1478
|
}
|
|
1852
1479
|
const relation = resolveHistoricalPeerRelation(entry, peer, entries, slotPolicyConfig);
|
|
@@ -1869,7 +1496,7 @@ function resolveHistoricalLineageBonus(entry, entries, scoresById, candidateScor
|
|
|
1869
1496
|
tentativeLineageSuppressed
|
|
1870
1497
|
};
|
|
1871
1498
|
}
|
|
1872
|
-
const base = entry
|
|
1499
|
+
const base = isStalePredecessor(entry, nowMs) ? HISTORICAL_STALE_PREDECESSOR_BOOST : HISTORICAL_OLDER_STATE_BOOST;
|
|
1873
1500
|
return {
|
|
1874
1501
|
bonus: shapeHistoricalLineageBonus(base, candidateScore, bestPeerScore),
|
|
1875
1502
|
tentativeLineageSuppressed
|
|
@@ -1880,8 +1507,11 @@ function shapeHistoricalLineageBonus(base, candidateScore, successorScore) {
|
|
|
1880
1507
|
const needed = gap > 0 ? gap + HISTORICAL_LINEAGE_GAP_MARGIN : 0;
|
|
1881
1508
|
return Math.min(HISTORICAL_LINEAGE_MAX_BONUS, Math.max(base, needed));
|
|
1882
1509
|
}
|
|
1883
|
-
function isPotentialCurrentPeer(entry) {
|
|
1884
|
-
return
|
|
1510
|
+
function isPotentialCurrentPeer(entry, nowMs) {
|
|
1511
|
+
return isCurrentlyValidMemory(entry, nowMs);
|
|
1512
|
+
}
|
|
1513
|
+
function isStalePredecessor(entry, nowMs) {
|
|
1514
|
+
return isStaleMemory(entry, nowMs);
|
|
1885
1515
|
}
|
|
1886
1516
|
function resolveHistoricalPeerRelation(left, right, entries, slotPolicyConfig) {
|
|
1887
1517
|
if (left.claim_key && right.claim_key && left.claim_key === right.claim_key) {
|
|
@@ -2034,18 +1664,18 @@ function resolveMmrMinPoolSize(policy) {
|
|
|
2034
1664
|
}
|
|
2035
1665
|
return Math.floor(raw);
|
|
2036
1666
|
}
|
|
2037
|
-
function applyClaimKeyResultShaping(candidates, claimKeyTrace, slotPolicyConfig) {
|
|
1667
|
+
function applyClaimKeyResultShaping(candidates, claimKeyTrace, nowMs, slotPolicyConfig) {
|
|
2038
1668
|
if (candidates.length === 0) {
|
|
2039
1669
|
return candidates;
|
|
2040
1670
|
}
|
|
2041
1671
|
const trustedActiveClaimKeys = new Set(
|
|
2042
1672
|
candidates.map((candidate) => candidate.entry).filter(
|
|
2043
|
-
(entry) => isPotentialCurrentPeer(entry) && entry.claim_key && entry.claim_key_status === "trusted" && resolveClaimSlotPolicy(entry.claim_key, slotPolicyConfig).policy === "exclusive"
|
|
1673
|
+
(entry) => isPotentialCurrentPeer(entry, nowMs) && entry.claim_key && entry.claim_key_status === "trusted" && resolveClaimSlotPolicy(entry.claim_key, slotPolicyConfig).policy === "exclusive"
|
|
2044
1674
|
).map((entry) => entry.claim_key)
|
|
2045
1675
|
);
|
|
2046
|
-
const trustedSlotRankById = rankTrustedSlotSiblings(candidates, slotPolicyConfig);
|
|
1676
|
+
const trustedSlotRankById = rankTrustedSlotSiblings(candidates, nowMs, slotPolicyConfig);
|
|
2047
1677
|
return candidates.map((candidate) => {
|
|
2048
|
-
const trustPenalty = shouldPenalizeTentativeCurrentSibling(candidate.entry, trustedActiveClaimKeys) ? CLAIM_KEY_TENTATIVE_CURRENT_PENALTY : 0;
|
|
1678
|
+
const trustPenalty = shouldPenalizeTentativeCurrentSibling(candidate.entry, trustedActiveClaimKeys, nowMs) ? CLAIM_KEY_TENTATIVE_CURRENT_PENALTY : 0;
|
|
2049
1679
|
const redundancyPenalty = resolveTrustedSlotRedundancyPenalty(candidate.entry.id, trustedSlotRankById);
|
|
2050
1680
|
if (trustPenalty <= 0 && redundancyPenalty <= 0) {
|
|
2051
1681
|
return candidate;
|
|
@@ -2067,12 +1697,12 @@ function applyClaimKeyResultShaping(candidates, claimKeyTrace, slotPolicyConfig)
|
|
|
2067
1697
|
};
|
|
2068
1698
|
});
|
|
2069
1699
|
}
|
|
2070
|
-
function rankTrustedSlotSiblings(candidates, slotPolicyConfig) {
|
|
1700
|
+
function rankTrustedSlotSiblings(candidates, nowMs, slotPolicyConfig) {
|
|
2071
1701
|
const candidatesById = new Map(candidates.map((candidate) => [candidate.entry.id, candidate]));
|
|
2072
1702
|
const trustedByClaimKey = /* @__PURE__ */ new Map();
|
|
2073
1703
|
for (const candidate of candidates) {
|
|
2074
1704
|
const claimKey = candidate.entry.claim_key;
|
|
2075
|
-
if (!claimKey || candidate.entry.claim_key_status !== "trusted" || !isPotentialCurrentPeer(candidate.entry) || resolveClaimSlotPolicy(claimKey, slotPolicyConfig).policy !== "exclusive") {
|
|
1705
|
+
if (!claimKey || candidate.entry.claim_key_status !== "trusted" || !isPotentialCurrentPeer(candidate.entry, nowMs) || resolveClaimSlotPolicy(claimKey, slotPolicyConfig).policy !== "exclusive") {
|
|
2076
1706
|
continue;
|
|
2077
1707
|
}
|
|
2078
1708
|
const siblings = trustedByClaimKey.get(claimKey) ?? [];
|
|
@@ -2092,8 +1722,8 @@ function rankTrustedSlotSiblings(candidates, slotPolicyConfig) {
|
|
|
2092
1722
|
function compareCandidatesForTrustedSlotRank(left, right) {
|
|
2093
1723
|
return right.score - left.score || createdAtMs(right.entry.created_at) - createdAtMs(left.entry.created_at) || left.entry.id.localeCompare(right.entry.id);
|
|
2094
1724
|
}
|
|
2095
|
-
function shouldPenalizeTentativeCurrentSibling(entry, trustedActiveClaimKeys) {
|
|
2096
|
-
return isPotentialCurrentPeer(entry) && entry.claim_key !== void 0 && entry.claim_key_status !== "trusted" && trustedActiveClaimKeys.has(entry.claim_key);
|
|
1725
|
+
function shouldPenalizeTentativeCurrentSibling(entry, trustedActiveClaimKeys, nowMs) {
|
|
1726
|
+
return isPotentialCurrentPeer(entry, nowMs) && entry.claim_key !== void 0 && entry.claim_key_status !== "trusted" && trustedActiveClaimKeys.has(entry.claim_key);
|
|
2097
1727
|
}
|
|
2098
1728
|
function resolveTrustedSlotRedundancyPenalty(entryId, trustedSlotRankById) {
|
|
2099
1729
|
const rank = trustedSlotRankById.get(entryId) ?? 0;
|
|
@@ -2199,7 +1829,7 @@ function mergeCandidates(vectorCandidates, ftsCandidates) {
|
|
|
2199
1829
|
ftsRanks
|
|
2200
1830
|
};
|
|
2201
1831
|
}
|
|
2202
|
-
function
|
|
1832
|
+
function buildDurableFilters(types, tags, since, until, options) {
|
|
2203
1833
|
const filters = {};
|
|
2204
1834
|
if (types && types.length > 0) {
|
|
2205
1835
|
filters.types = types;
|
|
@@ -2213,6 +1843,16 @@ function buildEntryFilters(types, tags, since, until) {
|
|
|
2213
1843
|
if (until) {
|
|
2214
1844
|
filters.until = until;
|
|
2215
1845
|
}
|
|
1846
|
+
if (options) {
|
|
1847
|
+
const validAsOf = resolveRecallValidAsOf({
|
|
1848
|
+
rankingProfile: options.rankingProfile,
|
|
1849
|
+
asOfDate: options.asOfDate,
|
|
1850
|
+
nowMs: options.nowMs
|
|
1851
|
+
});
|
|
1852
|
+
if (validAsOf) {
|
|
1853
|
+
filters.validAsOf = validAsOf;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
2216
1856
|
return Object.keys(filters).length > 0 ? filters : void 0;
|
|
2217
1857
|
}
|
|
2218
1858
|
function applyBudget(results, budget) {
|
|
@@ -2362,8 +2002,8 @@ function hasCanonicalConsecutivePhrase(haystack, needle) {
|
|
|
2362
2002
|
function estimateTokens(entry) {
|
|
2363
2003
|
return (entry.subject.length + entry.content.length) / 4;
|
|
2364
2004
|
}
|
|
2365
|
-
function parseAroundDate(value) {
|
|
2366
|
-
return parseRelativeDate(value) ?? inferAroundDate(value);
|
|
2005
|
+
function parseAroundDate(value, now) {
|
|
2006
|
+
return parseRelativeDate(value, now) ?? inferAroundDate(value, now);
|
|
2367
2007
|
}
|
|
2368
2008
|
function normalizeLimit(value) {
|
|
2369
2009
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
@@ -2399,15 +2039,6 @@ export {
|
|
|
2399
2039
|
importanceScore,
|
|
2400
2040
|
scoreCandidate,
|
|
2401
2041
|
cosineSimilarity,
|
|
2402
|
-
normalizeClaimKeySegment,
|
|
2403
|
-
normalizeClaimKey,
|
|
2404
|
-
compactClaimKey,
|
|
2405
|
-
validateExtractedClaimKey,
|
|
2406
|
-
inspectClaimKey,
|
|
2407
|
-
isTrustedClaimKeyForCleanup,
|
|
2408
|
-
describeClaimKeyNormalizationFailure,
|
|
2409
|
-
describeExtractedClaimKeyRejection,
|
|
2410
|
-
describeClaimKeySuspicion,
|
|
2411
2042
|
tokenize,
|
|
2412
2043
|
buildLexicalPlan,
|
|
2413
2044
|
computeLexicalScore,
|
|
@@ -2432,5 +2063,8 @@ export {
|
|
|
2432
2063
|
sharesEntryLineage,
|
|
2433
2064
|
sharesEpisodeLineage,
|
|
2434
2065
|
sharesProcedureLineage,
|
|
2435
|
-
recall
|
|
2066
|
+
recall,
|
|
2067
|
+
describeDurableLineageState,
|
|
2068
|
+
formatDurableClaimLifecycle,
|
|
2069
|
+
summarizeClaimFamilyTransition
|
|
2436
2070
|
};
|