jettypod 3.0.2 → 4.0.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,198 @@
1
+ // Production chore generator - analyzes implementation and proposes production-ready chores
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { getDb } = require('./database');
5
+ const { execSync } = require('child_process');
6
+
7
+ /**
8
+ * Analyze implementation files for a feature to identify production gaps
9
+ * @param {number} featureId - Feature ID to analyze
10
+ * @returns {Promise<Object>} Analysis result with files and production gaps
11
+ */
12
+ async function analyzeImplementation(featureId) {
13
+ const db = getDb();
14
+
15
+ // Get feature details
16
+ const feature = await new Promise((resolve, reject) => {
17
+ db.get('SELECT * FROM work_items WHERE id = ?', [featureId], (err, row) => {
18
+ if (err) return reject(err);
19
+ resolve(row);
20
+ });
21
+ });
22
+
23
+ if (!feature) {
24
+ throw new Error(`Feature #${featureId} not found`);
25
+ }
26
+
27
+ // Get files modified for this feature from git history
28
+ let implementationFiles = [];
29
+
30
+ try {
31
+ const featureSlug = feature.title.toLowerCase().replace(/\s+/g, '-');
32
+
33
+ // Try to find commits for this feature
34
+ const gitLog = execSync(
35
+ `git log --oneline --all --grep="${featureSlug}" -10`,
36
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }
37
+ ).trim();
38
+
39
+ if (gitLog) {
40
+ const commits = gitLog.split('\n').map(line => line.split(' ')[0]);
41
+
42
+ for (const commit of commits) {
43
+ try {
44
+ const files = execSync(
45
+ `git diff-tree --no-commit-id --name-only -r ${commit}`,
46
+ { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }
47
+ ).trim();
48
+
49
+ if (files) {
50
+ const fileList = files.split('\n').filter(f =>
51
+ f.length > 0 &&
52
+ !f.includes('test') &&
53
+ !f.includes('.feature') &&
54
+ (f.endsWith('.js') || f.endsWith('.ts') || f.endsWith('.jsx') || f.endsWith('.tsx'))
55
+ );
56
+ implementationFiles.push(...fileList);
57
+ }
58
+ } catch (err) {
59
+ // Skip failed commits
60
+ continue;
61
+ }
62
+ }
63
+ }
64
+ } catch (err) {
65
+ // If git fails, use empty array
66
+ console.warn(`Warning: Could not retrieve git history for feature #${featureId}`);
67
+ }
68
+
69
+ // Remove duplicates
70
+ implementationFiles = [...new Set(implementationFiles)];
71
+
72
+ // Check if no implementation files found
73
+ const warning = implementationFiles.length === 0
74
+ ? 'No git commits found for this feature'
75
+ : null;
76
+
77
+ // Analyze files for production concerns
78
+ const productionGaps = {
79
+ security: [],
80
+ scale: [],
81
+ compliance: []
82
+ };
83
+
84
+ for (const filePath of implementationFiles) {
85
+ const fullPath = path.join(process.cwd(), filePath);
86
+
87
+ if (!fs.existsSync(fullPath)) {
88
+ continue;
89
+ }
90
+
91
+ try {
92
+ const content = fs.readFileSync(fullPath, 'utf8');
93
+
94
+ // Security analysis
95
+ if (content.includes('POST') || content.includes('PUT') || content.includes('DELETE')) {
96
+ productionGaps.security.push(`Rate limiting needed on ${filePath}`);
97
+ }
98
+ if (content.includes('password') || content.includes('auth') || content.includes('login')) {
99
+ productionGaps.security.push(`Input sanitization for SQL injection prevention in ${filePath}`);
100
+ }
101
+ if (content.includes('api') || content.includes('endpoint')) {
102
+ productionGaps.security.push(`Authentication/authorization checks in ${filePath}`);
103
+ }
104
+
105
+ // Scale analysis
106
+ if (content.includes('db.') || content.includes('database') || content.includes('query')) {
107
+ productionGaps.scale.push(`Connection pooling needed in ${filePath}`);
108
+ }
109
+ if (content.includes('fetch') || content.includes('http') || content.includes('request')) {
110
+ productionGaps.scale.push(`Caching strategy for ${filePath}`);
111
+ }
112
+
113
+ // Compliance analysis
114
+ if (content.includes('user') || content.includes('data') || content.includes('record')) {
115
+ productionGaps.compliance.push(`Audit logging for user actions in ${filePath}`);
116
+ }
117
+ if (content.includes('email') || content.includes('phone') || content.includes('address')) {
118
+ productionGaps.compliance.push(`Data retention policy for ${filePath}`);
119
+ }
120
+ } catch (readErr) {
121
+ // Skip files that can't be read
122
+ continue;
123
+ }
124
+ }
125
+
126
+ // Remove duplicates from gaps
127
+ productionGaps.security = [...new Set(productionGaps.security)];
128
+ productionGaps.scale = [...new Set(productionGaps.scale)];
129
+ productionGaps.compliance = [...new Set(productionGaps.compliance)];
130
+
131
+ return {
132
+ filesAnalyzed: implementationFiles,
133
+ productionGaps,
134
+ warning
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Generate production chore proposals from analysis
140
+ * @param {Object} analysisResult - Result from analyzeImplementation
141
+ * @param {string} featureTitle - Title of the feature
142
+ * @returns {Array<Object>} Array of {title, description} chore proposals
143
+ */
144
+ function generateProductionChores(analysisResult, featureTitle) {
145
+ const chores = [];
146
+
147
+ // Security chores
148
+ if (analysisResult.productionGaps.security.length > 0) {
149
+ const securityGaps = analysisResult.productionGaps.security.slice(0, 3); // Top 3
150
+ chores.push({
151
+ title: `Add security hardening to ${featureTitle}`,
152
+ description: `Implement security measures for production readiness:\n\n${securityGaps.map(gap => `• ${gap}`).join('\n')}\n\nFiles analyzed: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Security - Rate limiting, input sanitization, auth checks`
153
+ });
154
+ }
155
+
156
+ // Scale chores
157
+ if (analysisResult.productionGaps.scale.length > 0) {
158
+ const scaleGaps = analysisResult.productionGaps.scale.slice(0, 3); // Top 3
159
+ chores.push({
160
+ title: `Add scale testing to ${featureTitle}`,
161
+ description: `Optimize and test for production scale:\n\n${scaleGaps.map(gap => `• ${gap}`).join('\n')}\n\nFiles analyzed: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Scale - Connection pooling, caching, load testing`
162
+ });
163
+ }
164
+
165
+ // Compliance chores
166
+ if (analysisResult.productionGaps.compliance.length > 0) {
167
+ const complianceGaps = analysisResult.productionGaps.compliance.slice(0, 3); // Top 3
168
+ chores.push({
169
+ title: `Add compliance requirements to ${featureTitle}`,
170
+ description: `Ensure compliance and audit trail for production:\n\n${complianceGaps.map(gap => `• ${gap}`).join('\n')}\n\nFiles analyzed: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Compliance - Audit logging, data retention, regulatory requirements`
171
+ });
172
+ }
173
+
174
+ // If no gaps found, create generic production chores
175
+ if (chores.length === 0) {
176
+ chores.push(
177
+ {
178
+ title: `Add security hardening to ${featureTitle}`,
179
+ description: `Add authentication/authorization checks, input sanitization, encryption, and attack protection (XSS, CSRF, injection) for ${featureTitle}\n\nFiles: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Security - General hardening needed`
180
+ },
181
+ {
182
+ title: `Add scale testing to ${featureTitle}`,
183
+ description: `Add performance optimization, load testing (100+ concurrent users), caching strategy, and monitoring for ${featureTitle}\n\nFiles: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Scale - Performance testing needed`
184
+ },
185
+ {
186
+ title: `Add compliance requirements to ${featureTitle}`,
187
+ description: `Add GDPR/HIPAA/SOC2 compliance, audit trails, data retention policies, and regulatory requirements for ${featureTitle}\n\nFiles: ${analysisResult.filesAnalyzed.join(', ')}\nGap: Compliance - Compliance checks needed`
188
+ }
189
+ );
190
+ }
191
+
192
+ return chores;
193
+ }
194
+
195
+ module.exports = {
196
+ analyzeImplementation,
197
+ generateProductionChores
198
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jettypod",
3
- "version": "3.0.2",
3
+ "version": "4.0.0",
4
4
  "description": "Simplified development mode manager",
5
5
  "main": "jettypod.js",
6
6
  "bin": {