up-cli 0.1.0__py3-none-any.whl → 0.2.0__py3-none-any.whl

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.
@@ -1,6 +1,7 @@
1
1
  """Learn system templates."""
2
2
 
3
3
  from pathlib import Path
4
+ from datetime import date
4
5
 
5
6
 
6
7
  def create_learn_system(target_dir: Path, ai_target: str, force: bool = False) -> None:
@@ -20,12 +21,16 @@ def create_learn_system(target_dir: Path, ai_target: str, force: bool = False) -
20
21
  _create_skill_md(skill_dir, force)
21
22
  _create_sources_json(skill_dir, force)
22
23
  _create_patterns_md(skill_dir, force)
24
+ _create_gap_analysis_md(skill_dir, force)
25
+ _create_project_analyzer(skill_dir, force)
26
+ _create_prd_template(skill_dir, force)
23
27
 
24
28
 
25
29
  def _write_file(path: Path, content: str, force: bool) -> None:
26
30
  """Write file if it doesn't exist or force is True."""
27
31
  if path.exists() and not force:
28
32
  return
33
+ path.parent.mkdir(parents=True, exist_ok=True)
29
34
  path.write_text(content)
30
35
 
31
36
 
@@ -35,32 +40,206 @@ def _create_skill_md(skill_dir: Path, force: bool) -> None:
35
40
  name: learn
36
41
  description: Research and create improvement plans
37
42
  user-invocable: true
38
- allowed-tools: Read, Write, Bash, WebFetch, WebSearch
43
+ allowed-tools: Read, Write, Bash, WebFetch, WebSearch, Glob, Grep
44
+ version: "1.0.0"
45
+ min-claude-version: "2024.01"
39
46
  ---
40
47
 
41
48
  # Learning System
42
49
 
43
- Research best practices and create actionable plans.
50
+ Research best practices from open source projects and blogs, then create actionable improvement plans.
44
51
 
45
52
  ## Workflow
46
53
 
47
54
  ```
48
- RESEARCH → ANALYZE → COMPARE → PLAN
55
+ RESEARCH → ANALYZE → COMPARE → PLAN → IMPLEMENT
49
56
  ```
50
57
 
51
58
  ## Commands
52
59
 
53
- - `/learn auto` - Auto-analyze project
54
- - `/learn research [topic]` - Research topic
55
- - `/learn plan` - Generate improvement PRD
60
+ | Command | Description |
61
+ |---------|-------------|
62
+ | `/learn auto` | Auto-analyze project and generate insights |
63
+ | `/learn research [topic]` | Research a specific topic |
64
+ | `/learn analyze` | Analyze all research files |
65
+ | `/learn compare` | Compare findings with current code |
66
+ | `/learn plan` | Generate improvement PRD |
67
+ | `/learn full` | Run complete pipeline |
56
68
 
