@jmtrin/opencode-kevin 0.6.0 → 0.7.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.
Files changed (52) hide show
  1. package/README.md +582 -580
  2. package/dist/migrations/001_initial.sql +91 -91
  3. package/dist/migrations/003_v02_signal.sql +57 -57
  4. package/dist/migrations/004_v03_knowledge.sql +138 -138
  5. package/dist/migrations/005_v04_signal.sql +57 -57
  6. package/dist/migrations/006_v05_glassbox.sql +118 -118
  7. package/dist/migrations/007_v06_pull.sql +144 -144
  8. package/dist/migrations/008_v07_truth.sql +124 -0
  9. package/dist/plugin/ConflictDetector.d.ts +35 -0
  10. package/dist/plugin/ConflictDetector.js +283 -0
  11. package/dist/plugin/ConflictDetector.js.map +1 -0
  12. package/dist/plugin/ConventionMiner.d.ts +35 -0
  13. package/dist/plugin/ConventionMiner.js +243 -0
  14. package/dist/plugin/ConventionMiner.js.map +1 -0
  15. package/dist/plugin/Curator.js +45 -14
  16. package/dist/plugin/Curator.js.map +1 -1
  17. package/dist/plugin/MemoryService.d.ts +18 -0
  18. package/dist/plugin/MemoryService.js +92 -2
  19. package/dist/plugin/MemoryService.js.map +1 -1
  20. package/dist/plugin/Migrate.js +31 -2
  21. package/dist/plugin/Migrate.js.map +1 -1
  22. package/dist/plugin/Reflector.js +13 -0
  23. package/dist/plugin/Reflector.js.map +1 -1
  24. package/dist/plugin/RepoTruth.d.ts +80 -0
  25. package/dist/plugin/RepoTruth.js +600 -0
  26. package/dist/plugin/RepoTruth.js.map +1 -0
  27. package/dist/plugin/Retrospective.js +8 -0
  28. package/dist/plugin/Retrospective.js.map +1 -1
  29. package/dist/plugin/index.d.ts +7 -2
  30. package/dist/plugin/index.js +135 -2
  31. package/dist/plugin/index.js.map +1 -1
  32. package/dist/plugin/kevin_audit.d.ts +41 -1
  33. package/dist/plugin/kevin_audit.js +98 -3
  34. package/dist/plugin/kevin_audit.js.map +1 -1
  35. package/dist/plugin/kevin_conflicts.d.ts +9 -0
  36. package/dist/plugin/kevin_conflicts.js +51 -0
  37. package/dist/plugin/kevin_conflicts.js.map +1 -0
  38. package/dist/plugin/kevin_facts.d.ts +42 -0
  39. package/dist/plugin/kevin_facts.js +37 -0
  40. package/dist/plugin/kevin_facts.js.map +1 -0
  41. package/dist/plugin/metrics.d.ts +3 -3
  42. package/dist/plugin/metrics.js +12 -2
  43. package/dist/plugin/metrics.js.map +1 -1
  44. package/dist/plugin/replay-types.d.ts +2 -2
  45. package/migrations/001_initial.sql +91 -91
  46. package/migrations/003_v02_signal.sql +57 -57
  47. package/migrations/004_v03_knowledge.sql +138 -138
  48. package/migrations/005_v04_signal.sql +57 -57
  49. package/migrations/006_v05_glassbox.sql +118 -118
  50. package/migrations/007_v06_pull.sql +144 -144
  51. package/migrations/008_v07_truth.sql +124 -0
  52. package/package.json +3 -2
