@jmtrin/opencode-kevin 0.7.0 → 0.9.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 (70) hide show
  1. package/README.md +254 -12
  2. package/dist/migrations/009_v08_team.sql +100 -0
  3. package/dist/migrations/010_v09_native.sql +78 -0
  4. package/dist/plugin/ArtifactWriter.d.ts +28 -0
  5. package/dist/plugin/ArtifactWriter.js +35 -2
  6. package/dist/plugin/ArtifactWriter.js.map +1 -1
  7. package/dist/plugin/ContextInjector.d.ts +9 -0
  8. package/dist/plugin/ContextInjector.js +14 -3
  9. package/dist/plugin/ContextInjector.js.map +1 -1
  10. package/dist/plugin/Curator.d.ts +22 -2
  11. package/dist/plugin/Curator.js +56 -14
  12. package/dist/plugin/Curator.js.map +1 -1
  13. package/dist/plugin/HookLiveness.d.ts +81 -0
  14. package/dist/plugin/HookLiveness.js +324 -0
  15. package/dist/plugin/HookLiveness.js.map +1 -0
  16. package/dist/plugin/InjectionLedger.d.ts +6 -0
  17. package/dist/plugin/InjectionLedger.js +6 -0
  18. package/dist/plugin/InjectionLedger.js.map +1 -1
  19. package/dist/plugin/Materializer.d.ts +29 -5
  20. package/dist/plugin/Materializer.js +48 -16
  21. package/dist/plugin/Materializer.js.map +1 -1
  22. package/dist/plugin/MemoryService.d.ts +34 -5
  23. package/dist/plugin/MemoryService.js +215 -7
  24. package/dist/plugin/MemoryService.js.map +1 -1
  25. package/dist/plugin/Migrate.d.ts +1 -0
  26. package/dist/plugin/Migrate.js +74 -3
  27. package/dist/plugin/Migrate.js.map +1 -1
  28. package/dist/plugin/RepoIdentity.d.ts +124 -0
  29. package/dist/plugin/RepoIdentity.js +301 -0
  30. package/dist/plugin/RepoIdentity.js.map +1 -0
  31. package/dist/plugin/Retrospective.js +18 -0
  32. package/dist/plugin/Retrospective.js.map +1 -1
  33. package/dist/plugin/SharedLayer.d.ts +159 -0
  34. package/dist/plugin/SharedLayer.js +463 -0
  35. package/dist/plugin/SharedLayer.js.map +1 -0
  36. package/dist/plugin/host.d.ts +70 -0
  37. package/dist/plugin/host.js +251 -0
  38. package/dist/plugin/host.js.map +1 -0
  39. package/dist/plugin/index.d.ts +30 -1
  40. package/dist/plugin/index.js +582 -12
  41. package/dist/plugin/index.js.map +1 -1
  42. package/dist/plugin/kevin_approve.js +7 -4
  43. package/dist/plugin/kevin_approve.js.map +1 -1
  44. package/dist/plugin/kevin_audit.d.ts +48 -1
  45. package/dist/plugin/kevin_audit.js +179 -3
  46. package/dist/plugin/kevin_audit.js.map +1 -1
  47. package/dist/plugin/kevin_doctor.d.ts +57 -0
  48. package/dist/plugin/kevin_doctor.js +168 -0
  49. package/dist/plugin/kevin_doctor.js.map +1 -0
  50. package/dist/plugin/kevin_native.d.ts +29 -0
  51. package/dist/plugin/kevin_native.js +80 -0
  52. package/dist/plugin/kevin_native.js.map +1 -0
  53. package/dist/plugin/metrics.d.ts +1 -1
  54. package/dist/plugin/metrics.js +9 -0
  55. package/dist/plugin/metrics.js.map +1 -1
  56. package/dist/plugin/native.d.ts +92 -0
  57. package/dist/plugin/native.js +191 -0
  58. package/dist/plugin/native.js.map +1 -0
  59. package/dist/plugin/okf-export.d.ts +2 -2
  60. package/dist/plugin/okf-export.js +15 -7
  61. package/dist/plugin/okf-export.js.map +1 -1
  62. package/dist/plugin/okf.d.ts +107 -0
  63. package/dist/plugin/okf.js +304 -0
  64. package/dist/plugin/okf.js.map +1 -0
  65. package/dist/plugin/replay-types.d.ts +29 -287
  66. package/dist/plugin/replay-types.js +145 -53
  67. package/dist/plugin/replay-types.js.map +1 -1
  68. package/migrations/009_v08_team.sql +100 -0
  69. package/migrations/010_v09_native.sql +78 -0
  70. package/package.json +2 -3
