@triedotdev/mcp 1.0.62 → 1.0.63

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 (56) hide show
  1. package/README.md +591 -52
  2. package/dist/agent-smith-W4HUCFGC.js +14 -0
  3. package/dist/{agent-smith-runner-ZU4R3I2Z.js → agent-smith-runner-QRVOEOBE.js} +13 -7
  4. package/dist/agent-smith-runner-QRVOEOBE.js.map +1 -0
  5. package/dist/chunk-4YSLDGBL.js +674 -0
  6. package/dist/chunk-4YSLDGBL.js.map +1 -0
  7. package/dist/chunk-7KHT2NKR.js +212 -0
  8. package/dist/chunk-7KHT2NKR.js.map +1 -0
  9. package/dist/{chunk-XSPS463E.js → chunk-ALA6733H.js} +492 -14
  10. package/dist/chunk-ALA6733H.js.map +1 -0
  11. package/dist/chunk-AQCAMIQQ.js +139 -0
  12. package/dist/chunk-AQCAMIQQ.js.map +1 -0
  13. package/dist/chunk-D3DMONAJ.js +904 -0
  14. package/dist/chunk-D3DMONAJ.js.map +1 -0
  15. package/dist/{chunk-KB5ZN6K2.js → chunk-GWSNINKX.js} +2 -2
  16. package/dist/{chunk-32WLOG6E.js → chunk-K6BQBKIR.js} +662 -633
  17. package/dist/chunk-K6BQBKIR.js.map +1 -0
  18. package/dist/{chunk-ASGSTVVF.js → chunk-KOFQ47YW.js} +10 -6
  19. package/dist/chunk-KOFQ47YW.js.map +1 -0
  20. package/dist/{chunk-XXNE6HBE.js → chunk-N2AZH3EQ.js} +7697 -4803
  21. package/dist/chunk-N2AZH3EQ.js.map +1 -0
  22. package/dist/chunk-PBOVCPKE.js +2566 -0
  23. package/dist/chunk-PBOVCPKE.js.map +1 -0
  24. package/dist/{chunk-NUT4G5AY.js → chunk-R7Z7OHTJ.js} +493 -650
  25. package/dist/chunk-R7Z7OHTJ.js.map +1 -0
  26. package/dist/chunk-TSHZQKCM.js +933 -0
  27. package/dist/chunk-TSHZQKCM.js.map +1 -0
  28. package/dist/{chunk-S4VGGLXF.js → chunk-X2PABPBH.js} +461 -892
  29. package/dist/chunk-X2PABPBH.js.map +1 -0
  30. package/dist/cli/create-agent.js +3 -2
  31. package/dist/cli/create-agent.js.map +1 -1
  32. package/dist/cli/main.js +1120 -70
  33. package/dist/cli/main.js.map +1 -1
  34. package/dist/cli/yolo-daemon.js +151 -41
  35. package/dist/cli/yolo-daemon.js.map +1 -1
  36. package/dist/goal-manager-KFBOAP4X.js +20 -0
  37. package/dist/goal-manager-KFBOAP4X.js.map +1 -0
  38. package/dist/guardian-agent-PULK546O.js +17 -0
  39. package/dist/guardian-agent-PULK546O.js.map +1 -0
  40. package/dist/index.js +173 -39
  41. package/dist/index.js.map +1 -1
  42. package/dist/issue-store-QRDF3X55.js +22 -0
  43. package/dist/issue-store-QRDF3X55.js.map +1 -0
  44. package/dist/workers/agent-worker.js +6 -3
  45. package/dist/workers/agent-worker.js.map +1 -1
  46. package/package.json +1 -1
  47. package/dist/agent-smith-57MKX5QC.js +0 -13
  48. package/dist/agent-smith-runner-ZU4R3I2Z.js.map +0 -1
  49. package/dist/chunk-32WLOG6E.js.map +0 -1
  50. package/dist/chunk-ASGSTVVF.js.map +0 -1
  51. package/dist/chunk-NUT4G5AY.js.map +0 -1
  52. package/dist/chunk-S4VGGLXF.js.map +0 -1
  53. package/dist/chunk-XSPS463E.js.map +0 -1
  54. package/dist/chunk-XXNE6HBE.js.map +0 -1
  55. /package/dist/{agent-smith-57MKX5QC.js.map → agent-smith-W4HUCFGC.js.map} +0 -0
  56. /package/dist/{chunk-KB5ZN6K2.js.map → chunk-GWSNINKX.js.map} +0 -0
