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.
- package/.claude/PROTECT_SKILLS.md +2 -2
- package/.claude/skills/{epic-discover → epic-planning}/SKILL.md +57 -22
- package/.claude/skills/{feature-discover → feature-planning}/SKILL.md +38 -22
- package/.claude/skills/speed-mode/SKILL.md +79 -8
- package/.claude/skills/stable-mode/SKILL.md +83 -1
- package/SYSTEM-BEHAVIOR.md +172 -21
- package/docs/COMMAND_REFERENCE.md +26 -26
- package/docs/gap-analysis-current-vs-comprehensive-methodology.md +3 -3
- package/features/auto-generate-production-chores.feature +62 -11
- package/features/backlog-command.feature +26 -0
- package/features/claude-md-protection/steps.js +6 -4
- package/features/decisions/index.js +10 -10
- package/features/git-hooks/simple-steps.js +4 -4
- package/features/git-hooks/steps.js +7 -7
- package/features/mode-prompts/simple-steps.js +3 -3
- package/features/step_definitions/auto-generate-production-chores.steps.js +542 -114
- package/features/step_definitions/backlog-command.steps.js +37 -0
- package/features/work-commands/index.js +192 -8
- package/features/work-commands/simple-steps.js +5 -5
- package/features/work-commands/steps.js +2 -2
- package/features/work-tracking/index.js +220 -38
- package/features/work-tracking/mode-required.feature +1 -1
- package/jettypod.js +15 -8
- package/lib/migrations/009-discovery-rationale-field.js +24 -0
- package/lib/production-chore-generator.js +198 -0
- package/package.json +1 -1
|
@@ -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
|
+
};
|