@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.
- package/README.md +66 -0
- package/dist/base-command.d.ts.map +1 -1
- package/dist/base-command.js +15 -0
- package/dist/base-command.js.map +1 -1
- package/dist/commands/auth/login.d.ts.map +1 -1
- package/dist/commands/auth/login.js +7 -0
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/crons/list.d.ts +7 -0
- package/dist/commands/crons/list.d.ts.map +1 -0
- package/dist/commands/crons/list.js +24 -0
- package/dist/commands/crons/list.js.map +1 -0
- package/dist/commands/crons/run.d.ts +13 -0
- package/dist/commands/crons/run.d.ts.map +1 -0
- package/dist/commands/crons/run.js +48 -0
- package/dist/commands/crons/run.js.map +1 -0
- package/dist/commands/evals/listen.d.ts +28 -2
- package/dist/commands/evals/listen.d.ts.map +1 -1
- package/dist/commands/evals/listen.js +159 -25
- package/dist/commands/evals/listen.js.map +1 -1
- package/dist/commands/evals/listen.test.d.ts +2 -0
- package/dist/commands/evals/listen.test.d.ts.map +1 -0
- package/dist/commands/evals/listen.test.js +48 -0
- package/dist/commands/evals/listen.test.js.map +1 -0
- package/dist/commands/gateway/ensure.js +1 -1
- package/dist/commands/gateway/ensure.js.map +1 -1
- package/dist/commands/hooks/install.d.ts.map +1 -1
- package/dist/commands/hooks/install.js +40 -3
- package/dist/commands/hooks/install.js.map +1 -1
- package/dist/commands/hooks/run.js +1 -1
- package/dist/commands/hooks/run.js.map +1 -1
- package/dist/commands/hooks/uninstall.d.ts.map +1 -1
- package/dist/commands/hooks/uninstall.js +9 -1
- package/dist/commands/hooks/uninstall.js.map +1 -1
- package/dist/commands/org/current.d.ts +7 -0
- package/dist/commands/org/current.d.ts.map +1 -0
- package/dist/commands/org/current.js +70 -0
- package/dist/commands/org/current.js.map +1 -0
- package/dist/commands/org/list.d.ts +7 -0
- package/dist/commands/org/list.d.ts.map +1 -0
- package/dist/commands/org/list.js +37 -0
- package/dist/commands/org/list.js.map +1 -0
- package/dist/commands/org/switch.d.ts +13 -0
- package/dist/commands/org/switch.d.ts.map +1 -0
- package/dist/commands/org/switch.js +52 -0
- package/dist/commands/org/switch.js.map +1 -0
- package/dist/commands/proxy/restart.d.ts +11 -0
- package/dist/commands/proxy/restart.d.ts.map +1 -0
- package/dist/commands/proxy/restart.js +36 -0
- package/dist/commands/proxy/restart.js.map +1 -0
- package/dist/commands/proxy/start.d.ts.map +1 -1
- package/dist/commands/proxy/start.js +4 -0
- package/dist/commands/proxy/start.js.map +1 -1
- package/dist/commands/service/install.d.ts +16 -0
- package/dist/commands/service/install.d.ts.map +1 -1
- package/dist/commands/service/install.js +145 -6
- package/dist/commands/service/install.js.map +1 -1
- package/dist/commands/service/uninstall.d.ts.map +1 -1
- package/dist/commands/service/uninstall.js +28 -0
- package/dist/commands/service/uninstall.js.map +1 -1
- package/dist/commands/sessions/start.d.ts.map +1 -1
- package/dist/commands/sessions/start.js +5 -0
- package/dist/commands/sessions/start.js.map +1 -1
- package/dist/commands/signals/report.d.ts +10 -0
- package/dist/commands/signals/report.d.ts.map +1 -0
- package/dist/commands/signals/report.js +35 -0
- package/dist/commands/signals/report.js.map +1 -0
- package/dist/commands/signals/report.test.d.ts +2 -0
- package/dist/commands/signals/report.test.d.ts.map +1 -0
- package/dist/commands/signals/report.test.js +65 -0
- package/dist/commands/signals/report.test.js.map +1 -0
- package/dist/commands/skills/export-approved.d.ts +10 -0
- package/dist/commands/skills/export-approved.d.ts.map +1 -0
- package/dist/commands/skills/export-approved.js +31 -0
- package/dist/commands/skills/export-approved.js.map +1 -0
- package/dist/commands/skills/publish.d.ts +17 -0
- package/dist/commands/skills/publish.d.ts.map +1 -0
- package/dist/commands/skills/publish.js +80 -0
- package/dist/commands/skills/publish.js.map +1 -0
- package/dist/commands/skills/update.d.ts +3 -0
- package/dist/commands/skills/update.d.ts.map +1 -1
- package/dist/commands/skills/update.js +17 -6
- package/dist/commands/skills/update.js.map +1 -1
- package/dist/commands/suggestions/accept.d.ts +16 -0
- package/dist/commands/suggestions/accept.d.ts.map +1 -0
- package/dist/commands/suggestions/accept.js +61 -0
- package/dist/commands/suggestions/accept.js.map +1 -0
- package/dist/commands/suggestions/accept.test.d.ts +2 -0
- package/dist/commands/suggestions/accept.test.d.ts.map +1 -0
- package/dist/commands/suggestions/accept.test.js +52 -0
- package/dist/commands/suggestions/accept.test.js.map +1 -0
- package/dist/commands/suggestions/dismiss.d.ts +10 -0
- package/dist/commands/suggestions/dismiss.d.ts.map +1 -0
- package/dist/commands/suggestions/dismiss.js +26 -0
- package/dist/commands/suggestions/dismiss.js.map +1 -0
- package/dist/commands/suggestions/list.d.ts +10 -0
- package/dist/commands/suggestions/list.d.ts.map +1 -0
- package/dist/commands/suggestions/list.js +40 -0
- package/dist/commands/suggestions/list.js.map +1 -0
- package/dist/commands/suggestions/refresh.d.ts +7 -0
- package/dist/commands/suggestions/refresh.d.ts.map +1 -0
- package/dist/commands/suggestions/refresh.js +11 -0
- package/dist/commands/suggestions/refresh.js.map +1 -0
- package/dist/dashboard/Dashboard.d.ts.map +1 -1
- package/dist/dashboard/Dashboard.js +7 -1
- package/dist/dashboard/Dashboard.js.map +1 -1
- package/dist/lib/active-org-refresh.d.ts +22 -0
- package/dist/lib/active-org-refresh.d.ts.map +1 -0
- package/dist/lib/active-org-refresh.js +108 -0
- package/dist/lib/active-org-refresh.js.map +1 -0
- package/dist/lib/active-org-refresh.test.d.ts +2 -0
- package/dist/lib/active-org-refresh.test.d.ts.map +1 -0
- package/dist/lib/active-org-refresh.test.js +190 -0
- package/dist/lib/active-org-refresh.test.js.map +1 -0
- package/dist/lib/active-org.d.ts +43 -0
- package/dist/lib/active-org.d.ts.map +1 -0
- package/dist/lib/active-org.js +96 -0
- package/dist/lib/active-org.js.map +1 -0
- package/dist/lib/active-org.test.d.ts +2 -0
- package/dist/lib/active-org.test.d.ts.map +1 -0
- package/dist/lib/active-org.test.js +147 -0
- package/dist/lib/active-org.test.js.map +1 -0
- package/dist/lib/cron-registry.d.ts +47 -0
- package/dist/lib/cron-registry.d.ts.map +1 -0
- package/dist/lib/cron-registry.js +102 -0
- package/dist/lib/cron-registry.js.map +1 -0
- package/dist/lib/cron-registry.test.d.ts +2 -0
- package/dist/lib/cron-registry.test.d.ts.map +1 -0
- package/dist/lib/cron-registry.test.js +136 -0
- package/dist/lib/cron-registry.test.js.map +1 -0
- package/dist/lib/cron-runner.d.ts +16 -0
- package/dist/lib/cron-runner.d.ts.map +1 -0
- package/dist/lib/cron-runner.js +68 -0
- package/dist/lib/cron-runner.js.map +1 -0
- package/dist/lib/detect-languages.d.ts +7 -0
- package/dist/lib/detect-languages.d.ts.map +1 -0
- package/dist/lib/detect-languages.js +113 -0
- package/dist/lib/detect-languages.js.map +1 -0
- package/dist/lib/detect-languages.test.d.ts +2 -0
- package/dist/lib/detect-languages.test.d.ts.map +1 -0
- package/dist/lib/detect-languages.test.js +29 -0
- package/dist/lib/detect-languages.test.js.map +1 -0
- package/dist/lib/eval-executor.d.ts.map +1 -1
- package/dist/lib/eval-executor.js +5 -2
- package/dist/lib/eval-executor.js.map +1 -1
- package/dist/lib/gateway-entry.js +4 -1
- package/dist/lib/gateway-entry.js.map +1 -1
- package/dist/lib/gateway-lifecycle.d.ts +1 -1
- package/dist/lib/gateway-lifecycle.d.ts.map +1 -1
- package/dist/lib/gateway-lifecycle.js +13 -2
- package/dist/lib/gateway-lifecycle.js.map +1 -1
- package/dist/lib/gateway.d.ts +4 -5
- package/dist/lib/gateway.d.ts.map +1 -1
- package/dist/lib/gateway.js +68 -2
- package/dist/lib/gateway.js.map +1 -1
- package/dist/lib/graphile-worker-runner.d.ts +124 -0
- package/dist/lib/graphile-worker-runner.d.ts.map +1 -0
- package/dist/lib/graphile-worker-runner.js +526 -0
- package/dist/lib/graphile-worker-runner.js.map +1 -0
- package/dist/lib/graphile-worker-runner.test.d.ts +2 -0
- package/dist/lib/graphile-worker-runner.test.d.ts.map +1 -0
- package/dist/lib/graphile-worker-runner.test.js +153 -0
- package/dist/lib/graphile-worker-runner.test.js.map +1 -0
- package/dist/lib/handlers/cron-close-stale-sessions.d.ts +3 -0
- package/dist/lib/handlers/cron-close-stale-sessions.d.ts.map +1 -0
- package/dist/lib/handlers/cron-close-stale-sessions.js +8 -0
- package/dist/lib/handlers/cron-close-stale-sessions.js.map +1 -0
- package/dist/lib/handlers/cron-data-integrity-audit.d.ts +3 -0
- package/dist/lib/handlers/cron-data-integrity-audit.d.ts.map +1 -0
- package/dist/lib/handlers/cron-data-integrity-audit.js +16 -0
- package/dist/lib/handlers/cron-data-integrity-audit.js.map +1 -0
- package/dist/lib/handlers/cron-refresh-skills.d.ts +3 -0
- package/dist/lib/handlers/cron-refresh-skills.d.ts.map +1 -0
- package/dist/lib/handlers/cron-refresh-skills.js +91 -0
- package/dist/lib/handlers/cron-refresh-skills.js.map +1 -0
- package/dist/lib/handlers/cron-refresh-skills.test.d.ts +2 -0
- package/dist/lib/handlers/cron-refresh-skills.test.d.ts.map +1 -0
- package/dist/lib/handlers/cron-refresh-skills.test.js +114 -0
- package/dist/lib/handlers/cron-refresh-skills.test.js.map +1 -0
- package/dist/lib/handlers/cron-regenerate-insights.d.ts +3 -0
- package/dist/lib/handlers/cron-regenerate-insights.d.ts.map +1 -0
- package/dist/lib/handlers/cron-regenerate-insights.js +6 -0
- package/dist/lib/handlers/cron-regenerate-insights.js.map +1 -0
- package/dist/lib/handlers/cron-suggest-instructions.d.ts +3 -0
- package/dist/lib/handlers/cron-suggest-instructions.d.ts.map +1 -0
- package/dist/lib/handlers/cron-suggest-instructions.js +159 -0
- package/dist/lib/handlers/cron-suggest-instructions.js.map +1 -0
- package/dist/lib/handlers/cron-suggest-instructions.test.d.ts +2 -0
- package/dist/lib/handlers/cron-suggest-instructions.test.d.ts.map +1 -0
- package/dist/lib/handlers/cron-suggest-instructions.test.js +80 -0
- package/dist/lib/handlers/cron-suggest-instructions.test.js.map +1 -0
- package/dist/lib/handlers/process-conversation.d.ts +35 -0
- package/dist/lib/handlers/process-conversation.d.ts.map +1 -0
- package/dist/lib/handlers/process-conversation.js +35 -0
- package/dist/lib/handlers/process-conversation.js.map +1 -0
- package/dist/lib/handlers/process-eval.d.ts +32 -0
- package/dist/lib/handlers/process-eval.d.ts.map +1 -0
- package/dist/lib/handlers/process-eval.js +207 -0
- package/dist/lib/handlers/process-eval.js.map +1 -0
- package/dist/lib/handlers/process-insights.d.ts +39 -0
- package/dist/lib/handlers/process-insights.d.ts.map +1 -0
- package/dist/lib/handlers/process-insights.js +300 -0
- package/dist/lib/handlers/process-insights.js.map +1 -0
- package/dist/lib/handlers/process-launch.d.ts +29 -0
- package/dist/lib/handlers/process-launch.d.ts.map +1 -0
- package/dist/lib/handlers/process-launch.js +41 -0
- package/dist/lib/handlers/process-launch.js.map +1 -0
- package/dist/lib/hooks-config.d.ts +28 -4
- package/dist/lib/hooks-config.d.ts.map +1 -1
- package/dist/lib/hooks-config.js +138 -10
- package/dist/lib/hooks-config.js.map +1 -1
- package/dist/lib/llm-client.d.ts.map +1 -1
- package/dist/lib/llm-client.js +149 -16
- package/dist/lib/llm-client.js.map +1 -1
- package/dist/lib/mirror-writer-db.d.ts +12 -0
- package/dist/lib/mirror-writer-db.d.ts.map +1 -0
- package/dist/lib/mirror-writer-db.js +51 -0
- package/dist/lib/mirror-writer-db.js.map +1 -0
- package/dist/lib/mirror-writer.d.ts +35 -0
- package/dist/lib/mirror-writer.d.ts.map +1 -0
- package/dist/lib/mirror-writer.js +27 -0
- package/dist/lib/mirror-writer.js.map +1 -0
- package/dist/lib/mirror-writer.test.d.ts +2 -0
- package/dist/lib/mirror-writer.test.d.ts.map +1 -0
- package/dist/lib/mirror-writer.test.js +47 -0
- package/dist/lib/mirror-writer.test.js.map +1 -0
- package/dist/lib/permanent-job-error.d.ts +17 -0
- package/dist/lib/permanent-job-error.d.ts.map +1 -0
- package/dist/lib/permanent-job-error.js +23 -0
- package/dist/lib/permanent-job-error.js.map +1 -0
- package/dist/lib/permanent-job-error.test.d.ts +2 -0
- package/dist/lib/permanent-job-error.test.d.ts.map +1 -0
- package/dist/lib/permanent-job-error.test.js +29 -0
- package/dist/lib/permanent-job-error.test.js.map +1 -0
- package/dist/lib/version-check.d.ts +11 -0
- package/dist/lib/version-check.d.ts.map +1 -0
- package/dist/lib/version-check.js +106 -0
- package/dist/lib/version-check.js.map +1 -0
- package/oclif.manifest.json +611 -81
- package/package.json +19 -5
- package/dist/commands/insights/sync.d.ts +0 -17
- package/dist/commands/insights/sync.d.ts.map +0 -1
- package/dist/commands/insights/sync.js +0 -477
- package/dist/commands/insights/sync.js.map +0 -1
- package/dist/lib/eval-worker.d.ts +0 -12
- package/dist/lib/eval-worker.d.ts.map +0 -1
- package/dist/lib/eval-worker.js +0 -395
- package/dist/lib/eval-worker.js.map +0 -1
- package/dist/lib/insights-worker.d.ts +0 -10
- package/dist/lib/insights-worker.d.ts.map +0 -1
- package/dist/lib/insights-worker.js +0 -329
- package/dist/lib/insights-worker.js.map +0 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Task } from 'graphile-worker';
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a Graphile cron handler with a uniform observability envelope.
|
|
4
|
+
*
|
|
5
|
+
* Every wrapped task emits three log lines on the same `[cron <name>]` prefix:
|
|
6
|
+
* - `[cron <name>] start (job#<id>, attempt <n>/<max>)` — before the handler runs
|
|
7
|
+
* - `[cron <name>] ok in <ms>ms` — on success
|
|
8
|
+
* - `[cron <name>] failed in <ms>ms attempt=<n>/<max>: <err>` — on rejection
|
|
9
|
+
*
|
|
10
|
+
* Why an envelope and not per-handler logging:
|
|
11
|
+
* - Pre-fix, three of five cron handlers logged ad-hoc start lines, two
|
|
12
|
+
* logged nothing. None logged duration. After today's launch-priority +
|
|
13
|
+
* keepalive arc we want a consistent grep-able signature so the dashboard
|
|
14
|
+
* and `flyctl logs | grep '[cron'` give one truth.
|
|
15
|
+
* - Wrapping at the registry boundary keeps individual handlers free of
|
|
16
|
+
* boilerplate. The handler body still emits its own granular progress
|
|
17
|
+
* lines (e.g. `cron_refresh_skills` logs each batch); the envelope just
|
|
18
|
+
* books-ends them.
|
|
19
|
+
*
|
|
20
|
+
* Re-throws the original rejection unchanged so graphile-worker's retry /
|
|
21
|
+
* permanent-fail logic remains intact — the envelope only observes, it
|
|
22
|
+
* never decides.
|
|
23
|
+
*/
|
|
24
|
+
export declare function wrapCronWithEnvelope(name: string, handler: Task): Task;
|
|
25
|
+
/**
|
|
26
|
+
* Single source of truth for every cron task this worker runs. Both the
|
|
27
|
+
* Graphile runner (in graphile-worker-runner.ts) and the `rulemetric crons`
|
|
28
|
+
* CLI commands read from this list so a schedule change in one place
|
|
29
|
+
* propagates everywhere.
|
|
30
|
+
*
|
|
31
|
+
* Naming: `name` is the canonical (un-suffixed) task name. The runner
|
|
32
|
+
* appends `__<userId>` so each laptop's worker only claims its own user's
|
|
33
|
+
* crons from the shared Graphile queue.
|
|
34
|
+
*/
|
|
35
|
+
export interface CronDefinition {
|
|
36
|
+
/** Canonical task name without the per-user suffix. */
|
|
37
|
+
name: string;
|
|
38
|
+
/** Standard 5-field crontab expression (UTC). */
|
|
39
|
+
schedule: string;
|
|
40
|
+
/** One-line human description shown by `rulemetric crons list`. */
|
|
41
|
+
description: string;
|
|
42
|
+
/** Graphile Task handler. */
|
|
43
|
+
handler: Task;
|
|
44
|
+
}
|
|
45
|
+
export declare const CRON_REGISTRY: readonly CronDefinition[];
|
|
46
|
+
export declare function findCron(name: string): CronDefinition | undefined;
|
|
47
|
+
//# sourceMappingURL=cron-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-registry.d.ts","sourceRoot":"","sources":["../../src/lib/cron-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,iBAAiB,CAAC;AAgBxD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,IAAI,CAgDtE;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,WAAW,EAAE,MAAM,CAAC;IACpB,6BAA6B;IAC7B,OAAO,EAAE,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,cAAc,EAiBlD,CAAC;AAEF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEjE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { getTracer } from '@rulemetric/telemetry';
|
|
2
|
+
import { cronRegenerateInsights } from './handlers/cron-regenerate-insights.js';
|
|
3
|
+
import { cronSuggestInstructions } from './handlers/cron-suggest-instructions.js';
|
|
4
|
+
// cron_close_stale_sessions removed in phase 1 (migration 00064 → pg_cron).
|
|
5
|
+
// cron_data_integrity_audit removed in phase 2 (migration 00065 → pg_cron).
|
|
6
|
+
// cron_refresh_skills removed in phase 3 (.github/workflows/refresh-skills-registry.yml
|
|
7
|
+
// now POSTs to /api/skills/sync-public
|
|
8
|
+
// after fetching from GitHub, daily).
|
|
9
|
+
// The handler files are kept as documentation of the original behaviour.
|
|
10
|
+
// cron_close_stale_sessions removed — migrated to Supabase pg_cron in
|
|
11
|
+
// supabase/migrations/00064_pg_cron_close_stale_sessions.sql. The handler
|
|
12
|
+
// file (handlers/cron-close-stale-sessions.ts) is kept as documentation of
|
|
13
|
+
// the original intent + the API endpoint /api/sessions/close-stale it
|
|
14
|
+
// shelled out to, but is no longer registered with the runner.
|
|
15
|
+
/**
|
|
16
|
+
* Wrap a Graphile cron handler with a uniform observability envelope.
|
|
17
|
+
*
|
|
18
|
+
* Every wrapped task emits three log lines on the same `[cron <name>]` prefix:
|
|
19
|
+
* - `[cron <name>] start (job#<id>, attempt <n>/<max>)` — before the handler runs
|
|
20
|
+
* - `[cron <name>] ok in <ms>ms` — on success
|
|
21
|
+
* - `[cron <name>] failed in <ms>ms attempt=<n>/<max>: <err>` — on rejection
|
|
22
|
+
*
|
|
23
|
+
* Why an envelope and not per-handler logging:
|
|
24
|
+
* - Pre-fix, three of five cron handlers logged ad-hoc start lines, two
|
|
25
|
+
* logged nothing. None logged duration. After today's launch-priority +
|
|
26
|
+
* keepalive arc we want a consistent grep-able signature so the dashboard
|
|
27
|
+
* and `flyctl logs | grep '[cron'` give one truth.
|
|
28
|
+
* - Wrapping at the registry boundary keeps individual handlers free of
|
|
29
|
+
* boilerplate. The handler body still emits its own granular progress
|
|
30
|
+
* lines (e.g. `cron_refresh_skills` logs each batch); the envelope just
|
|
31
|
+
* books-ends them.
|
|
32
|
+
*
|
|
33
|
+
* Re-throws the original rejection unchanged so graphile-worker's retry /
|
|
34
|
+
* permanent-fail logic remains intact — the envelope only observes, it
|
|
35
|
+
* never decides.
|
|
36
|
+
*/
|
|
37
|
+
export function wrapCronWithEnvelope(name, handler) {
|
|
38
|
+
return (async (payload, helpers) => {
|
|
39
|
+
const start = Date.now();
|
|
40
|
+
const job = helpers.job;
|
|
41
|
+
const meta = `job#${job.id}, attempt ${job.attempts}/${job.max_attempts}`;
|
|
42
|
+
// Open an OTel span around the entire firing so the worker-side trace
|
|
43
|
+
// surface mirrors the API's. With ConsoleSpanExporter (the default when
|
|
44
|
+
// OTEL_EXPORTER_OTLP_ENDPOINT is unset) this prints to worker-stdout
|
|
45
|
+
// alongside the existing envelope log lines; with OTLP configured it
|
|
46
|
+
// ships to a real backend. `startActiveSpan` makes child spans
|
|
47
|
+
// (e.g. inside the handler if it ever instruments DB calls) inherit
|
|
48
|
+
// this as parent.
|
|
49
|
+
const tracer = getTracer('rulemetric-cron');
|
|
50
|
+
return tracer.startActiveSpan(`cron ${name}`, {
|
|
51
|
+
attributes: {
|
|
52
|
+
'cron.name': name,
|
|
53
|
+
'cron.job_id': String(job.id),
|
|
54
|
+
'cron.attempt': job.attempts,
|
|
55
|
+
'cron.max_attempts': job.max_attempts,
|
|
56
|
+
},
|
|
57
|
+
}, async (span) => {
|
|
58
|
+
helpers.logger.info(`[cron ${name}] start (${meta})`);
|
|
59
|
+
try {
|
|
60
|
+
await handler(payload, helpers);
|
|
61
|
+
const duration = Date.now() - start;
|
|
62
|
+
helpers.logger.info(`[cron ${name}] ok in ${duration}ms`);
|
|
63
|
+
span.setAttribute('cron.duration_ms', duration);
|
|
64
|
+
span.setAttribute('cron.outcome', 'ok');
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
const duration = Date.now() - start;
|
|
68
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
69
|
+
helpers.logger.error(`[cron ${name}] failed in ${duration}ms attempt=${job.attempts}/${job.max_attempts}: ${msg}`);
|
|
70
|
+
span.setAttribute('cron.duration_ms', duration);
|
|
71
|
+
span.setAttribute('cron.outcome', 'failed');
|
|
72
|
+
span.recordException(err instanceof Error ? err : new Error(msg));
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
span.end();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export const CRON_REGISTRY = [
|
|
82
|
+
{
|
|
83
|
+
name: 'cron_regenerate_insights',
|
|
84
|
+
schedule: '0 */6 * * *',
|
|
85
|
+
description: 'Regenerate aggregated insights every 6 hours.',
|
|
86
|
+
handler: cronRegenerateInsights,
|
|
87
|
+
},
|
|
88
|
+
// cron_refresh_skills — moved to GitHub Actions (phase 3, daily 06:00 UTC).
|
|
89
|
+
// cron_close_stale_sessions — moved to Supabase pg_cron (migration 00064).
|
|
90
|
+
// cron_data_integrity_audit — moved to Supabase pg_cron (migration 00065).
|
|
91
|
+
// See note at the top of this file.
|
|
92
|
+
{
|
|
93
|
+
name: 'cron_suggest_instructions',
|
|
94
|
+
schedule: '30 4 * * *',
|
|
95
|
+
description: 'Precompute per-project instruction suggestions for the SessionStart hook.',
|
|
96
|
+
handler: cronSuggestInstructions,
|
|
97
|
+
},
|
|
98
|
+
];
|
|
99
|
+
export function findCron(name) {
|
|
100
|
+
return CRON_REGISTRY.find((c) => c.name === name);
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=cron-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-registry.js","sourceRoot":"","sources":["../../src/lib/cron-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAClF,4EAA4E;AAC5E,4EAA4E;AAC5E,6FAA6F;AAC7F,uFAAuF;AACvF,sFAAsF;AACtF,yEAAyE;AACzE,sEAAsE;AACtE,0EAA0E;AAC1E,2EAA2E;AAC3E,sEAAsE;AACtE,+DAA+D;AAE/D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY,EAAE,OAAa;IAC5D,OAAO,CAAC,KAAK,EAAE,OAAgB,EAAE,OAAmB,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAsE,CAAC;QAC3F,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QAE1E,sEAAsE;QACtE,wEAAwE;QACxE,qEAAqE;QACrE,qEAAqE;QACrE,+DAA+D;QAC/D,oEAAoE;QACpE,kBAAkB;QAClB,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC5C,OAAO,MAAM,CAAC,eAAe,CACzB,QAAQ,IAAI,EAAE,EACd;YACI,UAAU,EAAE;gBACR,WAAW,EAAE,IAAI;gBACjB,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7B,cAAc,EAAE,GAAG,CAAC,QAAQ;gBAC5B,mBAAmB,EAAE,GAAG,CAAC,YAAY;aACxC;SACJ,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,YAAY,IAAI,GAAG,CAAC,CAAC;YACtD,IAAI,CAAC;gBACD,MAAM,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBACpC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,WAAW,QAAQ,IAAI,CAAC,CAAC;gBAC1D,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;gBAChD,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;gBACpC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAChB,SAAS,IAAI,eAAe,QAAQ,cAAc,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,KAAK,GAAG,EAAE,CAC/F,CAAC;gBACF,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;gBAChD,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;gBAC5C,IAAI,CAAC,eAAe,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClE,MAAM,GAAG,CAAC;YACd,CAAC;oBAAS,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,CAAC;YACf,CAAC;QACL,CAAC,CACJ,CAAC;IACN,CAAC,CAAS,CAAC;AACf,CAAC;AAuBD,MAAM,CAAC,MAAM,aAAa,GAA8B;IACpD;QACI,IAAI,EAAE,0BAA0B;QAChC,QAAQ,EAAE,aAAa;QACvB,WAAW,EAAE,+CAA+C;QAC5D,OAAO,EAAE,sBAAsB;KAClC;IACD,mFAAmF;IACnF,4EAA4E;IAC5E,4EAA4E;IAC5E,oCAAoC;IACpC;QACI,IAAI,EAAE,2BAA2B;QACjC,QAAQ,EAAE,YAAY;QACtB,WAAW,EAAE,2EAA2E;QACxF,OAAO,EAAE,uBAAuB;KACnC;CACJ,CAAC;AAEF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACjC,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-registry.test.d.ts","sourceRoot":"","sources":["../../src/lib/cron-registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { CRON_REGISTRY, findCron, wrapCronWithEnvelope } from './cron-registry.js';
|
|
3
|
+
describe('CRON_REGISTRY', () => {
|
|
4
|
+
it('has only the claude-spawning crons remaining after the architecture migration', () => {
|
|
5
|
+
// cron_close_stale_sessions → pg_cron (phase 1, migration 00064)
|
|
6
|
+
// cron_data_integrity_audit → pg_cron (phase 2, migration 00065)
|
|
7
|
+
// cron_refresh_skills → GitHub Actions (phase 3,
|
|
8
|
+
// .github/workflows/refresh-skills-registry.yml)
|
|
9
|
+
// Remaining: regenerate_insights + suggest_instructions
|
|
10
|
+
// (genuinely need the laptop — they spawn `claude` CLI per project).
|
|
11
|
+
// These are exactly the two crons the worker is FOR.
|
|
12
|
+
const names = CRON_REGISTRY.map((c) => c.name);
|
|
13
|
+
expect(names).toContain('cron_suggest_instructions');
|
|
14
|
+
expect(names).toContain('cron_regenerate_insights');
|
|
15
|
+
expect(names).not.toContain('cron_close_stale_sessions');
|
|
16
|
+
expect(names).not.toContain('cron_data_integrity_audit');
|
|
17
|
+
expect(names).not.toContain('cron_refresh_skills');
|
|
18
|
+
// Worker is now responsible for ONLY the claude-spawning work.
|
|
19
|
+
expect(names.length).toBe(2);
|
|
20
|
+
});
|
|
21
|
+
it('has unique names (no double-registration)', () => {
|
|
22
|
+
const names = CRON_REGISTRY.map((c) => c.name);
|
|
23
|
+
expect(new Set(names).size).toBe(names.length);
|
|
24
|
+
});
|
|
25
|
+
it('every entry has a valid 5-field crontab expression', () => {
|
|
26
|
+
for (const c of CRON_REGISTRY) {
|
|
27
|
+
const fields = c.schedule.trim().split(/\s+/);
|
|
28
|
+
expect(fields, `${c.name} schedule "${c.schedule}"`).toHaveLength(5);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
it('every entry has a non-empty description', () => {
|
|
32
|
+
for (const c of CRON_REGISTRY) {
|
|
33
|
+
expect(c.description.length, c.name).toBeGreaterThan(10);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
it('findCron returns the right entry by name', () => {
|
|
37
|
+
// cron_refresh_skills (the historical test target) moved to GH Actions
|
|
38
|
+
// in phase 3. Use one of the remaining worker-side crons.
|
|
39
|
+
const found = findCron('cron_suggest_instructions');
|
|
40
|
+
expect(found?.name).toBe('cron_suggest_instructions');
|
|
41
|
+
expect(findCron('nope')).toBeUndefined();
|
|
42
|
+
});
|
|
43
|
+
// (Removed: 'suggest cron is scheduled after refresh-skills cron' — that
|
|
44
|
+
// ordering assertion was about cron_refresh_skills running at 04:00 UTC
|
|
45
|
+
// before cron_suggest_instructions at 04:30 UTC so suggest saw fresh
|
|
46
|
+
// skills. refresh_skills moved to GitHub Actions in phase 3 [daily
|
|
47
|
+
// 06:00 UTC], so it now runs AFTER suggest_instructions. Net effect on
|
|
48
|
+
// user experience: suggest may see day-old skills the day after a new
|
|
49
|
+
// source is added to sources.ts. Acceptable trade-off — the skills
|
|
50
|
+
// registry doesn't change daily in practice. If this becomes a problem,
|
|
51
|
+
// shift suggest_instructions to 06:30 UTC.)
|
|
52
|
+
});
|
|
53
|
+
// Test helpers for the envelope ----------------------------------------------
|
|
54
|
+
/** Build a minimal JobHelpers stub that records calls to `logger.{info,warn,error}`. */
|
|
55
|
+
function makeFakeHelpers(jobOverrides = {}) {
|
|
56
|
+
const calls = [];
|
|
57
|
+
const mkLog = (level) => (msg) => {
|
|
58
|
+
calls.push({ level, msg });
|
|
59
|
+
};
|
|
60
|
+
const logger = { info: mkLog('info'), warn: mkLog('warn'), error: mkLog('error') };
|
|
61
|
+
const job = {
|
|
62
|
+
id: '7777',
|
|
63
|
+
attempts: 1,
|
|
64
|
+
max_attempts: 25,
|
|
65
|
+
...jobOverrides,
|
|
66
|
+
};
|
|
67
|
+
const helpers = { job, logger, addJob: vi.fn() };
|
|
68
|
+
return { helpers, calls };
|
|
69
|
+
}
|
|
70
|
+
describe('wrapCronWithEnvelope', () => {
|
|
71
|
+
// Each cron handler previously logged ad-hoc start lines (some did, some
|
|
72
|
+
// didn't) and never logged duration. The envelope adds a uniform contract
|
|
73
|
+
// around every cron, callable by the runner at registration time. Tested
|
|
74
|
+
// here, not in the runner, so the logic stays a pure unit.
|
|
75
|
+
it('logs a start line BEFORE invoking the wrapped handler', async () => {
|
|
76
|
+
const order = [];
|
|
77
|
+
const { helpers } = makeFakeHelpers({ id: '42', attempts: 1, max_attempts: 3 });
|
|
78
|
+
helpers.logger.info = (m) => order.push(`log:${m}`);
|
|
79
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => {
|
|
80
|
+
order.push('handler-ran');
|
|
81
|
+
});
|
|
82
|
+
await wrapped({}, helpers);
|
|
83
|
+
expect(order[0]).toMatch(/^log:\[cron cron_demo\] start /);
|
|
84
|
+
expect(order).toContain('handler-ran');
|
|
85
|
+
});
|
|
86
|
+
it('logs an ok line with duration when the handler resolves', async () => {
|
|
87
|
+
const { helpers, calls } = makeFakeHelpers();
|
|
88
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => undefined);
|
|
89
|
+
await wrapped({}, helpers);
|
|
90
|
+
const ok = calls.find((c) => /\[cron cron_demo\] ok /.test(c.msg));
|
|
91
|
+
expect(ok).toBeDefined();
|
|
92
|
+
expect(ok.level).toBe('info');
|
|
93
|
+
expect(ok.msg).toMatch(/in \d+ms/);
|
|
94
|
+
});
|
|
95
|
+
it('logs an error line + re-throws when the handler rejects', async () => {
|
|
96
|
+
const { helpers, calls } = makeFakeHelpers({ attempts: 2, max_attempts: 3 });
|
|
97
|
+
const boom = new Error('kaboom');
|
|
98
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => {
|
|
99
|
+
throw boom;
|
|
100
|
+
});
|
|
101
|
+
await expect(wrapped({}, helpers)).rejects.toBe(boom);
|
|
102
|
+
const fail = calls.find((c) => /\[cron cron_demo\] failed /.test(c.msg));
|
|
103
|
+
expect(fail).toBeDefined();
|
|
104
|
+
expect(fail.level).toBe('error');
|
|
105
|
+
expect(fail.msg).toMatch(/attempt=2\/3/);
|
|
106
|
+
expect(fail.msg).toContain('kaboom');
|
|
107
|
+
});
|
|
108
|
+
it('reports duration as a non-negative integer', async () => {
|
|
109
|
+
const { helpers, calls } = makeFakeHelpers();
|
|
110
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => undefined);
|
|
111
|
+
await wrapped({}, helpers);
|
|
112
|
+
const ok = calls.find((c) => /\[cron cron_demo\] ok /.test(c.msg));
|
|
113
|
+
const match = ok.msg.match(/in (\d+)ms/);
|
|
114
|
+
expect(match).not.toBeNull();
|
|
115
|
+
expect(Number(match[1])).toBeGreaterThanOrEqual(0);
|
|
116
|
+
});
|
|
117
|
+
it('carries job#id and attempt info on the start line for grep-ability', async () => {
|
|
118
|
+
const { helpers, calls } = makeFakeHelpers({ id: '9999', attempts: 3, max_attempts: 25 });
|
|
119
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => undefined);
|
|
120
|
+
await wrapped({}, helpers);
|
|
121
|
+
const start = calls.find((c) => /\[cron cron_demo\] start /.test(c.msg));
|
|
122
|
+
expect(start.msg).toMatch(/job#9999/);
|
|
123
|
+
expect(start.msg).toMatch(/attempt 3\/25/);
|
|
124
|
+
});
|
|
125
|
+
it('preserves non-Error throws (e.g. string) without crashing the envelope', async () => {
|
|
126
|
+
const { helpers, calls } = makeFakeHelpers();
|
|
127
|
+
const wrapped = wrapCronWithEnvelope('cron_demo', async () => {
|
|
128
|
+
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
|
129
|
+
throw 'just-a-string';
|
|
130
|
+
});
|
|
131
|
+
await expect(wrapped({}, helpers)).rejects.toBe('just-a-string');
|
|
132
|
+
const fail = calls.find((c) => c.level === 'error');
|
|
133
|
+
expect(fail.msg).toContain('just-a-string');
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
//# sourceMappingURL=cron-registry.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-registry.test.js","sourceRoot":"","sources":["../../src/lib/cron-registry.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface CronRunResult {
|
|
2
|
+
name: string;
|
|
3
|
+
durationMs: number;
|
|
4
|
+
ok: boolean;
|
|
5
|
+
error?: string;
|
|
6
|
+
logs: Array<{
|
|
7
|
+
level: string;
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Synchronously invoke a cron handler by name. Returns a structured result
|
|
13
|
+
* with captured log lines so callers (CLI, tests) can render or assert.
|
|
14
|
+
*/
|
|
15
|
+
export declare function runCronByName(name: string): Promise<CronRunResult>;
|
|
16
|
+
//# sourceMappingURL=cron-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-runner.d.ts","sourceRoot":"","sources":["../../src/lib/cron-runner.ts"],"names":[],"mappings":"AAwCA,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAyBxE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { findCron } from './cron-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* Minimal JobHelpers stub for invoking a cron handler outside Graphile
|
|
4
|
+
* (from `rulemetric crons run`, tests, etc.). Handlers in this codebase
|
|
5
|
+
* only use `helpers.logger` and `helpers.job` — we provide both.
|
|
6
|
+
*/
|
|
7
|
+
function makeStubHelpers(name, onLog) {
|
|
8
|
+
const logger = {
|
|
9
|
+
info: (msg) => onLog('info', msg),
|
|
10
|
+
warn: (msg) => onLog('warn', msg),
|
|
11
|
+
error: (msg) => onLog('error', msg),
|
|
12
|
+
debug: (msg) => onLog('debug', msg),
|
|
13
|
+
scope: () => logger,
|
|
14
|
+
};
|
|
15
|
+
const job = {
|
|
16
|
+
id: 0n,
|
|
17
|
+
task_identifier: name,
|
|
18
|
+
attempts: 0,
|
|
19
|
+
max_attempts: 1,
|
|
20
|
+
payload: {},
|
|
21
|
+
run_at: new Date(),
|
|
22
|
+
created_at: new Date(),
|
|
23
|
+
updated_at: new Date(),
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
logger,
|
|
27
|
+
job: job,
|
|
28
|
+
// The handlers never call these, but the type demands them:
|
|
29
|
+
withPgClient: () => { throw new Error('withPgClient not available in stub helpers'); },
|
|
30
|
+
query: () => { throw new Error('query not available in stub helpers'); },
|
|
31
|
+
addJob: () => { throw new Error('addJob not available in stub helpers'); },
|
|
32
|
+
getQueueName: () => null,
|
|
33
|
+
abortPromise: new Promise(() => { }),
|
|
34
|
+
abortSignal: new AbortController().signal,
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Synchronously invoke a cron handler by name. Returns a structured result
|
|
40
|
+
* with captured log lines so callers (CLI, tests) can render or assert.
|
|
41
|
+
*/
|
|
42
|
+
export async function runCronByName(name) {
|
|
43
|
+
const def = findCron(name);
|
|
44
|
+
if (!def) {
|
|
45
|
+
return {
|
|
46
|
+
name, durationMs: 0, ok: false,
|
|
47
|
+
error: `Unknown cron: ${name}`,
|
|
48
|
+
logs: [],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const logs = [];
|
|
52
|
+
const helpers = makeStubHelpers(name, (level, message) => logs.push({ level, message }));
|
|
53
|
+
const start = Date.now();
|
|
54
|
+
try {
|
|
55
|
+
await def.handler({}, helpers);
|
|
56
|
+
return { name, durationMs: Date.now() - start, ok: true, logs };
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
return {
|
|
60
|
+
name,
|
|
61
|
+
durationMs: Date.now() - start,
|
|
62
|
+
ok: false,
|
|
63
|
+
error: err instanceof Error ? err.message : String(err),
|
|
64
|
+
logs,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=cron-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-runner.js","sourceRoot":"","sources":["../../src/lib/cron-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walk a directory up to MAX_DEPTH levels and collect filesystem signals.
|
|
3
|
+
* Returns a deduplicated array of language names. Requires ≥2 distinct
|
|
4
|
+
* signals before the caller scores; one signal is treated as insufficient.
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectLanguages(projectPath: string): string[];
|
|
7
|
+
//# sourceMappingURL=detect-languages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-languages.d.ts","sourceRoot":"","sources":["../../src/lib/detect-languages.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CA6E7D"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { existsSync, statSync, readdirSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const EXCLUDE_DIRS = new Set([
|
|
4
|
+
'node_modules', '.git', 'dist', 'build', '.next', '.turbo',
|
|
5
|
+
'.worktrees', 'target', 'venv', '__pycache__', '.cache',
|
|
6
|
+
]);
|
|
7
|
+
const MAX_DEPTH = 3;
|
|
8
|
+
/**
|
|
9
|
+
* Walk a directory up to MAX_DEPTH levels and collect filesystem signals.
|
|
10
|
+
* Returns a deduplicated array of language names. Requires ≥2 distinct
|
|
11
|
+
* signals before the caller scores; one signal is treated as insufficient.
|
|
12
|
+
*/
|
|
13
|
+
export function detectLanguages(projectPath) {
|
|
14
|
+
if (!existsSync(projectPath))
|
|
15
|
+
return [];
|
|
16
|
+
const signals = new Set();
|
|
17
|
+
const walk = (dir, depth) => {
|
|
18
|
+
if (depth > MAX_DEPTH)
|
|
19
|
+
return;
|
|
20
|
+
let entries;
|
|
21
|
+
try {
|
|
22
|
+
entries = readdirSync(dir);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
// Inspect file markers at this level. Each marker contributes a *distinct*
|
|
28
|
+
// signal so two files for the same language (e.g. pyproject.toml +
|
|
29
|
+
// requirements.txt) clear the ≥2-signals minimum on their own.
|
|
30
|
+
for (const name of entries) {
|
|
31
|
+
if (name === 'package.json')
|
|
32
|
+
signals.add('JavaScript/TypeScript');
|
|
33
|
+
if (name === 'tsconfig.json')
|
|
34
|
+
signals.add('TypeScript-config');
|
|
35
|
+
if (name === 'pyproject.toml')
|
|
36
|
+
signals.add('Python-pyproject');
|
|
37
|
+
if (name === 'setup.py')
|
|
38
|
+
signals.add('Python-setup');
|
|
39
|
+
if (name === 'requirements.txt')
|
|
40
|
+
signals.add('Python-requirements');
|
|
41
|
+
if (name === 'Pipfile')
|
|
42
|
+
signals.add('Python-pipfile');
|
|
43
|
+
if (name === 'Cargo.toml')
|
|
44
|
+
signals.add('Rust-cargo');
|
|
45
|
+
if (name === 'go.mod')
|
|
46
|
+
signals.add('Go-mod');
|
|
47
|
+
if (name === 'pom.xml')
|
|
48
|
+
signals.add('Java-pom');
|
|
49
|
+
if (name === 'build.gradle' || name === 'build.gradle.kts')
|
|
50
|
+
signals.add('Java-gradle');
|
|
51
|
+
if (name === 'Gemfile')
|
|
52
|
+
signals.add('Ruby-gemfile');
|
|
53
|
+
if (name === 'composer.json')
|
|
54
|
+
signals.add('PHP-composer');
|
|
55
|
+
if (name.endsWith('.ts') || name.endsWith('.tsx'))
|
|
56
|
+
signals.add('TypeScript-source');
|
|
57
|
+
if (name.endsWith('.py'))
|
|
58
|
+
signals.add('Python-source');
|
|
59
|
+
if (name.endsWith('.rs'))
|
|
60
|
+
signals.add('Rust-source');
|
|
61
|
+
if (name.endsWith('.go'))
|
|
62
|
+
signals.add('Go-source');
|
|
63
|
+
}
|
|
64
|
+
if (depth >= MAX_DEPTH)
|
|
65
|
+
return;
|
|
66
|
+
// Recurse into non-excluded subdirectories
|
|
67
|
+
for (const name of entries) {
|
|
68
|
+
if (EXCLUDE_DIRS.has(name))
|
|
69
|
+
continue;
|
|
70
|
+
const full = path.join(dir, name);
|
|
71
|
+
try {
|
|
72
|
+
if (statSync(full).isDirectory())
|
|
73
|
+
walk(full, depth + 1);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// skip unreadable
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
walk(projectPath, 0);
|
|
81
|
+
// Collapse the raw signals into language names for the LLM prompt
|
|
82
|
+
const result = new Set();
|
|
83
|
+
if (signals.has('TypeScript-source') || signals.has('TypeScript-config')) {
|
|
84
|
+
result.add('TypeScript');
|
|
85
|
+
}
|
|
86
|
+
else if (signals.has('JavaScript/TypeScript')) {
|
|
87
|
+
result.add('JavaScript');
|
|
88
|
+
}
|
|
89
|
+
if (signals.has('Python-pyproject') ||
|
|
90
|
+
signals.has('Python-setup') ||
|
|
91
|
+
signals.has('Python-requirements') ||
|
|
92
|
+
signals.has('Python-pipfile') ||
|
|
93
|
+
signals.has('Python-source'))
|
|
94
|
+
result.add('Python');
|
|
95
|
+
if (signals.has('Rust-cargo') || signals.has('Rust-source'))
|
|
96
|
+
result.add('Rust');
|
|
97
|
+
if (signals.has('Go-mod') || signals.has('Go-source'))
|
|
98
|
+
result.add('Go');
|
|
99
|
+
if (signals.has('Java-pom') || signals.has('Java-gradle'))
|
|
100
|
+
result.add('Java');
|
|
101
|
+
if (signals.has('Ruby-gemfile'))
|
|
102
|
+
result.add('Ruby');
|
|
103
|
+
if (signals.has('PHP-composer'))
|
|
104
|
+
result.add('PHP');
|
|
105
|
+
// The minimum-2-signals gate counts the raw signals, not the
|
|
106
|
+
// normalized language list. A package.json + tsconfig.json + .ts source
|
|
107
|
+
// is three signals → strong evidence even though the language collapses
|
|
108
|
+
// to one entry. A bare package.json with no .ts/.js source is one signal.
|
|
109
|
+
if (signals.size < 2)
|
|
110
|
+
return [];
|
|
111
|
+
return [...result];
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=detect-languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-languages.js","sourceRoot":"","sources":["../../src/lib/detect-languages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-languages.test.d.ts","sourceRoot":"","sources":["../../src/lib/detect-languages.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
2
|
+
import { mkdtempSync, writeFileSync, mkdirSync, 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 dir;
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
dir = mkdtempSync(path.join(tmpdir(), 'rm-lang-test-'));
|
|
10
|
+
writeFileSync(path.join(dir, 'package.json'), '{}');
|
|
11
|
+
writeFileSync(path.join(dir, 'tsconfig.json'), '{}');
|
|
12
|
+
mkdirSync(path.join(dir, 'src'));
|
|
13
|
+
writeFileSync(path.join(dir, 'src', 'index.ts'), '');
|
|
14
|
+
});
|
|
15
|
+
afterAll(() => rmSync(dir, { recursive: true, force: true }));
|
|
16
|
+
it('returns TypeScript when ≥2 signals present', () => {
|
|
17
|
+
expect(detectLanguages(dir)).toEqual(['TypeScript']);
|
|
18
|
+
});
|
|
19
|
+
it('returns [] for nonexistent paths', () => {
|
|
20
|
+
expect(detectLanguages('/no/such/path')).toEqual([]);
|
|
21
|
+
});
|
|
22
|
+
it('returns [] when only one signal is present', () => {
|
|
23
|
+
const lone = mkdtempSync(path.join(tmpdir(), 'rm-lang-lone-'));
|
|
24
|
+
writeFileSync(path.join(lone, 'package.json'), '{}');
|
|
25
|
+
expect(detectLanguages(lone)).toEqual([]);
|
|
26
|
+
rmSync(lone, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
//# sourceMappingURL=detect-languages.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-languages.test.js","sourceRoot":"","sources":["../../src/lib/detect-languages.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,IAAI,GAAW,CAAC;IAChB,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QACxD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;QACpD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,CAAC;QACrD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACjC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE9D,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;QAC/D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-executor.d.ts","sourceRoot":"","sources":["../../src/lib/eval-executor.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"eval-executor.d.ts","sourceRoot":"","sources":["../../src/lib/eval-executor.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8F3F"}
|
|
@@ -15,10 +15,13 @@ export async function executeEval(options) {
|
|
|
15
15
|
}
|
|
16
16
|
const startTime = Date.now();
|
|
17
17
|
return new Promise((resolve) => {
|
|
18
|
-
// Remove CLAUDECODE flag so spawned claude doesn't think it's a nested session
|
|
19
|
-
//
|
|
18
|
+
// Remove CLAUDECODE flag so spawned claude doesn't think it's a nested session.
|
|
19
|
+
// Remove HTTPS_PROXY so eval runs bypass the capture proxy — these are internal
|
|
20
|
+
// infrastructure calls, not user sessions. Routing through the proxy creates
|
|
21
|
+
// phantom sessions that pollute insights.
|
|
20
22
|
const env = { ...process.env };
|
|
21
23
|
delete env.CLAUDECODE;
|
|
24
|
+
delete env.HTTPS_PROXY;
|
|
22
25
|
const proc = spawn('claude', args, {
|
|
23
26
|
cwd: workDir,
|
|
24
27
|
env,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-executor.js","sourceRoot":"","sources":["../../src/lib/eval-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAmB3C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA4B;IAC5D,MAAM,EACJ,MAAM,EACN,aAAa,EACb,YAAY,EACZ,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,EACvB,OAAO,GAAG,OAAO,EACjB,KAAK,GACN,GAAG,OAAO,CAAC;IAEZ,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,aAAa,IAAI,YAAY,CAAC;IAChD,IAAI,SAAS,EAAE,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,EAAE;QACjD,gFAAgF;QAChF,
|
|
1
|
+
{"version":3,"file":"eval-executor.js","sourceRoot":"","sources":["../../src/lib/eval-executor.ts"],"names":[],"mappings":"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"}
|