@triedotdev/mcp 1.0.135 → 1.0.137

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 (68) hide show
  1. package/dist/{chunk-DFHMB44X.js → chunk-4JQ6W7LW.js} +3 -4
  2. package/dist/chunk-4JQ6W7LW.js.map +1 -0
  3. package/dist/{chunk-WS6OA7H6.js → chunk-4MJ52WBH.js} +2 -3
  4. package/dist/chunk-4MJ52WBH.js.map +1 -0
  5. package/dist/{chunk-UHMMANC2.js → chunk-6EP2VTHC.js} +15 -15
  6. package/dist/chunk-6EP2VTHC.js.map +1 -0
  7. package/dist/{chunk-T4THB2OR.js → chunk-A6PWS6ZV.js} +38 -27
  8. package/dist/chunk-A6PWS6ZV.js.map +1 -0
  9. package/dist/{chunk-TFGNTSMH.js → chunk-AXYNWBME.js} +319 -208
  10. package/dist/chunk-AXYNWBME.js.map +1 -0
  11. package/dist/{chunk-LRQV7SGQ.js → chunk-DPZLABUC.js} +33 -33
  12. package/dist/chunk-DPZLABUC.js.map +1 -0
  13. package/dist/{chunk-3DPVJQNM.js → chunk-G74XEI7K.js} +14 -15
  14. package/dist/chunk-G74XEI7K.js.map +1 -0
  15. package/dist/{goal-validator-KLAK5TZN.js → chunk-HUR67JXG.js} +72 -34
  16. package/dist/chunk-HUR67JXG.js.map +1 -0
  17. package/dist/{chunk-6OUWNVLX.js → chunk-K6NTRSDF.js} +4 -4
  18. package/dist/{chunk-JCU6REX7.js → chunk-O6OTJI3W.js} +16 -5
  19. package/dist/{chunk-JCU6REX7.js.map → chunk-O6OTJI3W.js.map} +1 -1
  20. package/dist/{chunk-T62V4H5O.js → chunk-QM5VIDFN.js} +76 -72
  21. package/dist/chunk-QM5VIDFN.js.map +1 -0
  22. package/dist/{chunk-4YJ6KLGI.js → chunk-QNKBXOIQ.js} +7 -5
  23. package/dist/chunk-QNKBXOIQ.js.map +1 -0
  24. package/dist/{chunk-JAKMZI5S.js → chunk-R3WZI6QZ.js} +290 -179
  25. package/dist/chunk-R3WZI6QZ.js.map +1 -0
  26. package/dist/{chunk-VRLMTOB6.js → chunk-TIMIKBY2.js} +1 -1
  27. package/dist/chunk-TIMIKBY2.js.map +1 -0
  28. package/dist/cli/main.js +104 -100
  29. package/dist/cli/main.js.map +1 -1
  30. package/dist/cli/yolo-daemon.js +14 -14
  31. package/dist/cli/yolo-daemon.js.map +1 -1
  32. package/dist/{client-OVI6TBX7.js → client-BZHI675W.js} +2 -2
  33. package/dist/{goal-manager-FAK7H4RR.js → goal-manager-62IL6WGY.js} +6 -7
  34. package/dist/goal-validator-HPPBSDXD.js +22 -0
  35. package/dist/guardian-agent-YKG5XURG.js +30 -0
  36. package/dist/{hypothesis-I276JIDW.js → hypothesis-W37VG6DA.js} +6 -7
  37. package/dist/index.js +263 -257
  38. package/dist/index.js.map +1 -1
  39. package/dist/{insight-store-F5KDBY5Y.js → insight-store-U3NYTOJE.js} +5 -3
  40. package/dist/issue-store-EZMBHOVN.js +32 -0
  41. package/dist/{output-manager-BOTMXSND.js → output-manager-DZO5LGSG.js} +2 -2
  42. package/dist/output-manager-DZO5LGSG.js.map +1 -0
  43. package/dist/ui/chat.html +1 -1
  44. package/package.json +1 -1
  45. package/dist/chunk-3DPVJQNM.js.map +0 -1
  46. package/dist/chunk-4YJ6KLGI.js.map +0 -1
  47. package/dist/chunk-DFHMB44X.js.map +0 -1
  48. package/dist/chunk-JAKMZI5S.js.map +0 -1
  49. package/dist/chunk-LRQV7SGQ.js.map +0 -1
  50. package/dist/chunk-PEJEYWVR.js +0 -135
  51. package/dist/chunk-PEJEYWVR.js.map +0 -1
  52. package/dist/chunk-T4THB2OR.js.map +0 -1
  53. package/dist/chunk-T62V4H5O.js.map +0 -1
  54. package/dist/chunk-TFGNTSMH.js.map +0 -1
  55. package/dist/chunk-UHMMANC2.js.map +0 -1
  56. package/dist/chunk-VRLMTOB6.js.map +0 -1
  57. package/dist/chunk-WS6OA7H6.js.map +0 -1
  58. package/dist/goal-validator-KLAK5TZN.js.map +0 -1
  59. package/dist/guardian-agent-3EUJUAJ2.js +0 -27
  60. package/dist/ledger-WKVJWHBX.js +0 -17
  61. /package/dist/{chunk-6OUWNVLX.js.map → chunk-K6NTRSDF.js.map} +0 -0
  62. /package/dist/{client-OVI6TBX7.js.map → client-BZHI675W.js.map} +0 -0
  63. /package/dist/{goal-manager-FAK7H4RR.js.map → goal-manager-62IL6WGY.js.map} +0 -0
  64. /package/dist/{guardian-agent-3EUJUAJ2.js.map → goal-validator-HPPBSDXD.js.map} +0 -0
  65. /package/dist/{hypothesis-I276JIDW.js.map → guardian-agent-YKG5XURG.js.map} +0 -0
  66. /package/dist/{insight-store-F5KDBY5Y.js.map → hypothesis-W37VG6DA.js.map} +0 -0
  67. /package/dist/{ledger-WKVJWHBX.js.map → insight-store-U3NYTOJE.js.map} +0 -0
  68. /package/dist/{output-manager-BOTMXSND.js.map → issue-store-EZMBHOVN.js.map} +0 -0
