@jmtrin/opencode-kevin 0.8.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 (36) hide show
  1. package/README.md +63 -10
  2. package/dist/migrations/010_v09_native.sql +78 -0
  3. package/dist/plugin/HookLiveness.d.ts +81 -0
  4. package/dist/plugin/HookLiveness.js +324 -0
  5. package/dist/plugin/HookLiveness.js.map +1 -0
  6. package/dist/plugin/Materializer.d.ts +25 -0
  7. package/dist/plugin/Materializer.js +39 -10
  8. package/dist/plugin/Materializer.js.map +1 -1
  9. package/dist/plugin/Migrate.d.ts +1 -0
  10. package/dist/plugin/Migrate.js +46 -5
  11. package/dist/plugin/Migrate.js.map +1 -1
  12. package/dist/plugin/RepoIdentity.d.ts +20 -9
  13. package/dist/plugin/RepoIdentity.js +44 -9
  14. package/dist/plugin/RepoIdentity.js.map +1 -1
  15. package/dist/plugin/Retrospective.js +9 -0
  16. package/dist/plugin/Retrospective.js.map +1 -1
  17. package/dist/plugin/host.d.ts +70 -0
  18. package/dist/plugin/host.js +251 -0
  19. package/dist/plugin/host.js.map +1 -0
  20. package/dist/plugin/index.d.ts +2 -2
  21. package/dist/plugin/index.js +129 -7
  22. package/dist/plugin/index.js.map +1 -1
  23. package/dist/plugin/kevin_audit.d.ts +29 -0
  24. package/dist/plugin/kevin_audit.js +84 -0
  25. package/dist/plugin/kevin_audit.js.map +1 -1
  26. package/dist/plugin/kevin_doctor.d.ts +57 -0
  27. package/dist/plugin/kevin_doctor.js +168 -0
  28. package/dist/plugin/kevin_doctor.js.map +1 -0
  29. package/dist/plugin/kevin_native.d.ts +29 -0
  30. package/dist/plugin/kevin_native.js +80 -0
  31. package/dist/plugin/kevin_native.js.map +1 -0
  32. package/dist/plugin/native.d.ts +92 -0
  33. package/dist/plugin/native.js +191 -0
  34. package/dist/plugin/native.js.map +1 -0
  35. package/migrations/010_v09_native.sql +78 -0
  36. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kevin_doctor.js","sourceRoot":"","sources":["../../plugin/kevin_doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { Store } from "./Store.js";
