@rulemetric/cli 0.1.1 → 0.2.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 (251) hide show
  1. package/README.md +66 -0
  2. package/dist/base-command.d.ts.map +1 -1
  3. package/dist/base-command.js +15 -0
  4. package/dist/base-command.js.map +1 -1
  5. package/dist/commands/auth/login.d.ts.map +1 -1
  6. package/dist/commands/auth/login.js +7 -0
  7. package/dist/commands/auth/login.js.map +1 -1
  8. package/dist/commands/crons/list.d.ts +7 -0
  9. package/dist/commands/crons/list.d.ts.map +1 -0
  10. package/dist/commands/crons/list.js +24 -0
  11. package/dist/commands/crons/list.js.map +1 -0
  12. package/dist/commands/crons/run.d.ts +13 -0
  13. package/dist/commands/crons/run.d.ts.map +1 -0
  14. package/dist/commands/crons/run.js +48 -0
  15. package/dist/commands/crons/run.js.map +1 -0
  16. package/dist/commands/evals/listen.d.ts +28 -2
  17. package/dist/commands/evals/listen.d.ts.map +1 -1
  18. package/dist/commands/evals/listen.js +159 -25
  19. package/dist/commands/evals/listen.js.map +1 -1
  20. package/dist/commands/evals/listen.test.d.ts +2 -0
  21. package/dist/commands/evals/listen.test.d.ts.map +1 -0
  22. package/dist/commands/evals/listen.test.js +48 -0
  23. package/dist/commands/evals/listen.test.js.map +1 -0
  24. package/dist/commands/gateway/ensure.js +1 -1
  25. package/dist/commands/gateway/ensure.js.map +1 -1
  26. package/dist/commands/hooks/install.d.ts.map +1 -1
  27. package/dist/commands/hooks/install.js +40 -3
  28. package/dist/commands/hooks/install.js.map +1 -1
  29. package/dist/commands/hooks/run.js +1 -1
  30. package/dist/commands/hooks/run.js.map +1 -1
  31. package/dist/commands/hooks/uninstall.d.ts.map +1 -1
  32. package/dist/commands/hooks/uninstall.js +9 -1
  33. package/dist/commands/hooks/uninstall.js.map +1 -1
  34. package/dist/commands/org/current.d.ts +7 -0
  35. package/dist/commands/org/current.d.ts.map +1 -0
  36. package/dist/commands/org/current.js +70 -0
  37. package/dist/commands/org/current.js.map +1 -0
  38. package/dist/commands/org/list.d.ts +7 -0
  39. package/dist/commands/org/list.d.ts.map +1 -0
  40. package/dist/commands/org/list.js +37 -0
  41. package/dist/commands/org/list.js.map +1 -0
  42. package/dist/commands/org/switch.d.ts +13 -0
  43. package/dist/commands/org/switch.d.ts.map +1 -0
  44. package/dist/commands/org/switch.js +52 -0
  45. package/dist/commands/org/switch.js.map +1 -0
  46. package/dist/commands/proxy/restart.d.ts +11 -0
  47. package/dist/commands/proxy/restart.d.ts.map +1 -0
  48. package/dist/commands/proxy/restart.js +36 -0
  49. package/dist/commands/proxy/restart.js.map +1 -0
  50. package/dist/commands/proxy/start.d.ts.map +1 -1
  51. package/dist/commands/proxy/start.js +4 -0
  52. package/dist/commands/proxy/start.js.map +1 -1
  53. package/dist/commands/service/install.d.ts +16 -0
  54. package/dist/commands/service/install.d.ts.map +1 -1
  55. package/dist/commands/service/install.js +145 -6
  56. package/dist/commands/service/install.js.map +1 -1
  57. package/dist/commands/service/uninstall.d.ts.map +1 -1
  58. package/dist/commands/service/uninstall.js +28 -0
  59. package/dist/commands/service/uninstall.js.map +1 -1
  60. package/dist/commands/sessions/start.d.ts.map +1 -1
  61. package/dist/commands/sessions/start.js +5 -0
  62. package/dist/commands/sessions/start.js.map +1 -1
  63. package/dist/commands/signals/report.d.ts +10 -0
  64. package/dist/commands/signals/report.d.ts.map +1 -0
  65. package/dist/commands/signals/report.js +35 -0
  66. package/dist/commands/signals/report.js.map +1 -0
  67. package/dist/commands/signals/report.test.d.ts +2 -0
  68. package/dist/commands/signals/report.test.d.ts.map +1 -0
  69. package/dist/commands/signals/report.test.js +65 -0
  70. package/dist/commands/signals/report.test.js.map +1 -0
  71. package/dist/commands/skills/export-approved.d.ts +10 -0
  72. package/dist/commands/skills/export-approved.d.ts.map +1 -0
  73. package/dist/commands/skills/export-approved.js +31 -0
  74. package/dist/commands/skills/export-approved.js.map +1 -0
  75. package/dist/commands/skills/publish.d.ts +17 -0
  76. package/dist/commands/skills/publish.d.ts.map +1 -0
  77. package/dist/commands/skills/publish.js +80 -0
  78. package/dist/commands/skills/publish.js.map +1 -0
  79. package/dist/commands/skills/update.d.ts +3 -0
  80. package/dist/commands/skills/update.d.ts.map +1 -1
  81. package/dist/commands/skills/update.js +17 -6
  82. package/dist/commands/skills/update.js.map +1 -1
  83. package/dist/commands/suggestions/accept.d.ts +16 -0
  84. package/dist/commands/suggestions/accept.d.ts.map +1 -0
  85. package/dist/commands/suggestions/accept.js +61 -0
  86. package/dist/commands/suggestions/accept.js.map +1 -0
  87. package/dist/commands/suggestions/accept.test.d.ts +2 -0
  88. package/dist/commands/suggestions/accept.test.d.ts.map +1 -0
  89. package/dist/commands/suggestions/accept.test.js +52 -0
  90. package/dist/commands/suggestions/accept.test.js.map +1 -0
  91. package/dist/commands/suggestions/dismiss.d.ts +10 -0
  92. package/dist/commands/suggestions/dismiss.d.ts.map +1 -0
  93. package/dist/commands/suggestions/dismiss.js +26 -0
  94. package/dist/commands/suggestions/dismiss.js.map +1 -0
  95. package/dist/commands/suggestions/list.d.ts +10 -0
  96. package/dist/commands/suggestions/list.d.ts.map +1 -0
  97. package/dist/commands/suggestions/list.js +40 -0
  98. package/dist/commands/suggestions/list.js.map +1 -0
  99. package/dist/commands/suggestions/refresh.d.ts +7 -0
  100. package/dist/commands/suggestions/refresh.d.ts.map +1 -0
  101. package/dist/commands/suggestions/refresh.js +11 -0
  102. package/dist/commands/suggestions/refresh.js.map +1 -0
  103. package/dist/dashboard/Dashboard.d.ts.map +1 -1
  104. package/dist/dashboard/Dashboard.js +7 -1
  105. package/dist/dashboard/Dashboard.js.map +1 -1
  106. package/dist/lib/active-org-refresh.d.ts +22 -0
  107. package/dist/lib/active-org-refresh.d.ts.map +1 -0
  108. package/dist/lib/active-org-refresh.js +108 -0
  109. package/dist/lib/active-org-refresh.js.map +1 -0
  110. package/dist/lib/active-org-refresh.test.d.ts +2 -0
  111. package/dist/lib/active-org-refresh.test.d.ts.map +1 -0
  112. package/dist/lib/active-org-refresh.test.js +190 -0
  113. package/dist/lib/active-org-refresh.test.js.map +1 -0
  114. package/dist/lib/active-org.d.ts +43 -0
  115. package/dist/lib/active-org.d.ts.map +1 -0
  116. package/dist/lib/active-org.js +96 -0
  117. package/dist/lib/active-org.js.map +1 -0
  118. package/dist/lib/active-org.test.d.ts +2 -0
  119. package/dist/lib/active-org.test.d.ts.map +1 -0
  120. package/dist/lib/active-org.test.js +147 -0
  121. package/dist/lib/active-org.test.js.map +1 -0
  122. package/dist/lib/cron-registry.d.ts +47 -0
  123. package/dist/lib/cron-registry.d.ts.map +1 -0
  124. package/dist/lib/cron-registry.js +102 -0
  125. package/dist/lib/cron-registry.js.map +1 -0
  126. package/dist/lib/cron-registry.test.d.ts +2 -0
  127. package/dist/lib/cron-registry.test.d.ts.map +1 -0
  128. package/dist/lib/cron-registry.test.js +136 -0
  129. package/dist/lib/cron-registry.test.js.map +1 -0
  130. package/dist/lib/cron-runner.d.ts +16 -0
  131. package/dist/lib/cron-runner.d.ts.map +1 -0
  132. package/dist/lib/cron-runner.js +68 -0
  133. package/dist/lib/cron-runner.js.map +1 -0
  134. package/dist/lib/detect-languages.d.ts +7 -0
  135. package/dist/lib/detect-languages.d.ts.map +1 -0
  136. package/dist/lib/detect-languages.js +113 -0
  137. package/dist/lib/detect-languages.js.map +1 -0
  138. package/dist/lib/detect-languages.test.d.ts +2 -0
  139. package/dist/lib/detect-languages.test.d.ts.map +1 -0
  140. package/dist/lib/detect-languages.test.js +29 -0
  141. package/dist/lib/detect-languages.test.js.map +1 -0
  142. package/dist/lib/eval-executor.d.ts.map +1 -1
  143. package/dist/lib/eval-executor.js +5 -2
  144. package/dist/lib/eval-executor.js.map +1 -1
  145. package/dist/lib/gateway-entry.js +4 -1
  146. package/dist/lib/gateway-entry.js.map +1 -1
  147. package/dist/lib/gateway-lifecycle.d.ts +1 -1
  148. package/dist/lib/gateway-lifecycle.d.ts.map +1 -1
  149. package/dist/lib/gateway-lifecycle.js +13 -2
  150. package/dist/lib/gateway-lifecycle.js.map +1 -1
  151. package/dist/lib/gateway.d.ts +4 -5
  152. package/dist/lib/gateway.d.ts.map +1 -1
  153. package/dist/lib/gateway.js +68 -2
  154. package/dist/lib/gateway.js.map +1 -1
  155. package/dist/lib/graphile-worker-runner.d.ts +124 -0
  156. package/dist/lib/graphile-worker-runner.d.ts.map +1 -0
  157. package/dist/lib/graphile-worker-runner.js +526 -0
  158. package/dist/lib/graphile-worker-runner.js.map +1 -0
  159. package/dist/lib/graphile-worker-runner.test.d.ts +2 -0
  160. package/dist/lib/graphile-worker-runner.test.d.ts.map +1 -0
  161. package/dist/lib/graphile-worker-runner.test.js +153 -0
  162. package/dist/lib/graphile-worker-runner.test.js.map +1 -0
  163. package/dist/lib/handlers/cron-close-stale-sessions.d.ts +3 -0
  164. package/dist/lib/handlers/cron-close-stale-sessions.d.ts.map +1 -0
  165. package/dist/lib/handlers/cron-close-stale-sessions.js +8 -0
  166. package/dist/lib/handlers/cron-close-stale-sessions.js.map +1 -0
  167. package/dist/lib/handlers/cron-data-integrity-audit.d.ts +3 -0
  168. package/dist/lib/handlers/cron-data-integrity-audit.d.ts.map +1 -0
  169. package/dist/lib/handlers/cron-data-integrity-audit.js +16 -0
  170. package/dist/lib/handlers/cron-data-integrity-audit.js.map +1 -0
  171. package/dist/lib/handlers/cron-refresh-skills.d.ts +3 -0
  172. package/dist/lib/handlers/cron-refresh-skills.d.ts.map +1 -0
  173. package/dist/lib/handlers/cron-refresh-skills.js +91 -0
  174. package/dist/lib/handlers/cron-refresh-skills.js.map +1 -0
  175. package/dist/lib/handlers/cron-refresh-skills.test.d.ts +2 -0
  176. package/dist/lib/handlers/cron-refresh-skills.test.d.ts.map +1 -0
  177. package/dist/lib/handlers/cron-refresh-skills.test.js +114 -0
  178. package/dist/lib/handlers/cron-refresh-skills.test.js.map +1 -0
  179. package/dist/lib/handlers/cron-regenerate-insights.d.ts +3 -0
  180. package/dist/lib/handlers/cron-regenerate-insights.d.ts.map +1 -0
  181. package/dist/lib/handlers/cron-regenerate-insights.js +6 -0
  182. package/dist/lib/handlers/cron-regenerate-insights.js.map +1 -0
  183. package/dist/lib/handlers/cron-suggest-instructions.d.ts +3 -0
  184. package/dist/lib/handlers/cron-suggest-instructions.d.ts.map +1 -0
  185. package/dist/lib/handlers/cron-suggest-instructions.js +159 -0
  186. package/dist/lib/handlers/cron-suggest-instructions.js.map +1 -0
  187. package/dist/lib/handlers/cron-suggest-instructions.test.d.ts +2 -0
  188. package/dist/lib/handlers/cron-suggest-instructions.test.d.ts.map +1 -0
  189. package/dist/lib/handlers/cron-suggest-instructions.test.js +80 -0
  190. package/dist/lib/handlers/cron-suggest-instructions.test.js.map +1 -0
  191. package/dist/lib/handlers/process-conversation.d.ts +35 -0
  192. package/dist/lib/handlers/process-conversation.d.ts.map +1 -0
  193. package/dist/lib/handlers/process-conversation.js +35 -0
  194. package/dist/lib/handlers/process-conversation.js.map +1 -0
  195. package/dist/lib/handlers/process-eval.d.ts +32 -0
  196. package/dist/lib/handlers/process-eval.d.ts.map +1 -0
  197. package/dist/lib/handlers/process-eval.js +207 -0
  198. package/dist/lib/handlers/process-eval.js.map +1 -0
  199. package/dist/lib/handlers/process-insights.d.ts +39 -0
  200. package/dist/lib/handlers/process-insights.d.ts.map +1 -0
  201. package/dist/lib/handlers/process-insights.js +300 -0
  202. package/dist/lib/handlers/process-insights.js.map +1 -0
  203. package/dist/lib/handlers/process-launch.d.ts +29 -0
  204. package/dist/lib/handlers/process-launch.d.ts.map +1 -0
  205. package/dist/lib/handlers/process-launch.js +41 -0
  206. package/dist/lib/handlers/process-launch.js.map +1 -0
  207. package/dist/lib/hooks-config.d.ts +28 -4
  208. package/dist/lib/hooks-config.d.ts.map +1 -1
  209. package/dist/lib/hooks-config.js +138 -10
  210. package/dist/lib/hooks-config.js.map +1 -1
  211. package/dist/lib/llm-client.d.ts.map +1 -1
  212. package/dist/lib/llm-client.js +149 -16
  213. package/dist/lib/llm-client.js.map +1 -1
  214. package/dist/lib/mirror-writer-db.d.ts +12 -0
  215. package/dist/lib/mirror-writer-db.d.ts.map +1 -0
  216. package/dist/lib/mirror-writer-db.js +51 -0
  217. package/dist/lib/mirror-writer-db.js.map +1 -0
  218. package/dist/lib/mirror-writer.d.ts +35 -0
  219. package/dist/lib/mirror-writer.d.ts.map +1 -0
  220. package/dist/lib/mirror-writer.js +27 -0
  221. package/dist/lib/mirror-writer.js.map +1 -0
  222. package/dist/lib/mirror-writer.test.d.ts +2 -0
  223. package/dist/lib/mirror-writer.test.d.ts.map +1 -0
  224. package/dist/lib/mirror-writer.test.js +47 -0
  225. package/dist/lib/mirror-writer.test.js.map +1 -0
  226. package/dist/lib/permanent-job-error.d.ts +17 -0
  227. package/dist/lib/permanent-job-error.d.ts.map +1 -0
  228. package/dist/lib/permanent-job-error.js +23 -0
  229. package/dist/lib/permanent-job-error.js.map +1 -0
  230. package/dist/lib/permanent-job-error.test.d.ts +2 -0
  231. package/dist/lib/permanent-job-error.test.d.ts.map +1 -0
  232. package/dist/lib/permanent-job-error.test.js +29 -0
  233. package/dist/lib/permanent-job-error.test.js.map +1 -0
  234. package/dist/lib/version-check.d.ts +11 -0
  235. package/dist/lib/version-check.d.ts.map +1 -0
  236. package/dist/lib/version-check.js +106 -0
  237. package/dist/lib/version-check.js.map +1 -0
  238. package/oclif.manifest.json +611 -81
  239. package/package.json +19 -5
  240. package/dist/commands/insights/sync.d.ts +0 -17
  241. package/dist/commands/insights/sync.d.ts.map +0 -1
  242. package/dist/commands/insights/sync.js +0 -477
  243. package/dist/commands/insights/sync.js.map +0 -1
  244. package/dist/lib/eval-worker.d.ts +0 -12
  245. package/dist/lib/eval-worker.d.ts.map +0 -1
  246. package/dist/lib/eval-worker.js +0 -395
  247. package/dist/lib/eval-worker.js.map +0 -1
  248. package/dist/lib/insights-worker.d.ts +0 -10
  249. package/dist/lib/insights-worker.d.ts.map +0 -1
  250. package/dist/lib/insights-worker.js +0 -329
  251. package/dist/lib/insights-worker.js.map +0 -1
