@jmtrin/kevin-core 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Archiver.d.ts +42 -0
- package/dist/Archiver.js +83 -0
- package/dist/ArtifactWriter.d.ts +93 -0
- package/dist/ArtifactWriter.js +291 -0
- package/dist/CausalChain.d.ts +22 -0
- package/dist/CausalChain.js +197 -0
- package/dist/ChatBridge.d.ts +41 -0
- package/dist/ChatBridge.js +103 -0
- package/dist/ConflictDetector.d.ts +35 -0
- package/dist/ConflictDetector.js +260 -0
- package/dist/ContextInjector.d.ts +222 -0
- package/dist/ContextInjector.js +533 -0
- package/dist/ConventionMiner.d.ts +35 -0
- package/dist/ConventionMiner.js +242 -0
- package/dist/Curator.d.ts +118 -0
- package/dist/Curator.js +326 -0
- package/dist/DashboardHtml.d.ts +5 -0
- package/dist/DashboardHtml.js +180 -0
- package/dist/Feedback.d.ts +67 -0
- package/dist/Feedback.js +120 -0
- package/dist/HookLiveness.d.ts +88 -0
- package/dist/HookLiveness.js +322 -0
- package/dist/InjectionLedger.d.ts +98 -0
- package/dist/InjectionLedger.js +295 -0
- package/dist/LessonFixer.d.ts +44 -0
- package/dist/LessonFixer.js +45 -0
- package/dist/Materializer.d.ts +84 -0
- package/dist/Materializer.js +181 -0
- package/dist/MemoryService.d.ts +360 -0
- package/dist/MemoryService.js +1242 -0
- package/dist/Migrate.d.ts +24 -0
- package/dist/Migrate.js +285 -0
- package/dist/PatternMiner.d.ts +49 -0
- package/dist/PatternMiner.js +132 -0
- package/dist/QualityGate.d.ts +124 -0
- package/dist/QualityGate.js +119 -0
- package/dist/Reflector.d.ts +91 -0
- package/dist/Reflector.js +307 -0
- package/dist/RepoIdentity.d.ts +124 -0
- package/dist/RepoIdentity.js +300 -0
- package/dist/RepoTruth.d.ts +80 -0
- package/dist/RepoTruth.js +599 -0
- package/dist/Retrospective.d.ts +18 -0
- package/dist/Retrospective.js +216 -0
- package/dist/SharedLayer.d.ts +159 -0
- package/dist/SharedLayer.js +462 -0
- package/dist/Store.d.ts +29 -0
- package/dist/Store.js +50 -0
- package/dist/ToolCallObserver.d.ts +32 -0
- package/dist/ToolCallObserver.js +201 -0
- package/dist/TuiActions.d.ts +43 -0
- package/dist/TuiActions.js +181 -0
- package/dist/TuiSnapshots.d.ts +24 -0
- package/dist/TuiSnapshots.js +159 -0
- package/dist/capabilities.d.ts +6 -0
- package/dist/capabilities.js +1 -0
- package/dist/columns.d.ts +11 -0
- package/dist/columns.js +54 -0
- package/dist/confidence.d.ts +8 -0
- package/dist/confidence.js +34 -0
- package/dist/contract.d.ts +68 -0
- package/dist/contract.js +430 -0
- package/dist/diff.d.ts +8 -0
- package/dist/diff.js +182 -0
- package/dist/env.d.ts +5 -0
- package/dist/env.js +12 -0
- package/dist/escape.d.ts +39 -0
- package/dist/escape.js +60 -0
- package/dist/fingerprint.d.ts +27 -0
- package/dist/fingerprint.js +73 -0
- package/dist/host.d.ts +18 -0
- package/dist/host.js +7 -0
- package/dist/idle-pipeline.d.ts +9 -0
- package/dist/idle-pipeline.js +44 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +109 -0
- package/dist/inferability.d.ts +32 -0
- package/dist/inferability.js +88 -0
- package/dist/kevin_approve.d.ts +34 -0
- package/dist/kevin_approve.js +52 -0
- package/dist/kevin_audit.d.ts +230 -0
- package/dist/kevin_audit.js +631 -0
- package/dist/kevin_bench.d.ts +11 -0
- package/dist/kevin_bench.js +83 -0
- package/dist/kevin_conflicts.d.ts +9 -0
- package/dist/kevin_conflicts.js +50 -0
- package/dist/kevin_contract.d.ts +8 -0
- package/dist/kevin_contract.js +59 -0
- package/dist/kevin_doctor.d.ts +63 -0
- package/dist/kevin_doctor.js +197 -0
- package/dist/kevin_facts.d.ts +42 -0
- package/dist/kevin_facts.js +36 -0
- package/dist/kevin_forget.d.ts +33 -0
- package/dist/kevin_forget.js +260 -0
- package/dist/kevin_native.d.ts +29 -0
- package/dist/kevin_native.js +79 -0
- package/dist/kevin_propose.d.ts +23 -0
- package/dist/kevin_propose.js +14 -0
- package/dist/kevin_publish.d.ts +38 -0
- package/dist/kevin_publish.js +18 -0
- package/dist/kevin_why.d.ts +23 -0
- package/dist/kevin_why.js +111 -0
- package/dist/memory-format.d.ts +20 -0
- package/dist/memory-format.js +59 -0
- package/dist/metrics.d.ts +97 -0
- package/dist/metrics.js +288 -0
- package/dist/migrations/001_initial.sql +92 -0
- package/dist/migrations/002_indexes.sql +14 -0
- package/dist/migrations/003_v02_signal.sql +58 -0
- package/dist/migrations/004_v03_knowledge.sql +138 -0
- package/dist/migrations/005_v04_signal.sql +57 -0
- package/dist/migrations/006_v05_glassbox.sql +118 -0
- package/dist/migrations/007_v06_pull.sql +145 -0
- package/dist/migrations/008_v07_truth.sql +124 -0
- package/dist/migrations/009_v08_team.sql +100 -0
- package/dist/migrations/010_v09_native.sql +78 -0
- package/dist/migrations/011_v10_proven.sql +69 -0
- package/dist/migrations/012_v11_drift.sql +24 -0
- package/dist/native.d.ts +23 -0
- package/dist/native.js +1 -0
- package/dist/okf-export.d.ts +3 -0
- package/dist/okf-export.js +134 -0
- package/dist/okf-import.d.ts +76 -0
- package/dist/okf-import.js +271 -0
- package/dist/okf.d.ts +107 -0
- package/dist/okf.js +303 -0
- package/dist/perf.d.ts +35 -0
- package/dist/perf.js +174 -0
- package/dist/query-tokenizer.d.ts +13 -0
- package/dist/query-tokenizer.js +133 -0
- package/dist/redact.d.ts +2 -0
- package/dist/redact.js +18 -0
- package/dist/replay-types.d.ts +69 -0
- package/dist/replay-types.js +156 -0
- package/dist/replay.d.ts +44 -0
- package/dist/replay.js +215 -0
- package/dist/sqlite-adapter.d.ts +12 -0
- package/dist/sqlite-adapter.js +78 -0
- package/dist/time-ms.d.ts +1 -0
- package/dist/time-ms.js +16 -0
- package/dist/tui-types.d.ts +59 -0
- package/dist/tui-types.js +4 -0
- package/dist/uuid.d.ts +1 -0
- package/dist/uuid.js +50 -0
- package/package.json +28 -0
package/dist/diff.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// v0.6.0 (K6-006 / plan §5.2, D6-05) — a minimal deterministic unified-diff
|
|
2
|
+
// generator. Pure, dependency-free, byte-for-byte compatible with
|
|
3
|
+
// `git diff -U3 --no-index` for the fixtures the tests compare.
|
|
4
|
+
//
|
|
5
|
+
// It exists for exactly one reason: approval prompts must show a diff, never
|
|
6
|
+
// prose (D6-05). Determinism is a hard requirement: the output is persisted
|
|
7
|
+
// into `curation_proposals.diff` and compared across runs. No timestamps, no
|
|
8
|
+
// `Object.keys` iteration, no `Set` iteration — arrays only.
|
|
9
|
+
const CONTEXT = 3;
|
|
10
|
+
/**
|
|
11
|
+
* Split text into logical lines. A trailing newline is not part of the line
|
|
12
|
+
* model, so a file that merely gains or loses its final newline produces no
|
|
13
|
+
* spurious final-line hunk.
|
|
14
|
+
*/
|
|
15
|
+
function linesOf(text) {
|
|
16
|
+
if (text === "")
|
|
17
|
+
return [];
|
|
18
|
+
const parts = text.split("\n");
|
|
19
|
+
if (parts[parts.length - 1] === "")
|
|
20
|
+
parts.pop();
|
|
21
|
+
return parts;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* LCS over lines via dynamic programming, then a deterministic walk emitting
|
|
25
|
+
* context / deletion / addition ops. Within each change region deletions are
|
|
26
|
+
* emitted before additions, matching git's block ordering exactly.
|
|
27
|
+
*/
|
|
28
|
+
function computeOps(a, b) {
|
|
29
|
+
const m = a.length;
|
|
30
|
+
const n = b.length;
|
|
31
|
+
const w = n + 1;
|
|
32
|
+
const dp = new Int32Array((m + 1) * w);
|
|
33
|
+
for (let i = m - 1; i >= 0; i--) {
|
|
34
|
+
for (let j = n - 1; j >= 0; j--) {
|
|
35
|
+
dp[i * w + j] =
|
|
36
|
+
a[i] === b[j]
|
|
37
|
+
? dp[(i + 1) * w + j + 1] + 1
|
|
38
|
+
: Math.max(dp[(i + 1) * w + j], dp[i * w + j + 1]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const ops = [];
|
|
42
|
+
const pendingDel = [];
|
|
43
|
+
const pendingAdd = [];
|
|
44
|
+
const flush = () => {
|
|
45
|
+
for (const line of pendingDel)
|
|
46
|
+
ops.push({ type: "del", line });
|
|
47
|
+
for (const line of pendingAdd)
|
|
48
|
+
ops.push({ type: "add", line });
|
|
49
|
+
pendingDel.length = 0;
|
|
50
|
+
pendingAdd.length = 0;
|
|
51
|
+
};
|
|
52
|
+
let i = 0;
|
|
53
|
+
let j = 0;
|
|
54
|
+
while (i < m && j < n) {
|
|
55
|
+
if (a[i] === b[j]) {
|
|
56
|
+
flush();
|
|
57
|
+
ops.push({ type: "ctx", line: a[i] });
|
|
58
|
+
i++;
|
|
59
|
+
j++;
|
|
60
|
+
}
|
|
61
|
+
else if (dp[(i + 1) * w + j] >= dp[i * w + j + 1]) {
|
|
62
|
+
pendingDel.push(a[i]);
|
|
63
|
+
i++;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
pendingAdd.push(b[j]);
|
|
67
|
+
j++;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
flush();
|
|
71
|
+
while (i < m) {
|
|
72
|
+
pendingDel.push(a[i]);
|
|
73
|
+
i++;
|
|
74
|
+
}
|
|
75
|
+
flush();
|
|
76
|
+
while (j < n) {
|
|
77
|
+
pendingAdd.push(b[j]);
|
|
78
|
+
j++;
|
|
79
|
+
}
|
|
80
|
+
flush();
|
|
81
|
+
return ops;
|
|
82
|
+
}
|
|
83
|
+
function buildHunks(ops) {
|
|
84
|
+
// Maximal change regions: runs of ops containing at least one del/add.
|
|
85
|
+
const regions = [];
|
|
86
|
+
let regionStart = -1;
|
|
87
|
+
for (let k = 0; k < ops.length; k++) {
|
|
88
|
+
if (ops[k].type !== "ctx") {
|
|
89
|
+
if (regionStart === -1)
|
|
90
|
+
regionStart = k;
|
|
91
|
+
}
|
|
92
|
+
else if (regionStart !== -1) {
|
|
93
|
+
regions.push([regionStart, k]);
|
|
94
|
+
regionStart = -1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (regionStart !== -1)
|
|
98
|
+
regions.push([regionStart, ops.length]);
|
|
99
|
+
// Extend each region by CONTEXT lines and merge overlapping windows.
|
|
100
|
+
const windows = [];
|
|
101
|
+
for (const [rs, re] of regions) {
|
|
102
|
+
const start = Math.max(0, rs - CONTEXT);
|
|
103
|
+
const end = Math.min(ops.length, re + CONTEXT);
|
|
104
|
+
const prev = windows[windows.length - 1];
|
|
105
|
+
if (prev !== undefined && start <= prev.end) {
|
|
106
|
+
prev.end = end;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
windows.push({ start, end });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const hunks = [];
|
|
113
|
+
for (const win of windows) {
|
|
114
|
+
let beforeStart = 0;
|
|
115
|
+
let afterStart = 0;
|
|
116
|
+
let countA = 0;
|
|
117
|
+
let countB = 0;
|
|
118
|
+
for (let k = 0; k < win.end; k++) {
|
|
119
|
+
const op = ops[k];
|
|
120
|
+
const inside = k >= win.start;
|
|
121
|
+
if (op.type === "del") {
|
|
122
|
+
if (!inside)
|
|
123
|
+
beforeStart++;
|
|
124
|
+
if (inside)
|
|
125
|
+
countA++;
|
|
126
|
+
}
|
|
127
|
+
else if (op.type === "add") {
|
|
128
|
+
if (!inside)
|
|
129
|
+
afterStart++;
|
|
130
|
+
if (inside)
|
|
131
|
+
countB++;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
if (!inside) {
|
|
135
|
+
beforeStart++;
|
|
136
|
+
afterStart++;
|
|
137
|
+
}
|
|
138
|
+
if (inside) {
|
|
139
|
+
countA++;
|
|
140
|
+
countB++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 1-based start lines; a side with zero lines starts at 0.
|
|
145
|
+
const startA = countA > 0 ? beforeStart + 1 : 0;
|
|
146
|
+
const startB = countB > 0 ? afterStart + 1 : 0;
|
|
147
|
+
const rangeA = countA === 1 ? `-${startA}` : `-${startA},${countA}`;
|
|
148
|
+
const rangeB = countB === 1 ? `+${startB}` : `+${startB},${countB}`;
|
|
149
|
+
const lines = [];
|
|
150
|
+
for (let k = win.start; k < win.end; k++) {
|
|
151
|
+
const op = ops[k];
|
|
152
|
+
if (op.type === "del")
|
|
153
|
+
lines.push(`-${op.line}`);
|
|
154
|
+
else if (op.type === "add")
|
|
155
|
+
lines.push(`+${op.line}`);
|
|
156
|
+
else
|
|
157
|
+
lines.push(` ${op.line}`);
|
|
158
|
+
}
|
|
159
|
+
hunks.push({ header: `@@ ${rangeA} ${rangeB} @@`, lines });
|
|
160
|
+
}
|
|
161
|
+
return hunks;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Unified diff between `before` and `after` for `path`, in git's format:
|
|
165
|
+
* `--- a/<path>` / `+++ b/<path>` headers, `@@ -l,s +l,s @@` hunk headers
|
|
166
|
+
* (count omitted when 1, `0,0` for an empty side), three lines of context and
|
|
167
|
+
* adjacent hunks merged when their context windows overlap. Identical inputs
|
|
168
|
+
* yield the empty string.
|
|
169
|
+
*/
|
|
170
|
+
export function unifiedDiff(path, before, after) {
|
|
171
|
+
const ops = computeOps(linesOf(before), linesOf(after));
|
|
172
|
+
const hunks = buildHunks(ops);
|
|
173
|
+
if (hunks.length === 0)
|
|
174
|
+
return "";
|
|
175
|
+
const parts = [];
|
|
176
|
+
for (const hunk of hunks) {
|
|
177
|
+
parts.push(hunk.header);
|
|
178
|
+
parts.push(...hunk.lines);
|
|
179
|
+
}
|
|
180
|
+
const header = `--- a/${path}\n+++ b/${path}\n`;
|
|
181
|
+
return `${header}${parts.join("\n")}\n`;
|
|
182
|
+
}
|
package/dist/env.d.ts
ADDED
package/dist/env.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// KevinEnv — injected environment (K13-005, D13-03).
|
|
2
|
+
// Defaults exist for standalone/test use while HOSTS inject explicitly.
|
|
3
|
+
// resolveEnv performs NO filesystem access; it only resolves defaults
|
|
4
|
+
// from process state (cwd/homedir).
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
export function resolveEnv(partial) {
|
|
8
|
+
return {
|
|
9
|
+
projectRoot: partial?.projectRoot ?? process.cwd(),
|
|
10
|
+
dataRoot: partial?.dataRoot ?? join(homedir(), ".opencode-kevin"),
|
|
11
|
+
};
|
|
12
|
+
}
|
package/dist/escape.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.0.0 (K10-027 / plan §5.7) — the untrusted-input boundary.
|
|
3
|
+
*
|
|
4
|
+
* One pure, total, idempotent escaping function per container Kevin
|
|
5
|
+
* writes stored text into. Every function here is a fixed point after
|
|
6
|
+
* one application — applying it twice equals applying it once — because
|
|
7
|
+
* a re-curated memory passes through the boundary on every regeneration
|
|
8
|
+
* and must not accumulate escaping.
|
|
9
|
+
*
|
|
10
|
+
* This module imports nothing and touches no filesystem. It is the
|
|
11
|
+
* boundary; the single enforcement point is ArtifactWriter (D6-01).
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Neutralise text destined for the AGENTS.md marker block: HTML-escape
|
|
15
|
+
* (the memory-format discipline, made idempotent) so the literal
|
|
16
|
+
* `<!-- kevin:end -->` marker sequence and every comment terminator
|
|
17
|
+
* lose their meaning inside the block. The line-level strip of anything
|
|
18
|
+
* containing `kevin:begin`/`kevin:end` stays in
|
|
19
|
+
* ArtifactWriter.sanitizeArtifactBody — it is a filter, not an escape.
|
|
20
|
+
*/
|
|
21
|
+
export declare function escapeForMarkerBlock(text: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Neutralise fenced-code delimiters: any run of three or more backticks
|
|
24
|
+
* or tildes would close (or open) a markdown fence around the rendered
|
|
25
|
+
* block and let stored text masquerade as un-fenced document content.
|
|
26
|
+
* Each byte of the run becomes its numeric HTML entity, which renders
|
|
27
|
+
* identically but can never form a delimiter again.
|
|
28
|
+
*/
|
|
29
|
+
export declare function escapeForFence(text: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Neutralise bytes that would terminate an OKF v2 line: newline,
|
|
32
|
+
* carriage return and every other C0 control character become their
|
|
33
|
+
* JSON-style escapes, so a statement can never split into a second
|
|
34
|
+
* line even if a future writer forgets JSON.stringify. Quotation marks
|
|
35
|
+
* and backslashes are deliberately NOT touched here — the OKF line is
|
|
36
|
+
* canonical JSON and re-escaping them would corrupt parsing; JSON
|
|
37
|
+
* already guarantees they stay inside the string.
|
|
38
|
+
*/
|
|
39
|
+
export declare function escapeForOkfLine(text: string): string;
|
package/dist/escape.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* v1.0.0 (K10-027 / plan §5.7) — the untrusted-input boundary.
|
|
3
|
+
*
|
|
4
|
+
* One pure, total, idempotent escaping function per container Kevin
|
|
5
|
+
* writes stored text into. Every function here is a fixed point after
|
|
6
|
+
* one application — applying it twice equals applying it once — because
|
|
7
|
+
* a re-curated memory passes through the boundary on every regeneration
|
|
8
|
+
* and must not accumulate escaping.
|
|
9
|
+
*
|
|
10
|
+
* This module imports nothing and touches no filesystem. It is the
|
|
11
|
+
* boundary; the single enforcement point is ArtifactWriter (D6-01).
|
|
12
|
+
*/
|
|
13
|
+
const ENTITY_HEADS = /&(?!(amp|lt|gt|#\d+);)/g;
|
|
14
|
+
/**
|
|
15
|
+
* Neutralise text destined for the AGENTS.md marker block: HTML-escape
|
|
16
|
+
* (the memory-format discipline, made idempotent) so the literal
|
|
17
|
+
* `<!-- kevin:end -->` marker sequence and every comment terminator
|
|
18
|
+
* lose their meaning inside the block. The line-level strip of anything
|
|
19
|
+
* containing `kevin:begin`/`kevin:end` stays in
|
|
20
|
+
* ArtifactWriter.sanitizeArtifactBody — it is a filter, not an escape.
|
|
21
|
+
*/
|
|
22
|
+
export function escapeForMarkerBlock(text) {
|
|
23
|
+
return text
|
|
24
|
+
.replace(ENTITY_HEADS, "&")
|
|
25
|
+
.replace(/</g, "<")
|
|
26
|
+
.replace(/>/g, ">");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Neutralise fenced-code delimiters: any run of three or more backticks
|
|
30
|
+
* or tildes would close (or open) a markdown fence around the rendered
|
|
31
|
+
* block and let stored text masquerade as un-fenced document content.
|
|
32
|
+
* Each byte of the run becomes its numeric HTML entity, which renders
|
|
33
|
+
* identically but can never form a delimiter again.
|
|
34
|
+
*/
|
|
35
|
+
export function escapeForFence(text) {
|
|
36
|
+
return text
|
|
37
|
+
.replace(/`{3,}/g, (run) => "`".repeat(run.length))
|
|
38
|
+
.replace(/~{3,}/g, (run) => "~".repeat(run.length));
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Neutralise bytes that would terminate an OKF v2 line: newline,
|
|
42
|
+
* carriage return and every other C0 control character become their
|
|
43
|
+
* JSON-style escapes, so a statement can never split into a second
|
|
44
|
+
* line even if a future writer forgets JSON.stringify. Quotation marks
|
|
45
|
+
* and backslashes are deliberately NOT touched here — the OKF line is
|
|
46
|
+
* canonical JSON and re-escaping them would corrupt parsing; JSON
|
|
47
|
+
* already guarantees they stay inside the string.
|
|
48
|
+
*/
|
|
49
|
+
export function escapeForOkfLine(text) {
|
|
50
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: neutralising control bytes is this function's entire job
|
|
51
|
+
return text.replace(/[\u0000-\u001f]/g, (c) => {
|
|
52
|
+
if (c === "\n")
|
|
53
|
+
return "\\n";
|
|
54
|
+
if (c === "\r")
|
|
55
|
+
return "\\r";
|
|
56
|
+
if (c === "\t")
|
|
57
|
+
return "\\t";
|
|
58
|
+
return `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize an error/output string before fingerprinting.
|
|
3
|
+
*
|
|
4
|
+
* Steps:
|
|
5
|
+
* 1. Strip ANSI CSI sequences.
|
|
6
|
+
* 2. Lowercase (for case-insensitive matching of paths/extensions).
|
|
7
|
+
* 3. Replace `<path>.<ext>:<line>[:<col>` with `.<ext>` so the same
|
|
8
|
+
* error thrown from different files hashes the same.
|
|
9
|
+
* 4. Collapse all whitespace runs to a single space and trim.
|
|
10
|
+
*/
|
|
11
|
+
export declare function normalize(content: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Compute the FNV-1a 64-bit hash of `input`, returned as a 16-char
|
|
14
|
+
* lowercase hex string (zero-padded to 64 bits).
|
|
15
|
+
*
|
|
16
|
+
* FNV-1a: hash = offset_basis; for each byte: hash ^= byte; hash *= prime (mod 2^64).
|
|
17
|
+
*/
|
|
18
|
+
export declare function fnv1a64(input: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Fingerprint an error/output string. Optionally salt the hash with
|
|
21
|
+
* `project_id` so the same error text in two different projects
|
|
22
|
+
* produces two distinct fingerprints (per decision D2-11/D2-14).
|
|
23
|
+
*
|
|
24
|
+
* Salt is prepended and separated by a NUL byte to avoid accidental
|
|
25
|
+
* collisions where one project's name is a prefix of another's.
|
|
26
|
+
*/
|
|
27
|
+
export declare function fingerprint(content: string, project_id?: string): string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Kevin 0.2.0 — fingerprint (K2-003)
|
|
3
|
+
// ============================================================
|
|
4
|
+
// Deterministic, zero-dependency content hash used to dedup
|
|
5
|
+
// error memories and to throttle per-fingerprint reflection.
|
|
6
|
+
//
|
|
7
|
+
// We deliberately avoid node:crypto so the module is portable
|
|
8
|
+
// across plugin hosts and stays cheap. FNV-1a 64-bit gives a
|
|
9
|
+
// decent spread for short-to-medium error strings and is
|
|
10
|
+
// reproducible across runs and platforms (BigInt arithmetic).
|
|
11
|
+
// ============================================================
|
|
12
|
+
const FNV_OFFSET_BASIS = 0xcbf29ce484222325n;
|
|
13
|
+
const FNV_PRIME = 0x100000001b3n;
|
|
14
|
+
const FNV_MOD = 1n << 64n;
|
|
15
|
+
// ANSI CSI sequences (color codes, cursor moves, etc.).
|
|
16
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI stripping requires matching the ESC (\x1b) control char by definition.
|
|
17
|
+
const ANSI_RE = /\x1b\[[0-9;]*[A-Za-z]/g;
|
|
18
|
+
// Path-with-line-and-column references: `src/foo.ts:42:7` -> `.ts`.
|
|
19
|
+
// Matches any non-whitespace path prefix followed by a dotted
|
|
20
|
+
// extension and `:NN` or `:NN:NN` line/column markers. Useful for
|
|
21
|
+
// stripping absolute or per-repo paths before fingerprinting so
|
|
22
|
+
// the same error text in two repos/copy-paste edits hashes alike.
|
|
23
|
+
const PATH_LINE_RE = /[^\s:]*\.([a-z0-9]+):\d+(?::\d+)?/g;
|
|
24
|
+
// Whitespace collapse — preserves token order but ignores
|
|
25
|
+
// line-break and indentation differences.
|
|
26
|
+
const WS_RE = /\s+/g;
|
|
27
|
+
/**
|
|
28
|
+
* Normalize an error/output string before fingerprinting.
|
|
29
|
+
*
|
|
30
|
+
* Steps:
|
|
31
|
+
* 1. Strip ANSI CSI sequences.
|
|
32
|
+
* 2. Lowercase (for case-insensitive matching of paths/extensions).
|
|
33
|
+
* 3. Replace `<path>.<ext>:<line>[:<col>` with `.<ext>` so the same
|
|
34
|
+
* error thrown from different files hashes the same.
|
|
35
|
+
* 4. Collapse all whitespace runs to a single space and trim.
|
|
36
|
+
*/
|
|
37
|
+
export function normalize(content) {
|
|
38
|
+
return content
|
|
39
|
+
.replace(ANSI_RE, "")
|
|
40
|
+
.toLowerCase()
|
|
41
|
+
.replace(PATH_LINE_RE, ".$1")
|
|
42
|
+
.replace(WS_RE, " ")
|
|
43
|
+
.trim();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compute the FNV-1a 64-bit hash of `input`, returned as a 16-char
|
|
47
|
+
* lowercase hex string (zero-padded to 64 bits).
|
|
48
|
+
*
|
|
49
|
+
* FNV-1a: hash = offset_basis; for each byte: hash ^= byte; hash *= prime (mod 2^64).
|
|
50
|
+
*/
|
|
51
|
+
export function fnv1a64(input) {
|
|
52
|
+
let hash = FNV_OFFSET_BASIS;
|
|
53
|
+
for (let i = 0; i < input.length; i++) {
|
|
54
|
+
const byte = input.charCodeAt(i) & 0xff;
|
|
55
|
+
hash ^= BigInt(byte);
|
|
56
|
+
hash = (hash * FNV_PRIME) % FNV_MOD;
|
|
57
|
+
}
|
|
58
|
+
// Encode as 16-char lowercase hex.
|
|
59
|
+
return hash.toString(16).padStart(16, "0");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fingerprint an error/output string. Optionally salt the hash with
|
|
63
|
+
* `project_id` so the same error text in two different projects
|
|
64
|
+
* produces two distinct fingerprints (per decision D2-11/D2-14).
|
|
65
|
+
*
|
|
66
|
+
* Salt is prepended and separated by a NUL byte to avoid accidental
|
|
67
|
+
* collisions where one project's name is a prefix of another's.
|
|
68
|
+
*/
|
|
69
|
+
export function fingerprint(content, project_id) {
|
|
70
|
+
const normalized = normalize(content);
|
|
71
|
+
const salted = project_id ? `${project_id}\u0000${normalized}` : normalized;
|
|
72
|
+
return fnv1a64(salted);
|
|
73
|
+
}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type HostFlavour = "v1-only" | "v1+v2";
|
|
2
|
+
export interface HostProject {
|
|
3
|
+
readonly id: string | null;
|
|
4
|
+
readonly worktree: string | null;
|
|
5
|
+
readonly directory: string | null;
|
|
6
|
+
}
|
|
7
|
+
export interface HostSurface {
|
|
8
|
+
readonly pluginVersion: string | null;
|
|
9
|
+
readonly flavour: HostFlavour;
|
|
10
|
+
readonly project: HostProject;
|
|
11
|
+
readonly hasShell: boolean;
|
|
12
|
+
readonly v2: {
|
|
13
|
+
readonly skill: boolean;
|
|
14
|
+
readonly reference: boolean;
|
|
15
|
+
};
|
|
16
|
+
readonly notes: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export declare function summarize(s: HostSurface): string;
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function summarize(s) {
|
|
2
|
+
const version = s.pluginVersion ?? "unknown";
|
|
3
|
+
const shell = s.hasShell ? "yes" : "no";
|
|
4
|
+
const skill = s.v2.skill ? "yes" : "no";
|
|
5
|
+
const reference = s.v2.reference ? "yes" : "no";
|
|
6
|
+
return `host plugin ${version}, flavour ${s.flavour}, shell ${shell}, v2 skill ${skill}, v2 reference ${reference}`;
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const IDLE_STEP_ORDER: readonly ["ledger.settle", "archiver.run", "retrospective", "reflectors.boost", "reflectors.penalize", "patternMiner.mine", "conventionMiner.mine", "conflictDetector.detect", "causalChain.onSessionIdle", "mailbox", "curator.propose", "sharedLayer.import", "snapshots.flush", "sessionRecordedWork", "metrics.flush", "perf.flush", "liveness.flush"];
|
|
2
|
+
export type IdleStepName = (typeof IDLE_STEP_ORDER)[number];
|
|
3
|
+
export type IdlePipelineDeps = Partial<Record<IdleStepName, () => void | Promise<void>>>;
|
|
4
|
+
/**
|
|
5
|
+
* Run idle steps in canonical ORDER, executing only those present in deps.
|
|
6
|
+
* Each step is best-effort: a throwing step is swallowed so the chain continues,
|
|
7
|
+
* matching the adapter's `try { } catch { }` around each sub-step.
|
|
8
|
+
*/
|
|
9
|
+
export declare function composeIdlePipeline(deps: IdlePipelineDeps, order?: readonly IdleStepName[]): Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// K13-010 (D13-07) — single definition of session.idle step ORDER.
|
|
2
|
+
// Both adapter (live) and replay (hermetic) consume this pipeline so a re-order
|
|
3
|
+
// is visible in both paths. The audit demanded dedup of the hand-synced wiring.
|
|
4
|
+
//
|
|
5
|
+
// The pipeline is PURE sequencing: it receives injected step closures and runs
|
|
6
|
+
// them in ORDER, swallowing per-step errors (best-effort, same contract as the
|
|
7
|
+
// adapter's try/catch blocks around each idle sub-step).
|
|
8
|
+
export const IDLE_STEP_ORDER = [
|
|
9
|
+
"ledger.settle",
|
|
10
|
+
"archiver.run",
|
|
11
|
+
"retrospective",
|
|
12
|
+
"reflectors.boost",
|
|
13
|
+
"reflectors.penalize",
|
|
14
|
+
"patternMiner.mine",
|
|
15
|
+
"conventionMiner.mine",
|
|
16
|
+
"conflictDetector.detect",
|
|
17
|
+
"causalChain.onSessionIdle",
|
|
18
|
+
"mailbox",
|
|
19
|
+
"curator.propose",
|
|
20
|
+
"sharedLayer.import",
|
|
21
|
+
"snapshots.flush",
|
|
22
|
+
"sessionRecordedWork",
|
|
23
|
+
"metrics.flush",
|
|
24
|
+
"perf.flush",
|
|
25
|
+
"liveness.flush",
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* Run idle steps in canonical ORDER, executing only those present in deps.
|
|
29
|
+
* Each step is best-effort: a throwing step is swallowed so the chain continues,
|
|
30
|
+
* matching the adapter's `try { } catch { }` around each sub-step.
|
|
31
|
+
*/
|
|
32
|
+
export async function composeIdlePipeline(deps, order = IDLE_STEP_ORDER) {
|
|
33
|
+
for (const name of order) {
|
|
34
|
+
const fn = deps[name];
|
|
35
|
+
if (!fn)
|
|
36
|
+
continue;
|
|
37
|
+
try {
|
|
38
|
+
await fn();
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// best-effort — identical to adapter's per-step try/catch
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export * from "./Store.js";
|
|
2
|
+
export * from "./Migrate.js";
|
|
3
|
+
export { MemoryService, DATE_NOW, mapRow, readOriginCallId, countSupersedeCandidates, hasRepoIdColumn } from "./MemoryService.js";
|
|
4
|
+
export type { Memory, SlimMemory, SlimMemoryWithEvidence, SaveInput, QueryInput, GetRelevantInput, MemoryType, MemoryScope, MemoryOrigin, MemoryUpdateResult } from "./MemoryService.js";
|
|
5
|
+
export * from "./ToolCallObserver.js";
|
|
6
|
+
export * from "./Reflector.js";
|
|
7
|
+
export * from "./ContextInjector.js";
|
|
8
|
+
export * from "./QualityGate.js";
|
|
9
|
+
export * from "./InjectionLedger.js";
|
|
10
|
+
export * from "./Curator.js";
|
|
11
|
+
export * from "./ArtifactWriter.js";
|
|
12
|
+
export * from "./SharedLayer.js";
|
|
13
|
+
export * from "./RepoIdentity.js";
|
|
14
|
+
export * from "./RepoTruth.js";
|
|
15
|
+
export * from "./ConflictDetector.js";
|
|
16
|
+
export * from "./CausalChain.js";
|
|
17
|
+
export * from "./PatternMiner.js";
|
|
18
|
+
export * from "./ConventionMiner.js";
|
|
19
|
+
export * from "./Feedback.js";
|
|
20
|
+
export * from "./Archiver.js";
|
|
21
|
+
export * from "./Retrospective.js";
|
|
22
|
+
export * from "./Materializer.js";
|
|
23
|
+
export * from "./HookLiveness.js";
|
|
24
|
+
export * from "./perf.js";
|
|
25
|
+
export * from "./metrics.js";
|
|
26
|
+
export * from "./okf.js";
|
|
27
|
+
export * from "./okf-export.js";
|
|
28
|
+
export * from "./okf-import.js";
|
|
29
|
+
export * from "./LessonFixer.js";
|
|
30
|
+
export * from "./contract.js";
|
|
31
|
+
export * from "./confidence.js";
|
|
32
|
+
export * from "./diff.js";
|
|
33
|
+
export * from "./escape.js";
|
|
34
|
+
export * from "./fingerprint.js";
|
|
35
|
+
export * from "./inferability.js";
|
|
36
|
+
export * from "./query-tokenizer.js";
|
|
37
|
+
export * from "./memory-format.js";
|
|
38
|
+
export * from "./redact.js";
|
|
39
|
+
export * from "./uuid.js";
|
|
40
|
+
export * from "./sqlite-adapter.js";
|
|
41
|
+
export { hasColumn, hasIgnoredColumn, hasCuratedColumn, hasTruthColumns, hasLayerColumn, hasRecurrenceColumn, hasArchivedColumn, hasFeedbackColumns, hasFeedbackTable } from "./columns.js";
|
|
42
|
+
export * from "./time-ms.js";
|
|
43
|
+
export * from "./idle-pipeline.js";
|
|
44
|
+
export * from "./replay.js";
|
|
45
|
+
export * from "./replay-types.js";
|
|
46
|
+
export * from "./ChatBridge.js";
|
|
47
|
+
export * from "./DashboardHtml.js";
|
|
48
|
+
export { deleteMailbox, processActions, readMailbox, writeResults, verifyFresh, consumeMailbox } from "./TuiActions.js";
|
|
49
|
+
export type { MailboxReadResult, PendingProposal, ProcessDeps, ActionStatus } from "./TuiActions.js";
|
|
50
|
+
export * from "./TuiSnapshots.js";
|
|
51
|
+
export type { ProposalView, ConflictView, HealthView, TuiSnapshotSet, TuiAction, ActionResult } from "./tui-types.js";
|
|
52
|
+
export * from "./capabilities.js";
|
|
53
|
+
export * from "./host.js";
|
|
54
|
+
export { V2_SPECIFIER } from "./native.js";
|
|
55
|
+
export type { NativeDeps, NativeRegistration, SettingsReader } from "./native.js";
|
|
56
|
+
export * from "./kevin_approve.js";
|
|
57
|
+
export { buildAudit, type AuditReport, type ChannelReport, type CurationReport, type TruthReport, type EmissionState } from "./kevin_audit.js";
|
|
58
|
+
export * from "./kevin_bench.js";
|
|
59
|
+
export * from "./kevin_conflicts.js";
|
|
60
|
+
export * from "./kevin_contract.js";
|
|
61
|
+
export * from "./kevin_doctor.js";
|
|
62
|
+
export * from "./kevin_facts.js";
|
|
63
|
+
export * from "./kevin_forget.js";
|
|
64
|
+
export { handleNative } from "./kevin_native.js";
|
|
65
|
+
export * from "./kevin_propose.js";
|
|
66
|
+
export { kevinPublish } from "./kevin_publish.js";
|
|
67
|
+
export type { PublishResult } from "./kevin_publish.js";
|
|
68
|
+
export * from "./kevin_why.js";
|
|
69
|
+
export * from "./env.js";
|
|
70
|
+
export declare const KEVIN_CONFIG_KEYS: readonly ["quality_gate_enabled", "lesson_snippet_injection", "patternminer_enabled", "cross_project_enabled", "llm_reflection_enabled", "tool_calls_dedup_enabled", "deterministic_retrieval", "pre_prompt_budget_tokens", "archive_after_days", "curation_enabled", "agents_md_path", "skill_emission_enabled", "reference_emission_enabled", "injection_confidence_floor", "repo_truth_enabled", "convention_mining_enabled", "conflict_detection_enabled", "error_lesson_mode", "shared_layer_enabled", "okf_path", "share_requires_approval", "author_identity_mode", "shared_confidence_floor", "hook_liveness_enabled", "native_registration_enabled", "host_probe_history_enabled", "dead_hook_report_threshold", "perf_enabled", "perf_ring_capacity", "perf_flush_on_idle", "contract_report_enabled", "tui_snapshots_enabled"];
|
|
71
|
+
export declare const ERROR_LESSON_MODE_VALUES: readonly ["all", "triage_only"];
|
|
72
|
+
export declare const KEVIN_VERSION = "1.3.0";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// @jmtrin/kevin-core public entry — Bedrock (K13-002)
|
|
2
|
+
// Explicit re-export list defines future C-10 surface; keep minimal and deliberate.
|
|
3
|
+
export * from "./Store.js";
|
|
4
|
+
export * from "./Migrate.js";
|
|
5
|
+
// MemoryService has duplicate hasRepoIdColumn with columns.ts — export selectively (keep MemoryService's hasRepoIdColumn, columns provides other helpers)
|
|
6
|
+
export { MemoryService, DATE_NOW, mapRow, readOriginCallId, countSupersedeCandidates, hasRepoIdColumn } from "./MemoryService.js";
|
|
7
|
+
export * from "./ToolCallObserver.js";
|
|
8
|
+
export * from "./Reflector.js";
|
|
9
|
+
export * from "./ContextInjector.js";
|
|
10
|
+
export * from "./QualityGate.js";
|
|
11
|
+
export * from "./InjectionLedger.js";
|
|
12
|
+
export * from "./Curator.js";
|
|
13
|
+
export * from "./ArtifactWriter.js";
|
|
14
|
+
export * from "./SharedLayer.js";
|
|
15
|
+
export * from "./RepoIdentity.js";
|
|
16
|
+
export * from "./RepoTruth.js";
|
|
17
|
+
export * from "./ConflictDetector.js";
|
|
18
|
+
export * from "./CausalChain.js";
|
|
19
|
+
export * from "./PatternMiner.js";
|
|
20
|
+
export * from "./ConventionMiner.js";
|
|
21
|
+
export * from "./Feedback.js";
|
|
22
|
+
export * from "./Archiver.js";
|
|
23
|
+
export * from "./Retrospective.js";
|
|
24
|
+
export * from "./Materializer.js";
|
|
25
|
+
export * from "./HookLiveness.js";
|
|
26
|
+
export * from "./perf.js";
|
|
27
|
+
export * from "./metrics.js";
|
|
28
|
+
export * from "./okf.js";
|
|
29
|
+
export * from "./okf-export.js";
|
|
30
|
+
export * from "./okf-import.js";
|
|
31
|
+
export * from "./LessonFixer.js";
|
|
32
|
+
export * from "./contract.js";
|
|
33
|
+
export * from "./confidence.js";
|
|
34
|
+
export * from "./diff.js";
|
|
35
|
+
export * from "./escape.js";
|
|
36
|
+
export * from "./fingerprint.js";
|
|
37
|
+
export * from "./inferability.js";
|
|
38
|
+
export * from "./query-tokenizer.js";
|
|
39
|
+
export * from "./memory-format.js";
|
|
40
|
+
export * from "./redact.js";
|
|
41
|
+
export * from "./uuid.js";
|
|
42
|
+
export * from "./sqlite-adapter.js";
|
|
43
|
+
// columns has duplicate hasRepoIdColumn with MemoryService — export without that function (MemoryService's version is canonical via index)
|
|
44
|
+
export { hasColumn, hasIgnoredColumn, hasCuratedColumn, hasTruthColumns, hasLayerColumn, hasRecurrenceColumn, hasArchivedColumn, hasFeedbackColumns, hasFeedbackTable } from "./columns.js";
|
|
45
|
+
export * from "./time-ms.js";
|
|
46
|
+
export * from "./idle-pipeline.js";
|
|
47
|
+
export * from "./replay.js";
|
|
48
|
+
export * from "./replay-types.js";
|
|
49
|
+
export * from "./ChatBridge.js";
|
|
50
|
+
export * from "./DashboardHtml.js";
|
|
51
|
+
// TuiActions duplicates proposalToken with DashboardHtml — export selectively (exclude proposalToken)
|
|
52
|
+
export { deleteMailbox, processActions, readMailbox, writeResults, verifyFresh, consumeMailbox } from "./TuiActions.js";
|
|
53
|
+
export * from "./TuiSnapshots.js";
|
|
54
|
+
// shims for isolation
|
|
55
|
+
export * from "./capabilities.js";
|
|
56
|
+
export * from "./host.js";
|
|
57
|
+
export { V2_SPECIFIER } from "./native.js";
|
|
58
|
+
// kevin_* handlers — avoid duplicate EmissionState / NativeDeps
|
|
59
|
+
export * from "./kevin_approve.js";
|
|
60
|
+
export { buildAudit } from "./kevin_audit.js";
|
|
61
|
+
export * from "./kevin_bench.js";
|
|
62
|
+
export * from "./kevin_conflicts.js";
|
|
63
|
+
export * from "./kevin_contract.js";
|
|
64
|
+
export * from "./kevin_doctor.js";
|
|
65
|
+
export * from "./kevin_facts.js";
|
|
66
|
+
export * from "./kevin_forget.js";
|
|
67
|
+
export { handleNative } from "./kevin_native.js";
|
|
68
|
+
export * from "./kevin_propose.js";
|
|
69
|
+
export { kevinPublish } from "./kevin_publish.js";
|
|
70
|
+
export * from "./kevin_why.js";
|
|
71
|
+
// KEVIN_CONFIG_KEYS and related constants — moved from adapter index so core owns the source of truth (C-04).
|
|
72
|
+
// Duplicated here to allow adapter to import from core; adapter will re-export them.
|
|
73
|
+
export * from "./env.js";
|
|
74
|
+
export const KEVIN_CONFIG_KEYS = [
|
|
75
|
+
"quality_gate_enabled",
|
|
76
|
+
"lesson_snippet_injection",
|
|
77
|
+
"patternminer_enabled",
|
|
78
|
+
"cross_project_enabled",
|
|
79
|
+
"llm_reflection_enabled",
|
|
80
|
+
"tool_calls_dedup_enabled",
|
|
81
|
+
"deterministic_retrieval",
|
|
82
|
+
"pre_prompt_budget_tokens",
|
|
83
|
+
"archive_after_days",
|
|
84
|
+
"curation_enabled",
|
|
85
|
+
"agents_md_path",
|
|
86
|
+
"skill_emission_enabled",
|
|
87
|
+
"reference_emission_enabled",
|
|
88
|
+
"injection_confidence_floor",
|
|
89
|
+
"repo_truth_enabled",
|
|
90
|
+
"convention_mining_enabled",
|
|
91
|
+
"conflict_detection_enabled",
|
|
92
|
+
"error_lesson_mode",
|
|
93
|
+
"shared_layer_enabled",
|
|
94
|
+
"okf_path",
|
|
95
|
+
"share_requires_approval",
|
|
96
|
+
"author_identity_mode",
|
|
97
|
+
"shared_confidence_floor",
|
|
98
|
+
"hook_liveness_enabled",
|
|
99
|
+
"native_registration_enabled",
|
|
100
|
+
"host_probe_history_enabled",
|
|
101
|
+
"dead_hook_report_threshold",
|
|
102
|
+
"perf_enabled",
|
|
103
|
+
"perf_ring_capacity",
|
|
104
|
+
"perf_flush_on_idle",
|
|
105
|
+
"contract_report_enabled",
|
|
106
|
+
"tui_snapshots_enabled",
|
|
107
|
+
];
|
|
108
|
+
export const ERROR_LESSON_MODE_VALUES = ["all", "triage_only"];
|
|
109
|
+
export const KEVIN_VERSION = "1.3.0";
|