@formigio/fazemos-cli 0.10.2 → 0.10.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/dist/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ import { Command } from 'commander';
3
+ declare const program: Command;
4
+ export { program };
package/dist/index.js CHANGED
@@ -4212,7 +4212,8 @@ step
4212
4212
  .option('--callback-token <token>', 'Callback token')
4213
4213
  .action(async (instanceId, stepId, opts) => {
4214
4214
  try {
4215
- const body = { text: opts.text };
4215
+ // I19: API expects `append` not `text`. Flag stays --text (operator muscle memory).
4216
+ const body = { append: opts.text };
4216
4217
  if (opts.callbackToken)
4217
4218
  body.callbackToken = opts.callbackToken;
4218
4219
  await api('PATCH', `/api/pipeline-instances/${instanceId}/steps/${stepId}/output`, body);
@@ -4291,7 +4292,11 @@ step
4291
4292
  });
4292
4293
  step
4293
4294
  .command('revise')
4294
- .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.')
4295
4300
  .argument('<instanceId>', 'Pipeline instance ID')
4296
4301
  .argument('<stepId>', 'Step instance ID')
4297
4302
  .requiredOption('--reason <text>', 'Revision feedback explaining what needs to change')
@@ -4302,6 +4307,11 @@ step
4302
4307
  });
4303
4308
  console.log(chalk.green(`Revision requested: ${data.step?.step_name || stepId}`));
4304
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
+ }
4305
4315
  }
4306
4316
  catch (err) {
4307
4317
  console.error(chalk.red(err.message));
@@ -4433,6 +4443,51 @@ step
4433
4443
  process.exit(1);
4434
4444
  }
4435
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
+ });
4436
4491
  // ── Queue ──────────────────────────────────────────────────
4437
4492
  const queue = program.command('queue').alias('q').description('Work queue commands');
4438
4493
  queue
@@ -7232,5 +7287,12 @@ docs
7232
7287
  handleScopedError(err);
7233
7288
  }
7234
7289
  });
7235
- program.parse();
7290
+ // Only auto-parse when invoked as the entry point (i.e. `node dist/index.js ...`
7291
+ // or `npx tsx src/index.ts ...`). When imported as a module — by tests using
7292
+ // `vi.mock` to intercept `api()` and asserting on `program.parseAsync(...)` —
7293
+ // skip auto-parse so the test controls invocation.
7294
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
7295
+ if (isMainModule)
7296
+ program.parse();
7297
+ export { program };
7236
7298
  //# sourceMappingURL=index.js.map