@jmtrin/opencode-kevin 0.2.0 → 0.4.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 (58) hide show
  1. package/README.md +108 -35
  2. package/dist/migrations/004_v03_knowledge.sql +138 -0
  3. package/dist/migrations/005_v04_signal.sql +57 -0
  4. package/dist/plugin/CausalChain.d.ts +22 -0
  5. package/dist/plugin/CausalChain.js +179 -0
  6. package/dist/plugin/CausalChain.js.map +1 -0
  7. package/dist/plugin/ContextInjector.d.ts +89 -1
  8. package/dist/plugin/ContextInjector.js +276 -71
  9. package/dist/plugin/ContextInjector.js.map +1 -1
  10. package/dist/plugin/InjectionLedger.d.ts +85 -0
  11. package/dist/plugin/InjectionLedger.js +189 -0
  12. package/dist/plugin/InjectionLedger.js.map +1 -0
  13. package/dist/plugin/LessonFixer.d.ts +44 -0
  14. package/dist/plugin/LessonFixer.js +46 -0
  15. package/dist/plugin/LessonFixer.js.map +1 -0
  16. package/dist/plugin/MemoryService.d.ts +123 -2
  17. package/dist/plugin/MemoryService.js +439 -31
  18. package/dist/plugin/MemoryService.js.map +1 -1
  19. package/dist/plugin/Migrate.js +22 -0
  20. package/dist/plugin/Migrate.js.map +1 -1
  21. package/dist/plugin/QualityGate.d.ts +71 -0
  22. package/dist/plugin/QualityGate.js +78 -0
  23. package/dist/plugin/QualityGate.js.map +1 -0
  24. package/dist/plugin/Reflector.d.ts +33 -0
  25. package/dist/plugin/Reflector.js +126 -32
  26. package/dist/plugin/Reflector.js.map +1 -1
  27. package/dist/plugin/Retrospective.js +10 -1
  28. package/dist/plugin/Retrospective.js.map +1 -1
  29. package/dist/plugin/ToolCallObserver.d.ts +1 -0
  30. package/dist/plugin/ToolCallObserver.js +16 -9
  31. package/dist/plugin/ToolCallObserver.js.map +1 -1
  32. package/dist/plugin/confidence.d.ts +6 -0
  33. package/dist/plugin/confidence.js +23 -0
  34. package/dist/plugin/confidence.js.map +1 -0
  35. package/dist/plugin/index.d.ts +5 -0
  36. package/dist/plugin/index.js +336 -44
  37. package/dist/plugin/index.js.map +1 -1
  38. package/dist/plugin/kevin_why.d.ts +23 -0
  39. package/dist/plugin/kevin_why.js +108 -0
  40. package/dist/plugin/kevin_why.js.map +1 -0
  41. package/dist/plugin/memory-format.d.ts +12 -0
  42. package/dist/plugin/memory-format.js +45 -5
  43. package/dist/plugin/memory-format.js.map +1 -1
  44. package/dist/plugin/metrics.d.ts +7 -1
  45. package/dist/plugin/metrics.js +19 -0
  46. package/dist/plugin/metrics.js.map +1 -1
  47. package/dist/plugin/okf-export.d.ts +3 -0
  48. package/dist/plugin/okf-export.js +127 -0
  49. package/dist/plugin/okf-export.js.map +1 -0
  50. package/dist/plugin/okf-import.d.ts +76 -0
  51. package/dist/plugin/okf-import.js +272 -0
  52. package/dist/plugin/okf-import.js.map +1 -0
  53. package/dist/plugin/query-tokenizer.d.ts +13 -0
  54. package/dist/plugin/query-tokenizer.js +86 -0
  55. package/dist/plugin/query-tokenizer.js.map +1 -0
  56. package/migrations/004_v03_knowledge.sql +138 -0
  57. package/migrations/005_v04_signal.sql +57 -0
  58. package/package.json +1 -1