@@ -1 +0,0 @@
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 { getTrieDirectory } from '../utils/workspace.js';\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 metadata: z.record(z.any()).optional(), // Track caught/fixed counts and other metadata\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(getTrieDirectory(this.projectPath), '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(getTrieDirectory(this.projectPath), '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 // Transition from proposed to testing when first evidence is gathered\n if (hypothesis.status === 'proposed' && hypothesis.evidence.length === 1) {\n hypothesis.status = 'testing';\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 (only if already testing)\n if (hypothesis.status === 'testing') {\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 \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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/output-manager.ts"],"sourcesContent":["/**\n * OutputManager - Unified output abstraction for all UI modes\n * \n * Routes content to the appropriate renderer based on current mode:\n * - TUI: Routes to InteractiveDashboard\n * - Console: Routes to console.error with ANSI colors\n * - MCP: Accumulates for markdown response\n * - JSON: Accumulates for JSON response\n * - Silent: Discards output\n * \n * This solves the problem of skills suppressing content in interactive mode\n * by redirecting it to the dashboard instead.\n */\n\nimport type { Issue } from '../types/index.js';\nimport type { StreamingManager } from './streaming.js';\nimport { isInteractiveMode } from './progress.js';\nimport pc from 'picocolors';\n\n// Output content types\nexport type OutputContentType = \n | 'banner' // ASCII art banner from skills\n | 'progress' // Progress update\n | 'issue' // Issue found\n | 'snippet' // Code snippet with context\n | 'cost' // Cost estimate from Moneybags\n | 'readiness' // Production readiness score\n | 'semantic' // Semantic analysis (data flow, race conditions)\n | 'attack' // Attack surface analysis\n | 'activity' // Activity log message\n | 'report' // Full markdown report section\n | 'log' // Raw log message\n | 'nudge'; // Proactive guardian notification\n\n// Nudge content for proactive notifications\nexport interface NudgeContent {\n message: string;\n severity: 'critical' | 'warning' | 'info';\n file?: string;\n autoHideMs?: number; // Auto-dismiss after this many milliseconds\n}\n\nexport interface BannerContent {\n skill: string;\n art: string;\n quote?: string;\n version?: string;\n}\n\nexport interface SnippetContent {\n file: string;\n lines: string[];\n highlightLine?: number;\n startLine: number;\n}\n\nexport interface CostContent {\n fixNowCost: number;\n productionCost: number;\n savings: number;\n perIssue?: Array<{ issue: string; cost: number }>;\n}\n\nexport interface ReadinessContent {\n score: number;\n requirementsMet: number;\n total: number;\n status: 'ready' | 'caution' | 'not-ready';\n requirements?: Array<{ name: string; met: boolean }>;\n}\n\nexport interface SemanticContent {\n dataFlowIssues: number;\n raceConditions: number;\n authIssues: number;\n details?: Array<{ type: string; description: string; file: string; line?: number }>;\n}\n\nexport interface AttackSurfaceContent {\n totalEndpoints: number;\n unprotected: number;\n riskScore: number;\n endpoints?: Array<{ path: string; method: string; auth: boolean; sensitive: boolean }>;\n}\n\nexport interface OutputContent {\n type: OutputContentType;\n content: any;\n timestamp?: number;\n metadata?: {\n severity?: 'critical' | 'serious' | 'moderate' | 'low';\n agent?: string;\n file?: string;\n };\n}\n\nexport type OutputMode = 'tui' | 'console' | 'mcp' | 'json' | 'silent';\n\n/**\n * Central output manager - singleton\n */\nclass OutputManagerImpl {\n private mode: OutputMode = 'console';\n private streamingManager?: StreamingManager;\n private markdownBuffer: string[] = [];\n private jsonBuffer: OutputContent[] = [];\n private rawLogBuffer: Array<{ time: string; level: string; message: string }> = [];\n \n // Callbacks for TUI integration (explicitly allow undefined for exactOptionalPropertyTypes)\n private onBanner: ((content: BannerContent) => void) | undefined = undefined;\n private onSnippet: ((content: SnippetContent) => void) | undefined = undefined;\n private onCost: ((content: CostContent) => void) | undefined = undefined;\n private onReadiness: ((content: ReadinessContent) => void) | undefined = undefined;\n private onSemantic: ((content: SemanticContent) => void) | undefined = undefined;\n private onAttack: ((content: AttackSurfaceContent) => void) | undefined = undefined;\n private onActivity: ((message: string) => void) | undefined = undefined;\n private onLog: ((level: string, message: string) => void) | undefined = undefined;\n private onNudge: ((content: NudgeContent) => void) | undefined = undefined;\n\n /**\n * Set the output mode\n */\n setMode(mode: OutputMode): void {\n this.mode = mode;\n }\n\n /**\n * Get current output mode\n */\n getMode(): OutputMode {\n return this.mode;\n }\n\n /**\n * Set streaming manager for TUI updates\n */\n setStreamingManager(manager: StreamingManager): void {\n this.streamingManager = manager;\n }\n\n /**\n * Register TUI callbacks for rich content\n */\n registerTUICallbacks(callbacks: {\n onBanner?: (content: BannerContent) => void;\n onSnippet?: (content: SnippetContent) => void;\n onCost?: (content: CostContent) => void;\n onReadiness?: (content: ReadinessContent) => void;\n onSemantic?: (content: SemanticContent) => void;\n onAttack?: (content: AttackSurfaceContent) => void;\n onActivity?: (message: string) => void;\n onLog?: (level: string, message: string) => void;\n onNudge?: (content: NudgeContent) => void;\n }): void {\n this.onBanner = callbacks.onBanner;\n this.onSnippet = callbacks.onSnippet;\n this.onCost = callbacks.onCost;\n this.onReadiness = callbacks.onReadiness;\n this.onSemantic = callbacks.onSemantic;\n this.onAttack = callbacks.onAttack;\n this.onActivity = callbacks.onActivity;\n this.onLog = callbacks.onLog;\n this.onNudge = callbacks.onNudge;\n }\n\n /**\n * Clear TUI callbacks (when dashboard stops)\n */\n clearTUICallbacks(): void {\n this.onBanner = undefined;\n this.onSnippet = undefined;\n this.onCost = undefined;\n this.onReadiness = undefined;\n this.onSemantic = undefined;\n this.onAttack = undefined;\n this.onActivity = undefined;\n this.onLog = undefined;\n this.onNudge = undefined;\n }\n\n /**\n * Emit content - routes to appropriate handler based on mode\n */\n emit(content: OutputContent): void {\n content.timestamp = content.timestamp ?? Date.now();\n \n switch (this.mode) {\n case 'tui':\n this.routeToTUI(content);\n break;\n case 'console':\n this.routeToConsole(content);\n break;\n case 'mcp':\n this.routeToMarkdown(content);\n break;\n case 'json':\n this.routeToJson(content);\n break;\n case 'silent':\n // Discard\n break;\n }\n \n // Always capture in raw log buffer\n this.captureRawLog(content);\n }\n\n /**\n * Route content to TUI (dashboard callbacks)\n */\n private routeToTUI(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n this.onBanner?.(content.content as BannerContent);\n break;\n case 'snippet':\n this.onSnippet?.(content.content as SnippetContent);\n break;\n case 'cost':\n this.onCost?.(content.content as CostContent);\n break;\n case 'readiness':\n this.onReadiness?.(content.content as ReadinessContent);\n break;\n case 'semantic':\n this.onSemantic?.(content.content as SemanticContent);\n break;\n case 'attack':\n this.onAttack?.(content.content as AttackSurfaceContent);\n break;\n case 'activity':\n this.onActivity?.(content.content as string);\n break;\n case 'log':\n const level = content.metadata?.severity ?? 'info';\n this.onLog?.(level, content.content as string);\n break;\n case 'issue':\n // Issues go through streaming manager\n this.streamingManager?.reportIssue(content.content as Issue);\n break;\n case 'progress':\n // Progress goes through streaming manager\n break;\n case 'report':\n // Reports are captured but not directly displayed\n break;\n case 'nudge':\n // Proactive notifications go to dashboard\n this.onNudge?.(content.content as NudgeContent);\n break;\n }\n }\n\n /**\n * Route content to console (ANSI formatted)\n */\n private routeToConsole(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n const banner = content.content as BannerContent;\n console.error('\\n' + '='.repeat(60));\n console.error(banner.art);\n if (banner.version) {\n console.error(` ${banner.skill} v${banner.version}`);\n }\n console.error('');\n if (banner.quote) {\n console.error(` \"${banner.quote}\"`);\n }\n console.error('='.repeat(60) + '\\n');\n break;\n \n case 'snippet':\n const snippet = content.content as SnippetContent;\n console.error(`\\n${pc.dim('File:')} ${snippet.file}`);\n for (let i = 0; i < snippet.lines.length; i++) {\n const lineNum = snippet.startLine + i;\n const isHighlight = lineNum === snippet.highlightLine;\n const prefix = isHighlight ? pc.red('→') : ' ';\n const lineNumStr = pc.dim(lineNum.toString().padStart(4));\n const line = isHighlight ? pc.yellow(snippet.lines[i]) : snippet.lines[i];\n console.error(`${prefix} ${lineNumStr} | ${line}`);\n }\n console.error('');\n break;\n \n case 'cost':\n const cost = content.content as CostContent;\n console.error('\\n' + pc.cyan('[$] Cost Estimate:'));\n console.error(` Fix now: ${pc.green(this.formatCurrency(cost.fixNowCost))}`);\n console.error(` If production: ${pc.red(this.formatCurrency(cost.productionCost))}`);\n console.error(` Savings: ${pc.yellow(this.formatCurrency(cost.savings))}`);\n console.error('');\n break;\n \n case 'readiness':\n const readiness = content.content as ReadinessContent;\n const statusColor = readiness.status === 'ready' ? pc.green : \n readiness.status === 'caution' ? pc.yellow : pc.red;\n console.error('\\n' + pc.cyan('[%] Production Readiness:'));\n console.error(` Score: ${statusColor(readiness.score + '/100')}`);\n console.error(` Requirements: ${readiness.requirementsMet}/${readiness.total}`);\n console.error(` Status: ${statusColor(readiness.status.toUpperCase())}`);\n console.error('');\n break;\n \n case 'semantic':\n const semantic = content.content as SemanticContent;\n console.error('\\n' + pc.cyan('[?] Semantic Analysis:'));\n if (semantic.dataFlowIssues > 0) {\n console.error(` ${pc.red('[!]')} ${semantic.dataFlowIssues} data flow vulnerabilities`);\n }\n if (semantic.raceConditions > 0) {\n console.error(` ${pc.yellow('[~]')} ${semantic.raceConditions} race conditions`);\n }\n if (semantic.authIssues > 0) {\n console.error(` ${pc.red('[!]')} ${semantic.authIssues} authentication issues`);\n }\n console.error('');\n break;\n \n case 'attack':\n const attack = content.content as AttackSurfaceContent;\n console.error('\\n' + pc.cyan('[>] Attack Surface:'));\n console.error(` Endpoints: ${attack.totalEndpoints}`);\n if (attack.unprotected > 0) {\n console.error(` ${pc.red('Unprotected:')} ${attack.unprotected}`);\n }\n console.error(` Risk Score: ${attack.riskScore}/100`);\n console.error('');\n break;\n \n case 'activity':\n console.error(pc.dim(`[${this.formatTime()}]`) + ` ${content.content}`);\n break;\n \n case 'log':\n // For log content, severity can be any string (info, warn, error, debug)\n const logLevel = String(content.metadata?.severity ?? 'info');\n const levelColor = logLevel === 'error' || logLevel === 'critical' ? pc.red :\n logLevel === 'warn' || logLevel === 'serious' ? pc.yellow :\n logLevel === 'info' || logLevel === 'moderate' ? pc.blue : pc.dim;\n console.error(levelColor(`[${logLevel.toUpperCase()}]`) + ` ${content.content}`);\n break;\n \n case 'issue':\n const issue = content.content as Issue;\n const sevColor = issue.severity === 'critical' ? pc.red :\n issue.severity === 'serious' ? pc.yellow :\n issue.severity === 'moderate' ? pc.blue : pc.dim;\n console.error(`${sevColor(`[${issue.severity.toUpperCase()}]`)} ${issue.issue}`);\n console.error(` ${pc.dim('File:')} ${issue.file}:${issue.line ?? '?'}`);\n break;\n \n case 'report':\n // Reports are printed as-is (already formatted)\n console.error(content.content);\n break;\n \n case 'nudge':\n // Proactive notifications in console mode\n const nudge = content.content as NudgeContent;\n const nudgeColor = nudge.severity === 'critical' ? pc.red :\n nudge.severity === 'warning' ? pc.yellow : pc.cyan;\n const nudgeIcon = nudge.severity === 'critical' ? '[!!!]' :\n nudge.severity === 'warning' ? '[!]' : '[>]';\n console.error('');\n console.error(nudgeColor('━'.repeat(60)));\n console.error(nudgeColor(`${nudgeIcon} TRIE AGENT SAYS:`));\n console.error(nudgeColor('━'.repeat(60)));\n console.error('');\n console.error(` ${pc.bold(nudge.message)}`);\n if (nudge.file) {\n console.error(` ${pc.dim('File:')} ${nudge.file}`);\n }\n console.error('');\n console.error(nudgeColor('━'.repeat(60)));\n console.error('');\n break;\n }\n }\n\n /**\n * Route content to markdown buffer\n */\n private routeToMarkdown(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n const banner = content.content as BannerContent;\n this.markdownBuffer.push(`## ${banner.skill}\\n`);\n if (banner.quote) {\n this.markdownBuffer.push(`> ${banner.quote}\\n`);\n }\n break;\n \n case 'snippet':\n const snippet = content.content as SnippetContent;\n this.markdownBuffer.push(`\\n**File:** \\`${snippet.file}\\`\\n`);\n this.markdownBuffer.push('```\\n');\n for (let i = 0; i < snippet.lines.length; i++) {\n const lineNum = snippet.startLine + i;\n const prefix = lineNum === snippet.highlightLine ? '→' : ' ';\n this.markdownBuffer.push(`${prefix} ${lineNum.toString().padStart(4)} | ${snippet.lines[i]}\\n`);\n }\n this.markdownBuffer.push('```\\n');\n break;\n \n case 'cost':\n const cost = content.content as CostContent;\n this.markdownBuffer.push(`\\n### Cost Estimate\\n`);\n this.markdownBuffer.push(`- Fix now: ${this.formatCurrency(cost.fixNowCost)}\\n`);\n this.markdownBuffer.push(`- If production: ${this.formatCurrency(cost.productionCost)}\\n`);\n this.markdownBuffer.push(`- Savings: ${this.formatCurrency(cost.savings)}\\n`);\n break;\n \n case 'readiness':\n const readiness = content.content as ReadinessContent;\n this.markdownBuffer.push(`\\n### Production Readiness\\n`);\n this.markdownBuffer.push(`- Score: ${readiness.score}/100\\n`);\n this.markdownBuffer.push(`- Requirements: ${readiness.requirementsMet}/${readiness.total}\\n`);\n this.markdownBuffer.push(`- Status: **${readiness.status.toUpperCase()}**\\n`);\n break;\n \n case 'semantic':\n const semantic = content.content as SemanticContent;\n this.markdownBuffer.push(`\\n### Semantic Analysis\\n`);\n if (semantic.dataFlowIssues > 0) {\n this.markdownBuffer.push(`- [CRITICAL] ${semantic.dataFlowIssues} data flow vulnerabilities\\n`);\n }\n if (semantic.raceConditions > 0) {\n this.markdownBuffer.push(`- [WARN] ${semantic.raceConditions} race conditions\\n`);\n }\n if (semantic.authIssues > 0) {\n this.markdownBuffer.push(`- [CRITICAL] ${semantic.authIssues} authentication issues\\n`);\n }\n break;\n \n case 'attack':\n const attack = content.content as AttackSurfaceContent;\n this.markdownBuffer.push(`\\n### Attack Surface\\n`);\n this.markdownBuffer.push(`- Endpoints: ${attack.totalEndpoints}\\n`);\n this.markdownBuffer.push(`- Unprotected: ${attack.unprotected}\\n`);\n this.markdownBuffer.push(`- Risk Score: ${attack.riskScore}/100\\n`);\n break;\n \n case 'report':\n this.markdownBuffer.push(content.content);\n break;\n \n default:\n // Other types are captured in JSON buffer\n this.jsonBuffer.push(content);\n }\n }\n\n /**\n * Route content to JSON buffer\n */\n private routeToJson(content: OutputContent): void {\n this.jsonBuffer.push(content);\n }\n\n /**\n * Capture content in raw log buffer\n */\n private captureRawLog(content: OutputContent): void {\n const time = this.formatTime(content.timestamp);\n const level = content.metadata?.severity ?? content.type;\n let message = '';\n \n switch (content.type) {\n case 'banner':\n message = `[BANNER] ${(content.content as BannerContent).skill}`;\n break;\n case 'activity':\n case 'log':\n message = content.content as string;\n break;\n case 'issue':\n const issue = content.content as Issue;\n message = `[${issue.severity.toUpperCase()}] ${issue.issue}`;\n break;\n default:\n message = `[${content.type.toUpperCase()}] Content received`;\n }\n \n this.rawLogBuffer.push({ time, level, message });\n \n // Keep buffer size reasonable\n if (this.rawLogBuffer.length > 500) {\n this.rawLogBuffer = this.rawLogBuffer.slice(-500);\n }\n }\n\n /**\n * Get raw log buffer for display\n */\n getRawLog(): Array<{ time: string; level: string; message: string }> {\n return [...this.rawLogBuffer];\n }\n\n /**\n * Get accumulated markdown output\n */\n getMarkdown(): string {\n return this.markdownBuffer.join('\\n');\n }\n\n /**\n * Get accumulated JSON output\n */\n getJson(): OutputContent[] {\n return [...this.jsonBuffer];\n }\n\n /**\n * Clear buffers\n */\n clearBuffers(): void {\n this.markdownBuffer = [];\n this.jsonBuffer = [];\n }\n\n // ============================================\n // Convenience methods for common output types\n // ============================================\n\n /**\n * Display a skill banner\n */\n banner(skill: string, art: string, options?: { quote?: string; version?: string }): void {\n this.emit({\n type: 'banner',\n content: { skill, art, quote: options?.quote, version: options?.version } as BannerContent,\n metadata: { agent: skill }\n });\n }\n\n /**\n * Display a code snippet\n */\n snippet(file: string, lines: string[], startLine: number, highlightLine?: number): void {\n this.emit({\n type: 'snippet',\n content: { file, lines, startLine, highlightLine } as SnippetContent,\n metadata: { file }\n });\n }\n\n /**\n * Display cost estimate\n */\n cost(fixNowCost: number, productionCost: number, savings: number, perIssue?: Array<{ issue: string; cost: number }>): void {\n this.emit({\n type: 'cost',\n content: { fixNowCost, productionCost, savings, perIssue } as CostContent\n });\n }\n\n /**\n * Display production readiness\n */\n readiness(\n score: number, \n requirementsMet: number, \n total: number, \n status: 'ready' | 'caution' | 'not-ready',\n requirements?: Array<{ name: string; met: boolean }>\n ): void {\n const content: ReadinessContent = { score, requirementsMet, total, status };\n if (requirements) {\n content.requirements = requirements;\n }\n this.emit({\n type: 'readiness',\n content\n });\n }\n\n /**\n * Display semantic analysis results\n */\n semantic(dataFlowIssues: number, raceConditions: number, authIssues: number): void {\n this.emit({\n type: 'semantic',\n content: { dataFlowIssues, raceConditions, authIssues } as SemanticContent\n });\n }\n\n /**\n * Display attack surface analysis\n */\n attack(totalEndpoints: number, unprotected: number, riskScore: number): void {\n this.emit({\n type: 'attack',\n content: { totalEndpoints, unprotected, riskScore } as AttackSurfaceContent\n });\n }\n\n /**\n * Log an activity message\n */\n activity(message: string): void {\n this.emit({\n type: 'activity',\n content: message\n });\n }\n\n /**\n * Log a message at specified level\n */\n log(level: 'info' | 'warn' | 'error' | 'debug', message: string): void {\n this.emit({\n type: 'log',\n content: message,\n metadata: { severity: level as any }\n });\n }\n\n /**\n * Log info message\n */\n info(message: string): void {\n this.log('info', message);\n }\n\n /**\n * Log warning message\n */\n warn(message: string): void {\n this.log('warn', message);\n }\n\n /**\n * Log error message\n */\n error(message: string): void {\n this.log('error', message);\n }\n\n /**\n * Log debug message\n */\n debug(message: string): void {\n this.log('debug', message);\n }\n\n /**\n * Report an issue\n */\n issue(issue: Issue): void {\n this.emit({\n type: 'issue',\n content: issue,\n metadata: { severity: issue.severity, agent: issue.agent, file: issue.file }\n });\n }\n\n /**\n * Add a report section\n */\n report(content: string): void {\n this.emit({\n type: 'report',\n content\n });\n }\n\n /**\n * Send a proactive notification/nudge to the user\n * This creates a prominent popup in TUI mode or a boxed message in console mode\n */\n nudge(message: string, severity: 'critical' | 'warning' | 'info' = 'warning', file?: string, autoHideMs?: number): void {\n const metadata: { severity?: 'critical' | 'serious' | 'moderate' | 'low'; agent?: string; file?: string } = {};\n // Map nudge severity to issue severity\n if (severity === 'critical') metadata.severity = 'critical';\n else if (severity === 'warning') metadata.severity = 'moderate';\n else metadata.severity = 'low';\n if (file !== undefined) metadata.file = file;\n this.emit({\n type: 'nudge',\n content: { message, severity, file, autoHideMs } as NudgeContent,\n metadata,\n });\n }\n\n // ============================================\n // Helpers\n // ============================================\n\n private formatCurrency(amount: number): string {\n if (amount >= 1000000) return `$${(amount / 1000000).toFixed(2)}M`;\n if (amount >= 1000) return `$${(amount / 1000).toFixed(1)}k`;\n return `$${amount}`;\n }\n\n private formatTime(timestamp?: number): string {\n const date = timestamp ? new Date(timestamp) : new Date();\n return date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n}\n\n// Singleton instance\nlet instance: OutputManagerImpl | null = null;\n\n/**\n * Get the OutputManager instance\n */\nexport function getOutputManager(): OutputManagerImpl {\n if (!instance) {\n instance = new OutputManagerImpl();\n \n // Auto-detect mode based on interactive mode flag\n if (isInteractiveMode()) {\n instance.setMode('tui');\n }\n }\n return instance;\n}\n\n/**\n * Convenience function - shorthand for getOutputManager()\n */\nexport function output(): OutputManagerImpl {\n return getOutputManager();\n}\n\n/**\n * Reset the OutputManager (for testing)\n */\nexport function resetOutputManager(): void {\n instance = null;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/backup-manager.ts","../src/memory/validation.ts"],"sourcesContent":["/**\n * Backup Manager\n * \n * Maintains rotational backups of critical data files.\n * Provides automatic recovery from corrupted files.\n * \n * Features:\n * - N rotational backups (default: 5)\n * - Automatic pruning of old backups\n * - Validation before recovery\n * - Timestamp-based backup naming\n */\n\nimport { copyFile, readdir, unlink, readFile, stat } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { dirname, basename, join } from 'path';\n\nexport interface BackupOptions {\n /**\n * Maximum number of backups to keep\n * @default 5\n */\n maxBackups?: number;\n \n /**\n * Custom validator function for backup validation\n * Returns true if the backup is valid\n */\n validator?: (content: string) => boolean;\n}\n\nexport interface BackupInfo {\n path: string;\n timestamp: number;\n size: number;\n}\n\n/**\n * Manages rotational backups for a file\n * \n * @example\n * ```typescript\n * const manager = new BackupManager('/path/to/issues.json');\n * \n * // Create backup before modifying\n * await manager.createBackup();\n * \n * // If corruption detected, recover\n * if (await manager.recoverFromBackup()) {\n * console.log('Recovered from backup');\n * }\n * ```\n */\nexport class BackupManager {\n private readonly filePath: string;\n private readonly maxBackups: number;\n private readonly validator: ((content: string) => boolean) | undefined;\n private readonly backupDir: string;\n private readonly baseFileName: string;\n\n constructor(filePath: string, options: BackupOptions = {}) {\n this.filePath = filePath;\n this.maxBackups = options.maxBackups ?? 5;\n this.validator = options.validator;\n this.backupDir = dirname(filePath);\n this.baseFileName = basename(filePath);\n }\n\n /**\n * Create a backup of the current file\n * \n * @returns The backup file path, or null if source doesn't exist\n */\n async createBackup(): Promise<string | null> {\n if (!existsSync(this.filePath)) {\n return null;\n }\n\n const timestamp = Date.now();\n const backupPath = this.getBackupPath(timestamp);\n\n await copyFile(this.filePath, backupPath);\n await this.pruneOldBackups();\n\n return backupPath;\n }\n\n /**\n * List all backups sorted by timestamp (newest first)\n */\n async listBackups(): Promise<BackupInfo[]> {\n if (!existsSync(this.backupDir)) {\n return [];\n }\n\n const files = await readdir(this.backupDir);\n const backupPattern = new RegExp(\n `^${this.escapeRegex(this.baseFileName)}\\\\.backup\\\\.(\\\\d+)$`\n );\n\n const backups: BackupInfo[] = [];\n\n for (const file of files) {\n const match = file.match(backupPattern);\n if (match) {\n const timestamp = parseInt(match[1]!, 10);\n const backupPath = join(this.backupDir, file);\n \n try {\n const stats = await stat(backupPath);\n backups.push({\n path: backupPath,\n timestamp,\n size: stats.size,\n });\n } catch {\n // Skip files we can't stat\n }\n }\n }\n\n // Sort by timestamp, newest first\n return backups.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n /**\n * Find the first valid backup\n * \n * Iterates through backups from newest to oldest,\n * returning the first one that passes validation.\n * \n * @returns Path to valid backup, or null if none found\n */\n async findValidBackup(): Promise<string | null> {\n const backups = await this.listBackups();\n\n for (const backup of backups) {\n if (await this.validateBackup(backup.path)) {\n return backup.path;\n }\n }\n\n return null;\n }\n\n /**\n * Validate a backup file\n * \n * If a custom validator was provided, uses that.\n * Otherwise, attempts JSON parse for .json files.\n * \n * @returns true if backup is valid\n */\n async validateBackup(backupPath: string): Promise<boolean> {\n try {\n const content = await readFile(backupPath, 'utf-8');\n\n // Use custom validator if provided\n if (this.validator) {\n return this.validator(content);\n }\n\n // Default validation: check if it's valid JSON for .json files\n if (this.filePath.endsWith('.json')) {\n JSON.parse(content);\n return true;\n }\n\n // For non-JSON files, just check it's readable\n return content.length > 0;\n } catch {\n return false;\n }\n }\n\n /**\n * Recover from the most recent valid backup\n * \n * @returns true if recovery was successful\n */\n async recoverFromBackup(): Promise<boolean> {\n const validBackup = await this.findValidBackup();\n \n if (!validBackup) {\n return false;\n }\n\n await copyFile(validBackup, this.filePath);\n return true;\n }\n\n /**\n * Remove old backups beyond the max limit\n */\n private async pruneOldBackups(): Promise<void> {\n const backups = await this.listBackups();\n\n // Remove backups beyond the limit\n const toRemove = backups.slice(this.maxBackups);\n \n for (const backup of toRemove) {\n try {\n await unlink(backup.path);\n } catch {\n // Ignore errors - backup might already be removed\n }\n }\n }\n\n /**\n * Get the backup path for a given timestamp\n */\n private getBackupPath(timestamp: number): string {\n return join(this.backupDir, `${this.baseFileName}.backup.${timestamp}`);\n }\n\n /**\n * Escape special regex characters in a string\n */\n private escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n }\n\n /**\n * Get the number of existing backups\n */\n async getBackupCount(): Promise<number> {\n const backups = await this.listBackups();\n return backups.length;\n }\n\n /**\n * Get the most recent backup timestamp\n */\n async getLatestBackupTime(): Promise<number | null> {\n const backups = await this.listBackups();\n return backups[0]?.timestamp ?? null;\n }\n\n /**\n * Delete all backups\n */\n async clearBackups(): Promise<number> {\n const backups = await this.listBackups();\n let deleted = 0;\n\n for (const backup of backups) {\n try {\n await unlink(backup.path);\n deleted++;\n } catch {\n // Ignore errors\n }\n }\n\n return deleted;\n }\n}\n\n/**\n * Default JSON validator\n * \n * Validates that content is valid JSON and optionally\n * checks for required fields.\n */\nexport function createJSONValidator(requiredFields?: string[]): (content: string) => boolean {\n return (content: string): boolean => {\n try {\n const parsed = JSON.parse(content);\n \n if (requiredFields && Array.isArray(parsed)) {\n // For arrays, check first element has required fields\n if (parsed.length > 0) {\n const first = parsed[0];\n return requiredFields.every(field => field in first);\n }\n // Empty array is valid\n return true;\n }\n \n if (requiredFields && typeof parsed === 'object' && parsed !== null) {\n return requiredFields.every(field => field in parsed);\n }\n \n return true;\n } catch {\n return false;\n }\n };\n}\n","/**\n * Memory Validation\n * \n * Schema validation for memory storage files using Zod.\n * Catches corruption early and provides clear error messages.\n * \n * Used by:\n * - issue-store.ts for issues.json\n * - global-memory.ts for global-patterns.json\n * - compactor.ts for compacted-summaries.json\n */\n\nimport { z } from 'zod';\n\n// ============================================================================\n// Issue Schemas\n// ============================================================================\n\n/**\n * Schema for a stored issue in issues.json\n */\nexport const StoredIssueSchema = z.object({\n id: z.string(),\n hash: z.string(),\n severity: z.string(),\n issue: z.string(),\n fix: z.string(),\n file: z.string(),\n line: z.number().optional(),\n agent: z.string(),\n category: z.string().optional(),\n timestamp: z.string(),\n project: z.string(),\n resolved: z.boolean().optional(),\n resolvedAt: z.string().optional(),\n});\n\nexport type ValidatedStoredIssue = z.infer<typeof StoredIssueSchema>;\n\n/**\n * Schema for the issues.json file (array of issues)\n */\nexport const IssueIndexSchema = z.array(StoredIssueSchema);\n\n// ============================================================================\n// Global Pattern Schemas\n// ============================================================================\n\n/**\n * Schema for a fix applied record\n */\nexport const FixAppliedSchema = z.object({\n project: z.string(),\n timestamp: z.string(),\n fix: z.string(),\n});\n\n/**\n * Schema for a global pattern in global-patterns.json\n */\nexport const GlobalPatternSchema = z.object({\n id: z.string(),\n pattern: z.string(),\n description: z.string(),\n severity: z.string(),\n agent: z.string(),\n occurrences: z.number(),\n projects: z.array(z.string()),\n firstSeen: z.string(),\n lastSeen: z.string(),\n fixApplied: FixAppliedSchema.optional(),\n});\n\nexport type ValidatedGlobalPattern = z.infer<typeof GlobalPatternSchema>;\n\n/**\n * Schema for global-patterns.json (array of patterns)\n */\nexport const GlobalPatternsIndexSchema = z.array(GlobalPatternSchema);\n\n// ============================================================================\n// Project Summary Schemas\n// ============================================================================\n\n/**\n * Schema for a project summary\n */\nexport const ProjectSummarySchema = z.object({\n name: z.string(),\n path: z.string(),\n lastScan: z.string(),\n healthScore: z.number(),\n totalIssues: z.number(),\n patterns: z.array(z.string()),\n});\n\nexport type ValidatedProjectSummary = z.infer<typeof ProjectSummarySchema>;\n\n// ============================================================================\n// Compacted Summary Schemas\n// ============================================================================\n\n/**\n * Schema for a pattern summary in compacted data\n */\nexport const PatternSummarySchema = z.object({\n pattern: z.string(),\n count: z.number(),\n severity: z.string(),\n agent: z.string(),\n exampleFix: z.string(),\n});\n\n/**\n * Schema for a hot file entry\n */\nexport const HotFileSchema = z.object({\n file: z.string(),\n count: z.number(),\n});\n\n/**\n * Schema for a compacted summary\n */\nexport const CompactedSummarySchema = z.object({\n period: z.string(),\n startDate: z.string(),\n endDate: z.string(),\n totalIssues: z.number(),\n resolvedCount: z.number(),\n bySeverity: z.record(z.string(), z.number()),\n byAgent: z.record(z.string(), z.number()),\n topPatterns: z.array(PatternSummarySchema),\n hotFiles: z.array(HotFileSchema),\n compactedAt: z.string(),\n});\n\nexport type ValidatedCompactedSummary = z.infer<typeof CompactedSummarySchema>;\n\n/**\n * Schema for compacted-summaries.json (array of summaries)\n */\nexport const CompactedSummariesIndexSchema = z.array(CompactedSummarySchema);\n\n// ============================================================================\n// Validation Error\n// ============================================================================\n\n/**\n * Custom error for validation failures\n */\nexport class ValidationError extends Error {\n constructor(\n message: string,\n public readonly zodError: z.ZodError,\n public readonly filePath?: string\n ) {\n super(message);\n this.name = 'ValidationError';\n }\n\n /**\n * Get a human-readable summary of validation errors\n */\n getSummary(): string {\n const issues = this.zodError.issues.slice(0, 5);\n const lines = issues.map(issue => {\n const path = issue.path.join('.');\n return ` - ${path}: ${issue.message}`;\n });\n \n if (this.zodError.issues.length > 5) {\n lines.push(` ... and ${this.zodError.issues.length - 5} more errors`);\n }\n \n return lines.join('\\n');\n }\n}\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validate issue index data\n * \n * @throws ValidationError if data is invalid\n * @returns Validated issue array\n */\nexport function validateIssueIndex(\n data: unknown,\n filePath?: string\n): ValidatedStoredIssue[] {\n const result = IssueIndexSchema.safeParse(data);\n \n if (!result.success) {\n throw new ValidationError(\n `Issue index validation failed${filePath ? ` (${filePath})` : ''}`,\n result.error,\n filePath\n );\n }\n \n return result.data;\n}\n\n/**\n * Validate global patterns data\n * \n * @throws ValidationError if data is invalid\n * @returns Validated patterns array\n */\nexport function validateGlobalPatterns(\n data: unknown,\n filePath?: string\n): ValidatedGlobalPattern[] {\n const result = GlobalPatternsIndexSchema.safeParse(data);\n \n if (!result.success) {\n throw new ValidationError(\n `Global patterns validation failed${filePath ? ` (${filePath})` : ''}`,\n result.error,\n filePath\n );\n }\n \n return result.data;\n}\n\n/**\n * Validate project summary data\n * \n * @throws ValidationError if data is invalid\n * @returns Validated project summary\n */\nexport function validateProjectSummary(\n data: unknown,\n filePath?: string\n): ValidatedProjectSummary {\n const result = ProjectSummarySchema.safeParse(data);\n \n if (!result.success) {\n throw new ValidationError(\n `Project summary validation failed${filePath ? ` (${filePath})` : ''}`,\n result.error,\n filePath\n );\n }\n \n return result.data;\n}\n\n/**\n * Validate compacted summaries data\n * \n * @throws ValidationError if data is invalid\n * @returns Validated summaries array\n */\nexport function validateCompactedSummaries(\n data: unknown,\n filePath?: string\n): ValidatedCompactedSummary[] {\n const result = CompactedSummariesIndexSchema.safeParse(data);\n \n if (!result.success) {\n throw new ValidationError(\n `Compacted summaries validation failed${filePath ? ` (${filePath})` : ''}`,\n result.error,\n filePath\n );\n }\n \n return result.data;\n}\n\n/**\n * Safely parse and validate JSON\n * \n * Combines JSON parsing with schema validation.\n * Returns null on any error instead of throwing.\n */\nexport function safeParseAndValidate<T>(\n content: string,\n schema: z.ZodSchema<T>\n): { success: true; data: T } | { success: false; error: string } {\n try {\n const parsed = JSON.parse(content);\n const result = schema.safeParse(parsed);\n \n if (result.success) {\n return { success: true, data: result.data };\n }\n \n return {\n success: false,\n error: `Validation failed: ${result.error.issues[0]?.message || 'Unknown error'}`,\n };\n } catch (error) {\n return {\n success: false,\n error: `JSON parse failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n };\n }\n}\n\n/**\n * Check if data matches a schema (non-throwing)\n */\nexport function isValidSchema<T>(data: unknown, schema: z.ZodSchema<T>): boolean {\n return schema.safeParse(data).success;\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/guardian/goal-validator.ts"],"sourcesContent":["/**\n * Goal Validator - Helpers for goal tracking\n * \n * Goal detection is handled entirely by the AI watcher in watch.ts.\n * The AI (Anthropic) checks every changed file against user-defined goals,\n * using the Trie's priority scoring for cost control.\n * \n * This module provides:\n * - getActiveGoals: loads active goals for the AI prompt\n * - recordGoalViolationCaught: tracks when a violation is detected\n * - recordGoalViolationFixed: tracks when a violation is auto-fixed\n */\n\nimport type { Goal } from './guardian-state.js';\nimport { getGuardianState } from './guardian-state.js';\n\n/**\n * Get active goals for a project (used by the AI watcher)\n */\nexport async function getActiveGoals(projectPath: string): Promise<Goal[]> {\n const guardianState = getGuardianState(projectPath);\n await guardianState.load();\n return guardianState.getAllGoals().filter(g => g.status === 'active');\n}\n\nexport async function recordGoalViolationCaught(\n goal: Goal,\n file: string,\n projectPath: string\n): Promise<void> {\n const guardianState = getGuardianState(projectPath);\n await guardianState.load();\n \n const metadata = goal.metadata || {};\n const caughtCount = (metadata.caughtCount || 0) + 1;\n \n await guardianState.updateGoal(goal.id, {\n metadata: {\n ...metadata,\n caughtCount,\n lastCaught: new Date().toISOString(),\n lastCaughtFile: file,\n },\n });\n}\n\nexport async function recordGoalViolationFixed(\n goal: Goal,\n file: string,\n projectPath: string\n): Promise<void> {\n const guardianState = getGuardianState(projectPath);\n await guardianState.load();\n \n const metadata = goal.metadata || {};\n const caughtCount = (metadata.caughtCount || 0) + 1;\n const fixedCount = (metadata.fixedCount || 0) + 1;\n \n await guardianState.updateGoal(goal.id, {\n metadata: {\n ...metadata,\n caughtCount,\n fixedCount,\n lastFixed: new Date().toISOString(),\n lastFixedFile: file,\n },\n });\n \n if (goal.type === 'reduction') {\n const newValue = Math.max(0, goal.currentValue - 1);\n await guardianState.updateGoal(goal.id, {\n currentValue: newValue,\n });\n \n if (newValue <= goal.target) {\n await guardianState.updateGoal(goal.id, {\n status: 'achieved',\n achievedAt: new Date().toISOString(),\n });\n }\n }\n}\n\n/**\n * Manually check files against goals\n * Returns violations found\n * \n * NOW WITH CACHING: Uses CodebaseIndex to avoid re-scanning unchanged files\n */\nexport async function checkFilesForGoalViolations(\n goals: Goal[],\n projectPath: string,\n filesToCheck?: string[],\n onProgress?: (message: string) => void\n): Promise<Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }>> {\n // Import AI client and codebase index\n const { isAIAvailable, runAIAnalysis } = await import('../ai/client.js');\n const { CodebaseIndex } = await import('../context/codebase-index.js');\n \n if (!isAIAvailable()) {\n throw new Error('AI not available - ANTHROPIC_API_KEY not set');\n }\n \n // Initialize codebase index for caching\n const codebaseIndex = new CodebaseIndex(projectPath);\n \n // Check if index needs to be built\n if (codebaseIndex.isEmpty()) {\n onProgress?.('Building codebase index (first-time, may take a minute)...');\n console.error('[Goal Check] Codebase index is empty - building index first...');\n console.error('[Goal Check] This is a one-time operation. Future checks will be much faster.');\n \n // Auto-index the codebase\n const { glob } = await import('glob');\n const indexPattern = `${projectPath}/**/*.{ts,tsx,js,jsx,mjs,vue,svelte,astro,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html}`;\n const indexFiles = await glob(indexPattern, {\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.trie/**', '**/coverage/**'],\n nodir: true,\n });\n \n let indexed = 0;\n const total = Math.min(indexFiles.length, 500); // Cap at 500 files for initial index\n for (const filePath of indexFiles.slice(0, 500)) {\n let relativePath = filePath;\n if (filePath.toLowerCase().startsWith(projectPath.toLowerCase() + '/')) {\n relativePath = filePath.slice(projectPath.length + 1);\n }\n const result = await codebaseIndex.indexFile(relativePath);\n if (result) indexed++;\n \n // Progress indicator every 50 files\n if (indexed % 50 === 0) {\n onProgress?.(`Indexing files (${indexed}/${total})...`);\n console.error(`[Goal Check] Indexed ${indexed}/${total} files...`);\n }\n }\n \n await codebaseIndex.save();\n console.error(`[Goal Check] Index built: ${indexed} files indexed`);\n }\n \n // Get files to check\n let files: string[] = [];\n if (filesToCheck && filesToCheck.length > 0) {\n files = filesToCheck;\n } else {\n // MANUAL CHECK MODE: Scan ALL relevant files, not just recently modified\n const { glob } = await import('glob');\n \n const pattern = `${projectPath}/**/*.{ts,tsx,js,jsx,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html,vue,svelte}`;\n const allFiles = await glob(pattern, {\n ignore: ['**/node_modules/**', '**/dist/**', '**/build/**', '**/.git/**', '**/.trie/**', '**/coverage/**'],\n nodir: true,\n });\n \n // For manual checks, use more files but still reasonable limit\n // Sort by modification time to prioritize recently modified\n const { stat } = await import('fs/promises');\n const withStats = await Promise.all(\n allFiles.map(async (f) => {\n try {\n const stats = await stat(f);\n return { file: f, mtime: stats.mtime.getTime() };\n } catch {\n return null;\n }\n })\n );\n \n files = withStats\n .filter((f): f is { file: string; mtime: number } => f !== null)\n .sort((a, b) => b.mtime - a.mtime)\n .slice(0, 100) // Check up to 100 files for manual scans\n .map(f => f.file);\n }\n \n if (files.length === 0) {\n throw new Error('No files found to check');\n }\n \n // Check which files need scanning vs can use cached results\n const filesToScan: string[] = [];\n const cachedViolations: Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }> = [];\n \n for (const filePath of files) {\n // Handle case-insensitive filesystems (macOS) and ensure we get a proper relative path\n let relativePath = filePath;\n if (filePath.toLowerCase().startsWith(projectPath.toLowerCase() + '/')) {\n relativePath = filePath.slice(projectPath.length + 1);\n } else if (filePath.startsWith('/')) {\n // Already absolute but doesn't match projectPath - skip this file\n // This can happen with stale cache entries from different projects\n continue;\n }\n const hasChanged = await codebaseIndex.hasChanged(relativePath);\n \n if (hasChanged) {\n // File changed or not indexed - needs scanning\n // Try to index the file first; skip if it doesn't exist\n const indexed = await codebaseIndex.indexFile(relativePath);\n if (indexed) {\n filesToScan.push(filePath);\n }\n // If indexFile returns null, file doesn't exist - skip it silently\n } else {\n // File unchanged - check cache for each goal\n for (const goal of goals) {\n const cached = codebaseIndex.getCachedViolations(relativePath, goal.id);\n if (cached && cached.length > 0) {\n const violation = cached[0];\n if (violation && violation.found) {\n cachedViolations.push({\n file: relativePath,\n message: `Goal \"${goal.description}\" violated in ${relativePath}: ${violation.details || 'Violation found'} [${violation.confidence || 90}% confidence] (cached)`,\n severity: 'warning',\n });\n }\n } else {\n // No cache for this goal - needs scanning\n if (!filesToScan.includes(filePath)) {\n filesToScan.push(filePath);\n }\n }\n }\n }\n }\n \n onProgress?.(`Checking ${filesToScan.length} files for violations...`);\n console.error(`[Goal Check] ${files.length} files total, ${filesToScan.length} need scanning, ${files.length - filesToScan.length} using cache`);\n \n // Process files that need scanning in batches\n const allViolations: Array<{ file: string; message: string; severity: 'critical' | 'warning' | 'info' }> = [...cachedViolations];\n \n if (filesToScan.length === 0) {\n // All results from cache!\n await codebaseIndex.save();\n return allViolations;\n }\n \n // For large file sets, process in batches to avoid token limits\n const BATCH_SIZE = 25; // Process 25 files at a time\n \n const totalBatches = Math.ceil(filesToScan.length / BATCH_SIZE);\n for (let batchStart = 0; batchStart < filesToScan.length; batchStart += BATCH_SIZE) {\n const batchNum = Math.floor(batchStart / BATCH_SIZE) + 1;\n onProgress?.(`Analyzing files (batch ${batchNum}/${totalBatches})...`);\n const batchFiles = filesToScan.slice(batchStart, batchStart + BATCH_SIZE);\n \n // Read file contents for this batch\n const { readFile } = await import('fs/promises');\n const fileContents = await Promise.all(\n batchFiles.map(async (filePath) => {\n try {\n const content = await readFile(filePath, 'utf-8');\n const relativePath = filePath.replace(projectPath + '/', '');\n return {\n path: relativePath,\n content: content.slice(0, 10000), // Increased limit for manual checks\n };\n } catch {\n return null;\n }\n })\n );\n \n const validFiles = fileContents.filter((f): f is { path: string; content: string } => f !== null);\n \n if (validFiles.length === 0) continue;\n \n // Build files block for AI\n const filesBlock = validFiles\n .map(f => `--- ${f.path} ---\\n${f.content}`)\n .join('\\n\\n');\n \n // Build goals section\n const goalsSection = `\nUSER-DEFINED GOALS (check EVERY file against ALL goals):\n${goals.map((g, i) => ` ${i + 1}. \"${g.description}\"`).join('\\n')}\n\nThis is a MANUAL CHECK requested by the user. Report ALL goal violations you find.\nFor emoji detection, look for Unicode emoji characters.\n`;\n \n // Run AI analysis\n const result = await runAIAnalysis({\n systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.\n${goalsSection}\nReply ONLY with a JSON array. Each element must have:\n- \"file\": relative file path\n- \"severity\": \"critical\" | \"major\" | \"minor\"\n- \"description\": 1-sentence description of the goal violation with specific examples\n- \"confidence\": number 0-100, how confident you are this is a violation\n- \"isGoalViolation\": true (always true for this scan)\n- \"goalIndex\": 0-based index of the violated goal\n\nCRITICAL DETECTION RULES:\n\n**EMOJIS**: Any Unicode emoji characters including but not limited to:\n- Emoticons: 😀😃😄😊🙂🙃😉😇🥰😍🤩😘😗☺️😚😙🥲\n- Symbols: ⚡️⚠️✅❌➜→←↑↓►◄▲▼★☆●○◆◇■□▪️▫️\n- Objects: 📊📈📉💻🖥️📱⌨️🖱️💾💿📀🔧🔨⚙️🛠️\n- Actions: 🔥💪👍👎👏🙌🤝✊👊🎯🎉🎊🚀\n- Weather: ☀️🌤️⛅☁️🌦️🌧️⛈️🌩️🌨️❄️\n- ALL OTHER Unicode emoji in ranges U+1F300-U+1F9FF, U+2600-U+27BF, U+2B00-U+2BFF\n\n**COLORS**: For \"purple\" or \"gradient\" goals, check:\n- CSS: purple, #purple, hsl(purple), rgb(purple), violet, #8B00FF, #9B59D6, etc.\n- Gradients: linear-gradient, radial-gradient, conic-gradient, background-image with gradients\n- Tailwind: purple-*, violet-*, bg-gradient-*\n- Styled components or CSS-in-JS with purple/violet/gradient\n\nBe EXTREMELY thorough. Check:\n1. String literals and template literals\n2. JSX/HTML content\n3. CSS files and style blocks\n4. Comments (emojis in comments still violate \"no emojis\")\n5. console.log statements\n6. Component names, variable names (if they contain emojis)\n\nIf a goal says \"no emojis\" and you see ANY emoji ANYWHERE in the file, report it.\nIf a goal says \"no console.log\" and you see console.log ANYWHERE, report it.\nIf a goal says \"no purple/gradient\" and you see ANY purple color or gradient, report it.\n\nIf no violations found, reply with: []\nOutput ONLY the JSON array, no markdown fences, no commentary.`,\n userPrompt: `Check these ${validFiles.length} files for goal violations:\\n\\n${filesBlock}`,\n maxTokens: 8192, // Increased for larger codebases\n temperature: 0.1,\n });\n \n // Parse response\n let issues: Array<{\n file: string;\n severity: 'critical' | 'major' | 'minor';\n description: string;\n confidence: number;\n isGoalViolation: boolean;\n goalIndex?: number;\n }> = [];\n \n try {\n const cleaned = result.content.replace(/```json?\\n?|\\n?```/g, '').trim();\n issues = JSON.parse(cleaned);\n if (!Array.isArray(issues)) issues = [];\n } catch {\n // Parse failed - continue to next batch\n continue;\n }\n \n // Convert to violation format and record\n for (const issue of issues) {\n if (!issue.isGoalViolation || issue.confidence < 50) continue;\n if (issue.goalIndex == null || issue.goalIndex < 0 || issue.goalIndex >= goals.length) continue;\n \n const goal = goals[issue.goalIndex]!;\n const severity = issue.severity === 'critical' ? 'critical' : 'warning';\n const message = `Goal \"${goal.description}\" violated in ${issue.file}: ${issue.description} [${issue.confidence}% confidence]`;\n \n allViolations.push({\n file: issue.file,\n message,\n severity,\n });\n \n // Cache the result in codebase index\n codebaseIndex.recordViolation(\n issue.file,\n goal.id,\n goal.description,\n true, // found\n issue.description,\n issue.confidence\n );\n \n // Record violation\n await recordGoalViolationCaught(goal, issue.file, projectPath);\n }\n \n // Also record \"no violation\" for scanned files\n for (const file of validFiles) {\n for (const goal of goals) {\n const hasViolation = issues.some(i => i.file === file.path && i.goalIndex === goals.indexOf(goal));\n if (!hasViolation) {\n codebaseIndex.recordViolation(\n file.path,\n goal.id,\n goal.description,\n false, // not found\n undefined,\n 100\n );\n }\n }\n }\n }\n \n // Save updated index\n await codebaseIndex.save();\n \n return allViolations;\n}\n"],"mappings":"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","names":[]}
@@ -1,27 +0,0 @@
1
- import {
2
- GuardianAgent,
3
- getGuardian
4
- } from "./chunk-T62V4H5O.js";
5
- import "./chunk-T4THB2OR.js";
6
- import "./chunk-LRQV7SGQ.js";
7
- import "./chunk-4YJ6KLGI.js";
8
- import "./chunk-3DPVJQNM.js";
9
- import "./chunk-JCU6REX7.js";
10
- import "./chunk-JAKMZI5S.js";
11
- import "./chunk-UHMMANC2.js";
12
- import "./chunk-WS6OA7H6.js";
13
- import "./chunk-F4NJ4CBP.js";
14
- import "./chunk-IXO4G4D3.js";
15
- import "./chunk-6NLHFIYA.js";
16
- import "./chunk-Z4DN527J.js";
17
- import "./chunk-55CBWOEZ.js";
18
- import "./chunk-PEJEYWVR.js";
19
- import "./chunk-43X6JBEM.js";
20
- import "./chunk-45Y5TLQZ.js";
21
- import "./chunk-APMV77PU.js";
22
- import "./chunk-DGUM43GV.js";
23
- export {
24
- GuardianAgent,
25
- getGuardian
26
- };
27
- //# sourceMappingURL=guardian-agent-3EUJUAJ2.js.map
@@ -1,17 +0,0 @@
1
- import {
2
- appendIssuesToLedger,
3
- computeMerkleRoot,
4
- getLedgerBlocks,
5
- verifyLedger
6
- } from "./chunk-PEJEYWVR.js";
7
- import "./chunk-43X6JBEM.js";
8
- import "./chunk-45Y5TLQZ.js";
9
- import "./chunk-APMV77PU.js";
10
- import "./chunk-DGUM43GV.js";
11
- export {
12
- appendIssuesToLedger,
13
- computeMerkleRoot,
14
- getLedgerBlocks,
15
- verifyLedger
16
- };
17
- //# sourceMappingURL=ledger-WKVJWHBX.js.map