57
- ## Output Files
69
+ ## Phase 1: RESEARCH
70
+
71
+ ### Default Sources
72
+
73
+ Read `sources.json` for configured sources. Research from:
74
+
75
+ **Open Source Projects:**
76
+ - semgrep/semgrep - Pattern-based code analysis
77
+ - github/codeql - Query-based analysis
78
+ - High-quality projects in your tech stack
79
+
80
+ **Blogs & Documentation:**
81
+ - Official documentation for your frameworks
82
+ - Engineering blogs from top companies
83
+
84
+ ### Actions
85
+
86
+ 1. Use `WebSearch` to find recent articles/releases
87
+ 2. Use `WebFetch` to read project READMEs and docs
88
+ 3. Extract architecture patterns
89
+ 4. Note innovative approaches
90
+
91
+ ### Output
92
+
93
+ Save findings to `research/YYYY-MM-DD-topic.md`:
94
+
95
+ ```markdown
96
+ # Research: [Topic Name]
97
+
98
+ **Created**: YYYY-MM-DD
99
+ **Status**: 📋 Reference
100
+ **Source**: [Project/Blog Name]
101
+
102
+ ---
103
+
104
+ ## Key Findings
105
+
106
+ 1. Finding 1
107
+ 2. Finding 2
108
+
109
+ ## Applicable Patterns
110
+
111
+ - Pattern A: Description
112
+ - Pattern B: Description
113
+
114
+ ## Code Examples
115
+
116
+ ```language
117
+ // example code
118
+ ```
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Phase 2: ANALYZE
124
+
125
+ Read all research files and extract:
126
+
127
+ 1. **Design Patterns** - Architectural approaches
128
+ 2. **Key Innovations** - Novel techniques
129
+ 3. **Best Practices** - Industry standards
130
+ 4. **Reusable Components** - Code/concepts to adopt
131
+
132
+ ### Output
133
+
134
+ Update `insights/patterns.md` with extracted patterns.
135
+
136
+ ---
137
+
138
+ ## Phase 3: COMPARE
139
+
140
+ Compare insights with current implementation:
141
+
142
+ 1. Read project's main documentation (CLAUDE.md, README.md)
143
+ 2. Scan source code for current patterns
144
+ 3. Identify gaps and opportunities
145
+
146
+ ### Output
147
+
148
+ Update `insights/gap-analysis.md` with findings.
149
+
150
+ ---
151
+
152
+ ## Phase 4: PLAN
153
+
154
+ Create improvement plan as PRD:
155
+
156
+ 1. Prioritize gaps by impact/effort
157
+ 2. Create user stories with acceptance criteria
158
+ 3. Order by dependencies
159
+ 4. Save as `prd.json`
160
+
161
+ ### PRD Schema
162
+
163
+ ```json
164
+ {
165
+ "project": "Project Name",
166
+ "branchName": "feature/improvements",
167
+ "description": "Brief description",
168
+ "userStories": [
169
+ {
170
+ "id": "US-001",
171
+ "title": "Story title",
172
+ "description": "Description",
173
+ "acceptanceCriteria": ["Criterion 1", "Criterion 2"],
174
+ "priority": 1,
175
+ "effort": "low|medium|high",
176
+ "passes": false
177
+ }
178
+ ]
179
+ }
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Phase 5: IMPLEMENT
185
+
186
+ Hand off to Product Loop:
187
+
188
+ ```
189
+ /product-loop
190
+ ```
191
+
192
+ The product loop will:
193
+ 1. Read `prd.json` generated by learning system
194
+ 2. Execute tasks with circuit breaker protection
195
+ 3. Checkpoint before risky changes
196
+ 4. Track progress
197
+
198
+ ---
199
+
200
+ ## AUTO Mode
201
+
202
+ When `/learn auto` is invoked:
203
+
204
+ 1. Scan the codebase to detect technologies and patterns
205
+ 2. Identify improvement areas automatically
206
+ 3. Generate research topics based on findings
207
+ 4. Research each topic (limit: 3 topics)
208
+ 5. Continue with analyze → compare → plan
209
+
210
+ ### Auto Mode Output
211
+
212
+ ```
213
+ Project Profile:
214
+ - Languages: Python, TypeScript
215
+ - Frameworks: FastAPI, React
216
+ - Patterns: Repository Pattern, React Hooks
217
+ - Improvements: add-caching, optimize-queries
218
+ - Topics: FastAPI caching best practices, React performance
219
+ ```
220
+
221
+ ---
222
+
223
+ ## State Files
58
224
 
59
225
  | File | Purpose |
60
226
  |------|---------|
61
- | `research/*.md` | Research notes |
227
+ | `sources.json` | Research sources config |
228
+ | `research/*.md` | Raw research notes |
62
229
  | `insights/patterns.md` | Extracted patterns |
63
- | `prd.json` | Improvement plan |
230
+ | `insights/gap-analysis.md` | Gap analysis |
231
+ | `prd.json` | Generated improvement plan |
232
+
233
+ ---
234
+
235
+ ## Context Budget
236
+
237
+ This skill is context-aware:
238
+ - Estimates token usage before reading files
239
+ - Warns when approaching budget limits
240
+ - Suggests summarization when needed
241
+
242
+ Check budget: Read `.claude/context_budget.json`
64
243
  """
65
244
  _write_file(skill_dir / "SKILL.md", content, force)
66
245
 
@@ -68,9 +247,27 @@ RESEARCH → ANALYZE → COMPARE → PLAN
68
247
  def _create_sources_json(skill_dir: Path, force: bool) -> None:
69
248
  """Create sources.json config."""
70
249
  content = """{
71
- "projects": [],
72
- "blogs": [],
73
- "topics": []
250
+ "version": "1.0",
251
+ "updated": "",
252
+ "projects": [
253
+ {
254
+ "name": "example-project",
255
+ "repo": "owner/repo",
256
+ "category": "reference",
257
+ "topics": ["topic1", "topic2"],
258
+ "docs_url": "https://docs.example.com/"
259
+ }
260
+ ],
261
+ "blogs": [
262
+ {
263
+ "name": "Example Blog",
264
+ "url": "https://blog.example.com/",
265
+ "topics": ["topic1", "topic2"]
266
+ }
267
+ ],
268
+ "research_topics": [
269
+ "Add topics relevant to your project"
270
+ ]
74
271
  }
