@fractary/faber-cli 1.5.41 → 1.5.43
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/plan/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/plan/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwDpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CA4B3C"}
|
|
@@ -31,6 +31,7 @@ export function createPlanCommand() {
|
|
|
31
31
|
.option('--json', 'Output as JSON (shorthand for --output json)')
|
|
32
32
|
.option('--limit <n>', 'Maximum number of issues to plan', parseInt)
|
|
33
33
|
.option('--order-by <strategy>', 'Order issues by: priority|created|updated (default: none)', 'none')
|
|
34
|
+
.option('--force-new', 'Force new plan generation even if a plan already exists')
|
|
34
35
|
.option('--order-direction <dir>', 'Order direction: asc|desc (default: desc)', 'desc')
|
|
35
36
|
.action(async (workId, options) => {
|
|
36
37
|
try {
|
|
@@ -330,22 +331,6 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
330
331
|
const { organization, project } = getRepoInfoFromConfig(config);
|
|
331
332
|
const branch = `feature/${issue.number}`;
|
|
332
333
|
const worktree = `~/.claude-worktrees/${organization}-${project}-${issue.number}`;
|
|
333
|
-
// Generate deterministic plan from resolved workflow
|
|
334
|
-
if (outputFormat === 'text') {
|
|
335
|
-
console.log(chalk.gray(' → Generating plan...'));
|
|
336
|
-
process.stdout.write(''); // Force flush
|
|
337
|
-
}
|
|
338
|
-
const plan = await anthropicClient.generatePlan({
|
|
339
|
-
workflow: issue.workflow,
|
|
340
|
-
issueTitle: issue.title,
|
|
341
|
-
issueDescription: issue.description,
|
|
342
|
-
issueNumber: issue.number,
|
|
343
|
-
});
|
|
344
|
-
// Apply autonomy override if provided (takes precedence over workflow-level autonomy)
|
|
345
|
-
if (options.autonomy) {
|
|
346
|
-
plan.autonomy = options.autonomy;
|
|
347
|
-
}
|
|
348
|
-
const planId = plan.id;
|
|
349
334
|
// Create branch without checking it out (so it won't conflict with worktree creation)
|
|
350
335
|
if (!options.noBranch) {
|
|
351
336
|
if (outputFormat === 'text') {
|
|
@@ -408,6 +393,47 @@ async function planSingleIssue(issue, config, repoClient, anthropicClient, optio
|
|
|
408
393
|
// Non-fatal: if cleanup fails, workflow-run will handle conflict detection
|
|
409
394
|
}
|
|
410
395
|
}
|
|
396
|
+
// Check for existing plan in worktree (skip if found, unless --force-new)
|
|
397
|
+
if (!options.forceNew && !options.noWorktree) {
|
|
398
|
+
const runsDir = path.join(worktreePath, '.fractary', 'faber', 'runs');
|
|
399
|
+
try {
|
|
400
|
+
const entries = await fs.readdir(runsDir);
|
|
401
|
+
for (const entry of entries) {
|
|
402
|
+
const planFile = path.join(runsDir, entry, 'plan.json');
|
|
403
|
+
try {
|
|
404
|
+
await fs.access(planFile);
|
|
405
|
+
// Found existing plan
|
|
406
|
+
if (outputFormat === 'text') {
|
|
407
|
+
console.log(chalk.yellow(` ⚠️ Plan already exists: ${entry} — skipping (use --force-new to regenerate)`));
|
|
408
|
+
}
|
|
409
|
+
return {
|
|
410
|
+
issue,
|
|
411
|
+
planId: entry,
|
|
412
|
+
branch,
|
|
413
|
+
worktree: worktreePath,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
catch { /* no plan.json in this entry */ }
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
catch { /* runs dir doesn't exist — proceed with planning */ }
|
|
420
|
+
}
|
|
421
|
+
// Generate deterministic plan from resolved workflow
|
|
422
|
+
if (outputFormat === 'text') {
|
|
423
|
+
console.log(chalk.gray(' → Generating plan...'));
|
|
424
|
+
process.stdout.write(''); // Force flush
|
|
425
|
+
}
|
|
426
|
+
const plan = await anthropicClient.generatePlan({
|
|
427
|
+
workflow: issue.workflow,
|
|
428
|
+
issueTitle: issue.title,
|
|
429
|
+
issueDescription: issue.description,
|
|
430
|
+
issueNumber: issue.number,
|
|
431
|
+
});
|
|
432
|
+
// Apply autonomy override if provided (takes precedence over workflow-level autonomy)
|
|
433
|
+
if (options.autonomy) {
|
|
434
|
+
plan.autonomy = options.autonomy;
|
|
435
|
+
}
|
|
436
|
+
const planId = plan.id;
|
|
411
437
|
// Write plan to worktree
|
|
412
438
|
if (!options.noWorktree) {
|
|
413
439
|
// Validate plan ID format (prevent path traversal via malicious plan IDs)
|