claude-autopm 2.2.0 ā 2.2.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/lib/cli/commands/prd.js +152 -86
- package/package.json +1 -1
package/lib/cli/commands/prd.js
CHANGED
|
@@ -310,13 +310,31 @@ async function prdNew(argv) {
|
|
|
310
310
|
// Build script path
|
|
311
311
|
const scriptPath = path.join(process.cwd(), '.claude', 'scripts', 'pm', 'prd-new.js');
|
|
312
312
|
|
|
313
|
+
// Debug: Show what we're looking for
|
|
314
|
+
if (process.env.DEBUG) {
|
|
315
|
+
console.log(chalk.gray(`\nDebug: Looking for script at: ${scriptPath}`));
|
|
316
|
+
console.log(chalk.gray(`Debug: Current directory: ${process.cwd()}`));
|
|
317
|
+
}
|
|
318
|
+
|
|
313
319
|
// Check if script exists
|
|
314
320
|
const scriptExists = await fs.pathExists(scriptPath);
|
|
315
321
|
if (!scriptExists) {
|
|
316
322
|
spinner.fail(chalk.red('PRD creation script not found'));
|
|
317
323
|
console.error(chalk.red('\nError: .claude/scripts/pm/prd-new.js not found'));
|
|
318
|
-
console.error(chalk.
|
|
319
|
-
|
|
324
|
+
console.error(chalk.red(`Expected location: ${scriptPath}`));
|
|
325
|
+
console.error(chalk.yellow('\nSolution: Run "autopm install" to install the framework'));
|
|
326
|
+
|
|
327
|
+
// Show what directories DO exist
|
|
328
|
+
const claudeDir = path.join(process.cwd(), '.claude');
|
|
329
|
+
const scriptsDir = path.join(claudeDir, 'scripts');
|
|
330
|
+
const pmDir = path.join(scriptsDir, 'pm');
|
|
331
|
+
|
|
332
|
+
console.error(chalk.gray('\nDirectory status:'));
|
|
333
|
+
console.error(chalk.gray(` .claude/ exists: ${await fs.pathExists(claudeDir)}`));
|
|
334
|
+
console.error(chalk.gray(` .claude/scripts/ exists: ${await fs.pathExists(scriptsDir)}`));
|
|
335
|
+
console.error(chalk.gray(` .claude/scripts/pm/ exists: ${await fs.pathExists(pmDir)}`));
|
|
336
|
+
|
|
337
|
+
process.exit(1);
|
|
320
338
|
}
|
|
321
339
|
|
|
322
340
|
// Build arguments
|
|
@@ -325,29 +343,57 @@ async function prdNew(argv) {
|
|
|
325
343
|
args.push('--template', argv.template);
|
|
326
344
|
}
|
|
327
345
|
|
|
346
|
+
if (process.env.DEBUG) {
|
|
347
|
+
console.log(chalk.gray(`Debug: Running: node ${args.join(' ')}`));
|
|
348
|
+
}
|
|
349
|
+
|
|
328
350
|
spinner.stop();
|
|
329
351
|
|
|
352
|
+
console.log(chalk.cyan(`\nš Starting PRD wizard for: ${argv.name}`));
|
|
353
|
+
if (argv.template) {
|
|
354
|
+
console.log(chalk.cyan(`š Using template: ${argv.template}`));
|
|
355
|
+
}
|
|
356
|
+
console.log(chalk.gray('Press Ctrl+C to cancel\n'));
|
|
357
|
+
|
|
330
358
|
// Spawn interactive process
|
|
331
359
|
const child = spawn('node', args, {
|
|
332
360
|
stdio: 'inherit',
|
|
333
|
-
cwd: process.cwd()
|
|
361
|
+
cwd: process.cwd(),
|
|
362
|
+
env: { ...process.env }
|
|
334
363
|
});
|
|
335
364
|
|
|
336
365
|
// Wait for completion
|
|
337
366
|
await new Promise((resolve, reject) => {
|
|
338
367
|
child.on('close', (code) => {
|
|
339
368
|
if (code === 0) {
|
|
369
|
+
console.log(chalk.green('\nā PRD created successfully'));
|
|
340
370
|
resolve();
|
|
371
|
+
} else if (code === null) {
|
|
372
|
+
console.error(chalk.yellow('\nā Process was terminated'));
|
|
373
|
+
reject(new Error('Process terminated'));
|
|
341
374
|
} else {
|
|
375
|
+
console.error(chalk.red(`\nā PRD creation failed with exit code ${code}`));
|
|
342
376
|
reject(new Error(`PRD creation failed with code ${code}`));
|
|
343
377
|
}
|
|
344
378
|
});
|
|
345
|
-
|
|
379
|
+
|
|
380
|
+
child.on('error', (err) => {
|
|
381
|
+
console.error(chalk.red(`\nā Failed to start process: ${err.message}`));
|
|
382
|
+
reject(err);
|
|
383
|
+
});
|
|
346
384
|
});
|
|
347
385
|
|
|
348
386
|
} catch (error) {
|
|
349
|
-
|
|
350
|
-
|
|
387
|
+
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
388
|
+
|
|
389
|
+
if (error.message.includes('terminated')) {
|
|
390
|
+
console.error(chalk.yellow('Operation cancelled by user'));
|
|
391
|
+
} else if (error.code === 'ENOENT') {
|
|
392
|
+
console.error(chalk.red('Node.js executable not found'));
|
|
393
|
+
console.error(chalk.yellow('Ensure Node.js is installed and in PATH'));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
process.exit(1);
|
|
351
397
|
}
|
|
352
398
|
}
|
|
353
399
|
|
|
@@ -357,10 +403,10 @@ async function prdNew(argv) {
|
|
|
357
403
|
*/
|
|
358
404
|
async function prdParse(argv) {
|
|
359
405
|
const spinner = ora(`Parsing PRD: ${argv.name}`).start();
|
|
360
|
-
const prdService = new PRDService();
|
|
361
406
|
|
|
362
407
|
try {
|
|
363
408
|
const content = await readPrdFile(argv.name);
|
|
409
|
+
const prdService = new PRDService();
|
|
364
410
|
|
|
365
411
|
if (argv.stream) {
|
|
366
412
|
// Streaming mode
|
|
@@ -388,12 +434,24 @@ async function prdParse(argv) {
|
|
|
388
434
|
spinner.fail(chalk.red('Failed to parse PRD'));
|
|
389
435
|
|
|
390
436
|
if (error.message.includes('not found')) {
|
|
391
|
-
console.error(chalk.red(`\
|
|
437
|
+
console.error(chalk.red(`\nā Error: PRD file not found`));
|
|
438
|
+
console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
|
|
439
|
+
console.error(chalk.yellow('\nš” Use: autopm prd list to see available PRDs'));
|
|
440
|
+
} else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
|
|
441
|
+
console.error(chalk.red(`\nā Error: API key not configured`));
|
|
442
|
+
console.error(chalk.yellow('\nš” Set your API key in .env file:'));
|
|
443
|
+
console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
|
|
392
444
|
} else if (error.message.includes('Failed to read')) {
|
|
393
|
-
console.error(chalk.red(`\
|
|
445
|
+
console.error(chalk.red(`\nā Error: Cannot read PRD file`));
|
|
446
|
+
console.error(chalk.red(` ${error.message}`));
|
|
394
447
|
} else {
|
|
395
|
-
console.error(chalk.red(`\
|
|
448
|
+
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
449
|
+
if (process.env.DEBUG) {
|
|
450
|
+
console.error(chalk.gray('\nStack trace:'));
|
|
451
|
+
console.error(chalk.gray(error.stack));
|
|
452
|
+
}
|
|
396
453
|
}
|
|
454
|
+
process.exit(1);
|
|
397
455
|
}
|
|
398
456
|
}
|
|
399
457
|
|
|
@@ -403,10 +461,10 @@ async function prdParse(argv) {
|
|
|
403
461
|
*/
|
|
404
462
|
async function prdExtractEpics(argv) {
|
|
405
463
|
const spinner = ora(`Extracting epics from: ${argv.name}`).start();
|
|
406
|
-
const prdService = new PRDService();
|
|
407
464
|
|
|
408
465
|
try {
|
|
409
466
|
const content = await readPrdFile(argv.name);
|
|
467
|
+
const prdService = new PRDService();
|
|
410
468
|
|
|
411
469
|
if (argv.stream) {
|
|
412
470
|
// Streaming mode
|
|
@@ -435,12 +493,24 @@ async function prdExtractEpics(argv) {
|
|
|
435
493
|
spinner.fail(chalk.red('Failed to extract epics'));
|
|
436
494
|
|
|
437
495
|
if (error.message.includes('not found')) {
|
|
438
|
-
console.error(chalk.red(`\
|
|
496
|
+
console.error(chalk.red(`\nā Error: PRD file not found`));
|
|
497
|
+
console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
|
|
498
|
+
console.error(chalk.yellow('\nš” Use: autopm prd list to see available PRDs'));
|
|
499
|
+
} else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
|
|
500
|
+
console.error(chalk.red(`\nā Error: API key not configured`));
|
|
501
|
+
console.error(chalk.yellow('\nš” Set your API key in .env file:'));
|
|
502
|
+
console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
|
|
439
503
|
} else if (error.message.includes('Failed to read')) {
|
|
440
|
-
console.error(chalk.red(`\
|
|
504
|
+
console.error(chalk.red(`\nā Error: Cannot read PRD file`));
|
|
505
|
+
console.error(chalk.red(` ${error.message}`));
|
|
441
506
|
} else {
|
|
442
|
-
console.error(chalk.red(`\
|
|
507
|
+
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
508
|
+
if (process.env.DEBUG) {
|
|
509
|
+
console.error(chalk.gray('\nStack trace:'));
|
|
510
|
+
console.error(chalk.gray(error.stack));
|
|
511
|
+
}
|
|
443
512
|
}
|
|
513
|
+
process.exit(1);
|
|
444
514
|
}
|
|
445
515
|
}
|
|
446
516
|
|
|
@@ -450,10 +520,10 @@ async function prdExtractEpics(argv) {
|
|
|
450
520
|
*/
|
|
451
521
|
async function prdSummarize(argv) {
|
|
452
522
|
const spinner = ora(`Generating summary for: ${argv.name}`).start();
|
|
453
|
-
const prdService = new PRDService();
|
|
454
523
|
|
|
455
524
|
try {
|
|
456
525
|
const content = await readPrdFile(argv.name);
|
|
526
|
+
const prdService = new PRDService();
|
|
457
527
|
|
|
458
528
|
if (argv.stream) {
|
|
459
529
|
// Streaming mode
|
|
@@ -477,12 +547,24 @@ async function prdSummarize(argv) {
|
|
|
477
547
|
spinner.fail(chalk.red('Failed to generate summary'));
|
|
478
548
|
|
|
479
549
|
if (error.message.includes('not found')) {
|
|
480
|
-
console.error(chalk.red(`\
|
|
550
|
+
console.error(chalk.red(`\nā Error: PRD file not found`));
|
|
551
|
+
console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
|
|
552
|
+
console.error(chalk.yellow('\nš” Use: autopm prd list to see available PRDs'));
|
|
553
|
+
} else if (error.message.includes('ANTHROPIC_API_KEY') || error.message.includes('API key')) {
|
|
554
|
+
console.error(chalk.red(`\nā Error: API key not configured`));
|
|
555
|
+
console.error(chalk.yellow('\nš” Set your API key in .env file:'));
|
|
556
|
+
console.error(chalk.cyan(' ANTHROPIC_API_KEY=sk-ant-api03-...'));
|
|
481
557
|
} else if (error.message.includes('Failed to read')) {
|
|
482
|
-
console.error(chalk.red(`\
|
|
558
|
+
console.error(chalk.red(`\nā Error: Cannot read PRD file`));
|
|
559
|
+
console.error(chalk.red(` ${error.message}`));
|
|
483
560
|
} else {
|
|
484
|
-
console.error(chalk.red(`\
|
|
561
|
+
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
562
|
+
if (process.env.DEBUG) {
|
|
563
|
+
console.error(chalk.gray('\nStack trace:'));
|
|
564
|
+
console.error(chalk.gray(error.stack));
|
|
565
|
+
}
|
|
485
566
|
}
|
|
567
|
+
process.exit(1);
|
|
486
568
|
}
|
|
487
569
|
}
|
|
488
570
|
|
|
@@ -492,83 +574,41 @@ async function prdSummarize(argv) {
|
|
|
492
574
|
*/
|
|
493
575
|
async function prdValidate(argv) {
|
|
494
576
|
const spinner = ora(`Validating PRD: ${argv.name}`).start();
|
|
495
|
-
const prdService = new PRDService();
|
|
496
577
|
|
|
497
578
|
try {
|
|
498
579
|
const content = await readPrdFile(argv.name);
|
|
580
|
+
const prdService = new PRDService();
|
|
499
581
|
const result = await prdService.validate(content);
|
|
500
582
|
|
|
501
583
|
if (result.valid) {
|
|
502
584
|
spinner.succeed(chalk.green('PRD is valid'));
|
|
503
|
-
console.log(chalk.green('\
|
|
585
|
+
console.log(chalk.green('\nā Validation passed - PRD structure is correct'));
|
|
504
586
|
} else {
|
|
505
587
|
spinner.fail(chalk.red(`PRD validation failed - ${result.issues.length} issues found`));
|
|
506
|
-
console.error(chalk.red(`\
|
|
588
|
+
console.error(chalk.red(`\nā Validation failed - ${result.issues.length} issue(s):`));
|
|
507
589
|
result.issues.forEach((issue, index) => {
|
|
508
590
|
console.error(chalk.red(` ${index + 1}. ${issue}`));
|
|
509
591
|
});
|
|
592
|
+
process.exit(1);
|
|
510
593
|
}
|
|
511
594
|
} catch (error) {
|
|
512
595
|
spinner.fail(chalk.red('Failed to validate PRD'));
|
|
513
596
|
|
|
514
597
|
if (error.message.includes('not found')) {
|
|
515
|
-
console.error(chalk.red(`\
|
|
598
|
+
console.error(chalk.red(`\nā Error: PRD file not found`));
|
|
599
|
+
console.error(chalk.red(` File: ${getPrdPath(argv.name)}`));
|
|
600
|
+
console.error(chalk.yellow('\nš” Use: autopm prd list to see available PRDs'));
|
|
516
601
|
} else if (error.message.includes('Failed to read')) {
|
|
517
|
-
console.error(chalk.red(`\
|
|
602
|
+
console.error(chalk.red(`\nā Error: Cannot read PRD file`));
|
|
603
|
+
console.error(chalk.red(` ${error.message}`));
|
|
518
604
|
} else {
|
|
519
|
-
console.error(chalk.red(`\
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
/**
|
|
525
|
-
* Main command handler
|
|
526
|
-
* @param {Object} argv - Command arguments
|
|
527
|
-
*/
|
|
528
|
-
async function handler(argv) {
|
|
529
|
-
// Validate action
|
|
530
|
-
const validActions = ['list', 'new', 'show', 'edit', 'status', 'parse', 'extract-epics', 'summarize', 'validate'];
|
|
531
|
-
|
|
532
|
-
if (!validActions.includes(argv.action)) {
|
|
533
|
-
console.error(chalk.red(`\nError: Unknown action: ${argv.action}`));
|
|
534
|
-
console.error(chalk.yellow(`Valid actions: ${validActions.join(', ')}`));
|
|
535
|
-
return;
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Route to appropriate handler
|
|
539
|
-
try {
|
|
540
|
-
switch (argv.action) {
|
|
541
|
-
case 'list':
|
|
542
|
-
await prdList(argv);
|
|
543
|
-
break;
|
|
544
|
-
case 'new':
|
|
545
|
-
await prdNew(argv);
|
|
546
|
-
break;
|
|
547
|
-
case 'show':
|
|
548
|
-
await prdShow(argv);
|
|
549
|
-
break;
|
|
550
|
-
case 'edit':
|
|
551
|
-
await prdEdit(argv);
|
|
552
|
-
break;
|
|
553
|
-
case 'status':
|
|
554
|
-
await prdStatus(argv);
|
|
555
|
-
break;
|
|
556
|
-
case 'parse':
|
|
557
|
-
await prdParse(argv);
|
|
558
|
-
break;
|
|
559
|
-
case 'extract-epics':
|
|
560
|
-
await prdExtractEpics(argv);
|
|
561
|
-
break;
|
|
562
|
-
case 'summarize':
|
|
563
|
-
await prdSummarize(argv);
|
|
564
|
-
break;
|
|
565
|
-
case 'validate':
|
|
566
|
-
await prdValidate(argv);
|
|
567
|
-
break;
|
|
605
|
+
console.error(chalk.red(`\nā Error: ${error.message}`));
|
|
606
|
+
if (process.env.DEBUG) {
|
|
607
|
+
console.error(chalk.gray('\nStack trace:'));
|
|
608
|
+
console.error(chalk.gray(error.stack));
|
|
609
|
+
}
|
|
568
610
|
}
|
|
569
|
-
|
|
570
|
-
// Global error handler for unexpected errors
|
|
571
|
-
console.error(chalk.red(`\nUnexpected error: ${error.message}`));
|
|
611
|
+
process.exit(1);
|
|
572
612
|
}
|
|
573
613
|
}
|
|
574
614
|
|
|
@@ -585,7 +625,8 @@ function builder(yargs) {
|
|
|
585
625
|
(yargs) => {
|
|
586
626
|
return yargs
|
|
587
627
|
.example('autopm prd list', 'Show all PRDs');
|
|
588
|
-
}
|
|
628
|
+
},
|
|
629
|
+
prdList // Handler
|
|
589
630
|
)
|
|
590
631
|
.command(
|
|
591
632
|
'new <name>',
|
|
@@ -603,7 +644,8 @@ function builder(yargs) {
|
|
|
603
644
|
})
|
|
604
645
|
.example('autopm prd new my-feature', 'Create PRD with wizard')
|
|
605
646
|
.example('autopm prd new payment-api --template api-feature', 'Create PRD from template');
|
|
606
|
-
}
|
|
647
|
+
},
|
|
648
|
+
prdNew // Handler
|
|
607
649
|
)
|
|
608
650
|
.command(
|
|
609
651
|
'show <name>',
|
|
@@ -615,7 +657,8 @@ function builder(yargs) {
|
|
|
615
657
|
type: 'string'
|
|
616
658
|
})
|
|
617
659
|
.example('autopm prd show my-feature', 'Display PRD content');
|
|
618
|
-
}
|
|
660
|
+
},
|
|
661
|
+
prdShow // Handler
|
|
619
662
|
)
|
|
620
663
|
.command(
|
|
621
664
|
'edit <name>',
|
|
@@ -628,7 +671,8 @@ function builder(yargs) {
|
|
|
628
671
|
})
|
|
629
672
|
.example('autopm prd edit my-feature', 'Open PRD in editor')
|
|
630
673
|
.example('EDITOR=code autopm prd edit my-feature', 'Open PRD in VS Code');
|
|
631
|
-
}
|
|
674
|
+
},
|
|
675
|
+
prdEdit // Handler
|
|
632
676
|
)
|
|
633
677
|
.command(
|
|
634
678
|
'status <name>',
|
|
@@ -640,7 +684,8 @@ function builder(yargs) {
|
|
|
640
684
|
type: 'string'
|
|
641
685
|
})
|
|
642
686
|
.example('autopm prd status my-feature', 'Show PRD status report');
|
|
643
|
-
}
|
|
687
|
+
},
|
|
688
|
+
prdStatus // Handler
|
|
644
689
|
)
|
|
645
690
|
.command(
|
|
646
691
|
'parse <name>',
|
|
@@ -661,7 +706,8 @@ function builder(yargs) {
|
|
|
661
706
|
type: 'boolean',
|
|
662
707
|
default: true
|
|
663
708
|
});
|
|
664
|
-
}
|
|
709
|
+
},
|
|
710
|
+
prdParse // Handler
|
|
665
711
|
)
|
|
666
712
|
.command(
|
|
667
713
|
'extract-epics <name>',
|
|
@@ -677,7 +723,8 @@ function builder(yargs) {
|
|
|
677
723
|
type: 'boolean',
|
|
678
724
|
default: false
|
|
679
725
|
});
|
|
680
|
-
}
|
|
726
|
+
},
|
|
727
|
+
prdExtractEpics // Handler
|
|
681
728
|
)
|
|
682
729
|
.command(
|
|
683
730
|
'summarize <name>',
|
|
@@ -693,7 +740,8 @@ function builder(yargs) {
|
|
|
693
740
|
type: 'boolean',
|
|
694
741
|
default: false
|
|
695
742
|
});
|
|
696
|
-
}
|
|
743
|
+
},
|
|
744
|
+
prdSummarize // Handler
|
|
697
745
|
)
|
|
698
746
|
.command(
|
|
699
747
|
'validate <name>',
|
|
@@ -704,7 +752,8 @@ function builder(yargs) {
|
|
|
704
752
|
describe: 'PRD name (without .md extension)',
|
|
705
753
|
type: 'string'
|
|
706
754
|
});
|
|
707
|
-
}
|
|
755
|
+
},
|
|
756
|
+
prdValidate // Handler
|
|
708
757
|
)
|
|
709
758
|
.demandCommand(1, 'You must specify a PRD action')
|
|
710
759
|
.strictCommands()
|
|
@@ -715,10 +764,27 @@ function builder(yargs) {
|
|
|
715
764
|
* Command export
|
|
716
765
|
*/
|
|
717
766
|
module.exports = {
|
|
718
|
-
command: 'prd
|
|
767
|
+
command: 'prd',
|
|
719
768
|
describe: 'Manage PRD (Product Requirements Documents)',
|
|
720
769
|
builder,
|
|
721
|
-
handler
|
|
770
|
+
handler: (argv) => {
|
|
771
|
+
// This is just for catching the base command without subcommand
|
|
772
|
+
if (!argv._.includes('prd') || argv._.length === 1) {
|
|
773
|
+
console.log(chalk.yellow('\nPlease specify a PRD command\n'));
|
|
774
|
+
console.log('Usage: autopm prd <command>\n');
|
|
775
|
+
console.log('Available commands:');
|
|
776
|
+
console.log(' list List all PRDs');
|
|
777
|
+
console.log(' new <name> Create new PRD');
|
|
778
|
+
console.log(' show <name> Display PRD');
|
|
779
|
+
console.log(' edit <name> Edit PRD');
|
|
780
|
+
console.log(' status <name> Show PRD status');
|
|
781
|
+
console.log(' parse <name> Parse PRD with AI');
|
|
782
|
+
console.log(' extract-epics <name> Extract epics');
|
|
783
|
+
console.log(' summarize <name> Generate summary');
|
|
784
|
+
console.log(' validate <name> Validate structure');
|
|
785
|
+
console.log('\nUse: autopm prd <command> --help for more info\n');
|
|
786
|
+
}
|
|
787
|
+
},
|
|
722
788
|
handlers: {
|
|
723
789
|
list: prdList,
|
|
724
790
|
new: prdNew,
|