@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.
- package/README.md +63 -10
- package/dist/migrations/010_v09_native.sql +78 -0
- package/dist/plugin/HookLiveness.d.ts +81 -0
- package/dist/plugin/HookLiveness.js +324 -0
- package/dist/plugin/HookLiveness.js.map +1 -0
- package/dist/plugin/Materializer.d.ts +25 -0
- package/dist/plugin/Materializer.js +39 -10
- package/dist/plugin/Materializer.js.map +1 -1
- package/dist/plugin/Migrate.d.ts +1 -0
- package/dist/plugin/Migrate.js +46 -5
- package/dist/plugin/Migrate.js.map +1 -1
- package/dist/plugin/RepoIdentity.d.ts +20 -9
- package/dist/plugin/RepoIdentity.js +44 -9
- package/dist/plugin/RepoIdentity.js.map +1 -1
- package/dist/plugin/Retrospective.js +9 -0
- package/dist/plugin/Retrospective.js.map +1 -1
- package/dist/plugin/host.d.ts +70 -0
- package/dist/plugin/host.js +251 -0
- package/dist/plugin/host.js.map +1 -0
- package/dist/plugin/index.d.ts +2 -2
- package/dist/plugin/index.js +129 -7
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/kevin_audit.d.ts +29 -0
- package/dist/plugin/kevin_audit.js +84 -0
- package/dist/plugin/kevin_audit.js.map +1 -1
- package/dist/plugin/kevin_doctor.d.ts +57 -0
- package/dist/plugin/kevin_doctor.js +168 -0
- package/dist/plugin/kevin_doctor.js.map +1 -0
- package/dist/plugin/kevin_native.d.ts +29 -0
- package/dist/plugin/kevin_native.js +80 -0
- package/dist/plugin/kevin_native.js.map +1 -0
- package/dist/plugin/native.d.ts +92 -0
- package/dist/plugin/native.js +191 -0
- package/dist/plugin/native.js.map +1 -0
- package/migrations/010_v09_native.sql +78 -0
- 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.
|
|
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.
|
|
29
|
+
"@opencode-ai/plugin": "^1.18.16"
|
|
30
30
|
},
|
|
31
31
|
"optionalDependencies": {
|
|
32
32
|
"better-sqlite3": "^12.11.0"
|