@@ -0,0 +1,674 @@
1
+ import {
2
+ BackupManager,
3
+ atomicWriteJSON,
4
+ safeParseAndValidate
5
+ } from "./chunk-TSHZQKCM.js";
6
+
7
+ // src/guardian/guardian-state.ts
8
+ import { mkdir, readFile } from "fs/promises";
9
+ import { existsSync } from "fs";
10
+ import { join } from "path";
11
+ import { z } from "zod";
12
+ var GoalSchema = z.object({
13
+ id: z.string(),
14
+ description: z.string(),
15
+ type: z.enum(["streak", "reduction", "score", "custom"]),
16
+ metric: z.string(),
17
+ target: z.number(),
18
+ currentValue: z.number(),
19
+ startValue: z.number().optional(),
20
+ status: z.enum(["active", "achieved", "failed", "paused", "rejected"]),
21
+ autoGenerated: z.boolean(),
22
+ confidence: z.number().min(0).max(1).optional(),
23
+ // For auto-generated goals
24
+ createdAt: z.string(),
25
+ updatedAt: z.string(),
26
+ achievedAt: z.string().optional(),
27
+ deadline: z.string().optional(),
28
+ category: z.enum(["security", "quality", "performance", "coverage", "general"]).optional(),
29
+ evidence: z.array(z.string()).optional()
30
+ // Why this goal was generated
31
+ });
32
+ var HypothesisSchema = z.object({
33
+ id: z.string(),
34
+ statement: z.string(),
35
+ confidence: z.number().min(0).max(1),
36
+ // 0-1, adjusts based on validation
37
+ status: z.enum(["proposed", "testing", "validated", "invalidated", "retired"]),
38
+ evidence: z.array(z.object({
39
+ type: z.enum(["supporting", "contradicting"]),
40
+ description: z.string(),
41
+ timestamp: z.string(),
42
+ weight: z.number().min(0).max(1).optional()
43
+ })),
44
+ createdAt: z.string(),
45
+ updatedAt: z.string(),
46
+ validatedAt: z.string().optional(),
47
+ testCriteria: z.string().optional(),
48
+ category: z.enum(["timing", "pattern", "team", "code", "general"]).optional()
49
+ });
50
+ var RiskBudgetSchema = z.object({
51
+ daily: z.number(),
52
+ weekly: z.number(),
53
+ usedToday: z.number(),
54
+ usedThisWeek: z.number(),
55
+ lastResetDay: z.string(),
56
+ // ISO date (YYYY-MM-DD)
57
+ lastResetWeek: z.string()
58
+ // ISO week (YYYY-WNN)
59
+ });
60
+ var AgentMetricsSchema = z.object({
61
+ predictiveAccuracy: z.number().min(0).max(1),
62
+ falsePositiveRate: z.number().min(0).max(1),
63
+ userSatisfaction: z.number().min(0).max(1),
64
+ hypothesisAccuracy: z.number().min(0).max(1),
65
+ totalPredictions: z.number(),
66
+ correctPredictions: z.number(),
67
+ totalInsights: z.number(),
68
+ helpfulInsights: z.number(),
69
+ dismissedInsights: z.number(),
70
+ actedOnInsights: z.number()
71
+ });
72
+ var TimingContextSchema = z.object({
73
+ quietHoursStart: z.number().min(0).max(23),
74
+ // Hour of day (0-23)
75
+ quietHoursEnd: z.number().min(0).max(23),
76
+ quietHoursEnabled: z.boolean(),
77
+ workDays: z.array(z.number().min(0).max(6)),
78
+ // 0 = Sunday
79
+ lastActiveTimestamp: z.number(),
80
+ timezone: z.string().optional(),
81
+ crunchMode: z.boolean(),
82
+ // During crunch, defer low-priority items
83
+ crunchModeUntil: z.string().optional()
84
+ });
85
+ var GuardianStateDataSchema = z.object({
86
+ version: z.literal(1),
87
+ goals: z.array(GoalSchema),
88
+ hypotheses: z.array(HypothesisSchema),
89
+ riskBudget: RiskBudgetSchema,
90
+ metrics: AgentMetricsSchema,
91
+ timing: TimingContextSchema,
92
+ scanFrequencyMs: z.number(),
93
+ // Current scan frequency
94
+ lastScanTimestamp: z.number().optional(),
95
+ lastUpdated: z.string()
96
+ });
97
+ var GuardianState = class {
98
+ projectPath;
99
+ data;
100
+ loaded = false;
101
+ dirty = false;
102
+ constructor(projectPath) {
103
+ this.projectPath = projectPath;
104
+ this.data = this.createDefaultState();
105
+ }
106
+ /**
107
+ * Get the storage file path
108
+ */
109
+ getStorePath() {
110
+ return join(this.projectPath, ".trie", "memory", "guardian-state.json");
111
+ }
112
+ /**
113
+ * Create default state
114
+ */
115
+ createDefaultState() {
116
+ const now = /* @__PURE__ */ new Date();
117
+ const today = now.toISOString().split("T")[0];
118
+ const week = this.getISOWeek(now);
119
+ return {
120
+ version: 1,
121
+ goals: [],
122
+ hypotheses: [],
123
+ riskBudget: {
124
+ daily: 10,
125
+ weekly: 50,
126
+ usedToday: 0,
127
+ usedThisWeek: 0,
128
+ lastResetDay: today,
129
+ lastResetWeek: week
130
+ },
131
+ metrics: {
132
+ predictiveAccuracy: 0.5,
133
+ // Start neutral
134
+ falsePositiveRate: 0.5,
135
+ userSatisfaction: 0.5,
136
+ hypothesisAccuracy: 0.5,
137
+ totalPredictions: 0,
138
+ correctPredictions: 0,
139
+ totalInsights: 0,
140
+ helpfulInsights: 0,
141
+ dismissedInsights: 0,
142
+ actedOnInsights: 0
143
+ },
144
+ timing: {
145
+ quietHoursStart: 21,
146
+ // 9 PM
147
+ quietHoursEnd: 8,
148
+ // 8 AM
149
+ quietHoursEnabled: true,
150
+ workDays: [1, 2, 3, 4, 5],
151
+ // Mon-Fri
152
+ lastActiveTimestamp: Date.now(),
153
+ crunchMode: false
154
+ },
155
+ scanFrequencyMs: 3e5,
156
+ // 5 minutes default
157
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
158
+ };
159
+ }
160
+ /**
161
+ * Get ISO week string (YYYY-WNN)
162
+ */
163
+ getISOWeek(date) {
164
+ const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
165
+ const dayNum = d.getUTCDay() || 7;
166
+ d.setUTCDate(d.getUTCDate() + 4 - dayNum);
167
+ const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
168
+ const weekNo = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
169
+ return `${d.getUTCFullYear()}-W${weekNo.toString().padStart(2, "0")}`;
170
+ }
171
+ /**
172
+ * Load state from disk
173
+ */
174
+ async load() {
175
+ if (this.loaded) {
176
+ return this.data;
177
+ }
178
+ const storePath = this.getStorePath();
179
+ try {
180
+ if (existsSync(storePath)) {
181
+ const content = await readFile(storePath, "utf-8");
182
+ const result = safeParseAndValidate(content, GuardianStateDataSchema);
183
+ if (result.success) {
184
+ this.data = result.data;
185
+ this.loaded = true;
186
+ await this.checkAndResetBudgets();
187
+ return this.data;
188
+ }
189
+ console.error(` \u26A0\uFE0F Guardian state corrupted: ${result.error}`);
190
+ const backupManager = new BackupManager(storePath);
191
+ if (await backupManager.recoverFromBackup()) {
192
+ console.error(" \u2705 Recovered from backup");
193
+ const recovered = await readFile(storePath, "utf-8");
194
+ const recoveredResult = safeParseAndValidate(recovered, GuardianStateDataSchema);
195
+ if (recoveredResult.success) {
196
+ this.data = recoveredResult.data;
197
+ this.loaded = true;
198
+ return this.data;
199
+ }
200
+ }
201
+ console.error(" \u274C No valid backup found, starting fresh");
202
+ }
203
+ } catch (error) {
204
+ console.error(` \u26A0\uFE0F Could not load guardian state: ${error}`);
205
+ }
206
+ this.data = this.createDefaultState();
207
+ this.loaded = true;
208
+ return this.data;
209
+ }
210
+ /**
211
+ * Save state to disk
212
+ */
213
+ async save() {
214
+ if (!this.dirty && this.loaded) {
215
+ return;
216
+ }
217
+ const storePath = this.getStorePath();
218
+ const memoryDir = join(this.projectPath, ".trie", "memory");
219
+ await mkdir(memoryDir, { recursive: true });
220
+ const backupManager = new BackupManager(storePath);
221
+ await backupManager.createBackup();
222
+ this.data.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
223
+ await atomicWriteJSON(storePath, this.data);
224
+ this.dirty = false;
225
+ }
226
+ /**
227
+ * Check and reset daily/weekly budgets if needed
228
+ */
229
+ async checkAndResetBudgets() {
230
+ const now = /* @__PURE__ */ new Date();
231
+ const today = now.toISOString().split("T")[0];
232
+ const week = this.getISOWeek(now);
233
+ let needsSave = false;
234
+ if (this.data.riskBudget.lastResetDay !== today) {
235
+ this.data.riskBudget.usedToday = 0;
236
+ this.data.riskBudget.lastResetDay = today;
237
+ needsSave = true;
238
+ }
239
+ if (this.data.riskBudget.lastResetWeek !== week) {
240
+ this.data.riskBudget.usedThisWeek = 0;
241
+ this.data.riskBudget.lastResetWeek = week;
242
+ needsSave = true;
243
+ }
244
+ if (needsSave) {
245
+ this.dirty = true;
246
+ await this.save();
247
+ }
248
+ }
249
+ // ========================================================================
250
+ // Goals
251
+ // ========================================================================
252
+ /**
253
+ * Add a goal
254
+ */
255
+ async addGoal(goal) {
256
+ await this.load();
257
+ if (this.data.goals.some((g) => g.id === goal.id)) {
258
+ return false;
259
+ }
260
+ this.data.goals.push(goal);
261
+ this.dirty = true;
262
+ await this.save();
263
+ return true;
264
+ }
265
+ /**
266
+ * Update a goal
267
+ */
268
+ async updateGoal(goalId, updates) {
269
+ await this.load();
270
+ const goal = this.data.goals.find((g) => g.id === goalId);
271
+ if (!goal) {
272
+ return false;
273
+ }
274
+ Object.assign(goal, updates, { updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
275
+ this.dirty = true;
276
+ await this.save();
277
+ return true;
278
+ }
279
+ /**
280
+ * Get active goals
281
+ */
282
+ getActiveGoals() {
283
+ return this.data.goals.filter((g) => g.status === "active");
284
+ }
285
+ /**
286
+ * Get all goals
287
+ */
288
+ getAllGoals() {
289
+ return [...this.data.goals];
290
+ }
291
+ /**
292
+ * Get goal by ID
293
+ */
294
+ getGoal(goalId) {
295
+ return this.data.goals.find((g) => g.id === goalId);
296
+ }
297
+ /**
298
+ * Remove a goal
299
+ */
300
+ async removeGoal(goalId) {
301
+ await this.load();
302
+ const index = this.data.goals.findIndex((g) => g.id === goalId);
303
+ if (index === -1) {
304
+ return false;
305
+ }
306
+ this.data.goals.splice(index, 1);
307
+ this.dirty = true;
308
+ await this.save();
309
+ return true;
310
+ }
311
+ /**
312
+ * Get auto-generated goals
313
+ */
314
+ getAutoGeneratedGoals() {
315
+ return this.data.goals.filter((g) => g.autoGenerated);
316
+ }
317
+ /**
318
+ * Accept or reject an auto-generated goal
319
+ */
320
+ async respondToGoal(goalId, accept) {
321
+ return this.updateGoal(goalId, {
322
+ status: accept ? "active" : "rejected"
323
+ });
324
+ }
325
+ // ========================================================================
326
+ // Hypotheses
327
+ // ========================================================================
328
+ /**
329
+ * Add a hypothesis
330
+ */
331
+ async addHypothesis(hypothesis) {
332
+ await this.load();
333
+ if (this.data.hypotheses.some((h) => h.id === hypothesis.id)) {
334
+ return false;
335
+ }
336
+ this.data.hypotheses.push(hypothesis);
337
+ this.dirty = true;
338
+ await this.save();
339
+ return true;
340
+ }
341
+ /**
342
+ * Update a hypothesis
343
+ */
344
+ async updateHypothesis(hypothesisId, updates) {
345
+ await this.load();
346
+ const hypothesis = this.data.hypotheses.find((h) => h.id === hypothesisId);
347
+ if (!hypothesis) {
348
+ return false;
349
+ }
350
+ Object.assign(hypothesis, updates, { updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
351
+ this.dirty = true;
352
+ await this.save();
353
+ return true;
354
+ }
355
+ /**
356
+ * Add evidence to a hypothesis
357
+ */
358
+ async addEvidence(hypothesisId, evidence) {
359
+ await this.load();
360
+ const hypothesis = this.data.hypotheses.find((h) => h.id === hypothesisId);
361
+ if (!hypothesis) {
362
+ return false;
363
+ }
364
+ hypothesis.evidence.push({
365
+ ...evidence,
366
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
367
+ });
368
+ const supportingCount = hypothesis.evidence.filter((e) => e.type === "supporting").length;
369
+ const contradictingCount = hypothesis.evidence.filter((e) => e.type === "contradicting").length;
370
+ const total = supportingCount + contradictingCount;
371
+ if (total > 0) {
372
+ hypothesis.confidence = supportingCount / total;
373
+ if (hypothesis.confidence > 0.8 && supportingCount >= 3) {
374
+ hypothesis.status = "validated";
375
+ hypothesis.validatedAt = (/* @__PURE__ */ new Date()).toISOString();
376
+ } else if (hypothesis.confidence < 0.2 && contradictingCount >= 3) {
377
+ hypothesis.status = "invalidated";
378
+ }
379
+ }
380
+ hypothesis.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
381
+ this.dirty = true;
382
+ await this.save();
383
+ return true;
384
+ }
385
+ /**
386
+ * Get active hypotheses
387
+ */
388
+ getActiveHypotheses() {
389
+ return this.data.hypotheses.filter(
390
+ (h) => h.status === "proposed" || h.status === "testing"
391
+ );
392
+ }
393
+ /**
394
+ * Get validated hypotheses
395
+ */
396
+ getValidatedHypotheses() {
397
+ return this.data.hypotheses.filter((h) => h.status === "validated");
398
+ }
399
+ /**
400
+ * Get all hypotheses
401
+ */
402
+ getAllHypotheses() {
403
+ return [...this.data.hypotheses];
404
+ }
405
+ /**
406
+ * Get hypothesis by ID
407
+ */
408
+ getHypothesis(hypothesisId) {
409
+ return this.data.hypotheses.find((h) => h.id === hypothesisId);
410
+ }
411
+ // ========================================================================
412
+ // Risk Budget
413
+ // ========================================================================
414
+ /**
415
+ * Get current risk budget
416
+ */
417
+ getRiskBudget() {
418
+ return { ...this.data.riskBudget };
419
+ }
420
+ /**
421
+ * Use risk budget
422
+ */
423
+ async useRiskBudget(amount) {
424
+ await this.load();
425
+ await this.checkAndResetBudgets();
426
+ if (this.data.riskBudget.usedToday + amount > this.data.riskBudget.daily) {
427
+ return false;
428
+ }
429
+ if (this.data.riskBudget.usedThisWeek + amount > this.data.riskBudget.weekly) {
430
+ return false;
431
+ }
432
+ this.data.riskBudget.usedToday += amount;
433
+ this.data.riskBudget.usedThisWeek += amount;
434
+ this.dirty = true;
435
+ await this.save();
436
+ return true;
437
+ }
438
+ /**
439
+ * Check if risk budget is available
440
+ */
441
+ hasRiskBudget(amount = 1) {
442
+ return this.data.riskBudget.usedToday + amount <= this.data.riskBudget.daily && this.data.riskBudget.usedThisWeek + amount <= this.data.riskBudget.weekly;
443
+ }
444
+ /**
445
+ * Update risk budget limits
446
+ */
447
+ async setRiskBudget(daily, weekly) {
448
+ await this.load();
449
+ this.data.riskBudget.daily = daily;
450
+ this.data.riskBudget.weekly = weekly;
451
+ this.dirty = true;
452
+ await this.save();
453
+ }
454
+ // ========================================================================
455
+ // Metrics
456
+ // ========================================================================
457
+ /**
458
+ * Get agent metrics
459
+ */
460
+ getMetrics() {
461
+ return { ...this.data.metrics };
462
+ }
463
+ /**
464
+ * Record a prediction outcome
465
+ */
466
+ async recordPrediction(correct) {
467
+ await this.load();
468
+ this.data.metrics.totalPredictions++;
469
+ if (correct) {
470
+ this.data.metrics.correctPredictions++;
471
+ }
472
+ this.data.metrics.predictiveAccuracy = this.data.metrics.correctPredictions / this.data.metrics.totalPredictions;
473
+ this.dirty = true;
474
+ await this.save();
475
+ }
476
+ /**
477
+ * Record user feedback on an insight
478
+ */
479
+ async recordInsightFeedback(feedback) {
480
+ await this.load();
481
+ this.data.metrics.totalInsights++;
482
+ switch (feedback) {
483
+ case "helpful":
484
+ this.data.metrics.helpfulInsights++;
485
+ break;
486
+ case "dismissed":
487
+ this.data.metrics.dismissedInsights++;
488
+ break;
489
+ case "acted":
490
+ this.data.metrics.actedOnInsights++;
491
+ this.data.metrics.helpfulInsights++;
492
+ break;
493
+ }
494
+ if (this.data.metrics.totalInsights > 0) {
495
+ this.data.metrics.userSatisfaction = this.data.metrics.helpfulInsights / this.data.metrics.totalInsights;
496
+ this.data.metrics.falsePositiveRate = this.data.metrics.dismissedInsights / this.data.metrics.totalInsights;
497
+ }
498
+ this.dirty = true;
499
+ await this.save();
500
+ }
501
+ /**
502
+ * Update hypothesis accuracy
503
+ */
504
+ async updateHypothesisAccuracy() {
505
+ await this.load();
506
+ const validated = this.data.hypotheses.filter((h) => h.status === "validated").length;
507
+ const invalidated = this.data.hypotheses.filter((h) => h.status === "invalidated").length;
508
+ const total = validated + invalidated;
509
+ if (total > 0) {
510
+ this.data.metrics.hypothesisAccuracy = validated / total;
511
+ this.dirty = true;
512
+ await this.save();
513
+ }
514
+ }
515
+ // ========================================================================
516
+ // Timing Context
517
+ // ========================================================================
518
+ /**
519
+ * Get timing context
520
+ */
521
+ getTimingContext() {
522
+ return { ...this.data.timing };
523
+ }
524
+ /**
525
+ * Check if currently in quiet hours
526
+ */
527
+ isQuietHours() {
528
+ if (!this.data.timing.quietHoursEnabled) {
529
+ return false;
530
+ }
531
+ const now = /* @__PURE__ */ new Date();
532
+ const hour = now.getHours();
533
+ const start = this.data.timing.quietHoursStart;
534
+ const end = this.data.timing.quietHoursEnd;
535
+ if (start > end) {
536
+ return hour >= start || hour < end;
537
+ }
538
+ return hour >= start && hour < end;
539
+ }
540
+ /**
541
+ * Check if today is a work day
542
+ */
543
+ isWorkDay() {
544
+ const dayOfWeek = (/* @__PURE__ */ new Date()).getDay();
545
+ return this.data.timing.workDays.includes(dayOfWeek);
546
+ }
547
+ /**
548
+ * Check if in crunch mode
549
+ */
550
+ isInCrunchMode() {
551
+ if (!this.data.timing.crunchMode) {
552
+ return false;
553
+ }
554
+ if (this.data.timing.crunchModeUntil) {
555
+ const until = new Date(this.data.timing.crunchModeUntil);
556
+ if (Date.now() > until.getTime()) {
557
+ this.data.timing.crunchMode = false;
558
+ this.data.timing.crunchModeUntil = void 0;
559
+ this.dirty = true;
560
+ return false;
561
+ }
562
+ }
563
+ return true;
564
+ }
565
+ /**
566
+ * Enable crunch mode
567
+ */
568
+ async setCrunchMode(enabled, until) {
569
+ await this.load();
570
+ this.data.timing.crunchMode = enabled;
571
+ this.data.timing.crunchModeUntil = until?.toISOString();
572
+ this.dirty = true;
573
+ await this.save();
574
+ }
575
+ /**
576
+ * Update quiet hours settings
577
+ */
578
+ async setQuietHours(start, end, enabled = true) {
579
+ await this.load();
580
+ this.data.timing.quietHoursStart = start;
581
+ this.data.timing.quietHoursEnd = end;
582
+ this.data.timing.quietHoursEnabled = enabled;
583
+ this.dirty = true;
584
+ await this.save();
585
+ }
586
+ /**
587
+ * Update work days
588
+ */
589
+ async setWorkDays(days) {
590
+ await this.load();
591
+ this.data.timing.workDays = days;
592
+ this.dirty = true;
593
+ await this.save();
594
+ }
595
+ /**
596
+ * Update last active timestamp
597
+ */
598
+ async touchActive() {
599
+ await this.load();
600
+ this.data.timing.lastActiveTimestamp = Date.now();
601
+ this.dirty = true;
602
+ await this.save();
603
+ }
604
+ // ========================================================================
605
+ // Scan Frequency
606
+ // ========================================================================
607
+ /**
608
+ * Get current scan frequency in milliseconds
609
+ */
610
+ getScanFrequencyMs() {
611
+ return this.data.scanFrequencyMs;
612
+ }
613
+ /**
614
+ * Set scan frequency
615
+ */
616
+ async setScanFrequency(ms) {
617
+ await this.load();
618
+ this.data.scanFrequencyMs = Math.max(1e4, ms);
619
+ this.dirty = true;
620
+ await this.save();
621
+ }
622
+ /**
623
+ * Record a scan timestamp
624
+ */
625
+ async recordScan() {
626
+ await this.load();
627
+ this.data.lastScanTimestamp = Date.now();
628
+ this.dirty = true;
629
+ await this.save();
630
+ }
631
+ /**
632
+ * Get last scan timestamp
633
+ */
634
+ getLastScanTimestamp() {
635
+ return this.data.lastScanTimestamp;
636
+ }
637
+ // ========================================================================
638
+ // Utility
639
+ // ========================================================================
640
+ /**
641
+ * Get full state data
642
+ */
643
+ getData() {
644
+ return { ...this.data };
645
+ }
646
+ /**
647
+ * Force reload from disk
648
+ */
649
+ async reload() {
650
+ this.loaded = false;
651
+ this.dirty = false;
652
+ return this.load();
653
+ }
654
+ /**
655
+ * Check if loaded
656
+ */
657
+ isLoaded() {
658
+ return this.loaded;
659
+ }
660
+ };
661
+ var guardianStates = /* @__PURE__ */ new Map();
662
+ function getGuardianState(projectPath) {
663
+ let state = guardianStates.get(projectPath);
664
+ if (!state) {
665
+ state = new GuardianState(projectPath);
666
+ guardianStates.set(projectPath, state);
667
+ }
668
+ return state;
669
+ }
670
+
671
+ export {
672
+ getGuardianState
673
+ };
674
+ //# sourceMappingURL=chunk-4YSLDGBL.js.map