@@ -0,0 +1,243 @@
1
+ import { fingerprint } from "./fingerprint.js";
2
+ const DEFAULT_MIN_SUPPORT = 5;
3
+ export class ConventionMiner {
4
+ store;
5
+ memoryService;
6
+ projectId;
7
+ metrics;
8
+ constructor(store, memoryService, projectId, metrics) {
9
+ this.store = store;
10
+ this.memoryService = memoryService;
11
+ this.projectId = projectId;
12
+ this.metrics = metrics ?? null;
13
+ // `memoryService` is retained for emission (K7-012); mining itself is
14
+ // store-only.
15
+ void this.memoryService;
16
+ }
17
+ /** v0.7.0 (K7-010) — the `sequence` miner over successful tool_calls. */
18
+ mineSequence(minSupport = DEFAULT_MIN_SUPPORT) {
19
+ const rows = this.fetchToolCalls();
20
+ if (rows.length === 0)
21
+ return [];
22
+ // Group successful calls by session in execution order (ts ASC, then id
23
+ // as a deterministic tie-break).
24
+ const bySession = new Map();
25
+ const sorted = [...rows]
26
+ .filter((r) => r.success === 1)
27
+ .sort((a, b) => a.session_id === b.session_id
28
+ ? compareTs(a.ts, b.ts) || a.id.localeCompare(b.id)
29
+ : a.session_id.localeCompare(b.session_id));
30
+ for (const r of sorted) {
31
+ const list = bySession.get(r.session_id) ?? [];
32
+ list.push(r);
33
+ bySession.set(r.session_id, list);
34
+ }
35
+ const map = new Map();
36
+ const record = (key, statement, sessionId) => {
37
+ let cand = map.get(key);
38
+ if (!cand) {
39
+ cand = { key, statement, sessions: new Set() };
40
+ map.set(key, cand);
41
+ }
42
+ cand.sessions.add(sessionId);
43
+ };
44
+ for (const [sessionId, list] of bySession) {
45
+ if (list.length < 2)
46
+ continue;
47
+ for (let i = 0; i < list.length - 1; i++) {
48
+ const a = list[i];
49
+ const b = list[i + 1];
50
+ const aTok = tokenOf(a);
51
+ const bTok = tokenOf(b);
52
+ const key2 = `seq::${aTok}::${bTok}`;
53
+ const stmt2 = statementForSequence(aTok, bTok);
54
+ record(key2, stmt2, sessionId);
55
+ if (i + 2 < list.length) {
56
+ const c = list[i + 2];
57
+ const cTok = tokenOf(c);
58
+ const key3 = `seq::${aTok}::${bTok}::${cTok}`;
59
+ const stmt3 = statementForSequence3(aTok, bTok, cTok);
60
+ record(key3, stmt3, sessionId);
61
+ }
62
+ }
63
+ }
64
+ return this.materialize(map, minSupport, "sequence");
65
+ }
66
+ /** v0.7.0 (K7-011) — the `co_edit` miner over same-session file writes. */
67
+ mineCoEdit(minSupport = DEFAULT_MIN_SUPPORT) {
68
+ const rows = this.fetchToolCalls();
69
+ if (rows.length === 0)
70
+ return [];
71
+ // Successful file writes (broad: any success call mentioning a path) per
72
+ // session. Pairs span two different directory prefixes.
73
+ const bySession = new Map();
74
+ const sorted = [...rows]
75
+ .filter((r) => r.success === 1 && pathOf(r) !== null)
76
+ .sort((a, b) => a.session_id === b.session_id
77
+ ? compareTs(a.ts, b.ts) || a.id.localeCompare(b.id)
78
+ : a.session_id.localeCompare(b.session_id));
79
+ for (const r of sorted) {
80
+ const list = bySession.get(r.session_id) ?? [];
81
+ list.push(pathOf(r));
82
+ bySession.set(r.session_id, list);
83
+ }
84
+ const map = new Map();
85
+ const record = (key, statement, sessionId) => {
86
+ let cand = map.get(key);
87
+ if (!cand) {
88
+ cand = { key, statement, sessions: new Set() };
89
+ map.set(key, cand);
90
+ }
91
+ cand.sessions.add(sessionId);
92
+ };
93
+ for (const [sessionId, paths] of bySession) {
94
+ const unique = [...new Set(paths)];
95
+ if (unique.length < 2)
96
+ continue;
97
+ // Bounded enumeration: a large session must not explode into an
98
+ // O(n²) pair set. Cap distinct prefixes per session at 40.
99
+ const limit = Math.min(unique.length, 40);
100
+ for (let i = 0; i < limit; i++) {
101
+ const pA = unique[i];
102
+ for (let j = i + 1; j < limit; j++) {
103
+ const pB = unique[j];
104
+ const prefixA = dirOf(pA);
105
+ const prefixB = dirOf(pB);
106
+ if (prefixA === prefixB)
107
+ continue;
108
+ const [lo, hi] = prefixA < prefixB ? [prefixA, prefixB] : [prefixB, prefixA];
109
+ const key = `coedit::${lo}::${hi}`;
110
+ const stmt = `every new file under ${lo}/ is accompanied by a change under ${hi}/`;
111
+ record(key, stmt, sessionId);
112
+ }
113
+ }
114
+ }
115
+ return this.materialize(map, minSupport, "co_edit");
116
+ }
117
+ /** v0.7.0 (K7-012) — mine both kinds in one call. */
118
+ mine(minSupport = DEFAULT_MIN_SUPPORT) {
119
+ return [
120
+ ...this.mineSequence(minSupport),
121
+ ...this.mineCoEdit(minSupport),
122
+ ].sort((a, b) => a.statement.localeCompare(b.statement));
123
+ }
124
+ /**
125
+ * v0.7.0 (K7-012 / plan §5.4, D7-11) — emit mined(conventions) as `rule`
126
+ * memories. Returns the number of memories created or refreshed and
127
+ * increments `conventions_mined`. Runs on session.idle only, behind
128
+ * convention_mining_enabled. The fingerprint derives from the statement,
129
+ * so a re-mine of an unchanged convention collides and supersedes.
130
+ */
131
+ emit(conventions) {
132
+ let emitted = 0;
133
+ for (const c of conventions) {
134
+ const derivedFingerprint = fingerprint(c.statement, this.projectId);
135
+ // save() derives the fingerprint-based supersede/collision path for
136
+ // `rule` types automatically, so re-emitting an unchanged convention
137
+ // refreshes rather than duplicates.
138
+ this.memoryService.save({
139
+ type: "rule",
140
+ origin: "pattern",
141
+ scope: "project",
142
+ projectId: this.projectId,
143
+ fingerprint: derivedFingerprint,
144
+ content: c.statement,
145
+ relevanceScore: 0.5,
146
+ sourceTool: "ConventionMiner",
147
+ });
148
+ this.metrics?.incr("conventions_mined", 1);
149
+ emitted += 1;
150
+ }
151
+ return emitted;
152
+ }
153
+ materialize(map, minSupport, kind) {
154
+ const out = [];
155
+ for (const cand of map.values()) {
156
+ if (cand.sessions.size < minSupport)
157
+ continue;
158
+ out.push({
159
+ fingerprint: fingerprint(cand.statement, this.projectId),
160
+ statement: cand.statement,
161
+ support: cand.sessions.size,
162
+ kind,
163
+ });
164
+ }
165
+ // Deterministic order: lexicographic by statement (ties are resolved).
166
+ return out.sort((a, b) => a.statement.localeCompare(b.statement));
167
+ }
168
+ fetchToolCalls() {
169
+ const rows = this.store
170
+ .prepare(`SELECT id, session_id, ts, tool, success, args_summary
171
+ FROM tool_calls
172
+ WHERE project_id = ?
173
+ ORDER BY session_id, ts`)
174
+ .all(this.projectId);
175
+ return rows;
176
+ }
177
+ }
178
+ // ---------------------------------------------------------------------------
179
+ // Helpers — deterministic token/path extraction. Every value is normalized so
180
+ // the same underlying fact never collides via a JavaScript type difference.
181
+ // ---------------------------------------------------------------------------
182
+ /** `<tool>:<first path segment>` token for sequence mining. */
183
+ function tokenOf(r) {
184
+ const seg = firstPathSegment(r.args_summary);
185
+ return `${r.tool}:${seg}`;
186
+ }
187
+ function compareTs(a, b) {
188
+ return a.localeCompare(b);
189
+ }
190
+ /** First path segment of the first path-like argument, else "*". */
191
+ function firstPathSegment(argsSummary) {
192
+ const paths = pathSegments(argsSummary);
193
+ const first = paths[0];
194
+ if (!first)
195
+ return "*";
196
+ return first.split("/").filter(Boolean)[0] ?? "*";
197
+ }
198
+ /** All path segments found in args_summary, in appearance order. */
199
+ function pathSegments(argsSummary) {
200
+ const text = argsSummary ?? "";
201
+ const found = [];
202
+ // Try JSON object string values first.
203
+ try {
204
+ const parsed = JSON.parse(text);
205
+ if (typeof parsed === "object" &&
206
+ parsed !== null &&
207
+ !Array.isArray(parsed)) {
208
+ for (const v of Object.values(parsed)) {
209
+ if (typeof v === "string" && /\//.test(v) && !v.includes(" ")) {
210
+ found.push(v.replace(/\\/g, "/").toLowerCase().trim());
211
+ }
212
+ }
213
+ }
214
+ }
215
+ catch {
216
+ /* not JSON */
217
+ }
218
+ if (found.length === 0) {
219
+ const m = text.match(/[^\s"':,=]*\/[^\s"':,=]*/g);
220
+ for (const tok of m ?? []) {
221
+ found.push(tok.replace(/\\/g, "/").toLowerCase().trim());
222
+ }
223
+ }
224
+ return found;
225
+ }
226
+ /** Directory of a path (drop the filename). `src/routes/user.ts` → `src/routes`. */
227
+ function dirOf(p) {
228
+ const segs = p.split("/").filter(Boolean);
229
+ segs.pop();
230
+ return segs.join("/") || "*";
231
+ }
232
+ /** A deterministic path for a call if it is a file write/read on disk. */
233
+ function pathOf(r) {
234
+ const segs = pathSegments(r.args_summary);
235
+ return segs[0] ?? null;
236
+ }
237
+ function statementForSequence(a, b) {
238
+ return `every ${a} is immediately followed by ${b}`;
239
+ }
240
+ function statementForSequence3(a, b, c) {
241
+ return `every ${a} is followed by ${b} and then ${c}`;
242
+ }
243
+ //# sourceMappingURL=ConventionMiner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConventionMiner.js","sourceRoot":"","sources":["../../plugin/ConventionMiner.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { homedir } from "node:os";
2
2
  import { join } from "node:path";
3
3
  import { MARKER_BEGIN, MARKER_END, } from "./ArtifactWriter.js";
4
4
  import { computeConfidence } from "./confidence.js";
5
+ import { normalize } from "./fingerprint.js";
5
6
  import { uuidv7 } from "./uuid.js";
6
7
  const MAX_CANDIDATE_LINES = 20;
7
8
  const MAX_CANDIDATE_CHARS = 4000;
@@ -127,20 +128,27 @@ export class Curator {
127
128
  const candidates = this.candidates();
128
129
  if (candidates.length === 0)
129
130
  return [];
130
- const newBlock = this.renderBlock(candidates);
131
- const currentBlock = extractBlock(writer.plan(targetPath, newBlock).before);
132
- // Merge: keep the current block verbatim and append only lines that
133
- // are not already in it. Without the dedup, a block the user (or an
134
- // approval) already pasted would be proposed doubled.
135
- const currentLines = currentBlock === "" ? [] : currentBlock.split(/\r?\n/);
136
- const newLines = newBlock
137
- .split("\n")
138
- .filter((l) => l !== "" && !currentLines.includes(l));
139
- const mergedBlock = currentBlock === ""
140
- ? newBlock
141
- : newLines.length === 0
142
- ? currentBlock
131
+ const readPlan = writer.plan(targetPath, this.renderBlock(candidates));
132
+ const currentBlock = extractBlock(readPlan.before);
133
+ // v0.7.0 (K7-013 / plan §4, D6-09) de-duplicate against the WHOLE
134
+ // file, not just the region between Kevin's markers. A convention the
135
+ // user already wrote in their own words in their own section must not
136
+ // be proposed back to them. The comparison is over the same normalized
137
+ // tokens the fingerprint uses — no new similarity metric (D7-11).
138
+ const entireFile = wholeFileLines(readPlan.before);
139
+ const freshCandidates = candidates.filter((candidate) => !entireFile.has(normalizeBullet(candidate.line)));
140
+ if (freshCandidates.length === 0 && currentBlock === "")
141
+ return [];
142
+ const newBlock = this.renderBlock(freshCandidates);
143
+ const newLines = newBlock.split("\n").filter((l) => l !== "");
144
+ const mergedBlock = newLines.length === 0
145
+ ? currentBlock
146
+ : currentBlock === ""
147
+ ? `${newLines.join("\n")}\n`
143
148
  : `${currentBlock}${currentBlock.endsWith("\n") ? "" : "\n"}${newLines.join("\n")}\n`;
149
+ // v0.7.0 (K7-013) — nothing new to propose: every candidate is already
150
+ // in the file (inside or outside the markers). A vacuous proposal would
151
+ // be noise; return none.
144
152
  const plan = writer.plan(targetPath, mergedBlock);
145
153
  const prior = this.store
146
154
  .prepare(`SELECT id FROM curation_proposals
@@ -150,7 +158,7 @@ export class Curator {
150
158
  for (const row of prior) {
151
159
  this.transition(row.id, "supersede");
152
160
  }
153
- const memoryIds = candidates.map((c) => c.memoryId);
161
+ const memoryIds = freshCandidates.map((c) => c.memoryId);
154
162
  const id = uuidv7();
155
163
  this.store
156
164
  .prepare(`INSERT INTO curation_proposals
@@ -249,4 +257,27 @@ function extractBlock(before) {
249
257
  .replace(/^\r?\n/, "")
250
258
  .replace(/\r?\n$/, "");
251
259
  }
260
+ /**
261
+ * v0.7.0 (K7-013 / plan §4) — the normalized set of bullet statements across
262
+ * the WHOLE file, including any the user wrote outside Kevin's markers. Only
263
+ * markdown bullets (`- ...`) are considered: prose and the marker lines are
264
+ * never a candidate to propose back.
265
+ */
266
+ function wholeFileLines(before) {
267
+ const set = new Set();
268
+ for (const line of before.split(/\r?\n/)) {
269
+ if (line.trim().startsWith("-")) {
270
+ set.add(normalizeBullet(line));
271
+ }
272
+ }
273
+ return set;
274
+ }
275
+ /** Normalize a rendered bullet for de-duplication — strip the marker prefix. */
276
+ function normalizeBullet(line) {
277
+ const statement = line
278
+ .replace(/^\s*-\s+/, "")
279
+ .trim()
280
+ .replace(/\s+\((?:verified|feedback)[^)]*\)\s*$/i, "");
281
+ return normalize(statement);
282
+ }
252
283
  //# sourceMappingURL=Curator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Curator.js","sourceRoot":"","sources":["../../plugin/Curator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Curator.js","sourceRoot":"","sources":["../../plugin/Curator.ts"],"names":[],"mappings":"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"}
@@ -54,6 +54,13 @@ export interface Memory {
54
54
  /** v0.5.0 (K5-010 / plan §5.3, D5-02) — human judgement counters,
55
55
  * folded into confidence by computeConfidence. */
56
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;
61
+ /** v0.7.0 (K7-008 / plan §5.3) — when the memory was first contradicted
62
+ * (ISO/sqlite time). Null when never contradicted. */
63
+ contradictedAt?: string | null;
57
64
  }
58
65
  export interface SaveInput {
59
66
  type: MemoryType;
@@ -150,6 +157,7 @@ export declare class MemoryService {
150
157
  private _hasRecurrenceColumn;
151
158
  private hasIgnoredColumn;
152
159
  private hasCuratedColumn;
160
+ private hasTruthColumns;
153
161
  save(input: SaveInput): string;
154
162
  /**
155
163
  * v0.6.0 (K6-011 / plan §5.4) — mark memories as curated. Batch in a
@@ -167,6 +175,16 @@ export declare class MemoryService {
167
175
  */
168
176
  getByFingerprint(fingerprint: string, type?: MemoryType): Memory | null;
169
177
  update(id: string, fields: Partial<Memory>): void;
178
+ /**
179
+ * v0.7.0 (K7-008 / plan §5.3, D7-03) — apply a bounded truth penalty.
180
+ * Clamps `penalty` to [0, 0.5], writes `truth_penalty` and `contradicted_at`,
181
+ * and increments `memories_contradicted` ONLY when the value moves from 0
182
+ * to non-zero (a second penalty on the same memory does not re-count).
183
+ * It NEVER writes `status` — contradiction de-ranks; it never deletes
184
+ * (Principle 24). `reason` is the human-readable explanation surfaced by
185
+ * `kevin_facts`; the caller persists it in the `memory_conflicts` row.
186
+ */
187
+ applyTruthPenalty(memoryId: string, penalty: number, reason: string): void;
170
188
  delete(id: string): void;
171
189
  /** v0.1.x behavior — returns full `Memory` rows. */
172
190
  query(input: QueryInput & {
@@ -112,6 +112,25 @@ function hasCuratedColumn(store) {
112
112
  return false;
113
113
  }
114
114
  }
115
+ /**
116
+ * v0.7.0 (K7-008 / migration 008) — cached per-store probe for the 008-only
117
+ * `truth_penalty` column (pre-008 DBs must not reference it). Same
118
+ * positive-only caching discipline as `curated` (K6-001a).
119
+ */
120
+ const truthColumnsCache = new WeakMap();
121
+ function hasTruthColumns(store) {
122
+ const cached = truthColumnsCache.get(store);
123
+ if (cached === true)
124
+ return true;
125
+ try {
126
+ store.prepare("SELECT truth_penalty FROM memories LIMIT 1").get();
127
+ truthColumnsCache.set(store, true);
128
+ return true;
129
+ }
130
+ catch {
131
+ return false;
132
+ }
133
+ }
115
134
  /**
116
135
  * v0.5.0 (K5-009 / plan §5.3) — the 006-only columns are appended when the
117
136
  * migration has run (same probe as the `ignored = 0` retrieval filter).
@@ -122,9 +141,12 @@ function rowSelect(store) {
122
141
  ? `${MEMORY_ROW_SELECT}, ignored, superseded_by,
123
142
  feedback_positive, feedback_negative`
124
143
  : MEMORY_ROW_SELECT;
125
- return hasCuratedColumn(store)
144
+ const withCurated = hasCuratedColumn(store)
126
145
  ? `${base}, curated, curated_at, inferable`
127
146
  : base;
147
+ return hasTruthColumns(store)
148
+ ? `${withCurated}, truth_penalty, contradicted_at`
149
+ : withCurated;
128
150
  }
129
151
  function mapRow(row, score) {
130
152
  const mem = {
@@ -171,6 +193,11 @@ function mapRow(row, score) {
171
193
  : row.inferable === 0
172
194
  ? "non_inferable"
173
195
  : null,
196
+ // v0.7.0 (K7-008 / plan §5.3, D7-03) — de-ranking state. `truth_penalty`
197
+ // defaults to 0 (a pre-008 row without the column reads 0), and
198
+ // `contradicted_at` is null until the first contradiction.
199
+ truthPenalty: row.truth_penalty ?? 0,
200
+ contradictedAt: row.contradicted_at ?? null,
174
201
  };
175
202
  if (score !== undefined) {
176
203
  if (!mem.metadata)
@@ -248,6 +275,12 @@ export class MemoryService {
248
275
  hasCuratedColumn() {
249
276
  return hasCuratedColumn(this.store);
250
277
  }
278
+ // v0.7.0 (K7-008 / plan §5.3) — cached column probe for pre-008 DBs
279
+ // (which lack `truth_penalty`); the retrieval SELECTs must not reference
280
+ // the column there, or rankScore cannot see the de-ranking factor.
281
+ hasTruthColumns() {
282
+ return hasTruthColumns(this.store);
283
+ }
251
284
  save(input) {
252
285
  const scope = input.scope ?? "project";
253
286
  const relevanceScore = input.relevanceScore ?? 0.5;
@@ -493,6 +526,48 @@ export class MemoryService {
493
526
  .prepare(`UPDATE memories SET ${cols.join(", ")} WHERE id = ?`)
494
527
  .run(...vals);
495
528
  }
529
+ /**
530
+ * v0.7.0 (K7-008 / plan §5.3, D7-03) — apply a bounded truth penalty.
531
+ * Clamps `penalty` to [0, 0.5], writes `truth_penalty` and `contradicted_at`,
532
+ * and increments `memories_contradicted` ONLY when the value moves from 0
533
+ * to non-zero (a second penalty on the same memory does not re-count).
534
+ * It NEVER writes `status` — contradiction de-ranks; it never deletes
535
+ * (Principle 24). `reason` is the human-readable explanation surfaced by
536
+ * `kevin_facts`; the caller persists it in the `memory_conflicts` row.
537
+ */
538
+ applyTruthPenalty(memoryId, penalty, reason) {
539
+ const clamped = Math.max(0, Math.min(0.5, penalty));
540
+ const row = this.store
541
+ .prepare("SELECT truth_penalty FROM memories WHERE id = ?")
542
+ .get(memoryId);
543
+ if (!row)
544
+ return;
545
+ const current = Number(row.truth_penalty ?? 0);
546
+ const hadPenalty = current > 0;
547
+ const nowHasPenalty = clamped > 0;
548
+ // `reason` is accepted for interface parity with plan §5.3; the caller
549
+ // records it in the conflict row, not here.
550
+ void reason;
551
+ const stamp = nowHasPenalty ? new Date().toISOString() : null;
552
+ this.store
553
+ .prepare(`UPDATE memories
554
+ SET truth_penalty = ?,
555
+ contradicted_at = CASE
556
+ WHEN ? IS NULL THEN NULL
557
+ ELSE COALESCE(contradicted_at, ?)
558
+ END
559
+ WHERE id = ?`)
560
+ .run(clamped, stamp, stamp, memoryId);
561
+ if (nowHasPenalty && !hadPenalty) {
562
+ this.metrics?.incr("memories_contradicted", 1);
563
+ }
564
+ // v0.7.0 (K7-008 / D7-03) — recovery: a penalty lifted back to 0
565
+ // (the repo no longer contradicts the memory) mirrors the counter,
566
+ // which the 008 post-apply hook re-derives as COUNT(truth_penalty > 0).
567
+ if (!nowHasPenalty && hadPenalty) {
568
+ this.metrics?.incr("memories_contradicted", -1);
569
+ }
570
+ }
496
571
  delete(id) {
497
572
  this.store.prepare("DELETE FROM memories WHERE id = ?").run(id);
498
573
  }
@@ -589,6 +664,10 @@ export class MemoryService {
589
664
  if (this.hasCuratedColumn()) {
590
665
  sql += ", curated, curated_at, inferable";
591
666
  }
667
+ // v0.7.0 (K7-008) — 008-only truth columns, appended when present.
668
+ if (this.hasTruthColumns()) {
669
+ sql += ", truth_penalty, contradicted_at";
670
+ }
592
671
  sql += `
593
672
  FROM memories
594
673
  WHERE (expires_at IS NULL OR expires_at > datetime('now'))`;
@@ -628,6 +707,11 @@ export class MemoryService {
628
707
  if (this.hasCuratedColumn()) {
629
708
  sql += ", m.curated, m.curated_at, m.inferable";
630
709
  }
710
+ // v0.7.0 (K7-008) — 008-only truth columns, appended when present so
711
+ // rankScore can apply the de-ranking factor in retrieval.
712
+ if (this.hasTruthColumns()) {
713
+ sql += ", m.truth_penalty, m.contradicted_at";
714
+ }
631
715
  sql += `,
632
716
  bm25(memories_fts) AS score
633
717
  FROM memories_fts
@@ -1023,7 +1107,13 @@ function rankScore(mem, nowMs, deterministic) {
1023
1107
  // the recency factor at 1.0 so ordering depends only on content
1024
1108
  // relevance and origin boost, never on the wall clock.
1025
1109
  const recencyDecay = deterministic ? 1 : RECENCY_DECAY_PER_DAY ** ageDays;
1026
- return base * originBoost(mem) * recencyDecay;
1110
+ // v0.7.0 (K7-008 / plan §5.3, D7-04) trailing multiplicative factor,
1111
+ // applied AFTER the existing chain. At the default (truthPenalty = 0) the
1112
+ // expression reduces to the v0.6.0 one exactly. rankScore returns a
1113
+ // NEGATIVE score for BM25 rows (more negative = better), so scaling by a
1114
+ // factor in (0.5, 1] moves a row toward zero — i.e. toward worse — which
1115
+ // is the intended de-ranking direction.
1116
+ return base * originBoost(mem) * recencyDecay * (1 - (mem.truthPenalty ?? 0));
1027
1117
  }
1028
1118
  function rankCompare(a, b, nowMs, deterministic) {
1029
1119
  const ra = rankScore(a, nowMs, deterministic);