claude-devloop 1.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.
Files changed (90) hide show
  1. package/README.md +340 -0
  2. package/dist/cli.d.ts +4 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +90 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/config.d.ts +9 -0
  7. package/dist/commands/config.d.ts.map +1 -0
  8. package/dist/commands/config.js +80 -0
  9. package/dist/commands/config.js.map +1 -0
  10. package/dist/commands/continue.d.ts +11 -0
  11. package/dist/commands/continue.d.ts.map +1 -0
  12. package/dist/commands/continue.js +167 -0
  13. package/dist/commands/continue.js.map +1 -0
  14. package/dist/commands/feature.d.ts +7 -0
  15. package/dist/commands/feature.d.ts.map +1 -0
  16. package/dist/commands/feature.js +123 -0
  17. package/dist/commands/feature.js.map +1 -0
  18. package/dist/commands/init.d.ts +8 -0
  19. package/dist/commands/init.d.ts.map +1 -0
  20. package/dist/commands/init.js +401 -0
  21. package/dist/commands/init.js.map +1 -0
  22. package/dist/commands/run.d.ts +12 -0
  23. package/dist/commands/run.d.ts.map +1 -0
  24. package/dist/commands/run.js +82 -0
  25. package/dist/commands/run.js.map +1 -0
  26. package/dist/commands/shared.d.ts +22 -0
  27. package/dist/commands/shared.d.ts.map +1 -0
  28. package/dist/commands/shared.js +32 -0
  29. package/dist/commands/shared.js.map +1 -0
  30. package/dist/commands/status.d.ts +8 -0
  31. package/dist/commands/status.d.ts.map +1 -0
  32. package/dist/commands/status.js +305 -0
  33. package/dist/commands/status.js.map +1 -0
  34. package/dist/commands/workspace.d.ts +2 -0
  35. package/dist/commands/workspace.d.ts.map +1 -0
  36. package/dist/commands/workspace.js +19 -0
  37. package/dist/commands/workspace.js.map +1 -0
  38. package/dist/constants.d.ts +21 -0
  39. package/dist/constants.d.ts.map +1 -0
  40. package/dist/constants.js +21 -0
  41. package/dist/constants.js.map +1 -0
  42. package/dist/core/claude.d.ts +20 -0
  43. package/dist/core/claude.d.ts.map +1 -0
  44. package/dist/core/claude.js +401 -0
  45. package/dist/core/claude.js.map +1 -0
  46. package/dist/core/commit-format.d.ts +22 -0
  47. package/dist/core/commit-format.d.ts.map +1 -0
  48. package/dist/core/commit-format.js +148 -0
  49. package/dist/core/commit-format.js.map +1 -0
  50. package/dist/core/config.d.ts +30 -0
  51. package/dist/core/config.d.ts.map +1 -0
  52. package/dist/core/config.js +130 -0
  53. package/dist/core/config.js.map +1 -0
  54. package/dist/core/feature-session.d.ts +8 -0
  55. package/dist/core/feature-session.d.ts.map +1 -0
  56. package/dist/core/feature-session.js +58 -0
  57. package/dist/core/feature-session.js.map +1 -0
  58. package/dist/core/git.d.ts +81 -0
  59. package/dist/core/git.d.ts.map +1 -0
  60. package/dist/core/git.js +475 -0
  61. package/dist/core/git.js.map +1 -0
  62. package/dist/core/loop.d.ts +3 -0
  63. package/dist/core/loop.d.ts.map +1 -0
  64. package/dist/core/loop.js +469 -0
  65. package/dist/core/loop.js.map +1 -0
  66. package/dist/core/session.d.ts +7 -0
  67. package/dist/core/session.d.ts.map +1 -0
  68. package/dist/core/session.js +57 -0
  69. package/dist/core/session.js.map +1 -0
  70. package/dist/index.d.ts +3 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +4 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/parser/progress.d.ts +7 -0
  75. package/dist/parser/progress.d.ts.map +1 -0
  76. package/dist/parser/progress.js +132 -0
  77. package/dist/parser/progress.js.map +1 -0
  78. package/dist/parser/requirements.d.ts +6 -0
  79. package/dist/parser/requirements.d.ts.map +1 -0
  80. package/dist/parser/requirements.js +126 -0
  81. package/dist/parser/requirements.js.map +1 -0
  82. package/dist/types/feature.d.ts +15 -0
  83. package/dist/types/feature.d.ts.map +1 -0
  84. package/dist/types/feature.js +2 -0
  85. package/dist/types/feature.js.map +1 -0
  86. package/dist/types/index.d.ts +78 -0
  87. package/dist/types/index.d.ts.map +1 -0
  88. package/dist/types/index.js +3 -0
  89. package/dist/types/index.js.map +1 -0
  90. package/package.json +40 -0
