prjct-cli 0.10.13 → 0.11.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/CHANGELOG.md +58 -0
- package/CLAUDE.md +47 -2
- package/bin/dev.js +217 -0
- package/bin/prjct +10 -0
- package/bin/serve.js +78 -0
- package/core/agentic/command-executor.js +38 -112
- package/core/agentic/prompt-builder.js +72 -0
- package/core/bus/index.js +322 -0
- package/core/command-registry.js +65 -0
- package/core/domain/snapshot-manager.js +375 -0
- package/core/plugin/hooks.js +313 -0
- package/core/plugin/index.js +52 -0
- package/core/plugin/loader.js +331 -0
- package/core/plugin/registry.js +325 -0
- package/core/plugins/webhook.js +143 -0
- package/core/session/index.js +449 -0
- package/core/session/metrics.js +293 -0
- package/package.json +18 -4
- package/templates/agentic/agent-routing.md +42 -9
- package/templates/agentic/checklist-routing.md +98 -0
- package/templates/checklists/accessibility.md +33 -0
- package/templates/checklists/architecture.md +28 -0
- package/templates/checklists/code-quality.md +28 -0
- package/templates/checklists/data.md +33 -0
- package/templates/checklists/documentation.md +33 -0
- package/templates/checklists/infrastructure.md +33 -0
- package/templates/checklists/performance.md +33 -0
- package/templates/checklists/security.md +33 -0
- package/templates/checklists/testing.md +33 -0
- package/templates/checklists/ux-ui.md +37 -0
- package/templates/commands/bug.md +27 -1
- package/templates/commands/done.md +176 -54
- package/templates/commands/feature.md +38 -1
- package/templates/commands/history.md +176 -0
- package/templates/commands/init.md +28 -1
- package/templates/commands/now.md +191 -9
- package/templates/commands/pause.md +176 -12
- package/templates/commands/redo.md +142 -0
- package/templates/commands/resume.md +166 -62
- package/templates/commands/serve.md +121 -0
- package/templates/commands/ship.md +45 -1
- package/templates/commands/sync.md +34 -1
- package/templates/commands/task.md +27 -1
- package/templates/commands/undo.md +152 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionMetrics - Metrics Calculation and Aggregation
|
|
3
|
+
*
|
|
4
|
+
* Calculates productivity metrics from session data.
|
|
5
|
+
*
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs').promises
|
|
10
|
+
const path = require('path')
|
|
11
|
+
const pathManager = require('../infrastructure/path-manager')
|
|
12
|
+
|
|
13
|
+
class SessionMetrics {
|
|
14
|
+
constructor(projectId) {
|
|
15
|
+
this.projectId = projectId
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get aggregated metrics for a time period
|
|
20
|
+
* @param {'day'|'week'|'month'|'all'} period
|
|
21
|
+
* @returns {Promise<Object>}
|
|
22
|
+
*/
|
|
23
|
+
async getMetrics(period = 'week') {
|
|
24
|
+
const sessions = await this.getSessionsForPeriod(period)
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
period,
|
|
28
|
+
totalSessions: sessions.length,
|
|
29
|
+
totalDuration: this.sumDurations(sessions),
|
|
30
|
+
totalDurationFormatted: this.formatDuration(this.sumDurations(sessions)),
|
|
31
|
+
averageDuration: this.averageDuration(sessions),
|
|
32
|
+
averageDurationFormatted: this.formatDuration(this.averageDuration(sessions)),
|
|
33
|
+
tasksCompleted: sessions.filter(s => s.status === 'completed').length,
|
|
34
|
+
filesChanged: this.sumMetric(sessions, 'filesChanged'),
|
|
35
|
+
linesAdded: this.sumMetric(sessions, 'linesAdded'),
|
|
36
|
+
linesRemoved: this.sumMetric(sessions, 'linesRemoved'),
|
|
37
|
+
commits: this.sumMetric(sessions, 'commits'),
|
|
38
|
+
productivityScore: this.calculateProductivityScore(sessions),
|
|
39
|
+
streak: await this.calculateStreak(),
|
|
40
|
+
byDay: this.groupByDay(sessions)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get sessions for a given period
|
|
46
|
+
* @param {string} period
|
|
47
|
+
* @returns {Promise<Array>}
|
|
48
|
+
*/
|
|
49
|
+
async getSessionsForPeriod(period) {
|
|
50
|
+
const globalPath = pathManager.getGlobalProjectPath(this.projectId)
|
|
51
|
+
const archiveDir = path.join(globalPath, 'sessions', 'archive')
|
|
52
|
+
|
|
53
|
+
const sessions = []
|
|
54
|
+
const cutoffDate = this.getCutoffDate(period)
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
const months = await fs.readdir(archiveDir)
|
|
58
|
+
|
|
59
|
+
for (const month of months) {
|
|
60
|
+
const monthDir = path.join(archiveDir, month)
|
|
61
|
+
const files = await fs.readdir(monthDir)
|
|
62
|
+
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
if (!file.endsWith('.json')) continue
|
|
65
|
+
|
|
66
|
+
const content = await fs.readFile(path.join(monthDir, file), 'utf-8')
|
|
67
|
+
const session = JSON.parse(content)
|
|
68
|
+
|
|
69
|
+
if (new Date(session.completedAt) >= cutoffDate) {
|
|
70
|
+
sessions.push(session)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Archive might not exist
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Also check current session
|
|
79
|
+
try {
|
|
80
|
+
const currentPath = path.join(globalPath, 'sessions', 'current.json')
|
|
81
|
+
const content = await fs.readFile(currentPath, 'utf-8')
|
|
82
|
+
const current = JSON.parse(content)
|
|
83
|
+
if (new Date(current.startedAt) >= cutoffDate) {
|
|
84
|
+
sessions.push(current)
|
|
85
|
+
}
|
|
86
|
+
} catch {
|
|
87
|
+
// No current session
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return sessions
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get cutoff date for period
|
|
95
|
+
* @param {string} period
|
|
96
|
+
* @returns {Date}
|
|
97
|
+
*/
|
|
98
|
+
getCutoffDate(period) {
|
|
99
|
+
const now = new Date()
|
|
100
|
+
|
|
101
|
+
switch (period) {
|
|
102
|
+
case 'day':
|
|
103
|
+
return new Date(now.setHours(0, 0, 0, 0))
|
|
104
|
+
case 'week':
|
|
105
|
+
const weekAgo = new Date(now)
|
|
106
|
+
weekAgo.setDate(weekAgo.getDate() - 7)
|
|
107
|
+
return weekAgo
|
|
108
|
+
case 'month':
|
|
109
|
+
const monthAgo = new Date(now)
|
|
110
|
+
monthAgo.setMonth(monthAgo.getMonth() - 1)
|
|
111
|
+
return monthAgo
|
|
112
|
+
case 'all':
|
|
113
|
+
default:
|
|
114
|
+
return new Date(0) // Beginning of time
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sum durations from sessions
|
|
120
|
+
* @param {Array} sessions
|
|
121
|
+
* @returns {number} Total seconds
|
|
122
|
+
*/
|
|
123
|
+
sumDurations(sessions) {
|
|
124
|
+
return sessions.reduce((sum, s) => sum + (s.duration || 0), 0)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Calculate average duration
|
|
129
|
+
* @param {Array} sessions
|
|
130
|
+
* @returns {number} Average seconds
|
|
131
|
+
*/
|
|
132
|
+
averageDuration(sessions) {
|
|
133
|
+
if (sessions.length === 0) return 0
|
|
134
|
+
return Math.round(this.sumDurations(sessions) / sessions.length)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Sum a specific metric
|
|
139
|
+
* @param {Array} sessions
|
|
140
|
+
* @param {string} metric
|
|
141
|
+
* @returns {number}
|
|
142
|
+
*/
|
|
143
|
+
sumMetric(sessions, metric) {
|
|
144
|
+
return sessions.reduce((sum, s) => {
|
|
145
|
+
return sum + (s.metrics?.[metric] || 0)
|
|
146
|
+
}, 0)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Calculate productivity score (0-100)
|
|
151
|
+
* Based on consistency, duration, and output
|
|
152
|
+
* @param {Array} sessions
|
|
153
|
+
* @returns {number}
|
|
154
|
+
*/
|
|
155
|
+
calculateProductivityScore(sessions) {
|
|
156
|
+
if (sessions.length === 0) return 0
|
|
157
|
+
|
|
158
|
+
// Factors:
|
|
159
|
+
// 1. Session count (more = better, up to a point)
|
|
160
|
+
const sessionScore = Math.min(sessions.length / 10, 1) * 30
|
|
161
|
+
|
|
162
|
+
// 2. Average duration (25-90 min is optimal)
|
|
163
|
+
const avgMins = this.averageDuration(sessions) / 60
|
|
164
|
+
let durationScore = 0
|
|
165
|
+
if (avgMins >= 25 && avgMins <= 90) {
|
|
166
|
+
durationScore = 30
|
|
167
|
+
} else if (avgMins > 0) {
|
|
168
|
+
durationScore = Math.max(0, 30 - Math.abs(avgMins - 57.5) / 2)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// 3. Completion rate
|
|
172
|
+
const completedCount = sessions.filter(s => s.status === 'completed').length
|
|
173
|
+
const completionScore = (completedCount / sessions.length) * 20
|
|
174
|
+
|
|
175
|
+
// 4. Output (commits + files changed)
|
|
176
|
+
const totalOutput = this.sumMetric(sessions, 'commits') + this.sumMetric(sessions, 'filesChanged')
|
|
177
|
+
const outputScore = Math.min(totalOutput / 50, 1) * 20
|
|
178
|
+
|
|
179
|
+
return Math.round(sessionScore + durationScore + completionScore + outputScore)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Calculate current streak (consecutive days with sessions)
|
|
184
|
+
* @returns {Promise<number>}
|
|
185
|
+
*/
|
|
186
|
+
async calculateStreak() {
|
|
187
|
+
const sessions = await this.getSessionsForPeriod('month')
|
|
188
|
+
|
|
189
|
+
// Get unique dates with sessions
|
|
190
|
+
const dates = new Set(
|
|
191
|
+
sessions.map(s => {
|
|
192
|
+
const d = new Date(s.completedAt || s.startedAt)
|
|
193
|
+
return `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`
|
|
194
|
+
})
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
// Count consecutive days from today
|
|
198
|
+
let streak = 0
|
|
199
|
+
const today = new Date()
|
|
200
|
+
|
|
201
|
+
for (let i = 0; i < 30; i++) {
|
|
202
|
+
const checkDate = new Date(today)
|
|
203
|
+
checkDate.setDate(checkDate.getDate() - i)
|
|
204
|
+
const key = `${checkDate.getFullYear()}-${checkDate.getMonth()}-${checkDate.getDate()}`
|
|
205
|
+
|
|
206
|
+
if (dates.has(key)) {
|
|
207
|
+
streak++
|
|
208
|
+
} else if (i > 0) {
|
|
209
|
+
break // Streak broken
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return streak
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Group sessions by day
|
|
218
|
+
* @param {Array} sessions
|
|
219
|
+
* @returns {Object}
|
|
220
|
+
*/
|
|
221
|
+
groupByDay(sessions) {
|
|
222
|
+
const byDay = {}
|
|
223
|
+
|
|
224
|
+
for (const session of sessions) {
|
|
225
|
+
const date = new Date(session.completedAt || session.startedAt)
|
|
226
|
+
const key = date.toISOString().split('T')[0]
|
|
227
|
+
|
|
228
|
+
if (!byDay[key]) {
|
|
229
|
+
byDay[key] = {
|
|
230
|
+
sessions: 0,
|
|
231
|
+
duration: 0,
|
|
232
|
+
commits: 0
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
byDay[key].sessions++
|
|
237
|
+
byDay[key].duration += session.duration || 0
|
|
238
|
+
byDay[key].commits += session.metrics?.commits || 0
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return byDay
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Format duration as human readable
|
|
246
|
+
* @param {number} seconds
|
|
247
|
+
* @returns {string}
|
|
248
|
+
*/
|
|
249
|
+
formatDuration(seconds) {
|
|
250
|
+
if (seconds < 60) return `${seconds}s`
|
|
251
|
+
if (seconds < 3600) return `${Math.round(seconds / 60)}m`
|
|
252
|
+
|
|
253
|
+
const hours = Math.floor(seconds / 3600)
|
|
254
|
+
const minutes = Math.round((seconds % 3600) / 60)
|
|
255
|
+
|
|
256
|
+
if (minutes === 0) return `${hours}h`
|
|
257
|
+
return `${hours}h ${minutes}m`
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Generate metrics summary for display
|
|
262
|
+
* @param {'day'|'week'|'month'} period
|
|
263
|
+
* @returns {Promise<string>}
|
|
264
|
+
*/
|
|
265
|
+
async generateSummary(period = 'week') {
|
|
266
|
+
const m = await this.getMetrics(period)
|
|
267
|
+
|
|
268
|
+
const periodLabel = {
|
|
269
|
+
day: 'Today',
|
|
270
|
+
week: 'This Week',
|
|
271
|
+
month: 'This Month',
|
|
272
|
+
all: 'All Time'
|
|
273
|
+
}[period]
|
|
274
|
+
|
|
275
|
+
return `
|
|
276
|
+
## ${periodLabel}
|
|
277
|
+
|
|
278
|
+
| Metric | Value |
|
|
279
|
+
|--------|-------|
|
|
280
|
+
| Sessions | ${m.totalSessions} |
|
|
281
|
+
| Total Time | ${m.totalDurationFormatted} |
|
|
282
|
+
| Avg Session | ${m.averageDurationFormatted} |
|
|
283
|
+
| Tasks Done | ${m.tasksCompleted} |
|
|
284
|
+
| Files Changed | ${m.filesChanged} |
|
|
285
|
+
| Lines +/- | +${m.linesAdded} / -${m.linesRemoved} |
|
|
286
|
+
| Commits | ${m.commits} |
|
|
287
|
+
| Streak | ${m.streak} days |
|
|
288
|
+
| Score | ${m.productivityScore}/100 |
|
|
289
|
+
`.trim()
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
module.exports = SessionMetrics
|
package/package.json
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prjct-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Built for Claude - Ship fast, track progress, stay focused. Developer momentum tool for indie hackers.",
|
|
5
5
|
"main": "core/index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"prjct": "bin/prjct"
|
|
7
|
+
"prjct": "bin/prjct",
|
|
8
|
+
"prjct-dev": "bin/dev.js",
|
|
9
|
+
"prjct-serve": "bin/serve.js"
|
|
8
10
|
},
|
|
11
|
+
"workspaces": [
|
|
12
|
+
"packages/*"
|
|
13
|
+
],
|
|
9
14
|
"publishConfig": {
|
|
10
15
|
"access": "public",
|
|
11
16
|
"registry": "https://registry.npmjs.org"
|
|
12
17
|
},
|
|
13
18
|
"scripts": {
|
|
19
|
+
"dev": "turbo run dev",
|
|
20
|
+
"build": "turbo run build",
|
|
21
|
+
"serve": "turbo run dev --filter=@prjct/server --filter=@prjct/web",
|
|
14
22
|
"postinstall": "node scripts/postinstall.js",
|
|
15
23
|
"update-commands": "node -e \"const installer = require('./core/infrastructure/command-installer'); installer.syncCommands().then(r => console.log('Commands updated:', r)).catch(e => console.error('Error:', e.message))\"",
|
|
16
24
|
"install-global": "./scripts/install.sh",
|
|
@@ -41,6 +49,7 @@
|
|
|
41
49
|
"dependencies": {
|
|
42
50
|
"chalk": "^4.1.2",
|
|
43
51
|
"glob": "^10.3.10",
|
|
52
|
+
"lightningcss": "^1.30.2",
|
|
44
53
|
"prompts": "^2.4.2"
|
|
45
54
|
},
|
|
46
55
|
"devDependencies": {
|
|
@@ -52,6 +61,7 @@
|
|
|
52
61
|
"eslint-plugin-n": "^16.6.2",
|
|
53
62
|
"eslint-plugin-promise": "^6.6.0",
|
|
54
63
|
"prettier": "^3.6.2",
|
|
64
|
+
"turbo": "^2.3.0",
|
|
55
65
|
"vitest": "^3.2.4"
|
|
56
66
|
},
|
|
57
67
|
"repository": {
|
|
@@ -62,6 +72,7 @@
|
|
|
62
72
|
"url": "https://github.com/jlopezlira/prjct-cli/issues"
|
|
63
73
|
},
|
|
64
74
|
"homepage": "https://prjct.app",
|
|
75
|
+
"packageManager": "npm@10.2.4",
|
|
65
76
|
"engines": {
|
|
66
77
|
"node": ">=18.0.0"
|
|
67
78
|
},
|
|
@@ -79,5 +90,8 @@
|
|
|
79
90
|
"trustedDependencies": [
|
|
80
91
|
"chalk",
|
|
81
92
|
"prompts"
|
|
82
|
-
]
|
|
83
|
-
|
|
93
|
+
],
|
|
94
|
+
"overrides": {
|
|
95
|
+
"esbuild": "^0.25.0"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -57,17 +57,49 @@ Consider these agent specializations:
|
|
|
57
57
|
3. Consider secondary areas
|
|
58
58
|
4. Choose agent with best expertise match
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## How to Invoke (EFFICIENT)
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
After deciding the best agent, **delegate via Task tool with REFERENCE, not content**:
|
|
63
63
|
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
```
|
|
65
|
+
Task(
|
|
66
|
+
subagent_type: 'general-purpose',
|
|
67
|
+
prompt: '
|
|
68
|
+
## Agent Assignment
|
|
69
|
+
Read and apply: ~/.prjct-cli/projects/{projectId}/agents/{agent-name}.md
|
|
70
|
+
|
|
71
|
+
## Task
|
|
72
|
+
{task description}
|
|
73
|
+
|
|
74
|
+
## Context
|
|
75
|
+
- Project: {projectPath}
|
|
76
|
+
- Files affected: {file list if known}
|
|
77
|
+
|
|
78
|
+
## Flow
|
|
79
|
+
1. Read agent file FIRST
|
|
80
|
+
2. Apply agent expertise and patterns
|
|
81
|
+
3. Execute task following agent guidelines
|
|
82
|
+
4. Return results
|
|
83
|
+
'
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Why References, Not Content
|
|
88
|
+
|
|
89
|
+
| Approach | Prompt Size | Issue |
|
|
90
|
+
|----------|-------------|-------|
|
|
91
|
+
| ❌ Inject content | 3-5KB | Bloats context, increases hallucinations |
|
|
92
|
+
| ✅ Pass reference | ~200 bytes | Subagent reads what it needs |
|
|
93
|
+
|
|
94
|
+
**CRITICAL:** The subagent reads the agent file itself. You do NOT need to read and inject the content.
|
|
95
|
+
|
|
96
|
+
## Output (After Delegation)
|
|
97
|
+
|
|
98
|
+
After Task tool returns, summarize:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
✅ Delegated to: {agent-name}
|
|
102
|
+
Result: {brief summary from subagent}
|
|
71
103
|
```
|
|
72
104
|
|
|
73
105
|
## Rules
|
|
@@ -75,4 +107,5 @@ Return the recommended agent with reasoning:
|
|
|
75
107
|
- **Task-driven, not tech-driven** - Focus on what needs to be done
|
|
76
108
|
- **Context matters** - Same tech can mean different things in different projects
|
|
77
109
|
- **Be flexible** - One project's "backend" might be another's "full-stack"
|
|
110
|
+
- **Pass PATH, not CONTENT** - Let subagent read the agent file
|
|
78
111
|
- **Explain your reasoning** - Don't just pick, justify
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: [Read, Glob]
|
|
3
|
+
description: 'Determine which quality checklists to apply - Claude decides'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Checklist Routing Instructions
|
|
7
|
+
|
|
8
|
+
## Objective
|
|
9
|
+
|
|
10
|
+
Determine which quality checklists are relevant for a task by analyzing the ACTUAL task and its scope.
|
|
11
|
+
|
|
12
|
+
## Step 1: Understand the Task
|
|
13
|
+
|
|
14
|
+
Read the task description and identify:
|
|
15
|
+
|
|
16
|
+
- What type of work is being done? (new feature, bug fix, refactor, infra, docs)
|
|
17
|
+
- What domains are affected? (code, UI, API, database, deployment)
|
|
18
|
+
- What is the scope? (small fix, major feature, architectural change)
|
|
19
|
+
|
|
20
|
+
## Step 2: Consider Task Domains
|
|
21
|
+
|
|
22
|
+
Each task can touch multiple domains. Consider:
|
|
23
|
+
|
|
24
|
+
| Domain | Signals |
|
|
25
|
+
|--------|---------|
|
|
26
|
+
| Code Quality | Writing/modifying any code |
|
|
27
|
+
| Architecture | New components, services, or major refactors |
|
|
28
|
+
| UX/UI | User-facing changes, CLI output, visual elements |
|
|
29
|
+
| Infrastructure | Deployment, containers, CI/CD, cloud resources |
|
|
30
|
+
| Security | Auth, user data, external inputs, secrets |
|
|
31
|
+
| Testing | New functionality, bug fixes, critical paths |
|
|
32
|
+
| Documentation | Public APIs, complex features, breaking changes |
|
|
33
|
+
| Performance | Data processing, loops, network calls, rendering |
|
|
34
|
+
| Accessibility | User interfaces (web, mobile, CLI) |
|
|
35
|
+
| Data | Database operations, caching, data transformations |
|
|
36
|
+
|
|
37
|
+
## Step 3: Match Task to Checklists
|
|
38
|
+
|
|
39
|
+
Based on your analysis, select relevant checklists:
|
|
40
|
+
|
|
41
|
+
**DO NOT assume:**
|
|
42
|
+
- Every task needs all checklists
|
|
43
|
+
- "Frontend" = only UX checklist
|
|
44
|
+
- "Backend" = only Code Quality checklist
|
|
45
|
+
|
|
46
|
+
**DO analyze:**
|
|
47
|
+
- What the task actually touches
|
|
48
|
+
- What quality dimensions matter for this specific work
|
|
49
|
+
- What could go wrong if not checked
|
|
50
|
+
|
|
51
|
+
## Available Checklists
|
|
52
|
+
|
|
53
|
+
Located in `templates/checklists/`:
|
|
54
|
+
|
|
55
|
+
| Checklist | When to Apply |
|
|
56
|
+
|-----------|---------------|
|
|
57
|
+
| `code-quality.md` | Any code changes (any language) |
|
|
58
|
+
| `architecture.md` | New modules, services, significant structural changes |
|
|
59
|
+
| `ux-ui.md` | User-facing interfaces (web, mobile, CLI, API DX) |
|
|
60
|
+
| `infrastructure.md` | Deployment, containers, CI/CD, cloud resources |
|
|
61
|
+
| `security.md` | ALWAYS for: auth, user input, external APIs, secrets |
|
|
62
|
+
| `testing.md` | New features, bug fixes, refactors |
|
|
63
|
+
| `documentation.md` | Public APIs, complex features, configuration changes |
|
|
64
|
+
| `performance.md` | Data-intensive operations, critical paths |
|
|
65
|
+
| `accessibility.md` | Any user interface work |
|
|
66
|
+
| `data.md` | Database, caching, data transformations |
|
|
67
|
+
|
|
68
|
+
## Decision Process
|
|
69
|
+
|
|
70
|
+
1. Read task description
|
|
71
|
+
2. Identify primary work domain
|
|
72
|
+
3. List secondary domains affected
|
|
73
|
+
4. Select 2-4 most relevant checklists
|
|
74
|
+
5. Consider Security (almost always relevant)
|
|
75
|
+
|
|
76
|
+
## Output
|
|
77
|
+
|
|
78
|
+
Return selected checklists with reasoning:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"checklists": ["code-quality", "security", "testing"],
|
|
83
|
+
"reasoning": "Task involves new API endpoint (code), handles user input (security), and adds business logic (testing)",
|
|
84
|
+
"priority_items": ["Input validation", "Error handling", "Happy path tests"],
|
|
85
|
+
"skipped": {
|
|
86
|
+
"accessibility": "No user interface changes",
|
|
87
|
+
"infrastructure": "No deployment changes"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Rules
|
|
93
|
+
|
|
94
|
+
- **Task-driven** - Focus on what the specific task needs
|
|
95
|
+
- **Less is more** - 2-4 focused checklists beat 10 unfocused
|
|
96
|
+
- **Security is special** - Default to including unless clearly irrelevant
|
|
97
|
+
- **Explain your reasoning** - Don't just pick, justify selections AND skips
|
|
98
|
+
- **Context matters** - Small typo fix ≠ major refactor in checklist needs
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Accessibility Checklist
|
|
2
|
+
|
|
3
|
+
> Applies to: Web (WCAG), Mobile, CLI, Desktop
|
|
4
|
+
|
|
5
|
+
## Perceivable
|
|
6
|
+
- [ ] Text alternatives for non-text content
|
|
7
|
+
- [ ] Sufficient color contrast (4.5:1 minimum)
|
|
8
|
+
- [ ] Content readable without color alone
|
|
9
|
+
- [ ] Resizable text supported (up to 200%)
|
|
10
|
+
|
|
11
|
+
## Operable
|
|
12
|
+
- [ ] Keyboard accessible (all functionality)
|
|
13
|
+
- [ ] No keyboard traps
|
|
14
|
+
- [ ] Sufficient time for interactions
|
|
15
|
+
- [ ] Seizure-safe (no flashing > 3Hz)
|
|
16
|
+
|
|
17
|
+
## Understandable
|
|
18
|
+
- [ ] Clear and simple language
|
|
19
|
+
- [ ] Consistent navigation
|
|
20
|
+
- [ ] Input assistance provided
|
|
21
|
+
- [ ] Error identification and suggestions
|
|
22
|
+
|
|
23
|
+
## Robust
|
|
24
|
+
- [ ] Compatible with assistive technologies
|
|
25
|
+
- [ ] Valid markup/structure
|
|
26
|
+
- [ ] ARIA used correctly (web)
|
|
27
|
+
- [ ] Semantic HTML elements used
|
|
28
|
+
|
|
29
|
+
## CLI Accessibility
|
|
30
|
+
- [ ] Screen reader compatible output
|
|
31
|
+
- [ ] No color-only information
|
|
32
|
+
- [ ] Clear text formatting
|
|
33
|
+
- [ ] Configurable output verbosity
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Architecture Checklist
|
|
2
|
+
|
|
3
|
+
> Applies to ANY system architecture
|
|
4
|
+
|
|
5
|
+
## Design Principles
|
|
6
|
+
- [ ] Clear separation of concerns
|
|
7
|
+
- [ ] Loose coupling between components
|
|
8
|
+
- [ ] High cohesion within modules
|
|
9
|
+
- [ ] Single source of truth for data
|
|
10
|
+
- [ ] Explicit dependencies (no hidden coupling)
|
|
11
|
+
|
|
12
|
+
## Scalability
|
|
13
|
+
- [ ] Stateless where possible
|
|
14
|
+
- [ ] Horizontal scaling considered
|
|
15
|
+
- [ ] Bottlenecks identified
|
|
16
|
+
- [ ] Caching strategy defined
|
|
17
|
+
|
|
18
|
+
## Resilience
|
|
19
|
+
- [ ] Failure modes documented
|
|
20
|
+
- [ ] Graceful degradation planned
|
|
21
|
+
- [ ] Recovery procedures defined
|
|
22
|
+
- [ ] Circuit breakers where needed
|
|
23
|
+
|
|
24
|
+
## Maintainability
|
|
25
|
+
- [ ] Clear boundaries between layers
|
|
26
|
+
- [ ] Easy to test in isolation
|
|
27
|
+
- [ ] Configuration externalized
|
|
28
|
+
- [ ] Logging and observability built-in
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Code Quality Checklist
|
|
2
|
+
|
|
3
|
+
> Universal principles for ANY programming language
|
|
4
|
+
|
|
5
|
+
## Universal Principles
|
|
6
|
+
- [ ] Single Responsibility: Each unit does ONE thing well
|
|
7
|
+
- [ ] DRY: No duplicated logic (extract shared code)
|
|
8
|
+
- [ ] KISS: Simplest solution that works
|
|
9
|
+
- [ ] Clear naming: Self-documenting identifiers
|
|
10
|
+
- [ ] Consistent patterns: Match existing codebase style
|
|
11
|
+
|
|
12
|
+
## Error Handling
|
|
13
|
+
- [ ] All error paths handled gracefully
|
|
14
|
+
- [ ] Meaningful error messages
|
|
15
|
+
- [ ] No silent failures
|
|
16
|
+
- [ ] Proper resource cleanup (files, connections, memory)
|
|
17
|
+
|
|
18
|
+
## Edge Cases
|
|
19
|
+
- [ ] Null/nil/None handling
|
|
20
|
+
- [ ] Empty collections handled
|
|
21
|
+
- [ ] Boundary conditions tested
|
|
22
|
+
- [ ] Invalid input rejected early
|
|
23
|
+
|
|
24
|
+
## Code Organization
|
|
25
|
+
- [ ] Functions/methods are small and focused
|
|
26
|
+
- [ ] Related code grouped together
|
|
27
|
+
- [ ] Clear module/package boundaries
|
|
28
|
+
- [ ] No circular dependencies
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Data Checklist
|
|
2
|
+
|
|
3
|
+
> Applies to: SQL, NoSQL, GraphQL, File storage, Caching
|
|
4
|
+
|
|
5
|
+
## Data Integrity
|
|
6
|
+
- [ ] Schema/structure defined
|
|
7
|
+
- [ ] Constraints enforced
|
|
8
|
+
- [ ] Transactions used appropriately
|
|
9
|
+
- [ ] Referential integrity maintained
|
|
10
|
+
|
|
11
|
+
## Query Performance
|
|
12
|
+
- [ ] Indexes on frequent queries
|
|
13
|
+
- [ ] N+1 queries eliminated
|
|
14
|
+
- [ ] Query complexity analyzed
|
|
15
|
+
- [ ] Pagination for large datasets
|
|
16
|
+
|
|
17
|
+
## Data Operations
|
|
18
|
+
- [ ] Migrations versioned and reversible
|
|
19
|
+
- [ ] Backup and restore tested
|
|
20
|
+
- [ ] Data validation at boundary
|
|
21
|
+
- [ ] Soft deletes considered (if applicable)
|
|
22
|
+
|
|
23
|
+
## Caching
|
|
24
|
+
- [ ] Cache invalidation strategy defined
|
|
25
|
+
- [ ] TTL values appropriate
|
|
26
|
+
- [ ] Cache warming considered
|
|
27
|
+
- [ ] Cache hit/miss monitored
|
|
28
|
+
|
|
29
|
+
## Data Privacy
|
|
30
|
+
- [ ] PII identified and protected
|
|
31
|
+
- [ ] Data anonymization where needed
|
|
32
|
+
- [ ] Audit trail for sensitive data
|
|
33
|
+
- [ ] Data deletion procedures defined
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Documentation Checklist
|
|
2
|
+
|
|
3
|
+
> Applies to ALL projects
|
|
4
|
+
|
|
5
|
+
## Essential Docs
|
|
6
|
+
- [ ] README with quick start
|
|
7
|
+
- [ ] Installation instructions
|
|
8
|
+
- [ ] Configuration options documented
|
|
9
|
+
- [ ] Common use cases shown
|
|
10
|
+
|
|
11
|
+
## Code Documentation
|
|
12
|
+
- [ ] Public APIs documented
|
|
13
|
+
- [ ] Complex logic explained
|
|
14
|
+
- [ ] Architecture decisions recorded (ADRs)
|
|
15
|
+
- [ ] Diagrams for complex flows
|
|
16
|
+
|
|
17
|
+
## Operational Docs
|
|
18
|
+
- [ ] Deployment process documented
|
|
19
|
+
- [ ] Troubleshooting guide
|
|
20
|
+
- [ ] Runbooks for common issues
|
|
21
|
+
- [ ] Changelog maintained
|
|
22
|
+
|
|
23
|
+
## API Documentation
|
|
24
|
+
- [ ] All endpoints documented
|
|
25
|
+
- [ ] Request/response examples
|
|
26
|
+
- [ ] Error codes explained
|
|
27
|
+
- [ ] Authentication documented
|
|
28
|
+
|
|
29
|
+
## Maintenance
|
|
30
|
+
- [ ] Docs updated with code changes
|
|
31
|
+
- [ ] Version-specific documentation
|
|
32
|
+
- [ ] Broken links checked
|
|
33
|
+
- [ ] Examples tested and working
|