@fractary/faber-cli 1.5.42 → 1.5.44

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;AAuDpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CA2B3C"}
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)
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAsJ1C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAiF7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAyB7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAoB5C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA2B9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA8B9C;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAoCrD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CA4BrD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CA0CtD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAkDpD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAchD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAgB/C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/workflow/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAsJ1C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAiF7C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAyB7C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAoB5C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA2B9C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CA8B9C;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAoCrD;AAED;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CA4BrD;AAED;;GAEG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CA0CtD;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAkDpD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAehD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAgB/C"}
@@ -538,6 +538,7 @@ export function createBatchPlanCommand() {
538
538
  .requiredOption('--work-id <ids>', 'Comma-separated work item IDs (e.g., "258,259,260")')
539
539
  .option('--name <batch-id>', 'Custom batch name/ID (default: auto-generated timestamp)')
540
540
  .option('--autonomous', 'Continue on plan failures without prompting')
541
+ .option('--force-new', 'Force new plan generation even if plans already exist')
541
542
  .option('--json', 'Output as JSON')
542
543
  .action(async (options) => {
543
544
  try {
@@ -625,6 +626,7 @@ async function executeBatchPlanCommand(options) {
625
626
  batch_id: batchId,
626
627
  status: 'planning',
627
628
  autonomous: options.autonomous ?? false,
629
+ force_new: options.forceNew ?? false,
628
630
  created_at: now,
629
631
  updated_at: now,
630
632
  items: workIds.map((id) => ({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fractary/faber-cli",
3
- "version": "1.5.42",
3
+ "version": "1.5.44",
4
4
  "description": "FABER CLI - Command-line interface for FABER development toolkit",
5
5
  "main": "dist/index.js",
6
6
  "bin": {