@jmtrin/opencode-kevin 1.2.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.
Files changed (141) hide show
  1. package/dist/plugin/index.d.ts +4 -3
  2. package/dist/plugin/index.js +122 -113
  3. package/dist/plugin/native.d.ts +2 -2
  4. package/dist/plugin/native.js +2 -2
  5. package/package.json +56 -68
  6. package/LICENSE +0 -21
  7. package/README.md +0 -605
  8. package/dist/migrations/001_initial.sql +0 -92
  9. package/dist/migrations/002_indexes.sql +0 -14
  10. package/dist/migrations/003_v02_signal.sql +0 -58
  11. package/dist/migrations/004_v03_knowledge.sql +0 -138
  12. package/dist/migrations/005_v04_signal.sql +0 -57
  13. package/dist/migrations/006_v05_glassbox.sql +0 -118
  14. package/dist/migrations/007_v06_pull.sql +0 -145
  15. package/dist/migrations/008_v07_truth.sql +0 -124
  16. package/dist/migrations/009_v08_team.sql +0 -100
  17. package/dist/migrations/010_v09_native.sql +0 -78
  18. package/dist/migrations/011_v10_proven.sql +0 -69
  19. package/dist/migrations/012_v11_drift.sql +0 -24
  20. package/dist/plugin/Archiver.d.ts +0 -42
  21. package/dist/plugin/Archiver.js +0 -83
  22. package/dist/plugin/ArtifactWriter.d.ts +0 -93
  23. package/dist/plugin/ArtifactWriter.js +0 -291
  24. package/dist/plugin/CausalChain.d.ts +0 -22
  25. package/dist/plugin/CausalChain.js +0 -197
  26. package/dist/plugin/ChatBridge.d.ts +0 -41
  27. package/dist/plugin/ChatBridge.js +0 -103
  28. package/dist/plugin/ConflictDetector.d.ts +0 -35
  29. package/dist/plugin/ConflictDetector.js +0 -260
  30. package/dist/plugin/ContextInjector.d.ts +0 -222
  31. package/dist/plugin/ContextInjector.js +0 -533
  32. package/dist/plugin/ConventionMiner.d.ts +0 -35
  33. package/dist/plugin/ConventionMiner.js +0 -242
  34. package/dist/plugin/Curator.d.ts +0 -116
  35. package/dist/plugin/Curator.js +0 -324
  36. package/dist/plugin/DashboardHtml.d.ts +0 -5
  37. package/dist/plugin/DashboardHtml.js +0 -180
  38. package/dist/plugin/Feedback.d.ts +0 -67
  39. package/dist/plugin/Feedback.js +0 -120
  40. package/dist/plugin/HookLiveness.d.ts +0 -88
  41. package/dist/plugin/HookLiveness.js +0 -322
  42. package/dist/plugin/InjectionLedger.d.ts +0 -98
  43. package/dist/plugin/InjectionLedger.js +0 -295
  44. package/dist/plugin/LessonFixer.d.ts +0 -44
  45. package/dist/plugin/LessonFixer.js +0 -45
  46. package/dist/plugin/Materializer.d.ts +0 -83
  47. package/dist/plugin/Materializer.js +0 -181
  48. package/dist/plugin/MemoryService.d.ts +0 -360
  49. package/dist/plugin/MemoryService.js +0 -1242
  50. package/dist/plugin/Migrate.d.ts +0 -17
  51. package/dist/plugin/Migrate.js +0 -271
  52. package/dist/plugin/PatternMiner.d.ts +0 -49
  53. package/dist/plugin/PatternMiner.js +0 -132
  54. package/dist/plugin/QualityGate.d.ts +0 -124
  55. package/dist/plugin/QualityGate.js +0 -119
  56. package/dist/plugin/Reflector.d.ts +0 -91
  57. package/dist/plugin/Reflector.js +0 -307
  58. package/dist/plugin/RepoIdentity.d.ts +0 -124
  59. package/dist/plugin/RepoIdentity.js +0 -300
  60. package/dist/plugin/RepoTruth.d.ts +0 -80
  61. package/dist/plugin/RepoTruth.js +0 -599
  62. package/dist/plugin/Retrospective.d.ts +0 -17
  63. package/dist/plugin/Retrospective.js +0 -216
  64. package/dist/plugin/SharedLayer.d.ts +0 -159
  65. package/dist/plugin/SharedLayer.js +0 -462
  66. package/dist/plugin/Store.d.ts +0 -29
  67. package/dist/plugin/Store.js +0 -50
  68. package/dist/plugin/ToolCallObserver.d.ts +0 -32
  69. package/dist/plugin/ToolCallObserver.js +0 -201
  70. package/dist/plugin/TuiActions.d.ts +0 -43
  71. package/dist/plugin/TuiActions.js +0 -181
  72. package/dist/plugin/TuiSnapshots.d.ts +0 -24
  73. package/dist/plugin/TuiSnapshots.js +0 -158
  74. package/dist/plugin/columns.d.ts +0 -11
  75. package/dist/plugin/columns.js +0 -54
  76. package/dist/plugin/confidence.d.ts +0 -8
  77. package/dist/plugin/confidence.js +0 -34
  78. package/dist/plugin/contract.d.ts +0 -54
  79. package/dist/plugin/contract.js +0 -386
  80. package/dist/plugin/diff.d.ts +0 -8
  81. package/dist/plugin/diff.js +0 -182
  82. package/dist/plugin/escape.d.ts +0 -39
  83. package/dist/plugin/escape.js +0 -60
  84. package/dist/plugin/fingerprint.d.ts +0 -27
  85. package/dist/plugin/fingerprint.js +0 -73
  86. package/dist/plugin/inferability.d.ts +0 -32
  87. package/dist/plugin/inferability.js +0 -88
  88. package/dist/plugin/kevin_approve.d.ts +0 -34
  89. package/dist/plugin/kevin_approve.js +0 -52
  90. package/dist/plugin/kevin_audit.d.ts +0 -229
  91. package/dist/plugin/kevin_audit.js +0 -631
  92. package/dist/plugin/kevin_bench.d.ts +0 -10
  93. package/dist/plugin/kevin_bench.js +0 -82
  94. package/dist/plugin/kevin_conflicts.d.ts +0 -9
  95. package/dist/plugin/kevin_conflicts.js +0 -50
  96. package/dist/plugin/kevin_contract.d.ts +0 -8
  97. package/dist/plugin/kevin_contract.js +0 -59
  98. package/dist/plugin/kevin_doctor.d.ts +0 -62
  99. package/dist/plugin/kevin_doctor.js +0 -196
  100. package/dist/plugin/kevin_facts.d.ts +0 -42
  101. package/dist/plugin/kevin_facts.js +0 -36
  102. package/dist/plugin/kevin_forget.d.ts +0 -33
  103. package/dist/plugin/kevin_forget.js +0 -260
  104. package/dist/plugin/kevin_native.d.ts +0 -29
  105. package/dist/plugin/kevin_native.js +0 -79
  106. package/dist/plugin/kevin_propose.d.ts +0 -23
  107. package/dist/plugin/kevin_propose.js +0 -14
  108. package/dist/plugin/kevin_publish.d.ts +0 -38
  109. package/dist/plugin/kevin_publish.js +0 -18
  110. package/dist/plugin/kevin_why.d.ts +0 -23
  111. package/dist/plugin/kevin_why.js +0 -111
  112. package/dist/plugin/memory-format.d.ts +0 -20
  113. package/dist/plugin/memory-format.js +0 -59
  114. package/dist/plugin/metrics.d.ts +0 -97
  115. package/dist/plugin/metrics.js +0 -288
  116. package/dist/plugin/okf-export.d.ts +0 -3
  117. package/dist/plugin/okf-export.js +0 -134
  118. package/dist/plugin/okf-import.d.ts +0 -76
  119. package/dist/plugin/okf-import.js +0 -271
  120. package/dist/plugin/okf.d.ts +0 -107
  121. package/dist/plugin/okf.js +0 -303
  122. package/dist/plugin/perf.d.ts +0 -35
  123. package/dist/plugin/perf.js +0 -174
  124. package/dist/plugin/query-tokenizer.d.ts +0 -13
  125. package/dist/plugin/query-tokenizer.js +0 -133
  126. package/dist/plugin/redact.d.ts +0 -2
  127. package/dist/plugin/redact.js +0 -18
  128. package/dist/plugin/replay-types.d.ts +0 -69
  129. package/dist/plugin/replay-types.js +0 -156
  130. package/dist/plugin/replay.d.ts +0 -36
  131. package/dist/plugin/replay.js +0 -202
  132. package/dist/plugin/sqlite-adapter.d.ts +0 -12
  133. package/dist/plugin/sqlite-adapter.js +0 -81
  134. package/dist/plugin/time-ms.d.ts +0 -1
  135. package/dist/plugin/time-ms.js +0 -16
  136. package/dist/plugin/tui-types.d.ts +0 -59
  137. package/dist/plugin/tui-types.js +0 -4
  138. package/dist/plugin/tui.d.ts +0 -18
  139. package/dist/plugin/tui.js +0 -198
  140. package/dist/plugin/uuid.d.ts +0 -1
  141. package/dist/plugin/uuid.js +0 -50
