@jmtrin/opencode-kevin 1.1.0 → 1.3.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/dist/plugin/capabilities.d.ts +2 -0
- package/dist/plugin/capabilities.js +3 -0
- package/dist/plugin/index.d.ts +5 -4
- package/dist/plugin/index.js +401 -108
- package/dist/plugin/native.d.ts +2 -2
- package/dist/plugin/native.js +2 -2
- package/package.json +56 -63
- package/LICENSE +0 -21
- package/README.md +0 -576
- package/dist/migrations/001_initial.sql +0 -92
- package/dist/migrations/002_indexes.sql +0 -14
- package/dist/migrations/003_v02_signal.sql +0 -58
- package/dist/migrations/004_v03_knowledge.sql +0 -138
- package/dist/migrations/005_v04_signal.sql +0 -57
- package/dist/migrations/006_v05_glassbox.sql +0 -118
- package/dist/migrations/007_v06_pull.sql +0 -145
- package/dist/migrations/008_v07_truth.sql +0 -124
- package/dist/migrations/009_v08_team.sql +0 -100
- package/dist/migrations/010_v09_native.sql +0 -78
- package/dist/migrations/011_v10_proven.sql +0 -69
- package/dist/migrations/012_v11_drift.sql +0 -24
- package/dist/plugin/Archiver.d.ts +0 -42
- package/dist/plugin/Archiver.js +0 -83
- package/dist/plugin/ArtifactWriter.d.ts +0 -93
- package/dist/plugin/ArtifactWriter.js +0 -291
- package/dist/plugin/CausalChain.d.ts +0 -22
- package/dist/plugin/CausalChain.js +0 -197
- package/dist/plugin/ConflictDetector.d.ts +0 -35
- package/dist/plugin/ConflictDetector.js +0 -260
- package/dist/plugin/ContextInjector.d.ts +0 -222
- package/dist/plugin/ContextInjector.js +0 -533
- package/dist/plugin/ConventionMiner.d.ts +0 -35
- package/dist/plugin/ConventionMiner.js +0 -242
- package/dist/plugin/Curator.d.ts +0 -116
- package/dist/plugin/Curator.js +0 -324
- package/dist/plugin/Feedback.d.ts +0 -67
- package/dist/plugin/Feedback.js +0 -120
- package/dist/plugin/HookLiveness.d.ts +0 -88
- package/dist/plugin/HookLiveness.js +0 -322
- package/dist/plugin/InjectionLedger.d.ts +0 -98
- package/dist/plugin/InjectionLedger.js +0 -295
- package/dist/plugin/LessonFixer.d.ts +0 -44
- package/dist/plugin/LessonFixer.js +0 -45
- package/dist/plugin/Materializer.d.ts +0 -83
- package/dist/plugin/Materializer.js +0 -181
- package/dist/plugin/MemoryService.d.ts +0 -360
- package/dist/plugin/MemoryService.js +0 -1242
- package/dist/plugin/Migrate.d.ts +0 -17
- package/dist/plugin/Migrate.js +0 -271
- package/dist/plugin/PatternMiner.d.ts +0 -49
- package/dist/plugin/PatternMiner.js +0 -132
- package/dist/plugin/QualityGate.d.ts +0 -124
- package/dist/plugin/QualityGate.js +0 -119
- package/dist/plugin/Reflector.d.ts +0 -91
- package/dist/plugin/Reflector.js +0 -307
- package/dist/plugin/RepoIdentity.d.ts +0 -124
- package/dist/plugin/RepoIdentity.js +0 -300
- package/dist/plugin/RepoTruth.d.ts +0 -80
- package/dist/plugin/RepoTruth.js +0 -599
- package/dist/plugin/Retrospective.d.ts +0 -17
- package/dist/plugin/Retrospective.js +0 -213
- package/dist/plugin/SharedLayer.d.ts +0 -159
- package/dist/plugin/SharedLayer.js +0 -462
- package/dist/plugin/Store.d.ts +0 -29
- package/dist/plugin/Store.js +0 -50
- package/dist/plugin/ToolCallObserver.d.ts +0 -32
- package/dist/plugin/ToolCallObserver.js +0 -201
- package/dist/plugin/columns.d.ts +0 -11
- package/dist/plugin/columns.js +0 -54
- package/dist/plugin/confidence.d.ts +0 -8
- package/dist/plugin/confidence.js +0 -34
- package/dist/plugin/contract.d.ts +0 -54
- package/dist/plugin/contract.js +0 -383
- package/dist/plugin/diff.d.ts +0 -8
- package/dist/plugin/diff.js +0 -182
- package/dist/plugin/escape.d.ts +0 -39
- package/dist/plugin/escape.js +0 -60
- package/dist/plugin/fingerprint.d.ts +0 -27
- package/dist/plugin/fingerprint.js +0 -73
- package/dist/plugin/inferability.d.ts +0 -32
- package/dist/plugin/inferability.js +0 -88
- package/dist/plugin/kevin_approve.d.ts +0 -34
- package/dist/plugin/kevin_approve.js +0 -52
- package/dist/plugin/kevin_audit.d.ts +0 -213
- package/dist/plugin/kevin_audit.js +0 -563
- package/dist/plugin/kevin_bench.d.ts +0 -10
- package/dist/plugin/kevin_bench.js +0 -82
- package/dist/plugin/kevin_conflicts.d.ts +0 -9
- package/dist/plugin/kevin_conflicts.js +0 -50
- package/dist/plugin/kevin_contract.d.ts +0 -8
- package/dist/plugin/kevin_contract.js +0 -59
- package/dist/plugin/kevin_doctor.d.ts +0 -62
- package/dist/plugin/kevin_doctor.js +0 -196
- package/dist/plugin/kevin_facts.d.ts +0 -42
- package/dist/plugin/kevin_facts.js +0 -36
- package/dist/plugin/kevin_forget.d.ts +0 -33
- package/dist/plugin/kevin_forget.js +0 -260
- package/dist/plugin/kevin_native.d.ts +0 -29
- package/dist/plugin/kevin_native.js +0 -79
- package/dist/plugin/kevin_propose.d.ts +0 -23
- package/dist/plugin/kevin_propose.js +0 -14
- package/dist/plugin/kevin_publish.d.ts +0 -38
- package/dist/plugin/kevin_publish.js +0 -18
- package/dist/plugin/kevin_why.d.ts +0 -23
- package/dist/plugin/kevin_why.js +0 -111
- package/dist/plugin/memory-format.d.ts +0 -20
- package/dist/plugin/memory-format.js +0 -59
- package/dist/plugin/metrics.d.ts +0 -97
- package/dist/plugin/metrics.js +0 -284
- package/dist/plugin/okf-export.d.ts +0 -3
- package/dist/plugin/okf-export.js +0 -134
- package/dist/plugin/okf-import.d.ts +0 -76
- package/dist/plugin/okf-import.js +0 -271
- package/dist/plugin/okf.d.ts +0 -107
- package/dist/plugin/okf.js +0 -303
- package/dist/plugin/perf.d.ts +0 -35
- package/dist/plugin/perf.js +0 -174
- package/dist/plugin/query-tokenizer.d.ts +0 -13
- package/dist/plugin/query-tokenizer.js +0 -133
- package/dist/plugin/redact.d.ts +0 -2
- package/dist/plugin/redact.js +0 -18
- package/dist/plugin/replay-types.d.ts +0 -69
- package/dist/plugin/replay-types.js +0 -156
- package/dist/plugin/replay.d.ts +0 -36
- package/dist/plugin/replay.js +0 -202
- package/dist/plugin/sqlite-adapter.d.ts +0 -12
- package/dist/plugin/sqlite-adapter.js +0 -81
- package/dist/plugin/time-ms.d.ts +0 -1
- package/dist/plugin/time-ms.js +0 -16
- package/dist/plugin/uuid.d.ts +0 -1
- package/dist/plugin/uuid.js +0 -50
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { firstSentence } from "./Curator.js";
|
|
4
|
-
import { normalize } from "./fingerprint.js";
|
|
5
|
-
import { STOP_WORDS } from "./query-tokenizer.js";
|
|
6
|
-
export const SKILL_TOPIC = "project-knowledge";
|
|
7
|
-
/** Hash-like noise: FNV-1a output is 16 lowercase hex chars; an 8+ hex
|
|
8
|
-
* token is indistinguishable from a fingerprint prefix and must never
|
|
9
|
-
* become a topic (D6-14). */
|
|
10
|
-
const HEX_LIKE_RE = /^[0-9a-f]{8,}$/;
|
|
11
|
-
const TOKEN_RE = /[^a-z0-9]+/;
|
|
12
|
-
/** Sanitize a memory type into a filesystem-safe topic prefix. */
|
|
13
|
-
function sanitizeType(type) {
|
|
14
|
-
const cleaned = type
|
|
15
|
-
.toLowerCase()
|
|
16
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
17
|
-
.replace(/-+/g, "-")
|
|
18
|
-
.replace(/^-|-$/g, "");
|
|
19
|
-
return cleaned === "" ? "memory" : cleaned;
|
|
20
|
-
}
|
|
21
|
-
function tokensOf(content) {
|
|
22
|
-
return normalize(content)
|
|
23
|
-
.split(TOKEN_RE)
|
|
24
|
-
.filter((t) => t !== "" && !STOP_WORDS.has(t) && !HEX_LIKE_RE.test(t));
|
|
25
|
-
}
|
|
26
|
-
/** Highest-frequency non-stop-word token, ties broken lexicographically
|
|
27
|
-
* (smallest wins) so the result is stable. "" when every token is a
|
|
28
|
-
* stop-word or hash-like noise. */
|
|
29
|
-
function dominantToken(rows) {
|
|
30
|
-
const counts = new Map();
|
|
31
|
-
for (const row of rows) {
|
|
32
|
-
for (const token of tokensOf(row.content)) {
|
|
33
|
-
counts.set(token, (counts.get(token) ?? 0) + 1);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
let best = "";
|
|
37
|
-
let bestCount = 0;
|
|
38
|
-
for (const [token, count] of counts) {
|
|
39
|
-
if (count > bestCount || (count === bestCount && token < best)) {
|
|
40
|
-
best = token;
|
|
41
|
-
bestCount = count;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return best;
|
|
45
|
-
}
|
|
46
|
-
function renderRows(rows) {
|
|
47
|
-
const sorted = [...rows].sort((a, b) => a.id.localeCompare(b.id));
|
|
48
|
-
const lines = sorted
|
|
49
|
-
.map((row) => `- ${firstSentence(row.content)}`)
|
|
50
|
-
.filter((line) => line !== "- ");
|
|
51
|
-
return lines.length === 0 ? "" : `${lines.join("\n")}\n`;
|
|
52
|
-
}
|
|
53
|
-
export class Materializer {
|
|
54
|
-
store;
|
|
55
|
-
/** `root` is injectable for tests; production defaults to ~/.opencode-kevin. */
|
|
56
|
-
root;
|
|
57
|
-
/**
|
|
58
|
-
* v0.9.0 (K9-016 / plan §5.4, D9-10) — the mutual-exclusion guard.
|
|
59
|
-
* A surface `attachNative()` registered is skipped by `materialize()`
|
|
60
|
-
* for that surface only; the other surface keeps emitting.
|
|
61
|
-
*/
|
|
62
|
-
nativeRegistered = new Set();
|
|
63
|
-
constructor(store, options = {}) {
|
|
64
|
-
this.store = store;
|
|
65
|
-
this.root = options.root ?? join(homedir(), ".opencode-kevin");
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* v0.9.0 (K9-016 / plan §5.4, D9-10) — record whether the surface was
|
|
69
|
-
* registered natively. Called at attach time (index.ts wiring, K9-018)
|
|
70
|
-
* with each `NativeRegistration.registered` flag.
|
|
71
|
-
*/
|
|
72
|
-
markNativeRegistered(surface, registered) {
|
|
73
|
-
if (registered)
|
|
74
|
-
this.nativeRegistered.add(surface);
|
|
75
|
-
else
|
|
76
|
-
this.nativeRegistered.delete(surface);
|
|
77
|
-
}
|
|
78
|
-
/** v0.9.0 (K9-016 / plan §5.4, D9-10) — is the surface registered natively? */
|
|
79
|
-
hasNativeRegistration(surface) {
|
|
80
|
-
return this.nativeRegistered.has(surface);
|
|
81
|
-
}
|
|
82
|
-
/** The curated, active memories — the knowledge the pull channels publish. */
|
|
83
|
-
curatedRows() {
|
|
84
|
-
return this.store
|
|
85
|
-
.prepare(`SELECT id, type, content FROM memories
|
|
86
|
-
WHERE status = 'active' AND curated = 1`)
|
|
87
|
-
.all();
|
|
88
|
-
}
|
|
89
|
-
/** The rendered skill body over all curated memories; "" when empty. */
|
|
90
|
-
skillBody() {
|
|
91
|
-
return renderRows(this.curatedRows());
|
|
92
|
-
}
|
|
93
|
-
/** Group rows by type, deriving each type's topic from its own content. */
|
|
94
|
-
groupByTopic(rows) {
|
|
95
|
-
const byType = new Map();
|
|
96
|
-
for (const row of rows) {
|
|
97
|
-
const list = byType.get(row.type) ?? [];
|
|
98
|
-
list.push(row);
|
|
99
|
-
byType.set(row.type, list);
|
|
100
|
-
}
|
|
101
|
-
const groups = [];
|
|
102
|
-
for (const [type, typeRows] of byType) {
|
|
103
|
-
const token = dominantToken(typeRows);
|
|
104
|
-
if (token === "")
|
|
105
|
-
continue;
|
|
106
|
-
groups.push({
|
|
107
|
-
topic: `${sanitizeType(type)}-${token}`,
|
|
108
|
-
rows: typeRows,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
return groups.sort((a, b) => a.topic.localeCompare(b.topic));
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* The pull-channel targets: the skill file plus one ref file per topic.
|
|
115
|
-
* The order is deterministic (skill first, refs by topic).
|
|
116
|
-
*/
|
|
117
|
-
bundleTargets() {
|
|
118
|
-
const rows = this.curatedRows();
|
|
119
|
-
const targets = [];
|
|
120
|
-
if (rows.length > 0 && renderRows(rows) !== "") {
|
|
121
|
-
targets.push({
|
|
122
|
-
topic: SKILL_TOPIC,
|
|
123
|
-
path: join(this.root, "skills", "project-knowledge.md"),
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
for (const group of this.groupByTopic(rows)) {
|
|
127
|
-
if (renderRows(group.rows) === "")
|
|
128
|
-
continue;
|
|
129
|
-
targets.push({
|
|
130
|
-
topic: group.topic,
|
|
131
|
-
path: join(this.root, "refs", `${group.topic}.md`),
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
return targets;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Regenerate every bundle through the ArtifactWriter (write). This is
|
|
138
|
-
* a call site of `write()` — the single write FUNCTION with two
|
|
139
|
-
* constrained targets: `kevin_approve` reaches `agents_md_path`, this
|
|
140
|
-
* module reaches `~/.opencode-kevin` only (D6-07; enforced by K6-020).
|
|
141
|
-
*
|
|
142
|
-
* v0.9.0 (K9-016 / plan §5.4, D9-10) — the guard: a surface registered
|
|
143
|
-
* natively by `attachNative()` is skipped here for that surface only.
|
|
144
|
-
* Both active would put the curated skill in front of the model twice
|
|
145
|
-
* from two sources that can disagree; neither active would silently
|
|
146
|
-
* remove the feature on hosts that gained the subpath.
|
|
147
|
-
*/
|
|
148
|
-
materialize(writer) {
|
|
149
|
-
const pending = [];
|
|
150
|
-
const rows = this.curatedRows();
|
|
151
|
-
const skillBody = renderRows(rows);
|
|
152
|
-
if (skillBody !== "" && !this.nativeRegistered.has("skill")) {
|
|
153
|
-
pending.push({
|
|
154
|
-
topic: SKILL_TOPIC,
|
|
155
|
-
path: join(this.root, "skills", "project-knowledge.md"),
|
|
156
|
-
body: skillBody,
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
if (!this.nativeRegistered.has("reference")) {
|
|
160
|
-
for (const group of this.groupByTopic(rows)) {
|
|
161
|
-
const body = renderRows(group.rows);
|
|
162
|
-
if (body === "")
|
|
163
|
-
continue;
|
|
164
|
-
pending.push({
|
|
165
|
-
topic: group.topic,
|
|
166
|
-
path: join(this.root, "refs", `${group.topic}.md`),
|
|
167
|
-
body,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return pending.map((bundle) => ({
|
|
172
|
-
topic: bundle.topic,
|
|
173
|
-
path: bundle.path,
|
|
174
|
-
outcome: writer.write({
|
|
175
|
-
path: bundle.path,
|
|
176
|
-
mode: "markers",
|
|
177
|
-
content: bundle.body,
|
|
178
|
-
}),
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
}
|
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import type { Store } from "./Store.js";
|
|
2
|
-
import type { Metrics } from "./metrics.js";
|
|
3
|
-
export type MemoryType = "error" | "pattern" | "decision" | "context" | "rule" | "solution";
|
|
4
|
-
export type MemoryScope = "project" | "session";
|
|
5
|
-
export type MemoryOrigin = "reflector" | "agent" | "pattern" | "retrospective" | "causal" | "imported";
|
|
6
|
-
export interface Memory {
|
|
7
|
-
id: string;
|
|
8
|
-
type: MemoryType;
|
|
9
|
-
content: string;
|
|
10
|
-
scope: MemoryScope;
|
|
11
|
-
relevanceScore: number;
|
|
12
|
-
sourceTool?: string | null;
|
|
13
|
-
sourceSession?: string | null;
|
|
14
|
-
metadata?: Record<string, unknown> | null;
|
|
15
|
-
createdAt: string;
|
|
16
|
-
updatedAt: string;
|
|
17
|
-
expiresAt?: string | null;
|
|
18
|
-
/** v0.2.0 — project the memory belongs to (nullable for legacy rows). */
|
|
19
|
-
projectId?: string | null;
|
|
20
|
-
/** v0.2.0 — content fingerprint for dedup (only set for `type='error'`). */
|
|
21
|
-
fingerprint?: string | null;
|
|
22
|
-
/** v0.2.0 — origin of the memory. */
|
|
23
|
-
origin?: MemoryOrigin | null;
|
|
24
|
-
/** v0.3.0 — confidence derived from causal evidence (0..1). Only set by CausalChain. */
|
|
25
|
-
confidence?: number | null;
|
|
26
|
-
/** v0.3.0 — number of confirmed causal fix confirmations. */
|
|
27
|
-
evidenceCount?: number | null;
|
|
28
|
-
/** v0.3.0 — last time causal evidence was observed. */
|
|
29
|
-
lastVerifiedAt?: string | null;
|
|
30
|
-
/** v0.3.0 — lifecycle status. Default 'active'. */
|
|
31
|
-
status?: string | null;
|
|
32
|
-
/** v0.4.0 — deterministic capture of the linked fix call (K4-014). */
|
|
33
|
-
fixArgs?: string | null;
|
|
34
|
-
/** v0.4.0 (BUG-008/010) — negative evidence: how many times the
|
|
35
|
-
* fingerprint recurred after injection (demotes confidence). */
|
|
36
|
-
recurrenceCount?: number | null;
|
|
37
|
-
/** v0.5.0 (K5-009 / plan §5.3, D5-07) — human verdict: ignored memories
|
|
38
|
-
* are excluded from retrieval and injection. */
|
|
39
|
-
ignored?: boolean;
|
|
40
|
-
/** v0.5.0 (K5-009 / plan §5.3) — id of the memory that superseded this
|
|
41
|
-
* one (decision/rule replacement, K3-014). Null when active. */
|
|
42
|
-
supersedes?: string | null;
|
|
43
|
-
/** v0.5.0 (K5-010 / plan §5.3, D5-02) — human judgement counters,
|
|
44
|
-
* folded into confidence by computeConfidence. */
|
|
45
|
-
feedbackPositive?: number;
|
|
46
|
-
/** v0.6.0 (K6-011 / plan §5.4) — curation state: curated memories have
|
|
47
|
-
* been written to AGENTS.md and are excluded from new candidates. */
|
|
48
|
-
curated?: boolean;
|
|
49
|
-
/** v0.6.0 (K6-011 / plan §5.4) — when the memory was curated (ISO time). */
|
|
50
|
-
curatedAt?: string | null;
|
|
51
|
-
/** v0.6.0 (K6-011 / plan §5.3) — deterministic inferability verdict from
|
|
52
|
-
* `inferability.classify()`; `null` = unknown, never collapsed. */
|
|
53
|
-
inferable?: "inferable" | "non_inferable" | null;
|
|
54
|
-
/** v0.5.0 (K5-010 / plan §5.3, D5-02) — human judgement counters,
|
|
55
|
-
* folded into confidence by computeConfidence. */
|
|
56
|
-
feedbackNegative?: number;
|
|
57
|
-
/** v0.7.0 (K7-008 / plan §5.3, D7-03) — de-ranking penalty in
|
|
58
|
-
* [0, 0.5], clamped by applyTruthPenalty. Multiplies rankScore as
|
|
59
|
-
* `(1 - truthPenalty)`. Defaults to 0. */
|
|
60
|
-
truthPenalty?: number | null;
|
|
61
|
-
/** v0.7.0 (K7-008 / plan §5.3, D7-03) — first contradiction timestamp. */
|
|
62
|
-
contradictedAt?: string | null;
|
|
63
|
-
/** v0.8.0 (K8-018 / plan §5.2) — the memory's layer marker: 'local'
|
|
64
|
-
* (default) or 'shared'. */
|
|
65
|
-
layer?: string | null;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* v0.8.0 (K8-018 / plan §5.2) — outcome of `update()`. A refusal is a
|
|
69
|
-
* typed value, never a throw and never a silent no-op.
|
|
70
|
-
*/
|
|
71
|
-
export type MemoryUpdateResult = {
|
|
72
|
-
ok: true;
|
|
73
|
-
} | {
|
|
74
|
-
ok: false;
|
|
75
|
-
refused: readonly string[];
|
|
76
|
-
};
|
|
77
|
-
export interface SaveInput {
|
|
78
|
-
type: MemoryType;
|
|
79
|
-
content: string;
|
|
80
|
-
/** v0.4.0 (BUG-008) — preserve the original id on okf import;
|
|
81
|
-
* when absent a fresh uuidv7 is generated. */
|
|
82
|
-
id?: string;
|
|
83
|
-
scope?: MemoryScope;
|
|
84
|
-
relevanceScore?: number;
|
|
85
|
-
sourceTool?: string;
|
|
86
|
-
sourceSession?: string;
|
|
87
|
-
metadata?: Record<string, unknown>;
|
|
88
|
-
expiresAt?: string;
|
|
89
|
-
/** v0.2.0 — project id. When absent, the memory is cross-project (NULL project_id). */
|
|
90
|
-
projectId?: string;
|
|
91
|
-
/** v0.2.0 — origin. Defaults to `'agent'` when omitted. */
|
|
92
|
-
origin?: MemoryOrigin;
|
|
93
|
-
/** v0.2.0 — explicit fingerprint. Auto-derived for `type='error'` if absent. */
|
|
94
|
-
fingerprint?: string;
|
|
95
|
-
/** v0.3.0 — number of confirmed causal fix confirmations. */
|
|
96
|
-
evidenceCount?: number;
|
|
97
|
-
/** v0.3.0 — last time causal evidence was observed. */
|
|
98
|
-
lastVerifiedAt?: string;
|
|
99
|
-
/** v0.3.0 — lifecycle status. Default 'active'. */
|
|
100
|
-
status?: string;
|
|
101
|
-
/** v0.4.0 (BUG-008/010) — how many times the fingerprint recurred
|
|
102
|
-
* after injection (negative evidence, demotes confidence). */
|
|
103
|
-
recurrenceCount?: number;
|
|
104
|
-
}
|
|
105
|
-
export interface QueryInput {
|
|
106
|
-
text: string;
|
|
107
|
-
type?: string;
|
|
108
|
-
scope?: MemoryScope | "all";
|
|
109
|
-
limit?: number;
|
|
110
|
-
/** v0.2.0 — when true, returns full `Memory` rows (v0.1.x behavior).
|
|
111
|
-
* When `false` or absent, returns `SlimMemory` rows (default v0.2.0
|
|
112
|
-
* behavior, per plan §B6.3 / K2-010).
|
|
113
|
-
*/
|
|
114
|
-
full?: boolean;
|
|
115
|
-
/** v0.3.0 — when true, includes rows where status = 'superseded'.
|
|
116
|
-
* Default false (only active rows). */
|
|
117
|
-
includeSuperseded?: boolean;
|
|
118
|
-
/** v0.3.0 (BUG-001) — when true, the slim payload also carries
|
|
119
|
-
* `confidence`, `evidence_count` and `last_verified_at` (v0.3.0 K3
|
|
120
|
-
* evidence fields). Default false (minimal slim shape). */
|
|
121
|
-
evidence?: boolean;
|
|
122
|
-
}
|
|
123
|
-
/** v0.2.0 — slim query payload (K2-010). Snippet is a short content prefix;
|
|
124
|
-
* `score` is the FTS5 BM25 score when available, falling back to
|
|
125
|
-
* `relevanceScore` for non-FTS callers. */
|
|
126
|
-
export interface SlimMemory {
|
|
127
|
-
id: string;
|
|
128
|
-
type: MemoryType;
|
|
129
|
-
scope: MemoryScope;
|
|
130
|
-
score: number;
|
|
131
|
-
snippet: string;
|
|
132
|
-
}
|
|
133
|
-
/** v0.3.0 (BUG-001) — slim payload extended with the evidence fields when
|
|
134
|
-
* `query({ evidence: true })`. Fills the `kevin_query(evidence: true)`
|
|
135
|
-
* contract without falling back to the full `Memory` shape. */
|
|
136
|
-
export interface SlimMemoryWithEvidence extends SlimMemory {
|
|
137
|
-
confidence: number | null;
|
|
138
|
-
evidence_count: number | null;
|
|
139
|
-
last_verified_at: string | null;
|
|
140
|
-
}
|
|
141
|
-
export interface GetRelevantInput {
|
|
142
|
-
query?: string;
|
|
143
|
-
maxTokens?: number;
|
|
144
|
-
scope?: MemoryScope | "all";
|
|
145
|
-
/** v0.3.0 — when true, includes rows where status = 'superseded'.
|
|
146
|
-
* Default false (only active rows). */
|
|
147
|
-
includeSuperseded?: boolean;
|
|
148
|
-
/**
|
|
149
|
-
* v0.4.0 (BUG-016) — when false, the relevance bump (K2-023) is
|
|
150
|
-
* skipped. Used by ContextInjector's probe fetch so the decision and
|
|
151
|
-
* any retry both see the ORIGINAL ranking; the single bump is applied
|
|
152
|
-
* by the fetch that actually produces the injected block.
|
|
153
|
-
*/
|
|
154
|
-
bump?: boolean;
|
|
155
|
-
/**
|
|
156
|
-
* v0.5.0 (K5-008 / plan §5.6, D5-10) — injectable clock. Defaults to
|
|
157
|
-
* `new Date()` at the top of the method and is the ONLY time source
|
|
158
|
-
* for recency decay: replay and tests can freeze time. Never call
|
|
159
|
-
* `Date.now()` again inside the method.
|
|
160
|
-
*/
|
|
161
|
-
now?: Date;
|
|
162
|
-
}
|
|
163
|
-
interface MemoryRow {
|
|
164
|
-
id: string;
|
|
165
|
-
type: MemoryType;
|
|
166
|
-
content: string;
|
|
167
|
-
scope: MemoryScope;
|
|
168
|
-
relevance_score: number;
|
|
169
|
-
source_tool: string | null;
|
|
170
|
-
source_session: string | null;
|
|
171
|
-
metadata: string | null;
|
|
172
|
-
created_at: string;
|
|
173
|
-
updated_at: string;
|
|
174
|
-
expires_at: string | null;
|
|
175
|
-
/** v0.2.0 columns — nullable for rows from pre-003 DBs. */
|
|
176
|
-
project_id?: string | null;
|
|
177
|
-
fingerprint?: string | null;
|
|
178
|
-
origin?: MemoryOrigin | null;
|
|
179
|
-
/** v0.3.0 */
|
|
180
|
-
evidence_count?: number;
|
|
181
|
-
last_verified_at?: string | null;
|
|
182
|
-
status?: string;
|
|
183
|
-
/** v0.4.0 */
|
|
184
|
-
recurrence_count?: number;
|
|
185
|
-
/** v0.4.0 */
|
|
186
|
-
fix_args?: string | null;
|
|
187
|
-
/** v0.5.0 (K5-009) */
|
|
188
|
-
ignored?: number;
|
|
189
|
-
/** v0.5.0 (K5-009) */
|
|
190
|
-
superseded_by?: string | null;
|
|
191
|
-
/** v0.5.0 (K5-010) */
|
|
192
|
-
feedback_positive?: number;
|
|
193
|
-
/** v0.5.0 (K5-010) */
|
|
194
|
-
feedback_negative?: number;
|
|
195
|
-
/** v0.6.0 (K6-011 / migration 007) */
|
|
196
|
-
curated?: number;
|
|
197
|
-
/** v0.6.0 (K6-011 / migration 007) */
|
|
198
|
-
curated_at?: string | null;
|
|
199
|
-
/** v0.6.0 (K6-011 / migration 007) — 1 = inferable, 0 = non_inferable,
|
|
200
|
-
* NULL = unknown. */
|
|
201
|
-
inferable?: number | null;
|
|
202
|
-
/** v0.7.0 (K7-008 / migration 008) — de-ranking penalty in [0, 0.5]. */
|
|
203
|
-
truth_penalty?: number | null;
|
|
204
|
-
/** v0.7.0 (K7-008 / migration 008) — first contradiction timestamp. */
|
|
205
|
-
contradicted_at?: string | null;
|
|
206
|
-
/** v0.8.0 (K8-018 / migration 009) — layer marker on the row. */
|
|
207
|
-
layer?: string | null;
|
|
208
|
-
}
|
|
209
|
-
export declare const DATE_NOW = "2099-01-01T00:00:00.000Z";
|
|
210
|
-
export declare function hasRepoIdColumn(store: Store): boolean;
|
|
211
|
-
export declare function mapRow(row: MemoryRow, score?: number): Memory;
|
|
212
|
-
export declare class MemoryService {
|
|
213
|
-
private readonly metrics;
|
|
214
|
-
constructor(store: Store, metrics?: Metrics | null, repoId?: string | null);
|
|
215
|
-
private store;
|
|
216
|
-
private repoId;
|
|
217
|
-
setRepoId(repoId: string | null): void;
|
|
218
|
-
private hasRecurrenceColumn;
|
|
219
|
-
private hasIgnoredColumn;
|
|
220
|
-
private hasCuratedColumn;
|
|
221
|
-
private hasTruthColumns;
|
|
222
|
-
private hasRepoIdColumn;
|
|
223
|
-
save(input: SaveInput): string;
|
|
224
|
-
/**
|
|
225
|
-
* v0.6.0 (K6-011 / plan §5.4) — mark memories as curated. Batch in a
|
|
226
|
-
* single statement with an `IN` clause; do not loop. Returns the number
|
|
227
|
-
* of rows matched by the statement (not only rows whose value changed):
|
|
228
|
-
* a second call with the same ids re-matches them, so the caller must
|
|
229
|
-
* re-filter the id list (e.g. by `curated = 0`) to observe 0.
|
|
230
|
-
*/
|
|
231
|
-
markCurated(ids: readonly string[], at: string): number;
|
|
232
|
-
getById(id: string): Memory | null;
|
|
233
|
-
/**
|
|
234
|
-
* v0.4.0 (K4-016) — most recent ACTIVE memory for a fingerprint,
|
|
235
|
-
* optionally filtered by type. Feeds the HITL suggestion lookup
|
|
236
|
-
* (most-recurred fingerprint → its pattern memory).
|
|
237
|
-
*/
|
|
238
|
-
getByFingerprint(fingerprint: string, type?: MemoryType): Memory | null;
|
|
239
|
-
/**
|
|
240
|
-
* v0.8.0 (K8-018 / plan §5.2) — result of a memory mutation.
|
|
241
|
-
* `refused` lists the shared-layer columns that were not written.
|
|
242
|
-
*/
|
|
243
|
-
update(id: string, fields: Partial<Memory>): MemoryUpdateResult;
|
|
244
|
-
/**
|
|
245
|
-
* v0.8.0 (K8-018 / plan §5.2) — count a refused shared-row write. The
|
|
246
|
-
* key lives OUTSIDE the frozen METRIC_KEYS ladder (K7-004), following
|
|
247
|
-
* the v0.6.0 `incrRegistered` precedent: it persists to the same
|
|
248
|
-
* `kevin_metrics` table and is read back by `kevin_audit` as a bare SQL
|
|
249
|
-
* scalar, so the counter survives across processes without growing the
|
|
250
|
-
* 39-key ladder.
|
|
251
|
-
*/
|
|
252
|
-
private countSharedRefusal;
|
|
253
|
-
/**
|
|
254
|
-
* v0.7.0 (K7-008 / plan §5.3, D7-03) — apply a bounded truth penalty.
|
|
255
|
-
* Clamps `penalty` to [0, 0.5], writes `truth_penalty` and `contradicted_at`,
|
|
256
|
-
* and increments `memories_contradicted` ONLY when the value moves from 0
|
|
257
|
-
* to non-zero (a second penalty on the same memory does not re-count).
|
|
258
|
-
* It NEVER writes `status` — contradiction de-ranks; it never deletes
|
|
259
|
-
* (Principle 24). `reason` is the human-readable explanation surfaced by
|
|
260
|
-
* `kevin_facts`; the caller persists it in the `memory_conflicts` row.
|
|
261
|
-
*/
|
|
262
|
-
applyTruthPenalty(memoryId: string, penalty: number, reason: string): void;
|
|
263
|
-
delete(id: string): void;
|
|
264
|
-
/** v0.1.x behavior — returns full `Memory` rows. */
|
|
265
|
-
query(input: QueryInput & {
|
|
266
|
-
full: true;
|
|
267
|
-
}): Memory[];
|
|
268
|
-
/** v0.3.0 (BUG-001) — slim rows carrying the evidence fields. */
|
|
269
|
-
query(input: QueryInput & {
|
|
270
|
-
evidence: true;
|
|
271
|
-
}): SlimMemoryWithEvidence[];
|
|
272
|
-
/** v0.2.0 default — returns `SlimMemory` rows. */
|
|
273
|
-
query(input: QueryInput): SlimMemory[];
|
|
274
|
-
private isCrossProjectEnabled;
|
|
275
|
-
/**
|
|
276
|
-
* v0.4.0 (K4-012) — read a kevin_settings flag by key. Falls back to
|
|
277
|
-
* the caller-provided default when the key is missing or the table is
|
|
278
|
-
* unavailable (legacy DB without the settings table).
|
|
279
|
-
*/
|
|
280
|
-
getSetting(key: string, fallback?: string): string;
|
|
281
|
-
private loadAll;
|
|
282
|
-
private queryRelevant;
|
|
283
|
-
getRelevant(input: GetRelevantInput): Memory[];
|
|
284
|
-
/**
|
|
285
|
-
* v0.4.0 (BUG-016) — apply the K2-023 relevance bump to a fixed slice
|
|
286
|
-
* of ids, exactly once. Lets ContextInjector probe without mutating
|
|
287
|
-
* and still bump the slice it actually injects.
|
|
288
|
-
*/
|
|
289
|
-
bumpRelevance(ids: string[]): void;
|
|
290
|
-
/**
|
|
291
|
-
* v0.3.0 (K3-004) — Promote an error memory to a causal pattern.
|
|
292
|
-
*
|
|
293
|
-
* Creates a new `pattern` memory with `origin = 'causal'`, derived
|
|
294
|
-
* confidence, and evidence count. The original error memory is NOT
|
|
295
|
-
* deleted — the audit trail is preserved. Returns the new memory id,
|
|
296
|
-
* or null when the source error is not eligible (missing fingerprint,
|
|
297
|
-
* wrong type, or already promoted).
|
|
298
|
-
*/
|
|
299
|
-
/**
|
|
300
|
-
* v0.4.0 (K4-009) — returns `{ id, created }` so callers can tell a
|
|
301
|
-
* newly-created pattern from an idempotent refresh.
|
|
302
|
-
*/
|
|
303
|
-
promoteToPattern(errorId: string, evidenceCount: number, recurrenceCount?: number): {
|
|
304
|
-
id: string;
|
|
305
|
-
created: boolean;
|
|
306
|
-
} | null;
|
|
307
|
-
/**
|
|
308
|
-
* v0.2.0 (K2-026) — Feedback loop positive half (plan §B6.10 / D2-10).
|
|
309
|
-
*
|
|
310
|
-
* For each reflector-sourced error memory emitted during the given session
|
|
311
|
-
* whose fingerprint did NOT recur as a failing `tool_call` within the same
|
|
312
|
-
* project, bump `relevance_score` by `RELEVANCE_BUMP` (capped at
|
|
313
|
-
* `RELEVANCE_MAX`). Agent-saved memories are NEVER auto-boosted by this
|
|
314
|
-
* loop (anti-gaming guarantee, D2-06).
|
|
315
|
-
*
|
|
316
|
-
* Returns the number of memories that received a positive boost.
|
|
317
|
-
*/
|
|
318
|
-
boostPositiveReflectors(sessionId: string): number;
|
|
319
|
-
/**
|
|
320
|
-
* v0.3.0 (K3-013) — Feedback loop negative half.
|
|
321
|
-
*
|
|
322
|
-
* For each reflector-sourced error memory from this session whose
|
|
323
|
-
* fingerprint DID recur as a failing tool_call (the lesson didn't
|
|
324
|
-
* prevent the error), decrement `relevance_score` by `RELEVANCE_PENALTY`
|
|
325
|
-
* (down to zero) and increment `evidence_count` as a negative signal.
|
|
326
|
-
* Agent-saved memories are NEVER penalized.
|
|
327
|
-
*
|
|
328
|
-
* Returns the number of memories penalized.
|
|
329
|
-
*/
|
|
330
|
-
/**
|
|
331
|
-
* v0.3.0 fix — Mirror of the free function `countSupersedeCandidates`
|
|
332
|
-
* exposed as an instance method so `okf-import` (which holds a
|
|
333
|
-
* `MemoryService` reference but not the underlying `Store`) can count
|
|
334
|
-
* rows that `save()` will mark as superseded.
|
|
335
|
-
*/
|
|
336
|
-
countSupersedeCandidates(type: MemoryType, fingerprint: string | null | undefined, projectId: string | null): number;
|
|
337
|
-
penalizeRecurringReflectors(sessionId: string): number;
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* v0.3.0 fix — Extract `origin_call_id` from the memory metadata blob.
|
|
341
|
-
*
|
|
342
|
-
* Reflector stores the failing tool_call id in metadata.origin_call_id
|
|
343
|
-
* (when available) so the feedback loop can exclude the original call
|
|
344
|
-
* from the recurrence count. Returns null when metadata is absent,
|
|
345
|
-
* malformed, or lacks the field.
|
|
346
|
-
* // v1.1.0 (K11-003 / plan §5.5, D11-05) — single source for origin lookup;
|
|
347
|
-
* // InjectionLedger reuses this implementation (K11-013).
|
|
348
|
-
*/
|
|
349
|
-
export declare function readOriginCallId(metadata: string | null): string | null;
|
|
350
|
-
/**
|
|
351
|
-
* v0.3.0 fix — Count active memories that would be superseded by a new
|
|
352
|
-
* row with the given (type, fingerprint, projectId) tuple. Used by
|
|
353
|
-
* `okf-import` to populate `ImportResult.superseded` accurately.
|
|
354
|
-
*
|
|
355
|
-
* Matches the supersede logic in `save()`: only `decision` and `rule`
|
|
356
|
-
* types supersede prior rows with the same fingerprint. Returns 0 for
|
|
357
|
-
* any other type.
|
|
358
|
-
*/
|
|
359
|
-
export declare function countSupersedeCandidates(store: Store, type: MemoryType, fingerprint: string | null | undefined, projectId: string | null): number;
|
|
360
|
-
export {};
|