add-skill-kit 3.2.2 → 3.2.4

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 (72) hide show
  1. package/bin/lib/commands/install.js +67 -45
  2. package/lib/agent-cli/README.md +21 -0
  3. package/lib/agent-cli/bin/ag-smart.js +158 -0
  4. package/lib/agent-cli/lib/audit.js +154 -0
  5. package/lib/agent-cli/lib/audit.test.js +100 -0
  6. package/lib/agent-cli/lib/auto-learn.js +319 -0
  7. package/lib/agent-cli/lib/auto_preview.py +148 -0
  8. package/lib/agent-cli/lib/backup.js +138 -0
  9. package/lib/agent-cli/lib/backup.test.js +78 -0
  10. package/lib/agent-cli/lib/checklist.py +222 -0
  11. package/lib/agent-cli/lib/cognitive-lesson.js +476 -0
  12. package/lib/agent-cli/lib/completion.js +149 -0
  13. package/lib/agent-cli/lib/config.js +35 -0
  14. package/lib/agent-cli/lib/eslint-fix.js +238 -0
  15. package/lib/agent-cli/lib/evolution-signal.js +215 -0
  16. package/lib/agent-cli/lib/export.js +86 -0
  17. package/lib/agent-cli/lib/export.test.js +65 -0
  18. package/lib/agent-cli/lib/fix.js +337 -0
  19. package/lib/agent-cli/lib/fix.test.js +80 -0
  20. package/lib/agent-cli/lib/gemini-export.js +83 -0
  21. package/lib/agent-cli/lib/generate-registry.js +42 -0
  22. package/lib/agent-cli/lib/hooks/install-hooks.js +152 -0
  23. package/lib/agent-cli/lib/hooks/lint-learn.js +172 -0
  24. package/lib/agent-cli/lib/ignore.js +116 -0
  25. package/lib/agent-cli/lib/ignore.test.js +58 -0
  26. package/lib/agent-cli/lib/init.js +124 -0
  27. package/lib/agent-cli/lib/learn.js +255 -0
  28. package/lib/agent-cli/lib/learn.test.js +70 -0
  29. package/lib/agent-cli/lib/migrate-to-v4.js +322 -0
  30. package/lib/agent-cli/lib/proposals.js +199 -0
  31. package/lib/agent-cli/lib/proposals.test.js +56 -0
  32. package/lib/agent-cli/lib/recall.js +820 -0
  33. package/lib/agent-cli/lib/recall.test.js +107 -0
  34. package/lib/agent-cli/lib/selfevolution-bridge.js +167 -0
  35. package/lib/agent-cli/lib/session_manager.py +120 -0
  36. package/lib/agent-cli/lib/settings.js +203 -0
  37. package/lib/agent-cli/lib/skill-learn.js +296 -0
  38. package/lib/agent-cli/lib/stats.js +132 -0
  39. package/lib/agent-cli/lib/stats.test.js +94 -0
  40. package/lib/agent-cli/lib/types.js +33 -0
  41. package/lib/agent-cli/lib/ui/audit-ui.js +146 -0
  42. package/lib/agent-cli/lib/ui/backup-ui.js +107 -0
  43. package/lib/agent-cli/lib/ui/clack-helpers.js +317 -0
  44. package/lib/agent-cli/lib/ui/common.js +83 -0
  45. package/lib/agent-cli/lib/ui/completion-ui.js +126 -0
  46. package/lib/agent-cli/lib/ui/custom-select.js +69 -0
  47. package/lib/agent-cli/lib/ui/dashboard-ui.js +123 -0
  48. package/lib/agent-cli/lib/ui/evolution-signals-ui.js +107 -0
  49. package/lib/agent-cli/lib/ui/export-ui.js +94 -0
  50. package/lib/agent-cli/lib/ui/fix-all-ui.js +191 -0
  51. package/lib/agent-cli/lib/ui/help-ui.js +49 -0
  52. package/lib/agent-cli/lib/ui/index.js +169 -0
  53. package/lib/agent-cli/lib/ui/init-ui.js +56 -0
  54. package/lib/agent-cli/lib/ui/knowledge-ui.js +55 -0
  55. package/lib/agent-cli/lib/ui/learn-ui.js +706 -0
  56. package/lib/agent-cli/lib/ui/lessons-ui.js +148 -0
  57. package/lib/agent-cli/lib/ui/pretty.js +145 -0
  58. package/lib/agent-cli/lib/ui/proposals-ui.js +99 -0
  59. package/lib/agent-cli/lib/ui/recall-ui.js +342 -0
  60. package/lib/agent-cli/lib/ui/routing-demo.js +79 -0
  61. package/lib/agent-cli/lib/ui/routing-ui.js +325 -0
  62. package/lib/agent-cli/lib/ui/settings-ui.js +381 -0
  63. package/lib/agent-cli/lib/ui/stats-ui.js +123 -0
  64. package/lib/agent-cli/lib/ui/watch-ui.js +236 -0
  65. package/lib/agent-cli/lib/verify_all.py +327 -0
  66. package/lib/agent-cli/lib/watcher.js +181 -0
  67. package/lib/agent-cli/lib/watcher.test.js +85 -0
  68. package/lib/agent-cli/package.json +51 -0
  69. package/lib/agentskillskit-cli/README.md +21 -0
  70. package/lib/agentskillskit-cli/ag-smart.js +158 -0
  71. package/lib/agentskillskit-cli/package.json +51 -0
  72. package/package.json +11 -6
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Master Checklist Runner - Agent Skill Kit
4
+ ==========================================
5
+
6
+ Orchestrates all validation scripts in priority order.
7
+ Use this for incremental validation during development.
8
+
9
+ Usage:
10
+ python scripts/checklist.py . # Run core checks
11
+ python scripts/checklist.py . --url <URL> # Include performance checks
12
+
13
+ Priority Order:
14
+ P0: Security Scan (vulnerabilities, secrets)
15
+ P1: Lint & Type Check (code quality)
16
+ P2: Schema Validation (if database exists)
17
+ P3: Test Runner (unit/integration tests)
18
+ P4: UX Audit (psychology laws, accessibility)
19
+ P5: SEO Check (meta tags, structure)
20
+ P6: Performance (lighthouse - requires URL)
21
+ """
22
+
23
+ import sys
24
+ import subprocess
25
+ import argparse
26
+ from pathlib import Path
27
+ from typing import List, Tuple, Optional
28
+
29
+ # ANSI colors for terminal output
30
+ class Colors:
31
+ HEADER = '\033[95m'
32
+ BLUE = '\033[94m'
33
+ CYAN = '\033[96m'
34
+ GREEN = '\033[92m'
35
+ YELLOW = '\033[93m'
36
+ RED = '\033[91m'
37
+ ENDC = '\033[0m'
38
+ BOLD = '\033[1m'
39
+
40
+ def print_header(text: str):
41
+ print(f"\n{Colors.BOLD}{Colors.CYAN}{'='*60}{Colors.ENDC}")
42
+ print(f"{Colors.BOLD}{Colors.CYAN}{text.center(60)}{Colors.ENDC}")
43
+ print(f"{Colors.BOLD}{Colors.CYAN}{'='*60}{Colors.ENDC}\n")
44
+
45
+ def print_step(text: str):
46
+ print(f"{Colors.BOLD}{Colors.BLUE}🔄 {text}{Colors.ENDC}")
47
+
48
+ def print_success(text: str):
49
+ print(f"{Colors.GREEN}✅ {text}{Colors.ENDC}")
50
+
51
+ def print_warning(text: str):
52
+ print(f"{Colors.YELLOW}⚠️ {text}{Colors.ENDC}")
53
+
54
+ def print_error(text: str):
55
+ print(f"{Colors.RED}❌ {text}{Colors.ENDC}")
56
+
57
+ # Define priority-ordered checks
58
+ CORE_CHECKS = [
59
+ ("Security Scan", ".agent/skills/vulnerability-scanner/scripts/security_scan.py", True),
60
+ ("Smart Audit", ".agent/scripts/audit.js", True),
61
+ ("Lint Check", ".agent/skills/lint-and-validate/scripts/lint_runner.py", True),
62
+ ("Schema Validation", ".agent/skills/database-design/scripts/schema_validator.py", False),
63
+ ("Test Runner", ".agent/skills/testing-patterns/scripts/test_runner.py", False),
64
+ ("UX Audit", ".agent/skills/frontend-design/scripts/ux_audit.py", False),
65
+ ("SEO Check", ".agent/skills/seo-fundamentals/scripts/seo_checker.py", False),
66
+ ]
67
+
68
+ PERFORMANCE_CHECKS = [
69
+ ("Lighthouse Audit", ".agent/skills/performance-profiling/scripts/lighthouse_audit.py", True),
70
+ ("Playwright E2E", ".agent/skills/webapp-testing/scripts/playwright_runner.py", False),
71
+ ]
72
+
73
+ def check_script_exists(script_path: Path) -> bool:
74
+ """Check if script file exists"""
75
+ return script_path.exists() and script_path.is_file()
76
+
77
+ def run_script(name: str, script_path: Path, project_path: str, url: Optional[str] = None) -> dict:
78
+ """
79
+ Run a validation script and capture results
80
+
81
+ Returns:
82
+ dict with keys: name, passed, output, skipped
83
+ """
84
+ if not check_script_exists(script_path):
85
+ print_warning(f"{name}: Script not found, skipping")
86
+ return {"name": name, "passed": True, "output": "", "skipped": True}
87
+
88
+ print_step(f"Running: {name}")
89
+
90
+ # Build command
91
+ if str(script_path).endswith('.js'):
92
+ cmd = ["node", str(script_path), project_path]
93
+ else:
94
+ cmd = ["python", str(script_path), project_path]
95
+
96
+ if url and ("lighthouse" in script_path.name.lower() or "playwright" in script_path.name.lower()):
97
+ cmd.append(url)
98
+
99
+ # Run script
100
+ try:
101
+ result = subprocess.run(
102
+ cmd,
103
+ capture_output=True,
104
+ text=True,
105
+ timeout=300 # 5 minute timeout
106
+ )
107
+
108
+ passed = result.returncode == 0
109
+
110
+ if passed:
111
+ print_success(f"{name}: PASSED")
112
+ else:
113
+ print_error(f"{name}: FAILED")
114
+ if result.stderr:
115
+ print(f" Error: {result.stderr[:200]}")
116
+
117
+ return {
118
+ "name": name,
119
+ "passed": passed,
120
+ "output": result.stdout,
121
+ "error": result.stderr,
122
+ "skipped": False
123
+ }
124
+
125
+ except subprocess.TimeoutExpired:
126
+ print_error(f"{name}: TIMEOUT (>5 minutes)")
127
+ return {"name": name, "passed": False, "output": "", "error": "Timeout", "skipped": False}
128
+
129
+ except Exception as e:
130
+ print_error(f"{name}: ERROR - {str(e)}")
131
+ return {"name": name, "passed": False, "output": "", "error": str(e), "skipped": False}
132
+
133
+ def print_summary(results: List[dict]):
134
+ """Print final summary report"""
135
+ print_header("📊 CHECKLIST SUMMARY")
136
+
137
+ passed_count = sum(1 for r in results if r["passed"] and not r.get("skipped"))
138
+ failed_count = sum(1 for r in results if not r["passed"] and not r.get("skipped"))
139
+ skipped_count = sum(1 for r in results if r.get("skipped"))
140
+
141
+ print(f"Total Checks: {len(results)}")
142
+ print(f"{Colors.GREEN}✅ Passed: {passed_count}{Colors.ENDC}")
143
+ print(f"{Colors.RED}❌ Failed: {failed_count}{Colors.ENDC}")
144
+ print(f"{Colors.YELLOW}⏭️ Skipped: {skipped_count}{Colors.ENDC}")
145
+ print()
146
+
147
+ # Detailed results
148
+ for r in results:
149
+ if r.get("skipped"):
150
+ status = f"{Colors.YELLOW}⏭️ {Colors.ENDC}"
151
+ elif r["passed"]:
152
+ status = f"{Colors.GREEN}✅{Colors.ENDC}"
153
+ else:
154
+ status = f"{Colors.RED}❌{Colors.ENDC}"
155
+
156
+ print(f"{status} {r['name']}")
157
+
158
+ print()
159
+
160
+ if failed_count > 0:
161
+ print_error(f"{failed_count} check(s) FAILED - Please fix before proceeding")
162
+ return False
163
+ else:
164
+ print_success("All checks PASSED ✨")
165
+ return True
166
+
167
+ def main():
168
+ parser = argparse.ArgumentParser(
169
+ description="Run Agent Skill Kit validation checklist",
170
+ formatter_class=argparse.RawDescriptionHelpFormatter,
171
+ epilog="""
172
+ Examples:
173
+ python scripts/checklist.py . # Core checks only
174
+ python scripts/checklist.py . --url http://localhost:3000 # Include performance
175
+ """
176
+ )
177
+ parser.add_argument("project", help="Project path to validate")
178
+ parser.add_argument("--url", help="URL for performance checks (lighthouse, playwright)")
179
+ parser.add_argument("--skip-performance", action="store_true", help="Skip performance checks even if URL provided")
180
+
181
+ args = parser.parse_args()
182
+
183
+ project_path = Path(args.project).resolve()
184
+
185
+ if not project_path.exists():
186
+ print_error(f"Project path does not exist: {project_path}")
187
+ sys.exit(1)
188
+
189
+ print_header("🚀 AGENT SKILLS KIT - MASTER CHECKLIST")
190
+ print(f"Project: {project_path}")
191
+ print(f"URL: {args.url if args.url else 'Not provided (performance checks skipped)'}")
192
+
193
+ results = []
194
+
195
+ # Run core checks
196
+ print_header("📋 CORE CHECKS")
197
+ for name, script_path, required in CORE_CHECKS:
198
+ script = project_path / script_path
199
+ result = run_script(name, script, str(project_path))
200
+ results.append(result)
201
+
202
+ # If required check fails, stop
203
+ if required and not result["passed"] and not result.get("skipped"):
204
+ print_error(f"CRITICAL: {name} failed. Stopping checklist.")
205
+ print_summary(results)
206
+ sys.exit(1)
207
+
208
+ # Run performance checks if URL provided
209
+ if args.url and not args.skip_performance:
210
+ print_header("⚡ PERFORMANCE CHECKS")
211
+ for name, script_path, required in PERFORMANCE_CHECKS:
212
+ script = project_path / script_path
213
+ result = run_script(name, script, str(project_path), args.url)
214
+ results.append(result)
215
+
216
+ # Print summary
217
+ all_passed = print_summary(results)
218
+
219
+ sys.exit(0 if all_passed else 1)
220
+
221
+ if __name__ == "__main__":
222
+ main()
@@ -0,0 +1,476 @@
1
+ /**
2
+ * Cognitive Lesson Engine - Intelligence Layers
3
+ *
4
+ * This module implements the cognitive intelligence that transforms
5
+ * raw data (mistakes.yaml + improvements.yaml) into Cognitive Lesson Units
6
+ *
7
+ * Levels:
8
+ * 1. Intent Inference - detect purpose
9
+ * 2. Pattern Intelligence - context matching
10
+ * 3. Maturity Calculation - confidence & state
11
+ * 4. Evolution Analysis - gap detection
12
+ * 5. Feedback Loop - self-evolution
13
+ */
14
+
15
+ import fs from 'fs';
16
+ import path from 'path';
17
+ import yaml from 'js-yaml';
18
+ import { fileURLToPath } from 'url';
19
+
20
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
+ const PROJECT_ROOT = path.join(__dirname, '../../..');
22
+ const KNOWLEDGE_DIR = path.join(PROJECT_ROOT, '.agent/knowledge');
23
+
24
+ // ============================================================================
25
+ // LEVEL 0: Data Loading
26
+ // ============================================================================
27
+
28
+ /**
29
+ * Load mistakes from YAML
30
+ */
31
+ export function loadMistakes() {
32
+ const filepath = path.join(KNOWLEDGE_DIR, 'mistakes.yaml');
33
+ if (!fs.existsSync(filepath)) {
34
+ return { version: 4.0, mistakes: [] };
35
+ }
36
+ try {
37
+ const content = fs.readFileSync(filepath, 'utf8');
38
+ return yaml.load(content) || { version: 4.0, mistakes: [] };
39
+ } catch (error) {
40
+ console.error('Error loading mistakes:', error.message);
41
+ return { version: 4.0, mistakes: [] };
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Load improvements from YAML
47
+ */
48
+ export function loadImprovements() {
49
+ const filepath = path.join(KNOWLEDGE_DIR, 'improvements.yaml');
50
+ if (!fs.existsSync(filepath)) {
51
+ return { version: 4.0, improvements: [] };
52
+ }
53
+ try {
54
+ const content = fs.readFileSync(filepath, 'utf8');
55
+ return yaml.load(content) || { version: 4.0, improvements: [] };
56
+ } catch (error) {
57
+ console.error('Error loading improvements:', error.message);
58
+ return { version: 4.0, improvements: [] };
59
+ }
60
+ }
61
+
62
+ // ============================================================================
63
+ // LEVEL 1: Intent Inference
64
+ // ============================================================================
65
+
66
+ /**
67
+ * Intent vocabulary - maps tag patterns to intents
68
+ */
69
+ const INTENT_PATTERNS = {
70
+ 'safe-rebranding': {
71
+ keywords: ['rebrand', 'rename', 'file-safety'],
72
+ goal: 'Rename files/entities without data loss or breaking changes',
73
+ category: 'file-operations',
74
+ },
75
+ 'cli-ux-consistency': {
76
+ keywords: ['cli', 'ux', 'menu', 'navigation', 'clack'],
77
+ goal: 'Provide consistent, intuitive CLI user experience',
78
+ category: 'user-experience',
79
+ },
80
+ 'error-prevention': {
81
+ keywords: ['validation', 'error', 'check', 'verify'],
82
+ goal: 'Prevent runtime errors through proactive validation',
83
+ category: 'reliability',
84
+ },
85
+ 'code-quality': {
86
+ keywords: ['import', 'architecture', 'quality'],
87
+ goal: 'Maintain clean, maintainable code structure',
88
+ category: 'maintainability',
89
+ },
90
+ };
91
+
92
+ /**
93
+ * Infer lesson intent from tags
94
+ * NO NEW FILE - computed runtime
95
+ */
96
+ export function inferIntent(tags) {
97
+ if (!tags || tags.length === 0) {
98
+ return {
99
+ id: 'unknown',
100
+ goal: 'General code quality improvement',
101
+ strength: 0.3,
102
+ category: 'general',
103
+ };
104
+ }
105
+
106
+ let bestMatch = null;
107
+ let bestScore = 0;
108
+
109
+ for (const [intentId, pattern] of Object.entries(INTENT_PATTERNS)) {
110
+ const matchCount = tags.filter(tag =>
111
+ pattern.keywords.some(kw => tag.toLowerCase().includes(kw.toLowerCase()))
112
+ ).length;
113
+
114
+ const score = matchCount / tags.length; // 0-1 confidence
115
+
116
+ if (score > bestScore) {
117
+ bestScore = score;
118
+ bestMatch = {
119
+ id: intentId,
120
+ goal: pattern.goal,
121
+ strength: score,
122
+ category: pattern.category,
123
+ };
124
+ }
125
+ }
126
+
127
+ return bestMatch || {
128
+ id: 'unknown',
129
+ goal: 'General code quality improvement',
130
+ strength: 0.3,
131
+ category: 'general',
132
+ };
133
+ }
134
+
135
+ // ============================================================================
136
+ // LEVEL 2: Pattern Intelligence
137
+ // ============================================================================
138
+
139
+ /**
140
+ * Build execution context from code
141
+ * Used for contextual pattern matching
142
+ */
143
+ export function buildContext(filePath, code) {
144
+ const context = {
145
+ framework: null,
146
+ intents: [],
147
+ environment: 'development',
148
+ fileType: path.extname(filePath),
149
+ };
150
+
151
+ // Detect framework from imports
152
+ if (code.includes('@clack/prompts')) context.framework = 'clack';
153
+ if (code.includes('inquirer')) context.framework = 'inquirer';
154
+ if (code.includes('react')) context.framework = 'react';
155
+
156
+ // Detect intent from code patterns
157
+ if (code.includes('p.select') || code.includes('showActionMenu')) {
158
+ context.intents.push('select-menu');
159
+ }
160
+ if (code.includes('rename') || code.includes('move')) {
161
+ context.intents.push('file-operation');
162
+ }
163
+ if (code.includes('import')) {
164
+ context.intents.push('module-usage');
165
+ }
166
+
167
+ return context;
168
+ }
169
+
170
+ /**
171
+ * Contextual pattern matching
172
+ * Smarter than text-only regex
173
+ */
174
+ export function matchPattern(code, mistake, context) {
175
+ // Basic pattern match
176
+ const regex = new RegExp(mistake.pattern);
177
+ const patternMatch = regex.test(code);
178
+
179
+ if (!patternMatch) return false;
180
+
181
+ // Context filtering - skip if not applicable
182
+ if (mistake.when) {
183
+ // Check framework requirement
184
+ if (mistake.when.framework && context.framework !== mistake.when.framework) {
185
+ return false; // Wrong framework, not applicable
186
+ }
187
+
188
+ // Check intent requirement
189
+ if (mistake.when.intent && !context.intents.includes(mistake.when.intent)) {
190
+ return false; // Intent mismatch
191
+ }
192
+ }
193
+
194
+ return true; // Pattern + context match
195
+ }
196
+
197
+ // ============================================================================
198
+ // LEVEL 3: Maturity Calculation
199
+ // ============================================================================
200
+
201
+ /**
202
+ * Calculate evidence score based on hit counts
203
+ */
204
+ function calculateEvidenceScore(mistakes, improvements) {
205
+ const totalMistakeHits = mistakes.reduce((sum, m) => sum + (m.hitCount || 0), 0);
206
+ const totalImprovementHits = improvements.reduce((sum, i) => sum + (i.appliedCount || 0), 0);
207
+
208
+ const totalHits = totalMistakeHits + totalImprovementHits;
209
+
210
+ if (totalHits === 0) return 0.1; // No evidence
211
+ if (totalHits < 5) return 0.3; // Weak
212
+ if (totalHits < 20) return 0.6; // Moderate
213
+ return 0.9; // Strong
214
+ }
215
+
216
+ /**
217
+ * Calculate recency score
218
+ */
219
+ function calculateRecencyScore(mistakes, improvements) {
220
+ const now = Date.now();
221
+
222
+ const allDates = [
223
+ ...mistakes.map(m => new Date(m.lastHit || m.added).getTime()),
224
+ ...improvements.map(i => new Date(i.lastApplied || i.added).getTime()),
225
+ ];
226
+
227
+ if (allDates.length === 0) return 0.5;
228
+
229
+ const lastUpdate = Math.max(...allDates);
230
+ const daysSinceUpdate = (now - lastUpdate) / (1000 * 60 * 60 * 24);
231
+
232
+ if (daysSinceUpdate < 7) return 1.0; // This week
233
+ if (daysSinceUpdate < 30) return 0.8; // This month
234
+ if (daysSinceUpdate < 90) return 0.5; // This quarter
235
+ return 0.3; // Stale
236
+ }
237
+
238
+ /**
239
+ * Get recommendation based on state and confidence
240
+ */
241
+ function getRecommendation(state, confidence) {
242
+ if (state === 'RAW') {
243
+ return 'URGENT: Discover best practices for this area';
244
+ }
245
+ if (state === 'LEARNING' && confidence < 0.5) {
246
+ return 'Needs more improvements to balance anti-patterns';
247
+ }
248
+ if (state === 'MATURE' && confidence > 0.8) {
249
+ return 'Stable - can be trusted for skill injection';
250
+ }
251
+ if (state === 'IDEAL') {
252
+ return 'Perfect - all best practices, no anti-patterns';
253
+ }
254
+ return 'Continue learning';
255
+ }
256
+
257
+ /**
258
+ * Calculate lesson maturity metrics
259
+ */
260
+ export function calculateMaturity(mistakes, improvements) {
261
+ const m = mistakes.length;
262
+ const i = improvements.length;
263
+
264
+ // State determination
265
+ let state;
266
+ if (i === 0 && m > 0) state = 'RAW'; // 🟥 Only mistakes
267
+ else if (i > 0 && m === 0) state = 'IDEAL'; // 🟦 Only improvements (rare)
268
+ else if (i >= m) state = 'MATURE'; // 🟩 Balanced or improvement-heavy
269
+ else state = 'LEARNING'; // 🟨 More mistakes than solutions
270
+
271
+ // Multi-factor confidence
272
+ const balanceScore = i / (m + i); // 0-1: improvement ratio
273
+ const evidenceScore = calculateEvidenceScore(mistakes, improvements); // 0-1: hit validation
274
+ const recencyScore = calculateRecencyScore(mistakes, improvements); // 0-1: freshness
275
+
276
+ const confidence = (
277
+ balanceScore * 0.5 + // Balance is most important
278
+ evidenceScore * 0.3 + // Evidence validates
279
+ recencyScore * 0.2 // Fresh is better
280
+ );
281
+
282
+ return {
283
+ state,
284
+ confidence: Math.round(confidence * 100) / 100,
285
+ indicators: {
286
+ balance: Math.round(balanceScore * 100) / 100,
287
+ evidence: Math.round(evidenceScore * 100) / 100,
288
+ recency: Math.round(recencyScore * 100) / 100,
289
+ },
290
+ coverage: `${m} mistakes / ${i} improvements`,
291
+ recommendation: getRecommendation(state, confidence),
292
+ };
293
+ }
294
+
295
+ // ============================================================================
296
+ // LEVEL 4: Evolution Analysis
297
+ // ============================================================================
298
+
299
+ /**
300
+ * Check if mistake has related improvement
301
+ */
302
+ function hasRelatedImprovement(mistake, improvements) {
303
+ return improvements.some(i =>
304
+ i.tags && mistake.tags && i.tags.some(tag => mistake.tags.includes(tag))
305
+ );
306
+ }
307
+
308
+ /**
309
+ * Determine next action from signals
310
+ */
311
+ function determineNextAction(signals) {
312
+ if (signals.some(s => s.priority === 'CRITICAL')) {
313
+ return 'Document solution for high-frequency violations immediately';
314
+ }
315
+ if (signals.some(s => s.type === 'SUGGEST_IMPROVEMENT_DISCOVERY')) {
316
+ return 'Research and document best practices in underserved areas';
317
+ }
318
+ return 'Continue normal learning';
319
+ }
320
+
321
+ /**
322
+ * Analyze evolution needs and gaps
323
+ */
324
+ export function analyzeEvolution(mistakes, improvements, intent) {
325
+ const signals = [];
326
+ const missingAreas = [];
327
+
328
+ // Signal 1: Many mistakes, few solutions
329
+ if (mistakes.length > improvements.length * 2) {
330
+ signals.push({
331
+ type: 'SUGGEST_IMPROVEMENT_DISCOVERY',
332
+ priority: 'HIGH',
333
+ reason: `${mistakes.length} anti-patterns but only ${improvements.length} solution(s)`,
334
+ });
335
+ }
336
+
337
+ // Signal 2: Uncovered tags
338
+ const mistakeTags = new Set(mistakes.flatMap(m => m.tags || []));
339
+ const improvementTags = new Set(improvements.flatMap(i => i.tags || []));
340
+
341
+ const uncoveredTags = [...mistakeTags].filter(tag => !improvementTags.has(tag));
342
+
343
+ uncoveredTags.forEach(tag => {
344
+ missingAreas.push({
345
+ area: tag,
346
+ reason: 'Anti-patterns detected but no best practice documented',
347
+ mistakeCount: mistakes.filter(m => m.tags && m.tags.includes(tag)).length,
348
+ });
349
+ });
350
+
351
+ // Signal 3: High-hit mistakes without solution
352
+ mistakes.forEach(m => {
353
+ if ((m.hitCount || 0) > 10 && !hasRelatedImprovement(m, improvements)) {
354
+ signals.push({
355
+ type: 'HOT_MISTAKE_NEEDS_SOLUTION',
356
+ priority: 'CRITICAL',
357
+ mistake: m.id,
358
+ reason: `${m.title} hit ${m.hitCount} times but no solution documented`,
359
+ });
360
+
361
+ missingAreas.push({
362
+ area: `solution-for-${m.id}`,
363
+ reason: 'Frequently violated anti-pattern needs best practice',
364
+ hitCount: m.hitCount,
365
+ });
366
+ }
367
+ });
368
+
369
+ // Signal 4: Intent under-served
370
+ if (intent && intent.strength > 0.7) {
371
+ const coverageScore = improvements.length / (mistakes.length + improvements.length);
372
+ if (coverageScore < 0.5) {
373
+ signals.push({
374
+ type: 'INTENT_UNDER_SERVED',
375
+ priority: 'MEDIUM',
376
+ reason: `Intent "${intent.goal}" is clear but solutions are scarce`,
377
+ });
378
+ }
379
+ }
380
+
381
+ return {
382
+ signals,
383
+ missingAreas,
384
+ nextAction: determineNextAction(signals),
385
+ };
386
+ }
387
+
388
+ // ============================================================================
389
+ // SYNTHESIS: Build Cognitive Lessons
390
+ // ============================================================================
391
+
392
+ /**
393
+ * Format tag as title
394
+ */
395
+ function formatTagAsTitle(tag) {
396
+ return tag
397
+ .split('-')
398
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
399
+ .join(' ');
400
+ }
401
+
402
+ /**
403
+ * Synthesize Cognitive Lesson Units from mistakes + improvements
404
+ * THIS IS THE MAIN FUNCTION
405
+ */
406
+ export function synthesizeLessons() {
407
+ const mistakesDb = loadMistakes();
408
+ const improvementsDb = loadImprovements();
409
+
410
+ // Group by tag
411
+ const groups = new Map();
412
+
413
+ // Add mistakes to groups
414
+ mistakesDb.mistakes.forEach(m => {
415
+ const tags = m.tags || ['uncategorized'];
416
+ tags.forEach(tag => {
417
+ if (!groups.has(tag)) {
418
+ groups.set(tag, { mistakes: [], improvements: [] });
419
+ }
420
+ groups.get(tag).mistakes.push(m);
421
+ });
422
+ });
423
+
424
+ // Add improvements to groups
425
+ improvementsDb.improvements.forEach(i => {
426
+ const tags = i.tags || ['uncategorized'];
427
+ tags.forEach(tag => {
428
+ if (!groups.has(tag)) {
429
+ groups.set(tag, { mistakes: [], improvements: [] });
430
+ }
431
+ groups.get(tag).improvements.push(i);
432
+ });
433
+ });
434
+
435
+ // Build Cognitive Lessons
436
+ const lessons = [];
437
+ let lessonId = 1;
438
+
439
+ groups.forEach((group, tag) => {
440
+ const intent = inferIntent([tag, ...group.mistakes.flatMap(m => m.tags || [])]);
441
+ const maturity = calculateMaturity(group.mistakes, group.improvements);
442
+ const evolution = analyzeEvolution(group.mistakes, group.improvements, intent);
443
+
444
+ lessons.push({
445
+ id: `LESSON-${String(lessonId++).padStart(3, '0')}`,
446
+ title: formatTagAsTitle(tag),
447
+ tag,
448
+ intent,
449
+ mistakes: group.mistakes,
450
+ improvements: group.improvements,
451
+ maturity,
452
+ evolution,
453
+ });
454
+ });
455
+
456
+ // Sort by maturity (MATURE first, RAW last)
457
+ const stateOrder = { 'IDEAL': 0, 'MATURE': 1, 'LEARNING': 2, 'RAW': 3 };
458
+ lessons.sort((a, b) => {
459
+ const stateCompare = stateOrder[a.maturity.state] - stateOrder[b.maturity.state];
460
+ if (stateCompare !== 0) return stateCompare;
461
+ return b.maturity.confidence - a.maturity.confidence; // Higher confidence first
462
+ });
463
+
464
+ return lessons;
465
+ }
466
+
467
+ export default {
468
+ loadMistakes,
469
+ loadImprovements,
470
+ inferIntent,
471
+ buildContext,
472
+ matchPattern,
473
+ calculateMaturity,
474
+ analyzeEvolution,
475
+ synthesizeLessons,
476
+ };