@remnic/core 9.3.597 → 9.3.598
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-cli.js +17 -17
- package/dist/access-http.js +6 -6
- package/dist/access-mcp.js +5 -5
- package/dist/access-service.js +4 -4
- package/dist/behavior-learner.js +2 -1
- package/dist/behavior-learner.js.map +1 -1
- package/dist/causal-behavior.js +3 -3
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.js +4 -4
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory.js +2 -2
- package/dist/{chunk-A2Z6UCWT.js → chunk-33JBK2XP.js} +2 -2
- package/dist/{chunk-D2MMMTDV.js → chunk-5SQ5CQJP.js} +2 -2
- package/dist/{chunk-F4LM4ULA.js → chunk-65JSA4MP.js} +12 -12
- package/dist/{chunk-SKGV326D.js → chunk-6GDHLVJC.js} +2 -2
- package/dist/chunk-6HEM6HTQ.js +359 -0
- package/dist/chunk-6HEM6HTQ.js.map +1 -0
- package/dist/{chunk-WXACKLKP.js → chunk-75O6YQ63.js} +22 -7
- package/dist/chunk-75O6YQ63.js.map +1 -0
- package/dist/{chunk-D65TSG24.js → chunk-7DZRO2DC.js} +2 -2
- package/dist/{chunk-TYICDVQW.js → chunk-BDCCWRHR.js} +4 -4
- package/dist/{chunk-LYPDMKUT.js → chunk-CL3MWNNQ.js} +2 -2
- package/dist/{chunk-YQMZ7IH2.js → chunk-D4KJ74JJ.js} +65 -27
- package/dist/chunk-D4KJ74JJ.js.map +1 -0
- package/dist/{chunk-W5O2FQTZ.js → chunk-GUPISBV2.js} +2 -2
- package/dist/{chunk-472U7RDF.js → chunk-JGSKJHF7.js} +2 -2
- package/dist/{chunk-IEFHBIU2.js → chunk-KDUVQU6Y.js} +14 -14
- package/dist/{chunk-6HZ6AO2P.js → chunk-LBJBNWS2.js} +37 -10
- package/dist/chunk-LBJBNWS2.js.map +1 -0
- package/dist/{chunk-Z4R6RI2N.js → chunk-NSKYFGDL.js} +2 -2
- package/dist/{chunk-OD5LFAPZ.js → chunk-V67GWXM2.js} +1 -1
- package/dist/{chunk-5NXIJZFX.js → chunk-WR64DQFE.js} +3 -3
- package/dist/{chunk-5BUGGPBR.js → chunk-WZA5Y6AC.js} +3 -3
- package/dist/chunk-ZBJMUXZH.js +121 -0
- package/dist/chunk-ZBJMUXZH.js.map +1 -0
- package/dist/{chunk-XPXEJRUB.js → chunk-ZRWB5D4H.js} +2 -2
- package/dist/{chunk-MA5MWGKP.js → chunk-ZT3EGNLR.js} +2 -2
- package/dist/{chunk-LMPHTYJC.js → chunk-ZZYF3BUL.js} +2 -2
- package/dist/cli.js +14 -14
- package/dist/compounding/engine.js +1 -1
- package/dist/direct-answer-wiring.js +3 -3
- package/dist/direct-answer.d.ts +1 -1
- package/dist/direct-answer.js +2 -2
- package/dist/harmonic-retrieval.js +2 -2
- package/dist/index.js +21 -21
- package/dist/orchestrator.js +16 -16
- package/dist/policy-runtime.js +3 -2
- package/dist/recall-query-policy.js +2 -1
- package/dist/recall-tokenization.d.ts +5 -1
- package/dist/recall-tokenization.js +3 -1
- package/dist/resume-bundles.js +3 -3
- package/dist/retrieval-agents.js +2 -2
- package/dist/schemas.d.ts +22 -22
- package/dist/semantic-consolidation.js +2 -2
- package/dist/semantic-rule-verifier.js +2 -2
- package/dist/temporal-index.js +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/trust-zones.js +2 -2
- package/dist/verified-recall.js +2 -2
- package/dist/work-product-ledger.js +2 -2
- package/package.json +1 -1
- package/src/causal-chain.ts +80 -42
- package/src/direct-answer.test.ts +618 -15
- package/src/direct-answer.ts +259 -20
- package/src/recall-query-policy.ts +49 -27
- package/src/recall-tokenization.ts +131 -21
- package/src/temporal-index.ts +23 -6
- package/dist/chunk-6HZ6AO2P.js.map +0 -1
- package/dist/chunk-DT5TVLJE.js +0 -32
- package/dist/chunk-DT5TVLJE.js.map +0 -1
- package/dist/chunk-WXACKLKP.js.map +0 -1
- package/dist/chunk-Y4FHOFJ2.js +0 -140
- package/dist/chunk-Y4FHOFJ2.js.map +0 -1
- package/dist/chunk-YQMZ7IH2.js.map +0 -1
- /package/dist/{chunk-A2Z6UCWT.js.map → chunk-33JBK2XP.js.map} +0 -0
- /package/dist/{chunk-D2MMMTDV.js.map → chunk-5SQ5CQJP.js.map} +0 -0
- /package/dist/{chunk-F4LM4ULA.js.map → chunk-65JSA4MP.js.map} +0 -0
- /package/dist/{chunk-SKGV326D.js.map → chunk-6GDHLVJC.js.map} +0 -0
- /package/dist/{chunk-D65TSG24.js.map → chunk-7DZRO2DC.js.map} +0 -0
- /package/dist/{chunk-TYICDVQW.js.map → chunk-BDCCWRHR.js.map} +0 -0
- /package/dist/{chunk-LYPDMKUT.js.map → chunk-CL3MWNNQ.js.map} +0 -0
- /package/dist/{chunk-W5O2FQTZ.js.map → chunk-GUPISBV2.js.map} +0 -0
- /package/dist/{chunk-472U7RDF.js.map → chunk-JGSKJHF7.js.map} +0 -0
- /package/dist/{chunk-IEFHBIU2.js.map → chunk-KDUVQU6Y.js.map} +0 -0
- /package/dist/{chunk-Z4R6RI2N.js.map → chunk-NSKYFGDL.js.map} +0 -0
- /package/dist/{chunk-OD5LFAPZ.js.map → chunk-V67GWXM2.js.map} +0 -0
- /package/dist/{chunk-5NXIJZFX.js.map → chunk-WR64DQFE.js.map} +0 -0
- /package/dist/{chunk-5BUGGPBR.js.map → chunk-WZA5Y6AC.js.map} +0 -0
- /package/dist/{chunk-XPXEJRUB.js.map → chunk-ZRWB5D4H.js.map} +0 -0
- /package/dist/{chunk-MA5MWGKP.js.map → chunk-ZT3EGNLR.js.map} +0 -0
- /package/dist/{chunk-LMPHTYJC.js.map → chunk-ZZYF3BUL.js.map} +0 -0
package/src/causal-chain.ts
CHANGED
|
@@ -6,20 +6,15 @@
|
|
|
6
6
|
* another session. Persists edges in a graph index for later retrieval.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import path from "node:path";
|
|
10
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
11
9
|
import { createHash } from "node:crypto";
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
10
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
11
|
+
import path from "node:path";
|
|
14
12
|
import { topicOverlapScore } from "./boxes.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
assertIsoRecordedAt,
|
|
18
|
-
assertString,
|
|
19
|
-
isRecord,
|
|
20
|
-
recordStoreDay,
|
|
21
|
-
} from "./store-contract.js";
|
|
13
|
+
import { type CausalTrajectoryRecord, resolveCausalTrajectoryStoreDir } from "./causal-trajectory.js";
|
|
14
|
+
import { listJsonFiles, readJsonFile } from "./json-store.js";
|
|
22
15
|
import { log } from "./logger.js";
|
|
16
|
+
import { normalizeRecallTokens } from "./recall-tokenization.js";
|
|
17
|
+
import { assertIsoRecordedAt, assertString, isRecord, recordStoreDay } from "./store-contract.js";
|
|
23
18
|
|
|
24
19
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
25
20
|
|
|
@@ -65,6 +60,59 @@ const STITCH_WEIGHTS = {
|
|
|
65
60
|
temporalProximity: 1.0,
|
|
66
61
|
} as const;
|
|
67
62
|
|
|
63
|
+
function hasUnsegmentableRecallChar(token: string): boolean {
|
|
64
|
+
if (token.includes("ー") || token.includes("ー")) return true;
|
|
65
|
+
return /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}]/u.test(token);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function extractUnsegmentableStitchPhrases(value: string): string[] {
|
|
69
|
+
const phrases = new Set<string>();
|
|
70
|
+
let segment = "";
|
|
71
|
+
|
|
72
|
+
const flushSegment = () => {
|
|
73
|
+
if ([...segment].length >= 4) {
|
|
74
|
+
phrases.add(segment);
|
|
75
|
+
}
|
|
76
|
+
segment = "";
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
for (const ch of value.toLowerCase().normalize("NFC")) {
|
|
80
|
+
if (hasUnsegmentableRecallChar(ch)) {
|
|
81
|
+
segment += ch;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (/\p{M}/u.test(ch) && segment.length > 0) {
|
|
85
|
+
segment += ch;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (/\s/u.test(ch) && segment.length > 0) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
flushSegment();
|
|
92
|
+
}
|
|
93
|
+
flushSegment();
|
|
94
|
+
|
|
95
|
+
return [...phrases];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function normalizeStitchLexicalTokens(value: string, extraStopWords: string[] = []): string[] {
|
|
99
|
+
const tokens = new Set(
|
|
100
|
+
normalizeRecallTokens(value, extraStopWords).filter((token) => !hasUnsegmentableRecallChar(token))
|
|
101
|
+
);
|
|
102
|
+
for (const phrase of extractUnsegmentableStitchPhrases(value)) {
|
|
103
|
+
tokens.add(phrase);
|
|
104
|
+
}
|
|
105
|
+
return [...tokens];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function countTokenSetOverlap(queryTokens: Set<string>, valueTokens: Set<string>): number {
|
|
109
|
+
let matches = 0;
|
|
110
|
+
for (const token of queryTokens) {
|
|
111
|
+
if (valueTokens.has(token)) matches += 1;
|
|
112
|
+
}
|
|
113
|
+
return matches;
|
|
114
|
+
}
|
|
115
|
+
|
|
68
116
|
// ─── Validation ──────────────────────────────────────────────────────────────
|
|
69
117
|
|
|
70
118
|
export function validateCausalEdge(raw: unknown): CausalEdge {
|
|
@@ -97,9 +145,7 @@ export function validateCausalEdge(raw: unknown): CausalEdge {
|
|
|
97
145
|
createdAt: assertIsoRecordedAt(assertString(raw.createdAt, "createdAt")),
|
|
98
146
|
metadata: isRecord(raw.metadata)
|
|
99
147
|
? Object.fromEntries(
|
|
100
|
-
Object.entries(raw.metadata).filter(
|
|
101
|
-
(entry): entry is [string, string] => typeof entry[1] === "string",
|
|
102
|
-
),
|
|
148
|
+
Object.entries(raw.metadata).filter((entry): entry is [string, string] => typeof entry[1] === "string")
|
|
103
149
|
)
|
|
104
150
|
: undefined,
|
|
105
151
|
};
|
|
@@ -108,10 +154,7 @@ export function validateCausalEdge(raw: unknown): CausalEdge {
|
|
|
108
154
|
// ─── Stable Edge ID ──────────────────────────────────────────────────────────
|
|
109
155
|
|
|
110
156
|
export function makeEdgeId(fromId: string, toId: string): string {
|
|
111
|
-
const digest = createHash("sha256")
|
|
112
|
-
.update(`${fromId}\0${toId}`)
|
|
113
|
-
.digest("hex")
|
|
114
|
-
.slice(0, 12);
|
|
157
|
+
const digest = createHash("sha256").update(`${fromId}\0${toId}`).digest("hex").slice(0, 12);
|
|
115
158
|
return `edge-${digest}`;
|
|
116
159
|
}
|
|
117
160
|
|
|
@@ -153,9 +196,9 @@ export async function readChainIndex(chainsDir: string): Promise<CausalChainInde
|
|
|
153
196
|
try {
|
|
154
197
|
const raw = JSON.parse(await readFile(chainIndexPath(chainsDir), "utf8"));
|
|
155
198
|
return {
|
|
156
|
-
outgoing: isRecord(raw.outgoing) ? raw.outgoing as Record<string, string[]> : {},
|
|
157
|
-
incoming: isRecord(raw.incoming) ? raw.incoming as Record<string, string[]> : {},
|
|
158
|
-
edges: isRecord(raw.edges) ? raw.edges as Record<string, CausalEdge> : {},
|
|
199
|
+
outgoing: isRecord(raw.outgoing) ? (raw.outgoing as Record<string, string[]>) : {},
|
|
200
|
+
incoming: isRecord(raw.incoming) ? (raw.incoming as Record<string, string[]>) : {},
|
|
201
|
+
edges: isRecord(raw.edges) ? (raw.edges as Record<string, CausalEdge>) : {},
|
|
159
202
|
updatedAt: typeof raw.updatedAt === "string" ? raw.updatedAt : new Date().toISOString(),
|
|
160
203
|
};
|
|
161
204
|
} catch {
|
|
@@ -202,19 +245,18 @@ function addEdgeToIndex(index: CausalChainIndex, edge: CausalEdge): void {
|
|
|
202
245
|
*/
|
|
203
246
|
export function scoreStitchCandidate(
|
|
204
247
|
newTrajectory: CausalTrajectoryRecord,
|
|
205
|
-
candidate: CausalTrajectoryRecord
|
|
248
|
+
candidate: CausalTrajectoryRecord
|
|
206
249
|
): StitchCandidate {
|
|
207
250
|
let score = 0;
|
|
208
251
|
let dominantMethod: CausalEdge["stitchMethod"] = "lexical";
|
|
209
252
|
let maxComponent = 0;
|
|
210
253
|
|
|
211
254
|
// 1. Follow-up → Goal match (token overlap)
|
|
212
|
-
const newFollowUpTokens = new Set(
|
|
213
|
-
|
|
214
|
-
);
|
|
215
|
-
const candidateGoalTokens = normalizeRecallTokens(candidate.goal, []);
|
|
255
|
+
const newFollowUpTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.followUpSummary ?? "", []));
|
|
256
|
+
const candidateGoalTokens = normalizeStitchLexicalTokens(candidate.goal, []);
|
|
257
|
+
const candidateGoalTokenSet = new Set(candidateGoalTokens);
|
|
216
258
|
if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
|
|
217
|
-
const overlap =
|
|
259
|
+
const overlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);
|
|
218
260
|
const normalized = overlap / Math.max(newFollowUpTokens.size, candidateGoalTokens.length);
|
|
219
261
|
const component = normalized * STITCH_WEIGHTS.followUpToGoal;
|
|
220
262
|
score += component;
|
|
@@ -225,12 +267,11 @@ export function scoreStitchCandidate(
|
|
|
225
267
|
}
|
|
226
268
|
|
|
227
269
|
// 1b. Candidate follow-up → New goal match (reverse direction)
|
|
228
|
-
const candidateFollowUpTokens = new Set(
|
|
229
|
-
|
|
230
|
-
);
|
|
231
|
-
const newGoalTokens = normalizeRecallTokens(newTrajectory.goal, []);
|
|
270
|
+
const candidateFollowUpTokens = new Set(normalizeStitchLexicalTokens(candidate.followUpSummary ?? "", []));
|
|
271
|
+
const newGoalTokens = normalizeStitchLexicalTokens(newTrajectory.goal, []);
|
|
272
|
+
const newGoalTokenSet = new Set(newGoalTokens);
|
|
232
273
|
if (candidateFollowUpTokens.size > 0 && newGoalTokens.length > 0) {
|
|
233
|
-
const overlap =
|
|
274
|
+
const overlap = countTokenSetOverlap(candidateFollowUpTokens, newGoalTokenSet);
|
|
234
275
|
const normalized = overlap / Math.max(candidateFollowUpTokens.size, newGoalTokens.length);
|
|
235
276
|
const component = normalized * 3.0;
|
|
236
277
|
score += component;
|
|
@@ -241,11 +282,9 @@ export function scoreStitchCandidate(
|
|
|
241
282
|
}
|
|
242
283
|
|
|
243
284
|
// 2. Outcome → Goal match
|
|
244
|
-
const newOutcomeTokens = new Set(
|
|
245
|
-
normalizeRecallTokens(newTrajectory.outcomeSummary, []),
|
|
246
|
-
);
|
|
285
|
+
const newOutcomeTokens = new Set(normalizeStitchLexicalTokens(newTrajectory.outcomeSummary, []));
|
|
247
286
|
if (newOutcomeTokens.size > 0) {
|
|
248
|
-
const overlap =
|
|
287
|
+
const overlap = countTokenSetOverlap(newOutcomeTokens, candidateGoalTokenSet);
|
|
249
288
|
const normalized = overlap / Math.max(newOutcomeTokens.size, candidateGoalTokens.length || 1);
|
|
250
289
|
const component = normalized * STITCH_WEIGHTS.outcomeToGoal;
|
|
251
290
|
score += component;
|
|
@@ -297,9 +336,8 @@ export function scoreStitchCandidate(
|
|
|
297
336
|
|
|
298
337
|
// Determine edge type by heuristic
|
|
299
338
|
let edgeType: CausalEdge["edgeType"] = "continuation";
|
|
300
|
-
const goalTokens = new Set(
|
|
301
|
-
const
|
|
302
|
-
const goalOverlap = [...goalTokens].filter((t) => candidateGoalSet.has(t)).length;
|
|
339
|
+
const goalTokens = new Set(newGoalTokens);
|
|
340
|
+
const goalOverlap = countTokenSetOverlap(goalTokens, candidateGoalTokenSet);
|
|
303
341
|
const goalSimilarity = goalTokens.size > 0 ? goalOverlap / goalTokens.size : 0;
|
|
304
342
|
|
|
305
343
|
if (goalSimilarity > 0.7 && candidate.outcomeKind === "failure") {
|
|
@@ -307,7 +345,7 @@ export function scoreStitchCandidate(
|
|
|
307
345
|
} else if (goalSimilarity > 0.7 && newTrajectory.outcomeKind !== candidate.outcomeKind) {
|
|
308
346
|
edgeType = "correction";
|
|
309
347
|
} else if (newFollowUpTokens.size > 0 && candidateGoalTokens.length > 0) {
|
|
310
|
-
const followUpGoalOverlap =
|
|
348
|
+
const followUpGoalOverlap = countTokenSetOverlap(newFollowUpTokens, candidateGoalTokenSet);
|
|
311
349
|
if (followUpGoalOverlap > 0) {
|
|
312
350
|
edgeType = "follow_up_to_goal";
|
|
313
351
|
}
|
|
@@ -324,7 +362,7 @@ async function readRecentTrajectories(
|
|
|
324
362
|
memoryDir: string,
|
|
325
363
|
causalTrajectoryStoreDir: string | undefined,
|
|
326
364
|
currentSessionKey: string,
|
|
327
|
-
lookbackDays: number
|
|
365
|
+
lookbackDays: number
|
|
328
366
|
): Promise<CausalTrajectoryRecord[]> {
|
|
329
367
|
const root = resolveCausalTrajectoryStoreDir(memoryDir, causalTrajectoryStoreDir);
|
|
330
368
|
const trajectoriesDir = path.join(root, "trajectories");
|
|
@@ -370,7 +408,7 @@ export async function stitchCausalChain(options: {
|
|
|
370
408
|
memoryDir,
|
|
371
409
|
causalTrajectoryStoreDir,
|
|
372
410
|
newTrajectory.sessionKey,
|
|
373
|
-
stitchConfig.lookbackDays
|
|
411
|
+
stitchConfig.lookbackDays
|
|
374
412
|
);
|
|
375
413
|
|
|
376
414
|
if (candidates.length === 0) return [];
|