@vainplex/openclaw-leuko 0.1.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 (65) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/LICENSE +21 -0
  3. package/README.md +160 -0
  4. package/dist/src/check-runner.d.ts +65 -0
  5. package/dist/src/check-runner.d.ts.map +1 -0
  6. package/dist/src/check-runner.js +40 -0
  7. package/dist/src/check-runner.js.map +1 -0
  8. package/dist/src/check-utils.d.ts +21 -0
  9. package/dist/src/check-utils.d.ts.map +1 -0
  10. package/dist/src/check-utils.js +39 -0
  11. package/dist/src/check-utils.js.map +1 -0
  12. package/dist/src/checks/anomaly-detection.d.ts +3 -0
  13. package/dist/src/checks/anomaly-detection.d.ts.map +1 -0
  14. package/dist/src/checks/anomaly-detection.js +127 -0
  15. package/dist/src/checks/anomaly-detection.js.map +1 -0
  16. package/dist/src/checks/bootstrap-integrity.d.ts +3 -0
  17. package/dist/src/checks/bootstrap-integrity.d.ts.map +1 -0
  18. package/dist/src/checks/bootstrap-integrity.js +107 -0
  19. package/dist/src/checks/bootstrap-integrity.js.map +1 -0
  20. package/dist/src/checks/goal-quality.d.ts +3 -0
  21. package/dist/src/checks/goal-quality.d.ts.map +1 -0
  22. package/dist/src/checks/goal-quality.js +143 -0
  23. package/dist/src/checks/goal-quality.js.map +1 -0
  24. package/dist/src/checks/pipeline-correlation.d.ts +7 -0
  25. package/dist/src/checks/pipeline-correlation.d.ts.map +1 -0
  26. package/dist/src/checks/pipeline-correlation.js +118 -0
  27. package/dist/src/checks/pipeline-correlation.js.map +1 -0
  28. package/dist/src/checks/recommendations.d.ts +3 -0
  29. package/dist/src/checks/recommendations.d.ts.map +1 -0
  30. package/dist/src/checks/recommendations.js +132 -0
  31. package/dist/src/checks/recommendations.js.map +1 -0
  32. package/dist/src/checks/thread-health.d.ts +3 -0
  33. package/dist/src/checks/thread-health.d.ts.map +1 -0
  34. package/dist/src/checks/thread-health.js +129 -0
  35. package/dist/src/checks/thread-health.js.map +1 -0
  36. package/dist/src/config.d.ts +10 -0
  37. package/dist/src/config.d.ts.map +1 -0
  38. package/dist/src/config.js +301 -0
  39. package/dist/src/config.js.map +1 -0
  40. package/dist/src/index.d.ts +27 -0
  41. package/dist/src/index.d.ts.map +1 -0
  42. package/dist/src/index.js +198 -0
  43. package/dist/src/index.js.map +1 -0
  44. package/dist/src/llm-client.d.ts +7 -0
  45. package/dist/src/llm-client.d.ts.map +1 -0
  46. package/dist/src/llm-client.js +111 -0
  47. package/dist/src/llm-client.js.map +1 -0
  48. package/dist/src/status-reader.d.ts +6 -0
  49. package/dist/src/status-reader.d.ts.map +1 -0
  50. package/dist/src/status-reader.js +156 -0
  51. package/dist/src/status-reader.js.map +1 -0
  52. package/dist/src/status-writer.d.ts +14 -0
  53. package/dist/src/status-writer.d.ts.map +1 -0
  54. package/dist/src/status-writer.js +52 -0
  55. package/dist/src/status-writer.js.map +1 -0
  56. package/dist/src/tool.d.ts +9 -0
  57. package/dist/src/tool.d.ts.map +1 -0
  58. package/dist/src/tool.js +129 -0
  59. package/dist/src/tool.js.map +1 -0
  60. package/dist/src/types.d.ts +261 -0
  61. package/dist/src/types.d.ts.map +1 -0
  62. package/dist/src/types.js +5 -0
  63. package/dist/src/types.js.map +1 -0
  64. package/openclaw.plugin.json +22 -0
  65. package/package.json +51 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap-integrity.js","sourceRoot":"","sources":["../../../src/checks/bootstrap-integrity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CognitiveCheckResult, GoalQualityCheckConfig, LlmClient, PluginLogger } from "../types.js";
