@triedotdev/mcp 1.0.164 → 1.0.165

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 (62) hide show
  1. package/README.md +16 -2
  2. package/dist/{chunk-62JD7MIS.js → chunk-5LRDF2WB.js} +15 -35
  3. package/dist/chunk-5LRDF2WB.js.map +1 -0
  4. package/dist/{chunk-D6E4Q4I6.js → chunk-CDG2GVBP.js} +279 -57
  5. package/dist/chunk-CDG2GVBP.js.map +1 -0
  6. package/dist/{chunk-5BYSJ7XT.js → chunk-GTKYBOXL.js} +13 -2
  7. package/dist/{chunk-5BYSJ7XT.js.map → chunk-GTKYBOXL.js.map} +1 -1
  8. package/dist/{chunk-ACU3IXZG.js → chunk-HC5P6FZD.js} +7 -7
  9. package/dist/{chunk-HFVPHQL3.js → chunk-IPNPHPNN.js} +9 -9
  10. package/dist/{chunk-OKK4QNK3.js → chunk-IS5UBN2R.js} +86 -12
  11. package/dist/chunk-IS5UBN2R.js.map +1 -0
  12. package/dist/{chunk-LLDZDU2Y.js → chunk-LR5M4RTN.js} +79 -1
  13. package/dist/chunk-LR5M4RTN.js.map +1 -0
  14. package/dist/{chunk-ERMLZJTK.js → chunk-M7HMBZ3R.js} +13 -13
  15. package/dist/chunk-OBQ74FOU.js +27 -0
  16. package/dist/chunk-OBQ74FOU.js.map +1 -0
  17. package/dist/{chunk-5TRCQAOE.js → chunk-RQ6QZBIN.js} +16 -5
  18. package/dist/chunk-RQ6QZBIN.js.map +1 -0
  19. package/dist/{chunk-IRZXBQVQ.js → chunk-SS2O3MTC.js} +134 -101
  20. package/dist/chunk-SS2O3MTC.js.map +1 -0
  21. package/dist/{chunk-LR46VMIE.js → chunk-WRYQHVPD.js} +5 -5
  22. package/dist/{chunk-Y4B3VEL7.js → chunk-YAL3SUBG.js} +435 -202
  23. package/dist/chunk-YAL3SUBG.js.map +1 -0
  24. package/dist/cli/main.js +215 -57
  25. package/dist/cli/main.js.map +1 -1
  26. package/dist/cli/yolo-daemon.js +15 -14
  27. package/dist/cli/yolo-daemon.js.map +1 -1
  28. package/dist/{fast-analyzer-LLZ6FLP5.js → fast-analyzer-54AHLVO5.js} +3 -3
  29. package/dist/{goal-manager-D6XKE3FY.js → goal-manager-563BNILQ.js} +5 -5
  30. package/dist/{goal-validator-4DDL7NBP.js → goal-validator-FJEDIYU7.js} +5 -5
  31. package/dist/{hypothesis-RI3Q33JB.js → hypothesis-4KC7XRBZ.js} +5 -5
  32. package/dist/index.js +16 -15
  33. package/dist/index.js.map +1 -1
  34. package/dist/{issue-store-DUR5UTYK.js → issue-store-FOS4T736.js} +3 -3
  35. package/dist/{ledger-ZTR63P3L.js → ledger-EDLPF6SB.js} +8 -2
  36. package/dist/project-state-AHPA77SM.js +28 -0
  37. package/dist/server/mcp-server.js +16 -15
  38. package/dist/sync-M2FSWPBC.js +12 -0
  39. package/dist/{tiered-storage-FHHAJR4P.js → tiered-storage-OP74NPJY.js} +2 -2
  40. package/dist/tiered-storage-OP74NPJY.js.map +1 -0
  41. package/dist/{trie-agent-NYSPGZYS.js → trie-agent-TM6ATSNR.js} +12 -12
  42. package/dist/trie-agent-TM6ATSNR.js.map +1 -0
  43. package/package.json +1 -1
  44. package/dist/chunk-5TRCQAOE.js.map +0 -1
  45. package/dist/chunk-62JD7MIS.js.map +0 -1
  46. package/dist/chunk-D6E4Q4I6.js.map +0 -1
  47. package/dist/chunk-IRZXBQVQ.js.map +0 -1
  48. package/dist/chunk-LLDZDU2Y.js.map +0 -1
  49. package/dist/chunk-OKK4QNK3.js.map +0 -1
  50. package/dist/chunk-Y4B3VEL7.js.map +0 -1
  51. /package/dist/{chunk-ACU3IXZG.js.map → chunk-HC5P6FZD.js.map} +0 -0
  52. /package/dist/{chunk-HFVPHQL3.js.map → chunk-IPNPHPNN.js.map} +0 -0
  53. /package/dist/{chunk-ERMLZJTK.js.map → chunk-M7HMBZ3R.js.map} +0 -0
  54. /package/dist/{chunk-LR46VMIE.js.map → chunk-WRYQHVPD.js.map} +0 -0
  55. /package/dist/{fast-analyzer-LLZ6FLP5.js.map → fast-analyzer-54AHLVO5.js.map} +0 -0
  56. /package/dist/{goal-manager-D6XKE3FY.js.map → goal-manager-563BNILQ.js.map} +0 -0
  57. /package/dist/{goal-validator-4DDL7NBP.js.map → goal-validator-FJEDIYU7.js.map} +0 -0
  58. /package/dist/{hypothesis-RI3Q33JB.js.map → hypothesis-4KC7XRBZ.js.map} +0 -0
  59. /package/dist/{issue-store-DUR5UTYK.js.map → issue-store-FOS4T736.js.map} +0 -0
  60. /package/dist/{ledger-ZTR63P3L.js.map → ledger-EDLPF6SB.js.map} +0 -0
  61. /package/dist/{tiered-storage-FHHAJR4P.js.map → project-state-AHPA77SM.js.map} +0 -0
  62. /package/dist/{trie-agent-NYSPGZYS.js.map → sync-M2FSWPBC.js.map} +0 -0