@@ -0,0 +1,159 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import os from 'node:os';
4
+ import { apiGet, apiPost } from '../api-client.js';
5
+ import { runLlmPrompt, detectLlmBackend } from '../llm-client.js';
6
+ import { buildRecommendationPrompt } from '@rulemetric/core';
7
+ import { normalizeProjectPath } from '@rulemetric/core/paths';
8
+ import { detectLanguages } from '../detect-languages.js';
9
+ const MAX_SUGGESTIONS_PER_PROJECT = 5;
10
+ const MAX_PROJECTS_PER_RUN = Number(process.env.RULEMETRIC_MAX_SUGGESTION_PROJECTS ?? 10);
11
+ const STALE_THRESHOLD_HOURS = 48;
12
+ const MIN_SCORE = 0.5;
13
+ const CONTENT_PREVIEW_CHARS = 400;
14
+ async function checkSkillsRegistryStale() {
15
+ const registryPath = path.join(os.homedir(), '.config', 'rulemetric', 'skills-registry.json');
16
+ try {
17
+ const raw = readFileSync(registryPath, 'utf-8');
18
+ const registry = JSON.parse(raw);
19
+ const ageMs = Date.now() - new Date(registry.generatedAt).getTime();
20
+ return ageMs > STALE_THRESHOLD_HOURS * 60 * 60 * 1000;
21
+ }
22
+ catch {
23
+ return true;
24
+ }
25
+ }
26
+ export const cronSuggestInstructions = async (_payload, helpers) => {
27
+ // Scoring uses the user's locally-installed LLM tooling — Claude Code CLI
28
+ // when available, otherwise the Anthropic SDK with ANTHROPIC_API_KEY.
29
+ // No third-party LLM_PROVIDER / LLM_API_KEY required. If neither backend
30
+ // is reachable, skip cleanly.
31
+ const backend = detectLlmBackend();
32
+ if (backend === 'none') {
33
+ helpers.logger.warn('No LLM backend available (claude CLI missing and ANTHROPIC_API_KEY unset); skipping suggestion compute');
34
+ return;
35
+ }
36
+ helpers.logger.info(`Scoring backend: ${backend}`);
37
+ // 1. Fetch recent project paths
38
+ let projectPaths;
39
+ try {
40
+ const res = await apiGet('/api/sessions/project-paths?limit=' + MAX_PROJECTS_PER_RUN);
41
+ projectPaths = res.projectPaths;
42
+ }
43
+ catch (err) {
44
+ helpers.logger.warn(`Failed to fetch project paths: ${err instanceof Error ? err.message : String(err)}`);
45
+ return;
46
+ }
47
+ if (projectPaths.length === 0) {
48
+ helpers.logger.info('No recent project paths; nothing to score');
49
+ return;
50
+ }
51
+ // 2. Fetch candidate instructions: public+org+team from /catalog, plus
52
+ // the user's own (personal+created) from /instructions. Dedup by id.
53
+ const candidates = new Map();
54
+ try {
55
+ const catalogRows = await apiGet('/api/catalog?limit=200');
56
+ for (const row of catalogRows) {
57
+ candidates.set(row.id, {
58
+ id: row.id,
59
+ name: row.name,
60
+ description: row.description ?? '',
61
+ tags: row.tags ?? [],
62
+ contentPreview: (row.content ?? '').slice(0, CONTENT_PREVIEW_CHARS),
63
+ });
64
+ }
65
+ }
66
+ catch (err) {
67
+ helpers.logger.warn(`Failed to fetch catalog: ${err instanceof Error ? err.message : String(err)}`);
68
+ }
69
+ try {
70
+ const personalRes = await apiGet('/api/instructions?limit=100');
71
+ for (const row of personalRes.instructions ?? []) {
72
+ if (!candidates.has(row.id)) {
73
+ candidates.set(row.id, {
74
+ id: row.id,
75
+ name: row.name,
76
+ description: row.description ?? '',
77
+ tags: row.tags ?? [],
78
+ contentPreview: (row.content ?? '').slice(0, CONTENT_PREVIEW_CHARS),
79
+ });
80
+ }
81
+ }
82
+ }
83
+ catch (err) {
84
+ helpers.logger.warn(`Failed to fetch personal instructions: ${err instanceof Error ? err.message : String(err)}`);
85
+ }
86
+ const candidateList = [...candidates.values()];
87
+ if (candidateList.length === 0) {
88
+ helpers.logger.info('No candidate instructions; nothing to score');
89
+ return;
90
+ }
91
+ helpers.logger.info(`Scoring ${candidateList.length} candidates across ${projectPaths.length} project(s)`);
92
+ // 3. Score per project
93
+ let scored = 0;
94
+ for (const rawPath of projectPaths) {
95
+ try {
96
+ const projectPath = normalizeProjectPath(rawPath);
97
+ const languages = detectLanguages(projectPath);
98
+ if (languages.length === 0) {
99
+ helpers.logger.info(`Skipping ${projectPath}: insufficient language signals`);
100
+ continue;
101
+ }
102
+ const context = {
103
+ name: path.basename(projectPath),
104
+ description: null,
105
+ languages,
106
+ topics: [],
107
+ dependencies: [],
108
+ };
109
+ const prompt = buildRecommendationPrompt(context, candidateList);
110
+ // runLlmPrompt expects (systemPrompt, data, maxTokens). The recommendation
111
+ // prompt is fully self-contained; pass an empty data block.
112
+ const parsed = await runLlmPrompt(prompt, '', 4096);
113
+ if (!parsed) {
114
+ helpers.logger.warn(`LLM returned null for ${projectPath} (backend ${backend})`);
115
+ continue;
116
+ }
117
+ const raw = (parsed.recommendations ?? []);
118
+ const recommendations = raw
119
+ .filter((r) => typeof r.instructionId === 'string' && typeof r.score === 'number' && typeof r.reason === 'string')
120
+ .map((r) => ({
121
+ instructionId: r.instructionId,
122
+ score: r.score,
123
+ reason: r.reason,
124
+ }));
125
+ const top = recommendations
126
+ .filter((r) => r.score >= MIN_SCORE)
127
+ .sort((a, b) => b.score - a.score)
128
+ .slice(0, MAX_SUGGESTIONS_PER_PROJECT);
129
+ if (top.length === 0) {
130
+ helpers.logger.info(`No suggestions over threshold for ${projectPath}`);
131
+ continue;
132
+ }
133
+ await apiPost('/api/instruction-suggestions/batch-upsert', {
134
+ projectPath,
135
+ suggestions: top.map((r) => ({
136
+ instructionId: r.instructionId,
137
+ score: r.score,
138
+ reason: r.reason,
139
+ })),
140
+ });
141
+ scored++;
142
+ }
143
+ catch (err) {
144
+ helpers.logger.warn(`Failed to score ${rawPath}: ${err instanceof Error ? err.message : String(err)}`);
145
+ }
146
+ }
147
+ // 4. Mark stale if registry is old
148
+ if (await checkSkillsRegistryStale()) {
149
+ try {
150
+ await apiPost('/api/instruction-suggestions/mark-stale', {});
151
+ helpers.logger.warn('Skills registry is stale (>48h); marked all suggestions stale');
152
+ }
153
+ catch {
154
+ // Non-fatal
155
+ }
156
+ }
157
+ helpers.logger.info(`Done: scored ${scored}/${projectPaths.length} projects`);
158
+ };
159
+ //# sourceMappingURL=cron-suggest-instructions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-suggest-instructions.js","sourceRoot":"","sources":["../../../src/lib/handlers/cron-suggest-instructions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cron-suggest-instructions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-suggest-instructions.test.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/cron-suggest-instructions.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import path from 'node:path';
5
+ import { detectLanguages } from '../detect-languages.js';
6
+ describe('detectLanguages', () => {
7
+ let root;
8
+ beforeAll(() => {
9
+ root = mkdtempSync(path.join(tmpdir(), 'rulemetric-detect-'));
10
+ });
11
+ afterAll(() => {
12
+ rmSync(root, { recursive: true, force: true });
13
+ });
14
+ function fresh(name) {
15
+ const dir = path.join(root, name);
16
+ mkdirSync(dir, { recursive: true });
17
+ return dir;
18
+ }
19
+ it('returns [] for an empty directory', () => {
20
+ const dir = fresh('empty');
21
+ expect(detectLanguages(dir)).toEqual([]);
22
+ });
23
+ it('returns [] for a single signal (insufficient evidence)', () => {
24
+ const dir = fresh('one-signal');
25
+ writeFileSync(path.join(dir, 'package.json'), '{}');
26
+ // Just package.json with no .ts/.js source = 1 signal
27
+ expect(detectLanguages(dir)).toEqual([]);
28
+ });
29
+ it('detects TypeScript from package.json + tsconfig.json', () => {
30
+ const dir = fresh('ts-config');
31
+ writeFileSync(path.join(dir, 'package.json'), '{}');
32
+ writeFileSync(path.join(dir, 'tsconfig.json'), '{}');
33
+ expect(detectLanguages(dir)).toContain('TypeScript');
34
+ });
35
+ it('detects TypeScript from package.json + a .ts source file', () => {
36
+ const dir = fresh('ts-source');
37
+ writeFileSync(path.join(dir, 'package.json'), '{}');
38
+ const src = path.join(dir, 'src');
39
+ mkdirSync(src);
40
+ writeFileSync(path.join(src, 'index.ts'), 'export {};');
41
+ expect(detectLanguages(dir)).toContain('TypeScript');
42
+ });
43
+ it('detects Python from pyproject.toml + requirements.txt', () => {
44
+ const dir = fresh('py');
45
+ writeFileSync(path.join(dir, 'pyproject.toml'), '');
46
+ writeFileSync(path.join(dir, 'requirements.txt'), '');
47
+ expect(detectLanguages(dir)).toContain('Python');
48
+ });
49
+ it('detects multiple languages in a polyglot project', () => {
50
+ const dir = fresh('polyglot');
51
+ writeFileSync(path.join(dir, 'package.json'), '{}');
52
+ writeFileSync(path.join(dir, 'pyproject.toml'), '');
53
+ const langs = detectLanguages(dir);
54
+ expect(langs).toContain('JavaScript');
55
+ expect(langs).toContain('Python');
56
+ });
57
+ it('walks 3 levels deep (monorepo case)', () => {
58
+ const dir = fresh('mono');
59
+ // packages/foo/src/index.ts is 3 levels deep
60
+ const deep = path.join(dir, 'packages', 'foo', 'src');
61
+ mkdirSync(deep, { recursive: true });
62
+ writeFileSync(path.join(dir, 'package.json'), '{}');
63
+ writeFileSync(path.join(deep, 'index.ts'), 'export {};');
64
+ expect(detectLanguages(dir)).toContain('TypeScript');
65
+ });
66
+ it('skips excluded directories like node_modules', () => {
67
+ const dir = fresh('exclude');
68
+ // ONLY signals are inside node_modules — should not count
69
+ const nm = path.join(dir, 'node_modules', 'foo');
70
+ mkdirSync(nm, { recursive: true });
71
+ writeFileSync(path.join(nm, 'package.json'), '{}');
72
+ writeFileSync(path.join(nm, 'index.ts'), 'export {};');
73
+ // Root itself has nothing → 0 signals → []
74
+ expect(detectLanguages(dir)).toEqual([]);
75
+ });
76
+ it('returns [] for a non-existent path without throwing', () => {
77
+ expect(detectLanguages(path.join(root, 'nonexistent'))).toEqual([]);
78
+ });
79
+ });
80
+ //# sourceMappingURL=cron-suggest-instructions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-suggest-instructions.test.js","sourceRoot":"","sources":["../../../src/lib/handlers/cron-suggest-instructions.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { JobHelpers } from 'graphile-worker';
2
+ interface ConversationJobConfig {
3
+ type: 'conversation';
4
+ conversationId: string;
5
+ messageId: string;
6
+ messageContent: string;
7
+ }
8
+ interface ConversationPayload {
9
+ mirrorId: string;
10
+ evalTargetId: string;
11
+ config: ConversationJobConfig;
12
+ }
13
+ /**
14
+ * Graphile-shaped handler for the `process_conversation` task.
15
+ *
16
+ * Thin wrapper around `eval-conversation-handler.processConversationJob` —
17
+ * the existing function already does all the work (action decision,
18
+ * run_evals/generate_cases/analyze branches, idempotency guard via
19
+ * already-posted assistant messages). The handler just unpacks the payload
20
+ * and threads the helpers' logger through.
21
+ *
22
+ * Mechanical contract vs. the legacy worker:
23
+ * - no claim — Graphile claimed the job before invoking us
24
+ * - no /complete POST — we return a small marker on success (matches the
25
+ * `{ type: 'conversation' }` blob the legacy code POSTed)
26
+ * - no surrounding try/catch — errors propagate to Graphile, which flips
27
+ * the mirror row to `failed` via the runner.events handler
28
+ *
29
+ * Conversation jobs run with `maxAttempts: 1` (set at enqueue time in
30
+ * `apps/api/src/lib/queue.ts`) — chat is interactive and silent retries
31
+ * would confuse users mid-flow.
32
+ */
33
+ export declare function processConversation(payload: ConversationPayload, helpers: JobHelpers): Promise<Record<string, unknown>>;
34
+ export {};
35
+ //# sourceMappingURL=process-conversation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-conversation.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/process-conversation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAIlD,UAAU,qBAAqB;IAC7B,IAAI,EAAE,cAAc,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAclC"}
@@ -0,0 +1,35 @@
1
+ import { apiPatch } from '../api-client.js';
2
+ import { processConversationJob } from '../eval-conversation-handler.js';
3
+ /**
4
+ * Graphile-shaped handler for the `process_conversation` task.
5
+ *
6
+ * Thin wrapper around `eval-conversation-handler.processConversationJob` —
7
+ * the existing function already does all the work (action decision,
8
+ * run_evals/generate_cases/analyze branches, idempotency guard via
9
+ * already-posted assistant messages). The handler just unpacks the payload
10
+ * and threads the helpers' logger through.
11
+ *
12
+ * Mechanical contract vs. the legacy worker:
13
+ * - no claim — Graphile claimed the job before invoking us
14
+ * - no /complete POST — we return a small marker on success (matches the
15
+ * `{ type: 'conversation' }` blob the legacy code POSTed)
16
+ * - no surrounding try/catch — errors propagate to Graphile, which flips
17
+ * the mirror row to `failed` via the runner.events handler
18
+ *
19
+ * Conversation jobs run with `maxAttempts: 1` (set at enqueue time in
20
+ * `apps/api/src/lib/queue.ts`) — chat is interactive and silent retries
21
+ * would confuse users mid-flow.
22
+ */
23
+ export async function processConversation(payload, helpers) {
24
+ const { mirrorId, evalTargetId, config } = payload;
25
+ const log = (msg) => helpers.logger.info(msg);
26
+ await processConversationJob(config, evalTargetId, log);
27
+ const result = { type: 'conversation', conversationId: config.conversationId };
28
+ // Graphile discards task return values, so persist a small marker onto
29
+ // the mirror row so the dashboard can tell the job finished. Best-effort.
30
+ await apiPatch(`/api/eval-jobs/${mirrorId}/state`, { result }).catch((err) => {
31
+ log(`result persist failed: ${err instanceof Error ? err.message : String(err)}`);
32
+ });
33
+ return result;
34
+ }
35
+ //# sourceMappingURL=process-conversation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-conversation.js","sourceRoot":"","sources":["../../../src/lib/handlers/process-conversation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAezE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,OAA4B,EAC5B,OAAmB;IAEnB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtD,MAAM,sBAAsB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC;IAE/E,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACpF,GAAG,CAAC,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { JobHelpers } from 'graphile-worker';
2
+ interface EvalPayload {
3
+ mirrorId: string;
4
+ evalTargetId: string;
5
+ config: {
6
+ parallel?: number;
7
+ runsPerEval?: number;
8
+ iteration?: number;
9
+ skipBaseline?: boolean;
10
+ skipGrading?: boolean;
11
+ model?: string;
12
+ graderModel?: string;
13
+ timeout?: number;
14
+ };
15
+ }
16
+ /**
17
+ * Graphile-shaped handler for the `process_eval` task.
18
+ *
19
+ * Lifted verbatim from the legacy `eval-worker.ts:processJob` body, with the
20
+ * queue plumbing stripped out:
21
+ * - no claim — Graphile already claimed the job before invoking us
22
+ * - no /complete POST — we return the result object (or throw)
23
+ * - no `processing` flag — that lived in the polling loop's closure
24
+ * - no conversation branch — split into its own handler (Task 14)
25
+ *
26
+ * Mid-job progress patches still hit the existing
27
+ * `PATCH /api/eval-jobs/:id/progress` endpoint, just keyed by the mirror row's
28
+ * id instead of the legacy queue id.
29
+ */
30
+ export declare function processEval(payload: EvalPayload, helpers: JobHelpers): Promise<Record<string, unknown>>;
31
+ export {};
32
+ //# sourceMappingURL=process-eval.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-eval.d.ts","sourceRoot":"","sources":["../../../src/lib/handlers/process-eval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAwBlD,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QACN,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAiMlC"}
@@ -0,0 +1,207 @@
1
+ import { apiGet, apiPost, apiPatch } from '../api-client.js';
2
+ import { executeEval } from '../eval-executor.js';
3
+ import { gradeEvalOutput } from '../eval-grader.js';
4
+ import { judgeEvalQuality } from '../eval-meta-judge.js';
5
+ import { createEvalWorktree } from '../eval-worktree.js';
6
+ import { PermanentJobError } from '../permanent-job-error.js';
7
+ /**
8
+ * Graphile-shaped handler for the `process_eval` task.
9
+ *
10
+ * Lifted verbatim from the legacy `eval-worker.ts:processJob` body, with the
11
+ * queue plumbing stripped out:
12
+ * - no claim — Graphile already claimed the job before invoking us
13
+ * - no /complete POST — we return the result object (or throw)
14
+ * - no `processing` flag — that lived in the polling loop's closure
15
+ * - no conversation branch — split into its own handler (Task 14)
16
+ *
17
+ * Mid-job progress patches still hit the existing
18
+ * `PATCH /api/eval-jobs/:id/progress` endpoint, just keyed by the mirror row's
19
+ * id instead of the legacy queue id.
20
+ */
21
+ export async function processEval(payload, helpers) {
22
+ const { mirrorId, evalTargetId, config } = payload;
23
+ const log = (msg) => helpers.logger.info(msg);
24
+ // Fail-fast on retry. Each eval_run is INSERT'd as it completes, but
25
+ // there's no idempotency key tying a row to a specific job — re-running
26
+ // the whole batch would duplicate every previously-completed row in
27
+ // eval_runs. Until proper resume-from-progress-checkpoint lands, surface
28
+ // the failure to the user instead of silently doubling-up rows. See
29
+ // docs/audits/2026-05-07-worker-audit.md "Handlers not idempotent".
30
+ if (helpers.job.attempts > 1) {
31
+ throw new PermanentJobError(`process_eval is not safe to retry (attempt ${helpers.job.attempts}). Re-trigger the eval run from the UI.`);
32
+ }
33
+ const target = await apiGet(`/api/eval-targets/${evalTargetId}`);
34
+ const evalCases = await apiGet(`/api/eval-targets/${evalTargetId}/evals`);
35
+ if (evalCases.length === 0) {
36
+ // No retries — eval cases don't materialize on their own; the user has
37
+ // to add one via the UI/CLI. Skip Graphile's retry loop.
38
+ throw new PermanentJobError('No evals defined for target');
39
+ }
40
+ const runsPerEval = config.runsPerEval ?? 1;
41
+ const timeout = config.timeout ?? 120_000;
42
+ const iteration = config.iteration ?? 1;
43
+ const configurations = [
44
+ { name: 'with_target', content: target.content },
45
+ ];
46
+ if (!config.skipBaseline) {
47
+ configurations.push({ name: 'without_target' });
48
+ }
49
+ // Build work queue
50
+ const workQueue = [];
51
+ for (const eval_ of evalCases) {
52
+ for (const cfg of configurations) {
53
+ for (let run = 1; run <= runsPerEval; run++) {
54
+ workQueue.push({ eval_: eval_, configuration: cfg.name, targetContent: cfg.content, runNumber: run });
55
+ }
56
+ }
57
+ }
58
+ const total = workQueue.length;
59
+ let completed = 0;
60
+ const concurrency = Math.min(config.parallel ?? 1, 4); // cap at 4 parallel
61
+ await apiPatch(`/api/eval-jobs/${mirrorId}/progress`, {
62
+ status: 'running',
63
+ progress: { total, completed: 0, current: null, message: `Starting ${total} eval runs (concurrency: ${concurrency})...` },
64
+ });
65
+ const results = [];
66
+ // Process work items — sequential if concurrency=1, parallel otherwise
67
+ async function processItem(item) {
68
+ const label = `${item.configuration} · ${item.eval_.name} · run#${item.runNumber}`;
69
+ log(`[${completed + 1}/${total}] ${label}`);
70
+ // Create isolated worktree for parallel execution
71
+ const worktree = concurrency > 1 ? createEvalWorktree() : null;
72
+ try {
73
+ const execResult = await executeEval({
74
+ prompt: item.eval_.prompt,
75
+ targetContent: item.targetContent,
76
+ workDir: worktree?.workDir,
77
+ timeout,
78
+ model: config.model,
79
+ });
80
+ let grading = {};
81
+ if (!config.skipGrading && item.eval_.expectations.length > 0 && !execResult.error) {
82
+ const gradingResult = await gradeEvalOutput({
83
+ prompt: item.eval_.prompt,
84
+ output: execResult.output,
85
+ expectations: item.eval_.expectations,
86
+ model: config.graderModel ?? config.model,
87
+ timeout,
88
+ });
89
+ grading = gradingResult;
90
+ }
91
+ return {
92
+ evalId: item.eval_.id,
93
+ evalTargetId: target.id,
94
+ evalTargetVersion: target.version,
95
+ configuration: item.configuration,
96
+ runNumber: item.runNumber,
97
+ iteration,
98
+ status: execResult.error ? 'failed' : 'completed',
99
+ outputs: execResult.error ? { error: execResult.error } : { transcript: execResult.output },
100
+ timing: { duration_ms: execResult.durationMs, total_tokens: execResult.totalTokens },
101
+ grading,
102
+ worktree: worktree?.isWorktree ? true : undefined,
103
+ };
104
+ }
105
+ finally {
106
+ worktree?.cleanup();
107
+ }
108
+ }
109
+ if (concurrency <= 1) {
110
+ // Sequential execution (existing behavior)
111
+ for (const item of workQueue) {
112
+ const label = `${item.configuration} · ${item.eval_.name} · run#${item.runNumber}`;
113
+ await apiPatch(`/api/eval-jobs/${mirrorId}/progress`, {
114
+ status: 'running',
115
+ progress: { total, completed, current: label, message: `Executing ${label}...` },
116
+ });
117
+ const runResult = await processItem(item);
118
+ await apiPost('/api/eval-runs', runResult);
119
+ results.push(runResult);
120
+ completed++;
121
+ await apiPatch(`/api/eval-jobs/${mirrorId}/progress`, {
122
+ status: 'running',
123
+ progress: { total, completed, current: label, message: `Completed ${label}` },
124
+ });
125
+ }
126
+ }
127
+ else {
128
+ // Parallel execution with worktree isolation
129
+ log(`Running ${total} evals with concurrency=${concurrency} (worktree isolation)`);
130
+ for (let i = 0; i < workQueue.length; i += concurrency) {
131
+ const batch = workQueue.slice(i, i + concurrency);
132
+ const batchLabel = `batch ${Math.floor(i / concurrency) + 1}/${Math.ceil(workQueue.length / concurrency)}`;
133
+ await apiPatch(`/api/eval-jobs/${mirrorId}/progress`, {
134
+ status: 'running',
135
+ progress: { total, completed, current: batchLabel, message: `Executing ${batchLabel} (${batch.length} parallel)...` },
136
+ });
137
+ const batchResults = await Promise.all(batch.map(processItem));
138
+ for (const runResult of batchResults) {
139
+ await apiPost('/api/eval-runs', runResult);
140
+ results.push(runResult);
141
+ completed++;
142
+ }
143
+ await apiPatch(`/api/eval-jobs/${mirrorId}/progress`, {
144
+ status: 'running',
145
+ progress: { total, completed, current: batchLabel, message: `Completed ${batchLabel}` },
146
+ });
147
+ }
148
+ }
149
+ const summary = buildSummary(results);
150
+ // Meta-judge: assess eval quality if we have grading results
151
+ let metaJudgement;
152
+ if (!config.skipGrading && results.some(r => r.grading && Object.keys(r.grading).length > 0)) {
153
+ try {
154
+ log(`Running meta-judge for job ${mirrorId}...`);
155
+ const evalInputs = evalCases.map(e => {
156
+ const matchingResults = results.filter(r => r.evalId === e.id && r.configuration === 'with_target');
157
+ const firstResult = matchingResults[0];
158
+ return {
159
+ evalName: e.name,
160
+ prompt: e.prompt,
161
+ expectations: e.expectations,
162
+ grading: firstResult?.grading ? firstResult.grading : null,
163
+ output: firstResult?.outputs?.transcript?.slice(0, 500),
164
+ };
165
+ });
166
+ metaJudgement = await judgeEvalQuality({
167
+ targetName: target.name,
168
+ evalResults: evalInputs,
169
+ model: config.graderModel ?? config.model,
170
+ timeout: 60000,
171
+ });
172
+ log(`Meta-judge: quality=${metaJudgement.quality_score}/5, issues=${metaJudgement.issues.length}`);
173
+ }
174
+ catch (err) {
175
+ log(`Meta-judge failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
176
+ }
177
+ }
178
+ const result = metaJudgement
179
+ ? { ...summary, meta_judgement: metaJudgement }
180
+ : summary;
181
+ log(`Job ${mirrorId} completed: ${completed}/${total} runs`);
182
+ // Graphile discards task return values, so persist the summary onto the
183
+ // mirror row here. Best-effort: a failure to write the result must not
184
+ // mark the job as failed (it succeeded; we just lose the summary blob).
185
+ await apiPatch(`/api/eval-jobs/${mirrorId}/state`, { result }).catch((err) => {
186
+ log(`result persist failed: ${err instanceof Error ? err.message : String(err)}`);
187
+ });
188
+ return result;
189
+ }
190
+ function buildSummary(results) {
191
+ const completed = results.filter((r) => r.status === 'completed');
192
+ const failed = results.filter((r) => r.status === 'failed');
193
+ const gradedRuns = completed.filter((r) => {
194
+ const grading = r.grading;
195
+ return grading && Object.keys(grading).length > 0;
196
+ });
197
+ const avgPassRate = gradedRuns.length > 0
198
+ ? gradedRuns.reduce((sum, r) => sum + (r.grading?.summary?.pass_rate ?? 0), 0) / gradedRuns.length
199
+ : null;
200
+ return {
201
+ total: results.length,
202
+ completed: completed.length,
203
+ failed: failed.length,
204
+ avgPassRate,
205
+ };
206
+ }
207
+ //# sourceMappingURL=process-eval.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-eval.js","sourceRoot":"","sources":["../../../src/lib/handlers/process-eval.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAsB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAsB,MAAM,uBAAuB,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAiC9D;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,OAAoB,EACpB,OAAmB;IAEnB,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtD,qEAAqE;IACrE,wEAAwE;IACxE,oEAAoE;IACpE,yEAAyE;IACzE,oEAAoE;IACpE,oEAAoE;IACpE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,iBAAiB,CACzB,8CAA8C,OAAO,CAAC,GAAG,CAAC,QAAQ,yCAAyC,CAC5G,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAa,qBAAqB,YAAY,EAAE,CAAC,CAAC;IAC7E,MAAM,SAAS,GAAG,MAAM,MAAM,CAAS,qBAAqB,YAAY,QAAQ,CAAC,CAAC;IAElF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,uEAAuE;QACvE,yDAAyD;QACzD,MAAM,IAAI,iBAAiB,CAAC,6BAA6B,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC;IAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;IAExC,MAAM,cAAc,GAA8C;QAChE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE;KACjD,CAAC;IACF,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACzB,cAAc,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,mBAAmB;IACnB,MAAM,SAAS,GAA6F,EAAE,CAAC;IAC/G,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;YACjC,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,WAAW,EAAE,GAAG,EAAE,EAAE,CAAC;gBAC5C,SAAS,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;YACxG,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,CAAC;IAC/B,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,oBAAoB;IAE3E,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,WAAW,EAAE;QACpD,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,KAAK,4BAA4B,WAAW,MAAM,EAAE;KAC1H,CAAC,CAAC;IAEH,MAAM,OAAO,GAA8B,EAAE,CAAC;IAE9C,uEAAuE;IACvE,KAAK,UAAU,WAAW,CAAC,IAAyB;QAClD,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,aAAa,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;QACnF,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC,CAAC;QAE5C,kDAAkD;QAClD,MAAM,QAAQ,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAE/D,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC;gBACnC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;gBACzB,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,OAAO,EAAE,QAAQ,EAAE,OAAO;gBAC1B,OAAO;gBACP,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;YAEH,IAAI,OAAO,GAA4B,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnF,MAAM,aAAa,GAAG,MAAM,eAAe,CAAC;oBAC1C,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;oBACzB,MAAM,EAAE,UAAU,CAAC,MAAM;oBACzB,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY;oBACrC,KAAK,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK;oBACzC,OAAO;iBACR,CAAC,CAAC;gBACH,OAAO,GAAG,aAAmD,CAAC;YAChE,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;gBACrB,YAAY,EAAE,MAAM,CAAC,EAAE;gBACvB,iBAAiB,EAAE,MAAM,CAAC,OAAO;gBACjC,aAAa,EAAE,IAAI,CAAC,aAAa;gBACjC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS;gBACT,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW;gBACjD,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE;gBAC3F,MAAM,EAAE,EAAE,WAAW,EAAE,UAAU,CAAC,UAAU,EAAE,YAAY,EAAE,UAAU,CAAC,WAAW,EAAE;gBACpF,OAAO;gBACP,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;aAClD,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,QAAQ,EAAE,OAAO,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;QACrB,2CAA2C;QAC3C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,aAAa,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,UAAU,IAAI,CAAC,SAAS,EAAE,CAAC;YACnF,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,WAAW,EAAE;gBACpD,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,KAAK,KAAK,EAAE;aACjF,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACxB,SAAS,EAAE,CAAC;YAEZ,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,WAAW,EAAE;gBACpD,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,KAAK,EAAE,EAAE;aAC9E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,CAAC;QACN,6CAA6C;QAC7C,GAAG,CAAC,WAAW,KAAK,2BAA2B,WAAW,uBAAuB,CAAC,CAAC;QACnF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,SAAS,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,WAAW,CAAC,EAAE,CAAC;YAE3G,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,WAAW,EAAE;gBACpD,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,UAAU,KAAK,KAAK,CAAC,MAAM,eAAe,EAAE;aACtH,CAAC,CAAC;YAEH,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;YAE/D,KAAK,MAAM,SAAS,IAAI,YAAY,EAAE,CAAC;gBACrC,MAAM,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;gBAC3C,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACxB,SAAS,EAAE,CAAC;YACd,CAAC;YAED,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,WAAW,EAAE;gBACpD,MAAM,EAAE,SAAS;gBACjB,QAAQ,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,UAAU,EAAE,EAAE;aACxF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IAEtC,6DAA6D;IAC7D,IAAI,aAAwC,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAiB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACvG,IAAI,CAAC;YACH,GAAG,CAAC,8BAA8B,QAAQ,KAAK,CAAC,CAAC;YACjD,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBACnC,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,aAAa,KAAK,aAAa,CAAC,CAAC;gBACpG,MAAM,WAAW,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;gBACvC,OAAO;oBACL,QAAQ,EAAE,CAAC,CAAC,IAAI;oBAChB,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,YAAY,EAAE,CAAC,CAAC,YAAY;oBAC5B,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,OAAmC,CAAC,CAAC,CAAC,IAAI;oBACtF,MAAM,EAAG,WAAW,EAAE,OAAkC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;iBACpF,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,aAAa,GAAG,MAAM,gBAAgB,CAAC;gBACrC,UAAU,EAAE,MAAM,CAAC,IAAI;gBACvB,WAAW,EAAE,UAAU;gBACvB,KAAK,EAAE,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,KAAK;gBACzC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YACH,GAAG,CAAC,uBAAuB,aAAa,CAAC,aAAa,cAAc,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACrG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,GAAG,CAAC,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,aAAa;QAC1B,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE;QAC/C,CAAC,CAAC,OAAO,CAAC;IACZ,GAAG,CAAC,OAAO,QAAQ,eAAe,SAAS,IAAI,KAAK,OAAO,CAAC,CAAC;IAE7D,wEAAwE;IACxE,uEAAuE;IACvE,wEAAwE;IACxE,MAAM,QAAQ,CAAC,kBAAkB,QAAQ,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACpF,GAAG,CAAC,0BAA0B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,OAAkC;IACtD,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC;IAClE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;IAE5D,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACxC,MAAM,OAAO,GAAG,CAAC,CAAC,OAA8B,CAAC;QACjD,OAAO,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC;QACvC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAE,CAAC,CAAC,OAAe,EAAE,OAAO,EAAE,SAAS,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM;QAC3G,CAAC,CAAC,IAAI,CAAC;IAET,OAAO;QACL,KAAK,EAAE,OAAO,CAAC,MAAM;QACrB,SAAS,EAAE,SAAS,CAAC,MAAM;QAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW;KACZ,CAAC;AACJ,CAAC"}