@remnic/core 9.3.624 → 9.3.625
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 +18 -16
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +12 -5
- package/dist/access-http.js +10 -9
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +8 -8
- package/dist/access-schema.d.ts +5 -5
- package/dist/{access-service-CBNEKjzN.d.ts → access-service-C_sfOHsX.d.ts} +26 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +7 -7
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +2 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/{chunk-7TPH6UZL.js → chunk-2RHI3FGV.js} +540 -17
- package/dist/chunk-2RHI3FGV.js.map +1 -0
- package/dist/{chunk-GYTVOLNX.js → chunk-3MNBW7R7.js} +2 -2
- package/dist/{chunk-QFQQFX2H.js → chunk-3R2UZV3U.js} +2 -2
- package/dist/{chunk-O4UNM6OR.js → chunk-532VCWYW.js} +2 -2
- package/dist/{chunk-2UFQYU5F.js → chunk-57QXN2CS.js} +2 -2
- package/dist/chunk-7WV3F5DQ.js +22 -0
- package/dist/chunk-7WV3F5DQ.js.map +1 -0
- package/dist/{chunk-RKW6QR7W.js → chunk-AZ4RI3QD.js} +1461 -78
- package/dist/chunk-AZ4RI3QD.js.map +1 -0
- package/dist/{chunk-KQFQ3IS5.js → chunk-F3FY3D3S.js} +43 -7
- package/dist/chunk-F3FY3D3S.js.map +1 -0
- package/dist/{chunk-4R4KTDIE.js → chunk-FPNQF475.js} +1 -1
- package/dist/chunk-FPNQF475.js.map +1 -0
- package/dist/{chunk-UGEBPVNI.js → chunk-GE7Q7KXP.js} +2 -2
- package/dist/{chunk-GLWW3EJQ.js → chunk-KB4MFBF5.js} +3 -3
- package/dist/{chunk-5GOMXHLC.js → chunk-KKTXCFD7.js} +255 -1
- package/dist/chunk-KKTXCFD7.js.map +1 -0
- package/dist/{chunk-FH3PPO42.js → chunk-KVFYTRMV.js} +2 -2
- package/dist/{chunk-BNW5NJJH.js → chunk-LQYTQCXM.js} +2 -2
- package/dist/{chunk-AYHXQR53.js → chunk-MVQN73GT.js} +2 -2
- package/dist/{chunk-ZZPIJPPD.js → chunk-N5RGXWLQ.js} +2 -2
- package/dist/chunk-NDAH7BJ5.js +213 -0
- package/dist/chunk-NDAH7BJ5.js.map +1 -0
- package/dist/{chunk-R3OQGYOU.js → chunk-P2D2MM47.js} +2 -2
- package/dist/{chunk-PSUB67YB.js → chunk-PW6GURU3.js} +2 -2
- package/dist/{chunk-W3BKVM64.js → chunk-QDV6VAD4.js} +2 -2
- package/dist/{chunk-3QSU4NFF.js → chunk-QHXW3LZV.js} +3 -3
- package/dist/{chunk-I6UCUHLK.js → chunk-SHV5Y2WU.js} +182 -3
- package/dist/chunk-SHV5Y2WU.js.map +1 -0
- package/dist/{chunk-OZXVGYGZ.js → chunk-STDAAGH7.js} +2 -2
- package/dist/{chunk-FMGWXIES.js → chunk-TZDSNIRO.js} +5 -5
- package/dist/{chunk-2L54V4ZO.js → chunk-UELS6WWF.js} +2 -2
- package/dist/{chunk-PJGB7XRR.js → chunk-UGHUNQ74.js} +502 -134
- package/dist/chunk-UGHUNQ74.js.map +1 -0
- package/dist/{chunk-FG76RDVI.js → chunk-Y3TMFC6I.js} +136 -4
- package/dist/chunk-Y3TMFC6I.js.map +1 -0
- package/dist/{chunk-BPSGLMQ4.js → chunk-YQNADJCT.js} +2 -2
- package/dist/{cli-Cw729yLf.d.ts → cli-EZv6YE6_.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +23 -21
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +307 -9
- package/dist/index.js +155 -29
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +8 -7
- package/dist/{orchestrator-CqWOjfgl.d.ts → orchestrator-CEycaY3M.d.ts} +361 -4
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +13 -11
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +3 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +10 -10
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
- package/dist/{semantic-consolidation-4HkHWgeI.d.ts → semantic-consolidation-FbhPeJjB.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +5 -5
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +19 -1
- package/dist/storage.js +2 -2
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/types-D5VRAI04.d.ts +3134 -0
- package/dist/types.d.ts +3 -2862
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +1 -1
- package/src/access-http.ts +167 -0
- package/src/access-mcp.ts +198 -0
- package/src/access-service.ts +65 -0
- package/src/cli.ts +187 -0
- package/src/config.ts +7 -0
- package/src/index.ts +7 -0
- package/src/orchestrator.ts +42 -0
- package/src/storage.ts +106 -0
- package/src/types.ts +5 -0
- package/src/wearables/cleanup.test.ts +134 -0
- package/src/wearables/cleanup.ts +188 -0
- package/src/wearables/cli.test.ts +170 -0
- package/src/wearables/cli.ts +441 -0
- package/src/wearables/config.test.ts +143 -0
- package/src/wearables/config.ts +332 -0
- package/src/wearables/corrections.test.ts +118 -0
- package/src/wearables/corrections.ts +211 -0
- package/src/wearables/day-store.test.ts +143 -0
- package/src/wearables/day-store.ts +238 -0
- package/src/wearables/errors.test.ts +32 -0
- package/src/wearables/errors.ts +29 -0
- package/src/wearables/index.ts +114 -0
- package/src/wearables/memory-gen.test.ts +342 -0
- package/src/wearables/memory-gen.ts +413 -0
- package/src/wearables/pipeline.test.ts +608 -0
- package/src/wearables/pipeline.ts +519 -0
- package/src/wearables/redaction.test.ts +94 -0
- package/src/wearables/redaction.ts +156 -0
- package/src/wearables/registry.test.ts +62 -0
- package/src/wearables/registry.ts +133 -0
- package/src/wearables/service.test.ts +425 -0
- package/src/wearables/service.ts +691 -0
- package/src/wearables/speakers.test.ts +110 -0
- package/src/wearables/speakers.ts +174 -0
- package/src/wearables/storage-io.test.ts +105 -0
- package/src/wearables/sync-state.test.ts +134 -0
- package/src/wearables/sync-state.ts +186 -0
- package/src/wearables/types.ts +285 -0
- package/dist/chunk-4R4KTDIE.js.map +0 -1
- package/dist/chunk-5GOMXHLC.js.map +0 -1
- package/dist/chunk-7TPH6UZL.js.map +0 -1
- package/dist/chunk-FG76RDVI.js.map +0 -1
- package/dist/chunk-I6UCUHLK.js.map +0 -1
- package/dist/chunk-KQFQ3IS5.js.map +0 -1
- package/dist/chunk-PJGB7XRR.js.map +0 -1
- package/dist/chunk-RKW6QR7W.js.map +0 -1
- /package/dist/{chunk-GYTVOLNX.js.map → chunk-3MNBW7R7.js.map} +0 -0
- /package/dist/{chunk-QFQQFX2H.js.map → chunk-3R2UZV3U.js.map} +0 -0
- /package/dist/{chunk-O4UNM6OR.js.map → chunk-532VCWYW.js.map} +0 -0
- /package/dist/{chunk-2UFQYU5F.js.map → chunk-57QXN2CS.js.map} +0 -0
- /package/dist/{chunk-UGEBPVNI.js.map → chunk-GE7Q7KXP.js.map} +0 -0
- /package/dist/{chunk-GLWW3EJQ.js.map → chunk-KB4MFBF5.js.map} +0 -0
- /package/dist/{chunk-FH3PPO42.js.map → chunk-KVFYTRMV.js.map} +0 -0
- /package/dist/{chunk-BNW5NJJH.js.map → chunk-LQYTQCXM.js.map} +0 -0
- /package/dist/{chunk-AYHXQR53.js.map → chunk-MVQN73GT.js.map} +0 -0
- /package/dist/{chunk-ZZPIJPPD.js.map → chunk-N5RGXWLQ.js.map} +0 -0
- /package/dist/{chunk-R3OQGYOU.js.map → chunk-P2D2MM47.js.map} +0 -0
- /package/dist/{chunk-PSUB67YB.js.map → chunk-PW6GURU3.js.map} +0 -0
- /package/dist/{chunk-W3BKVM64.js.map → chunk-QDV6VAD4.js.map} +0 -0
- /package/dist/{chunk-3QSU4NFF.js.map → chunk-QHXW3LZV.js.map} +0 -0
- /package/dist/{chunk-OZXVGYGZ.js.map → chunk-STDAAGH7.js.map} +0 -0
- /package/dist/{chunk-FMGWXIES.js.map → chunk-TZDSNIRO.js.map} +0 -0
- /package/dist/{chunk-2L54V4ZO.js.map → chunk-UELS6WWF.js.map} +0 -0
- /package/dist/{chunk-BPSGLMQ4.js.map → chunk-YQNADJCT.js.map} +0 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
|
|
4
|
+
import type { BufferTurn, ExtractionResult } from "../types.js";
|
|
5
|
+
import {
|
|
6
|
+
buildExtractionTurns,
|
|
7
|
+
generateWearableMemories,
|
|
8
|
+
importNativeMemories,
|
|
9
|
+
memoryStatusForMode,
|
|
10
|
+
writeDailyDigestMemory,
|
|
11
|
+
type WearableMemoryWriter,
|
|
12
|
+
} from "./memory-gen.js";
|
|
13
|
+
import { emptySpeakerRegistry } from "./speakers.js";
|
|
14
|
+
import type { WearableConversation, WearableSourceSettings } from "./types.js";
|
|
15
|
+
|
|
16
|
+
const REGISTRY = emptySpeakerRegistry();
|
|
17
|
+
|
|
18
|
+
function settings(
|
|
19
|
+
overrides: Partial<WearableSourceSettings> = {},
|
|
20
|
+
): WearableSourceSettings {
|
|
21
|
+
return {
|
|
22
|
+
enabled: true,
|
|
23
|
+
memoryMode: "review",
|
|
24
|
+
minConfidence: 0.6,
|
|
25
|
+
minImportance: "low",
|
|
26
|
+
maxMemoriesPerDay: 20,
|
|
27
|
+
importNativeMemories: "off",
|
|
28
|
+
cleanup: {
|
|
29
|
+
mergeSameSpeaker: true,
|
|
30
|
+
stripFillers: true,
|
|
31
|
+
collapseRepeats: true,
|
|
32
|
+
dropLowQuality: true,
|
|
33
|
+
},
|
|
34
|
+
...overrides,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function conversation(
|
|
39
|
+
id: string,
|
|
40
|
+
texts: string[],
|
|
41
|
+
): WearableConversation {
|
|
42
|
+
return {
|
|
43
|
+
id,
|
|
44
|
+
source: "limitless",
|
|
45
|
+
title: "Planning chat",
|
|
46
|
+
startIso: "2026-06-10T15:00:00Z",
|
|
47
|
+
endIso: "2026-06-10T15:30:00Z",
|
|
48
|
+
segments: texts.map((text, index) => ({
|
|
49
|
+
speakerKey: index % 2 === 0 ? "user" : "Speaker 2",
|
|
50
|
+
isWearer: index % 2 === 0,
|
|
51
|
+
text,
|
|
52
|
+
})),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const LONG_CONVERSATION = conversation("conv-1", [
|
|
57
|
+
"I decided we are moving the launch to September twelfth, that is final.",
|
|
58
|
+
"Sounds good, I will tell the vendor about the new date tomorrow morning.",
|
|
59
|
+
"Also remember that my daughter's recital is on Friday at six pm sharp.",
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
interface WriteCall {
|
|
63
|
+
category: string;
|
|
64
|
+
content: string;
|
|
65
|
+
options: Record<string, unknown>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function makeWriter(existingHashes: string[] = []): {
|
|
69
|
+
writer: WearableMemoryWriter;
|
|
70
|
+
writes: WriteCall[];
|
|
71
|
+
} {
|
|
72
|
+
const writes: WriteCall[] = [];
|
|
73
|
+
const existing = new Set(existingHashes);
|
|
74
|
+
return {
|
|
75
|
+
writes,
|
|
76
|
+
writer: {
|
|
77
|
+
async writeMemory(category, content, options) {
|
|
78
|
+
writes.push({ category, content, options: options as Record<string, unknown> });
|
|
79
|
+
return `id-${writes.length}`;
|
|
80
|
+
},
|
|
81
|
+
async hasFactContentHash(content) {
|
|
82
|
+
return existing.has(content);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function extractionReturning(
|
|
89
|
+
facts: ExtractionResult["facts"],
|
|
90
|
+
): (turns: BufferTurn[]) => Promise<ExtractionResult> {
|
|
91
|
+
return async () => ({
|
|
92
|
+
facts,
|
|
93
|
+
profileUpdates: [],
|
|
94
|
+
entities: [],
|
|
95
|
+
questions: [],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
test("buildExtractionTurns labels speakers, marks the wearer, and chunks", () => {
|
|
100
|
+
const turns = buildExtractionTurns("limitless", "2026-06-10", LONG_CONVERSATION, REGISTRY);
|
|
101
|
+
assert.equal(turns.length, 1);
|
|
102
|
+
assert.equal(turns[0].role, "user");
|
|
103
|
+
assert.match(turns[0].content, /Me \(you\): I decided we are moving the launch/);
|
|
104
|
+
assert.match(turns[0].content, /Speaker 2: Sounds good/);
|
|
105
|
+
assert.match(turns[0].content, /Wearable transcript \(limitless\) — 2026-06-10/);
|
|
106
|
+
assert.equal(turns[0].sourceValidAt, "2026-06-10T15:00:00Z");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("buildExtractionTurns skips conversations with no substance", () => {
|
|
110
|
+
const turns = buildExtractionTurns(
|
|
111
|
+
"limitless",
|
|
112
|
+
"2026-06-10",
|
|
113
|
+
conversation("tiny", ["ok", "yes"]),
|
|
114
|
+
REGISTRY,
|
|
115
|
+
);
|
|
116
|
+
assert.equal(turns.length, 0);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("memoryStatusForMode maps review to pending_review and auto to active", () => {
|
|
120
|
+
assert.equal(memoryStatusForMode("review"), "pending_review");
|
|
121
|
+
assert.equal(memoryStatusForMode("off"), "pending_review");
|
|
122
|
+
assert.equal(memoryStatusForMode("auto"), "active");
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test("mode off never extracts or writes", async () => {
|
|
126
|
+
const { writer, writes } = makeWriter();
|
|
127
|
+
let extracted = 0;
|
|
128
|
+
const result = await generateWearableMemories(
|
|
129
|
+
"limitless",
|
|
130
|
+
"2026-06-10",
|
|
131
|
+
[LONG_CONVERSATION],
|
|
132
|
+
settings({ memoryMode: "off" }),
|
|
133
|
+
REGISTRY,
|
|
134
|
+
{
|
|
135
|
+
extract: async () => {
|
|
136
|
+
extracted += 1;
|
|
137
|
+
return { facts: [], profileUpdates: [], entities: [], questions: [] };
|
|
138
|
+
},
|
|
139
|
+
writer,
|
|
140
|
+
},
|
|
141
|
+
);
|
|
142
|
+
assert.equal(extracted, 0);
|
|
143
|
+
assert.equal(writes.length, 0);
|
|
144
|
+
assert.equal(result.created, 0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test("review mode writes pending_review with full wearable provenance", async () => {
|
|
148
|
+
const { writer, writes } = makeWriter();
|
|
149
|
+
const result = await generateWearableMemories(
|
|
150
|
+
"limitless",
|
|
151
|
+
"2026-06-10",
|
|
152
|
+
[LONG_CONVERSATION],
|
|
153
|
+
settings(),
|
|
154
|
+
REGISTRY,
|
|
155
|
+
{
|
|
156
|
+
extract: extractionReturning([
|
|
157
|
+
{
|
|
158
|
+
category: "decision",
|
|
159
|
+
content: "Launch moved to September 12.",
|
|
160
|
+
confidence: 0.9,
|
|
161
|
+
tags: ["launch"],
|
|
162
|
+
},
|
|
163
|
+
]),
|
|
164
|
+
writer,
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
assert.equal(result.created, 1);
|
|
168
|
+
assert.equal(writes.length, 1);
|
|
169
|
+
const write = writes[0];
|
|
170
|
+
assert.equal(write.category, "decision");
|
|
171
|
+
assert.equal(write.options.status, "pending_review");
|
|
172
|
+
assert.equal(write.options.source, "wearable:limitless");
|
|
173
|
+
assert.equal(write.options.validAt, "2026-06-10T15:00:00Z");
|
|
174
|
+
const attrs = write.options.structuredAttributes as Record<string, string>;
|
|
175
|
+
assert.equal(attrs.wearableSource, "limitless");
|
|
176
|
+
assert.equal(attrs.wearableDate, "2026-06-10");
|
|
177
|
+
assert.equal(attrs.wearableConversationId, "conv-1");
|
|
178
|
+
const tags = write.options.tags as string[];
|
|
179
|
+
assert.ok(tags.includes("wearable"));
|
|
180
|
+
assert.ok(tags.includes("wearable:limitless"));
|
|
181
|
+
assert.ok(tags.includes("wearable-day:2026-06-10"));
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("auto mode writes active status", async () => {
|
|
185
|
+
const { writer, writes } = makeWriter();
|
|
186
|
+
await generateWearableMemories(
|
|
187
|
+
"limitless",
|
|
188
|
+
"2026-06-10",
|
|
189
|
+
[LONG_CONVERSATION],
|
|
190
|
+
settings({ memoryMode: "auto" }),
|
|
191
|
+
REGISTRY,
|
|
192
|
+
{
|
|
193
|
+
extract: extractionReturning([
|
|
194
|
+
{ category: "fact", content: "Vendor call happens tomorrow morning.", confidence: 0.8, tags: [] },
|
|
195
|
+
]),
|
|
196
|
+
writer,
|
|
197
|
+
},
|
|
198
|
+
);
|
|
199
|
+
assert.equal(writes[0].options.status, "active");
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test("gates: confidence floor, importance floor, dedup, and unsupported categories", async () => {
|
|
203
|
+
const { writer, writes } = makeWriter(["Already stored fact about the vendor."]);
|
|
204
|
+
const result = await generateWearableMemories(
|
|
205
|
+
"limitless",
|
|
206
|
+
"2026-06-10",
|
|
207
|
+
[LONG_CONVERSATION],
|
|
208
|
+
settings({ minConfidence: 0.7, minImportance: "low" }),
|
|
209
|
+
REGISTRY,
|
|
210
|
+
{
|
|
211
|
+
extract: extractionReturning([
|
|
212
|
+
{ category: "fact", content: "Low confidence rumor.", confidence: 0.3, tags: [] },
|
|
213
|
+
{ category: "fact", content: "ok", confidence: 0.9, tags: [] },
|
|
214
|
+
{ category: "procedure", content: "Step one do thing.", confidence: 0.9, tags: [] },
|
|
215
|
+
{ category: "fact", content: "Already stored fact about the vendor.", confidence: 0.9, tags: [] },
|
|
216
|
+
{ category: "fact", content: "Recital is Friday at 6pm.", confidence: 0.9, tags: [] },
|
|
217
|
+
{ category: "fact", content: "Recital is Friday at 6pm.", confidence: 0.9, tags: [] },
|
|
218
|
+
]),
|
|
219
|
+
writer,
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
assert.equal(result.created, 1);
|
|
223
|
+
assert.equal(writes[0].content, "Recital is Friday at 6pm.");
|
|
224
|
+
assert.equal(result.skippedByReason["below-confidence"], 1);
|
|
225
|
+
assert.equal(result.skippedByReason["below-importance"], 1);
|
|
226
|
+
assert.equal(result.skippedByReason["unsupported-category"], 1);
|
|
227
|
+
assert.equal(result.skippedByReason["duplicate-existing"], 1);
|
|
228
|
+
assert.equal(result.skippedByReason["duplicate-in-run"], 1);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("day cap keeps the most important candidates; 0 disables the cap", async () => {
|
|
232
|
+
const facts = [
|
|
233
|
+
{ category: "fact" as const, content: "I prefer the aisle seat on long flights always.", confidence: 0.9, tags: [] },
|
|
234
|
+
{ category: "decision" as const, content: "Critical: I decided to sign the ACME contract.", confidence: 0.95, tags: [] },
|
|
235
|
+
{ category: "fact" as const, content: "We talked about the weather being warm lately.", confidence: 0.9, tags: [] },
|
|
236
|
+
];
|
|
237
|
+
{
|
|
238
|
+
const { writer, writes } = makeWriter();
|
|
239
|
+
const result = await generateWearableMemories(
|
|
240
|
+
"limitless",
|
|
241
|
+
"2026-06-10",
|
|
242
|
+
[LONG_CONVERSATION],
|
|
243
|
+
settings({ maxMemoriesPerDay: 1 }),
|
|
244
|
+
REGISTRY,
|
|
245
|
+
{ extract: extractionReturning(facts), writer },
|
|
246
|
+
);
|
|
247
|
+
assert.equal(result.created, 1);
|
|
248
|
+
assert.equal(result.skippedByReason["over-day-cap"], 2);
|
|
249
|
+
assert.match(writes[0].content, /ACME contract/);
|
|
250
|
+
}
|
|
251
|
+
{
|
|
252
|
+
const { writer, writes } = makeWriter();
|
|
253
|
+
await generateWearableMemories(
|
|
254
|
+
"limitless",
|
|
255
|
+
"2026-06-10",
|
|
256
|
+
[LONG_CONVERSATION],
|
|
257
|
+
settings({ maxMemoriesPerDay: 0 }),
|
|
258
|
+
REGISTRY,
|
|
259
|
+
{ extract: extractionReturning(facts), writer },
|
|
260
|
+
);
|
|
261
|
+
assert.equal(writes.length, 3, "cap of 0 must disable the limit");
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
test("an extraction failure aborts with one warning instead of hammering the engine", async () => {
|
|
266
|
+
const { writer, writes } = makeWriter();
|
|
267
|
+
let calls = 0;
|
|
268
|
+
const result = await generateWearableMemories(
|
|
269
|
+
"limitless",
|
|
270
|
+
"2026-06-10",
|
|
271
|
+
[conversation("a", [LONG_CONVERSATION.segments[0].text, LONG_CONVERSATION.segments[1].text, LONG_CONVERSATION.segments[2].text]), LONG_CONVERSATION],
|
|
272
|
+
settings(),
|
|
273
|
+
REGISTRY,
|
|
274
|
+
{
|
|
275
|
+
extract: async () => {
|
|
276
|
+
calls += 1;
|
|
277
|
+
throw new Error("provider exploded");
|
|
278
|
+
},
|
|
279
|
+
writer,
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
assert.equal(calls, 1);
|
|
283
|
+
assert.equal(result.warnings.length, 1);
|
|
284
|
+
// Foreign error text is reduced to the error class (project-standard
|
|
285
|
+
// displayErrorDetail semantics) — the message itself never surfaces.
|
|
286
|
+
assert.match(result.warnings[0], /extraction failed for limitless\/2026-06-10/);
|
|
287
|
+
assert.ok(!result.warnings[0].includes("provider exploded"));
|
|
288
|
+
assert.equal(writes.length, 0);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test("daily digest writes one deterministic episode memory and dedups", async () => {
|
|
292
|
+
const { writer, writes } = makeWriter();
|
|
293
|
+
const wrote = await writeDailyDigestMemory(
|
|
294
|
+
"limitless",
|
|
295
|
+
"2026-06-10",
|
|
296
|
+
[LONG_CONVERSATION],
|
|
297
|
+
settings(),
|
|
298
|
+
REGISTRY,
|
|
299
|
+
writer,
|
|
300
|
+
);
|
|
301
|
+
assert.equal(wrote, true);
|
|
302
|
+
assert.equal(writes.length, 1);
|
|
303
|
+
assert.equal(writes[0].category, "moment");
|
|
304
|
+
assert.equal(writes[0].options.memoryKind, "episode");
|
|
305
|
+
assert.match(writes[0].content, /Wearable day digest — limitless, 2026-06-10/);
|
|
306
|
+
assert.match(writes[0].content, /Planning chat \(2 speakers\)/);
|
|
307
|
+
|
|
308
|
+
const { writer: writer2, writes: writes2 } = makeWriter([writes[0].content]);
|
|
309
|
+
const wroteAgain = await writeDailyDigestMemory(
|
|
310
|
+
"limitless",
|
|
311
|
+
"2026-06-10",
|
|
312
|
+
[LONG_CONVERSATION],
|
|
313
|
+
settings(),
|
|
314
|
+
REGISTRY,
|
|
315
|
+
writer2,
|
|
316
|
+
);
|
|
317
|
+
assert.equal(wroteAgain, false);
|
|
318
|
+
assert.equal(writes2.length, 0);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test("native memories always import as pending_review and respect prior imports", async () => {
|
|
322
|
+
const { writer, writes } = makeWriter(["Provider fact already in Remnic."]);
|
|
323
|
+
const result = await importNativeMemories(
|
|
324
|
+
"bee",
|
|
325
|
+
[
|
|
326
|
+
{ id: "n1", content: "User enjoys morning runs by the lake." },
|
|
327
|
+
{ id: "n2", content: "Provider fact already in Remnic." },
|
|
328
|
+
{ id: "n3", content: "User enjoys morning runs by the lake. " },
|
|
329
|
+
{ id: "n4", content: "" },
|
|
330
|
+
{ id: "n5", content: "Previously imported." },
|
|
331
|
+
],
|
|
332
|
+
new Set(["n5"]),
|
|
333
|
+
writer,
|
|
334
|
+
);
|
|
335
|
+
// n1 imports; n2 dedups against existing storage; n3 dedups against
|
|
336
|
+
// n1 within the run; n4 is empty; n5 was imported on a prior sync.
|
|
337
|
+
assert.equal(result.imported, 1);
|
|
338
|
+
assert.equal(writes.length, 1);
|
|
339
|
+
assert.equal(writes[0].options.status, "pending_review");
|
|
340
|
+
assert.equal(writes[0].options.source, "wearable:bee:native");
|
|
341
|
+
assert.deepEqual(result.importedIds.sort(), ["n1", "n2", "n3"]);
|
|
342
|
+
});
|