@@ -682,8 +682,19 @@ function getProjectState(projectPath) {
682
682
  }
683
683
  return state;
684
684
  }
685
+ function clearProjectStates() {
686
+ projectStates.clear();
687
+ }
685
688
 
686
689
  export {
687
- getProjectState
690
+ GoalSchema,
691
+ HypothesisSchema,
692
+ RiskBudgetSchema,
693
+ AgentMetricsSchema,
694
+ TimingContextSchema,
695
+ ProjectStateDataSchema,
696
+ ProjectState,
697
+ getProjectState,
698
+ clearProjectStates
688
699
  };
689
- //# sourceMappingURL=chunk-5BYSJ7XT.js.map
700
+ //# sourceMappingURL=chunk-GTKYBOXL.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/agent/project-state.ts"],"sourcesContent":["/**\n * Project State - Persistent state management for Trie\n * \n * Persists to: .trie/memory/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 achievedBy: z.enum(['user', 'agent']).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 validatedBy: z.enum(['user', 'agent']).optional(),\n testCriteria: z.string().optional(),\n category: z.enum(['timing', 'pattern', 'team', 'code', 'general']).optional(),\n autoGenerated: z.boolean().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 project state file\n */\nexport const ProjectStateDataSchema = 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 ProjectStateData = z.infer<typeof ProjectStateDataSchema>;\n\n// ============================================================================\n// ProjectState Class\n// ============================================================================\n\n/**\n * Persistent state manager for project goals, hypotheses, and metrics.\n * \n * Manages goals, hypotheses, risk budget, metrics, and timing context.\n */\nexport class ProjectState {\n private projectPath: string;\n private data: ProjectStateData;\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', 'state.json');\n }\n \n /**\n * Create default state\n */\n private createDefaultState(): ProjectStateData {\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<ProjectStateData> {\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, ProjectStateDataSchema);\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(` 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, ProjectStateDataSchema);\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 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(): ProjectStateData {\n return { ...this.data };\n }\n \n /**\n * Force reload from disk\n */\n async reload(): Promise<ProjectStateData> {\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 projectStates: Map<string, ProjectState> = new Map();\n\n/**\n * Get the ProjectState for a project (singleton per project)\n */\nexport function getProjectState(projectPath: string): ProjectState {\n let state = projectStates.get(projectPath);\n if (!state) {\n state = new ProjectState(projectPath);\n projectStates.set(projectPath, state);\n }\n return state;\n}\n\n/**\n * Clear all ProjectState instances (for testing)\n */\nexport function clearProjectStates(): void {\n projectStates.clear();\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/agent/project-state.ts"],"sourcesContent":["/**\n * Project State - Persistent state management for Trie\n * \n * Persists to: .trie/memory/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 achievedBy: z.enum(['user', 'agent']).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 validatedBy: z.enum(['user', 'agent']).optional(),\n testCriteria: z.string().optional(),\n category: z.enum(['timing', 'pattern', 'team', 'code', 'general']).optional(),\n autoGenerated: z.boolean().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 project state file\n */\nexport const ProjectStateDataSchema = 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 ProjectStateData = z.infer<typeof ProjectStateDataSchema>;\n\n// ============================================================================\n// ProjectState Class\n// ============================================================================\n\n/**\n * Persistent state manager for project goals, hypotheses, and metrics.\n * \n * Manages goals, hypotheses, risk budget, metrics, and timing context.\n */\nexport class ProjectState {\n private projectPath: string;\n private data: ProjectStateData;\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', 'state.json');\n }\n \n /**\n * Create default state\n */\n private createDefaultState(): ProjectStateData {\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<ProjectStateData> {\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, ProjectStateDataSchema);\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(` 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, ProjectStateDataSchema);\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 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(): ProjectStateData {\n return { ...this.data };\n }\n \n /**\n * Force reload from disk\n */\n async reload(): Promise<ProjectStateData> {\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 projectStates: Map<string, ProjectState> = new Map();\n\n/**\n * Get the ProjectState for a project (singleton per project)\n */\nexport function getProjectState(projectPath: string): ProjectState {\n let state = projectStates.get(projectPath);\n if (!state) {\n state = new ProjectState(projectPath);\n projectStates.set(projectPath, state);\n }\n return state;\n}\n\n/**\n * Clear all ProjectState instances (for testing)\n */\nexport function clearProjectStates(): void {\n projectStates.clear();\n}\n"],"mappings":";;;;;;;;;;;;AAcA,SAAS,OAAO,gBAAgB;AAChC,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AAErB,SAAS,SAAS;AAYX,IAAM,aAAa,EAAE,OAAO;AAAA,EACjC,IAAI,EAAE,OAAO;AAAA,EACb,aAAa,EAAE,OAAO;AAAA,EACtB,MAAM,EAAE,KAAK,CAAC,UAAU,aAAa,SAAS,QAAQ,CAAC;AAAA,EACvD,QAAQ,EAAE,OAAO;AAAA,EACjB,QAAQ,EAAE,OAAO;AAAA,EACjB,cAAc,EAAE,OAAO;AAAA,EACvB,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,QAAQ,EAAE,KAAK,CAAC,UAAU,YAAY,UAAU,UAAU,UAAU,CAAC;AAAA,EACrE,eAAe,EAAE,QAAQ;AAAA,EACzB,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAC9C,WAAW,EAAE,OAAO;AAAA,EACpB,WAAW,EAAE,OAAO;AAAA,EACpB,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,YAAY,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EAC/C,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,UAAU,EAAE,KAAK,CAAC,YAAY,WAAW,eAAe,YAAY,SAAS,CAAC,EAAE,SAAS;AAAA,EACzF,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EACvC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AACvC,CAAC;AAOM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,IAAI,EAAE,OAAO;AAAA,EACb,WAAW,EAAE,OAAO;AAAA,EACpB,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA;AAAA,EACnC,QAAQ,EAAE,KAAK,CAAC,YAAY,WAAW,aAAa,eAAe,SAAS,CAAC;AAAA,EAC7E,UAAU,EAAE,MAAM,EAAE,OAAO;AAAA,IACzB,MAAM,EAAE,KAAK,CAAC,cAAc,eAAe,CAAC;AAAA,IAC5C,aAAa,EAAE,OAAO;AAAA,IACtB,WAAW,EAAE,OAAO;AAAA,IACpB,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC5C,CAAC,CAAC;AAAA,EACF,WAAW,EAAE,OAAO;AAAA,EACpB,WAAW,EAAE,OAAO;AAAA,EACpB,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,aAAa,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EAChD,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,UAAU,EAAE,KAAK,CAAC,UAAU,WAAW,QAAQ,QAAQ,SAAS,CAAC,EAAE,SAAS;AAAA,EAC5E,eAAe,EAAE,QAAQ,EAAE,SAAS;AACtC,CAAC;AAOM,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,OAAO,EAAE,OAAO;AAAA,EAChB,QAAQ,EAAE,OAAO;AAAA,EACjB,WAAW,EAAE,OAAO;AAAA,EACpB,cAAc,EAAE,OAAO;AAAA,EACvB,cAAc,EAAE,OAAO;AAAA;AAAA,EACvB,eAAe,EAAE,OAAO;AAAA;AAC1B,CAAC;AAOM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC3C,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC1C,kBAAkB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACzC,oBAAoB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC3C,kBAAkB,EAAE,OAAO;AAAA,EAC3B,oBAAoB,EAAE,OAAO;AAAA,EAC7B,eAAe,EAAE,OAAO;AAAA,EACxB,iBAAiB,EAAE,OAAO;AAAA,EAC1B,mBAAmB,EAAE,OAAO;AAAA,EAC5B,iBAAiB,EAAE,OAAO;AAC5B,CAAC;AAOM,IAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA;AAAA,EACzC,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EACvC,mBAAmB,EAAE,QAAQ;AAAA,EAC7B,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AAAA;AAAA,EAC1C,qBAAqB,EAAE,OAAO;AAAA,EAC9B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,YAAY,EAAE,QAAQ;AAAA;AAAA,EACtB,iBAAiB,EAAE,OAAO,EAAE,SAAS;AACvC,CAAC;AAOM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,SAAS,EAAE,QAAQ,CAAC;AAAA,EACpB,OAAO,EAAE,MAAM,UAAU;AAAA,EACzB,YAAY,EAAE,MAAM,gBAAgB;AAAA,EACpC,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,iBAAiB,EAAE,OAAO;AAAA;AAAA,EAC1B,mBAAmB,EAAE,OAAO,EAAE,SAAS;AAAA,EACvC,aAAa,EAAE,OAAO;AACxB,CAAC;AAaM,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA,SAAkB;AAAA,EAClB,QAAiB;AAAA,EAEzB,YAAY,aAAqB;AAC/B,SAAK,cAAc;AACnB,SAAK,OAAO,KAAK,mBAAmB;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAuB;AAC7B,WAAO,KAAK,iBAAiB,KAAK,WAAW,GAAG,UAAU,YAAY;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAuC;AAC7C,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,QAAQ,IAAI,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAC5C,UAAM,OAAO,KAAK,WAAW,GAAG;AAEhC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,CAAC;AAAA,MACR,YAAY,CAAC;AAAA,MACb,YAAY;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,WAAW;AAAA,QACX,cAAc;AAAA,QACd,cAAc;AAAA,QACd,eAAe;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,QACP,oBAAoB;AAAA;AAAA,QACpB,mBAAmB;AAAA,QACnB,kBAAkB;AAAA,QAClB,oBAAoB;AAAA,QACpB,kBAAkB;AAAA,QAClB,oBAAoB;AAAA,QACpB,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,mBAAmB;AAAA,QACnB,iBAAiB;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,QACN,iBAAiB;AAAA;AAAA,QACjB,eAAe;AAAA;AAAA,QACf,mBAAmB;AAAA,QACnB,UAAU,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA;AAAA,QACxB,qBAAqB,KAAK,IAAI;AAAA,QAC9B,YAAY;AAAA,MACd;AAAA,MACA,iBAAiB;AAAA;AAAA,MACjB,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,MAAoB;AACrC,UAAM,IAAI,IAAI,KAAK,KAAK,IAAI,KAAK,YAAY,GAAG,KAAK,SAAS,GAAG,KAAK,QAAQ,CAAC,CAAC;AAChF,UAAM,SAAS,EAAE,UAAU,KAAK;AAChC,MAAE,WAAW,EAAE,WAAW,IAAI,IAAI,MAAM;AACxC,UAAM,YAAY,IAAI,KAAK,KAAK,IAAI,EAAE,eAAe,GAAG,GAAG,CAAC,CAAC;AAC7D,UAAM,SAAS,KAAK,OAAQ,EAAE,QAAQ,IAAI,UAAU,QAAQ,KAAK,QAAY,KAAK,CAAC;AACnF,WAAO,GAAG,EAAE,eAAe,CAAC,KAAK,OAAO,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAkC;AACtC,QAAI,KAAK,QAAQ;AACf,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,YAAY,KAAK,aAAa;AAEpC,QAAI;AACF,UAAI,WAAW,SAAS,GAAG;AACzB,cAAM,UAAU,MAAM,SAAS,WAAW,OAAO;AACjD,cAAM,SAAS,qBAAqB,SAAS,sBAAsB;AAEnE,YAAI,OAAO,SAAS;AAClB,eAAK,OAAO,OAAO;AACnB,eAAK,SAAS;AAGd,gBAAM,KAAK,qBAAqB;AAEhC,iBAAO,KAAK;AAAA,QACd;AAGA,gBAAQ,MAAM,uBAAuB,OAAO,KAAK,EAAE;AACnD,cAAM,gBAAgB,IAAI,cAAc,SAAS;AAEjD,YAAI,MAAM,cAAc,kBAAkB,GAAG;AAC3C,kBAAQ,MAAM,iCAA4B;AAC1C,gBAAM,YAAY,MAAM,SAAS,WAAW,OAAO;AACnD,gBAAM,kBAAkB,qBAAqB,WAAW,sBAAsB;AAC9E,cAAI,gBAAgB,SAAS;AAC3B,iBAAK,OAAO,gBAAgB;AAC5B,iBAAK,SAAS;AACd,mBAAO,KAAK;AAAA,UACd;AAAA,QACF;AAEA,gBAAQ,MAAM,0CAA0C;AAAA,MAC1D;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,4BAA4B,KAAK,EAAE;AAAA,IACnD;AAEA,SAAK,OAAO,KAAK,mBAAmB;AACpC,SAAK,SAAS;AACd,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,SAAS,KAAK,QAAQ;AAC9B;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,aAAa;AACpC,UAAM,YAAY,KAAK,iBAAiB,KAAK,WAAW,GAAG,QAAQ;AAEnE,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAE1C,UAAM,gBAAgB,IAAI,cAAc,SAAS;AACjD,UAAM,cAAc,aAAa;AAEjC,SAAK,KAAK,eAAc,oBAAI,KAAK,GAAE,YAAY;AAE/C,UAAM,gBAAgB,WAAW,KAAK,IAAI;AAE1C,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAsC;AAClD,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,QAAQ,IAAI,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAC5C,UAAM,OAAO,KAAK,WAAW,GAAG;AAEhC,QAAI,YAAY;AAEhB,QAAI,KAAK,KAAK,WAAW,iBAAiB,OAAO;AAC/C,WAAK,KAAK,WAAW,YAAY;AACjC,WAAK,KAAK,WAAW,eAAe;AACpC,kBAAY;AAAA,IACd;AAEA,QAAI,KAAK,KAAK,WAAW,kBAAkB,MAAM;AAC/C,WAAK,KAAK,WAAW,eAAe;AACpC,WAAK,KAAK,WAAW,gBAAgB;AACrC,kBAAY;AAAA,IACd;AAEA,QAAI,WAAW;AACb,WAAK,QAAQ;AACb,YAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,MAA8B;AAC1C,UAAM,KAAK,KAAK;AAEhB,QAAI,KAAK,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,KAAK,EAAE,GAAG;AAC/C,aAAO;AAAA,IACT;AAEA,SAAK,KAAK,MAAM,KAAK,IAAI;AACzB,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,QAAgB,SAA0C;AACzE,UAAM,KAAK,KAAK;AAEhB,UAAM,OAAO,KAAK,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AACtD,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,IACT;AAEA,WAAO,OAAO,MAAM,SAAS,EAAE,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AACpE,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACvB,WAAO,KAAK,KAAK,MAAM,OAAO,OAAK,EAAE,WAAW,QAAQ;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,cAAsB;AACpB,WAAO,CAAC,GAAG,KAAK,KAAK,KAAK;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,QAAkC;AACxC,WAAO,KAAK,KAAK,MAAM,KAAK,OAAK,EAAE,OAAO,MAAM;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,QAAkC;AACjD,UAAM,KAAK,KAAK;AAEhB,UAAM,QAAQ,KAAK,KAAK,MAAM,UAAU,OAAK,EAAE,OAAO,MAAM;AAC5D,QAAI,UAAU,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,SAAK,KAAK,MAAM,OAAO,OAAO,CAAC;AAC/B,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAgC;AAC9B,WAAO,KAAK,KAAK,MAAM,OAAO,OAAK,EAAE,aAAa;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,QAAgB,QAAmC;AACrE,WAAO,KAAK,WAAW,QAAQ;AAAA,MAC7B,QAAQ,SAAS,WAAW;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cAAc,YAA0C;AAC5D,UAAM,KAAK,KAAK;AAEhB,QAAI,KAAK,KAAK,WAAW,KAAK,OAAK,EAAE,OAAO,WAAW,EAAE,GAAG;AAC1D,aAAO;AAAA,IACT;AAEA,SAAK,KAAK,WAAW,KAAK,UAAU;AACpC,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,cAAsB,SAAgD;AAC3F,UAAM,KAAK,KAAK;AAEhB,UAAM,aAAa,KAAK,KAAK,WAAW,KAAK,OAAK,EAAE,OAAO,YAAY;AACvE,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,WAAO,OAAO,YAAY,SAAS,EAAE,YAAW,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AAC1E,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YACJ,cACA,UACkB;AAClB,UAAM,KAAK,KAAK;AAEhB,UAAM,aAAa,KAAK,KAAK,WAAW,KAAK,OAAK,EAAE,OAAO,YAAY;AACvE,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AAEA,eAAW,SAAS,KAAK;AAAA,MACvB,GAAG;AAAA,MACH,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,CAAC;AAGD,QAAI,WAAW,WAAW,cAAc,WAAW,SAAS,WAAW,GAAG;AACxE,iBAAW,SAAS;AAAA,IACtB;AAGA,UAAM,kBAAkB,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,YAAY,EAAE;AACjF,UAAM,qBAAqB,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,eAAe,EAAE;AACvF,UAAM,QAAQ,kBAAkB;AAEhC,QAAI,QAAQ,GAAG;AACb,iBAAW,aAAa,kBAAkB;AAG1C,UAAI,WAAW,WAAW,WAAW;AACnC,YAAI,WAAW,aAAa,OAAO,mBAAmB,GAAG;AACvD,qBAAW,SAAS;AACpB,qBAAW,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,QAClD,WAAW,WAAW,aAAa,OAAO,sBAAsB,GAAG;AACjE,qBAAW,SAAS;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAEA,eAAW,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC9C,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,sBAAoC;AAClC,WAAO,KAAK,KAAK,WAAW;AAAA,MAAO,OACjC,EAAE,WAAW,cAAc,EAAE,WAAW;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,yBAAuC;AACrC,WAAO,KAAK,KAAK,WAAW,OAAO,OAAK,EAAE,WAAW,WAAW;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAiC;AAC/B,WAAO,CAAC,GAAG,KAAK,KAAK,UAAU;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,cAA8C;AAC1D,WAAO,KAAK,KAAK,WAAW,KAAK,OAAK,EAAE,OAAO,YAAY;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBAA4B;AAC1B,WAAO,EAAE,GAAG,KAAK,KAAK,WAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,QAAkC;AACpD,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,qBAAqB;AAEhC,QAAI,KAAK,KAAK,WAAW,YAAY,SAAS,KAAK,KAAK,WAAW,OAAO;AACxE,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,KAAK,WAAW,eAAe,SAAS,KAAK,KAAK,WAAW,QAAQ;AAC5E,aAAO;AAAA,IACT;AAEA,SAAK,KAAK,WAAW,aAAa;AAClC,SAAK,KAAK,WAAW,gBAAgB;AACrC,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,SAAiB,GAAY;AACzC,WACE,KAAK,KAAK,WAAW,YAAY,UAAU,KAAK,KAAK,WAAW,SAChE,KAAK,KAAK,WAAW,eAAe,UAAU,KAAK,KAAK,WAAW;AAAA,EAEvE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAe,QAA+B;AAChE,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,WAAW,QAAQ;AAC7B,SAAK,KAAK,WAAW,SAAS;AAC9B,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAA2B;AACzB,WAAO,EAAE,GAAG,KAAK,KAAK,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,SAAiC;AACtD,UAAM,KAAK,KAAK;AAEhB,SAAK,KAAK,QAAQ;AAClB,QAAI,SAAS;AACX,WAAK,KAAK,QAAQ;AAAA,IACpB;AAGA,SAAK,KAAK,QAAQ,qBAChB,KAAK,KAAK,QAAQ,qBAAqB,KAAK,KAAK,QAAQ;AAE3D,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,sBAAsB,UAA4D;AACtF,UAAM,KAAK,KAAK;AAEhB,SAAK,KAAK,QAAQ;AAElB,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,aAAK,KAAK,QAAQ;AAClB;AAAA,MACF,KAAK;AACH,aAAK,KAAK,QAAQ;AAClB;AAAA,MACF,KAAK;AACH,aAAK,KAAK,QAAQ;AAClB,aAAK,KAAK,QAAQ;AAClB;AAAA,IACJ;AAGA,QAAI,KAAK,KAAK,QAAQ,gBAAgB,GAAG;AACvC,WAAK,KAAK,QAAQ,mBAChB,KAAK,KAAK,QAAQ,kBAAkB,KAAK,KAAK,QAAQ;AACxD,WAAK,KAAK,QAAQ,oBAChB,KAAK,KAAK,QAAQ,oBAAoB,KAAK,KAAK,QAAQ;AAAA,IAC5D;AAEA,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BAA0C;AAC9C,UAAM,KAAK,KAAK;AAEhB,UAAM,YAAY,KAAK,KAAK,WAAW,OAAO,OAAK,EAAE,WAAW,WAAW,EAAE;AAC7E,UAAM,cAAc,KAAK,KAAK,WAAW,OAAO,OAAK,EAAE,WAAW,aAAa,EAAE;AACjF,UAAM,QAAQ,YAAY;AAE1B,QAAI,QAAQ,GAAG;AACb,WAAK,KAAK,QAAQ,qBAAqB,YAAY;AACnD,WAAK,QAAQ;AACb,YAAM,KAAK,KAAK;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,mBAAkC;AAChC,WAAO,EAAE,GAAG,KAAK,KAAK,OAAO;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACtB,QAAI,CAAC,KAAK,KAAK,OAAO,mBAAmB;AACvC,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,oBAAI,KAAK;AACrB,UAAM,OAAO,IAAI,SAAS;AAC1B,UAAM,QAAQ,KAAK,KAAK,OAAO;AAC/B,UAAM,MAAM,KAAK,KAAK,OAAO;AAG7B,QAAI,QAAQ,KAAK;AACf,aAAO,QAAQ,SAAS,OAAO;AAAA,IACjC;AAGA,WAAO,QAAQ,SAAS,OAAO;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,UAAM,aAAY,oBAAI,KAAK,GAAE,OAAO;AACpC,WAAO,KAAK,KAAK,OAAO,SAAS,SAAS,SAAS;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA0B;AACxB,QAAI,CAAC,KAAK,KAAK,OAAO,YAAY;AAChC,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,KAAK,OAAO,iBAAiB;AACpC,YAAM,QAAQ,IAAI,KAAK,KAAK,KAAK,OAAO,eAAe;AACvD,UAAI,KAAK,IAAI,IAAI,MAAM,QAAQ,GAAG;AAEhC,aAAK,KAAK,OAAO,aAAa;AAC9B,aAAK,KAAK,OAAO,kBAAkB;AACnC,aAAK,QAAQ;AACb,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,SAAkB,OAA6B;AACjE,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,OAAO,aAAa;AAC9B,SAAK,KAAK,OAAO,kBAAkB,OAAO,YAAY;AACtD,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAe,KAAa,UAAmB,MAAqB;AACtF,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,OAAO,kBAAkB;AACnC,SAAK,KAAK,OAAO,gBAAgB;AACjC,SAAK,KAAK,OAAO,oBAAoB;AACrC,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,MAA+B;AAC/C,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,OAAO,WAAW;AAC5B,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAA6B;AACjC,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,OAAO,sBAAsB,KAAK,IAAI;AAChD,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,qBAA6B;AAC3B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAiB,IAA2B;AAChD,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,kBAAkB,KAAK,IAAI,KAAO,EAAE;AAC9C,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAA4B;AAChC,UAAM,KAAK,KAAK;AAChB,SAAK,KAAK,oBAAoB,KAAK,IAAI;AACvC,SAAK,QAAQ;AACb,UAAM,KAAK,KAAK;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,uBAA2C;AACzC,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAA4B;AAC1B,WAAO,EAAE,GAAG,KAAK,KAAK;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAoC;AACxC,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AACF;AAMA,IAAM,gBAA2C,oBAAI,IAAI;AAKlD,SAAS,gBAAgB,aAAmC;AACjE,MAAI,QAAQ,cAAc,IAAI,WAAW;AACzC,MAAI,CAAC,OAAO;AACV,YAAQ,IAAI,aAAa,WAAW;AACpC,kBAAc,IAAI,aAAa,KAAK;AAAA,EACtC;AACA,SAAO;AACT;AAKO,SAAS,qBAA2B;AACzC,gBAAc,MAAM;AACtB;","names":[]}
@@ -1,9 +1,9 @@
1
- import {
2
- getProjectState
3
- } from "./chunk-5BYSJ7XT.js";
4
1
  import {
5
2
  searchIssues
6
- } from "./chunk-IRZXBQVQ.js";
3
+ } from "./chunk-SS2O3MTC.js";
4
+ import {
5
+ getProjectState
6
+ } from "./chunk-GTKYBOXL.js";
7
7
 
