agent-recall-core 3.4.31 → 3.4.35
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 +52 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -9
- 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/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 +32 -0
- package/dist/storage/classification.d.ts.map +1 -0
- package/dist/storage/classification.js +74 -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 +246 -21
- package/dist/storage/corrections.d.ts.map +1 -1
- package/dist/storage/corrections.js +605 -56
- 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 +8 -0
- package/dist/supabase/config.d.ts.map +1 -1
- package/dist/supabase/config.js +5 -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.map +1 -1
- package/dist/supabase/sync.js +30 -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 +31 -2
- 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/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 +57 -0
- package/dist/tools-logic/prior-builder.js.map +1 -0
- package/dist/tools-logic/recognition-builder.d.ts +116 -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 +68 -29
- package/dist/tools-logic/session-end-reflect.js.map +1 -1
- package/dist/tools-logic/session-end.d.ts +9 -0
- package/dist/tools-logic/session-end.d.ts.map +1 -1
- package/dist/tools-logic/session-end.js +111 -13
- 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 +10 -0
- package/dist/tools-logic/session-start-lite.js.map +1 -1
- package/dist/tools-logic/session-start.d.ts +46 -0
- package/dist/tools-logic/session-start.d.ts.map +1 -1
- package/dist/tools-logic/session-start.js +96 -3
- 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/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/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 +1 -1
- 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,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* content-guard.ts — pre-sync content scrubbing for opt-in cloud users.
|
|
3
|
+
*
|
|
4
|
+
* Applied BEFORE any journalWrite → syncToSupabase call so that secrets and
|
|
5
|
+
* prompt-injection attempts do not reach Supabase or the embedding API.
|
|
6
|
+
*
|
|
7
|
+
* Two-layer scrub:
|
|
8
|
+
* 1. scrubPromptInjection — strip XML system-marker tags, bidi overrides,
|
|
9
|
+
* null bytes, and explicit injection phrases. Extracted from bootstrap.ts
|
|
10
|
+
* and re-exported here so journal-write/palace-write can import from a
|
|
11
|
+
* single source of truth.
|
|
12
|
+
* 2. scrubSecretContent — redact known secret token prefixes (AKIA…, ghp_…,
|
|
13
|
+
* gho_…, ghs_…, sk-…, xoxb-…, PEM markers). Operates on content, not
|
|
14
|
+
* filenames (bootstrap.ts isSecretFile() handles filename-level rejection).
|
|
15
|
+
*
|
|
16
|
+
* scrubForCloud(content) = scrubSecretContent(scrubPromptInjection(content))
|
|
17
|
+
*
|
|
18
|
+
* Design guarantees:
|
|
19
|
+
* - Never throws — any failure returns the original content unchanged.
|
|
20
|
+
* - Pure function, no I/O, no Supabase imports.
|
|
21
|
+
* - Returns a SecretScanResult so callers can log/block if desired.
|
|
22
|
+
*
|
|
23
|
+
* Usage: call scrubForCloud(content) in journal-write.ts and palace-write.ts
|
|
24
|
+
* before passing content to syncToSupabase.
|
|
25
|
+
*/
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Layer 1 — prompt-injection scrub (re-export from bootstrap logic)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Strip prompt-injection patterns from content before it leaves the machine.
|
|
31
|
+
* Same logic as bootstrap.ts:scrubPromptInjection but exported here for
|
|
32
|
+
* journal-write and palace-write to use at sync time.
|
|
33
|
+
*/
|
|
34
|
+
export function scrubPromptInjection(s) {
|
|
35
|
+
try {
|
|
36
|
+
return s
|
|
37
|
+
.replace(/<\/?\s*(system[-_]?(reminder|prompt|message|instruction)|important|critical)\b[^>]*>/gi, "[stripped tag]")
|
|
38
|
+
.replace(/<\|im_(start|end)\|>/gi, "[stripped]")
|
|
39
|
+
.replace(/\b(ignore|disregard|forget)\s+(all\s+)?(previous|prior|above)\s+(instructions?|prompts?|messages?)/gi, "[stripped injection attempt]")
|
|
40
|
+
.replace(/[--]/g, "") // bidi override chars
|
|
41
|
+
.replace(/\0/g, ""); // null bytes
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return s;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
// Layer 2 — content-level secret scan
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
/**
|
|
51
|
+
* Patterns that match known secret token prefixes / PEM markers in CONTENT.
|
|
52
|
+
* Complements isSecretFile() in bootstrap.ts which tests filenames only.
|
|
53
|
+
*
|
|
54
|
+
* Prefix list (grounding: packages/core/src/supabase/sync.ts risk analysis):
|
|
55
|
+
* AKIA… — AWS access key
|
|
56
|
+
* ghp_… — GitHub personal access token
|
|
57
|
+
* gho_… — GitHub OAuth token
|
|
58
|
+
* ghs_… — GitHub app installation token
|
|
59
|
+
* sk-… — OpenAI / Anthropic secret key (≥20 chars to avoid false-positives)
|
|
60
|
+
* xoxb-… — Slack bot token
|
|
61
|
+
* xoxp-… — Slack user token
|
|
62
|
+
* -----BEGIN … KEY/CERTIFICATE— PEM markers
|
|
63
|
+
*/
|
|
64
|
+
// NOTE: generic `Authorization: Bearer <jwt>` is intentionally NOT scanned here.
|
|
65
|
+
// JWTs are short-lived and the pattern has a very high false-positive rate on
|
|
66
|
+
// normal journal content. This is a documented scope decision, not a silent gap.
|
|
67
|
+
const SECRET_CONTENT_PATTERNS = [
|
|
68
|
+
{ re: /\bAKIA[0-9A-Z]{16,}\b/g, label: "AWS access key" },
|
|
69
|
+
{ re: /\bghp_[A-Za-z0-9_]{20,}\b/g, label: "GitHub PAT (ghp_)" },
|
|
70
|
+
{ re: /\bgho_[A-Za-z0-9_]{20,}\b/g, label: "GitHub OAuth token (gho_)" },
|
|
71
|
+
{ re: /\bghs_[A-Za-z0-9_]{20,}\b/g, label: "GitHub app token (ghs_)" },
|
|
72
|
+
{ re: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, label: "GitHub fine-grained PAT (github_pat_)" },
|
|
73
|
+
{ re: /\bghr_[A-Za-z0-9]{20,}\b/g, label: "GitHub refresh token (ghr_)" },
|
|
74
|
+
{ re: /\bsk-[A-Za-z0-9\-_]{20,}\b/g, label: "OpenAI/Anthropic secret key (sk-)" },
|
|
75
|
+
{ re: /\bxoxb-[A-Za-z0-9\-]{20,}\b/g, label: "Slack bot token (xoxb-)" },
|
|
76
|
+
{ re: /\bxoxp-[A-Za-z0-9\-]{20,}\b/g, label: "Slack user token (xoxp-)" },
|
|
77
|
+
{ re: /\bnpm_[A-Za-z0-9]{20,}\b/g, label: "npm registry token" },
|
|
78
|
+
{ re: /_authToken=[^\s"'\r\n]{8,}/g, label: "npm _authToken (.npmrc)" },
|
|
79
|
+
{
|
|
80
|
+
re: /-----BEGIN\s+(?:RSA |EC |DSA |OPENSSH |ENCRYPTED )?(?:PRIVATE KEY|CERTIFICATE)-----[\s\S]*?-----END\s+(?:RSA |EC |DSA |OPENSSH |ENCRYPTED )?(?:PRIVATE KEY|CERTIFICATE)-----/g,
|
|
81
|
+
label: "PEM private key/certificate block",
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
const REDACTED_PLACEHOLDER = "[REDACTED-SECRET]";
|
|
85
|
+
/**
|
|
86
|
+
* Scan content for known secret token patterns and redact them in-place.
|
|
87
|
+
* Returns the redacted content and a count of how many matches were replaced.
|
|
88
|
+
*/
|
|
89
|
+
export function scrubSecretContent(content) {
|
|
90
|
+
try {
|
|
91
|
+
let result = content;
|
|
92
|
+
let redactedCount = 0;
|
|
93
|
+
const labels = [];
|
|
94
|
+
for (const { re, label } of SECRET_CONTENT_PATTERNS) {
|
|
95
|
+
// Reset lastIndex for global regexes (they carry state across calls if reused).
|
|
96
|
+
re.lastIndex = 0;
|
|
97
|
+
const matches = result.match(re);
|
|
98
|
+
if (matches && matches.length > 0) {
|
|
99
|
+
re.lastIndex = 0;
|
|
100
|
+
result = result.replace(re, REDACTED_PLACEHOLDER);
|
|
101
|
+
redactedCount += matches.length;
|
|
102
|
+
labels.push(label);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return { content: result, redactedCount, labels };
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Never throw — return original content on error.
|
|
109
|
+
return { content, redactedCount: 0, labels: [] };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// ---------------------------------------------------------------------------
|
|
113
|
+
// Composite scrub — the single call site for journal-write / palace-write
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
/**
|
|
116
|
+
* scrubForCloud(content) applies both layers in order:
|
|
117
|
+
* 1. scrubPromptInjection — removes injection/override attempts
|
|
118
|
+
* 2. scrubSecretContent — redacts known secret token patterns
|
|
119
|
+
*
|
|
120
|
+
* Returns the sanitised string. Never throws.
|
|
121
|
+
*/
|
|
122
|
+
export function scrubForCloud(content) {
|
|
123
|
+
try {
|
|
124
|
+
const afterInjection = scrubPromptInjection(content);
|
|
125
|
+
const { content: afterSecrets } = scrubSecretContent(afterInjection);
|
|
126
|
+
return afterSecrets;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
return content;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Fail-CLOSED export scrub — for deliberate egress (e.g. `ar corrections export`)
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
/**
|
|
136
|
+
* Raised by scrubForExport when a secret survives scrubbing. Distinct error type
|
|
137
|
+
* so callers can abort an export and name the offending record.
|
|
138
|
+
*/
|
|
139
|
+
export class SecretScanError extends Error {
|
|
140
|
+
label;
|
|
141
|
+
constructor(label) {
|
|
142
|
+
super(`secret survived export scrub (${label}) — refusing to emit`);
|
|
143
|
+
this.label = label;
|
|
144
|
+
this.name = "SecretScanError";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* scrubForExport(content) — the fail-CLOSED sibling of scrubForCloud.
|
|
149
|
+
*
|
|
150
|
+
* scrubForCloud is fail-OPEN: on any internal error it returns the ORIGINAL
|
|
151
|
+
* content unchanged, which is the right call on the sync hot-path (never block a
|
|
152
|
+
* write) but the WRONG call for a deliberate export that will be handed to an
|
|
153
|
+
* external store. scrubForExport adds a post-condition: it re-scans the scrubbed
|
|
154
|
+
* output and THROWS SecretScanError if any known secret pattern still matches —
|
|
155
|
+
* so a redaction that silently failed open aborts the export instead of leaking.
|
|
156
|
+
*
|
|
157
|
+
* Use this for every string that leaves AgentRecall via an export/adapter path.
|
|
158
|
+
*/
|
|
159
|
+
export function scrubForExport(content) {
|
|
160
|
+
const scrubbed = scrubForCloud(content);
|
|
161
|
+
// Fail-CLOSED post-condition. Re-scan the OUTPUT with the secret patterns
|
|
162
|
+
// DIRECTLY — not via scrubSecretContent(), whose own try/catch returns
|
|
163
|
+
// redactedCount:0 on an internal error and would silently re-open the fail-open
|
|
164
|
+
// hole this function exists to close. A bare re.test() here lets any regex-engine
|
|
165
|
+
// error propagate and abort the export rather than leak.
|
|
166
|
+
//
|
|
167
|
+
// Under scrubForCloud's current contract a successful scrub leaves no residue,
|
|
168
|
+
// so this never fires on normal input — it is a defense-in-depth guard that trips
|
|
169
|
+
// only if scrubForCloud fails open (its outer catch returns the original) or its
|
|
170
|
+
// redaction contract regresses. Either way: refuse to emit.
|
|
171
|
+
for (const { re, label } of SECRET_CONTENT_PATTERNS) {
|
|
172
|
+
re.lastIndex = 0;
|
|
173
|
+
if (re.test(scrubbed)) {
|
|
174
|
+
throw new SecretScanError(label);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return scrubbed;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=content-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-guard.js","sourceRoot":"","sources":["../../src/storage/content-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,12 +30,63 @@ export interface CorrectionRecord {
|
|
|
30
30
|
/** Set when retractCorrection() soft-deletes this record. */
|
|
31
31
|
retracted_at?: string;
|
|
32
32
|
retract_reason?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Wave 5 — corrections-prediction (north-star).
|
|
35
|
+
*
|
|
36
|
+
* `authoritative`: a human correction is GROUND TRUTH that can OVERRIDE the
|
|
37
|
+
* model (check_action `verdict:'blocked'`). Defaults true for `kind:'correction'`
|
|
38
|
+
* via applyCorrectionDefaults; explicit `authoritative:false` opts a record out
|
|
39
|
+
* of the override gate. Insights/hunches/facts default to NOT authoritative.
|
|
40
|
+
*
|
|
41
|
+
* predict_* counters track the predict-the-correction loop. They are kept
|
|
42
|
+
* STRICTLY SEPARATE from `precision` (= heeded/retrieved) — `predict_precision`
|
|
43
|
+
* = predict_hits / predicted_count and must never mutate the heeded metric.
|
|
44
|
+
*/
|
|
45
|
+
authoritative?: boolean;
|
|
46
|
+
predicted_count?: number;
|
|
47
|
+
predict_hits?: number;
|
|
48
|
+
predict_precision?: number;
|
|
49
|
+
last_predicted?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Consolidation & lifecycle (2026-06-29). Borrowed from Hindsight's REAL
|
|
52
|
+
* mechanisms — proof-count evidence grounding, refine-not-overwrite
|
|
53
|
+
* consolidation, contradiction→supersession, staleness — implemented
|
|
54
|
+
* AR-native (local, file-backed, no LLM on the storage path). Every field is
|
|
55
|
+
* optional and defaulted in applyCorrectionDefaults so pre-existing JSON
|
|
56
|
+
* (which has none of them) normalizes on read with no migration.
|
|
57
|
+
*/
|
|
58
|
+
proof_count?: number;
|
|
59
|
+
proof_confidence?: number;
|
|
60
|
+
superseded_by?: string;
|
|
61
|
+
merged_from?: string[];
|
|
62
|
+
stale?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* One discarded correction-candidate, appended to corrections/_rejected.jsonl
|
|
66
|
+
* when the capture gate rejects the text. This is the survivorship-bias probe:
|
|
67
|
+
* the soft corrections the palace never sees ("that's not what I meant",
|
|
68
|
+
* "closer but the spacing is off") become VISIBLE here instead of vanishing.
|
|
69
|
+
*
|
|
70
|
+
* Written best-effort only — see logRejectedCorrection. A rejection log can
|
|
71
|
+
* NEVER throw into the capture path.
|
|
72
|
+
*/
|
|
73
|
+
export interface RejectedCorrectionRecord {
|
|
74
|
+
ts: string;
|
|
75
|
+
project: string;
|
|
76
|
+
rule: string;
|
|
77
|
+
reason: string;
|
|
78
|
+
gate_version: string;
|
|
33
79
|
}
|
|
34
80
|
export interface CorrectionOutcome {
|
|
35
81
|
correction_id: string;
|
|
36
82
|
project: string;
|
|
37
|
-
/**
|
|
38
|
-
|
|
83
|
+
/**
|
|
84
|
+
* "retrieved" = surfaced via check/recall. "heeded" = agent's action honored
|
|
85
|
+
* the warning. "recurred" = same bug happened again.
|
|
86
|
+
* Wave 5 — "predicted" = predictCorrection fired this risk before the user
|
|
87
|
+
* corrected; "predict_hit" = that prediction later became a real recurrence.
|
|
88
|
+
*/
|
|
89
|
+
kind: "retrieved" | "heeded" | "recurred" | "predicted" | "predict_hit";
|
|
39
90
|
/** ISO timestamp */
|
|
40
91
|
at: string;
|
|
41
92
|
/** Free-text evidence — what made you decide. */
|
|
@@ -63,30 +114,105 @@ export interface CorrectionKPI {
|
|
|
63
114
|
precision: number;
|
|
64
115
|
retrieved: number;
|
|
65
116
|
}>;
|
|
117
|
+
/** P4: active corrections untouched > STALE_DAYS — review candidates. */
|
|
118
|
+
stale_candidates: Array<{
|
|
119
|
+
id: string;
|
|
120
|
+
rule: string;
|
|
121
|
+
last_seen: string;
|
|
122
|
+
}>;
|
|
66
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Gate version stamp — bump whenever isLikelyRealCorrection's accept criteria
|
|
126
|
+
* change so a rejected-log analysis can attribute discard rates to a specific
|
|
127
|
+
* gate revision. Kept in lock-step with the classifier below.
|
|
128
|
+
*
|
|
129
|
+
* v3 (2026-06-21, Loop 8): the gate now scans the FULL correction text (and its
|
|
130
|
+
* decimal-safe sentence fragments) for an actionable marker instead of only the
|
|
131
|
+
* truncated first sentence. Loop 7 proved the first-sentence-slice discarded
|
|
132
|
+
* genuine soft corrections whose directive lived in sentence 2. The NOISE
|
|
133
|
+
* filters (system-fragment / too-short / pure-acknowledgment / doc-header) are
|
|
134
|
+
* unchanged and still run FIRST so the precision floor holds.
|
|
135
|
+
*
|
|
136
|
+
* v4 (2026-06-22, Loop 14): split directive markers into STRONG (accept anywhere)
|
|
137
|
+
* vs WEAK (accept only outside a hedged/reporting frame), closing the round-table's
|
|
138
|
+
* MEDIUM false-accept where tentative filler ("I think we should use it") passed on
|
|
139
|
+
* a bare weak verb. Recall-safe — no fixture correction relies on a hedged weak verb.
|
|
140
|
+
*/
|
|
141
|
+
export declare const GATE_VERSION = "v4-2026-06-22";
|
|
142
|
+
/**
|
|
143
|
+
* P4: a correction is stale when its most recent touch (last_retrieved, else
|
|
144
|
+
* last_outcome, else its date) is older than STALE_DAYS. Pure — `nowMs` is
|
|
145
|
+
* injectable for tests. INFORMATIONAL ONLY: the corrections room is decay-
|
|
146
|
+
* protected, so this never archives on its own; it surfaces a review candidate.
|
|
147
|
+
*/
|
|
148
|
+
export declare function isStaleCorrection(rec: CorrectionRecord, nowMs?: number): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Decimal-safe sentence splitter. Splits on sentence-ending punctuation
|
|
151
|
+
* (`.`, `!`, `?`, or a newline) ONLY when followed by whitespace or end-of-text
|
|
152
|
+
* — NOT on a bare `.` that sits between digits/word chars. This protects
|
|
153
|
+
* version/model tokens like "Opus 4.7", "v3.4.32", "novada-search" and URLs
|
|
154
|
+
* from being chopped mid-fragment (the exact Loop-7 mis-split that hid the
|
|
155
|
+
* imperative in "Show BOTH Opus 4.7 and 4.8" behind the slice "Show BOTH Opus 4").
|
|
156
|
+
*
|
|
157
|
+
* Returns the FULL text as a single fragment when no sentence boundary is found.
|
|
158
|
+
* Empty fragments are dropped. This is a classifier helper, not a linguistic
|
|
159
|
+
* tokenizer — it deliberately errs toward NOT splitting.
|
|
160
|
+
*/
|
|
161
|
+
export declare function splitSentences(text: string): string[];
|
|
67
162
|
/**
|
|
68
163
|
* Capture-quality gate — rejects context-free fragments, pure acknowledgments,
|
|
69
164
|
* and text that carries no actionable signal.
|
|
70
165
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
166
|
+
* v3 (2026-06-21, Loop 8): the ACTIONABLE-signal scan now runs over the FULL
|
|
167
|
+
* text AND each decimal-safe sentence fragment — accepting if ANY fragment
|
|
168
|
+
* carries an imperative/modal/preference marker. This fixes the Loop-7 root
|
|
169
|
+
* cause where the gate only ever saw the truncated first sentence
|
|
170
|
+
* (`text.split(/[.\n]/)[0].slice(0,100)`), discarding ~60% of genuine soft
|
|
171
|
+
* corrections whose directive lived in sentence 2 (e.g. "No, that's wrong.
|
|
172
|
+
* Don't use dark backgrounds.") or whose first sentence was chopped by a
|
|
173
|
+
* decimal ("Show BOTH Opus 4.7 and 4.8" → "Show BOTH Opus 4").
|
|
174
|
+
*
|
|
175
|
+
* PRECISION FLOOR: the HARD noise gates run FIRST, on the WHOLE text — these can
|
|
176
|
+
* never be rescued by the actionable scan:
|
|
177
|
+
* 1. too-short (< 12 chars).
|
|
178
|
+
* 2. system/tool fragment: starts with '<', pure number, bare file path.
|
|
179
|
+
* 3. doc/report/transcript header (starts with '#', a report/mission title,
|
|
180
|
+
* or a file:// URL) — pasted artifacts, never a behavioral rule.
|
|
181
|
+
*
|
|
182
|
+
* Then the ACTIONABLE-signal scan runs over the FULL text + each fragment. A
|
|
183
|
+
* text that OPENS like an acknowledgment ("No, that's wrong …") is RESCUED only
|
|
184
|
+
* if a fragment carries a genuine directive (the Loop-7 leak: "No, that's wrong.
|
|
185
|
+
* Don't use dark backgrounds." → fragment 2 "Don't use …" is a real rule).
|
|
186
|
+
*
|
|
187
|
+
* Finally the SOFT acknowledgment gate rejects pure acks that the actionable
|
|
188
|
+
* scan did NOT rescue (bare "ok sure", "no that's not what I meant"). Because it
|
|
189
|
+
* runs AFTER the actionable scan, it can no longer eat a genuine correction that
|
|
190
|
+
* merely opens with "no" — but a content-free ack still has no directive to
|
|
191
|
+
* rescue it, so it is still dropped. The marker set is TIGHT (dropped the v2
|
|
192
|
+
* loose "verb-ish anywhere" path) so a long prose blob with no real directive
|
|
193
|
+
* is NOT re-admitted just because it contains a generic verb.
|
|
194
|
+
*
|
|
195
|
+
* Returns { ok: true } when the text passes, or { ok: false, reason } explaining
|
|
196
|
+
* which gate fired. Callers may surface the reason in a warning.
|
|
89
197
|
*/
|
|
198
|
+
/**
|
|
199
|
+
* dropHardNoise — the four hard-noise precision-floor gates extracted so they
|
|
200
|
+
* can be called independently by the two-lane router (both lanes apply the same
|
|
201
|
+
* pre-filter before routing).
|
|
202
|
+
*
|
|
203
|
+
* Returns true = text passes (KEEP — not obviously noise)
|
|
204
|
+
* Returns false = text fails a hard gate (DROP — un-rescuable by actionable scan)
|
|
205
|
+
*
|
|
206
|
+
* Identical semantics to the inline gates in isLikelyRealCorrection; this
|
|
207
|
+
* extraction must NOT change gate v4 behaviour (Loops 7/8/14 must stay intact).
|
|
208
|
+
*
|
|
209
|
+
* Gate 1 — minimum length (< 12 chars)
|
|
210
|
+
* Gate 2a — starts with '<' (system/tool fragment)
|
|
211
|
+
* Gate 2b — pure digits (bare number, no rule content)
|
|
212
|
+
* Gate 2c — bare file path (no spaces, has / or \, no 4+ letter word)
|
|
213
|
+
* Gate 3 — doc/report/transcript header (markdown '#', file://, ⏺, report title)
|
|
214
|
+
*/
|
|
215
|
+
export declare function dropHardNoise(text: string): boolean;
|
|
90
216
|
export declare function isLikelyRealCorrection(rule: string, _context?: string): {
|
|
91
217
|
ok: boolean;
|
|
92
218
|
reason?: string;
|
|
@@ -94,6 +220,10 @@ export declare function isLikelyRealCorrection(rule: string, _context?: string):
|
|
|
94
220
|
export interface WriteCorrectionResult {
|
|
95
221
|
written: boolean;
|
|
96
222
|
reason?: string;
|
|
223
|
+
/** P1 consolidation: true when this intake was folded into an existing record. */
|
|
224
|
+
merged?: boolean;
|
|
225
|
+
/** id of the written record, or the existing record's id on a merge. */
|
|
226
|
+
id?: string;
|
|
97
227
|
}
|
|
98
228
|
/**
|
|
99
229
|
* Write a correction to persistent storage.
|
|
@@ -128,15 +258,110 @@ export interface RetractCorrectionResult {
|
|
|
128
258
|
* The file is rewritten atomically — never deleted. The record remains in
|
|
129
259
|
* _outcomes.jsonl history and can be manually reactivated by editing the JSON.
|
|
130
260
|
*/
|
|
131
|
-
export declare function retractCorrection(project: string, id: string, reason?: string): RetractCorrectionResult;
|
|
261
|
+
export declare function retractCorrection(project: string, id: string, reason?: string, supersededBy?: string): RetractCorrectionResult;
|
|
132
262
|
/**
|
|
133
263
|
* Record an outcome event for a correction (retrieved / heeded / recurred).
|
|
134
264
|
* Appends to _outcomes.jsonl and also updates the correction JSON's counters
|
|
135
265
|
* + precision cache. Atomic per-write.
|
|
136
266
|
*/
|
|
137
267
|
export declare function recordOutcome(outcome: CorrectionOutcome): void;
|
|
268
|
+
/**
|
|
269
|
+
* Best-effort: append one row to corrections/_rejected.jsonl recording a
|
|
270
|
+
* gate-rejected correction candidate. INVARIANT: never throws — every fs op is
|
|
271
|
+
* wrapped so a rejection log can never escalate into the capture path. Reads
|
|
272
|
+
* nothing on the hot path except the (already-small) file it rotates.
|
|
273
|
+
*
|
|
274
|
+
* Rotation: when the file exceeds REJECTED_LOG_CAP rows, it is rewritten with
|
|
275
|
+
* only the most-recent rows (append-only semantics, bounded size). Rotation is
|
|
276
|
+
* itself best-effort — a rotation failure still leaves the append intact.
|
|
277
|
+
*/
|
|
278
|
+
export declare function logRejectedCorrection(project: string, rule: string, reason: string): void;
|
|
279
|
+
/**
|
|
280
|
+
* Read all rejected correction candidates for a project, oldest-first (file
|
|
281
|
+
* order). Returns [] when no log exists — never throws. Skips malformed lines.
|
|
282
|
+
*/
|
|
283
|
+
export declare function readRejectedCorrections(project: string): RejectedCorrectionRecord[];
|
|
284
|
+
export interface RejectedStats {
|
|
285
|
+
project: string;
|
|
286
|
+
discarded: number;
|
|
287
|
+
/** Discard rate = discarded / (discarded + accepted). undefined if accepted unknown. */
|
|
288
|
+
rate?: number;
|
|
289
|
+
/** Accepted count if known (e.g. from readCorrections). */
|
|
290
|
+
accepted?: number;
|
|
291
|
+
/** Reasons sorted by descending count. */
|
|
292
|
+
top_reasons: Array<{
|
|
293
|
+
reason: string;
|
|
294
|
+
count: number;
|
|
295
|
+
}>;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Aggregate the rejected log into discard count + per-reason breakdown. When
|
|
299
|
+
* `acceptedCount` is supplied the discard RATE is computed too. Read-only.
|
|
300
|
+
*/
|
|
301
|
+
export declare function getRejectedStats(project: string, acceptedCount?: number): RejectedStats;
|
|
302
|
+
/**
|
|
303
|
+
* Wave 5 — single source for "what outcomes already fired today" across the
|
|
304
|
+
* predict / check-action / session-start / session-end call sites. Reads the
|
|
305
|
+
* _outcomes.jsonl audit trail and buckets today's events (local-TZ) per
|
|
306
|
+
* correction id. Returns an empty Map when no log exists — never throws.
|
|
307
|
+
*
|
|
308
|
+
* Local-TZ date (`sv` locale → YYYY-MM-DD) matches the 1/day guards elsewhere
|
|
309
|
+
* (session-start/session-end) so "today" agrees across all four readers.
|
|
310
|
+
*/
|
|
311
|
+
export declare function readOutcomesForToday(project: string): Map<string, Set<CorrectionOutcome["kind"]>>;
|
|
312
|
+
/**
|
|
313
|
+
* Loop 3 — bucket outcome events recorded STRICTLY BEFORE a given ISO/date
|
|
314
|
+
* cutoff (local-TZ day comparison). Mirrors readOutcomesForToday but with an
|
|
315
|
+
* explicit date arg, so the cross-day predict_hit path can ask "was this risk
|
|
316
|
+
* already PREDICTED on an earlier day?" without depending on today's bucket.
|
|
317
|
+
*
|
|
318
|
+
* `isoCutoff` may be a full ISO timestamp or a YYYY-MM-DD date; only its
|
|
319
|
+
* local-TZ day is used. An event on the SAME day as the cutoff is EXCLUDED
|
|
320
|
+
* (strictly-before) — this is what keeps a same-session/same-day prediction
|
|
321
|
+
* from ever counting as a cross-day hit.
|
|
322
|
+
*/
|
|
323
|
+
export declare function readOutcomesBefore(project: string, isoCutoff: string): Map<string, Set<CorrectionOutcome["kind"]>>;
|
|
324
|
+
/**
|
|
325
|
+
* Loop 3 — bucket outcome events recorded ON a specific local-TZ day. Mirrors
|
|
326
|
+
* readOutcomesForToday but with an explicit date arg (for replaying a past day
|
|
327
|
+
* in tests / offline analysis). `isoDate` may be a full ISO timestamp or a
|
|
328
|
+
* YYYY-MM-DD date; only its local-TZ day is used.
|
|
329
|
+
*/
|
|
330
|
+
export declare function readOutcomesOnDate(project: string, isoDate: string): Map<string, Set<CorrectionOutcome["kind"]>>;
|
|
138
331
|
/**
|
|
139
332
|
* Aggregate KPIs over all corrections for a project — the "is this learning loop working?" view.
|
|
140
333
|
*/
|
|
141
334
|
export declare function getCorrectionKPIs(project: string): CorrectionKPI;
|
|
335
|
+
export interface NoiseReview {
|
|
336
|
+
/** Low-signal corrections (precision<0.3, retrieved≥3) proposed for archiving. */
|
|
337
|
+
suggestions: Array<{
|
|
338
|
+
id: string;
|
|
339
|
+
rule: string;
|
|
340
|
+
precision: number;
|
|
341
|
+
}>;
|
|
342
|
+
/** ids actually retracted — non-empty ONLY when auto mode is on. */
|
|
343
|
+
pruned: string[];
|
|
344
|
+
/** Whether this call ran in auto-prune mode. */
|
|
345
|
+
auto: boolean;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* P4: review low-signal corrections for archiving. SUGGEST-ONLY by default —
|
|
349
|
+
* returns candidates and mutates NOTHING. Set AR_CONSOLIDATE_AUTO=1 (or pass
|
|
350
|
+
* { auto: true }) to actually retract them. This mirrors AR's conservative
|
|
351
|
+
* posture: deleting belief is a deliberate act, so the default never mutates;
|
|
352
|
+
* an explicit human (or opt-in flag) triggers the retraction.
|
|
353
|
+
*/
|
|
354
|
+
export declare function reviewNoiseCorrections(project: string, opts?: {
|
|
355
|
+
auto?: boolean;
|
|
356
|
+
}): NoiseReview;
|
|
357
|
+
/**
|
|
358
|
+
* P5: order corrections for surfacing when a cap applies. Today P0s are surfaced
|
|
359
|
+
* `slice(0, 10)` in newest-first FILENAME order — so when a project has >10 P0s
|
|
360
|
+
* the ones that survive are arbitrary (just the most-recently-dated). This ranks
|
|
361
|
+
* by a composite LOCAL score (NO key, NO network) so the most authoritative +
|
|
362
|
+
* evidence-backed + recently-relevant rules win the cap:
|
|
363
|
+
* severity (p0 always above p1) ≫ proof_confidence ≫ recency ≫ proof_count.
|
|
364
|
+
* Deterministic and stable; pure (Date.now only for recency decay).
|
|
365
|
+
*/
|
|
366
|
+
export declare function rankCorrections(records: CorrectionRecord[], limit?: number): CorrectionRecord[];
|
|
142
367
|
//# sourceMappingURL=corrections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"corrections.d.ts","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"corrections.d.ts","sourceRoot":"","sources":["../../src/storage/corrections.ts"],"names":[],"mappings":"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"}
|