2
+ export declare function runGoalQualityCheck(config: GoalQualityCheckConfig, llm: LlmClient, logger: PluginLogger): Promise<CognitiveCheckResult>;
3
+ //# sourceMappingURL=goal-quality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-quality.d.ts","sourceRoot":"","sources":["../../../src/checks/goal-quality.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,sBAAsB,EACtB,SAAS,EAET,YAAY,EACb,MAAM,aAAa,CAAC;AA4GrB,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,sBAAsB,EAC9B,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,oBAAoB,CAAC,CA2D/B"}
@@ -0,0 +1,143 @@
1
+ import { readJsonInput } from "../status-reader.js";
2
+ import { parseSeverityString, worstSeverity } from "../check-utils.js";
3
+ import { runLlmCheck } from "../check-runner.js";
4
+ const CHECK_NAME = "cognitive:goal_quality";
5
+ const SYSTEM_PROMPT = `You are a system health evaluator. Analyze the pending goals and assess their quality.
6
+ Respond ONLY with valid JSON matching this schema:
7
+ {
8
+ "severity": "ok" | "warn" | "critical",
9
+ "detail": "single line summary",
10
+ "findings": [
11
+ {
12
+ "item_id": "goal id",
13
+ "issue": "vague_title" | "duplicate" | "expired" | "no_action" | "noise",
14
+ "detail": "explanation",
15
+ "recommendation": "what to do"
16
+ }
17
+ ]
18
+ }
19
+
20
+ Evaluation rules:
21
+ - Is each goal specific enough to act on? Vague goals like "Fix recurring general failures" are WARN
22
+ - Are there near-duplicates? Multiple similar "Fix recurring X failures" → WARN: consolidate
23
+ - Does proposed_action contain a real plan or just a placeholder?
24
+ - Are expired goals present? (expires < current date → WARN)
25
+ - If ALL goals are specific and actionable → severity "ok"
26
+ - If ≥1 vague/duplicate/expired goal → severity "warn"
27
+ - If ≥50% of goals are noise → severity "critical"`;
28
+ function extractGoals(data) {
29
+ if (Array.isArray(data))
30
+ return data;
31
+ if (typeof data === "object" && data !== null) {
32
+ const obj = data;
33
+ if (Array.isArray(obj.goals))
34
+ return obj.goals;
35
+ if (Array.isArray(obj.pending_goals))
36
+ return obj.pending_goals;
37
+ }
38
+ return [];
39
+ }
40
+ function preFilterGoals(goals) {
41
+ const findings = [];
42
+ const now = Date.now();
43
+ for (const goal of goals) {
44
+ checkExpired(goal, now, findings);
45
+ checkStaleProposal(goal, now, findings);
46
+ }
47
+ return findings;
48
+ }
49
+ function checkExpired(goal, now, out) {
50
+ if (!goal.expires)
51
+ return;
52
+ const expiryMs = new Date(goal.expires).getTime();
53
+ if (!isNaN(expiryMs) && expiryMs < now) {
54
+ out.push({
55
+ item_id: goal.id,
56
+ issue: "expired",
57
+ detail: `Goal "${goal.title}" expired on ${goal.expires}`,
58
+ recommendation: "Remove or renew this goal",
59
+ });
60
+ }
61
+ }
62
+ function checkStaleProposal(goal, now, out) {
63
+ if (!goal.proposed_at || goal.status !== "proposed")
64
+ return;
65
+ const proposedMs = new Date(goal.proposed_at).getTime();
66
+ if (!isNaN(proposedMs) && now - proposedMs > 48 * 60 * 60 * 1000) {
67
+ out.push({
68
+ item_id: goal.id,
69
+ issue: "stale_proposal",
70
+ detail: `Goal "${goal.title}" proposed ${Math.round((now - proposedMs) / 3600000)}h ago, still not approved`,
71
+ recommendation: "Review and approve or reject this goal",
72
+ });
73
+ }
74
+ }
75
+ function mergeLlmFindings(preFindings, parsed) {
76
+ const llmFindings = Array.isArray(parsed.findings)
77
+ ? parsed.findings.map((f) => ({
78
+ item_id: typeof f.item_id === "string" ? f.item_id : undefined,
79
+ issue: typeof f.issue === "string" ? f.issue : "unknown",
80
+ detail: typeof f.detail === "string" ? f.detail : "",
81
+ recommendation: typeof f.recommendation === "string" ? f.recommendation : undefined,
82
+ }))
83
+ : [];
84
+ const seenIds = new Set(preFindings.map((f) => f.item_id).filter(Boolean));
85
+ const unique = llmFindings.filter((f) => !f.item_id || !seenIds.has(f.item_id));
86
+ return [...preFindings, ...unique];
87
+ }
88
+ export async function runGoalQualityCheck(config, llm, logger) {
89
+ return runLlmCheck({
90
+ name: CHECK_NAME,
91
+ systemPrompt: SYSTEM_PROMPT,
92
+ llm,
93
+ logger,
94
+ readInput(timestamp, startMs) {
95
+ const rawData = readJsonInput(config.inputPath, logger);
96
+ if (rawData === null) {
97
+ return { ok: false, skip: { check_name: CHECK_NAME, severity: "ok", detail: "Goals file not found — check skipped", timestamp, duration_ms: Date.now() - startMs } };
98
+ }
99
+ const goals = extractGoals(rawData);
100
+ if (goals.length === 0) {
101
+ return { ok: false, skip: { check_name: CHECK_NAME, severity: "ok", detail: "No pending goals found", timestamp, duration_ms: Date.now() - startMs } };
102
+ }
103
+ return { ok: true, input: goals };
104
+ },
105
+ preFilter(goals) {
106
+ const findings = preFilterGoals(goals);
107
+ return { severity: findings.length > 0 ? "warn" : "ok", findingCount: findings.length, data: { findings } };
108
+ },
109
+ buildPrompt(goals) {
110
+ const goalsText = JSON.stringify(goals, null, 2).substring(0, 4000);
111
+ return `Current date: ${new Date().toISOString().split("T")[0]}\n\nPending goals (${goals.length} total):\n${goalsText}`;
112
+ },
113
+ buildFailOpen({ pre, message, llmModel, llmTokens, timestamp, startMs }) {
114
+ const preFindings = pre.data["findings"];
115
+ return {
116
+ check_name: CHECK_NAME,
117
+ severity: pre.severity,
118
+ detail: `${message} — ${pre.findingCount} pre-filter findings`,
119
+ findings: preFindings,
120
+ timestamp,
121
+ model_used: llmModel,
122
+ tokens_used: llmTokens,
123
+ duration_ms: Date.now() - startMs,
124
+ };
125
+ },
126
+ mergeResults(opts) {
127
+ const preFindings = opts.pre.data["findings"];
128
+ const allFindings = mergeLlmFindings(preFindings, opts.parsed);
129
+ const severity = worstSeverity(parseSeverityString(opts.parsed.severity), opts.pre.severity);
130
+ return {
131
+ check_name: CHECK_NAME,
132
+ severity,
133
+ detail: typeof opts.parsed.detail === "string" ? opts.parsed.detail : `${allFindings.length} findings`,
134
+ findings: allFindings,
135
+ timestamp: opts.timestamp,
136
+ model_used: opts.llmModel,
137
+ tokens_used: opts.llmTokens,
138
+ duration_ms: Date.now() - opts.startMs,
139
+ };
140
+ },
141
+ });
142
+ }
143
+ //# sourceMappingURL=goal-quality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-quality.js","sourceRoot":"","sources":["../../../src/checks/goal-quality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { CognitiveCheckResult, PipelineCorrelationCheckConfig, LeukoStatus, PluginLogger } from "../types.js";
2
+ export interface PipelineCorrelationDeps {
3
+ threadsPath: string;
4
+ daemonChecks: LeukoStatus["daemon_checks"];
5
+ }
6
+ export declare function runPipelineCorrelationCheck(config: PipelineCorrelationCheckConfig, deps: PipelineCorrelationDeps, logger: PluginLogger): CognitiveCheckResult;
7
+ //# sourceMappingURL=pipeline-correlation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-correlation.d.ts","sourceRoot":"","sources":["../../../src/checks/pipeline-correlation.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EAEpB,8BAA8B,EAC9B,WAAW,EACX,YAAY,EAEb,MAAM,aAAa,CAAC;AAwDrB,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,WAAW,CAAC,eAAe,CAAC,CAAC;CAC5C;AAoED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,8BAA8B,EACtC,IAAI,EAAE,uBAAuB,EAC7B,MAAM,EAAE,YAAY,GACnB,oBAAoB,CAYtB"}
@@ -0,0 +1,118 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { statSync, existsSync } from "node:fs";
3
+ import { worstSeverity } from "../check-utils.js";
4
+ const CHECK_NAME = "cognitive:pipeline_correlation";
5
+ /**
6
+ * Try to get NATS stream message count via CLI.
7
+ * Returns null if nats CLI not available or fails.
8
+ */
9
+ function getNatsEventCount(stream, logger) {
10
+ try {
11
+ const result = execFileSync("nats", ["stream", "info", stream, "--json"], {
12
+ timeout: 5000,
13
+ encoding: "utf-8",
14
+ stdio: ["pipe", "pipe", "pipe"],
15
+ });
16
+ const parsed = JSON.parse(result);
17
+ if (typeof parsed !== "object" || parsed === null)
18
+ return null;
19
+ const state = parsed["state"];
20
+ if (typeof state === "object" && state !== null) {
21
+ const msgs = state["messages"];
22
+ if (typeof msgs === "number")
23
+ return msgs;
24
+ }
25
+ return null;
26
+ }
27
+ catch {
28
+ logger.debug("[leuko] NATS CLI not available or stream not found");
29
+ return null;
30
+ }
31
+ }
32
+ function fileAgeHours(path) {
33
+ try {
34
+ if (!existsSync(path))
35
+ return null;
36
+ return (Date.now() - statSync(path).mtimeMs) / (60 * 60 * 1000);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ function isBusinessHours(bh) {
43
+ const hour = new Date().getUTCHours() + 1;
44
+ return hour >= bh.start && hour < bh.end;
45
+ }
46
+ function getCronStatus(daemonChecks) {
47
+ let allOk = true;
48
+ let staleOutputs = 0;
49
+ for (const check of daemonChecks) {
50
+ if (check.check_name.startsWith("cron_health:") && check.severity !== "ok")
51
+ allOk = false;
52
+ if (check.check_name.startsWith("output_freshness:") && check.severity !== "ok")
53
+ staleOutputs++;
54
+ }
55
+ return { allOk, staleOutputs };
56
+ }
57
+ function gatherSignals(config, deps, logger) {
58
+ return {
59
+ natsTotal: getNatsEventCount(config.natsStream, logger),
60
+ threadsAgeH: fileAgeHours(deps.threadsPath),
61
+ cronStatus: getCronStatus(deps.daemonChecks),
62
+ inBusinessHours: isBusinessHours(config.businessHours),
63
+ };
64
+ }
65
+ function buildCorrelations(signals, windowHours) {
66
+ const correlations = [];
67
+ addNatsThreadCorrelation(signals, windowHours, correlations);
68
+ addPipelineDisconnectCorrelation(signals, correlations);
69
+ addEventSourceSilentCorrelation(signals, correlations);
70
+ return correlations;
71
+ }
72
+ function addNatsThreadCorrelation(s, windowH, out) {
73
+ if (s.natsTotal === null || s.natsTotal <= 0 || s.threadsAgeH === null)
74
+ return;
75
+ if (s.threadsAgeH > 4) {
76
+ out.push({ input: "nats_total_messages", input_value: s.natsTotal, output: "threads_age_hours", output_value: Math.round(s.threadsAgeH * 10) / 10, diagnosis: "consumer_disconnected" });
77
+ }
78
+ else if (s.threadsAgeH > windowH) {
79
+ out.push({ input: "nats_total_messages", input_value: s.natsTotal, output: "threads_age_hours", output_value: Math.round(s.threadsAgeH * 10) / 10, diagnosis: "consumer_slow" });
80
+ }
81
+ }
82
+ function addPipelineDisconnectCorrelation(s, out) {
83
+ if (s.cronStatus.allOk && s.cronStatus.staleOutputs >= 2) {
84
+ out.push({ input: "crons_all_ok", input_value: 1, output: "stale_outputs", output_value: s.cronStatus.staleOutputs, diagnosis: "pipeline_disconnected" });
85
+ }
86
+ }
87
+ function addEventSourceSilentCorrelation(s, out) {
88
+ if (s.natsTotal !== null && s.natsTotal === 0 && s.inBusinessHours) {
89
+ out.push({ input: "nats_events", input_value: 0, output: "business_hours", output_value: 1, diagnosis: "event_source_silent" });
90
+ }
91
+ }
92
+ function computeCorrelationSeverity(correlations) {
93
+ let severity = "ok";
94
+ for (const c of correlations) {
95
+ if (c.diagnosis === "consumer_disconnected" && c.output_value > 4) {
96
+ severity = worstSeverity(severity, "critical");
97
+ }
98
+ else if (c.diagnosis === "consumer_disconnected") {
99
+ severity = worstSeverity(severity, "warn");
100
+ }
101
+ else if (c.diagnosis === "pipeline_disconnected" || c.diagnosis === "event_source_silent") {
102
+ severity = worstSeverity(severity, "warn");
103
+ }
104
+ }
105
+ return severity;
106
+ }
107
+ export function runPipelineCorrelationCheck(config, deps, logger) {
108
+ const startMs = Date.now();
109
+ const timestamp = new Date().toISOString();
110
+ const signals = gatherSignals(config, deps, logger);
111
+ const correlations = buildCorrelations(signals, config.correlationWindowHours);
112
+ const severity = computeCorrelationSeverity(correlations);
113
+ const detail = correlations.length === 0
114
+ ? "All pipeline correlations normal"
115
+ : `${correlations.length} correlation issue(s) detected`;
116
+ return { check_name: CHECK_NAME, severity, detail, correlations, timestamp, duration_ms: Date.now() - startMs };
117
+ }
118
+ //# sourceMappingURL=pipeline-correlation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline-correlation.js","sourceRoot":"","sources":["../../../src/checks/pipeline-correlation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CognitiveCheckResult, RecommendationsCheckConfig, LlmClient, LeukoStatus, LeukoHistory, PluginLogger } from "../types.js";
2
+ export declare function runRecommendationsCheck(config: RecommendationsCheckConfig, llm: LlmClient, currentResults: CognitiveCheckResult[], status: LeukoStatus | null, _history: LeukoHistory | null, logger: PluginLogger): Promise<CognitiveCheckResult>;
3
+ //# sourceMappingURL=recommendations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommendations.d.ts","sourceRoot":"","sources":["../../../src/checks/recommendations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,0BAA0B,EAC1B,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,EACb,MAAM,aAAa,CAAC;AA2GrB,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,0BAA0B,EAClC,GAAG,EAAE,SAAS,EACd,cAAc,EAAE,oBAAoB,EAAE,EACtC,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,QAAQ,EAAE,YAAY,GAAG,IAAI,EAC7B,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAsD/B"}
@@ -0,0 +1,132 @@
1
+ import { parseSeverityString } from "../check-utils.js";
2
+ import { runLlmCheck } from "../check-runner.js";
3
+ const CHECK_NAME = "cognitive:recommendations";
4
+ const SYSTEM_PROMPT = `You are a system health advisor. Based on the current check results and system history, generate housekeeping recommendations.
5
+ Respond ONLY with valid JSON matching this schema:
6
+ {
7
+ "severity": "ok" | "warn" | "critical",
8
+ "detail": "N recommendations generated",
9
+ "recommendations": [
10
+ {
11
+ "type": "archive_thread" | "cleanup_goals" | "adjust_config" | "investigate" | "maintenance",
12
+ "target": "what to act on",
13
+ "reason": "why this is recommended",
14
+ "priority": "low" | "medium" | "high"
15
+ }
16
+ ]
17
+ }
18
+
19
+ Rules:
20
+ - Patterns in heal history (same check failing repeatedly → systemic issue)
21
+ - Stale threads/goals → archive candidates
22
+ - Cron jobs with repeated warnings → config change suggestion
23
+ - L1 checks stuck on warn for > 48h → needs human investigation
24
+ - severity "ok" when there are only low-priority suggestions
25
+ - severity "warn" when there are medium/high priority recommendations
26
+ - Maximum recommendations: as specified`;
27
+ function buildFindingsSummary(currentResults, status) {
28
+ const sections = ["=== Current Cognitive Check Results ==="];
29
+ for (const result of currentResults) {
30
+ sections.push(`${result.check_name}: ${result.severity} — ${result.detail}`);
31
+ appendFindings(result, sections);
32
+ appendCorrelations(result, sections);
33
+ appendAnomalies(result, sections);
34
+ }
35
+ appendDaemonIssues(status, sections);
36
+ return sections.join("\n").substring(0, 4000);
37
+ }
38
+ function appendFindings(result, out) {
39
+ if (!result.findings || result.findings.length === 0)
40
+ return;
41
+ for (const f of result.findings.slice(0, 5)) {
42
+ out.push(` - ${f.issue}: ${f.detail}`);
43
+ }
44
+ }
45
+ function appendCorrelations(result, out) {
46
+ if (!result.correlations || result.correlations.length === 0)
47
+ return;
48
+ for (const c of result.correlations.slice(0, 5)) {
49
+ out.push(` - ${c.diagnosis}: ${c.input}=${c.input_value} → ${c.output}=${c.output_value}`);
50
+ }
51
+ }
52
+ function appendAnomalies(result, out) {
53
+ if (!result.anomalies || result.anomalies.length === 0)
54
+ return;
55
+ for (const a of result.anomalies.slice(0, 5)) {
56
+ out.push(` - ${a.metric}: ${a.deviation}`);
57
+ }
58
+ }
59
+ function appendDaemonIssues(status, out) {
60
+ if (!status)
61
+ return;
62
+ const issues = status.daemon_checks.filter((c) => c.severity !== "ok");
63
+ if (issues.length === 0)
64
+ return;
65
+ out.push("\n=== Current Daemon Issues ===");
66
+ for (const issue of issues) {
67
+ out.push(`${issue.check_name}: ${issue.severity} — ${issue.detail}`);
68
+ }
69
+ }
70
+ function parseRecommendations(parsed, max) {
71
+ if (!Array.isArray(parsed.recommendations))
72
+ return [];
73
+ return parsed.recommendations.slice(0, max).map((r) => ({
74
+ type: typeof r.type === "string" ? r.type : "maintenance",
75
+ target: typeof r.target === "string" ? r.target : "unknown",
76
+ reason: typeof r.reason === "string" ? r.reason : "",
77
+ priority: (r.priority === "low" || r.priority === "medium" || r.priority === "high")
78
+ ? r.priority
79
+ : "low",
80
+ }));
81
+ }
82
+ export async function runRecommendationsCheck(config, llm, currentResults, status, _history, logger) {
83
+ return runLlmCheck({
84
+ name: CHECK_NAME,
85
+ systemPrompt: SYSTEM_PROMPT,
86
+ llm,
87
+ logger,
88
+ readInput() {
89
+ const summary = buildFindingsSummary(currentResults, status);
90
+ return { ok: true, input: { summary, maxRecs: config.maxRecommendations } };
91
+ },
92
+ preFilter() {
93
+ return { severity: "ok", findingCount: 0, data: {} };
94
+ },
95
+ buildPrompt(input) {
96
+ return [
97
+ `Current date: ${new Date().toISOString().split("T")[0]}`,
98
+ `Maximum recommendations: ${input.maxRecs}`,
99
+ "",
100
+ input.summary,
101
+ ].join("\n");
102
+ },
103
+ buildFailOpen({ message, llmModel, llmTokens, timestamp, startMs }) {
104
+ return {
105
+ check_name: CHECK_NAME,
106
+ severity: "ok",
107
+ detail: `${message} — no recommendations`,
108
+ recommendations: [],
109
+ timestamp,
110
+ model_used: llmModel,
111
+ tokens_used: llmTokens,
112
+ duration_ms: Date.now() - startMs,
113
+ };
114
+ },
115
+ mergeResults(opts) {
116
+ const recs = parseRecommendations(opts.parsed, config.maxRecommendations);
117
+ return {
118
+ check_name: CHECK_NAME,
119
+ severity: parseSeverityString(opts.parsed.severity),
120
+ detail: typeof opts.parsed.detail === "string"
121
+ ? opts.parsed.detail
122
+ : `${recs.length} recommendations generated`,
123
+ recommendations: recs,
124
+ timestamp: opts.timestamp,
125
+ model_used: opts.llmModel,
126
+ tokens_used: opts.llmTokens,
127
+ duration_ms: Date.now() - opts.startMs,
128
+ };
129
+ },
130
+ });
131
+ }
132
+ //# sourceMappingURL=recommendations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recommendations.js","sourceRoot":"","sources":["../../../src/checks/recommendations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { CognitiveCheckResult, ThreadHealthCheckConfig, LlmClient, PluginLogger } from "../types.js";
2
+ export declare function runThreadHealthCheck(config: ThreadHealthCheckConfig, llm: LlmClient, logger: PluginLogger): Promise<CognitiveCheckResult>;
3
+ //# sourceMappingURL=thread-health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-health.d.ts","sourceRoot":"","sources":["../../../src/checks/thread-health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,uBAAuB,EACvB,SAAS,EAGT,YAAY,EACb,MAAM,aAAa,CAAC;AA2FrB,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,uBAAuB,EAC/B,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,oBAAoB,CAAC,CA2D/B"}
@@ -0,0 +1,129 @@
1
+ import { readJsonInput } from "../status-reader.js";
2
+ import { parseSeverityString, worstSeverity } from "../check-utils.js";
3
+ import { runLlmCheck } from "../check-runner.js";
4
+ const CHECK_NAME = "cognitive:thread_health";
5
+ const SYSTEM_PROMPT = `You are a system health evaluator. Analyze the conversation threads and assess their health.
6
+ Respond ONLY with valid JSON matching this schema:
7
+ {
8
+ "severity": "ok" | "warn" | "critical",
9
+ "detail": "single line summary",
10
+ "findings": [
11
+ {
12
+ "thread_id": "thread id",
13
+ "issue": "stale" | "duplicate" | "incomplete" | "accumulating",
14
+ "detail": "explanation",
15
+ "days_since_update": 0,
16
+ "recommendation": "what to do"
17
+ }
18
+ ]
19
+ }
20
+
21
+ Evaluation rules:
22
+ - Open threads with no update for > staleDays → WARN: stale
23
+ - Threads with identical or near-identical titles → WARN: duplicate
24
+ - Threads with empty or minimal description → WARN: incomplete
25
+ - Ratio of open to total (>80% open with >10 total) → WARN: accumulating
26
+ - ALL threads current and well-formed → severity "ok"
27
+ - ≥1 stale/duplicate/incomplete → severity "warn"
28
+ - ≥50% threads are stale or noise → severity "critical"`;
29
+ function extractThreads(data) {
30
+ if (typeof data !== "object" || data === null)
31
+ return [];
32
+ const obj = data;
33
+ if (Array.isArray(obj.threads))
34
+ return obj.threads;
35
+ if (Array.isArray(data))
36
+ return data;
37
+ return [];
38
+ }
39
+ function preFilterThreads(threads, staleDays) {
40
+ const findings = [];
41
+ const now = Date.now();
42
+ const staleMs = staleDays * 24 * 60 * 60 * 1000;
43
+ for (const thread of threads) {
44
+ if (thread.status !== "open" || !thread.last_activity)
45
+ continue;
46
+ const lastMs = new Date(thread.last_activity).getTime();
47
+ if (isNaN(lastMs) || now - lastMs <= staleMs)
48
+ continue;
49
+ const daysSince = Math.round((now - lastMs) / (24 * 60 * 60 * 1000));
50
+ findings.push({
51
+ thread_id: thread.id,
52
+ issue: "stale",
53
+ detail: `Thread "${thread.title}" has no update for ${daysSince} days`,
54
+ days_since_update: daysSince,
55
+ recommendation: "Archive or update thread",
56
+ });
57
+ }
58
+ return findings;
59
+ }
60
+ function mergeLlmFindings(preFindings, parsed) {
61
+ const llmFindings = Array.isArray(parsed.findings)
62
+ ? parsed.findings.map((f) => ({
63
+ thread_id: typeof f.thread_id === "string" ? f.thread_id : undefined,
64
+ issue: typeof f.issue === "string" ? f.issue : "unknown",
65
+ detail: typeof f.detail === "string" ? f.detail : "",
66
+ days_since_update: typeof f.days_since_update === "number" ? f.days_since_update : undefined,
67
+ recommendation: typeof f.recommendation === "string" ? f.recommendation : undefined,
68
+ }))
69
+ : [];
70
+ const seenIds = new Set(preFindings.map((f) => f.thread_id).filter(Boolean));
71
+ const unique = llmFindings.filter((f) => !f.thread_id || !seenIds.has(f.thread_id));
72
+ return [...preFindings, ...unique];
73
+ }
74
+ export async function runThreadHealthCheck(config, llm, logger) {
75
+ return runLlmCheck({
76
+ name: CHECK_NAME,
77
+ systemPrompt: SYSTEM_PROMPT,
78
+ llm,
79
+ logger,
80
+ readInput(timestamp, startMs) {
81
+ const rawData = readJsonInput(config.inputPath, logger);
82
+ if (rawData === null) {
83
+ return { ok: false, skip: { check_name: CHECK_NAME, severity: "ok", detail: "Threads file not found — check skipped", timestamp, duration_ms: Date.now() - startMs } };
84
+ }
85
+ const threads = extractThreads(rawData);
86
+ if (threads.length === 0) {
87
+ return { ok: false, skip: { check_name: CHECK_NAME, severity: "ok", detail: "No threads found", timestamp, duration_ms: Date.now() - startMs } };
88
+ }
89
+ return { ok: true, input: { threads, staleDays: config.staleDays } };
90
+ },
91
+ preFilter(input) {
92
+ const findings = preFilterThreads(input.threads, input.staleDays);
93
+ return { severity: findings.length > 0 ? "warn" : "ok", findingCount: findings.length, data: { findings } };
94
+ },
95
+ buildPrompt(input) {
96
+ const text = JSON.stringify(input.threads, null, 2).substring(0, 4000);
97
+ return `Current date: ${new Date().toISOString().split("T")[0]}\nStale threshold: ${input.staleDays} days\n\nThreads (${input.threads.length} total):\n${text}`;
98
+ },
99
+ buildFailOpen({ pre, message, llmModel, llmTokens, timestamp, startMs }) {
100
+ const preFindings = pre.data["findings"];
101
+ return {
102
+ check_name: CHECK_NAME,
103
+ severity: pre.severity,
104
+ detail: `${message} — ${pre.findingCount} pre-filter findings`,
105
+ findings: preFindings,
106
+ timestamp,
107
+ model_used: llmModel,
108
+ tokens_used: llmTokens,
109
+ duration_ms: Date.now() - startMs,
110
+ };
111
+ },
112
+ mergeResults(opts) {
113
+ const preFindings = opts.pre.data["findings"];
114
+ const allFindings = mergeLlmFindings(preFindings, opts.parsed);
115
+ const severity = worstSeverity(parseSeverityString(opts.parsed.severity), opts.pre.severity);
116
+ return {
117
+ check_name: CHECK_NAME,
118
+ severity,
119
+ detail: typeof opts.parsed.detail === "string" ? opts.parsed.detail : `${allFindings.length} findings`,
120
+ findings: allFindings,
121
+ timestamp: opts.timestamp,
122
+ model_used: opts.llmModel,
123
+ tokens_used: opts.llmTokens,
124
+ duration_ms: Date.now() - opts.startMs,
125
+ };
126
+ },
127
+ });
128
+ }
129
+ //# sourceMappingURL=thread-health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-health.js","sourceRoot":"","sources":["../../../src/checks/thread-health.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { LeukoConfig, PluginLogger } from "./types.js";
2
+ export declare const DEFAULTS: LeukoConfig;
3
+ export declare function resolveConfig(pluginConfig?: Record<string, unknown>): LeukoConfig;
4
+ export interface ConfigLoadResult {
5
+ readonly config: LeukoConfig;
6
+ readonly source: "inline" | "file" | "defaults";
7
+ readonly filePath?: string;
8
+ }
9
+ export declare function loadConfig(pluginConfig: Record<string, unknown> | undefined, logger: PluginLogger): ConfigLoadResult;
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EAKX,YAAY,EAEb,MAAM,YAAY,CAAC;AASpB,eAAO,MAAM,QAAQ,EAAE,WAyEtB,CAAC;AAyJF,wBAAgB,aAAa,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,CAajF;AAoED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,UAAU,CACxB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACjD,MAAM,EAAE,YAAY,GACnB,gBAAgB,CAkClB"}