8
8
  // src/agent/goal-validator.ts
9
9
  async function getActiveGoals(projectPath) {
@@ -38,9 +38,9 @@ async function recordGoalViolationFixed(goal, file, projectPath) {
38
38
  lastFixedFile: file
39
39
  }
40
40
  });
41
- const { resolveGoalViolation } = await import("./issue-store-DUR5UTYK.js");
41
+ const { resolveGoalViolation } = await import("./issue-store-FOS4T736.js");
42
42
  await resolveGoalViolation(file, goal.description, projectPath);
43
- const { getGoalManager } = await import("./goal-manager-D6XKE3FY.js");
43
+ const { getGoalManager } = await import("./goal-manager-563BNILQ.js");
44
44
  const goalManager = getGoalManager(projectPath);
45
45
  await goalManager.updateGoalProgress();
46
46
  }
@@ -351,4 +351,4 @@ export {
351
351
  measureInitialGoalValue,
352
352
  checkFilesForGoalViolations
353
353
  };
354
- //# sourceMappingURL=chunk-ACU3IXZG.js.map
354
+ //# sourceMappingURL=chunk-HC5P6FZD.js.map
@@ -1,23 +1,23 @@
1
+ import {
2
+ scanForVulnerabilities
3
+ } from "./chunk-SY6KQG44.js";
4
+ import {
5
+ scanForVibeCodeIssues
6
+ } from "./chunk-OMR4YCBS.js";
1
7
  import {
2
8
  getStorage
3
- } from "./chunk-LLDZDU2Y.js";
9
+ } from "./chunk-LR5M4RTN.js";
4
10
  import {
5
11
  tryGetClient
6
12
  } from "./chunk-FQ45QP5A.js";
