@formigio/fazemos-cli 0.10.4 → 0.10.6

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/dist/index.js CHANGED
@@ -4292,7 +4292,11 @@ step
4292
4292
  });
4293
4293
  step
4294
4294
  .command('revise')
4295
- .description('Request revision on a submitted step. Sends the step back to "in_progress" with feedback. The assignee can then resubmit. The step\'s review cycle counter increments; if max cycles are reached, the step auto-approves.')
4295
+ .description('Request revision on a submitted step. Sends the step back to "in_progress" with feedback. ' +
4296
+ 'The assignee can then resubmit. The step\'s review cycle counter increments. ' +
4297
+ 'If the review cycle limit is reached, the step transitions to \'failed\'. ' +
4298
+ 'Use \'fazemos pl step reset-review-cycles <instanceId> <stepId> --feedback "<text>"\' ' +
4299
+ 'to reset the counter with new guidance and retry.')
4296
4300
  .argument('<instanceId>', 'Pipeline instance ID')
4297
4301
  .argument('<stepId>', 'Step instance ID')
4298
4302
  .requiredOption('--reason <text>', 'Revision feedback explaining what needs to change')
@@ -4303,6 +4307,11 @@ step
4303
4307
  });
4304
4308
  console.log(chalk.green(`Revision requested: ${data.step?.step_name || stepId}`));
4305
4309
  console.log(` Status: ${data.step?.status}`);
4310
+ if (data.step?.status === 'failed' && data.step?.metadata?.error_class === 'max_review_cycles_reached') {
4311
+ console.log(chalk.yellow(` Review cycle limit reached. Step has been marked as failed.`));
4312
+ console.log(` To retry with new guidance:`);
4313
+ console.log(` fazemos pl step reset-review-cycles ${instanceId} ${data.step?.id || stepId} --feedback "<new guidance>"`);
4314
+ }
4306
4315
  }
4307
4316
  catch (err) {
4308
4317
  console.error(chalk.red(err.message));
@@ -4434,6 +4443,51 @@ step
4434
4443
  process.exit(1);
4435
4444
  }
4436
4445
  });
4446
+ step
4447
+ .command('reset-review-cycles')
4448
+ .description('Reset a step\'s review cycle counter to 0 with mandatory feedback. ' +
4449
+ 'Only valid when the step is in \'failed\' status with error_class \'max_review_cycles_reached\'. ' +
4450
+ 'The step transitions back to \'in_progress\' and the feedback is stored for the assignee\'s next attempt. ' +
4451
+ 'Requires owner or admin role. ' +
4452
+ 'Use "pl step show <instanceId> <stepId>" to check step status and error class.')
4453
+ .argument('<instanceId>', 'Pipeline instance ID')
4454
+ .argument('<stepId>', 'Step instance ID')
4455
+ .requiredOption('-f, --feedback <text>', 'New guidance for the assignee\'s next attempt. Cannot be empty.')
4456
+ .action(async (instanceId, stepId, opts) => {
4457
+ try {
4458
+ const feedback = opts.feedback?.trim();
4459
+ if (!feedback) {
4460
+ console.error(chalk.red('Error: --feedback is required and cannot be empty.'));
4461
+ process.exit(1);
4462
+ }
4463
+ const data = await api('POST', `/api/pipeline-instances/${instanceId}/steps/${stepId}/reset-review-cycles`, {
4464
+ feedback,
4465
+ });
4466
+ const stepName = data.step?.step_name || stepId;
4467
+ const status = data.step?.status || 'unknown';
4468
+ const previousCount = data.reset_metadata?.previous_cycle_count ?? '?';
4469
+ const feedbackRecorded = feedback.length > 120 ? feedback.slice(0, 120) + '...' : feedback;
4470
+ console.log(chalk.green(`Step reset (review cycles): "${stepName}" (${status})`));
4471
+ console.log(` Cycles reset: ${previousCount} → 0`);
4472
+ console.log(` Feedback recorded: "${feedbackRecorded}"`);
4473
+ console.log(chalk.yellow(` Note: Manual dispatch may be needed until I16 ships. Run: fazemos execute ...`));
4474
+ }
4475
+ catch (err) {
4476
+ if (err.code === 'INVALID_STATE') {
4477
+ const currentStatus = err.details?.current_status || 'unknown';
4478
+ console.error(chalk.red(`Error: Step is not in a failed state with max_review_cycles_reached error class.`));
4479
+ console.error(`Current status: ${currentStatus}`);
4480
+ console.error(`Use this command only after a step has failed due to review cycle exhaustion.`);
4481
+ }
4482
+ else if (err.code === 'FORBIDDEN' || err.status === 403) {
4483
+ console.error(chalk.red(`Error: Only owners and admins can reset review cycles.`));
4484
+ }
4485
+ else {
4486
+ console.error(chalk.red(err.message));
4487
+ }
4488
+ process.exit(1);
4489
+ }
4490
+ });
4437
4491
  // ── Queue ──────────────────────────────────────────────────
4438
4492
  const queue = program.command('queue').alias('q').description('Work queue commands');
4439
4493
  queue
@@ -7233,12 +7287,16 @@ docs
7233
7287
  handleScopedError(err);
7234
7288
  }
7235
7289
  });
7236
- // Only auto-parse when invoked as the entry point (i.e. `node dist/index.js ...`
7237
- // or `npx tsx src/index.ts ...`). When imported as a module — by tests using
7238
- // `vi.mock` to intercept `api()` and asserting on `program.parseAsync(...)`
7239
- // skip auto-parse so the test controls invocation.
7240
- const isMainModule = import.meta.url === `file://${process.argv[1]}`;
7241
- if (isMainModule)
7290
+ // Skip auto-parse only when running under Vitest (which sets process.env.VITEST).
7291
+ // Tests import `program` and drive it via `program.parseAsync(...)` after mocking
7292
+ // `./api.js`. In every other context direct invocation, npx tsx, OR the bin
7293
+ // shim that does `import('../dist/index.js')` — auto-parse must run, otherwise
7294
+ // the CLI produces no output.
7295
+ //
7296
+ // Earlier `import.meta.url === file://${process.argv[1]}` check was wrong: the
7297
+ // bin shim's argv[1] is the shim path, not the dist/index.js path, so the guard
7298
+ // returned false and silently skipped parse.
7299
+ if (!process.env.VITEST)
7242
7300
  program.parse();
7243
7301
  export { program };
7244
7302
  //# sourceMappingURL=index.js.map