@@ -1,216 +0,0 @@
1
- import { mkdirSync, writeFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
- import { uuidv7 } from "./uuid.js";
5
- // v0.6.0 (K6-004 / plan §8.16) — exported so tests can assert that every
6
- // METRIC_KEYS entry has a label by iterating the keys (not by counting).
7
- export const METRIC_KEY_LABELS = {
8
- tokens_injected_pre_prompt: "Tokens inyectados (pre-prompt)",
9
- tokens_injected_compacting: "Tokens inyectados (compacting)",
10
- reflections_throttled: "Reflexiones throttled",
11
- duplicate_suppressions: "Supresiones por dedup",
12
- tool_calls_deduped: "Tool calls deduped",
13
- patterns_mined: "Patrones minados",
14
- // BUG-014 — v0.4.0 keys (K4-006/K4-008/K4-025) had no Spanish labels,
15
- // so the "## Métricas" section printed raw keys for them.
16
- injections_total: "Inyecciones totales",
17
- injections_effective: "Inyecciones efectivas",
18
- injections_ineffective: "Inyecciones ineficaces",
19
- patterns_promoted_new: "Patrones promovidos (nuevos)",
20
- patterns_causal: "Patrones causales",
21
- causal_links: "Enlaces causales",
22
- memories_superseded: "Memorias superadas",
23
- // v0.5.0 (K5-004 / plan §8.3) — the K5 metric keys need their own
24
- // Spanish labels; the e2e BUG-014 regression test forbids raw-key
25
- // fallback for any key in METRIC_KEYS.
26
- injections_inconclusive: "Inyecciones sin conclusión",
27
- injections_blocked_seen: "Inyecciones bloqueadas (ya vistas)",
28
- injections_blocked_weak: "Inyecciones bloqueadas (débiles)",
29
- injections_blocked_recurrence: "Inyecciones bloqueadas (recurrentes)",
30
- injections_blocked_stale: "Inyecciones bloqueadas (obsoletas)",
31
- injections_blocked_ignored: "Inyecciones bloqueadas (ignoradas)",
32
- feedback_positive_total: "Feedback positivo total",
33
- feedback_negative_total: "Feedback negativo total",
34
- memories_archived: "Memorias archivadas",
35
- // v0.6.0 (K6-004 / plan §8.16) — the K6 metric keys need their own
36
- // Spanish labels; the audit regression forbids raw-key fallback for any
37
- // key in METRIC_KEYS.
38
- proposals_created: "Propuestas de curación creadas",
39
- proposals_approved: "Propuestas aprobadas",
40
- proposals_rejected: "Propuestas rechazadas",
41
- artifact_writes_total: "Escrituras de artefacto (escritas)",
42
- artifact_writes_noop: "Escrituras de artefacto (sin cambios)",
43
- injections_blocked_confidence: "Inyecciones bloqueadas (confianza baja)",
44
- // v0.7.0 (K7-004 / plan §8.3) — the K7 metric keys need their own
45
- // Spanish labels; the audit regression forbids raw-key fallback for any
46
- // key in METRIC_KEYS.
47
- repo_facts_scanned: "Hechos del repositorio escaneados",
48
- memories_contradicted: "Memorias contradichas",
49
- conventions_mined: "Convenciones minadas",
50
- conflicts_detected: "Conflictos detectados",
51
- error_lessons_suppressed: "Lecciones de error suprimidas",
52
- // v0.8.0 (K8-003 / plan §8.16) — the K8 metric keys need their own
53
- // Spanish labels; the audit regression forbids raw-key fallback for any
54
- // key in METRIC_KEYS.
55
- shared_entries_total: "Entradas compartidas (totales)",
56
- shared_entries_imported: "Entradas compartidas importadas",
57
- shared_entries_exported: "Entradas compartidas exportadas",
58
- okf_merge_folds: "Fusiones OKF (folds)",
59
- rekey_events: "Re-keys de repositorio",
60
- injections_from_shared: "Inyecciones desde la capa compartida",
61
- // v0.9.0 (K9-003 / plan §8.16) — the K9 metric keys need their own
62
- // Spanish labels; the audit regression forbids raw-key fallback for any
63
- // key in METRIC_KEYS.
64
- hook_fires_total: "Disparos de hooks (totales)",
65
- hook_errors_total: "Errores de hooks",
66
- hooks_dead_total: "Hooks muertos",
67
- injections_suppressed_dead_hook: "Inyecciones suprimidas (hook muerto)",
68
- native_registrations_total: "Registros nativos (totales)",
69
- native_registration_failures: "Fallos de registro nativo",
70
- // v1.0.0 (K10-005 / plan §6) — the six keys seeded by migration 011 section 3.
71
- perf_samples_recorded: "Muestras de rendimiento registradas",
72
- perf_budget_breaches: "Brechas de presupuesto de rendimiento",
73
- dispose_fires_total: "Disparos de dispose (totales)",
74
- dispose_misses_total: "Misses de dispose",
75
- contract_digest_changes: "Cambios de digest de contrato",
76
- bench_runs_total: "Ejecuciones de benchmark (totales)",
77
- // v1.1.0 (K11-001 / plan §4) — drift metrics; labels required by BUG-014 regression.
78
- bench_regression_failures: "Fallos de regresion de benchmark",
79
- forget_requests_total: "Solicitudes de olvido totales",
80
- forget_tombstones_published: "Tombstones publicados por olvido",
81
- // v1.2.0 (K12-001 / plan §4) — surface metrics; labels required by BUG-014 regression.
82
- tui_snapshots_flushed: "Snapshots TUI generados",
83
- tui_actions_invoked: "Acciones TUI invocadas",
84
- };
85
- function originLabel(origin) {
86
- if (origin === "reflector")
87
- return "reflector";
88
- if (origin === "pattern")
89
- return "pattern";
90
- if (origin === "retrospective")
91
- return "retrospective";
92
- return "agent";
93
- }
94
- export class Retrospective {
95
- store;
96
- memoryService;
97
- retrospectivesDir;
98
- metrics;
99
- constructor(store, memoryService, options, metrics) {
100
- this.store = store;
101
- this.memoryService = memoryService;
102
- this.retrospectivesDir =
103
- options?.dir ?? join(homedir(), ".opencode-kevin", "retrospectives");
104
- this.metrics = metrics ?? null;
105
- }
106
- async generate(sessionId) {
107
- const existing = this.store
108
- .prepare("SELECT file_path FROM retrospectives WHERE session_id = ?")
109
- .get(sessionId);
110
- if (existing?.file_path)
111
- return existing.file_path;
112
- const counts = this.store
113
- .prepare(`SELECT
114
- SUM(CASE WHEN success = 1 THEN 1 ELSE 0 END) AS success_count,
115
- SUM(CASE WHEN success = 0 THEN 1 ELSE 0 END) AS failure_count,
116
- COUNT(*) AS total
117
- FROM tool_calls WHERE session_id = ?`)
118
- .get(sessionId);
119
- const successCount = counts?.success_count ?? 0;
120
- const failureCount = counts?.failure_count ?? 0;
121
- const total = counts?.total ?? 0;
122
- if (failureCount === 0)
123
- return null;
124
- const failedTools = this.store
125
- .prepare(`SELECT tool, args_summary, error_type
126
- FROM tool_calls
127
- WHERE session_id = ? AND success = 0
128
- ORDER BY ts ASC`)
129
- .all(sessionId);
130
- const lessons = this.store
131
- .prepare(`SELECT id, content, origin, fingerprint, project_id
132
- FROM memories
133
- WHERE type = 'error' AND source_session = ?
134
- ORDER BY created_at ASC`)
135
- .all(sessionId);
136
- const falsePositives = this.collectFalsePositives(sessionId, lessons);
137
- const metricsSnapshot = this.metrics?.snapshot() ?? null;
138
- const md = this.buildMarkdown(sessionId, total, successCount, failureCount, failedTools, lessons, falsePositives, metricsSnapshot);
139
- mkdirSync(this.retrospectivesDir, { recursive: true });
140
- const filePath = join(this.retrospectivesDir, `${sessionId}.md`);
141
- writeFileSync(filePath, md, "utf8");
142
- const id = uuidv7();
143
- this.store
144
- .prepare(`INSERT OR IGNORE INTO retrospectives
145
- (id, session_id, ts, failure_count, success_count, lessons_count, file_path, metadata)
146
- VALUES (?, ?, datetime('now'), ?, ?, ?, ?, ?)`)
147
- .run(id, sessionId, failureCount, successCount, lessons.length, filePath, null);
148
- return filePath;
149
- }
150
- collectFalsePositives(_sessionId, lessons) {
151
- const reflectorLessons = lessons.filter((l) => l.origin === "reflector" && l.fingerprint !== null);
152
- if (reflectorLessons.length === 0)
153
- return [];
154
- const result = [];
155
- for (const lesson of reflectorLessons) {
156
- const fp = lesson.fingerprint;
157
- const row = this.store
158
- .prepare(`SELECT COUNT(*) AS c FROM tool_calls
159
- WHERE COALESCE(error_fingerprint, fingerprint) = ?
160
- AND success = 0
161
- AND (project_id IS ? OR (project_id IS NULL AND ? IS NULL))`)
162
- .get(fp, lesson.project_id, lesson.project_id);
163
- const recurrenceCount = row?.c ?? 0;
164
- if (recurrenceCount > 0) {
165
- result.push({
166
- id: lesson.id,
167
- content: lesson.content,
168
- fingerprint: fp,
169
- project_id: lesson.project_id,
170
- recurrence_count: recurrenceCount,
171
- });
172
- }
173
- }
174
- return result;
175
- }
176
- buildMarkdown(sessionId, total, successCount, failureCount, failedTools, lessons, falsePositives, metricsSnapshot) {
177
- const lines = [];
178
- lines.push(`# Retrospective — Session ${sessionId}`);
179
- lines.push("");
180
- lines.push("## Resumen");
181
- lines.push(`- Tool calls: ${total} (${successCount} ok, ${failureCount} failed)`);
182
- lines.push("");
183
- lines.push("## Tools que fallaron");
184
- for (const ft of failedTools) {
185
- const et = ft.error_type ?? "unknown";
186
- const summary = ft.args_summary ?? "";
187
- lines.push(`- ${ft.tool} (${et}): ${summary}`);
188
- }
189
- lines.push("");
190
- lines.push("## Lecciones generadas");
191
- for (const lesson of lessons) {
192
- const label = originLabel(lesson.origin);
193
- lines.push(`- [${label}] ${lesson.content}`);
194
- }
195
- lines.push("");
196
- lines.push("## False-positive recap");
197
- if (falsePositives.length === 0) {
198
- lines.push("- Ninguna lección reflector-sourceada recurrrió en tool_calls.");
199
- }
200
- else {
201
- for (const fp of falsePositives) {
202
- lines.push(`- [reflector] ${fp.content} (fingerprint ${fp.fingerprint}, recurrencias: ${fp.recurrence_count})`);
203
- }
204
- }
205
- lines.push("");
206
- if (metricsSnapshot !== null) {
207
- lines.push("## Métricas");
208
- for (const [key, value] of Object.entries(metricsSnapshot)) {
209
- const label = METRIC_KEY_LABELS[key] ?? key;
210
- lines.push(`- ${label}: ${value}`);
211
- }
212
- lines.push("");
213
- }
214
- return lines.join("\n");
215
- }
216
- }
@@ -1,159 +0,0 @@
1
- import type { ArtifactWriter, WriteOutcome, WritePlan, WriteRequest } from "./ArtifactWriter.js";
2
- import { type ParseResult } from "./okf.js";
3
- export interface ImportReport {
4
- path: string;
5
- /** null when the file does not exist. */
6
- fileHash: string | null;
7
- parsed: number;
8
- folded: number;
9
- rejected: number;
10
- /** rows inserted or updated in shared_entries. */
11
- imported: number;
12
- /** shared memories retired by an incoming tombstone. */
13
- tombstoned: number;
14
- /** true when fileHash matches the last okf_imports row. */
15
- skipped: boolean;
16
- }
17
- /**
18
- * A planned (or applied) export (K8-020 / plan §5.5). The refusal is
19
- * carried by the write plan itself — `outcome: "refused"` with both
20
- * hashes audited — so a refused plan is indistinguishable from a
21
- * written one until `outcome` is read.
22
- */
23
- export interface ExportPlan {
24
- path: string;
25
- /** The whole-mode write request; applying re-plans through the single write funnel. */
26
- request: WriteRequest;
27
- /** The pure preview from planning time — diff and outcome, nothing written. */
28
- write: WritePlan;
29
- /** Entry ids in the merged corpus absent from the current file. */
30
- entriesAdded: number;
31
- /** Set by applyExport: the outcome of the actual write. */
32
- applied?: WriteOutcome;
33
- }
34
- export declare class SharedLayer {
35
- private readonly store;
36
- private readonly repoId;
37
- private readonly projectId;
38
- private readonly version;
39
- private readonly writer;
40
- constructor(deps: {
41
- store: StoreLike;
42
- repoId: string;
43
- projectId: string;
44
- version: string;
45
- writer: ArtifactWriter;
46
- });
47
- /**
48
- * The single whole-file (mode `whole`) construction site in
49
- * SharedLayer (K8-019 / K8-020, D8-08, asserted by
50
- * tests/unit/single_write_path.test.ts): the OKF file is written
51
- * through the ArtifactWriter's write funnel like every other file
52
- * Kevin owns — there is no second write path.
53
- */
54
- private wholeRequest;
55
- /**
56
- * Pure export planner (K8-020 / plan §5.5): reads the current file
57
- * and merges the given local memories' projections into the corpus,
58
- * producing a {@link WritePlan} — but writes nothing. Refusals are
59
- * audited like any other write: `after === before`, both hashes
60
- * recorded (D6-04). The refusal ladder, in the order the code
61
- * evaluates it — file-side refusals first (not_okf, version_ahead,
62
- * repo_mismatch), then candidate-side refusals in the loop order
63
- * (line_too_long, below_floor, not_curated, unknown_entry), then
64
- * too_many_entries and finally parse_damaged.
65
- */
66
- planExport(memoryIds: string[], path: string): ExportPlan;
67
- /**
68
- * Tombstone-append planner (K8-020 / D8-09): emits one `tombstone`
69
- * line per entry id, never deletes a line. The identifying triple is
70
- * reconstructed from the local projection (a memory with
71
- * `shared_entry_id`) so the line still passes parse's
72
- * tamper-evident entry_id check; an id with no local projection is
73
- * refused rather than emitting an invalid line.
74
- */
75
- planTombstone(entryIds: string[], path: string): ExportPlan;
76
- /**
77
- * v0.8.0 (BUG-003) — heal a stale `#repo` header after a rekey.
78
- * Rekey changes the scope the file is written under; a stale first
79
- * line would make every later planExport/planTombstone refuse with
80
- * repo_mismatch forever. Only the header line is replaced; the entry
81
- * bytes, line endings and trailing newline are preserved. The write
82
- * goes through the single funnel (D8-08). Returns true when the
83
- * header was rewritten. Never throws: a missing or unreadable file
84
- * is nothing to heal.
85
- */
86
- healHeader(path: string, newRepoId: string): boolean;
87
- /**
88
- * Apply a previously planned export: the write goes through the
89
- * single write funnel (re-planning against the file's current state),
90
- * and the outcome is recorded on the returned plan (K8-020).
91
- */
92
- applyExport(plan: ExportPlan): ExportPlan;
93
- /** Refusal plans are audited with both hashes (after === before). */
94
- private refused;
95
- /**
96
- * Convert the requested local memories into OKF candidates and run
97
- * the candidate-side refusals — line_too_long, below_floor,
98
- * not_curated — in plan §5.5 order.
99
- */
100
- private candidateEntries;
101
- private setting;
102
- private readWithFlag;
103
- /**
104
- * Read and parse the shared file. Total: a missing or unreadable
105
- * file yields an empty ParseResult, never a throw (D8-14).
106
- */
107
- read(path: string): ParseResult;
108
- /**
109
- * Idempotent and cheap to call (K8-016 / plan §5.5): hash the file
110
- * first and return `{ skipped: true }` when the hash matches the
111
- * most recent `okf_imports` row for this repo_id — the session.idle
112
- * path costs one readFileSync plus one hash on an unchanged
113
- * repository. A missing file is not an error: it returns
114
- * `fileHash: null`, `parsed: 0`, and still writes an audit row.
115
- */
116
- import(path: string): ImportReport;
117
- private writeImportRow;
118
- /**
119
- * Project every imported entry into memories (K8-017 / plan §5.5,
120
- * D8-10): a shared memory IS a memory, so getRelevant(), rankScore(),
121
- * the five gates, truth_penalty, ConflictDetector and every audit
122
- * rollup keep working unchanged.
123
- *
124
- * - assert entries: inserted once, never updated — re-importing an
125
- * unchanged file must not create duplicates, bump evidence_count or
126
- * move updated_at. `fingerprint` is deliberately left NULL: it is a
127
- * different identity dimension (plan §3.3) and conflating it with
128
- * `shared_entry_id` would make the v0.4.0 supersede path fire on
129
- * unrelated entries (K8-017 acceptance).
130
- * - tombstone entries: the ONE place in this codebase where the shared
131
- * layer may write memories.status. This is NOT a v0.7.0 Principle 24
132
- * violation: that principle forbids *contradiction* — a fuzzy
133
- * inference — from writing status, and a tombstone is the opposite:
134
- * an explicit, committed, human-reviewed decision that arrived
135
- * through a pull request (D8-09, plan §5.5).
136
- *
137
- * Returns the number of memories archived by tombstones.
138
- */
139
- private projectEntries;
140
- /**
141
- * Upsert every entry into shared_entries keyed on (repo_id,
142
- * entry_id) — the UNIQUE index from migration 009 makes this an
143
- * upsert rather than an append. `confidence` is the DERIVED value
144
- * (deriveConfidence), never a transported float (plan §5.3).
145
- * Returns the number of rows inserted or updated.
146
- */
147
- private upsertEntries;
148
- }
149
- /**
150
- * The Store surface SharedLayer needs. Kept structural so tests can
151
- * use the real Store without importing plugin internals.
152
- */
153
- export interface StoreLike {
154
- prepare(sql: string): {
155
- get(...params: unknown[]): unknown;
156
- all(...params: unknown[]): unknown[];
157
- run(...params: unknown[]): void;
158
- };
159
- }