7
13
  import {
8
14
  searchIssues
9
- } from "./chunk-IRZXBQVQ.js";
15
+ } from "./chunk-SS2O3MTC.js";
10
16
  import {
11
17
  BackupManager,
12
18
  GlobalPatternsIndexSchema,
13
19
  safeParseAndValidate
14
20
  } from "./chunk-EFWVF6TI.js";
15
- import {
16
- scanForVulnerabilities
17
- } from "./chunk-SY6KQG44.js";
18
- import {
19
- scanForVibeCodeIssues
20
- } from "./chunk-OMR4YCBS.js";
21
21
  import {
22
22
  atomicWriteJSON
23
23
  } from "./chunk-43X6JBEM.js";
@@ -821,4 +821,4 @@ export {
821
821
  SlackIntegration,
822
822
  GotchaPredictor
823
823
  };
824
- //# sourceMappingURL=chunk-HFVPHQL3.js.map
824
+ //# sourceMappingURL=chunk-IPNPHPNN.js.map
@@ -43,16 +43,18 @@ import {
43
43
  getPrompt,
44
44
  getSystemPrompt,
45
45
  handleCheckpointTool
46
- } from "./chunk-D6E4Q4I6.js";
46
+ } from "./chunk-CDG2GVBP.js";
47
47
  import {
48
48
  CodebaseIndex
49
49
  } from "./chunk-Q5EKA5YA.js";
