recallnest 2.3.0 → 2.6.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/CHANGELOG.md +187 -0
- package/README.md +49 -38
- package/README_CN.md +46 -31
- package/assets/ui/app.js +1031 -0
- package/assets/ui/index.html +224 -0
- package/assets/ui/styles.css +781 -0
- package/config.json.example +4 -1
- package/docs/api-reference.md +1291 -0
- package/docs/architecture.md +168 -0
- package/docs/connector-spec.md +126 -0
- package/eval/cases-canary.json +58 -0
- package/eval/cases-scope-robustness.json +278 -0
- package/eval/cases.json +117 -20
- package/package.json +25 -4
- package/src/__tests__/access-tracker-novelty.test.ts +304 -0
- package/src/__tests__/activity-counter.test.ts +125 -0
- package/src/__tests__/adaptive-fidelity.test.ts +102 -0
- package/src/__tests__/admission-control.test.ts +206 -0
- package/src/__tests__/anchor-generator.test.ts +67 -0
- package/src/__tests__/api-server-security.test.ts +102 -0
- package/src/__tests__/auto-consolidation.test.ts +168 -0
- package/src/__tests__/auto-recall.test.ts +131 -0
- package/src/__tests__/babel-integration.test.ts +144 -0
- package/src/__tests__/batch-dedup.test.ts +65 -0
- package/src/__tests__/belief-history.test.ts +220 -0
- package/src/__tests__/canary-eval.test.ts +114 -0
- package/src/__tests__/capture-engine.test.ts +1328 -0
- package/src/__tests__/capture-heuristic.test.ts +171 -0
- package/src/__tests__/cascade-forget.test.ts +210 -0
- package/src/__tests__/category-min-scores.test.ts +116 -0
- package/src/__tests__/cc8-cc1-essential-context.test.ts +298 -0
- package/src/__tests__/circuit-breaker.test.ts +99 -0
- package/src/__tests__/cluster-consolidation.test.ts +945 -0
- package/src/__tests__/confidence-metadata.test.ts +125 -0
- package/src/__tests__/confidence-tracker.test.ts +261 -0
- package/src/__tests__/conflict-advisor.test.ts +206 -0
- package/src/__tests__/conflict-escalation.test.ts +149 -0
- package/src/__tests__/conflict-lifecycle.test.ts +83 -0
- package/src/__tests__/conflict-output.test.ts +85 -0
- package/src/__tests__/conflict-store.test.ts +418 -0
- package/src/__tests__/connector-v1.test.ts +181 -0
- package/src/__tests__/consolidation-engine.test.ts +430 -0
- package/src/__tests__/constructive-retrieval.test.ts +509 -0
- package/src/__tests__/context-collapse-renderer.test.ts +214 -0
- package/src/__tests__/context-composer-pins.test.ts +64 -0
- package/src/__tests__/context-composer-task-selection.test.ts +24 -0
- package/src/__tests__/context-reconstructor.test.ts +65 -0
- package/src/__tests__/context-renderer.test.ts +91 -0
- package/src/__tests__/continuity-eval.test.ts +275 -0
- package/src/__tests__/continuity-schema.test.ts +97 -0
- package/src/__tests__/contracts.test.ts +262 -0
- package/src/__tests__/conversation-importer.test.ts +692 -0
- package/src/__tests__/core-recall-eval.test.ts +235 -0
- package/src/__tests__/core-summary.test.ts +109 -0
- package/src/__tests__/data-checkup.test.ts +276 -0
- package/src/__tests__/decay-exemption.test.ts +129 -0
- package/src/__tests__/dedup-actions.test.ts +58 -0
- package/src/__tests__/dedup-guard.test.ts +39 -0
- package/src/__tests__/deterministic-id.test.ts +39 -0
- package/src/__tests__/distill-lock.test.ts +305 -0
- package/src/__tests__/distill-session-argshape.test.ts +79 -0
- package/src/__tests__/doctor.test.ts +319 -0
- package/src/__tests__/dream-pipeline.test.ts +780 -0
- package/src/__tests__/drill-down.test.ts +108 -0
- package/src/__tests__/embedder.test.ts +122 -0
- package/src/__tests__/emotion-decay.test.ts +46 -0
- package/src/__tests__/emotion-detector.test.ts +56 -0
- package/src/__tests__/emotion-phase1-integration.test.ts +153 -0
- package/src/__tests__/emotion-retrieval.test.ts +56 -0
- package/src/__tests__/entity-resolver.test.ts +58 -0
- package/src/__tests__/env-config.test.ts +151 -0
- package/src/__tests__/error-signature-boost.test.ts +87 -0
- package/src/__tests__/error-signature.test.ts +95 -0
- package/src/__tests__/error-taxonomy.test.ts +129 -0
- package/src/__tests__/ethics-layer.test.ts +476 -0
- package/src/__tests__/event-segmenter.test.ts +153 -0
- package/src/__tests__/feature-flags-integration.test.ts +54 -0
- package/src/__tests__/frequency-tracker.test.ts +113 -0
- package/src/__tests__/freshness.test.ts +186 -0
- package/src/__tests__/graph-export.test.ts +489 -0
- package/src/__tests__/hotness-blend.test.ts +283 -0
- package/src/__tests__/ingest-chunking.test.ts +44 -0
- package/src/__tests__/ingest.test.ts +360 -0
- package/src/__tests__/interference-detector.test.ts +203 -0
- package/src/__tests__/kg-extractor.test.ts +192 -0
- package/src/__tests__/kg-store.test.ts +300 -0
- package/src/__tests__/llm-client-pivot.test.ts +628 -0
- package/src/__tests__/llm-consolidation.test.ts +226 -0
- package/src/__tests__/maintenance-locks.test.ts +189 -0
- package/src/__tests__/mcp-efficiency.test.ts +288 -0
- package/src/__tests__/mcp-related-scopes.test.ts +151 -0
- package/src/__tests__/memory-boundaries.test.ts +282 -0
- package/src/__tests__/memory-evolution-b2-b3-e1.test.ts +345 -0
- package/src/__tests__/memory-evolution.test.ts +271 -0
- package/src/__tests__/memory-health-rebalance.test.ts +144 -0
- package/src/__tests__/memory-lint.test.ts +421 -0
- package/src/__tests__/memory-output.test.ts +215 -0
- package/src/__tests__/memory-promotion.test.ts +315 -0
- package/src/__tests__/migrate-dedup-ids.test.ts +65 -0
- package/src/__tests__/multi-vector.test.ts +242 -0
- package/src/__tests__/narrative-architecture.test.ts +456 -0
- package/src/__tests__/noise-filter.test.ts +205 -0
- package/src/__tests__/noise-prototype-bank.test.ts +280 -0
- package/src/__tests__/obsidian-connector.test.ts +363 -0
- package/src/__tests__/omitted-reporting.test.ts +98 -0
- package/src/__tests__/pending-review.test.ts +77 -0
- package/src/__tests__/pii-redact.test.ts +333 -0
- package/src/__tests__/pivot-apply.test.ts +373 -0
- package/src/__tests__/pivot-distill-supervisor.test.ts +457 -0
- package/src/__tests__/pivot-distill.test.ts +1178 -0
- package/src/__tests__/post-retrieval-filter.test.ts +178 -0
- package/src/__tests__/ppr-traversal.test.ts +256 -0
- package/src/__tests__/prediction-engine.test.ts +349 -0
- package/src/__tests__/predictive-prospective-memory.test.ts +416 -0
- package/src/__tests__/preference-guard-smoke.test.ts +211 -0
- package/src/__tests__/preference-matcher.test.ts +282 -0
- package/src/__tests__/preference-slots.test.ts +205 -0
- package/src/__tests__/prospective-memory.test.ts +283 -0
- package/src/__tests__/pull-from-macbook-sync-only.test.ts +679 -0
- package/src/__tests__/query-entity-detector.test.ts +171 -0
- package/src/__tests__/query-expander-alias.test.ts +146 -0
- package/src/__tests__/query-expander.test.ts +34 -0
- package/src/__tests__/recall-gate.test.ts +266 -0
- package/src/__tests__/recall-governor.test.ts +227 -0
- package/src/__tests__/recall-mode.test.ts +64 -0
- package/src/__tests__/resolve-db-path.test.ts +130 -0
- package/src/__tests__/resolve-tier.test.ts +64 -0
- package/src/__tests__/result-synthesizer.test.ts +198 -0
- package/src/__tests__/resume-context.test.ts +4898 -0
- package/src/__tests__/retrieval-eval.test.ts +163 -0
- package/src/__tests__/retrieval-trace.test.ts +213 -0
- package/src/__tests__/retriever-boundary-weight.test.ts +136 -0
- package/src/__tests__/retriever-lazy-init-dispatch.test.ts +123 -0
- package/src/__tests__/retroactive-boost.test.ts +223 -0
- package/src/__tests__/salience-scoring.test.ts +106 -0
- package/src/__tests__/scope-inventory.test.ts +200 -0
- package/src/__tests__/scope-policy.test.ts +69 -0
- package/src/__tests__/scope-suggester.test.ts +80 -0
- package/src/__tests__/session-checkpoint.test.ts +291 -0
- package/src/__tests__/session-distiller.test.ts +640 -0
- package/src/__tests__/session-gc.test.ts +215 -0
- package/src/__tests__/skill-engine.test.ts +552 -0
- package/src/__tests__/skill-promotion.test.ts +654 -0
- package/src/__tests__/skill-verifier.test.ts +122 -0
- package/src/__tests__/source-heartbeat.test.ts +250 -0
- package/src/__tests__/stable-context-length-contract.test.ts +62 -0
- package/src/__tests__/store-patch-metadata.test.ts +205 -0
- package/src/__tests__/store-read-consistency.test.ts +122 -0
- package/src/__tests__/store-schema-migration.test.ts +87 -0
- package/src/__tests__/store-scope-audit.test.ts +81 -0
- package/src/__tests__/store-upsert.test.ts +201 -0
- package/src/__tests__/supersede-chain.test.ts +154 -0
- package/src/__tests__/temporal-parser.test.ts +241 -0
- package/src/__tests__/temporal-validity.test.ts +160 -0
- package/src/__tests__/term-registry-terminal-roster.test.ts +127 -0
- package/src/__tests__/term-registry.test.ts +121 -0
- package/src/__tests__/tool-error-surfacing.test.ts +98 -0
- package/src/__tests__/tool-output-compressor.test.ts +160 -0
- package/src/__tests__/topic-tag.test.ts +113 -0
- package/src/__tests__/trusted-memory.test.ts +839 -0
- package/src/__tests__/ui-server-security.test.ts +93 -0
- package/src/__tests__/usage-tracker.test.ts +287 -0
- package/src/__tests__/version-manager.test.ts +213 -0
- package/src/__tests__/workflow-observation-skill-outcome.test.ts +352 -0
- package/src/__tests__/workflow-observation.test.ts +433 -0
- package/src/__tests__/write-verifier.test.ts +122 -0
- package/src/access-tracker.ts +90 -34
- package/src/activity-counter.ts +46 -18
- package/src/adaptive-retrieval.ts +11 -0
- package/src/aliases.ts +133 -0
- package/src/api-server.ts +36 -9
- package/src/audit-log.ts +4 -2
- package/src/auto-consolidation.ts +8 -3
- package/src/auto-gc.ts +85 -21
- package/src/auto-recall.ts +61 -1
- package/src/belief-history.ts +164 -0
- package/src/capture-engine.ts +142 -32
- package/src/cli.ts +268 -41
- package/src/confidence-tracker.ts +36 -18
- package/src/conflict-engine.ts +24 -3
- package/src/consolidation-engine.ts +255 -23
- package/src/context-composer-stable-selection.ts +7 -1
- package/src/context-composer.ts +8 -1
- package/src/data-checkup.ts +96 -7
- package/src/decay-engine.ts +59 -7
- package/src/distill-lock.ts +194 -15
- package/src/doctor.ts +13 -4
- package/src/dream-pipeline.ts +473 -41
- package/src/env-config.ts +118 -0
- package/src/error-signature.ts +153 -0
- package/src/error-taxonomy.ts +115 -0
- package/src/eval.ts +402 -14
- package/src/freshness.ts +192 -0
- package/src/http-request-policy.ts +148 -0
- package/src/idempotency.ts +8 -0
- package/src/ingest.ts +308 -12
- package/src/kg-extractor.ts +13 -3
- package/src/kg-store.ts +236 -44
- package/src/llm-client.ts +106 -11
- package/src/llm-consolidation.ts +2 -1
- package/src/mcp-server.ts +87 -1800
- package/src/mcp-tool-deps.ts +48 -0
- package/src/mcp-tools-advanced.ts +954 -0
- package/src/mcp-tools-core.ts +637 -0
- package/src/mcp-tools-governance.ts +475 -0
- package/src/memory-boundaries.ts +26 -3
- package/src/memory-evolution.ts +73 -1
- package/src/memory-health-rebalance.ts +4 -0
- package/src/memory-lint.ts +183 -10
- package/src/memory-output.ts +129 -4
- package/src/memory-promotion.ts +246 -0
- package/src/memory-schema.ts +25 -2
- package/src/memory-store-port.ts +46 -0
- package/src/multi-vector.ts +2 -1
- package/src/narrative-schema.ts +2 -1
- package/src/noise-filter.ts +57 -6
- package/src/noise-prototype-bank.ts +408 -0
- package/src/pii-detector.ts +207 -5
- package/src/pivot-apply.ts +399 -0
- package/src/preference-matcher.ts +37 -3
- package/src/query-expander.ts +90 -9
- package/src/recall-gate.ts +305 -0
- package/src/result-synthesizer.ts +2 -1
- package/src/retention-policy.ts +2 -1
- package/src/retrieval-profiles.ts +46 -4
- package/src/retriever.ts +354 -157
- package/src/retroactive-boost.ts +6 -2
- package/src/runtime-config.ts +78 -6
- package/src/scope-suggester.ts +113 -0
- package/src/session-distiller.ts +23 -2
- package/src/session-engine.ts +2 -1
- package/src/session-schema.ts +1 -0
- package/src/session-store.ts +5 -0
- package/src/skill-engine.ts +78 -0
- package/src/skill-promotion.ts +304 -48
- package/src/skill-schema.ts +16 -3
- package/src/skill-verifier.ts +152 -0
- package/src/store.ts +321 -57
- package/src/term-registry.ts +35 -0
- package/src/tool-output-compressor.ts +3 -1
- package/src/ui-server.ts +9 -1
- package/src/usage-tracker.ts +242 -0
- package/src/version-manager.ts +3 -2
- package/src/version.ts +19 -0
- package/src/workflow-observation-engine.ts +2 -1
- package/src/workflow-observation-schema.ts +2 -1
- package/src/workflow-observation-store.ts +6 -2
- package/.env +0 -4
- package/CLAUDE.md +0 -46
- package/config.json +0 -55
- package/daily-recall.sh +0 -110
- package/logs/daily-recall.error.log +0 -0
- package/logs/daily-recall.log +0 -60
- package/logs/ingest-2026-04-11.log +0 -110
- package/logs/ingest-2026-04-12.log +0 -90
- package/logs/ingest-2026-04-13.log +0 -87
- package/logs/launchagent-stderr.log +0 -0
- package/logs/launchagent-stdout.log +0 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for Tier 3.4: Prospective Memory (Conditional Trigger Reminders)
|
|
3
|
+
*
|
|
4
|
+
* Validates:
|
|
5
|
+
* 1. setReminder creates a properly structured memory entry
|
|
6
|
+
* 2. checkTriggers finds matching pending reminders
|
|
7
|
+
* 3. checkTriggers ignores fired/expired reminders
|
|
8
|
+
* 4. fireReminder marks the reminder as fired
|
|
9
|
+
* 5. formatReminders produces readable output
|
|
10
|
+
* 6. Trigger matching uses keyword logic
|
|
11
|
+
* 7. Expiration is handled correctly
|
|
12
|
+
*/
|
|
13
|
+
import { describe, expect, it } from "bun:test";
|
|
14
|
+
import {
|
|
15
|
+
setReminder,
|
|
16
|
+
checkTriggers,
|
|
17
|
+
fireReminder,
|
|
18
|
+
formatReminders,
|
|
19
|
+
} from "../prospective-memory.js";
|
|
20
|
+
import type { MemoryEntry, MemorySearchResult } from "../store.js";
|
|
21
|
+
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Helpers
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
|
|
26
|
+
function createMockStore() {
|
|
27
|
+
const data = new Map<string, MemoryEntry>();
|
|
28
|
+
let idCounter = 0;
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
data,
|
|
32
|
+
async store(entry: Omit<MemoryEntry, "id" | "timestamp">) {
|
|
33
|
+
const id = `reminder-${++idCounter}`;
|
|
34
|
+
const full: MemoryEntry = {
|
|
35
|
+
...entry,
|
|
36
|
+
id,
|
|
37
|
+
timestamp: Date.now(),
|
|
38
|
+
} as MemoryEntry;
|
|
39
|
+
data.set(id, full);
|
|
40
|
+
return full;
|
|
41
|
+
},
|
|
42
|
+
async vectorSearch(
|
|
43
|
+
_vector: number[],
|
|
44
|
+
_limit: number,
|
|
45
|
+
_minScore: number,
|
|
46
|
+
_scopeFilter?: string[],
|
|
47
|
+
): Promise<MemorySearchResult[]> {
|
|
48
|
+
return [...data.values()].map(e => ({ entry: e, score: 0.8 }));
|
|
49
|
+
},
|
|
50
|
+
async getById(id: string) {
|
|
51
|
+
return data.get(id) ?? null;
|
|
52
|
+
},
|
|
53
|
+
async update(id: string, upd: { metadata?: string; text?: string }, _scope?: string[]) {
|
|
54
|
+
const entry = data.get(id);
|
|
55
|
+
if (!entry) return null;
|
|
56
|
+
if (upd.metadata) entry.metadata = upd.metadata;
|
|
57
|
+
if (upd.text) entry.text = upd.text;
|
|
58
|
+
return entry;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function createMockEmbedder() {
|
|
64
|
+
return {
|
|
65
|
+
async embedPassage(_text: string) {
|
|
66
|
+
return [0.1, 0.2, 0.3];
|
|
67
|
+
},
|
|
68
|
+
async embedBatchPassage(texts: string[]) {
|
|
69
|
+
return texts.map(() => [0.1, 0.2, 0.3]);
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// setReminder
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
describe("setReminder", () => {
|
|
79
|
+
it("creates a reminder with prospective metadata", async () => {
|
|
80
|
+
const store = createMockStore();
|
|
81
|
+
const embedder = createMockEmbedder();
|
|
82
|
+
|
|
83
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
84
|
+
trigger: "deployment",
|
|
85
|
+
action: "Check the monitoring dashboard after deploy",
|
|
86
|
+
scope: "project:test",
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
expect(entry.id).toBeTruthy();
|
|
90
|
+
expect(entry.category).toBe("patterns");
|
|
91
|
+
expect(entry.text).toContain("Reminder");
|
|
92
|
+
expect(entry.text).toContain("deployment");
|
|
93
|
+
|
|
94
|
+
const meta = JSON.parse(entry.metadata);
|
|
95
|
+
expect(meta.prospective.trigger).toBe("deployment");
|
|
96
|
+
expect(meta.prospective.action).toBe("Check the monitoring dashboard after deploy");
|
|
97
|
+
expect(meta.prospective.status).toBe("pending");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("creates a reminder with expiration", async () => {
|
|
101
|
+
const store = createMockStore();
|
|
102
|
+
const embedder = createMockEmbedder();
|
|
103
|
+
|
|
104
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
105
|
+
trigger: "release",
|
|
106
|
+
action: "Update changelog",
|
|
107
|
+
scope: "project:test",
|
|
108
|
+
expiresInDays: 7,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const meta = JSON.parse(entry.metadata);
|
|
112
|
+
expect(meta.prospective.expiresAt).toBeTruthy();
|
|
113
|
+
// Should expire roughly 7 days from now
|
|
114
|
+
const expiresAt = new Date(meta.prospective.expiresAt).getTime();
|
|
115
|
+
const now = Date.now();
|
|
116
|
+
const sevenDays = 7 * 86_400_000;
|
|
117
|
+
expect(expiresAt - now).toBeGreaterThan(sevenDays - 60_000);
|
|
118
|
+
expect(expiresAt - now).toBeLessThan(sevenDays + 60_000);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
// checkTriggers
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
describe("checkTriggers", () => {
|
|
127
|
+
it("finds matching pending reminders", async () => {
|
|
128
|
+
const store = createMockStore();
|
|
129
|
+
const embedder = createMockEmbedder();
|
|
130
|
+
|
|
131
|
+
await setReminder(store as any, embedder as any, {
|
|
132
|
+
trigger: "deployment",
|
|
133
|
+
action: "Check monitoring",
|
|
134
|
+
scope: "project:test",
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const reminders = await checkTriggers(
|
|
138
|
+
store as any,
|
|
139
|
+
embedder as any,
|
|
140
|
+
"We need to do a deployment today",
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
expect(reminders.length).toBe(1);
|
|
144
|
+
expect(reminders[0].action).toBe("Check monitoring");
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("ignores non-matching queries", async () => {
|
|
148
|
+
const store = createMockStore();
|
|
149
|
+
const embedder = createMockEmbedder();
|
|
150
|
+
|
|
151
|
+
await setReminder(store as any, embedder as any, {
|
|
152
|
+
trigger: "deployment",
|
|
153
|
+
action: "Check monitoring",
|
|
154
|
+
scope: "project:test",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const reminders = await checkTriggers(
|
|
158
|
+
store as any,
|
|
159
|
+
embedder as any,
|
|
160
|
+
"Let me review the code changes",
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(reminders.length).toBe(0);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("ignores fired reminders", async () => {
|
|
167
|
+
const store = createMockStore();
|
|
168
|
+
const embedder = createMockEmbedder();
|
|
169
|
+
|
|
170
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
171
|
+
trigger: "deployment",
|
|
172
|
+
action: "Check monitoring",
|
|
173
|
+
scope: "project:test",
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Fire the reminder
|
|
177
|
+
await fireReminder(store as any, entry.id);
|
|
178
|
+
|
|
179
|
+
const reminders = await checkTriggers(
|
|
180
|
+
store as any,
|
|
181
|
+
embedder as any,
|
|
182
|
+
"deployment is happening",
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
expect(reminders.length).toBe(0);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("handles expired reminders", async () => {
|
|
189
|
+
const store = createMockStore();
|
|
190
|
+
const embedder = createMockEmbedder();
|
|
191
|
+
|
|
192
|
+
// Create a reminder that's already expired
|
|
193
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
194
|
+
trigger: "something",
|
|
195
|
+
action: "do something",
|
|
196
|
+
scope: "project:test",
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Manually set expiresAt to past
|
|
200
|
+
const meta = JSON.parse(entry.metadata);
|
|
201
|
+
meta.prospective.expiresAt = "2020-01-01T00:00:00Z";
|
|
202
|
+
entry.metadata = JSON.stringify(meta);
|
|
203
|
+
|
|
204
|
+
const reminders = await checkTriggers(
|
|
205
|
+
store as any,
|
|
206
|
+
embedder as any,
|
|
207
|
+
"something came up",
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
expect(reminders.length).toBe(0);
|
|
211
|
+
// Should be marked as expired
|
|
212
|
+
const updated = JSON.parse(entry.metadata);
|
|
213
|
+
expect(updated.prospective.status).toBe("expired");
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// ---------------------------------------------------------------------------
|
|
218
|
+
// fireReminder
|
|
219
|
+
// ---------------------------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
describe("fireReminder", () => {
|
|
222
|
+
it("marks reminder as fired and returns action", async () => {
|
|
223
|
+
const store = createMockStore();
|
|
224
|
+
const embedder = createMockEmbedder();
|
|
225
|
+
|
|
226
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
227
|
+
trigger: "test",
|
|
228
|
+
action: "do the thing",
|
|
229
|
+
scope: "project:test",
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const action = await fireReminder(store as any, entry.id);
|
|
233
|
+
|
|
234
|
+
expect(action).toBe("do the thing");
|
|
235
|
+
const meta = JSON.parse(store.data.get(entry.id)!.metadata);
|
|
236
|
+
expect(meta.prospective.status).toBe("fired");
|
|
237
|
+
expect(meta.prospective.firedAt).toBeTruthy();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it("returns null for non-existent entry", async () => {
|
|
241
|
+
const store = createMockStore();
|
|
242
|
+
const action = await fireReminder(store as any, "nonexistent");
|
|
243
|
+
expect(action).toBeNull();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("returns null for already-fired reminder", async () => {
|
|
247
|
+
const store = createMockStore();
|
|
248
|
+
const embedder = createMockEmbedder();
|
|
249
|
+
|
|
250
|
+
const entry = await setReminder(store as any, embedder as any, {
|
|
251
|
+
trigger: "test",
|
|
252
|
+
action: "do it",
|
|
253
|
+
scope: "project:test",
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await fireReminder(store as any, entry.id);
|
|
257
|
+
const secondFire = await fireReminder(store as any, entry.id);
|
|
258
|
+
|
|
259
|
+
expect(secondFire).toBeNull();
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// ---------------------------------------------------------------------------
|
|
264
|
+
// formatReminders
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
describe("formatReminders", () => {
|
|
268
|
+
it("formats reminders for context injection", () => {
|
|
269
|
+
const formatted = formatReminders([
|
|
270
|
+
{ entryId: "r1", trigger: "deploy", action: "Check monitoring after deploy" },
|
|
271
|
+
{ entryId: "r2", trigger: "meeting", action: "Bring up the budget issue" },
|
|
272
|
+
]);
|
|
273
|
+
|
|
274
|
+
expect(formatted.length).toBe(2);
|
|
275
|
+
expect(formatted[0]).toContain("deploy");
|
|
276
|
+
expect(formatted[0]).toContain("Check monitoring after deploy");
|
|
277
|
+
expect(formatted[1]).toContain("meeting");
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("handles empty array", () => {
|
|
281
|
+
expect(formatReminders([])).toEqual([]);
|
|
282
|
+
});
|
|
283
|
+
});
|