agent-recall-core 3.4.31 → 3.4.36
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/README.md +121 -441
- package/dist/digest/store.d.ts.map +1 -1
- package/dist/digest/store.js +4 -3
- package/dist/digest/store.js.map +1 -1
- package/dist/display/board-render.d.ts +61 -0
- package/dist/display/board-render.d.ts.map +1 -0
- package/dist/display/board-render.js +223 -0
- package/dist/display/board-render.js.map +1 -0
- package/dist/helpers/alignment-patterns.d.ts +10 -0
- package/dist/helpers/alignment-patterns.d.ts.map +1 -1
- package/dist/helpers/alignment-patterns.js +5 -1
- package/dist/helpers/alignment-patterns.js.map +1 -1
- package/dist/helpers/blind-spots.d.ts +86 -0
- package/dist/helpers/blind-spots.d.ts.map +1 -0
- package/dist/helpers/blind-spots.js +205 -0
- package/dist/helpers/blind-spots.js.map +1 -0
- package/dist/helpers/conflict-scan.d.ts +10 -0
- package/dist/helpers/conflict-scan.d.ts.map +1 -1
- package/dist/helpers/conflict-scan.js +3 -3
- package/dist/helpers/conflict-scan.js.map +1 -1
- package/dist/helpers/semantic-match.d.ts +82 -0
- package/dist/helpers/semantic-match.d.ts.map +1 -0
- package/dist/helpers/semantic-match.js +229 -0
- package/dist/helpers/semantic-match.js.map +1 -0
- package/dist/index.d.ts +57 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +60 -14
- package/dist/index.js.map +1 -1
- package/dist/palace/awareness.d.ts +30 -0
- package/dist/palace/awareness.d.ts.map +1 -1
- package/dist/palace/awareness.js +65 -2
- package/dist/palace/awareness.js.map +1 -1
- package/dist/palace/consolidate.d.ts.map +1 -1
- package/dist/palace/consolidate.js +17 -0
- package/dist/palace/consolidate.js.map +1 -1
- package/dist/palace/decay-pass.d.ts +46 -0
- package/dist/palace/decay-pass.d.ts.map +1 -0
- package/dist/palace/decay-pass.js +87 -0
- package/dist/palace/decay-pass.js.map +1 -0
- package/dist/palace/insights-index.d.ts.map +1 -1
- package/dist/palace/insights-index.js +4 -2
- package/dist/palace/insights-index.js.map +1 -1
- package/dist/palace/skills.d.ts +41 -2
- package/dist/palace/skills.d.ts.map +1 -1
- package/dist/palace/skills.js +106 -4
- package/dist/palace/skills.js.map +1 -1
- package/dist/prompts/consolidation-prompt.d.ts +25 -0
- package/dist/prompts/consolidation-prompt.d.ts.map +1 -0
- package/dist/prompts/consolidation-prompt.js +91 -0
- package/dist/prompts/consolidation-prompt.js.map +1 -0
- package/dist/storage/ab-experiment.d.ts +184 -0
- package/dist/storage/ab-experiment.d.ts.map +1 -0
- package/dist/storage/ab-experiment.js +294 -0
- package/dist/storage/ab-experiment.js.map +1 -0
- package/dist/storage/archive-prune.d.ts +56 -0
- package/dist/storage/archive-prune.d.ts.map +1 -0
- package/dist/storage/archive-prune.js +118 -0
- package/dist/storage/archive-prune.js.map +1 -0
- package/dist/storage/archive-write.d.ts +38 -0
- package/dist/storage/archive-write.d.ts.map +1 -0
- package/dist/storage/archive-write.js +98 -0
- package/dist/storage/archive-write.js.map +1 -0
- package/dist/storage/blind-spots-store.d.ts +30 -0
- package/dist/storage/blind-spots-store.d.ts.map +1 -0
- package/dist/storage/blind-spots-store.js +91 -0
- package/dist/storage/blind-spots-store.js.map +1 -0
- package/dist/storage/capture-router.d.ts +60 -0
- package/dist/storage/capture-router.d.ts.map +1 -0
- package/dist/storage/capture-router.js +133 -0
- package/dist/storage/capture-router.js.map +1 -0
- package/dist/storage/classification.d.ts +36 -0
- package/dist/storage/classification.d.ts.map +1 -0
- package/dist/storage/classification.js +78 -0
- package/dist/storage/classification.js.map +1 -0
- package/dist/storage/consolidation-queue.d.ts +39 -0
- package/dist/storage/consolidation-queue.d.ts.map +1 -0
- package/dist/storage/consolidation-queue.js +120 -0
- package/dist/storage/consolidation-queue.js.map +1 -0
- package/dist/storage/content-guard.d.ts +74 -0
- package/dist/storage/content-guard.d.ts.map +1 -0
- package/dist/storage/content-guard.js +179 -0
- package/dist/storage/content-guard.js.map +1 -0
- package/dist/storage/corrections.d.ts +329 -22
- package/dist/storage/corrections.d.ts.map +1 -1
- package/dist/storage/corrections.js +788 -58
- package/dist/storage/corrections.js.map +1 -1
- package/dist/storage/durable-intent.d.ts +49 -0
- package/dist/storage/durable-intent.d.ts.map +1 -0
- package/dist/storage/durable-intent.js +124 -0
- package/dist/storage/durable-intent.js.map +1 -0
- package/dist/storage/filelock.d.ts +6 -0
- package/dist/storage/filelock.d.ts.map +1 -1
- package/dist/storage/filelock.js +6 -1
- package/dist/storage/filelock.js.map +1 -1
- package/dist/storage/memory-protocol.d.ts +19 -0
- package/dist/storage/memory-protocol.d.ts.map +1 -0
- package/dist/storage/memory-protocol.js +101 -0
- package/dist/storage/memory-protocol.js.map +1 -0
- package/dist/storage/paths.d.ts +23 -0
- package/dist/storage/paths.d.ts.map +1 -1
- package/dist/storage/paths.js +39 -0
- package/dist/storage/paths.js.map +1 -1
- package/dist/storage/retention.d.ts +23 -0
- package/dist/storage/retention.d.ts.map +1 -0
- package/dist/storage/retention.js +48 -0
- package/dist/storage/retention.js.map +1 -0
- package/dist/storage/session.d.ts +2 -2
- package/dist/storage/session.d.ts.map +1 -1
- package/dist/storage/session.js +11 -1
- package/dist/storage/session.js.map +1 -1
- package/dist/supabase/config.d.ts +26 -0
- package/dist/supabase/config.d.ts.map +1 -1
- package/dist/supabase/config.js +11 -0
- package/dist/supabase/config.js.map +1 -1
- package/dist/supabase/recall-backend.d.ts +1 -0
- package/dist/supabase/recall-backend.d.ts.map +1 -1
- package/dist/supabase/recall-backend.js +13 -13
- package/dist/supabase/recall-backend.js.map +1 -1
- package/dist/supabase/sync.d.ts +1 -1
- package/dist/supabase/sync.d.ts.map +1 -1
- package/dist/supabase/sync.js +85 -3
- package/dist/supabase/sync.js.map +1 -1
- package/dist/tools-logic/bootstrap.d.ts +15 -0
- package/dist/tools-logic/bootstrap.d.ts.map +1 -1
- package/dist/tools-logic/bootstrap.js +238 -47
- package/dist/tools-logic/bootstrap.js.map +1 -1
- package/dist/tools-logic/brief.d.ts +84 -0
- package/dist/tools-logic/brief.d.ts.map +1 -0
- package/dist/tools-logic/brief.js +193 -0
- package/dist/tools-logic/brief.js.map +1 -0
- package/dist/tools-logic/check-action.d.ts +9 -0
- package/dist/tools-logic/check-action.d.ts.map +1 -1
- package/dist/tools-logic/check-action.js +61 -3
- package/dist/tools-logic/check-action.js.map +1 -1
- package/dist/tools-logic/check.d.ts +7 -0
- package/dist/tools-logic/check.d.ts.map +1 -1
- package/dist/tools-logic/check.js +24 -2
- package/dist/tools-logic/check.js.map +1 -1
- package/dist/tools-logic/confidence.d.ts +50 -0
- package/dist/tools-logic/confidence.d.ts.map +1 -0
- package/dist/tools-logic/confidence.js +70 -0
- package/dist/tools-logic/confidence.js.map +1 -0
- package/dist/tools-logic/drill-down.d.ts +37 -0
- package/dist/tools-logic/drill-down.d.ts.map +1 -0
- package/dist/tools-logic/drill-down.js +63 -0
- package/dist/tools-logic/drill-down.js.map +1 -0
- package/dist/tools-logic/export-corrections.d.ts +63 -0
- package/dist/tools-logic/export-corrections.d.ts.map +1 -0
- package/dist/tools-logic/export-corrections.js +124 -0
- package/dist/tools-logic/export-corrections.js.map +1 -0
- package/dist/tools-logic/journal-capture.d.ts.map +1 -1
- package/dist/tools-logic/journal-capture.js +4 -1
- package/dist/tools-logic/journal-capture.js.map +1 -1
- package/dist/tools-logic/journal-write.d.ts.map +1 -1
- package/dist/tools-logic/journal-write.js +3 -2
- package/dist/tools-logic/journal-write.js.map +1 -1
- package/dist/tools-logic/local-archive-backend.d.ts +33 -0
- package/dist/tools-logic/local-archive-backend.d.ts.map +1 -0
- package/dist/tools-logic/local-archive-backend.js +124 -0
- package/dist/tools-logic/local-archive-backend.js.map +1 -0
- package/dist/tools-logic/memory-backend.d.ts +74 -0
- package/dist/tools-logic/memory-backend.d.ts.map +1 -0
- package/dist/tools-logic/memory-backend.js +172 -0
- package/dist/tools-logic/memory-backend.js.map +1 -0
- package/dist/tools-logic/memory-query.d.ts +10 -3
- package/dist/tools-logic/memory-query.d.ts.map +1 -1
- package/dist/tools-logic/memory-query.js +31 -7
- package/dist/tools-logic/memory-query.js.map +1 -1
- package/dist/tools-logic/mirror-builder.d.ts +115 -0
- package/dist/tools-logic/mirror-builder.d.ts.map +1 -0
- package/dist/tools-logic/mirror-builder.js +348 -0
- package/dist/tools-logic/mirror-builder.js.map +1 -0
- package/dist/tools-logic/palace-write.d.ts.map +1 -1
- package/dist/tools-logic/palace-write.js +3 -2
- package/dist/tools-logic/palace-write.js.map +1 -1
- package/dist/tools-logic/pipeline-close.d.ts.map +1 -1
- package/dist/tools-logic/pipeline-close.js +2 -1
- package/dist/tools-logic/pipeline-close.js.map +1 -1
- package/dist/tools-logic/pipeline-open.d.ts.map +1 -1
- package/dist/tools-logic/pipeline-open.js +2 -1
- package/dist/tools-logic/pipeline-open.js.map +1 -1
- package/dist/tools-logic/predict-correction.d.ts +47 -0
- package/dist/tools-logic/predict-correction.d.ts.map +1 -0
- package/dist/tools-logic/predict-correction.js +137 -0
- package/dist/tools-logic/predict-correction.js.map +1 -0
- package/dist/tools-logic/prior-builder.d.ts +27 -0
- package/dist/tools-logic/prior-builder.d.ts.map +1 -0
- package/dist/tools-logic/prior-builder.js +90 -0
- package/dist/tools-logic/prior-builder.js.map +1 -0
- package/dist/tools-logic/recognition-builder.d.ts +122 -0
- package/dist/tools-logic/recognition-builder.d.ts.map +1 -0
- package/dist/tools-logic/recognition-builder.js +289 -0
- package/dist/tools-logic/recognition-builder.js.map +1 -0
- package/dist/tools-logic/safety-consolidation.d.ts +104 -0
- package/dist/tools-logic/safety-consolidation.d.ts.map +1 -0
- package/dist/tools-logic/safety-consolidation.js +256 -0
- package/dist/tools-logic/safety-consolidation.js.map +1 -0
- package/dist/tools-logic/session-end-reflect.d.ts +18 -0
- package/dist/tools-logic/session-end-reflect.d.ts.map +1 -1
- package/dist/tools-logic/session-end-reflect.js +69 -30
- package/dist/tools-logic/session-end-reflect.js.map +1 -1
- package/dist/tools-logic/session-end.d.ts +18 -0
- package/dist/tools-logic/session-end.d.ts.map +1 -1
- package/dist/tools-logic/session-end.js +189 -34
- package/dist/tools-logic/session-end.js.map +1 -1
- package/dist/tools-logic/session-start-lite.d.ts +2 -0
- package/dist/tools-logic/session-start-lite.d.ts.map +1 -1
- package/dist/tools-logic/session-start-lite.js +11 -2
- package/dist/tools-logic/session-start-lite.js.map +1 -1
- package/dist/tools-logic/session-start.d.ts +81 -2
- package/dist/tools-logic/session-start.d.ts.map +1 -1
- package/dist/tools-logic/session-start.js +357 -40
- package/dist/tools-logic/session-start.js.map +1 -1
- package/dist/tools-logic/skill-propose.d.ts +27 -0
- package/dist/tools-logic/skill-propose.d.ts.map +1 -0
- package/dist/tools-logic/skill-propose.js +66 -0
- package/dist/tools-logic/skill-propose.js.map +1 -0
- package/dist/tools-logic/skill-recall.d.ts +5 -0
- package/dist/tools-logic/skill-recall.d.ts.map +1 -1
- package/dist/tools-logic/skill-recall.js +14 -1
- package/dist/tools-logic/skill-recall.js.map +1 -1
- package/dist/tools-logic/smart-recall.d.ts +17 -0
- package/dist/tools-logic/smart-recall.d.ts.map +1 -1
- package/dist/tools-logic/smart-recall.js +51 -16
- package/dist/tools-logic/smart-recall.js.map +1 -1
- package/dist/tools-logic/smart-remember.js +8 -9
- package/dist/tools-logic/smart-remember.js.map +1 -1
- package/dist/tools-logic/store-doctor.d.ts +71 -0
- package/dist/tools-logic/store-doctor.d.ts.map +1 -0
- package/dist/tools-logic/store-doctor.js +387 -0
- package/dist/tools-logic/store-doctor.js.map +1 -0
- package/dist/tools-logic/store-repair.d.ts +64 -0
- package/dist/tools-logic/store-repair.d.ts.map +1 -0
- package/dist/tools-logic/store-repair.js +243 -0
- package/dist/tools-logic/store-repair.js.map +1 -0
- package/dist/tools-logic/supersession.d.ts +34 -0
- package/dist/tools-logic/supersession.d.ts.map +1 -0
- package/dist/tools-logic/supersession.js +103 -0
- package/dist/tools-logic/supersession.js.map +1 -0
- package/dist/types.d.ts +7 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/vector/embedding.d.ts +8 -0
- package/dist/vector/embedding.d.ts.map +1 -1
- package/dist/vector/embedding.js +9 -1
- package/dist/vector/embedding.js.map +1 -1
- package/dist/vector/local-vector-backend.d.ts.map +1 -1
- package/dist/vector/local-vector-backend.js +14 -17
- package/dist/vector/local-vector-backend.js.map +1 -1
- package/package.json +2 -2
- package/dist/relevance/injector.d.ts +0 -51
- package/dist/relevance/injector.d.ts.map +0 -1
- package/dist/relevance/injector.js +0 -121
- package/dist/relevance/injector.js.map +0 -1
- package/dist/relevance/precision.d.ts +0 -109
- package/dist/relevance/precision.d.ts.map +0 -1
- package/dist/relevance/precision.js +0 -279
- package/dist/relevance/precision.js.map +0 -1
- package/dist/relevance/promoter.d.ts +0 -60
- package/dist/relevance/promoter.d.ts.map +0 -1
- package/dist/relevance/promoter.js +0 -336
- package/dist/relevance/promoter.js.map +0 -1
- package/dist/relevance/stager.d.ts +0 -61
- package/dist/relevance/stager.d.ts.map +0 -1
- package/dist/relevance/stager.js +0 -251
- package/dist/relevance/stager.js.map +0 -1
- package/dist/relevance/surfacer.d.ts +0 -34
- package/dist/relevance/surfacer.d.ts.map +0 -1
- package/dist/relevance/surfacer.js +0 -333
- package/dist/relevance/surfacer.js.map +0 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// packages/core/src/tools-logic/local-archive-backend.ts
|
|
2
|
+
//
|
|
3
|
+
// LocalArchiveMemoryBackend — the reference MemoryBackend implementation.
|
|
4
|
+
//
|
|
5
|
+
// Purpose (two roles):
|
|
6
|
+
// 1. TESTING: round-trip verification of the retain() contract without
|
|
7
|
+
// a live third-party service.
|
|
8
|
+
// 2. ADAPTER TEMPLATE: fork this file to build a real backend adapter.
|
|
9
|
+
// Replace the JSON write with a client.retain() call; keep the
|
|
10
|
+
// scrub-upstream assumption and the RetainResult shape unchanged.
|
|
11
|
+
//
|
|
12
|
+
// Storage layout:
|
|
13
|
+
// <root>/exports/<backend-name>/YYYY-MM-DD.json
|
|
14
|
+
//
|
|
15
|
+
// Each daily file is an array of CorrectionExport objects. A second call on
|
|
16
|
+
// the same day appends (unique by id — the seam is idempotent; a repeated
|
|
17
|
+
// `ar corrections export --to-backend` run on the same set does not create
|
|
18
|
+
// duplicate entries).
|
|
19
|
+
import * as fs from "node:fs";
|
|
20
|
+
import * as path from "node:path";
|
|
21
|
+
import { getRoot } from "../types.js";
|
|
22
|
+
/** Human-readable name surfaced in CLI output and log lines. */
|
|
23
|
+
const BACKEND_NAME = "local-archive";
|
|
24
|
+
/**
|
|
25
|
+
* Date string for today (YYYY-MM-DD) in the LOCAL timezone — injectable in
|
|
26
|
+
* tests via the fn arg.
|
|
27
|
+
*
|
|
28
|
+
* NOTE: uses local time, not UTC, so the archive file matches the operator's
|
|
29
|
+
* calendar day. toISOString() returns UTC and would produce the wrong date for
|
|
30
|
+
* operators running past midnight UTC in a positive-offset timezone.
|
|
31
|
+
*/
|
|
32
|
+
export function todayDateString() {
|
|
33
|
+
const d = new Date();
|
|
34
|
+
const y = d.getFullYear();
|
|
35
|
+
const m = String(d.getMonth() + 1).padStart(2, "0");
|
|
36
|
+
const day = String(d.getDate()).padStart(2, "0");
|
|
37
|
+
return `${y}-${m}-${day}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* LocalArchiveMemoryBackend — writes scrubbed CorrectionExport arrays to
|
|
41
|
+
* <root>/exports/local-archive/YYYY-MM-DD.json.
|
|
42
|
+
*
|
|
43
|
+
* CONTRACT:
|
|
44
|
+
* - Assumes records are already scrubbed (exportCorrections() upstream).
|
|
45
|
+
* - Idempotent: re-running with the same IDs does not duplicate entries.
|
|
46
|
+
* - Never throws into session flow — errors map to rejected entries.
|
|
47
|
+
*/
|
|
48
|
+
export class LocalArchiveMemoryBackend {
|
|
49
|
+
/** Override in tests via the constructor to pin the date. */
|
|
50
|
+
_dateFn;
|
|
51
|
+
constructor(opts = {}) {
|
|
52
|
+
this._dateFn = opts.dateFn ?? todayDateString;
|
|
53
|
+
}
|
|
54
|
+
name() {
|
|
55
|
+
return BACKEND_NAME;
|
|
56
|
+
}
|
|
57
|
+
async available() {
|
|
58
|
+
// Always available — only needs a writable filesystem, same guarantee
|
|
59
|
+
// as the rest of the local store.
|
|
60
|
+
try {
|
|
61
|
+
const dir = this._archiveDir();
|
|
62
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async retain(records) {
|
|
70
|
+
const accepted = [];
|
|
71
|
+
const rejected = [];
|
|
72
|
+
if (records.length === 0) {
|
|
73
|
+
return { accepted, rejected };
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
const dir = this._archiveDir();
|
|
77
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
78
|
+
const file = path.join(dir, `${this._dateFn()}.json`);
|
|
79
|
+
// Load existing entries (idempotency — deduplicate by id).
|
|
80
|
+
let existing = [];
|
|
81
|
+
try {
|
|
82
|
+
if (fs.existsSync(file)) {
|
|
83
|
+
const raw = fs.readFileSync(file, "utf-8");
|
|
84
|
+
const parsed = JSON.parse(raw);
|
|
85
|
+
if (Array.isArray(parsed)) {
|
|
86
|
+
existing = parsed;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Malformed file — start fresh. A corrupt archive must not block new writes.
|
|
92
|
+
existing = [];
|
|
93
|
+
}
|
|
94
|
+
const existingIds = new Set(existing.map((e) => e.id));
|
|
95
|
+
const toWrite = [...existing];
|
|
96
|
+
for (const record of records) {
|
|
97
|
+
if (existingIds.has(record.id)) {
|
|
98
|
+
// Already present — idempotent accept (not a rejection).
|
|
99
|
+
accepted.push(record.id);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
toWrite.push(record);
|
|
103
|
+
existingIds.add(record.id);
|
|
104
|
+
accepted.push(record.id);
|
|
105
|
+
}
|
|
106
|
+
fs.writeFileSync(file, JSON.stringify(toWrite, null, 2), "utf-8");
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
// A filesystem failure rejects ALL records in this batch.
|
|
110
|
+
const reason = `write failed: ${String(err)}`;
|
|
111
|
+
for (const r of records) {
|
|
112
|
+
if (!accepted.includes(r.id)) {
|
|
113
|
+
rejected.push({ id: r.id, reason });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return { accepted, rejected };
|
|
118
|
+
}
|
|
119
|
+
/** Absolute path of the archive directory for this backend. */
|
|
120
|
+
_archiveDir() {
|
|
121
|
+
return path.join(getRoot(), "exports", BACKEND_NAME);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=local-archive-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-archive-backend.js","sourceRoot":"","sources":["../../src/tools-logic/local-archive-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CorrectionExport } from "./export-corrections.js";
|
|
2
|
+
/**
|
|
3
|
+
* RetainResult — structured response from a backend's retain() call.
|
|
4
|
+
* Mirrors the Hindsight `retain()` response shape so the local-archive
|
|
5
|
+
* reference backend and any third-party adapter speak the same dialect.
|
|
6
|
+
*/
|
|
7
|
+
export interface RetainResult {
|
|
8
|
+
/** IDs successfully written to the backend. */
|
|
9
|
+
accepted: string[];
|
|
10
|
+
/** IDs the backend refused, each with a machine-readable reason. */
|
|
11
|
+
rejected: {
|
|
12
|
+
id: string;
|
|
13
|
+
reason: string;
|
|
14
|
+
}[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* MemoryBackend — write seam for external belief stores.
|
|
18
|
+
*
|
|
19
|
+
* CONTRACT:
|
|
20
|
+
* - retain() receives a CorrectionExport[] that has ALREADY been scrubbed by
|
|
21
|
+
* exportCorrections(). The backend may assume every string field is clean.
|
|
22
|
+
* Backends MUST NOT re-implement the scrub — that is a recipe for drift.
|
|
23
|
+
* - records MUST come from exportCorrections(); the type system cannot
|
|
24
|
+
* enforce this — which is exactly why the core barrel deliberately does
|
|
25
|
+
* NOT export concrete backends (only this interface + the factory). The
|
|
26
|
+
* sole supported path to a backend instance is getMemoryBackend(), and the
|
|
27
|
+
* sole supported record source is exportCorrections().
|
|
28
|
+
* - available() must never throw. Return false if the backend is misconfigured.
|
|
29
|
+
* - name() returns a stable human-readable label for logging.
|
|
30
|
+
* - Backend failure must be surfaced as a rejected entry or a thrown error that
|
|
31
|
+
* the CLI catches and prints as a warning — never as a process crash.
|
|
32
|
+
*/
|
|
33
|
+
export interface MemoryBackend {
|
|
34
|
+
retain(records: CorrectionExport[]): Promise<RetainResult>;
|
|
35
|
+
available(): Promise<boolean>;
|
|
36
|
+
name(): string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* DisabledMemoryBackend — returned when AR_MEMORY_BACKEND is unset.
|
|
40
|
+
* available() is false so callers can gate on it cleanly.
|
|
41
|
+
*/
|
|
42
|
+
export declare class DisabledMemoryBackend implements MemoryBackend {
|
|
43
|
+
name(): string;
|
|
44
|
+
available(): Promise<boolean>;
|
|
45
|
+
retain(_records: CorrectionExport[]): Promise<RetainResult>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Get the configured MemoryBackend.
|
|
49
|
+
*
|
|
50
|
+
* Selection order:
|
|
51
|
+
* 1. AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (built-in)
|
|
52
|
+
* 2. AR_MEMORY_BACKEND=<module> → dynamic import of that module
|
|
53
|
+
* 3. (unset | "none" | "disabled") → DisabledMemoryBackend
|
|
54
|
+
*
|
|
55
|
+
* Case handling: built-in keywords (none/disabled/local-archive) match
|
|
56
|
+
* case-insensitively — pure operator convenience, nothing is imported.
|
|
57
|
+
* A third-party module specifier is used VERBATIM (npm names are
|
|
58
|
+
* case-sensitive on registry lookup and lowercase-only for new packages);
|
|
59
|
+
* uppercase input is rejected by SAFE_MODULE_RE with a clear message rather
|
|
60
|
+
* than silently normalized to a different package name.
|
|
61
|
+
*
|
|
62
|
+
* Dynamic import contract: the module must export a default class satisfying
|
|
63
|
+
* MemoryBackend. If the import fails, the specifier is invalid, a Node builtin,
|
|
64
|
+
* or the backend reports unavailable, the factory logs a warning to stderr and
|
|
65
|
+
* falls back to DisabledMemoryBackend — it NEVER crashes the session flow.
|
|
66
|
+
*
|
|
67
|
+
* @agent_instruction Returns DisabledMemoryBackend when no backend is configured.
|
|
68
|
+
* Check (await backend.available()) before calling retain(). If false, surface
|
|
69
|
+
* a clear "no backend configured" error to the operator.
|
|
70
|
+
*/
|
|
71
|
+
export declare function getMemoryBackend(): Promise<MemoryBackend>;
|
|
72
|
+
/** Reset the cached backend instance (for testing). */
|
|
73
|
+
export declare function resetMemoryBackend(): void;
|
|
74
|
+
//# sourceMappingURL=memory-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-backend.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-backend.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAMhE;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,oEAAoE;IACpE,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,OAAO,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3D,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,IAAI,IAAI,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,IAAI,IAAI,MAAM;IAIR,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAI7B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC;CASlE;AAmCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CA+E/D;AAED,uDAAuD;AACvD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// packages/core/src/tools-logic/memory-backend.ts
|
|
2
|
+
//
|
|
3
|
+
// MemoryBackend — symmetric WRITE seam for the RecallBackend READ abstraction.
|
|
4
|
+
//
|
|
5
|
+
// Design contract:
|
|
6
|
+
// - Records are ALWAYS the scrubbed CorrectionExport projection. The seam
|
|
7
|
+
// consumes exportCorrections() output (which runs fail-closed scrubForExport
|
|
8
|
+
// on every free-text field). Raw CorrectionRecord is NEVER passed through —
|
|
9
|
+
// the scrub guarantee is upstream by construction. Assert: callers must call
|
|
10
|
+
// exportCorrections() first; they MUST NOT build CorrectionExport manually
|
|
11
|
+
// and bypass the scrub.
|
|
12
|
+
// - Backend failure is a warning, not a session error. The seam is an explicit
|
|
13
|
+
// invocation path (ar corrections export --to-backend) — it never runs
|
|
14
|
+
// automatically on session_end in this version.
|
|
15
|
+
// - Zero-cloud default: the factory returns a DisabledMemoryBackend unless
|
|
16
|
+
// AR_MEMORY_BACKEND is set. No env var = no egress, unchanged.
|
|
17
|
+
//
|
|
18
|
+
// Environment selection (mirrors getRecallBackend()):
|
|
19
|
+
// AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (reference)
|
|
20
|
+
// AR_MEMORY_BACKEND=<npm-module> → dynamic import of third-party adapter
|
|
21
|
+
// (unset / "none" / "disabled") → DisabledMemoryBackend
|
|
22
|
+
//
|
|
23
|
+
// Third-party adapters (e.g. a future hindsight-adapter package) must export a
|
|
24
|
+
// default class that satisfies MemoryBackend via dynamic import.
|
|
25
|
+
import { builtinModules } from "node:module";
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Disabled (default / zero-cloud) backend
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* DisabledMemoryBackend — returned when AR_MEMORY_BACKEND is unset.
|
|
31
|
+
* available() is false so callers can gate on it cleanly.
|
|
32
|
+
*/
|
|
33
|
+
export class DisabledMemoryBackend {
|
|
34
|
+
name() {
|
|
35
|
+
return "disabled";
|
|
36
|
+
}
|
|
37
|
+
async available() {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
async retain(_records) {
|
|
41
|
+
return {
|
|
42
|
+
accepted: [],
|
|
43
|
+
rejected: _records.map((r) => ({
|
|
44
|
+
id: r.id,
|
|
45
|
+
reason: "no backend configured (AR_MEMORY_BACKEND not set)",
|
|
46
|
+
})),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Factory
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
/** Cached backend instance. Reset via resetMemoryBackend() in tests. */
|
|
54
|
+
let _cachedBackend = null;
|
|
55
|
+
/**
|
|
56
|
+
* Allowlist for third-party module specifiers: bare npm package names only.
|
|
57
|
+
* - unscoped: [a-z0-9][a-z0-9._-]*
|
|
58
|
+
* - scoped: @[a-z0-9][a-z0-9._-]* / [a-z0-9][a-z0-9._-]*
|
|
59
|
+
* LOWERCASE ONLY — npm forbids uppercase in new package names, and we do NOT
|
|
60
|
+
* case-normalize the value before import: silently lowercasing "MyAdapter" to
|
|
61
|
+
* "myadapter" would import a DIFFERENT package than the operator named (a
|
|
62
|
+
* squat-redirect hazard). Uppercase input is rejected with a clear message.
|
|
63
|
+
* No path separators, no "..", no leading dots — a crafted value cannot reach
|
|
64
|
+
* import() as a file path.
|
|
65
|
+
*/
|
|
66
|
+
const SAFE_MODULE_RE = /^(@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$/;
|
|
67
|
+
/**
|
|
68
|
+
* Denylist: Node builtin modules must never be import()ed as backends.
|
|
69
|
+
* They would fail the Ctor typecheck anyway (fail-safe), but the gate rejects
|
|
70
|
+
* them up front with a clear message instead of a confusing typecheck error.
|
|
71
|
+
* Explicit floor list + runtime builtinModules union for completeness across
|
|
72
|
+
* Node versions.
|
|
73
|
+
*/
|
|
74
|
+
const BUILTIN_DENYLIST = new Set([
|
|
75
|
+
"fs", "path", "os", "http", "https", "child_process", "net",
|
|
76
|
+
"crypto", "module", "process", "vm", "worker_threads",
|
|
77
|
+
...(Array.isArray(builtinModules) ? builtinModules : []),
|
|
78
|
+
]);
|
|
79
|
+
/**
|
|
80
|
+
* Get the configured MemoryBackend.
|
|
81
|
+
*
|
|
82
|
+
* Selection order:
|
|
83
|
+
* 1. AR_MEMORY_BACKEND=local-archive → LocalArchiveMemoryBackend (built-in)
|
|
84
|
+
* 2. AR_MEMORY_BACKEND=<module> → dynamic import of that module
|
|
85
|
+
* 3. (unset | "none" | "disabled") → DisabledMemoryBackend
|
|
86
|
+
*
|
|
87
|
+
* Case handling: built-in keywords (none/disabled/local-archive) match
|
|
88
|
+
* case-insensitively — pure operator convenience, nothing is imported.
|
|
89
|
+
* A third-party module specifier is used VERBATIM (npm names are
|
|
90
|
+
* case-sensitive on registry lookup and lowercase-only for new packages);
|
|
91
|
+
* uppercase input is rejected by SAFE_MODULE_RE with a clear message rather
|
|
92
|
+
* than silently normalized to a different package name.
|
|
93
|
+
*
|
|
94
|
+
* Dynamic import contract: the module must export a default class satisfying
|
|
95
|
+
* MemoryBackend. If the import fails, the specifier is invalid, a Node builtin,
|
|
96
|
+
* or the backend reports unavailable, the factory logs a warning to stderr and
|
|
97
|
+
* falls back to DisabledMemoryBackend — it NEVER crashes the session flow.
|
|
98
|
+
*
|
|
99
|
+
* @agent_instruction Returns DisabledMemoryBackend when no backend is configured.
|
|
100
|
+
* Check (await backend.available()) before calling retain(). If false, surface
|
|
101
|
+
* a clear "no backend configured" error to the operator.
|
|
102
|
+
*/
|
|
103
|
+
export async function getMemoryBackend() {
|
|
104
|
+
if (_cachedBackend)
|
|
105
|
+
return _cachedBackend;
|
|
106
|
+
const rawSpec = (process.env.AR_MEMORY_BACKEND ?? "").trim();
|
|
107
|
+
// Keywords only — the verbatim rawSpec is what reaches import() below.
|
|
108
|
+
const keyword = rawSpec.toLowerCase();
|
|
109
|
+
if (!keyword || keyword === "none" || keyword === "disabled") {
|
|
110
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
111
|
+
return _cachedBackend;
|
|
112
|
+
}
|
|
113
|
+
if (keyword === "local-archive") {
|
|
114
|
+
try {
|
|
115
|
+
const mod = await import("./local-archive-backend.js");
|
|
116
|
+
_cachedBackend = new mod.LocalArchiveMemoryBackend();
|
|
117
|
+
return _cachedBackend;
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
process.stderr.write(`[agent-recall] memory-backend: failed to load local-archive backend: ${String(err)}\n`);
|
|
121
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
122
|
+
return _cachedBackend;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Third-party module path — dynamic import.
|
|
126
|
+
// SECURITY: AR_MEMORY_BACKEND is operator-controlled env input; treat as
|
|
127
|
+
// untrusted. Gate 1: allowlist shape (bare/scoped npm package name, verbatim).
|
|
128
|
+
if (!SAFE_MODULE_RE.test(rawSpec)) {
|
|
129
|
+
process.stderr.write(`[agent-recall] memory-backend: AR_MEMORY_BACKEND="${rawSpec}" is not a valid npm package name — ` +
|
|
130
|
+
`only lowercase bare package names (e.g. "ar-mem0-adapter") or scoped packages (@org/pkg) are accepted. ` +
|
|
131
|
+
`Path specifiers and uppercase are not allowed. Falling back to disabled.\n`);
|
|
132
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
133
|
+
return _cachedBackend;
|
|
134
|
+
}
|
|
135
|
+
// Gate 2: Node builtins are never valid backends — reject before import().
|
|
136
|
+
if (BUILTIN_DENYLIST.has(rawSpec) || rawSpec.startsWith("node:")) {
|
|
137
|
+
process.stderr.write(`[agent-recall] memory-backend: AR_MEMORY_BACKEND="${rawSpec}" is a Node builtin module, ` +
|
|
138
|
+
`not a memory backend — refusing to load it. Falling back to disabled.\n`);
|
|
139
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
140
|
+
return _cachedBackend;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
const mod = await import(rawSpec);
|
|
145
|
+
// The module must export a default class or a named MemoryBackend class.
|
|
146
|
+
const Ctor = mod.default ?? mod.MemoryBackend;
|
|
147
|
+
if (typeof Ctor !== "function") {
|
|
148
|
+
throw new TypeError(`module "${rawSpec}" does not export a default class or MemoryBackend — got ${typeof Ctor}`);
|
|
149
|
+
}
|
|
150
|
+
const backend = new Ctor();
|
|
151
|
+
if (!(await backend.available())) {
|
|
152
|
+
// Contract: a loaded-but-unavailable backend falls back to Disabled.
|
|
153
|
+
// Caching and returning the unavailable instance would silently swallow
|
|
154
|
+
// all rejections for any caller that skips the available() check.
|
|
155
|
+
process.stderr.write(`[agent-recall] memory-backend: "${rawSpec}" loaded but reported unavailable — falling back to disabled\n`);
|
|
156
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
157
|
+
return _cachedBackend;
|
|
158
|
+
}
|
|
159
|
+
_cachedBackend = backend;
|
|
160
|
+
return backend;
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
process.stderr.write(`[agent-recall] memory-backend: failed to load "${rawSpec}": ${String(err)} — falling back to disabled\n`);
|
|
164
|
+
_cachedBackend = new DisabledMemoryBackend();
|
|
165
|
+
return _cachedBackend;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/** Reset the cached backend instance (for testing). */
|
|
169
|
+
export function resetMemoryBackend() {
|
|
170
|
+
_cachedBackend = null;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=memory-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-backend.js","sourceRoot":"","sources":["../../src/tools-logic/memory-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
* Unlike `recall` (general search), this is called mid-task:
|
|
5
5
|
* "I'm about to do X — what should I know?"
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Returns high/medium confidence results as the primary list. When the primary
|
|
8
|
+
* filter is empty (the match exists but is only low-confidence), the BRIDGE
|
|
9
|
+
* (Wave 4) attaches the verbatim drill-down source under `fallback` instead of
|
|
10
|
+
* silently suppressing it — so the agent gets the lossless source plus a
|
|
11
|
+
* "verify before relying" caution rather than a bare "nothing found" string.
|
|
9
12
|
*/
|
|
13
|
+
import { type BridgedSource } from "./smart-recall.js";
|
|
10
14
|
export interface MemoryQueryInput {
|
|
11
15
|
/** Describe what you're about to do or decide. e.g. "push to npm" or "modify auth middleware" */
|
|
12
16
|
intent: string;
|
|
@@ -28,9 +32,12 @@ export interface MemoryQueryResult {
|
|
|
28
32
|
intent: string;
|
|
29
33
|
project: string;
|
|
30
34
|
results: MemoryQueryItem[];
|
|
31
|
-
/** True when no memory
|
|
35
|
+
/** True when no memory passed the confidence threshold for the primary list. */
|
|
32
36
|
empty: boolean;
|
|
33
37
|
guidance?: string;
|
|
38
|
+
/** Verbatim drill-down source attached when the primary filter was empty but a
|
|
39
|
+
* low-confidence match exists (Wave 4 bridge). */
|
|
40
|
+
fallback?: BridgedSource[];
|
|
34
41
|
}
|
|
35
42
|
export declare function memoryQuery(input: MemoryQueryInput): Promise<MemoryQueryResult>;
|
|
36
43
|
//# sourceMappingURL=memory-query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-query.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"memory-query.d.ts","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAe,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOpE,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kEAAkE;IAClE,cAAc,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IAC3C,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,gFAAgF;IAChF,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;uDACmD;IACnD,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AAgBD,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAuDrF"}
|
|
@@ -4,8 +4,11 @@
|
|
|
4
4
|
* Unlike `recall` (general search), this is called mid-task:
|
|
5
5
|
* "I'm about to do X — what should I know?"
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Returns high/medium confidence results as the primary list. When the primary
|
|
8
|
+
* filter is empty (the match exists but is only low-confidence), the BRIDGE
|
|
9
|
+
* (Wave 4) attaches the verbatim drill-down source under `fallback` instead of
|
|
10
|
+
* silently suppressing it — so the agent gets the lossless source plus a
|
|
11
|
+
* "verify before relying" caution rather than a bare "nothing found" string.
|
|
9
12
|
*/
|
|
10
13
|
import { smartRecall } from "./smart-recall.js";
|
|
11
14
|
import { resolveProject } from "../storage/project.js";
|
|
@@ -28,6 +31,7 @@ export async function memoryQuery(input) {
|
|
|
28
31
|
query: input.intent,
|
|
29
32
|
project,
|
|
30
33
|
limit: limit * 2, // over-fetch then filter by confidence
|
|
34
|
+
drilldown: true, // bridge: attach verbatim source for low-confidence hits
|
|
31
35
|
});
|
|
32
36
|
const filtered = recalled.results
|
|
33
37
|
.filter((r) => r.score >= minScore)
|
|
@@ -40,14 +44,34 @@ export async function memoryQuery(input) {
|
|
|
40
44
|
confidence: r.confidence,
|
|
41
45
|
room: r.room,
|
|
42
46
|
}));
|
|
47
|
+
if (filtered.length > 0) {
|
|
48
|
+
return {
|
|
49
|
+
intent: input.intent,
|
|
50
|
+
project,
|
|
51
|
+
results: filtered,
|
|
52
|
+
empty: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
// Primary filter empty — fall back to the bridged verbatim source if the
|
|
56
|
+
// model tier had a low-confidence match worth drilling into.
|
|
57
|
+
const fallback = recalled.bridged;
|
|
58
|
+
if (fallback && fallback.length > 0) {
|
|
59
|
+
return {
|
|
60
|
+
intent: input.intent,
|
|
61
|
+
project,
|
|
62
|
+
results: [],
|
|
63
|
+
empty: true,
|
|
64
|
+
fallback,
|
|
65
|
+
guidance: `Low-confidence match — verbatim source attached; verify before relying.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
43
68
|
return {
|
|
44
69
|
intent: input.intent,
|
|
45
70
|
project,
|
|
46
|
-
results:
|
|
47
|
-
empty:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
: undefined,
|
|
71
|
+
results: [],
|
|
72
|
+
empty: true,
|
|
73
|
+
fallback: [],
|
|
74
|
+
guidance: `No memory found relevant to: "${input.intent}". This may be a new area — proceed with standard caution.`,
|
|
51
75
|
};
|
|
52
76
|
}
|
|
53
77
|
//# sourceMappingURL=memory-query.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-query.js","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"memory-query.js","sourceRoot":"","sources":["../../src/tools-logic/memory-query.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqCvD,8EAA8E;AAC9E,uCAAuC;AACvC,8EAA8E;AAE9E,MAAM,oBAAoB,GAA2B;IACnD,IAAI,EAAE,IAAI;IACV,MAAM,EAAE,IAAI;IACZ,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAuB;IACvD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,oBAAoB,CAAC,KAAK,CAAC,cAAc,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC;IAChF,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;IAE/B,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC;QACjC,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,OAAO;QACP,KAAK,EAAE,KAAK,GAAG,CAAC,EAAG,uCAAuC;QAC1D,SAAS,EAAE,IAAI,EAAI,yDAAyD;KAC7E,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO;SAC9B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,QAAQ,CAAC;SAClC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU;QACxB,IAAI,EAAE,CAAC,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;IAEN,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO;YACP,OAAO,EAAE,QAAQ;YACjB,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;IAClC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO;YACP,OAAO,EAAE,EAAE;YACX,KAAK,EAAE,IAAI;YACX,QAAQ;YACR,QAAQ,EAAE,yEAAyE;SACpF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO;QACP,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,IAAI;QACX,QAAQ,EAAE,EAAE;QACZ,QAAQ,EAAE,iCAAiC,KAAK,CAAC,MAAM,4DAA4D;KACpH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mirror.ts — "The Mirror" (Loop 9): a VISIBLE, CORRECTABLE self-model.
|
|
3
|
+
*
|
|
4
|
+
* For nine loops the system has accumulated a one-sided, HIDDEN model of the
|
|
5
|
+
* user (corrections, blind-spots, awareness insights). Loop 3 proved that model
|
|
6
|
+
* is weak at PREDICTION (0/13 keyword recall on a strict LOO). The Mirror flips
|
|
7
|
+
* the hidden model into a first-person reflection the human can READ and CORRECT:
|
|
8
|
+
*
|
|
9
|
+
* "You've corrected me 8 times about X."
|
|
10
|
+
* "I've noticed you tend to …" (with the corrections it's derived from)
|
|
11
|
+
*
|
|
12
|
+
* Each correction-OF-the-mirror is itself a high-value correction — the human
|
|
13
|
+
* pointing at the line and saying "no, that's not why" is exactly the signal the
|
|
14
|
+
* predict-the-correction loop needs.
|
|
15
|
+
*
|
|
16
|
+
* HARD RULES (enforced here and asserted in test/mirror.test.mjs):
|
|
17
|
+
* 1. NEVER fabricate a trait. Every rendered observation traces to ≥1 real
|
|
18
|
+
* stored record — its `cites` array is non-empty and lists real ids.
|
|
19
|
+
* 2. Carry an explicit fallibility caveat on every reflection (Loop 3: this
|
|
20
|
+
* model is NOT yet predictive — "what I've noticed", not "what's true").
|
|
21
|
+
* 3. Personal-tier, LOCAL-ONLY. Reads the same personal/ + awareness artifacts
|
|
22
|
+
* the rest of Wave 5 reads. No network, no LLM, fully deterministic.
|
|
23
|
+
*
|
|
24
|
+
* Pure assembly: this module reads stored data via injected readers (so tests
|
|
25
|
+
* can feed a known store) and renders. It performs NO IO of its own beyond the
|
|
26
|
+
* default readers, which are the existing disk-backed functions.
|
|
27
|
+
*/
|
|
28
|
+
import { type CorrectionRecord } from "../storage/corrections.js";
|
|
29
|
+
import { type BlindSpotProfile } from "../helpers/blind-spots.js";
|
|
30
|
+
import { type AwarenessState } from "../palace/awareness.js";
|
|
31
|
+
/**
|
|
32
|
+
* One first-person observation in the mirror. `text` is the rendered line;
|
|
33
|
+
* `cites` lists the REAL stored record ids it was derived from — NEVER empty
|
|
34
|
+
* for a real line (the no-fabrication invariant). `kind` tags the source tier.
|
|
35
|
+
*/
|
|
36
|
+
export interface MirrorObservation {
|
|
37
|
+
/** First-person line, e.g. "You've corrected me 8 times about: …". */
|
|
38
|
+
text: string;
|
|
39
|
+
/** Source tier this observation was assembled from. */
|
|
40
|
+
kind: "correction" | "tendency" | "insight" | "cross_project";
|
|
41
|
+
/** Real stored ids this line is grounded in (≥1; the anti-fabrication anchor). */
|
|
42
|
+
cites: string[];
|
|
43
|
+
/** Evidence weight — how many records back this line (for ordering / display). */
|
|
44
|
+
evidence_count: number;
|
|
45
|
+
}
|
|
46
|
+
export interface MirrorReflection {
|
|
47
|
+
/** ISO timestamp the reflection was assembled. */
|
|
48
|
+
generated_at: string;
|
|
49
|
+
/** Project this mirror reflects, or "_global" when assembled cross-project. */
|
|
50
|
+
project: string;
|
|
51
|
+
/** First-person observations, strongest-evidence first. Empty ⇒ empty mirror. */
|
|
52
|
+
observations: MirrorObservation[];
|
|
53
|
+
/**
|
|
54
|
+
* The fallibility caveat (Loop 3). ALWAYS present, even on an empty mirror —
|
|
55
|
+
* the mirror is "what I've noticed", explicitly NOT "what's true about you",
|
|
56
|
+
* and explicitly NOT yet predictive.
|
|
57
|
+
*/
|
|
58
|
+
caveat: string;
|
|
59
|
+
/** True when there is no stored data to reflect — render an honest empty mirror. */
|
|
60
|
+
empty: boolean;
|
|
61
|
+
/** Headcount of the underlying corpus this was built from (for the header). */
|
|
62
|
+
basis: {
|
|
63
|
+
corrections: number;
|
|
64
|
+
tendencies: number;
|
|
65
|
+
insights: number;
|
|
66
|
+
cross_project_projects: number;
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/** Injectable readers so tests can feed a known store; defaults read real disk. */
|
|
70
|
+
export interface MirrorReaders {
|
|
71
|
+
corrections: (project: string) => CorrectionRecord[];
|
|
72
|
+
blindSpots: (project: string) => BlindSpotProfile | null;
|
|
73
|
+
awareness: () => AwarenessState | null;
|
|
74
|
+
/** Returns [slug, corrections] for every project (cross-project pass). */
|
|
75
|
+
allProjectCorrections: () => Array<{
|
|
76
|
+
slug: string;
|
|
77
|
+
corrections: CorrectionRecord[];
|
|
78
|
+
}>;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Assemble the mirror for a project (or "_global" when project is omitted).
|
|
82
|
+
*
|
|
83
|
+
* DETERMINISTIC: given the same stored data the output is byte-identical except
|
|
84
|
+
* `generated_at`. Ordering is fully specified (evidence desc, then severity,
|
|
85
|
+
* then a stable text tiebreak) so there is no Set/Map iteration nondeterminism.
|
|
86
|
+
*
|
|
87
|
+
* @param project — project slug; when omitted, assembles a cross-project mirror
|
|
88
|
+
* keyed "_global" that also surfaces patterns recurring across ≥2 projects.
|
|
89
|
+
* @param readers — injectable for tests; defaults to the real disk-backed store.
|
|
90
|
+
*/
|
|
91
|
+
export declare function buildMirror(project?: string, readers?: Partial<MirrorReaders>): MirrorReflection;
|
|
92
|
+
export interface CrossProjectPattern {
|
|
93
|
+
/** Representative topic (cleaned rule of the strongest member). */
|
|
94
|
+
topic: string;
|
|
95
|
+
/** Distinct project slugs the pattern spans (≥2). */
|
|
96
|
+
projects: string[];
|
|
97
|
+
/** Real correction ids backing the pattern. */
|
|
98
|
+
cites: string[];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Find correction clusters that recur across ≥2 projects. We tokenize each
|
|
102
|
+
* correction, greedily cluster by ≥2 shared content tokens, and keep clusters
|
|
103
|
+
* whose members span ≥2 distinct projects. Deterministic: corrections are
|
|
104
|
+
* pre-sorted by (date, id) before clustering.
|
|
105
|
+
*/
|
|
106
|
+
export declare function deriveCrossProjectPatterns(perProject: Array<{
|
|
107
|
+
slug: string;
|
|
108
|
+
corrections: CorrectionRecord[];
|
|
109
|
+
}>): {
|
|
110
|
+
patterns: CrossProjectPattern[];
|
|
111
|
+
projectCount: number;
|
|
112
|
+
};
|
|
113
|
+
/** Render a reflection as first-person human-readable text (for `ar mirror`). */
|
|
114
|
+
export declare function renderMirror(m: MirrorReflection): string;
|
|
115
|
+
//# sourceMappingURL=mirror-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mirror-builder.d.ts","sourceRoot":"","sources":["../../src/tools-logic/mirror-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAoC,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACpG,OAAO,EAAsB,KAAK,cAAc,EAAgB,MAAM,wBAAwB,CAAC;AAQ/F;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;IAC9D,kFAAkF;IAClF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,kFAAkF;IAClF,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,iFAAiF;IACjF,YAAY,EAAE,iBAAiB,EAAE,CAAC;IAClC;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,KAAK,EAAE,OAAO,CAAC;IACf,+EAA+E;IAC/E,KAAK,EAAE;QACL,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,sBAAsB,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,mFAAmF;AACnF,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;IACrD,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACzD,SAAS,EAAE,MAAM,cAAc,GAAG,IAAI,CAAC;IACvC,0EAA0E;IAC1E,qBAAqB,EAAE,MAAM,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,gBAAgB,EAAE,CAAA;KAAE,CAAC,CAAC;CACvF;AAuDD;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,gBAAgB,CAqIhG;AAiDD,MAAM,WAAW,mBAAmB;IAClC,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,GACnE;IAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAmD3D;AAMD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,CAAC,EAAE,gBAAgB,GAAG,MAAM,CA6BxD"}
|