@fermindi/pwn-cli 0.9.4 → 0.9.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fermindi/pwn-cli",
3
- "version": "0.9.4",
3
+ "version": "0.9.5",
4
4
  "description": "Professional AI Workspace - Inject structured memory and automation into any project for AI-powered development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -391,34 +391,24 @@ export async function runBatch(options = {}, cwd = process.cwd()) {
391
391
  }
392
392
  }
393
393
 
394
- // --- Branch isolation: create/checkout task branch ---
395
- let taskBranch = null;
394
+ // --- Pre-validation: check existing feat branch before reset ---
395
+ let storyDone = false;
396
+ const taskBranchName = `feat/${task.id}`;
397
+ let branchExists = false;
396
398
  try {
397
- taskBranch = await createTaskBranch(task.id, cwd);
398
- branchesCreated.push(taskBranch);
399
- console.log(chalk.blue(` Branch: ${chalk.bold(taskBranch)}`));
399
+ await execAsync(`git rev-parse --verify ${taskBranchName}`, { cwd });
400
+ branchExists = true;
401
+ } catch {}
400
402
 
401
- // Track branch in task file
402
- if (taskFile) {
403
- taskFile.branch = taskBranch;
404
- saveTaskFile(taskFile, cwd);
405
- }
406
- } catch (err) {
407
- console.log(chalk.red(` Failed to create branch feat/${task.id}: ${err.message}`));
408
- console.log(chalk.yellow(' Continuing on current branch...'));
409
- }
410
-
411
- // --- Pre-validation: check if existing branch already passes gates ---
412
- let storyDone = false;
413
- if (taskBranch) {
414
- // Check if this branch has commits beyond the batch branch
403
+ if (branchExists) {
415
404
  try {
416
- const { stdout: diffStat } = await execAsync('git diff --stat HEAD~1 2>/dev/null || echo ""', { cwd });
405
+ // Checkout WITHOUT reset to inspect existing work
406
+ await checkoutBranch(taskBranchName, cwd, { stash: true });
417
407
  const { stdout: logCount } = await execAsync(`git rev-list --count ${batchBranch}..HEAD`, { cwd });
418
408
  const commits = parseInt(logCount.trim(), 10);
419
409
 
420
410
  if (commits > 0) {
421
- console.log(chalk.blue(` Pre-validation: found ${commits} commit(s) on ${taskBranch}, running quality gates...`));
411
+ console.log(chalk.blue(` Pre-validation: found ${commits} commit(s) on ${taskBranchName}, running quality gates...`));
422
412
  const preGates = await runGatesWithStatus(cwd);
423
413
 
424
414
  if (preGates.success) {
@@ -445,35 +435,56 @@ export async function runBatch(options = {}, cwd = process.cwd()) {
445
435
  // Merge into batch branch
446
436
  try {
447
437
  await checkoutBranch(batchBranch, cwd, { stash: true });
448
- await mergeBranch(taskBranch, cwd);
438
+ await mergeBranch(taskBranchName, cwd);
449
439
  mergedCount++;
450
- mergedBranches.push(taskBranch);
451
- console.log(chalk.green(` Merged ${taskBranch} → ${batchBranch}`));
440
+ mergedBranches.push(taskBranchName);
441
+ console.log(chalk.green(` Merged ${taskBranchName} → ${batchBranch}`));
452
442
  } catch (err) {
453
443
  console.log(chalk.red(` Merge failed: ${err.message}`));
454
- console.log(chalk.yellow(` Branch ${taskBranch} available for manual merge`));
455
- unmergedBranches.push(taskBranch);
444
+ console.log(chalk.yellow(` Branch ${taskBranchName} available for manual merge`));
445
+ unmergedBranches.push(taskBranchName);
456
446
  }
457
447
  } else {
458
448
  console.log(chalk.yellow(` Pre-validation FAILED — will re-execute`));
449
+ // Return to batch branch so createTaskBranch resets properly
450
+ await checkoutBranch(batchBranch, cwd, { force: true, stash: true });
459
451
  }
452
+ } else {
453
+ // No commits — return to batch branch for normal flow
454
+ await checkoutBranch(batchBranch, cwd, { force: true, stash: true });
460
455
  }
461
456
  } catch {
462
- // No commits or comparison failed — proceed normally
457
+ // Checkout failed — proceed normally
458
+ try { await checkoutBranch(batchBranch, cwd, { force: true, stash: true }); } catch {}
463
459
  }
464
460
  }
465
461
 
466
462
  if (storyDone) {
467
- // Return to batch branch
468
- if (taskBranch) {
469
- try {
470
- await checkoutBranch(batchBranch, cwd, { force: true, stash: true });
471
- console.log(chalk.dim(` Returned to branch: ${batchBranch}`));
472
- } catch {}
473
- }
463
+ branchesCreated.push(taskBranchName);
464
+ try {
465
+ await checkoutBranch(batchBranch, cwd, { force: true, stash: true });
466
+ console.log(chalk.dim(` Returned to branch: ${batchBranch}`));
467
+ } catch {}
474
468
  continue;
475
469
  }
476
470
 
471
+ // --- Branch isolation: create/checkout task branch (resets existing) ---
472
+ let taskBranch = null;
473
+ try {
474
+ taskBranch = await createTaskBranch(task.id, cwd);
475
+ branchesCreated.push(taskBranch);
476
+ console.log(chalk.blue(` Branch: ${chalk.bold(taskBranch)}`));
477
+
478
+ // Track branch in task file
479
+ if (taskFile) {
480
+ taskFile.branch = taskBranch;
481
+ saveTaskFile(taskFile, cwd);
482
+ }
483
+ } catch (err) {
484
+ console.log(chalk.red(` Failed to create branch feat/${task.id}: ${err.message}`));
485
+ console.log(chalk.yellow(' Continuing on current branch...'));
486
+ }
487
+
477
488
  // --- Phase 2: Execution ---
478
489
  const phaseLabel = noPlan ? '' : 'Phase 2';
479
490
  console.log(chalk.blue(` ${noPlan ? 'Executing' : 'Phase 2: Executing'} ${task.id}...`));