openwolf-enhanced 1.9.3

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 (127) hide show
  1. package/CHANGELOG.md +386 -0
  2. package/LICENSE +663 -0
  3. package/NOTICE +48 -0
  4. package/README.md +283 -0
  5. package/dist/bin/openwolf.js +10 -0
  6. package/dist/bin/openwolf.js.map +1 -0
  7. package/dist/dashboard/assets/AISuggestions-DHXOgHMM.js +9 -0
  8. package/dist/dashboard/assets/ActivityTimeline-BXLwacZV.js +1 -0
  9. package/dist/dashboard/assets/AnatomyBrowser-CUyC8M2I.js +1 -0
  10. package/dist/dashboard/assets/BugLog-Bxvy1sPW.js +1 -0
  11. package/dist/dashboard/assets/CerebrumViewer-DCySVmzA.js +1 -0
  12. package/dist/dashboard/assets/CronStatus-BA4fmQX3.js +1 -0
  13. package/dist/dashboard/assets/DesignQC-BhNEKryS.js +1 -0
  14. package/dist/dashboard/assets/MemoryViewer-0y9lsDUO.js +1 -0
  15. package/dist/dashboard/assets/ProjectOverview-CC51rVRe.js +1 -0
  16. package/dist/dashboard/assets/StatusBadge-4NJI_F2G.js +1 -0
  17. package/dist/dashboard/assets/TokenUsage-7pCxlnCX.js +55 -0
  18. package/dist/dashboard/assets/index-4O5rk-qB.css +2 -0
  19. package/dist/dashboard/assets/index-jfgWxxsn.js +13 -0
  20. package/dist/dashboard/assets/utils-BqE_aDxV.js +1 -0
  21. package/dist/dashboard/index.html +16 -0
  22. package/dist/hooks/post-read.js +85 -0
  23. package/dist/hooks/post-write.js +520 -0
  24. package/dist/hooks/pre-read.js +107 -0
  25. package/dist/hooks/pre-write.js +120 -0
  26. package/dist/hooks/session-start.js +76 -0
  27. package/dist/hooks/shared.js +0 -0
  28. package/dist/hooks/stop.js +219 -0
  29. package/dist/src/buglog/bug-matcher.js +3 -0
  30. package/dist/src/buglog/bug-matcher.js.map +1 -0
  31. package/dist/src/buglog/bug-tracker.js +89 -0
  32. package/dist/src/buglog/bug-tracker.js.map +1 -0
  33. package/dist/src/cli/bug-cmd.js +31 -0
  34. package/dist/src/cli/bug-cmd.js.map +1 -0
  35. package/dist/src/cli/cron-cmd.js +107 -0
  36. package/dist/src/cli/cron-cmd.js.map +1 -0
  37. package/dist/src/cli/daemon-cmd.js +180 -0
  38. package/dist/src/cli/daemon-cmd.js.map +1 -0
  39. package/dist/src/cli/dashboard.js +88 -0
  40. package/dist/src/cli/dashboard.js.map +1 -0
  41. package/dist/src/cli/designqc-cmd.js +31 -0
  42. package/dist/src/cli/designqc-cmd.js.map +1 -0
  43. package/dist/src/cli/doctor-cmd.js +94 -0
  44. package/dist/src/cli/doctor-cmd.js.map +1 -0
  45. package/dist/src/cli/index.js +158 -0
  46. package/dist/src/cli/index.js.map +1 -0
  47. package/dist/src/cli/init.js +493 -0
  48. package/dist/src/cli/init.js.map +1 -0
  49. package/dist/src/cli/registry.js +93 -0
  50. package/dist/src/cli/registry.js.map +1 -0
  51. package/dist/src/cli/scan.js +39 -0
  52. package/dist/src/cli/scan.js.map +1 -0
  53. package/dist/src/cli/status.js +98 -0
  54. package/dist/src/cli/status.js.map +1 -0
  55. package/dist/src/cli/update.js +435 -0
  56. package/dist/src/cli/update.js.map +1 -0
  57. package/dist/src/daemon/cron-engine.js +321 -0
  58. package/dist/src/daemon/cron-engine.js.map +1 -0
  59. package/dist/src/daemon/file-watcher.js +64 -0
  60. package/dist/src/daemon/file-watcher.js.map +1 -0
  61. package/dist/src/daemon/health.js +23 -0
  62. package/dist/src/daemon/health.js.map +1 -0
  63. package/dist/src/daemon/wolf-daemon.js +440 -0
  64. package/dist/src/daemon/wolf-daemon.js.map +1 -0
  65. package/dist/src/designqc/designqc-capture.js +278 -0
  66. package/dist/src/designqc/designqc-capture.js.map +1 -0
  67. package/dist/src/designqc/designqc-engine.js +159 -0
  68. package/dist/src/designqc/designqc-engine.js.map +1 -0
  69. package/dist/src/designqc/designqc-types.js +5 -0
  70. package/dist/src/designqc/designqc-types.js.map +1 -0
  71. package/dist/src/hooks/post-read.js +86 -0
  72. package/dist/src/hooks/post-read.js.map +1 -0
  73. package/dist/src/hooks/post-write.js +521 -0
  74. package/dist/src/hooks/post-write.js.map +1 -0
  75. package/dist/src/hooks/pre-read.js +108 -0
  76. package/dist/src/hooks/pre-read.js.map +1 -0
  77. package/dist/src/hooks/pre-write.js +121 -0
  78. package/dist/src/hooks/pre-write.js.map +1 -0
  79. package/dist/src/hooks/session-start.js +77 -0
  80. package/dist/src/hooks/session-start.js.map +1 -0
  81. package/dist/src/hooks/shared.js +0 -0
  82. package/dist/src/hooks/shared.js.map +1 -0
  83. package/dist/src/hooks/stop.js +220 -0
  84. package/dist/src/hooks/stop.js.map +1 -0
  85. package/dist/src/scanner/anatomy-scanner.js +278 -0
  86. package/dist/src/scanner/anatomy-scanner.js.map +1 -0
  87. package/dist/src/scanner/description-extractor.js +1007 -0
  88. package/dist/src/scanner/description-extractor.js.map +1 -0
  89. package/dist/src/scanner/project-root.js +52 -0
  90. package/dist/src/scanner/project-root.js.map +1 -0
  91. package/dist/src/tracker/token-estimator.js +20 -0
  92. package/dist/src/tracker/token-estimator.js.map +1 -0
  93. package/dist/src/tracker/token-ledger.js +55 -0
  94. package/dist/src/tracker/token-ledger.js.map +1 -0
  95. package/dist/src/tracker/waste-detector.js +101 -0
  96. package/dist/src/tracker/waste-detector.js.map +1 -0
  97. package/dist/src/utils/dashboard-auth.js +50 -0
  98. package/dist/src/utils/dashboard-auth.js.map +1 -0
  99. package/dist/src/utils/fs-safe.js +135 -0
  100. package/dist/src/utils/fs-safe.js.map +1 -0
  101. package/dist/src/utils/hooks-deploy.js +70 -0
  102. package/dist/src/utils/hooks-deploy.js.map +1 -0
  103. package/dist/src/utils/logger.js +48 -0
  104. package/dist/src/utils/logger.js.map +1 -0
  105. package/dist/src/utils/maintenance.js +385 -0
  106. package/dist/src/utils/maintenance.js.map +1 -0
  107. package/dist/src/utils/paths.js +23 -0
  108. package/dist/src/utils/paths.js.map +1 -0
  109. package/dist/src/utils/platform.js +14 -0
  110. package/dist/src/utils/platform.js.map +1 -0
  111. package/dist/src/utils/seed.js +61 -0
  112. package/dist/src/utils/seed.js.map +1 -0
  113. package/package.json +82 -0
  114. package/src/templates/OPENWOLF.md +147 -0
  115. package/src/templates/STATUS.md +48 -0
  116. package/src/templates/anatomy.md +5 -0
  117. package/src/templates/buglog.json +4 -0
  118. package/src/templates/cerebrum.md +22 -0
  119. package/src/templates/claude-md-snippet.md +5 -0
  120. package/src/templates/claude-rules-openwolf.md +17 -0
  121. package/src/templates/config.json +83 -0
  122. package/src/templates/cron-manifest.json +97 -0
  123. package/src/templates/cron-state.json +7 -0
  124. package/src/templates/identity.md +9 -0
  125. package/src/templates/memory.md +4 -0
  126. package/src/templates/reframe-frameworks.md +597 -0
  127. package/src/templates/token-ledger.json +21 -0
