@oscharko-dev/keiko-memory-retrieval 0.2.0
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/.tsbuildinfo +1 -0
- package/dist/context.d.ts +16 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +151 -0
- package/dist/decay.d.ts +2 -0
- package/dist/decay.d.ts.map +1 -0
- package/dist/decay.js +22 -0
- package/dist/diversity.d.ts +8 -0
- package/dist/diversity.d.ts.map +1 -0
- package/dist/diversity.js +87 -0
- package/dist/errors.d.ts +9 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/graph.d.ts +3 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +33 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/ranking.d.ts +19 -0
- package/dist/ranking.d.ts.map +1 -0
- package/dist/ranking.js +266 -0
- package/dist/recency.d.ts +3 -0
- package/dist/recency.d.ts.map +1 -0
- package/dist/recency.js +17 -0
- package/dist/relevance.d.ts +8 -0
- package/dist/relevance.d.ts.map +1 -0
- package/dist/relevance.js +60 -0
- package/dist/retrieve.d.ts +3 -0
- package/dist/retrieve.d.ts.map +1 -0
- package/dist/retrieve.js +256 -0
- package/dist/strength.d.ts +9 -0
- package/dist/strength.d.ts.map +1 -0
- package/dist/strength.js +51 -0
- package/dist/suppression.d.ts +8 -0
- package/dist/suppression.d.ts.map +1 -0
- package/dist/suppression.js +82 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +40 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +4 -0
- package/package.json +31 -0
package/dist/strength.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Reinforcement-strength primitive (#204 plasticity). Turns a memory's access history — how OFTEN
|
|
2
|
+
// and how RECENTLY it has been recalled — into a [0,1] re-ranking signal so a frequently-reused
|
|
3
|
+
// memory is surfaced ahead of a never-touched one. This realises the core plasticity promise ("a
|
|
4
|
+
// memory gets stronger when reused") at retrieval time; the maintenance pass already strengthens on
|
|
5
|
+
// a slower cadence, but ranking is where reuse must change what the user actually sees.
|
|
6
|
+
//
|
|
7
|
+
// Cognitive basis (ACT-R base-level activation, simplified): activation rises with practice
|
|
8
|
+
// frequency and decays with disuse. Two bounded, deterministic factors, multiplied:
|
|
9
|
+
// accessRecency = exp(-ln2 * (now - lastAccessedAt) / HALF_LIFE) disuse decay, 45-day half-life
|
|
10
|
+
// frequency = 1 - exp(-accessCount / SATURATION) saturating practice gain
|
|
11
|
+
// A NEVER-accessed memory scores 0 (no reinforcement yet) so this subscore only ever ADDS signal for
|
|
12
|
+
// genuine reuse and never perturbs a fresh memory's existing relevance/recency/confidence ranking.
|
|
13
|
+
//
|
|
14
|
+
// Pure: no clock (now is passed in), no IO, no randomness. Same inputs => same output, so the
|
|
15
|
+
// retrieval layer stays replay-stable and the deterministic eval can pin it.
|
|
16
|
+
import { exponentialDecay } from "./decay.js";
|
|
17
|
+
const MS_PER_DAY = 86_400_000;
|
|
18
|
+
// Disuse half-life. Matches the maintenance strength curve (keiko-memory-governance maintenance.ts)
|
|
19
|
+
// so "recency of use" decays at one consistent rate across ranking and the decay/forget cycle.
|
|
20
|
+
export const STRENGTH_HALF_LIFE_MS = 45 * MS_PER_DAY;
|
|
21
|
+
// Access count at which the frequency factor reaches ~0.63 of its ceiling. Logarithmic-feeling
|
|
22
|
+
// saturation: 1 recall ≈ 0.12, 8 ≈ 0.63, 24 ≈ 0.95 — heavy reuse keeps mattering with diminishing
|
|
23
|
+
// returns, matching the practice-curve intuition without an unbounded count term.
|
|
24
|
+
export const STRENGTH_FREQUENCY_SATURATION = 8;
|
|
25
|
+
// Reinforcement strength in [0,1]. `undefined` stat (memory never accessed) => 0.
|
|
26
|
+
export function reinforcementStrength(stat, nowMs) {
|
|
27
|
+
if (stat === undefined)
|
|
28
|
+
return 0;
|
|
29
|
+
// Reuse-recency: decays since last ACCESS (future-dated clamps to full recency). Shares the kernel
|
|
30
|
+
// in decay.ts with edit-recency (recency.ts), which decays since last UPDATE at a different half-life.
|
|
31
|
+
const accessRecency = exponentialDecay(nowMs - stat.lastAccessedAt, STRENGTH_HALF_LIFE_MS);
|
|
32
|
+
const count = stat.accessCount > 0 ? stat.accessCount : 0;
|
|
33
|
+
const frequency = 1 - Math.exp(-count / STRENGTH_FREQUENCY_SATURATION);
|
|
34
|
+
const strength = frequency * accessRecency;
|
|
35
|
+
if (strength < 0)
|
|
36
|
+
return 0;
|
|
37
|
+
if (strength > 1)
|
|
38
|
+
return 1;
|
|
39
|
+
return strength;
|
|
40
|
+
}
|
|
41
|
+
// Convenience: build the per-memory strength map the ranker consumes from a map of access stats.
|
|
42
|
+
// Lives here (next to the formula) so callers cannot drift from the canonical computation.
|
|
43
|
+
export function buildStrengthById(statsById, nowMs) {
|
|
44
|
+
const out = new Map();
|
|
45
|
+
for (const [id, stat] of statsById) {
|
|
46
|
+
const strength = reinforcementStrength(stat, nowMs);
|
|
47
|
+
if (strength > 0)
|
|
48
|
+
out.set(id, strength);
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MemoryRecord } from "@oscharko-dev/keiko-contracts/memory";
|
|
2
|
+
export type SuppressionReason = "archived" | "forgotten" | "conflicted" | "expired" | "proposed" | "rejected" | "stale-low-confidence";
|
|
3
|
+
export interface SuppressionResult {
|
|
4
|
+
readonly suppressed: boolean;
|
|
5
|
+
readonly reason?: SuppressionReason;
|
|
6
|
+
}
|
|
7
|
+
export declare function isMemorySuppressed(memory: MemoryRecord, nowMs: number, staleConfidenceThreshold: number): SuppressionResult;
|
|
8
|
+
//# sourceMappingURL=suppression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppression.d.ts","sourceRoot":"","sources":["../src/suppression.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,sCAAsC,CAAC;AAIvF,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,WAAW,GACX,YAAY,GACZ,SAAS,GACT,UAAU,GACV,UAAU,GACV,sBAAsB,CAAC;AAE3B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CACrC;AAuDD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,wBAAwB,EAAE,MAAM,GAC/B,iBAAiB,CASnB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Retrieval-suppression predicate.
|
|
2
|
+
//
|
|
3
|
+
// MUST stay in sync with @oscharko-dev/keiko-memory-governance/src/suppression.ts.
|
|
4
|
+
// Duplicated by design (per Issue #210 brief) so this package depends ONLY on
|
|
5
|
+
// keiko-contracts and keiko-security — see ADR-0019 direction rule 3j. A future refactor
|
|
6
|
+
// MAY extract a shared helper into a fourth "contracts-adjacent" package; until then a
|
|
7
|
+
// drift between the two implementations is a correctness bug and any change here must be
|
|
8
|
+
// mirrored there.
|
|
9
|
+
//
|
|
10
|
+
// The semantics map the discriminated MemoryStatus enum to a suppression reason and
|
|
11
|
+
// additionally apply two derived rules:
|
|
12
|
+
// - validity.validUntil <= nowMs => "expired"
|
|
13
|
+
// - provenance.confidence <= staleConfidenceThreshold => "stale-low-confidence"
|
|
14
|
+
//
|
|
15
|
+
// The threshold default of 0.3 matches consolidation (#208) and governance (#209) so the
|
|
16
|
+
// three layers agree on what counts as low-confidence. The comparison is `<=` so a record
|
|
17
|
+
// exactly at the threshold is suppressed.
|
|
18
|
+
//
|
|
19
|
+
// A future widening of MemoryStatus surfaces as an exhaustiveness compile error here
|
|
20
|
+
// (the `never` branch in statusSuppression).
|
|
21
|
+
import { RetrievalError } from "./errors.js";
|
|
22
|
+
const NOT_SUPPRESSED = { suppressed: false };
|
|
23
|
+
function isFiniteInRange(value, min, max) {
|
|
24
|
+
return Number.isFinite(value) && value >= min && value <= max;
|
|
25
|
+
}
|
|
26
|
+
function assertValidThreshold(staleConfidenceThreshold) {
|
|
27
|
+
if (isFiniteInRange(staleConfidenceThreshold, 0, 1))
|
|
28
|
+
return;
|
|
29
|
+
throw new RetrievalError("invalid-threshold", `staleConfidenceThreshold must be a finite number in [0, 1] (got ${String(staleConfidenceThreshold)})`);
|
|
30
|
+
}
|
|
31
|
+
function statusSuppression(status) {
|
|
32
|
+
switch (status) {
|
|
33
|
+
case "archived":
|
|
34
|
+
return { suppressed: true, reason: "archived" };
|
|
35
|
+
case "forgotten":
|
|
36
|
+
return { suppressed: true, reason: "forgotten" };
|
|
37
|
+
case "conflicted":
|
|
38
|
+
return { suppressed: true, reason: "conflicted" };
|
|
39
|
+
case "rejected":
|
|
40
|
+
return { suppressed: true, reason: "rejected" };
|
|
41
|
+
case "expired":
|
|
42
|
+
// Validity-based "expired" is checked separately so an explicit `expired` status
|
|
43
|
+
// carries the same surface reason whether the retrieval index pinned it via status
|
|
44
|
+
// or derived it from the validity window.
|
|
45
|
+
return { suppressed: true, reason: "expired" };
|
|
46
|
+
case "proposed":
|
|
47
|
+
return { suppressed: true, reason: "proposed" };
|
|
48
|
+
case "accepted":
|
|
49
|
+
case "superseded":
|
|
50
|
+
return null;
|
|
51
|
+
default: {
|
|
52
|
+
const _exhaustive = status;
|
|
53
|
+
void _exhaustive;
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function validitySuppression(memory, nowMs) {
|
|
59
|
+
if (memory.validity.validUntil === undefined)
|
|
60
|
+
return null;
|
|
61
|
+
if (memory.validity.validUntil > nowMs)
|
|
62
|
+
return null;
|
|
63
|
+
return { suppressed: true, reason: "expired" };
|
|
64
|
+
}
|
|
65
|
+
function confidenceSuppression(memory, threshold) {
|
|
66
|
+
if (memory.provenance.confidence > threshold)
|
|
67
|
+
return null;
|
|
68
|
+
return { suppressed: true, reason: "stale-low-confidence" };
|
|
69
|
+
}
|
|
70
|
+
export function isMemorySuppressed(memory, nowMs, staleConfidenceThreshold) {
|
|
71
|
+
assertValidThreshold(staleConfidenceThreshold);
|
|
72
|
+
const byStatus = statusSuppression(memory.status);
|
|
73
|
+
if (byStatus !== null)
|
|
74
|
+
return byStatus;
|
|
75
|
+
const byValidity = validitySuppression(memory, nowMs);
|
|
76
|
+
if (byValidity !== null)
|
|
77
|
+
return byValidity;
|
|
78
|
+
const byConfidence = confidenceSuppression(memory, staleConfidenceThreshold);
|
|
79
|
+
if (byConfidence !== null)
|
|
80
|
+
return byConfidence;
|
|
81
|
+
return NOT_SUPPRESSED;
|
|
82
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { MemoryEdge, MemoryId, MemoryRecord, MemoryScope, MemorySensitivity, MemorySourceKind, MemoryStatus, MemoryType } from "@oscharko-dev/keiko-contracts/memory";
|
|
2
|
+
export interface MemoryQueryPort {
|
|
3
|
+
/** Fetch memories visible at the given scope. Cross-scope queries forbidden. */
|
|
4
|
+
listByScope(scope: MemoryScope, options?: ListByScopeOptions): readonly MemoryRecord[];
|
|
5
|
+
/** Fetch outgoing edges for graph-proximity scoring. */
|
|
6
|
+
listOutgoingEdges?(memoryId: MemoryId): readonly MemoryEdge[];
|
|
7
|
+
/** Fetch incoming edges. */
|
|
8
|
+
listIncomingEdges?(memoryId: MemoryId): readonly MemoryEdge[];
|
|
9
|
+
}
|
|
10
|
+
export interface ListByScopeOptions {
|
|
11
|
+
readonly includeForgotten?: boolean;
|
|
12
|
+
readonly includeArchived?: boolean;
|
|
13
|
+
readonly includeExpired?: boolean;
|
|
14
|
+
readonly maxResults?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface RankingWeights {
|
|
17
|
+
readonly relevance: number;
|
|
18
|
+
readonly recency: number;
|
|
19
|
+
readonly confidence: number;
|
|
20
|
+
readonly pinned: number;
|
|
21
|
+
readonly correction: number;
|
|
22
|
+
readonly graph: number;
|
|
23
|
+
readonly semantic: number;
|
|
24
|
+
readonly strength: number;
|
|
25
|
+
readonly importance: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const DEFAULT_RANKING_WEIGHTS: RankingWeights;
|
|
28
|
+
export declare const DEFAULT_BUDGET_TOKENS = 1500;
|
|
29
|
+
export declare const DEFAULT_MAX_INCLUDED = 12;
|
|
30
|
+
export declare const DEFAULT_STALE_CONFIDENCE_THRESHOLD = 0.3;
|
|
31
|
+
export declare const DEFAULT_LIST_BY_SCOPE_MAX_RESULTS = 500;
|
|
32
|
+
export type RankingFusionMode = "weighted-sum" | "rrf";
|
|
33
|
+
export interface MemoryRetrievalRequest {
|
|
34
|
+
readonly scopes: readonly MemoryScope[];
|
|
35
|
+
readonly queryText?: string;
|
|
36
|
+
readonly types?: readonly MemoryType[];
|
|
37
|
+
readonly nowMs: number;
|
|
38
|
+
readonly budgetTokens?: number;
|
|
39
|
+
readonly maxIncluded?: number;
|
|
40
|
+
readonly recencyWeight?: number;
|
|
41
|
+
readonly confidenceWeight?: number;
|
|
42
|
+
readonly pinnedBoost?: number;
|
|
43
|
+
readonly correctionBoost?: number;
|
|
44
|
+
readonly graphProximityBoost?: number;
|
|
45
|
+
readonly relevanceWeight?: number;
|
|
46
|
+
readonly semanticWeight?: number;
|
|
47
|
+
readonly staleConfidenceThreshold?: number;
|
|
48
|
+
/** Audit/debug opt-in. Active context retrieval suppresses superseded memories by default. */
|
|
49
|
+
readonly includeSuperseded?: boolean;
|
|
50
|
+
readonly semanticById?: ReadonlyMap<MemoryId, number>;
|
|
51
|
+
readonly strengthById?: ReadonlyMap<MemoryId, number>;
|
|
52
|
+
readonly strengthWeight?: number;
|
|
53
|
+
readonly importanceWeight?: number;
|
|
54
|
+
readonly embeddingById?: ReadonlyMap<MemoryId, Float32Array>;
|
|
55
|
+
readonly mmrLambda?: number;
|
|
56
|
+
readonly fusion?: RankingFusionMode;
|
|
57
|
+
}
|
|
58
|
+
export interface MemoryContextBlockEntry {
|
|
59
|
+
readonly memoryId: MemoryId;
|
|
60
|
+
readonly bodyExcerpt: string;
|
|
61
|
+
readonly inclusionReason: string;
|
|
62
|
+
readonly sourceKind: MemorySourceKind;
|
|
63
|
+
readonly captureRationale?: string | undefined;
|
|
64
|
+
readonly sensitivity: MemorySensitivity;
|
|
65
|
+
readonly confidence: number;
|
|
66
|
+
readonly status: MemoryStatus;
|
|
67
|
+
readonly capturedAt: number;
|
|
68
|
+
}
|
|
69
|
+
export interface MemoryContextBlock {
|
|
70
|
+
/** Compact text rendering for prompt assembly. */
|
|
71
|
+
readonly text: string;
|
|
72
|
+
/** Structured payload for UI/audit consumers. */
|
|
73
|
+
readonly memories: readonly MemoryContextBlockEntry[];
|
|
74
|
+
}
|
|
75
|
+
export interface IncludedSubscores {
|
|
76
|
+
readonly relevance: number;
|
|
77
|
+
readonly recency: number;
|
|
78
|
+
readonly confidence: number;
|
|
79
|
+
readonly pinned: number;
|
|
80
|
+
readonly correction: number;
|
|
81
|
+
readonly graph: number;
|
|
82
|
+
readonly semantic: number;
|
|
83
|
+
readonly strength: number;
|
|
84
|
+
readonly importance: number;
|
|
85
|
+
}
|
|
86
|
+
export interface IncludedMemory {
|
|
87
|
+
readonly memoryId: MemoryId;
|
|
88
|
+
readonly score: number;
|
|
89
|
+
readonly subscores: IncludedSubscores;
|
|
90
|
+
readonly inclusionReason: string;
|
|
91
|
+
}
|
|
92
|
+
export type OmittedReason = "suppressed-by-status" | "below-threshold" | "budget-exceeded" | "out-of-scope" | "type-filtered";
|
|
93
|
+
export interface OmittedMemory {
|
|
94
|
+
readonly memoryId: MemoryId;
|
|
95
|
+
readonly reason: OmittedReason;
|
|
96
|
+
readonly suppressionDetail?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface MemoryBudget {
|
|
99
|
+
readonly tokens: number;
|
|
100
|
+
readonly used: number;
|
|
101
|
+
}
|
|
102
|
+
export interface MemoryRetrievalResult {
|
|
103
|
+
readonly contextBlock: MemoryContextBlock;
|
|
104
|
+
readonly included: readonly IncludedMemory[];
|
|
105
|
+
readonly omitted: readonly OmittedMemory[];
|
|
106
|
+
readonly budget: MemoryBudget;
|
|
107
|
+
readonly request: MemoryRetrievalRequest;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Internal result type used by `assembleContextBlock`. Mirrors `MemoryRetrievalResult`
|
|
111
|
+
* minus the `request` field, which is attached by `retrieveMemoryContext` after assembly.
|
|
112
|
+
* The brief lists `assembleContextBlock(ranked, memories, options): MemoryRetrievalResult`
|
|
113
|
+
* but the assembler has no need for the request envelope to compose its output — keeping
|
|
114
|
+
* the function pure on its (ranked, memories, options) inputs is cleaner than threading
|
|
115
|
+
* the request through a layer that does not read it.
|
|
116
|
+
*/
|
|
117
|
+
export type AssembledContext = Omit<MemoryRetrievalResult, "request">;
|
|
118
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Public type surface for the memory-retrieval layer (Epic #204 / Issue #210).
|
|
2
|
+
//
|
|
3
|
+
// Pure types + a handful of `Object.freeze`d default-weight tables. No IO, no clock, no
|
|
4
|
+
// randomness. All durable timestamps are epoch milliseconds; the caller supplies `nowMs`.
|
|
5
|
+
//
|
|
6
|
+
// Cross-cutting invariants encoded structurally:
|
|
7
|
+
// 1. MemoryQueryPort.listByScope is the SINGLE seam through which records enter this
|
|
8
|
+
// layer. There is no "list all" surface — the port is scope-addressed, so cross-scope
|
|
9
|
+
// leakage requires an explicit second call to a second scope. The orchestrator
|
|
10
|
+
// (retrieve.ts) is the one place that decides which scopes to ask for, and it ONLY
|
|
11
|
+
// iterates `request.scopes`.
|
|
12
|
+
// 2. ListByScopeOptions.maxResults bounds the upstream fetch so a misbehaving port can
|
|
13
|
+
// never flood this layer; the orchestrator passes its own bound regardless of caller.
|
|
14
|
+
// 3. Every IncludedMemory carries the full subscore breakdown so audit and UI can
|
|
15
|
+
// reconstruct WHY a memory was chosen without re-running the ranker.
|
|
16
|
+
// 4. Every OmittedMemory carries one of a closed-set of reasons so audit dashboards can
|
|
17
|
+
// bucket suppressions without parsing free-form strings.
|
|
18
|
+
// Defaults are documented at the request-type boundary; this table is the single source of
|
|
19
|
+
// truth the orchestrator reads when a field is `undefined` on the request. Frozen so a
|
|
20
|
+
// downstream consumer cannot mutate the global default.
|
|
21
|
+
export const DEFAULT_RANKING_WEIGHTS = Object.freeze({
|
|
22
|
+
relevance: 0.2,
|
|
23
|
+
recency: 0.2,
|
|
24
|
+
confidence: 0.2,
|
|
25
|
+
pinned: 0.3,
|
|
26
|
+
correction: 0.1,
|
|
27
|
+
graph: 0.15,
|
|
28
|
+
semantic: 0.25,
|
|
29
|
+
// Reinforcement weight (#204). Sits between recency and semantic: reuse is a strong signal but must
|
|
30
|
+
// not override an explicit pin or a fresh correction. Only participates when the caller supplies
|
|
31
|
+
// per-memory strength scores; otherwise the ranker forces it to 0 (byte-identical legacy behaviour).
|
|
32
|
+
strength: 0.2,
|
|
33
|
+
// Source-authority importance weight (#204, O-F5). Default 0 (opt-in): always computed but inert
|
|
34
|
+
// until an operator sets a non-zero weight, so legacy ranking is byte-identical.
|
|
35
|
+
importance: 0,
|
|
36
|
+
});
|
|
37
|
+
export const DEFAULT_BUDGET_TOKENS = 1500;
|
|
38
|
+
export const DEFAULT_MAX_INCLUDED = 12;
|
|
39
|
+
export const DEFAULT_STALE_CONFIDENCE_THRESHOLD = 0.3;
|
|
40
|
+
export const DEFAULT_LIST_BY_SCOPE_MAX_RESULTS = 500;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,8BAA8B,EAAG,OAAgB,CAAC"}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Single source of truth for the package version. Pinned as a literal so consumers can
|
|
2
|
+
// import it for telemetry or evidence persistence without parsing package.json at runtime.
|
|
3
|
+
// Bump in lockstep with package.json on every release.
|
|
4
|
+
export const KEIKO_MEMORY_RETRIEVAL_VERSION = "0.1.0";
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@oscharko-dev/keiko-memory-retrieval",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"description": "MemoriaViva — Internal memory-retrieval package (Epic #204 child #210): pure-function scoped retrieval + hybrid ranking + token-budgeted context assembly over Governed Enterprise Memory Vault records. Caller supplies a MemoryQueryPort (no keiko-memory-vault import) so the vault remains injectable and this layer stays pure (no IO, no clock, no randomness; caller supplies nowMs). Ranking combines deterministic lexical relevance, recency decay, provenance confidence, pinned boost, correction boost, and graph proximity into a weighted sum. The context block carries inclusion/omission reasons per memory so downstream callers (Conversation Center #212, workflow agents #213) and audit (#214) can render fully explainable surfaces. Suppression check is duplicated inline (synced with @oscharko-dev/keiko-memory-governance/suppression.ts) to keep the dep graph on contracts+security only. ADR-0019 direction rule 3j enforces this scope. Not published independently.",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -b tsconfig.json",
|
|
17
|
+
"typecheck": "tsc -b tsconfig.json",
|
|
18
|
+
"test": "vitest run"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"sideEffects": false,
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@oscharko-dev/keiko-contracts": "0.2.0",
|
|
29
|
+
"@oscharko-dev/keiko-security": "0.2.0"
|
|
30
|
+
}
|
|
31
|
+
}
|