75
272
  """
76
273
  _write_file(skill_dir / "sources.json", content, force)
@@ -78,16 +275,372 @@ def _create_sources_json(skill_dir: Path, force: bool) -> None:
78
275
 
79
276
  def _create_patterns_md(skill_dir: Path, force: bool) -> None:
80
277
  """Create patterns template."""
81
- content = """# Extracted Patterns
278
+ today = date.today().isoformat()
279
+ content = f"""# Extracted Patterns
82
280
 
281
+ **Created**: {today}
282
+ **Updated**: {today}
83
283
  **Status**: 🔄 Active
84
284
 
85
285
  ---
86
286
 
287
+ ## How to Use
288
+
289
+ Add patterns discovered during research phases.
290
+
291
+ ---
292
+
87
293
  ## Pattern Template
88
294
 
295
+ ### Pattern: [Name]
296
+
89
297
  - **Source**: Project/Blog
298
+ - **Category**: Architecture | Design | Performance | Security
90
299
  - **Description**: What it does
91
- - **Applicability**: How to use it
300
+ - **Implementation**: How it works
301
+ - **Applicability**: How we can use it
302
+ - **Trade-offs**: Pros and cons
303
+
304
+ ### Code Example
305
+
306
+ ```language
307
+ // Example implementation
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Patterns
313
+
314
+ *Add patterns below this line*
315
+
316
+ ---
92
317
  """
93
318
  _write_file(skill_dir / "insights/patterns.md", content, force)