@@ -0,0 +1,463 @@
1
+ // ============================================================
2
+ // Kevin 0.8.0 — SharedLayer (F3, K8-016 … K8-020)
3
+ // ============================================================
4
+ // The two-directional bridge between the OKF file and the local
5
+ // store. Import may retire a memory — but only on an explicit
6
+ // committed tombstone. Export may write a file — but only through
7
+ // the one write path that has existed since v0.6.0 (D8-08).
8
+ //
9
+ // Every statement filters on `repo_id` (D8-02): there is no
10
+ // unscoped read or write of `shared_entries` or `okf_imports`.
11
+ // ============================================================
12
+ import { readFileSync } from "node:fs";
13
+ import { computeConfidence } from "./confidence.js";
14
+ import { fnv1a64 } from "./fingerprint.js";
15
+ import { MAX_ENTRIES, MAX_LINE_BYTES, OKF_VERSION, canonicalize, computeEntryId, deriveConfidence, merge, parse, serialize, } from "./okf.js";
16
+ import { uuidv7 } from "./uuid.js";
17
+ /**
18
+ * Project a local memory into its OKF candidate (K8-020): the
19
+ * identifying triple (type, statement, scope) determines the
20
+ * entry_id, so a re-export of the same memory is byte-identical.
21
+ * created_at is normalized from SQLite's "YYYY-MM-DD HH:MM:SS" to
22
+ * the file's ISO-8601 form, keeping join()'s min from flipping
23
+ * formats across exports.
24
+ */
25
+ function memoryToEntry(row) {
26
+ return {
27
+ entry_id: computeEntryId(row.type, row.content, row.scope),
28
+ type: row.type,
29
+ statement: row.content,
30
+ scope: row.scope,
31
+ evidence: row.evidence_count ?? 0,
32
+ recurrence: row.recurrence_count ?? 0,
33
+ origin: row.origin ?? "pattern",
34
+ author_hash: null,
35
+ op: "assert",
36
+ created_at: `${(row.created_at ?? "").replace(" ", "T")}Z`,
37
+ supersedes: null,
38
+ };
39
+ }
40
+ export class SharedLayer {
41
+ store;
42
+ repoId;
43
+ projectId;
44
+ version;
45
+ writer;
46
+ constructor(deps) {
47
+ this.store = deps.store;
48
+ this.repoId = deps.repoId;
49
+ this.projectId = deps.projectId;
50
+ this.version = deps.version;
51
+ this.writer = deps.writer;
52
+ }
53
+ /**
54
+ * The single whole-file (mode `whole`) construction site in
55
+ * SharedLayer (K8-019 / K8-020, D8-08, asserted by
56
+ * tests/unit/single_write_path.test.ts): the OKF file is written
57
+ * through the ArtifactWriter's write funnel like every other file
58
+ * Kevin owns — there is no second write path.
59
+ */
60
+ wholeRequest(path, content, refusal) {
61
+ return {
62
+ path,
63
+ mode: "whole",
64
+ content,
65
+ ...(refusal !== undefined ? { refusal } : {}),
66
+ };
67
+ }
68
+ /**
69
+ * Pure export planner (K8-020 / plan §5.5): reads the current file
70
+ * and merges the given local memories' projections into the corpus,
71
+ * producing a {@link WritePlan} — but writes nothing. Refusals are
72
+ * audited like any other write: `after === before`, both hashes
73
+ * recorded (D6-04). The refusal ladder, in the order the code
74
+ * evaluates it — file-side refusals first (not_okf, version_ahead,
75
+ * repo_mismatch), then candidate-side refusals in the loop order
76
+ * (line_too_long, below_floor, not_curated, unknown_entry), then
77
+ * too_many_entries and finally parse_damaged.
78
+ */
79
+ planExport(memoryIds, path) {
80
+ const { exists, parsed } = this.readWithFlag(path);
81
+ if (exists && parsed.version === 0) {
82
+ return this.refused(path, "not_okf");
83
+ }
84
+ if (exists && parsed.version > OKF_VERSION) {
85
+ return this.refused(path, "version_ahead");
86
+ }
87
+ if (parsed.repoId !== null && parsed.repoId !== this.repoId) {
88
+ return this.refused(path, "repo_mismatch");
89
+ }
90
+ const candidates = this.candidateEntries(memoryIds);
91
+ if (candidates.refusal !== null) {
92
+ return this.refused(path, candidates.refusal);
93
+ }
94
+ const merged = merge(parsed.entries, candidates.entries);
95
+ if (merged.length > MAX_ENTRIES) {
96
+ return this.refused(path, "too_many_entries");
97
+ }
98
+ if (exists && parsed.rejected.length > 0) {
99
+ return this.refused(path, "parse_damaged");
100
+ }
101
+ const content = serialize(merged, this.repoId, this.version);
102
+ const existing = new Set(parsed.entries.map((e) => e.entry_id));
103
+ const entriesAdded = merged.filter((e) => !existing.has(e.entry_id)).length;
104
+ const request = this.wholeRequest(path, content);
105
+ return { path, request, write: this.writer.plan(request), entriesAdded };
106
+ }
107
+ /**
108
+ * Tombstone-append planner (K8-020 / D8-09): emits one `tombstone`
109
+ * line per entry id, never deletes a line. The identifying triple is
110
+ * reconstructed from the local projection (a memory with
111
+ * `shared_entry_id`) so the line still passes parse's
112
+ * tamper-evident entry_id check; an id with no local projection is
113
+ * refused rather than emitting an invalid line.
114
+ */
115
+ planTombstone(entryIds, path) {
116
+ const { exists, parsed } = this.readWithFlag(path);
117
+ if (exists && parsed.version === 0) {
118
+ return this.refused(path, "not_okf");
119
+ }
120
+ if (exists && parsed.version > OKF_VERSION) {
121
+ return this.refused(path, "version_ahead");
122
+ }
123
+ if (parsed.repoId !== null && parsed.repoId !== this.repoId) {
124
+ return this.refused(path, "repo_mismatch");
125
+ }
126
+ if (exists && parsed.rejected.length > 0) {
127
+ return this.refused(path, "parse_damaged");
128
+ }
129
+ if (entryIds.length === 0) {
130
+ const content = serialize(parsed.entries, this.repoId, this.version);
131
+ const request = this.wholeRequest(path, content);
132
+ return {
133
+ path,
134
+ request,
135
+ write: this.writer.plan(request),
136
+ entriesAdded: 0,
137
+ };
138
+ }
139
+ const unique = [...new Set(entryIds)];
140
+ const placeholders = unique.map(() => "?").join(", ");
141
+ const rows = this.store
142
+ .prepare(`SELECT type, content, scope, evidence_count, recurrence_count,
143
+ origin, created_at
144
+ FROM memories
145
+ WHERE shared_entry_id IN (${placeholders}) AND repo_id = ?`)
146
+ .all(...unique, this.repoId);
147
+ if (rows.length !== entryIds.length) {
148
+ return this.refused(path, "unknown_entry");
149
+ }
150
+ const tombstones = rows.map((row) => ({
151
+ ...memoryToEntry(row),
152
+ op: "tombstone",
153
+ }));
154
+ const merged = merge(parsed.entries, tombstones);
155
+ if (merged.length > MAX_ENTRIES) {
156
+ return this.refused(path, "too_many_entries");
157
+ }
158
+ const content = serialize(merged, this.repoId, this.version);
159
+ const existing = new Set(parsed.entries.map((e) => e.entry_id));
160
+ const entriesAdded = merged.filter((e) => !existing.has(e.entry_id)).length;
161
+ const request = this.wholeRequest(path, content);
162
+ return { path, request, write: this.writer.plan(request), entriesAdded };
163
+ }
164
+ /**
165
+ * v0.8.0 (BUG-003) — heal a stale `#repo` header after a rekey.
166
+ * Rekey changes the scope the file is written under; a stale first
167
+ * line would make every later planExport/planTombstone refuse with
168
+ * repo_mismatch forever. Only the header line is replaced; the entry
169
+ * bytes, line endings and trailing newline are preserved. The write
170
+ * goes through the single funnel (D8-08). Returns true when the
171
+ * header was rewritten. Never throws: a missing or unreadable file
172
+ * is nothing to heal.
173
+ */
174
+ healHeader(path, newRepoId) {
175
+ let text;
176
+ try {
177
+ text = readFileSync(path, "utf8");
178
+ }
179
+ catch {
180
+ return false;
181
+ }
182
+ const eol = text.includes("\r\n") ? "\r\n" : "\n";
183
+ const lines = text.split(/\r?\n/);
184
+ const header = `#repo ${newRepoId}`;
185
+ const repoLine = lines.findIndex((l) => l.startsWith("#repo "));
186
+ if (repoLine === -1 || lines[repoLine] === header)
187
+ return false;
188
+ lines[repoLine] = header;
189
+ this.writer.write(this.wholeRequest(path, lines.join(eol)));
190
+ return true;
191
+ }
192
+ /**
193
+ * Apply a previously planned export: the write goes through the
194
+ * single write funnel (re-planning against the file's current state),
195
+ * and the outcome is recorded on the returned plan (K8-020).
196
+ */
197
+ applyExport(plan) {
198
+ return { ...plan, applied: this.writer.write(plan.request) };
199
+ }
200
+ /** Refusal plans are audited with both hashes (after === before). */
201
+ refused(path, reason) {
202
+ const request = this.wholeRequest(path, "", reason);
203
+ return {
204
+ path,
205
+ request,
206
+ write: this.writer.plan(request),
207
+ entriesAdded: 0,
208
+ };
209
+ }
210
+ /**
211
+ * Convert the requested local memories into OKF candidates and run
212
+ * the candidate-side refusals — line_too_long, below_floor,
213
+ * not_curated — in plan §5.5 order.
214
+ */
215
+ candidateEntries(memoryIds) {
216
+ if (memoryIds.length === 0) {
217
+ return { entries: [], refusal: null };
218
+ }
219
+ const placeholders = memoryIds.map(() => "?").join(", ");
220
+ const rows = this.store
221
+ .prepare(`SELECT type, content, scope, evidence_count, recurrence_count,
222
+ origin, created_at, curated
223
+ FROM memories WHERE id IN (${placeholders}) AND repo_id = ?`)
224
+ .all(...memoryIds, this.repoId);
225
+ // v0.8.0 (BUG-006) — every requested id must have a local
226
+ // projection, exactly like planTombstone: a typo'd or foreign id
227
+ // is refused instead of silently sharing the matching subset.
228
+ if (rows.length !== memoryIds.length) {
229
+ return { entries: [], refusal: "unknown_entry" };
230
+ }
231
+ const requiresApproval = this.setting("share_requires_approval", "1") === "1";
232
+ const floor = Number.parseFloat(this.setting("shared_confidence_floor", "0.7"));
233
+ const clampedFloor = Number.isNaN(floor)
234
+ ? 0.7
235
+ : Math.min(1, Math.max(0, floor));
236
+ const entries = [];
237
+ for (const row of rows) {
238
+ const entry = memoryToEntry(row);
239
+ if (Buffer.byteLength(canonicalize(entry), "utf8") > MAX_LINE_BYTES) {
240
+ return { entries: [], refusal: "line_too_long" };
241
+ }
242
+ if (computeConfidence(entry.evidence, entry.recurrence) < clampedFloor) {
243
+ return { entries: [], refusal: "below_floor" };
244
+ }
245
+ if (requiresApproval && row.curated !== 1) {
246
+ return { entries: [], refusal: "not_curated" };
247
+ }
248
+ entries.push(entry);
249
+ }
250
+ return { entries, refusal: null };
251
+ }
252
+ setting(key, fallback) {
253
+ const row = this.store
254
+ .prepare("SELECT value FROM kevin_settings WHERE key = ?")
255
+ .get(key);
256
+ return row?.value ?? fallback;
257
+ }
258
+ readWithFlag(path) {
259
+ let text;
260
+ try {
261
+ text = readFileSync(path, "utf8");
262
+ }
263
+ catch {
264
+ return {
265
+ exists: false,
266
+ parsed: {
267
+ version: 0,
268
+ repoId: null,
269
+ entries: [],
270
+ rejected: [],
271
+ folded: 0,
272
+ },
273
+ };
274
+ }
275
+ return { exists: true, parsed: parse(text) };
276
+ }
277
+ /**
278
+ * Read and parse the shared file. Total: a missing or unreadable
279
+ * file yields an empty ParseResult, never a throw (D8-14).
280
+ */
281
+ read(path) {
282
+ let text;
283
+ try {
284
+ text = readFileSync(path, "utf8");
285
+ }
286
+ catch {
287
+ return {
288
+ version: 0,
289
+ repoId: null,
290
+ entries: [],
291
+ rejected: [],
292
+ folded: 0,
293
+ };
294
+ }
295
+ return parse(text);
296
+ }
297
+ /**
298
+ * Idempotent and cheap to call (K8-016 / plan §5.5): hash the file
299
+ * first and return `{ skipped: true }` when the hash matches the
300
+ * most recent `okf_imports` row for this repo_id — the session.idle
301
+ * path costs one readFileSync plus one hash on an unchanged
302
+ * repository. A missing file is not an error: it returns
303
+ * `fileHash: null`, `parsed: 0`, and still writes an audit row.
304
+ */
305
+ import(path) {
306
+ let fileHash = null;
307
+ let text;
308
+ try {
309
+ text = readFileSync(path, "utf8");
310
+ fileHash = fnv1a64(text);
311
+ }
312
+ catch {
313
+ fileHash = null;
314
+ this.writeImportRow(path, null, 0, 0, 0, 0);
315
+ return {
316
+ path,
317
+ fileHash: null,
318
+ parsed: 0,
319
+ folded: 0,
320
+ rejected: 0,
321
+ imported: 0,
322
+ tombstoned: 0,
323
+ skipped: false,
324
+ };
325
+ }
326
+ const last = this.store
327
+ .prepare(`SELECT file_hash FROM okf_imports
328
+ WHERE repo_id = ? ORDER BY imported_at DESC, rowid DESC LIMIT 1`)
329
+ .get(this.repoId);
330
+ if (last !== undefined && last.file_hash === fileHash) {
331
+ this.writeImportRow(path, fileHash, 0, 0, 0, 1);
332
+ return {
333
+ path,
334
+ fileHash,
335
+ parsed: 0,
336
+ folded: 0,
337
+ rejected: 0,
338
+ imported: 0,
339
+ tombstoned: 0,
340
+ skipped: true,
341
+ };
342
+ }
343
+ const result = parse(text);
344
+ const imported = this.upsertEntries(result.entries);
345
+ const tombstoned = this.projectEntries(result.entries);
346
+ if (result.folded > 0) {
347
+ // A persistently non-zero value is signal, not error: the team
348
+ // is editing the same entries concurrently and the lattice is
349
+ // absorbing it (K8-016).
350
+ this.store
351
+ .prepare(`INSERT INTO kevin_metrics (key, value, updated_at)
352
+ VALUES ('okf_merge_folds', ?, datetime('now'))
353
+ ON CONFLICT(key) DO UPDATE SET
354
+ value = value + excluded.value,
355
+ updated_at = datetime('now')`)
356
+ .run(result.folded);
357
+ }
358
+ this.writeImportRow(path, fileHash, result.entries.length, result.folded, result.rejected.length, 0);
359
+ return {
360
+ path,
361
+ fileHash,
362
+ parsed: result.entries.length,
363
+ folded: result.folded,
364
+ rejected: result.rejected.length,
365
+ imported,
366
+ tombstoned,
367
+ skipped: false,
368
+ };
369
+ }
370
+ writeImportRow(path, fileHash, parsed, folded, rejected, skipped) {
371
+ this.store
372
+ .prepare(`INSERT INTO okf_imports
373
+ (id, repo_id, path, file_hash, entries_parsed, entries_folded,
374
+ entries_rejected, skipped)
375
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`)
376
+ .run(uuidv7(), this.repoId, path, fileHash, parsed, folded, rejected, skipped);
377
+ }
378
+ /**
379
+ * Project every imported entry into memories (K8-017 / plan §5.5,
380
+ * D8-10): a shared memory IS a memory, so getRelevant(), rankScore(),
381
+ * the five gates, truth_penalty, ConflictDetector and every audit
382
+ * rollup keep working unchanged.
383
+ *
384
+ * - assert entries: inserted once, never updated — re-importing an
385
+ * unchanged file must not create duplicates, bump evidence_count or
386
+ * move updated_at. `fingerprint` is deliberately left NULL: it is a
387
+ * different identity dimension (plan §3.3) and conflating it with
388
+ * `shared_entry_id` would make the v0.4.0 supersede path fire on
389
+ * unrelated entries (K8-017 acceptance).
390
+ * - tombstone entries: the ONE place in this codebase where the shared
391
+ * layer may write memories.status. This is NOT a v0.7.0 Principle 24
392
+ * violation: that principle forbids *contradiction* — a fuzzy
393
+ * inference — from writing status, and a tombstone is the opposite:
394
+ * an explicit, committed, human-reviewed decision that arrived
395
+ * through a pull request (D8-09, plan §5.5).
396
+ *
397
+ * Returns the number of memories archived by tombstones.
398
+ */
399
+ projectEntries(entries) {
400
+ const findMemory = this.store.prepare(`SELECT id FROM memories
401
+ WHERE shared_entry_id = ? AND repo_id = ? LIMIT 1`);
402
+ const insertMemory = this.store.prepare(`INSERT INTO memories
403
+ (id, type, content, scope, relevance_score, project_id, origin,
404
+ evidence_count, recurrence_count, created_at, updated_at, status,
405
+ curated, inferable, layer, repo_id, shared_entry_id)
406
+ VALUES (?, ?, ?, ?, ?, ?, 'imported', ?, ?, datetime('now'),
407
+ datetime('now'), 'active', 1, 1, 'shared', ?, ?)`);
408
+ const tombstone = this.store.prepare(`UPDATE memories SET status = 'archived'
409
+ WHERE shared_entry_id = ? AND repo_id = ? AND layer = 'shared'
410
+ AND status = 'active'`);
411
+ const lastChanges = this.store.prepare("SELECT changes() AS c");
412
+ let archived = 0;
413
+ for (const e of entries) {
414
+ if (e.op === "tombstone") {
415
+ // Explicit committed decision — see the class comment above.
416
+ tombstone.run(e.entry_id, this.repoId);
417
+ archived += lastChanges.get().c;
418
+ continue;
419
+ }
420
+ const existing = findMemory.get(e.entry_id, this.repoId);
421
+ if (existing)
422
+ continue;
423
+ insertMemory.run(uuidv7(), e.type, e.statement,
424
+ // memories.scope is CHECK-constrained to project/session; a
425
+ // path-prefix scope from the file degrades to 'project'.
426
+ e.scope === "project" || e.scope === "session" ? e.scope : "project", deriveConfidence(e), this.projectId, e.evidence, e.recurrence, this.repoId, e.entry_id);
427
+ }
428
+ return archived;
429
+ }
430
+ /**
431
+ * Upsert every entry into shared_entries keyed on (repo_id,
432
+ * entry_id) — the UNIQUE index from migration 009 makes this an
433
+ * upsert rather than an append. `confidence` is the DERIVED value
434
+ * (deriveConfidence), never a transported float (plan §5.3).
435
+ * Returns the number of rows inserted or updated.
436
+ */
437
+ upsertEntries(entries) {
438
+ const upsert = this.store.prepare(`INSERT INTO shared_entries
439
+ (id, repo_id, entry_id, type, statement, scope, confidence,
440
+ evidence, origin, author_hash, op, supersedes, created_at,
441
+ imported_at)
442
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
443
+ ON CONFLICT(repo_id, entry_id) DO UPDATE SET
444
+ type = excluded.type,
445
+ statement = excluded.statement,
446
+ scope = excluded.scope,
447
+ confidence = excluded.confidence,
448
+ evidence = excluded.evidence,
449
+ origin = excluded.origin,
450
+ author_hash = excluded.author_hash,
451
+ op = excluded.op,
452
+ supersedes = excluded.supersedes,
453
+ created_at = excluded.created_at,
454
+ imported_at = datetime('now')`);
455
+ let n = 0;
456
+ for (const e of entries) {
457
+ upsert.run(uuidv7(), this.repoId, e.entry_id, e.type, e.statement, e.scope, deriveConfidence(e), e.evidence, e.origin, e.author_hash, e.op, e.supersedes, e.created_at);
458
+ n++;
459
+ }
460
+ return n;
461
+ }
462
+ }
463
+ //# sourceMappingURL=SharedLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SharedLayer.js","sourceRoot":"","sources":["../../plugin/SharedLayer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * K9-004 — v0.9.0 native — host probe (plan §5.1, D9-12).
3
+ *
4
+ * Kevin stops assuming the host and asks it instead. `probeHost()` inspects the
5
+ * plugin input and the resolved `@opencode-ai/plugin` package and answers four
6
+ * questions once per process: what plugin version is actually installed, which
7
+ * v1+v2 surface exists, what project context the host already knows, and
8
+ * whether a shell was handed over.
9
+ *
10
+ * Contract (plan §5.1 / §4 traps 24-26):
11
+ * - Never throws: every read is guarded, every failure appends to `notes` and
12
+ * yields a conservative `false`. A throw during construction takes down the
13
+ * host's plugin load — strictly worse than any missing feature.
14
+ * - Duck-typed: only `typeof` and `in` checks, never `instanceof`, never a cast
15
+ * to a host class.
16
+ * - The v2 probe is a dynamic `await import()` of the v2/promise subpath inside
17
+ * a try. Rejection is the answer (a pre-v2 package). When it resolves we record
18
+ * which domains are actually exposed rather than assuming both — the promise
19
+ * subpath exports `define` at runtime and its `skill`/`reference` domains are
20
+ * compile-time types, so domain availability is verified against the resolved
21
+ * package's own declaration files.
22
+ * - Runs once: the result is cached and frozen. A capability that appears
23
+ * mid-session is indistinguishable from a bug (D9-12).
24
+ * - `pluginVersion` comes from the resolved package's `package.json` — never
25
+ * from the declared range, which plan §3.4 showed to be untrustworthy.
26
+ * - The v2 subpath string itself lives in native.ts (K9-013 containment): this
27
+ * module only ever names it through the imported symbol.
28
+ */
29
+ /** v0.9.0 (K9-004 / plan §5.1, D9-12) */
30
+ export type HostFlavour = "v1-only" | "v1+v2";
31
+ /** v0.9.0 (K9-004 / plan §5.1) */
32
+ export interface HostProject {
33
+ readonly id: string | null;
34
+ readonly worktree: string | null;
35
+ readonly directory: string | null;
36
+ }
37
+ /** v0.9.0 (K9-004 / plan §5.1) */
38
+ export interface HostSurface {
39
+ /** Resolved `version` from the installed package's package.json, or null. */
40
+ readonly pluginVersion: string | null;
41
+ readonly flavour: HostFlavour;
42
+ readonly project: HostProject;
43
+ /** The host handed over `input.$` (BunShell). Zero-spawn remains a choice. */
44
+ readonly hasShell: boolean;
45
+ /** Which v2 domains the resolved package actually exposes. */
46
+ readonly v2: {
47
+ readonly skill: boolean;
48
+ readonly reference: boolean;
49
+ };
50
+ /** Every degraded read is explained here; never empty on a degraded probe. */
51
+ readonly notes: readonly string[];
52
+ }
53
+ /**
54
+ * v0.9.0 (K9-004 / plan §5.1, D9-12)
55
+ * `importV2` is a test seam; production callers omit it and the real
56
+ * `await import()` runs inside the try.
57
+ */
58
+ export declare function probeHost(input: unknown, options?: {
59
+ importV2?: () => Promise<unknown>;
60
+ }): Promise<HostSurface>;
61
+ /**
62
+ * v0.9.0 (K9-004) — test hook. probeHost caches its result (probe once, freeze,
63
+ * restart to re-probe); tests reset between cases.
64
+ */
65
+ export declare function resetHostProbeCache(): void;
66
+ /**
67
+ * v0.9.0 (K9-004 / plan §5.1) — one stable paragraph: version, flavour and the
68
+ * domain flags. No paths, no identifiers; safe to paste into an issue report.
69
+ */
70
+ export declare function summarize(s: HostSurface): string;