@@ -0,0 +1,108 @@
1
+ import { TS_CODE_RULES } from "./Reflector.js";
2
+ import { computeConfidence } from "./confidence.js";
3
+ import { toMatchClause, tokenizeQuery } from "./query-tokenizer.js";
4
+ export function kevinWhy(store, query) {
5
+ // v0.3.0 fix (bug #7) — the old code wrapped the WHOLE query in a
6
+ // single quoted phrase, so it only matched the exact full-string
7
+ // sequence. Tokenize like MemoryService.queryRelevant: quote each
8
+ // word (escaping inner quotes) and AND them together, so partial or
9
+ // multi-word queries still hit the FTS index.
10
+ const tokens = tokenizeQuery(query);
11
+ if (tokens.length === 0)
12
+ return null;
13
+ const match = toMatchClause(tokens, " AND ");
14
+ // Best-effort (v0.4.0): DBs pre-005 lack `recurrence_count`; degrade
15
+ // to "no explanation" instead of crashing the calling session.
16
+ let patternRows;
17
+ try {
18
+ patternRows = store
19
+ .prepare(`SELECT m.id, m.content, m.fingerprint, m.evidence_count,
20
+ m.recurrence_count, m.fix_args, m.last_verified_at, m.created_at
21
+ FROM memories_fts
22
+ JOIN memories m ON m.rowid = memories_fts.rowid
23
+ WHERE memories_fts MATCH ?
24
+ AND m.type = 'pattern'
25
+ AND m.origin IN ('causal', 'pattern')
26
+ AND m.status = 'active'
27
+ ORDER BY m.evidence_count DESC, m.created_at DESC
28
+ LIMIT 1`)
29
+ .all(match);
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ if (patternRows.length === 0)
35
+ return null;
36
+ const pattern = patternRows[0];
37
+ const fp = pattern.fingerprint;
38
+ // v0.4.0 (K4-010) — two-sided confidence shared with promoteToPattern.
39
+ const confidence = computeConfidence(pattern.evidence_count ?? 0, pattern.recurrence_count ?? 0);
40
+ // BUG-007 — the trace is built from the error-memory sessions below;
41
+ // the legacy `traceRows` probe (executed but unused, with a
42
+ // never-matching `tc.fingerprint LIKE '%<8-hex>%'` branch against the
43
+ // tool|args|success hash) was deleted.
44
+ const trace = [];
45
+ const errorSessions = store
46
+ .prepare(`SELECT DISTINCT source_session, fingerprint, created_at
47
+ FROM memories
48
+ WHERE fingerprint = ? AND type = 'error' AND origin = 'reflector'
49
+ ORDER BY created_at ASC`)
50
+ .all(fp);
51
+ for (const err of errorSessions) {
52
+ trace.push({
53
+ event: "failure",
54
+ fingerprint: err.fingerprint,
55
+ session: err.source_session ?? "unknown",
56
+ ts: err.created_at,
57
+ });
58
+ const fixRow = store
59
+ .prepare(`SELECT session_id, ts FROM tool_calls
60
+ WHERE fix_for_fingerprint = ?
61
+ AND session_id = ?
62
+ ORDER BY ts ASC LIMIT 1`)
63
+ .get(fp, err.source_session);
64
+ if (fixRow) {
65
+ trace.push({
66
+ event: "fix",
67
+ fingerprint: fp,
68
+ session: fixRow.session_id,
69
+ ts: fixRow.ts,
70
+ });
71
+ }
72
+ }
73
+ const relatedRules = [];
74
+ const tsCodeMatch = query.match(/TS(\d{4,5})/);
75
+ if (tsCodeMatch) {
76
+ const hint = TS_CODE_RULES[tsCodeMatch[1]] ?? `review TS${tsCodeMatch[1]}`;
77
+ relatedRules.push(hint);
78
+ }
79
+ // v0.4.0 (K4-020) — honest summary (plan §5.3 / D4-11): with
80
+ // recurrences the pattern is NOT consistently resolved, so the
81
+ // phrasing reports the real success ratio ("resolved in N of M
82
+ // attempts") instead of "consistently resolved".
83
+ const evidenceCount = pattern.evidence_count ?? 0;
84
+ const recurrence = pattern.recurrence_count ?? 0;
85
+ let summary;
86
+ if (recurrence > 0) {
87
+ const fix = pattern.fix_args
88
+ ? `fixing ${pattern.fix_args}`
89
+ : `fixing ${relatedRules.length > 0
90
+ ? relatedRules.join(", ")
91
+ : "the underlying issue"}`;
92
+ summary = `When tool fails with ${query}: resolved in ${evidenceCount} of ${evidenceCount + recurrence} attempts by ${fix}.`;
93
+ }
94
+ else {
95
+ summary = `When tool fails with ${query}: ${confidence >= 0.7 ? "consistently" : "often"} resolved by fixing ${relatedRules.length > 0 ? relatedRules.join(", ") : "the underlying issue"}.`;
96
+ }
97
+ return {
98
+ summary,
99
+ confidence,
100
+ evidence_count: evidenceCount,
101
+ recurrence_count: recurrence,
102
+ fix_args: pattern.fix_args ?? null,
103
+ last_verified: pattern.last_verified_at ?? null,
104
+ trace,
105
+ related_rules: relatedRules,
106
+ };
107
+ }
108
+ //# sourceMappingURL=kevin_why.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kevin_why.js","sourceRoot":"","sources":["../../plugin/kevin_why.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,18 @@ export interface MemoryBlockItem {
3
3
  type: string;
4
4
  content: string;
5
5
  protect?: boolean;
6
+ /** v0.4.0 (K4-023) — weak lesson admitted in debug mode: the row is
7
+ * rendered with a `(low confidence)` marker line. */
8
+ weak?: boolean;
6
9
  }
