awesome-slash 2.4.2
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-plugin/marketplace.json +54 -0
- package/.claude-plugin/plugin.json +11 -0
- package/.mcp.json +8 -0
- package/CHANGELOG.md +261 -0
- package/LICENSE +21 -0
- package/README.md +363 -0
- package/SECURITY.md +101 -0
- package/adapters/README.md +256 -0
- package/adapters/codex/README.md +272 -0
- package/adapters/codex/install.sh +179 -0
- package/adapters/opencode/README.md +301 -0
- package/adapters/opencode/install.sh +223 -0
- package/lib/patterns/review-patterns.js +511 -0
- package/lib/patterns/slop-patterns.js +647 -0
- package/lib/platform/detect-platform.js +535 -0
- package/lib/platform/verify-tools.js +235 -0
- package/lib/state/workflow-state.js +635 -0
- package/lib/state/workflow-state.schema.json +282 -0
- package/lib/utils/context-optimizer.js +227 -0
- package/mcp-server/index.js +303 -0
- package/mcp-server/package.json +23 -0
- package/package.json +63 -0
- package/plugins/deslop-around/.claude-plugin/plugin.json +20 -0
- package/plugins/deslop-around/commands/deslop-around.md +220 -0
- package/plugins/deslop-around/lib/patterns/review-patterns.js +511 -0
- package/plugins/deslop-around/lib/patterns/slop-patterns.js +641 -0
- package/plugins/deslop-around/lib/platform/detect-platform.js +514 -0
- package/plugins/deslop-around/lib/platform/verify-tools.js +235 -0
- package/plugins/deslop-around/lib/state/workflow-state.js +635 -0
- package/plugins/deslop-around/lib/state/workflow-state.schema.json +282 -0
- package/plugins/deslop-around/lib/utils/context-optimizer.js +222 -0
- package/plugins/next-task/.claude-plugin/plugin.json +24 -0
- package/plugins/next-task/agents/ci-fixer.md +236 -0
- package/plugins/next-task/agents/ci-monitor.md +291 -0
- package/plugins/next-task/agents/delivery-validator.md +451 -0
- package/plugins/next-task/agents/deslop-work.md +272 -0
- package/plugins/next-task/agents/docs-updater.md +506 -0
- package/plugins/next-task/agents/exploration-agent.md +277 -0
- package/plugins/next-task/agents/implementation-agent.md +427 -0
- package/plugins/next-task/agents/planning-agent.md +236 -0
- package/plugins/next-task/agents/policy-selector.md +248 -0
- package/plugins/next-task/agents/review-orchestrator.md +521 -0
- package/plugins/next-task/agents/simple-fixer.md +136 -0
- package/plugins/next-task/agents/task-discoverer.md +357 -0
- package/plugins/next-task/agents/test-coverage-checker.md +447 -0
- package/plugins/next-task/agents/worktree-manager.md +419 -0
- package/plugins/next-task/commands/delivery-approval.md +331 -0
- package/plugins/next-task/commands/next-task.md +627 -0
- package/plugins/next-task/commands/update-docs-around.md +418 -0
- package/plugins/next-task/hooks/hooks.json +14 -0
- package/plugins/next-task/lib/patterns/review-patterns.js +511 -0
- package/plugins/next-task/lib/patterns/slop-patterns.js +641 -0
- package/plugins/next-task/lib/platform/detect-platform.js +514 -0
- package/plugins/next-task/lib/platform/verify-tools.js +235 -0
- package/plugins/next-task/lib/state/tasks-registry.schema.json +85 -0
- package/plugins/next-task/lib/state/workflow-state.js +635 -0
- package/plugins/next-task/lib/state/workflow-state.schema.json +282 -0
- package/plugins/next-task/lib/state/worktree-status.schema.json +219 -0
- package/plugins/next-task/lib/utils/context-optimizer.js +222 -0
- package/plugins/project-review/.claude-plugin/plugin.json +20 -0
- package/plugins/project-review/commands/project-review-agents.md +286 -0
- package/plugins/project-review/commands/project-review-github.md +142 -0
- package/plugins/project-review/commands/project-review.md +273 -0
- package/plugins/project-review/lib/patterns/review-patterns.js +511 -0
- package/plugins/project-review/lib/patterns/slop-patterns.js +641 -0
- package/plugins/project-review/lib/platform/detect-platform.js +514 -0
- package/plugins/project-review/lib/platform/verify-tools.js +235 -0
- package/plugins/project-review/lib/state/workflow-state.js +635 -0
- package/plugins/project-review/lib/state/workflow-state.schema.json +282 -0
- package/plugins/project-review/lib/utils/context-optimizer.js +222 -0
- package/plugins/reality-check/.claude-plugin/plugin.json +23 -0
- package/plugins/reality-check/README.md +156 -0
- package/plugins/reality-check/agents/code-explorer.md +353 -0
- package/plugins/reality-check/agents/doc-analyzer.md +337 -0
- package/plugins/reality-check/agents/issue-scanner.md +231 -0
- package/plugins/reality-check/agents/plan-synthesizer.md +479 -0
- package/plugins/reality-check/commands/scan.md +242 -0
- package/plugins/reality-check/commands/set.md +203 -0
- package/plugins/reality-check/lib/state/reality-check-state.js +509 -0
- package/plugins/reality-check/skills/reality-analysis/SKILL.md +317 -0
- package/plugins/ship/.claude-plugin/plugin.json +21 -0
- package/plugins/ship/commands/ship-ci-review-loop.md +443 -0
- package/plugins/ship/commands/ship-deployment.md +330 -0
- package/plugins/ship/commands/ship-error-handling.md +254 -0
- package/plugins/ship/commands/ship.md +370 -0
- package/plugins/ship/lib/patterns/review-patterns.js +511 -0
- package/plugins/ship/lib/patterns/slop-patterns.js +641 -0
- package/plugins/ship/lib/platform/detect-platform.js +514 -0
- package/plugins/ship/lib/platform/verify-tools.js +235 -0
- package/plugins/ship/lib/state/workflow-state.js +635 -0
- package/plugins/ship/lib/state/workflow-state.schema.json +282 -0
- package/plugins/ship/lib/utils/context-optimizer.js +222 -0
- package/scripts/install/claude.sh +50 -0
- package/scripts/install/codex.sh +181 -0
- package/scripts/install/opencode.sh +211 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "workflow-state.schema.json",
|
|
4
|
+
"title": "Workflow State",
|
|
5
|
+
"description": "Schema for next-task workflow orchestration state",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "workflow"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"version": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"pattern": "^\\d+\\.\\d+\\.\\d+$",
|
|
12
|
+
"description": "Schema version for migrations"
|
|
13
|
+
},
|
|
14
|
+
"workflow": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"required": ["id", "type", "status", "startedAt"],
|
|
17
|
+
"properties": {
|
|
18
|
+
"id": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^workflow-\\d{8}-\\d{6}-[a-z0-9]+$",
|
|
21
|
+
"description": "Unique workflow identifier"
|
|
22
|
+
},
|
|
23
|
+
"type": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["next-task", "ship", "manual"],
|
|
26
|
+
"description": "Workflow type"
|
|
27
|
+
},
|
|
28
|
+
"status": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"enum": ["pending", "in_progress", "paused", "completed", "failed", "aborted"],
|
|
31
|
+
"description": "Current workflow status"
|
|
32
|
+
},
|
|
33
|
+
"startedAt": {
|
|
34
|
+
"type": "string",
|
|
35
|
+
"format": "date-time",
|
|
36
|
+
"description": "Workflow start timestamp"
|
|
37
|
+
},
|
|
38
|
+
"lastUpdatedAt": {
|
|
39
|
+
"type": "string",
|
|
40
|
+
"format": "date-time",
|
|
41
|
+
"description": "Last state update timestamp"
|
|
42
|
+
},
|
|
43
|
+
"completedAt": {
|
|
44
|
+
"type": ["string", "null"],
|
|
45
|
+
"format": "date-time",
|
|
46
|
+
"description": "Workflow completion timestamp"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"policy": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"properties": {
|
|
53
|
+
"taskSource": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"enum": ["defaults", "gh-issues", "linear", "tasks-md", "custom"],
|
|
56
|
+
"default": "gh-issues"
|
|
57
|
+
},
|
|
58
|
+
"priorityFilter": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"enum": ["continue", "bugs", "security", "features", "all"],
|
|
61
|
+
"default": "continue"
|
|
62
|
+
},
|
|
63
|
+
"platform": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"enum": ["detected", "manual"],
|
|
66
|
+
"default": "detected"
|
|
67
|
+
},
|
|
68
|
+
"stoppingPoint": {
|
|
69
|
+
"type": "string",
|
|
70
|
+
"enum": ["implemented", "pr-created", "all-green", "merged", "deployed", "production"],
|
|
71
|
+
"default": "merged"
|
|
72
|
+
},
|
|
73
|
+
"mergeStrategy": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": ["squash", "merge", "rebase"],
|
|
76
|
+
"default": "squash"
|
|
77
|
+
},
|
|
78
|
+
"autoFix": {
|
|
79
|
+
"type": "boolean",
|
|
80
|
+
"default": true
|
|
81
|
+
},
|
|
82
|
+
"maxReviewIterations": {
|
|
83
|
+
"type": "integer",
|
|
84
|
+
"minimum": 1,
|
|
85
|
+
"maximum": 10,
|
|
86
|
+
"default": 3
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"task": {
|
|
91
|
+
"type": ["object", "null"],
|
|
92
|
+
"properties": {
|
|
93
|
+
"id": {
|
|
94
|
+
"type": "string",
|
|
95
|
+
"description": "Task identifier (issue number, Linear ID, etc.)"
|
|
96
|
+
},
|
|
97
|
+
"source": {
|
|
98
|
+
"type": "string",
|
|
99
|
+
"enum": ["github", "linear", "tasks-md", "manual"]
|
|
100
|
+
},
|
|
101
|
+
"title": {
|
|
102
|
+
"type": "string"
|
|
103
|
+
},
|
|
104
|
+
"description": {
|
|
105
|
+
"type": "string"
|
|
106
|
+
},
|
|
107
|
+
"labels": {
|
|
108
|
+
"type": "array",
|
|
109
|
+
"items": { "type": "string" }
|
|
110
|
+
},
|
|
111
|
+
"url": {
|
|
112
|
+
"type": ["string", "null"],
|
|
113
|
+
"format": "uri"
|
|
114
|
+
},
|
|
115
|
+
"linearId": {
|
|
116
|
+
"type": ["string", "null"]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"git": {
|
|
121
|
+
"type": ["object", "null"],
|
|
122
|
+
"properties": {
|
|
123
|
+
"originalBranch": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"description": "Branch before workflow started"
|
|
126
|
+
},
|
|
127
|
+
"workingBranch": {
|
|
128
|
+
"type": "string",
|
|
129
|
+
"description": "Feature branch for this task"
|
|
130
|
+
},
|
|
131
|
+
"worktreePath": {
|
|
132
|
+
"type": ["string", "null"],
|
|
133
|
+
"description": "Path to worktree if using isolated development"
|
|
134
|
+
},
|
|
135
|
+
"baseSha": {
|
|
136
|
+
"type": "string",
|
|
137
|
+
"description": "Base commit SHA when branched"
|
|
138
|
+
},
|
|
139
|
+
"currentSha": {
|
|
140
|
+
"type": "string",
|
|
141
|
+
"description": "Current HEAD commit SHA"
|
|
142
|
+
},
|
|
143
|
+
"isWorktree": {
|
|
144
|
+
"type": "boolean",
|
|
145
|
+
"default": false
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"pr": {
|
|
150
|
+
"type": ["object", "null"],
|
|
151
|
+
"properties": {
|
|
152
|
+
"number": {
|
|
153
|
+
"type": "integer"
|
|
154
|
+
},
|
|
155
|
+
"url": {
|
|
156
|
+
"type": "string",
|
|
157
|
+
"format": "uri"
|
|
158
|
+
},
|
|
159
|
+
"state": {
|
|
160
|
+
"type": "string",
|
|
161
|
+
"enum": ["draft", "open", "merged", "closed"]
|
|
162
|
+
},
|
|
163
|
+
"ciStatus": {
|
|
164
|
+
"type": "string",
|
|
165
|
+
"enum": ["pending", "running", "success", "failure", "unknown"]
|
|
166
|
+
},
|
|
167
|
+
"reviewState": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"enum": ["pending", "changes_requested", "approved", "dismissed"]
|
|
170
|
+
},
|
|
171
|
+
"lastCheckedAt": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"format": "date-time"
|
|
174
|
+
},
|
|
175
|
+
"checksWaitingCount": {
|
|
176
|
+
"type": "integer",
|
|
177
|
+
"default": 0
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"phases": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"current": {
|
|
185
|
+
"type": "string",
|
|
186
|
+
"enum": [
|
|
187
|
+
"policy-selection",
|
|
188
|
+
"task-discovery",
|
|
189
|
+
"worktree-setup",
|
|
190
|
+
"exploration",
|
|
191
|
+
"planning",
|
|
192
|
+
"user-approval",
|
|
193
|
+
"implementation",
|
|
194
|
+
"review-loop",
|
|
195
|
+
"delivery-approval",
|
|
196
|
+
"ship-prep",
|
|
197
|
+
"create-pr",
|
|
198
|
+
"ci-wait",
|
|
199
|
+
"comment-fix",
|
|
200
|
+
"merge",
|
|
201
|
+
"production-ci",
|
|
202
|
+
"deploy",
|
|
203
|
+
"production-release",
|
|
204
|
+
"complete"
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
"currentIteration": {
|
|
208
|
+
"type": "integer",
|
|
209
|
+
"minimum": 0,
|
|
210
|
+
"default": 0
|
|
211
|
+
},
|
|
212
|
+
"history": {
|
|
213
|
+
"type": "array",
|
|
214
|
+
"items": {
|
|
215
|
+
"type": "object",
|
|
216
|
+
"required": ["phase", "status", "startedAt"],
|
|
217
|
+
"properties": {
|
|
218
|
+
"phase": { "type": "string" },
|
|
219
|
+
"status": {
|
|
220
|
+
"type": "string",
|
|
221
|
+
"enum": ["pending", "in_progress", "completed", "failed", "skipped"]
|
|
222
|
+
},
|
|
223
|
+
"startedAt": { "type": "string", "format": "date-time" },
|
|
224
|
+
"completedAt": { "type": ["string", "null"], "format": "date-time" },
|
|
225
|
+
"duration": { "type": "integer", "description": "Duration in milliseconds" },
|
|
226
|
+
"iteration": { "type": "integer" },
|
|
227
|
+
"result": { "type": "object" }
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
"agents": {
|
|
234
|
+
"type": ["object", "null"],
|
|
235
|
+
"properties": {
|
|
236
|
+
"lastRun": {
|
|
237
|
+
"type": "object",
|
|
238
|
+
"additionalProperties": {
|
|
239
|
+
"type": "object",
|
|
240
|
+
"properties": {
|
|
241
|
+
"status": { "type": "string", "enum": ["pending", "running", "completed", "failed"] },
|
|
242
|
+
"issues": { "type": "integer" },
|
|
243
|
+
"critical": { "type": "integer" },
|
|
244
|
+
"high": { "type": "integer" }
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
"totalIterations": { "type": "integer", "default": 0 },
|
|
249
|
+
"totalIssuesFound": { "type": "integer", "default": 0 },
|
|
250
|
+
"totalIssuesFixed": { "type": "integer", "default": 0 }
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
"checkpoints": {
|
|
254
|
+
"type": "object",
|
|
255
|
+
"properties": {
|
|
256
|
+
"canResume": {
|
|
257
|
+
"type": "boolean",
|
|
258
|
+
"default": true
|
|
259
|
+
},
|
|
260
|
+
"resumeFrom": {
|
|
261
|
+
"type": ["string", "null"],
|
|
262
|
+
"description": "Phase to resume from"
|
|
263
|
+
},
|
|
264
|
+
"resumeContext": {
|
|
265
|
+
"type": ["object", "null"],
|
|
266
|
+
"description": "Additional context needed for resume"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"metrics": {
|
|
271
|
+
"type": ["object", "null"],
|
|
272
|
+
"properties": {
|
|
273
|
+
"totalDuration": { "type": "integer", "description": "Total duration in milliseconds" },
|
|
274
|
+
"tokensUsed": { "type": "integer" },
|
|
275
|
+
"toolCalls": { "type": "integer" },
|
|
276
|
+
"filesModified": { "type": "integer" },
|
|
277
|
+
"linesAdded": { "type": "integer" },
|
|
278
|
+
"linesRemoved": { "type": "integer" }
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Optimizer Utilities
|
|
3
|
+
* Provides optimized git commands to minimize token usage while gathering context
|
|
4
|
+
*
|
|
5
|
+
* Target: Keep command execution under 50k tokens
|
|
6
|
+
*
|
|
7
|
+
* @author Avi Fenesh
|
|
8
|
+
* @license MIT
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Escape shell special characters for safe command interpolation
|
|
13
|
+
* Handles all dangerous shell metacharacters including command injection vectors
|
|
14
|
+
* @param {string} str - String to escape
|
|
15
|
+
* @returns {string} Escaped string safe for shell use
|
|
16
|
+
*/
|
|
17
|
+
function escapeShell(str) {
|
|
18
|
+
if (typeof str !== 'string') return '';
|
|
19
|
+
// Reject null bytes and newlines which could be used for injection
|
|
20
|
+
if (str.includes('\0') || str.includes('\n') || str.includes('\r')) {
|
|
21
|
+
throw new Error('Input contains invalid characters (null bytes or newlines)');
|
|
22
|
+
}
|
|
23
|
+
// Escape all shell metacharacters: " $ ` \ ! ; | & > < ( ) { } [ ] * ? ~ # ' space tab
|
|
24
|
+
return str.replace(/["\$`\\!;|&><(){}[\]*?~#'\s]/g, '\\$&');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Escape single quotes for shell (replace ' with '\''
|
|
29
|
+
* @param {string} str - String to escape
|
|
30
|
+
* @returns {string} Escaped string safe for single-quoted shell use
|
|
31
|
+
*/
|
|
32
|
+
function escapeSingleQuotes(str) {
|
|
33
|
+
if (typeof str !== 'string') return '';
|
|
34
|
+
return str.replace(/'/g, "'\\''");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Validate and sanitize file extension
|
|
39
|
+
* @param {string} ext - Extension to validate
|
|
40
|
+
* @returns {string} Safe extension (alphanumeric only)
|
|
41
|
+
*/
|
|
42
|
+
function sanitizeExtension(ext) {
|
|
43
|
+
if (typeof ext !== 'string') return 'ts';
|
|
44
|
+
const safe = ext.replace(/[^a-zA-Z0-9]/g, '');
|
|
45
|
+
return safe || 'ts';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Git command optimization utilities for context efficiency
|
|
50
|
+
*/
|
|
51
|
+
const contextOptimizer = {
|
|
52
|
+
/**
|
|
53
|
+
* Get recent commits with minimal formatting
|
|
54
|
+
* @param {number} limit - Number of commits to retrieve (default: 10)
|
|
55
|
+
* @returns {string} Git command
|
|
56
|
+
*/
|
|
57
|
+
recentCommits: (limit = 10) =>
|
|
58
|
+
`git log --oneline --no-decorate -${limit} --format="%h %s"`,
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get compact git status (untracked files excluded)
|
|
62
|
+
* @returns {string} Git command
|
|
63
|
+
*/
|
|
64
|
+
compactStatus: () =>
|
|
65
|
+
'git status -uno --porcelain',
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get file changes between refs
|
|
69
|
+
* @param {string} ref - Reference to compare from (default: 'HEAD~5')
|
|
70
|
+
* @returns {string} Git command
|
|
71
|
+
*/
|
|
72
|
+
fileChanges: (ref = 'HEAD~5') =>
|
|
73
|
+
`git diff ${ref}..HEAD --name-status`,
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Get current branch name
|
|
77
|
+
* @returns {string} Git command
|
|
78
|
+
*/
|
|
79
|
+
currentBranch: () =>
|
|
80
|
+
'git branch --show-current',
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Get remote information (limited to 2 lines)
|
|
84
|
+
* @returns {string} Git command
|
|
85
|
+
*/
|
|
86
|
+
remoteInfo: () =>
|
|
87
|
+
'git remote -v | head -2',
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Check if there are stashed changes
|
|
91
|
+
* @returns {string} Git command
|
|
92
|
+
*/
|
|
93
|
+
hasStashes: () =>
|
|
94
|
+
'git stash list --oneline | wc -l',
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Get worktree list in porcelain format
|
|
98
|
+
* @returns {string} Git command
|
|
99
|
+
*/
|
|
100
|
+
worktreeList: () =>
|
|
101
|
+
'git worktree list --porcelain',
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get the age of a specific line (for TODO checking)
|
|
105
|
+
* @param {string} file - File path
|
|
106
|
+
* @param {number} line - Line number
|
|
107
|
+
* @returns {string} Git command
|
|
108
|
+
*/
|
|
109
|
+
lineAge: (file, line) => {
|
|
110
|
+
// Validate line is a positive integer
|
|
111
|
+
const lineNum = parseInt(line, 10);
|
|
112
|
+
if (!Number.isInteger(lineNum) || lineNum < 1) {
|
|
113
|
+
throw new Error('Line must be a positive integer');
|
|
114
|
+
}
|
|
115
|
+
// Escape file path for safe shell usage
|
|
116
|
+
const safeFile = escapeShell(file);
|
|
117
|
+
return `git blame -L ${lineNum},${lineNum} "${safeFile}" --porcelain | grep '^committer-time' | cut -d' ' -f2`;
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Find source files by extension
|
|
122
|
+
* @param {string} extension - File extension (e.g., 'ts', 'py', 'rs')
|
|
123
|
+
* @returns {string} Git command
|
|
124
|
+
*/
|
|
125
|
+
findSourceFiles: (extension = 'ts') => {
|
|
126
|
+
const safeExt = sanitizeExtension(extension);
|
|
127
|
+
return `git ls-files | grep '\\.${safeExt}$'`;
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get diff stat summary
|
|
132
|
+
* @param {string} ref - Reference to compare from (default: 'HEAD~5')
|
|
133
|
+
* @returns {string} Git command
|
|
134
|
+
*/
|
|
135
|
+
diffStat: (ref = 'HEAD~5') =>
|
|
136
|
+
`git diff ${ref}..HEAD --stat | head -20`,
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Get contributors list (limited to top 10)
|
|
140
|
+
* @returns {string} Git command
|
|
141
|
+
*/
|
|
142
|
+
contributors: () =>
|
|
143
|
+
'git shortlog -sn --no-merges | head -10',
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get last commit message
|
|
147
|
+
* @returns {string} Git command
|
|
148
|
+
*/
|
|
149
|
+
lastCommitMessage: () =>
|
|
150
|
+
'git log -1 --format=%s',
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get files changed in last commit
|
|
154
|
+
* @returns {string} Git command
|
|
155
|
+
*/
|
|
156
|
+
lastCommitFiles: () =>
|
|
157
|
+
'git diff-tree --no-commit-id --name-only -r HEAD',
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get branch list (local only, limited)
|
|
161
|
+
* @param {number} limit - Number of branches (default: 10)
|
|
162
|
+
* @returns {string} Git command
|
|
163
|
+
*/
|
|
164
|
+
branches: (limit = 10) =>
|
|
165
|
+
`git branch --format='%(refname:short)' | head -${limit}`,
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get tags list (limited)
|
|
169
|
+
* @param {number} limit - Number of tags (default: 10)
|
|
170
|
+
* @returns {string} Git command
|
|
171
|
+
*/
|
|
172
|
+
tags: (limit = 10) =>
|
|
173
|
+
`git tag --sort=-creatordate | head -${limit}`,
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get count of commits on current branch since branching from main
|
|
177
|
+
* @param {string} mainBranch - Main branch name (default: 'main')
|
|
178
|
+
* @returns {string} Git command
|
|
179
|
+
*/
|
|
180
|
+
commitsSinceBranch: (mainBranch = 'main') =>
|
|
181
|
+
`git rev-list --count ${mainBranch}..HEAD`,
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if working directory is clean
|
|
185
|
+
* @returns {string} Git command
|
|
186
|
+
*/
|
|
187
|
+
isClean: () =>
|
|
188
|
+
'git status --porcelain | wc -l',
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Get merge base with main branch
|
|
192
|
+
* @param {string} mainBranch - Main branch name (default: 'main')
|
|
193
|
+
* @returns {string} Git command
|
|
194
|
+
*/
|
|
195
|
+
mergeBase: (mainBranch = 'main') =>
|
|
196
|
+
`git merge-base ${mainBranch} HEAD`,
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get files modified in current branch (since branching)
|
|
200
|
+
* @param {string} mainBranch - Main branch name (default: 'main')
|
|
201
|
+
* @returns {string} Git command
|
|
202
|
+
*/
|
|
203
|
+
branchChangedFiles: (mainBranch = 'main') =>
|
|
204
|
+
`git diff ${mainBranch}...HEAD --name-only`,
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get commit count by author
|
|
208
|
+
* @param {string} author - Author name or email
|
|
209
|
+
* @returns {string} Git command
|
|
210
|
+
*/
|
|
211
|
+
authorCommitCount: (author) => {
|
|
212
|
+
const safeAuthor = escapeShell(author);
|
|
213
|
+
return `git log --author="${safeAuthor}" --oneline | wc -l`;
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Check if file exists in repository
|
|
218
|
+
* @param {string} file - File path
|
|
219
|
+
* @returns {string} Git command
|
|
220
|
+
*/
|
|
221
|
+
fileExists: (file) => {
|
|
222
|
+
const safeFile = escapeSingleQuotes(file);
|
|
223
|
+
return `git ls-files | grep -q '${safeFile}' && echo 'true' || echo 'false'`;
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
module.exports = contextOptimizer;
|