319
+
320
+
321
+ def _create_gap_analysis_md(skill_dir: Path, force: bool) -> None:
322
+ """Create gap analysis template."""
323
+ today = date.today().isoformat()
324
+ content = f"""# Gap Analysis
325
+
326
+ **Created**: {today}
327
+ **Updated**: {today}
328
+ **Status**: 🔄 Active
329
+
330
+ ---
331
+
332
+ ## Summary
333
+
334
+ | Impact | Count | Description |
335
+ |--------|-------|-------------|
336
+ | 🔴 High | 0 | Critical gaps |
337
+ | 🟡 Medium | 0 | Important gaps |
338
+ | 🟢 Low | 0 | Nice-to-have |
339
+
340
+ ---
341
+
342
+ ## Gap Template
343
+
344
+ ### Gap: [Name]
345
+
346
+ - **Current State**: What we have now
347
+ - **Best Practice**: What leading projects do
348
+ - **Impact**: 🔴 High | 🟡 Medium | 🟢 Low
349
+ - **Effort**: Low | Medium | High
350
+ - **Recommendation**: What to do
351
+
352
+ ---
353
+
354
+ ## Identified Gaps
355
+
356
+ *Add gaps below this line*
357
+
358
+ ---
359
+ """
360
+ _write_file(skill_dir / "insights/gap-analysis.md", content, force)
361
+
362
+
363
+ def _create_project_analyzer(skill_dir: Path, force: bool) -> None:
364
+ """Create project analyzer script."""
365
+ content = '''#!/usr/bin/env python3
366
+ """
367
+ Project Analyzer - Automatically identifies improvement areas in the codebase.
368
+
369
+ Usage:
370
+ python project_analyzer.py [--workspace /path/to/project]
371
+ """
372
+
373
+ import json
374
+ import os
375
+ import re
376
+ from dataclasses import dataclass, field
377
+ from pathlib import Path
378
+ from typing import Optional
379
+
380
+
381
+ @dataclass
382
+ class ProjectProfile:
383
+ """Profile of the current project."""
384
+ name: str
385
+ languages: list[str] = field(default_factory=list)
386
+ frameworks: list[str] = field(default_factory=list)
387
+ patterns_detected: list[str] = field(default_factory=list)
388
+ improvement_areas: list[str] = field(default_factory=list)
389
+ research_topics: list[str] = field(default_factory=list)
390
+
391
+
392
+ class ProjectAnalyzer:
393
+ """Analyzes project to identify improvement opportunities."""
394
+
395
+ # File extension to language mapping
396
+ EXTENSIONS = {
397
+ ".py": "Python",
398
+ ".js": "JavaScript",
399
+ ".ts": "TypeScript",
400
+ ".tsx": "TypeScript",
401
+ ".jsx": "JavaScript",
402
+ ".go": "Go",
403
+ ".rs": "Rust",
404
+ ".java": "Java",
405
+ ".rb": "Ruby",
406
+ ".php": "PHP",
407
+ ".swift": "Swift",
408
+ ".kt": "Kotlin",
409
+ }
410
+
411
+ # Framework indicators
412
+ FRAMEWORK_INDICATORS = {
413
+ # Python
414
+ "fastapi": "FastAPI",
415
+ "django": "Django",
416
+ "flask": "Flask",
417
+ "langchain": "LangChain",
418
+ "langgraph": "LangGraph",
419
+ "pytest": "pytest",
420
+ "sqlalchemy": "SQLAlchemy",
421
+ # JavaScript/TypeScript
422
+ "react": "React",
423
+ "next": "Next.js",
424
+ "vue": "Vue.js",
425
+ "express": "Express",
426
+ "nestjs": "NestJS",
427
+ # Others
428
+ "spring": "Spring",
429
+ "rails": "Rails",
430
+ }
431
+
432
+ # Pattern indicators (regex patterns)
433
+ PATTERN_INDICATORS = {
434
+ r"class.*Repository": "Repository Pattern",
435
+ r"class.*Factory": "Factory Pattern",
436
+ r"class.*Service": "Service Layer",
437
+ r"@dataclass": "Dataclasses",
438
+ r"class.*Protocol": "Protocol Pattern",
439
+ r"async def": "Async/Await",
440
+ r"useEffect|useState": "React Hooks",
441
+ r"def test_": "Unit Tests",
442
+ }
443
+
444
+ def __init__(self, workspace: Optional[Path] = None):
445
+ self.workspace = workspace or Path.cwd()
446
+
447
+ def analyze(self) -> ProjectProfile:
448
+ """Analyze the project and return a profile."""
449
+ profile = ProjectProfile(name=self.workspace.name)
450
+
451
+ profile.languages = self._detect_languages()
452
+ profile.frameworks = self._detect_frameworks()
453
+ profile.patterns_detected = self._detect_patterns()
454
+ profile.improvement_areas = self._identify_improvements(profile)
455
+ profile.research_topics = self._generate_topics(profile)
456
+
457
+ return profile
458
+
459
+ def _detect_languages(self) -> list[str]:
460
+ """Detect programming languages in the project."""
461
+ found = set()
462
+ skip_dirs = {".git", "node_modules", "__pycache__", ".venv", "venv", "build", "dist"}
463
+
464
+ for root, dirs, files in os.walk(self.workspace):
465
+ dirs[:] = [d for d in dirs if d not in skip_dirs]
466
+
467
+ for f in files:
468
+ ext = Path(f).suffix.lower()
469
+ if ext in self.EXTENSIONS:
470
+ found.add(self.EXTENSIONS[ext])
471
+
472
+ return sorted(found)
473
+
474
+ def _detect_frameworks(self) -> list[str]:
475
+ """Detect frameworks and tools in use."""
476
+ frameworks = []
477
+
478
+ # Check common config files
479
+ config_files = [
480
+ self.workspace / "pyproject.toml",
481
+ self.workspace / "requirements.txt",
482
+ self.workspace / "package.json",
483
+ self.workspace / "Cargo.toml",
484
+ self.workspace / "go.mod",
485
+ ]
486
+
487
+ for config in config_files:
488
+ if config.exists():
489
+ try:
490
+ content = config.read_text().lower()
491
+ for key, name in self.FRAMEWORK_INDICATORS.items():
492
+ if key in content:
493
+ frameworks.append(name)
494
+ except Exception:
495
+ pass
496
+
497
+ return list(set(frameworks))
498
+
499
+ def _detect_patterns(self) -> list[str]:
500
+ """Detect code patterns in use."""
501
+ patterns = set()
502
+ skip_dirs = {".git", "node_modules", "__pycache__", ".venv"}
503
+
504
+ src_dir = self.workspace / "src"
505
+ if not src_dir.exists():
506
+ src_dir = self.workspace
507
+
508
+ code_extensions = {".py", ".js", ".ts", ".tsx", ".jsx", ".go", ".rs", ".java"}
509
+
510
+ for root, dirs, files in os.walk(src_dir):
511
+ dirs[:] = [d for d in dirs if d not in skip_dirs]
512
+
513
+ for f in files:
514
+ if Path(f).suffix.lower() not in code_extensions:
515
+ continue
516
+
517
+ filepath = Path(root) / f
518
+ try:
519
+ content = filepath.read_text()
520
+ for pattern, name in self.PATTERN_INDICATORS.items():
521
+ if re.search(pattern, content, re.IGNORECASE):
522
+ patterns.add(name)
523
+ except Exception:
524
+ continue
525
+
526
+ return sorted(patterns)
527
+
528
+ def _identify_improvements(self, profile: ProjectProfile) -> list[str]:
529
+ """Identify areas that could be improved."""
530
+ improvements = []
531
+
532
+ # Check for missing patterns
533
+ if "Python" in profile.languages:
534
+ if "Unit Tests" not in profile.patterns_detected:
535
+ improvements.append("add-unit-tests")
536
+ if "Protocol Pattern" not in profile.patterns_detected:
537
+ improvements.append("add-interfaces")
538
+
539
+ if "TypeScript" in profile.languages:
540
+ if "Unit Tests" not in profile.patterns_detected:
541
+ improvements.append("add-unit-tests")
542
+
543
+ # Check for optimization opportunities
544
+ if any(f in profile.frameworks for f in ["FastAPI", "Django", "Flask"]):
545
+ improvements.append("add-caching")
546
+ improvements.append("optimize-queries")
547
+
548
+ if "React" in profile.frameworks:
549
+ improvements.append("optimize-renders")
550
+
551
+ return list(set(improvements))
552
+
553
+ def _generate_topics(self, profile: ProjectProfile) -> list[str]:
554
+ """Generate research topics based on profile."""
555
+ topics = []
556
+
557
+ # Map improvements to research topics
558
+ topic_map = {
559
+ "add-unit-tests": "testing best practices",
560
+ "add-interfaces": "Python Protocol and ABC patterns",
561
+ "add-caching": "caching strategies",
562
+ "optimize-queries": "database query optimization",
563
+ "optimize-renders": "React performance optimization",
564
+ }
565
+
566
+ for improvement in profile.improvement_areas:
567
+ if improvement in topic_map:
568
+ topics.append(topic_map[improvement])
569
+
570
+ # Add framework-specific topics
571
+ for framework in profile.frameworks[:2]: # Limit to 2
572
+ topics.append(f"{framework} best practices")
573
+
574
+ return topics[:5] # Limit to 5 topics
575
+
576
+ def save_profile(self, profile: ProjectProfile) -> Path:
577
+ """Save profile to JSON file."""
578
+ filepath = self.workspace / ".claude/skills/learning-system/project_profile.json"
579
+ filepath.parent.mkdir(parents=True, exist_ok=True)
580
+
581
+ data = {
582
+ "name": profile.name,
583
+ "languages": profile.languages,
584
+ "frameworks": profile.frameworks,
585
+ "patterns_detected": profile.patterns_detected,
586
+ "improvement_areas": profile.improvement_areas,
587
+ "research_topics": profile.research_topics,
588
+ }
589
+
590
+ filepath.write_text(json.dumps(data, indent=2))
591
+ return filepath
592
+
593
+
594
+ def main():
595
+ import sys
596
+
597
+ workspace = None
598
+ if len(sys.argv) > 2 and sys.argv[1] == "--workspace":
599
+ workspace = Path(sys.argv[2])
600
+
601
+ analyzer = ProjectAnalyzer(workspace)
602
+ profile = analyzer.analyze()
603
+
604
+ print(f"Project: {profile.name}")
605
+ print(f"Languages: {', '.join(profile.languages) or 'None detected'}")
606
+ print(f"Frameworks: {', '.join(profile.frameworks) or 'None detected'}")
607
+ print(f"Patterns: {', '.join(profile.patterns_detected) or 'None detected'}")
608
+ print(f"Improvements: {', '.join(profile.improvement_areas) or 'None identified'}")
609
+ print(f"Topics: {', '.join(profile.research_topics) or 'None generated'}")
610
+
611
+ # Save profile
612
+ path = analyzer.save_profile(profile)
613
+ print(f"\\nProfile saved to: {path}")
614
+
615
+
616
+ if __name__ == "__main__":
617
+ main()
618
+ '''
619
+ _write_file(skill_dir / "project_analyzer.py", content, force)
620
+
621
+
622
+ def _create_prd_template(skill_dir: Path, force: bool) -> None:
623
+ """Create PRD template file."""
624
+ content = """{
625
+ "project": "Project Improvements",
626
+ "branchName": "feature/improvements",
627
+ "description": "Improvements identified by learning system",
628
+ "createdAt": "",
629
+ "userStories": [
630
+ {
631
+ "id": "US-001",
632
+ "title": "Example User Story",
633
+ "description": "As a developer, I want X so that Y",
634
+ "acceptanceCriteria": [
635
+ "Criterion 1",
636
+ "Criterion 2"
637
+ ],
638
+ "priority": 1,
639
+ "effort": "medium",
640
+ "passes": false,
641
+ "notes": ""
642
+ }
643
+ ]
644
+ }
645
+ """
646
+ _write_file(skill_dir / "prd_template.json", content, force)