sdd-jc-methodology 0.2.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.
Files changed (148) hide show
  1. package/.claude/commands/sdd-archive.md +122 -0
  2. package/.claude/commands/sdd-constitution.md +240 -0
  3. package/.claude/commands/sdd-execute.md +132 -0
  4. package/.claude/commands/sdd-propose.md +149 -0
  5. package/.claude/commands/sdd-seo.md +251 -0
  6. package/.claude/commands/sdd-specify.md +264 -0
  7. package/.claude/commands/sdd-test.md +128 -0
  8. package/.claude/commands/sdd-validate.md +165 -0
  9. package/.claude/skills/api-design-principles/SKILL.md +528 -0
  10. package/.claude/skills/api-design-principles/assets/api-design-checklist.md +155 -0
  11. package/.claude/skills/api-design-principles/assets/rest-api-template.py +182 -0
  12. package/.claude/skills/api-design-principles/references/graphql-schema-design.md +583 -0
  13. package/.claude/skills/api-design-principles/references/rest-best-practices.md +408 -0
  14. package/.claude/skills/aws-serverless/SKILL.md +323 -0
  15. package/.claude/skills/brainstorming/SKILL.md +96 -0
  16. package/.claude/skills/error-handling-patterns/SKILL.md +641 -0
  17. package/.claude/skills/frontend-design/LICENSE.txt +177 -0
  18. package/.claude/skills/frontend-design/SKILL.md +272 -0
  19. package/.claude/skills/nestjs-expert/SKILL.md +552 -0
  20. package/.claude/skills/product-manager-toolkit/SKILL.md +351 -0
  21. package/.claude/skills/product-manager-toolkit/references/prd_templates.md +317 -0
  22. package/.claude/skills/product-manager-toolkit/scripts/customer_interview_analyzer.py +441 -0
  23. package/.claude/skills/product-manager-toolkit/scripts/rice_prioritizer.py +296 -0
  24. package/.claude/skills/react-doctor/AGENTS.md +15 -0
  25. package/.claude/skills/react-doctor/SKILL.md +19 -0
  26. package/.claude/skills/shadcn-ui/SKILL.md +1677 -0
  27. package/.claude/skills/shadcn-ui/references/learn.md +145 -0
  28. package/.claude/skills/shadcn-ui/references/official-ui-reference.md +1725 -0
  29. package/.claude/skills/shadcn-ui/references/reference.md +586 -0
  30. package/.claude/skills/shadcn-ui/references/ui-reference.md +1578 -0
  31. package/.claude/skills/stitch-design/README.md +50 -0
  32. package/.claude/skills/stitch-design/SKILL.md +84 -0
  33. package/.claude/skills/stitch-design/examples/DESIGN.md +22 -0
  34. package/.claude/skills/stitch-design/examples/enhanced-prompt.md +28 -0
  35. package/.claude/skills/stitch-design/references/design-mappings.md +45 -0
  36. package/.claude/skills/stitch-design/references/prompt-keywords.md +114 -0
  37. package/.claude/skills/stitch-design/references/tool-schemas.md +76 -0
  38. package/.claude/skills/stitch-design/workflows/edit-design.md +44 -0
  39. package/.claude/skills/stitch-design/workflows/generate-design-md.md +63 -0
  40. package/.claude/skills/stitch-design/workflows/text-to-design.md +47 -0
  41. package/.claude/skills/systematic-debugging/CREATION-LOG.md +119 -0
  42. package/.claude/skills/systematic-debugging/SKILL.md +296 -0
  43. package/.claude/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
  44. package/.claude/skills/systematic-debugging/condition-based-waiting.md +115 -0
  45. package/.claude/skills/systematic-debugging/defense-in-depth.md +122 -0
  46. package/.claude/skills/systematic-debugging/find-polluter.sh +63 -0
  47. package/.claude/skills/systematic-debugging/root-cause-tracing.md +169 -0
  48. package/.claude/skills/systematic-debugging/test-academic.md +14 -0
  49. package/.claude/skills/systematic-debugging/test-pressure-1.md +58 -0
  50. package/.claude/skills/systematic-debugging/test-pressure-2.md +68 -0
  51. package/.claude/skills/systematic-debugging/test-pressure-3.md +69 -0
  52. package/.claude/skills/tailwind-design-system/SKILL.md +874 -0
  53. package/.claude/skills/ui-ux-pro-max/SKILL.md +377 -0
  54. package/.claude/skills/ui-ux-pro-max/data/charts.csv +26 -0
  55. package/.claude/skills/ui-ux-pro-max/data/colors.csv +97 -0
  56. package/.claude/skills/ui-ux-pro-max/data/icons.csv +101 -0
  57. package/.claude/skills/ui-ux-pro-max/data/landing.csv +31 -0
  58. package/.claude/skills/ui-ux-pro-max/data/products.csv +97 -0
  59. package/.claude/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
  60. package/.claude/skills/ui-ux-pro-max/data/stacks/astro.csv +54 -0
  61. package/.claude/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  62. package/.claude/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  63. package/.claude/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  64. package/.claude/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  65. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  66. package/.claude/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  67. package/.claude/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  68. package/.claude/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
  69. package/.claude/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  70. package/.claude/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  71. package/.claude/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  72. package/.claude/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  73. package/.claude/skills/ui-ux-pro-max/data/styles.csv +68 -0
  74. package/.claude/skills/ui-ux-pro-max/data/typography.csv +58 -0
  75. package/.claude/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  76. package/.claude/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  77. package/.claude/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
  78. package/.claude/skills/ui-ux-pro-max/scripts/core.py +253 -0
  79. package/.claude/skills/ui-ux-pro-max/scripts/design_system.py +1067 -0
  80. package/.claude/skills/ui-ux-pro-max/scripts/search.py +114 -0
  81. package/.claude/skills/vercel-react-best-practices/AGENTS.md +2934 -0
  82. package/.claude/skills/vercel-react-best-practices/SKILL.md +136 -0
  83. package/.claude/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  84. package/.claude/skills/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
  85. package/.claude/skills/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
  86. package/.claude/skills/vercel-react-best-practices/rules/async-api-routes.md +38 -0
  87. package/.claude/skills/vercel-react-best-practices/rules/async-defer-await.md +80 -0
  88. package/.claude/skills/vercel-react-best-practices/rules/async-dependencies.md +51 -0
  89. package/.claude/skills/vercel-react-best-practices/rules/async-parallel.md +28 -0
  90. package/.claude/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
  91. package/.claude/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +59 -0
  92. package/.claude/skills/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
  93. package/.claude/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
  94. package/.claude/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  95. package/.claude/skills/vercel-react-best-practices/rules/bundle-preload.md +50 -0
  96. package/.claude/skills/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
  97. package/.claude/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
  98. package/.claude/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
  99. package/.claude/skills/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
  100. package/.claude/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
  101. package/.claude/skills/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
  102. package/.claude/skills/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
  103. package/.claude/skills/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
  104. package/.claude/skills/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
  105. package/.claude/skills/vercel-react-best-practices/rules/js-early-exit.md +50 -0
  106. package/.claude/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
  107. package/.claude/skills/vercel-react-best-practices/rules/js-index-maps.md +37 -0
  108. package/.claude/skills/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
  109. package/.claude/skills/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
  110. package/.claude/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
  111. package/.claude/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
  112. package/.claude/skills/vercel-react-best-practices/rules/rendering-activity.md +26 -0
  113. package/.claude/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  114. package/.claude/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
  115. package/.claude/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
  116. package/.claude/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  117. package/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  118. package/.claude/skills/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
  119. package/.claude/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
  120. package/.claude/skills/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
  121. package/.claude/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
  122. package/.claude/skills/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
  123. package/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  124. package/.claude/skills/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
  125. package/.claude/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
  126. package/.claude/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  127. package/.claude/skills/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
  128. package/.claude/skills/vercel-react-best-practices/rules/rerender-memo.md +44 -0
  129. package/.claude/skills/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  130. package/.claude/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  131. package/.claude/skills/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
  132. package/.claude/skills/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  133. package/.claude/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
  134. package/.claude/skills/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
  135. package/.claude/skills/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
  136. package/.claude/skills/vercel-react-best-practices/rules/server-cache-react.md +76 -0
  137. package/.claude/skills/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
  138. package/.claude/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
  139. package/.claude/skills/vercel-react-best-practices/rules/server-serialization.md +38 -0
  140. package/.mcp.json.example +12 -0
  141. package/CHANGELOG.md +61 -0
  142. package/LICENSE +21 -0
  143. package/README.md +571 -0
  144. package/assets/jc-fox-mark.svg +10 -0
  145. package/assets/jc-methodology-badge.png +0 -0
  146. package/bin/sdd-jc.js +379 -0
  147. package/package.json +43 -0
  148. package/scripts/gsc_verify.py +162 -0
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ RICE Prioritization Framework
4
+ Calculates RICE scores for feature prioritization
5
+ RICE = (Reach x Impact x Confidence) / Effort
6
+ """
7
+
8
+ import json
9
+ import csv
10
+ from typing import List, Dict, Tuple
11
+ import argparse
12
+
13
+ class RICECalculator:
14
+ """Calculate RICE scores for feature prioritization"""
15
+
16
+ def __init__(self):
17
+ self.impact_map = {
18
+ 'massive': 3.0,
19
+ 'high': 2.0,
20
+ 'medium': 1.0,
21
+ 'low': 0.5,
22
+ 'minimal': 0.25
23
+ }
24
+
25
+ self.confidence_map = {
26
+ 'high': 100,
27
+ 'medium': 80,
28
+ 'low': 50
29
+ }
30
+
31
+ self.effort_map = {
32
+ 'xl': 13,
33
+ 'l': 8,
34
+ 'm': 5,
35
+ 's': 3,
36
+ 'xs': 1
37
+ }
38
+
39
+ def calculate_rice(self, reach: int, impact: str, confidence: str, effort: str) -> float:
40
+ """
41
+ Calculate RICE score
42
+
43
+ Args:
44
+ reach: Number of users/customers affected per quarter
45
+ impact: massive/high/medium/low/minimal
46
+ confidence: high/medium/low (percentage)
47
+ effort: xl/l/m/s/xs (person-months)
48
+ """
49
+ impact_score = self.impact_map.get(impact.lower(), 1.0)
50
+ confidence_score = self.confidence_map.get(confidence.lower(), 50) / 100
51
+ effort_score = self.effort_map.get(effort.lower(), 5)
52
+
53
+ if effort_score == 0:
54
+ return 0
55
+
56
+ rice_score = (reach * impact_score * confidence_score) / effort_score
57
+ return round(rice_score, 2)
58
+
59
+ def prioritize_features(self, features: List[Dict]) -> List[Dict]:
60
+ """
61
+ Calculate RICE scores and rank features
62
+
63
+ Args:
64
+ features: List of feature dictionaries with RICE components
65
+ """
66
+ for feature in features:
67
+ feature['rice_score'] = self.calculate_rice(
68
+ feature.get('reach', 0),
69
+ feature.get('impact', 'medium'),
70
+ feature.get('confidence', 'medium'),
71
+ feature.get('effort', 'm')
72
+ )
73
+
74
+ # Sort by RICE score descending
75
+ return sorted(features, key=lambda x: x['rice_score'], reverse=True)
76
+
77
+ def analyze_portfolio(self, features: List[Dict]) -> Dict:
78
+ """
79
+ Analyze the feature portfolio for balance and insights
80
+ """
81
+ if not features:
82
+ return {}
83
+
84
+ total_effort = sum(
85
+ self.effort_map.get(f.get('effort', 'm').lower(), 5)
86
+ for f in features
87
+ )
88
+
89
+ total_reach = sum(f.get('reach', 0) for f in features)
90
+
91
+ effort_distribution = {}
92
+ impact_distribution = {}
93
+
94
+ for feature in features:
95
+ effort = feature.get('effort', 'm').lower()
96
+ impact = feature.get('impact', 'medium').lower()
97
+
98
+ effort_distribution[effort] = effort_distribution.get(effort, 0) + 1
99
+ impact_distribution[impact] = impact_distribution.get(impact, 0) + 1
100
+
101
+ # Calculate quick wins (high impact, low effort)
102
+ quick_wins = [
103
+ f for f in features
104
+ if f.get('impact', '').lower() in ['massive', 'high']
105
+ and f.get('effort', '').lower() in ['xs', 's']
106
+ ]
107
+
108
+ # Calculate big bets (high impact, high effort)
109
+ big_bets = [
110
+ f for f in features
111
+ if f.get('impact', '').lower() in ['massive', 'high']
112
+ and f.get('effort', '').lower() in ['l', 'xl']
113
+ ]
114
+
115
+ return {
116
+ 'total_features': len(features),
117
+ 'total_effort_months': total_effort,
118
+ 'total_reach': total_reach,
119
+ 'average_rice': round(sum(f['rice_score'] for f in features) / len(features), 2),
120
+ 'effort_distribution': effort_distribution,
121
+ 'impact_distribution': impact_distribution,
122
+ 'quick_wins': len(quick_wins),
123
+ 'big_bets': len(big_bets),
124
+ 'quick_wins_list': quick_wins[:3], # Top 3 quick wins
125
+ 'big_bets_list': big_bets[:3] # Top 3 big bets
126
+ }
127
+
128
+ def generate_roadmap(self, features: List[Dict], team_capacity: int = 10) -> List[Dict]:
129
+ """
130
+ Generate a quarterly roadmap based on team capacity
131
+
132
+ Args:
133
+ features: Prioritized feature list
134
+ team_capacity: Person-months available per quarter
135
+ """
136
+ quarters = []
137
+ current_quarter = {
138
+ 'quarter': 1,
139
+ 'features': [],
140
+ 'capacity_used': 0,
141
+ 'capacity_available': team_capacity
142
+ }
143
+
144
+ for feature in features:
145
+ effort = self.effort_map.get(feature.get('effort', 'm').lower(), 5)
146
+
147
+ if current_quarter['capacity_used'] + effort <= team_capacity:
148
+ current_quarter['features'].append(feature)
149
+ current_quarter['capacity_used'] += effort
150
+ else:
151
+ # Move to next quarter
152
+ current_quarter['capacity_available'] = team_capacity - current_quarter['capacity_used']
153
+ quarters.append(current_quarter)
154
+
155
+ current_quarter = {
156
+ 'quarter': len(quarters) + 1,
157
+ 'features': [feature],
158
+ 'capacity_used': effort,
159
+ 'capacity_available': team_capacity - effort
160
+ }
161
+
162
+ if current_quarter['features']:
163
+ current_quarter['capacity_available'] = team_capacity - current_quarter['capacity_used']
164
+ quarters.append(current_quarter)
165
+
166
+ return quarters
167
+
168
+ def format_output(features: List[Dict], analysis: Dict, roadmap: List[Dict]) -> str:
169
+ """Format the results for display"""
170
+ output = ["=" * 60]
171
+ output.append("RICE PRIORITIZATION RESULTS")
172
+ output.append("=" * 60)
173
+
174
+ # Top prioritized features
175
+ output.append("\nšŸ“Š TOP PRIORITIZED FEATURES\n")
176
+ for i, feature in enumerate(features[:10], 1):
177
+ output.append(f"{i}. {feature.get('name', 'Unnamed')}")
178
+ output.append(f" RICE Score: {feature['rice_score']}")
179
+ output.append(f" Reach: {feature.get('reach', 0)} | Impact: {feature.get('impact', 'medium')} | "
180
+ f"Confidence: {feature.get('confidence', 'medium')} | Effort: {feature.get('effort', 'm')}")
181
+ output.append("")
182
+
183
+ # Portfolio analysis
184
+ output.append("\nšŸ“ˆ PORTFOLIO ANALYSIS\n")
185
+ output.append(f"Total Features: {analysis.get('total_features', 0)}")
186
+ output.append(f"Total Effort: {analysis.get('total_effort_months', 0)} person-months")
187
+ output.append(f"Total Reach: {analysis.get('total_reach', 0):,} users")
188
+ output.append(f"Average RICE Score: {analysis.get('average_rice', 0)}")
189
+
190
+ output.append(f"\nšŸŽÆ Quick Wins: {analysis.get('quick_wins', 0)} features")
191
+ for qw in analysis.get('quick_wins_list', []):
192
+ output.append(f" • {qw.get('name', 'Unnamed')} (RICE: {qw['rice_score']})")
193
+
194
+ output.append(f"\nšŸš€ Big Bets: {analysis.get('big_bets', 0)} features")
195
+ for bb in analysis.get('big_bets_list', []):
196
+ output.append(f" • {bb.get('name', 'Unnamed')} (RICE: {bb['rice_score']})")
197
+
198
+ # Roadmap
199
+ output.append("\n\nšŸ“… SUGGESTED ROADMAP\n")
200
+ for quarter in roadmap:
201
+ output.append(f"\nQ{quarter['quarter']} - Capacity: {quarter['capacity_used']}/{quarter['capacity_used'] + quarter['capacity_available']} person-months")
202
+ for feature in quarter['features']:
203
+ output.append(f" • {feature.get('name', 'Unnamed')} (RICE: {feature['rice_score']})")
204
+
205
+ return "\n".join(output)
206
+
207
+ def load_features_from_csv(filepath: str) -> List[Dict]:
208
+ """Load features from CSV file"""
209
+ features = []
210
+ with open(filepath, 'r') as f:
211
+ reader = csv.DictReader(f)
212
+ for row in reader:
213
+ feature = {
214
+ 'name': row.get('name', ''),
215
+ 'reach': int(row.get('reach', 0)),
216
+ 'impact': row.get('impact', 'medium'),
217
+ 'confidence': row.get('confidence', 'medium'),
218
+ 'effort': row.get('effort', 'm'),
219
+ 'description': row.get('description', '')
220
+ }
221
+ features.append(feature)
222
+ return features
223
+
224
+ def create_sample_csv(filepath: str):
225
+ """Create a sample CSV file for testing"""
226
+ sample_features = [
227
+ ['name', 'reach', 'impact', 'confidence', 'effort', 'description'],
228
+ ['User Dashboard Redesign', '5000', 'high', 'high', 'l', 'Complete redesign of user dashboard'],
229
+ ['Mobile Push Notifications', '10000', 'massive', 'medium', 'm', 'Add push notification support'],
230
+ ['Dark Mode', '8000', 'medium', 'high', 's', 'Implement dark mode theme'],
231
+ ['API Rate Limiting', '2000', 'low', 'high', 'xs', 'Add rate limiting to API'],
232
+ ['Social Login', '12000', 'high', 'medium', 'm', 'Add Google/Facebook login'],
233
+ ['Export to PDF', '3000', 'medium', 'low', 's', 'Export reports as PDF'],
234
+ ['Team Collaboration', '4000', 'massive', 'low', 'xl', 'Real-time collaboration features'],
235
+ ['Search Improvements', '15000', 'high', 'high', 'm', 'Enhance search functionality'],
236
+ ['Onboarding Flow', '20000', 'massive', 'high', 's', 'Improve new user onboarding'],
237
+ ['Analytics Dashboard', '6000', 'high', 'medium', 'l', 'Advanced analytics for users'],
238
+ ]
239
+
240
+ with open(filepath, 'w', newline='') as f:
241
+ writer = csv.writer(f)
242
+ writer.writerows(sample_features)
243
+
244
+ print(f"Sample CSV created at: {filepath}")
245
+
246
+ def main():
247
+ parser = argparse.ArgumentParser(description='RICE Framework for Feature Prioritization')
248
+ parser.add_argument('input', nargs='?', help='CSV file with features or "sample" to create sample')
249
+ parser.add_argument('--capacity', type=int, default=10, help='Team capacity per quarter (person-months)')
250
+ parser.add_argument('--output', choices=['text', 'json', 'csv'], default='text', help='Output format')
251
+
252
+ args = parser.parse_args()
253
+
254
+ # Create sample if requested
255
+ if args.input == 'sample':
256
+ create_sample_csv('sample_features.csv')
257
+ return
258
+
259
+ # Use sample data if no input provided
260
+ if not args.input:
261
+ features = [
262
+ {'name': 'User Dashboard', 'reach': 5000, 'impact': 'high', 'confidence': 'high', 'effort': 'l'},
263
+ {'name': 'Push Notifications', 'reach': 10000, 'impact': 'massive', 'confidence': 'medium', 'effort': 'm'},
264
+ {'name': 'Dark Mode', 'reach': 8000, 'impact': 'medium', 'confidence': 'high', 'effort': 's'},
265
+ {'name': 'API Rate Limiting', 'reach': 2000, 'impact': 'low', 'confidence': 'high', 'effort': 'xs'},
266
+ {'name': 'Social Login', 'reach': 12000, 'impact': 'high', 'confidence': 'medium', 'effort': 'm'},
267
+ ]
268
+ else:
269
+ features = load_features_from_csv(args.input)
270
+
271
+ # Calculate RICE scores
272
+ calculator = RICECalculator()
273
+ prioritized = calculator.prioritize_features(features)
274
+ analysis = calculator.analyze_portfolio(prioritized)
275
+ roadmap = calculator.generate_roadmap(prioritized, args.capacity)
276
+
277
+ # Output results
278
+ if args.output == 'json':
279
+ result = {
280
+ 'features': prioritized,
281
+ 'analysis': analysis,
282
+ 'roadmap': roadmap
283
+ }
284
+ print(json.dumps(result, indent=2))
285
+ elif args.output == 'csv':
286
+ # Output prioritized features as CSV
287
+ if prioritized:
288
+ keys = prioritized[0].keys()
289
+ print(','.join(keys))
290
+ for feature in prioritized:
291
+ print(','.join(str(feature.get(k, '')) for k in keys))
292
+ else:
293
+ print(format_output(prioritized, analysis, roadmap))
294
+
295
+ if __name__ == "__main__":
296
+ main()
@@ -0,0 +1,15 @@
1
+ # React Doctor
2
+
3
+ Run after making React changes to catch issues early. Use when reviewing code, finishing a feature, or fixing bugs in a React project.
4
+
5
+ Scans your React codebase for security, performance, correctness, and architecture issues. Outputs a 0-100 score with actionable diagnostics.
6
+
7
+ ## Usage
8
+
9
+ ```bash
10
+ npx -y react-doctor@latest . --verbose --diff
11
+ ```
12
+
13
+ ## Workflow
14
+
15
+ Run after making changes to catch issues early. Fix errors first, then re-run to verify the score improved.
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: react-doctor
3
+ description: Run after making React changes to catch issues early. Use when reviewing code, finishing a feature, or fixing bugs in a React project.
4
+ version: 1.0.0
5
+ ---
6
+
7
+ # React Doctor
8
+
9
+ Scans your React codebase for security, performance, correctness, and architecture issues. Outputs a 0-100 score with actionable diagnostics.
10
+
11
+ ## Usage
12
+
13
+ ```bash
14
+ npx -y react-doctor@latest . --verbose --diff
15
+ ```
16
+
17
+ ## Workflow
18
+
19
+ Run after making changes to catch issues early. Fix errors first, then re-run to verify the score improved.