2
+ import type { HostSurface } from "./host.js";
3
+ import type { SettingsReader } from "./native.js";
4
+ export type NativeAction = "show" | "enable" | "disable";
5
+ export interface NativeRegistrationRow {
6
+ readonly surface: "skill" | "reference";
7
+ readonly registered: boolean;
8
+ readonly verified: boolean;
9
+ readonly attached_at: string | null;
10
+ }
11
+ export interface NativeReport {
12
+ readonly action: NativeAction;
13
+ /** The setting value: '1' or '0' as stored (TEXT). */
14
+ readonly value: "1" | "0";
15
+ /** Whether registration would be effective on THIS host (v2 subpath present). */
16
+ readonly effective: boolean;
17
+ /** Present when `effective` is false: why the intent is inert. */
18
+ readonly reason?: string;
19
+ /** The latest persisted outcome per surface (show only). */
20
+ readonly registrations?: NativeRegistrationRow[];
21
+ /** The restart note (enable/disable only). */
22
+ readonly note?: string;
23
+ }
24
+ export interface NativeDeps {
25
+ readonly host: HostSurface;
26
+ readonly store: Store;
27
+ readonly settings: SettingsReader;
28
+ }
29
+ export declare function handleNative(action: NativeAction, deps: NativeDeps): NativeReport;
@@ -0,0 +1,80 @@
1
+ // v0.9.0 (K9-019 / plan §5.5, D9-12) — `kevin_native`: inspect and toggle
2
+ // `native_registration_enabled`.
3
+ //
4
+ // Pure in the sense that matters: `show` reads only; `enable`/`disable`
5
+ // write `kevin_settings` and nothing else. Neither action re-attaches —
6
+ // the probe is frozen for the process lifetime (D9-12) — and the response
7
+ // says so explicitly, naming a restart as the requirement. `enable` on a
8
+ // host without the v2 subpath succeeds and reports the registration as
9
+ // inert: the setting is a statement of intent that becomes effective when
10
+ // the host catches up, and refusing would make it untestable on the
11
+ // majority of installations.
12
+ //
13
+ // The stored value is TEXT `'1'` or `'0'` — never a boolean, never
14
+ // `'true'` (kevin_settings.value is TEXT; compare with `=== "1"`).
15
+ function lastRows(store) {
16
+ try {
17
+ return store
18
+ .prepare(`SELECT surface, registered, verified, attached_at
19
+ FROM native_registrations
20
+ ORDER BY attached_at DESC, id DESC
21
+ LIMIT 20`)
22
+ .all()
23
+ .map((row) => {
24
+ const r = row;
25
+ return {
26
+ surface: r.surface,
27
+ registered: r.registered === 1,
28
+ verified: r.verified === 1,
29
+ attached_at: r.attached_at,
30
+ };
31
+ });
32
+ }
33
+ catch {
34
+ // pre-010 database: the table does not exist yet — no rows to
35
+ // report, and that is the truth.
36
+ return [];
37
+ }
38
+ }
39
+ /** v0.9.0 (K9-019 / plan §5.5, D9-12) — the pure decision: the probe is
40
+ * frozen for the process lifetime, so "effective" is derived from the
41
+ * resolved host surface, never from a fresh probe call. */
42
+ function effectiveOn(host) {
43
+ return host.v2.skill || host.v2.reference;
44
+ }
45
+ export function handleNative(action, deps) {
46
+ const current = deps.settings.getSetting("native_registration_enabled", "0");
47
+ const value = current === "1" ? "1" : "0";
48
+ if (action === "show") {
49
+ const report = {
50
+ action,
51
+ value,
52
+ effective: effectiveOn(deps.host),
53
+ registrations: lastRows(deps.store),
54
+ ...(effectiveOn(deps.host)
55
+ ? {}
56
+ : {
57
+ reason: "v2 subpath absent from the resolved host package — registration would be inert",
58
+ }),
59
+ };
60
+ return report;
61
+ }
62
+ const next = action === "enable" ? "1" : "0";
63
+ deps.store
64
+ .prepare(`INSERT INTO kevin_settings (key, value) VALUES (?, ?)
65
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`)
66
+ .run("native_registration_enabled", next);
67
+ const report = {
68
+ action,
69
+ value: next,
70
+ effective: effectiveOn(deps.host),
71
+ note: "the probe is frozen for the process lifetime — restart the host for the change to take effect",
72
+ ...(effectiveOn(deps.host)
73
+ ? {}
74
+ : {
75
+ reason: "v2 subpath absent from the resolved host package — registration would be inert",
76
+ }),
77
+ };
78
+ return report;
79
+ }
80
+ //# sourceMappingURL=kevin_native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kevin_native.js","sourceRoot":"","sources":["../../plugin/kevin_native.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,iCAAiC;AACjC,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,0EAA0E;AAC1E,yEAAyE;AACzE,uEAAuE;AACvE,0EAA0E;AAC1E,oEAAoE;AACpE,6BAA6B;AAC7B,EAAE;AACF,mEAAmE;AACnE,mEAAmE;AAmCnE,SAAS,QAAQ,CAAC,KAAY;IAC7B,IAAI,CAAC;QACJ,OAAO,KAAK;aACV,OAAO,CACP;;;cAGU,CACV;aACA,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACZ,MAAM,CAAC,GAAG,GAKT,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,UAAU,EAAE,CAAC,CAAC,UAAU,KAAK,CAAC;gBAC9B,QAAQ,EAAE,CAAC,CAAC,QAAQ,KAAK,CAAC;gBAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;aAC1B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACR,8DAA8D;QAC9D,iCAAiC;QACjC,OAAO,EAAE,CAAC;IACX,CAAC;AACF,CAAC;AAED;;2DAE2D;AAC3D,SAAS,WAAW,CAAC,IAAiB;IACrC,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,YAAY,CAC3B,MAAoB,EACpB,IAAgB;IAEhB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;IAC7E,MAAM,KAAK,GAAc,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAErD,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,MAAM,GAAiB;YAC5B,MAAM;YACN,KAAK;YACL,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YACjC,aAAa,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;YACnC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBACzB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACA,MAAM,EACL,gFAAgF;iBACjF,CAAC;SACJ,CAAC;QACF,OAAO,MAAM,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAc,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,IAAI,CAAC,KAAK;SACR,OAAO,CACP;0DACuD,CACvD;SACA,GAAG,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAiB;QAC5B,MAAM;QACN,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QACjC,IAAI,EAAE,+FAA+F;QACrG,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YACzB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACA,MAAM,EACL,gFAAgF;aACjF,CAAC;KACJ,CAAC;IACF,OAAO,MAAM,CAAC;AACf,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { type Materializer } from "./Materializer.js";
2
+ import type { Store } from "./Store.js";
3
+ import type { HostSurface } from "./host.js";
4
+ /** The surface `attachNative()` returned. `verified` is filled by the
5
+ * read-back checks (K9-014/015) once the host ran `setup()`. */
6
+ export interface NativeRegistration {
7
+ registered: {
8
+ skill: boolean;
9
+ reference: boolean;
10
+ };
11
+ verified: {
12
+ skill: boolean;
13
+ reference: boolean;
14
+ };
15
+ notes: string[];
16
+ }
17
+ /** Minimal settings reader — matches MemoryService.getSetting(key, fallback). */
18
+ export interface SettingsReader {
19
+ getSetting(key: string, fallback?: string): string | null;
20
+ }
21
+ export interface NativeDeps {
22
+ materializer: Materializer;
23
+ settings: SettingsReader;
24
+ /**
25
+ * v0.9.0 (K9-014 / plan §5.4) — reports the outcome of each surface
26
+ * registration once the host ran `setup()`. `registered` reflects
27
+ * whether the transform completed; `verified` whether the read-back
28
+ * (`draft.list()`) contained the provided source. The host's own
29
+ * `setup()` runs asynchronously, so this callback may fire after
30
+ * `attachNative()` resolved.
31
+ */
32
+ onVerified?: (surface: "skill" | "reference", registered: boolean, verified: boolean) => void;
33
+ /**
34
+ * v0.9.0 (K9-017 / plan §6.2) — the persistence sink. When present,
35
+ * every surface outcome is appended to `native_registrations` and the
36
+ * two live counters are bumped. Attach time is construction, not a
37
+ * hot path, so a direct write is correct here and the
38
+ * `metrics.flush()` cadence does not apply.
39
+ */
40
+ store?: Store;
41
+ }
42
+ /** The only place in the repository allowed to name the v2 subpath. */
43
+ export declare const V2_SPECIFIER = "@opencode-ai/plugin/v2/promise";
44
+ /**
45
+ * Duck-typed mirror of the host's v2 PluginContext. The host's own
46
+ * compile-time types (dist/v2/promise/context.d.ts) are not importable
47
+ * here — a static type import would name the specifier outside a dynamic
48
+ * `import()` and break the containment scan.
49
+ */
50
+ export interface KevinNativeContext {
51
+ readonly skill: {
52
+ transform(hook: (draft: unknown) => Promise<void> | void): Promise<void> | void;
53
+ };
54
+ readonly reference: {
55
+ transform(hook: (draft: unknown) => Promise<void> | void): Promise<void> | void;
56
+ };
57
+ }
58
+ /**
59
+ * Duck-typed mirror of the v2 `Plugin` contract
60
+ * (dist/v2/promise/plugin.d.ts). `define()` is the identity function —
61
+ * 54 bytes, `return plugin` — so adopting it is neither a framework nor
62
+ * a commitment (D9-02); the object literal below already satisfies the
63
+ * contract.
64
+ */
65
+ export interface KevinNativePlugin {
66
+ readonly id: string;
67
+ readonly setup: (context: KevinNativeContext) => Promise<void> | void;
68
+ }
69
+ /** The skill body Kevin registers through `skill.transform`. */
70
+ export declare function kevinSkillSource(materializer: Materializer): string;
71
+ /**
72
+ * Build the v2 plugin. Registration replaces emission (D9-10): when the
73
+ * host runs `setup()`, the skill/reference surfaces are registered
74
+ * natively and the Materializer's `*_emission_enabled` file path is
75
+ * skipped for those surfaces (guard in K9-016).
76
+ */
77
+ export declare function buildNativePlugin(deps: NativeDeps): KevinNativePlugin;
78
+ export interface AttachOptions {
79
+ /** Injectable v2 loader for tests; defaults to the real dynamic import. */
80
+ importV2?: () => Promise<unknown>;
81
+ /** Collects notes for the caller when the result is null. */
82
+ notes?: string[];
83
+ }
84
+ /**
85
+ * Attach the native surface when the host exposes it AND the user asked
86
+ * for it. Returns `null` — cleanly, with a `note` — whenever the host
87
+ * lacks the subpath or `native_registration_enabled` is not `'1'`; that
88
+ * is the default on every existing installation, so the default
89
+ * behaviour of this release is byte-identical to v0.8.0. Never throws
90
+ * (D9-12): every failure path is a `null` plus a `note`.
91
+ */
92
+ export declare function attachNative(host: HostSurface, deps: NativeDeps, options?: AttachOptions): Promise<NativeRegistration | null>;
@@ -0,0 +1,191 @@
1
+ import { SKILL_TOPIC } from "./Materializer.js";
2
+ import { uuidv7 } from "./uuid.js";
3
+ /** The only place in the repository allowed to name the v2 subpath. */
4
+ export const V2_SPECIFIER = "@opencode-ai/plugin/v2/promise";
5
+ /** The skill body Kevin registers through `skill.transform`. */
6
+ export function kevinSkillSource(materializer) {
7
+ return materializer.skillBody();
8
+ }
9
+ /**
10
+ * Build the v2 plugin. Registration replaces emission (D9-10): when the
11
+ * host runs `setup()`, the skill/reference surfaces are registered
12
+ * natively and the Materializer's `*_emission_enabled` file path is
13
+ * skipped for those surfaces (guard in K9-016).
14
+ */
15
+ export function buildNativePlugin(deps) {
16
+ return {
17
+ id: "opencode-kevin",
18
+ setup: async (ctx) => {
19
+ try {
20
+ await ctx.skill.transform(async (draft) => {
21
+ const source = kevinSkillSource(deps.materializer);
22
+ // The draft is a mutable builder valid only for the
23
+ // duration of this callback; it never escapes (D9-10
24
+ // property 3). K9-014's source scan asserts that.
25
+ const draftApi = draft;
26
+ if (typeof draftApi.source !== "function") {
27
+ deps.onVerified?.("skill", false, false);
28
+ return;
29
+ }
30
+ draftApi.source(source);
31
+ // v0.9.0 (K9-014 / plan §5.4 property 2) — verification is a
32
+ // read-back: the registered source must show up in the
33
+ // draft's own list(). An unverified registration is a note
34
+ // (and a metric in K9-017), never a throw.
35
+ const verified = typeof draftApi.list === "function" &&
36
+ draftApi.list().some((entry) => entry === source);
37
+ deps.onVerified?.("skill", true, verified);
38
+ });
39
+ }
40
+ catch {
41
+ // A rejecting transform still reports, never throws (K9-014).
42
+ deps.onVerified?.("skill", false, false);
43
+ }
44
+ try {
45
+ await ctx.reference.transform(async (draft) => {
46
+ // v0.9.0 (K9-015 / plan §5.4, D6-14) — one add() per
47
+ // materialized ref target (topic !== SKILL_TOPIC), named
48
+ // `@kevin/<topic>`. Topics follow the v0.6.0 rule
49
+ // `<type>-<dominant token>`; dominantToken already
50
+ // excludes hex-like tokens, so a fingerprint prefix can
51
+ // never become a reference name. Sources use the v2
52
+ // `{ type: "local", path }` shape (read from the
53
+ // resolved SDK's ReferenceLocalSource, duck-typed).
54
+ const draftApi = draft;
55
+ if (typeof draftApi.add !== "function") {
56
+ deps.onVerified?.("reference", false, false);
57
+ return;
58
+ }
59
+ const added = [];
60
+ for (const target of deps.materializer.bundleTargets()) {
61
+ if (target.topic === SKILL_TOPIC)
62
+ continue;
63
+ const name = `@kevin/${target.topic}`;
64
+ draftApi.add(name, {
65
+ type: "local",
66
+ path: target.path,
67
+ });
68
+ added.push(name);
69
+ }
70
+ // Verification is the same read-back as K9-014: every
71
+ // name we added must show up in the draft's own list().
72
+ const listed = typeof draftApi.list === "function" ? draftApi.list() : [];
73
+ const listedNames = new Set(listed.map((entry) => {
74
+ const tuple = entry;
75
+ return tuple[0];
76
+ }));
77
+ const verified = added.every((name) => listedNames.has(name));
78
+ deps.onVerified?.("reference", true, verified);
79
+ });
80
+ }
81
+ catch {
82
+ deps.onVerified?.("reference", false, false);
83
+ }
84
+ },
85
+ };
86
+ }
87
+ /**
88
+ * Attach the native surface when the host exposes it AND the user asked
89
+ * for it. Returns `null` — cleanly, with a `note` — whenever the host
90
+ * lacks the subpath or `native_registration_enabled` is not `'1'`; that
91
+ * is the default on every existing installation, so the default
92
+ * behaviour of this release is byte-identical to v0.8.0. Never throws
93
+ * (D9-12): every failure path is a `null` plus a `note`.
94
+ */
95
+ export async function attachNative(host, deps, options = {}) {
96
+ const notes = options.notes ?? [];
97
+ const enabled = deps.settings.getSetting("native_registration_enabled", "0") === "1";
98
+ if (!enabled)
99
+ return null;
100
+ if (!host.v2.skill && !host.v2.reference) {
101
+ notes.push("v2 subpath absent from the resolved host package — native registration skipped");
102
+ return null;
103
+ }
104
+ let mod;
105
+ try {
106
+ mod = await (options.importV2 ?? (() => import(/* @vite-ignore */ V2_SPECIFIER)))();
107
+ }
108
+ catch {
109
+ notes.push("v2 subpath import rejected — native registration skipped");
110
+ return null;
111
+ }
112
+ const record = mod;
113
+ const define = typeof record.define === "function"
114
+ ? record.define
115
+ : null;
116
+ if (define === null) {
117
+ notes.push("v2 module exposes no define() — native registration skipped");
118
+ return null;
119
+ }
120
+ // `define()` is the identity function (D9-02): passing the built
121
+ // plugin through it validates the contract without adding a framework.
122
+ // v0.9.0 (K9-014 / plan §5.4 property 2) — the collector for the
123
+ // read-back results: `verified` is filled by the host running setup()
124
+ // (draft.list()), reported back through onVerified. The setup callback
125
+ // may fire after this function resolved; the caller keeps the returned
126
+ // registration as the final word.
127
+ const registered = { skill: host.v2.skill, reference: host.v2.reference };
128
+ const verified = { skill: false, reference: false };
129
+ const plugin = buildNativePlugin({
130
+ ...deps,
131
+ onVerified: (surface, didRegister, isVerified) => {
132
+ if (!didRegister)
133
+ registered[surface] = false;
134
+ verified[surface] = isVerified;
135
+ if (!isVerified) {
136
+ notes.push(`${surface} read-back does not contain the provided source — unverified registration`);
137
+ }
138
+ // v0.9.0 (K9-017 / plan §6.2) — append the outcome row at attach
139
+ // time (construction, not a hot path; a direct write is correct,
140
+ // the flush cadence does not apply). Only surfaces the host
141
+ // actually exposes are persisted: a surface the host cannot
142
+ // serve is not an outcome to record.
143
+ if (deps.store && host.v2[surface]) {
144
+ const note = !isVerified
145
+ ? `${surface} read-back does not contain the provided source — unverified registration`
146
+ : null;
147
+ persistRegistration(deps.store, surface, didRegister, isVerified, note);
148
+ }
149
+ },
150
+ });
151
+ define(plugin);
152
+ return {
153
+ registered,
154
+ verified,
155
+ notes,
156
+ };
157
+ }
158
+ /**
159
+ * v0.9.0 (K9-017 / plan §6.2) — one `native_registrations` row per
160
+ * surface per attach attempt, plus the two live counters. The counters
161
+ * live OUTSIDE the frozen `METRIC_KEYS` ladder (K7-004) but persist to
162
+ * the same `kevin_metrics` table, following the v0.6.0 `incrRegistered`
163
+ * precedent (K6-018/019): written immediately, never debounced. The
164
+ * `surface` CHECK lives in the schema (migration 010), so a bad surface
165
+ * fails loudly at the constraint rather than being coerced — the closed
166
+ * enumeration is deliberate (plan §6.2).
167
+ */
168
+ function persistRegistration(store, surface, registered, verified, note) {
169
+ store
170
+ .prepare(`INSERT INTO native_registrations (id, surface, registered, verified, note)
171
+ VALUES (?, ?, ?, ?, ?)`)
172
+ .run(uuidv7(), surface, registered ? 1 : 0, verified ? 1 : 0, note);
173
+ if (verified) {
174
+ bumpNativeCounter(store, "native_registrations_total");
175
+ }
176
+ else if (registered) {
177
+ // "Registered but unverified": the host accepted the call and did
178
+ // not honour it — the interesting state (K9-017).
179
+ bumpNativeCounter(store, "native_registration_failures");
180
+ }
181
+ }
182
+ function bumpNativeCounter(store, key) {
183
+ store
184
+ .prepare(`INSERT INTO kevin_metrics (key, value, updated_at)
185
+ VALUES (?, 1, datetime('now'))
186
+ ON CONFLICT(key) DO UPDATE SET
187
+ value = value + excluded.value,
188
+ updated_at = datetime('now')`)
189
+ .run(key);
190
+ }
191
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../../plugin/native.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ -- ============================================================
2
+ -- Kevin v0.9.0 "Native" — host surface and hook liveness
3
+ -- Migration 010. Additive only. No table rebuild.
4
+ -- ============================================================
5
+
6
+ -- 1. Hook liveness. Deliberately NOT project-scoped: a hook is a
7
+ -- property of the host binary, not of a checkout. One row per
8
+ -- hook name, updated in place. See D9-08.
9
+ CREATE TABLE IF NOT EXISTS hook_liveness (
10
+ hook TEXT PRIMARY KEY,
11
+ experimental INTEGER NOT NULL DEFAULT 0,
12
+ fire_count INTEGER NOT NULL DEFAULT 0,
13
+ error_count INTEGER NOT NULL DEFAULT 0,
14
+ expected_count INTEGER NOT NULL DEFAULT 0,
15
+ first_seen_at TEXT,
16
+ last_seen_at TEXT,
17
+ dead_since TEXT,
18
+ plugin_version TEXT
19
+ );
20
+
21
+ CREATE INDEX IF NOT EXISTS idx_hook_liveness_dead
22
+ ON hook_liveness(dead_since);
23
+
24
+ -- 2. Host probe history. Append-only. Off by default; exists so a
25
+ -- user chasing an intermittent fault can turn it on and get a
26
+ -- timeline instead of a single current value.
27
+ CREATE TABLE IF NOT EXISTS host_probes (
28
+ id TEXT PRIMARY KEY,
29
+ probed_at TEXT NOT NULL DEFAULT (datetime('now')),
30
+ plugin_version TEXT,
31
+ flavour TEXT NOT NULL,
32
+ has_shell INTEGER NOT NULL DEFAULT 0,
33
+ v2_skill INTEGER NOT NULL DEFAULT 0,
34
+ v2_reference INTEGER NOT NULL DEFAULT 0,
35
+ notes TEXT
36
+ );
37
+
38
+ CREATE INDEX IF NOT EXISTS idx_host_probes_at
39
+ ON host_probes(probed_at);
40
+
41
+ -- 3. Native registration outcomes. One row per attach attempt, so
42
+ -- "registered but unverified" is a queryable state rather than a
43
+ -- log line.
44
+ CREATE TABLE IF NOT EXISTS native_registrations (
45
+ id TEXT PRIMARY KEY,
46
+ attached_at TEXT NOT NULL DEFAULT (datetime('now')),
47
+ surface TEXT NOT NULL CHECK (surface IN ('skill', 'reference')),
48
+ registered INTEGER NOT NULL DEFAULT 0,
49
+ verified INTEGER NOT NULL DEFAULT 0,
50
+ note TEXT
51
+ );
52
+
53
+ CREATE INDEX IF NOT EXISTS idx_native_registrations_surface
54
+ ON native_registrations(surface, attached_at);
55
+
56
+ -- 4. Metric seeds (39 -> 45).
57
+ INSERT OR IGNORE INTO kevin_metrics (key, value) VALUES
58
+ ('hook_fires_total', 0),
59
+ ('hook_errors_total', 0),
60
+ ('hooks_dead_total', 0),
61
+ ('injections_suppressed_dead_hook', 0),
62
+ ('native_registrations_total', 0),
63
+ ('native_registration_failures', 0);
64
+
65
+ -- 5. Setting seeds (23 -> 27).
66
+ -- hook_liveness_enabled defaults ON: it is a read-only instrument
67
+ -- on the success path, and an instrument nobody switches on is an
68
+ -- instrument nobody has.
69
+ -- native_registration_enabled defaults OFF: it changes where a
70
+ -- curated skill comes from, and that is a change a user opts into.
71
+ INSERT OR IGNORE INTO kevin_settings (key, value) VALUES
72
+ ('hook_liveness_enabled', '1'),
73
+ ('native_registration_enabled', '0'),
74
+ ('host_probe_history_enabled', '0'),
75
+ ('dead_hook_report_threshold', '3');
76
+
77
+ -- 6. Version marker.
78
+ INSERT OR IGNORE INTO schema_version (version) VALUES ('010');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmtrin/opencode-kevin",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Kevin — Observa y aprende: capa de aprendizaje para OpenCode",
5
5
  "type": "module",
6
6
  "main": "dist/plugin/index.js",
@@ -26,7 +26,7 @@
26
26
  "measure:mix": "node --import tsx scripts/measure-mix.ts"
27
27
  },
28
28
  "dependencies": {
29
- "@opencode-ai/plugin": "^1.17.6"
29
+ "@opencode-ai/plugin": "^1.18.16"
30
30
  },
31
31
  "optionalDependencies": {
32
32
  "better-sqlite3": "^12.11.0"