7
10
  export declare function escapeInjectedText(text: string): string;
11
+ /**
12
+ * v0.4.0 (K4-012) — progressive disclosure for injection: a short
13
+ * snippet row instead of the full body. Row = `id:` line + `[type]`
14
+ * prefix + the first 2 non-empty lines of content, wrapped in
15
+ * `<protect>` unless the memory opted out (`protect: false`). The
16
+ * full body stays available via `kevin_get`.
17
+ */
18
+ export declare function formatSnippet(m: MemoryBlockItem): string;
8
19
  export declare function formatMemories(memories: MemoryBlockItem[], tag: "context" | "memory"): string;
20
+ export declare function formatMemorySnippets(memories: MemoryBlockItem[], tag: "context" | "memory"): string;
@@ -4,17 +4,57 @@ export function escapeInjectedText(text) {
4
4
  .replace(/</g, "&lt;")
5
5
  .replace(/>/g, "&gt;");
6
6
  }
7
+ function typePrefix(m) {
8
+ const t = escapeInjectedText(String(m.type));
9
+ return m.weak ? `[${t}] (low confidence)` : `[${t}]`;
10
+ }
7
11
  function formatRow(m) {
8
12
  const idLine = m.id ? `id: ${escapeInjectedText(m.id)}\n` : "";
9
- const body = `${idLine}[${escapeInjectedText(String(m.type))}] ${escapeInjectedText(m.content)}`;
13
+ const body = `${idLine}${typePrefix(m)} ${escapeInjectedText(m.content)}`;
10
14
  return m.protect === false ? body : `<protect>\n${body}\n</protect>`;
11
15
  }
