@iservu-inc/adf-cli 0.9.1 → 0.11.0

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.
@@ -0,0 +1,526 @@
1
+ # Pattern Decay Algorithm Design
2
+
3
+ **Phase:** 6 - Advanced Learning Features
4
+ **Component:** Pattern Decay System
5
+ **Version:** 1.0
6
+ **Date:** 2025-10-26
7
+ **Status:** Design Complete
8
+
9
+ ---
10
+
11
+ ## 🎯 Goal
12
+
13
+ Reduce confidence scores over time for inactive patterns to keep learning data fresh and relevant, preventing stale patterns from affecting interview filtering.
14
+
15
+ ---
16
+
17
+ ## 📊 Problem Statement
18
+
19
+ **Current Issue:**
20
+ - Patterns remain at high confidence indefinitely
21
+ - Old patterns may no longer reflect user preferences
22
+ - User workflows change over time (e.g., prototypes → production apps)
23
+ - No mechanism to "forget" outdated patterns
24
+ - Stale patterns can cause incorrect filtering
25
+
26
+ **Example Scenarios:**
27
+
28
+ **Scenario 1: Workflow Change**
29
+ - User builds prototypes for 3 months → skips deployment questions (pattern: 90% confidence)
30
+ - User switches to production apps → needs deployment questions
31
+ - Old pattern still active → incorrectly filters deployment questions
32
+ - **Solution:** Pattern confidence decays, eventually removed
33
+
34
+ **Scenario 2: Team Growth**
35
+ - Solo developer → skips collaboration questions (pattern: 85% confidence)
36
+ - Hires team → needs collaboration questions
37
+ - Old pattern persists → filters important questions
38
+ - **Solution:** Pattern confidence reduces over 2-3 months
39
+
40
+ ---
41
+
42
+ ## 🏗️ Algorithm Design
43
+
44
+ ### Decay Formula
45
+
46
+ **Time-Based Exponential Decay:**
47
+
48
+ ```
49
+ newConfidence = currentConfidence × (1 - decayRate)^monthsInactive
50
+
51
+ Where:
52
+ - currentConfidence: Current pattern confidence (0-100)
53
+ - decayRate: Monthly decay rate (default 0.15 = 15% reduction per month)
54
+ - monthsInactive: Months since lastSeen timestamp
55
+ ```
56
+
57
+ **Alternative: Linear Decay (Simpler)**
58
+
59
+ ```
60
+ newConfidence = currentConfidence - (decayRate × monthsInactive)
61
+
62
+ Where:
63
+ - decayRate: Points to reduce per month (default 10 points/month)
64
+ ```
65
+
66
+ **Recommendation:** Use exponential decay for natural forgetting curve.
67
+
68
+ ### Decay Rates by Confidence Level
69
+
70
+ Different decay rates based on initial confidence:
71
+
72
+ ```javascript
73
+ function getDecayRate(confidence, baseRate = 0.15) {
74
+ if (confidence >= 90) return baseRate * 0.5; // High confidence decays slower (7.5%/month)
75
+ if (confidence >= 75) return baseRate; // Medium confidence decays normally (15%/month)
76
+ return baseRate * 1.5; // Low confidence decays faster (22.5%/month)
77
+ }
78
+ ```
79
+
80
+ **Rationale:**
81
+ - High-confidence patterns (90%+) are strong signals → decay slower
82
+ - Low-confidence patterns (<75%) are weak signals → decay faster
83
+ - Natural forgetting: stronger memories fade slower
84
+
85
+ ---
86
+
87
+ ## 📐 Data Structure Changes
88
+
89
+ ### Pattern Data Structure (Enhanced)
90
+
91
+ ```json
92
+ {
93
+ "id": "pattern_001",
94
+ "type": "consistent_skip",
95
+ "questionId": "q_deployment_host",
96
+ "confidence": 90,
97
+ "initialConfidence": 90,
98
+ "sessionsAnalyzed": 10,
99
+ "skipCount": 9,
100
+ "status": "active",
101
+ "userApproved": true,
102
+ "createdAt": "2025-09-01T10:00:00Z",
103
+ "lastSeen": "2025-10-26T15:30:00Z",
104
+ "lastDecayCalculation": "2025-10-26T15:30:00Z",
105
+ "decayRate": 0.15,
106
+ "timesRenewed": 0
107
+ }
108
+ ```
109
+
110
+ **New Fields:**
111
+ - `createdAt`: When pattern was first detected
112
+ - `lastSeen`: Last time pattern was observed (skip event matching this pattern)
113
+ - `lastDecayCalculation`: Last time decay was applied
114
+ - `initialConfidence`: Original confidence score (for tracking decay history)
115
+ - `decayRate`: Custom decay rate for this pattern (overrides default)
116
+ - `timesRenewed`: Count of how many times pattern was reconfirmed
117
+
118
+ ### Configuration Structure
119
+
120
+ ```json
121
+ {
122
+ "decay": {
123
+ "enabled": true,
124
+ "baseDecayRate": 0.15,
125
+ "minConfidenceThreshold": 50,
126
+ "decayCheckInterval": "weekly",
127
+ "removeBelow": 40,
128
+ "highConfidenceThreshold": 90,
129
+ "lowConfidenceThreshold": 75,
130
+ "renewalBoost": 10
131
+ }
132
+ }
133
+ ```
134
+
135
+ **Configuration Options:**
136
+ - `enabled`: Master switch for decay system
137
+ - `baseDecayRate`: Default monthly decay rate (0-1, default 0.15)
138
+ - `minConfidenceThreshold`: Patterns below this don't affect filtering
139
+ - `decayCheckInterval`: How often to calculate decay (daily/weekly/monthly)
140
+ - `removeBelow`: Auto-remove patterns below this confidence
141
+ - `renewalBoost`: Confidence points added when pattern reconfirmed
142
+
143
+ ---
144
+
145
+ ## 🔄 Algorithm Pseudocode
146
+
147
+ ### Decay Calculation
148
+
149
+ ```javascript
150
+ function calculateDecay(pattern, config) {
151
+ // Skip if decay disabled
152
+ if (!config.decay.enabled) return pattern;
153
+
154
+ // Skip if user manually approved (optional protection)
155
+ if (pattern.userApproved && config.decay.protectApproved) {
156
+ return pattern;
157
+ }
158
+
159
+ // Calculate time since last seen
160
+ const now = new Date();
161
+ const lastSeen = new Date(pattern.lastSeen);
162
+ const monthsInactive = (now - lastSeen) / (1000 * 60 * 60 * 24 * 30);
163
+
164
+ // Skip if recently seen (< 1 week)
165
+ if (monthsInactive < 0.25) return pattern;
166
+
167
+ // Get decay rate based on confidence
168
+ const decayRate = getDecayRate(pattern.confidence, config.decay.baseDecayRate);
169
+
170
+ // Apply exponential decay
171
+ const newConfidence = pattern.confidence * Math.pow(1 - decayRate, monthsInactive);
172
+
173
+ // Round to 2 decimal places
174
+ const roundedConfidence = Math.round(newConfidence * 100) / 100;
175
+
176
+ // Update pattern
177
+ return {
178
+ ...pattern,
179
+ confidence: Math.max(0, roundedConfidence),
180
+ lastDecayCalculation: now.toISOString()
181
+ };
182
+ }
183
+ ```
184
+
185
+ ### Pattern Renewal (Reconfirmation)
186
+
187
+ ```javascript
188
+ function renewPattern(pattern, config) {
189
+ // Pattern was observed again (skip event matched)
190
+ const now = new Date();
191
+
192
+ // Calculate time since creation (for natural growth)
193
+ const createdAt = new Date(pattern.createdAt);
194
+ const monthsSinceCreation = (now - createdAt) / (1000 * 60 * 60 * 24 * 30);
195
+
196
+ // Boost confidence by renewal amount
197
+ let newConfidence = pattern.confidence + config.decay.renewalBoost;
198
+
199
+ // Cap at initial confidence + some growth allowance
200
+ const maxConfidence = Math.min(pattern.initialConfidence + 5, 100);
201
+ newConfidence = Math.min(newConfidence, maxConfidence);
202
+
203
+ return {
204
+ ...pattern,
205
+ confidence: newConfidence,
206
+ lastSeen: now.toISOString(),
207
+ timesRenewed: pattern.timesRenewed + 1,
208
+ // Prevent immediate decay after renewal
209
+ lastDecayCalculation: now.toISOString()
210
+ };
211
+ }
212
+ ```
213
+
214
+ ### Pattern Cleanup
215
+
216
+ ```javascript
217
+ function cleanupPatterns(patterns, config) {
218
+ const now = new Date();
219
+ const activePatterns = [];
220
+ const removedPatterns = [];
221
+
222
+ for (const pattern of patterns) {
223
+ // Apply decay first
224
+ const decayedPattern = calculateDecay(pattern, config);
225
+
226
+ // Check if below removal threshold
227
+ if (decayedPattern.confidence < config.decay.removeBelow) {
228
+ removedPatterns.push({
229
+ ...decayedPattern,
230
+ status: 'removed',
231
+ removedAt: now.toISOString(),
232
+ removalReason: 'confidence_too_low'
233
+ });
234
+ }
235
+ // Check if inactive for too long (6+ months)
236
+ else if (isInactive(decayedPattern, 6)) {
237
+ removedPatterns.push({
238
+ ...decayedPattern,
239
+ status: 'removed',
240
+ removedAt: now.toISOString(),
241
+ removalReason: 'inactive_too_long'
242
+ });
243
+ }
244
+ else {
245
+ activePatterns.push(decayedPattern);
246
+ }
247
+ }
248
+
249
+ return { activePatterns, removedPatterns };
250
+ }
251
+ ```
252
+
253
+ ---
254
+
255
+ ## 🎨 Edge Cases & Solutions
256
+
257
+ ### Edge Case 1: Pattern Reconfirmed
258
+ **Scenario:** Pattern confidence decayed to 60%, then user skips question again
259
+ **Solution:** Boost confidence by renewalBoost amount (default +10 points)
260
+ **Result:** Confidence increases to 70%, lastSeen updated
261
+
262
+ ### Edge Case 2: User-Approved Pattern
263
+ **Scenario:** User manually approved pattern, should it decay?
264
+ **Options:**
265
+ - **Option A:** Never decay user-approved patterns (protect forever)
266
+ - **Option B:** Decay slower (half rate)
267
+ - **Option C:** Decay normally (user can re-approve)
268
+ **Recommendation:** Option B - decay at half rate, prompt user to re-approve if drops below 70%
269
+
270
+ ### Edge Case 3: Rapid Confidence Loss
271
+ **Scenario:** High-confidence pattern (95%) decays quickly
272
+ **Solution:** Apply decay rate cap: max 20 points/month
273
+ **Result:** Gradual decline prevents sudden filtering changes
274
+
275
+ ### Edge Case 4: Pattern Oscillation
276
+ **Scenario:** Pattern decays, gets renewed, decays again (oscillates)
277
+ **Solution:** Track `timesRenewed` counter
278
+ - If timesRenewed > 3 in 6 months → stable pattern, reduce decay rate
279
+ - If timesRenewed = 0 in 6 months → unstable pattern, increase decay rate
280
+
281
+ ### Edge Case 5: Multiple Sessions Per Day
282
+ **Scenario:** User runs 5 interviews in one day, pattern renewed 5x
283
+ **Solution:** Limit renewals to 1 per day per pattern
284
+ **Result:** Prevents artificial confidence inflation
285
+
286
+ ---
287
+
288
+ ## ⚙️ Configuration Options
289
+
290
+ ### User-Configurable Settings
291
+
292
+ Accessible via `adf config` → Learning System → Pattern Decay Settings:
293
+
294
+ ```
295
+ Pattern Decay Settings
296
+ ─────────────────────────────────────────
297
+
298
+ [x] Enable Pattern Decay
299
+ Patterns lose confidence over time when inactive
300
+
301
+ Base Decay Rate: [15%] per month
302
+ How quickly patterns fade (0-50%)
303
+
304
+ Minimum Active Confidence: [50] points
305
+ Patterns below this won't affect filtering
306
+
307
+ Auto-Remove Below: [40] points
308
+ Automatically remove patterns below this
309
+
310
+ Protect User-Approved: [x]
311
+ User-approved patterns decay at half rate
312
+
313
+ Renewal Boost: [+10] points
314
+ Confidence boost when pattern reconfirmed
315
+
316
+ [Save Changes] [Reset to Defaults]
317
+ ```
318
+
319
+ ### Default Configuration
320
+
321
+ ```javascript
322
+ const DEFAULT_DECAY_CONFIG = {
323
+ enabled: true,
324
+ baseDecayRate: 0.15, // 15% per month
325
+ minConfidenceThreshold: 50, // Don't filter if confidence < 50
326
+ removeBelow: 40, // Auto-remove if < 40
327
+ decayCheckInterval: 'weekly', // Run decay calc weekly
328
+ renewalBoost: 10, // +10 points on renewal
329
+ protectApproved: true, // Approved patterns decay at 0.5x rate
330
+ highConfidenceThreshold: 90, // Decay slower if >= 90
331
+ lowConfidenceThreshold: 75, // Decay faster if < 75
332
+ maxRenewalsPerDay: 1 // Limit renewal inflation
333
+ };
334
+ ```
335
+
336
+ ---
337
+
338
+ ## 📊 Performance Considerations
339
+
340
+ ### Computational Complexity
341
+
342
+ **Decay Calculation:**
343
+ - Time: O(n) where n = number of patterns
344
+ - Space: O(1) per pattern
345
+ - Expected patterns: 10-50 per user
346
+ - **Performance:** < 10ms for 50 patterns
347
+
348
+ **Optimization:**
349
+ - Only calculate decay weekly (not every session)
350
+ - Cache decay calculations for current session
351
+ - Lazy evaluation: calc on first use of pattern
352
+
353
+ ### Storage Impact
354
+
355
+ **Additional Fields:**
356
+ - 4 new timestamps per pattern (4 × 24 bytes = 96 bytes)
357
+ - 2 new numbers (decayRate, timesRenewed = 16 bytes)
358
+ - **Total:** ~112 bytes per pattern
359
+ - **For 50 patterns:** ~5.5 KB (negligible)
360
+
361
+ ---
362
+
363
+ ## 🧪 Testing Strategy
364
+
365
+ ### Unit Tests
366
+
367
+ ```javascript
368
+ describe('Pattern Decay Algorithm', () => {
369
+ test('decays confidence over time', () => {
370
+ const pattern = createPattern({ confidence: 90, lastSeen: '2025-08-01' });
371
+ const decayed = calculateDecay(pattern, config);
372
+ expect(decayed.confidence).toBeLessThan(90);
373
+ });
374
+
375
+ test('high confidence patterns decay slower', () => {
376
+ const high = createPattern({ confidence: 95, lastSeen: '2025-08-01' });
377
+ const low = createPattern({ confidence: 65, lastSeen: '2025-08-01' });
378
+
379
+ const highDecayed = calculateDecay(high, config);
380
+ const lowDecayed = calculateDecay(low, config);
381
+
382
+ // Calculate decay percentages
383
+ const highDecayPct = (high.confidence - highDecayed.confidence) / high.confidence;
384
+ const lowDecayPct = (low.confidence - lowDecayed.confidence) / low.confidence;
385
+
386
+ expect(highDecayPct).toBeLessThan(lowDecayPct);
387
+ });
388
+
389
+ test('pattern renewal increases confidence', () => {
390
+ const pattern = createPattern({ confidence: 60 });
391
+ const renewed = renewPattern(pattern, config);
392
+ expect(renewed.confidence).toBe(70);
393
+ expect(renewed.timesRenewed).toBe(1);
394
+ });
395
+
396
+ test('removes patterns below threshold', () => {
397
+ const patterns = [
398
+ createPattern({ confidence: 35 }), // Below removeBelow (40)
399
+ createPattern({ confidence: 60 }) // Above threshold
400
+ ];
401
+
402
+ const { activePatterns, removedPatterns } = cleanupPatterns(patterns, config);
403
+ expect(activePatterns).toHaveLength(1);
404
+ expect(removedPatterns).toHaveLength(1);
405
+ });
406
+
407
+ test('user-approved patterns decay slower', () => {
408
+ const approved = createPattern({
409
+ confidence: 90,
410
+ lastSeen: '2025-08-01',
411
+ userApproved: true
412
+ });
413
+ const normal = createPattern({
414
+ confidence: 90,
415
+ lastSeen: '2025-08-01',
416
+ userApproved: false
417
+ });
418
+
419
+ const approvedDecayed = calculateDecay(approved, {
420
+ ...config,
421
+ decay: { ...config.decay, protectApproved: true }
422
+ });
423
+ const normalDecayed = calculateDecay(normal, config);
424
+
425
+ expect(approvedDecayed.confidence).toBeGreaterThan(normalDecayed.confidence);
426
+ });
427
+ });
428
+ ```
429
+
430
+ ### Integration Tests
431
+
432
+ - Test decay across multiple sessions
433
+ - Test renewal after decay
434
+ - Test auto-removal of stale patterns
435
+ - Test configuration changes affect decay
436
+ - Test migration from non-decay patterns
437
+
438
+ ---
439
+
440
+ ## 🚀 Implementation Plan
441
+
442
+ ### Phase 1: Data Structure (Week 1)
443
+ 1. Add new fields to pattern schema
444
+ 2. Create migration script for existing patterns
445
+ 3. Add decay configuration to learning config
446
+ 4. Update storage.js to handle new fields
447
+
448
+ ### Phase 2: Core Algorithm (Week 1-2)
449
+ 1. Implement calculateDecay()
450
+ 2. Implement renewPattern()
451
+ 3. Implement cleanupPatterns()
452
+ 4. Add decay rate calculation logic
453
+ 5. Write comprehensive unit tests
454
+
455
+ ### Phase 3: Integration (Week 2)
456
+ 1. Integrate decay into pattern-detector.js
457
+ 2. Add decay check to interview startup
458
+ 3. Update skip-tracker.js to handle renewals
459
+ 4. Add decay scheduling (weekly cron)
460
+
461
+ ### Phase 4: UI & Configuration (Week 2)
462
+ 1. Add decay settings to adf config
463
+ 2. Show decay status in learning dashboard
464
+ 3. Display pattern age and decay info
465
+ 4. Add user prompts for low-confidence patterns
466
+
467
+ ### Phase 5: Testing & Polish (Week 3)
468
+ 1. Integration testing with real sessions
469
+ 2. Performance testing with 100+ patterns
470
+ 3. User acceptance testing
471
+ 4. Documentation updates
472
+
473
+ ---
474
+
475
+ ## 📈 Success Metrics
476
+
477
+ **Quantitative:**
478
+ - ✅ 90%+ of stale patterns removed within 6 months
479
+ - ✅ Decay calculation completes in < 10ms for 50 patterns
480
+ - ✅ Zero data corruption from decay operations
481
+ - ✅ Patterns correctly renewed when reconfirmed
482
+
483
+ **Qualitative:**
484
+ - ✅ Users report improved filtering accuracy over time
485
+ - ✅ No user complaints about "forgotten" recent preferences
486
+ - ✅ Clear communication of pattern status and decay
487
+ - ✅ User control over decay parameters feels intuitive
488
+
489
+ ---
490
+
491
+ ## 🔮 Future Enhancements
492
+
493
+ ### Smart Decay Rates
494
+ - Use machine learning to optimize decay rates per user
495
+ - Adjust decay based on project type (prototypes vs production)
496
+ - Seasonal patterns (higher decay for prototype patterns)
497
+
498
+ ### Pattern Resurrection
499
+ - Allow manual reactivation of removed patterns
500
+ - Suggest patterns for reactivation based on new behavior
501
+ - "Undo removal" feature
502
+
503
+ ### Confidence Visualization
504
+ - Graph showing pattern confidence over time
505
+ - Visual decay trajectory prediction
506
+ - Highlight patterns approaching removal
507
+
508
+ ---
509
+
510
+ ## ✅ Design Approval Checklist
511
+
512
+ - [x] Algorithm mathematically sound
513
+ - [x] Edge cases identified and handled
514
+ - [x] Performance acceptable (< 10ms)
515
+ - [x] Storage impact minimal (< 10 KB)
516
+ - [x] User control provided
517
+ - [x] Testing strategy comprehensive
518
+ - [x] Implementation plan clear
519
+ - [x] Success metrics defined
520
+ - [x] Documentation complete
521
+
522
+ ---
523
+
524
+ **Status:** ✅ Design Complete, Ready for Implementation
525
+ **Next Step:** Review with stakeholder, then proceed to implementation phase
526
+ **Estimated Implementation Time:** 2-3 weeks