@@ -0,0 +1,321 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import cron from "node-cron";
4
+ import { readJSON, writeJSON, readText, writeText, withLock } from "../utils/fs-safe.js";
5
+ import { scanProject } from "../scanner/anatomy-scanner.js";
6
+ import { detectWaste } from "../tracker/waste-detector.js";
7
+ export class CronEngine {
8
+ wolfDir;
9
+ projectRoot;
10
+ logger;
11
+ broadcast;
12
+ scheduledTasks = [];
13
+ failureCounts = new Map();
14
+ constructor(wolfDir, projectRoot, logger, broadcast) {
15
+ this.wolfDir = wolfDir;
16
+ this.projectRoot = projectRoot;
17
+ this.logger = logger;
18
+ this.broadcast = broadcast;
19
+ }
20
+ start() {
21
+ const manifest = this.readManifest();
22
+ for (const task of manifest.tasks) {
23
+ if (!task.enabled)
24
+ continue;
25
+ if (!cron.validate(task.schedule)) {
26
+ this.logger.warn(`Invalid cron schedule for ${task.id}: ${task.schedule}`);
27
+ continue;
28
+ }
29
+ const scheduled = cron.schedule(task.schedule, () => {
30
+ this.executeTask(task).catch((err) => {
31
+ this.logger.error(`Task ${task.id} failed: ${err}`);
32
+ });
33
+ });
34
+ this.scheduledTasks.push(scheduled);
35
+ this.logger.info(`Scheduled task: ${task.name} (${task.schedule})`);
36
+ }
37
+ }
38
+ stop() {
39
+ for (const task of this.scheduledTasks) {
40
+ task.stop();
41
+ }
42
+ this.scheduledTasks = [];
43
+ }
44
+ async runTask(taskId) {
45
+ const manifest = this.readManifest();
46
+ const task = manifest.tasks.find((t) => t.id === taskId);
47
+ if (!task) {
48
+ this.logger.warn(`Task not found: ${taskId}`);
49
+ return;
50
+ }
51
+ await this.executeTask(task);
52
+ }
53
+ readManifest() {
54
+ return readJSON(path.join(this.wolfDir, "cron-manifest.json"), { version: 1, tasks: [] });
55
+ }
56
+ readState() {
57
+ // Merge stored state over complete defaults so array fields (execution_log, dead_letter_queue)
58
+ // are always present — a partial cron-state.json used to crash task logging (upstream #4, bug 8).
59
+ const defaults = { last_heartbeat: null, engine_status: "running", execution_log: [], dead_letter_queue: [], upcoming: [] };
60
+ const stored = readJSON(path.join(this.wolfDir, "cron-state.json"), {});
61
+ return { ...defaults, ...stored };
62
+ }
63
+ writeState(state) {
64
+ writeJSON(path.join(this.wolfDir, "cron-state.json"), state);
65
+ }
66
+ async executeTask(task) {
67
+ const startTime = Date.now();
68
+ this.logger.info(`Executing task: ${task.name}`);
69
+ try {
70
+ await this.runAction(task.action);
71
+ const duration = Date.now() - startTime;
72
+ // Log success
73
+ const state = this.readState();
74
+ state.execution_log.push({
75
+ task_id: task.id,
76
+ status: "success",
77
+ timestamp: new Date().toISOString(),
78
+ duration_ms: duration,
79
+ });
80
+ // Keep last 100 entries
81
+ if (state.execution_log.length > 100) {
82
+ state.execution_log = state.execution_log.slice(-100);
83
+ }
84
+ this.writeState(state);
85
+ this.failureCounts.set(task.id, 0);
86
+ this.broadcast({
87
+ type: "cron_executed",
88
+ task_id: task.id,
89
+ status: "success",
90
+ duration_ms: duration,
91
+ });
92
+ this.logger.info(`Task ${task.name} completed in ${duration}ms`);
93
+ }
94
+ catch (err) {
95
+ const errorMsg = err instanceof Error ? err.message : String(err);
96
+ const duration = Date.now() - startTime;
97
+ const failures = (this.failureCounts.get(task.id) ?? 0) + 1;
98
+ this.failureCounts.set(task.id, failures);
99
+ this.logger.error(`Task ${task.name} failed (attempt ${failures}): ${errorMsg}`);
100
+ if (failures < task.retry.max_attempts) {
101
+ // Retry with backoff
102
+ const delay = this.calculateDelay(task.retry.backoff, task.retry.base_delay_seconds, failures);
103
+ this.logger.info(`Retrying ${task.name} in ${delay}ms`);
104
+ setTimeout(() => {
105
+ this.executeTask(task).catch(() => { });
106
+ }, delay);
107
+ }
108
+ else {
109
+ // Dead letter or skip
110
+ const state = this.readState();
111
+ state.execution_log.push({
112
+ task_id: task.id,
113
+ status: "failed",
114
+ timestamp: new Date().toISOString(),
115
+ duration_ms: duration,
116
+ error: errorMsg,
117
+ });
118
+ if (task.failsafe.dead_letter) {
119
+ state.dead_letter_queue.push({
120
+ task_id: task.id,
121
+ error: errorMsg,
122
+ timestamp: new Date().toISOString(),
123
+ attempts: failures,
124
+ });
125
+ // Keep the dead-letter queue bounded (execution_log is already capped elsewhere).
126
+ if (state.dead_letter_queue.length > 100) {
127
+ state.dead_letter_queue = state.dead_letter_queue.slice(-100);
128
+ }
129
+ }
130
+ this.writeState(state);
131
+ this.failureCounts.set(task.id, 0);
132
+ // Notify the dashboard that this task permanently failed (upstream #4, bug 1).
133
+ this.broadcast({ type: "task_error", task_id: task.id, error: errorMsg });
134
+ }
135
+ this.broadcast({
136
+ type: "cron_executed",
137
+ task_id: task.id,
138
+ status: "failed",
139
+ duration_ms: duration,
140
+ });
141
+ }
142
+ }
143
+ calculateDelay(backoff, baseSec, attempt) {
144
+ const baseMs = baseSec * 1000;
145
+ switch (backoff) {
146
+ case "exponential":
147
+ return baseMs * Math.pow(2, attempt - 1);
148
+ case "linear":
149
+ return baseMs * attempt;
150
+ default:
151
+ return 0;
152
+ }
153
+ }
154
+ async runAction(action) {
155
+ switch (action.type) {
156
+ case "scan_project":
157
+ scanProject(this.wolfDir, this.projectRoot);
158
+ break;
159
+ case "consolidate_memory":
160
+ this.consolidateMemory(action.params?.older_than_days ?? 7);
161
+ break;
162
+ case "generate_token_report":
163
+ this.generateTokenReport();
164
+ break;
165
+ case "ai_task":
166
+ await this.runAiTask(action.params);
167
+ break;
168
+ default:
169
+ throw new Error(`Unknown action type: ${action.type}`);
170
+ }
171
+ }
172
+ consolidateMemory(olderThanDays) {
173
+ const memoryPath = path.join(this.wolfDir, "memory.md");
174
+ const content = readText(memoryPath);
175
+ if (!content)
176
+ return;
177
+ const cutoff = new Date();
178
+ cutoff.setDate(cutoff.getDate() - olderThanDays);
179
+ const lines = content.split("\n");
180
+ const result = [];
181
+ let inOldSession = false;
182
+ let oldSessionLines = [];
183
+ let currentSessionDate = null;
184
+ for (const line of lines) {
185
+ const sessionMatch = line.match(/^## Session: (\d{4}-\d{2}-\d{2})/);
186
+ if (sessionMatch) {
187
+ // Flush previous old session
188
+ if (inOldSession && oldSessionLines.length > 0) {
189
+ const actionCount = oldSessionLines.filter((l) => l.startsWith("|") && !l.startsWith("|--") && !l.startsWith("| Time")).length;
190
+ result.push(`> Consolidated session (${actionCount} actions)`);
191
+ result.push("");
192
+ }
193
+ currentSessionDate = new Date(sessionMatch[1]);
194
+ if (currentSessionDate < cutoff) {
195
+ inOldSession = true;
196
+ oldSessionLines = [];
197
+ result.push(line); // Keep the header
198
+ }
199
+ else {
200
+ inOldSession = false;
201
+ result.push(line);
202
+ }
203
+ continue;
204
+ }
205
+ if (inOldSession) {
206
+ oldSessionLines.push(line);
207
+ }
208
+ else {
209
+ result.push(line);
210
+ }
211
+ }
212
+ // Flush last old session
213
+ if (inOldSession && oldSessionLines.length > 0) {
214
+ const actionCount = oldSessionLines.filter((l) => l.startsWith("|") && !l.startsWith("|--") && !l.startsWith("| Time")).length;
215
+ result.push(`> Consolidated session (${actionCount} actions)`);
216
+ result.push("");
217
+ }
218
+ writeText(memoryPath, result.join("\n"));
219
+ }
220
+ generateTokenReport() {
221
+ const flags = detectWaste(this.wolfDir);
222
+ const ledgerPath = path.join(this.wolfDir, "token-ledger.json");
223
+ // Lock the read-modify-write — the stop hook writes the same ledger from another process (M1).
224
+ withLock(ledgerPath, () => {
225
+ const ledger = readJSON(ledgerPath, {});
226
+ // Keep waste_flags bounded (defensive — detectWaste could in principle return many).
227
+ ledger.waste_flags =
228
+ flags.length > 200 ? flags.slice(-200) : flags;
229
+ ledger.optimization_report = {
230
+ last_generated: new Date().toISOString(),
231
+ patterns: flags.map((f) => f.pattern),
232
+ };
233
+ writeJSON(ledgerPath, ledger);
234
+ });
235
+ }
236
+ async runAiTask(params) {
237
+ // Cap each context file so one large file can't blow up the prompt.
238
+ const MAX_CONTEXT_BYTES = 20 * 1024;
239
+ const contextParts = [];
240
+ const rootPrefix = path.resolve(this.projectRoot) + path.sep;
241
+ for (const file of params.context_files) {
242
+ const filePath = path.resolve(this.projectRoot, file);
243
+ // Reject paths that escape the project root (e.g. "../../etc/passwd") — the file
244
+ // contents are fed to the model, so traversal would exfiltrate arbitrary files (#34).
245
+ if (filePath !== path.resolve(this.projectRoot) && !filePath.startsWith(rootPrefix)) {
246
+ contextParts.push(`--- ${file} --- (rejected: outside project root)`);
247
+ continue;
248
+ }
249
+ try {
250
+ let content = fs.readFileSync(filePath, "utf-8");
251
+ if (Buffer.byteLength(content, "utf-8") > MAX_CONTEXT_BYTES) {
252
+ content = "...[truncated — showing most recent]\n" + content.slice(-MAX_CONTEXT_BYTES);
253
+ }
254
+ contextParts.push(`--- ${file} ---\n${content}`);
255
+ }
256
+ catch {
257
+ contextParts.push(`--- ${file} --- (not found)`);
258
+ }
259
+ }
260
+ const fullPrompt = `${params.prompt}\n\n---\nContext:\n${contextParts.join("\n\n")}`;
261
+ // A background daemon can't drive the interactive `claude` CLI (it delegates auth to the
262
+ // desktop app and fails headless). Use a direct API key instead, with a clear error if it's
263
+ // missing — the dashboard then shows a copy-able prompt to run inside a session (upstream #4, bug 2).
264
+ if (!process.env.ANTHROPIC_API_KEY) {
265
+ throw new Error("ANTHROPIC_API_KEY is not set. AI tasks require a direct API key when running as a background daemon. " +
266
+ "Set it in your shell profile: export ANTHROPIC_API_KEY=sk-ant-api03-…");
267
+ }
268
+ let result = await this.runViaApi(fullPrompt, process.env.ANTHROPIC_API_KEY);
269
+ const fenceMatch = result.match(/```[\w]*\n([\s\S]*?)\n```/);
270
+ if (fenceMatch)
271
+ result = fenceMatch[1].trim();
272
+ // Write result to suggestions.json if it's JSON, otherwise treat as a cerebrum update.
273
+ try {
274
+ const parsed = JSON.parse(result);
275
+ writeJSON(path.join(this.wolfDir, "suggestions.json"), { generated_at: new Date().toISOString(), ...parsed });
276
+ }
277
+ catch {
278
+ if (result.includes("## User Preferences") || result.includes("## Key Learnings") || result.includes("# Cerebrum")) {
279
+ writeText(path.join(this.wolfDir, "cerebrum.md"), result);
280
+ }
281
+ }
282
+ }
283
+ async runViaApi(prompt, apiKey) {
284
+ // Abort after 120s so a hung request can't leave the cron task stuck forever
285
+ // (the previous spawnSync path had a 120s timeout; fetch has none by default).
286
+ const controller = new AbortController();
287
+ const timer = setTimeout(() => controller.abort(), 120_000);
288
+ let response;
289
+ try {
290
+ response = await fetch("https://api.anthropic.com/v1/messages", {
291
+ method: "POST",
292
+ headers: {
293
+ "x-api-key": apiKey,
294
+ "anthropic-version": "2023-06-01",
295
+ "content-type": "application/json",
296
+ },
297
+ body: JSON.stringify({
298
+ model: "claude-haiku-4-5-20251001",
299
+ max_tokens: 2048,
300
+ messages: [{ role: "user", content: prompt }],
301
+ }),
302
+ signal: controller.signal,
303
+ });
304
+ }
305
+ catch (err) {
306
+ if (err.name === "AbortError")
307
+ throw new Error("Anthropic API request timed out after 120s");
308
+ throw err;
309
+ }
310
+ finally {
311
+ clearTimeout(timer);
312
+ }
313
+ if (!response.ok) {
314
+ const body = await response.text();
315
+ throw new Error(`Anthropic API error ${response.status}: ${body.slice(0, 200)}`);
316
+ }
317
+ const data = (await response.json());
318
+ return data.content.find((b) => b.type === "text")?.text?.trim() ?? "";
319
+ }
320
+ }
321
+ //# sourceMappingURL=cron-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-engine.js","sourceRoot":"","sources":["../../../src/daemon/cron-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { watch } from "chokidar";
4
+ export function startFileWatcher(wolfDir, logger, broadcast) {
5
+ const watcher = watch(wolfDir, {
6
+ ignoreInitial: true,
7
+ // chokidar 4+ dropped glob-string support in `ignored` — a glob string is treated
8
+ // as a literal path and never matches, silently defeating these ignores. Use a
9
+ // predicate (path, stats?) => boolean so the exclusions actually fire.
10
+ // Large, high-churn files (token-ledger.json / buglog.json): re-read + broadcast of
11
+ // the full content on every write is the daemon's worst waste. The dashboard fetches
12
+ // them via full_state on demand.
13
+ ignored: (filePath) => {
14
+ const base = path.basename(filePath);
15
+ return (base.endsWith(".tmp") ||
16
+ base.endsWith(".lock") ||
17
+ base === "daemon.log" ||
18
+ base === "_session.json" ||
19
+ base === "token-ledger.json" ||
20
+ base === "buglog.json");
21
+ },
22
+ persistent: true,
23
+ awaitWriteFinish: {
24
+ stabilityThreshold: 500,
25
+ pollInterval: 100,
26
+ },
27
+ });
28
+ watcher.on("change", (filePath) => {
29
+ const relativePath = path.relative(wolfDir, filePath);
30
+ const fileName = path.basename(filePath);
31
+ logger.debug(`File changed: ${relativePath}`);
32
+ try {
33
+ const content = fs.readFileSync(filePath, "utf-8");
34
+ broadcast({
35
+ type: "file_changed",
36
+ file: relativePath,
37
+ content,
38
+ timestamp: new Date().toISOString(),
39
+ });
40
+ }
41
+ catch {
42
+ // File might be in process of being written
43
+ }
44
+ // Hot-reload config
45
+ if (fileName === "config.json") {
46
+ logger.info("Config changed — hot-reload not fully implemented yet");
47
+ }
48
+ // Hot-reload cron manifest
49
+ if (fileName === "cron-manifest.json") {
50
+ logger.info("Cron manifest changed — restart daemon to apply");
51
+ }
52
+ });
53
+ watcher.on("add", (filePath) => {
54
+ const relativePath = path.relative(wolfDir, filePath);
55
+ logger.debug(`File added: ${relativePath}`);
56
+ });
57
+ watcher.on("unlink", (filePath) => {
58
+ const relativePath = path.relative(wolfDir, filePath);
59
+ logger.debug(`File removed: ${relativePath}`);
60
+ });
61
+ logger.info("File watcher started on .wolf/");
62
+ return watcher;
63
+ }
64
+ //# sourceMappingURL=file-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../../src/daemon/file-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,KAAK,EAAkB,MAAM,UAAU,CAAC;AAGjD,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,MAAc,EACd,SAAiC;IAEjC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE;QAC7B,aAAa,EAAE,IAAI;QACnB,kFAAkF;QAClF,+EAA+E;QAC/E,uEAAuE;QACvE,oFAAoF;QACpF,qFAAqF;QACrF,iCAAiC;QACjC,OAAO,EAAE,CAAC,QAAgB,EAAW,EAAE;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACrC,OAAO,CACL,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACrB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBACtB,IAAI,KAAK,YAAY;gBACrB,IAAI,KAAK,eAAe;gBACxB,IAAI,KAAK,mBAAmB;gBAC5B,IAAI,KAAK,aAAa,CACvB,CAAC;QACJ,CAAC;QACD,UAAU,EAAE,IAAI;QAChB,gBAAgB,EAAE;YAChB,kBAAkB,EAAE,GAAG;YACvB,YAAY,EAAE,GAAG;SAClB;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAkB,CAAC,CAAC;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAkB,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,iBAAiB,YAAY,EAAE,CAAC,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAkB,EAAE,OAAO,CAAC,CAAC;YAC7D,SAAS,CAAC;gBACR,IAAI,EAAE,cAAc;gBACpB,IAAI,EAAE,YAAY;gBAClB,OAAO;gBACP,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,4CAA4C;QAC9C,CAAC;QAED,oBAAoB;QACpB,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC/B,MAAM,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACvE,CAAC;QAED,2BAA2B;QAC3B,IAAI,QAAQ,KAAK,oBAAoB,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC7B,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAkB,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,eAAe,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAkB,CAAC,CAAC;QAChE,MAAM,CAAC,KAAK,CAAC,iBAAiB,YAAY,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAC9C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import * as path from "node:path";
2
+ import { readJSON } from "../utils/fs-safe.js";
3
+ export function getHealth(wolfDir, startTime) {
4
+ const cronState = readJSON(path.join(wolfDir, "cron-state.json"), {
5
+ last_heartbeat: null,
6
+ dead_letter_queue: [],
7
+ });
8
+ const manifest = readJSON(path.join(wolfDir, "cron-manifest.json"), { tasks: [] });
9
+ const deadLetterCount = cronState.dead_letter_queue.length;
10
+ let status = "healthy";
11
+ if (deadLetterCount > 0)
12
+ status = "degraded";
13
+ if (deadLetterCount > 3)
14
+ status = "unhealthy";
15
+ return {
16
+ status,
17
+ uptime_seconds: Math.floor((Date.now() - startTime) / 1000),
18
+ last_heartbeat: cronState.last_heartbeat,
19
+ tasks: manifest.tasks.length,
20
+ dead_letters: deadLetterCount,
21
+ };
22
+ }
23
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/daemon/health.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAU/C,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,SAAiB;IAC1D,MAAM,SAAS,GAAG,QAAQ,CAGvB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE;QACxC,cAAc,EAAE,IAAI;QACpB,iBAAiB,EAAE,EAAE;KACtB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,QAAQ,CACvB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,oBAAoB,CAAC,EACxC,EAAE,KAAK,EAAE,EAAE,EAAE,CACd,CAAC;IAEF,MAAM,eAAe,GAAG,SAAS,CAAC,iBAAiB,CAAC,MAAM,CAAC;IAC3D,IAAI,MAAM,GAAyC,SAAS,CAAC;IAC7D,IAAI,eAAe,GAAG,CAAC;QAAE,MAAM,GAAG,UAAU,CAAC;IAC7C,IAAI,eAAe,GAAG,CAAC;QAAE,MAAM,GAAG,WAAW,CAAC;IAE9C,OAAO;QACL,MAAM;QACN,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC;QAC3D,cAAc,EAAE,SAAS,CAAC,cAAc;QACxC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM;QAC5B,YAAY,EAAE,eAAe;KAC9B,CAAC;AACJ,CAAC"}