12
- export function formatMemories(memories, tag) {
13
- if (memories.length === 0)
14
- return "";
15
- const body = memories.map(formatRow).join("\n");
16
+ /**
17
+ * v0.4.0 (K4-012) — progressive disclosure for injection: a short
18
+ * snippet row instead of the full body. Row = `id:` line + `[type]`
19
+ * prefix + the first 2 non-empty lines of content, wrapped in
20
+ * `<protect>` unless the memory opted out (`protect: false`). The
21
+ * full body stays available via `kevin_get`.
22
+ */
23
+ export function formatSnippet(m) {
24
+ const lines = m.content
25
+ .split(/\r?\n/)
26
+ .map((l) => l.trim())
27
+ .filter((l) => l.length > 0)
28
+ .slice(0, 2);
29
+ // v0.4.0 (K4-025) — a pattern's `Fixed by:` line is the highest-value
30
+ // payload (plan §5.4 / D4-07); surface it in the snippet even though
31
+ // it sits below the 2-line cut. Only patterns carry the line.
32
+ const fixLine = lines
33
+ .map((l) => l)
34
+ .concat(m.content
35
+ .split(/\r?\n/)
36
+ .map((l) => l.trim())
37
+ .filter((l) => l.startsWith("Fixed by:")))[2];
38
+ const idLine = m.id ? `id: ${escapeInjectedText(m.id)}\n` : "";
39
+ const bodyLines = fixLine ? [...lines, fixLine] : lines;
40
+ const body = bodyLines.length === 0
41
+ ? ""
42
+ : `${idLine}${typePrefix(m)} ${escapeInjectedText(bodyLines.join("\n"))}`;
43
+ return m.protect === false ? body : `<protect>\n${body}\n</protect>`;
44
+ }
45
+ function wrapBlock(body, tag) {
16
46
  return tag === "context"
17
47
  ? `<kevin-context>Lecciones relevantes:\n${body}\n</kevin-context>`
18
48
  : `<kevin-memory>\n${body}\n</kevin-memory>`;
19
49
  }
50
+ export function formatMemories(memories, tag) {
51
+ if (memories.length === 0)
52
+ return "";
53
+ return wrapBlock(memories.map(formatRow).join("\n"), tag);
54
+ }
55
+ export function formatMemorySnippets(memories, tag) {
56
+ if (memories.length === 0)
57
+ return "";
58
+ return wrapBlock(memories.map(formatSnippet).join("\n"), tag);
59
+ }
20
60
  //# sourceMappingURL=memory-format.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-format.js","sourceRoot":"","sources":["../../plugin/memory-format.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC9C,OAAO,IAAI;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,CAAkB;IACpC,MAAM,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG,GAAG,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,kBAAkB,CAClF,CAAC,CAAC,OAAO,CACT,EAAE,CAAC;IACJ,OAAO,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc,IAAI,cAAc,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,QAA2B,EAC3B,GAAyB;IAEzB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,GAAG,KAAK,SAAS;QACvB,CAAC,CAAC,yCAAyC,IAAI,oBAAoB;QACnE,CAAC,CAAC,mBAAmB,IAAI,mBAAmB,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"memory-format.js","sourceRoot":"","sources":["../../plugin/memory-format.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import type { Store } from "./Store.js";
6
6
  * underlying table is empty (e.g., before 003 is applied, on a fresh
7
7
  * :memory: test DB, or after a manual wipe).
8
8
  */
9
- export declare const METRIC_KEYS: readonly ["tokens_injected_pre_prompt", "tokens_injected_compacting", "reflections_throttled", "duplicate_suppressions", "tool_calls_deduped", "patterns_mined"];
9
+ export declare const METRIC_KEYS: readonly ["tokens_injected_pre_prompt", "tokens_injected_compacting", "reflections_throttled", "duplicate_suppressions", "tool_calls_deduped", "patterns_mined", "patterns_causal", "causal_links", "memories_superseded", "injections_total", "injections_effective", "injections_ineffective", "patterns_promoted_new"];
10
10
  export type MetricKey = (typeof METRIC_KEYS)[number];
11
11
  /**
12
12
  * Cheap token estimate used when bumping the `tokens_injected_*` counters.
@@ -44,6 +44,12 @@ export declare class Metrics {
44
44
  * Returns the cached value for a single key. Does NOT flush.
45
45
  */
46
46
  get(key: MetricKey): number;
47
+ /**
48
+ * v0.4.0 (K4-008): injection precision = effective / total settled
49
+ * injections. 0 when the ledger has no entries yet (no division by zero).
50
+ * Computed from the cached counters — does NOT flush.
51
+ */
52
+ precisionRate(): number;
47
53
  /** True iff a debounced flush is scheduled. Useful for tests. */
48
54
  isFlushScheduled(): boolean;
49
55
  /**
@@ -12,6 +12,13 @@ export const METRIC_KEYS = [
12
12
  "duplicate_suppressions",
13
13
  "tool_calls_deduped",
14
14
  "patterns_mined",
15
+ "patterns_causal",
16
+ "causal_links",
17
+ "memories_superseded",
18
+ "injections_total",
19
+ "injections_effective",
20
+ "injections_ineffective",
21
+ "patterns_promoted_new",
15
22
  ];
16
23
  const DEFAULT_FLUSH_MS = 1000;
17
24
  function zeroCache() {
@@ -95,6 +102,18 @@ export class Metrics {
95
102
  get(key) {
96
103
  return this.cache.get(key) ?? 0;
97
104
  }
105
+ /**
106
+ * v0.4.0 (K4-008): injection precision = effective / total settled
107
+ * injections. 0 when the ledger has no entries yet (no division by zero).
108
+ * Computed from the cached counters — does NOT flush.
109
+ */
110
+ precisionRate() {
111
+ const total = this.cache.get("injections_total") ?? 0;
112
+ if (total <= 0)
113
+ return 0;
114
+ const effective = this.cache.get("injections_effective") ?? 0;
115
+ return Math.min(1, effective / total);
116
+ }
98
117
  /** True iff a debounced flush is scheduled. Useful for tests. */
99
118
  isFlushScheduled() {
100
119
  return this.flushTimer !== null;
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../plugin/metrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../plugin/metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Store } from "./Store.js";
2
+ export declare function exportOkf(store: Store): string;
3
+ export declare function exportMarkdown(store: Store): string;
@@ -0,0 +1,127 @@
1
+ import { computeConfidence } from "./confidence.js";
2
+ const EXPORT_TYPES = new Set(["decision", "rule", "pattern"]);
3
+ function formatTimestamp(ts) {
4
+ try {
5
+ // SQLite `datetime('now')` is UTC without a zone suffix; parse as
6
+ // UTC so a round-trip never shifts the value by the local offset.
7
+ const iso = ts.includes("T") ? ts : `${ts.replace(" ", "T")}Z`;
8
+ return new Date(iso).toISOString().replace("T", " ").slice(0, 19);
9
+ }
10
+ catch {
11
+ return ts;
12
+ }
13
+ }
14
+ /**
15
+ * BUG-008 — select export rows including `recurrence_count` (the v0.4.0
16
+ * demotion signal, column from migration 005). DBs that predate 005 have
17
+ * no such column; the SELECT is retried without it and recurrences
18
+ * degrade to 0 (legacy confidence formula applies — see below).
19
+ */
20
+ function selectExportRows(store) {
21
+ try {
22
+ return {
23
+ hasRecurrence: true,
24
+ rows: store
25
+ .prepare(`SELECT id, type, content, scope, relevance_score, fingerprint,
26
+ evidence_count, recurrence_count, last_verified_at, status,
27
+ source_tool, source_session, created_at, updated_at
28
+ FROM memories
29
+ WHERE status = 'active'
30
+ ORDER BY type, created_at DESC`)
31
+ .all(),
32
+ };
33
+ }
34
+ catch {
35
+ const legacy = store
36
+ .prepare(`SELECT id, type, content, scope, relevance_score, fingerprint,
37
+ evidence_count, last_verified_at, status,
38
+ source_tool, source_session, created_at, updated_at
39
+ FROM memories
40
+ WHERE status = 'active'
41
+ ORDER BY type, created_at DESC`)
42
+ .all();
43
+ return {
44
+ hasRecurrence: false,
45
+ rows: legacy.map((r) => ({ ...r, recurrence_count: 0 })),
46
+ };
47
+ }
48
+ }
49
+ /**
50
+ * BUG-008 — the exported confidence must match the two-sided v0.4.0
51
+ * formula (K4-010), demoting lessons with recurrences. Pre-005 DBs (no
52
+ * `recurrence_count` column) keep the legacy one-sided formula.
53
+ */
54
+ function exportConfidence(row, hasRecurrence) {
55
+ const confidence = hasRecurrence
56
+ ? computeConfidence(row.evidence_count, row.recurrence_count)
57
+ : Math.min(1, 0.5 + 0.1 * row.evidence_count);
58
+ return confidence.toFixed(2);
59
+ }
60
+ export function exportOkf(store) {
61
+ const { rows: allRows, hasRecurrence } = selectExportRows(store);
62
+ const filtered = allRows.filter((r) => EXPORT_TYPES.has(r.type));
63
+ if (filtered.length === 0)
64
+ return "<!-- No exportable memories found. -->\n";
65
+ const blocks = [];
66
+ for (const m of filtered) {
67
+ const fm = [];
68
+ fm.push("---");
69
+ fm.push(`id: ${m.id}`);
70
+ fm.push(`type: ${m.type}`);
71
+ fm.push(`confidence: ${exportConfidence(m, hasRecurrence)}`);
72
+ fm.push(`evidence_count: ${m.evidence_count}`);
73
+ if (m.recurrence_count > 0) {
74
+ fm.push(`recurrence_count: ${m.recurrence_count}`);
75
+ }
76
+ if (m.last_verified_at) {
77
+ fm.push(`last_verified_at: ${formatTimestamp(m.last_verified_at)}`);
78
+ }
79
+ if (m.fingerprint) {
80
+ fm.push(`fingerprint: ${m.fingerprint}`);
81
+ }
82
+ fm.push(`created: ${formatTimestamp(m.created_at)}`);
83
+ fm.push(`scope: ${m.scope}`);
84
+ fm.push("---");
85
+ fm.push("");
86
+ fm.push(m.content);
87
+ blocks.push(fm.join("\n"));
88
+ }
89
+ return `${blocks.join("\n\n")}\n`;
90
+ }
91
+ export function exportMarkdown(store) {
92
+ const { rows: allRows, hasRecurrence } = selectExportRows(store);
93
+ const filtered = allRows.filter((r) => EXPORT_TYPES.has(r.type));
94
+ if (filtered.length === 0)
95
+ return "# Kevin Knowledge Export\n\n_No exportable memories found._\n";
96
+ const lines = [];
97
+ lines.push("# Kevin Knowledge Export");
98
+ lines.push("");
99
+ lines.push(`Exported: ${new Date().toISOString().replace("T", " ").slice(0, 19)}`);
100
+ lines.push(`Total entries: ${filtered.length}`);
101
+ lines.push("");
102
+ for (const m of filtered) {
103
+ lines.push(`## ${m.type}: \`${m.fingerprint ?? m.id.slice(0, 8)}\``);
104
+ lines.push("");
105
+ lines.push(`- **ID:** \`${m.id}\``);
106
+ lines.push(`- **Confidence:** ${exportConfidence(m, hasRecurrence)}`);
107
+ lines.push(`- **Evidence count:** ${m.evidence_count}`);
108
+ if (m.recurrence_count > 0) {
109
+ lines.push(`- **Recurrence count:** ${m.recurrence_count}`);
110
+ }
111
+ if (m.last_verified_at) {
112
+ lines.push(`- **Last verified:** ${formatTimestamp(m.last_verified_at)}`);
113
+ }
114
+ if (m.fingerprint) {
115
+ lines.push(`- **Fingerprint:** \`${m.fingerprint}\``);
116
+ }
117
+ lines.push(`- **Scope:** ${m.scope}`);
118
+ lines.push(`- **Created:** ${formatTimestamp(m.created_at)}`);
119
+ lines.push("");
120
+ lines.push(m.content);
121
+ lines.push("");
122
+ lines.push("---");
123
+ lines.push("");
124
+ }
125
+ return lines.join("\n");
126
+ }
127
+ //# sourceMappingURL=okf-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"okf-export.js","sourceRoot":"","sources":["../../plugin/okf-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { MemoryService } from "./MemoryService.js";
2
+ /**
3
+ * v0.3.0 fix — A single parsed bundle entry. `evidence_count` and
4
+ * `last_verified_at` are preserved across round-trips (export → import)
5
+ * so causal confidence is not lost when knowledge is shared between
6
+ * projects. v0.4.0 (BUG-008) — `recurrence_count` too, so the two-sided
7
+ * v0.4.0 confidence demotion survives the round-trip.
8
+ */
9
+ export interface ParsedEntry {
10
+ id: string;
11
+ type: string;
12
+ content: string;
13
+ fingerprint: string | null;
14
+ evidence_count: number;
15
+ /** v0.4.0 (BUG-008) — recurrence demotion, 0 when absent. */
16
+ recurrence_count: number;
17
+ last_verified_at: string | null;
18
+ }
19
+ /**
20
+ * v0.3.0 fix — Clean state-machine parser for the frontmatter bundle
21
+ * format produced by `okf-export.ts::exportOkf`. Each entry is:
22
+ *
23
+ * ---
24
+ * id: <uuid>
25
+ * type: <decision|rule|pattern>
26
+ * confidence: 0.70
27
+ * evidence_count: 2
28
+ * last_verified_at: 2026-07-25 12:34:56
29
+ * fingerprint: <hex>
30
+ * created: 2026-07-25 12:00:00
31
+ * scope: project
32
+ * ---
33
+ *
34
+ * <content body, may span multiple lines, may include `---` lines
35
+ * within — the body terminator is the NEXT top-level `---` followed
36
+ * by an `id:` line, or EOF>
37
+ *
38
+ * The previous implementation only ever flagged `inFm = true` once and
39
+ * never reset `contentStarted` between entries, so 2..N entries were
40
+ * silently dropped (bug #1). This rewrite handles arbitrary numbers of
41
+ * consecutive frontmatter sections.
42
+ */
43
+ export declare function parseMarkdownBundle(text: string): ParsedEntry[];
44
+ /**
45
+ * v0.3.0 fix — Fallback parser for the markdown-style `##` heading
46
+ * format produced by `okf-export.ts::exportMarkdown`. The previous
47
+ * version extracted `fingerprint: null` for every entry (regex was
48
+ * pinned to 16 hex chars while actual fingerprints are variable
49
+ * length) and contaminated `content` with the heading line and
50
+ * metadata bullets. This version cleanly separates metadata bullets
51
+ * (looking for `**ID:**`, `**Fingerprint:**`, `**Evidence count:**`,
52
+ * `**Last verified:**`, `**Scope:**` prefixes) from the content
53
+ * body, which starts after the first blank line following the bullet
54
+ * block and runs until the trailing `---` separator (or EOF).
55
+ */
56
+ export declare function parseMarkdownHeadings(text: string): ParsedEntry[];
57
+ export interface ImportResult {
58
+ imported: number;
59
+ superseded: number;
60
+ }
61
+ /**
62
+ * v0.3.0 fix — Ingest a bundle (frontmatter OR markdown) into the
63
+ * local SQLite store as `context` memories with `origin='imported'`.
64
+ *
65
+ * Fixes over the v0.3.0 baseline:
66
+ * * Multi-entry bundles now produce N imports instead of N=1 — the
67
+ * parser bug is closed.
68
+ * * `ParsedEntry.evidence_count` and `last_verified_at` are
69
+ * threaded through so causal confidence survives a round-trip.
70
+ * * `ImportResult.superseded` is populated using
71
+ * `countSupersedeCandidates`, which mirrors the supersede logic
72
+ * in `MemoryService.save()`. Previously it was hard-coded to 0.
73
+ * * Generated ids use `uuidv7()` (the project's id generator)
74
+ * instead of `crypto.randomUUID()` for consistency.
75
+ */
76
+ export declare function importOkf(bundle: string, memoryService: MemoryService): ImportResult;