@hy-sde-org/dsh-memory-extraction 0.1.2-rc.1

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.
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Evidence planning for automatic memory extraction: which session events are
3
+ * Memory evidence (user-authored text only), how the bounded evidence index is
4
+ * fitted, and the same-session history search that localizes elliptical
5
+ * assertions. Ported from Maka `memory-extraction-evidence.ts`; provider-prefix
6
+ * binding is dropped (the bounded evidence text is authoritative for both the
7
+ * model and admission — see the package README deviation note).
8
+ * @module @hy-sde-org/dsh-memory-extraction/evidence
9
+ */
10
+ export const MAX_MEMORY_EVIDENCE_JSON_CHARS = 12_000;
11
+ export const MAX_EVIDENCE_TEXT_CHARS = 4_000;
12
+ export const MIN_EVIDENCE_TEXT_CHARS = 64;
13
+ export const MAX_LOCALIZED_TURNS = 7;
14
+ export const MAX_LOCALIZED_CONTEXT_CHARS = 12_000;
15
+ export const MAX_LOCALIZED_EVENT_CHARS = 2_000;
16
+ /**
17
+ * Plan one complete trigger range. Tool and runtime-control events produce no
18
+ * evidence but stay in the range so the session cursor crosses them instead of
19
+ * reconsidering them. If every user evidence record cannot fit the bounded
20
+ * evidence index, fail closed instead of silently consuming part of the range.
21
+ */
22
+ export function planMemoryCoverage(pendingEntries, options = {}) {
23
+ if (pendingEntries.length === 0)
24
+ return undefined;
25
+ const budget = options.maxEvidenceJsonChars ?? MAX_MEMORY_EVIDENCE_JSON_CHARS;
26
+ const coverage = bindProviderVisibleEvidence(projectMemoryExtractionEvidence(pendingEntries.map(entry => entry.event)));
27
+ const fitted = fitMemoryExtractionEvidence(coverage, budget);
28
+ if (!fitted)
29
+ return undefined;
30
+ const fittedRefs = new Set(fitted.map(entry => entry.sourceRef));
31
+ if (coverage.some(entry => !fittedRefs.has(entry.sourceRef)))
32
+ return undefined;
33
+ return { entries: [...pendingEntries], evidence: fitted };
34
+ }
35
+ /** Projects only stable user-authored text into Memory evidence. */
36
+ export function projectMemoryExtractionEvidence(events) {
37
+ const projected = [];
38
+ for (const event of events) {
39
+ if (event.role !== 'user' || event.author !== 'user')
40
+ continue;
41
+ const fullText = normalizeEvidenceText(event.text ?? '');
42
+ if (!fullText)
43
+ continue;
44
+ projected.push({
45
+ sourceRef: `event:${event.seq}`,
46
+ type: 'user_message',
47
+ text: boundedEvidenceText(fullText, undefined),
48
+ events: [event],
49
+ });
50
+ }
51
+ return projected;
52
+ }
53
+ /**
54
+ * Keep every evidence record represented while shrinking supplemental text to
55
+ * the actual serialized JSON budget. `undefined` means even the record
56
+ * identities cannot fit and the cursor must not advance.
57
+ */
58
+ export function fitMemoryExtractionEvidence(evidence, maxJsonChars = MAX_MEMORY_EVIDENCE_JSON_CHARS) {
59
+ if (!Number.isSafeInteger(maxJsonChars) || maxJsonChars < 1)
60
+ return undefined;
61
+ if (memoryExtractionEvidenceJsonSize(evidence) <= maxJsonChars)
62
+ return evidence;
63
+ let low = MIN_EVIDENCE_TEXT_CHARS;
64
+ let high = MAX_EVIDENCE_TEXT_CHARS;
65
+ let best;
66
+ while (low <= high) {
67
+ const cap = Math.floor((low + high) / 2);
68
+ const candidate = evidence.map(entry => ({
69
+ ...entry,
70
+ text: sliceCodePoints(entry.text, cap),
71
+ }));
72
+ if (memoryExtractionEvidenceJsonSize(candidate) <= maxJsonChars) {
73
+ best = candidate;
74
+ low = cap + 1;
75
+ }
76
+ else {
77
+ high = cap - 1;
78
+ }
79
+ }
80
+ return best;
81
+ }
82
+ export function memoryExtractionEvidenceJsonSize(evidence) {
83
+ return JSON.stringify(renderMemoryExtractionEvidence(evidence)).length;
84
+ }
85
+ /** The bounded evidence index rendered into the pipeline prompts. */
86
+ export function renderMemoryExtractionEvidence(evidence) {
87
+ return evidence.map(entry => ({
88
+ sourceRef: entry.sourceRef,
89
+ type: entry.type,
90
+ observedAt: minuteTimestamp(Math.max(0, ...entry.events.map(event => event.time))),
91
+ text: entry.text,
92
+ }));
93
+ }
94
+ /** Present for parity with Maka's port shape; kept as the binding hook. */
95
+ function bindProviderVisibleEvidence(evidence) {
96
+ return evidence;
97
+ }
98
+ /**
99
+ * Rank matching turns by term coverage and recency, then add a one-turn
100
+ * neighborhood. Applies over the same bounded event window (`throughSeq`).
101
+ * A "turn" is the adapter-declared `turn` id when present (DSH turn numbers);
102
+ * otherwise each text event is its own group.
103
+ */
104
+ export function searchSameSessionMemoryHistory(entries, throughSeq, search, afterSeq = 0) {
105
+ const eligible = entries.filter(({ seq, event }) => seq > afterSeq
106
+ && seq <= throughSeq
107
+ && (event.text !== undefined && event.text.length > 0)
108
+ && ((event.role === 'user' && event.author === 'user')
109
+ || (event.role === 'assistant' && event.author === 'model')));
110
+ const turns = [];
111
+ for (const entry of eligible) {
112
+ const key = entry.event.turn !== undefined ? `t${entry.event.turn}` : `e${entry.seq}`;
113
+ const last = turns.at(-1);
114
+ if (last?.key === key)
115
+ last.entries.push(entry);
116
+ else
117
+ turns.push({ key, entries: [entry] });
118
+ }
119
+ const terms = search.terms.map(term => normalizeEvidenceText(term).toLowerCase());
120
+ const allowedRoles = search.roles ? new Set(search.roles) : undefined;
121
+ const hits = turns
122
+ .map((turn, index) => ({
123
+ index,
124
+ score: terms.filter(term => turn.entries.some((entry) => {
125
+ if (allowedRoles && !allowedRoles.has(historyRole(entry.event)))
126
+ return false;
127
+ return normalizeEvidenceText(entry.event.text ?? '').toLowerCase().includes(term);
128
+ })).length,
129
+ }))
130
+ .filter(({ score }) => score > 0)
131
+ .sort((left, right) => right.score - left.score || right.index - left.index);
132
+ const selected = new Set();
133
+ for (const hit of hits) {
134
+ for (const index of [hit.index, hit.index - 1, hit.index + 1]) {
135
+ if (index < 0 || index >= turns.length || selected.has(index))
136
+ continue;
137
+ if (selected.size >= MAX_LOCALIZED_TURNS)
138
+ break;
139
+ selected.add(index);
140
+ }
141
+ if (selected.size >= MAX_LOCALIZED_TURNS)
142
+ break;
143
+ }
144
+ return [...selected]
145
+ .sort((left, right) => left - right)
146
+ .flatMap(index => turns[index]?.entries ?? []);
147
+ }
148
+ /** Bounded user/assistant text used only to interpret elliptical user evidence. */
149
+ export function renderMemoryLocalizationContext(entries) {
150
+ let remaining = MAX_LOCALIZED_CONTEXT_CHARS;
151
+ const rendered = [];
152
+ for (const { seq, event } of entries) {
153
+ if (remaining <= 0 || event.text === undefined || event.text.length === 0)
154
+ continue;
155
+ const role = historyRole(event);
156
+ const text = sliceCodePoints(normalizeEvidenceText(event.text), MAX_LOCALIZED_EVENT_CHARS);
157
+ if (!text)
158
+ continue;
159
+ const line = `[${role} event:${seq}] ${text}`;
160
+ const bounded = sliceCodePoints(line, remaining);
161
+ rendered.push(bounded);
162
+ remaining -= Array.from(bounded).length;
163
+ }
164
+ return rendered.join('\n');
165
+ }
166
+ /** Resolve the admission evidence map for one coverage plan. */
167
+ export function evidenceByRef(evidence) {
168
+ return new Map(evidence.map(entry => [entry.sourceRef, entry]));
169
+ }
170
+ /** Whether one citation's quote is verbatim inside its referenced evidence. */
171
+ export function evidenceContainsCitation(citation, evidence) {
172
+ const source = evidence.get(citation.sourceRef);
173
+ if (!source)
174
+ return false;
175
+ const quote = normalizeEvidenceText(citation.quote);
176
+ if (!quote)
177
+ return false;
178
+ return source.text.includes(quote);
179
+ }
180
+ function boundedEvidenceText(value, terms) {
181
+ const codePoints = Array.from(value);
182
+ if (codePoints.length <= MAX_EVIDENCE_TEXT_CHARS)
183
+ return value;
184
+ const normalizedTerms = terms
185
+ ?.map(term => normalizeEvidenceText(term).toLowerCase())
186
+ .filter(Boolean);
187
+ const lower = value.toLowerCase();
188
+ const hit = normalizedTerms
189
+ ?.map(term => lower.indexOf(term))
190
+ .filter(index => index >= 0)
191
+ .sort((left, right) => left - right)[0];
192
+ if (hit === undefined)
193
+ return codePoints.slice(0, MAX_EVIDENCE_TEXT_CHARS).join('');
194
+ const before = Math.floor(MAX_EVIDENCE_TEXT_CHARS / 3);
195
+ const start = Math.max(0, Array.from(value.slice(0, hit)).length - before);
196
+ return codePoints.slice(start, start + MAX_EVIDENCE_TEXT_CHARS).join('');
197
+ }
198
+ export function normalizeEvidenceText(value) {
199
+ return value.normalize('NFC').replace(/\s+/g, ' ').trim();
200
+ }
201
+ export function minuteTimestamp(value) {
202
+ return Math.floor(value / 60_000) * 60_000;
203
+ }
204
+ export function historyRole(event) {
205
+ return event.role === 'assistant' ? 'assistant' : 'user';
206
+ }
207
+ export function sliceCodePoints(value, maximum) {
208
+ return Array.from(value).slice(0, maximum).join('');
209
+ }
210
+ /** Event identity of one entry, used by the coverage hash. */
211
+ export function coverageEntryIdentity(entry) {
212
+ const label = entry.event.text !== undefined && entry.event.text.length > 0
213
+ ? `${entry.event.role}:${entry.event.author}`
214
+ : entry.event.role;
215
+ return [entry.seq, label];
216
+ }
217
+ /** Sort helper retained for tests and derived projections. */
218
+ export function sortEntriesBySeq(entries) {
219
+ return [...entries].sort((left, right) => left.seq - right.seq);
220
+ }
221
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../src/evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Automatic long-term-memory extraction at compaction checkpoints (Maka port,
3
+ * slice No. 2): one host-plane plugin that observes every session's
4
+ * `compaction/summary` event and runs a bounded, fail-open extraction pipeline
5
+ * writing durable facts into the same `ctx.memory` bank `retain`/`learn` use.
6
+ *
7
+ * Plane split (load-bearing — do not move rows between planes):
8
+ * - This row is HOST: it resolves host services (`memory`, `llm`,
9
+ * `storage.backend.<backend>`) and opens the `memory_extraction` control
10
+ * unit once per process. A preset row would collide on unit-open and scope
11
+ * the listener to one agent (and a scoped listener would miss other
12
+ * sessions' compactions). An unscoped host `ctx.on('session/event')` is
13
+ * admitted globally by the scope filter, so every session's events arrive.
14
+ * - No tool or prompt section: DSH's explicit `retain`/`learn`/`memory_edit`
15
+ * surface stays the model-facing path (Maka's `memory_remember`/
16
+ * `memory_extract` verbs are reserved, not ported).
17
+ * @module @hy-sde-org/dsh-memory-extraction
18
+ */
19
+ import { Context } from '@deepseek-ai/cordis';
20
+ import z from '@deepseek-ai/schemastery';
21
+ import type { RuntimeConfig } from './runtime.ts';
22
+ export * from './types.ts';
23
+ export * from './evidence.ts';
24
+ export * from './proposal.ts';
25
+ export * from './control.ts';
26
+ export * from './engine.ts';
27
+ export * from './events.ts';
28
+ export * from './memory-adapter.ts';
29
+ export { MemoryExtractionRuntime, openControlUnit } from './runtime.ts';
30
+ /** Plugin configuration. */
31
+ export interface Config extends RuntimeConfig {
32
+ /** Master switch; false makes the plugin inert (default true). */
33
+ enabled?: boolean;
34
+ /** Storage backend name whose kv facet hosts the control unit (default `sqlite`). */
35
+ backend?: string;
36
+ /** Cheap-model override; falls back to the session's routed request header. */
37
+ provider?: string;
38
+ /** Auxiliary model id override; falls back to the session's routed request header. */
39
+ model?: string;
40
+ /** Importance stamped on auto-extracted bank entries (default 0.5). */
41
+ importance?: number;
42
+ /** Probe the bank before commit to skip exact duplicates (default true). */
43
+ dedupe?: boolean;
44
+ /** Skip subagent/child sessions (default true). */
45
+ excludeSubagents?: boolean;
46
+ /** Auxiliary call timeout in milliseconds (default 60 000). */
47
+ timeoutMs?: number;
48
+ }
49
+ export declare const Config: z<Config>;
50
+ export declare const name = "memory-extraction";
51
+ export declare const inject: string[];
52
+ /**
53
+ * Mount the extraction runtime. Async boot (open the control unit) happens in
54
+ * an effect so plugin teardown releases the unit; a missing storage backend
55
+ * logs and leaves the plugin inert rather than failing composition.
56
+ */
57
+ export declare function apply(ctx: Context, config: Config): void;
58
+ declare const _default: {
59
+ name: string;
60
+ inject: string[];
61
+ apply: typeof apply;
62
+ };
63
+ export default _default;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAEvE,4BAA4B;AAC5B,MAAM,WAAW,MAAO,SAAQ,aAAa;IAC3C,kEAAkE;IAClE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sFAAsF;IACtF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,mDAAmD;IACnD,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,MAAM,EAAE,CAAC,CAAC,MAAM,CAS3B,CAAA;AAEF,eAAO,MAAM,IAAI,sBAAsB,CAAA;AAEvC,eAAO,MAAM,MAAM,UAAoB,CAAA;AAEvC;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBxD;;;;;;AAED,wBAAsC"}
package/dist/index.js ADDED
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Automatic long-term-memory extraction at compaction checkpoints (Maka port,
3
+ * slice No. 2): one host-plane plugin that observes every session's
4
+ * `compaction/summary` event and runs a bounded, fail-open extraction pipeline
5
+ * writing durable facts into the same `ctx.memory` bank `retain`/`learn` use.
6
+ *
7
+ * Plane split (load-bearing — do not move rows between planes):
8
+ * - This row is HOST: it resolves host services (`memory`, `llm`,
9
+ * `storage.backend.<backend>`) and opens the `memory_extraction` control
10
+ * unit once per process. A preset row would collide on unit-open and scope
11
+ * the listener to one agent (and a scoped listener would miss other
12
+ * sessions' compactions). An unscoped host `ctx.on('session/event')` is
13
+ * admitted globally by the scope filter, so every session's events arrive.
14
+ * - No tool or prompt section: DSH's explicit `retain`/`learn`/`memory_edit`
15
+ * surface stays the model-facing path (Maka's `memory_remember`/
16
+ * `memory_extract` verbs are reserved, not ported).
17
+ * @module @hy-sde-org/dsh-memory-extraction
18
+ */
19
+ import z from '@deepseek-ai/schemastery';
20
+ import { MemoryExtractionRuntime, openControlUnit } from "./runtime.js";
21
+ export * from "./types.js";
22
+ export * from "./evidence.js";
23
+ export * from "./proposal.js";
24
+ export * from "./control.js";
25
+ export * from "./engine.js";
26
+ export * from "./events.js";
27
+ export * from "./memory-adapter.js";
28
+ export { MemoryExtractionRuntime, openControlUnit } from "./runtime.js";
29
+ export const Config = z.object({
30
+ enabled: z.boolean().default(true),
31
+ backend: z.string().default('sqlite'),
32
+ provider: z.string(),
33
+ model: z.string(),
34
+ importance: z.number(),
35
+ dedupe: z.boolean().default(true),
36
+ excludeSubagents: z.boolean().default(true),
37
+ timeoutMs: z.number().step(1).min(1),
38
+ });
39
+ export const name = 'memory-extraction';
40
+ export const inject = ['memory', 'llm'];
41
+ /**
42
+ * Mount the extraction runtime. Async boot (open the control unit) happens in
43
+ * an effect so plugin teardown releases the unit; a missing storage backend
44
+ * logs and leaves the plugin inert rather than failing composition.
45
+ */
46
+ export function apply(ctx, config) {
47
+ ctx.effect(() => {
48
+ const state = { cancelled: false };
49
+ const disposers = [];
50
+ void (async () => {
51
+ try {
52
+ const { unit, store } = await openControlUnit(ctx, config.backend ?? 'sqlite');
53
+ if (state.cancelled) {
54
+ await unit.close();
55
+ return;
56
+ }
57
+ const runtime = new MemoryExtractionRuntime(ctx, config, store, ctx.memory);
58
+ disposers.push(runtime.attach(), () => { void unit.close(); });
59
+ }
60
+ catch (error) {
61
+ ctx.logger.warn(`memory-extraction: not mounted (${String(error)}); extraction stays off`);
62
+ }
63
+ })();
64
+ return () => {
65
+ state.cancelled = true;
66
+ for (const dispose of disposers.splice(0))
67
+ dispose();
68
+ };
69
+ });
70
+ }
71
+ export default { name, inject, apply };
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AACxC,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAGvE,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,qBAAqB,CAAA;AACnC,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAsBvE,MAAM,CAAC,MAAM,MAAM,GAAc,CAAC,CAAC,MAAM,CAAC;IACxC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;IACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACjC,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CACrC,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,IAAI,GAAG,mBAAmB,CAAA;AAEvC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAA;AAEvC;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,GAAY,EAAE,MAAc;IAChD,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE;QACd,MAAM,KAAK,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAA;QAClC,MAAM,SAAS,GAAsB,EAAE,CAAA;QACvC,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,IAAI,CAAC;gBACH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,IAAI,QAAQ,CAAC,CAAA;gBAC9E,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;oBACpB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;oBAClB,OAAM;gBACR,CAAC;gBACD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;gBAC3E,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;YAC/D,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,MAAM,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAA;YAC5F,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QACJ,OAAO,GAAG,EAAE;YACV,KAAK,CAAC,SAAS,GAAG,IAAI,CAAA;YACtB,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAA;QACtD,CAAC,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The gated store adapter: commits admitted items into the existing
3
+ * `ctx.memory` project bank (the same store `retain`/`learn` write to) and
4
+ * resolves the extraction gate. Dedupe probes the existing bank with the
5
+ * recall search (design decision: content hash + project, via the existing
6
+ * search) so a cross-store crash between item writes and the cursor/receipt
7
+ * writes cannot duplicate facts on retry.
8
+ * @module @hy-sde-org/dsh-memory-extraction/memory-adapter
9
+ */
10
+ import type { MemoryContext, MemorySaveInput, MemorySaveResult, MemorySearchOptions, MemorySearchResult } from '@hy-sde-org/dsh-memory';
11
+ import type { AdmittedMemoryItem, MemoryExtractionGate, MemoryExtractionSourceSnapshot } from './types.ts';
12
+ /** Structural view of the `ctx.memory` service the adapter needs. */
13
+ export interface MemoryCommitSurface {
14
+ save(context: MemoryContext, input: MemorySaveInput): Promise<MemorySaveResult>;
15
+ search(context: MemoryContext, query: string, options?: MemorySearchOptions): Promise<MemorySearchResult>;
16
+ }
17
+ /** Adapter configuration. */
18
+ export interface MemoryCommitAdapterConfig {
19
+ /** Importance stamped on auto-extracted bank entries (default 0.5). */
20
+ importance?: number;
21
+ /** Probe the existing bank before writing to skip exact duplicates (default true). */
22
+ dedupe?: boolean;
23
+ }
24
+ export declare class MemoryCommitAdapter {
25
+ private readonly memory;
26
+ private readonly config;
27
+ constructor(memory: MemoryCommitSurface, config?: MemoryCommitAdapterConfig);
28
+ commitItems(input: {
29
+ readonly sessionId: string;
30
+ readonly workspaceKey?: string;
31
+ readonly trigger: MemoryExtractionSourceSnapshot['trigger'];
32
+ readonly boundarySeq: number;
33
+ readonly items: readonly AdmittedMemoryItem[];
34
+ }): Promise<{
35
+ readonly committed: readonly string[];
36
+ }>;
37
+ private isDuplicate;
38
+ }
39
+ /** Resolve the extraction gate: config toggle + subagent/child exclusion. */
40
+ export declare function createExtractionGate(config: {
41
+ readonly enabled?: boolean;
42
+ readonly excludeSubagents?: boolean;
43
+ }): (snapshot: MemoryExtractionSourceSnapshot) => MemoryExtractionGate;
44
+ //# sourceMappingURL=memory-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-adapter.d.ts","sourceRoot":"","sources":["../src/memory-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EACnB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EACV,kBAAkB,EAClB,oBAAoB,EACpB,8BAA8B,EAC/B,MAAM,YAAY,CAAA;AAQnB,qEAAqE;AACrE,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC/E,MAAM,CAAC,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;CAC1G;AAED,6BAA6B;AAC7B,MAAM,WAAW,yBAAyB;IACxC,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sFAAsF;IACtF,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,MAAM,EAAE,mBAAmB,EAC3B,MAAM,GAAE,yBAA8B;IAGnD,WAAW,CAAC,KAAK,EAAE;QACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;QAC9B,QAAQ,CAAC,OAAO,EAAE,8BAA8B,CAAC,SAAS,CAAC,CAAA;QAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAA;KAC9C,GAAG,OAAO,CAAC;QAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC;YAuBxC,WAAW;CAO1B;AAED,6EAA6E;AAC7E,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CACpC,GAAG,CAAC,QAAQ,EAAE,8BAA8B,KAAK,oBAAoB,CAUrE"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The gated store adapter: commits admitted items into the existing
3
+ * `ctx.memory` project bank (the same store `retain`/`learn` write to) and
4
+ * resolves the extraction gate. Dedupe probes the existing bank with the
5
+ * recall search (design decision: content hash + project, via the existing
6
+ * search) so a cross-store crash between item writes and the cursor/receipt
7
+ * writes cannot duplicate facts on retry.
8
+ * @module @hy-sde-org/dsh-memory-extraction/memory-adapter
9
+ */
10
+ import { normalizeProposedMemoryText } from "./proposal.js";
11
+ const IMPORTANCE_AUTO_EXTRACT = 0.5;
12
+ const SOURCE_AUTO_EXTRACT = 'memory_extract';
13
+ const DEDUPE_PROBE_LIMIT = 5;
14
+ const DEDUPE_QUERY_CHARS = 200;
15
+ export class MemoryCommitAdapter {
16
+ memory;
17
+ config;
18
+ constructor(memory, config = {}) {
19
+ this.memory = memory;
20
+ this.config = config;
21
+ }
22
+ async commitItems(input) {
23
+ const context = input.workspaceKey !== undefined
24
+ ? { cwd: input.workspaceKey }
25
+ : { cwd: process.cwd() };
26
+ const importance = this.config.importance ?? IMPORTANCE_AUTO_EXTRACT;
27
+ const dedupe = this.config.dedupe ?? true;
28
+ const committed = [];
29
+ for (const item of input.items) {
30
+ const content = normalizeProposedMemoryText(item.content);
31
+ if (content === undefined)
32
+ continue;
33
+ if (dedupe && await this.isDuplicate(context, content))
34
+ continue;
35
+ const result = await this.memory.save(context, {
36
+ content,
37
+ context: `automatic memory extraction from session ${input.sessionId} (compaction checkpoint through seq ${input.boundarySeq})`,
38
+ source: SOURCE_AUTO_EXTRACT,
39
+ importance,
40
+ sessionId: input.sessionId,
41
+ });
42
+ if (result.stored > 0)
43
+ committed.push(content);
44
+ }
45
+ return { committed };
46
+ }
47
+ async isDuplicate(context, content) {
48
+ const query = content.slice(0, DEDUPE_QUERY_CHARS);
49
+ const result = await this.memory.search(context, query, { limit: DEDUPE_PROBE_LIMIT });
50
+ const expected = normalizeProposedMemoryText(content);
51
+ if (expected === undefined)
52
+ return true;
53
+ return result.items.some(item => normalizeProposedMemoryText(item.content) === expected);
54
+ }
55
+ }
56
+ /** Resolve the extraction gate: config toggle + subagent/child exclusion. */
57
+ export function createExtractionGate(config) {
58
+ const enabled = config.enabled ?? true;
59
+ const excludeSubagents = config.excludeSubagents ?? true;
60
+ return (snapshot) => {
61
+ if (!enabled)
62
+ return { allowed: false, reason: 'disabled' };
63
+ if (excludeSubagents && (snapshot.origin === 'subagent' || (snapshot.delegationDepth ?? 0) > 0)) {
64
+ return { allowed: false, reason: 'ineligible' };
65
+ }
66
+ return { allowed: true };
67
+ };
68
+ }
69
+ //# sourceMappingURL=memory-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-adapter.js","sourceRoot":"","sources":["../src/memory-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAA;AAE3D,MAAM,uBAAuB,GAAG,GAAG,CAAA;AACnC,MAAM,mBAAmB,GAAG,gBAAgB,CAAA;AAC5C,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAC5B,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAgB9B,MAAM,OAAO,mBAAmB;IAEX;IACA;IAFnB,YACmB,MAA2B,EAC3B,SAAoC,EAAE;QADtC,WAAM,GAAN,MAAM,CAAqB;QAC3B,WAAM,GAAN,MAAM,CAAgC;IACrD,CAAC;IAEL,KAAK,CAAC,WAAW,CAAC,KAMjB;QACC,MAAM,OAAO,GAAkB,KAAK,CAAC,YAAY,KAAK,SAAS;YAC7D,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,YAAY,EAAE;YAC7B,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAA;QAC1B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,uBAAuB,CAAA;QACpE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAA;QACzC,MAAM,SAAS,GAAa,EAAE,CAAA;QAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACzD,IAAI,OAAO,KAAK,SAAS;gBAAE,SAAQ;YACnC,IAAI,MAAM,IAAI,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC;gBAAE,SAAQ;YAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE;gBAC7C,OAAO;gBACP,OAAO,EAAE,4CAA4C,KAAK,CAAC,SAAS,uCAAuC,KAAK,CAAC,WAAW,GAAG;gBAC/H,MAAM,EAAE,mBAAmB;gBAC3B,UAAU;gBACV,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC,CAAA;YACF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAChD,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,CAAA;IACtB,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,OAAsB,EAAE,OAAe;QAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAA;QAClD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,CAAA;QACtF,MAAM,QAAQ,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAA;QACrD,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,IAAI,CAAA;QACvC,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAA;IAC1F,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,UAAU,oBAAoB,CAAC,MAGpC;IACC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,IAAI,CAAA;IACtC,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAA;IACxD,OAAO,CAAC,QAAQ,EAAE,EAAE;QAClB,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,CAAA;QAC3D,IAAI,gBAAgB,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAChG,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;QACjD,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;IAC1B,CAAC,CAAA;AACH,CAAC"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Proposal / canonicalization language for automatic memory extraction:
3
+ * stage-1 and localized prompts, strict hand-rolled JSON parsers, and
4
+ * admission (verbatim quote verification, deterministic policy rejection,
5
+ * bounds). Ported from Maka `memory-extraction-proposal.ts` with the facet
6
+ * schema reduced to `{content, evidence}` (see package README).
7
+ * @module @hy-sde-org/dsh-memory-extraction/proposal
8
+ */
9
+ import { evidenceByRef } from './evidence.ts';
10
+ import type { AdmittedMemoryItem, LocalizedMemoryProposal, MemoryCanonicalization, MemoryExtractionEvidence, MemoryProposal, MemoryProposalItem } from './types.ts';
11
+ export declare const MAX_ITEM_CONTENT_CHARS = 2000;
12
+ export declare const MAX_ITEM_EVIDENCE_CITATIONS = 8;
13
+ export declare const MAX_CITATION_QUOTE_CHARS = 1000;
14
+ export declare const MAX_CITATION_SOURCEREF_CHARS = 160;
15
+ export declare const MAX_INCIDENT_ITEMS = 10;
16
+ export declare const MIN_CITATION_QUOTE_CHARS = 4;
17
+ export declare const MAX_SEARCH_TERMS = 8;
18
+ export declare const MAX_CANDIDATES = 20;
19
+ /**
20
+ * Parse one stage-1 proposal response. Strict JSON object only (no fences, no
21
+ * extra keys) — the pipeline fails closed on anything else.
22
+ */
23
+ export declare function parseMemoryProposal(raw: string): MemoryProposal | undefined;
24
+ /** Parse one localized (second-pass) proposal response. */
25
+ export declare function parseLocalizedMemoryProposal(raw: string): LocalizedMemoryProposal | undefined;
26
+ /** Parse one canonicalization response: exactly one result per candidateId. */
27
+ export declare function parseMemoryCanonicalization(raw: string): MemoryCanonicalization | undefined;
28
+ /** Stage-1 prompt: incidental extraction from the bounded evidence index. */
29
+ export declare function buildFirstMemoryProposalPrompt(input: {
30
+ readonly now: number;
31
+ readonly evidence: readonly MemoryExtractionEvidence[];
32
+ }): string;
33
+ /** Localized prompt: resolve one search_required with bounded same-session context. */
34
+ export declare function buildLocalizedMemoryProposalPrompt(input: {
35
+ readonly now: number;
36
+ readonly evidence: readonly MemoryExtractionEvidence[];
37
+ readonly interpretationContext: string;
38
+ }): string;
39
+ /** Canonicalization prompt: rewrite/reject candidates against user evidence only. */
40
+ export declare function buildMemoryCanonicalizationPrompt(input: {
41
+ readonly now: number;
42
+ readonly candidates: readonly {
43
+ readonly candidateId: string;
44
+ readonly evidence: readonly {
45
+ readonly sourceRef: string;
46
+ readonly quote: string;
47
+ readonly observedAt: number;
48
+ }[];
49
+ }[];
50
+ }): string;
51
+ /** Deterministic policy rejection: any secret-pattern text fails before admission. */
52
+ export declare function deterministicMemoryPolicyRejection(item: MemoryProposalItem): boolean;
53
+ /**
54
+ * Admit one proposal item: normalize content, verify every citation verbatim
55
+ * against its referenced bounded evidence, and collect the cited seqs for
56
+ * provenance. Returns undefined on any violation (fail closed).
57
+ */
58
+ export declare function admitMemoryProposalItem(item: MemoryProposalItem, evidence: ReadonlyMap<string, MemoryExtractionEvidence>): AdmittedMemoryItem | undefined;
59
+ /** Normalized, policy-safe, bounded stored content (mirrors the bank write path). */
60
+ export declare function normalizeProposedMemoryText(value: string): string | undefined;
61
+ /** Evidence map helper re-exported for the engine. */
62
+ export { evidenceByRef };
63
+ //# sourceMappingURL=proposal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposal.d.ts","sourceRoot":"","sources":["../src/proposal.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAEL,aAAa,EAKd,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EAEtB,wBAAwB,EACxB,cAAc,EACd,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,sBAAsB,OAAQ,CAAA;AAC3C,eAAO,MAAM,2BAA2B,IAAI,CAAA;AAC5C,eAAO,MAAM,wBAAwB,OAAQ,CAAA;AAC7C,eAAO,MAAM,4BAA4B,MAAM,CAAA;AAC/C,eAAO,MAAM,kBAAkB,KAAK,CAAA;AACpC,eAAO,MAAM,wBAAwB,IAAI,CAAA;AACzC,eAAO,MAAM,gBAAgB,IAAI,CAAA;AACjC,eAAO,MAAM,cAAc,KAAK,CAAA;AA4DhC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CA4B3E;AAED,2DAA2D;AAC3D,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG,uBAAuB,GAAG,SAAS,CAsB7F;AAED,+EAA+E;AAC/E,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAiC3F;AAID,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACpD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAA;CACvD,GAAG,MAAM,CAqBT;AAED,uFAAuF;AACvF,wBAAgB,kCAAkC,CAAC,KAAK,EAAE;IACxD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAA;IACtD,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAA;CACvC,GAAG,MAAM,CAqBT;AAED,qFAAqF;AACrF,wBAAgB,iCAAiC,CAAC,KAAK,EAAE;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,SAAS;QAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS;YAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAClH,EAAE,CAAA;CACJ,GAAG,MAAM,CAeT;AAID,sFAAsF;AACtF,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAKpF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,kBAAkB,EACxB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,wBAAwB,CAAC,GACtD,kBAAkB,GAAG,SAAS,CAiBhC;AAED,qFAAqF;AACrF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI7E;AAED,sDAAsD;AACtD,OAAO,EAAE,aAAa,EAAE,CAAA"}