@triedotdev/mcp 1.0.62 → 1.0.64

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 +329 -74
  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 @@
1
+ {"version":3,"sources":["../src/guardian/guardian-state.ts"],"sourcesContent":["/**\n * Guardian State - Persistent state management for Guardian Agent\n * \n * Phase 1 of Guardian Agency Plan: State persistence\n * \n * Persists to: .trie/memory/guardian-state.json\n * \n * Features:\n * - Goal storage (manual and auto-generated)\n * - Risk budget tracking\n * - Hypothesis storage\n * - Agent metrics\n * - Contextual timing state (quiet hours, etc.)\n * - Atomic writes with backup rotation\n */\n\nimport { mkdir, readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { z } from 'zod';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { safeParseAndValidate } from '../memory/validation.js';\n\n// ============================================================================\n// Schemas\n// ============================================================================\n\n/**\n * Schema for a Goal\n */\nexport const GoalSchema = z.object({\n id: z.string(),\n description: z.string(),\n type: z.enum(['streak', 'reduction', 'score', 'custom']),\n metric: z.string(),\n target: z.number(),\n currentValue: z.number(),\n startValue: z.number().optional(),\n status: z.enum(['active', 'achieved', 'failed', 'paused', 'rejected']),\n autoGenerated: z.boolean(),\n confidence: z.number().min(0).max(1).optional(), // For auto-generated goals\n createdAt: z.string(),\n updatedAt: z.string(),\n achievedAt: z.string().optional(),\n deadline: z.string().optional(),\n category: z.enum(['security', 'quality', 'performance', 'coverage', 'general']).optional(),\n evidence: z.array(z.string()).optional(), // Why this goal was generated\n});\n\nexport type Goal = z.infer<typeof GoalSchema>;\n\n/**\n * Schema for a Hypothesis\n */\nexport const HypothesisSchema = z.object({\n id: z.string(),\n statement: z.string(),\n confidence: z.number().min(0).max(1), // 0-1, adjusts based on validation\n status: z.enum(['proposed', 'testing', 'validated', 'invalidated', 'retired']),\n evidence: z.array(z.object({\n type: z.enum(['supporting', 'contradicting']),\n description: z.string(),\n timestamp: z.string(),\n weight: z.number().min(0).max(1).optional(),\n })),\n createdAt: z.string(),\n updatedAt: z.string(),\n validatedAt: z.string().optional(),\n testCriteria: z.string().optional(),\n category: z.enum(['timing', 'pattern', 'team', 'code', 'general']).optional(),\n});\n\nexport type Hypothesis = z.infer<typeof HypothesisSchema>;\n\n/**\n * Schema for Risk Budget\n */\nexport const RiskBudgetSchema = z.object({\n daily: z.number(),\n weekly: z.number(),\n usedToday: z.number(),\n usedThisWeek: z.number(),\n lastResetDay: z.string(), // ISO date (YYYY-MM-DD)\n lastResetWeek: z.string(), // ISO week (YYYY-WNN)\n});\n\nexport type RiskBudget = z.infer<typeof RiskBudgetSchema>;\n\n/**\n * Schema for Agent Metrics (Meta-Learning)\n */\nexport const AgentMetricsSchema = z.object({\n predictiveAccuracy: z.number().min(0).max(1),\n falsePositiveRate: z.number().min(0).max(1),\n userSatisfaction: z.number().min(0).max(1),\n hypothesisAccuracy: z.number().min(0).max(1),\n totalPredictions: z.number(),\n correctPredictions: z.number(),\n totalInsights: z.number(),\n helpfulInsights: z.number(),\n dismissedInsights: z.number(),\n actedOnInsights: z.number(),\n});\n\nexport type AgentMetrics = z.infer<typeof AgentMetricsSchema>;\n\n/**\n * Schema for Timing Context\n */\nexport const TimingContextSchema = z.object({\n quietHoursStart: z.number().min(0).max(23), // Hour of day (0-23)\n quietHoursEnd: z.number().min(0).max(23),\n quietHoursEnabled: z.boolean(),\n workDays: z.array(z.number().min(0).max(6)), // 0 = Sunday\n lastActiveTimestamp: z.number(),\n timezone: z.string().optional(),\n crunchMode: z.boolean(), // During crunch, defer low-priority items\n crunchModeUntil: z.string().optional(),\n});\n\nexport type TimingContext = z.infer<typeof TimingContextSchema>;\n\n/**\n * Schema for the entire Guardian state file\n */\nexport const GuardianStateDataSchema = z.object({\n version: z.literal(1),\n goals: z.array(GoalSchema),\n hypotheses: z.array(HypothesisSchema),\n riskBudget: RiskBudgetSchema,\n metrics: AgentMetricsSchema,\n timing: TimingContextSchema,\n scanFrequencyMs: z.number(), // Current scan frequency\n lastScanTimestamp: z.number().optional(),\n lastUpdated: z.string(),\n});\n\nexport type GuardianStateData = z.infer<typeof GuardianStateDataSchema>;\n\n// ============================================================================\n// GuardianState Class\n// ============================================================================\n\n/**\n * Persistent state manager for Guardian Agent\n * \n * Manages goals, hypotheses, risk budget, metrics, and timing context.\n */\nexport class GuardianState {\n private projectPath: string;\n private data: GuardianStateData;\n private loaded: boolean = false;\n private dirty: boolean = false;\n \n constructor(projectPath: string) {\n this.projectPath = projectPath;\n this.data = this.createDefaultState();\n }\n \n /**\n * Get the storage file path\n */\n private getStorePath(): string {\n return join(this.projectPath, '.trie', 'memory', 'guardian-state.json');\n }\n \n /**\n * Create default state\n */\n private createDefaultState(): GuardianStateData {\n const now = new Date();\n const today = now.toISOString().split('T')[0]!;\n const week = this.getISOWeek(now);\n \n return {\n version: 1,\n goals: [],\n hypotheses: [],\n riskBudget: {\n daily: 10,\n weekly: 50,\n usedToday: 0,\n usedThisWeek: 0,\n lastResetDay: today,\n lastResetWeek: week,\n },\n metrics: {\n predictiveAccuracy: 0.5, // Start neutral\n falsePositiveRate: 0.5,\n userSatisfaction: 0.5,\n hypothesisAccuracy: 0.5,\n totalPredictions: 0,\n correctPredictions: 0,\n totalInsights: 0,\n helpfulInsights: 0,\n dismissedInsights: 0,\n actedOnInsights: 0,\n },\n timing: {\n quietHoursStart: 21, // 9 PM\n quietHoursEnd: 8, // 8 AM\n quietHoursEnabled: true,\n workDays: [1, 2, 3, 4, 5], // Mon-Fri\n lastActiveTimestamp: Date.now(),\n crunchMode: false,\n },\n scanFrequencyMs: 300000, // 5 minutes default\n lastUpdated: new Date().toISOString(),\n };\n }\n \n /**\n * Get ISO week string (YYYY-WNN)\n */\n private getISOWeek(date: Date): string {\n const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));\n const dayNum = d.getUTCDay() || 7;\n d.setUTCDate(d.getUTCDate() + 4 - dayNum);\n const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\n const weekNo = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);\n return `${d.getUTCFullYear()}-W${weekNo.toString().padStart(2, '0')}`;\n }\n \n /**\n * Load state from disk\n */\n async load(): Promise<GuardianStateData> {\n if (this.loaded) {\n return this.data;\n }\n \n const storePath = this.getStorePath();\n \n try {\n if (existsSync(storePath)) {\n const content = await readFile(storePath, 'utf-8');\n const result = safeParseAndValidate(content, GuardianStateDataSchema);\n \n if (result.success) {\n this.data = result.data;\n this.loaded = true;\n \n // Check for day/week reset\n await this.checkAndResetBudgets();\n \n return this.data;\n }\n \n // Validation failed - attempt recovery\n console.error(` ⚠️ Guardian state corrupted: ${result.error}`);\n const backupManager = new BackupManager(storePath);\n \n if (await backupManager.recoverFromBackup()) {\n console.error(' ✅ Recovered from backup');\n const recovered = await readFile(storePath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, GuardianStateDataSchema);\n if (recoveredResult.success) {\n this.data = recoveredResult.data;\n this.loaded = true;\n return this.data;\n }\n }\n \n console.error(' ❌ No valid backup found, starting fresh');\n }\n } catch (error) {\n console.error(` ⚠️ Could not load guardian state: ${error}`);\n }\n \n this.data = this.createDefaultState();\n this.loaded = true;\n return this.data;\n }\n \n /**\n * Save state to disk\n */\n async save(): Promise<void> {\n if (!this.dirty && this.loaded) {\n return;\n }\n \n const storePath = this.getStorePath();\n const memoryDir = join(this.projectPath, '.trie', 'memory');\n \n await mkdir(memoryDir, { recursive: true });\n \n const backupManager = new BackupManager(storePath);\n await backupManager.createBackup();\n \n this.data.lastUpdated = new Date().toISOString();\n \n await atomicWriteJSON(storePath, this.data);\n \n this.dirty = false;\n }\n \n /**\n * Check and reset daily/weekly budgets if needed\n */\n private async checkAndResetBudgets(): Promise<void> {\n const now = new Date();\n const today = now.toISOString().split('T')[0]!;\n const week = this.getISOWeek(now);\n \n let needsSave = false;\n \n if (this.data.riskBudget.lastResetDay !== today) {\n this.data.riskBudget.usedToday = 0;\n this.data.riskBudget.lastResetDay = today;\n needsSave = true;\n }\n \n if (this.data.riskBudget.lastResetWeek !== week) {\n this.data.riskBudget.usedThisWeek = 0;\n this.data.riskBudget.lastResetWeek = week;\n needsSave = true;\n }\n \n if (needsSave) {\n this.dirty = true;\n await this.save();\n }\n }\n \n // ========================================================================\n // Goals\n // ========================================================================\n \n /**\n * Add a goal\n */\n async addGoal(goal: Goal): Promise<boolean> {\n await this.load();\n \n if (this.data.goals.some(g => g.id === goal.id)) {\n return false;\n }\n \n this.data.goals.push(goal);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Update a goal\n */\n async updateGoal(goalId: string, updates: Partial<Goal>): Promise<boolean> {\n await this.load();\n \n const goal = this.data.goals.find(g => g.id === goalId);\n if (!goal) {\n return false;\n }\n \n Object.assign(goal, updates, { updatedAt: new Date().toISOString() });\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Get active goals\n */\n getActiveGoals(): Goal[] {\n return this.data.goals.filter(g => g.status === 'active');\n }\n \n /**\n * Get all goals\n */\n getAllGoals(): Goal[] {\n return [...this.data.goals];\n }\n \n /**\n * Get goal by ID\n */\n getGoal(goalId: string): Goal | undefined {\n return this.data.goals.find(g => g.id === goalId);\n }\n \n /**\n * Remove a goal\n */\n async removeGoal(goalId: string): Promise<boolean> {\n await this.load();\n \n const index = this.data.goals.findIndex(g => g.id === goalId);\n if (index === -1) {\n return false;\n }\n \n this.data.goals.splice(index, 1);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Get auto-generated goals\n */\n getAutoGeneratedGoals(): Goal[] {\n return this.data.goals.filter(g => g.autoGenerated);\n }\n \n /**\n * Accept or reject an auto-generated goal\n */\n async respondToGoal(goalId: string, accept: boolean): Promise<boolean> {\n return this.updateGoal(goalId, {\n status: accept ? 'active' : 'rejected',\n });\n }\n \n // ========================================================================\n // Hypotheses\n // ========================================================================\n \n /**\n * Add a hypothesis\n */\n async addHypothesis(hypothesis: Hypothesis): Promise<boolean> {\n await this.load();\n \n if (this.data.hypotheses.some(h => h.id === hypothesis.id)) {\n return false;\n }\n \n this.data.hypotheses.push(hypothesis);\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Update a hypothesis\n */\n async updateHypothesis(hypothesisId: string, updates: Partial<Hypothesis>): Promise<boolean> {\n await this.load();\n \n const hypothesis = this.data.hypotheses.find(h => h.id === hypothesisId);\n if (!hypothesis) {\n return false;\n }\n \n Object.assign(hypothesis, updates, { updatedAt: new Date().toISOString() });\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Add evidence to a hypothesis\n */\n async addEvidence(\n hypothesisId: string,\n evidence: { type: 'supporting' | 'contradicting'; description: string; weight?: number }\n ): Promise<boolean> {\n await this.load();\n \n const hypothesis = this.data.hypotheses.find(h => h.id === hypothesisId);\n if (!hypothesis) {\n return false;\n }\n \n hypothesis.evidence.push({\n ...evidence,\n timestamp: new Date().toISOString(),\n });\n \n // Adjust confidence based on evidence\n const supportingCount = hypothesis.evidence.filter(e => e.type === 'supporting').length;\n const contradictingCount = hypothesis.evidence.filter(e => e.type === 'contradicting').length;\n const total = supportingCount + contradictingCount;\n \n if (total > 0) {\n hypothesis.confidence = supportingCount / total;\n \n // Update status based on confidence\n if (hypothesis.confidence > 0.8 && supportingCount >= 3) {\n hypothesis.status = 'validated';\n hypothesis.validatedAt = new Date().toISOString();\n } else if (hypothesis.confidence < 0.2 && contradictingCount >= 3) {\n hypothesis.status = 'invalidated';\n }\n }\n \n hypothesis.updatedAt = new Date().toISOString();\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Get active hypotheses\n */\n getActiveHypotheses(): Hypothesis[] {\n return this.data.hypotheses.filter(h => \n h.status === 'proposed' || h.status === 'testing'\n );\n }\n \n /**\n * Get validated hypotheses\n */\n getValidatedHypotheses(): Hypothesis[] {\n return this.data.hypotheses.filter(h => h.status === 'validated');\n }\n \n /**\n * Get all hypotheses\n */\n getAllHypotheses(): Hypothesis[] {\n return [...this.data.hypotheses];\n }\n \n /**\n * Get hypothesis by ID\n */\n getHypothesis(hypothesisId: string): Hypothesis | undefined {\n return this.data.hypotheses.find(h => h.id === hypothesisId);\n }\n \n // ========================================================================\n // Risk Budget\n // ========================================================================\n \n /**\n * Get current risk budget\n */\n getRiskBudget(): RiskBudget {\n return { ...this.data.riskBudget };\n }\n \n /**\n * Use risk budget\n */\n async useRiskBudget(amount: number): Promise<boolean> {\n await this.load();\n await this.checkAndResetBudgets();\n \n if (this.data.riskBudget.usedToday + amount > this.data.riskBudget.daily) {\n return false; // Would exceed daily budget\n }\n \n if (this.data.riskBudget.usedThisWeek + amount > this.data.riskBudget.weekly) {\n return false; // Would exceed weekly budget\n }\n \n this.data.riskBudget.usedToday += amount;\n this.data.riskBudget.usedThisWeek += amount;\n this.dirty = true;\n await this.save();\n \n return true;\n }\n \n /**\n * Check if risk budget is available\n */\n hasRiskBudget(amount: number = 1): boolean {\n return (\n this.data.riskBudget.usedToday + amount <= this.data.riskBudget.daily &&\n this.data.riskBudget.usedThisWeek + amount <= this.data.riskBudget.weekly\n );\n }\n \n /**\n * Update risk budget limits\n */\n async setRiskBudget(daily: number, weekly: number): Promise<void> {\n await this.load();\n this.data.riskBudget.daily = daily;\n this.data.riskBudget.weekly = weekly;\n this.dirty = true;\n await this.save();\n }\n \n // ========================================================================\n // Metrics\n // ========================================================================\n \n /**\n * Get agent metrics\n */\n getMetrics(): AgentMetrics {\n return { ...this.data.metrics };\n }\n \n /**\n * Record a prediction outcome\n */\n async recordPrediction(correct: boolean): Promise<void> {\n await this.load();\n \n this.data.metrics.totalPredictions++;\n if (correct) {\n this.data.metrics.correctPredictions++;\n }\n \n // Recalculate accuracy\n this.data.metrics.predictiveAccuracy = \n this.data.metrics.correctPredictions / this.data.metrics.totalPredictions;\n \n this.dirty = true;\n await this.save();\n }\n \n /**\n * Record user feedback on an insight\n */\n async recordInsightFeedback(feedback: 'helpful' | 'dismissed' | 'acted'): Promise<void> {\n await this.load();\n \n this.data.metrics.totalInsights++;\n \n switch (feedback) {\n case 'helpful':\n this.data.metrics.helpfulInsights++;\n break;\n case 'dismissed':\n this.data.metrics.dismissedInsights++;\n break;\n case 'acted':\n this.data.metrics.actedOnInsights++;\n this.data.metrics.helpfulInsights++; // Acted on is also helpful\n break;\n }\n \n // Recalculate satisfaction\n if (this.data.metrics.totalInsights > 0) {\n this.data.metrics.userSatisfaction = \n this.data.metrics.helpfulInsights / this.data.metrics.totalInsights;\n this.data.metrics.falsePositiveRate = \n this.data.metrics.dismissedInsights / this.data.metrics.totalInsights;\n }\n \n this.dirty = true;\n await this.save();\n }\n \n /**\n * Update hypothesis accuracy\n */\n async updateHypothesisAccuracy(): Promise<void> {\n await this.load();\n \n const validated = this.data.hypotheses.filter(h => h.status === 'validated').length;\n const invalidated = this.data.hypotheses.filter(h => h.status === 'invalidated').length;\n const total = validated + invalidated;\n \n if (total > 0) {\n this.data.metrics.hypothesisAccuracy = validated / total;\n this.dirty = true;\n await this.save();\n }\n }\n \n // ========================================================================\n // Timing Context\n // ========================================================================\n \n /**\n * Get timing context\n */\n getTimingContext(): TimingContext {\n return { ...this.data.timing };\n }\n \n /**\n * Check if currently in quiet hours\n */\n isQuietHours(): boolean {\n if (!this.data.timing.quietHoursEnabled) {\n return false;\n }\n \n const now = new Date();\n const hour = now.getHours();\n const start = this.data.timing.quietHoursStart;\n const end = this.data.timing.quietHoursEnd;\n \n // Handle overnight quiet hours (e.g., 21:00 - 08:00)\n if (start > end) {\n return hour >= start || hour < end;\n }\n \n // Same-day quiet hours (e.g., 12:00 - 14:00)\n return hour >= start && hour < end;\n }\n \n /**\n * Check if today is a work day\n */\n isWorkDay(): boolean {\n const dayOfWeek = new Date().getDay();\n return this.data.timing.workDays.includes(dayOfWeek);\n }\n \n /**\n * Check if in crunch mode\n */\n isInCrunchMode(): boolean {\n if (!this.data.timing.crunchMode) {\n return false;\n }\n \n if (this.data.timing.crunchModeUntil) {\n const until = new Date(this.data.timing.crunchModeUntil);\n if (Date.now() > until.getTime()) {\n // Crunch mode expired\n this.data.timing.crunchMode = false;\n this.data.timing.crunchModeUntil = undefined;\n this.dirty = true;\n return false;\n }\n }\n \n return true;\n }\n \n /**\n * Enable crunch mode\n */\n async setCrunchMode(enabled: boolean, until?: Date): Promise<void> {\n await this.load();\n this.data.timing.crunchMode = enabled;\n this.data.timing.crunchModeUntil = until?.toISOString();\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Update quiet hours settings\n */\n async setQuietHours(start: number, end: number, enabled: boolean = true): Promise<void> {\n await this.load();\n this.data.timing.quietHoursStart = start;\n this.data.timing.quietHoursEnd = end;\n this.data.timing.quietHoursEnabled = enabled;\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Update work days\n */\n async setWorkDays(days: number[]): Promise<void> {\n await this.load();\n this.data.timing.workDays = days;\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Update last active timestamp\n */\n async touchActive(): Promise<void> {\n await this.load();\n this.data.timing.lastActiveTimestamp = Date.now();\n this.dirty = true;\n await this.save();\n }\n \n // ========================================================================\n // Scan Frequency\n // ========================================================================\n \n /**\n * Get current scan frequency in milliseconds\n */\n getScanFrequencyMs(): number {\n return this.data.scanFrequencyMs;\n }\n \n /**\n * Set scan frequency\n */\n async setScanFrequency(ms: number): Promise<void> {\n await this.load();\n this.data.scanFrequencyMs = Math.max(10000, ms); // Min 10 seconds\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Record a scan timestamp\n */\n async recordScan(): Promise<void> {\n await this.load();\n this.data.lastScanTimestamp = Date.now();\n this.dirty = true;\n await this.save();\n }\n \n /**\n * Get last scan timestamp\n */\n getLastScanTimestamp(): number | undefined {\n return this.data.lastScanTimestamp;\n }\n \n // ========================================================================\n // Utility\n // ========================================================================\n \n /**\n * Get full state data\n */\n getData(): GuardianStateData {\n return { ...this.data };\n }\n \n /**\n * Force reload from disk\n */\n async reload(): Promise<GuardianStateData> {\n this.loaded = false;\n this.dirty = false;\n return this.load();\n }\n \n /**\n * Check if loaded\n */\n isLoaded(): boolean {\n return this.loaded;\n }\n}\n\n// ============================================================================\n// Singleton Management\n// ============================================================================\n\nconst guardianStates: Map<string, GuardianState> = new Map();\n\n/**\n * Get the GuardianState for a project (singleton per project)\n */\nexport function getGuardianState(projectPath: string): GuardianState {\n let state = guardianStates.get(projectPath);\n if (!state) {\n state = new GuardianState(projectPath);\n guardianStates.set(projectPath, state);\n }\n return state;\n}\n\n/**\n * Clear all GuardianState instances (for testing)\n */\nexport function clearGuardianStates(): void {\n guardianStates.clear();\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,212 @@
1
+ import {
2
+ BackupManager,
3
+ GlobalPatternsIndexSchema,
4
+ atomicWriteJSON,
5
+ safeParseAndValidate
6
+ } from "./chunk-TSHZQKCM.js";
7
+
8
+ // src/memory/global-memory.ts
9
+ import { mkdir, writeFile, readFile, readdir } from "fs/promises";
10
+ import { createHash } from "crypto";
11
+ import { existsSync } from "fs";
12
+ import { join } from "path";
13
+ import { homedir } from "os";
14
+ var GLOBAL_TRIE_DIR = join(homedir(), ".trie");
15
+ var GLOBAL_MEMORY_DIR = join(GLOBAL_TRIE_DIR, "memory");
16
+ async function recordToGlobalMemory(issues, projectName, projectPath, healthScore = 0) {
17
+ await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
18
+ await mkdir(join(GLOBAL_MEMORY_DIR, "projects"), { recursive: true });
19
+ const patterns = await loadGlobalPatterns();
20
+ const now = (/* @__PURE__ */ new Date()).toISOString();
21
+ for (const issue of issues) {
22
+ const patternId = extractPatternId(issue);
23
+ const existing = patterns.find((p) => p.id === patternId);
24
+ if (existing) {
25
+ existing.occurrences++;
26
+ existing.lastSeen = now;
27
+ if (!existing.projects.includes(projectName)) {
28
+ existing.projects.push(projectName);
29
+ }
30
+ } else {
31
+ patterns.push({
32
+ id: patternId,
33
+ pattern: issue.issue.slice(0, 200),
34
+ description: issue.fix.slice(0, 200),
35
+ severity: issue.severity,
36
+ agent: issue.agent,
37
+ occurrences: 1,
38
+ projects: [projectName],
39
+ firstSeen: now,
40
+ lastSeen: now
41
+ });
42
+ }
43
+ }
44
+ await saveGlobalPatterns(patterns);
45
+ const summaryPath = join(GLOBAL_MEMORY_DIR, "projects", `${sanitizeName(projectName)}.json`);
46
+ const summary = {
47
+ name: projectName,
48
+ path: projectPath,
49
+ lastScan: now,
50
+ healthScore,
51
+ totalIssues: issues.length,
52
+ patterns: [...new Set(issues.map((i) => extractPatternId(i)))]
53
+ };
54
+ await atomicWriteJSON(summaryPath, summary);
55
+ }
56
+ async function findCrossProjectPatterns(minOccurrences = 2) {
57
+ const patterns = await loadGlobalPatterns();
58
+ return patterns.filter((p) => p.projects.length >= minOccurrences).sort((a, b) => b.occurrences - a.occurrences);
59
+ }
60
+ async function listTrackedProjects() {
61
+ const projectsDir = join(GLOBAL_MEMORY_DIR, "projects");
62
+ try {
63
+ if (!existsSync(projectsDir)) return [];
64
+ const files = await readdir(projectsDir);
65
+ const summaries = [];
66
+ for (const file of files) {
67
+ if (!file.endsWith(".json")) continue;
68
+ try {
69
+ const content = await readFile(join(projectsDir, file), "utf-8");
70
+ summaries.push(JSON.parse(content));
71
+ } catch {
72
+ }
73
+ }
74
+ return summaries.sort(
75
+ (a, b) => new Date(b.lastScan).getTime() - new Date(a.lastScan).getTime()
76
+ );
77
+ } catch {
78
+ return [];
79
+ }
80
+ }
81
+ async function getGlobalMemoryStats() {
82
+ const patterns = await loadGlobalPatterns();
83
+ const projects = await listTrackedProjects();
84
+ const patternsByAgent = {};
85
+ for (const pattern of patterns) {
86
+ patternsByAgent[pattern.agent] = (patternsByAgent[pattern.agent] || 0) + 1;
87
+ }
88
+ return {
89
+ totalPatterns: patterns.length,
90
+ crossProjectPatterns: patterns.filter((p) => p.projects.length >= 2).length,
91
+ trackedProjects: projects.length,
92
+ totalOccurrences: patterns.reduce((sum, p) => sum + p.occurrences, 0),
93
+ fixedPatterns: patterns.filter((p) => p.fixApplied).length,
94
+ patternsByAgent
95
+ };
96
+ }
97
+ async function updateGlobalMemoryMd() {
98
+ const patterns = await loadGlobalPatterns();
99
+ const crossProject = patterns.filter((p) => p.projects.length >= 2);
100
+ const projects = await listTrackedProjects();
101
+ const lines = [
102
+ "# Global Trie Memory",
103
+ "",
104
+ "> Auto-generated file tracking patterns across all your projects.",
105
+ `> Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
106
+ "",
107
+ "## Summary",
108
+ "",
109
+ `- **Projects tracked:** ${projects.length}`,
110
+ `- **Total patterns:** ${patterns.length}`,
111
+ `- **Cross-project patterns:** ${crossProject.length}`,
112
+ "",
113
+ "## Cross-Project Patterns",
114
+ "",
115
+ "These issues appear in multiple projects:",
116
+ ""
117
+ ];
118
+ for (const p of crossProject.slice(0, 20)) {
119
+ lines.push(
120
+ `### ${p.pattern.slice(0, 60)}${p.pattern.length > 60 ? "..." : ""}`,
121
+ "",
122
+ `- **Severity:** ${p.severity}`,
123
+ `- **Agent:** ${p.agent}`,
124
+ `- **Occurrences:** ${p.occurrences} across ${p.projects.length} projects`,
125
+ `- **Projects:** ${p.projects.slice(0, 5).join(", ")}${p.projects.length > 5 ? "..." : ""}`
126
+ );
127
+ if (p.fixApplied) {
128
+ lines.push(`- **Fixed in:** ${p.fixApplied.project} on ${p.fixApplied.timestamp.split("T")[0]}`);
129
+ } else {
130
+ lines.push("- **Status:** Not fixed");
131
+ }
132
+ lines.push("");
133
+ }
134
+ lines.push(
135
+ "## Tracked Projects",
136
+ "",
137
+ "| Project | Last Scan | Health | Issues |",
138
+ "|---------|-----------|--------|--------|"
139
+ );
140
+ for (const p of projects.slice(0, 20)) {
141
+ lines.push(`| ${p.name} | ${p.lastScan.split("T")[0]} | ${p.healthScore}% | ${p.totalIssues} |`);
142
+ }
143
+ lines.push("", "---", "", "*This file is auto-generated by Trie. Do not edit manually.*");
144
+ await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
145
+ await writeFile(join(GLOBAL_MEMORY_DIR, "GLOBAL_MEMORY.md"), lines.join("\n"));
146
+ }
147
+ async function searchGlobalPatterns(query, options = {}) {
148
+ const patterns = await loadGlobalPatterns();
149
+ const limit = options.limit || 10;
150
+ const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
151
+ const scored = patterns.filter((p) => {
152
+ if (options.severity && !options.severity.includes(p.severity)) return false;
153
+ if (options.agent && p.agent !== options.agent) return false;
154
+ return true;
155
+ }).map((p) => {
156
+ const text = `${p.pattern} ${p.description} ${p.agent}`.toLowerCase();
157
+ let score = 0;
158
+ for (const term of queryTerms) {
159
+ if (text.includes(term)) score++;
160
+ }
161
+ return { pattern: p, score };
162
+ }).filter((s) => s.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
163
+ return scored.map((s) => s.pattern);
164
+ }
165
+ async function loadGlobalPatterns() {
166
+ const patternsPath = join(GLOBAL_MEMORY_DIR, "global-patterns.json");
167
+ try {
168
+ if (existsSync(patternsPath)) {
169
+ const content = await readFile(patternsPath, "utf-8");
170
+ const result = safeParseAndValidate(content, GlobalPatternsIndexSchema);
171
+ if (result.success) {
172
+ return result.data;
173
+ }
174
+ const backupManager = new BackupManager(patternsPath);
175
+ if (await backupManager.recoverFromBackup()) {
176
+ const recovered = await readFile(patternsPath, "utf-8");
177
+ const recoveredResult = safeParseAndValidate(recovered, GlobalPatternsIndexSchema);
178
+ if (recoveredResult.success) {
179
+ return recoveredResult.data;
180
+ }
181
+ }
182
+ }
183
+ } catch {
184
+ }
185
+ return [];
186
+ }
187
+ async function saveGlobalPatterns(patterns) {
188
+ await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });
189
+ const patternsPath = join(GLOBAL_MEMORY_DIR, "global-patterns.json");
190
+ const pruned = patterns.sort((a, b) => new Date(b.lastSeen).getTime() - new Date(a.lastSeen).getTime()).slice(0, 500);
191
+ const backupManager = new BackupManager(patternsPath);
192
+ await backupManager.createBackup();
193
+ await atomicWriteJSON(patternsPath, pruned);
194
+ }
195
+ function extractPatternId(issue) {
196
+ const normalized = issue.issue.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/['"]/g, "").slice(0, 100);
197
+ const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 12);
198
+ return `${issue.agent}-${issue.severity}-${hash}`;
199
+ }
200
+ function sanitizeName(name) {
201
+ return name.replace(/[^a-zA-Z0-9-_]/g, "-").toLowerCase();
202
+ }
203
+
204
+ export {
205
+ recordToGlobalMemory,
206
+ findCrossProjectPatterns,
207
+ listTrackedProjects,
208
+ getGlobalMemoryStats,
209
+ updateGlobalMemoryMd,
210
+ searchGlobalPatterns
211
+ };
212
+ //# sourceMappingURL=chunk-7KHT2NKR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory/global-memory.ts"],"sourcesContent":["/**\n * Cross-Project Memory\n * \n * Stores and retrieves patterns across all projects.\n * Location: ~/.trie/memory/\n * \n * Phase 1 Hardening:\n * - SHA256 hashing for pattern IDs\n * - Atomic writes to prevent corruption\n * - Rotational backups for recovery\n * - Zod validation for data integrity\n */\n\nimport { mkdir, writeFile, readFile, readdir } from 'fs/promises';\nimport { createHash } from 'crypto';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { Issue } from '../types/index.js';\nimport { atomicWriteJSON } from '../utils/atomic-write.js';\nimport { BackupManager } from '../utils/backup-manager.js';\nimport { GlobalPatternsIndexSchema, safeParseAndValidate } from './validation.js';\n\nconst GLOBAL_TRIE_DIR = join(homedir(), '.trie');\nconst GLOBAL_MEMORY_DIR = join(GLOBAL_TRIE_DIR, 'memory');\n\nexport interface GlobalPattern {\n id: string;\n pattern: string;\n description: string;\n severity: string;\n agent: string;\n occurrences: number;\n projects: string[];\n firstSeen: string;\n lastSeen: string;\n fixApplied?: {\n project: string;\n timestamp: string;\n fix: string;\n };\n}\n\nexport interface ProjectSummary {\n name: string;\n path: string;\n lastScan: string;\n healthScore: number;\n totalIssues: number;\n patterns: string[];\n}\n\n/**\n * Record issues to global memory\n */\nexport async function recordToGlobalMemory(\n issues: Issue[],\n projectName: string,\n projectPath: string,\n healthScore: number = 0\n): Promise<void> {\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n await mkdir(join(GLOBAL_MEMORY_DIR, 'projects'), { recursive: true });\n\n const patterns = await loadGlobalPatterns();\n const now = new Date().toISOString();\n\n for (const issue of issues) {\n const patternId = extractPatternId(issue);\n const existing = patterns.find(p => p.id === patternId);\n\n if (existing) {\n existing.occurrences++;\n existing.lastSeen = now;\n if (!existing.projects.includes(projectName)) {\n existing.projects.push(projectName);\n }\n } else {\n patterns.push({\n id: patternId,\n pattern: issue.issue.slice(0, 200),\n description: issue.fix.slice(0, 200),\n severity: issue.severity,\n agent: issue.agent,\n occurrences: 1,\n projects: [projectName],\n firstSeen: now,\n lastSeen: now,\n });\n }\n }\n\n await saveGlobalPatterns(patterns);\n\n const summaryPath = join(GLOBAL_MEMORY_DIR, 'projects', `${sanitizeName(projectName)}.json`);\n const summary: ProjectSummary = {\n name: projectName,\n path: projectPath,\n lastScan: now,\n healthScore,\n totalIssues: issues.length,\n patterns: [...new Set(issues.map(i => extractPatternId(i)))],\n };\n \n // Use atomic write for project summary\n await atomicWriteJSON(summaryPath, summary);\n}\n\n/**\n * Find patterns that appear across multiple projects\n */\nexport async function findCrossProjectPatterns(\n minOccurrences: number = 2\n): Promise<GlobalPattern[]> {\n const patterns = await loadGlobalPatterns();\n return patterns\n .filter(p => p.projects.length >= minOccurrences)\n .sort((a, b) => b.occurrences - a.occurrences);\n}\n\n/**\n * Check if an issue has been fixed in another project\n */\nexport async function findFixFromOtherProjects(\n issue: Issue\n): Promise<GlobalPattern | null> {\n const patterns = await loadGlobalPatterns();\n const patternId = extractPatternId(issue);\n const pattern = patterns.find(p => p.id === patternId);\n\n if (pattern?.fixApplied) {\n return pattern;\n }\n\n return null;\n}\n\n/**\n * Record that a pattern was fixed\n */\nexport async function recordPatternFix(\n issue: Issue,\n projectName: string,\n fix: string\n): Promise<void> {\n const patterns = await loadGlobalPatterns();\n const patternId = extractPatternId(issue);\n const pattern = patterns.find(p => p.id === patternId);\n\n if (pattern && !pattern.fixApplied) {\n pattern.fixApplied = {\n project: projectName,\n timestamp: new Date().toISOString(),\n fix: fix.slice(0, 500),\n };\n await saveGlobalPatterns(patterns);\n }\n}\n\n/**\n * Get all tracked projects\n */\nexport async function listTrackedProjects(): Promise<ProjectSummary[]> {\n const projectsDir = join(GLOBAL_MEMORY_DIR, 'projects');\n \n try {\n if (!existsSync(projectsDir)) return [];\n \n const files = await readdir(projectsDir);\n const summaries: ProjectSummary[] = [];\n \n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n try {\n const content = await readFile(join(projectsDir, file), 'utf-8');\n summaries.push(JSON.parse(content));\n } catch {\n // Skip invalid files\n }\n }\n \n return summaries.sort((a, b) => \n new Date(b.lastScan).getTime() - new Date(a.lastScan).getTime()\n );\n } catch {\n return [];\n }\n}\n\n/**\n * Get global memory statistics\n */\nexport async function getGlobalMemoryStats(): Promise<{\n totalPatterns: number;\n crossProjectPatterns: number;\n trackedProjects: number;\n totalOccurrences: number;\n fixedPatterns: number;\n patternsByAgent: Record<string, number>;\n}> {\n const patterns = await loadGlobalPatterns();\n const projects = await listTrackedProjects();\n \n // Count patterns by agent type\n const patternsByAgent: Record<string, number> = {};\n for (const pattern of patterns) {\n patternsByAgent[pattern.agent] = (patternsByAgent[pattern.agent] || 0) + 1;\n }\n \n return {\n totalPatterns: patterns.length,\n crossProjectPatterns: patterns.filter(p => p.projects.length >= 2).length,\n trackedProjects: projects.length,\n totalOccurrences: patterns.reduce((sum, p) => sum + p.occurrences, 0),\n fixedPatterns: patterns.filter(p => p.fixApplied).length,\n patternsByAgent,\n };\n}\n\n/**\n * Update GLOBAL_MEMORY.md with current patterns\n */\nexport async function updateGlobalMemoryMd(): Promise<void> {\n const patterns = await loadGlobalPatterns();\n const crossProject = patterns.filter(p => p.projects.length >= 2);\n const projects = await listTrackedProjects();\n\n const lines: string[] = [\n '# Global Trie Memory',\n '',\n '> Auto-generated file tracking patterns across all your projects.',\n `> Last updated: ${new Date().toISOString()}`,\n '',\n '## Summary',\n '',\n `- **Projects tracked:** ${projects.length}`,\n `- **Total patterns:** ${patterns.length}`,\n `- **Cross-project patterns:** ${crossProject.length}`,\n '',\n '## Cross-Project Patterns',\n '',\n 'These issues appear in multiple projects:',\n '',\n ];\n \n for (const p of crossProject.slice(0, 20)) {\n lines.push(\n `### ${p.pattern.slice(0, 60)}${p.pattern.length > 60 ? '...' : ''}`,\n '',\n `- **Severity:** ${p.severity}`,\n `- **Agent:** ${p.agent}`,\n `- **Occurrences:** ${p.occurrences} across ${p.projects.length} projects`,\n `- **Projects:** ${p.projects.slice(0, 5).join(', ')}${p.projects.length > 5 ? '...' : ''}`,\n );\n if (p.fixApplied) {\n lines.push(`- **Fixed in:** ${p.fixApplied.project} on ${p.fixApplied.timestamp.split('T')[0]}`);\n } else {\n lines.push('- **Status:** Not fixed');\n }\n lines.push('');\n }\n\n lines.push(\n '## Tracked Projects',\n '',\n '| Project | Last Scan | Health | Issues |',\n '|---------|-----------|--------|--------|',\n );\n \n for (const p of projects.slice(0, 20)) {\n lines.push(`| ${p.name} | ${p.lastScan.split('T')[0]} | ${p.healthScore}% | ${p.totalIssues} |`);\n }\n\n lines.push('', '---', '', '*This file is auto-generated by Trie. Do not edit manually.*');\n\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n await writeFile(join(GLOBAL_MEMORY_DIR, 'GLOBAL_MEMORY.md'), lines.join('\\n'));\n}\n\n/**\n * Search global patterns\n */\nexport async function searchGlobalPatterns(\n query: string,\n options: {\n limit?: number;\n severity?: string[];\n agent?: string;\n } = {}\n): Promise<GlobalPattern[]> {\n const patterns = await loadGlobalPatterns();\n const limit = options.limit || 10;\n const queryTerms = query.toLowerCase().split(/\\s+/).filter(t => t.length > 2);\n \n const scored = patterns\n .filter(p => {\n if (options.severity && !options.severity.includes(p.severity)) return false;\n if (options.agent && p.agent !== options.agent) return false;\n return true;\n })\n .map(p => {\n const text = `${p.pattern} ${p.description} ${p.agent}`.toLowerCase();\n let score = 0;\n for (const term of queryTerms) {\n if (text.includes(term)) score++;\n }\n return { pattern: p, score };\n })\n .filter(s => s.score > 0)\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n \n return scored.map(s => s.pattern);\n}\n\n// Private helpers\n\n/**\n * Load global patterns with validation and auto-recovery\n */\nasync function loadGlobalPatterns(): Promise<GlobalPattern[]> {\n const patternsPath = join(GLOBAL_MEMORY_DIR, 'global-patterns.json');\n \n try {\n if (existsSync(patternsPath)) {\n const content = await readFile(patternsPath, 'utf-8');\n const result = safeParseAndValidate(content, GlobalPatternsIndexSchema);\n \n if (result.success) {\n return result.data as GlobalPattern[];\n }\n \n // Validation failed - attempt recovery\n const backupManager = new BackupManager(patternsPath);\n if (await backupManager.recoverFromBackup()) {\n const recovered = await readFile(patternsPath, 'utf-8');\n const recoveredResult = safeParseAndValidate(recovered, GlobalPatternsIndexSchema);\n if (recoveredResult.success) {\n return recoveredResult.data as GlobalPattern[];\n }\n }\n }\n } catch {\n // File doesn't exist or recovery failed\n }\n \n return [];\n}\n\n/**\n * Save global patterns with backup and atomic write\n */\nasync function saveGlobalPatterns(patterns: GlobalPattern[]): Promise<void> {\n await mkdir(GLOBAL_MEMORY_DIR, { recursive: true });\n const patternsPath = join(GLOBAL_MEMORY_DIR, 'global-patterns.json');\n \n const pruned = patterns\n .sort((a, b) => new Date(b.lastSeen).getTime() - new Date(a.lastSeen).getTime())\n .slice(0, 500);\n \n // Create backup before writing\n const backupManager = new BackupManager(patternsPath);\n await backupManager.createBackup();\n \n // Atomic write\n await atomicWriteJSON(patternsPath, pruned);\n}\n\n/**\n * Extract a pattern ID using SHA256 for proper deduplication\n * \n * Normalizes the issue text to group similar patterns:\n * - Lowercases\n * - Replaces code snippets with 'CODE'\n * - Replaces numbers with 'N'\n * - Removes quotes\n * \n * Uses SHA256 truncated to 12 chars for collision-free IDs.\n */\nfunction extractPatternId(issue: Issue): string {\n const normalized = issue.issue\n .toLowerCase()\n .replace(/`[^`]+`/g, 'CODE')\n .replace(/\\b\\d+\\b/g, 'N')\n .replace(/['\"]/g, '')\n .slice(0, 100);\n \n const hash = createHash('sha256')\n .update(normalized)\n .digest('hex')\n .slice(0, 12);\n \n return `${issue.agent}-${issue.severity}-${hash}`;\n}\n\nfunction sanitizeName(name: string): string {\n return name.replace(/[^a-zA-Z0-9-_]/g, '-').toLowerCase();\n}\n"],"mappings":"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","names":[]}