@@ -0,0 +1,401 @@
1
+ import { spawn } from 'child_process';
2
+ import * as fs from 'fs/promises';
3
+ import * as fsSync from 'fs';
4
+ import * as path from 'path';
5
+ import * as os from 'os';
6
+ /**
7
+ * Parse token usage from Claude JSON output
8
+ */
9
+ function parseTokenUsage(jsonOutput) {
10
+ try {
11
+ const usage = jsonOutput?.usage;
12
+ if (!usage)
13
+ return undefined;
14
+ const inputTokens = usage.input_tokens || 0;
15
+ const outputTokens = usage.output_tokens || 0;
16
+ const cacheCreationTokens = usage.cache_creation_input_tokens || 0;
17
+ const cacheReadTokens = usage.cache_read_input_tokens || 0;
18
+ return {
19
+ inputTokens,
20
+ outputTokens,
21
+ cacheCreationTokens,
22
+ cacheReadTokens,
23
+ totalTokens: inputTokens + outputTokens + cacheCreationTokens + cacheReadTokens,
24
+ costUsd: jsonOutput?.total_cost_usd || 0
25
+ };
26
+ }
27
+ catch {
28
+ return undefined;
29
+ }
30
+ }
31
+ /**
32
+ * Classifies an error from Claude CLI output to determine if it's an API error
33
+ * (which should stop the loop) or a task failure (which can continue).
34
+ */
35
+ function classifyError(stderr, errorMessage) {
36
+ const errorText = ((stderr || '') + (errorMessage || '')).toLowerCase();
37
+ // Rate limit errors (400/429)
38
+ if (errorText.includes('rate limit') ||
39
+ errorText.includes('api usage limit') ||
40
+ errorText.includes('429') ||
41
+ (errorText.includes('400') && errorText.includes('limit'))) {
42
+ return 'rate_limit';
43
+ }
44
+ // API overload (503)
45
+ if (errorText.includes('overload') || errorText.includes('503')) {
46
+ return 'api_overload';
47
+ }
48
+ // Authentication errors (401)
49
+ if (errorText.includes('401') ||
50
+ errorText.includes('unauthorized') ||
51
+ errorText.includes('authentication')) {
52
+ return 'auth_error';
53
+ }
54
+ // Network errors
55
+ if (errorText.includes('econnrefused') ||
56
+ errorText.includes('enotfound') ||
57
+ errorText.includes('timeout') ||
58
+ errorText.includes('network')) {
59
+ return 'network_error';
60
+ }
61
+ // If it has "api error" in it, treat as unknown API error
62
+ if (errorText.includes('api error')) {
63
+ return 'unknown';
64
+ }
65
+ // Otherwise it's likely a task failure (Claude ran but task didn't complete)
66
+ return 'task_failure';
67
+ }
68
+ /**
69
+ * Checks if an error type represents an API-level error that should stop the loop.
70
+ */
71
+ export function isApiError(errorType) {
72
+ return errorType !== undefined && errorType !== 'task_failure';
73
+ }
74
+ /**
75
+ * Creates a workspace-scoped Claude settings file that restricts
76
+ * file operations to the workspace directory only.
77
+ */
78
+ export async function ensureWorkspaceSettings(workspacePath) {
79
+ const claudeDir = path.join(workspacePath, '.claude');
80
+ const settingsPath = path.join(claudeDir, 'settings.json');
81
+ try {
82
+ await fs.mkdir(claudeDir, { recursive: true });
83
+ }
84
+ catch {
85
+ // Directory exists
86
+ }
87
+ const settings = {
88
+ permissions: {
89
+ allow: [
90
+ `Bash(cd:${workspacePath})`,
91
+ `Bash(cd:${workspacePath}/**)`,
92
+ "Bash(npm:*)",
93
+ "Bash(npx:*)",
94
+ "Bash(node:*)",
95
+ "Bash(git:*)",
96
+ "Bash(tsc:*)",
97
+ "Bash(mkdir:*)",
98
+ "Bash(ls:*)",
99
+ "Bash(cat:*)",
100
+ "Bash(echo:*)",
101
+ "Read",
102
+ "Write",
103
+ "Edit",
104
+ "Glob",
105
+ "Grep"
106
+ ],
107
+ deny: [
108
+ "Bash(rm -rf /)",
109
+ "Bash(rm -rf ~)",
110
+ "Bash(rm -rf ..)",
111
+ "Bash(sudo:*)",
112
+ "Bash(chmod:*)",
113
+ "Bash(chown:*)"
114
+ ]
115
+ },
116
+ restrictToWorkspace: true,
117
+ workspacePath: workspacePath
118
+ };
119
+ await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
120
+ }
121
+ /**
122
+ * Format a tool name and input into a human-readable activity string.
123
+ */
124
+ function formatToolActivity(toolName, toolInput) {
125
+ // Extract relevant info from tool input
126
+ let detail = '';
127
+ if (toolInput) {
128
+ // Common patterns in tool inputs
129
+ if (toolInput.file_path) {
130
+ detail = toolInput.file_path;
131
+ }
132
+ else if (toolInput.path) {
133
+ detail = toolInput.path;
134
+ }
135
+ else if (toolInput.pattern) {
136
+ detail = toolInput.pattern;
137
+ }
138
+ else if (toolInput.command) {
139
+ // For bash, show just the first word of the command
140
+ detail = toolInput.command.split(' ')[0].split('\n')[0];
141
+ }
142
+ else if (toolInput.query) {
143
+ detail = toolInput.query.slice(0, 30);
144
+ }
145
+ else if (toolInput.url) {
146
+ detail = toolInput.url.slice(0, 30);
147
+ }
148
+ }
149
+ // Shorten long details
150
+ if (detail.length > 40) {
151
+ detail = '...' + detail.slice(-37);
152
+ }
153
+ switch (toolName.toLowerCase()) {
154
+ case 'read':
155
+ return detail ? `Reading ${detail}` : 'Reading file';
156
+ case 'write':
157
+ return detail ? `Writing ${detail}` : 'Writing file';
158
+ case 'edit':
159
+ return detail ? `Editing ${detail}` : 'Editing file';
160
+ case 'glob':
161
+ return detail ? `Finding ${detail}` : 'Searching files';
162
+ case 'grep':
163
+ return detail ? `Searching: ${detail}` : 'Searching in files';
164
+ case 'bash':
165
+ return detail ? `Running ${detail}` : 'Running command';
166
+ case 'webfetch':
167
+ return 'Fetching URL';
168
+ case 'websearch':
169
+ return detail ? `Searching: ${detail}` : 'Searching web';
170
+ case 'task':
171
+ return 'Running sub-task';
172
+ default:
173
+ return `Using ${toolName}`;
174
+ }
175
+ }
176
+ export async function invokeClaudeAutomated(prompt, workingDirectory, options = {}) {
177
+ const { verbose = false, onProgress } = options;
178
+ const startTime = Date.now();
179
+ // Ensure workspace settings exist
180
+ await ensureWorkspaceSettings(workingDirectory);
181
+ return new Promise((resolve) => {
182
+ // Write prompt to temp file to avoid command line length limits and quoting issues
183
+ const tempDir = os.tmpdir();
184
+ const promptFile = path.join(tempDir, `devloop-prompt-${Date.now()}.txt`);
185
+ fsSync.writeFileSync(promptFile, prompt, 'utf-8');
186
+ if (verbose) {
187
+ console.log(` Executing: claude -p [prompt from file] --dangerously-skip-permissions --output-format stream-json --add-dir "${workingDirectory}"`);
188
+ }
189
+ // Use stream-json format for real-time progress events
190
+ // Note: stream-json requires --verbose when using -p
191
+ const args = [
192
+ '-p', '-',
193
+ '--dangerously-skip-permissions',
194
+ '--output-format', 'stream-json',
195
+ '--verbose',
196
+ '--add-dir', workingDirectory
197
+ ];
198
+ const child = spawn('claude', args, {
199
+ cwd: workingDirectory,
200
+ shell: true,
201
+ env: { ...process.env },
202
+ stdio: ['pipe', 'pipe', 'pipe']
203
+ });
204
+ // Pipe the prompt file content to stdin
205
+ const promptContent = fsSync.readFileSync(promptFile, 'utf-8');
206
+ child.stdin?.write(promptContent);
207
+ child.stdin?.end();
208
+ let stderr = '';
209
+ let resultText = '';
210
+ let tokenUsage;
211
+ let isError = false;
212
+ let lineBuffer = '';
213
+ // Parse streaming JSON events from stdout
214
+ child.stdout?.on('data', (data) => {
215
+ const chunk = data.toString();
216
+ if (verbose) {
217
+ process.stdout.write(chunk);
218
+ }
219
+ // Buffer lines (events are newline-delimited JSON)
220
+ lineBuffer += chunk;
221
+ const lines = lineBuffer.split('\n');
222
+ lineBuffer = lines.pop() || ''; // Keep incomplete line in buffer
223
+ for (const line of lines) {
224
+ if (!line.trim())
225
+ continue;
226
+ try {
227
+ const event = JSON.parse(line);
228
+ // Handle different event types
229
+ if (event.type === 'content_block_start') {
230
+ // Tool usage starting
231
+ const block = event.content_block;
232
+ if (block?.type === 'tool_use' && block?.name && onProgress) {
233
+ const activity = formatToolActivity(block.name, block.input);
234
+ onProgress(activity);
235
+ }
236
+ }
237
+ else if (event.type === 'content_block_delta') {
238
+ // Tool input being streamed (partial)
239
+ const delta = event.delta;
240
+ if (delta?.type === 'input_json_delta' && onProgress) {
241
+ // Could parse partial input here if needed
242
+ }
243
+ }
244
+ else if (event.type === 'result') {
245
+ // Final result with token usage
246
+ resultText = event.result || '';
247
+ isError = event.is_error === true;
248
+ tokenUsage = parseTokenUsage(event);
249
+ if (verbose && tokenUsage) {
250
+ console.log(` Token usage: ${tokenUsage.totalTokens} total (${tokenUsage.inputTokens} in, ${tokenUsage.outputTokens} out)`);
251
+ }
252
+ }
253
+ else if (event.type === 'assistant' && event.message?.content) {
254
+ // Assistant message with tool uses
255
+ for (const block of event.message.content) {
256
+ if (block.type === 'tool_use' && block.name && onProgress) {
257
+ const activity = formatToolActivity(block.name, block.input);
258
+ onProgress(activity);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ catch {
264
+ // Not valid JSON, ignore
265
+ }
266
+ }
267
+ });
268
+ // Collect stderr for error messages
269
+ child.stderr?.on('data', (data) => {
270
+ const chunk = data.toString();
271
+ stderr += chunk;
272
+ if (verbose) {
273
+ process.stderr.write(chunk);
274
+ }
275
+ });
276
+ child.on('close', (code) => {
277
+ // Clean up temp file
278
+ try {
279
+ fsSync.unlinkSync(promptFile);
280
+ }
281
+ catch {
282
+ // Ignore cleanup errors
283
+ }
284
+ // Process any remaining buffered line
285
+ if (lineBuffer.trim()) {
286
+ try {
287
+ const event = JSON.parse(lineBuffer);
288
+ if (event.type === 'result') {
289
+ resultText = event.result || resultText;
290
+ isError = event.is_error === true;
291
+ tokenUsage = parseTokenUsage(event) || tokenUsage;
292
+ }
293
+ }
294
+ catch {
295
+ // Ignore
296
+ }
297
+ }
298
+ const duration = Date.now() - startTime;
299
+ const hasError = code !== 0 || isError;
300
+ // Combine all available error information
301
+ let errorMessage;
302
+ if (hasError) {
303
+ const parts = [];
304
+ if (stderr)
305
+ parts.push(stderr.trim());
306
+ if (resultText && resultText.includes('API Error')) {
307
+ parts.push(resultText);
308
+ }
309
+ errorMessage = parts.join('\n') || 'Unknown error';
310
+ }
311
+ const errorType = hasError ? classifyError(errorMessage || stderr || '', null) : undefined;
312
+ resolve({
313
+ success: !hasError,
314
+ output: resultText,
315
+ error: errorMessage,
316
+ errorType,
317
+ duration,
318
+ tokenUsage
319
+ });
320
+ });
321
+ child.on('error', (err) => {
322
+ // Clean up temp file
323
+ try {
324
+ fsSync.unlinkSync(promptFile);
325
+ }
326
+ catch {
327
+ // Ignore cleanup errors
328
+ }
329
+ resolve({
330
+ success: false,
331
+ output: '',
332
+ error: err.message,
333
+ errorType: classifyError(err.message, null),
334
+ duration: Date.now() - startTime,
335
+ tokenUsage: undefined
336
+ });
337
+ });
338
+ });
339
+ }
340
+ export function spawnClaudeInteractive(workingDirectory, sessionId) {
341
+ const args = [];
342
+ if (sessionId) {
343
+ args.push('--resume', sessionId);
344
+ }
345
+ // Spawn Claude in fully interactive mode (no -p flag)
346
+ const child = spawn('claude', args, {
347
+ cwd: workingDirectory,
348
+ shell: true,
349
+ stdio: 'inherit',
350
+ env: { ...process.env }
351
+ });
352
+ return child;
353
+ }
354
+ export function buildTaskPrompt(task, requirementsPath, progressPath, workspacePath) {
355
+ return `You are working on an automated development task. Follow these instructions carefully:
356
+
357
+ WORKSPACE RESTRICTION:
358
+ You are ONLY allowed to work within: ${workspacePath}
359
+ - Do NOT read, write, or modify any files outside this directory
360
+ - Do NOT run commands that affect files outside this directory
361
+ - All file paths must be within the workspace
362
+
363
+ 1. READ the requirements file at: ${requirementsPath}
364
+ 2. READ the progress file at: ${progressPath} (if it exists)
365
+
366
+ YOUR CURRENT TASK:
367
+ - Task ID: ${task.id}
368
+ - Title: ${task.title}
369
+ - Description: ${task.description}
370
+ - Priority: ${task.priority}
371
+
372
+ INSTRUCTIONS:
373
+ 1. Complete the task described above
374
+ 2. Make all necessary code changes WITHIN THE WORKSPACE ONLY
375
+ 3. After completing the task, update the requirements file to mark task ${task.id} as "done" by changing its Status line from "pending" to "done"
376
+ 4. Do NOT work on any other tasks
377
+
378
+ IMPORTANT:
379
+ - Focus only on this specific task
380
+ - Make clean, well-documented changes
381
+ - If you encounter blockers, document them but still attempt the task
382
+ - Update the task status to "done" when complete
383
+ - NEVER modify files outside ${workspacePath}
384
+
385
+ Begin working on ${task.id} now.`;
386
+ }
387
+ export async function checkClaudeInstalled() {
388
+ return new Promise((resolve) => {
389
+ const child = spawn('claude', ['--version'], {
390
+ shell: true,
391
+ stdio: 'pipe'
392
+ });
393
+ child.on('close', (code) => {
394
+ resolve(code === 0);
395
+ });
396
+ child.on('error', () => {
397
+ resolve(false);
398
+ });
399
+ });
400
+ }
401
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/core/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface CommitFormatDetection {
2
+ detected: boolean;
3
+ format?: string;
4
+ formatFailed?: string;
5
+ source?: string;
6
+ }
7
+ export interface CommitVariables {
8
+ feature?: string;
9
+ iteration: number;
10
+ status: 'Complete' | 'Attempted';
11
+ taskId: string;
12
+ title: string;
13
+ }
14
+ /**
15
+ * Detects commit message format from git hooks and config files
16
+ */
17
+ export declare function detectCommitFormat(workspace: string): Promise<CommitFormatDetection>;
18
+ /**
19
+ * Applies commit message template with variable substitution
20
+ */
21
+ export declare function formatCommitMessage(template: string, variables: CommitVariables): string;
22
+ //# sourceMappingURL=commit-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit-format.d.ts","sourceRoot":"","sources":["../../src/core/commit-format.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,GAAG,WAAW,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAmC1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,GAAG,MAAM,CAQxF"}
@@ -0,0 +1,148 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ /**
4
+ * Detects commit message format from git hooks and config files
5
+ */
6
+ export async function detectCommitFormat(workspace) {
7
+ // Check commitlint config
8
+ const commitlintFormat = await checkCommitlint(workspace);
9
+ if (commitlintFormat) {
10
+ return {
11
+ detected: true,
12
+ format: commitlintFormat.format,
13
+ formatFailed: commitlintFormat.formatFailed,
14
+ source: 'commitlint'
15
+ };
16
+ }
17
+ // Check git hooks
18
+ const gitHookFormat = await checkGitHooks(workspace);
19
+ if (gitHookFormat) {
20
+ return {
21
+ detected: true,
22
+ format: gitHookFormat.format,
23
+ formatFailed: gitHookFormat.formatFailed,
24
+ source: 'git hook'
25
+ };
26
+ }
27
+ // Check husky
28
+ const huskyFormat = await checkHusky(workspace);
29
+ if (huskyFormat) {
30
+ return {
31
+ detected: true,
32
+ format: huskyFormat.format,
33
+ formatFailed: huskyFormat.formatFailed,
34
+ source: 'husky'
35
+ };
36
+ }
37
+ return { detected: false };
38
+ }
39
+ /**
40
+ * Applies commit message template with variable substitution
41
+ */
42
+ export function formatCommitMessage(template, variables) {
43
+ return template
44
+ .replace(/\{feature\}/g, variables.feature || '')
45
+ .replace(/\{iteration\}/g, String(variables.iteration))
46
+ .replace(/\{status\}/g, variables.status)
47
+ .replace(/\{taskId\}/g, variables.taskId)
48
+ .replace(/\{title\}/g, variables.title)
49
+ .trim();
50
+ }
51
+ /**
52
+ * Check commitlint configuration files
53
+ */
54
+ async function checkCommitlint(workspace) {
55
+ const configFiles = [
56
+ '.commitlintrc',
57
+ '.commitlintrc.json',
58
+ '.commitlintrc.js',
59
+ 'commitlint.config.js'
60
+ ];
61
+ for (const configFile of configFiles) {
62
+ const configPath = path.join(workspace, configFile);
63
+ try {
64
+ await fs.access(configPath);
65
+ // If commitlint config exists, assume conventional commits
66
+ // Suggest format based on conventional commits pattern
67
+ return {
68
+ format: 'feat({feature}): {title}',
69
+ formatFailed: 'wip({feature}): {title}'
70
+ };
71
+ }
72
+ catch {
73
+ // File doesn't exist, try next
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+ /**
79
+ * Check git hooks for commit message patterns
80
+ */
81
+ async function checkGitHooks(workspace) {
82
+ const hookPaths = [
83
+ path.join(workspace, '.git', 'hooks', 'commit-msg'),
84
+ path.join(workspace, '.git', 'hooks', 'pre-commit')
85
+ ];
86
+ for (const hookPath of hookPaths) {
87
+ try {
88
+ const content = await fs.readFile(hookPath, 'utf-8');
89
+ // Check for conventional commits pattern
90
+ if (/\^?\(feat\|fix\|docs\|chore\)/i.test(content)) {
91
+ return {
92
+ format: 'feat({feature}): {title}',
93
+ formatFailed: 'wip({feature}): {title}'
94
+ };
95
+ }
96
+ // Check for Jira-style pattern
97
+ if (/\[A-Z\]\+-\\d\+/i.test(content) || /\^?\[A-Z\]\+-\\d\+/i.test(content)) {
98
+ return {
99
+ format: '[{taskId}] {status} - {title}',
100
+ formatFailed: '[{taskId}] {status} - {title}'
101
+ };
102
+ }
103
+ }
104
+ catch {
105
+ // File doesn't exist or can't be read, try next
106
+ }
107
+ }
108
+ return null;
109
+ }
110
+ /**
111
+ * Check husky configuration
112
+ */
113
+ async function checkHusky(workspace) {
114
+ // Check .husky/commit-msg
115
+ const huskyHookPath = path.join(workspace, '.husky', 'commit-msg');
116
+ try {
117
+ const content = await fs.readFile(huskyHookPath, 'utf-8');
118
+ // If it mentions commitlint, use conventional commits
119
+ if (/commitlint/.test(content)) {
120
+ return {
121
+ format: 'feat({feature}): {title}',
122
+ formatFailed: 'wip({feature}): {title}'
123
+ };
124
+ }
125
+ }
126
+ catch {
127
+ // File doesn't exist
128
+ }
129
+ // Check package.json for husky config
130
+ try {
131
+ const packageJsonPath = path.join(workspace, 'package.json');
132
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
133
+ if (packageJson.husky?.hooks?.['commit-msg']) {
134
+ const hook = packageJson.husky.hooks['commit-msg'];
135
+ if (/commitlint/.test(hook)) {
136
+ return {
137
+ format: 'feat({feature}): {title}',
138
+ formatFailed: 'wip({feature}): {title}'
139
+ };
140
+ }
141
+ }
142
+ }
143
+ catch {
144
+ // File doesn't exist or invalid JSON
145
+ }
146
+ return null;
147
+ }
148
+ //# sourceMappingURL=commit-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commit-format.js","sourceRoot":"","sources":["../../src/core/commit-format.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { GlobalConfig } from '../types/index.js';
2
+ export declare function ensureConfigDir(): Promise<void>;
3
+ export declare function readGlobalConfig(): Promise<GlobalConfig>;
4
+ export declare function writeGlobalConfig(config: GlobalConfig): Promise<void>;
5
+ export declare function getDefaultWorkspace(): Promise<string | null>;
6
+ export declare function setDefaultWorkspace(workspacePath: string): Promise<void>;
7
+ export declare function resolveWorkspace(cliWorkspace?: string): Promise<string>;
8
+ export declare function getRequirementsPath(workspace: string): string;
9
+ export declare function getProgressPath(workspace: string): string;
10
+ export declare function getSessionPath(workspace: string): string;
11
+ /**
12
+ * Validates a feature name to ensure it's a safe filename
13
+ * @throws Error if feature name is invalid
14
+ */
15
+ export declare function validateFeatureName(feature: string): void;
16
+ /**
17
+ * Resolves feature input to normalized paths
18
+ * Handles both short form (auth) and explicit paths (requirements/auth.md)
19
+ */
20
+ export declare function resolveFeaturePath(workspace: string, featureInput: string): {
21
+ featureName: string;
22
+ requirementsPath: string;
23
+ progressPath: string;
24
+ };
25
+ export declare function getFeatureRequirementsPath(workspace: string, feature: string): string;
26
+ export declare function getFeatureProgressPath(workspace: string, feature: string): string;
27
+ export declare function getWorkspaceConfigPath(workspace: string): string;
28
+ export declare function readWorkspaceConfig(workspace: string): Promise<import('../types/feature.js').WorkspaceConfig>;
29
+ export declare function writeWorkspaceConfig(workspace: string, config: import('../types/feature.js').WorkspaceConfig): Promise<void>;
30
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAUjD,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAMrD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC,CAO9D;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGlE;AAED,wBAAsB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9E;AAED,wBAAsB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY7E;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAczD;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB,CA6BA;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAErF;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjF;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,qBAAqB,EAAE,eAAe,CAAC,CAQnH;AAED,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,qBAAqB,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlI"}