50
50
  import {
51
- exportToJson,
52
51
  formatFriendlyError,
53
- importFromJson,
54
52
  isTrieInitialized
55
- } from "./chunk-62JD7MIS.js";
53
+ } from "./chunk-5LRDF2WB.js";
54
+ import {
55
+ exportToJson,
56
+ importFromJson
57
+ } from "./chunk-OBQ74FOU.js";
56
58
  import {
57
59
  loadConfig
58
60
  } from "./chunk-GDWA3CH3.js";
@@ -61,13 +63,13 @@ import {
61
63
  getGlobalMemoryStats,
62
64
  listTrackedProjects,
63
65
  searchGlobalPatterns
64
- } from "./chunk-HFVPHQL3.js";
65
- import {
66
- getStorage
67
- } from "./chunk-LLDZDU2Y.js";
66
+ } from "./chunk-IPNPHPNN.js";
68
67
  import {
69
68
  ContextGraph
70
69
  } from "./chunk-VUL52BQL.js";
70
+ import {
71
+ getStorage
72
+ } from "./chunk-LR5M4RTN.js";
71
73
  import {
72
74
  findSimilarIssues,
73
75
  getMemoryStats,
@@ -75,10 +77,10 @@ import {
75
77
  markIssueResolved,
76
78
  purgeIssues,
77
79
  searchIssues
78
- } from "./chunk-IRZXBQVQ.js";
80
+ } from "./chunk-SS2O3MTC.js";
79
81
  import {
80
82
  runShellCommandSync
81
- } from "./chunk-Y4B3VEL7.js";
83
+ } from "./chunk-YAL3SUBG.js";
82
84
  import {
83
85
  getTrieDirectory,
84
86
  getWorkingDirectory
@@ -1522,8 +1524,14 @@ var TrieMemorySearchTool = class {
1522
1524
  case "purge":
1523
1525
  resultText = await this.handlePurge(params, workDir);
1524
1526
  break;
1527
+ case "nudges":
1528
+ resultText = await this.handleNudges(params, workDir);
1529
+ break;
1530
+ case "clear-nudges":
1531
+ resultText = await this.handleClearNudges(params, workDir);
1532
+ break;
1525
1533
  default:
1526
- resultText = "Unknown action. Use: search, stats, recent, similar, resolve, global, or purge";
1534
+ resultText = "Unknown action. Use: search, stats, recent, similar, resolve, global, purge, nudges, or clear-nudges";
1527
1535
  }
1528
1536
  return {
1529
1537
  content: [{
@@ -1821,6 +1829,72 @@ var TrieMemorySearchTool = class {
1821
1829
  lines.push("", "**Note:** Compacted historical summaries were preserved for trend analysis.");
1822
1830
  return lines.join("\n");
1823
1831
  }
1832
+ async handleNudges(params, workDir) {
1833
+ const storage = getStorage(workDir);
1834
+ await storage.initialize();
1835
+ const queryParams = {
1836
+ limit: params.limit || 20
1837
+ };
1838
+ if (!params.includeResolved) {
1839
+ queryParams.resolved = false;
1840
+ }
1841
+ const nudges = await storage.queryNudges(queryParams);
1842
+ if (nudges.length === 0) {
1843
+ return params.includeResolved ? "No nudges found in storage." : "No unresolved nudges. All clear!";
1844
+ }
1845
+ const lines = [
1846
+ "# Nudges (Goal Violations & Alerts)",
1847
+ "",
1848
+ `Found ${nudges.length} nudge(s):`,
1849
+ ""
1850
+ ];
1851
+ for (const nudge of nudges) {
1852
+ const status = nudge.resolved ? ` [${nudge.resolution || "RESOLVED"}]` : "";
1853
+ const severity = nudge.severity.toUpperCase();
1854
+ lines.push(
1855
+ `## [${severity}]${status} ${nudge.message.slice(0, 80)}${nudge.message.length > 80 ? "..." : ""}`,
1856
+ "",
1857
+ `- **ID:** \`${nudge.id}\``,
1858
+ nudge.file ? `- **File:** \`${nudge.file}\`` : "",
1859
+ `- **Time:** ${new Date(nudge.timestamp).toLocaleString()}`,
1860
+ nudge.suggestedAction ? `- **Suggested:** ${nudge.suggestedAction}` : "",
1861
+ ""
1862
+ );
1863
+ }
1864
+ lines.push(
1865
+ "---",
1866
+ "",
1867
+ "**Actions:**",
1868
+ "- `trie_memory action:clear-nudges nudgeId:<id>` - Dismiss a specific nudge",
1869
+ "- `trie_memory action:clear-nudges clearAll:true` - Clear all nudges",
1870
+ '- `trie_memory action:clear-nudges pattern:"<text>"` - Clear nudges matching pattern'
1871
+ );
1872
+ return lines.join("\n");
1873
+ }
1874
+ async handleClearNudges(params, workDir) {
1875
+ const storage = getStorage(workDir);
1876
+ await storage.initialize();
1877
+ if (params.clearAll) {
1878
+ await storage.clearAllNudges();
1879
+ return "\u2713 All nudges have been cleared.";
1880
+ }
1881
+ if (params.nudgeId) {
1882
+ await storage.dismissNudge(params.nudgeId);
1883
+ return `\u2713 Nudge \`${params.nudgeId}\` has been dismissed.`;
1884
+ }
1885
+ if (params.pattern) {
1886
+ const count = await storage.resolveNudgesByPattern(params.pattern, "dismissed");
1887
+ return count > 0 ? `\u2713 Cleared ${count} nudge(s) matching "${params.pattern}".` : `No nudges found matching "${params.pattern}".`;
1888
+ }
1889
+ return [
1890
+ "Missing parameter. Specify one of:",
1891
+ "- `nudgeId` - ID of specific nudge to dismiss",
1892
+ "- `clearAll: true` - Clear all nudges",
1893
+ "- `pattern` - Clear nudges matching text pattern",
1894
+ "",
1895
+ "Use `trie_memory action:nudges` to list current nudges and their IDs."
1896
+ ].join("\n");
1897
+ }
1824
1898
  };
1825
1899
 
1826
1900
  // src/tools/reconcile.ts
@@ -4028,4 +4102,4 @@ export {
4028
4102
  MCPServer,
4029
4103
  startServer
4030
4104
  };
4031
- //# sourceMappingURL=chunk-OKK4QNK3.js.map
4105
+ //# sourceMappingURL=chunk-IS5UBN2R.js.map